1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +02:00

* server sends confirmation (given later to player interface) after applying request (will be needed for AI)

* created new package for injuring multiple units - needed for area spells (not tested)
* proper screen updating on garrison change
* spell effects will be removed when they time out
* Corpse (Skeleton) will be accessible from all directions
* new objects supported:
- Corpse
- Lean To
- Wagon
- Warrior's Tomb

* several minor improvements
This commit is contained in:
Michał W. Urbańczyk 2009-04-16 00:28:54 +00:00
parent f9ae91d88c
commit d80afb1902
20 changed files with 576 additions and 180 deletions

View File

@ -35,6 +35,7 @@ struct BattleStackAttacked;
struct SpellCasted;
struct SetStackEffect;
struct HeroBonus;
struct PackageApplied;
class CLoadFile;
class CSaveFile;
template <typename Serializer> class CISer;
@ -88,6 +89,7 @@ public:
virtual void yourTurn(){};
virtual void availableCreaturesChanged(const CGTownInstance *town){};
virtual void heroBonusChanged(const CGHeroInstance *hero, const HeroBonus &bonus, bool gain){};//if gain hero received bonus, else he lost it
virtual void requestRealized(PackageApplied *pa){}
virtual void serialize(COSer<CSaveFile> &h, const int version){}; //saving
virtual void serialize(CISer<CLoadFile> &h, const int version){}; //loading

View File

@ -2112,8 +2112,8 @@ void CPlayerInterface::garrisonChanged(const CGObjectInstance * obj)
wasGarrison = true;
}
}
if(wasGarrison)
LOCPLINT->totalRedraw();
LOCPLINT->totalRedraw();
}
void CPlayerInterface::buildChanged(const CGTownInstance *town, int buildingID, int what) //what: 1 - built, 2 - demolished
@ -4761,14 +4761,14 @@ void CGarrisonWindow::deactivate()
void CGarrisonWindow::show(SDL_Surface * to)
{
blitAt(graphics->flags->ourImages[garr->odown->getOwner()].bitmap,pos.x+29,pos.y+125,to);
blitAt(graphics->portraitLarge[static_cast<const CGHeroInstance*>(garr->odown)->portrait],pos.x+29,pos.y+222,to);
printAtMiddle(CGI->generaltexth->allTexts[709],pos.x+275,pos.y+30,GEOR16,tytulowy,to);
blitAt(bg,pos,to);
split->show(to);
quit->show(to);
garr->show(to);
blitAt(graphics->flags->ourImages[garr->odown->getOwner()].bitmap,pos.x+29,pos.y+125,to);
blitAt(graphics->portraitLarge[static_cast<const CGHeroInstance*>(garr->odown)->portrait],pos.x+29,pos.y+222,to);
printAtMiddle(CGI->generaltexth->allTexts[709],pos.x+275,pos.y+30,GEOR16,tytulowy,to);
}
CGarrisonWindow::CGarrisonWindow( const CArmedInstance *up, const CGHeroInstance *down )

View File

@ -124,10 +124,16 @@ void CClient::run()
CPack *pack;
while(1)
{
tlog5 << "Listening... ";
*serv >> pack;
tlog5 << "\treceived server message of type " << typeid(*pack).name() << std::endl;
CBaseForCLApply *apply = applier->apps[typeList.getTypeID(pack)];
//get the package from the server
{
boost::unique_lock<boost::mutex> lock(*serv->rmx);
tlog5 << "Listening... ";
*serv >> pack;
tlog5 << "\treceived server message of type " << typeid(*pack).name() << std::endl;
}
CBaseForCLApply *apply = applier->apps[typeList.getTypeID(pack)]; //find the applier
if(apply)
{
apply->applyOnClBefore(this,pack);
@ -139,7 +145,7 @@ void CClient::run()
}
else
{
tlog5 << "Message cannot be applied, cannot find applier!\n";
tlog1 << "Message cannot be applied, cannot find applier!\n";
}
delete pack;
pack = NULL;

View File

@ -79,7 +79,7 @@ public:
//not working yet, will be implement somewhen later with support for local-sim-based gameplay
void changeSpells(int hid, bool give, const std::set<ui32> &spells){};
void removeObject(int objid){};
bool removeObject(int objid){return false;};
void setBlockVis(int objid, bool bv){};
void setOwner(int objid, ui8 owner){};
void setHoverName(int objid, MetaString * name){};
@ -98,7 +98,7 @@ public:
void startBattleI(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb){}; //use hero=NULL for no hero
void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb){}; //for hero<=>neutral army
void setAmount(int objid, ui32 val){};
void moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255){};
bool moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255){return false;};
void giveHeroBonus(GiveBonus * bonus){};
void setMovePoints(SetMovePoints * smp){};
void setManaPoints(int hid, int val){};

View File

