diff --git a/source/glest_game/game/stats.cpp b/source/glest_game/game/stats.cpp new file mode 100644 index 00000000..753c4527 --- /dev/null +++ b/source/glest_game/game/stats.cpp @@ -0,0 +1,58 @@ +// ============================================================== +// This file is part of Glest (www.glest.org) +// +// Copyright (C) 2001-2008 Marti�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 diff --git a/source/glest_game/game/stats.h b/source/glest_game/game/stats.h new file mode 100644 index 00000000..7f3fcb81 --- /dev/null +++ b/source/glest_game/game/stats.h @@ -0,0 +1,80 @@ +// ============================================================== +// This file is part of Glest (www.glest.org) +// +// Copyright (C) 2001-2008 Marti�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 + +#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 diff --git a/source/glest_game/type_instances/faction.cpp b/source/glest_game/type_instances/faction.cpp new file mode 100644 index 00000000..72986b4e --- /dev/null +++ b/source/glest_game/type_instances/faction.cpp @@ -0,0 +1,454 @@ +// ============================================================== +// This file is part of Glest (www.glest.org) +// +// Copyright (C) 2001-2008 Marti�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 +#include + +#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; igetResourceTypeCount(); ++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; iapplyUpgrade(ut); + } +} + +// ==================== reqs ==================== + +//checks if all required units and upgrades are present +bool Faction::reqsOk(const RequirableType *rt) const{ + + //required units + for(int i=0; igetUnitReqCount(); ++i){ + bool found=false; + for(int j=0; jgetType(); + if(rt->getUnitReq(i)==ut && unit->isOperative()){ + found= true; + break; + } + } + if(!found){ + return false; + } + } + + //required upgrades + for(int i=0; igetUpgradeReqCount(); ++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(ct); + if(upgradeManager.isUpgradingOrUpgraded(uct->getProducedUpgrade())){ + return false; + } + } + + return reqsOk(static_cast(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; igetCostCount(); ++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; igetCostCount(); ++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; igetCostCount(); ++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; igetCostCount(); ++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; igetCostCount(); ++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; igetCostCount(); ++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; igetCostCount(); ++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; jisOperative()){ + for(int k=0; kgetType()->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; jisOperative()){ + for(int k=0; kgetType()->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; igetCostCount(); ++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; igetType()==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; igetType()==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; igetId()); + assert(units.size()==unitMap.size()); + return; + } + } + assert(false); +} + +void Faction::addStore(const UnitType *unitType){ + for(int i=0; igetStoredResourceCount(); ++i){ + const Resource *r= unitType->getStoredResource(i); + for(int j=0; jgetType() == r->getType()){ + storedResource->setAmount(storedResource->getAmount() + r->getAmount()); + } + } + } +} + +void Faction::removeStore(const UnitType *unitType){ + for(int i=0; igetStoredResourceCount(); ++i){ + const Resource *r= unitType->getStoredResource(i); + for(int j=0; jgetType() == r->getType()){ + storedResource->setAmount(storedResource->getAmount() - r->getAmount()); + } + } + } + limitResourcesToStore(); +} + +void Faction::limitResourcesToStore() +{ + for(int i=0; igetType()->getClass() != rcStatic && r->getAmount()>s->getAmount()) + { + r->setAmount(s->getAmount()); + } + } +} + +void Faction::resetResourceAmount(const ResourceType *rt){ + for(int i=0; i +#include + +#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 Resources; + typedef vector Store; + typedef vector Allies; + typedef vector Units; + typedef map 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 diff --git a/source/glest_game/world/world.cpp b/source/glest_game/world/world.cpp index 5746e296..f048c081 100644 --- a/source/glest_game/world/world.cpp +++ b/source/glest_game/world/world.cpp @@ -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�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; igetFactionTypeName(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));