1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-07-17 01:32:21 +02:00

Stacks #2 -> towards new system of stack operations.

This commit is contained in:
Michał W. Urbańczyk
2010-11-27 01:46:19 +00:00
parent 32ce20af15
commit 7c3f3d20c3
17 changed files with 406 additions and 126 deletions

View File

@ -317,7 +317,7 @@ float CGeniusAI::TownObjective::getValue() const
case upgradeCreatures: case upgradeCreatures:
UpgradeInfo ui = AI->m_cb->getUpgradeInfo(whichTown->t,which); UpgradeInfo ui = AI->m_cb->getUpgradeInfo(whichTown->t,which);
ID = whichTown->creaturesInGarrison.getCreature(which)->idNumber; ID = whichTown->creaturesInGarrison.getCreature(which)->idNumber;
howMany = whichTown->creaturesInGarrison.getAmount(which); howMany = whichTown->creaturesInGarrison.getStackCount(which);
newID = ui.newID.back(); newID = ui.newID.back();
int upgrade_serial = ui.newID.size() - 1; int upgrade_serial = ui.newID.size() - 1;

View File

@ -113,7 +113,10 @@ public:
void giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet creatures, bool remove) {}; void giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet creatures, bool remove) {};
void takeCreatures (int objid, TSlots creatures){}; void takeCreatures (int objid, TSlots creatures){};
void takeCreatures (int objid, std::vector<CStackBasicDescriptor> creatures){}; void takeCreatures (int objid, std::vector<CStackBasicDescriptor> creatures){};
void changeCreatureType (int objid, TSlot slot, TCreature creature){}; void changeStackType(const StackLocation &sl, CCreature *c){};
void changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false){};
void insertNewStack(const StackLocation &sl, CCreature *c, TQuantity count){};
void eraseStack(const StackLocation &sl){};
void showCompInfo(ShowInInfobox * comp){}; void showCompInfo(ShowInInfobox * comp){};
void heroVisitCastle(int obj, int heroID){}; void heroVisitCastle(int obj, int heroID){};
void stopHeroVisitCastle(int obj, int heroID){}; void stopHeroVisitCastle(int obj, int heroID){};

View File