@ -404,6 +404,12 @@ void SetStackEffect::applyCl( CClient *cl )
cl->playerint[GS(cl)->curB->side2]->battleStacksEffectsSet(*this);
}
void StacksInjured::applyCl( CClient *cl )
{
INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side1,battleStacksAttacked,stacks);
INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side2,battleStacksAttacked,stacks);
}
CGameState* CPackForClient::GS( CClient *cl )
{
return cl->gs;
@ -418,6 +424,11 @@ void EndAction::applyCl( CClient *cl )
cl->curbaction = NULL;
}
void PackageApplied::applyCl( CClient *cl )
{
INTERFACE_CALL_IF_PRESENT(GS(cl)->currentPlayer,requestRealized,this);
}
void SystemMessage::applyCl( CClient *cl )
{
std::ostringstream str;

View File

@ -54,6 +54,7 @@ enum ElossCon {lossCastle, lossHero, timeExpires, lossStandard=255};
enum EHeroClasses {HERO_KNIGHT, HERO_CLERIC, HERO_RANGER, HERO_DRUID, HERO_ALCHEMIST, HERO_WIZARD,
HERO_DEMONIAC, HERO_HERETIC, HERO_DEATHKNIGHT, HERO_NECROMANCER, HERO_WARLOCK, HERO_OVERLORD,
HERO_BARBARIAN, HERO_BATTLEMAGE, HERO_BEASTMASTER, HERO_WITCH, HERO_PLANESWALKER, HERO_ELEMENTALIST};
enum EartClass {ART_SPECIAL=1, ART_TREASURE=2, ART_MINOR=4, ART_MAJOR=8, ART_RELIC=16}; //artifact classes
enum EAbilities {DOUBLE_WIDE, FLYING, SHOOTER, TWO_HEX_ATTACK, SIEGE_ABILITY, SIEGE_WEAPON,
KING1, KING2, KING3, MIND_IMMUNITY, NO_OBSTACLE_PENALTY, NO_CLOSE_COMBAT_PENALTY,
JOUSTING, FIRE_IMMUNITY, TWICE_ATTACK, NO_ENEMY_RETALIATION, NO_MORAL_PENALTY,

View File

@ -43,7 +43,7 @@ void CArtHandler::loadArtifacts(bool onlyTxt)
std::vector<ui16> slots;
slots += 17, 16, 15,14,13, 18, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0;
std::map<char,EartClass> classes =
map_list_of('S',SartClass)('T',TartClass)('N',NartClass)('J',JartClass)('R',RartClass);
map_list_of('S',ART_SPECIAL)('T',ART_TREASURE)('N',ART_MINOR)('J',ART_MAJOR)('R',ART_RELIC);
std::string buf = bitmaph->getTextFile("ARTRAITS.TXT"), dump, pom;
int it=0;
for(int i=0; i<2; ++i)
@ -112,16 +112,16 @@ void CArtHandler::sortArts()
{
switch (artifacts[i].aClass)
{
case TartClass:
case ART_TREASURE:
treasures.push_back(&(artifacts[i]));
break;
case NartClass:
case ART_MINOR:
minors.push_back(&(artifacts[i]));
break;
case JartClass:
case ART_MAJOR:
majors.push_back(&(artifacts[i]));
break;
case RartClass:
case ART_RELIC:
relics.push_back(&(artifacts[i]));
break;
}

View File

@ -6,17 +6,15 @@
#include <string>
#include <vector>
/*
* CArtHandler.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
/*
* CArtHandler.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
enum EartClass {SartClass=0, TartClass, NartClass, JartClass, RartClass}; //artifact class (relict, treasure, strong, weak etc.)
class CDefHandler;
class DLL_EXPORT CArtifact //container for artifacts

View File

@ -89,7 +89,7 @@ void CDefObjInfoHandler::load()
}
else
{
static int visitableFromTop[] = {111,33,81,12,9,212,215}; //whirlpool, garrison, scholar, campfire, borderguard, bordergate, questguard
static int visitableFromTop[] = {111,33,81,12,9,212,215,22}; //whirlpool, garrison, scholar, campfire, borderguard, bordergate, questguard, corpse
for(int i=0; i < ARRAY_COUNT(visitableFromTop); i++)
{
if(visitableFromTop[i] == nobj->id)

View File

@ -778,7 +778,8 @@ double CGHeroInstance::getHeroStrength() const
int CGHeroInstance::getTotalStrength() const
{
return getHeroStrength() * getArmyStrength();
double ret = getHeroStrength() * getArmyStrength();
return (int) ret;
}
ui8 CGHeroInstance::getSpellSchoolLevel(const CSpell * spell) const
@ -1444,14 +1445,14 @@ int CGCreature::takenAction(const CGHeroInstance *h, bool allowJoin) const
//TODO: it's provisional formula, should be replaced with original one (or something closer to it)
//TODO: should be deterministic (will be needed for Vision spell)
int hlp2 = (hlp - 2)*1000;
int hlp2 = (int) (hlp - 2)*1000;
if(!neverFlees
&& hlp2 >= 0
&& rand()%2000 < hlp2
)
return -1;
return -1; //flee
else
return -2;
return -2; //fight
}
@ -2425,3 +2426,202 @@ void CGScholar::initObj()
}
}
}
void CGOnceVisitable::onHeroVisit( const CGHeroInstance * h ) const
{
int txtid = -1;
switch(ID)
{
case 22: //Corpse
txtid = 37;
break;
case 39: //Lean To
txtid = 64;
break;
case 105://Wagon
txtid = 154;
break;
case 108:
break;
default:
tlog1 << "Error: Unknown object (" << ID <<") treated as CGOnceVisitable!\n";
return;
}
if(ID == 108)//Warrior's Tomb
{
//ask if player wants to search the Tomb
BlockingDialog bd(true, false);
bd.player = h->getOwner();
bd.text.addTxt(MetaString::ADVOB_TXT,161);
cb->showBlockingDialog(&bd,boost::bind(&CGOnceVisitable::searchTomb,this,h,_1));
return;
}
InfoWindow iw;
iw.player = h->getOwner();
if(players.size()) //we have been already visited...
{
txtid++;
if(ID == 105) //wagon has extra text (for finding art) we need to ommit
txtid++;
iw.text.addTxt(MetaString::ADVOB_TXT, txtid);
}
else //first visit - give bonus!
{
if(ID == 105 && artOrRes == 1)
{
txtid++;
iw.text.replacements.push_back(VLC->arth->artifacts[bonusType].Name());
}
switch(artOrRes)
{
case 0:
txtid++;
break;
case 1: //art
iw.components.push_back(Component(Component::ARTIFACT,bonusType,0,0));
cb->giveHeroArtifact(bonusType,h->id,-2);
break;
case 2: //res
iw.components.push_back(Component(Component::RESOURCE,bonusType,bonusVal,0));
cb->giveResource(h->getOwner(),bonusType,bonusVal);
break;
}
iw.text.addTxt(MetaString::ADVOB_TXT, txtid);
}
cb->showInfoDialog(&iw);
cb->setObjProperty(id,10,h->getOwner());
}
const std::string & CGOnceVisitable::getHoverText() const
{
hoverName = VLC->generaltexth->names[ID] + " ";
hoverName += (hasVisited(cb->getCurrentPlayer())
? (VLC->generaltexth->allTexts[352]) //visited
: ( VLC->generaltexth->allTexts[353])); //not visited
return hoverName;
}
void CGOnceVisitable::initObj()
{
switch(ID)
{
case 22: //Corpse
{
blockVisit = true;
int hlp = ran()%100;
if(hlp < 20)
{
artOrRes = 1;
std::vector<CArtifact*> arts;
cb->getAllowed(arts, ART_TREASURE | ART_MINOR | ART_MAJOR);
bonusType = arts[ran() % arts.size()]->id;
}
else
{
artOrRes = 0;
}
}
break;
case 39: //Lean To
{
artOrRes = 2;
bonusType = ran()%6; //any basic resource without gold
bonusVal = ran()%4 + 1;
break;
}
case 108://Warrior's Tomb
{
artOrRes = 1;
std::vector<CArtifact*> arts;
int hlp = ran()%100;
if(hlp < 30)
cb->getAllowed(arts,ART_TREASURE);
else if(hlp < 80)
cb->getAllowed(arts,ART_MINOR);
else if(hlp < 95)
cb->getAllowed(arts,ART_MAJOR);
else
cb->getAllowed(arts,ART_RELIC);
bonusType = arts[ran() % arts.size()]->id;
}
break;
case 105://Wagon
{
int hlp = ran()%100;
if(hlp < 10)
{
artOrRes = 0; // nothing... :(
}
else if(hlp < 50) //minor or treasure art
{
artOrRes = 1;
std::vector<CArtifact*> arts;
cb->getAllowed(arts, ART_TREASURE | ART_MINOR);
bonusType = arts[ran() % arts.size()]->id;
}
else //2 - 5 of non-gold resource
{
artOrRes = 2;
bonusType = ran()%6;
bonusVal = ran()%4 + 2;
}
break;
}
}
}
void CGOnceVisitable::searchTomb(const CGHeroInstance *h, ui32 accept) const
{
if(accept)
{
InfoWindow iw;
iw.player = h->getOwner();
iw.components.push_back(Component(Component::MORALE,0,-3,0));
if(players.size()) //we've been already visited, player found nothing
{
iw.text.addTxt(MetaString::ADVOB_TXT,163);
}
else //first visit - give artifact
{
iw.text.addTxt(MetaString::ADVOB_TXT,162);
iw.components.push_back(Component(Component::ARTIFACT,bonusType,0,0));
iw.text.replacements.push_back(VLC->arth->artifacts[bonusType].Name());
cb->giveHeroArtifact(bonusType,h->id,-2);
}
if(!h->getBonus(HeroBonus::OBJECT,ID)) //we don't have modifier from this object yet
{
//ruin morale
GiveBonus gb;
gb.hid = h->id;
gb.bonus = HeroBonus(HeroBonus::ONE_BATTLE,HeroBonus::MORALE,HeroBonus::OBJECT,-3,id,"");
gb.bdescr.addTxt(MetaString::ARRAY_TXT,104); //Warrior Tomb Visited -3
cb->giveHeroBonus(&gb);
}
cb->showInfoDialog(&iw);
//add player to the visitors (for visited tooltop)
cb->setObjProperty(id,10,h->getOwner());
}
}

View File

@ -705,6 +705,25 @@ public:
}
};
class DLL_EXPORT CGOnceVisitable : public CPlayersVisited //wagon, corpse, lean to, warriors tomb
{
public:
ui8 artOrRes; //0 - nothing; 1 - artifact; 2 - resource
ui32 bonusType, //id of res or artifact
bonusVal; //resource amount (or not used)
void onHeroVisit(const CGHeroInstance * h) const;
const std::string & getHoverText() const;
void initObj();
void searchTomb(const CGHeroInstance *h, ui32 accept) const;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<CGObjectInstance&>(*this) & static_cast<CPlayersVisited&>(*this);;
h & bonusType & bonusVal;
}
};
class DLL_EXPORT CObjectHandler

View File

@ -4,6 +4,8 @@
#include "../map.h"
#include "../hch/CObjectHandler.h"
#include "../StartInfo.h"
#include "../hch/CArtHandler.h"
#include "../lib/VCMI_Lib.h"
/*
* IGameCallback.cpp, part of VCMI engine
@ -112,8 +114,34 @@ bool IGameCallback::isAllowed( int type, int id )
{
case 0:
return gs->map->allowedSpell[id];
case 1:
return gs->map->allowedArtifact[id];
default:
tlog1 << "Wrong call to IGameCallback::isAllowed!\n";
return false;
}
}
void IGameCallback::getAllowedArts(std::vector<CArtifact*> &out, std::vector<CArtifact*> CArtHandler::*arts)
{
for(int i = 0; i < (VLC->arth->*arts).size(); i++)
{
CArtifact *art = (VLC->arth->*arts)[i];
if(isAllowed(1,art->id))
{
out.push_back(art);
}
}
}
void IGameCallback::getAllowed(std::vector<CArtifact*> &out, int flags)
{
if(flags & ART_TREASURE)
getAllowedArts(out,&CArtHandler::treasures);
if(flags & ART_MINOR)
getAllowedArts(out,&CArtHandler::minors);
if(flags & ART_MAJOR)
getAllowedArts(out,&CArtHandler::majors);
if(flags & ART_RELIC)
getAllowedArts(out,&CArtHandler::relics);
}

View File

@ -29,6 +29,8 @@ struct BattleResult;
class CGameState;
struct PlayerSettings;
struct CPackForClient;
class CArtHandler;
class CArtifact;
class DLL_EXPORT IGameCallback
{
@ -49,11 +51,13 @@ public:
virtual const PlayerSettings * getPlayerSettings(int color);
virtual int getHeroCount(int player, bool includeGarrisoned);
virtual void getTilesInRange(std::set<int3> &tiles, int3 pos, int radious, int player=-1, int mode=0); //mode 1 - only unrevealed tiles; mode 0 - all, mode -1 - only unrevealed
virtual bool isAllowed(int type, int id); //type: 0 - spell
virtual bool isAllowed(int type, int id); //type: 0 - spell; 1- artifact
virtual void getAllowedArts(std::vector<CArtifact*> &out, std::vector<CArtifact*> CArtHandler::*arts);
virtual void getAllowed(std::vector<CArtifact*> &out, int flags); //flags: bitfield uses EartClass
//do sth
virtual void changeSpells(int hid, bool give, const std::set<ui32> &spells)=0;
virtual void removeObject(int objid)=0;
virtual bool removeObject(int objid)=0;
virtual void setBlockVis(int objid, bool bv)=0;
virtual void setOwner(int objid, ui8 owner)=0;
virtual void setHoverName(int objid, MetaString * name)=0;
@ -72,7 +76,7 @@ public:
virtual void startBattleI(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb)=0; //use hero=NULL for no hero
virtual void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb)=0; //for hero<=>neutral army
virtual void setAmount(int objid, ui32 val)=0;
virtual void moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255)=0;
virtual bool moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255)=0;
virtual void giveHeroBonus(GiveBonus * bonus)=0;
virtual void setMovePoints(SetMovePoints * smp)=0;
virtual void setManaPoints(int hid, int val)=0;

View File

@ -57,7 +57,7 @@ struct CPackForServer : public CPack
c = NULL;
};
void applyGh(CGameHandler *gh)//called after applying to gs
bool applyGh(CGameHandler *gh)//called after applying to gs
{};
};
@ -108,6 +108,21 @@ struct MetaString : public CPack //2001 helper for object scrips
/***********************************************************************************************************/
struct PackageApplied : public CPackForClient //94
{
PackageApplied() {type = 94;}
PackageApplied(ui8 Result) : result(Result) {type = 94;}
void applyCl(CClient *cl);
ui8 result; //0 - something went wrong, request hasn't been realized; 1 - OK
ui32 packType; //type id of applied package
template <typename Handler> void serialize(Handler &h, const int version)
{
h & result;
}
};
struct SystemMessage : public CPackForClient //95
{
SystemMessage(const std::string Text) : text(Text){type = 95;};
@ -490,7 +505,7 @@ struct NewTurn : public CPackForClient //101
struct Component : public CPack //2002 helper for object scrips informations
{
enum {PRIM_SKILL,SEC_SKILL,RESOURCE,CREATURE,ARTIFACT,EXPERIENCE,SPELL};
enum {PRIM_SKILL,SEC_SKILL,RESOURCE,CREATURE,ARTIFACT,EXPERIENCE,SPELL, MORALE=8, LUCK};
ui16 id, subtype; //id uses ^^^ enums, when id==EXPPERIENCE subtype==0 means exp points and subtype==1 levels)
si32 val; // + give; - take
si16 when; // 0 - now; +x - within x days; -x - per x days
@ -814,6 +829,19 @@ struct SetStackEffect : public CPackForClient //3010
}
};
struct StacksInjured : public CPackForClient //3011
{
StacksInjured(){type = 3011;}
DLL_EXPORT void applyGs(CGameState *gs);
void applyCl(CClient *cl);
std::set<BattleStackAttacked> stacks;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & stacks;
}
};
struct ShowInInfobox : public CPackForClient //107
{
ShowInInfobox(){type = 107;};
@ -832,14 +860,14 @@ struct ShowInInfobox : public CPackForClient //107
struct CloseServer : public CPackForServer
{
void applyGh(CGameHandler *gh);
bool applyGh(CGameHandler *gh);
template <typename Handler> void serialize(Handler &h, const int version)
{}
};
struct EndTurn : public CPackForServer
{
void applyGh(CGameHandler *gh);
bool applyGh(CGameHandler *gh);
template <typename Handler> void serialize(Handler &h, const int version)
{}
};
@ -850,7 +878,7 @@ struct DismissHero : public CPackForServer
DismissHero(si32 HID) : hid(HID) {};
si32 hid;
void applyGh(CGameHandler *gh);
bool applyGh(CGameHandler *gh);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & hid;
@ -864,7 +892,7 @@ struct MoveHero : public CPackForServer
int3 dest;
si32 hid;
void applyGh(CGameHandler *gh);
bool applyGh(CGameHandler *gh);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & dest & hid;
@ -881,7 +909,7 @@ struct ArrangeStacks : public CPackForServer
ui8 p1, p2; //positions of first and second stack
si32 id1, id2; //ids of objects with garrison
si32 val;
void applyGh(CGameHandler *gh);
bool applyGh(CGameHandler *gh);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & what & p1 & p2 & id1 & id2 & val;
@ -895,7 +923,7 @@ struct DisbandCreature : public CPackForServer
ui8 pos; //stack pos
si32 id; //object id
void applyGh(CGameHandler *gh);
bool applyGh(CGameHandler *gh);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & pos & id;
@ -908,7 +936,7 @@ struct BuildStructure : public CPackForServer
BuildStructure(si32 TID, si32 BID):bid(BID),tid(TID){};
si32 bid, tid; //structure and town ids
void applyGh(CGameHandler *gh);
bool applyGh(CGameHandler *gh);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & tid & bid;
@ -922,7 +950,7 @@ struct RecruitCreatures : public CPackForServer
si32 tid; //town id
ui32 crid, amount;//creature ID and amount
void applyGh(CGameHandler *gh);
bool applyGh(CGameHandler *gh);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & tid & crid & amount;
@ -937,7 +965,7 @@ struct UpgradeCreature : public CPackForServer
si32 id; //object id
si32 cid; //id of type to which we want make upgrade
void applyGh(CGameHandler *gh);
bool applyGh(CGameHandler *gh);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & pos & id & cid;
@ -950,7 +978,7 @@ struct GarrisonHeroSwap : public CPackForServer
GarrisonHeroSwap(si32 TID):tid(TID){};
si32 tid;
void applyGh(CGameHandler *gh);
bool applyGh(CGameHandler *gh);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & tid;
@ -965,7 +993,7 @@ struct ExchangeArtifacts : public CPackForServer
si32 hid1, hid2;
ui16 slot1, slot2;
void applyGh(CGameHandler *gh);
bool applyGh(CGameHandler *gh);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & hid1 & hid2 & slot1 & slot2;
@ -978,7 +1006,7 @@ struct BuyArtifact : public CPackForServer
BuyArtifact(si32 HID, si32 AID):hid(HID),aid(AID){};
si32 hid, aid; //hero and artifact id
void applyGh(CGameHandler *gh);
bool applyGh(CGameHandler *gh);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & hid & aid;
@ -996,7 +1024,7 @@ struct TradeOnMarketplace : public CPackForServer
ui32 r1, r2; //mode 0: r1 - sold resource, r2 - bought res
ui32 val; //units of sold resource
void applyGh(CGameHandler *gh);
bool applyGh(CGameHandler *gh);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & player & mode & /*id & */r1 & r2 & val;
@ -1010,7 +1038,7 @@ struct SetFormation : public CPackForServer
si32 hid;
ui8 formation;
void applyGh(CGameHandler *gh);
bool applyGh(CGameHandler *gh);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & hid & formation;
@ -1023,7 +1051,7 @@ struct HireHero : public CPackForServer
HireHero(si32 HID, si32 TID):hid(HID),tid(TID){};
si32 hid, tid; //available hero serial and town id
void applyGh(CGameHandler *gh);
bool applyGh(CGameHandler *gh);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & hid & tid;
@ -1036,7 +1064,7 @@ struct QueryReply : public CPackForServer
QueryReply(ui32 QID, ui32 Answer):qid(QID),answer(Answer){};
ui32 qid, answer; //hero and artifact id
void applyGh(CGameHandler *gh);
bool applyGh(CGameHandler *gh);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & qid & answer;
@ -1049,7 +1077,7 @@ struct MakeAction : public CPackForServer
MakeAction(const BattleAction &BA):ba(BA){};
BattleAction ba;
void applyGh(CGameHandler *gh);
bool applyGh(CGameHandler *gh);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & ba;
@ -1062,7 +1090,7 @@ struct MakeCustomAction : public CPackForServer
MakeCustomAction(const BattleAction &BA):ba(BA){};
BattleAction ba;
void applyGh(CGameHandler *gh);
bool applyGh(CGameHandler *gh);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & ba;
@ -1079,7 +1107,7 @@ struct SaveGame : public CPackForClient, public CPackForServer
void applyCl(CClient *cl);
void applyGs(CGameState *gs){};
void applyGh(CGameHandler *gh);
bool applyGh(CGameHandler *gh);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & fname;
@ -1094,7 +1122,7 @@ struct PlayerMessage : public CPackForClient, public CPackForServer //513
{CPackForClient::type = 513;};
void applyCl(CClient *cl);
void applyGs(CGameState *gs){};
void applyGh(CGameHandler *gh);
bool applyGh(CGameHandler *gh);
ui8 player;
std::string text;
@ -1110,7 +1138,7 @@ struct SetSelection : public CPackForClient, public CPackForServer //514
{
SetSelection(){CPackForClient::type = 514;};
DLL_EXPORT void applyGs(CGameState *gs);
void applyGh(CGameHandler *gh);
bool applyGh(CGameHandler *gh);
ui8 player;
ui32 id;

View File

@ -448,6 +448,16 @@ DLL_EXPORT void BattleNextRound::applyGs( CGameState *gs )
s->state -= MOVED;
s->state -= HAD_MORALE;
s->counterAttacks = 1;
//remove effects and restore only those with remaining turns in duration
std::vector<CStack::StackEffect> tmpEffects = s->effects;
s->effects.clear();
for(int i=0; i < tmpEffects.size(); i++)
{
tmpEffects[i].turnsRemain--;
if(tmpEffects[i].turnsRemain > 0)
s->effects.push_back(tmpEffects[i]);
}
}
}
@ -545,6 +555,12 @@ DLL_EXPORT void SetStackEffect::applyGs( CGameState *gs )
}
}
DLL_EXPORT void StacksInjured::applyGs( CGameState *gs )
{
BOOST_FOREACH(BattleStackAttacked stackAttacked, stacks)
stackAttacked.applyGs(gs);
}
DLL_EXPORT void YourTurn::applyGs( CGameState *gs )
{
gs->currentPlayer = player;

View File

@ -42,12 +42,14 @@ void registerTypes1(Serializer &s)
s.template registerType<CGBonusingObject>();
s.template registerType<CGMagicWell>();
s.template registerType<CGObservatory>();
s.template registerType<CGOnceVisitable>();
s.template registerType<CGObjectInstance>();
}
template<typename Serializer> DLL_EXPORT
void registerTypes2(Serializer &s)
{
s.template registerType<PackageApplied>();
s.template registerType<SystemMessage>();
s.template registerType<YourTurn>();
s.template registerType<SetResource>();
@ -89,6 +91,7 @@ void registerTypes2(Serializer &s)
s.template registerType<EndAction>();
s.template registerType<SpellCasted>();
s.template registerType<SetStackEffect>();
s.template registerType<StacksInjured>();
s.template registerType<ShowInInfobox>();
s.template registerType<SaveGame>();

View File

@ -1802,6 +1802,14 @@ void Mapa::readObjects( unsigned char * bufor, int &i)
nobj = new CGObservatory();
break;
}
case 22: //Corpse
case 39: //Lean To
case 105://Wagon
case 108://Warrior's Tomb
{
nobj = new CGOnceVisitable();
break;
}
case 214: //hero placeholder
{
i+=3; //TODO: handle it more properly

View File

@ -55,16 +55,16 @@ CondSh<BattleResult *> battleResult(NULL);
class CBaseForGHApply
{
public:
virtual void applyOnGH(CGameHandler *gh, CConnection *c, void *pack) const =0;
virtual bool applyOnGH(CGameHandler *gh, CConnection *c, void *pack) const =0;
};
template <typename T> class CApplyOnGH : public CBaseForGHApply
{
public:
void applyOnGH(CGameHandler *gh, CConnection *c, void *pack) const
bool applyOnGH(CGameHandler *gh, CConnection *c, void *pack) const
{
T *ptr = static_cast<T*>(pack);
ptr->c = c;
ptr->applyGh(gh);
return ptr->applyGh(gh);
}
};
@ -484,17 +484,32 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
{
while(!end2)
{
c >> pack;
tlog5 << "Received client message of type " << typeid(*pack).name() << std::endl;
CBaseForGHApply *apply = applier->apps[typeList.getTypeID(pack)];
{
boost::unique_lock<boost::mutex> lock(*c.rmx);
c >> pack; //get the package
tlog5 << "Received client message of type " << typeid(*pack).name() << std::endl;
}
int packType = typeList.getTypeID(pack); //get the id of type
CBaseForGHApply *apply = applier->apps[packType]; //and appropriae applier object
if(apply)
{
apply->applyOnGH(this,&c,pack);
tlog5 << "Message successfully applied!\n";
bool result = apply->applyOnGH(this,&c,pack);
tlog5 << "Message successfully applied (result=" << result << ")!\n";
//send confirmation that we've applied the package
PackageApplied applied;
applied.result = result;
applied.packType = packType;
{
boost::unique_lock<boost::mutex> lock(*c.wmx);
c << &applied;
}
}
else
{
tlog5 << "Message cannot be applied, cannot find applier!\n";
tlog1 << "Message cannot be applied, cannot find applier (unregistered type)!\n";
}
delete pack;
pack = NULL;
@ -759,6 +774,7 @@ void CGameHandler::run(bool resume)
{
YourTurn yt;
yt.player = i->first;
boost::unique_lock<boost::mutex> lock(*connections[i->first]->wmx);
*connections[i->first] << &yt;
}
@ -1063,11 +1079,19 @@ void CGameHandler::setBlockVis(int objid, bool bv)
SetObjectProperty sop(objid,2,bv);
sendAndApply(&sop);
}
void CGameHandler::removeObject(int objid)
bool CGameHandler::removeObject( int objid )
{
if(!getObj(objid))
{
tlog1 << "Something wrong, that object already has been removed or hasn't existed!\n";
return false;
}
RemoveObject ro;
ro.id = objid;
sendAndApply(&ro);
return true;
}
void CGameHandler::setAmount(int objid, ui32 val)
@ -1076,7 +1100,7 @@ void CGameHandler::setAmount(int objid, ui32 val)
sendAndApply(&sop);
}
void CGameHandler::moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker)
bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*/ )
{
bool blockvis = false;
const CGHeroInstance *h = getHero(hid);
@ -1085,7 +1109,7 @@ void CGameHandler::moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker)
)
{
tlog1 << "Illegal call to move hero!\n";
return;
return false;
}
tlog5 << "Player " <<int(asker) << " wants to move hero "<< hid << " from "<< h->pos << " to " << dst << std::endl;
@ -1109,7 +1133,7 @@ void CGameHandler::moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker)
{
tlog2 << "Cannot move hero, destination tile is blocked!\n";
sendAndApply(&tmh);
return;
return false;
}
//checks for standard movement
@ -1121,7 +1145,7 @@ void CGameHandler::moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker)
{
tlog2 << "Cannot move hero, not enough move points or tiles are not neighbouring!\n";
sendAndApply(&tmh);
return;
return false;
}
//check if there is blocking visitable object
@ -1148,7 +1172,7 @@ void CGameHandler::moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker)
}
}
tlog5 << "Blocking visit at " << hmpos << std::endl;
return;
return true;
}
else //normal move
{
@ -1169,6 +1193,7 @@ void CGameHandler::moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker)
}
}
tlog5 << "Movement end!\n";
return true;
}
else //instant move - teleportation
{
@ -1177,16 +1202,17 @@ void CGameHandler::moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker)
if(obj->ID==HEROI_TYPE)
{
if(obj->tempOwner==h->tempOwner)
return;//TODO: exchange
return true;//TODO: exchange
//TODO: check for ally
CGHeroInstance *dh = static_cast<CGHeroInstance *>(obj);
startBattleI(&h->army,&dh->army,dst,h,dh,0);
return;
return true;
}
}
tmh.result = instant+1;
getTilesInRange(tmh.fowRevealed,h->getSightCenter()+(tmh.end-tmh.start),h->getSightRadious(),h->tempOwner,1);
sendAndApply(&tmh);
return true;
}
}
void CGameHandler::setOwner(int objid, ui8 owner)
@ -1452,7 +1478,7 @@ void CGameHandler::close()
//exit(0);
}
void CGameHandler::arrangeStacks(si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2, si32 val)
bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2, si32 val )
{
CArmedInstance *s1 = static_cast<CArmedInstance*>(gs->map->objects[id1]),
*s2 = static_cast<CArmedInstance*>(gs->map->objects[id2]);
@ -1462,7 +1488,7 @@ void CGameHandler::arrangeStacks(si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2, s
if(!isAllowedExchange(id1,id2))
{
complain("Cannot exchange stacks between these two objects!\n");
return;
return false;
}
if(what==1) //swap
@ -1480,7 +1506,7 @@ void CGameHandler::arrangeStacks(si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2, s
if(S1.slots[p1].first != S2.slots[p2].first) //not same creature
{
complain("Cannot merge different creatures stacks!");
return;
return false;
}
S2.slots[p2].second += S1.slots[p1].second;
@ -1492,7 +1518,7 @@ void CGameHandler::arrangeStacks(si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2, s
if((!vstd::contains(S1.slots,p1) && complain("no creatures to split"))
|| (val<1 && complain("no creatures to split")) )
{
return;
return false;
}
@ -1503,7 +1529,7 @@ void CGameHandler::arrangeStacks(si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2, s
|| (S2.slots[p2].first != S1.slots[p1].first && complain("Cannot rebalance different creatures stacks!"))
)
{
return;
return false;
}
S2.slots[p2].second = val;
@ -1514,7 +1540,7 @@ void CGameHandler::arrangeStacks(si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2, s
if(S1.slots[p1].second < val)//not enough creatures
{
complain("Cannot split that stack, not enough creatures!");
return;
return false;
}
S2.slots[p2].first = S1.slots[p1].first;
S2.slots[p2].second = val;
@ -1529,7 +1555,7 @@ void CGameHandler::arrangeStacks(si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2, s
)
{
complain("Cannot take the last stack!");
return; //leave without applying changes to garrison
return false; //leave without applying changes to garrison
}
//apply changes
@ -1538,6 +1564,7 @@ void CGameHandler::arrangeStacks(si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2, s
if(s1 != s2)
sg.garrs[id2] = S2;
sendAndApply(&sg);
return true;
}
int CGameHandler::getPlayerAt( CConnection *c ) const
@ -1564,21 +1591,22 @@ int CGameHandler::getPlayerAt( CConnection *c ) const
}
}
void CGameHandler::disbandCreature(si32 id, ui8 pos)
bool CGameHandler::disbandCreature( si32 id, ui8 pos )
{
CArmedInstance *s1 = static_cast<CArmedInstance*>(gs->map->objects[id]);
if(!vstd::contains(s1->army.slots,pos))
{
complain("Illegal call to disbandCreature - no such stack in army!");
return;
return false;
}
s1->army.slots.erase(pos);
SetGarrisons sg;
sg.garrs[id] = s1->army;
sendAndApply(&sg);
return true;
}
void CGameHandler::buildStructure(si32 tid, si32 bid)
bool CGameHandler::buildStructure( si32 tid, si32 bid )
{
CGTownInstance * t = static_cast<CGTownInstance*>(gs->map->objects[tid]);
CBuilding * b = VLC->buildh->buildings[t->subID][bid];
@ -1586,7 +1614,7 @@ void CGameHandler::buildStructure(si32 tid, si32 bid)
if(gs->canBuildStructure(t,bid) != 7)
{
complain("Cannot build that building!");
return;
return false;
}
NewStructures ns;
@ -1625,6 +1653,8 @@ void CGameHandler::buildStructure(si32 tid, si32 bid)
if(t->garrisonHero)
giveSpells(t,t->garrisonHero);
}
return true;
}
void CGameHandler::sendMessageToAll( const std::string &message )
@ -1634,7 +1664,7 @@ void CGameHandler::sendMessageToAll( const std::string &message )
sendToAllClients(&sm);
}
void CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram )
bool CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram )
{
si32 ser = -1;
CGTownInstance * t = static_cast<CGTownInstance*>(gs->map->objects[objid]);
@ -1654,11 +1684,13 @@ void CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram )
}
int slot = t->army.getSlotFor(crid);
if(!found || //no such creature
cram > VLC->creh->creatures[crid].maxAmount(gs->getPlayer(t->tempOwner)->resources) || //lack of resources
cram<=0 ||
slot<0 )
return;
if(!found && complain("Cannot recruit: no such creatures!")
|| cram > VLC->creh->creatures[crid].maxAmount(gs->getPlayer(t->tempOwner)->resources) && complain("Cannot recruit: lack of resources!")
|| cram<=0 && complain("Cannot recruit: cram <= 0!")
|| slot<0 && complain("Cannot recruit: no available slot!"))
{
return false;
}
//recruit
SetResources sr;
@ -1684,9 +1716,10 @@ void CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram )
sendAndApply(&sr);
sendAndApply(&sac);
sendAndApply(&sg);
return true;
}
void 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]);
UpgradeInfo ui = gs->getUpgradeInfo(obj,pos);
@ -1694,8 +1727,10 @@ void CGameHandler::upgradeCreature( ui32 objid, ui8 pos, ui32 upgID )
int crQuantity = obj->army.slots[pos].second;
//check if upgrade is possible
if(ui.oldID<0 || !vstd::contains(ui.newID,upgID))
return;
if((ui.oldID<0 || !vstd::contains(ui.newID,upgID)) && complain("That upgrade is not possible!"))
{
return false;
}
//check if player has enough resources
for(int i=0;i<ui.cost.size();i++)
@ -1703,7 +1738,10 @@ void CGameHandler::upgradeCreature( ui32 objid, ui8 pos, ui32 upgID )
for (std::set<std::pair<int,int> >::iterator j=ui.cost[i].begin(); j!=ui.cost[i].end(); j++)
{
if(gs->getPlayer(player)->resources[j->first] < j->second*crQuantity)
return;
{
complain("Cannot upgrade, not enough resources!");
return false;
}
}
}
@ -1725,9 +1763,10 @@ void CGameHandler::upgradeCreature( ui32 objid, ui8 pos, ui32 upgID )
sg.garrs[objid] = obj->army;
sg.garrs[objid].slots[pos].first = upgID;
sendAndApply(&sg);
return true;
}
void CGameHandler::garrisonSwap(si32 tid)
bool CGameHandler::garrisonSwap( si32 tid )
{
CGTownInstance *town = gs->getTown(tid);
if(!town->garrisonHero && town->visitingHero) //visiting => garrison, merge armies
@ -1737,7 +1776,10 @@ void CGameHandler::garrisonSwap(si32 tid)
{
int pos = csn.getSlotFor(cso.slots.begin()->second.first);
if(pos<0)
return;
{
complain("Cannot make garrison swap, not enough free slots!");
return false;
}
if(csn.slots.find(pos)!=csn.slots.end()) //add creatures to the existing stack
{
csn.slots[pos].second += cso.slots.begin()->second.second;
@ -1759,6 +1801,7 @@ void CGameHandler::garrisonSwap(si32 tid)
intown.visiting = -1;
intown.garrison = town->visitingHero->id;
sendAndApply(&intown);
return true;
}
else if (town->garrisonHero && !town->visitingHero) //move hero out of the garrison
{
@ -1766,7 +1809,7 @@ void CGameHandler::garrisonSwap(si32 tid)
if(getHeroCount(town->garrisonHero->tempOwner,true) >= 8)
{
complain("Cannot move hero out of the garrison, there are already 8 wandering heroes!");
return;
return false;
}
SetHeroesInTown intown;
@ -1779,6 +1822,7 @@ void CGameHandler::garrisonSwap(si32 tid)
SetGarrisons sg;
sg.garrs[tid] = CCreatureSet();
sendAndApply(&sg);
return true;
}
else if (town->garrisonHero && town->visitingHero) //swap visiting and garrison hero
{
@ -1792,18 +1836,21 @@ void CGameHandler::garrisonSwap(si32 tid)
intown.visiting = town->garrisonHero->id;
sendAndApply(&intown);
sendAndApply(&sg);
return true;
}
else
{
complain("Cannot swap garrison hero!");
return false;
}
}
void CGameHandler::swapArtifacts( si32 hid1, si32 hid2, ui16 slot1, ui16 slot2 )
bool CGameHandler::swapArtifacts( si32 hid1, si32 hid2, ui16 slot1, ui16 slot2 )
{
CGHeroInstance *h1 = gs->getHero(hid1), *h2 = gs->getHero(hid2);
if((distance(h1->pos,h2->pos) > 1.0) || (h1->tempOwner != h2->tempOwner))
return;
return false;
const CArtifact *a1 = h1->getArt(slot1),
*a2=h2->getArt(slot2);
@ -1813,7 +1860,7 @@ void CGameHandler::swapArtifacts( si32 hid1, si32 hid2, ui16 slot1, ui16 slot2 )
{
//artifact doesn't fit dst slot
complain("Cannot swap artifacts!");
return;
return false;
}
@ -1832,9 +1879,11 @@ void CGameHandler::swapArtifacts( si32 hid1, si32 hid2, ui16 slot1, ui16 slot2 )
sha.setArtAtPos(slot2,h1->getArtAtPos(slot1));
sendAndApply(&sha);
}
return true;
}
void CGameHandler::buyArtifact( ui32 hid, si32 aid )
bool CGameHandler::buyArtifact( ui32 hid, si32 aid )
{
CGHeroInstance *hero = gs->getHero(hid);
CGTownInstance *town = hero->visitedTown;
@ -1844,29 +1893,32 @@ void CGameHandler::buyArtifact( ui32 hid, si32 aid )
|| getResource(hero->getOwner(),6)<500 && complain("Cannot buy a spellbook, not enough gold!")
|| hero->getArt(17) && complain("Cannot buy a spellbook, hero already has a one!")
)
return;
return false;
giveResource(hero->getOwner(),6,-500);
giveHeroArtifact(0,hid,17);
giveSpells(town,hero);
return true;
}
else if(aid < 7 && aid > 3) //war machine
{
int price = VLC->arth->artifacts[aid].price;
if(vstd::contains(hero->artifWorn,ui16(9+aid)) //hero already has this machine
|| !vstd::contains(town->builtBuildings,si32(16)) //no blackismith
|| gs->getPlayer(hero->getOwner())->resources[6] < price //no gold
|| town->town->warMachine!= aid ) //this machine is not available here (//TODO: support ballista yard in stronghold)
if(vstd::contains(hero->artifWorn,ui16(9+aid)) && complain("Hero already has this machine!")
|| !vstd::contains(town->builtBuildings,si32(16)) && complain("No blackismith!")
|| gs->getPlayer(hero->getOwner())->resources[6] < price && complain("Not enough gold!") //no gold
|| town->town->warMachine!= aid && complain("This machine is unavailale here!") ) //TODO: ballista yard in Stronghold
{
return;
return false;
}
giveResource(hero->getOwner(),6,-price);
giveHeroArtifact(aid,hid,9+aid);
return true;
}
return false;
}
void CGameHandler::tradeResources( ui32 val, ui8 player, ui32 id1, ui32 id2 )
bool CGameHandler::tradeResources( ui32 val, ui8 player, ui32 id1, ui32 id2 )
{
val = std::min(si32(val),gs->getPlayer(player)->resources[id1]);
double uzysk = (double)gs->resVals[id1] * val * gs->getMarketEfficiency(player);
@ -1880,22 +1932,25 @@ void CGameHandler::tradeResources( ui32 val, ui8 player, ui32 id1, ui32 id2 )
sr.resid = id2;
sr.val = gs->getPlayer(player)->resources[id2] + (int)uzysk;
sendAndApply(&sr);
return true;
}
void CGameHandler::setFormation( si32 hid, ui8 formation )
bool CGameHandler::setFormation( si32 hid, ui8 formation )
{
gs->getHero(hid)->army.formation = formation;
return true;
}
void CGameHandler::hireHero( ui32 tid, ui8 hid )
bool CGameHandler::hireHero( ui32 tid, ui8 hid )
{
CGTownInstance *t = gs->getTown(tid);
if(!vstd::contains(t->builtBuildings,5) //no tavern in the town
|| gs->getPlayer(t->tempOwner)->resources[6]<2500 //not enough gold
|| t->visitingHero //there is visiting hero - no place
if(!vstd::contains(t->builtBuildings,5) && complain("No tavern!")
|| gs->getPlayer(t->tempOwner)->resources[6]<2500 && complain("Not enough gold for buying hero!")
|| t->visitingHero && complain("There is visiting hero - no place!")
|| getHeroCount(t->tempOwner,false) >= 8 && complain("Cannot hire hero, only 8 wandering heroes are allowed!")
)
return;
return false;
CGHeroInstance *nh = gs->getPlayer(t->tempOwner)->availableHeroes[hid];
HeroRecruited hr;
@ -1919,9 +1974,10 @@ void CGameHandler::hireHero( ui32 tid, ui8 hid )
sendAndApply(&sr);
giveSpells(t,nh);
return true;
}
void CGameHandler::queryReply( ui32 qid, ui32 answer )
bool CGameHandler::queryReply( ui32 qid, ui32 answer )
{
boost::unique_lock<boost::recursive_mutex> lock(gsm);
if(vstd::contains(callbacks,qid))
@ -1941,11 +1997,14 @@ void CGameHandler::queryReply( ui32 qid, ui32 answer )
else
{
tlog1 << "Unknown query reply...\n";
return false;
}
return true;
}
void CGameHandler::makeBattleAction( BattleAction &ba )
bool CGameHandler::makeBattleAction( BattleAction &ba )
{
bool ok = true;
switch(ba.actionType)
{
case 2: //walk
@ -1985,11 +2044,13 @@ void CGameHandler::makeBattleAction( BattleAction &ba )
if(curStack->position != ba.destinationTile) //we wasn't able to reach destination tile
{
tlog3<<"We cannot move this stack to its destination "<<curStack->creature->namePl<<std::endl;
ok = false;
}
if(!stackAtEnd)
{
tlog3 << "There is no stack on " << ba.additionalInfo << " tile (no attack)!";
ok = false;
break;
}
@ -2010,7 +2071,7 @@ void CGameHandler::makeBattleAction( BattleAction &ba )
{
tlog3 << "Attack cannot be performed!";
sendAndApply(&EndAction());
break;
ok = false;
}
//attack
@ -2080,6 +2141,7 @@ void CGameHandler::makeBattleAction( BattleAction &ba )
}
}
battleMadeAction.setn(true);
return ok;
}
void CGameHandler::playerMessage( ui8 player, const std::string &message )
@ -2182,7 +2244,7 @@ void CGameHandler::playerMessage( ui8 player, const std::string &message )
}
}
void CGameHandler::makeCustomAction( BattleAction &ba )
bool CGameHandler::makeCustomAction( BattleAction &ba )
{
switch(ba.actionType)
{
@ -2192,12 +2254,12 @@ void CGameHandler::makeCustomAction( BattleAction &ba )
if(!h)
{
tlog2 << "Wrong caster!\n";
return;
return false;
}
if(ba.additionalInfo >= VLC->spellh->spells.size())
{
tlog2 << "Wrong spell id (" << ba.additionalInfo << ")!\n";
return;
return false;
}
CSpell *s = &VLC->spellh->spells[ba.additionalInfo];
@ -2210,7 +2272,7 @@ void CGameHandler::makeCustomAction( BattleAction &ba )
)
{
tlog2 << "Spell cannot be casted!\n";
return;
return false;
}
sendAndApply(&StartAction(ba)); //start spell casting
@ -2343,8 +2405,10 @@ void CGameHandler::makeCustomAction( BattleAction &ba )
}
}
sendAndApply(&EndAction());
return true;
}
}
return false;
}
void CGameHandler::handleTimeEvents()

