Files
source/Laptop/CampaignStats.cpp
T

805 lines
24 KiB
C++

/**
* @file
* @author Flugente (bears-pit.com)
*/
#include "CampaignStats.h"
#include "message.h"
#include "SaveLoadGame.h"
#include "GameVersion.h"
#include "Campaign Types.h"
#include "Game Clock.h"
#include "Soldier macros.h"
#include "Text.h"
#include "Laptop.h"
#include "LaptopSave.h"
#include "email.h"
#include "DynamicDialogue.h"
Campaign_Stats gCampaignStats;
Incident_Stats gCurrentIncident; // we might save during an incident, thus we have to store the ongoing incident
CAMPAIGNSTATSEVENT zCampaignStatsEvent[NUM_CAMPAIGNSTATSEVENTS];
void
Incident_Stats::clear()
{
usID = 0;
usTime = 0;
usSector = 0;
usLevel = 0;
usInterestRating = 0;
usNPCDied = 0;
usCivFactionFought = 0;
usIncidentFlags = 0;
usOneTimeEventFlags = 0;
for (UINT8 i = 0; i < CAMPAIGNHISTORY_SD_MAX; ++i)
{
usKills[i] = 0;
usWounds[i] = 0;
usPrisoners[i] = 0;
usShots[i] = 0;
usParticipants[i] = 0;
usPromotions[i] = 0;
}
}
// determine how 'interesting' an incident is - the more happens, the more interesting it is
void
Incident_Stats::CalcInterestRating()
{
usInterestRating = 0;
for (UINT8 i = 0; i < CAMPAIGNHISTORY_SD_MAX; ++i)
{
usInterestRating += 100 * usKills[i];
usInterestRating += 50 * usWounds[i];
usInterestRating += 75 * usPrisoners[i];
usInterestRating += usShots[i] / 30;
usInterestRating += 20 * usParticipants[i];
usInterestRating += 5 * usPromotions[i];
}
if ( usNPCDied )
usInterestRating += 500;
if ( usCivFactionFought )
usInterestRating += 1000;
// evaluate flags
if ( usIncidentFlags & INCIDENT_ARTILLERY_ENEMY ) usInterestRating += 500;
if ( usIncidentFlags & INCIDENT_ARTILLERY_PLAYERSIDE ) usInterestRating += 500;
if ( usIncidentFlags & INCIDENT_TANKS_ENEMY ) usInterestRating += 1000;
if ( usIncidentFlags & INCIDENT_TANKS_PLAYERSIDE ) usInterestRating += 2000;
if ( usIncidentFlags & INCIDENT_MUSTARDGAS_ENEMY ) usInterestRating += 500;
if ( usIncidentFlags & INCIDENT_MUSTARDGAS_PLAYERSIDE ) usInterestRating += 500;
if ( usIncidentFlags & INCIDENT_ATTACK_ENEMY ) usInterestRating += 200;
if ( usIncidentFlags & INCIDENT_ATTACK_PLAYERSIDE ) usInterestRating += 100;
if ( usIncidentFlags & INCIDENT_REINFORCEMENTS_ENEMY ) usInterestRating += 500;
if ( usIncidentFlags & INCIDENT_REINFORCEMENTS_PLAYERSIDE ) usInterestRating += 500;
if ( usIncidentFlags & INCIDENT_SNIPERS_ENEMY ) usInterestRating += 200;
if ( usIncidentFlags & INCIDENT_SNIPERS_PLAYERSIDE ) usInterestRating += 100;
if ( usIncidentFlags & INCIDENT_AMBUSH ) usInterestRating += 100;
if ( usIncidentFlags & INCIDENT_AIRDROP ) usInterestRating += 100;
if ( usIncidentFlags & INCIDENT_SURGERY ) usInterestRating += 50;
if ( usIncidentFlags & INCIDENT_BUILDINGS_DAMAGED ) usInterestRating += 100;
if ( usIncidentFlags & INCIDENT_WIN ) usInterestRating += 100;
else usInterestRating += 200;
if ( usIncidentFlags & INCIDENT_SAMSITE_SABOTAGED ) usInterestRating += 1500;
if ( usOneTimeEventFlags & INCIDENT_ONETIMEEVENT_OMERTA ) usInterestRating += 1000;
if ( usOneTimeEventFlags & INCIDENT_ONETIMEEVENT_DEATH_KINGPIN ) usInterestRating += 500;
if ( usOneTimeEventFlags & (INCIDENT_ONETIMEEVENT_MASSACRE_HICKS|INCIDENT_ONETIMEEVENT_MASSACRE_BLOODCATS) ) usInterestRating += 800;
if ( usOneTimeEventFlags & INCIDENT_ONETIMEEVENT_CITY_RETAKEN ) usInterestRating += 2000;
if ( usOneTimeEventFlags & INCIDENT_ONETIMEEVENT_CITY_LIBERATED ) usInterestRating += 1000;
}
BOOLEAN
Incident_Stats::Save( HWFILE hFile )
{
UINT32 uiNumBytesWritten = 0;
if ( !FileWrite( hFile, this, SIZEOF_INCIDENT_STATS_POD, &uiNumBytesWritten ) )
{
return(FALSE);
}
return( TRUE );
}
BOOLEAN
Incident_Stats::Load( HWFILE hwFile )
{
if(guiCurrentSaveGameVersion >= CAMPAIGNSTATS)
{
UINT32 numBytesRead = 0;
numBytesRead = ReadFieldByField(hwFile, &usID, sizeof(usID), sizeof(UINT32), numBytesRead);
numBytesRead = ReadFieldByField(hwFile, &usTime, sizeof(usTime), sizeof(UINT32), numBytesRead);
numBytesRead = ReadFieldByField(hwFile, &usSector, sizeof(usSector), sizeof(UINT8), numBytesRead);
numBytesRead = ReadFieldByField(hwFile, &usLevel, sizeof(usLevel), sizeof(UINT8), numBytesRead);
numBytesRead = ReadFieldByField(hwFile, &usInterestRating, sizeof(usInterestRating), sizeof(UINT32), numBytesRead);
numBytesRead = ReadFieldByField(hwFile, &usNPCDied, sizeof(usNPCDied), sizeof(UINT8), numBytesRead);
numBytesRead = ReadFieldByField(hwFile, &usCivFactionFought, sizeof(usCivFactionFought), sizeof(UINT8), numBytesRead);
numBytesRead = ReadFieldByField(hwFile, &usIncidentFlags, sizeof(usIncidentFlags), sizeof(UINT64), numBytesRead);
numBytesRead = ReadFieldByField(hwFile, &usOneTimeEventFlags, sizeof(usOneTimeEventFlags),sizeof(UINT64), numBytesRead);
numBytesRead = ReadFieldByField(hwFile, &usKills, sizeof(usKills), sizeof(UINT16), numBytesRead);
numBytesRead = ReadFieldByField(hwFile, &usWounds, sizeof(usWounds), sizeof(UINT16), numBytesRead);
numBytesRead = ReadFieldByField(hwFile, &usPrisoners, sizeof(usPrisoners), sizeof(UINT16), numBytesRead);
numBytesRead = ReadFieldByField(hwFile, &usShots, sizeof(usShots), sizeof(UINT16), numBytesRead);
numBytesRead = ReadFieldByField(hwFile, &usParticipants, sizeof(usParticipants), sizeof(UINT16), numBytesRead);
numBytesRead = ReadFieldByField(hwFile, &usPromotions, sizeof(usPromotions), sizeof(UINT16), numBytesRead);
numBytesRead = ReadFieldByField(hwFile, &usFiller, sizeof(usFiller), sizeof(UINT8), numBytesRead);
if( numBytesRead != SIZEOF_INCIDENT_STATS_POD )
return(FALSE);
}
return( TRUE );
}
void
Incident_Stats::AddStat( SOLDIERTYPE* pSoldier, UINT8 aType )
{
UINT8 group = CAMPAIGNHISTORY_SD_MERC;
if ( pSoldier )
{
switch ( pSoldier->bTeam )
{
case OUR_TEAM:
group = CAMPAIGNHISTORY_SD_MERC;
break;
case ENEMY_TEAM:
{
if ( ARMED_VEHICLE( pSoldier ) || ENEMYROBOT( pSoldier ) )
group = CAMPAIGNHISTORY_SD_ENEMY_TANK;
else if ( pSoldier->ubSoldierClass == SOLDIER_CLASS_ADMINISTRATOR )
group = CAMPAIGNHISTORY_SD_ENEMY_ADMIN;
else if ( pSoldier->ubSoldierClass == SOLDIER_CLASS_ELITE )
group = CAMPAIGNHISTORY_SD_ENEMY_ELITE;
else if ( pSoldier->ubSoldierClass == SOLDIER_CLASS_ARMY )
group = CAMPAIGNHISTORY_SD_ENEMY_ARMY;
}
break;
case CREATURE_TEAM:
if ( pSoldier->IsZombie() )
group = CAMPAIGNHISTORY_SD_ZOMBIE;
else if ( pSoldier->ubSoldierClass == SOLDIER_CLASS_BANDIT )
group = CAMPAIGNHISTORY_SD_ENEMY_ADMIN;
else
group = CAMPAIGNHISTORY_SD_CREATURE;
break;
case MILITIA_TEAM:
{
if ( pSoldier->ubSoldierClass == SOLDIER_CLASS_GREEN_MILITIA )
group = CAMPAIGNHISTORY_SD_MILITIA_GREEN;
else if ( pSoldier->ubSoldierClass == SOLDIER_CLASS_REG_MILITIA )
group = CAMPAIGNHISTORY_SD_MILITIA_REGULAR;
else if ( pSoldier->ubSoldierClass == SOLDIER_CLASS_ELITE_MILITIA )
group = CAMPAIGNHISTORY_SD_MILITIA_ELITE;
}
break;
case CIV_TEAM:
default:
group = CAMPAIGNHISTORY_SD_CIV;
break;
}
if ( ARMED_VEHICLE( pSoldier ) )
{
if ( pSoldier->bSide == 0 )
usIncidentFlags |= INCIDENT_TANKS_PLAYERSIDE;
else
usIncidentFlags |= INCIDENT_TANKS_ENEMY;
}
}
switch ( aType )
{
case CAMPAIGNHISTORY_TYPE_KILL:
{
usKills[group]++;
if ( pSoldier )
{
if ( pSoldier->ubProfile == KINGPIN )
usOneTimeEventFlags |= INCIDENT_ONETIMEEVENT_DEATH_KINGPIN;
else if ( pSoldier->ubProfile == DARREL )
usOneTimeEventFlags |= INCIDENT_ONETIMEEVENT_MASSACRE_HICKS;
}
}
break;
case CAMPAIGNHISTORY_TYPE_WOUND:
usWounds[group]++;
break;
case CAMPAIGNHISTORY_TYPE_PRISONER:
usPrisoners[group]++;
break;
case CAMPAIGNHISTORY_TYPE_SHOT:
usShots[group]++;
break;
case CAMPAIGNHISTORY_TYPE_PARTICIPANT:
usParticipants[group]++;
break;
case CAMPAIGNHISTORY_TYPE_PROMOTION:
default:
usPromotions[group]++;
break;
}
}
UINT8 tmpnr = 0;
static CHAR16 tmpdirstring[2][ 50 ]; // we need 2 arrays, in case we need 2 name pointers in one string
STR16
Incident_Stats::GetAttackerDirString( BOOLEAN fAttacker )
{
CHAR16 helperstr[ 50 ];
swprintf(helperstr, L"" );
++tmpnr;
if ( tmpnr > 1 )
tmpnr = 0;
tmpdirstring[tmpnr][0] = '\0' ;
UINT8 dirs = 0;
CHAR16 dir1[ 10 ], dir2[ 10 ], dir3[ 10 ], dir4[ 10 ];
swprintf(dir1, L"" );
swprintf(dir2, L"" );
swprintf(dir3, L"" );
swprintf(dir4, L"" );
if ( (fAttacker && usIncidentFlags & INCIDENT_ATTACK_ENEMY) || (!fAttacker && usIncidentFlags & INCIDENT_ATTACK_PLAYERSIDE) )
{
if ( usIncidentFlags & INCIDENT_ATTACKDIR_NORTH_ENEMY )
{
swprintf(dir1, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_NORTH] );
++dirs;
if ( usIncidentFlags & INCIDENT_ATTACKDIR_WEST_ENEMY )
{
swprintf(dir2, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_WEST] );
++dirs;
if ( usIncidentFlags & INCIDENT_ATTACKDIR_SOUTH_ENEMY )
{
swprintf(dir3, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_SOUTH] );
++dirs;
if ( usIncidentFlags & INCIDENT_ATTACKDIR_EAST_ENEMY )
{
swprintf(dir4, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_EAST] );
++dirs;
}
}
else if ( usIncidentFlags & INCIDENT_ATTACKDIR_EAST_ENEMY )
{
swprintf(dir3, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_EAST] );
++dirs;
}
}
else if ( usIncidentFlags & INCIDENT_ATTACKDIR_SOUTH_ENEMY )
{
swprintf(dir2, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_SOUTH] );
++dirs;
if ( usIncidentFlags & INCIDENT_ATTACKDIR_EAST_ENEMY )
{
swprintf(dir3, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_EAST] );
++dirs;
}
}
else if ( usIncidentFlags & INCIDENT_ATTACKDIR_EAST_ENEMY )
{
swprintf(dir2, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_EAST] );
++dirs;
}
}
else if ( usIncidentFlags & INCIDENT_ATTACKDIR_WEST_ENEMY )
{
swprintf(dir1, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_WEST] );
++dirs;
if ( usIncidentFlags & INCIDENT_ATTACKDIR_SOUTH_ENEMY )
{
swprintf(dir2, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_SOUTH] );
++dirs;
if ( usIncidentFlags & INCIDENT_ATTACKDIR_EAST_ENEMY )
{
swprintf(dir3, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_EAST] );
++dirs;
}
}
else if ( usIncidentFlags & INCIDENT_ATTACKDIR_EAST_ENEMY )
{
swprintf(dir2, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_EAST] );
++dirs;
}
}
else if ( usIncidentFlags & INCIDENT_ATTACKDIR_SOUTH_ENEMY )
{
swprintf(dir1, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_SOUTH] );
++dirs;
if ( usIncidentFlags & INCIDENT_ATTACKDIR_EAST_ENEMY )
{
swprintf(dir2, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_EAST] );
++dirs;
}
}
else if ( usIncidentFlags & INCIDENT_ATTACKDIR_EAST_ENEMY )
{
swprintf(dir1, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_EAST] );
++dirs;
}
}
else
{
if ( usIncidentFlags & INCIDENT_ATTACKDIR_NORTH )
{
swprintf(dir1, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_NORTH] );
++dirs;
if ( usIncidentFlags & INCIDENT_ATTACKDIR_WEST )
{
swprintf(dir2, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_WEST] );
++dirs;
if ( usIncidentFlags & INCIDENT_ATTACKDIR_SOUTH )
{
swprintf(dir3, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_SOUTH] );
++dirs;
if ( usIncidentFlags & INCIDENT_ATTACKDIR_EAST )
{
swprintf(dir4, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_EAST] );
++dirs;
}
}
else if ( usIncidentFlags & INCIDENT_ATTACKDIR_EAST )
{
swprintf(dir3, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_EAST] );
++dirs;
}
}
else if ( usIncidentFlags & INCIDENT_ATTACKDIR_SOUTH )
{
swprintf(dir2, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_SOUTH] );
++dirs;
if ( usIncidentFlags & INCIDENT_ATTACKDIR_EAST )
{
swprintf(dir3, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_EAST] );
++dirs;
}
}
else if ( usIncidentFlags & INCIDENT_ATTACKDIR_EAST )
{
swprintf(dir2, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_EAST] );
++dirs;
}
}
else if ( usIncidentFlags & INCIDENT_ATTACKDIR_WEST )
{
swprintf(dir1, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_WEST] );
++dirs;
if ( usIncidentFlags & INCIDENT_ATTACKDIR_SOUTH )
{
swprintf(dir2, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_SOUTH] );
++dirs;
if ( usIncidentFlags & INCIDENT_ATTACKDIR_EAST )
{
swprintf(dir3, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_EAST] );
++dirs;
}
}
else if ( usIncidentFlags & INCIDENT_ATTACKDIR_EAST )
{
swprintf(dir2, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_EAST] );
++dirs;
}
}
else if ( usIncidentFlags & INCIDENT_ATTACKDIR_SOUTH )
{
swprintf(dir1, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_SOUTH] );
++dirs;
if ( usIncidentFlags & INCIDENT_ATTACKDIR_EAST )
{
swprintf(dir2, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_EAST] );
++dirs;
}
}
else if ( usIncidentFlags & INCIDENT_ATTACKDIR_EAST )
{
swprintf(dir1, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_EAST] );
++dirs;
}
}
switch ( dirs )
{
case 4:
swprintf(helperstr, L"%s, %s, %s %s %s", dir1, dir2, dir3, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_AND], dir4 );
break;
case 3:
swprintf(helperstr, L"%s, %s %s %s", dir1, dir2, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_AND], dir3 );
break;
case 2:
swprintf(helperstr, L"%s %s %s", dir1, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_AND], dir2 );
break;
case 1:
swprintf(helperstr, L"%s", dir1 );
break;
case 0:
swprintf(helperstr, szCampaignHistoryDetail[TEXT_CAMPAIGNHISTORY_DETAIL_UNKNOWNLOCATION] );
break;
default:
break;
}
wcscat( tmpdirstring[tmpnr], helperstr );
return tmpdirstring[tmpnr];
}
void
Incident_Stats::GetTerrainandType(UINT8& arTerrain, UINT8& arType)
{
if ( usLevel > 0 )
arTerrain = CAMPAINGHISTORY_PICLIBRARY_TERRAIN_UNDERGROUND;
else
{
SECTORINFO *pSector = &SectorInfo[ usSector ];
switch( pSector->ubTraversability[ THROUGH_STRATEGIC_MOVE ] )
{
case COASTAL:
case COASTAL_ROAD:
case WATER:
arTerrain = CAMPAINGHISTORY_PICLIBRARY_TERRAIN_COASTAL;
break;
case SAND:
case SAND_ROAD:
case SAND_SAM_SITE:
arTerrain = CAMPAINGHISTORY_PICLIBRARY_TERRAIN_DESERT;
break;
case DENSE:
case DENSE_ROAD:
arTerrain = CAMPAINGHISTORY_PICLIBRARY_TERRAIN_FOREST;
break;
case GROUNDBARRIER:
case EDGEOFWORLD:
case HILLS:
case HILLS_ROAD:
arTerrain = CAMPAINGHISTORY_PICLIBRARY_TERRAIN_MOUNTAIN;
break;
case NS_RIVER:
case EW_RIVER:
arTerrain = CAMPAINGHISTORY_PICLIBRARY_TERRAIN_RIVER;
break;
case SWAMP:
case SWAMP_ROAD:
arTerrain = CAMPAINGHISTORY_PICLIBRARY_TERRAIN_SWAMP;
break;
case TROPICS:
case TROPICS_ROAD:
case TROPICS_SAM_SITE:
arTerrain = CAMPAINGHISTORY_PICLIBRARY_TERRAIN_TROPICAL;
break;
case TOWN:
case MEDUNA_SAM_SITE:
case CAMBRIA_HOSPITAL_SITE:
case DRASSEN_AIRPORT_SITE:
case MEDUNA_AIRPORT_SITE:
case SAM_SITE:
case REBEL_HIDEOUT:
case TIXA_DUNGEON:
case CREATURE_LAIR:
case ORTA_BASEMENT:
case TUNNEL:
case SHELTER:
case ABANDONED_MINE:
arTerrain = CAMPAINGHISTORY_PICLIBRARY_TERRAIN_URBAN;
break;
case ROAD:
case PLAINS:
case SPARSE:
case FARMLAND:
case PLAINS_ROAD:
case SPARSE_ROAD:
case FARMLAND_ROAD:
case SPARSE_SAM_SITE:
default:
arTerrain = CAMPAINGHISTORY_PICLIBRARY_TERRAIN_SPARSE;
break;
}
}
if ( usIncidentFlags & INCIDENT_AIRDROP )
arType = CAMPAINGHISTORY_PICLIBRARY_TYPE_AIRDROP;
else if ( usIncidentFlags & (INCIDENT_TANKS_ENEMY|INCIDENT_TANKS_PLAYERSIDE) )
arType = CAMPAINGHISTORY_PICLIBRARY_TYPE_TANKS;
else if ( usIncidentFlags & INCIDENT_WIN )
arType = CAMPAINGHISTORY_PICLIBRARY_TYPE_WIN;
else
arType = CAMPAINGHISTORY_PICLIBRARY_TYPE_LOSS;
}
Campaign_Stats::Campaign_Stats()
{
//*mspSelf = *this;
}
Campaign_Stats::~Campaign_Stats()
{
//if ( mspSelf )
//delete mspSelf;
}
/*Campaign_Stats*
Campaign_Stats::GetObject()
{
if ( !mspSelf )
mspSelf = new Campaign_Stats;
return mspSelf;
}*/
void
Campaign_Stats::clear()
{
memset(this, 0, SIZEOF_CAMPAIGN_STATS_POD);
mIncidentVector.clear();
}
BOOLEAN
Campaign_Stats::Save( HWFILE hFile )
{
if(guiCurrentSaveGameVersion >= CAMPAIGNSTATS)
{
UINT32 uiNumBytesWritten = 0;
if ( !FileWrite( hFile, this, SIZEOF_CAMPAIGN_STATS_POD, &uiNumBytesWritten ) )
return(FALSE);
std::vector<Incident_Stats>::iterator itend = mIncidentVector.end();
for (std::vector<Incident_Stats>::iterator it = mIncidentVector.begin(); it != itend; ++it)
{
if ( !(*it).Save ( hFile ) )
return(FALSE);
}
}
return( TRUE );
}
BOOLEAN
Campaign_Stats::Load( HWFILE hwFile )
{
if(guiCurrentSaveGameVersion >= CAMPAIGNSTATS)
{
clear();
UINT32 numBytesRead = 0;
numBytesRead = ReadFieldByField(hwFile, &usKills, sizeof(usKills), sizeof(UINT32), numBytesRead);
numBytesRead = ReadFieldByField(hwFile, &usWounds, sizeof(usWounds), sizeof(UINT32), numBytesRead);
numBytesRead = ReadFieldByField(hwFile, &usPrisoners, sizeof(usPrisoners), sizeof(UINT32), numBytesRead);
numBytesRead = ReadFieldByField(hwFile, &usShots, sizeof(usShots), sizeof(UINT32), numBytesRead);
numBytesRead = ReadFieldByField(hwFile, &sMoneyEarned, sizeof(sMoneyEarned), sizeof(INT32), numBytesRead);
numBytesRead = ReadFieldByField(hwFile, &usConsumed, sizeof(usConsumed), sizeof(FLOAT), numBytesRead);
numBytesRead = ReadFieldByField(hwFile, &usNumIncidents, sizeof(usNumIncidents), sizeof(UINT32), numBytesRead);
numBytesRead = ReadFieldByField(hwFile, &usHighestID, sizeof(usHighestID), sizeof(UINT32), numBytesRead);
numBytesRead = ReadFieldByField(hwFile, &usFiller, sizeof(usFiller), sizeof(UINT8), numBytesRead);
if( numBytesRead != SIZEOF_CAMPAIGN_STATS_POD )
return(FALSE);
for (UINT32 i = 0; i < usNumIncidents; ++i)
{
Incident_Stats incident;
if ( !incident.Load ( hwFile ) )
return(FALSE);
// if option is active, only read the last reports and forget the rest
if ( gGameExternalOptions.usReportsToLoad < 0 || i >= usNumIncidents - gGameExternalOptions.usReportsToLoad )
mIncidentVector.push_back(incident);
}
// re-evaluate the vector size - we may have been ordered to forget some
usNumIncidents = mIncidentVector.size();
}
return( TRUE );
}
// Warning! As this also updates the overall kill counters, don't use this function when loading incidents
void
Campaign_Stats::AddNewIncident(Incident_Stats arIncident)
{
// make sure interest rating is up to date
arIncident.CalcInterestRating();
mIncidentVector.push_back(arIncident);
++usNumIncidents;
// update kills/wounds/prisoner numbers
for (UINT16 i = 0; i < CAMPAIGNHISTORY_SD_MAX; ++i)
{
usKills[i] += arIncident.usKills[i];
usWounds[i] += arIncident.usWounds[i];
usPrisoners[i] += arIncident.usPrisoners[i];
usShots[i] += arIncident.usShots[i];
}
}
void
Campaign_Stats::AddMoneyEarned(UINT8 aType, INT32 aVal)
{
if ( aType >= CAMPAIGN_MONEY_MAX )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Error: Unknown money type!" );
return;
}
sMoneyEarned[aType] += aVal;
}
void
Campaign_Stats::AddConsumption(UINT8 aType, FLOAT aVal)
{
if ( aType >= CAMPAIGN_CONSUMED_MAX )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Error: Unknown consumption type!" );
return;
}
usConsumed[aType] += aVal;
}
// add this incident to the campaign stats and then clear it
void FinishIncident(INT16 sX, INT16 sY, INT8 sZ)
{
// it is possible to enter a combat without any real fighting.
// For now, lets just assume this happens with undetected spies. If nothing of interest happened, don't add this incident (it would be boring to read anyway)
if ( gCurrentIncident.usIncidentFlags & (INCIDENT_SPYACTION_ENEMY|INCIDENT_SPYACTION_PLAYERSIDE) && !(gCurrentIncident.usIncidentFlags & INCIDENT_SPYACTION_UNCOVERED) )
{
// if noting of interest happened...
if ( !(gCurrentIncident.usIncidentFlags & INCIDENT_EVENT) && gCurrentIncident.usOneTimeEventFlags == 0 )
{
UINT16 i = 0;
// if nobody was harmed...
for (i = 0; i < CAMPAIGNHISTORY_SD_MAX; ++i)
{
if ( gCurrentIncident.usKills[i] || gCurrentIncident.usWounds[i] || gCurrentIncident.usPrisoners[i] )
break;
}
if ( i == CAMPAIGNHISTORY_SD_MAX )
{
// totally boring. Don't add this, just clean it and exit
gCurrentIncident.clear();
return;
}
}
}
// due to odd coding, we do not know when an incident starts
// (checking for entering combat isn't enough, as we do that multiple times per battle)
// we thus set the relevant data when finishing an incident
gCampaignStats.usHighestID++;
gCurrentIncident.usID = gCampaignStats.usHighestID;
gCurrentIncident.usTime = GetWorldTotalSeconds();
gCurrentIncident.usSector = SECTOR(sX, sY);
gCurrentIncident.usLevel = sZ;
// add flags depending on quests etc.
// if this is incident 1, we just landed - special text then
if ( gCampaignStats.usHighestID == 1 )
gCurrentIncident.usOneTimeEventFlags |= INCIDENT_ONETIMEEVENT_OMERTA;
// dynamic opinions
if (gGameExternalOptions.fDynamicOpinions)
{
HandleDynamicOpinionBattleFinished((gCurrentIncident.usIncidentFlags & INCIDENT_WIN) != 0);
}
gCampaignStats.AddNewIncident(gCurrentIncident);
// reset incident after adding it
gCurrentIncident.clear();
}
// start a new incident
void StartIncident(INT16 sX, INT16 sY, INT8 sZ)
{
gCampaignStats.usHighestID++;
gCurrentIncident.usID = gCampaignStats.usHighestID;
gCurrentIncident.usTime = GetWorldTotalSeconds();
gCurrentIncident.usSector = SECTOR(sX, sY);
gCurrentIncident.usLevel = sZ;
}
INT32 GetPositionOfIncident( UINT32 aIncidentId )
{
INT32 cnt = 0;
std::vector<Incident_Stats>::iterator itend = gCampaignStats.mIncidentVector.end( );
for ( std::vector<Incident_Stats>::iterator it = gCampaignStats.mIncidentVector.begin( ); it != itend; ++it )
{
if ( (*it).usID == aIncidentId )
return cnt;
++cnt;
}
return -1;
}
static CHAR16 gIncidentNameText[100];
STR16 GetIncidentName( UINT32 aIncidentId )
{
swprintf( gIncidentNameText, L"NAME NOT FOUND" );
std::vector<Incident_Stats>::iterator itend = gCampaignStats.mIncidentVector.end( );
for ( std::vector<Incident_Stats>::iterator it = gCampaignStats.mIncidentVector.begin( ); it != itend; ++it )
{
if ( (*it).usID == aIncidentId )
{
Incident_Stats incident = (*it);
UINT32 prefix = (incident.usTime + incident.usKills[CAMPAIGNHISTORY_SD_ENEMY_ARMY] + incident.usID) % CAMPAIGNSTATS_OPERATION_NUM_PREFIX;
UINT32 suffix = (incident.usTime + incident.usShots[CAMPAIGNHISTORY_SD_MERC] + 7 * incident.usID) % CAMPAIGNSTATS_OPERATION_NUM_SUFFIX;
swprintf( gIncidentNameText, szCampaignStatsOperationPrefix[prefix], szCampaignStatsOperationSuffix[suffix] );
break;
}
}
return gIncidentNameText;
}
UINT32 GetIdOfCurrentlyOngoingIncident()
{
return gCampaignStats.usHighestID + 1;
}