1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00

Stacks #4 -> giving creatures still needs to be fixed.

This commit is contained in:
Michał W. Urbańczyk 2010-12-05 23:10:02 +00:00
parent fdb541d81e
commit 848a00bc6f
23 changed files with 492 additions and 334 deletions

View File

@ -4,6 +4,7 @@
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/lambda/if.hpp>
#include <boost/foreach.hpp>
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN //excludes rarely used stuff from windows headers - delete this line if something is missing
@ -72,8 +73,8 @@ void CBattleLogic::SetCurrentTurn(int turn)
void CBattleLogic::MakeStatistics(int currentCreatureId)
{
typedef std::map<int, CStack> map_stacks;
map_stacks allStacks = m_cb->battleGetStacks();
typedef std::vector<const CStack*> vector_stacks;
vector_stacks allStacks = m_cb->battleGetStacks();
const CStack *currentStack = m_cb->battleGetStackByID(currentCreatureId);
if(currentStack->position < 0) //turret
{
@ -118,14 +119,13 @@ void CBattleLogic::MakeStatistics(int currentCreatureId)
int totalDamage = 0;
int totalHitPoints = 0;
for (map_stacks::const_iterator it = allStacks.begin(); it != allStacks.end(); ++it)
BOOST_FOREACH(const CStack *st, allStacks)
{
const CStack *st = &it->second;
const int stackHP = st->valOfBonuses(Bonus::STACK_HEALTH);
if ((it->second.attackerOwned != 0) != m_bIsAttacker)
if ((st->attackerOwned != 0) != m_bIsAttacker)
{
int id = it->first;
int id = st->ID;
if (st->count < 1)
{
continue;

View File

@ -542,19 +542,19 @@ int CCallback::battleGetPos(int stack)
return -1;
}
std::map<int, CStack> CCallback::battleGetStacks()
std::vector<const CStack*> CCallback::battleGetStacks()
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
std::map<int, CStack> ret;
std::vector<const CStack*> ret;
if(!gs->curB) //there is no battle
{
tlog2<<"battleGetStacks called when there is no battle!"<<std::endl;
return ret;
}
for(size_t g=0; g<gs->curB->stacks.size(); ++g)
{
ret[gs->curB->stacks[g]->ID] = *(gs->curB->stacks[g]);
}
BOOST_FOREACH(const CStack *s, gs->curB->stacks)
ret.push_back(s);
return ret;
}
@ -1037,7 +1037,7 @@ InfoAboutTown::~InfoAboutTown()
void InfoAboutTown::initFromTown( const CGTownInstance *t, bool detailed )
{
obj = t;
army = t->getArmy();
army = ArmyDescriptor(t, detailed);
built = t->builded;
fortLevel = t->fortLevel();
name = t->name;
@ -1053,21 +1053,14 @@ void InfoAboutTown::initFromTown( const CGTownInstance *t, bool detailed )
details->hallLevel = t->hallLevel();
details->garrisonedHero = t->garrisonHero;
}
/*else
{
//hide info about hero stacks counts
for(std::map<si32,std::pair<ui32,si32> >::iterator i = slots.begin(); i != slots.end(); ++i)
{
i->second.second = 0;
}
}*/
//TODO: adjust undetailed info about army to our count of thieves guilds
}
void InfoAboutTown::initFromGarrison(const CGGarrison *garr, bool detailed)
{
obj = garr;
fortLevel = 0;
army = garr->getArmy();
army = ArmyDescriptor(garr, detailed);
name = CGI->generaltexth->names[33]; // "Garrison"
owner = garr->tempOwner;
built = false;

View File

@ -61,7 +61,7 @@ struct InfoAboutTown
CTown *tType;
bool built;
CCreatureSet army; //numbers of creatures are valid only if details
ArmyDescriptor army; //numbers of creatures are valid only if details
InfoAboutTown();
~InfoAboutTown();
@ -166,7 +166,7 @@ public:
virtual const CStack * battleGetStackByPos(int pos, bool onlyAlive = true)=0; //returns stack info by given pos
virtual int battleGetPos(int stack)=0; //returns position (tile ID) of stack
virtual int battleMakeAction(BattleAction* action)=0;//for casting spells by hero - DO NOT use it for moving active stack
virtual std::map<int, CStack> battleGetStacks()=0; //returns stacks on battlefield
virtual std::vector<const CStack*> battleGetStacks()=0; //returns stacks on battlefield
virtual void getStackQueue( std::vector<const CStack *> &out, int howMany )=0; //returns vector of stack in order of their move sequence
virtual CCreature battleGetCreature(int number)=0; //returns type of creature by given number of stack
//virtual bool battleMoveCreature(int ID, int dest)=0; //moves creature with id ID to dest if possible
@ -297,7 +297,7 @@ public:
const CStack * battleGetStackByPos(int pos, bool onlyAlive = true); //returns stack info by given pos
int battleGetPos(int stack); //returns position (tile ID) of stack
int battleMakeAction(BattleAction* action);//for casting spells by hero - DO NOT use it for moving active stack
std::map<int, CStack> battleGetStacks(); //returns stacks on battlefield
std::vector<const CStack*> battleGetStacks(); //returns stacks on battlefield
void getStackQueue( std::vector<const CStack *> &out, int howMany ); //returns vector of stack in order of their move sequence
CCreature battleGetCreature(int number); //returns type of creature by given number of stack
std::vector<int> battleGetAvailableHexes(int ID, bool addOccupiable); //reutrns numbers of hexes reachable by creature with id ID

View File

@ -26,6 +26,7 @@
#include "../hch/CVideoHandler.h"
#include "../hch/CTownHandler.h"
#include <boost/assign/list_of.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string/replace.hpp>
#ifndef __GNUC__
@ -1138,12 +1139,12 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe
curInt->battleInt = this;
//initializing armies
this->army1 = *army1;
this->army2 = *army2;
std::map<int, CStack> stacks = curInt->cb->battleGetStacks();
for(std::map<int, CStack>::iterator b=stacks.begin(); b!=stacks.end(); ++b)
this->army1 = army1;
this->army2 = army2;
std::vector<const CStack*> stacks = curInt->cb->battleGetStacks();
BOOST_FOREACH(const CStack *s, stacks)
{
newStack(b->second.ID);
newStack(s->ID);
}
//preparing menu background and terrain
@ -1264,34 +1265,33 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe
bfield[h].myInterface = this;
}
//locking occupied positions on batlefield
for(std::map<int, CStack>::iterator it = stacks.begin(); it!=stacks.end(); ++it) //stacks gained at top of this function
{
if(it->second.position >= 0) //turrets have position < 0
bfield[it->second.position].accessible = false;
}
BOOST_FOREACH(const CStack *s, stacks) //stacks gained at top of this function
if(s->position >= 0) //turrets have position < 0
bfield[s->position].accessible = false;
//loading projectiles for units
for(std::map<int, CStack>::iterator g = stacks.begin(); g != stacks.end(); ++g)
BOOST_FOREACH(const CStack *s, stacks)
{
int creID = (g->second.getCreature()->idNumber == 149) ? CGI->creh->factionToTurretCreature[siegeH->town->town->typeID] : g->second.getCreature()->idNumber; //id of creature whose shots should be loaded
if(g->second.getCreature()->isShooting() && CGI->creh->idToProjectile.find(creID) != CGI->creh->idToProjectile.end())
{
idToProjectile[g->second.getCreature()->idNumber] = CDefHandler::giveDef(CGI->creh->idToProjectile.find(creID)->second);
int creID = (s->getCreature()->idNumber == 149) ? CGI->creh->factionToTurretCreature[siegeH->town->town->typeID] : s->getCreature()->idNumber; //id of creature whose shots should be loaded
if(s->getCreature()->isShooting() && vstd::contains(CGI->creh->idToProjectile, creID))
{
CDefHandler *&projectile = idToProjectile[s->getCreature()->idNumber];
projectile = CDefHandler::giveDef(CGI->creh->idToProjectile[creID]);
if(idToProjectile[g->second.getCreature()->idNumber]->ourImages.size() > 2) //add symmetric images
if(projectile->ourImages.size() > 2) //add symmetric images
{
for(int k = idToProjectile[g->second.getCreature()->idNumber]->ourImages.size()-2; k > 1; --k)
for(int k = projectile->ourImages.size()-2; k > 1; --k)
{
Cimage ci;
ci.bitmap = CSDL_Ext::rotate01(idToProjectile[g->second.getCreature()->idNumber]->ourImages[k].bitmap);
ci.bitmap = CSDL_Ext::rotate01(projectile->ourImages[k].bitmap);
ci.groupNumber = 0;
ci.imName = std::string();
idToProjectile[g->second.getCreature()->idNumber]->ourImages.push_back(ci);
projectile->ourImages.push_back(ci);
}
}
for(int s=0; s<idToProjectile[g->second.getCreature()->idNumber]->ourImages.size(); ++s) //alpha transforming
for(int s=0; s<projectile->ourImages.size(); ++s) //alpha transforming
{
CSDL_Ext::alphaTransform(idToProjectile[g->second.getCreature()->idNumber]->ourImages[s].bitmap);
CSDL_Ext::alphaTransform(projectile->ourImages[s].bitmap);
}
}
}
@ -1467,7 +1467,7 @@ void CBattleInterface::deactivate()
void CBattleInterface::show(SDL_Surface * to)
{
std::map<int, CStack> stacks = curInt->cb->battleGetStacks(); //used in a few places
std::vector<const CStack*> stacks = curInt->cb->battleGetStacks(); //used in a few places
++animCount;
if(!to) //"evaluating" to
to = screen;
@ -1558,20 +1558,20 @@ void CBattleInterface::show(SDL_Surface * to)
////showing units //a lot of work...
std::vector<int> stackAliveByHex[BFIELD_SIZE];
//double loop because dead stacks should be printed first
for(std::map<int, CStack>::iterator j=stacks.begin(); j!=stacks.end(); ++j)
BOOST_FOREACH(const CStack *s, stacks)
{
if(creAnims.find(j->second.ID) == creAnims.end()) //eg. for summoned but not yet handled stacks
if(creAnims.find(s->ID) == creAnims.end()) //eg. for summoned but not yet handled stacks
continue;
if(creAnims[j->second.ID]->getType() != 5 && j->second.position >= 0) //don't show turrets here
stackAliveByHex[j->second.position].push_back(j->second.ID);
if(creAnims[s->ID]->getType() != 5 && s->position >= 0) //don't show turrets here
stackAliveByHex[s->position].push_back(s->ID);
}
std::vector<int> stackDeadByHex[BFIELD_SIZE];
for(std::map<int, CStack>::iterator j=stacks.begin(); j!=stacks.end(); ++j)
BOOST_FOREACH(const CStack *s, stacks)
{
if(creAnims.find(j->second.ID) == creAnims.end()) //eg. for summoned but not yet handled stacks
if(creAnims.find(s->ID) == creAnims.end()) //eg. for summoned but not yet handled stacks
continue;
if(creAnims[j->second.ID]->getType() == 5)
stackDeadByHex[j->second.position].push_back(j->second.ID);
if(creAnims[s->ID]->getType() == 5)
stackDeadByHex[s->position].push_back(s->ID);
}
//handle animations
@ -1607,11 +1607,11 @@ void CBattleInterface::show(SDL_Surface * to)
activate();
//restoring good directions of stacks
for(std::map<int, CStack>::const_iterator it = stacks.begin(); it != stacks.end(); ++it)
BOOST_FOREACH(const CStack *s, stacks)
{
if(creDir[it->second.ID] != bool(it->second.attackerOwned) && it->second.alive())
if(creDir[s->ID] != bool(s->attackerOwned) && s->alive())
{
addNewAnim(new CReverseAnim(this, it->second.ID, it->second.position, false));
addNewAnim(new CReverseAnim(this, s->ID, s->position, false));
}
}
@ -1631,17 +1631,18 @@ void CBattleInterface::show(SDL_Surface * to)
creAnims[stackDeadByHex[b][v]]->nextFrame(to, creAnims[stackDeadByHex[b][v]]->pos.x, creAnims[stackDeadByHex[b][v]]->pos.y, creDir[stackDeadByHex[b][v]], animCount, false); //increment always when moving, never if stack died
}
}
std::vector<int> flyingStacks; //flying stacks should be displayed later, over other stacks and obstacles
std::vector<const CStack *> flyingStacks; //flying stacks should be displayed later, over other stacks and obstacles
for(int b=0; b<BFIELD_SIZE; ++b) //showing alive stacks
{
for(size_t v=0; v<stackAliveByHex[b].size(); ++v)
{
int curStackID = stackAliveByHex[b][v];
const CStack *s = LOCPLINT->cb->battleGetStackByID(curStackID, false); //TODO: dlaczego brak false psuje?
if(!stacks[curStackID].hasBonusOfType(Bonus::FLYING) || creAnims[curStackID]->getType() != 0)
showAliveStack(curStackID, stacks, to);
if(!s->hasBonusOfType(Bonus::FLYING) || creAnims[curStackID]->getType() != 0)
showAliveStack(s, to);
else
flyingStacks.push_back(curStackID);
flyingStacks.push_back(s);
}
//showing obstacles
@ -1663,7 +1664,7 @@ void CBattleInterface::show(SDL_Surface * to)
}
for(int b=0; b<flyingStacks.size(); ++b) //showing flyign stacks
showAliveStack(flyingStacks[b], stacks, to);
showAliveStack(flyingStacks[b], to);
//units shown
@ -2279,23 +2280,23 @@ void CBattleInterface::stackAttacking(int ID, int dest, int attackedID)
void CBattleInterface::newRoundFirst( int round )
{
//handle regeneration
std::map<int, CStack> stacks = curInt->cb->battleGetStacks();
for(std::map<int, CStack>::const_iterator it = stacks.begin(); it != stacks.end(); ++it)
std::vector<const CStack*> stacks = curInt->cb->battleGetStacks();
BOOST_FOREACH(const CStack *s, stacks)
{
//don't show animation when no HP is regenerated
if (it->second.firstHPleft == it->second.MaxHealth())
if (s->firstHPleft == s->MaxHealth())
{
continue;
}
if( it->second.hasBonusOfType(Bonus::HP_REGENERATION) && it->second.alive() )
displayEffect(74, it->second.position);
if( s->hasBonusOfType(Bonus::HP_REGENERATION) && s->alive() )
displayEffect(74, s->position);
if( it->second.hasBonusOfType(Bonus::FULL_HP_REGENERATION, 0) && it->second.alive() )
displayEffect(4, it->second.position);
if( s->hasBonusOfType(Bonus::FULL_HP_REGENERATION, 0) && s->alive() )
displayEffect(4, s->position);
if( it->second.hasBonusOfType(Bonus::FULL_HP_REGENERATION, 1) && it->second.alive() )
displayEffect(74, it->second.position);
if( s->hasBonusOfType(Bonus::FULL_HP_REGENERATION, 1) && s->alive() )
displayEffect(74, s->position);
}
}
@ -2967,12 +2968,12 @@ void CBattleInterface::endCastingSpell()
CGI->curh->changeGraphic(1, 6);
}
void CBattleInterface::showAliveStack(int ID, const std::map<int, CStack> & stacks, SDL_Surface * to)
void CBattleInterface::showAliveStack(const CStack *stack, SDL_Surface * to)
{
int ID = stack->ID;
if(creAnims.find(ID) == creAnims.end()) //eg. for summoned but not yet handled stacks
return;
const CStack &curStack = stacks.find(ID)->second;
int animType = creAnims[ID]->getType();
int affectingSpeed = curInt->sysOpts.animSpeed;
@ -3006,21 +3007,21 @@ void CBattleInterface::showAliveStack(int ID, const std::map<int, CStack> & stac
creAnims[ID]->nextFrame(to, creAnims[ID]->pos.x, creAnims[ID]->pos.y, creDir[ID], animCount, incrementFrame, ID==activeStack, ID==mouseHoveredStack); //increment always when moving, never if stack died
//printing amount
if(curStack.count > 0 //don't print if stack is not alive
if(stack->count > 0 //don't print if stack is not alive
&& (!curInt->curAction
|| (curInt->curAction->stackNumber != ID //don't print if stack is currently taking an action
&& (curInt->curAction->actionType != 6 || curStack.position != curInt->curAction->additionalInfo) //nor if it's an object of attack
&& (curInt->curAction->destinationTile != curStack.position) //nor if it's on destination tile for current action
&& (curInt->curAction->actionType != 6 || stack->position != curInt->curAction->additionalInfo) //nor if it's an object of attack
&& (curInt->curAction->destinationTile != stack->position) //nor if it's on destination tile for current action
)
)
&& !curStack.hasBonusOfType(Bonus::SIEGE_WEAPON) //and not a war machine...
&& !stack->hasBonusOfType(Bonus::SIEGE_WEAPON) //and not a war machine...
)
{
int xAdd = curStack.attackerOwned ? 220 : 202;
int xAdd = stack->attackerOwned ? 220 : 202;
//blitting amoutn background box
SDL_Surface *amountBG = NULL;
BonusList spellEffects = curStack.getSpellBonuses();
BonusList spellEffects = stack->getSpellBonuses();
if(!spellEffects.size())
{
amountBG = amountNormal;
@ -3028,7 +3029,7 @@ void CBattleInterface::showAliveStack(int ID, const std::map<int, CStack> & stac
else
{
int pos=0; //determining total positiveness of effects
std::vector<si32> spellIds = curStack.activeSpells();
std::vector<si32> spellIds = stack->activeSpells();
for(std::vector<si32>::const_iterator it = spellIds.begin(); it != spellIds.end(); it++)
{
pos += CGI->spellh->spells[ *it ].positiveness;
@ -3049,7 +3050,7 @@ void CBattleInterface::showAliveStack(int ID, const std::map<int, CStack> & stac
SDL_BlitSurface(amountBG, NULL, to, &genRect(amountNormal->h, amountNormal->w, creAnims[ID]->pos.x + xAdd, creAnims[ID]->pos.y + 260));
//blitting amount
CSDL_Ext::printAtMiddle(
makeNumberShort(curStack.count),
makeNumberShort(stack->count),
creAnims[ID]->pos.x + xAdd + 15,
creAnims[ID]->pos.y + 260 + 5,
FONT_TINY,
@ -3059,7 +3060,7 @@ void CBattleInterface::showAliveStack(int ID, const std::map<int, CStack> & stac
}
}
void CBattleInterface::showPieceOfWall(SDL_Surface * to, int hex, const std::map<int, CStack> & stacks)
void CBattleInterface::showPieceOfWall(SDL_Surface * to, int hex, const std::vector<const CStack*> & stacks)
{
if(!siegeH)
return;
@ -3094,18 +3095,20 @@ void CBattleInterface::showPieceOfWall(SDL_Surface * to, int hex, const std::map
if(posToSeek != -1)
{
int ID = -1;
for(std::map<int, CStack>::const_iterator it = stacks.begin(); it != stacks.end(); ++it)
const CStack *turret = NULL;
BOOST_FOREACH(const CStack *s, stacks)
{
if(it->second.position == posToSeek)
if(s->position == posToSeek)
{
ID = it->second.ID;
turret = s;
break;
}
}
if(ID != -1)
if(turret)
{
showAliveStack(ID, stacks, to);
showAliveStack(turret, to);
//blitting creature cover
switch(posToSeek)
{
@ -3621,7 +3624,7 @@ void CBattleHex::clickRight(tribool down, bool previousState)
if(!myst.alive()) return;
if(down)
{
GH.pushInt(new CCreInfoWindow(*myst.base));
GH.pushInt(new CCreInfoWindow(myst));
}
}
}
@ -3746,7 +3749,7 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect
{
int bestMonsterID = -1;
int bestPower = 0;
for(TSlots::const_iterator it = owner->army1.Slots().begin(); it!=owner->army1.Slots().end(); ++it)
for(TSlots::const_iterator it = owner->army1->Slots().begin(); it!=owner->army1->Slots().end(); ++it)
{
if( it->second->type->AIValue > bestPower)
{
@ -3768,7 +3771,7 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect
{
int bestMonsterID = -1;
int bestPower = 0;
for(TSlots::const_iterator it = owner->army2.Slots().begin(); it!=owner->army2.Slots().end(); ++it)
for(TSlots::const_iterator it = owner->army2->Slots().begin(); it!=owner->army2->Slots().end(); ++it)
{
if( it->second->type->AIValue > bestPower)
{

View File

@ -384,7 +384,7 @@ private:
CBattleConsole * console;
CBattleHero * attackingHero, * defendingHero; //fighting heroes
CStackQueue *queue;
CCreatureSet army1, army2; //copy of initial armies (for result window)
const CCreatureSet *army1, *army2; //copy of initial armies (for result window)
const CGHeroInstance * attackingHeroInstance, * defendingHeroInstance;
std::map< int, CCreatureAnimation * > creAnims; //animations of creatures from fighting armies (order by BattleInfo's stacks' ID)
std::map< int, CDefHandler * > idToProjectile; //projectiles of creatures (creatureID, defhandler)
@ -407,8 +407,8 @@ private:
BattleAction * spellToCast; //spell for which player is choosing destination
void endCastingSpell(); //ends casting spell (eg. when spell has been cast or canceled)
void showAliveStack(int ID, const std::map<int, CStack> & stacks, SDL_Surface * to); //helper function for function show
void showPieceOfWall(SDL_Surface * to, int hex, const std::map<int, CStack> & stacks); //helper function for show
void showAliveStack(const CStack *stack, SDL_Surface * to); //helper function for function show
void showPieceOfWall(SDL_Surface * to, int hex, const std::vector<const CStack*> & stacks); //helper function for show
void redrawBackgroundWithHexes(int activeStack);
void printConsoleAttacked(int ID, int dmg, int killed, int IDby);

View File

@ -2087,7 +2087,7 @@ CCreInfoWindow::CCreInfoWindow(const CStackInstance &st, int Type, boost::functi
: type(Type), dsm(Dsm), dismiss(0), upgrade(0), ok(0)
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
init(st.type, &st, st.count);
init(st.type, &st, dynamic_cast<const CGHeroInstance*>(st.armyObj), st.count);
//print abilities text - if r-click popup
if(type)
@ -2132,31 +2132,25 @@ CCreInfoWindow::CCreInfoWindow(const CStackInstance &st, int Type, boost::functi
}
ok = new AdventureMapButton("",CGI->generaltexth->zelp[445].second,boost::bind(&CCreInfoWindow::close,this),216,237,"IOKAY.DEF",SDLK_RETURN);
}
else
{
printAtWB(c->abilityText,17,231,FONT_SMALL,35,zwykly,*bitmap);
}
//if we are displying window fo r stack in battle, there are several more things that we need to display
if(const CStack *battleStack = dynamic_cast<const CStack*>(&st))
{
//spell effects
int printed=0; //how many effect pics have been printed
std::vector<si32> spells = battleStack->activeSpells();
BOOST_FOREACH(si32 effect, spells)
{
blitAt(graphics->spellEffectsPics->ourImages[effect + 1].bitmap, 127 + 52 * printed, 186, *bitmap);
++printed;
if(printed >= 3) //we can fit only 3 effects
break;
}
//print current health
printLine(5, CGI->generaltexth->allTexts[200], battleStack->firstHPleft);
}
}
CCreInfoWindow::CCreInfoWindow(int Cid, int Type, int creatureCount)
: type(Type), dismiss(0), upgrade(0), ok(0)
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
const CCreature *cre = CGI->creh->creatures[Cid];
init(cre, NULL, NULL, creatureCount);
}
CCreInfoWindow::CCreInfoWindow(const CStack &st, int Type /*= 0*/)
: type(Type), dismiss(0), upgrade(0), ok(0)
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
init(st.getCreature(), &st, st.getMyHero(), st.count);
}
void CCreInfoWindow::printLine(int nr, const std::string &text, int baseVal, int val/*=-1*/, bool range/*=false*/)
{
printAt(text, 155, 48 + nr*19, FONT_SMALL, zwykly, *bitmap);
@ -2172,15 +2166,11 @@ void CCreInfoWindow::printLine(int nr, const std::string &text, int baseVal, int
printTo(hlp, 276, 61 + nr*19, FONT_SMALL, zwykly, *bitmap);
}
void CCreInfoWindow::init(const CCreature *cre, const CStackInstance *stack, int creatureCount)
//void CCreInfoWindow::init(const CCreature *cre, const CStackInstance *stack, int creatureCount)
void CCreInfoWindow::init(const CCreature *cre, const CBonusSystemNode *stackNode, const CGHeroInstance *heroOwner, int creatureCount)
{
const CBonusSystemNode *finalNode = NULL;
if(stack)
finalNode = stack;
else
finalNode = cre;
c = cre;
if(!stackNode) stackNode = c;
bitmap = new CPicture("CRSTKPU.bmp");
bitmap->colorizeAndConvert(LOCPLINT->playerID);
@ -2190,52 +2180,67 @@ void CCreInfoWindow::init(const CCreature *cre, const CStackInstance *stack, int
count = boost::lexical_cast<std::string>(creatureCount);
printAtMiddle(c->namePl,149,30,FONT_SMALL,tytulowy,*bitmap); //creature name
printLine(0, CGI->generaltexth->primarySkillNames[0], cre->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK), finalNode->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK));
printLine(1, CGI->generaltexth->primarySkillNames[1], cre->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE), finalNode->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE));
printLine(0, CGI->generaltexth->primarySkillNames[0], cre->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK), stackNode->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK));
printLine(1, CGI->generaltexth->primarySkillNames[1], cre->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE), stackNode->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE));
if(c->shots)
printLine(2, CGI->generaltexth->allTexts[198], c->shots);
//TODO
int dmgMultiply = 1;
if(stack && stack->hasBonusOfType(Bonus::SIEGE_WEAPON))
dmgMultiply += stack->armyObj->Attack();
if(heroOwner && stackNode->hasBonusOfType(Bonus::SIEGE_WEAPON))
dmgMultiply += heroOwner->Attack();
printLine(3, CGI->generaltexth->allTexts[199], finalNode->getMinDamage() * dmgMultiply, finalNode->getMaxDamage() * dmgMultiply, true);
printLine(4, CGI->generaltexth->allTexts[388], cre->valOfBonuses(Bonus::STACK_HEALTH), finalNode->valOfBonuses(Bonus::STACK_HEALTH));
printLine(6, CGI->generaltexth->zelp[441].first, cre->valOfBonuses(Bonus::STACKS_SPEED), finalNode->valOfBonuses(Bonus::STACKS_SPEED));
printLine(3, CGI->generaltexth->allTexts[199], stackNode->getMinDamage() * dmgMultiply, stackNode->getMaxDamage() * dmgMultiply, true);
printLine(4, CGI->generaltexth->allTexts[388], cre->valOfBonuses(Bonus::STACK_HEALTH), stackNode->valOfBonuses(Bonus::STACK_HEALTH));
printLine(6, CGI->generaltexth->zelp[441].first, cre->valOfBonuses(Bonus::STACKS_SPEED), stackNode->valOfBonuses(Bonus::STACKS_SPEED));
//setting morale
morale = new MoraleLuckBox(true);
morale->pos = genRect(42, 42, pos.x + 24, pos.y + 189);
morale->set(stack);
morale->set(stackNode);
//setting luck
luck = new MoraleLuckBox(false);
luck->pos = genRect(42, 42, pos.x + 77, pos.y + 189);
luck->set(stack);
luck->set(stackNode);
//luck and morale
int luck = 3, morale = 3;
if(stack)
if(stackNode)
{
//add modifiers
luck += stack->LuckVal();
morale += stack->MoraleVal();
luck += stackNode->LuckVal();
morale += stackNode->MoraleVal();
}
blitAt(graphics->morale42->ourImages[morale].bitmap, 24, 189, *bitmap);
blitAt(graphics->luck42->ourImages[luck].bitmap, 77, 189, *bitmap);
if(!type)
{
printAtWB(c->abilityText,17,231,FONT_SMALL,35,zwykly,*bitmap);
}
//if we are displying window fo r stack in battle, there are several more things that we need to display
if(const CStack *battleStack = dynamic_cast<const CStack*>(stackNode))
{
//spell effects
int printed=0; //how many effect pics have been printed
std::vector<si32> spells = battleStack->activeSpells();
BOOST_FOREACH(si32 effect, spells)
{
blitAt(graphics->spellEffectsPics->ourImages[effect + 1].bitmap, 127 + 52 * printed, 186, *bitmap);
++printed;
if(printed >= 3) //we can fit only 3 effects
break;
}
//print current health
printLine(5, CGI->generaltexth->allTexts[200], battleStack->firstHPleft);
}
}
CCreInfoWindow::CCreInfoWindow(int Cid, int Type, int creatureCount)
: type(Type), dismiss(0), upgrade(0), ok(0)
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
const CCreature *cre = CGI->creh->creatures[Cid];
init(cre, NULL, creatureCount);
}
CCreInfoWindow::~CCreInfoWindow()
{

View File

@ -25,6 +25,7 @@
*
*/
class CStackBasicDescriptor;
class CBonusSystemNode;
class CArtifact;
class CDefEssential;
@ -879,8 +880,9 @@ public:
AdventureMapButton *dismiss, *upgrade, *ok;
CCreInfoWindow(const CStackInstance &st, int Type = 0, boost::function<void()> Upg = 0, boost::function<void()> Dsm = 0, UpgradeInfo *ui = NULL); //c-tor
CCreInfoWindow(const CStack &st, int Type = 0); //c-tor
CCreInfoWindow(int Cid, int Type, int creatureCount); //c-tor
void init(const CCreature *cre, const CStackInstance *stack, int creatureCount);
void init(const CCreature *cre, const CBonusSystemNode *stackNode, const CGHeroInstance *heroOwner, int creatureCount);
void printLine(int nr, const std::string &text, int baseVal, int val=-1, bool range=false);
~CCreInfoWindow(); //d-tor
void activate();
@ -892,10 +894,21 @@ public:
void show(SDL_Surface * to);
};
namespace Arts
{
enum EPos
{
PRE_FIRST = -1,
HEAD, SHOULDERS, NECK, RIGHT_HAND, LEFT_HAND, TORSO, RIGHT_RING, LEFT_RING, FEET, MISC1, MISC2, MISC3, MISC4,
MACH1, MACH2, MACH3, MACH4, SPELLBOOK, MISC5,
AFTER_LAST
};
}
class CArtPlace: public LRClickableAreaWTextComp
{
public:
ui16 slotID; //0 head 1 shoulders 2 neck 3 right hand 4 left hand 5 torso 6 right ring 7 left ring 8 feet 9 misc. slot 1 10 misc. slot 2 11 misc. slot 3 12 misc. slot 4 13 ballista (war machine 1) 14 ammo cart (war machine 2) 15 first aid tent (war machine 3) 16 catapult 17 spell book 18 misc. slot 5 19+ backpack slots
int slotID; //0 head 1 shoulders 2 neck 3 right hand 4 left hand 5 torso 6 right ring 7 left ring 8 feet 9 misc. slot 1 10 misc. slot 2 11 misc. slot 3 12 misc. slot 4 13 ballista (war machine 1) 14 ammo cart (war machine 2) 15 first aid tent (war machine 3) 16 catapult 17 spell book 18 misc. slot 5 19+ backpack slots
bool marked;
bool selectedNo;
@ -915,6 +928,7 @@ public:
~CArtPlace(); //d-tor
};
class CArtifactsOfHero : public CIntObject
{
CGHeroInstance * curHero; //local copy of hero on which we operate

View File

@ -53,17 +53,17 @@ SDL_Surface * Graphics::drawHeroInfoWin(const InfoAboutHero &curh)
blitAt(graphics->portraitLarge[curh.portrait],11,12,ret); //portrait
//army
for (TSlots::const_iterator i = curh.army.Slots().begin(); i!=curh.army.Slots().end();i++)
for (ArmyDescriptor::const_iterator i = curh.army.begin(); i!=curh.army.end();i++)
{
blitAt(graphics->smallImgs[(*i).second->type->idNumber],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret);
blitAt(graphics->smallImgs[i->second.type->idNumber],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret);
if(curh.details)
{
SDL_itoa((*i).second->count,buf,10);
SDL_itoa((*i).second.count,buf,10);
printAtMiddle(buf,slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+41,FONT_TINY,zwykly,ret);
}
else
{
printAtMiddle(VLC->generaltexth->arraytxt[174 + 3*(i->second->count-1)],slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+41,FONT_TINY,zwykly,ret);
printAtMiddle(VLC->generaltexth->arraytxt[174 + 3*(i->second.count-1)],slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+41,FONT_TINY,zwykly,ret);
}
}
@ -110,15 +110,15 @@ SDL_Surface * Graphics::drawTownInfoWin( const InfoAboutTown & curh )
int pom = curh.fortLevel - 1; if(pom<0) pom = 3; //fort pic id
blitAt(forts->ourImages[pom].bitmap,115,42,ret); //fort
for (TSlots::const_iterator i=curh.army.Slots().begin(); i!=curh.army.Slots().end();i++)
for (ArmyDescriptor::const_iterator i=curh.army.begin(); i!=curh.army.end();i++)
{
//if(!i->second.second)
// continue;
blitAt(graphics->smallImgs[(*i).second->type->idNumber],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret);
blitAt(graphics->smallImgs[(*i).second.type->idNumber],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret);
if(curh.details)
{
// Show exact creature amount.
SDL_itoa((*i).second->count,buf,10);
SDL_itoa((*i).second.count,buf,10);
printAtMiddle(buf,slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+41,FONT_TINY,zwykly,ret);
}
else

View File

@ -308,12 +308,12 @@ void TryMoveHero::applyCl( CClient *cl )
}
}
void SetGarrisons::applyCl( CClient *cl )
{
for(std::map<ui32,CCreatureSet>::iterator i = garrs.begin(); i!=garrs.end(); i++)
if(vstd::contains(cl->playerint,cl->getOwner(i->first)))
cl->playerint[cl->getOwner(i->first)]->garrisonChanged(cl->getObj(i->first));
}
// void SetGarrisons::applyCl( CClient *cl )
// {
// for(std::map<ui32,CCreatureSet>::iterator i = garrs.begin(); i!=garrs.end(); i++)
// if(vstd::contains(cl->playerint,cl->getOwner(i->first)))
// cl->playerint[cl->getOwner(i->first)]->garrisonChanged(cl->getObj(i->first));
// }
void NewStructures::applyCl( CClient *cl )
{

View File

@ -531,13 +531,12 @@ void CCampaignScenario::prepareCrossoverHeroes( std::vector<CGHeroInstance *> he
//trimming creatures
BOOST_FOREACH(CGHeroInstance * cgh, crossoverHeroes)
{
CCreatureSet army = cgh->getArmy();
for (TSlots::iterator j = army.slots.begin(); j != army.slots.end(); j++)
for (TSlots::const_iterator j = cgh->Slots().begin(); j != cgh->Slots().end(); j++)
{
if (! (travelOptions.monstersKeptByHero[j->first / 8] & (1 << (j->first%8)) ))
if (!(travelOptions.monstersKeptByHero[j->first / 8] & (1 << (j->first%8)) ))
{
army.slots.erase(j);
j = army.slots.begin();
cgh->eraseStack(j->first);
j = cgh->Slots().begin();
}
}
}

View File

@ -777,6 +777,7 @@ const CArtifact * CGHeroInstance::getArt(int pos) const
CGHeroInstance::CGHeroInstance()
: IBoatGenerator(this)
{
nodeType = HERO;
ID = HEROI_TYPE;
tacticFormationEnabled = inTownGarrison = false;
mana = movement = portrait = level = -1;
@ -3449,28 +3450,27 @@ void CGTeleport::onHeroVisit( const CGHeroInstance * h ) const
{
if (!h->hasBonusOfType(Bonus::WHIRLPOOL_PROTECTION))
{
CCreatureSet army = h->getArmy();
if (army.Slots().size() > 1 || army.Slots().begin()->second->count > 1)
if (h->Slots().size() > 1 || h->Slots().begin()->second->count > 1)
{ //we can't remove last unit
int targetstack = army.Slots().begin()->first; //slot numbers may vary
for(TSlots::const_reverse_iterator i = army.Slots().rbegin(); i != army.Slots().rend(); i++)
TSlot targetstack = h->Slots().begin()->first; //slot numbers may vary
for(TSlots::const_reverse_iterator i = h->Slots().rbegin(); i != h->Slots().rend(); i++)
{
if (army.getPower(targetstack) > army.getPower(i->first))
if (h->getPower(targetstack) > h->getPower(i->first))
{
targetstack = (i->first);
}
}
std::vector<CStackBasicDescriptor> cresToTake;
cresToTake.push_back(CStackBasicDescriptor(army.getStack(targetstack)));
cresToTake[0].count * 0.5;
amax (cresToTake[0].count, 1);
TQuantity countToTake = h->getStackCount(targetstack) * 0.5;
amax(countToTake, 1);
InfoWindow iw;
iw.player = h->tempOwner;
iw.text.addTxt (MetaString::ADVOB_TXT, 168);
iw.components.push_back (Component(cresToTake[0]));
iw.components.push_back (Component(CStackBasicDescriptor(h->getCreature(targetstack), countToTake)));
cb->showInfoDialog(&iw);
cb->takeCreatures (h->id, cresToTake);
cb->changeStackCount(StackLocation(h, targetstack), -countToTake);
}
}
}
@ -4380,7 +4380,7 @@ int CGSeerHut::checkDirection() const
return 4;
}
}
void CGSeerHut::finishQuest (const CGHeroInstance * h, ui32 accept) const
void CGSeerHut::finishQuest(const CGHeroInstance * h, ui32 accept) const
{
if (accept)
{
@ -4393,7 +4393,7 @@ void CGSeerHut::finishQuest (const CGHeroInstance * h, ui32 accept) const
}
break;
case CQuest::MISSION_ARMY:
cb->takeCreatures (h->id, m6creatures);
cb->takeCreatures(h->id, m6creatures);
break;
case CQuest::MISSION_RESOURCES:
for (int i = 0; i < 7; ++i)
@ -4404,7 +4404,7 @@ void CGSeerHut::finishQuest (const CGHeroInstance * h, ui32 accept) const
default:
break;
}
cb->setObjProperty (id,11,0); //no more mission avaliable
cb->setObjProperty(id,11,0); //no more mission avaliable
completeQuest(h); //make sure to remove QuestQuard at the very end
}
}
@ -4453,11 +4453,11 @@ void CGSeerHut::completeQuest (const CGHeroInstance * h) const //reward
}
break;
case 10:// creature
{
CCreatureSet creatures;
creatures.setCreature (0, rID, rVal);
cb->giveCreatures (id, h, creatures,false);
}
{
CCreatureSet creatures;
creatures.setCreature(0, rID, rVal);
cb->giveCreatures (id, h, creatures,false);
}
break;
default:
break;

View File

@ -295,6 +295,11 @@ CCreatureSet::CCreatureSet()
formation = false;
}
CCreatureSet::CCreatureSet(const CCreatureSet&)
{
assert(0);
}
CCreatureSet::~CCreatureSet()
{
clear();
@ -322,7 +327,11 @@ CStackInstance * CCreatureSet::detachStack(TSlot slot)
CStackInstance *ret = slots[slot];
if(CArmedInstance *armedObj = castToArmyObj())
ret->detachFrom(armedObj);
{
ret->setArmyObj(NULL); //detaches from current armyobj
}
assert(!ret->armyObj); //we failed detaching?
slots.erase(slot);
return ret;
@ -353,6 +362,12 @@ bool CCreatureSet::hasStackAtSlot(TSlot slot) const
return vstd::contains(slots, slot);
}
CCreatureSet & CCreatureSet::operator=(const CCreatureSet&cs)
{
assert(0);
return cs;
}
CStackInstance::CStackInstance()
: armyObj(_armyObj)
{
@ -410,10 +425,9 @@ void CStackInstance::setArmyObj(const CArmedInstance *ArmyObj)
if(_armyObj)
detachFrom(const_cast<CArmedInstance*>(_armyObj));
_armyObj = ArmyObj;
if(ArmyObj)
{
_armyObj = ArmyObj;
attachTo(const_cast<CArmedInstance*>(_armyObj));
}
}
@ -446,6 +460,11 @@ bool CStackInstance::valid(bool allowUnrandomized) const
return allowUnrandomized;
}
CStackInstance::~CStackInstance()
{
}
CStackBasicDescriptor::CStackBasicDescriptor()
{
type = NULL;
@ -457,6 +476,11 @@ CStackBasicDescriptor::CStackBasicDescriptor(TCreature id, TQuantity Count)
{
}
CStackBasicDescriptor::CStackBasicDescriptor(const CCreature *c, TQuantity Count)
: type(c), count(Count)
{
}
DLL_EXPORT std::ostream & operator<<(std::ostream & str, const CStackInstance & sth)
{
if(!sth.valid(true))

View File

@ -24,6 +24,7 @@ public:
CStackBasicDescriptor();
CStackBasicDescriptor(TCreature id, TQuantity Count);
CStackBasicDescriptor(const CCreature *c, TQuantity Count);
template <typename Handler> void serialize(Handler &h, const int version)
{
@ -57,6 +58,8 @@ public:
CStackInstance();
CStackInstance(TCreature id, TQuantity count);
CStackInstance(const CCreature *cre, TQuantity count);
~CStackInstance();
void setType(int creID);
void setType(const CCreature *c);
void setArmyObj(const CArmedInstance *ArmyObj);
@ -71,6 +74,8 @@ typedef std::map<TSlot, CStackInstance*> TSlots;
class DLL_EXPORT CCreatureSet //seven combined creatures
{
CCreatureSet(const CCreatureSet&);;
CCreatureSet &operator=(const CCreatureSet&);
public:
TSlots slots; //slots[slot_id]->> pair(creature_id,creature_quantity)
ui8 formation; //false - wide, true - tight

View File

@ -708,7 +708,7 @@ CStack::CStack()
}
CStack::CStack(const CStackBasicDescriptor *stack, int O, int I, bool AO, int S)
: ID(I), owner(O), slot(S), attackerOwned(AO), position(-1), counterAttacks(1)
: base(NULL), ID(I), owner(O), slot(S), attackerOwned(AO), position(-1), counterAttacks(1)
{
type = stack->type;
count = baseAmount = stack->count;
@ -1021,10 +1021,23 @@ std::vector<si32> CStack::activeSpells() const
CStack::~CStack()
{
detachFromAll();
if(vstd::contains(state, SUMMONED))
delNull(base);
}
const CGHeroInstance * CStack::getMyHero() const
{
if(base)
return dynamic_cast<const CGHeroInstance *>(base->armyObj);
else //we are attached directly?
BOOST_FOREACH(const CBonusSystemNode *n, parents)
if(n->nodeType == HERO)
dynamic_cast<const CGHeroInstance *>(n);
return NULL;
}
CGHeroInstance * CGameState::HeroesPool::pickHeroFor(bool native, int player, const CTown *town, std::map<ui32,CGHeroInstance *> &available, const CHeroClass *bannedClass /*= NULL*/) const
{
CGHeroInstance *ret = NULL;
@ -3482,14 +3495,18 @@ int BattleInfo::calculateSpellDuration( const CSpell * spell, const CGHeroInstan
CStack * BattleInfo::generateNewStack(const CStackInstance &base, int stackID, bool attackerOwned, int slot, int position) const
{
CStack * ret = new CStack(&base, attackerOwned ? side1 : side2, stackID, attackerOwned, slot);
int owner = attackerOwned ? side1 : side2;
assert(owner >= PLAYER_LIMIT || base.armyObj && base.armyObj->tempOwner == owner);
CStack * ret = new CStack(&base, owner, stackID, attackerOwned, slot);
ret->position = position;
return ret;
}
CStack * BattleInfo::generateNewStack(const CStackBasicDescriptor &base, int stackID, bool attackerOwned, int slot, int position) const
{
CStack * ret = new CStack(&base, attackerOwned ? side1 : side2, stackID, attackerOwned, slot);
int owner = attackerOwned ? side1 : side2;
CStack * ret = new CStack(&base, owner, stackID, attackerOwned, slot);
ret->position = position;
return ret;
}
@ -4578,7 +4595,7 @@ void InfoAboutHero::initFromHero( const CGHeroInstance *h, bool detailed )
hclass = h->type->heroClass;
name = h->name;
portrait = h->portrait;
army = h->getArmy();
army = ArmyDescriptor(h, detailed);
if(detailed)
{
@ -4594,14 +4611,6 @@ void InfoAboutHero::initFromHero( const CGHeroInstance *h, bool detailed )
details->primskills[i] = h->getPrimSkillLevel(i);
}
}
else
{
//hide info about hero stacks counts using descriptives names ids
for(TSlots::const_iterator i = army.Slots().begin(); i != army.Slots().end(); ++i)
{
army.setStackCount(i->first, i->second->getQuantityID()+1);
}
}
}
void InfoAboutHero::assign( const InfoAboutHero & iah )
@ -4621,3 +4630,19 @@ InfoAboutHero & InfoAboutHero::operator=( const InfoAboutHero & iah )
}
ArmyDescriptor::ArmyDescriptor(const CArmedInstance *army, bool detailed)
{
for(TSlots::const_iterator i = army->Slots().begin(); i != army->Slots().end(); i++)
{
if(detailed)
(*this)[i->first] = *i->second;
else
(*this)[i->first] = CStackBasicDescriptor(i->second->type, i->second->getQuantityID());
}
}
ArmyDescriptor::ArmyDescriptor()
{
}

View File

@ -68,6 +68,13 @@ namespace boost
class shared_mutex;
}
//numbers of creatures are exact numbers if detailed else they are quantity ids (0 - a few, 1 - several and so on; additionaly -1 - unknown)
struct DLL_EXPORT ArmyDescriptor : public std::map<TSlot, CStackBasicDescriptor>
{
ArmyDescriptor(const CArmedInstance *army, bool detailed); //not detailed -> quantity ids as count
ArmyDescriptor();
};
struct DLL_EXPORT InfoAboutHero
{
private:
@ -83,7 +90,8 @@ public:
const CHeroClass *hclass;
std::string name;
int portrait;
CCreatureSet army; //numbers of creatures are exact numbers if detailed else they are quantity ids (0 - a few, 1 - several and so on)
ArmyDescriptor army;
InfoAboutHero();
InfoAboutHero(const InfoAboutHero & iah);
@ -285,6 +293,7 @@ public:
BonusList getSpellBonuses() const;
void stackEffectToFeature(BonusList & sf, const Bonus & sse);
std::vector<si32> activeSpells() const; //returns vector of active spell IDs sorted by time of cast
const CGHeroInstance *getMyHero() const; //if stack belongs to hero (directly or was by him summoned) returns hero, NULL otherwise
static inline Bonus *featureGenerator(Bonus::BonusType type, si16 subtype, si32 value, ui16 turnsRemain, si32 additionalInfo = 0, si32 limit = Bonus::NO_LIMIT)
{
@ -307,6 +316,12 @@ public:
template <typename Handler> void serialize(Handler &h, const int version)
{
assert(isIndependentNode());
h & static_cast<CBonusSystemNode&>(*this);
h & static_cast<CStackBasicDescriptor&>(*this);
h & ID & baseAmount & firstHPleft & owner & slot & attackerOwned & position & state & counterAttacks
& shots & count;
TSlot slot = (base ? base->armyObj->findStack(base) : -1);
const CArmedInstance *army = (base ? base->armyObj : NULL);
if(h.saving)
@ -316,13 +331,17 @@ public:
else
{
h & army & slot;
base = &army->getStack(slot);
if(!army || slot == -1 || !army->hasStackAtSlot(slot))
{
base = NULL;
tlog3 << type->nameSing << " don't have a base stack!\n";
}
else
{
base = &army->getStack(slot);
}
}
h & static_cast<CBonusSystemNode&>(*this);
h & static_cast<CStackBasicDescriptor&>(*this);
h & ID & baseAmount & firstHPleft & owner & slot & attackerOwned & position & state & counterAttacks
& shots & count;
}
bool alive() const //determines if stack is alive
{

View File

@ -116,6 +116,7 @@ int CBonusSystemNode::valOfBonuses(Bonus::BonusType type, const CSelector &selec
{
return valOfBonuses(Selector::type(type) && selector);
}
int CBonusSystemNode::valOfBonuses(Bonus::BonusType type, int subtype /*= -1*/) const
{
CSelector s = Selector::type(type);
@ -124,6 +125,7 @@ int CBonusSystemNode::valOfBonuses(Bonus::BonusType type, int subtype /*= -1*/)
return valOfBonuses(s);
}
int CBonusSystemNode::valOfBonuses(const CSelector &selector) const
{
BonusList hlp;
@ -300,8 +302,7 @@ CBonusSystemNode::CBonusSystemNode()
CBonusSystemNode::~CBonusSystemNode()
{
while(parents.size())
detachFrom(parents.front());
detachFromAll();
if(children.size())
{
@ -313,13 +314,13 @@ void CBonusSystemNode::attachTo(CBonusSystemNode *parent)
{
assert(!vstd::contains(parents, parent));
parents.push_back(parent);
BOOST_FOREACH(Bonus *b, exportedBonuses)
propagateBonus(b);
if(parent->weActAsBonusSourceOnly())
{
}
// BOOST_FOREACH(Bonus *b, exportedBonuses)
// propagateBonus(b);
//
// if(parent->weActAsBonusSourceOnly())
// {
//
// }
parent->newChildAttached(this);
}
@ -413,6 +414,17 @@ void CBonusSystemNode::childDetached(CBonusSystemNode *child)
children -= child;
}
void CBonusSystemNode::detachFromAll()
{
while(parents.size())
detachFrom(parents.front());
}
bool CBonusSystemNode::isIndependentNode() const
{
return parents.empty() && children.empty();
}
int NBonus::valOf(const CBonusSystemNode *obj, Bonus::BonusType type, int subtype /*= -1*/)
{
if(obj)
@ -466,7 +478,7 @@ std::string Bonus::Description() const
str << VLC->creh->creatures[id]->namePl;
break;
}
return str.str();
}

View File

@ -410,6 +410,7 @@ public:
void attachTo(CBonusSystemNode *parent);
void detachFrom(CBonusSystemNode *parent);
void detachFromAll();
void addNewBonus(Bonus *b); //b will be deleted with destruction of node
void newChildAttached(CBonusSystemNode *child);
@ -419,6 +420,7 @@ public:
void removeBonus(Bonus *b);
TNodesVector &nodesOnWhichWePropagate();
bool isIndependentNode() const; //node is independent when it has no parents nor children
bool weActAsBonusSourceOnly() const;
bool isLimitedOnUs(Bonus *b) const; //if bonus should be removed from list acquired from this node
CBonusSystemNode *whereToPropagate(Bonus *b);
@ -432,7 +434,7 @@ public:
enum ENodeTypes
{
UNKNOWN, STACK, SPECIALITY, ARTIFACT, CREATURE, ARTIFACT_INSTANCE
UNKNOWN, STACK, SPECIALITY, ARTIFACT, CREATURE, ARTIFACT_INSTANCE, HERO
};
};

View File

@ -88,7 +88,7 @@ public:
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 takeCreatures (int objid, TSlots creatures) =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;

View File

@ -529,19 +529,20 @@ struct TryMoveHero : public CPackForClient //501
}
};
struct SetGarrisons : public CPackForClient //502
{
SetGarrisons(){type = 502;};
void applyCl(CClient *cl);
DLL_EXPORT void applyGs(CGameState *gs);
// struct SetGarrisons : public CPackForClient //502
// {
// SetGarrisons(){type = 502;};
// void applyCl(CClient *cl);
// DLL_EXPORT void applyGs(CGameState *gs);
//
// std::map<ui32,CCreatureSet> garrs;
//
// template <typename Handler> void serialize(Handler &h, const int version)
// {
// h & garrs;
// }
// };
std::map<ui32,CCreatureSet> garrs;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & garrs;
}
};
struct NewStructures : public CPackForClient //504
{
NewStructures(){type = 504;};
@ -598,7 +599,7 @@ struct SetHeroesInTown : public CPackForClient //508
{
h & tid & visiting & garrison;
}
};
};
struct SetHeroArtifacts : public CPackForClient //509
{
SetHeroArtifacts(){type = 509;};
@ -798,7 +799,7 @@ struct SwapStacks : CGarrisonOperationPack //524
struct InsertNewStack : CGarrisonOperationPack //525
{
StackLocation sl;
CStackInstance *stack;
CStackBasicDescriptor stack;
void applyCl(CClient *cl);
DLL_EXPORT void applyGs(CGameState *gs);
@ -810,7 +811,7 @@ struct InsertNewStack : CGarrisonOperationPack //525
};
//moves creatures from src stack to dst slot, may be used for merging/splittint/moving stacks
struct RebalanceStacks : CGarrisonOperationPack //525
struct RebalanceStacks : CGarrisonOperationPack //526
{
StackLocation src, dst;
TQuantity count;

View File

@ -375,23 +375,23 @@ void TryMoveHero::applyGs( CGameState *gs )
gs->getPlayerTeam(h->getOwner())->fogOfWarMap[t.x][t.y][t.z] = 1;
}
DLL_EXPORT void SetGarrisons::applyGs( CGameState *gs )
{
for(std::map<ui32,CCreatureSet>::iterator i = garrs.begin(); i!=garrs.end(); i++)
{
CArmedInstance *ai = static_cast<CArmedInstance*>(gs->map->objects[i->first]);
ai->setToArmy(i->second);
if(ai->ID==TOWNI_TYPE && (static_cast<CGTownInstance*>(ai))->garrisonHero) //if there is a hero in garrison then we must update also his army
const_cast<CGHeroInstance*>((static_cast<CGTownInstance*>(ai))->garrisonHero)->setToArmy(i->second);
else if(ai->ID==HEROI_TYPE)
{
CGHeroInstance *h = static_cast<CGHeroInstance*>(ai);
CGTownInstance *t = const_cast<CGTownInstance *>(h->visitedTown);
if(t && h->inTownGarrison)
t->setToArmy(i->second);
}
}
}
// DLL_EXPORT void SetGarrisons::applyGs( CGameState *gs )
// {
// for(std::map<ui32,CCreatureSet>::iterator i = garrs.begin(); i!=garrs.end(); i++)
// {
// CArmedInstance *ai = static_cast<CArmedInstance*>(gs->map->objects[i->first]);
// ai->setToArmy(i->second);
// if(ai->ID==TOWNI_TYPE && (static_cast<CGTownInstance*>(ai))->garrisonHero) //if there is a hero in garrison then we must update also his army
// const_cast<CGHeroInstance*>((static_cast<CGTownInstance*>(ai))->garrisonHero)->setToArmy(i->second);
// else if(ai->ID==HEROI_TYPE)
// {
// CGHeroInstance *h = static_cast<CGHeroInstance*>(ai);
// CGTownInstance *t = const_cast<CGTownInstance *>(h->visitedTown);
// if(t && h->inTownGarrison)
// t->setToArmy(i->second);
// }
// }
// }
DLL_EXPORT void NewStructures::applyGs( CGameState *gs )
{
@ -634,11 +634,43 @@ DLL_EXPORT void SwapStacks::applyGs( CGameState *gs )
DLL_EXPORT void InsertNewStack::applyGs( CGameState *gs )
{
sl.army->putStack(sl.slot, stack);
CStackInstance *s = new CStackInstance(stack.type, stack.count);
sl.army->putStack(sl.slot, s);
}
DLL_EXPORT void RebalanceStacks::applyGs( CGameState *gs )
{
const CCreature *srcType = src.army->getCreature(src.slot);
TQuantity srcCount = src.army->getStackCount(src.slot);
if(srcCount == count) //moving whole stack
{
if(const CCreature *c = dst.army->getCreature(dst.slot)) //stack at dest -> merge
{
assert(c == srcType);
src.army->eraseStack(src.slot);
dst.army->changeStackCount(dst.slot, count);
}
else //move stack to an empty slot
{
CStackInstance *stackDetached = src.army->detachStack(src.slot);
dst.army->putStack(dst.slot, stackDetached);
}
}
else
{
if(const CCreature *c = dst.army->getCreature(dst.slot)) //stack at dest -> rebalance
{
assert(c == srcType);
src.army->changeStackCount(src.slot, -count);
dst.army->changeStackCount(dst.slot, count);
}
else //split stack to an empty slot
{
src.army->changeStackCount(src.slot, -count);
dst.army->addToSlot(dst.slot, srcType->idNumber, count, false);
}
}
}
DLL_EXPORT void SetAvailableArtifacts::applyGs( CGameState *gs )
@ -786,7 +818,20 @@ DLL_EXPORT void BattleStart::applyGs( CGameState *gs )
info->belligerents[0]->battle = info->belligerents[1]->battle = info;
BOOST_FOREACH(CStack *s, info->stacks)
s->attachTo(const_cast<CStackInstance*>(s->base));
{
if(s->base) //stack originating from "real" stack in garrison -> attach to it
{
s->attachTo(const_cast<CStackInstance*>(s->base));
}
else //attach directly to obj to which stack belongs and creature type
{
CArmedInstance *army = info->belligerents[!s->attackerOwned];
s->attachTo(army);
assert(s->type);
s->attachTo(const_cast<CCreature*>(s->type));
}
s->postInit();
}
}
DLL_EXPORT void BattleNextRound::applyGs( CGameState *gs )

View File

@ -105,7 +105,7 @@ void registerTypes2(Serializer &s)
s.template registerType<UpdateCampaignState>();
s.template registerType<RemoveObject>();
s.template registerType<TryMoveHero>();
s.template registerType<SetGarrisons>();
//s.template registerType<SetGarrisons>();
s.template registerType<NewStructures>();
s.template registerType<RazeStructures>();
s.template registerType<SetAvailableCreatures>();

View File

@ -310,27 +310,26 @@ void CGameHandler::changeSecSkill( int ID, int which, int val, bool abs/*=false*
}
}
static CCreatureSet takeCasualties(int color, const CCreatureSet &set, BattleInfo *bat)
void CGameHandler::takeCasualties(const CArmedInstance *army, BattleInfo *bat)
{
int color = army->tempOwner;
if(color == 254)
color = 255;
color = NEUTRAL_PLAYER;
CCreatureSet ret(set);
for(int i=0; i<bat->stacks.size();i++)
BOOST_FOREACH(CStack *st, bat->stacks)
{
CStack *st = bat->stacks[i];
if(vstd::contains(st->state, SUMMONED)) //don't take into account sumoned stacks
continue;
if(st->owner==color && !set.slotEmpty(st->slot) && st->count < set.getStackCount(st->slot))
if(st->owner==color && !army->slotEmpty(st->slot) && st->count < army->getStackCount(st->slot))
{
StackLocation sl(army, st->slot);
if(st->alive())
ret.setStackCount(st->slot, st->count);
changeStackCount(sl, st->count, true);
else
ret.eraseStack(st->slot);
eraseStack(sl);
}
}
return ret;
}
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)
@ -582,18 +581,6 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
if(bEndArmy2 && bEndArmy2->tempOwner<PLAYER_LIMIT)
states.setFlag(bEndArmy2->tempOwner, &PlayerStatus::engagedIntoBattle, false);
//casualties among heroes armies
SetGarrisons sg;
sg.garrs[bEndArmy1->id] = takeCasualties(bEndArmy1->tempOwner, *bEndArmy1, gs->curB);
sg.garrs[bEndArmy2->id] = takeCasualties(bEndArmy2->tempOwner, *bEndArmy2, gs->curB);
sendAndApply(&sg);
ui8 sides[2];
sides[0] = gs->curB->side1;
sides[1] = gs->curB->side2;
ui8 loser = sides[!battleResult.data->winner];
//end battle, remove all info, free memory
giveExp(*battleResult.data);
if (hero1)
@ -602,6 +589,16 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
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];
//if one hero has lost we will erase him
if(battleResult.data->winner!=0 && hero1)
{
@ -645,7 +642,6 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
if (slot != -1)
{
winnerHero->showNecromancyDialog(raisedStack);
sendAndApply(&sg);
addToSlot(StackLocation(winnerHero, slot), raisedStack.type, raisedStack.count);
}
}
@ -2096,64 +2092,71 @@ void CGameHandler::giveResource(int player, int which, int val)
}
void CGameHandler::giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet creatures, bool remove)
{
if (creatures.stacksCount() <= 0)
return;
CCreatureSet heroArmy = h->getArmy();
std::set<int> takenSlots;
for (TSlots::const_iterator it = creatures.Slots().begin(); it != creatures.Slots().end(); it++)
{
int slot = heroArmy.getSlotFor(it->second->type->idNumber);
if (slot >= 0)
{
heroArmy.addToSlot(slot, it->second); //move all matching creatures to hero's army
takenSlots.insert(it->first); //slot id
}
}
for (std::set<int>::iterator it = takenSlots.begin(); it != takenSlots.end(); it++)
creatures.eraseStack(*it); //delete them from used army
SetGarrisons sg;
sg.garrs[h->id] = heroArmy;
sg.garrs[objid] = creatures;
sendAndApply (&sg);
if (remove) //show garrison window and let player pick remaining creatures
{
if (creatures.stacksCount()) //Pandora needs to exist until we close garrison window
{
showGarrisonDialog (objid, h->id, true, boost::bind(&CGameHandler::removeObject, this, objid));
}
else
removeObject(objid);
}
else if (creatures.stacksCount())
showGarrisonDialog (objid, h->id, true, 0);
}
void CGameHandler::takeCreatures (int objid, TSlots creatures) //probably we could use ArmedInstance as well
{
if (creatures.size() <= 0)
return;
const CArmedInstance* obj = static_cast<const CArmedInstance*>(getObj(objid));
CCreatureSet newArmy = obj->getArmy();
while (creatures.size())
{
int slot = newArmy.getSlotFor(creatures.begin()->second->type->idNumber);
if (slot < 0)
break;
newArmy.slots[slot]->count -= creatures.begin()->second->count;
if (newArmy.getStack(slot).count < 1)
newArmy.eraseStack(slot);
creatures.erase(creatures.begin());
}
SetGarrisons sg;
sg.garrs[objid] = newArmy;
sendAndApply(&sg);
assert(0);
// if (creatures.stacksCount() <= 0)
// return;
// CCreatureSet heroArmy = h->getArmy();
// std::set<int> takenSlots;
// for (TSlots::const_iterator it = creatures.Slots().begin(); it != creatures.Slots().end(); it++)
// {
// int slot = heroArmy.getSlotFor(it->second->type->idNumber);
// if (slot >= 0)
// {
// heroArmy.addToSlot(slot, it->second); //move all matching creatures to hero's army
// takenSlots.insert(it->first); //slot id
// }
// }
// for (std::set<int>::iterator it = takenSlots.begin(); it != takenSlots.end(); it++)
// creatures.eraseStack(*it); //delete them from used army
//
// SetGarrisons sg;
// sg.garrs[h->id] = heroArmy;
// sg.garrs[objid] = creatures;
// sendAndApply (&sg);
//
// if (remove) //show garrison window and let player pick remaining creatures
// {
// if (creatures.stacksCount()) //Pandora needs to exist until we close garrison window
// {
// showGarrisonDialog (objid, h->id, true, boost::bind(&CGameHandler::removeObject, this, objid));
// }
// else
// removeObject(objid);
// }
// else if (creatures.stacksCount())
// showGarrisonDialog (objid, h->id, true, 0);
}
void CGameHandler::takeCreatures(int objid, std::vector<CStackBasicDescriptor> creatures)
{
if (creatures.size() <= 0)
return;
const CArmedInstance* obj = static_cast<const CArmedInstance*>(getObj(objid));
BOOST_FOREACH(CStackBasicDescriptor &sbd, creatures)
{
TQuantity collected = 0;
while(collected < sbd.count)
{
TSlots::const_iterator i = obj->Slots().begin();
for(; i != obj->Slots().end(); i++)
{
if(i->second->type == sbd.type)
{
TQuantity take = std::min(sbd.count - collected, i->second->count); //collect as much creatures as we can
changeStackCount(StackLocation(obj, i->first), take, false);
collected += take;
break;
}
}
if(i == obj->Slots().end()) //we went through the whole loop and haven't found appropriate creatures
{
complain("Unexpected failure during taking creatures!");
return;
}
}
}
}
void CGameHandler::showCompInfo(ShowInInfobox * comp)
@ -2549,18 +2552,25 @@ void CGameHandler::sendToAllClients( CPackForClient * info )
void CGameHandler::sendAndApply( CPackForClient * info )
{
gs->apply(info);
sendToAllClients(info);
gs->apply(info);
}
void CGameHandler::sendAndApply( SetGarrisons * info )
void CGameHandler::sendAndApply(CGarrisonOperationPack * info)
{
sendAndApply((CPackForClient*)info);
if(gs->map->victoryCondition.condition == gatherTroop)
for(std::map<ui32,CCreatureSet>::const_iterator i = info->garrs.begin(); i != info->garrs.end(); i++)
checkLossVictory(getObj(i->first)->tempOwner);
winLoseHandle();
}
// void CGameHandler::sendAndApply( SetGarrisons * info )
// {
// sendAndApply((CPackForClient*)info);
// if(gs->map->victoryCondition.condition == gatherTroop)
// for(std::map<ui32,CCreatureSet>::const_iterator i = info->garrs.begin(); i != info->garrs.end(); i++)
// checkLossVictory(getObj(i->first)->tempOwner);
// }
void CGameHandler::sendAndApply( SetResource * info )
{
sendAndApply((CPackForClient*)info);
@ -2581,6 +2591,7 @@ void CGameHandler::sendAndApply( NewStructures * info )
if(gs->map->victoryCondition.condition == buildCity)
checkLossVictory(getTown(info->tid)->tempOwner);
}
void CGameHandler::save( const std::string &fname )
{
{
@ -5221,7 +5232,7 @@ bool CGameHandler::insertNewStack(const StackLocation &sl, const CCreature *c, T
InsertNewStack ins;
ins.sl = sl;
ins.stack = new CStackInstance(c, count);
ins.stack = CStackBasicDescriptor(c, count);
sendAndApply(&ins);
return true;
}

View File

@ -92,6 +92,7 @@ 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
@ -136,7 +137,6 @@ public:
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 takeCreatures (int objid, TSlots creatures);
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);
@ -152,7 +152,6 @@ public:
void stopHeroVisitCastle(int obj, int heroID);
void giveHeroArtifact(int artid, int hid, int position); //pos==-1 - first free slot in backpack; pos==-2 - default if available or backpack
void giveNewArtifact(int hid, int position);
void moveArtifact(int hid, int oldPosition, int destPos);
bool removeArtifact(CArtifact* art, int hid);
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, boost::function<void(BattleResult*)> cb = 0, const CGTownInstance *town = NULL); //use hero=NULL for no hero
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false); //if any of armies is hero, hero will be used
@ -223,7 +222,8 @@ public:
void ask(Query * sel, ui8 player, const CFunctionList<void(ui32)> &callback);
void sendToAllClients(CPackForClient * info);
void sendAndApply(CPackForClient * info);
void sendAndApply(SetGarrisons * info);
void sendAndApply(CGarrisonOperationPack * info);
//void sendAndApply(SetGarrisons * info);
void sendAndApply(SetResource * info);
void sendAndApply(SetResources * info);
void sendAndApply(NewStructures * info);