@ -2919,7 +2919,7 @@ void CTradeWindow::initSubs(bool Left)
switch(itemsType[1]) switch(itemsType[1])
{ {
case CREATURE: case CREATURE:
t->subtitle = boost::lexical_cast<std::string>(hero->getAmount(t->serial)); t->subtitle = boost::lexical_cast<std::string>(hero->getStackCount(t->serial));
break; break;
case RESOURCE: case RESOURCE:
t->subtitle = boost::lexical_cast<std::string>(LOCPLINT->cb->getResourceAmount(t->serial)); t->subtitle = boost::lexical_cast<std::string>(LOCPLINT->cb->getResourceAmount(t->serial));
@ -2992,7 +2992,7 @@ void CTradeWindow::removeItem(CTradeableItem * t)
void CTradeWindow::getEmptySlots(std::set<CTradeableItem *> &toRemove) void CTradeWindow::getEmptySlots(std::set<CTradeableItem *> &toRemove)
{ {
BOOST_FOREACH(CTradeableItem *t, items[1]) BOOST_FOREACH(CTradeableItem *t, items[1])
if(!hero->getAmount(t->serial)) if(!hero->getStackCount(t->serial))
toRemove.insert(t); toRemove.insert(t);
} }
@ -3225,7 +3225,7 @@ void CMarketplaceWindow::selectionChanged(bool side)
if(itemsType[1] == RESOURCE) if(itemsType[1] == RESOURCE)
newAmount = LOCPLINT->cb->getResourceAmount(hLeft->id); newAmount = LOCPLINT->cb->getResourceAmount(hLeft->id);
else if(itemsType[1] == CREATURE) else if(itemsType[1] == CREATURE)
newAmount = hero->getAmount(hLeft->serial) - (hero->Slots().size() == 1 && hero->needsLastStack()); newAmount = hero->getStackCount(hLeft->serial) - (hero->Slots().size() == 1 && hero->needsLastStack());
else else
assert(0); assert(0);
@ -3598,7 +3598,7 @@ void CAltarWindow::SacrificeAll()
{ {
bool movedAnything = false; bool movedAnything = false;
BOOST_FOREACH(CTradeableItem *t, items[1]) BOOST_FOREACH(CTradeableItem *t, items[1])
sacrificedUnits[t->serial] = hero->getAmount(t->serial); sacrificedUnits[t->serial] = hero->getStackCount(t->serial);
sacrificedUnits[items[1].front()->serial]--; sacrificedUnits[items[1].front()->serial]--;
@ -3637,10 +3637,10 @@ void CAltarWindow::selectionChanged(bool side)
int stackCount = 0; int stackCount = 0;
for (int i = 0; i < ARMY_SIZE; i++) for (int i = 0; i < ARMY_SIZE; i++)
if(hero->getAmount(i) > sacrificedUnits[i]) if(hero->getStackCount(i) > sacrificedUnits[i])
stackCount++; stackCount++;
slider->setAmount(hero->getAmount(hLeft->serial) - (stackCount == 1)); slider->setAmount(hero->getStackCount(hLeft->serial) - (stackCount == 1));
slider->block(!slider->amount); slider->block(!slider->amount);
slider->value = sacrificedUnits[hLeft->serial]; slider->value = sacrificedUnits[hLeft->serial];
max->block(!slider->amount); max->block(!slider->amount);
@ -5783,7 +5783,7 @@ CTransformerWindow::CTransformerWindow(const CGHeroInstance * _hero, const CGTow
for (int i=0; i<7; i++ ) for (int i=0; i<7; i++ )
if ( army->getCreature(i) ) if ( army->getCreature(i) )
items.push_back(new CItem(this, army->getAmount(i), i)); items.push_back(new CItem(this, army->getStackCount(i), i));
all = new AdventureMapButton(CGI->generaltexth->zelp[590],boost::bind(&CTransformerWindow::addAll,this), 146,416,"ALTARMY.DEF",SDLK_a); all = new AdventureMapButton(CGI->generaltexth->zelp[590],boost::bind(&CTransformerWindow::addAll,this), 146,416,"ALTARMY.DEF",SDLK_a);
convert= new AdventureMapButton(CGI->generaltexth->zelp[591],boost::bind(&CTransformerWindow::makeDeal,this), 269,416,"ALTSACR.DEF",SDLK_RETURN); convert= new AdventureMapButton(CGI->generaltexth->zelp[591],boost::bind(&CTransformerWindow::makeDeal,this), 269,416,"ALTSACR.DEF",SDLK_RETURN);
@ -6024,7 +6024,7 @@ void CHillFortWindow::updateGarrisons()
if (info.newID.size())//we have upgrades here - update costs if (info.newID.size())//we have upgrades here - update costs
for(std::set<std::pair<int,int> >::iterator it=info.cost[0].begin(); it!=info.cost[0].end(); it++) for(std::set<std::pair<int,int> >::iterator it=info.cost[0].begin(); it!=info.cost[0].end(); it++)
{ {
std::pair<int, int> pair = std::make_pair(it->first, it->second * hero->getAmount(i) ); std::pair<int, int> pair = std::make_pair(it->first, it->second * hero->getStackCount(i) );
costs[i].insert(pair); costs[i].insert(pair);
totalSumm[pair.first] += pair.second; totalSumm[pair.first] += pair.second;
} }
@ -6137,7 +6137,7 @@ std::string CHillFortWindow::getTextForSlot(int slot)
return ""; return "";
std::string str = CGI->generaltexth->allTexts[318]; std::string str = CGI->generaltexth->allTexts[318];
int amount = hero->getAmount(slot); int amount = hero->getStackCount(slot);
if ( amount == 1 ) if ( amount == 1 )
boost::algorithm::replace_first(str,"%s",hero->getCreature(slot)->nameSing); boost::algorithm::replace_first(str,"%s",hero->getCreature(slot)->nameSing);
else else
@ -6172,7 +6172,7 @@ int CHillFortWindow::getState(int slot)
return 1; return 1;
for(std::set<std::pair<int,int> >::iterator it=info.cost[0].begin(); it!=info.cost[0].end(); it++) for(std::set<std::pair<int,int> >::iterator it=info.cost[0].begin(); it!=info.cost[0].end(); it++)
if(LOCPLINT->cb->getResourceAmount(it->first) < it->second * hero->getAmount(slot)) if(LOCPLINT->cb->getResourceAmount(it->first) < it->second * hero->getStackCount(slot))
return 0; return 0;
return 2;//can upgrade return 2;//can upgrade
} }

View File

@ -893,7 +893,7 @@ void CGHeroInstance::initArmy(CCreatureSet *dst /*= NULL*/)
} }
} }
else else
dst->addStack(stackNo-warMachinesGiven, new CStackInstance(creID, count)); dst->putStack(stackNo-warMachinesGiven, new CStackInstance(creID, count));
} }
} }
void CGHeroInstance::initHeroDefInfo() void CGHeroInstance::initHeroDefInfo()
@ -1587,7 +1587,7 @@ void CGDwelling::initObj()
creatures[0].second.push_back(crid); creatures[0].second.push_back(crid);
hoverName = VLC->generaltexth->creGens[subID]; hoverName = VLC->generaltexth->creGens[subID];
if(crs->level > 4) if(crs->level > 4)
addStack(0, new CStackInstance(crs, (crs->growth) * 3)); putStack(0, new CStackInstance(crs, (crs->growth) * 3));
if (getOwner() != 255) if (getOwner() != 255)
cb->gameState()->players[getOwner()].dwellings.push_back (this); cb->gameState()->players[getOwner()].dwellings.push_back (this);
} }
@ -1602,8 +1602,8 @@ void CGDwelling::initObj()
creatures[2].second.push_back(116); //Gold Golem creatures[2].second.push_back(116); //Gold Golem
creatures[3].second.push_back(117); //Diamond Golem creatures[3].second.push_back(117); //Diamond Golem
//guards //guards
addStack(0, new CStackInstance(116, 9)); putStack(0, new CStackInstance(116, 9));
addStack(1, new CStackInstance(117, 6)); putStack(1, new CStackInstance(117, 6));
} }
else if(subID == 0) // Elemental Conflux else if(subID == 0) // Elemental Conflux
{ {
@ -1612,7 +1612,7 @@ void CGDwelling::initObj()
creatures[2].second.push_back(113); //Earth Elemental creatures[2].second.push_back(113); //Earth Elemental
creatures[3].second.push_back(115); //Water Elemental creatures[3].second.push_back(115); //Water Elemental
//guards //guards
addStack(0, new CStackInstance(113, 12)); putStack(0, new CStackInstance(113, 12));
} }
else else
{ {
@ -2170,38 +2170,34 @@ void CGTownInstance::newTurn() const
if (nativeCrits.size()) if (nativeCrits.size())
{ {
TSlot pos = nativeCrits[rand() % nativeCrits.size()]; TSlot pos = nativeCrits[rand() % nativeCrits.size()];
StackLocation sl(this, pos);
const CCreature *c = getCreature(pos); const CCreature *c = getCreature(pos);
if (rand()%100 < 90 || c->upgrades.empty()) //increase number if no upgrade avaliable if (rand()%100 < 90 || c->upgrades.empty()) //increase number if no upgrade avaliable
{ {
SetGarrisons sg; cb->changeStackCount(sl, c->growth);
sg.garrs[id] = getArmy();
sg.garrs[id].slots[pos]->count += c->growth;
cb->sendAndApply(&sg);
} }
else //upgrade else //upgrade
{ {
SetGarrisons sg; //somewhat better upgrade pack would come in handy cb->changeStackType(sl, VLC->creh->creatures[*c->upgrades.begin()]);
sg.garrs[id] = getArmy();
//////////////////////////////////////////////////////////////////////////
//sg.garrs[id].t (pos, *c->upgrades.begin(), );
//sg.garrs[id].setCreature(pos, *c->upgrades.begin(), slt[pos].count);
cb->sendAndApply(&sg);
} }
} }
if ((stacksCount() < ARMY_SIZE && rand()%100 < 25) || Slots().empty()) //add new stack if ((stacksCount() < ARMY_SIZE && rand()%100 < 25) || Slots().empty()) //add new stack
{ {
int n, i = rand() % std::min (ARMY_SIZE, cb->getDate(3)<<1); int i = rand() % std::min (ARMY_SIZE, cb->getDate(3)<<1);
TCreature c = town->basicCreatures[i];
TSlot n = -1;
TQuantity count = creatureGrowth(i);
{//no lower tiers or above current month {//no lower tiers or above current month
if ((n = getSlotFor(town->basicCreatures[i], ARMY_SIZE))>=0) if ((n = getSlotFor(c))>=0)
{ {
SetGarrisons sg; StackLocation sl(this, n);
sg.garrs[id] = getArmy();
if (slotEmpty(n)) if (slotEmpty(n))
sg.garrs[id].setCreature (n, town->basicCreatures[i], creatureGrowth(i)); //if the stack is not yet present cb->insertNewStack(sl, VLC->creh->creatures[c], count);
else else //add to existing
sg.garrs[id].addToSlot(n, town->basicCreatures[i], creatureGrowth(i)); //add to existing cb->changeStackCount(sl, count);
cb->sendAndApply(&sg);
} }
} }
} }
@ -2896,7 +2892,7 @@ void CGCreature::onHeroVisit( const CGHeroInstance * h ) const
BlockingDialog ynd(true,false); BlockingDialog ynd(true,false);
ynd.player = h->tempOwner; ynd.player = h->tempOwner;
std::string tmp = VLC->generaltexth->advobtxt[90]; std::string tmp = VLC->generaltexth->advobtxt[90];
boost::algorithm::replace_first(tmp,"%d",boost::lexical_cast<std::string>(getAmount(0))); boost::algorithm::replace_first(tmp,"%d",boost::lexical_cast<std::string>(getStackCount(0)));
boost::algorithm::replace_first(tmp,"%d",boost::lexical_cast<std::string>(action)); boost::algorithm::replace_first(tmp,"%d",boost::lexical_cast<std::string>(action));
boost::algorithm::replace_first(tmp,"%s",VLC->creh->creatures[subID]->namePl); boost::algorithm::replace_first(tmp,"%s",VLC->creh->creatures[subID]->namePl);
ynd.text << tmp; ynd.text << tmp;
@ -3040,7 +3036,7 @@ int CGCreature::takenAction(const CGHeroInstance *h, bool allowJoin) const
if(h->getSecSkillLevel(4) + sympathy + 1 >= character) if(h->getSecSkillLevel(4) + sympathy + 1 >= character)
return 0; //join for free return 0; //join for free
else if(h->getSecSkillLevel(4) * 2 + sympathy + 1 >= character) else if(h->getSecSkillLevel(4) * 2 + sympathy + 1 >= character)
return VLC->creh->creatures[subID]->cost[6] * getAmount(0); //join for gold return VLC->creh->creatures[subID]->cost[6] * getStackCount(0); //join for gold
} }
} }
@ -3112,7 +3108,7 @@ void CGCreature::joinDecision(const CGHeroInstance *h, int cost, ui32 accept) co
//add creatures //add creatures
SetGarrisons sg; SetGarrisons sg;
sg.garrs[h->id] = h->getArmy(); sg.garrs[h->id] = h->getArmy();
sg.garrs[h->id].addToSlot(slot, subID, getAmount(0)); sg.garrs[h->id].addToSlot(slot, subID, getStackCount(0));
cb->sendAndApply(&sg); cb->sendAndApply(&sg);
cb->removeObject(id); cb->removeObject(id);
} }
@ -3180,7 +3176,7 @@ void CGMine::initObj()
//set guardians //set guardians
int howManyTroglodytes = 100 + ran()%100; int howManyTroglodytes = 100 + ran()%100;
CStackInstance *troglodytes = new CStackInstance(70, howManyTroglodytes); CStackInstance *troglodytes = new CStackInstance(70, howManyTroglodytes);
addStack(0, troglodytes); putStack(0, troglodytes);
//after map reading tempOwner placeholds bitmask for allowed resources //after map reading tempOwner placeholds bitmask for allowed resources
std::vector<int> possibleResources; std::vector<int> possibleResources;
@ -4673,7 +4669,7 @@ void CGBonusingObject::onHeroVisit( const CGHeroInstance * h ) const
iw.components.push_back(Component(Component::CREATURE,11,0,1)); iw.components.push_back(Component(Component::CREATURE,11,0,1));
for (TSlots::const_iterator i = creatures.slots.begin(); i != creatures.slots.end(); ++i) for (TSlots::const_iterator i = creatures.slots.begin(); i != creatures.slots.end(); ++i)
{ {
cb->changeCreatureType(h->id, i->first, 11); cb->changeStackType(StackLocation(h, i->first), VLC->creh->creatures[11]);
} }
} }
else else
@ -6525,20 +6521,6 @@ void CGLighthouse::giveBonusTo( ui8 player ) const
gb.bonus.source = Bonus::OBJECT; gb.bonus.source = Bonus::OBJECT;
gb.bonus.id = id; gb.bonus.id = id;
cb->sendAndApply(&gb); cb->sendAndApply(&gb);
}
void CArmedInstance::setArmy(const CCreatureSet &src)
{
assert(0);
// slots.clear();
//
// for(TSlots::const_iterator i = src.Slots().begin(); i != src.Slots().end(); i++)
// {
// CStackInstance &inserted = slots[i->first];
// inserted = i->second;
// inserted.setArmyObj(this);
// }
} }
CCreatureSet& CArmedInstance::getArmy() const CCreatureSet& CArmedInstance::getArmy() const

