1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

refactoring & expanding

This commit is contained in:
Laserlicht 2024-08-01 22:36:32 +02:00
parent 490f1bfee6
commit 380d5bb05b
3 changed files with 108 additions and 86 deletions

View File

@ -1588,81 +1588,6 @@ struct statsHLP
}
return h[best];
}
//calculates total number of artifacts that belong to given player
static int getNumberOfArts(const PlayerState * ps)
{
int ret = 0;
for(auto h : ps->heroes)
{
ret += (int)h->artifactsInBackpack.size() + (int)h->artifactsWorn.size();
}
return ret;
}
// get total strength of player army
static si64 getArmyStrength(const PlayerState * ps)
{
si64 str = 0;
for(auto h : ps->heroes)
{
if(!h->inTownGarrison) //original h3 behavior
str += h->getArmyStrength();
}
return str;
}
// get total gold income
static int getIncome(const PlayerState * ps)
{
int totalIncome = 0;
const CGObjectInstance * heroOrTown = nullptr;
//Heroes can produce gold as well - skill, specialty or arts
for(const auto & h : ps->heroes)
{
totalIncome += h->valOfBonuses(Selector::typeSubtype(BonusType::GENERATE_RESOURCE, BonusSubtypeID(GameResID(GameResID::GOLD))));
if(!heroOrTown)
heroOrTown = h;
}
//Add town income of all towns
for(const auto & t : ps->towns)
{
totalIncome += t->dailyIncome()[EGameResID::GOLD];
if(!heroOrTown)
heroOrTown = t;
}
/// FIXME: Dirty dirty hack
/// Stats helper need some access to gamestate.
std::vector<const CGObjectInstance *> ownedObjects;
for(const CGObjectInstance * obj : heroOrTown->cb->gameState()->map->objects)
{
if(obj && obj->tempOwner == ps->color)
ownedObjects.push_back(obj);
}
/// This is code from CPlayerSpecificInfoCallback::getMyObjects
/// I'm really need to find out about callback interface design...
for(const auto * object : ownedObjects)
{
//Mines
if ( object->ID == Obj::MINE )
{
const auto * mine = dynamic_cast<const CGMine *>(object);
assert(mine);
if (mine->producedResource == EGameResID::GOLD)
totalIncome += mine->producedQuantity;
}
}
return totalIncome;
}
};
void CGameState::obtainPlayersStats(SThievesGuildInfo & tgi, int level)
@ -1739,15 +1664,15 @@ void CGameState::obtainPlayersStats(SThievesGuildInfo & tgi, int level)
}
if(level >= 4) //artifacts
{
FILL_FIELD(artifacts, statsHLP::getNumberOfArts(&g->second))
FILL_FIELD(artifacts, Statistic::getNumberOfArts(&g->second))
}
if(level >= 4) //army strength
{
FILL_FIELD(army, statsHLP::getArmyStrength(&g->second))
FILL_FIELD(army, Statistic::getArmyStrength(&g->second))
}
if(level >= 5) //income
{
FILL_FIELD(income, statsHLP::getIncome(&g->second))
FILL_FIELD(income, Statistic::getIncome(&g->second))
}
if(level >= 2) //best hero's stats
{

View File

@ -12,6 +12,11 @@
#include "../CPlayerState.h"
#include "../constants/StringConstants.h"
#include "CGameState.h"
#include "../mapObjects/CGHeroInstance.h"
#include "../mapObjects/CGTownInstance.h"
#include "../mapObjects/CGObjectInstance.h"
#include "../mapObjects/MiscObjects.h"
#include "../mapping/CMap.h"
VCMI_LIB_NAMESPACE_BEGIN
@ -28,8 +33,11 @@ StatisticDataSetEntry StatisticDataSet::createEntry(const PlayerState * ps, cons
data.player = ps->color;
data.team = ps->team;
data.resources = ps->resources;
data.heroesCount = ps->heroes.size();
data.townCount = ps->towns.size();
data.numberHeroes = ps->heroes.size();
data.numberTowns = ps->towns.size();
data.numberArtifacts = Statistic::getNumberOfArts(ps);
data.armyStrength = Statistic::getArmyStrength(ps);
data.income = Statistic::getIncome(ps);
return data;
}
@ -40,14 +48,14 @@ std::string StatisticDataSet::toCsv()
auto resources = std::vector<EGameResID>{EGameResID::GOLD, EGameResID::WOOD, EGameResID::MERCURY, EGameResID::ORE, EGameResID::SULFUR, EGameResID::CRYSTAL, EGameResID::GEMS};
ss << "Day" << ";" << "Player" << ";" << "Team" << ";" << "HeroesCount" << ";" << "TownCount";
ss << "Day" << ";" << "Player" << ";" << "Team" << ";" << "NumberHeroes" << ";" << "NumberTowns" << ";" << "NumberArtifacts" << ";" << "ArmyStrength" << ";" << "Income";
for(auto & resource : resources)
ss << ";" << GameConstants::RESOURCE_NAMES[resource];
ss << "\r\n";
for(auto & entry : data)
{
ss << entry.day << ";" << GameConstants::PLAYER_COLOR_NAMES[entry.player] << ";" << entry.team.getNum() << ";" << entry.heroesCount << ";" << entry.townCount;
ss << entry.day << ";" << GameConstants::PLAYER_COLOR_NAMES[entry.player] << ";" << entry.team.getNum() << ";" << entry.numberHeroes << ";" << entry.numberTowns << ";" << entry.numberArtifacts << ";" << entry.armyStrength << ";" << entry.income;
for(auto & resource : resources)
ss << ";" << entry.resources[resource];
ss << "\r\n";
@ -56,4 +64,79 @@ std::string StatisticDataSet::toCsv()
return ss.str();
}
//calculates total number of artifacts that belong to given player
int Statistic::getNumberOfArts(const PlayerState * ps)
{
int ret = 0;
for(auto h : ps->heroes)
{
ret += (int)h->artifactsInBackpack.size() + (int)h->artifactsWorn.size();
}
return ret;
}
// get total strength of player army
si64 Statistic::getArmyStrength(const PlayerState * ps)
{
si64 str = 0;
for(auto h : ps->heroes)
{
if(!h->inTownGarrison) //original h3 behavior
str += h->getArmyStrength();
}
return str;
}
// get total gold income
int Statistic::getIncome(const PlayerState * ps)
{
int totalIncome = 0;
const CGObjectInstance * heroOrTown = nullptr;
//Heroes can produce gold as well - skill, specialty or arts
for(const auto & h : ps->heroes)
{
totalIncome += h->valOfBonuses(Selector::typeSubtype(BonusType::GENERATE_RESOURCE, BonusSubtypeID(GameResID(GameResID::GOLD))));
if(!heroOrTown)
heroOrTown = h;
}
//Add town income of all towns
for(const auto & t : ps->towns)
{
totalIncome += t->dailyIncome()[EGameResID::GOLD];
if(!heroOrTown)
heroOrTown = t;
}
/// FIXME: Dirty dirty hack
/// Stats helper need some access to gamestate.
std::vector<const CGObjectInstance *> ownedObjects;
for(const CGObjectInstance * obj : heroOrTown->cb->gameState()->map->objects)
{
if(obj && obj->tempOwner == ps->color)
ownedObjects.push_back(obj);
}
/// This is code from CPlayerSpecificInfoCallback::getMyObjects
/// I'm really need to find out about callback interface design...
for(const auto * object : ownedObjects)
{
//Mines
if ( object->ID == Obj::MINE )
{
const auto * mine = dynamic_cast<const CGMine *>(object);
assert(mine);
if (mine->producedResource == EGameResID::GOLD)
totalIncome += mine->producedQuantity;
}
}
return totalIncome;
}
VCMI_LIB_NAMESPACE_END

View File

@ -23,8 +23,11 @@ struct DLL_LINKAGE StatisticDataSetEntry
PlayerColor player;
TeamID team;
TResources resources;
int heroesCount;
int townCount;
int numberHeroes;
int numberTowns;
int numberArtifacts;
si64 armyStrength;
int income;
template <typename Handler> void serialize(Handler &h)
{
@ -32,8 +35,11 @@ struct DLL_LINKAGE StatisticDataSetEntry
h & player;
h & team;
h & resources;
h & heroesCount;
h & townCount;
h & numberHeroes;
h & numberTowns;
h & numberArtifacts;
h & armyStrength;
h & income;
}
};
@ -52,4 +58,12 @@ public:
}
};
class DLL_LINKAGE Statistic
{
public:
static int getNumberOfArts(const PlayerState * ps);
static si64 getArmyStrength(const PlayerState * ps);
static int getIncome(const PlayerState * ps);
};
VCMI_LIB_NAMESPACE_END