View File

@ -103,7 +103,7 @@ public:
//do sth
void changeSpells(int hid, bool give, const std::set<ui32> &spells);
void removeObject(int objid);
bool removeObject(int objid);
void setBlockVis(int objid, bool bv);
void setOwner(int objid, ui8 owner);
void setHoverName(int objid, MetaString * name);
@ -124,7 +124,7 @@ public:
void startBattleI(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb); //use hero=NULL for no hero
void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb); //for hero<=>neutral army
void setAmount(int objid, ui32 val);
void moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255);
bool moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255);
void giveHeroBonus(GiveBonus * bonus);
void setMovePoints(SetMovePoints * smp);
void setManaPoints(int hid, int val);
@ -137,20 +137,20 @@ public:
int getPlayerAt(CConnection *c) const;
void playerMessage( ui8 player, const std::string &message);
void makeBattleAction(BattleAction &ba);
void makeCustomAction(BattleAction &ba);
void queryReply( ui32 qid, ui32 answer );
void hireHero( ui32 tid, ui8 hid );
void setFormation( si32 hid, ui8 formation );
void tradeResources( ui32 val, ui8 player, ui32 id1, ui32 id2 );
void buyArtifact( ui32 hid, si32 aid );
void swapArtifacts( si32 hid1, si32 hid2, ui16 slot1, ui16 slot2 );
void garrisonSwap(si32 tid);
void upgradeCreature( ui32 objid, ui8 pos, ui32 upgID );
void recruitCreatures(si32 objid, ui32 crid, ui32 cram);
void buildStructure(si32 tid, si32 bid);
void disbandCreature( si32 id, ui8 pos );
void arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2, si32 val );
bool makeBattleAction(BattleAction &ba);
bool makeCustomAction(BattleAction &ba);
bool queryReply( ui32 qid, ui32 answer );
bool hireHero( ui32 tid, ui8 hid );
bool setFormation( si32 hid, ui8 formation );
bool tradeResources( ui32 val, ui8 player, ui32 id1, ui32 id2 );
bool buyArtifact( ui32 hid, si32 aid );
bool swapArtifacts( si32 hid1, si32 hid2, ui16 slot1, ui16 slot2 );
bool garrisonSwap(si32 tid);
bool upgradeCreature( ui32 objid, ui8 pos, ui32 upgID );
bool recruitCreatures(si32 objid, ui32 crid, ui32 cram);
bool buildStructure(si32 tid, si32 bid);
bool disbandCreature( si32 id, ui8 pos );
bool arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2, si32 val );
void save(const std::string &fname);
void close();
void handleTimeEvents();