View File

@ -222,7 +222,6 @@ class DLL_EXPORT CArmedInstance: public CGObjectInstance, public CBonusSystemNod
public: public:
BattleInfo *battle; //set to the current battle, if engaged BattleInfo *battle; //set to the current battle, if engaged
void setArmy(const CCreatureSet &src);
CCreatureSet& getArmy() const; CCreatureSet& getArmy() const;
void randomizeArmy(int type); void randomizeArmy(int type);

View File

@ -17,7 +17,7 @@ const CStackInstance &CCreatureSet::operator[](TSlot slot) const
throw std::string("That slot is empty!"); throw std::string("That slot is empty!");
} }
const CCreature* CCreatureSet::getCreature(TSlot slot) const /*workaround of map issue */ const CCreature* CCreatureSet::getCreature(TSlot slot) const
{ {
TSlots::const_iterator i = slots.find(slot); TSlots::const_iterator i = slots.find(slot);
if (i != slots.end()) if (i != slots.end())
@ -37,16 +37,14 @@ bool CCreatureSet::setCreature(TSlot slot, TCreature type, TQuantity quantity) /
{ {
tlog2 << "Using set creature to delete stack?\n"; tlog2 << "Using set creature to delete stack?\n";
eraseStack(slot); eraseStack(slot);
return true;
} }
if(vstd::contains(slots, slot)) //remove old creature if(vstd::contains(slots, slot)) //remove old creature
{
eraseStack(slot); eraseStack(slot);
}
CStackInstance *stack = new CStackInstance(type, quantity); putStack(slot, new CStackInstance(type, quantity));
stack->armyObj = castToArmyObj(); //brutal force return true;
slots[slot] = stack;
} }
TSlot CCreatureSet::getSlotFor(TCreature creature, ui32 slotsAmount/*=7*/) const /*returns -1 if no slot available */ TSlot CCreatureSet::getSlotFor(TCreature creature, ui32 slotsAmount/*=7*/) const /*returns -1 if no slot available */
@ -68,7 +66,7 @@ TSlot CCreatureSet::getSlotFor(TCreature creature, ui32 slotsAmount/*=7*/) const
return -1; //no slot available return -1; //no slot available
} }
int CCreatureSet::getAmount(TSlot slot) const int CCreatureSet::getStackCount(TSlot slot) const
{ {
TSlots::const_iterator i = slots.find(slot); TSlots::const_iterator i = slots.find(slot);
if (i != slots.end()) if (i != slots.end())
@ -130,24 +128,31 @@ void CCreatureSet::addToSlot(TSlot slot, TCreature cre, TQuantity count, bool al
{ {
setCreature(slot, cre, count); setCreature(slot, cre, count);
} }
else if(slots[slot]->type == c && allowMerging); //that slot was empty or contained same type creature else if(getCreature(slot) == c && allowMerging) //that slot was empty or contained same type creature
{ {
setStackCount(slot, slots[slot]->count + count); setStackCount(slot, getStackCount(slot) + count);
}
else
{
tlog1 << "Failed adding to slot!\n";
} }
} }
void CCreatureSet::addToSlot(TSlot slot, CStackInstance *stack, bool allowMerging/* = true*/) void CCreatureSet::addToSlot(TSlot slot, CStackInstance *stack, bool allowMerging/* = true*/)
{ {
assert(stack->type == VLC->creh->creatures[stack->type->idNumber]); assert(stack->valid(true));
if(!vstd::contains(slots, slot)) if(!vstd::contains(slots, slot))
{ {
slots[slot] = stack; putStack(slot, stack);
stack->setArmyObj(castToArmyObj()); }
else if(allowMerging && stack->type == getCreature(slot))
{
joinStack(slot, stack);
} }
else else
{ {
addToSlot(slot, stack->type->idNumber, stack->count, allowMerging); tlog1 << "Cannot add to slot " << slot << " stack " << *stack << std::endl;
} }
} }
@ -155,14 +160,8 @@ bool CCreatureSet::validTypes(bool allowUnrandomized /*= false*/) const
{ {
for(TSlots::const_iterator i=slots.begin(); i!=slots.end(); ++i) for(TSlots::const_iterator i=slots.begin(); i!=slots.end(); ++i)
{ {
bool isRand = (i->second->idRand != -1); if(!i->second->valid(allowUnrandomized))
if(!isRand) return false;
{
assert(i->second->type);
assert(i->second->type == VLC->creh->creatures[i->second->type->idNumber]);
}
else
assert(allowUnrandomized);
} }
return true; return true;
} }
@ -187,11 +186,11 @@ int CCreatureSet::getArmyStrength() const
ui64 CCreatureSet::getPower (TSlot slot) const ui64 CCreatureSet::getPower (TSlot slot) const
{ {
return getCreature(slot)->AIValue * getAmount(slot); return getCreature(slot)->AIValue * getStackCount(slot);
} }
std::string CCreatureSet::getRoughAmount (TSlot slot) const std::string CCreatureSet::getRoughAmount (TSlot slot) const
{ {
return VLC->generaltexth->arraytxt[174 + 3*CCreature::getQuantityID(getAmount(slot))]; return VLC->generaltexth->arraytxt[174 + 3*CCreature::getQuantityID(getStackCount(slot))];
} }
int CCreatureSet::stacksCount() const int CCreatureSet::stacksCount() const
@ -199,11 +198,6 @@ int CCreatureSet::stacksCount() const
return slots.size(); return slots.size();
} }
void CCreatureSet::addStack(TSlot slot, CStackInstance *stack)
{
addToSlot(slot, stack, false);
}
void CCreatureSet::setFormation(bool tight) void CCreatureSet::setFormation(bool tight)
{ {
formation = tight; formation = tight;
@ -218,7 +212,10 @@ void CCreatureSet::setStackCount(TSlot slot, TQuantity count)
void CCreatureSet::clear() void CCreatureSet::clear()
{ {
slots.clear(); while(!slots.empty())
{
eraseStack(slots.begin()->first);
}
} }
const CStackInstance& CCreatureSet::getStack(TSlot slot) const const CStackInstance& CCreatureSet::getStack(TSlot slot) const
@ -230,6 +227,7 @@ const CStackInstance& CCreatureSet::getStack(TSlot slot) const
void CCreatureSet::eraseStack(TSlot slot) void CCreatureSet::eraseStack(TSlot slot)
{ {
assert(vstd::contains(slots, slot)); assert(vstd::contains(slots, slot));
delNull(slots[slot]);
slots.erase(slot); slots.erase(slot);
} }
@ -262,20 +260,89 @@ CArmedInstance * CCreatureSet::castToArmyObj()
return dynamic_cast<CArmedInstance *>(this); return dynamic_cast<CArmedInstance *>(this);
} }
void CCreatureSet::putStack(TSlot slot, CStackInstance *stack)
{
assert(!vstd::contains(slots, slot));
slots[slot] = stack;
stack->setArmyObj(castToArmyObj());
}
void CCreatureSet::joinStack(TSlot slot, CStackInstance * stack)
{
const CCreature *c = getCreature(slot);
assert(c == stack->type);
assert(c);
//TODO move stuff
changeStackCount(slot, stack->count);
delNull(stack);
}
void CCreatureSet::changeStackCount(TSlot slot, TQuantity toAdd)
{
setStackCount(slot, getStackCount(slot) + toAdd);
}
CCreatureSet::CCreatureSet()
{
formation = false;
}
CCreatureSet::~CCreatureSet()
{
clear();
}
void CCreatureSet::setToArmy(CCreatureSet &src)
{
clear();
while(src)
{
TSlots::iterator i = src.slots.begin();
assert(i->second->type);
assert(i->second->valid(false));
assert(i->second->armyObj == NULL);
putStack(i->first, i->second);
src.slots.erase(i);
}
}
CStackInstance * CCreatureSet::detachStack(TSlot slot)
{
assert(vstd::contains(slots, slot));
CStackInstance *ret = slots[slot];
if(CArmedInstance *armedObj = castToArmyObj())
ret->detachFrom(armedObj);
return ret;
}
void CCreatureSet::setStackType(TSlot slot, const CCreature *type)
{
assert(vstd::contains(slots, slot));
CStackInstance *s = slots[slot];
s->setType(type->idNumber);
}
CStackInstance::CStackInstance() CStackInstance::CStackInstance()
: armyObj(_armyObj)
{ {
init(); init();
} }
CStackInstance::CStackInstance(TCreature id, TQuantity Count, const CArmedInstance *ArmyObj) CStackInstance::CStackInstance(TCreature id, TQuantity Count)
: armyObj(_armyObj)
{ {
init(); init();
setType(id); setType(id);
setArmyObj(ArmyObj);
count = Count; count = Count;
} }
CStackInstance::CStackInstance(const CCreature *cre, TQuantity Count) CStackInstance::CStackInstance(const CCreature *cre, TQuantity Count)
: armyObj(_armyObj)
{ {
init(); init();
type = cre; type = cre;
@ -288,7 +355,7 @@ void CStackInstance::init()
count = 0; count = 0;
type = NULL; type = NULL;
idRand = -1; idRand = -1;
armyObj = NULL; _armyObj = NULL;
nodeType = STACK; nodeType = STACK;
} }
@ -298,23 +365,31 @@ int CStackInstance::getQuantityID() const
} }
void CStackInstance::setType(int creID) void CStackInstance::setType(int creID)
{
setType(VLC->creh->creatures[creID]);
}
void CStackInstance::setType(const CCreature *c)
{ {
if(type) if(type)
detachFrom(const_cast<CCreature*>(type)); detachFrom(const_cast<CCreature*>(type));
type = VLC->creh->creatures[creID]; type = c;
attachTo(const_cast<CCreature*>(type)); attachTo(const_cast<CCreature*>(type));
} }
void CStackInstance::setArmyObj(const CArmedInstance *ArmyObj) void CStackInstance::setArmyObj(const CArmedInstance *ArmyObj)
{ {
if(armyObj) if(_armyObj)
detachFrom(const_cast<CArmedInstance*>(armyObj)); detachFrom(const_cast<CArmedInstance*>(_armyObj));
armyObj = ArmyObj; if(ArmyObj)
{
_armyObj = ArmyObj;
attachTo(const_cast<CArmedInstance*>(armyObj)); attachTo(const_cast<CArmedInstance*>(_armyObj));
}
} }
// void CStackInstance::getParents(TCNodes &out, const CBonusSystemNode *source /*= NULL*/) const // void CStackInstance::getParents(TCNodes &out, const CBonusSystemNode *source /*= NULL*/) const
// { // {
@ -334,6 +409,17 @@ std::string CStackInstance::getQuantityTXT(bool capitalized /*= true*/) const
return VLC->generaltexth->arraytxt[174 + getQuantityID()*3 + 2 - capitalized]; return VLC->generaltexth->arraytxt[174 + getQuantityID()*3 + 2 - capitalized];
} }
bool CStackInstance::valid(bool allowUnrandomized) const
{
bool isRand = (idRand != -1);
if(!isRand)
{
return (type && type == VLC->creh->creatures[type->idNumber]);
}
else
return allowUnrandomized;
}
CStackBasicDescriptor::CStackBasicDescriptor() CStackBasicDescriptor::CStackBasicDescriptor()
{ {
type = NULL; type = NULL;
@ -343,4 +429,18 @@ CStackBasicDescriptor::CStackBasicDescriptor()
CStackBasicDescriptor::CStackBasicDescriptor(TCreature id, TQuantity Count) CStackBasicDescriptor::CStackBasicDescriptor(TCreature id, TQuantity Count)
: type (VLC->creh->creatures[id]), count(Count) : type (VLC->creh->creatures[id]), count(Count)
{ {
}
DLL_EXPORT std::ostream & operator<<(std::ostream & str, const CStackInstance & sth)
{
if(!sth.valid(true))
str << "an invalid stack!";
str << "stack with " << sth.count << " of ";
if(sth.type)
str << sth.type->namePl;
else
str << sth.idRand;
return str;
} }

View File

@ -33,10 +33,11 @@ public:
class DLL_EXPORT CStackInstance : public CBonusSystemNode, public CStackBasicDescriptor class DLL_EXPORT CStackInstance : public CBonusSystemNode, public CStackBasicDescriptor
{ {
const CArmedInstance *_armyObj; //stack must be part of some army, army must be part of some object
public: public:
int idRand; //hlp variable used during loading game -> "id" placeholder for randomization int idRand; //hlp variable used during loading game -> "id" placeholder for randomization
const CArmedInstance *armyObj; //stack must be part of some army, army must be part of some object const CArmedInstance * const & armyObj; //stack must be part of some army, army must be part of some object
ui32 experience; //TODO: handle ui32 experience; //TODO: handle
//TODO: stack artifacts //TODO: stack artifacts
@ -44,7 +45,7 @@ public:
{ {
h & static_cast<CBonusSystemNode&>(*this); h & static_cast<CBonusSystemNode&>(*this);
h & static_cast<CStackBasicDescriptor&>(*this); h & static_cast<CStackBasicDescriptor&>(*this);
h & armyObj & experience; h & _armyObj & experience;
} }
//overrides CBonusSystemNode //overrides CBonusSystemNode
@ -54,12 +55,15 @@ public:
std::string getQuantityTXT(bool capitalized = true) const; std::string getQuantityTXT(bool capitalized = true) const;
void init(); void init();
CStackInstance(); CStackInstance();
CStackInstance(TCreature id, TQuantity count, const CArmedInstance *ArmyObj = NULL); CStackInstance(TCreature id, TQuantity count);
CStackInstance(const CCreature *cre, TQuantity count); CStackInstance(const CCreature *cre, TQuantity count);
void setType(int creID); void setType(int creID);
void setType(const CCreature *c);
void setArmyObj(const CArmedInstance *ArmyObj); void setArmyObj(const CArmedInstance *ArmyObj);
bool valid(bool allowUnrandomized) const;
}; };
DLL_EXPORT std::ostream & operator<<(std::ostream & str, const CStackInstance & sth);
typedef std::map<TSlot, CStackInstance*> TSlots; typedef std::map<TSlot, CStackInstance*> TSlots;
@ -71,22 +75,35 @@ public:
TSlots slots; //slots[slot_id]->> pair(creature_id,creature_quantity) TSlots slots; //slots[slot_id]->> pair(creature_id,creature_quantity)
ui8 formation; //false - wide, true - tight ui8 formation; //false - wide, true - tight
CCreatureSet();
virtual ~CCreatureSet();
const CStackInstance &operator[](TSlot slot) const; const CStackInstance &operator[](TSlot slot) const;
const TSlots &Slots() const {return slots;} const TSlots &Slots() const {return slots;}
void addToSlot(TSlot slot, TCreature cre, TQuantity count, bool allowMerging = true); //Adds stack to slot. Slot must be empty or with same type creature void addToSlot(TSlot slot, TCreature cre, TQuantity count, bool allowMerging = true); //Adds stack to slot. Slot must be empty or with same type creature
void addToSlot(TSlot slot, CStackInstance *stack, bool allowMerging = true); //Adds stack to slot. Slot must be empty or with same type creature void addToSlot(TSlot slot, CStackInstance *stack, bool allowMerging = true); //Adds stack to slot. Slot must be empty or with same type creature
void addStack(TSlot slot, CStackInstance *stack); //adds new stack to the army, slot must be empty
bool setCreature (TSlot slot, TCreature type, TQuantity quantity); //slots 0 to 6, if quantity=0, erases stack
void clear(); void clear();
void setFormation(bool tight); void setFormation(bool tight);
CArmedInstance *castToArmyObj();
//basic operations
void eraseStack(TSlot slot); //slot must be occupied
void putStack(TSlot slot, CStackInstance *stack); //adds new stack to the army, slot must be empty
void joinStack(TSlot slot, CStackInstance * stack); //adds new stack to the existing stack of the same type
void setStackCount(TSlot slot, TQuantity count); //stack must exist! void setStackCount(TSlot slot, TQuantity count); //stack must exist!
void eraseStack(TSlot slot); CStackInstance *detachStack(TSlot slot); //removes stack from army but doesn't destroy it (so it can be moved somewhere else)
void setStackType(TSlot slot, const CCreature *type);
//derivative
void changeStackCount(TSlot slot, TQuantity toAdd); //stack must exist!
bool setCreature (TSlot slot, TCreature type, TQuantity quantity); //replaces creature in stack; slots 0 to 6, if quantity=0 erases stack
void setToArmy(CCreatureSet &src); //erases all our army and moves stacks from src to us; src MUST NOT be an armed object! WARNING: use it wisely. Or better do not use at all.
const CStackInstance& getStack(TSlot slot) const; const CStackInstance& getStack(TSlot slot) const;
const CCreature* getCreature(TSlot slot) const; //workaround of map issue; const CCreature* getCreature(TSlot slot) const; //workaround of map issue;
int getAmount (TSlot slot) const; int getStackCount (TSlot slot) const;
TSlot findStack(const CStackInstance *stack) const; //-1 if none TSlot findStack(const CStackInstance *stack) const; //-1 if none
TSlot getSlotFor(TCreature creature, ui32 slotsAmount=ARMY_SIZE) const; //returns -1 if no slot available TSlot getSlotFor(TCreature creature, ui32 slotsAmount=ARMY_SIZE) const; //returns -1 if no slot available
bool mergableStacks(std::pair<TSlot, TSlot> &out, TSlot preferable = -1) const; //looks for two same stacks, returns slot positions; bool mergableStacks(std::pair<TSlot, TSlot> &out, TSlot preferable = -1) const; //looks for two same stacks, returns slot positions;
@ -100,7 +117,6 @@ public:
bool contains(const CStackInstance *stack) const; bool contains(const CStackInstance *stack) const;
CArmedInstance *castToArmyObj();
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {

View File

@ -1019,6 +1019,12 @@ std::vector<si32> CStack::activeSpells() const
return ret; return ret;
} }
CStack::~CStack()
{
if(vstd::contains(state, SUMMONED))
delNull(base);
}
CGHeroInstance * CGameState::HeroesPool::pickHeroFor(bool native, int player, const CTown *town, std::map<ui32,CGHeroInstance *> &available, const CHeroClass *bannedClass /*= NULL*/) const CGHeroInstance * CGameState::HeroesPool::pickHeroFor(bool native, int player, const CTown *town, std::map<ui32,CGHeroInstance *> &available, const CHeroClass *bannedClass /*= NULL*/) const
{ {
CGHeroInstance *ret = NULL; CGHeroInstance *ret = NULL;

View File

@ -272,6 +272,7 @@ public:
CStack(const CStackInstance *base, int O, int I, bool AO, int S); //c-tor CStack(const CStackInstance *base, int O, int I, bool AO, int S); //c-tor
CStack(const CStackBasicDescriptor *stack, int O, int I, bool AO, int S = 255); //c-tor CStack(const CStackBasicDescriptor *stack, int O, int I, bool AO, int S = 255); //c-tor
CStack(); //c-tor CStack(); //c-tor
~CStack();
void init(); //set initial (invalid) values void init(); //set initial (invalid) values
void postInit(); //used to finish initialization when inheriting creature parameters is working void postInit(); //used to finish initialization when inheriting creature parameters is working

View File

@ -109,7 +109,7 @@ void DLL_EXPORT BonusList::removeSpells(Bonus::BonusSource sourceType)
void BonusList::limit(const CBonusSystemNode &node) void BonusList::limit(const CBonusSystemNode &node)
{ {
remove_if(boost::bind(&CBonusSystemNode::isLimitedOnUs, node, _1)); remove_if(boost::bind(&CBonusSystemNode::isLimitedOnUs, boost::ref(node), _1));
} }
int CBonusSystemNode::valOfBonuses(Bonus::BonusType type, const CSelector &selector) const int CBonusSystemNode::valOfBonuses(Bonus::BonusType type, const CSelector &selector) const
@ -300,7 +300,13 @@ CBonusSystemNode::CBonusSystemNode()
CBonusSystemNode::~CBonusSystemNode() CBonusSystemNode::~CBonusSystemNode()
{ {
while(parents.size())
detachFrom(parents.front());
if(children.size())
{
tlog2 << "Warning: an orphaned child!\n";
}
} }
void CBonusSystemNode::attachTo(CBonusSystemNode *parent) void CBonusSystemNode::attachTo(CBonusSystemNode *parent)

View File

@ -37,6 +37,7 @@ class CArmedInstance;
struct TerrainTile; struct TerrainTile;
struct PlayerState; struct PlayerState;
class CTown; class CTown;
struct StackLocation;
class DLL_EXPORT IGameCallback class DLL_EXPORT IGameCallback
{ {
@ -89,7 +90,10 @@ public:
virtual void giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet creatures, bool remove) =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 void takeCreatures (int objid, std::vector<CStackBasicDescriptor> creatures) =0;
virtual void changeCreatureType (int objid, TSlot slot, TCreature creature) =0; virtual void changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false) =0;
virtual void changeStackType(const StackLocation &sl, CCreature *c) =0;
virtual void insertNewStack(const StackLocation &sl, CCreature *c, TQuantity count) =0;
virtual void eraseStack(const StackLocation &sl) =0;
virtual void showCompInfo(ShowInInfobox * comp)=0; virtual void showCompInfo(ShowInInfobox * comp)=0;
virtual void heroVisitCastle(int obj, int heroID)=0; virtual void heroVisitCastle(int obj, int heroID)=0;
virtual void stopHeroVisitCastle(int obj, int heroID)=0; virtual void stopHeroVisitCastle(int obj, int heroID)=0;

View File

@ -527,7 +527,8 @@ struct TryMoveHero : public CPackForClient //501
{ {
h & id & result & start & end & movePoints & fowRevealed & attackedFrom; h & id & result & start & end & movePoints & fowRevealed & attackedFrom;
} }
}; };
struct SetGarrisons : public CPackForClient //502 struct SetGarrisons : public CPackForClient //502
{ {
SetGarrisons(){type = 502;}; SetGarrisons(){type = 502;};
@ -713,6 +714,106 @@ struct NewArtifact : public CPackForClient
} }
}; };
struct StackLocation
{
CArmedInstance *army;
TSlot slot;
StackLocation()
{
army = NULL;
slot = -1;
}
StackLocation(const CArmedInstance *Army, TSlot Slot)
{
army = const_cast<CArmedInstance*>(Army); //we are allowed here to const cast -> change will go through one of our packages... do not abuse!
slot = Slot;
}
template <typename Handler> void serialize(Handler &h, const int version)
{
h & army & slot;
}
};
struct ChangeStackCount : CPackForClient //521
{
StackLocation sl;
TQuantity count;
ui8 absoluteValue; //if not -> count will be added (or subtracted if negative)
DLL_EXPORT void applyGs(CGameState *gs);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & sl & count;
}
};
struct SetStackType : CPackForClient //522
{
StackLocation sl;
CCreature *type;
DLL_EXPORT void applyGs(CGameState *gs);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & sl & type;
}
};
struct EraseStack : CPackForClient //523
{
StackLocation sl;
DLL_EXPORT void applyGs(CGameState *gs);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & sl;
}
};
struct SwapStacks : CPackForClient //524
{
StackLocation sl1, sl2;
DLL_EXPORT void applyGs(CGameState *gs);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & sl1 & sl2;
}
};
struct InsertNewStack : CPackForClient //525
{
StackLocation sl;
CStackInstance *stack;
DLL_EXPORT void applyGs(CGameState *gs);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & sl & stack;
}
};
//moves creatures from src stack to dst slot, may be used for merging/splittint/moving stacks
struct RebalanceStacks : CPackForClient //525
{
StackLocation src, dst;
TQuantity count;
DLL_EXPORT void applyGs(CGameState *gs);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & src & dst & count;
}
};
struct NewTurn : public CPackForClient //101 struct NewTurn : public CPackForClient //101
{ {
enum weekType {NORMAL, DOUBLE_GROWTH, BONUS_GROWTH, DEITYOFFIRE, PLAGUE, CUSTOM, NO_ACTION, NONE}; enum weekType {NORMAL, DOUBLE_GROWTH, BONUS_GROWTH, DEITYOFFIRE, PLAGUE, CUSTOM, NO_ACTION, NONE};

View File

@ -178,7 +178,7 @@ DLL_EXPORT void SetAvailableHeroes::applyGs( CGameState *gs )
{ {
CGHeroInstance *h = (hid[i]>=0 ? gs->hpool.heroesPool[hid[i]] : NULL); CGHeroInstance *h = (hid[i]>=0 ? gs->hpool.heroesPool[hid[i]] : NULL);
if(h && army[i]) if(h && army[i])
h->setArmy(*army[i]); h->setToArmy(*army[i]);
p->availableHeroes.push_back(h); p->availableHeroes.push_back(h);
} }
} }
@ -380,15 +380,15 @@ DLL_EXPORT void SetGarrisons::applyGs( CGameState *gs )
for(std::map<ui32,CCreatureSet>::iterator i = garrs.begin(); i!=garrs.end(); i++) for(std::map<ui32,CCreatureSet>::iterator i = garrs.begin(); i!=garrs.end(); i++)
{ {
CArmedInstance *ai = static_cast<CArmedInstance*>(gs->map->objects[i->first]); CArmedInstance *ai = static_cast<CArmedInstance*>(gs->map->objects[i->first]);
ai->setArmy(i->second); 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 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)->setArmy(i->second); const_cast<CGHeroInstance*>((static_cast<CGTownInstance*>(ai))->garrisonHero)->setToArmy(i->second);
else if(ai->ID==HEROI_TYPE) else if(ai->ID==HEROI_TYPE)
{ {
CGHeroInstance *h = static_cast<CGHeroInstance*>(ai); CGHeroInstance *h = static_cast<CGHeroInstance*>(ai);
CGTownInstance *t = const_cast<CGTownInstance *>(h->visitedTown); CGTownInstance *t = const_cast<CGTownInstance *>(h->visitedTown);
if(t && h->inTownGarrison) if(t && h->inTownGarrison)
t->setArmy(i->second); t->setToArmy(i->second);
} }
} }
} }
@ -605,6 +605,38 @@ DLL_EXPORT void NewArtifact::applyGs( CGameState *gs )
gs->map->artInstances.push_back(art); gs->map->artInstances.push_back(art);
} }
DLL_EXPORT void ChangeStackCount::applyGs( CGameState *gs )
{
if(absoluteValue)
sl.army->setStackCount(sl.slot, count);
else
sl.army->changeStackCount(sl.slot, count);
}
DLL_EXPORT void SetStackType::applyGs( CGameState *gs )
{
sl.army->setStackType(sl.slot, type);
}
DLL_EXPORT void EraseStack::applyGs( CGameState *gs )
{
sl.army->eraseStack(sl.slot);
}
DLL_EXPORT void SwapStacks::applyGs( CGameState *gs )
{
}
DLL_EXPORT void InsertNewStack::applyGs( CGameState *gs )
{
sl.army->putStack(sl.slot, stack);
}
DLL_EXPORT void RebalanceStacks::applyGs( CGameState *gs )
{
}
DLL_EXPORT void SetAvailableArtifacts::applyGs( CGameState *gs ) DLL_EXPORT void SetAvailableArtifacts::applyGs( CGameState *gs )
{ {
if(id >= 0) if(id >= 0)
@ -1007,10 +1039,11 @@ DLL_EXPORT void BattleSpellCast::applyGs( CGameState *gs )
} }
} }
CStack * summonedStack = gs->curB->generateNewStack(CStackInstance(creID, h->getPrimSkillLevel(2) * VLC->spellh->spells[id].powers[skill], h), gs->curB->stacks.size(), !side, 255, pos); CStackInstance *csi = new CStackInstance(creID, h->getPrimSkillLevel(2) * VLC->spellh->spells[id].powers[skill]); //deleted by d-tor of summoned stack
csi->setArmyObj(h);
CStack * summonedStack = gs->curB->generateNewStack(*csi, gs->curB->stacks.size(), !side, 255, pos);
summonedStack->state.insert(SUMMONED); summonedStack->state.insert(SUMMONED);
//summonedStack->addNewBonus( makeFeature(HeroBonus::SUMMONED, HeroBonus::ONE_BATTLE, 0, 0, HeroBonus::BONUS_FROM_HERO) ); //summonedStack->addNewBonus( makeFeature(HeroBonus::SUMMONED, HeroBonus::ONE_BATTLE, 0, 0, HeroBonus::BONUS_FROM_HERO) );
gs->curB->stacks.push_back(summonedStack); gs->curB->stacks.push_back(summonedStack);
} }
} }

