592 lines
14 KiB
C++
592 lines
14 KiB
C++
//-----------------------------------------------------------------------------
|
|
//
|
|
// $Logfile:: /EF2/Code/DLLs/game/playerheuristics.cpp $
|
|
// $Revision:: 14 $
|
|
// $Author:: Singlis $
|
|
// $Date:: 9/26/03 2:36p $
|
|
//
|
|
// Copyright (C) 2001 by Ritual Entertainment, Inc.
|
|
// All rights reserved.
|
|
//
|
|
// This source may not be distributed and/or modified without
|
|
// expressly written permission by Ritual Entertainment, Inc.
|
|
//
|
|
//
|
|
// DESCRIPTION:
|
|
|
|
#include "_pch_cpp.h"
|
|
#include "playerheuristics.h"
|
|
|
|
static fileHandle_t heuristicFile=NULL;
|
|
static str heuristicFileName=NULL;
|
|
|
|
PlayerHeuristics::PlayerHeuristics()
|
|
{
|
|
//Single Player Stats
|
|
shotsFired = 0;
|
|
shotsHit = 0;
|
|
numberOfDeaths = 0;
|
|
enemiesKilled = 0;
|
|
timeOnLevel = 0;
|
|
levelStartTime = 0;
|
|
levelEndTime = 0;
|
|
playerHealth = 0.0f;
|
|
lastLevel = "";
|
|
currentLevel = "";
|
|
|
|
shotsFiredInLevel = 0;
|
|
shotsHitInLevel = 0;
|
|
enemiesKilledInLevel = 0;
|
|
|
|
|
|
//Multiplayer Stats
|
|
ping = 0;
|
|
itemsPickedUp = 0;
|
|
specialEvents = 0;
|
|
|
|
|
|
//Skill Level
|
|
skillLevel = 0;
|
|
|
|
//Mission Objectives
|
|
numObjectives = 0;
|
|
numCompleteObjectives = 0;
|
|
numFailedObjectives = 0;
|
|
|
|
}
|
|
|
|
PlayerHeuristics::PlayerHeuristics( const PlayerHeuristics &pHeuristic )
|
|
{
|
|
//Single Player Stats
|
|
shotsFired = pHeuristic.shotsFired;
|
|
shotsHit = pHeuristic.shotsHit;
|
|
numberOfDeaths = pHeuristic.numberOfDeaths;
|
|
enemiesKilled = pHeuristic.enemiesKilled;
|
|
timeOnLevel = pHeuristic.timeOnLevel;
|
|
levelStartTime = pHeuristic.levelStartTime;
|
|
levelEndTime = pHeuristic.levelEndTime;
|
|
playerHealth = pHeuristic.playerHealth;
|
|
lastLevel = pHeuristic.lastLevel;
|
|
currentLevel = pHeuristic.currentLevel;
|
|
|
|
|
|
shotsFiredInLevel = pHeuristic.shotsFiredInLevel;
|
|
shotsHitInLevel = pHeuristic.shotsHitInLevel;
|
|
enemiesKilledInLevel = pHeuristic.enemiesKilledInLevel;
|
|
teammatesKilledInLevel = pHeuristic.teammatesKilledInLevel;
|
|
|
|
//Multiplayer Stats
|
|
ping = pHeuristic.ping;
|
|
itemsPickedUp = pHeuristic.itemsPickedUp;
|
|
specialEvents = pHeuristic.specialEvents;
|
|
|
|
//Skill Level
|
|
skillLevel = pHeuristic.skillLevel;
|
|
|
|
//Mission Objectives
|
|
numObjectives = pHeuristic.numObjectives;
|
|
numCompleteObjectives = pHeuristic.numCompleteObjectives;
|
|
numFailedObjectives = pHeuristic.numFailedObjectives;
|
|
|
|
}
|
|
|
|
PlayerHeuristics::~PlayerHeuristics()
|
|
{
|
|
|
|
}
|
|
|
|
void PlayerHeuristics::ShowHeuristics( const Player *player )
|
|
{
|
|
//Show Player Information in the console
|
|
|
|
levelEndTime = level.time;
|
|
timeOnLevel+= levelEndTime;
|
|
playerHealth = player->health;
|
|
|
|
ping = player->client->ping;
|
|
|
|
float accuracy = 0;
|
|
|
|
if ( shotsFired != 0 )
|
|
{
|
|
accuracy = (float)shotsHit / (float)shotsFired;
|
|
accuracy *= 100.0f;
|
|
}
|
|
|
|
gi.Printf( "\nPlayer Heuristics:\n");
|
|
gi.Printf( "Shots Fired: %d\n", shotsFired );
|
|
gi.Printf( "Shots Hit: %d\n", shotsHit );
|
|
gi.Printf( "Accuracy: %%%.2f\n", accuracy );
|
|
gi.Printf( "Number of Deaths: %d\n", numberOfDeaths );
|
|
gi.Printf( "Time On Level: %f\n", timeOnLevel );
|
|
gi.Printf( "Player Health: %d\n", playerHealth );
|
|
gi.Printf( "Ping: %d\n", ping );
|
|
gi.Printf( "Items Picked Up: %d\n", itemsPickedUp );
|
|
gi.Printf( "Special Events: %d\n", specialEvents );
|
|
gi.Printf( "Enemies Killed %d\n", enemiesKilled );
|
|
gi.Printf( "\n" );
|
|
gi.Printf( "Skill Level: %f\n", CalculateSkillLevel() );
|
|
|
|
gi.Printf( "\n" );
|
|
|
|
}
|
|
|
|
void PlayerHeuristics::SaveHeuristics( const Player *player )
|
|
{
|
|
str token;
|
|
str levelName;
|
|
Script script;
|
|
qboolean currentHeuristicsWritten;
|
|
PlayerHeuristics *pHeuristic;
|
|
|
|
//Precalculation for stats
|
|
levelEndTime = level.time;
|
|
timeOnLevel+= levelEndTime;
|
|
playerHealth = player->health;
|
|
ping = player->client->ping;
|
|
skillLevel = CalculateSkillLevel();
|
|
|
|
script.LoadFile( heuristicFileName );
|
|
|
|
OpenPlayerHeuristicFile();
|
|
if ( !heuristicFile )
|
|
{
|
|
script.Close();
|
|
return;
|
|
}
|
|
|
|
//Save off a copy of our current stats
|
|
pHeuristic = new PlayerHeuristics( *this );
|
|
|
|
currentHeuristicsWritten = false;
|
|
while( script.TokenAvailable( true ) )
|
|
{
|
|
token = script.GetToken(false);
|
|
|
|
//The reason we saved off our old stats, and are reading through
|
|
//is that in order to keep all the stats for all the other levels
|
|
//we need to read them all in and write them back out, just replacing
|
|
//the information we need for our current level
|
|
if ( !Q_stricmp( token.c_str(), "Level:" ) )
|
|
{
|
|
levelName = script.GetToken(false);
|
|
if ( Q_stricmp( levelName.c_str(), level.mapname.c_str() ) ) //Not Equal
|
|
{
|
|
script.UnGetToken();
|
|
ReadInHeuristicData(script, levelName);
|
|
}
|
|
else
|
|
{
|
|
|
|
//Restore Values
|
|
shotsFired = pHeuristic->shotsFired;
|
|
shotsHit = pHeuristic->shotsHit;
|
|
numberOfDeaths = pHeuristic->numberOfDeaths;
|
|
enemiesKilled = pHeuristic->enemiesKilled;
|
|
timeOnLevel = pHeuristic->timeOnLevel;
|
|
levelStartTime = pHeuristic->levelStartTime;
|
|
levelEndTime = pHeuristic->levelEndTime;
|
|
playerHealth = pHeuristic->playerHealth;
|
|
lastLevel = pHeuristic->lastLevel;
|
|
currentLevel = pHeuristic->currentLevel;
|
|
|
|
//Multiplayer Stats
|
|
ping = pHeuristic->ping;
|
|
itemsPickedUp = pHeuristic->itemsPickedUp;
|
|
specialEvents = pHeuristic->specialEvents;
|
|
|
|
|
|
//Skill Level
|
|
skillLevel = pHeuristic->skillLevel;
|
|
|
|
teammatesKilledInLevel = pHeuristic->teammatesKilledInLevel;
|
|
shotsFiredInLevel = pHeuristic->shotsFiredInLevel;
|
|
shotsHitInLevel = pHeuristic->shotsFiredInLevel;
|
|
|
|
numObjectives = pHeuristic->numObjectives;
|
|
numCompleteObjectives = pHeuristic->numCompleteObjectives;
|
|
numFailedObjectives = pHeuristic->numFailedObjectives;
|
|
|
|
|
|
|
|
currentHeuristicsWritten = true;
|
|
}
|
|
|
|
WriteOutHeuristicData(levelName);
|
|
}
|
|
}
|
|
|
|
if (!currentHeuristicsWritten)
|
|
{
|
|
currentHeuristicsWritten = true;
|
|
WriteOutHeuristicData(level.mapname);
|
|
}
|
|
|
|
ClosePlayerHeuristicFile();
|
|
}
|
|
|
|
void PlayerHeuristics::LoadHeuristics()
|
|
{
|
|
str token;
|
|
Script script;
|
|
|
|
CheckForHeuristicFile();
|
|
|
|
//Clear Heuristic Data Structure;
|
|
shotsFired = 0;
|
|
shotsHit = 0;
|
|
numberOfDeaths = 0;
|
|
enemiesKilled = 0;
|
|
timeOnLevel = 0;
|
|
levelStartTime = 0;
|
|
levelEndTime = 0;
|
|
playerHealth = 0;
|
|
|
|
ping = 0;
|
|
itemsPickedUp = 0;
|
|
specialEvents = 0;
|
|
|
|
//skillLevel = 0;
|
|
|
|
script.LoadFile( heuristicFileName );
|
|
|
|
ReadInHeuristicData(script, level.mapname);
|
|
|
|
//level.setSkill(skillLevel);
|
|
|
|
script.Close();
|
|
ClosePlayerHeuristicFile();
|
|
}
|
|
|
|
void PlayerHeuristics::ReadInHeuristicData( Script& script, str& levelName )
|
|
{
|
|
str token;
|
|
str precedingToken ;
|
|
|
|
//Fill Structure from File
|
|
while( script.TokenAvailable( true ) )
|
|
{
|
|
str heuristic;
|
|
str endSection;
|
|
token = script.GetToken( false );
|
|
|
|
if ( !Q_stricmp( token.c_str(), levelName.c_str() ) && ( precedingToken == "Level:" ) )
|
|
{
|
|
endSection = levelName + "_end";
|
|
|
|
while ( Q_stricmp( token.c_str(), endSection.c_str() ) )
|
|
{
|
|
token = script.GetToken( false );
|
|
if ( !Q_stricmp( token.c_str(), "ShotsFired:" ) )
|
|
{
|
|
heuristic = script.GetToken(false);
|
|
shotsFired = atol(heuristic.c_str());
|
|
}
|
|
else if ( !Q_stricmp( token.c_str(), "ShotsHit:" ) )
|
|
{
|
|
heuristic = script.GetToken(false);
|
|
shotsHit = atol(heuristic.c_str());
|
|
}
|
|
else if ( !Q_stricmp( token.c_str(), "NumberOfDeaths:" ) )
|
|
{
|
|
heuristic = script.GetToken(false);
|
|
numberOfDeaths = atol(heuristic.c_str());
|
|
}
|
|
else if ( !Q_stricmp( token.c_str(), "EnemiesKilled:" ) )
|
|
{
|
|
heuristic = script.GetToken(false);
|
|
enemiesKilled = atol(heuristic.c_str());
|
|
}
|
|
else if ( !Q_stricmp( token.c_str(), "TimeOnLevel:" ) )
|
|
{
|
|
heuristic = script.GetToken(false);
|
|
timeOnLevel = (float)atof(heuristic.c_str());
|
|
}
|
|
else if ( !Q_stricmp( token.c_str(), "PlayerHealth:" ) )
|
|
{
|
|
heuristic = script.GetToken(false);
|
|
playerHealth = atoi(heuristic.c_str());
|
|
}
|
|
else if ( !Q_stricmp( token.c_str(), "Ping:" ) )
|
|
{
|
|
heuristic = script.GetToken(false);
|
|
ping = atoi(heuristic.c_str());
|
|
}
|
|
else if ( !Q_stricmp( token.c_str(), "ItemsPickedUp:" ) )
|
|
{
|
|
heuristic = script.GetToken(false);
|
|
itemsPickedUp = atoi(heuristic.c_str());
|
|
}
|
|
else if ( !Q_stricmp( token.c_str(), "SpecialEvents:" ) )
|
|
{
|
|
heuristic = script.GetToken(false);
|
|
specialEvents = atoi(heuristic.c_str());
|
|
}
|
|
else if ( !Q_stricmp( token.c_str(), "SkillLevel:" ) )
|
|
{
|
|
heuristic = script.GetToken(false);
|
|
skillLevel = atof(heuristic.c_str());
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
precedingToken = token ;
|
|
}
|
|
}
|
|
|
|
void PlayerHeuristics::WriteOutHeuristicData( const str &levelName )
|
|
{
|
|
str s;
|
|
str stat;
|
|
|
|
//Build File String
|
|
s = "Level: " + levelName + "\n";
|
|
|
|
stat = va("%l", shotsFired);
|
|
s+= "ShotsFired: " + stat + "\n";
|
|
|
|
stat = va("%l", shotsHit);
|
|
s+= "ShotsHit: " + stat + "\n";
|
|
|
|
stat = va("%l", numberOfDeaths);
|
|
s+= "NumberOfDeaths: " + stat + "\n";
|
|
|
|
stat = va("%l", enemiesKilled);
|
|
s+= "EnemiesKilled: " + stat + "\n";
|
|
|
|
stat = timeOnLevel;
|
|
s+= "TimeOnLevel: " + stat + "\n";
|
|
|
|
stat = playerHealth;
|
|
s+= "PlayerHealth: " + stat + "\n";
|
|
|
|
stat = ping;
|
|
s+= "Ping: " + stat + "\n";
|
|
|
|
stat = itemsPickedUp;
|
|
s+= "ItemsPickedUp: " + stat + "\n";
|
|
|
|
stat = specialEvents;
|
|
s+= "SpecialEvents: " + stat + "\n";
|
|
|
|
stat = skillLevel;
|
|
s+= "SkillLevel: " + stat + "\n";
|
|
|
|
s+= levelName + "_end";
|
|
s+= "\n\n";
|
|
|
|
gi.FS_Write( s, s.length(), heuristicFile );
|
|
gi.FS_Flush( heuristicFile );
|
|
|
|
}
|
|
|
|
void PlayerHeuristics::CreateInitialHeuristicFile()
|
|
{
|
|
//Clear Heuristic Data Structure;
|
|
shotsFired = 0;
|
|
shotsHit = 0;
|
|
numberOfDeaths = 0;
|
|
enemiesKilled = 0;
|
|
timeOnLevel = 0;
|
|
levelStartTime = 0;
|
|
levelEndTime = 0;
|
|
playerHealth = 0;
|
|
|
|
ping = 0;
|
|
itemsPickedUp = 0;
|
|
specialEvents = 0;
|
|
|
|
skillLevel = 0;
|
|
|
|
OpenPlayerHeuristicFile();
|
|
if ( !heuristicFile )
|
|
{
|
|
return;
|
|
}
|
|
|
|
WriteOutHeuristicData(level.mapname);
|
|
ClosePlayerHeuristicFile();
|
|
}
|
|
|
|
|
|
|
|
void PlayerHeuristics::OpenPlayerHeuristicFile()
|
|
{
|
|
if ( !heuristicFile )
|
|
{
|
|
heuristicFile = gi.FS_FOpenFileWrite( heuristicFileName.c_str() );
|
|
}
|
|
}
|
|
|
|
void PlayerHeuristics::ClosePlayerHeuristicFile()
|
|
{
|
|
if ( heuristicFile )
|
|
{
|
|
gi.FS_FCloseFile( heuristicFile );
|
|
heuristicFile = NULL;
|
|
}
|
|
}
|
|
|
|
void PlayerHeuristics::CheckForHeuristicFile()
|
|
{
|
|
str s,filename;
|
|
int filesize;
|
|
|
|
s = "heuristics";
|
|
filename = gi.GetArchiveFileName( NULL, s, "log", qtrue );
|
|
heuristicFileName = filename.c_str();
|
|
|
|
filesize = gi.FS_ReadFile( heuristicFileName.c_str(), NULL, true );
|
|
if ( filesize <= 0 ) //File Does Not Exsist
|
|
CreateInitialHeuristicFile();
|
|
}
|
|
|
|
float PlayerHeuristics::CalculateSkillLevel()
|
|
{
|
|
// Current Skill Level Formula
|
|
// (((Accuracy * 100) * .75 ) + (1 - (Deaths * .25))) / 10
|
|
// Returns a floating point number between 0 and 10
|
|
|
|
// I expect this function to change a lot during the course of development
|
|
// That is why it is written so verbosely.
|
|
|
|
float Accuracy;
|
|
float Deaths;
|
|
float SkillLevel;
|
|
|
|
Accuracy = (float)shotsHit / (float)shotsFired;
|
|
Deaths = numberOfDeaths;
|
|
|
|
SkillLevel = (((Accuracy * 100.0f) * .75f ) + (1.0f - (Deaths * .25f))) / 10.0f;
|
|
if (SkillLevel < 0.0f )
|
|
{
|
|
SkillLevel = 0.0f;
|
|
}
|
|
|
|
return SkillLevel;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------
|
|
//
|
|
// Name: ClearLevelStatistics
|
|
// Class: PlayerHeuristics
|
|
//
|
|
// Description: Clears the variables that are level specific.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//-----------------------------------------------------
|
|
void PlayerHeuristics::ClearLevelStatistics(void)
|
|
{
|
|
shotsFiredInLevel = 0;
|
|
shotsHitInLevel = 0;
|
|
enemiesKilledInLevel = 0;
|
|
numCompleteObjectives = 0;
|
|
numObjectives = 0;
|
|
numFailedObjectives = 0;
|
|
teammatesKilledInLevel = 0;
|
|
}
|
|
|
|
|
|
void PlayerHeuristics::SetShotsFired( long int shots )
|
|
{
|
|
shotsFired = shots;
|
|
}
|
|
|
|
void PlayerHeuristics::IncrementShotsFired( void )
|
|
{
|
|
shotsFired++;
|
|
shotsFiredInLevel++;
|
|
}
|
|
|
|
void PlayerHeuristics::SetShotsHit( long int shots )
|
|
{
|
|
shotsHit = shots;
|
|
}
|
|
|
|
void PlayerHeuristics::IncrementShotsHit()
|
|
{
|
|
shotsHit++;
|
|
shotsHitInLevel++;
|
|
}
|
|
|
|
void PlayerHeuristics::SetNumberOfDeaths( long int deaths )
|
|
{
|
|
numberOfDeaths = deaths;
|
|
}
|
|
|
|
void PlayerHeuristics::IncrementNumberOfDeaths()
|
|
{
|
|
numberOfDeaths++;
|
|
}
|
|
|
|
void PlayerHeuristics::SetTimeOnLevel( float levelTime )
|
|
{
|
|
timeOnLevel = levelTime;
|
|
}
|
|
|
|
void PlayerHeuristics::SetPlayerHealth( int health )
|
|
{
|
|
playerHealth = health;
|
|
}
|
|
|
|
void PlayerHeuristics::SetPing( int ping_value )
|
|
{
|
|
ping = ping_value;
|
|
}
|
|
|
|
void PlayerHeuristics::SetItemsPickedUp( int items )
|
|
{
|
|
itemsPickedUp = items;
|
|
}
|
|
|
|
void PlayerHeuristics::IncrementItemsPickedUp()
|
|
{
|
|
itemsPickedUp++;
|
|
}
|
|
|
|
void PlayerHeuristics::SetSpecialEvents( int specialevent )
|
|
{
|
|
specialEvents = specialevent;
|
|
}
|
|
|
|
void PlayerHeuristics::IncrementSpecialEvents()
|
|
{
|
|
specialEvents++;
|
|
}
|
|
|
|
void PlayerHeuristics::UpdateShotsFired( void )
|
|
{
|
|
IncrementShotsFired();
|
|
}
|
|
|
|
|
|
void PlayerHeuristics::SetObjectives(int numMissionObjectives)
|
|
{
|
|
numObjectives = numMissionObjectives;
|
|
}
|
|
|
|
void PlayerHeuristics::IncrementCompleteObjectives()
|
|
{
|
|
numCompleteObjectives++;
|
|
}
|
|
|
|
void PlayerHeuristics::IncrementFailedObjectives()
|
|
{
|
|
numFailedObjectives++;
|
|
}
|
|
|
|
void PlayerHeuristics::IncrementEnemiesKilled(void)
|
|
{
|
|
enemiesKilled++;
|
|
enemiesKilledInLevel++;
|
|
}
|
|
|
|
void PlayerHeuristics::IncrementTeammatesKilled(void)
|
|
{
|
|
teammatesKilledInLevel++;
|
|
}
|