View File

@ -5,7 +5,7 @@
#define PLAYER_OWNS(id) (gh->getPlayerAt(c)==gh->getOwner(id))
#define ERROR_AND_RETURN {if(c) *c << &SystemMessage("You are not allowed to perform this action!"); \
tlog1<<"Player is not allowed to perform this action!\n"; \
return;}
return false;}
#define ERROR_IF_NOT_OWNS(id) if(!PLAYER_OWNS(id)) ERROR_AND_RETURN
/*
@ -23,128 +23,136 @@ CGameState* CPackForServer::GS(CGameHandler *gh)
return gh->gs;
}
void SaveGame::applyGh( CGameHandler *gh )
bool SaveGame::applyGh( CGameHandler *gh )
{
gh->sendMessageTo(*c,"Saving...");
gh->save(fname);
gh->sendMessageTo(*c,"Game has been succesfully saved!");
return true;
}
void CloseServer::applyGh( CGameHandler *gh )
bool CloseServer::applyGh( CGameHandler *gh )
{
gh->close();
return true;
}
void EndTurn::applyGh( CGameHandler *gh )
bool EndTurn::applyGh( CGameHandler *gh )
{
gh->states.setFlag(GS(gh)->currentPlayer,&PlayerStatus::makingTurn,false);
return true;
}
void DismissHero::applyGh( CGameHandler *gh )
bool DismissHero::applyGh( CGameHandler *gh )
{
ERROR_IF_NOT_OWNS(hid);
gh->removeObject(hid);
return gh->removeObject(hid);
}
void MoveHero::applyGh( CGameHandler *gh )
bool MoveHero::applyGh( CGameHandler *gh )
{
ERROR_IF_NOT_OWNS(hid);
gh->moveHero(hid,dest,0,gh->getPlayerAt(c));
return gh->moveHero(hid,dest,0,gh->getPlayerAt(c));
}
void ArrangeStacks::applyGh( CGameHandler *gh )
bool ArrangeStacks::applyGh( CGameHandler *gh )
{
//ERROR_IF_NOT_OWNS(id1);
//ERROR_IF_NOT_OWNS(id2);
gh->arrangeStacks(id1,id2,what,p1,p2,val);
//checks for owning in the gh func
return gh->arrangeStacks(id1,id2,what,p1,p2,val);
}
void DisbandCreature::applyGh( CGameHandler *gh )
bool DisbandCreature::applyGh( CGameHandler *gh )
{
ERROR_IF_NOT_OWNS(id);
gh->disbandCreature(id,pos);
return gh->disbandCreature(id,pos);
}
void BuildStructure::applyGh( CGameHandler *gh )
bool BuildStructure::applyGh( CGameHandler *gh )
{
ERROR_IF_NOT_OWNS(tid);
gh->buildStructure(tid,bid);
return gh->buildStructure(tid,bid);
}
void RecruitCreatures::applyGh( CGameHandler *gh )
bool RecruitCreatures::applyGh( CGameHandler *gh )
{
ERROR_IF_NOT_OWNS(tid);
gh->recruitCreatures(tid,crid,amount);
return gh->recruitCreatures(tid,crid,amount);
}
void UpgradeCreature::applyGh( CGameHandler *gh )
bool UpgradeCreature::applyGh( CGameHandler *gh )
{
ERROR_IF_NOT_OWNS(id);
gh->upgradeCreature(id,pos,cid);
return gh->upgradeCreature(id,pos,cid);
}
void GarrisonHeroSwap::applyGh( CGameHandler *gh )
bool GarrisonHeroSwap::applyGh( CGameHandler *gh )
{
ERROR_IF_NOT_OWNS(tid);
gh->garrisonSwap(tid);
return gh->garrisonSwap(tid);
}
void ExchangeArtifacts::applyGh( CGameHandler *gh )
bool ExchangeArtifacts::applyGh( CGameHandler *gh )
{
ERROR_IF_NOT_OWNS(hid1);
ERROR_IF_NOT_OWNS(hid2);
gh->swapArtifacts(hid1,hid2,slot1,slot2);
return gh->swapArtifacts(hid1,hid2,slot1,slot2);
}
void BuyArtifact::applyGh( CGameHandler *gh )
bool BuyArtifact::applyGh( CGameHandler *gh )
{
ERROR_IF_NOT_OWNS(hid);
gh->buyArtifact(hid,aid);
return gh->buyArtifact(hid,aid);
}
void TradeOnMarketplace::applyGh( CGameHandler *gh )
bool TradeOnMarketplace::applyGh( CGameHandler *gh )
{
if(gh->getPlayerAt(c) != player) ERROR_AND_RETURN;
gh->tradeResources(val,player,r1,r2);
return gh->tradeResources(val,player,r1,r2);
}
void SetFormation::applyGh( CGameHandler *gh )
bool SetFormation::applyGh( CGameHandler *gh )
{
ERROR_IF_NOT_OWNS(hid);
gh->setFormation(hid,formation);
return gh->setFormation(hid,formation);
}
void HireHero::applyGh( CGameHandler *gh )
bool HireHero::applyGh( CGameHandler *gh )
{
ERROR_IF_NOT_OWNS(tid);
gh->hireHero(tid,hid);
return gh->hireHero(tid,hid);
}
void QueryReply::applyGh( CGameHandler *gh )
bool QueryReply::applyGh( CGameHandler *gh )
{
gh->queryReply(qid,answer);
//TODO - check if player matches the query
return gh->queryReply(qid,answer);
}
void MakeAction::applyGh( CGameHandler *gh )
bool MakeAction::applyGh( CGameHandler *gh )
{
if(!GS(gh)->curB) ERROR_AND_RETURN;
if(gh->connections[GS(gh)->curB->getStack(GS(gh)->curB->activeStack)->owner] != c) ERROR_AND_RETURN;
gh->makeBattleAction(ba);
return gh->makeBattleAction(ba);
}
void MakeCustomAction::applyGh( CGameHandler *gh )
bool MakeCustomAction::applyGh( CGameHandler *gh )
{
if(!GS(gh)->curB) ERROR_AND_RETURN;
if(gh->connections[GS(gh)->curB->getStack(GS(gh)->curB->activeStack)->owner] != c) ERROR_AND_RETURN;
gh->makeCustomAction(ba);
return gh->makeCustomAction(ba);
}
void PlayerMessage::applyGh( CGameHandler *gh )
bool PlayerMessage::applyGh( CGameHandler *gh )
{
if(gh->getPlayerAt(c) != player) ERROR_AND_RETURN;
gh->playerMessage(player,text);
return true;
}
void SetSelection::applyGh( CGameHandler *gh )
bool SetSelection::applyGh( CGameHandler *gh )
{
if(gh->getPlayerAt(c) != player) ERROR_AND_RETURN;
if(!gh->getObj(id)) ERROR_AND_RETURN;
gh->sendAndApply(this);
return true;
}