mirror of
https://github.com/electronicarts/CnC_Renegade.git
synced 2025-12-15 23:21:40 -05:00
Initial commit of Command & Conquer Renegade source code.
This commit is contained in:
471
Code/Combat/playerdata.cpp
Normal file
471
Code/Combat/playerdata.cpp
Normal file
@@ -0,0 +1,471 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** Confidential - Westwood Studios ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Commando *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/Combat/playerdata.cpp $*
|
||||
* *
|
||||
* $Author:: Byon_g $*
|
||||
* *
|
||||
* $Modtime:: 3/29/02 3:40p $*
|
||||
* *
|
||||
* $Revision:: 38 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "playerdata.h"
|
||||
#include "debug.h"
|
||||
#include "chunkio.h"
|
||||
#include "wwpacket.h"
|
||||
#include "persistfactory.h"
|
||||
#include "combatchunkid.h"
|
||||
#include "combat.h"
|
||||
#include "hud.h"
|
||||
#include "soldier.h"
|
||||
#include "systeminfolog.h"
|
||||
#include "stackdump.h"
|
||||
|
||||
/*
|
||||
**
|
||||
*/
|
||||
PlayerDataClass::PlayerDataClass( void ) :
|
||||
Score( 0 ),
|
||||
Money( 0 ),
|
||||
PunishTimer( 0 )
|
||||
{
|
||||
Stats_Reset();
|
||||
}
|
||||
|
||||
PlayerDataClass::~PlayerDataClass( void )
|
||||
{
|
||||
PlayerInfoLog::Append_To_Log(this);
|
||||
if ( Get_GameObj() ) {
|
||||
Get_GameObj()->Set_Player_Data( NULL );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
*/
|
||||
enum {
|
||||
CHUNKID_VARIABLES = 201011247,
|
||||
CHUNKID_STATS_WEAPON,
|
||||
|
||||
MICROCHUNKID_SCORE = 1,
|
||||
MICROCHUNKID_MONEY,
|
||||
MICROCHUNKID_STAT_TIME_IN_GAME,
|
||||
MICROCHUNKID_STAT_ENEMIES_KILLED,
|
||||
MICROCHUNKID_STAT_ALLIES_KILLED,
|
||||
MICROCHUNKID_STAT_SHOTS_FIRED,
|
||||
MICROCHUNKID_STAT_HEAD_SHOTS,
|
||||
MICROCHUNKID_STAT_TORSO_SHOTS,
|
||||
MICROCHUNKID_STAT_ARM_SHOTS,
|
||||
MICROCHUNKID_STAT_LEG_SHOTS,
|
||||
MICROCHUNKID_STAT_CROTCH_CHOTS,
|
||||
MICROCHUNKID_STAT_FINAL_HEALTH,
|
||||
MICROCHUNKID_STAT_POWERUPS,
|
||||
MICROCHUNKID_STAT_VEHICLES_DESTROYED,
|
||||
MICROCHUNKID_STAT_TIME_IN_VEHICLES,
|
||||
MICROCHUNKID_STAT_KILLS_FROM_VEHICLES,
|
||||
MICROCHUNKID_STAT_SQUISHES,
|
||||
MICROCHUNKID_STAT_CREDITS_GRANTED,
|
||||
MICROCHUNKID_STAT_BUILDINGS_DESTROYED,
|
||||
MICROCHUNKID_STAT_HEAD_HITS,
|
||||
MICROCHUNKID_STAT_TORSO_HITS,
|
||||
MICROCHUNKID_STAT_ARM_HITS,
|
||||
MICROCHUNKID_STAT_LEG_HITS,
|
||||
MICROCHUNKID_STAT_CROTCH_HITS,
|
||||
|
||||
MICROCHUNKID_STAT_WEAPON_ID,
|
||||
MICROCHUNKID_STAT_WEAPON_COUNT,
|
||||
};
|
||||
|
||||
bool PlayerDataClass::Save( ChunkSaveClass & csave )
|
||||
{
|
||||
csave.Begin_Chunk( CHUNKID_VARIABLES );
|
||||
WRITE_SAFE_MICRO_CHUNK( csave, MICROCHUNKID_SCORE, Score, float );
|
||||
WRITE_SAFE_MICRO_CHUNK( csave, MICROCHUNKID_MONEY, Money, float );
|
||||
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STAT_TIME_IN_GAME, StatTimeInGame );
|
||||
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STAT_ENEMIES_KILLED, StatEnemiesKilled );
|
||||
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STAT_ALLIES_KILLED, StatAlliesKilled );
|
||||
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STAT_SHOTS_FIRED, StatShotsFired );
|
||||
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STAT_HEAD_SHOTS, StatHeadShots );
|
||||
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STAT_TORSO_SHOTS, StatTorsoShots );
|
||||
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STAT_ARM_SHOTS, StatArmShots );
|
||||
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STAT_LEG_SHOTS, StatLegShots );
|
||||
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STAT_CROTCH_CHOTS, StatCrotchShots );
|
||||
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STAT_FINAL_HEALTH, StatFinalHealth );
|
||||
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STAT_POWERUPS, StatPowerups );
|
||||
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STAT_VEHICLES_DESTROYED, StatVehiclesDestroyed );
|
||||
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STAT_TIME_IN_VEHICLES, StatTimeInVehicles );
|
||||
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STAT_KILLS_FROM_VEHICLES, StatKillsFromVehicles );
|
||||
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STAT_SQUISHES, StatSquishes );
|
||||
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STAT_CREDITS_GRANTED, StatCreditsGranted );
|
||||
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STAT_BUILDINGS_DESTROYED, StatBuildingsDestroyed );
|
||||
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STAT_HEAD_HITS, StatHeadHits );
|
||||
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STAT_TORSO_HITS, StatTorsoHits );
|
||||
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STAT_ARM_HITS, StatArmHits );
|
||||
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STAT_LEG_HITS, StatLegHits );
|
||||
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STAT_CROTCH_HITS, StatCrotchHits );
|
||||
csave.End_Chunk();
|
||||
|
||||
for (int i = 0; i < StatWeaponIDFired.Count(); i++) {
|
||||
int id = StatWeaponIDFired[i];
|
||||
int count = StatWeaponFireCount[i];
|
||||
csave.Begin_Chunk( CHUNKID_STATS_WEAPON );
|
||||
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STAT_WEAPON_ID, id );
|
||||
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STAT_WEAPON_COUNT, count );
|
||||
csave.End_Chunk();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PlayerDataClass::Load( ChunkLoadClass &cload )
|
||||
{
|
||||
StatTimeInSession=0.0f;
|
||||
StatLastWeaponIndex = -1;
|
||||
WWASSERT( StatWeaponIDFired.Count() == 0 );
|
||||
WWASSERT( StatWeaponFireCount.Count() == 0 );
|
||||
|
||||
while (cload.Open_Chunk()) {
|
||||
switch(cload.Cur_Chunk_ID()) {
|
||||
|
||||
case CHUNKID_VARIABLES:
|
||||
while (cload.Open_Micro_Chunk()) {
|
||||
switch(cload.Cur_Micro_Chunk_ID()) {
|
||||
READ_SAFE_MICRO_CHUNK( cload, MICROCHUNKID_SCORE, Score, float );
|
||||
READ_SAFE_MICRO_CHUNK( cload, MICROCHUNKID_MONEY, Money, float );
|
||||
READ_MICRO_CHUNK( cload, MICROCHUNKID_STAT_TIME_IN_GAME, StatTimeInGame );
|
||||
READ_MICRO_CHUNK( cload, MICROCHUNKID_STAT_ENEMIES_KILLED, StatEnemiesKilled );
|
||||
READ_MICRO_CHUNK( cload, MICROCHUNKID_STAT_ALLIES_KILLED, StatAlliesKilled );
|
||||
READ_MICRO_CHUNK( cload, MICROCHUNKID_STAT_SHOTS_FIRED, StatShotsFired );
|
||||
READ_MICRO_CHUNK( cload, MICROCHUNKID_STAT_HEAD_SHOTS, StatHeadShots );
|
||||
READ_MICRO_CHUNK( cload, MICROCHUNKID_STAT_TORSO_SHOTS, StatTorsoShots );
|
||||
READ_MICRO_CHUNK( cload, MICROCHUNKID_STAT_ARM_SHOTS, StatArmShots );
|
||||
READ_MICRO_CHUNK( cload, MICROCHUNKID_STAT_LEG_SHOTS, StatLegShots );
|
||||
READ_MICRO_CHUNK( cload, MICROCHUNKID_STAT_CROTCH_CHOTS, StatCrotchShots );
|
||||
READ_MICRO_CHUNK( cload, MICROCHUNKID_STAT_FINAL_HEALTH, StatFinalHealth );
|
||||
READ_MICRO_CHUNK( cload, MICROCHUNKID_STAT_POWERUPS, StatPowerups );
|
||||
READ_MICRO_CHUNK( cload, MICROCHUNKID_STAT_VEHICLES_DESTROYED, StatVehiclesDestroyed );
|
||||
READ_MICRO_CHUNK( cload, MICROCHUNKID_STAT_TIME_IN_VEHICLES, StatTimeInVehicles );
|
||||
READ_MICRO_CHUNK( cload, MICROCHUNKID_STAT_KILLS_FROM_VEHICLES, StatKillsFromVehicles );
|
||||
READ_MICRO_CHUNK( cload, MICROCHUNKID_STAT_SQUISHES, StatSquishes );
|
||||
READ_MICRO_CHUNK( cload, MICROCHUNKID_STAT_CREDITS_GRANTED, StatCreditsGranted );
|
||||
READ_MICRO_CHUNK( cload, MICROCHUNKID_STAT_BUILDINGS_DESTROYED, StatBuildingsDestroyed );
|
||||
READ_MICRO_CHUNK( cload, MICROCHUNKID_STAT_HEAD_HITS, StatHeadHits );
|
||||
READ_MICRO_CHUNK( cload, MICROCHUNKID_STAT_TORSO_HITS, StatTorsoHits );
|
||||
READ_MICRO_CHUNK( cload, MICROCHUNKID_STAT_ARM_HITS, StatArmHits );
|
||||
READ_MICRO_CHUNK( cload, MICROCHUNKID_STAT_LEG_HITS, StatLegHits );
|
||||
READ_MICRO_CHUNK( cload, MICROCHUNKID_STAT_CROTCH_HITS, StatCrotchHits );
|
||||
default:
|
||||
Debug_Say(("Unhandled Micro Chunk:%d File:%s Line:%d\r\n",cload.Cur_Micro_Chunk_ID(),__FILE__,__LINE__));
|
||||
break;
|
||||
}
|
||||
cload.Close_Micro_Chunk();
|
||||
}
|
||||
break;
|
||||
|
||||
case CHUNKID_STATS_WEAPON:
|
||||
{
|
||||
int id = 0;
|
||||
int count = 0;
|
||||
|
||||
while (cload.Open_Micro_Chunk()) {
|
||||
switch(cload.Cur_Micro_Chunk_ID()) {
|
||||
READ_MICRO_CHUNK( cload, MICROCHUNKID_STAT_WEAPON_ID, id );
|
||||
READ_MICRO_CHUNK( cload, MICROCHUNKID_STAT_WEAPON_COUNT, count );
|
||||
|
||||
default:
|
||||
Debug_Say(("Unhandled Micro Chunk:%d File:%s Line:%d\r\n",cload.Cur_Micro_Chunk_ID(),__FILE__,__LINE__));
|
||||
break;
|
||||
}
|
||||
cload.Close_Micro_Chunk();
|
||||
}
|
||||
|
||||
WWASSERT( id != 0 );
|
||||
StatWeaponIDFired.Add(id);
|
||||
StatWeaponFireCount.Add(count);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
Debug_Say(("Unhandled Chunk:%d File:%s Line:%d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
|
||||
break;
|
||||
|
||||
}
|
||||
cload.Close_Chunk();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlayerDataClass::Reset_Player(void)
|
||||
{
|
||||
Stats_Reset();
|
||||
Set_Score( 0 );
|
||||
Set_Money( 0 );
|
||||
}
|
||||
|
||||
void PlayerDataClass::Increment_Score( float add )
|
||||
{
|
||||
if (!CombatManager::Is_Gameplay_Permitted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Look out for very big increments
|
||||
//
|
||||
static int warning_num = 0;
|
||||
if (add >= 10000 && ++warning_num < 10) {
|
||||
WWDEBUG_SAY(("* PlayerDataClass::Increment_Score(%10.2f) - is this ok?\n", add));
|
||||
LOG_CALL_STACK;
|
||||
}
|
||||
|
||||
Score = (float)Score + add;
|
||||
|
||||
//
|
||||
// TSS101001 - let's try giving 1 credit per point
|
||||
//
|
||||
if (add > 0) {
|
||||
Increment_Money(add);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerDataClass::Increment_Money( float add )
|
||||
{
|
||||
if (add > 0 && !CombatManager::Is_Gameplay_Permitted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Look out for very big increments
|
||||
//
|
||||
#pragma message ("(gth) this caused a crash and seems like debugging code so I'm disabling it...")
|
||||
#if 0
|
||||
static int warning_num = 0;
|
||||
if (add >= 10000 && ++warning_num < 10) {
|
||||
WWDEBUG_SAY(("* PlayerDataClass::Increment_Money(%f) - is this ok?\n", add));
|
||||
LOG_CALL_STACK;
|
||||
}
|
||||
#endif
|
||||
|
||||
Money = (float)Money + add;
|
||||
|
||||
if ( add > 0 ) {
|
||||
Stats_Add_Credit_Grant( (int) add );
|
||||
}
|
||||
|
||||
//Set_Object_Dirty_Bit(NetworkObjectClass::BIT_OCCASIONAL, true);
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
*/
|
||||
void PlayerDataClass::Apply_Damage_Points( float points, DamageableGameObj * victim )
|
||||
{
|
||||
//Increment_Score( ::fabs(points) );
|
||||
Increment_Score( points );
|
||||
|
||||
// If this is the star's PlayerData, display the points on the HUD
|
||||
if ( COMBAT_STAR && COMBAT_STAR->Get_Player_Data() == this ) {
|
||||
HUDClass::Display_Points( points );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void PlayerDataClass::Apply_Death_Points( float points, DamageableGameObj * victim )
|
||||
{
|
||||
Increment_Score( points );
|
||||
|
||||
if ( Get_GameObj() == COMBAT_STAR && COMBAT_STAR != NULL ) {
|
||||
HUDClass::Display_Points( points );
|
||||
}
|
||||
}
|
||||
|
||||
bool PlayerDataClass::Purchase_Item( int cost )
|
||||
{
|
||||
bool retval = false;
|
||||
|
||||
if (cost >= 0) {
|
||||
|
||||
//
|
||||
// Check to ensure the player has enough cash
|
||||
//
|
||||
float money = (float)Money;
|
||||
if (money >= cost) {
|
||||
/*
|
||||
money -= cost;
|
||||
Money = money;
|
||||
*/
|
||||
//
|
||||
// Use Increment_Money so that dirty is set.
|
||||
//
|
||||
Increment_Money(-1 * cost);
|
||||
|
||||
retval = true;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Import_Rare
|
||||
//
|
||||
void PlayerDataClass::Import_Occasional( BitStreamClass & packet )
|
||||
{
|
||||
//
|
||||
// Get the score and money from the server
|
||||
//
|
||||
|
||||
float score = packet.Get(score);
|
||||
Score = score;
|
||||
|
||||
float money = packet.Get(money);
|
||||
Money = money;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Export_Rare
|
||||
//
|
||||
void PlayerDataClass::Export_Occasional( BitStreamClass & packet )
|
||||
{
|
||||
//
|
||||
// Transmit the score and money
|
||||
//
|
||||
packet.Add ((float)Score);
|
||||
packet.Add ((float)Money);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Stats
|
||||
*/
|
||||
void PlayerDataClass::Stats_Reset( void )
|
||||
{
|
||||
StatTimeInGame = 0.0f;
|
||||
StatTimeInSession = 0.0f;
|
||||
StatEnemiesKilled = 0;
|
||||
StatAlliesKilled = 0;
|
||||
StatShotsFired = 0;
|
||||
StatHeadShots = 0;
|
||||
StatTorsoShots = 0;
|
||||
StatArmShots = 0;
|
||||
StatLegShots = 0;
|
||||
StatCrotchShots = 0;
|
||||
StatFinalHealth = 0;
|
||||
StatPowerups = 0;
|
||||
StatVehiclesDestroyed = 0;
|
||||
StatTimeInVehicles = 0;
|
||||
StatKillsFromVehicles = 0;
|
||||
StatSquishes = 0;
|
||||
StatCreditsGranted = 0;
|
||||
StatBuildingsDestroyed = 0;
|
||||
StatHeadHits = 0;
|
||||
StatTorsoHits = 0;
|
||||
StatArmHits = 0;
|
||||
StatLegHits = 0;
|
||||
StatCrotchHits = 0;
|
||||
|
||||
StatLastWeaponIndex = -1;
|
||||
StatWeaponIDFired.Delete_All();
|
||||
StatWeaponFireCount.Delete_All();
|
||||
}
|
||||
|
||||
void PlayerDataClass::Stats_Add_Weapon_Fired( int weapon_id )
|
||||
{
|
||||
// Check for using same weapon as last time
|
||||
if ((StatLastWeaponIndex >= 0) && (StatWeaponIDFired[StatLastWeaponIndex] == weapon_id)) {
|
||||
StatWeaponFireCount[StatLastWeaponIndex]++;
|
||||
return;
|
||||
}
|
||||
|
||||
// See if we already have this weapon
|
||||
for (int i = 0; i < StatWeaponIDFired.Count(); i++) {
|
||||
if (StatWeaponIDFired[i] == weapon_id) {
|
||||
StatLastWeaponIndex = i;
|
||||
StatWeaponFireCount[StatLastWeaponIndex]++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Add this new weapon
|
||||
StatLastWeaponIndex = StatWeaponIDFired.Count();
|
||||
StatWeaponIDFired.Add(weapon_id);
|
||||
StatWeaponFireCount.Add(1);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
int PlayerDataClass::Get_Weapon_Fired_Count(void) const
|
||||
{
|
||||
return StatWeaponIDFired.Count();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
bool PlayerDataClass::Get_Weapon_Fired(int index, unsigned long& weaponID, unsigned long& firedCount) const
|
||||
{
|
||||
if ((index >= 0) && (index < StatWeaponIDFired.Count())) {
|
||||
weaponID = (unsigned long)StatWeaponIDFired[index];
|
||||
firedCount = (unsigned long)StatWeaponFireCount[index];
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
bool PlayerDataClass::Purchase_Item( int cost )
|
||||
{
|
||||
bool retval = false;
|
||||
|
||||
//
|
||||
// Check to ensure the player has enough cash
|
||||
//
|
||||
int score = (int)Score;
|
||||
if (score >= cost) {
|
||||
score -= cost;
|
||||
Score = score;
|
||||
retval = true;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user