1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-03-19 21:10:12 +02:00

More fixes for stacks, some basic macro-based logging for bonus graph operations.

This commit is contained in:
Michał W. Urbańczyk 2010-12-11 23:11:26 +00:00
parent e677cd5b07
commit fc6d6e02a3
17 changed files with 143 additions and 69 deletions

View File

@ -26,6 +26,8 @@
#include <cmath>
#include <sstream>
#include <boost/format.hpp>
#include "../hch/CCreatureHandler.h"
#include "../hch/CMusicHandler.h"
using namespace boost::assign;
using namespace CSDL_Ext;

View File

@ -110,13 +110,13 @@ public:
void showGarrisonDialog(int upobj, int hid, bool removableUnits, const boost::function<void()> &cb){};
void showThievesGuildWindow(int requestingObjId){};
void giveResource(int player, int which, int val){};
void giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet &creatures, bool remove) {};
void giveCreatures (int objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) {};
void takeCreatures (int objid, TSlots creatures){};
void takeCreatures (int objid, std::vector<CStackBasicDescriptor> creatures){};
bool changeStackType(const StackLocation &sl, CCreature *c){return false;};
bool changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false){return false;};
bool insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count){return false;};
bool eraseStack(const StackLocation &sl){return false;};
bool eraseStack(const StackLocation &sl, bool forceRemoval = false){return false;};
bool swapStacks(const StackLocation &sl1, const StackLocation &sl2){return false;}
bool addToSlot(const StackLocation &sl, const CCreature *c, TQuantity count){return false;}
void tryJoiningArmy(const CArmedInstance *src, const CArmedInstance *dst, bool removeObjWhenFinished){}

View File

