mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-25 22:42:04 +02:00
Stacks #3 -> towards new system of stack operations.
This commit is contained in:
@@ -113,10 +113,14 @@ 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 changeStackType(const StackLocation &sl, CCreature *c){};
|
bool changeStackType(const StackLocation &sl, CCreature *c){return false;};
|
||||||
void changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false){};
|
bool changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false){return false;};
|
||||||
void insertNewStack(const StackLocation &sl, CCreature *c, TQuantity count){};
|
bool insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count){return false;};
|
||||||
void eraseStack(const StackLocation &sl){};
|
bool eraseStack(const StackLocation &sl){return false;};
|
||||||
|
bool swapStacks(const StackLocation &sl1, const StackLocation &sl2){return false;}
|
||||||
|
bool addToSlot(const StackLocation &sl, const CCreature *c, TQuantity count){return false;}
|
||||||
|
void tryJoiningArmy(const CArmedInstance *src, const CArmedInstance *dst, bool removeObjWhenFinished){}
|
||||||
|
bool moveStack(const StackLocation &src, const StackLocation &dst, TQuantity count = -1){return false;}
|
||||||
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){};
|
||||||
|
|||||||
@@ -122,6 +122,40 @@ void SetAvailableHeroes::applyCl( CClient *cl )
|
|||||||
//TODO: inform interface?
|
//TODO: inform interface?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChangeStackCount::applyCl( CClient *cl )
|
||||||
|
{
|
||||||
|
INTERFACE_CALL_IF_PRESENT(sl.army->tempOwner,garrisonChanged,sl.army);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetStackType::applyCl( CClient *cl )
|
||||||
|
{
|
||||||
|
INTERFACE_CALL_IF_PRESENT(sl.army->tempOwner,garrisonChanged,sl.army);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EraseStack::applyCl( CClient *cl )
|
||||||
|
{
|
||||||
|
INTERFACE_CALL_IF_PRESENT(sl.army->tempOwner,garrisonChanged,sl.army);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SwapStacks::applyCl( CClient *cl )
|
||||||
|
{
|
||||||
|
INTERFACE_CALL_IF_PRESENT(sl1.army->tempOwner,garrisonChanged,sl1.army);
|
||||||
|
if(sl1.army != sl2.army)
|
||||||
|
INTERFACE_CALL_IF_PRESENT(sl2.army->tempOwner,garrisonChanged,sl2.army);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InsertNewStack::applyCl( CClient *cl )
|
||||||
|
{
|
||||||
|
INTERFACE_CALL_IF_PRESENT(sl.army->tempOwner,garrisonChanged,sl.army);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RebalanceStacks::applyCl( CClient *cl )
|
||||||
|
{
|
||||||
|
INTERFACE_CALL_IF_PRESENT(src.army->tempOwner,garrisonChanged,src.army);
|
||||||
|
if(src.army != dst.army)
|
||||||
|
INTERFACE_CALL_IF_PRESENT(dst.army->tempOwner,garrisonChanged,dst.army);
|
||||||
|
}
|
||||||
|
|
||||||
void GiveBonus::applyCl( CClient *cl )
|
void GiveBonus::applyCl( CClient *cl )
|
||||||
{
|
{
|
||||||
switch(who)
|
switch(who)
|
||||||
|
|||||||
@@ -139,6 +139,11 @@ bool CCreature::isMyUpgrade(const CCreature *anotherCre) const
|
|||||||
return vstd::contains(upgrades, anotherCre->idNumber);
|
return vstd::contains(upgrades, anotherCre->idNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CCreature::valid() const
|
||||||
|
{
|
||||||
|
return this == VLC->creh->creatures[idNumber];
|
||||||
|
}
|
||||||
|
|
||||||
int readNumber(int & befi, int & i, int andame, std::string & buf) //helper function for void CCreatureHandler::loadCreatures() and loadUnitAnimInfo()
|
int readNumber(int & befi, int & i, int andame, std::string & buf) //helper function for void CCreatureHandler::loadCreatures() and loadUnitAnimInfo()
|
||||||
{
|
{
|
||||||
befi=i;
|
befi=i;
|
||||||
|
|||||||
@@ -61,6 +61,8 @@ public:
|
|||||||
static int getQuantityID(const int & quantity); //0 - a few, 1 - several, 2 - pack, 3 - lots, 4 - horde, 5 - throng, 6 - swarm, 7 - zounds, 8 - legion
|
static int getQuantityID(const int & quantity); //0 - a few, 1 - several, 2 - pack, 3 - lots, 4 - horde, 5 - throng, 6 - swarm, 7 - zounds, 8 - legion
|
||||||
bool isMyUpgrade(const CCreature *anotherCre) const;
|
bool isMyUpgrade(const CCreature *anotherCre) const;
|
||||||
|
|
||||||
|
bool valid() const;
|
||||||
|
|
||||||
void addBonus(int val, int type, int subtype = -1);
|
void addBonus(int val, int type, int subtype = -1);
|
||||||
//void getParents(TCNodes &out, const CBonusSystemNode *root /*= NULL*/) const;
|
//void getParents(TCNodes &out, const CBonusSystemNode *root /*= NULL*/) const;
|
||||||
|
|
||||||
|
|||||||
@@ -1766,10 +1766,11 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h, ui32 answer ) co
|
|||||||
|
|
||||||
int crid = creatures[0].second[0];
|
int crid = creatures[0].second[0];
|
||||||
CCreature *crs = VLC->creh->creatures[crid];
|
CCreature *crs = VLC->creh->creatures[crid];
|
||||||
|
TQuantity count = creatures[0].first;
|
||||||
|
|
||||||
if(crs->level == 1 && ID != 78) //first level - creatures are for free
|
if(crs->level == 1 && ID != 78) //first level - creatures are for free
|
||||||
{
|
{
|
||||||
if(creatures[0].first) //there are available creatures
|
if(count) //there are available creatures
|
||||||
{
|
{
|
||||||
int slot = h->getSlotFor(crid);
|
int slot = h->getSlotFor(crid);
|
||||||
if(slot < 0) //no available slot
|
if(slot < 0) //no available slot
|
||||||
@@ -1787,19 +1788,16 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h, ui32 answer ) co
|
|||||||
sac.creatures = creatures;
|
sac.creatures = creatures;
|
||||||
sac.creatures[0].first = 0;
|
sac.creatures[0].first = 0;
|
||||||
|
|
||||||
SetGarrisons sg;
|
|
||||||
sg.garrs[h->id] = *h;
|
|
||||||
sg.garrs[h->id].addToSlot(slot, crid, creatures[0].first);
|
|
||||||
|
|
||||||
InfoWindow iw;
|
InfoWindow iw;
|
||||||
iw.player = h->tempOwner;
|
iw.player = h->tempOwner;
|
||||||
iw.text.addTxt(MetaString::GENERAL_TXT, 423); //%d %s join your army.
|
iw.text.addTxt(MetaString::GENERAL_TXT, 423); //%d %s join your army.
|
||||||
iw.text.addReplacement(creatures[0].first);
|
iw.text.addReplacement(count);
|
||||||
iw.text.addReplacement(MetaString::CRE_PL_NAMES, crid);
|
iw.text.addReplacement(MetaString::CRE_PL_NAMES, crid);
|
||||||
|
|
||||||
cb->showInfoDialog(&iw);
|
cb->showInfoDialog(&iw);
|
||||||
cb->sendAndApply(&sac);
|
cb->sendAndApply(&sac);
|
||||||
cb->sendAndApply(&sg);
|
cb->addToSlot(StackLocation(h, slot), crs, count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else //there no creatures
|
else //there no creatures
|
||||||
@@ -3102,20 +3100,21 @@ void CGCreature::joinDecision(const CGHeroInstance *h, int cost, ui32 accept) co
|
|||||||
if(cost)
|
if(cost)
|
||||||
cb->giveResource(h->tempOwner,6,-cost);
|
cb->giveResource(h->tempOwner,6,-cost);
|
||||||
|
|
||||||
int slot = h->getSlotFor(subID);
|
cb->tryJoiningArmy(this, h, true);
|
||||||
if(slot >= 0) //there is place
|
// int slot = h->getSlotFor(subID);
|
||||||
{
|
// if(slot >= 0) //there is place
|
||||||
//add creatures
|
// {
|
||||||
SetGarrisons sg;
|
// //add creatures
|
||||||
sg.garrs[h->id] = h->getArmy();
|
// SetGarrisons sg;
|
||||||
sg.garrs[h->id].addToSlot(slot, subID, getStackCount(0));
|
// sg.garrs[h->id] = h->getArmy();
|
||||||
cb->sendAndApply(&sg);
|
// sg.garrs[h->id].addToSlot(slot, subID, getStackCount(0));
|
||||||
cb->removeObject(id);
|
// cb->sendAndApply(&sg);
|
||||||
}
|
// cb->removeObject(id);
|
||||||
else
|
// }
|
||||||
{
|
// else
|
||||||
cb->showGarrisonDialog(id,h->id,true,boost::bind(&IGameCallback::removeObject,cb,id)); //show garrison window and remove ourselves from map when player ends
|
// {
|
||||||
}
|
// cb->showGarrisonDialog(id,h->id,true,boost::bind(&IGameCallback::removeObject,cb,id)); //show garrison window and remove ourselves from map when player ends
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6158,14 +6157,13 @@ void CGSirens::onHeroVisit( const CGHeroInstance * h ) const
|
|||||||
{
|
{
|
||||||
giveDummyBonus(h->id, Bonus::ONE_BATTLE);
|
giveDummyBonus(h->id, Bonus::ONE_BATTLE);
|
||||||
int xp = 0;
|
int xp = 0;
|
||||||
SetGarrisons sg;
|
|
||||||
sg.garrs[h->id] = h->getArmy();
|
|
||||||
for (TSlots::const_iterator i = h->Slots().begin(); i != h->Slots().end(); i++)
|
for (TSlots::const_iterator i = h->Slots().begin(); i != h->Slots().end(); i++)
|
||||||
{
|
{
|
||||||
int drown = (int)(i->second->count * 0.3);
|
TQuantity drown = i->second->count * 0.3;
|
||||||
if(drown)
|
if(drown)
|
||||||
{
|
{
|
||||||
sg.garrs[h->id].setStackCount(i->first, i->second->count - drown);
|
cb->changeStackCount(StackLocation(h, i->first), -drown);
|
||||||
xp += drown * i->second->type->valOfBonuses(Bonus::STACK_HEALTH);
|
xp += drown * i->second->type->valOfBonuses(Bonus::STACK_HEALTH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6174,7 +6172,6 @@ void CGSirens::onHeroVisit( const CGHeroInstance * h ) const
|
|||||||
{
|
{
|
||||||
iw.text.addTxt(11,132);
|
iw.text.addTxt(11,132);
|
||||||
iw.text.addReplacement(xp);
|
iw.text.addReplacement(xp);
|
||||||
cb->sendAndApply(&sg);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -6182,6 +6179,8 @@ void CGSirens::onHeroVisit( const CGHeroInstance * h ) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
cb->showInfoDialog(&iw);
|
cb->showInfoDialog(&iw);
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
///TODO: WHAT WITH EXP?
|
||||||
}
|
}
|
||||||
|
|
||||||
//bool IShipyard::validLocation() const
|
//bool IShipyard::validLocation() const
|
||||||
|
|||||||
@@ -49,9 +49,16 @@ bool CCreatureSet::setCreature(TSlot slot, TCreature type, TQuantity quantity) /
|
|||||||
|
|
||||||
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 */
|
||||||
{
|
{
|
||||||
|
return getSlotFor(VLC->creh->creatures[creature], slotsAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
TSlot CCreatureSet::getSlotFor(const CCreature *c, ui32 slotsAmount/*=ARMY_SIZE*/) const
|
||||||
|
{
|
||||||
|
assert(c->valid());
|
||||||
for(TSlots::const_iterator i=slots.begin(); i!=slots.end(); ++i)
|
for(TSlots::const_iterator i=slots.begin(); i!=slots.end(); ++i)
|
||||||
{
|
{
|
||||||
if(i->second->type->idNumber == creature)
|
assert(i->second->type->valid());
|
||||||
|
if(i->second->type == c)
|
||||||
{
|
{
|
||||||
return i->first; //if there is already such creature we return its slot id
|
return i->first; //if there is already such creature we return its slot id
|
||||||
}
|
}
|
||||||
@@ -317,6 +324,7 @@ CStackInstance * CCreatureSet::detachStack(TSlot slot)
|
|||||||
if(CArmedInstance *armedObj = castToArmyObj())
|
if(CArmedInstance *armedObj = castToArmyObj())
|
||||||
ret->detachFrom(armedObj);
|
ret->detachFrom(armedObj);
|
||||||
|
|
||||||
|
slots.erase(slot);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,6 +335,24 @@ void CCreatureSet::setStackType(TSlot slot, const CCreature *type)
|
|||||||
s->setType(type->idNumber);
|
s->setType(type->idNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CCreatureSet::canBeMergedWith(const CCreatureSet &cs) const
|
||||||
|
{
|
||||||
|
std::set<const CCreature*> cres;
|
||||||
|
|
||||||
|
//get types of creatures that need their own slot
|
||||||
|
for(TSlots::const_iterator i = cs.slots.begin(); i != cs.slots.end(); i++)
|
||||||
|
cres.insert(i->second->type);
|
||||||
|
for(TSlots::const_iterator i = slots.begin(); i != slots.end(); i++)
|
||||||
|
cres.insert(i->second->type);
|
||||||
|
|
||||||
|
return cres.size() <= ARMY_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCreatureSet::hasStackAtSlot(TSlot slot) const
|
||||||
|
{
|
||||||
|
return vstd::contains(slots, slot);
|
||||||
|
}
|
||||||
|
|
||||||
CStackInstance::CStackInstance()
|
CStackInstance::CStackInstance()
|
||||||
: armyObj(_armyObj)
|
: armyObj(_armyObj)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ public:
|
|||||||
int getStackCount (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
|
||||||
|
TSlot getSlotFor(const CCreature *c, 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;
|
||||||
bool validTypes(bool allowUnrandomized = false) const; //checks if all types of creatures are set properly
|
bool validTypes(bool allowUnrandomized = false) const; //checks if all types of creatures are set properly
|
||||||
bool slotEmpty(TSlot slot) const;
|
bool slotEmpty(TSlot slot) const;
|
||||||
@@ -114,9 +115,10 @@ public:
|
|||||||
int getArmyStrength() const; //sum of AI values of creatures
|
int getArmyStrength() const; //sum of AI values of creatures
|
||||||
ui64 getPower (TSlot slot) const; //value of specific stack
|
ui64 getPower (TSlot slot) const; //value of specific stack
|
||||||
std::string getRoughAmount (TSlot slot) const; //rough size of specific stack
|
std::string getRoughAmount (TSlot slot) const; //rough size of specific stack
|
||||||
|
bool hasStackAtSlot(TSlot slot) const;
|
||||||
|
|
||||||
bool contains(const CStackInstance *stack) const;
|
bool contains(const CStackInstance *stack) const;
|
||||||
|
bool canBeMergedWith(const CCreatureSet &cs) const;
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -90,10 +90,14 @@ 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 changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false) =0;
|
virtual bool changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false) =0;
|
||||||
virtual void changeStackType(const StackLocation &sl, CCreature *c) =0;
|
virtual bool changeStackType(const StackLocation &sl, CCreature *c) =0;
|
||||||
virtual void insertNewStack(const StackLocation &sl, CCreature *c, TQuantity count) =0;
|
virtual bool insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count = -1) =0; //count -1 => moves whole stack
|
||||||
virtual void eraseStack(const StackLocation &sl) =0;
|
virtual bool eraseStack(const StackLocation &sl) =0;
|
||||||
|
virtual bool swapStacks(const StackLocation &sl1, const StackLocation &sl2) =0;
|
||||||
|
virtual bool addToSlot(const StackLocation &sl, const CCreature *c, TQuantity count) =0; //makes new stack or increases count of already existing
|
||||||
|
virtual void tryJoiningArmy(const CArmedInstance *src, const CArmedInstance *dst, bool removeObjWhenFinished) =0; //merges army from src do dst or opens a garrison window
|
||||||
|
virtual bool moveStack(const StackLocation &src, const StackLocation &dst, TQuantity count) = 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;
|
||||||
|
|||||||
@@ -736,12 +736,17 @@ struct StackLocation
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ChangeStackCount : CPackForClient //521
|
struct CGarrisonOperationPack : CPackForClient
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ChangeStackCount : CGarrisonOperationPack //521
|
||||||
{
|
{
|
||||||
StackLocation sl;
|
StackLocation sl;
|
||||||
TQuantity count;
|
TQuantity count;
|
||||||
ui8 absoluteValue; //if not -> count will be added (or subtracted if negative)
|
ui8 absoluteValue; //if not -> count will be added (or subtracted if negative)
|
||||||
|
|
||||||
|
void applyCl(CClient *cl);
|
||||||
DLL_EXPORT void applyGs(CGameState *gs);
|
DLL_EXPORT void applyGs(CGameState *gs);
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
@@ -750,11 +755,12 @@ struct ChangeStackCount : CPackForClient //521
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SetStackType : CPackForClient //522
|
struct SetStackType : CGarrisonOperationPack //522
|
||||||
{
|
{
|
||||||
StackLocation sl;
|
StackLocation sl;
|
||||||
CCreature *type;
|
CCreature *type;
|
||||||
|
|
||||||
|
void applyCl(CClient *cl);
|
||||||
DLL_EXPORT void applyGs(CGameState *gs);
|
DLL_EXPORT void applyGs(CGameState *gs);
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
@@ -763,10 +769,11 @@ struct SetStackType : CPackForClient //522
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EraseStack : CPackForClient //523
|
struct EraseStack : CGarrisonOperationPack //523
|
||||||
{
|
{
|
||||||
StackLocation sl;
|
StackLocation sl;
|
||||||
|
|
||||||
|
void applyCl(CClient *cl);
|
||||||
DLL_EXPORT void applyGs(CGameState *gs);
|
DLL_EXPORT void applyGs(CGameState *gs);
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
@@ -775,10 +782,11 @@ struct EraseStack : CPackForClient //523
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SwapStacks : CPackForClient //524
|
struct SwapStacks : CGarrisonOperationPack //524
|
||||||
{
|
{
|
||||||
StackLocation sl1, sl2;
|
StackLocation sl1, sl2;
|
||||||
|
|
||||||
|
void applyCl(CClient *cl);
|
||||||
DLL_EXPORT void applyGs(CGameState *gs);
|
DLL_EXPORT void applyGs(CGameState *gs);
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
@@ -787,11 +795,12 @@ struct SwapStacks : CPackForClient //524
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InsertNewStack : CPackForClient //525
|
struct InsertNewStack : CGarrisonOperationPack //525
|
||||||
{
|
{
|
||||||
StackLocation sl;
|
StackLocation sl;
|
||||||
CStackInstance *stack;
|
CStackInstance *stack;
|
||||||
|
|
||||||
|
void applyCl(CClient *cl);
|
||||||
DLL_EXPORT void applyGs(CGameState *gs);
|
DLL_EXPORT void applyGs(CGameState *gs);
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
@@ -801,11 +810,12 @@ struct InsertNewStack : CPackForClient //525
|
|||||||
};
|
};
|
||||||
|
|
||||||
//moves creatures from src stack to dst slot, may be used for merging/splittint/moving stacks
|
//moves creatures from src stack to dst slot, may be used for merging/splittint/moving stacks
|
||||||
struct RebalanceStacks : CPackForClient //525
|
struct RebalanceStacks : CGarrisonOperationPack //525
|
||||||
{
|
{
|
||||||
StackLocation src, dst;
|
StackLocation src, dst;
|
||||||
TQuantity count;
|
TQuantity count;
|
||||||
|
|
||||||
|
void applyCl(CClient *cl);
|
||||||
DLL_EXPORT void applyGs(CGameState *gs);
|
DLL_EXPORT void applyGs(CGameState *gs);
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
|||||||
@@ -625,7 +625,11 @@ DLL_EXPORT void EraseStack::applyGs( CGameState *gs )
|
|||||||
|
|
||||||
DLL_EXPORT void SwapStacks::applyGs( CGameState *gs )
|
DLL_EXPORT void SwapStacks::applyGs( CGameState *gs )
|
||||||
{
|
{
|
||||||
|
CStackInstance *s1 = sl1.army->detachStack(sl1.slot),
|
||||||
|
*s2 = sl2.army->detachStack(sl2.slot);
|
||||||
|
|
||||||
|
sl2.army->putStack(sl2.slot, s1);
|
||||||
|
sl1.army->putStack(sl1.slot, s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
DLL_EXPORT void InsertNewStack::applyGs( CGameState *gs )
|
DLL_EXPORT void InsertNewStack::applyGs( CGameState *gs )
|
||||||
|
|||||||
@@ -640,20 +640,13 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
|
|||||||
// Give raised units to winner and show dialog, if any were raised.
|
// Give raised units to winner and show dialog, if any were raised.
|
||||||
if (raisedStack.type)
|
if (raisedStack.type)
|
||||||
{
|
{
|
||||||
int slot = winnerHero->getSlotFor(raisedStack.type->idNumber);
|
TSlot slot = winnerHero->getSlotFor(raisedStack.type);
|
||||||
|
|
||||||
if (slot != -1)
|
if (slot != -1)
|
||||||
{
|
{
|
||||||
SetGarrisons sg;
|
|
||||||
sg.garrs[winnerHero->id] = winnerHero->getArmy();
|
|
||||||
sg.garrs[winnerHero->id].addToSlot(slot, raisedStack.type->idNumber, raisedStack.count);
|
|
||||||
|
|
||||||
// if (vstd::contains(winnerHero->slots, slot)) // Add to existing stack.
|
|
||||||
// sg.garrs[winnerHero->id].slots[slot]->count += raisedStack.count;
|
|
||||||
// else // Create a new stack.
|
|
||||||
// sg.garrs[winnerHero->id].slots[slot]->= raisedStack;
|
|
||||||
winnerHero->showNecromancyDialog(raisedStack);
|
winnerHero->showNecromancyDialog(raisedStack);
|
||||||
sendAndApply(&sg);
|
sendAndApply(&sg);
|
||||||
|
addToSlot(StackLocation(winnerHero, slot), raisedStack.type, raisedStack.count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -926,6 +919,7 @@ int CGameHandler::moveStack(int stack, int dest)
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
CGameHandler::CGameHandler(void)
|
CGameHandler::CGameHandler(void)
|
||||||
{
|
{
|
||||||
QID = 1;
|
QID = 1;
|
||||||
@@ -2624,8 +2618,8 @@ bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2,
|
|||||||
{
|
{
|
||||||
CArmedInstance *s1 = static_cast<CArmedInstance*>(gs->map->objects[id1]),
|
CArmedInstance *s1 = static_cast<CArmedInstance*>(gs->map->objects[id1]),
|
||||||
*s2 = static_cast<CArmedInstance*>(gs->map->objects[id2]);
|
*s2 = static_cast<CArmedInstance*>(gs->map->objects[id2]);
|
||||||
CCreatureSet temp1 = s1->getArmy(), temp2 = s2->getArmy(),
|
CCreatureSet &S1 = *s1, &S2 = *s2;
|
||||||
&S1 = temp1, &S2 = (s1!=s2)?(temp2):(temp1);
|
StackLocation sl1(s1, p1), sl2(s2, p2);
|
||||||
|
|
||||||
if(!isAllowedExchange(id1,id2))
|
if(!isAllowedExchange(id1,id2))
|
||||||
{
|
{
|
||||||
@@ -2641,14 +2635,8 @@ bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2,
|
|||||||
complain("Can't take troops from another player!");
|
complain("Can't take troops from another player!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::swap(S1.slots[p1], S2.slots[p2]); //swap slots
|
|
||||||
|
|
||||||
//if one of them is empty, remove entry
|
swapStacks(sl1, sl2);
|
||||||
if(!S1.slots[p1]->count)
|
|
||||||
S1.slots.erase(p1);
|
|
||||||
if(!S2.slots[p2]->count)
|
|
||||||
S2.slots.erase(p2);
|
|
||||||
}
|
}
|
||||||
else if(what==2)//merge
|
else if(what==2)//merge
|
||||||
{
|
{
|
||||||
@@ -2656,11 +2644,17 @@ bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2,
|
|||||||
|| ((s1->tempOwner != player && s1->tempOwner != 254) && S2.slots[p2]->count) && complain("Can't take troops from another player!"))
|
|| ((s1->tempOwner != player && s1->tempOwner != 254) && S2.slots[p2]->count) && complain("Can't take troops from another player!"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
S2.slots[p2]->count += S1.slots[p1]->count;
|
moveStack(sl1, sl2);
|
||||||
S1.slots.erase(p1);
|
|
||||||
}
|
}
|
||||||
else if(what==3) //split
|
else if(what==3) //split
|
||||||
{
|
{
|
||||||
|
if ( (s1->tempOwner != player && S1.slots[p1]->count < s1->getArmy().getStackCount(p1) )
|
||||||
|
|| (s2->tempOwner != player && S2.slots[p2]->count < s2->getArmy().getStackCount(p2) ) )
|
||||||
|
{
|
||||||
|
complain("Can't move troops of another player!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//general conditions checking
|
//general conditions checking
|
||||||
if((!vstd::contains(S1.slots,p1) && complain("no creatures to split"))
|
if((!vstd::contains(S1.slots,p1) && complain("no creatures to split"))
|
||||||
|| (val<1 && complain("no creatures to split")) )
|
|| (val<1 && complain("no creatures to split")) )
|
||||||
@@ -2679,8 +2673,9 @@ bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
S2.slots[p2]->count = val;
|
moveStack(sl1, sl2, val - S2.slots[p2]->count);
|
||||||
S1.slots[p1]->count = total - val;
|
//S2.slots[p2]->count = val;
|
||||||
|
//S1.slots[p1]->count = total - val;
|
||||||
}
|
}
|
||||||
else //split one stack to the two
|
else //split one stack to the two
|
||||||
{
|
{
|
||||||
@@ -2689,35 +2684,12 @@ bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2,
|
|||||||
complain("Cannot split that stack, not enough creatures!");
|
complain("Cannot split that stack, not enough creatures!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
S2.slots[p2]->type = S1.slots[p1]->type;
|
|
||||||
S2.slots[p2]->count = val;
|
|
||||||
S1.slots[p1]->count -= val;
|
moveStack(sl1, sl2, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (s1->tempOwner != player && S1.slots[p1]->count < s1->getArmy().getStackCount(p1) )
|
|
||||||
|| (s2->tempOwner != player && S2.slots[p2]->count < s2->getArmy().getStackCount(p2) ) )
|
|
||||||
{
|
|
||||||
complain("Can't move troops of another player!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!S1.slots[p1]->count) //if we've moved all creatures
|
|
||||||
S1.slots.erase(p1);
|
|
||||||
}
|
}
|
||||||
if((s1->needsLastStack() && !S1.stacksCount()) //it's not allowed to take last stack from hero army!
|
|
||||||
|| (s2->needsLastStack() && !S2.stacksCount())
|
|
||||||
)
|
|
||||||
{
|
|
||||||
complain("Cannot take the last stack!");
|
|
||||||
return false; //leave without applying changes to garrison
|
|
||||||
}
|
|
||||||
|
|
||||||
//apply changes
|
|
||||||
SetGarrisons sg;
|
|
||||||
sg.garrs[id1] = S1;
|
|
||||||
if(s1 != s2)
|
|
||||||
sg.garrs[id2] = S2;
|
|
||||||
sendAndApply(&sg);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2753,10 +2725,8 @@ bool CGameHandler::disbandCreature( si32 id, ui8 pos )
|
|||||||
complain("Illegal call to disbandCreature - no such stack in army!");
|
complain("Illegal call to disbandCreature - no such stack in army!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
s1->slots.erase(pos);
|
|
||||||
SetGarrisons sg;
|
eraseStack(StackLocation(s1, pos));
|
||||||
sg.garrs[id] = s1->getArmy();
|
|
||||||
sendAndApply(&sg);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2983,10 +2953,7 @@ bool CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram, si32 from
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SetGarrisons sg;
|
addToSlot(StackLocation(dst, slot), c, cram);
|
||||||
sg.garrs[dst->id] = dst->getArmy();
|
|
||||||
sg.garrs[dst->id] .addToSlot(slot, crid, cram);
|
|
||||||
sendAndApply(&sg);
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -2994,6 +2961,7 @@ bool CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram, si32 from
|
|||||||
bool CGameHandler::upgradeCreature( ui32 objid, ui8 pos, ui32 upgID )
|
bool CGameHandler::upgradeCreature( ui32 objid, ui8 pos, ui32 upgID )
|
||||||
{
|
{
|
||||||
CArmedInstance *obj = static_cast<CArmedInstance*>(gs->map->objects[objid]);
|
CArmedInstance *obj = static_cast<CArmedInstance*>(gs->map->objects[objid]);
|
||||||
|
assert(obj->hasStackAtSlot(pos));
|
||||||
UpgradeInfo ui = gs->getUpgradeInfo(obj->getStack(pos));
|
UpgradeInfo ui = gs->getUpgradeInfo(obj->getStack(pos));
|
||||||
int player = obj->tempOwner;
|
int player = obj->tempOwner;
|
||||||
int crQuantity = obj->slots[pos]->count;
|
int crQuantity = obj->slots[pos]->count;
|
||||||
@@ -3027,21 +2995,20 @@ bool CGameHandler::upgradeCreature( ui32 objid, ui8 pos, ui32 upgID )
|
|||||||
}
|
}
|
||||||
|
|
||||||
//upgrade creature
|
//upgrade creature
|
||||||
SetGarrisons sg;
|
changeStackType(StackLocation(obj, pos), VLC->creh->creatures[upgID]);
|
||||||
sg.garrs[objid] = obj->getArmy();
|
|
||||||
sg.garrs[objid].slots[pos]->setType(upgID);
|
|
||||||
sendAndApply(&sg);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGameHandler::changeStackType(const StackLocation &sl, CCreature *c)
|
bool CGameHandler::changeStackType(const StackLocation &sl, CCreature *c)
|
||||||
{
|
{
|
||||||
assert(sl.army->getCreature(sl.slot));
|
if(!sl.army->hasStackAtSlot(sl.slot))
|
||||||
|
COMPLAIN_RET("Cannot find a stack to change type");
|
||||||
|
|
||||||
SetStackType sst;
|
SetStackType sst;
|
||||||
sst.sl = sl;
|
sst.sl = sl;
|
||||||
sst.type = c;
|
sst.type = c;
|
||||||
sendAndApply(&sst);
|
sendAndApply(&sst);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CGameHandler::garrisonSwap( si32 tid )
|
bool CGameHandler::garrisonSwap( si32 tid )
|
||||||
@@ -3049,42 +3016,43 @@ bool CGameHandler::garrisonSwap( si32 tid )
|
|||||||
CGTownInstance *town = gs->getTown(tid);
|
CGTownInstance *town = gs->getTown(tid);
|
||||||
if(!town->garrisonHero && town->visitingHero) //visiting => garrison, merge armies: town army => hero army
|
if(!town->garrisonHero && town->visitingHero) //visiting => garrison, merge armies: town army => hero army
|
||||||
{
|
{
|
||||||
CCreatureSet csn = town->visitingHero->getArmy(), cso = town->getArmy();
|
|
||||||
|
if(!town->visitingHero->canBeMergedWith(*town))
|
||||||
|
{
|
||||||
|
complain("Cannot make garrison swap, not enough free slots!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CCreatureSet &cso = *town;
|
||||||
|
const CCreatureSet &csn = *town->visitingHero;
|
||||||
|
|
||||||
while(!cso.slots.empty())//while there are unmoved creatures
|
while(!cso.slots.empty())//while there are unmoved creatures
|
||||||
{
|
{
|
||||||
int pos = csn.getSlotFor(cso.slots.begin()->second->type->idNumber);
|
TSlots::const_iterator i = cso.slots.begin(); //iterator to stack to move
|
||||||
if(pos<0)
|
StackLocation sl(town, i->first); //location of stack to move
|
||||||
|
|
||||||
|
TSlot pos = csn.getSlotFor(i->second->type);
|
||||||
|
if(pos < 0)
|
||||||
{
|
{
|
||||||
//try to merge two other stacks to make place
|
//try to merge two other stacks to make place
|
||||||
std::pair<TSlot, TSlot> toMerge;
|
std::pair<TSlot, TSlot> toMerge;
|
||||||
if(csn.mergableStacks(toMerge, cso.slots.begin()->first))
|
if(csn.mergableStacks(toMerge, i->first))
|
||||||
{
|
{
|
||||||
//merge
|
moveStack(StackLocation(town->visitingHero, toMerge.first), StackLocation(town->visitingHero, toMerge.second)); //merge toMerge.first into toMerge.second
|
||||||
csn.slots[toMerge.second]->count += csn.slots[toMerge.first]->count;
|
moveStack(sl, StackLocation(town->visitingHero, toMerge.first)); //move stack to freed slot
|
||||||
csn.slots[toMerge.first] = cso.slots.begin()->second;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
complain("Cannot make garrison swap, not enough free slots!");
|
complain("Unexpected failure during an attempt to merge town and visiting hero armies!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(csn.slots.find(pos) != csn.slots.end()) //add creatures to the existing stack
|
else
|
||||||
{
|
{
|
||||||
csn.slots[pos]->count += cso.slots.begin()->second->count;
|
moveStack(sl, StackLocation(town->visitingHero, pos));
|
||||||
}
|
}
|
||||||
else //move stack on the free pos
|
|
||||||
{
|
|
||||||
csn.slots[pos]->type = cso.slots.begin()->second->type;
|
|
||||||
csn.slots[pos]->count = cso.slots.begin()->second->count;
|
|
||||||
}
|
|
||||||
cso.slots.erase(cso.slots.begin());
|
|
||||||
}
|
}
|
||||||
SetGarrisons sg;
|
|
||||||
sg.garrs[town->visitingHero->id] = csn;
|
|
||||||
sg.garrs[town->id] = csn;
|
|
||||||
sendAndApply(&sg);
|
|
||||||
|
|
||||||
SetHeroesInTown intown;
|
SetHeroesInTown intown;
|
||||||
intown.tid = tid;
|
intown.tid = tid;
|
||||||
intown.visiting = -1;
|
intown.visiting = -1;
|
||||||
@@ -3106,25 +3074,14 @@ bool CGameHandler::garrisonSwap( si32 tid )
|
|||||||
intown.garrison = -1;
|
intown.garrison = -1;
|
||||||
intown.visiting = town->garrisonHero->id;
|
intown.visiting = town->garrisonHero->id;
|
||||||
sendAndApply(&intown);
|
sendAndApply(&intown);
|
||||||
|
|
||||||
//town will be empty
|
|
||||||
SetGarrisons sg;
|
|
||||||
sg.garrs[tid] = CCreatureSet();
|
|
||||||
sendAndApply(&sg);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
else if (town->garrisonHero && town->visitingHero) //swap visiting and garrison hero
|
else if (town->garrisonHero && town->visitingHero) //swap visiting and garrison hero
|
||||||
{
|
{
|
||||||
SetGarrisons sg;
|
|
||||||
sg.garrs[town->id] = town->visitingHero->getArmy();;
|
|
||||||
sg.garrs[town->garrisonHero->id] = town->garrisonHero->getArmy();
|
|
||||||
|
|
||||||
SetHeroesInTown intown;
|
SetHeroesInTown intown;
|
||||||
intown.tid = tid;
|
intown.tid = tid;
|
||||||
intown.garrison = town->visitingHero->id;
|
intown.garrison = town->visitingHero->id;
|
||||||
intown.visiting = town->garrisonHero->id;
|
intown.visiting = town->garrisonHero->id;
|
||||||
sendAndApply(&intown);
|
sendAndApply(&intown);
|
||||||
sendAndApply(&sg);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -3537,14 +3494,7 @@ bool CGameHandler::sellCreatures(ui32 count, const IMarket *market, const CGHero
|
|||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changeStackCount(StackLocation(hero, slot), -count);
|
||||||
SetGarrisons sg;
|
|
||||||
sg.garrs[hero->id] = hero->getArmy();
|
|
||||||
if(s.count > count)
|
|
||||||
sg.garrs[hero->id].setStackCount(slot, s.count - count);
|
|
||||||
else
|
|
||||||
sg.garrs[hero->id].eraseStack(slot);
|
|
||||||
sendAndApply(&sg);
|
|
||||||
|
|
||||||
SetResource sr;
|
SetResource sr;
|
||||||
sr.player = hero->tempOwner;
|
sr.player = hero->tempOwner;
|
||||||
@@ -3561,13 +3511,14 @@ bool CGameHandler::transformInUndead(const IMarket *market, const CGHeroInstance
|
|||||||
if (hero)
|
if (hero)
|
||||||
army = hero;
|
army = hero;
|
||||||
else
|
else
|
||||||
{
|
|
||||||
army = dynamic_cast<const CGTownInstance *>(market->o);
|
army = dynamic_cast<const CGTownInstance *>(market->o);
|
||||||
}
|
|
||||||
if (!army)
|
if (!army)
|
||||||
COMPLAIN_RET("Incorrect call to transform in undead!");
|
COMPLAIN_RET("Incorrect call to transform in undead!");
|
||||||
if(!vstd::contains(army->Slots(), slot))
|
if(!army->hasStackAtSlot(slot))
|
||||||
COMPLAIN_RET("Army doesn't have any creature in that slot!");
|
COMPLAIN_RET("Army doesn't have any creature in that slot!");
|
||||||
|
|
||||||
|
|
||||||
const CStackInstance &s = army->getStack(slot);
|
const CStackInstance &s = army->getStack(slot);
|
||||||
int resCreature;//resulting creature - bone dragons or skeletons
|
int resCreature;//resulting creature - bone dragons or skeletons
|
||||||
|
|
||||||
@@ -3575,10 +3526,8 @@ bool CGameHandler::transformInUndead(const IMarket *market, const CGHeroInstance
|
|||||||
resCreature = 68;
|
resCreature = 68;
|
||||||
else
|
else
|
||||||
resCreature = 56;
|
resCreature = 56;
|
||||||
SetGarrisons sg;
|
|
||||||
sg.garrs[army->id] = army->getArmy();
|
changeStackType(StackLocation(army, slot), VLC->creh->creatures[resCreature]);
|
||||||
sg.garrs[army->id].setCreature(slot, resCreature, s.count);
|
|
||||||
sendAndApply(&sg);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4054,30 +4003,22 @@ void CGameHandler::playerMessage( ui8 player, const std::string &message )
|
|||||||
else if(message == "vcmiainur") //gives 5 archangels into each slot
|
else if(message == "vcmiainur") //gives 5 archangels into each slot
|
||||||
{
|
{
|
||||||
CGHeroInstance *hero = gs->getHero(gs->getPlayer(player)->currentSelection);
|
CGHeroInstance *hero = gs->getHero(gs->getPlayer(player)->currentSelection);
|
||||||
|
const CCreature *archangel = VLC->creh->creatures[13];
|
||||||
if(!hero) return;
|
if(!hero) return;
|
||||||
|
|
||||||
SetGarrisons sg;
|
for(int i = 0; i < ARMY_SIZE; i++)
|
||||||
CCreatureSet &newArmy = sg.garrs[hero->id];
|
if(!hero->hasStackAtSlot(i))
|
||||||
|
insertNewStack(StackLocation(hero, i), archangel, 10);
|
||||||
newArmy = hero->getArmy();
|
|
||||||
for(int i=0; i<ARMY_SIZE; i++)
|
|
||||||
if(newArmy.slotEmpty(i))
|
|
||||||
newArmy.addToSlot(i, 13, 5);
|
|
||||||
sendAndApply(&sg);
|
|
||||||
}
|
}
|
||||||
else if(message == "vcmiangband") //gives 10 black knight into each slot
|
else if(message == "vcmiangband") //gives 10 black knight into each slot
|
||||||
{
|
{
|
||||||
CGHeroInstance *hero = gs->getHero(gs->getPlayer(player)->currentSelection);
|
CGHeroInstance *hero = gs->getHero(gs->getPlayer(player)->currentSelection);
|
||||||
|
const CCreature *blackKnight = VLC->creh->creatures[66];
|
||||||
if(!hero) return;
|
if(!hero) return;
|
||||||
|
|
||||||
SetGarrisons sg;
|
for(int i = 0; i < ARMY_SIZE; i++)
|
||||||
CCreatureSet &newArmy = sg.garrs[hero->id];
|
if(!hero->hasStackAtSlot(i))
|
||||||
|
insertNewStack(StackLocation(hero, i), blackKnight, 10);
|
||||||
newArmy = hero->getArmy();
|
|
||||||
for(int i=0; i<ARMY_SIZE; i++)
|
|
||||||
if(newArmy.slotEmpty(i))
|
|
||||||
newArmy.addToSlot(i, 66, 10);
|
|
||||||
sendAndApply(&sg);
|
|
||||||
}
|
}
|
||||||
else if(message == "vcminoldor") //all war machines
|
else if(message == "vcminoldor") //all war machines
|
||||||
{
|
{
|
||||||
@@ -5244,7 +5185,6 @@ 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->getStackCount(slot);
|
int oldCount = hero->getStackCount(slot);
|
||||||
int newCount = oldCount - count;
|
|
||||||
|
|
||||||
if(oldCount < count)
|
if(oldCount < count)
|
||||||
COMPLAIN_RET("Not enough creatures to sacrifice!")
|
COMPLAIN_RET("Not enough creatures to sacrifice!")
|
||||||
@@ -5253,18 +5193,12 @@ bool CGameHandler::sacrificeCreatures(const IMarket *market, const CGHeroInstanc
|
|||||||
|
|
||||||
int crid = hero->getStack(slot).type->idNumber;
|
int crid = hero->getStack(slot).type->idNumber;
|
||||||
|
|
||||||
SetGarrisons sg;
|
changeStackCount(StackLocation(hero, slot), -count);
|
||||||
sg.garrs[hero->id] = hero->getArmy();
|
|
||||||
if(newCount)
|
|
||||||
sg.garrs[hero->id].setStackCount(slot, newCount);
|
|
||||||
else
|
|
||||||
sg.garrs[hero->id].eraseStack(slot);
|
|
||||||
sendAndApply(&sg);
|
|
||||||
|
|
||||||
int dump, exp;
|
int dump, exp;
|
||||||
market->getOffer(crid, 0, dump, exp, CREATURE_EXP);
|
market->getOffer(crid, 0, dump, exp, CREATURE_EXP);
|
||||||
exp *= count;
|
exp *= count;
|
||||||
changePrimSkill (hero->id, 4, exp*(100+hero->getSecSkillLevel(21)*5)/100.0f);
|
changePrimSkill(hero->id, 4, exp*(100+hero->getSecSkillLevel(21)*5)/100.0f);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -5280,26 +5214,149 @@ bool CGameHandler::sacrificeArtifact(const IMarket * m, const CGHeroInstance * h
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGameHandler::insertNewStack(const StackLocation &sl, CCreature *c, TQuantity count)
|
bool CGameHandler::insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count)
|
||||||
{
|
{
|
||||||
|
if(sl.army->hasStackAtSlot(sl.slot))
|
||||||
|
COMPLAIN_RET("Slot is already taken!");
|
||||||
|
|
||||||
InsertNewStack ins;
|
InsertNewStack ins;
|
||||||
ins.sl = sl;
|
ins.sl = sl;
|
||||||
ins.stack = new CStackInstance(c, count);
|
ins.stack = new CStackInstance(c, count);
|
||||||
sendAndApply(&ins);
|
sendAndApply(&ins);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGameHandler::eraseStack(const StackLocation &sl)
|
bool CGameHandler::eraseStack(const StackLocation &sl)
|
||||||
{
|
{
|
||||||
|
if(!sl.army->hasStackAtSlot(sl.slot))
|
||||||
|
COMPLAIN_RET("Cannot find a stack to erase");
|
||||||
|
|
||||||
|
if(sl.army->Slots().size() == 1 //from the last stack
|
||||||
|
&& sl.army->needsLastStack()) //that must be left
|
||||||
|
{
|
||||||
|
COMPLAIN_RET("Cannot erase the last stack!");
|
||||||
|
}
|
||||||
|
|
||||||
EraseStack es;
|
EraseStack es;
|
||||||
es.sl = sl;
|
es.sl = sl;
|
||||||
sendAndApply(&es);
|
sendAndApply(&es);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGameHandler::changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue /*= false*/)
|
bool CGameHandler::changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue /*= false*/)
|
||||||
{
|
{
|
||||||
ChangeStackCount csc;
|
TQuantity currentCount = sl.army->getStackCount(sl.slot);
|
||||||
csc.sl = sl;
|
if(absoluteValue && count < 0
|
||||||
csc.count = count;
|
|| !absoluteValue && -count > currentCount)
|
||||||
csc.absoluteValue = absoluteValue;
|
{
|
||||||
sendAndApply(&csc);
|
COMPLAIN_RET("Cannot take more stacks than present!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(currentCount == -count && !absoluteValue
|
||||||
|
|| !count && absoluteValue)
|
||||||
|
{
|
||||||
|
eraseStack(sl);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ChangeStackCount csc;
|
||||||
|
csc.sl = sl;
|
||||||
|
csc.count = count;
|
||||||
|
csc.absoluteValue = absoluteValue;
|
||||||
|
sendAndApply(&csc);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CGameHandler::addToSlot(const StackLocation &sl, const CCreature *c, TQuantity count)
|
||||||
|
{
|
||||||
|
const CCreature *slotC = sl.army->getCreature(sl.slot);
|
||||||
|
if(!slotC) //slot is empty
|
||||||
|
insertNewStack(sl, c, count);
|
||||||
|
else if(c == slotC)
|
||||||
|
changeStackCount(sl, count);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tlog1 << "Cannot add " << c->namePl << " to slot " << sl.slot << std::endl;
|
||||||
|
COMPLAIN_RET("Cannot add stack to slot!");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGameHandler::tryJoiningArmy(const CArmedInstance *src, const CArmedInstance *dst, bool removeObjWhenFinished)
|
||||||
|
{
|
||||||
|
if(!dst->canBeMergedWith(*src))
|
||||||
|
{
|
||||||
|
boost::function<void()> removeOrNot = 0;
|
||||||
|
if(removeObjWhenFinished)
|
||||||
|
removeOrNot = boost::bind(&IGameCallback::removeObject,this,src->id);
|
||||||
|
showGarrisonDialog(src->id, dst->id, true, removeOrNot); //show garrison window and optionally remove ourselves from map when player ends
|
||||||
|
}
|
||||||
|
else //merge
|
||||||
|
{
|
||||||
|
while(src->slots.size()) //there are not moved cres
|
||||||
|
{
|
||||||
|
TSlots::const_iterator i = src->slots.begin();
|
||||||
|
|
||||||
|
TSlot dstSlot = dst->getSlotFor(i->second->type);
|
||||||
|
if(dstSlot >= 0) //there is place
|
||||||
|
{
|
||||||
|
moveStack(StackLocation(src, i->first), StackLocation(dst, dstSlot), i->second->count);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tlog1 << "Unexpected Failure on merging armies!\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(removeObjWhenFinished)
|
||||||
|
removeObject(src->id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CGameHandler::moveStack(const StackLocation &src, const StackLocation &dst, TQuantity count)
|
||||||
|
{
|
||||||
|
if(!src.army->hasStackAtSlot(src.slot))
|
||||||
|
COMPLAIN_RET("No stack to move!");
|
||||||
|
|
||||||
|
if(dst.army->hasStackAtSlot(dst.slot) && dst.army->getCreature(dst.slot) != src.army->getCreature(src.slot))
|
||||||
|
COMPLAIN_RET("Cannot move: stack of different type at destination pos!");
|
||||||
|
|
||||||
|
if(count == -1)
|
||||||
|
{
|
||||||
|
count = src.army->getStackCount(src.slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(src.army != dst.army //moving away
|
||||||
|
&& count == src.army->getStackCount(src.slot) //all creatures
|
||||||
|
&& src.army->Slots().size() == 1 //from the last stack
|
||||||
|
&& src.army->needsLastStack()) //that must be left
|
||||||
|
{
|
||||||
|
COMPLAIN_RET("Cannot move away the alst creature!");
|
||||||
|
}
|
||||||
|
|
||||||
|
RebalanceStacks rs;
|
||||||
|
rs.src = src;
|
||||||
|
rs.dst = dst;
|
||||||
|
rs.count = count;
|
||||||
|
sendAndApply(&rs);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CGameHandler::swapStacks(const StackLocation &sl1, const StackLocation &sl2)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(!sl1.army->hasStackAtSlot(sl1.slot))
|
||||||
|
return moveStack(sl2, sl1);
|
||||||
|
else if(!sl2.army->hasStackAtSlot(sl2.slot))
|
||||||
|
return moveStack(sl1, sl2);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SwapStacks ss;
|
||||||
|
ss.sl1 = sl1;
|
||||||
|
ss.sl2 = sl2;
|
||||||
|
sendAndApply(&ss);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -138,10 +138,14 @@ 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 changeStackType(const StackLocation &sl, CCreature *c);
|
bool changeStackType(const StackLocation &sl, CCreature *c);
|
||||||
void changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false);
|
bool changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false);
|
||||||
void insertNewStack(const StackLocation &sl, CCreature *c, TQuantity count);
|
bool insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count);
|
||||||
void eraseStack(const StackLocation &sl);
|
bool eraseStack(const StackLocation &sl);
|
||||||
|
bool swapStacks(const StackLocation &sl1, const StackLocation &sl2);
|
||||||
|
bool addToSlot(const StackLocation &sl, const CCreature *c, TQuantity count);
|
||||||
|
void tryJoiningArmy(const CArmedInstance *src, const CArmedInstance *dst, bool removeObjWhenFinished);
|
||||||
|
bool moveStack(const StackLocation &src, const StackLocation &dst, TQuantity count = -1);
|
||||||
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);
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
CGameState* CPackForServer::GS(CGameHandler *gh)
|
CGameState* CPackForServer::GS(CGameHandler *gh)
|
||||||
{
|
{
|
||||||
return gh->gs;
|
return gh->gs;
|
||||||
|
|||||||
Reference in New Issue
Block a user