re3-wiiu/src/control/Darkel.cpp

409 lines
12 KiB
C++
Raw Normal View History

#include "common.h"
2020-04-17 15:31:11 +02:00
2019-07-04 22:31:21 +02:00
#include "main.h"
#include "Darkel.h"
2019-10-05 15:44:03 +02:00
#include "PlayerPed.h"
2020-03-28 15:47:52 +01:00
#include "Wanted.h"
2019-07-04 22:31:21 +02:00
#include "Timer.h"
#include "DMAudio.h"
#include "Population.h"
2020-10-11 11:56:33 +02:00
#include "Replay.h"
2019-07-04 22:31:21 +02:00
#include "Weapon.h"
#include "World.h"
#include "Stats.h"
#include "Font.h"
#include "Text.h"
2020-01-07 15:37:20 +01:00
#include "Vehicle.h"
2020-05-31 19:59:01 +02:00
#include "GameLogic.h"
2020-01-07 15:37:20 +01:00
2020-10-11 11:56:33 +02:00
//--MIAMI: file done except TODO
2020-01-07 15:37:20 +01:00
#define FRENZY_ANY_PED -1
#define FRENZY_ANY_CAR -2
int32 CDarkel::TimeLimit;
int32 CDarkel::PreviousTime;
int32 CDarkel::TimeOfFrenzyStart;
int32 CDarkel::WeaponType;
int32 CDarkel::AmmoInterruptedWeapon;
int32 CDarkel::KillsNeeded;
2020-10-11 11:56:33 +02:00
int32 CDarkel::InterruptedWeaponType;
int32 CDarkel::InterruptedWeaponSelected;
2019-10-05 15:44:03 +02:00
/*
2020-07-07 01:02:39 +02:00
* TODO: Collect timer/kill counter RGBA colors on top like in Hud/Frontend.
2019-10-05 15:44:03 +02:00
* bStandardSoundAndMessages is a completely beta thing,
* makes game handle sounds & messages instead of SCM (just like in GTA2)
* but it's never been used in the game. Has unused sliding text when frenzy completed etc.
*/
2020-08-14 16:34:04 +02:00
bool CDarkel::bStandardSoundAndMessages;
bool CDarkel::bNeedHeadShot;
bool CDarkel::bProperKillFrenzy;
uint16 CDarkel::Status;
uint16 CDarkel::RegisteredKills[NUM_DEFAULT_MODELS];
int32 CDarkel::ModelToKill;
int32 CDarkel::ModelToKill2;
int32 CDarkel::ModelToKill3;
int32 CDarkel::ModelToKill4;
wchar *CDarkel::pStartMessage;
2019-07-04 22:31:21 +02:00
2019-10-05 15:44:03 +02:00
uint8
CDarkel::CalcFade(uint32 time, uint32 start, uint32 end)
{
2019-07-07 09:13:04 +02:00
if (time >= start && time <= end) {
if (time >= start + 500) {
if (time <= end - 500)
2019-07-07 20:59:49 +02:00
return 255;
2019-07-04 22:31:21 +02:00
else
2019-07-07 09:13:04 +02:00
return 255 * (end - time) / 500;
2019-10-05 15:44:03 +02:00
} else
2019-07-07 09:13:04 +02:00
return 255 * (time - start) / 500;
2019-10-05 15:44:03 +02:00
} else
2019-07-04 22:31:21 +02:00
return 0;
}
2019-10-05 15:44:03 +02:00
void
CDarkel::DrawMessages()
2019-07-04 22:31:21 +02:00
{
2020-10-11 11:56:33 +02:00
if (CReplay::IsPlayingBack())
return;
2019-07-04 22:31:21 +02:00
switch (Status) {
2019-10-05 15:44:03 +02:00
case KILLFRENZY_ONGOING:
{
CFont::SetJustifyOff();
CFont::SetBackgroundOff();
CFont::SetCentreSize(SCREEN_SCALE_X(610.0f));
2019-10-05 15:44:03 +02:00
CFont::SetCentreOn();
CFont::SetPropOn();
2020-10-11 11:56:33 +02:00
uint32 timePassedSinceStart = CTimer::GetTimeInMilliseconds() - TimeOfFrenzyStart;
if (bStandardSoundAndMessages) {
2019-10-05 15:44:03 +02:00
if (timePassedSinceStart >= 3000 && timePassedSinceStart < 11000) {
CFont::SetScale(SCREEN_SCALE_X(1.3f), SCREEN_SCALE_Y(1.3f));
CFont::SetJustifyOff();
CFont::SetColor(CRGBA(255, 255, 128, CalcFade(timePassedSinceStart, 3000, 11000)));
2020-06-07 03:10:06 +02:00
CFont::SetFontStyle(FONT_STANDARD);
2019-10-05 15:44:03 +02:00
if (pStartMessage) {
CFont::PrintString(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, pStartMessage);
}
}
} else {
if (timePassedSinceStart < 8000) {
CFont::SetScale(SCREEN_SCALE_X(1.3f), SCREEN_SCALE_Y(1.3f));
CFont::SetJustifyOff();
CFont::SetColor(CRGBA(255, 255, 128, CalcFade(timePassedSinceStart, 0, 8000)));
2020-06-07 03:10:06 +02:00
CFont::SetFontStyle(FONT_STANDARD);
2019-10-05 15:44:03 +02:00
if (pStartMessage) {
CFont::PrintString(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, pStartMessage);
}
}
}
CFont::SetScale(SCREEN_SCALE_X(0.75f), SCREEN_SCALE_Y(1.5f));
CFont::SetCentreOff();
CFont::SetRightJustifyOn();
CFont::SetFontStyle(FONT_HEADING);
2020-10-11 11:56:33 +02:00
if (TimeLimit >= 0) {
uint32 timeLeft = TimeLimit - (CTimer::GetTimeInMilliseconds() - TimeOfFrenzyStart);
2019-10-05 15:44:03 +02:00
sprintf(gString, "%d:%02d", timeLeft / 60000, timeLeft % 60000 / 1000);
AsciiToUnicode(gString, gUString);
if (timeLeft > 4000 || CTimer::GetFrameCounter() & 1) {
CFont::SetColor(CRGBA(0, 0, 0, 255));
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(35.0f), SCREEN_SCALE_Y(109.0f), gUString);
2020-07-07 01:02:39 +02:00
CFont::SetColor(CRGBA(0, 207, 133, 255));
2019-10-05 15:44:03 +02:00
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(34.0f), SCREEN_SCALE_Y(108.0f), gUString);
}
}
2020-10-11 11:56:33 +02:00
sprintf(gString, "%d", (KillsNeeded >= 0 ? KillsNeeded : 0));
2019-07-04 22:31:21 +02:00
AsciiToUnicode(gString, gUString);
CFont::SetColor(CRGBA(0, 0, 0, 255));
2019-10-05 15:44:03 +02:00
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(35.0f), SCREEN_SCALE_Y(144.0f), gUString);
2020-07-07 01:02:39 +02:00
CFont::SetColor(CRGBA(156, 91, 40, 255));
2019-10-05 15:44:03 +02:00
CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(34.0f), SCREEN_SCALE_Y(143.0f), gUString);
break;
2019-07-04 22:31:21 +02:00
}
2019-10-05 15:44:03 +02:00
case KILLFRENZY_PASSED:
{
2020-10-11 11:56:33 +02:00
if (bStandardSoundAndMessages) {
uint32 timePassedSinceStart = CTimer::GetTimeInMilliseconds() - TimeOfFrenzyStart;
if (CTimer::GetTimeInMilliseconds() - TimeOfFrenzyStart < 5000) {
2019-10-05 15:44:03 +02:00
CFont::SetBackgroundOff();
CFont::SetCentreSize(SCREEN_SCALE_X(620.0f));
2019-10-05 15:44:03 +02:00
CFont::SetCentreOn();
CFont::SetScale(SCREEN_SCALE_X(1.5f), SCREEN_SCALE_Y(1.5f));
CFont::SetJustifyOff();
CFont::SetColor(CRGBA(128, 255, 128, CalcFade(timePassedSinceStart, 0, 5000)));
2020-06-07 03:10:06 +02:00
CFont::SetFontStyle(FONT_STANDARD);
2019-10-05 15:44:03 +02:00
int y = SCREEN_HEIGHT / 2 + SCREEN_SCALE_Y(25.0f - timePassedSinceStart * 0.01f);
CFont::PrintString(SCREEN_WIDTH / 2, y, TheText.Get("KF_3"));
}
}
break;
}
default:
break;
2019-07-04 22:31:21 +02:00
}
}
2019-10-05 15:44:03 +02:00
void
CDarkel::Init()
2019-07-04 22:31:21 +02:00
{
2019-07-07 09:13:04 +02:00
Status = KILLFRENZY_NONE;
2019-07-04 22:31:21 +02:00
}
2019-10-05 15:44:03 +02:00
uint16
CDarkel::QueryModelsKilledByPlayer(int32 modelId)
2019-07-04 22:31:21 +02:00
{
return RegisteredKills[modelId];
}
2019-06-15 01:34:19 +02:00
2019-10-05 15:44:03 +02:00
bool
CDarkel::FrenzyOnGoing()
{
2019-07-04 22:31:21 +02:00
return Status == KILLFRENZY_ONGOING;
}
2019-10-05 15:44:03 +02:00
uint16
CDarkel::ReadStatus()
2019-07-04 22:31:21 +02:00
{
return Status;
}
2020-01-07 15:37:20 +01:00
void
CDarkel::RegisterCarBlownUpByPlayer(CVehicle *vehicle)
2019-07-04 22:31:21 +02:00
{
2020-10-05 15:09:44 +02:00
#ifdef FIX_BUGS
if (CReplay::IsPlayingBack())
return;
#endif
2020-01-07 15:37:20 +01:00
if (FrenzyOnGoing()) {
int32 model = vehicle->GetModelIndex();
if (ModelToKill == FRENZY_ANY_CAR || ModelToKill == model || ModelToKill2 == model || ModelToKill3 == model || ModelToKill4 == model) {
KillsNeeded--;
DMAudio.PlayFrontEndSound(SOUND_RAMPAGE_CAR_BLOWN, 0);
}
}
RegisteredKills[vehicle->GetModelIndex()]++;
2020-10-11 11:56:33 +02:00
switch (vehicle->GetVehicleAppearance()) {
case VEHICLE_APPEARANCE_CAR:
case VEHICLE_APPEARANCE_BIKE:
CStats::CarsExploded++;;
break;
case VEHICLE_APPEARANCE_HELI:
case VEHICLE_APPEARANCE_PLANE:
CStats::HelisDestroyed++;
break;
case VEHICLE_APPEARANCE_BOAT:
CStats::BoatsExploded++;
break;
}
2019-07-04 22:31:21 +02:00
}
2020-01-07 15:37:20 +01:00
void
CDarkel::RegisterKillByPlayer(CPed *victim, eWeaponType weapon, bool headshot)
2019-07-04 22:31:21 +02:00
{
2020-10-05 15:09:44 +02:00
#ifdef FIX_BUGS
if (CReplay::IsPlayingBack())
return;
#endif
2020-01-07 15:37:20 +01:00
if (FrenzyOnGoing() && (weapon == WeaponType
|| weapon == WEAPONTYPE_EXPLOSION
|| weapon == WEAPONTYPE_UZI_DRIVEBY && WeaponType == WEAPONTYPE_UZI
|| weapon == WEAPONTYPE_RAMMEDBYCAR && WeaponType == WEAPONTYPE_RUNOVERBYCAR
|| weapon == WEAPONTYPE_RUNOVERBYCAR && WeaponType == WEAPONTYPE_RAMMEDBYCAR
|| weapon == WEAPONTYPE_FLAMETHROWER && WeaponType == WEAPONTYPE_MOLOTOV)) {
int32 model = victim->GetModelIndex();
if (ModelToKill == FRENZY_ANY_PED || ModelToKill == model || ModelToKill2 == model || ModelToKill3 == model || ModelToKill4 == model) {
if (!bNeedHeadShot || headshot) {
KillsNeeded--;
DMAudio.PlayFrontEndSound(SOUND_RAMPAGE_KILL, 0);
}
}
}
CStats::PeopleKilledByPlayer++;
RegisteredKills[victim->GetModelIndex()]++;
CStats::PedsKilledOfThisType[victim->bChrisCriminal ? PEDTYPE_CRIMINAL : victim->m_nPedType]++;
if (headshot)
CStats::HeadsPopped++;
CStats::KillsSinceLastCheckpoint++;
2019-07-04 22:31:21 +02:00
}
2019-10-05 15:44:03 +02:00
void
CDarkel::RegisterKillNotByPlayer(CPed* victim, eWeaponType weapontype)
2019-07-04 22:31:21 +02:00
{
2020-10-05 15:09:44 +02:00
#ifdef FIX_BUGS
if (CReplay::IsPlayingBack())
return;
#endif
2020-01-07 15:37:20 +01:00
CStats::PeopleKilledByOthers++;
2019-07-04 22:31:21 +02:00
}
2019-10-05 15:44:03 +02:00
void
CDarkel::ResetModelsKilledByPlayer()
2019-07-04 22:31:21 +02:00
{
2019-10-06 23:39:25 +02:00
for (int i = 0; i < NUM_DEFAULT_MODELS; i++)
2019-07-07 09:13:04 +02:00
RegisteredKills[i] = 0;
2019-07-04 22:31:21 +02:00
}
2019-10-05 15:44:03 +02:00
void
CDarkel::ResetOnPlayerDeath()
2019-07-04 22:31:21 +02:00
{
2019-07-07 09:13:04 +02:00
if (Status != KILLFRENZY_ONGOING)
return;
2019-07-04 22:31:21 +02:00
2019-07-07 09:13:04 +02:00
CPopulation::m_AllRandomPedsThisType = -1;
Status = KILLFRENZY_FAILED;
TimeOfFrenzyStart = CTimer::GetTimeInMilliseconds();
2019-07-04 22:31:21 +02:00
2020-10-11 11:56:33 +02:00
DealWithWeaponChangeAtEndOfFrenzy();
2019-07-04 22:31:21 +02:00
}
2019-10-05 15:44:03 +02:00
void
CDarkel::StartFrenzy(eWeaponType weaponType, int32 time, uint16 kill, int32 modelId0, wchar *text, int32 modelId2, int32 modelId3, int32 modelId4, bool standardSound, bool needHeadShot)
2019-07-04 22:31:21 +02:00
{
2020-05-31 19:59:01 +02:00
CGameLogic::ClearShortCut();
CGameLogic::RemoveShortCutDropOffPointForMission();
2019-10-05 15:44:03 +02:00
eWeaponType fixedWeapon;
2019-07-04 22:31:21 +02:00
if (weaponType == WEAPONTYPE_UZI_DRIVEBY)
2019-10-05 15:44:03 +02:00
fixedWeapon = WEAPONTYPE_UZI;
else
fixedWeapon = weaponType;
2019-07-04 22:31:21 +02:00
WeaponType = weaponType;
Status = KILLFRENZY_ONGOING;
KillsNeeded = kill;
ModelToKill = modelId0;
ModelToKill2 = modelId2;
ModelToKill3 = modelId3;
ModelToKill4 = modelId4;
pStartMessage = text;
if (text == TheText.Get("PAGE_00")) {
CDarkel::bProperKillFrenzy = true;
CDarkel::pStartMessage = nil;
2019-10-05 15:44:03 +02:00
} else
bProperKillFrenzy = false;
2019-07-04 22:31:21 +02:00
bStandardSoundAndMessages = standardSound;
bNeedHeadShot = needHeadShot;
TimeOfFrenzyStart = CTimer::GetTimeInMilliseconds();
TimeLimit = time;
PreviousTime = time / 1000;
2019-10-05 15:44:03 +02:00
CPlayerPed *player = FindPlayerPed();
if (fixedWeapon < WEAPONTYPE_TOTALWEAPONS) {
2020-10-11 11:56:33 +02:00
InterruptedWeaponSelected = player->GetWeapon()->m_eWeaponType;
player->RemoveWeaponAnims(InterruptedWeaponSelected, -1000.0f);
InterruptedWeaponType = player->GetWeapon(player->GetWeaponSlot(fixedWeapon)).m_eWeaponType;
2019-10-05 15:44:03 +02:00
AmmoInterruptedWeapon = player->GetWeapon(player->GetWeaponSlot(fixedWeapon)).m_nAmmoTotal;
2020-10-11 11:56:33 +02:00
if (InterruptedWeaponType)
CModelInfo::GetModelInfo(CWeaponInfo::GetWeaponInfo((eWeaponType)InterruptedWeaponType)->m_nModelId)->AddRef();
2019-10-05 15:44:03 +02:00
player->GiveWeapon(fixedWeapon, 30000);
2020-10-11 11:56:33 +02:00
player->SetCurrentWeapon(fixedWeapon);
2019-10-05 15:44:03 +02:00
player->MakeChangesForNewWeapon(player->m_nSelectedWepSlot);
2019-07-04 22:31:21 +02:00
if (FindPlayerVehicle()) {
2020-10-11 11:56:33 +02:00
player->SetCurrentWeapon(FindPlayerPed()->m_nSelectedWepSlot);
player->SetAmmo(fixedWeapon, Min(player->GetWeapon()->m_nAmmoTotal, CWeaponInfo::GetWeaponInfo(player->GetWeapon()->m_eWeaponType)->m_nAmountofAmmunition));
2019-10-05 15:44:03 +02:00
player->ClearWeaponTarget();
2019-07-04 22:31:21 +02:00
}
}
if (CDarkel::bStandardSoundAndMessages)
DMAudio.PlayFrontEndSound(SOUND_RAMPAGE_START, 0);
}
2019-10-05 15:44:03 +02:00
void
CDarkel::Update()
2019-07-04 22:31:21 +02:00
{
2020-10-05 15:09:44 +02:00
#ifdef FIX_BUGS
if (CReplay::IsPlayingBack())
return;
#endif
2019-07-07 09:13:04 +02:00
if (Status != KILLFRENZY_ONGOING)
return;
2019-07-04 22:31:21 +02:00
2019-07-07 09:13:04 +02:00
int32 FrameTime = TimeLimit - (CTimer::GetTimeInMilliseconds() - TimeOfFrenzyStart);
2019-10-13 21:44:39 +02:00
if (FrameTime > 0 || TimeLimit < 0) {
2019-10-05 15:44:03 +02:00
2019-07-07 09:13:04 +02:00
DMAudio.PlayFrontEndSound(SOUND_RAMPAGE_ONGOING, FrameTime);
2019-07-04 22:31:21 +02:00
2019-07-07 09:13:04 +02:00
int32 PrevTime = FrameTime / 1000;
2019-07-04 22:31:21 +02:00
2019-07-07 09:13:04 +02:00
if (PrevTime != PreviousTime) {
if (PreviousTime < 12)
DMAudio.PlayFrontEndSound(SOUND_CLOCK_TICK, PrevTime);
PreviousTime = PrevTime;
}
2019-07-04 22:31:21 +02:00
2019-10-05 15:44:03 +02:00
} else {
2019-07-07 09:13:04 +02:00
CPopulation::m_AllRandomPedsThisType = -1;
Status = KILLFRENZY_FAILED;
TimeOfFrenzyStart = CTimer::GetTimeInMilliseconds();
2020-10-11 11:56:33 +02:00
DealWithWeaponChangeAtEndOfFrenzy();
2019-07-04 22:31:21 +02:00
2019-07-07 09:13:04 +02:00
if (bStandardSoundAndMessages)
DMAudio.PlayFrontEndSound(SOUND_RAMPAGE_FAILED, 0);
}
2019-07-04 22:31:21 +02:00
2019-07-07 09:13:04 +02:00
if (KillsNeeded <= 0) {
CPopulation::m_AllRandomPedsThisType = -1;
Status = KILLFRENZY_PASSED;
2019-07-04 22:31:21 +02:00
2019-07-07 09:13:04 +02:00
if (bProperKillFrenzy)
CStats::AnotherKillFrenzyPassed();
2019-07-04 22:31:21 +02:00
2019-07-07 09:13:04 +02:00
TimeOfFrenzyStart = CTimer::GetTimeInMilliseconds();
2019-07-04 22:31:21 +02:00
2019-07-12 18:01:22 +02:00
FindPlayerPed()->m_pWanted->SetWantedLevel(0);
2019-07-04 22:31:21 +02:00
2020-10-11 11:56:33 +02:00
DealWithWeaponChangeAtEndOfFrenzy();
2019-07-07 09:13:04 +02:00
if (bStandardSoundAndMessages)
DMAudio.PlayFrontEndSound(SOUND_RAMPAGE_PASSED, 0);
2019-07-04 22:31:21 +02:00
}
}
2020-10-11 11:56:33 +02:00
void
CDarkel::DealWithWeaponChangeAtEndOfFrenzy()
{
eWeaponType fixedWeapon;
if (WeaponType == WEAPONTYPE_UZI_DRIVEBY)
fixedWeapon = WEAPONTYPE_UZI;
else
fixedWeapon = (eWeaponType)WeaponType;
if (fixedWeapon < WEAPONTYPE_TOTALWEAPONS && InterruptedWeaponType)
CModelInfo::GetModelInfo(CWeaponInfo::GetWeaponInfo((eWeaponType)InterruptedWeaponType)->m_nModelId)->RemoveRef();
if (fixedWeapon < WEAPONTYPE_TOTALWEAPONS) {
int slot = CWeaponInfo::GetWeaponInfo(fixedWeapon)->m_nWeaponSlot;
FindPlayerPed()->RemoveWeaponModel(FindPlayerPed()->GetWeapon(slot).GetInfo()->m_nModelId);
FindPlayerPed()->GetWeapon(slot).m_eWeaponType = WEAPONTYPE_UNARMED;
FindPlayerPed()->GetWeapon(slot).m_nAmmoTotal = 0;
FindPlayerPed()->GetWeapon(slot).m_nAmmoInClip = 0;
FindPlayerPed()->GetWeapon(slot).m_eWeaponState = WEAPONSTATE_READY;
FindPlayerPed()->RemoveWeaponAnims(fixedWeapon, -1000.0f);
CModelInfo::GetModelInfo(CWeaponInfo::GetWeaponInfo(fixedWeapon)->m_nModelId)->RemoveRef();
}
CPlayerPed* player = FindPlayerPed();
if (fixedWeapon < WEAPONTYPE_TOTALWEAPONS) {
2020-10-17 11:31:14 +02:00
player->m_nSelectedWepSlot = CWeaponInfo::GetWeaponInfo((eWeaponType)InterruptedWeaponSelected)->m_nWeaponSlot;
2020-10-11 11:56:33 +02:00
player->GiveWeapon((eWeaponType)InterruptedWeaponType, AmmoInterruptedWeapon, true);
}
if (FindPlayerVehicle()) {
player->RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(player->GetWeapon()->m_eWeaponType)->m_nModelId);
if (FindPlayerPed()->GetWeapon(WEAPONSLOT_SUBMACHINEGUN).m_eWeaponType)
FindPlayerPed()->m_nSelectedWepSlot = WEAPONSLOT_SUBMACHINEGUN;
else
FindPlayerPed()->m_nSelectedWepSlot = WEAPONSLOT_UNARMED;
player->SetCurrentWeapon(FindPlayerPed()->m_nSelectedWepSlot);
player->MakeChangesForNewWeapon(player->m_currentWeapon);
//player->RemoveDriveByAnims(); // TODO(MIAMI)
}
}