@ -47,6 +47,8 @@
#include "../StartInfo.h"
#include "CPreGame.h"
#include "../lib/HeroBonus.h"
#include "../hch/CCreatureHandler.h"
#include "../hch/CMusicHandler.h"
/*
* GUIClasses.cpp, part of VCMI engine
@ -4873,8 +4875,8 @@ void CArtifactsOfHero::setHero(const CGHeroInstance * hero)
{
if(curHero != hero)
{
delete curHero;
hero = curHero = new CGHeroInstance(*hero);
//delete curHero;
//hero = curHero = new CGHeroInstance(*hero);
}
// Compensate backpack pos if an artifact was insertad before it.
@ -4923,8 +4925,8 @@ void CArtifactsOfHero::setHero(const CGHeroInstance * hero)
if(hero != curHero)
{
delete curHero;
curHero = new CGHeroInstance(*hero);
// delete curHero;
// curHero = new CGHeroInstance(*hero);
}
if (curHero->artifacts.size() > 0)

View File

@ -1575,6 +1575,11 @@ void CGHeroInstance::initExp()
level = 1;
}
std::string CGHeroInstance::nodeName() const
{
return "Hero " + name;
}
void CGDwelling::initObj()
{
switch(ID)
@ -5008,24 +5013,23 @@ void CGPandoraBox::giveContents( const CGHeroInstance *h, bool afterBattle ) con
if (creatures.Slots().size())
{ //this part is taken straight from creature bank
MetaString loot;
CCreatureSet ourArmy = creatures;
for(TSlots::const_iterator i = ourArmy.Slots().begin(); i != ourArmy.Slots().end(); i++)
for(TSlots::const_iterator i = creatures.Slots().begin(); i != creatures.Slots().end(); i++)
{ //build list of joined creatures
iw.components.push_back(Component(*i->second));
loot << "%s";
loot.addReplacement(*i->second);
}
if (ourArmy.Slots().size() == 1 && ourArmy.Slots().begin()->second->count == 1)
iw.text.addTxt (MetaString::ADVOB_TXT, 185);
if (creatures.Slots().size() == 1 && creatures.Slots().begin()->second->count == 1)
iw.text.addTxt(MetaString::ADVOB_TXT, 185);
else
iw.text.addTxt (MetaString::ADVOB_TXT, 186);
iw.text.addTxt(MetaString::ADVOB_TXT, 186);
iw.text.addReplacement(loot.buildList());
iw.text.addReplacement(h->name);
cb->showInfoDialog(&iw);
cb->giveCreatures (id, h, ourArmy, true);
cb->giveCreatures (id, h, creatures, true);
//boost::bind(&CGPandoraBox::endBattle, this, h, _1)
}
if(!afterBattle && message.size())

View File

@ -369,6 +369,8 @@ public:
//////////////////////////////////////////////////////////////////////////
virtual std::string nodeName() const OVERRIDE;
void setPropertyDer(ui8 what, ui32 val);//synchr
void initObj();
void onHeroVisit(const CGHeroInstance * h) const;

View File

@ -7,6 +7,7 @@
#include "IGameCallback.h"
#include "CGameState.h"
#include "../hch/CGeneralTextHandler.h"
#include <sstream>
const CStackInstance &CCreatureSet::operator[](TSlot slot) const
{
@ -465,6 +466,20 @@ CStackInstance::~CStackInstance()
}
std::string CStackInstance::nodeName() const
{
std::ostringstream oss;
oss << "Stack of " << count << " creatures of ";
if(type)
oss << type->namePl;
else if(idRand)
oss << "[no type, idRand=" << idRand << "]";
else
oss << "[UNDEFINED TYPE]";
return oss.str();
}
CStackBasicDescriptor::CStackBasicDescriptor()
{
type = NULL;

View File

@ -64,6 +64,7 @@ public:
void setType(const CCreature *c);
void setArmyObj(const CArmedInstance *ArmyObj);
bool valid(bool allowUnrandomized) const;
virtual std::string nodeName() const OVERRIDE;
};
DLL_EXPORT std::ostream & operator<<(std::ostream & str, const CStackInstance & sth);

View File

@ -1038,6 +1038,21 @@ const CGHeroInstance * CStack::getMyHero() const
return NULL;
}
std::string CStack::nodeName() const
{
std::ostringstream oss;
oss << "Battle stack of " << count << " creatures of ";
if(type)
oss << type->namePl;
else
oss << "[UNDEFINED TYPE]";
oss << " from slot " << (int)slot;
if(base && base->armyObj)
oss << " of armyobj=" << base->armyObj->id;
return oss.str();
}
CGHeroInstance * CGameState::HeroesPool::pickHeroFor(bool native, int player, const CTown *town, std::map<ui32,CGHeroInstance *> &available, const CHeroClass *bannedClass /*= NULL*/) const
{
CGHeroInstance *ret = NULL;
@ -4556,6 +4571,11 @@ PlayerState::PlayerState()
}
std::string PlayerState::nodeName() const
{
return "Player " + (color < VLC->generaltexth->capColors.size() ? VLC->generaltexth->capColors[color] : boost::lexical_cast<std::string>(color));
}
// void PlayerState::getParents(TCNodes &out, const CBonusSystemNode *root /*= NULL*/) const
// {
// return; //no loops possible

View File

@ -143,6 +143,7 @@ public:
ui8 daysWithoutCastle;
PlayerState();
std::string nodeName() const OVERRIDE;
//override
//void getParents(TCNodes &out, const CBonusSystemNode *root = NULL) const;
@ -281,6 +282,7 @@ public:
CStack(const CStackBasicDescriptor *stack, int O, int I, bool AO, int S = 255); //c-tor
CStack(); //c-tor
~CStack();
std::string nodeName() const OVERRIDE;
void init(); //set initial (invalid) values
void postInit(); //used to finish initialization when inheriting creature parameters is working

View File