View File

@ -142,6 +142,12 @@ void registerTypes2(Serializer &s)
s.template registerType<OpenWindow>(); s.template registerType<OpenWindow>();
s.template registerType<NewObject>(); s.template registerType<NewObject>();
s.template registerType<NewArtifact>(); s.template registerType<NewArtifact>();
s.template registerType<ChangeStackCount>();
s.template registerType<SetStackType>();
s.template registerType<EraseStack>();
s.template registerType<SwapStacks>();
s.template registerType<InsertNewStack>();
s.template registerType<RebalanceStacks>();
s.template registerType<SetAvailableArtifacts>(); s.template registerType<SetAvailableArtifacts>();
s.template registerType<SaveGame>(); s.template registerType<SaveGame>();

View File

@ -106,7 +106,7 @@ void readCreatureSet(CCreatureSet *out, const unsigned char * bufor, int &i, int
else else
hlp->setType(creID); hlp->setType(creID);
out->addStack(ir, hlp); out->putStack(ir, hlp);
} }
i+=number*bytesPerCre; i+=number*bytesPerCre;

View File

@ -322,7 +322,7 @@ static CCreatureSet takeCasualties(int color, const CCreatureSet &set, BattleInf
if(vstd::contains(st->state, SUMMONED)) //don't take into account sumoned stacks if(vstd::contains(st->state, SUMMONED)) //don't take into account sumoned stacks
continue; continue;
if(st->owner==color && !set.slotEmpty(st->slot) && st->count < set.getAmount(st->slot)) if(st->owner==color && !set.slotEmpty(st->slot) && st->count < set.getStackCount(st->slot))
{ {
if(st->alive()) if(st->alive())
ret.setStackCount(st->slot, st->count); ret.setStackCount(st->slot, st->count);
@ -2694,8 +2694,8 @@ bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2,
S1.slots[p1]->count -= val; S1.slots[p1]->count -= val;
} }
if ( (s1->tempOwner != player && S1.slots[p1]->count < s1->getArmy().getAmount(p1) ) if ( (s1->tempOwner != player && S1.slots[p1]->count < s1->getArmy().getStackCount(p1) )
|| (s2->tempOwner != player && S2.slots[p2]->count < s2->getArmy().getAmount(p2) ) ) || (s2->tempOwner != player && S2.slots[p2]->count < s2->getArmy().getStackCount(p2) ) )
{ {
complain("Can't move troops of another player!"); complain("Can't move troops of another player!");
return false; return false;
@ -3034,18 +3034,14 @@ bool CGameHandler::upgradeCreature( ui32 objid, ui8 pos, ui32 upgID )
return true; return true;
} }
void CGameHandler::changeCreatureType (int objid, TSlot slot, TCreature creature) void CGameHandler::changeStackType(const StackLocation &sl, CCreature *c)
{ {
CArmedInstance *obj = static_cast<CArmedInstance*>(gs->map->objects[objid]); assert(sl.army->getCreature(sl.slot));
if (obj)
{ SetStackType sst;
SetGarrisons sg; sst.sl = sl;
sg.garrs[objid] = obj->getArmy(); sst.type = c;
sg.garrs[objid].slots[slot]->setType(creature); sendAndApply(&sst);
sendAndApply(&sg);
}
else
tlog2 <<"Illegal call of changeCreatureType for non-armed instance!\n";
} }
bool CGameHandler::garrisonSwap( si32 tid ) bool CGameHandler::garrisonSwap( si32 tid )
@ -5247,7 +5243,7 @@ bool CGameHandler::tryAttackingGuard(const int3 &guardPos, const CGHeroInstance
bool CGameHandler::sacrificeCreatures(const IMarket *market, const CGHeroInstance *hero, TSlot slot, ui32 count) bool CGameHandler::sacrificeCreatures(const IMarket *market, const CGHeroInstance *hero, TSlot slot, ui32 count)
{ {
int oldCount = hero->getAmount(slot); int oldCount = hero->getStackCount(slot);
int newCount = oldCount - count; int newCount = oldCount - count;
if(oldCount < count) if(oldCount < count)
@ -5283,3 +5279,27 @@ bool CGameHandler::sacrificeArtifact(const IMarket * m, const CGHeroInstance * h
changePrimSkill(hero->id, 4, expToGive); changePrimSkill(hero->id, 4, expToGive);
return true; return true;
} }
void CGameHandler::insertNewStack(const StackLocation &sl, CCreature *c, TQuantity count)
{
InsertNewStack ins;
ins.sl = sl;
ins.stack = new CStackInstance(c, count);
sendAndApply(&ins);
}
void CGameHandler::eraseStack(const StackLocation &sl)
{
EraseStack es;
es.sl = sl;
sendAndApply(&es);
}
void CGameHandler::changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue /*= false*/)
{
ChangeStackCount csc;
csc.sl = sl;
csc.count = count;
csc.absoluteValue = absoluteValue;
sendAndApply(&csc);
}

View File

@ -138,7 +138,10 @@ public:
void giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet creatures, bool remove); void giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet creatures, bool remove);
void takeCreatures (int objid, TSlots creatures); void takeCreatures (int objid, TSlots creatures);
void takeCreatures (int objid, std::vector<CStackBasicDescriptor> creatures); void takeCreatures (int objid, std::vector<CStackBasicDescriptor> creatures);
void changeCreatureType (int objid, TSlot slot, TCreature creature); void changeStackType(const StackLocation &sl, CCreature *c);
void changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false);
void insertNewStack(const StackLocation &sl, CCreature *c, TQuantity count);
void eraseStack(const StackLocation &sl);
void showCompInfo(ShowInInfobox * comp); void showCompInfo(ShowInInfobox * comp);
void heroVisitCastle(int obj, int heroID); void heroVisitCastle(int obj, int heroID);
void vistiCastleObjects (const CGTownInstance *t, const CGHeroInstance *h); void vistiCastleObjects (const CGTownInstance *t, const CGHeroInstance *h);