#include "common.h" #include "Stats.h" #include "Text.h" #include "World.h" #include "Pad.h" #include "DMAudio.h" #include "main.h" #include "Font.h" #include "Frontend.h" #include int32 CStats::SeagullsKilled; int32 CStats::BoatsExploded; int32 CStats::WantedStarsAttained; int32 CStats::WantedStarsEvaded; int32 CStats::DaysPassed; int32 CStats::HeadsPopped; int32 CStats::CommercialPassed; int32 CStats::IndustrialPassed; int32 CStats::SuburbanPassed; int32 CStats::NumberKillFrenziesPassed; int32 CStats::PeopleKilledByOthers; int32 CStats::HelisDestroyed; int32 CStats::PedsKilledOfThisType[NUM_PEDTYPES]; int32 CStats::TimesDied; int32 CStats::TimesArrested; int32 CStats::KillsSinceLastCheckpoint; float CStats::DistanceTravelledByCar; float CStats::DistanceTravelledByHelicoptor; float CStats::DistanceTravelledByBike; float CStats::DistanceTravelledByBoat; float CStats::DistanceTravelledByPlane; float CStats::DistanceTravelledByGolfCart; float CStats::DistanceTravelledOnFoot; int32 CStats::FlightTime; int32 CStats::TimesDrowned; int32 CStats::PhotosTaken; float CStats::LoanSharks; float CStats::StoresKnockedOff; float CStats::MovieStunts; float CStats::Assassinations; float CStats::PizzasDelivered; float CStats::GarbagePickups; float CStats::IceCreamSold; float CStats::TopShootingRangeScore; float CStats::ShootingRank; int32 CStats::ProgressMade; int32 CStats::TotalProgressInGame; int32 CStats::CarsExploded; int32 CStats::PeopleKilledByPlayer; float CStats::MaximumJumpDistance; float CStats::MaximumJumpHeight; int32 CStats::MaximumJumpFlips; int32 CStats::MaximumJumpSpins; int32 CStats::BestStuntJump; int32 CStats::NumberOfUniqueJumpsFound; int32 CStats::TotalNumberOfUniqueJumps; int32 CStats::PassengersDroppedOffWithTaxi; int32 CStats::MoneyMadeWithTaxi; int32 CStats::MissionsGiven; int32 CStats::MissionsPassed; char CStats::LastMissionPassedName[8]; int32 CStats::TotalLegitimateKills; int32 CStats::LivesSavedWithAmbulance; int32 CStats::CriminalsCaught; int32 CStats::HighestLevelAmbulanceMission; int32 CStats::HighestLevelVigilanteMission; int32 CStats::HighestLevelFireMission; int32 CStats::FiresExtinguished; int32 CStats::TotalNumberKillFrenzies; int32 CStats::TotalNumberMissions; int32 CStats::RoundsFiredByPlayer; int32 CStats::KgsOfExplosivesUsed; int32 CStats::BulletsThatHit; int32 CStats::BestTimeBombDefusal; int32 CStats::FastestTimes[CStats::TOTAL_FASTEST_TIMES]; int32 CStats::HighestScores[CStats::TOTAL_HIGHEST_SCORES]; int32 CStats::BestPositions[CStats::TOTAL_BEST_POSITIONS]; bool CStats::PropertyOwned[CStats::TOTAL_PROPERTIES]; int32 CStats::NumPropertyOwned; int32 CStats::PropertyDestroyed; float CStats::HighestChaseValue; int32 CStats::CheatedCount; int32 CStats::ShowChaseStatOnScreen; int32 CStats::PamphletMissionPassed; bool CStats::abSonyCDs[1]; int32 CStats::BloodRingKills; int32 CStats::BloodRingTime; float CStats::FavoriteRadioStationList[NUM_RADIOS]; int32 CStats::Sprayings; float CStats::AutoPaintingBudget; int32 CStats::NoMoreHurricanes; float CStats::FashionBudget; float CStats::PropertyBudget; float CStats::WeaponBudget; int32 CStats::SafeHouseVisits; int32 CStats::TyresPopped; int32 CStats::LongestWheelie; int32 CStats::LongestStoppie; int32 CStats::Longest2Wheel; float CStats::LongestWheelieDist; float CStats::LongestStoppieDist; float CStats::Longest2WheelDist; // --MIAMI: functions below are done, but there are some to be moved from Frontend void CStats::Init() { PeopleKilledByOthers = 0; PeopleKilledByPlayer = 0; CarsExploded = 0; BoatsExploded = 0; RoundsFiredByPlayer = 0; for (int i = 0; i < NUM_PEDTYPES; i++) PedsKilledOfThisType[i] = 0; HelisDestroyed = 0; ProgressMade = 0; KgsOfExplosivesUsed = 0; BulletsThatHit = 0; TyresPopped = 0; HeadsPopped = 0; WantedStarsAttained = 0; WantedStarsEvaded = 0; TimesArrested = 0; TimesDied = 0; DaysPassed = 0; SafeHouseVisits = 0; Sprayings = 0; MaximumJumpDistance = 0; MaximumJumpHeight = 0; MaximumJumpFlips = 0; MaximumJumpSpins = 0; BestStuntJump = 0; NumberOfUniqueJumpsFound = 0; TotalNumberOfUniqueJumps = 0; MissionsGiven = 0; MissionsPassed = 0; PassengersDroppedOffWithTaxi = 0; MoneyMadeWithTaxi = 0; DistanceTravelledOnFoot = 0; DistanceTravelledByCar = 0; DistanceTravelledByBike = 0; DistanceTravelledByBoat = 0; DistanceTravelledByGolfCart = 0; DistanceTravelledByHelicoptor = 0; #ifdef FIX_BUGS DistanceTravelledByPlane = 0; #endif LivesSavedWithAmbulance = 0; CriminalsCaught = 0; HighestLevelVigilanteMission = 0; HighestLevelAmbulanceMission = 0; HighestLevelFireMission = 0; FiresExtinguished = 0; PhotosTaken = 0; NumberKillFrenziesPassed = 0; TotalNumberKillFrenzies = 0; TotalNumberMissions = 0; FlightTime = 0; TimesDrowned = 0; SeagullsKilled = 0; WeaponBudget = 0.0f; FashionBudget = 0.0f; LoanSharks = 0.0f; StoresKnockedOff = 0.0f; MovieStunts = 0.0f; Assassinations = 0.0f; PizzasDelivered = 0.0f; GarbagePickups = 0.0f; IceCreamSold = 0.0f; TopShootingRangeScore = 0.0f; ShootingRank = 0.0f; LongestWheelie = 0; LongestStoppie = 0; Longest2Wheel = 0; LongestWheelieDist = 0.0f; LongestStoppieDist = 0.0f; Longest2WheelDist = 0.0f; PropertyBudget = 0.0f; AutoPaintingBudget = 0.0f; PropertyDestroyed = 0; HighestChaseValue = 0.0f; CheatedCount = 0; for (int i = 0; i < TOTAL_FASTEST_TIMES; i++) FastestTimes[i] = 0; for (int i = 0; i < TOTAL_HIGHEST_SCORES; i++) HighestScores[i] = 0; for (int i = 0; i < TOTAL_BEST_POSITIONS; i++) BestPositions[i] = INT_MAX; KillsSinceLastCheckpoint = 0; TotalLegitimateKills = 0; for (int i = 0; i < ARRAY_SIZE(LastMissionPassedName); i++) LastMissionPassedName[i] = 0; IndustrialPassed = 0; CommercialPassed = 0; SuburbanPassed = 0; PamphletMissionPassed = 0; NoMoreHurricanes = 0; ShowChaseStatOnScreen = 0; for (int i = 0; i < ARRAY_SIZE(abSonyCDs); i++) abSonyCDs[i] = 0; PopulateFavoriteRadioStationList(); NumPropertyOwned = 0; for (int i = 0; i < TOTAL_PROPERTIES; i++) PropertyOwned[i] = false; BloodRingKills = 0; BloodRingTime = 0; } void CStats::RegisterFastestTime(int32 index, int32 time) { assert(index >= 0 && index < TOTAL_FASTEST_TIMES); if (FastestTimes[index] == 0) FastestTimes[index] = time; else FastestTimes[index] = Min(FastestTimes[index], time); } void CStats::RegisterHighestScore(int32 index, int32 score) { assert(index >= 0 && index < TOTAL_HIGHEST_SCORES); HighestScores[index] = Max(HighestScores[index], score); } void CStats::RegisterBestPosition(int32 index, int32 position) { assert(index >= 0 && index < TOTAL_BEST_POSITIONS); BestPositions[index] = Min(BestPositions[index], position); } void CStats::AnotherLifeSavedWithAmbulance() { ++LivesSavedWithAmbulance; } void CStats::AnotherCriminalCaught() { ++CriminalsCaught; } void CStats::RegisterLevelAmbulanceMission(int32 level) { HighestLevelAmbulanceMission = Max(HighestLevelAmbulanceMission, level); } void CStats::RegisterLevelVigilanteMission(int32 level) { HighestLevelVigilanteMission = Max(HighestLevelVigilanteMission, level); } void CStats::RegisterLevelFireMission(int32 level) { HighestLevelFireMission = Max(HighestLevelFireMission, level); } void CStats::AnotherFireExtinguished() { ++FiresExtinguished; } void CStats::AnotherKillFrenzyPassed() { ++NumberKillFrenziesPassed; } void CStats::SetTotalNumberKillFrenzies(int32 total) { TotalNumberKillFrenzies = total; } void CStats::SetTotalNumberMissions(int32 total) { TotalNumberMissions = total; } wchar *CStats::FindCriminalRatingString() { int rating = FindCriminalRatingNumber(); if (rating < 0) { if (rating > -500) return TheText.Get("RATNG53"); if (rating > -2000) return TheText.Get("RATNG54"); if (rating > -4000) return TheText.Get("RATNG55"); if (rating > -6000) return TheText.Get("RATNG56"); return TheText.Get("RATNG57"); } if (rating < 20) return TheText.Get("RATNG1"); if (rating < 50) return TheText.Get("RATNG2"); if (rating < 75) return TheText.Get("RATNG3"); if (rating < 100) return TheText.Get("RATNG4"); if (rating < 120) return TheText.Get("RATNG5"); if (rating < 150) return TheText.Get("RATNG6"); if (rating < 200) return TheText.Get("RATNG7"); if (rating < 240) return TheText.Get("RATNG8"); if (rating < 270) return TheText.Get("RATNG9"); if (rating < 300) return TheText.Get("RATNG10"); if (rating < 335) return TheText.Get("RATNG11"); if (rating < 370) return TheText.Get("RATNG12"); if (rating < 400) return TheText.Get("RATNG13"); if (rating < 450) return TheText.Get("RATNG14"); if (rating < 500) return TheText.Get("RATNG15"); if (rating < 550) return TheText.Get("RATNG16"); if (rating < 600) return TheText.Get("RATNG17"); if (rating < 610) return TheText.Get("RATNG18"); if (rating < 650) return TheText.Get("RATNG19"); if (rating < 700) return TheText.Get("RATNG20"); if (rating < 850) return TheText.Get("RATNG21"); if (rating < 1000) return TheText.Get("RATNG22"); if (rating < 1005) return TheText.Get("RATNG23"); if (rating < 1150) return TheText.Get("RATNG24"); if (rating < 1300) return TheText.Get(TimesArrested > 0 ? "RATNG25" : "RATNG24"); if (rating < 1500) return TheText.Get("RATNG26"); if (rating < 1700) return TheText.Get("RATNG27"); if (rating < 2000) return TheText.Get("RATNG28"); if (rating < 2100) return TheText.Get("RATNG29"); if (rating < 2300) return TheText.Get("RATNG30"); if (rating < 2500) return TheText.Get("RATNG31"); if (rating < 2750) return TheText.Get("RATNG32"); if (rating < 3000) return TheText.Get("RATNG33"); if (rating < 3500) return TheText.Get("RATNG34"); if (rating < 4000) return TheText.Get("RATNG35"); if (rating < 5000) return TheText.Get("RATNG36"); if (rating < 7500) return TheText.Get("RATNG37"); if (rating < 10000) return TheText.Get("RATNG38"); if (rating < 20000) return TheText.Get("RATNG39"); if (rating < 30000) return TheText.Get("RATNG40"); if (rating < 40000) return TheText.Get("RATNG41"); if (rating < 50000) return TheText.Get("RATNG42"); if (rating < 65000) return TheText.Get("RATNG43"); if (rating < 80000) return TheText.Get("RATNG44"); if (rating < 100000) return TheText.Get("RATNG45"); if (rating < 150000) return TheText.Get("RATNG46"); if (rating < 200000) return TheText.Get("RATNG47"); if (rating < 300000) return TheText.Get("RATNG48"); if (rating < 375000) return TheText.Get("RATNG49"); if (rating < 500000) return TheText.Get(FlightTime / 60000 / 60 > 10 ? "RATNG50" : "RATNG49"); if (rating < 1000000) return TheText.Get("RATNG51"); return TheText.Get(CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney > 10000000 ? "RATNG52" : "RATNG51"); } wchar *CStats::FindChaseString(float fMediaLevel) { if (fMediaLevel < 20.0f) return TheText.Get("MEDIA1"); if (fMediaLevel < 50.0f) return TheText.Get("MEDIA2"); if (fMediaLevel < 75.0f) return TheText.Get("MEDIA3"); if (fMediaLevel < 100.0f) return TheText.Get("MEDIA4"); if (fMediaLevel < 150.0f) return TheText.Get("MEDIA5"); if (fMediaLevel < 200.0f) return TheText.Get("MEDIA6"); if (fMediaLevel < 250.0f) return TheText.Get("MEDIA7"); if (fMediaLevel < 300.0f) return TheText.Get("MEDIA8"); if (fMediaLevel < 350.0f) return TheText.Get("MEDIA9"); if (fMediaLevel < 400.0f) return TheText.Get("MEDIA10"); if (fMediaLevel < 500.0f) return TheText.Get("MEDIA11"); if (fMediaLevel < 600.0f) return TheText.Get("MEDIA12"); if (fMediaLevel < 700.0f) return TheText.Get("MEDIA13"); if (fMediaLevel < 800.0f) return TheText.Get("MEDIA14"); if (fMediaLevel < 900.0f) return TheText.Get("MEDIA15"); if (fMediaLevel < 1000.0f) return TheText.Get("MEDIA16"); if (fMediaLevel < 1200.0f) return TheText.Get("MEDIA17"); if (fMediaLevel < 1400.0f) return TheText.Get("MEDIA18"); if (fMediaLevel < 1600.0f) return TheText.Get("MEDIA19"); if (fMediaLevel < 1800.0f) return TheText.Get("MEDIA20"); return TheText.Get("MEDIA21"); } int32 CStats::FindCriminalRatingNumber() { int32 rating; rating = FiresExtinguished + 10 * HighestLevelFireMission + 10 * HighestLevelAmbulanceMission + CriminalsCaught + LivesSavedWithAmbulance + 30 * HelisDestroyed + TotalLegitimateKills - 3 * TimesArrested - 3 * TimesDied + CWorld::Players[CWorld::PlayerInFocus].m_nMoney / 5000; if (CPad::bHasPlayerCheated || CheatedCount > 0) { rating -= CheatedCount; if (rating <= -10000) rating = -10000; } else if (rating <= 0) { rating = 0; } if (RoundsFiredByPlayer > 100) rating += (float)CStats::BulletsThatHit / (float)CStats::RoundsFiredByPlayer * 500.0f; if (TotalProgressInGame) rating += (float)CStats::ProgressMade / (float)CStats::TotalProgressInGame * 1000.0f; return rating; } float CStats::GetPercentageProgress() { float percentCompleted = (CStats::TotalProgressInGame == 0 ? 0 : CStats::ProgressMade * 100.0f / (CGame::nastyGame ? CStats::TotalProgressInGame : CStats::TotalProgressInGame - 1.0f)); return Min(percentCompleted, 100.0f); } void CStats::MoneySpentOnWeapons(int32 money) { WeaponBudget += money; } void CStats::MoneySpentOnProperty(int32 money) { PropertyBudget += money; } void CStats::MoneySpentOnAutoPainting(int32 money) { AutoPaintingBudget += money; } void CStats::MoneySpentOnFashion(int32 money) { FashionBudget += money; } void CStats::NumOfVisitsFromLoanSharks(int32 num) { LoanSharks += num; } void CStats::NumOfStoresKnockedOff(int32 num) { StoresKnockedOff += num; } void CStats::NumOfMovieStunts(int32 num) { MovieStunts += num; } void CStats::NumOfAssassinations(int32 num) { Assassinations += num; } void CStats::NumOfPizzasDelivered(int32 num) { PizzasDelivered += num; } void CStats::NumOfGarbagePickups(int32 num) { GarbagePickups += num; } void CStats::NumOfIceCreamSold(int32 num) { IceCreamSold += num; } void CStats::AddNumBloodRingKills(int32 num) { BloodRingKills += num; } void CStats::LongestTimeInBloodRing(int32 time) { if (BloodRingTime < time) BloodRingTime = time; } void CStats::AddPropertyAsOwned(int32 id) { if (!PropertyOwned[id]) { PropertyOwned[id] = true; ++NumPropertyOwned; } } float CStats::GetFavoriteRadioStationList(int32 station) { return FavoriteRadioStationList[station]; } void CStats::SaveStats(uint8 *buf, uint32 *size) { CheckPointReachedSuccessfully(); uint8 *buf_start = buf; *size = sizeof(PeopleKilledByPlayer) + sizeof(PeopleKilledByOthers) + sizeof(CarsExploded) + sizeof(BoatsExploded) + sizeof(TyresPopped) + sizeof(RoundsFiredByPlayer) + sizeof(PedsKilledOfThisType) + sizeof(HelisDestroyed) + sizeof(ProgressMade) + sizeof(TotalProgressInGame) + sizeof(KgsOfExplosivesUsed) + sizeof(BulletsThatHit) + sizeof(HeadsPopped) + sizeof(WantedStarsAttained) + sizeof(WantedStarsEvaded) + sizeof(TimesArrested) + sizeof(TimesDied) + sizeof(DaysPassed) + sizeof(SafeHouseVisits) + sizeof(Sprayings) + sizeof(MaximumJumpDistance) + sizeof(MaximumJumpHeight) + sizeof(MaximumJumpFlips) + sizeof(MaximumJumpSpins) + sizeof(BestStuntJump) + sizeof(NumberOfUniqueJumpsFound) + sizeof(TotalNumberOfUniqueJumps) + sizeof(MissionsGiven) + sizeof(PassengersDroppedOffWithTaxi) + sizeof(MoneyMadeWithTaxi) + sizeof(IndustrialPassed) + sizeof(CommercialPassed) + sizeof(SuburbanPassed) + sizeof(PamphletMissionPassed) + sizeof(NoMoreHurricanes) + sizeof(DistanceTravelledOnFoot) + sizeof(DistanceTravelledByCar) + sizeof(DistanceTravelledByBike) + sizeof(DistanceTravelledByBoat) + sizeof(DistanceTravelledByGolfCart) + sizeof(DistanceTravelledByHelicoptor) + sizeof(DistanceTravelledByPlane) + sizeof(LivesSavedWithAmbulance) + sizeof(CriminalsCaught) + sizeof(FiresExtinguished) + sizeof(HighestLevelVigilanteMission) + sizeof(HighestLevelAmbulanceMission) + sizeof(HighestLevelFireMission) + sizeof(PhotosTaken) + sizeof(NumberKillFrenziesPassed) + sizeof(TotalNumberKillFrenzies) + sizeof(TotalNumberMissions) + sizeof(FlightTime) + sizeof(TimesDrowned) + sizeof(SeagullsKilled) + sizeof(WeaponBudget) + sizeof(FashionBudget) + sizeof(LoanSharks) + sizeof(StoresKnockedOff) + sizeof(MovieStunts) + sizeof(Assassinations) + sizeof(PizzasDelivered) + sizeof(GarbagePickups) + sizeof(IceCreamSold) + sizeof(TopShootingRangeScore) + sizeof(ShootingRank) + sizeof(LongestWheelie) + sizeof(LongestStoppie) + sizeof(Longest2Wheel) + sizeof(LongestWheelieDist) + sizeof(LongestStoppieDist) + sizeof(Longest2WheelDist) + sizeof(PropertyBudget) + sizeof(AutoPaintingBudget) + sizeof(PropertyDestroyed) + sizeof(NumPropertyOwned) + sizeof(BloodRingKills) + sizeof(BloodRingTime) + sizeof(PropertyOwned) + sizeof(HighestChaseValue) + sizeof(FastestTimes) + sizeof(HighestScores) + sizeof(BestPositions) + sizeof(KillsSinceLastCheckpoint) + sizeof(TotalLegitimateKills) + sizeof(LastMissionPassedName) + sizeof(CheatedCount) + sizeof(FavoriteRadioStationList); #define CopyToBuf(buf, data) memcpy(buf, &data, sizeof(data)); buf += sizeof(data); CopyToBuf(buf, PeopleKilledByPlayer); CopyToBuf(buf, PeopleKilledByOthers); CopyToBuf(buf, CarsExploded); CopyToBuf(buf, BoatsExploded); CopyToBuf(buf, TyresPopped); CopyToBuf(buf, RoundsFiredByPlayer); CopyToBuf(buf, PedsKilledOfThisType); CopyToBuf(buf, HelisDestroyed); CopyToBuf(buf, ProgressMade); CopyToBuf(buf, TotalProgressInGame); CopyToBuf(buf, KgsOfExplosivesUsed); CopyToBuf(buf, BulletsThatHit); CopyToBuf(buf, HeadsPopped); CopyToBuf(buf, WantedStarsAttained); CopyToBuf(buf, WantedStarsEvaded); CopyToBuf(buf, TimesArrested); CopyToBuf(buf, TimesDied); CopyToBuf(buf, DaysPassed); CopyToBuf(buf, SafeHouseVisits); CopyToBuf(buf, Sprayings); CopyToBuf(buf, MaximumJumpDistance); CopyToBuf(buf, MaximumJumpHeight); CopyToBuf(buf, MaximumJumpFlips); CopyToBuf(buf, MaximumJumpSpins); CopyToBuf(buf, BestStuntJump); CopyToBuf(buf, NumberOfUniqueJumpsFound); CopyToBuf(buf, TotalNumberOfUniqueJumps); CopyToBuf(buf, MissionsGiven); CopyToBuf(buf, PassengersDroppedOffWithTaxi); CopyToBuf(buf, MoneyMadeWithTaxi); CopyToBuf(buf, IndustrialPassed); CopyToBuf(buf, CommercialPassed); CopyToBuf(buf, SuburbanPassed); CopyToBuf(buf, PamphletMissionPassed); CopyToBuf(buf, NoMoreHurricanes); CopyToBuf(buf, DistanceTravelledOnFoot); CopyToBuf(buf, DistanceTravelledByCar); CopyToBuf(buf, DistanceTravelledByBike); CopyToBuf(buf, DistanceTravelledByBoat); CopyToBuf(buf, DistanceTravelledByGolfCart); CopyToBuf(buf, DistanceTravelledByHelicoptor); CopyToBuf(buf, DistanceTravelledByPlane); CopyToBuf(buf, LivesSavedWithAmbulance); CopyToBuf(buf, CriminalsCaught); CopyToBuf(buf, FiresExtinguished); CopyToBuf(buf, HighestLevelVigilanteMission); CopyToBuf(buf, HighestLevelAmbulanceMission); CopyToBuf(buf, HighestLevelFireMission); CopyToBuf(buf, PhotosTaken); CopyToBuf(buf, NumberKillFrenziesPassed); CopyToBuf(buf, TotalNumberKillFrenzies); CopyToBuf(buf, TotalNumberMissions); CopyToBuf(buf, FlightTime); CopyToBuf(buf, TimesDrowned); CopyToBuf(buf, SeagullsKilled); CopyToBuf(buf, WeaponBudget); CopyToBuf(buf, FashionBudget); CopyToBuf(buf, LoanSharks); CopyToBuf(buf, StoresKnockedOff); CopyToBuf(buf, MovieStunts); CopyToBuf(buf, Assassinations); CopyToBuf(buf, PizzasDelivered); CopyToBuf(buf, GarbagePickups); CopyToBuf(buf, IceCreamSold); CopyToBuf(buf, TopShootingRangeScore); CopyToBuf(buf, ShootingRank); CopyToBuf(buf, LongestWheelie); CopyToBuf(buf, LongestStoppie); CopyToBuf(buf, Longest2Wheel); CopyToBuf(buf, LongestWheelieDist); CopyToBuf(buf, LongestStoppieDist); CopyToBuf(buf, Longest2WheelDist); CopyToBuf(buf, PropertyBudget); CopyToBuf(buf, AutoPaintingBudget); CopyToBuf(buf, PropertyDestroyed); CopyToBuf(buf, NumPropertyOwned); CopyToBuf(buf, BloodRingKills); CopyToBuf(buf, BloodRingTime); CopyToBuf(buf, PropertyOwned); CopyToBuf(buf, HighestChaseValue); CopyToBuf(buf, FastestTimes); CopyToBuf(buf, HighestScores); CopyToBuf(buf, BestPositions); CopyToBuf(buf, KillsSinceLastCheckpoint); CopyToBuf(buf, TotalLegitimateKills); CopyToBuf(buf, LastMissionPassedName); CopyToBuf(buf, CheatedCount); PopulateFavoriteRadioStationList(); CopyToBuf(buf, FavoriteRadioStationList); assert(buf - buf_start == *size); #undef CopyToBuf } void CStats::LoadStats(uint8 *buf, uint32 size) { uint8* buf_start = buf; #define CopyFromBuf(buf, data) memcpy(&data, buf, sizeof(data)); buf += sizeof(data); CopyFromBuf(buf, PeopleKilledByPlayer); CopyFromBuf(buf, PeopleKilledByOthers); CopyFromBuf(buf, CarsExploded); CopyFromBuf(buf, BoatsExploded); CopyFromBuf(buf, TyresPopped); CopyFromBuf(buf, RoundsFiredByPlayer); CopyFromBuf(buf, PedsKilledOfThisType); CopyFromBuf(buf, HelisDestroyed); CopyFromBuf(buf, ProgressMade); CopyFromBuf(buf, TotalProgressInGame); CopyFromBuf(buf, KgsOfExplosivesUsed); CopyFromBuf(buf, BulletsThatHit); CopyFromBuf(buf, HeadsPopped); CopyFromBuf(buf, WantedStarsAttained); CopyFromBuf(buf, WantedStarsEvaded); CopyFromBuf(buf, TimesArrested); CopyFromBuf(buf, TimesDied); CopyFromBuf(buf, DaysPassed); CopyFromBuf(buf, SafeHouseVisits); CopyFromBuf(buf, Sprayings); CopyFromBuf(buf, MaximumJumpDistance); CopyFromBuf(buf, MaximumJumpHeight); CopyFromBuf(buf, MaximumJumpFlips); CopyFromBuf(buf, MaximumJumpSpins); CopyFromBuf(buf, BestStuntJump); CopyFromBuf(buf, NumberOfUniqueJumpsFound); CopyFromBuf(buf, TotalNumberOfUniqueJumps); CopyFromBuf(buf, MissionsGiven); CopyFromBuf(buf, PassengersDroppedOffWithTaxi); CopyFromBuf(buf, MoneyMadeWithTaxi); CopyFromBuf(buf, IndustrialPassed); CopyFromBuf(buf, CommercialPassed); CopyFromBuf(buf, SuburbanPassed); CopyFromBuf(buf, PamphletMissionPassed); CopyFromBuf(buf, NoMoreHurricanes); CopyFromBuf(buf, DistanceTravelledOnFoot); CopyFromBuf(buf, DistanceTravelledByCar); CopyFromBuf(buf, DistanceTravelledByBike); CopyFromBuf(buf, DistanceTravelledByBoat); CopyFromBuf(buf, DistanceTravelledByGolfCart); CopyFromBuf(buf, DistanceTravelledByHelicoptor); CopyFromBuf(buf, DistanceTravelledByPlane); CopyFromBuf(buf, LivesSavedWithAmbulance); CopyFromBuf(buf, CriminalsCaught); CopyFromBuf(buf, FiresExtinguished); CopyFromBuf(buf, HighestLevelVigilanteMission); CopyFromBuf(buf, HighestLevelAmbulanceMission); CopyFromBuf(buf, HighestLevelFireMission); CopyFromBuf(buf, PhotosTaken); CopyFromBuf(buf, NumberKillFrenziesPassed); CopyFromBuf(buf, TotalNumberKillFrenzies); CopyFromBuf(buf, TotalNumberMissions); CopyFromBuf(buf, FlightTime); CopyFromBuf(buf, TimesDrowned); CopyFromBuf(buf, SeagullsKilled); CopyFromBuf(buf, WeaponBudget); CopyFromBuf(buf, FashionBudget); CopyFromBuf(buf, LoanSharks); CopyFromBuf(buf, StoresKnockedOff); CopyFromBuf(buf, MovieStunts); CopyFromBuf(buf, Assassinations); CopyFromBuf(buf, PizzasDelivered); CopyFromBuf(buf, GarbagePickups); CopyFromBuf(buf, IceCreamSold); CopyFromBuf(buf, TopShootingRangeScore); CopyFromBuf(buf, ShootingRank); CopyFromBuf(buf, LongestWheelie); CopyFromBuf(buf, LongestStoppie); CopyFromBuf(buf, Longest2Wheel); CopyFromBuf(buf, LongestWheelieDist); CopyFromBuf(buf, LongestStoppieDist); CopyFromBuf(buf, Longest2WheelDist); CopyFromBuf(buf, PropertyBudget); CopyFromBuf(buf, AutoPaintingBudget); CopyFromBuf(buf, PropertyDestroyed); CopyFromBuf(buf, NumPropertyOwned); CopyFromBuf(buf, BloodRingKills); CopyFromBuf(buf, BloodRingTime); CopyFromBuf(buf, PropertyOwned); CopyFromBuf(buf, HighestChaseValue); CopyFromBuf(buf, FastestTimes); CopyFromBuf(buf, HighestScores); CopyFromBuf(buf, BestPositions); CopyFromBuf(buf, KillsSinceLastCheckpoint); CopyFromBuf(buf, TotalLegitimateKills); CopyFromBuf(buf, LastMissionPassedName); CopyFromBuf(buf, CheatedCount); CopyFromBuf(buf, FavoriteRadioStationList); assert(buf - buf_start == size); #undef CopyFromBuf } void CStats::PopulateFavoriteRadioStationList() { float* pListenTimeArray = DMAudio.GetListenTimeArray(); for (int i = 0; i < NUM_RADIOS; i++) FavoriteRadioStationList[i] = pListenTimeArray[i]; } void CStats::BuildStatLine(Const char *text, void *stat, int displayType, void *stat2, int isTime) { #define STAT_D *(int*)stat #define STAT_F *(float*)stat #define STAT2_D *(int*)stat2 #define STAT2_F *(float*)stat2 if (!text) return; gString2[0] = '\0'; if (isTime == 1) { if (*((int*)stat2) >= 10) sprintf(gString2, " %d:%d", STAT_D, STAT2_D); else sprintf(gString2, " %d:0%d", STAT_D, STAT2_D); } else if (stat2) { #ifdef MORE_LANGUAGES if (CFont::IsJapanese()) { switch (displayType) { case 0: case 4: sprintf(gString2, " %d/%d", STAT_D, STAT2_D); break; case 1: sprintf(gString2, " %.2f/%.2f", STAT_F, STAT2_F); break; case 2: sprintf(gString2, " %d%%/%d%%", STAT_D, STAT2_D); break; case 3: sprintf(gString2, " $%.2f/$%.2f", STAT_F, STAT2_F); break; default: break; } } else #endif { switch (displayType) { case 0: sprintf(gString2, " %d %s %d", STAT_D, UnicodeToAscii(TheText.Get("FEST_OO")), STAT2_D); break; case 1: sprintf(gString2, " %.2f %s %.2f", STAT_F, UnicodeToAscii(TheText.Get("FEST_OO")), STAT2_F); break; case 2: sprintf(gString2, " %d%% %s %d%%", STAT_D, UnicodeToAscii(TheText.Get("FEST_OO")), STAT2_D); break; case 3: sprintf(gString2, " $%.2f %s $%.2f", STAT_F, UnicodeToAscii(TheText.Get("FEST_OO")), STAT2_F); break; case 4: sprintf(gString2, " %d_ %s %d_", STAT_D, UnicodeToAscii(TheText.Get("FEST_OO")), STAT2_D); break; default: break; } } } else if (stat) { switch (displayType) { case 0: sprintf(gString2, "%d", STAT_D); break; case 1: sprintf(gString2, "%.2f", STAT_F); break; case 2: sprintf(gString2, "%d%%", STAT_D); break; case 3: sprintf(gString2, "$%.2f", STAT_F); break; case 4: #ifdef MORE_LANGUAGES if (CFont::IsJapanese()) sprintf(gString2, "%d", STAT_D); else #endif sprintf(gString2, "%d_", STAT_D); break; default: break; } } UnicodeStrcpy(gUString, TheText.Get(text)); CFont::FilterOutTokensFromString(gUString); AsciiToUnicode(gString2, gUString2); #undef STAT_D #undef STAT_F #undef STAT2_D #undef STAT2_F } // TODO(Miami) // rowIdx 99999 returns total numbers of rows. otherwise it returns 0. int CStats::ConstructStatLine(int rowIdx) { #define STAT_LINE(str, left, isFloat, right) \ do { \ if(counter == rowIdx){ \ BuildStatLine(str, left, isFloat ? 1 : 0, right, 0); \ return 0; \ } counter++; \ } while(0) int counter = 0, nTemp; STAT_LINE("PL_STAT", nil, false, nil); int percentCompleted = GetPercentageProgress(); STAT_LINE("PER_COM", &percentCompleted, false, nil); STAT_LINE("NMISON", &MissionsGiven, false, nil); STAT_LINE("FEST_MP", &MissionsPassed, false, &TotalNumberMissions); if (CGame::nastyGame) { STAT_LINE("FEST_RP", &NumberKillFrenziesPassed, false, &TotalNumberKillFrenzies); } CPlayerInfo &player = CWorld::Players[CWorld::PlayerInFocus]; float packagesPercent = 0.0f; if (player.m_nTotalPackages != 0) packagesPercent = player.m_nCollectedPackages * 100.0f / player.m_nTotalPackages; int nPackagesPercent = packagesPercent; STAT_LINE("PERPIC", &nPackagesPercent, false, &(nTemp = 100)); STAT_LINE("NOUNIF", &NumberOfUniqueJumpsFound, false, &TotalNumberOfUniqueJumps); STAT_LINE("DAYSPS", &DaysPassed, false, nil); if (CGame::nastyGame) { STAT_LINE("PE_WAST", &PeopleKilledByPlayer, false, nil); STAT_LINE("PE_WSOT", &PeopleKilledByOthers, false, nil); } STAT_LINE("CAR_EXP", &CarsExploded, false, nil); STAT_LINE("TM_BUST", &TimesArrested, false, nil); STAT_LINE("TM_DED", &TimesDied, false, nil); STAT_LINE("GNG_WST", &(nTemp = PedsKilledOfThisType[PEDTYPE_GANG9] + PedsKilledOfThisType[PEDTYPE_GANG8] + PedsKilledOfThisType[PEDTYPE_GANG7] + PedsKilledOfThisType[PEDTYPE_GANG6] + PedsKilledOfThisType[PEDTYPE_GANG5] + PedsKilledOfThisType[PEDTYPE_GANG4] + PedsKilledOfThisType[PEDTYPE_GANG3] + PedsKilledOfThisType[PEDTYPE_GANG2] + PedsKilledOfThisType[PEDTYPE_GANG1]), false, nil); STAT_LINE("DED_CRI", &(nTemp = PedsKilledOfThisType[PEDTYPE_CRIMINAL]), false, nil); STAT_LINE("HEL_DST", &HelisDestroyed, false, nil); STAT_LINE("KGS_EXP", &KgsOfExplosivesUsed, false, nil); if (HighestScores[0] > 0) { STAT_LINE("FEST_BB", nil, false, nil); STAT_LINE("FEST_H0", &HighestScores[0], false, nil); } if (HighestScores[4] + HighestScores[3] + HighestScores[2] + HighestScores[1] > 0) { STAT_LINE("FEST_GC", nil, false, nil); } if (HighestScores[1] > 0) { STAT_LINE("FEST_H1", &HighestScores[1], false, nil); } if (HighestScores[2] > 0) { STAT_LINE("FEST_H2", &HighestScores[2], false, nil); } if (HighestScores[3] > 0) { STAT_LINE("FEST_H3", &HighestScores[3], false, nil); } if (HighestScores[4] > 0) { STAT_LINE("FEST_H4", &HighestScores[4], false, nil); } switch (FrontEndMenuManager.m_PrefsLanguage) { case CMenuManager::LANGUAGE_AMERICAN: #ifndef USE_MEASUREMENTS_IN_METERS float fTemp; STAT_LINE("FEST_DF", &(fTemp = DistanceTravelledOnFoot * MILES_IN_METER), true, nil); STAT_LINE("FEST_DC", &(fTemp = DistanceTravelledByCar * MILES_IN_METER), true, nil); STAT_LINE("DISTBIK", &(fTemp = DistanceTravelledByBike * MILES_IN_METER), true, nil); STAT_LINE("DISTBOA", &(fTemp = DistanceTravelledByBoat * MILES_IN_METER), true, nil); STAT_LINE("DISTGOL", &(fTemp = DistanceTravelledByGolfCart * MILES_IN_METER), true, nil); STAT_LINE("DISTHEL", &(fTemp = DistanceTravelledByHelicoptor * MILES_IN_METER), true, nil); STAT_LINE("MXCARD", &(fTemp = MaximumJumpDistance * FEET_IN_METER), true, nil); STAT_LINE("MXCARJ", &(fTemp = MaximumJumpHeight * FEET_IN_METER), true, nil); break; #endif case CMenuManager::LANGUAGE_FRENCH: case CMenuManager::LANGUAGE_GERMAN: case CMenuManager::LANGUAGE_ITALIAN: case CMenuManager::LANGUAGE_SPANISH: #ifdef MORE_LANGUAGES case CMenuManager::LANGUAGE_POLISH: case CMenuManager::LANGUAGE_RUSSIAN: case CMenuManager::LANGUAGE_JAPANESE: #endif STAT_LINE("FESTDFM", &DistanceTravelledOnFoot, true, nil); STAT_LINE("FESTDCM", &DistanceTravelledByCar, true, nil); STAT_LINE("DISTBIM", &DistanceTravelledByBike, true, nil); STAT_LINE("DISTBOM", &DistanceTravelledByBoat, true, nil); STAT_LINE("DISTGOM", &DistanceTravelledByGolfCart, true, nil); STAT_LINE("DISTHEM", &DistanceTravelledByHelicoptor, true, nil); STAT_LINE("MXCARDM", &MaximumJumpDistance, true, nil); STAT_LINE("MXCARJM", &MaximumJumpHeight, true, nil); break; default: break; } STAT_LINE("MXFLIP", &MaximumJumpFlips, false, nil); STAT_LINE("MXJUMP", &MaximumJumpSpins, false, nil); STAT_LINE("BSTSTU", nil, false, nil); if (counter == rowIdx) { gUString[0] = '\0'; switch (BestStuntJump) { case 1: UnicodeStrcpy(gUString2, TheText.Get("INSTUN")); return 0; case 2: UnicodeStrcpy(gUString2, TheText.Get("PRINST")); return 0; case 3: UnicodeStrcpy(gUString2, TheText.Get("DBINST")); return 0; case 4: UnicodeStrcpy(gUString2, TheText.Get("DBPINS")); return 0; case 5: UnicodeStrcpy(gUString2, TheText.Get("TRINST")); return 0; case 6: UnicodeStrcpy(gUString2, TheText.Get("PRTRST")); return 0; case 7: UnicodeStrcpy(gUString2, TheText.Get("QUINST")); return 0; case 8: UnicodeStrcpy(gUString2, TheText.Get("PQUINS")); return 0; default: UnicodeStrcpy(gUString2, TheText.Get("NOSTUC")); return 0; } } counter++; STAT_LINE("PASDRO", &PassengersDroppedOffWithTaxi, false, nil); STAT_LINE("MONTAX", &MoneyMadeWithTaxi, false, nil); STAT_LINE("FEST_LS", &LivesSavedWithAmbulance, false, nil); STAT_LINE("FEST_HA", &HighestLevelAmbulanceMission, false, nil); STAT_LINE("FEST_CC", &CriminalsCaught, false, nil); STAT_LINE("FEST_FE", &FiresExtinguished, false, nil); STAT_LINE("DAYPLC", &(nTemp = CTimer::GetTimeInMilliseconds() + 100), false, nil); return counter; #undef STAT_LINE }