@ -18,6 +18,8 @@
DLL_EXPORT const std::map<std::string, int> bonusNameMap = boost::assign::map_list_of BONUS_LIST;
#undef BONUS_NAME
#define BONUS_LOG_LINE(x) tlog0 << x << std::endl
int DLL_EXPORT BonusList::totalValue() const
{
int base = 0;
@ -406,12 +408,14 @@ void CBonusSystemNode::newChildAttached(CBonusSystemNode *child)
{
assert(!vstd::contains(children, child));
children.push_back(child);
BONUS_LOG_LINE(child->nodeName() << " #attached to# " << nodeName());
}
void CBonusSystemNode::childDetached(CBonusSystemNode *child)
{
assert(vstd::contains(children, child));
children -= child;
BONUS_LOG_LINE(child->nodeName() << " #detached from# " << nodeName());
}
void CBonusSystemNode::detachFromAll()
@ -425,6 +429,11 @@ bool CBonusSystemNode::isIndependentNode() const
return parents.empty() && children.empty();
}
std::string CBonusSystemNode::nodeName() const
{
return std::string("Bonus system node of type ") + typeid(*this).name();
}
int NBonus::valOf(const CBonusSystemNode *obj, Bonus::BonusType type, int subtype /*= -1*/)
{
if(obj)

View File

@ -394,8 +394,8 @@ public:
bool hasBonusFrom(ui8 source, ui32 sourceID) const;
void getModifiersWDescr( TModDescr &out, Bonus::BonusType type, int subtype = -1 ) const; //out: pairs<modifier value, modifier description>
int getBonusesCount(int from, int id) const;
virtual ui32 getMinDamage() const; //used for stacks and creatures only
virtual ui32 getMaxDamage() const;
ui32 getMinDamage() const; //used for stacks and creatures only
ui32 getMaxDamage() const;
int MoraleVal() const; //range [-3, +3]
int LuckVal() const; //range [-3, +3]
@ -426,6 +426,7 @@ public:
CBonusSystemNode *whereToPropagate(Bonus *b);
void popBonuses(const CSelector &s);
virtual std::string nodeName() const;
template <typename Handler> void serialize(Handler &h, const int version)
{

View File

@ -87,13 +87,13 @@ public:
virtual void showGarrisonDialog(int upobj, int hid, bool removableUnits, const boost::function<void()> &cb) =0; //cb will be called when player closes garrison window
virtual void showThievesGuildWindow(int requestingObjId) =0;
virtual void giveResource(int player, int which, int val)=0;
virtual void giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet &creatures, bool remove) =0;
virtual void giveCreatures (int objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) =0;
//virtual void takeCreatures (int objid, TSlots creatures) =0;
virtual void takeCreatures (int objid, std::vector<CStackBasicDescriptor> creatures) =0;
virtual bool changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false) =0;
virtual bool changeStackType(const StackLocation &sl, CCreature *c) =0;
virtual bool insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count = -1) =0; //count -1 => moves whole stack
virtual bool eraseStack(const StackLocation &sl) =0;
virtual bool eraseStack(const StackLocation &sl, bool forceRemoval = false) =0;
virtual bool swapStacks(const StackLocation &sl1, const StackLocation &sl2) =0;
virtual bool addToSlot(const StackLocation &sl, const CCreature *c, TQuantity count) =0; //makes new stack or increases count of already existing
virtual void tryJoiningArmy(const CArmedInstance *src, const CArmedInstance *dst, bool removeObjWhenFinished) =0; //merges army from src do dst or opens a garrison window

View File

@ -752,7 +752,7 @@ struct ChangeStackCount : CGarrisonOperationPack //521
template <typename Handler> void serialize(Handler &h, const int version)
{
h & sl & count;
h & sl & count & absoluteValue;
}
};

View File

@ -777,10 +777,9 @@ void Mapa::loadTown( CGObjectInstance * &nobj, const unsigned char * bufor, int
nt->garrisonHero = NULL;
}
void Mapa::loadHero( CGObjectInstance * &nobj, const unsigned char * bufor, int &i )
CGObjectInstance * Mapa::loadHero(const unsigned char * bufor, int &i)
{
CGHeroInstance * nhi = new CGHeroInstance;
nobj=nhi;
CGHeroInstance * nhi = new CGHeroInstance();
int identifier = 0;
if(version>RoE)
@ -789,20 +788,20 @@ void Mapa::loadHero( CGObjectInstance * &nobj, const unsigned char * bufor, int
}
ui8 owner = bufor[i++];
nobj->subID = readNormalNr(bufor,i, 1); ++i;
nhi->subID = readNormalNr(bufor,i, 1); ++i;
for(unsigned int j=0; j<predefinedHeroes.size(); j++)
{
if(predefinedHeroes[j]->subID == nobj->subID)
if(predefinedHeroes[j]->subID == nhi->subID)
{
*nhi = *predefinedHeroes[j];
tlog0 << "Hero " << nhi->subID << " will be taken from the predefined heroes list.\n";
delete nhi;
nhi = predefinedHeroes[j];
break;
}
}
nobj->setOwner(owner);
nhi->setOwner(owner);
//(*(static_cast<CGObjectInstance*>(nhi))) = *nobj;
//delete nobj;
nhi->portrait = nhi->subID;
for(unsigned int j=0; j<disposedHeroes.size(); j++)
@ -954,11 +953,8 @@ void Mapa::loadHero( CGObjectInstance * &nobj, const unsigned char * bufor, int
}
}
i+=16;
nhi->moveDir = 4;
nhi->isStanding = true;
nhi->level = -1;
nhi->mana = -1;
nhi->movement = -1;
return nhi;
}
void Mapa::readRumors( const unsigned char * bufor, int &i)
@ -1385,7 +1381,7 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
}
case 34: case 70: case 62: //34 - hero; 70 - random hero; 62 - prison
{
loadHero(nobj, bufor, i);
nobj = loadHero(bufor, i);
break;
}
case 4: //Arena

