Bugfix for lua. Units died by hunger are reported in luas <unitDied>-section too

Also fixed the stats by counting this kind of death too.
This commit is contained in:
Titus Tscharntke 2010-03-19 18:58:46 +00:00
parent 5c2bb68e72
commit c4a9f61842
5 changed files with 737 additions and 2 deletions

View File

@ -0,0 +1,58 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "stats.h"
#include "leak_dumper.h"
namespace Glest{ namespace Game{
PlayerStats::PlayerStats(){
victory= false;
kills= 0;
deaths= 0;
unitsProduced= 0;
resourcesHarvested= 0;
}
// =====================================================
// class Stats
// =====================================================
void Stats::init(int factionCount, int thisFactionIndex, const string& description){
this->thisFactionIndex= thisFactionIndex;
this->factionCount= factionCount;
this->description= description;
}
void Stats::setVictorious(int playerIndex){
playerStats[playerIndex].victory= true;
}
void Stats::kill(int killerFactionIndex, int killedFactionIndex){
playerStats[killerFactionIndex].kills++;
playerStats[killedFactionIndex].deaths++;
}
void Stats::die(int diedFactionIndex){
playerStats[diedFactionIndex].deaths++;
}
void Stats::produce(int producerFactionIndex){
playerStats[producerFactionIndex].unitsProduced++;
}
void Stats::harvest(int harvesterFactionIndex, int amount){
playerStats[harvesterFactionIndex].resourcesHarvested+= amount;
}
}}//end namespace

View File

@ -0,0 +1,80 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#ifndef _GLEST_GAME_STATS_H_
#define _GLEST_GAME_STATS_H_
#include <string>
#include "game_constants.h"
#include "faction.h"
using std::string;
namespace Glest{ namespace Game{
struct PlayerStats{
PlayerStats();
ControlType control;
string factionTypeName;
int teamIndex;
bool victory;
int kills;
int deaths;
int unitsProduced;
int resourcesHarvested;
};
// =====================================================
// class Stats
//
/// Player statistics that are shown after the game ends
// =====================================================
class Stats{
private:
PlayerStats playerStats[GameConstants::maxPlayers];
string description;
int factionCount;
int thisFactionIndex;
public:
void init(int factionCount, int thisFactionIndex, const string &description);
string getDescription() const {return description;}
int getThisFactionIndex() const {return thisFactionIndex;}
int getFactionCount() const {return factionCount;}
const string &getFactionTypeName(int factionIndex) const {return playerStats[factionIndex].factionTypeName;}
ControlType getControl(int factionIndex) const {return playerStats[factionIndex].control;}
bool getVictory(int factionIndex) const {return playerStats[factionIndex].victory;}
int getTeam(int factionIndex) const {return playerStats[factionIndex].teamIndex;}
int getKills(int factionIndex) const {return playerStats[factionIndex].kills;}
int getDeaths(int factionIndex) const {return playerStats[factionIndex].deaths;}
int getUnitsProduced(int factionIndex) const {return playerStats[factionIndex].unitsProduced;}
int getResourcesHarvested(int factionIndex) const {return playerStats[factionIndex].resourcesHarvested;}
void setDescription(const string& description) {this->description = description;}
void setFactionTypeName(int playerIndex, const string& factionTypeName) {playerStats[playerIndex].factionTypeName= factionTypeName;}
void setControl(int playerIndex, ControlType control) {playerStats[playerIndex].control= control;}
void setTeam(int playerIndex, int teamIndex) {playerStats[playerIndex].teamIndex= teamIndex;}
void setVictorious(int playerIndex);
void kill(int killerFactionIndex, int killedFactionIndex);
void die(int diedFactionIndex);
void produce(int producerFactionIndex);
void harvest(int harvesterFactionIndex, int amount);
};
}}//end namespace
#endif

View File