View File

@ -293,7 +293,7 @@ struct DLL_EXPORT Mapa : public CMapHeader
void readPredefinedHeroes( const unsigned char * bufor, int &i);
void readHeader( const unsigned char * bufor, int &i);
void readRumors( const unsigned char * bufor, int &i);
void loadHero( CGObjectInstance * &nobj, const unsigned char * bufor, int &i);
CGObjectInstance *loadHero(const unsigned char * bufor, int &i);
void loadTown( CGObjectInstance * &nobj, const unsigned char * bufor, int &i, int subid);
int loadSeerHut( const unsigned char * bufor, int i, CGObjectInstance *& nobj);

View File

@ -310,28 +310,6 @@ void CGameHandler::changeSecSkill( int ID, int which, int val, bool abs/*=false*
}
}
void CGameHandler::takeCasualties(const CArmedInstance *army, BattleInfo *bat)
{
int color = army->tempOwner;
if(color == 254)
color = NEUTRAL_PLAYER;
BOOST_FOREACH(CStack *st, bat->stacks)
{
if(vstd::contains(st->state, SUMMONED)) //don't take into account sumoned stacks
continue;
if(st->owner==color && !army->slotEmpty(st->slot) && st->count < army->getStackCount(st->slot))
{
StackLocation sl(army, st->slot);
if(st->alive())
changeStackCount(sl, st->count, true);
else
eraseStack(sl);
}
}
}
void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function<void(BattleResult*)> cb, const CGTownInstance *town)
{
battleEndCallback = new boost::function<void(BattleResult*)>(cb);
@ -567,7 +545,6 @@ void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance
void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2)
{
BattleResultsApplied resultsApplied;
resultsApplied.player1 = bEndArmy1->tempOwner;
resultsApplied.player2 = bEndArmy2->tempOwner;
@ -584,18 +561,16 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
battleResult.data->exp[0] *= (100+hero1->getSecSkillLevel(21)*5)/100.0f;//sholar skill
if (hero2)
battleResult.data->exp[1] *= (100+hero2->getSecSkillLevel(21)*5)/100.0f;
sendAndApply(battleResult.data);
//casualties among heroes armies
takeCasualties(bEndArmy1, gs->curB);
takeCasualties(bEndArmy2, gs->curB);
ui8 sides[2];
sides[0] = gs->curB->side1;
sides[1] = gs->curB->side2;
ui8 loser = sides[!battleResult.data->winner];
CasualtiesAfterBattle cab1(bEndArmy1, gs->curB), cab2(bEndArmy2, gs->curB); //calculate casualties before deleting battle
sendAndApply(battleResult.data);
cab1.takeFromArmy(this); cab2.takeFromArmy(this); //take casualties after battle is deleted
//if one hero has lost we will erase him
if(battleResult.data->winner!=0 && hero1)
{
@ -2087,7 +2062,7 @@ void CGameHandler::giveResource(int player, int which, int val)
sr.val = gs->players.find(player)->second.resources[which]+val;
sendAndApply(&sr);
}
void CGameHandler::giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet &creatures, bool remove)
void CGameHandler::giveCreatures (int objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove)
{
assert(0);
// if (creatures.stacksCount() <= 0)
@ -3082,6 +3057,7 @@ bool CGameHandler::garrisonSwap( si32 tid )
intown.garrison = -1;
intown.visiting = town->garrisonHero->id;
sendAndApply(&intown);
return true;
}
else if (town->garrisonHero && town->visitingHero) //swap visiting and garrison hero
{
@ -5246,13 +5222,14 @@ bool CGameHandler::insertNewStack(const StackLocation &sl, const CCreature *c, T
return true;
}
bool CGameHandler::eraseStack(const StackLocation &sl)
bool CGameHandler::eraseStack(const StackLocation &sl, bool forceRemoval/* = false*/)
{
if(!sl.army->hasStackAtSlot(sl.slot))
COMPLAIN_RET("Cannot find a stack to erase");
if(sl.army->Slots().size() == 1 //from the last stack
&& sl.army->needsLastStack()) //that must be left
&& sl.army->needsLastStack() //that must be left
&& !forceRemoval) //ignore above conditions if we are forcing removal
{
COMPLAIN_RET("Cannot erase the last stack!");
}
@ -5379,4 +5356,37 @@ bool CGameHandler::swapStacks(const StackLocation &sl1, const StackLocation &sl2
sendAndApply(&ss);
return true;
}
}
CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleInfo *bat)
{
int color = army->tempOwner;
if(color == 254)
color = NEUTRAL_PLAYER;
BOOST_FOREACH(CStack *st, bat->stacks)
{
if(vstd::contains(st->state, SUMMONED)) //don't take into account sumoned stacks
continue;
if(st->owner==color && !army->slotEmpty(st->slot) && st->count < army->getStackCount(st->slot))
{
StackLocation sl(army, st->slot);
if(st->alive())
newStackCounts.push_back(std::pair<StackLocation, int>(sl, st->count));
else
newStackCounts.push_back(std::pair<StackLocation, int>(sl, 0));
}
}
}
void CasualtiesAfterBattle::takeFromArmy(CGameHandler *gh)
{
BOOST_FOREACH(TStackAndItsNewCount &ncount, newStackCounts)
{
if(ncount.second > 0)
gh->changeStackCount(ncount.first, ncount.second, true);
else
gh->eraseStack(ncount.first, true);
}
}

View File

@ -23,6 +23,7 @@
*
*/
class CGameHandler;
class CVCMIServer;
class CGameState;
struct StartInfo;
@ -74,6 +75,16 @@ public:
}
};
struct CasualtiesAfterBattle
{
typedef std::pair<StackLocation, int> TStackAndItsNewCount;
enum {ERASE = -1};
std::vector<TStackAndItsNewCount> newStackCounts;
CasualtiesAfterBattle(const CArmedInstance *army, BattleInfo *bat);
void takeFromArmy(CGameHandler *gh);
};
class CGameHandler : public IGameCallback
{
private:
@ -94,7 +105,6 @@ public:
bool isAllowedExchange(int id1, int id2);
void giveSpells(const CGTownInstance *t, const CGHeroInstance *h);
int moveStack(int stack, int dest); //returned value - travelled distance
void takeCasualties(const CArmedInstance *army, BattleInfo *bat);
void startBattle(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function<void(BattleResult*)> cb, const CGTownInstance *town = NULL); //use hero=NULL for no hero
void checkLossVictory(ui8 player);
void winLoseHandle(ui8 players=255); //players: bit field - colours of players to be checked; default: all
@ -138,12 +148,12 @@ public:
void showGarrisonDialog(int upobj, int hid, bool removableUnits, const boost::function<void()> &cb);
void showThievesGuildWindow(int requestingObjId); //TODO: make something more general?
void giveResource(int player, int which, int val);
void giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet &creatures, bool remove);
void giveCreatures (int objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove);
void takeCreatures (int objid, std::vector<CStackBasicDescriptor> creatures);
bool changeStackType(const StackLocation &sl, CCreature *c);
bool changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false);
bool insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count);
bool eraseStack(const StackLocation &sl);
bool eraseStack(const StackLocation &sl, bool forceRemoval = false);
bool swapStacks(const StackLocation &sl1, const StackLocation &sl2);
bool addToSlot(const StackLocation &sl, const CCreature *c, TQuantity count);
void tryJoiningArmy(const CArmedInstance *src, const CArmedInstance *dst, bool removeObjWhenFinished);