@ -0,0 +1,454 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "faction.h"
#include <algorithm>
#include <cassert>
#include "resource_type.h"
#include "unit.h"
#include "util.h"
#include "sound_renderer.h"
#include "renderer.h"
#include "tech_tree.h"
#include "leak_dumper.h"
#include "game.h"
using namespace Shared::Util;
namespace Glest{ namespace Game{
// =====================================================
// class Faction
// =====================================================
void Faction::init(
const FactionType *factionType, ControlType control, TechTree *techTree, Game *game,
int factionIndex, int teamIndex, int startLocationIndex, bool thisFaction, bool giveResources)
{
this->control= control;
this->factionType= factionType;
this->startLocationIndex= startLocationIndex;
this->index= factionIndex;
this->teamIndex= teamIndex;
this->thisFaction= thisFaction;
this->world= game->getWorld();
this->scriptManager= game->getScriptManager();
resources.resize(techTree->getResourceTypeCount());
store.resize(techTree->getResourceTypeCount());
for(int i=0; i<techTree->getResourceTypeCount(); ++i){
const ResourceType *rt= techTree->getResourceType(i);
int resourceAmount= giveResources? factionType->getStartingResourceAmount(rt): 0;
resources[i].init(rt, resourceAmount);
store[i].init(rt, 0);
}
texture= Renderer::getInstance().newTexture2D(rsGame);
texture->load("data/core/faction_textures/faction"+intToStr(index)+".tga");
}
void Faction::end(){
deleteValues(units.begin(), units.end());
}
// ================== get ==================
const Resource *Faction::getResource(const ResourceType *rt) const{
for(int i=0; i<resources.size(); ++i){
if(rt==resources[i].getType()){
return &resources[i];
}
}
assert(false);
return NULL;
}
int Faction::getStoreAmount(const ResourceType *rt) const{
for(int i=0; i<store.size(); ++i){
if(rt==store[i].getType()){
return store[i].getAmount();
}
}
assert(false);
return 0;
}
bool Faction::getCpuControl() const{
return control==ctCpuEasy ||control==ctCpu || control==ctCpuUltra|| control==ctCpuMega;
}
// ==================== upgrade manager ====================
void Faction::startUpgrade(const UpgradeType *ut){
upgradeManager.startUpgrade(ut, index);
}
void Faction::cancelUpgrade(const UpgradeType *ut){
upgradeManager.cancelUpgrade(ut);
}
void Faction::finishUpgrade(const UpgradeType *ut){
upgradeManager.finishUpgrade(ut);
for(int i=0; i<getUnitCount(); ++i){
getUnit(i)->applyUpgrade(ut);
}
}
// ==================== reqs ====================
//checks if all required units and upgrades are present
bool Faction::reqsOk(const RequirableType *rt) const{
//required units
for(int i=0; i<rt->getUnitReqCount(); ++i){
bool found=false;
for(int j=0; j<getUnitCount(); ++j){
Unit *unit= getUnit(j);
const UnitType *ut= unit->getType();
if(rt->getUnitReq(i)==ut && unit->isOperative()){
found= true;
break;
}
}
if(!found){
return false;
}
}
//required upgrades
for(int i=0; i<rt->getUpgradeReqCount(); ++i){
if(!upgradeManager.isUpgraded(rt->getUpgradeReq(i))){
return false;
}
}
return true;
}
bool Faction::reqsOk(const CommandType *ct) const{
if(ct->getProduced()!=NULL && !reqsOk(ct->getProduced())){
return false;
}
if(ct->getClass()==ccUpgrade){
const UpgradeCommandType *uct= static_cast<const UpgradeCommandType*>(ct);
if(upgradeManager.isUpgradingOrUpgraded(uct->getProducedUpgrade())){
return false;
}
}
return reqsOk(static_cast<const RequirableType*>(ct));
}
// ================== cost application ==================
//apply costs except static production (start building/production)
bool Faction::applyCosts(const ProducibleType *p){
if(!checkCosts(p)){
return false;
}
//for each unit cost spend it
//pass 2, decrease resources, except negative static costs (ie: farms)
for(int i=0; i<p->getCostCount(); ++i)
{
const ResourceType *rt= p->getCost(i)->getType();
int cost= p->getCost(i)->getAmount();
if((cost > 0 || (rt->getClass() != rcStatic)) && rt->getClass() != rcConsumable)
{
incResourceAmount(rt, -(cost));
}
}
return true;
}
//apply discount (when a morph ends)
void Faction::applyDiscount(const ProducibleType *p, int discount)
{
//increase resources
for(int i=0; i<p->getCostCount(); ++i)
{
const ResourceType *rt= p->getCost(i)->getType();
int cost= p->getCost(i)->getAmount();
if((cost > 0 || (rt->getClass() != rcStatic)) && rt->getClass() != rcConsumable)
{
incResourceAmount(rt, cost*discount/100);
}
}
}
//apply static production (for starting units)
void Faction::applyStaticCosts(const ProducibleType *p)
{
//decrease static resources
for(int i=0; i<p->getCostCount(); ++i)
{
const ResourceType *rt= p->getCost(i)->getType();
if(rt->getClass() == rcStatic)
{
int cost= p->getCost(i)->getAmount();
if(cost > 0)
{
incResourceAmount(rt, -cost);
}
}
}
}
//apply static production (when a mana source is done)
void Faction::applyStaticProduction(const ProducibleType *p)
{
//decrease static resources
for(int i=0; i<p->getCostCount(); ++i)
{
const ResourceType *rt= p->getCost(i)->getType();
if(rt->getClass() == rcStatic)
{
int cost= p->getCost(i)->getAmount();
if(cost < 0)
{
incResourceAmount(rt, -cost);
}
}
}
}
//deapply all costs except static production (usually when a building is cancelled)
void Faction::deApplyCosts(const ProducibleType *p)
{
//increase resources
for(int i=0; i<p->getCostCount(); ++i)
{
const ResourceType *rt= p->getCost(i)->getType();
int cost= p->getCost(i)->getAmount();
if((cost > 0 || (rt->getClass() != rcStatic)) && rt->getClass() != rcConsumable)
{
incResourceAmount(rt, cost);
}
}
}
//deapply static costs (usually when a unit dies)
void Faction::deApplyStaticCosts(const ProducibleType *p)
{
//decrease resources
for(int i=0; i<p->getCostCount(); ++i)
{
const ResourceType *rt= p->getCost(i)->getType();
if(rt->getClass() == rcStatic)
{
if(rt->getRecoup_cost() == true)
{
int cost= p->getCost(i)->getAmount();
incResourceAmount(rt, cost);
}
}
}
}
//deapply static costs, but not negative costs, for when building gets killed
void Faction::deApplyStaticConsumption(const ProducibleType *p)
{
//decrease resources
for(int i=0; i<p->getCostCount(); ++i)
{
const ResourceType *rt= p->getCost(i)->getType();
if(rt->getClass() == rcStatic)
{
int cost= p->getCost(i)->getAmount();
if(cost>0)
{
incResourceAmount(rt, cost);
}
}
}
}
//apply resource on interval (cosumable resouces)
void Faction::applyCostsOnInterval(){
//increment consumables
for(int j=0; j<getUnitCount(); ++j){
Unit *unit= getUnit(j);
if(unit->isOperative()){
for(int k=0; k<unit->getType()->getCostCount(); ++k){
const Resource *resource= unit->getType()->getCost(k);
if(resource->getType()->getClass()==rcConsumable && resource->getAmount()<0){
incResourceAmount(resource->getType(), -resource->getAmount());
}
}
}
}
//decrement consumables
for(int j=0; j<getUnitCount(); ++j){
Unit *unit= getUnit(j);
if(unit->isOperative()){
for(int k=0; k<unit->getType()->getCostCount(); ++k){
const Resource *resource= unit->getType()->getCost(k);
if(resource->getType()->getClass()==rcConsumable && resource->getAmount()>0){
incResourceAmount(resource->getType(), -resource->getAmount());
//decrease unit hp
if(getResource(resource->getType())->getAmount()<0){
resetResourceAmount(resource->getType());
bool decHpResult=unit->decHp(unit->getType()->getMaxHp()/3);
if(decHpResult){
world->getStats()->die(unit->getFactionIndex());
scriptManager->onUnitDied(unit);
}
StaticSound *sound= unit->getType()->getFirstStOfClass(scDie)->getSound();
if(sound!=NULL && thisFaction){
SoundRenderer::getInstance().playFx(sound);
}
}
}
}
}
}
}
bool Faction::checkCosts(const ProducibleType *pt){
//for each unit cost check if enough resources
for(int i=0; i<pt->getCostCount(); ++i){
const ResourceType *rt= pt->getCost(i)->getType();
int cost= pt->getCost(i)->getAmount();
if(cost>0){
int available= getResource(rt)->getAmount();
if(cost>available){
return false;
}
}
}
return true;
}
// ================== diplomacy ==================
bool Faction::isAlly(const Faction *faction){
return teamIndex==faction->getTeam();
}
// ================== misc ==================
void Faction::incResourceAmount(const ResourceType *rt, int amount)
{
for(int i=0; i<resources.size(); ++i)
{
Resource *r= &resources[i];
if(r->getType()==rt)
{
r->setAmount(r->getAmount()+amount);
if(r->getType()->getClass() != rcStatic && r->getAmount()>getStoreAmount(rt))
{
r->setAmount(getStoreAmount(rt));
}
return;
}
}
assert(false);
}
void Faction::setResourceBalance(const ResourceType *rt, int balance){
for(int i=0; i<resources.size(); ++i){
Resource *r= &resources[i];
if(r->getType()==rt){
r->setBalance(balance);
return;
}
}
assert(false);
}
Unit *Faction::findUnit(int id){
UnitMap::iterator it= unitMap.find(id);
if(it==unitMap.end()){
return NULL;
}
return it->second;
}
void Faction::addUnit(Unit *unit){
units.push_back(unit);
unitMap.insert(make_pair(unit->getId(), unit));
}
void Faction::removeUnit(Unit *unit){
for(int i=0; i<units.size(); ++i){
if(units[i]==unit){
units.erase(units.begin()+i);
unitMap.erase(unit->getId());
assert(units.size()==unitMap.size());
return;
}
}
assert(false);
}
void Faction::addStore(const UnitType *unitType){
for(int i=0; i<unitType->getStoredResourceCount(); ++i){
const Resource *r= unitType->getStoredResource(i);
for(int j=0; j<store.size(); ++j){
Resource *storedResource= &store[j];
if(storedResource->getType() == r->getType()){
storedResource->setAmount(storedResource->getAmount() + r->getAmount());
}
}
}
}
void Faction::removeStore(const UnitType *unitType){
for(int i=0; i<unitType->getStoredResourceCount(); ++i){
const Resource *r= unitType->getStoredResource(i);
for(int j=0; j<store.size(); ++j){
Resource *storedResource= &store[j];
if(storedResource->getType() == r->getType()){
storedResource->setAmount(storedResource->getAmount() - r->getAmount());
}
}
}
limitResourcesToStore();
}
void Faction::limitResourcesToStore()
{
for(int i=0; i<resources.size(); ++i)
{
Resource *r= &resources[i];
Resource *s= &store[i];
if(r->getType()->getClass() != rcStatic && r->getAmount()>s->getAmount())
{
r->setAmount(s->getAmount());
}
}
}
void Faction::resetResourceAmount(const ResourceType *rt){
for(int i=0; i<resources.size(); ++i){
if(resources[i].getType()==rt){
resources[i].setAmount(0);
return;
}
}
assert(false);
}
}}//end namespace

View File

@ -0,0 +1,143 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#ifndef _GLEST_GAME_FACTION_H_
#define _GLEST_GAME_FACTION_H_
#include <vector>
#include <map>
#include "upgrade.h"
#include "texture.h"
#include "resource.h"
#include "game_constants.h"
using std::map;
using std::vector;
using Shared::Graphics::Texture2D;
namespace Glest{ namespace Game{
class Unit;
class TechTree;
class FactionType;
class ProducibleType;
class RequirableType;
class CommandType;
class UnitType;
class Game;
class ScriptManager;
class World;
// =====================================================
// class Faction
//
/// Each of the game players
// =====================================================
class Faction{
private:
typedef vector<Resource> Resources;
typedef vector<Resource> Store;
typedef vector<Faction*> Allies;
typedef vector<Unit*> Units;
typedef map<int, Unit*> UnitMap;
private:
UpgradeManager upgradeManager;
Resources resources;
Store store;
Allies allies;
Units units;
UnitMap unitMap;
World *world;
ScriptManager *scriptManager;
ControlType control;
Texture2D *texture;
const FactionType *factionType;
int index;
int teamIndex;
int startLocationIndex;
bool thisFaction;
public:
void init(
const FactionType *factionType, ControlType control, TechTree *techTree, Game *game,
int factionIndex, int teamIndex, int startLocationIndex, bool thisFaction, bool giveResources);
void end();
//get
const Resource *getResource(const ResourceType *rt) const;
const Resource *getResource(int i) const {return &resources[i];}
int getStoreAmount(const ResourceType *rt) const;
const FactionType *getType() const {return factionType;}
int getIndex() const {return index;}
int getTeam() const {return teamIndex;}
bool getCpuControl() const;
bool getCpuEasyControl() const {return control==ctCpuEasy;}
bool getCpuUltraControl() const {return control==ctCpuUltra;}
bool getCpuMegaControl() const {return control==ctCpuMega;}
ControlType getControlType() const {return control;}
Unit *getUnit(int i) const {return units[i];}
int getUnitCount() const {return units.size();}
const UpgradeManager *getUpgradeManager() const {return &upgradeManager;}
const Texture2D *getTexture() const {return texture;}
int getStartLocationIndex() const {return startLocationIndex;}
//upgrades
void startUpgrade(const UpgradeType *ut);
void cancelUpgrade(const UpgradeType *ut);
void finishUpgrade(const UpgradeType *ut);
//cost application
bool applyCosts(const ProducibleType *p);
void applyDiscount(const ProducibleType *p, int discount);
void applyStaticCosts(const ProducibleType *p);
void applyStaticProduction(const ProducibleType *p);
void deApplyCosts(const ProducibleType *p);
void deApplyStaticCosts(const ProducibleType *p);
void deApplyStaticConsumption(const ProducibleType *p);
void applyCostsOnInterval();
bool checkCosts(const ProducibleType *pt);
//reqs
bool reqsOk(const RequirableType *rt) const;
bool reqsOk(const CommandType *ct) const;
//diplomacy
bool isAlly(const Faction *faction);
//other
Unit *findUnit(int id);
void addUnit(Unit *unit);
void removeUnit(Unit *unit);
void addStore(const UnitType *unitType);
void removeStore(const UnitType *unitType);
//resources
void incResourceAmount(const ResourceType *rt, int amount);
void setResourceBalance(const ResourceType *rt, int balance);
private:
void limitResourcesToStore();
void resetResourceAmount(const ResourceType *rt);
};
}}//end namespace
#endif

View File

@ -1,7 +1,7 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Martiño Figueroa
// Copyright (C) 2001-2008 Marti<EFBFBD>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
@ -554,7 +554,7 @@ void World::initFactionTypes(GameSettings *gs){
for(int i=0; i<factions.size(); ++i){
const FactionType *ft= techTree.getType(gs->getFactionTypeName(i));
factions[i].init(
ft, gs->getFactionControl(i), &techTree, i, gs->getTeam(i),
ft, gs->getFactionControl(i), &techTree, game, i, gs->getTeam(i),
gs->getStartLocationIndex(i), i==thisFactionIndex, gs->getDefaultResources());
stats.setTeam(i, gs->getTeam(i));