1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-08-13 19:54:17 +02:00

New files for lib:

* lib/ERMScriptModule.cpp
* lib/ERMScriptModule.h
* lib/CObstacleInstance.h

More jugglery with callbacks. Moving stuff from CGameState to CGameInfoCallback. Work on unified game events interface for player (AI or GUI) and script module. Directing events to ERM interpretetr, first attempts of calling some triggers. Crashy, if there any scripts.
Some other changes, including fighting amount of includes in includes and tracking of hero visits (need further work).
This commit is contained in:
Michał W. Urbańczyk
2011-05-09 22:20:47 +00:00
parent 743df272e4
commit 617e1f962e
33 changed files with 466 additions and 409 deletions

View File

@@ -9,6 +9,7 @@
#include "../../lib/VCMI_Lib.h"
#include "../../lib/NetPacks.h"
#include "AIPriorities.h"
#include "../../lib/CGameState.h"
using std::endl;
using geniusai::CGeniusAI;

View File

@@ -170,10 +170,10 @@ void CStupidAI::battleEnd(const BattleResult *br)
print("battleEnd called");
}
void CStupidAI::battleResultsApplied()
{
print("battleResultsApplied called");
}
// void CStupidAI::battleResultsApplied()
// {
// print("battleResultsApplied called");
// }
void CStupidAI::battleNewRoundFirst(int round)
{

View File

@@ -18,7 +18,7 @@ public:
void battleAttack(const BattleAttack *ba) OVERRIDE; //called when stack is performing attack
void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa) OVERRIDE; //called when stack receives damage (after battleAttack())
void battleEnd(const BattleResult *br) OVERRIDE;
void battleResultsApplied() OVERRIDE; //called when all effects of last battle are applied
//void battleResultsApplied() OVERRIDE; //called when all effects of last battle are applied
void battleNewRoundFirst(int round) OVERRIDE; //called at the beginning of each turn before changes are applied;
void battleNewRound(int round) OVERRIDE; //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
void battleStackMoved(const CStack * stack, THex dest, int distance, bool end) OVERRIDE;

View File

@@ -47,10 +47,6 @@ public:
class IGameActionCallback
{
// IGameActionCallback(CGameState * GS, int Player);
// bool isVisible(int3 pos, int Player) const;
// bool isVisible(const CGObjectInstance *obj, int Player) const;
// virtual bool hasAccess(int playerId) const;
public:
//hero
virtual bool moveHero(const CGHeroInstance *h, int3 dst) =0; //dst must be free, neighbouring tile (this function can move hero only by one tile)

View File

@@ -5,6 +5,7 @@
#include <vector>
#include "lib/BattleAction.h"
#include "client/FunctionList.h"
#include "lib/IGameEventsReceiver.h"
/*
* CGameInterface.h, part of VCMI engine
@@ -54,7 +55,7 @@ template <typename Serializer> class CISer;
template <typename Serializer> class COSer;
struct ArtifactLocation;
class CBattleGameInterface
class CBattleGameInterface : public IBattleEventsReceiver
{
public:
bool human;
@@ -62,90 +63,21 @@ public:
std::string dllName;
virtual ~CBattleGameInterface() {};
virtual void init(CBattleCallback * CB){};
//battle call-ins
virtual void actionFinished(const BattleAction *action){};//occurs AFTER every action taken by any stack or by the hero
virtual void actionStarted(const BattleAction *action){};//occurs BEFORE every action taken by any stack or by the hero
virtual BattleAction activeStack(const CStack * stack)=0; //called when it's turn of that stack
virtual void battleAttack(const BattleAttack *ba){}; //called when stack is performing attack
virtual void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa){}; //called when stack receives damage (after battleAttack())
virtual void battleEnd(const BattleResult *br){};
virtual void battleResultsApplied(){}; //called when all effects of last battle are applied
virtual void battleNewRoundFirst(int round){}; //called at the beginning of each turn before changes are applied;
virtual void battleNewRound(int round){}; //called at the beginning of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
virtual void battleStackMoved(const CStack * stack, THex dest, int distance, bool end){};
virtual void battleSpellCast(const BattleSpellCast *sc){};
virtual void battleStacksEffectsSet(const SetStackEffect & sse){};//called when a specific effect is set to stacks
virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side){}; //called by engine when battle starts; side=0 - left, side=1 - right
virtual void battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, si32 lifeDrainFrom){}; //called when stacks are healed / resurrected first element of pair - stack id, second - healed hp
virtual void battleNewStackAppeared(const CStack * stack){}; //not called at the beginning of a battle or by resurrection; called eg. when elemental is summoned
virtual void battleObstaclesRemoved(const std::set<si32> & removedObstacles){}; //called when a certain set of obstacles is removed from batlefield; IDs of them are given
virtual void battleCatapultAttacked(const CatapultAttack & ca){}; //called when catapult makes an attack
virtual void battleStacksRemoved(const BattleStacksRemoved & bsr){}; //called when certain stack is completely removed from battlefield
};
/// Central class for managing human player / AI interface logic
class CGameInterface : public CBattleGameInterface
class CGameInterface : public CBattleGameInterface, public IGameEventsReceiver
{
public:
virtual void buildChanged(const CGTownInstance *town, int buildingID, int what){}; //what: 1 - built, 2 - demolished
//garrison operations
virtual void stackChagedCount(const StackLocation &location, const TQuantity &change, bool isAbsolute){}; //if absolute, change is the new count; otherwise count was modified by adding change
virtual void stackChangedType(const StackLocation &location, const CCreature &newType){}; //used eg. when upgrading creatures
virtual void stacksErased(const StackLocation &location){}; //stack removed from previously filled slot
virtual void stacksSwapped(const StackLocation &loc1, const StackLocation &loc2){};
virtual void newStackInserted(const StackLocation &location, const CStackInstance &stack){}; //new stack inserted at given (previously empty position)
virtual void stacksRebalanced(const StackLocation &src, const StackLocation &dst, TQuantity count){}; //moves creatures from src stack to dst slot, may be used for merging/splittint/moving stacks
//virtual void garrisonChanged(const CGObjectInstance * obj){};
//artifacts operations
virtual void artifactPut(const ArtifactLocation &al){};
virtual void artifactRemoved(const ArtifactLocation &al){};
virtual void artifactAssembled(const ArtifactLocation &al){};
virtual void artifactDisassembled(const ArtifactLocation &al){};
virtual void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst){};
virtual void heroCreated(const CGHeroInstance*){};
virtual void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback)=0; //pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id
virtual void heroInGarrisonChange(const CGTownInstance *town){};
//virtual void heroKilled(const CGHeroInstance*){};
virtual void heroMoved(const TryMoveHero & details){};
virtual void heroPrimarySkillChanged(const CGHeroInstance * hero, int which, si64 val){};
virtual void heroSecondarySkillChanged(const CGHeroInstance * hero, int which, int val){};
virtual void heroManaPointsChanged(const CGHeroInstance * hero){} //not called at the beginning of turn and after spell casts
virtual void heroMovePointsChanged(const CGHeroInstance * hero){} //not called at the beginning of turn and after movement
virtual void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town){};
virtual void init(CCallback * CB){};
virtual void receivedResource(int type, int val){};
virtual void showInfoDialog(const std::string &text, const std::vector<Component*> &components, int soundID){};
virtual void showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level){}
virtual void showShipyardDialog(const IShipyard *obj){} //obj may be town or shipyard; state: 0 - can buid, 1 - lack of resources, 2 - dest tile is blocked, 3 - no water
virtual void yourTurn(){};
virtual void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback)=0; //pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id
virtual void showBlockingDialog(const std::string &text, const std::vector<Component> &components, ui32 askID, const int soundID, bool selection, bool cancel) = 0; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID.
virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, boost::function<void()> &onEnd) = 0; //all stacks operations between these objects become allowed, interface has to call onEnd when done
virtual void showPuzzleMap(){};
virtual void showMarketWindow(const IMarket *market, const CGHeroInstance *visitor){};
virtual void showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor){};
virtual void showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor){};
virtual void showTavernWindow(const CGObjectInstance *townOrTavern){};
virtual void advmapSpellCast(const CGHeroInstance * caster, int spellID){}; //called when a hero casts a spell
virtual void tileHidden(const boost::unordered_set<int3, ShashInt3> &pos){};
virtual void tileRevealed(const boost::unordered_set<int3, ShashInt3> &pos){};
virtual void newObject(const CGObjectInstance * obj){}; //eg. ship built in shipyard
virtual void availableArtifactsChanged(const CGBlackMarket *bm = NULL){}; //bm may be NULL, then artifacts are changed in the global pool (used by merchants in towns)
virtual void yourTurn(){};
virtual void centerView (int3 pos, int focusTime){};
virtual void availableCreaturesChanged(const CGDwelling *town){};
virtual void heroBonusChanged(const CGHeroInstance *hero, const Bonus &bonus, bool gain){};//if gain hero received bonus, else he lost it
virtual void playerBonusChanged(const Bonus &bonus, bool gain){};//if gain hero received bonus, else he lost it
virtual void requestRealized(PackageApplied *pa){};
virtual void heroExchangeStarted(si32 hero1, si32 hero2){};
virtual void objectPropertyChanged(const SetObjectProperty * sop){}; //eg. mine has been flagged
virtual void objectRemoved(const CGObjectInstance *obj){}; //eg. collected resource, picked artifact, beaten hero
virtual void playerBlocked(int reason){}; //reason: 0 - upcoming battle
virtual void gameOver(ui8 player, bool victory){}; //player lost or won the game
virtual void serialize(COSer<CSaveFile> &h, const int version){}; //saving
virtual void serialize(CISer<CLoadFile> &h, const int version){}; //loading
};

View File

@@ -31,6 +31,7 @@
#include "../lib/CSpellHandler.h"
#include <boost/foreach.hpp>
#include "CSoundBase.h"
#include "../lib/CGameState.h"
#ifdef _MSC_VER
#pragma warning (disable : 4355)
@@ -193,7 +194,7 @@ void CMinimap::initMap(int level)
{
int mx=(mapSizes.x*x)/pos.w;
int my=(mapSizes.y*y)/pos.h;
const TerrainTile * tile = LOCPLINT->cb->getTileInfo(int3(mx, my, i));
const TerrainTile * tile = LOCPLINT->cb->getTile(int3(mx, my, i), false);
if(tile)
{
if (tile->blocked && (!tile->visitable))
@@ -342,7 +343,7 @@ void CMinimap::showTile(const int3 &pos)
if ((pos.x*wo+ii<this->pos.w) && (pos.y*ho+jj<this->pos.h))
CSDL_Ext::SDL_PutPixelWithoutRefresh(FoW[pos.z],pos.x*wo+ii,pos.y*ho+jj,0,0,0,0);
const TerrainTile * tile = LOCPLINT->cb->getTileInfo(pos);
const TerrainTile * tile = LOCPLINT->cb->getTile(pos, false);
if(tile)
{
if (tile->blocked && (!tile->visitable))
@@ -1776,14 +1777,14 @@ void CAdvMapInt::tileLClicked(const int3 &mp)
std::vector < const CGObjectInstance * > bobjs = LOCPLINT->cb->getBlockingObjs(mp), //blocking objects at tile
vobjs = LOCPLINT->cb->getVisitableObjs(mp); //visitable objects
const TerrainTile *tile = LOCPLINT->cb->getTileInfo(mp);
const TerrainTile *tile = LOCPLINT->cb->getTile(mp);
const CGObjectInstance *topBlocking = bobjs.size() ? bobjs.back() : NULL;
int3 selPos = selection->getSightCenter();
if(spellBeingCasted && isInScreenRange(selPos, mp))
{
const TerrainTile *heroTile = LOCPLINT->cb->getTileInfo(selPos);
const TerrainTile *heroTile = LOCPLINT->cb->getTile(selPos);
switch(spellBeingCasted->id)
{
@@ -1898,9 +1899,9 @@ void CAdvMapInt::tileHovered(const int3 &tile)
return;
case Spells::DIMENSION_DOOR:
{
const TerrainTile *t = LOCPLINT->cb->getTileInfo(tile);
const TerrainTile *t = LOCPLINT->cb->getTile(tile, false);
int3 hpos = selection->getSightCenter();
if((!t || t->isClear(LOCPLINT->cb->getTileInfo(hpos))) && isInScreenRange(hpos, tile))
if((!t || t->isClear(LOCPLINT->cb->getTile(hpos))) && isInScreenRange(hpos, tile))
CCS->curh->changeGraphic(0, 41);
else
CCS->curh->changeGraphic(0, 0);
@@ -2023,7 +2024,7 @@ void CAdvMapInt::tileHovered(const int3 &tile)
} else {
if(pnode->land)
{
if(LOCPLINT->cb->getTileInfo(h->getPosition(false))->tertype != TerrainTile::water)
if(LOCPLINT->cb->getTile(h->getPosition(false))->tertype != TerrainTile::water)
CCS->curh->changeGraphic(0, 4 + turns*6);
else
CCS->curh->changeGraphic(0, 7 + turns*6); //anchor
@@ -2060,7 +2061,7 @@ void CAdvMapInt::tileRClicked(const int3 &mp)
if(!objs.size())
{
// Bare or undiscovered terrain
const TerrainTile * tile = LOCPLINT->cb->getTileInfo(mp);
const TerrainTile * tile = LOCPLINT->cb->getTile(mp);
if (tile)
{
std::string hlp;

View File

@@ -21,6 +21,7 @@
#include <boost/format.hpp>
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include "../lib/CGameState.h"
using namespace CSDL_Ext;

View File

@@ -1,5 +1,6 @@
#ifndef __CHEROWINDOW_H__
#define __CHEROWINDOW_H__
#include "..\lib\HeroBonus.h"
//#include "CPlayerInterface.h"

View File

@@ -44,6 +44,7 @@
#include <boost/filesystem.hpp>
#include "../StartInfo.h"
#include <boost/foreach.hpp>
#include "../lib/CGameState.h"
#ifdef min
#undef min
@@ -1058,7 +1059,7 @@ bool CPlayerInterface::moveHero( const CGHeroInstance *h, CGPath path )
enum TerrainTile::EterrainType newTerrain;
int sh = -1;
const TerrainTile * curTile = cb->getTileInfo(CGHeroInstance::convertPosition(h->pos, false));
const TerrainTile * curTile = cb->getTile(CGHeroInstance::convertPosition(h->pos, false));
for(int i=path.nodes.size()-1; i>0 && (stillMoveHero.data == CONTINUE_MOVE || curTile->blocked); i--)
{
@@ -1076,7 +1077,7 @@ bool CPlayerInterface::moveHero( const CGHeroInstance *h, CGPath path )
sh = CCS->soundh->playSound(soundBase::horseFlying, -1);
#endif
{
newTerrain = cb->getTileInfo(CGHeroInstance::convertPosition(path.nodes[i].coord, false))->tertype;
newTerrain = cb->getTile(CGHeroInstance::convertPosition(path.nodes[i].coord, false))->tertype;
if (newTerrain != currentTerrain) {
CCS->soundh->stopSound(sh);
@@ -2009,11 +2010,11 @@ void CPlayerInterface::tryDiggging(const CGHeroInstance *h)
std::string hlp;
if(h->movement < h->maxMovePoints(true))
showInfoDialog(CGI->generaltexth->allTexts[56]); //"Digging for artifacts requires a whole day, try again tomorrow."
else if(cb->getTileInfo(h->getPosition(false))->tertype == TerrainTile::water)
else if(cb->getTile(h->getPosition(false))->tertype == TerrainTile::water)
showInfoDialog(CGI->generaltexth->allTexts[60]); //Try looking on land!
else
{
const TerrainTile *t = cb->getTileInfo(h->getPosition());
const TerrainTile *t = cb->getTile(h->getPosition());
CGI->mh->getTerrainDescr(h->getPosition(false), hlp, false);
if(hlp.length() || t->blockingObjects.size() > 1)
showInfoDialog(CGI->generaltexth->allTexts[97]); //Try searching on clear ground.

View File

@@ -33,9 +33,11 @@
#include "CPreGame.h"
#include "CBattleInterface.h"
#include "../CThreadHelper.h"
#include "../lib/ERMScriptModule.h"
#define NOT_LIB
#include "../lib/RegisterTypes.cpp"
extern std::string NAME;
namespace intpr = boost::interprocess;
@@ -300,19 +302,6 @@ void CClient::loadGame( const std::string & fname )
}
}
int CClient::getCurrentPlayer()
{
return gs->currentPlayer;
}
int CClient::getSelectedHero()
{
if(const CGHeroInstance *selHero = IGameCallback::getSelectedHero(getCurrentPlayer()))
return selHero->id;
else
return -1;
}
void CClient::newGame( CConnection *con, StartInfo *si )
{
enum {SINGLE, HOST, GUEST} networkMode = SINGLE;
@@ -436,7 +425,10 @@ void CClient::newGame( CConnection *con, StartInfo *si )
serv->addStdVecItems(const_cast<CGameInfo*>(CGI)->state);
hotSeat = (humanPlayers > 1);
CERMScriptModule *erm = new CERMScriptModule();
privilagedGameEventReceivers.push_back(erm);
privilagedBattleEventReceivers.push_back(erm);
erm->init();
}
template <typename Handler>

View File

@@ -18,6 +18,8 @@
*
*/
class IGameEventsReceiver;
class IBattleEventsReceiver;
class CBattleGameInterface;
struct StartInfo;
class CGameState;
@@ -62,6 +64,8 @@ class CClient : public IGameCallback
public:
CCallback *cb;
std::set<CCallback*> callbacks; //callbacks given to player interfaces
std::vector<IGameEventsReceiver*> privilagedGameEventReceivers; //scripting modules, spectator interfaces
std::vector<IBattleEventsReceiver*> privilagedBattleEventReceivers; //scripting modules, spectator interfaces
std::map<ui8,CGameInterface *> playerint;
std::map<ui8,CBattleGameInterface *> battleints;
bool hotSeat;
@@ -96,10 +100,6 @@ public:
boost::thread *connectionHandler; //thread running run() method
//////////////////////////////////////////////////////////////////////////
//from IGameCallback
int getCurrentPlayer();
int getSelectedHero();
//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) OVERRIDE {};
bool removeObject(int objid) OVERRIDE {return false;};
@@ -116,8 +116,8 @@ public:
void showThievesGuildWindow(int requestingObjId) OVERRIDE {};
void giveResource(int player, int which, int val) OVERRIDE {};
void giveCreatures (const CArmedInstance * objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) OVERRIDE {};
void takeCreatures (int objid, std::vector<CStackBasicDescriptor> creatures) OVERRIDE {};
void giveCreatures(const CArmedInstance * objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) OVERRIDE {};
void takeCreatures(int objid, const std::vector<CStackBasicDescriptor> &creatures) OVERRIDE {};
bool changeStackType(const StackLocation &sl, CCreature *c) OVERRIDE {return false;};
bool changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false) OVERRIDE {return false;};
bool insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count) OVERRIDE {return false;};

View File

@@ -52,6 +52,7 @@
#include "../lib/CCreatureHandler.h"
#include "CMusicHandler.h"
#include "../lib/BattleState.h"
#include "../lib/CGameState.h"
/*
* GUIClasses.cpp, part of VCMI engine

View File

@@ -22,6 +22,7 @@
#include "CBitmapHandler.h"
#include "../lib/CObjectHandler.h"
#include "../lib/CDefObjInfoHandler.h"
#include "../lib/CGameState.h"
using namespace boost::assign;
using namespace CSDL_Ext;

View File

@@ -28,18 +28,48 @@
//macro to avoid code duplication - calls given method with given arguments if interface for specific player is present
#define INTERFACE_CALL_IF_PRESENT(player,function,...) \
if(vstd::contains(cl->playerint,player)) \
cl->playerint[player]->function(__VA_ARGS__);
#define CALL_ONLY_THAT_INTERFACE(player, function, ...) \
do \
{ \
if(vstd::contains(cl->playerint,player)) \
cl->playerint[player]->function(__VA_ARGS__); \
}while(0)
#define INTERFACE_CALL_IF_PRESENT(player,function,...) \
do \
{ \
CALL_ONLY_THAT_INTERFACE(player, function, __VA_ARGS__);\
BOOST_FOREACH(IGameEventsReceiver *ger, cl->privilagedGameEventReceivers)\
ger->function(__VA_ARGS__); \
} while(0)
#define CALL_ONLY_THT_BATTLE_INTERFACE(player,function,...) \
do \
{ \
if(vstd::contains(cl->battleints,player)) \
cl->battleints[player]->function(__VA_ARGS__); \
} while (0);
#define BATTLE_INTERFACE_CALL_RECEIVERS(function,...) \
do \
{ \
BOOST_FOREACH(IBattleEventsReceiver *ber, cl->privilagedBattleEventReceivers)\
ber->function(__VA_ARGS__); \
} while(0)
#define BATTLE_INTERFACE_CALL_IF_PRESENT(player,function,...) \
if(vstd::contains(cl->battleints,player)) \
cl->battleints[player]->function(__VA_ARGS__);
do \
{ \
CALL_ONLY_THAT_INTERFACE(player, function, __VA_ARGS__);\
BATTLE_INTERFACE_CALL_RECEIVERS(function, __VA_ARGS__); \
} while(0)
#define BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(function,...) \
BATTLE_INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->sides[0], function, __VA_ARGS__) \
BATTLE_INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->sides[1], function, __VA_ARGS__) \
BATTLE_INTERFACE_CALL_IF_PRESENT(254, function, __VA_ARGS__)
#define BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(function,...) \
CALL_ONLY_THT_BATTLE_INTERFACE(GS(cl)->curB->sides[0], function, __VA_ARGS__) \
CALL_ONLY_THT_BATTLE_INTERFACE(GS(cl)->curB->sides[1], function, __VA_ARGS__) \
BATTLE_INTERFACE_CALL_RECEIVERS(function, __VA_ARGS__)
/*
* NetPacksClient.cpp, part of VCMI engine
*
@@ -62,7 +92,7 @@ void SetResource::applyCl( CClient *cl )
void SetPrimSkill::applyCl( CClient *cl )
{
const CGHeroInstance *h = GS(cl)->getHero(id);
const CGHeroInstance *h = cl->getHero(id);
if(!h)
{
tlog1 << "Cannot find hero with ID " << id << std::endl;
@@ -73,7 +103,7 @@ void SetPrimSkill::applyCl( CClient *cl )
void SetSecSkill::applyCl( CClient *cl )
{
const CGHeroInstance *h = GS(cl)->getHero(id);
const CGHeroInstance *h = cl->getHero(id);
if(!h)
{
tlog1 << "Cannot find hero with ID " << id << std::endl;
@@ -84,9 +114,11 @@ void SetSecSkill::applyCl( CClient *cl )
void HeroVisitCastle::applyCl( CClient *cl )
{
if(start() && vstd::contains(cl->playerint,GS(cl)->getHero(hid)->tempOwner))
const CGHeroInstance *h = cl->getHero(hid);
if(start())
{
cl->playerint[GS(cl)->getHero(hid)->tempOwner]->heroVisitsTown(GS(cl)->getHero(hid),GS(cl)->getTown(tid));
INTERFACE_CALL_IF_PRESENT(h->tempOwner, heroVisitsTown, h, GS(cl)->getTown(tid));
}
}
@@ -97,33 +129,28 @@ void ChangeSpells::applyCl( CClient *cl )
void SetMana::applyCl( CClient *cl )
{
CGHeroInstance *h = GS(cl)->getHero(hid);
if(vstd::contains(cl->playerint,h->tempOwner))
cl->playerint[h->tempOwner]->heroManaPointsChanged(h);
const CGHeroInstance *h = cl->getHero(hid);
INTERFACE_CALL_IF_PRESENT(h->tempOwner, heroManaPointsChanged, h);
}
void SetMovePoints::applyCl( CClient *cl )
{
CGHeroInstance *h = GS(cl)->getHero(hid);
const CGHeroInstance *h = cl->getHero(hid);
if (cl->IGameCallback::getSelectedHero(LOCPLINT->playerID) == h)//if we have selected that hero
{
GS(cl)->calculatePaths(h, *cl->pathInfo);
}
if(vstd::contains(cl->playerint,h->tempOwner))
cl->playerint[h->tempOwner]->heroMovePointsChanged(h);
INTERFACE_CALL_IF_PRESENT(h->tempOwner, heroMovePointsChanged, h);
}
void FoWChange::applyCl( CClient *cl )
{
if(!vstd::contains(cl->playerint,player))
return;
if(mode)
cl->playerint[player]->tileRevealed(tiles);
INTERFACE_CALL_IF_PRESENT(player, tileRevealed, tiles);
else
cl->playerint[player]->tileHidden(tiles);
INTERFACE_CALL_IF_PRESENT(player, tileHidden, tiles);
cl->updatePaths();
}
@@ -135,24 +162,24 @@ void SetAvailableHeroes::applyCl( CClient *cl )
void ChangeStackCount::applyCl( CClient *cl )
{
INTERFACE_CALL_IF_PRESENT(sl.army->tempOwner,stackChagedCount, sl, count, absoluteValue);
INTERFACE_CALL_IF_PRESENT(sl.army->tempOwner, stackChagedCount, sl, count, absoluteValue);
}
void SetStackType::applyCl( CClient *cl )
{
INTERFACE_CALL_IF_PRESENT(sl.army->tempOwner,stackChangedType,sl, *type);
INTERFACE_CALL_IF_PRESENT(sl.army->tempOwner, stackChangedType, sl, *type);
}
void EraseStack::applyCl( CClient *cl )
{
INTERFACE_CALL_IF_PRESENT(sl.army->tempOwner,stacksErased,sl);
INTERFACE_CALL_IF_PRESENT(sl.army->tempOwner, stacksErased, sl);
}
void SwapStacks::applyCl( CClient *cl )
{
INTERFACE_CALL_IF_PRESENT(sl1.army->tempOwner,stacksSwapped, sl1, sl2);
INTERFACE_CALL_IF_PRESENT(sl1.army->tempOwner, stacksSwapped, sl1, sl2);
if(sl1.army->tempOwner != sl2.army->tempOwner)
INTERFACE_CALL_IF_PRESENT(sl2.army->tempOwner,stacksSwapped, sl1, sl2);
INTERFACE_CALL_IF_PRESENT(sl2.army->tempOwner, stacksSwapped, sl1, sl2);
}
void InsertNewStack::applyCl( CClient *cl )
@@ -194,6 +221,12 @@ void DisassembledArtifact::applyCl( CClient *cl )
INTERFACE_CALL_IF_PRESENT(al.hero->tempOwner, artifactDisassembled, al);
}
void HeroVisit::applyCl( CClient *cl )
{
INTERFACE_CALL_IF_PRESENT(hero->tempOwner, heroVisit, hero, obj, starting);
}
void GiveBonus::applyCl( CClient *cl )
{
switch(who)
@@ -346,13 +379,6 @@ void TryMoveHero::applyCl( CClient *cl )
}
}
// void SetGarrisons::applyCl( CClient *cl )
// {
// for(std::map<ui32,CCreatureSet>::iterator i = garrs.begin(); i!=garrs.end(); i++)
// if(vstd::contains(cl->playerint,cl->getOwner(i->first)))
// cl->playerint[cl->getOwner(i->first)]->garrisonChanged(cl->getObj(i->first));
// }
void NewStructures::applyCl( CClient *cl )
{
CGTownInstance *town = GS(cl)->getTown(tid);
@@ -692,7 +718,7 @@ void PlayerBlocked::applyCl( CClient *cl )
void YourTurn::applyCl( CClient *cl )
{
INTERFACE_CALL_IF_PRESENT(player,yourTurn);
CALL_ONLY_THAT_INTERFACE(player,yourTurn);
}
void SaveGame::applyCl(CClient *cl)

View File

@@ -5,7 +5,7 @@
#include "CCreatureSet.h"
#include "CObjectHandler.h"
#include "CCreatureHandler.h"
#include "CObstacleInstance.h"
#include "ConstTransitivePtr.h"
/*
@@ -25,17 +25,6 @@ class CGTownInstance;
class CStackInstance;
struct BattleStackAttacked;
struct DLL_EXPORT CObstacleInstance
{
int uniqueID;
int ID; //ID of obstacle (defines type of it)
int pos; //position on battlefield
template <typename Handler> void serialize(Handler &h, const int version)
{
h & ID & pos & uniqueID;
}
};
//only for use in BattleInfo
struct DLL_EXPORT SiegeInfo
{

View File

@@ -7,8 +7,6 @@
#include <set>
#include "../lib/HeroBonus.h"
#include "../lib/CGameState.h"
#include "../lib/CCreatureSet.h"
#include "../lib/ConstTransitivePtr.h"
/*
@@ -38,7 +36,7 @@ public:
ui32 ammMin, ammMax;
ui8 level; // 0 - unknown
std::string abilityText; //description of abilities
std::string abilityRefs; //references to abilities, in textformat
std::string abilityRefs; //references to abilities, in text format
std::string animDefName;
si32 idNumber;
si8 faction; //-1 = neutral

View File

@@ -535,34 +535,7 @@ int CGameState::pickHero(int owner)
}
return h;
}
CGHeroInstance *CGameState::getHero(int objid)
{
if(objid<0 || objid>=map->objects.size() || map->objects[objid]->ID!=HEROI_TYPE)
return NULL;
return static_cast<CGHeroInstance *>(map->objects[objid].get());
}
const CGHeroInstance * CGameState::getHero( int objid ) const
{
return (const_cast<CGameState *>(this))->getHero(objid);
}
CGTownInstance *CGameState::getTown(int objid)
{
if(objid<0 || objid>=map->objects.size())
return NULL;
CGObjectInstance *obj = map->objects[objid];
if(obj->ID != TOWNI_TYPE)
return NULL;
return static_cast<CGTownInstance *>(obj);
}
const CGTownInstance * CGameState::getTown( int objid ) const
{
return (const_cast<CGameState *>(this))->getTown(objid);
}
std::pair<int,int> CGameState::pickObject (CGObjectInstance *obj)
{
@@ -810,6 +783,7 @@ int CGameState::getDate(int mode) const
}
CGameState::CGameState()
{
gs = this;
mx = new boost::shared_mutex();
applierGs = new CApplier<CBaseForGSApply>;
registerTypes2(*applierGs);
@@ -1871,152 +1845,12 @@ int CGameState::getMovementCost(const CGHeroInstance *h, const int3 &src, const
return ret;
}
std::set<int> CGameState::getBuildingRequiments(const CGTownInstance *t, int ID)
{
std::set<int> used;
used.insert(ID);
std::set<int> reqs = VLC->townh->requirements[t->subID][ID];
while(true)
{
size_t noloop=0;
for(std::set<int>::iterator i=reqs.begin();i!=reqs.end();i++)
{
if(used.find(*i)==used.end()) //we haven't added requirements for this building
{
used.insert(*i);
for(
std::set<int>::iterator j=VLC->townh->requirements[t->subID][*i].begin();
j!=VLC->townh->requirements[t->subID][*i].end();
j++)
{
reqs.insert(*j);//creating full list of requirements
}
}
else
{
noloop++;
}
}
if(noloop==reqs.size())
break;
}
return reqs;
}
int CGameState::canBuildStructure( const CGTownInstance *t, int ID )
{
int ret = Buildings::ALLOWED;
if(t->builded >= MAX_BUILDING_PER_TURN)
ret = Buildings::CANT_BUILD_TODAY; //building limit
CBuilding * pom = VLC->buildh->buildings[t->subID][ID];
if(!pom)
return Buildings::ERROR;
//checking resources
for(int res=0; res<RESOURCE_QUANTITY; res++)
{
if(pom->resources[res] > getPlayer(t->tempOwner)->resources[res])
ret = Buildings::NO_RESOURCES; //lack of res
}
//checking for requirements
std::set<int> reqs = getBuildingRequiments(t, ID);//getting all requiments
for( std::set<int>::iterator ri = reqs.begin(); ri != reqs.end(); ri++ )
{
if(t->builtBuildings.find(*ri)==t->builtBuildings.end())
ret = Buildings::PREREQUIRES; //lack of requirements - cannot build
}
//can we build it?
if(t->forbiddenBuildings.find(ID)!=t->forbiddenBuildings.end())
ret = Buildings::FORBIDDEN; //forbidden
if(ID == 13) //capitol
{
for(unsigned int in = 0; in < map->towns.size(); in++)
{
if(map->towns[in]->tempOwner==t->tempOwner && vstd::contains(map->towns[in]->builtBuildings,13))
{
ret = Buildings::HAVE_CAPITAL; //no more than one capitol
break;
}
}
}
else if(ID == 6) //shipyard
{
int3 tile = t->bestLocation();
if( !map->isInTheMap(tile) || map->getTile(tile).tertype != TerrainTile::water )
ret = Buildings::NO_WATER; //lack of water
}
if(t->builtBuildings.find(ID)!=t->builtBuildings.end()) //already built
ret = Buildings::ALREADY_PRESENT;
return ret;
}
void CGameState::apply(CPack *pack)
{
ui16 typ = typeList.getTypeID(pack);
applierGs->apps[typ]->applyOnGS(this,pack);
}
TeamState *CGameState::getTeam(ui8 teamID)
{
if(vstd::contains(teams,teamID))
{
return &teams[teamID];
}
else
{
tlog2 << "Warning: Cannot find info for team " << int(teamID) << std::endl;
return NULL;
}
}
TeamState *CGameState::getPlayerTeam(ui8 color)
{
PlayerState * ps = getPlayer(color);
if (ps)
return getTeam(ps->team);
return NULL;
}
PlayerState * CGameState::getPlayer( ui8 color, bool verbose )
{
if(vstd::contains(players,color))
{
return &players[color];
}
else
{
if(verbose)
tlog2 << "Warning: Cannot find info for player " << int(color) << std::endl;
return NULL;
}
}
const PlayerState * CGameState::getPlayer( ui8 color, bool verbose ) const
{
return (const_cast<CGameState *>(this))->getPlayer(color, verbose);
}
const TeamState * CGameState::getTeam( ui8 teamID ) const
{
return (const_cast<CGameState *>(this))->getTeam(teamID);
}
const TeamState * CGameState::getPlayerTeam( ui8 teamID ) const
{
return (const_cast<CGameState *>(this))->getPlayerTeam(teamID);
}
bool CGameState::getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath &ret)
{
if(!map->isInTheMap(src) || !map->isInTheMap(dest)) //check input
@@ -2505,7 +2339,7 @@ bool CGameState::checkForVisitableDir( const int3 & src, const TerrainTile *pom,
int CGameState::victoryCheck( ui8 player ) const
{
const PlayerState *p = getPlayer(player);
const PlayerState *p = CGameInfoCallback::getPlayer(player);
if(map->victoryCondition.condition == winStandard || map->victoryCondition.allowNormalVictory)
if(player == checkForStandardWin())
return -1;
@@ -2659,7 +2493,7 @@ ui8 CGameState::checkForStandardWin() const
bool CGameState::checkForStandardLoss( ui8 player ) const
{
//std loss condition is: player lost all towns and heroes
const PlayerState &p = *getPlayer(player);
const PlayerState &p = *CGameInfoCallback::getPlayer(player);
return !p.heroes.size() && !p.towns.size();
}
@@ -2848,7 +2682,7 @@ void CGameState::obtainPlayersStats(SThievesGuildInfo & tgi, int level)
int CGameState::lossCheck( ui8 player ) const
{
const PlayerState *p = getPlayer(player);
const PlayerState *p = CGameInfoCallback::getPlayer(player);
//if(map->lossCondition.typeOfLossCon == lossStandard)
if(checkForStandardLoss(player))
return -1;

View File

@@ -22,6 +22,7 @@
#endif
#include "ConstTransitivePtr.h"
#include "IGameCallback.h"
/*
@@ -310,7 +311,7 @@ struct DLL_EXPORT DuelParameters
struct BattleInfo;
class DLL_EXPORT CGameState
class DLL_EXPORT CGameState : public CNonConstInfoCallback
{
public:
ConstTransitivePtr<StartInfo> scenarioOps, initialOpts; //second one is a copy of settings received from pregame (not randomized)
@@ -324,6 +325,7 @@ public:
bmap<ui8, TeamState> teams; //ID <-> team state
bmap<int, ConstTransitivePtr<CGDefInfo> > villages, forts, capitols; //def-info for town graphics
CBonusSystemNode globalEffects;
bmap<const CGHeroInstance*, const CGObjectInstance*> ongoingVisits;
struct DLL_EXPORT HeroesPool
{
@@ -339,28 +341,17 @@ public:
} hpool; //we have here all heroes available on this map that are not hired
boost::shared_mutex *mx;
PlayerState *getPlayer(ui8 color, bool verbose = true);
TeamState *getTeam(ui8 teamID);//get team by team ID
TeamState *getPlayerTeam(ui8 color);// get team by player color
const PlayerState *getPlayer(ui8 color, bool verbose = true) const;
const TeamState *getTeam(ui8 teamID) const;
const TeamState *getPlayerTeam(ui8 color) const;
void init(StartInfo * si, ui32 checksum, int Seed);
void loadTownDInfos();
void randomizeObject(CGObjectInstance *cur);
std::pair<int,int> pickObject(CGObjectInstance *obj); //chooses type of object to be randomized, returns <type, subtype>
int pickHero(int owner);
void apply(CPack *pack);
CGHeroInstance *getHero(int objid);
CGTownInstance *getTown(int objid);
const CGHeroInstance *getHero(int objid) const;
const CGTownInstance *getTown(int objid) const;
int battleGetBattlefieldType(int3 tile = int3());// 1. sand/shore 2. sand/mesas 3. dirt/birches 4. dirt/hills 5. dirt/pines 6. grass/hills 7. grass/pines 8. lava 9. magic plains 10. snow/mountains 11. snow/trees 12. subterranean 13. swamp/trees 14. fiery fields 15. rock lands 16. magic clouds 17. lucid pools 18. holy ground 19. clover field 20. evil fog 21. "favourable winds" text on magic plains background 22. cursed ground 23. rough 24. ship to ship 25. ship
UpgradeInfo getUpgradeInfo(const CStackInstance &stack);
int getPlayerRelations(ui8 color1, ui8 color2);// 0 = enemy, 1 = ally, 2 = same player
//float getMarketEfficiency(int player, int mode=0);
std::set<int> getBuildingRequiments(const CGTownInstance *t, int ID);
int canBuildStructure(const CGTownInstance *t, int ID);// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements
bool checkForVisitableDir(const int3 & src, const int3 & dst) const; //check if src tile is visitable from dst tile
bool checkForVisitableDir(const int3 & src, const TerrainTile *pom, const int3 & dst) const; //check if src tile is visitable from dst tile
bool getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath &ret); //calculates path between src and dest; returns pointer to newly allocated CPath or NULL if path does not exists

View File

@@ -420,7 +420,7 @@ void CGObjectInstance::hideTiles(int ourplayer, int radius) const
if ( !vstd::contains(i->second.players, ourplayer ))//another team
{
for (std::set<ui8>::iterator j = i->second.players.begin(); j != i->second.players.end(); j++)
if ( cb->getPlayerState(*j)->status == PlayerState::INGAME )//seek for living player (if any)
if ( cb->getPlayer(*j)->status == PlayerState::INGAME )//seek for living player (if any)
{
FoWChange fw;
fw.mode = 0;
@@ -2184,7 +2184,7 @@ int CGTownInstance::getMarketEfficiency() const
if(!vstd::contains(builtBuildings, 14))
return 0;
const PlayerState *p = cb->getPlayerState(tempOwner);
const PlayerState *p = cb->getPlayer(tempOwner);
assert(p);
int marketCount = 0;
@@ -6313,7 +6313,7 @@ int3 IBoatGenerator::bestLocation() const
for (int i = 0; i < offsets.size(); ++i)
{
TerrainTile *tile = IObjectInterface::cb->getTile(o->pos + offsets[i]);
const TerrainTile *tile = IObjectInterface::cb->getTile(o->pos + offsets[i]);
if (tile) //tile is in the map
{
if (tile->tertype == TerrainTile::water && (!tile->blocked || tile->blockingObjects.front()->ID == 8)) //and is water and is not blocked or is blocked by boat
@@ -6326,7 +6326,7 @@ int3 IBoatGenerator::bestLocation() const
int IBoatGenerator::state() const
{
int3 tile = bestLocation();
TerrainTile *t = IObjectInterface::cb->getTile(tile);
const TerrainTile *t = IObjectInterface::cb->getTile(tile);
if(!t)
return 2; //no available water
else if(!t->blockingObjects.size())

12
lib/CObstacleInstance.h Normal file
View File

@@ -0,0 +1,12 @@
#pragma once
struct DLL_EXPORT CObstacleInstance
{
int uniqueID;
int ID; //ID of obstacle (defines type of it)
int pos; //position on battlefield
template <typename Handler> void serialize(Handler &h, const int version)
{
h & ID & pos & uniqueID;
}
};

View File

@@ -1,3 +1,4 @@
#define VCMI_DLL
#include "ERMInterpreter.h"
#include <boost/filesystem.hpp>
@@ -1118,6 +1119,18 @@ void ERMInterpreter::executeTriggerType( VERMInterpreter::TriggerType tt, bool p
}
}
void ERMInterpreter::executeTriggerType(const char *trigger, int id)
{
TIDPattern tip;
tip[0] = std::vector<int>(1, id);
executeTriggerType(VERMInterpreter::TriggerType(trigger), true, tip);
}
void ERMInterpreter::executeTriggerType(const char *trigger)
{
executeTriggerType(VERMInterpreter::TriggerType(trigger), true, TIDPattern());
}
ERM::Ttrigger ERMInterpreter::retrieveTrigger( ERM::TLine line )
{
if(line.which() == 1)
@@ -1253,6 +1266,11 @@ FunctionLocalVars * ERMInterpreter::getFuncVars( int funNum )
return funcVars + funNum - 1;
}
void ERMInterpreter::executeInstructions()
{
//TODO implement me
}
const std::string ERMInterpreter::triggerSymbol = "trigger";
const std::string ERMInterpreter::postTriggerSymbol = "postTrigger";
const std::string ERMInterpreter::defunSymbol = "defun";

View File

@@ -507,7 +507,10 @@ class ERMInterpreter
IexpValStr getVar(std::string toFollow, boost::optional<int> initVal) const;
public:
typedef std::map< int, std::vector<int> > TIDPattern;
void executeInstructions(); //called when starting a new game, before most of the map settings are done
void executeTriggerType(VERMInterpreter::TriggerType tt, bool pre, const TIDPattern & identifier); //use this to run triggers
void executeTriggerType(const char *trigger, int id); //convenience version of above, for pre-trigger when there is only one argument
void executeTriggerType(const char *trigger); //convenience version of above, for pre-trigger when there are no args
void init(); //sets up environment etc.
void scanForScripts();

49
lib/ERMScriptModule.cpp Normal file
View File

@@ -0,0 +1,49 @@
#define VCMI_DLL
#include "ERMScriptModule.h"
#include "ERMInterpreter.h"
#include <boost/assign/std/vector.hpp>
#include <boost/assign/list_of.hpp>
#include "CObjectHandler.h"
using namespace boost::assign;
CScriptingModule::~CScriptingModule()
{
}
CERMScriptModule::CERMScriptModule(void)
{
}
CERMScriptModule::~CERMScriptModule(void)
{
}
void CERMScriptModule::init()
{
interpreter = new ERMInterpreter();
interpreter->init();
interpreter->scanForScripts();
interpreter->scanScripts();
interpreter->executeInstructions();
interpreter->executeTriggerType("PI");
}
void CERMScriptModule::heroVisit(const CGHeroInstance *visitor, const CGObjectInstance *visitedObj, bool start)
{
ERMInterpreter::TIDPattern tip;
tip[1] = list_of(visitedObj->ID);
tip[2] = list_of(visitedObj->ID)(visitedObj->subID);
tip[3] = list_of(visitedObj->pos.x)(visitedObj->pos.y)(visitedObj->pos.z);
interpreter->executeTriggerType(VERMInterpreter::TriggerType("OB"), start, tip);
}
void CERMScriptModule::battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side)
{
interpreter->executeTriggerType("BA", 0);
interpreter->executeTriggerType("BR", -1);
interpreter->executeTriggerType("BF", 0);
//TODO tactics or not
}

28
lib/ERMScriptModule.h Normal file
View File

@@ -0,0 +1,28 @@
#pragma once
#include "..\global.h"
#include "IGameEventsReceiver.h"
class ERMInterpreter;
class DLL_EXPORT CScriptingModule : public IGameEventsReceiver, public IBattleEventsReceiver
{
public:
virtual void init(){}; //called upon the start of game (after map randomization, before first turn)
virtual ~CScriptingModule();
};
class DLL_EXPORT CERMScriptModule : public CScriptingModule
{
public:
ERMInterpreter *interpreter;
CERMScriptModule(void);
~CERMScriptModule(void);
virtual void heroVisit(const CGHeroInstance *visitor, const CGObjectInstance *visitedObj, bool start) OVERRIDE;
virtual void init() OVERRIDE;
virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side) OVERRIDE;
};

View File

@@ -14,6 +14,7 @@
#include <boost/foreach.hpp>
#include "NetPacks.h"
#include <boost/bind.hpp>
#include "CBuildingHandler.h"
/*
* IGameCallback.cpp, part of VCMI engine
@@ -25,10 +26,11 @@
*
*/
//TODO make clean
#define ERROR_SILENT_RET_VAL_IF(cond, txt, retVal) do {if(cond){return retVal;}} while(0)
#define ERROR_VERBOSE_OR_NOT_RET_VAL_IF(cond, verbose, txt, retVal) do {if(cond){if(verbose)tlog1 << BOOST_CURRENT_FUNCTION << ": " << txt << std::endl; return retVal;}} while(0)
#define ERROR_RET_IF(cond, txt) do {if(cond){tlog1 << BOOST_CURRENT_FUNCTION << ": " << txt << std::endl; return;}} while(0)
#define ERROR_RET_VAL_IF(cond, txt, retVal) do {if(cond){tlog1 << BOOST_CURRENT_FUNCTION << ": " << txt << std::endl; return retVal;}} while(0)
//#define ERROR_RET_IF(cond, printCond, txt, retVal) do {if(cond){ if(printCond) tlog1 << BOOST_CURRENT_FUNCTION << ": " << txt << std::endl; return retVal;}} while(0)
extern boost::rand48 ran;
@@ -347,7 +349,7 @@ int CGameInfoCallback::getOwner(int heroID) const
int CGameInfoCallback::getResource(int Player, int which) const
{
const PlayerState *p = getPlayerState(Player);
const PlayerState *p = getPlayer(Player);
ERROR_RET_VAL_IF(!p, "No player info!", -1);
ERROR_RET_VAL_IF(p->resources.size() <= which || which < 0, "No such resource!", -1);
return p->resources[which];
@@ -355,7 +357,7 @@ int CGameInfoCallback::getResource(int Player, int which) const
const CGHeroInstance* CGameInfoCallback::getSelectedHero( int Player ) const
{
const PlayerState *p = getPlayerState(Player);
const PlayerState *p = getPlayer(Player);
ERROR_RET_VAL_IF(!p, "No player info!", NULL);
return getHero(p->currentSelection);
}
@@ -446,7 +448,7 @@ void CPrivilagedInfoCallback::getFreeTiles (std::vector<int3> &tiles) const
{
floors.push_back(b);
}
TerrainTile *tinfo;
const TerrainTile *tinfo;
for (std::vector<int>::const_iterator i = floors.begin(); i!= floors.end(); i++)
{
register int zd = *i;
@@ -519,17 +521,18 @@ void CPrivilagedInfoCallback::getAllowedSpells(std::vector<ui16> &out, ui16 leve
}
}
inline TerrainTile * CPrivilagedInfoCallback::getTile( int3 pos ) const
inline TerrainTile * CNonConstInfoCallback::getTile( int3 pos )
{
if(!gs->map->isInTheMap(pos))
return NULL;
return &gs->map->getTile(pos);
}
const PlayerState * CGameInfoCallback::getPlayerState(int color) const
const PlayerState * CGameInfoCallback::getPlayer(int color, bool verbose) const
{
ERROR_RET_VAL_IF(!hasAccess(color), "Cannot access player " << color << "info!", NULL);
return gs->getPlayer(color, false);
ERROR_VERBOSE_OR_NOT_RET_VAL_IF(!hasAccess(color), verbose, "Cannot access player " << color << "info!", NULL);
ERROR_VERBOSE_OR_NOT_RET_VAL_IF(!vstd::contains(gs->players,color), verbose, "Cannot find player " << color << "info!", NULL);
return &gs->players[color];
}
const CTown * CGameInfoCallback::getNativeTown(int color) const
@@ -703,7 +706,7 @@ std::vector < std::string > CGameInfoCallback::getObjDescriptions(int3 pos) cons
{
//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
std::vector<std::string> ret;
const TerrainTile *t = getTileInfo(pos);
const TerrainTile *t = getTile(pos);
ERROR_RET_VAL_IF(!t, "Not a valid tile given!", ret);
@@ -715,7 +718,8 @@ bool CGameInfoCallback::verifyPath(CPath * path, bool blockSea) const
{
for (size_t i=0; i < path->nodes.size(); ++i)
{
const TerrainTile *t = getTileInfo(path->nodes[i].coord); //current tile
const TerrainTile *t = getTile(path->nodes[i].coord); //current tile
ERROR_RET_VAL_IF(!t, "Path contains not visible tile: " << path->nodes[i].coord << "!", false);
if (t->blocked && !t->visitable)
return false; //path is wrong - one of the tiles is blocked
@@ -724,7 +728,7 @@ bool CGameInfoCallback::verifyPath(CPath * path, bool blockSea) const
if (i==0)
continue;
const TerrainTile *prev = getTileInfo(path->nodes[i-1].coord); //tile of previous node on the path
const TerrainTile *prev = getTile(path->nodes[i-1].coord); //tile of previous node on the path
if (( t->tertype == TerrainTile::water && prev->tertype != TerrainTile::water)
|| (t->tertype != TerrainTile::water && prev->tertype == TerrainTile::water)
|| prev->tertype == TerrainTile::rock
@@ -740,7 +744,7 @@ bool CGameInfoCallback::verifyPath(CPath * path, bool blockSea) const
bool CGameInfoCallback::isVisible(int3 pos, int Player) const
{
//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
return gs->map->isInTheMap(pos) && gs->isVisible(pos, Player);
return gs->map->isInTheMap(pos) && (Player == -1 || gs->isVisible(pos, Player));
}
bool CGameInfoCallback::isVisible(int3 pos) const
@@ -771,7 +775,7 @@ bool CGameInfoCallback::isVisible(const CGObjectInstance *obj) const
std::vector < const CGObjectInstance * > CGameInfoCallback::getBlockingObjs( int3 pos ) const
{
std::vector<const CGObjectInstance *> ret;
const TerrainTile *t = getTileInfo(pos);
const TerrainTile *t = getTile(pos);
ERROR_RET_VAL_IF(!t, "Not a valid tile requested!", ret);
BOOST_FOREACH(const CGObjectInstance * obj, t->blockingObjects)
@@ -782,7 +786,7 @@ std::vector < const CGObjectInstance * > CGameInfoCallback::getBlockingObjs( int
std::vector < const CGObjectInstance * > CGameInfoCallback::getVisitableObjs( int3 pos ) const
{
std::vector<const CGObjectInstance *> ret;
const TerrainTile *t = getTileInfo(pos);
const TerrainTile *t = getTile(pos);
ERROR_RET_VAL_IF(!t, "Not a valid tile requested!", ret);
//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
@@ -794,7 +798,7 @@ std::vector < const CGObjectInstance * > CGameInfoCallback::getVisitableObjs( in
std::vector < const CGObjectInstance * > CGameInfoCallback::getFlaggableObjects(int3 pos) const
{
std::vector<const CGObjectInstance *> ret;
const TerrainTile *t = getTileInfo(pos);
const TerrainTile *t = getTile(pos);
ERROR_RET_VAL_IF(!t, "Not a valid tile requested!", ret);
BOOST_FOREACH(const CGObjectInstance *obj, t->blockingObjects)
if(obj->tempOwner != 254)
@@ -822,10 +826,9 @@ std::vector<const CGHeroInstance *> CGameInfoCallback::getAvailableHeroes(const
return ret;
}
const TerrainTile * CGameInfoCallback::getTileInfo( int3 tile ) const
const TerrainTile * CGameInfoCallback::getTile( int3 tile, bool verbose) const
{
//ERROR_RET_VAL_IF(!gs->map->isInTheMap(tile), tile << " is outside the map!", NULL);
ERROR_SILENT_RET_VAL_IF(!isVisible(tile), tile << " is not visible!", NULL);
ERROR_VERBOSE_OR_NOT_RET_VAL_IF(!isVisible(tile), verbose, tile << " is not visible!", NULL);
//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
return &gs->map->getTile(tile);
@@ -834,13 +837,97 @@ const TerrainTile * CGameInfoCallback::getTileInfo( int3 tile ) const
int CGameInfoCallback::canBuildStructure( const CGTownInstance *t, int ID )
{
ERROR_RET_VAL_IF(!canGetFullInfo(t), "Town is not owned!", -1);
return gs->canBuildStructure(t,ID);
int ret = Buildings::ALLOWED;
if(t->builded >= MAX_BUILDING_PER_TURN)
ret = Buildings::CANT_BUILD_TODAY; //building limit
CBuilding * pom = VLC->buildh->buildings[t->subID][ID];
if(!pom)
return Buildings::ERROR;
//checking resources
for(int res=0; res<RESOURCE_QUANTITY; res++)
{
if(pom->resources[res] > getResource(t->tempOwner, res))
ret = Buildings::NO_RESOURCES; //lack of res
}
//checking for requirements
std::set<int> reqs = getBuildingRequiments(t, ID);//getting all requirements
for( std::set<int>::iterator ri = reqs.begin(); ri != reqs.end(); ri++ )
{
if(t->builtBuildings.find(*ri)==t->builtBuildings.end())
ret = Buildings::PREREQUIRES; //lack of requirements - cannot build
}
//can we build it?
if(t->forbiddenBuildings.find(ID)!=t->forbiddenBuildings.end())
ret = Buildings::FORBIDDEN; //forbidden
if(ID == 13) //capitol
{
const PlayerState *ps = getPlayer(t->tempOwner);
if(ps)
{
BOOST_FOREACH(const CGTownInstance *t, ps->towns)
{
if(vstd::contains(t->builtBuildings, 13))
{
ret = Buildings::HAVE_CAPITAL; //no more than one capitol
break;
}
}
}
}
else if(ID == 6) //shipyard
{
const TerrainTile *tile = getTile(t->bestLocation());
if(!tile || tile->tertype != TerrainTile::water )
ret = Buildings::NO_WATER; //lack of water
}
if(t->builtBuildings.find(ID)!=t->builtBuildings.end()) //already built
ret = Buildings::ALREADY_PRESENT;
return ret;
}
std::set<int> CGameInfoCallback::getBuildingRequiments( const CGTownInstance *t, int ID )
{
ERROR_RET_VAL_IF(!canGetFullInfo(t), "Town is not owned!", std::set<int>());
return gs->getBuildingRequiments(t,ID);
std::set<int> used;
used.insert(ID);
std::set<int> reqs = VLC->townh->requirements[t->subID][ID];
while(true)
{
size_t noloop=0;
for(std::set<int>::iterator i=reqs.begin();i!=reqs.end();i++)
{
if(used.find(*i)==used.end()) //we haven't added requirements for this building
{
used.insert(*i);
for(
std::set<int>::iterator j=VLC->townh->requirements[t->subID][*i].begin();
j!=VLC->townh->requirements[t->subID][*i].end();
j++)
{
reqs.insert(*j);//creating full list of requirements
}
}
else
{
noloop++;
}
}
if(noloop==reqs.size())
break;
}
return reqs;
}
const CMapHeader * CGameInfoCallback::getMapHeader() const
@@ -850,7 +937,7 @@ const CMapHeader * CGameInfoCallback::getMapHeader() const
bool CGameInfoCallback::hasAccess(int playerId) const
{
return gs->getPlayerRelations( playerId, player ) || player < 0;
return player < 0 || gs->getPlayerRelations( playerId, player );
}
int CGameInfoCallback::getPlayerStatus(int player) const
@@ -896,7 +983,7 @@ bool CGameInfoCallback::isOwnedOrVisited(const CGObjectInstance *obj) const
if(canGetFullInfo(obj))
return true;
const TerrainTile *t = getTileInfo(obj->visitablePos()); //get entrance tile
const TerrainTile *t = getTile(obj->visitablePos()); //get entrance tile
const CGObjectInstance *visitor = t->visitableObjects.back(); //visitong hero if present or the obejct itself at last
return visitor->ID == HEROI_TYPE && canGetFullInfo(visitor); //owned or allied hero is a visitor
}
@@ -1014,7 +1101,7 @@ int CPlayerSpecificInfoCallback::howManyHeroes(bool includeGarrisoned) const
const CGHeroInstance* CPlayerSpecificInfoCallback::getHeroBySerial(int serialId) const
{
const PlayerState *p = getPlayerState(serialId);
const PlayerState *p = getPlayer(serialId);
ERROR_RET_VAL_IF(!p, "No player info", NULL);
ERROR_RET_VAL_IF(serialId < 0 || serialId >= p->heroes.size(), "No player info", NULL);
return p->heroes[serialId];
@@ -1022,7 +1109,7 @@ const CGHeroInstance* CPlayerSpecificInfoCallback::getHeroBySerial(int serialId)
const CGTownInstance* CPlayerSpecificInfoCallback::getTownBySerial(int serialId) const
{
const PlayerState *p = getPlayerState(serialId);
const PlayerState *p = getPlayer(serialId);
ERROR_RET_VAL_IF(!p, "No player info", NULL);
ERROR_RET_VAL_IF(serialId < 0 || serialId >= p->towns.size(), "No player info", NULL);
return p->towns[serialId];
@@ -1041,3 +1128,46 @@ std::vector<si32> CPlayerSpecificInfoCallback::getResourceAmount() const
ERROR_RET_VAL_IF(player == -1, "Applicable only for player callbacks", std::vector<si32>());
return gs->players[player].resources;
}
CGHeroInstance *CNonConstInfoCallback::getHero(int objid)
{
return const_cast<CGHeroInstance*>(CGameInfoCallback::getHero(objid));
}
CGTownInstance *CNonConstInfoCallback::getTown(int objid)
{
return const_cast<CGTownInstance*>(CGameInfoCallback::getTown(objid));
}
TeamState *CNonConstInfoCallback::getTeam(ui8 teamID)
{
return const_cast<TeamState*>(CGameInfoCallback::getTeam(teamID));
}
TeamState *CNonConstInfoCallback::getPlayerTeam(ui8 color)
{
return const_cast<TeamState*>(CGameInfoCallback::getPlayerTeam(color));
}
PlayerState * CNonConstInfoCallback::getPlayer( ui8 color, bool verbose )
{
return const_cast<PlayerState*>(CGameInfoCallback::getPlayer(color, verbose));
}
const TeamState * CGameInfoCallback::getTeam( ui8 teamID ) const
{
ERROR_RET_VAL_IF(!vstd::contains(gs->teams, teamID), "Cannot find info for team " << int(teamID), NULL);
const TeamState *ret = &gs->teams[teamID];
ERROR_RET_VAL_IF(player != -1 && !vstd::contains(ret->players, player), "Illegal attempt to access team data!", NULL);
return ret;
}
const TeamState * CGameInfoCallback::getPlayerTeam( ui8 teamID ) const
{
const PlayerState * ps = getPlayer(teamID);
if (ps)
return getTeam(ps->team);
return NULL;
}

View File

@@ -5,8 +5,7 @@
#include <vector>
#include <set>
#include "../client/FunctionList.h"
#include "CCreatureSet.h"
#include "BattleState.h"
#include "CObstacleInstance.h"
/*
* IGameCallback.h, part of VCMI engine
@@ -51,6 +50,11 @@ struct InfoAboutHero;
class CMapHeader;
struct BattleAction;
class CStack;
class CSpell;
class CCreatureSet;
class CCreature;
class CStackBasicDescriptor;
class TeamState;
typedef std::vector<const CStack*> TStacks;
@@ -104,7 +108,7 @@ public:
si8 battleGetTacticDist(); //returns tactic distance for calling player or 0 if player is not in tactic phase
ui8 battleGetMySide(); //return side of player in battle (attacker/defender)
//convienience methods using the ones above
//convenience methods using the ones above
TStacks battleGetAllStacks() //returns all stacks, alive or dead or undead or mechanical :)
{
return battleGetStacks(MINE_AND_ENEMY, false);
@@ -121,7 +125,7 @@ protected:
bool isVisible(const CGObjectInstance *obj, int Player) const;
bool isVisible(const CGObjectInstance *obj) const;
bool canGetFullInfo(const CGObjectInstance *obj) const; //true we player owns obj or ally owns obj or privilaged mode
bool canGetFullInfo(const CGObjectInstance *obj) const; //true we player owns obj or ally owns obj or privileged mode
bool isOwnedOrVisited(const CGObjectInstance *obj) const;
public:
@@ -131,7 +135,7 @@ public:
bool isAllowed(int type, int id); //type: 0 - spell; 1- artifact; 2 - secondary skill
//player
const PlayerState * getPlayerState(int color) const;
const PlayerState * getPlayer(int color, bool verbose = true) const;
int getResource(int Player, int which) const;
bool isVisible(int3 pos) const;
int getPlayerRelations(ui8 color1, ui8 color2) const;// 0 = enemy, 1 = ally, 2 = same player
@@ -140,15 +144,19 @@ public:
int getCurrentPlayer() const; //player that currently makes move // TODO synchronous turns
const PlayerSettings * getPlayerSettings(int color) const;
//armed object
void getUpgradeInfo(const CArmedInstance *obj, int stackPos, UpgradeInfo &out)const;
//hero
const CGHeroInstance* getHero(int objid) const;
int getHeroCount(int player, bool includeGarrisoned) const;
bool getHeroInfo(const CGObjectInstance *hero, InfoAboutHero &dest) const;
int getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //when called during battle, takes into account creatures' spell cost reduction
int estimateSpellDamage(const CSpell * sp, const CGHeroInstance * hero) const; //estimates damage of given spell; returns 0 if spell causes no dmg
bool verifyPath(CPath * path, bool blockSea)const;
const CGHeroInstance* getSelectedHero(int player) const; //NULL if no hero is selected
int getSelectedHero() const; //of current (active) player
//objects
const CGObjectInstance* getObj(int objid, bool verbose = true) const;
@@ -157,14 +165,16 @@ public:
std::vector <const CGObjectInstance * > getFlaggableObjects(int3 pos) const;
std::vector <std::string > getObjDescriptions(int3 pos)const; //returns descriptions of objects at pos in order from the lowest to the highest
int getOwner(int heroID) const;
const CGObjectInstance *getObjByQuestIdentifier(int identifier) const; //NULL if object has been removed (eg. killed)
//map
int3 guardingCreaturePosition (int3 pos) const;
const CMapHeader * getMapHeader()const;
int3 getMapSize() const; //returns size of map - z is 1 for one - level map and 2 for two level map
const TerrainTile * getTileInfo(int3 tile) const;
const TerrainTile * getTile(int3 tile, bool verbose = true) const;
//town
const CGTownInstance* getTown(int objid) const;
int howManyTowns(int Player) const;
const CGTownInstance * getTownInfo(int val, bool mode)const; //mode = 0 -> val = player town serial; mode = 1 -> val = object id (serial)
std::vector<const CGHeroInstance *> getAvailableHeroes(const CGObjectInstance * townOrTavern) const; //heroes that can be recruited
@@ -172,15 +182,13 @@ public:
int canBuildStructure(const CGTownInstance *t, int ID);//// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements
std::set<int> getBuildingRequiments(const CGTownInstance *t, int ID);
virtual bool getTownInfo(const CGObjectInstance *town, InfoAboutTown &dest) const;
//moved
const CGHeroInstance* getHero(int objid) const;
const CGTownInstance* getTown(int objid) const;
const CGHeroInstance* getSelectedHero(int player) const; //NULL if no hero is selected
const CGObjectInstance *getObjByQuestIdentifier(int identifier) const; //NULL if object has been removed (eg. killed)
int getSelectedHero() const;
const CTown *getNativeTown(int color) const;
//from gs
const TeamState *getTeam(ui8 teamID) const;
const TeamState *getPlayerTeam(ui8 color) const;
std::set<int> getBuildingRequiments(const CGTownInstance *t, int ID) const;
int canBuildStructure(const CGTownInstance *t, int ID) const;// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements
};
@@ -210,7 +218,6 @@ class DLL_EXPORT CPrivilagedInfoCallback : public CGameInfoCallback
{
public:
CGameState *const gameState ();
TerrainTile * getTile(int3 pos) const;
void getFreeTiles (std::vector<int3> &tiles) const; //used for random spawns
void getTilesInRange(boost::unordered_set<int3, ShashInt3> &tiles, int3 pos, int radious, int player=-1, int mode=0) const; //mode 1 - only unrevealed tiles; mode 0 - all, mode -1 - only unrevealed
void getAllTiles (boost::unordered_set<int3, ShashInt3> &tiles, int player=-1, int level=-1, int surface=0) const; //returns all tiles on given level (-1 - both levels, otherwise number of level); surface: 0 - land and water, 1 - only land, 2 - only water
@@ -221,6 +228,17 @@ public:
void getAllowedSpells(std::vector<ui16> &out, ui16 level);
};
class DLL_EXPORT CNonConstInfoCallback : public CPrivilagedInfoCallback
{
public:
PlayerState *getPlayer(ui8 color, bool verbose = true);
TeamState *getTeam(ui8 teamID);//get team by team ID
TeamState *getPlayerTeam(ui8 color);// get team by player color
CGHeroInstance *getHero(int objid);
CGTownInstance *getTown(int objid);
TerrainTile * getTile(int3 pos);
};
/// Interface class for handling general game logic and actions
class DLL_EXPORT IGameCallback : public CPrivilagedInfoCallback
{
@@ -243,8 +261,8 @@ public:
virtual void showThievesGuildWindow(int requestingObjId) =0;
virtual void giveResource(int player, int which, int val)=0;
virtual void giveCreatures (const CArmedInstance *objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) =0;
virtual void takeCreatures (int objid, std::vector<CStackBasicDescriptor> creatures) =0;
virtual void giveCreatures(const CArmedInstance *objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) =0;
virtual void takeCreatures(int objid, const std::vector<CStackBasicDescriptor> &creatures) =0;
virtual bool changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false) =0;
virtual bool changeStackType(const StackLocation &sl, CCreature *c) =0;
virtual bool insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count = -1) =0; //count -1 => moves whole stack

View File

@@ -927,6 +927,21 @@ struct DisassembledArtifact : CArtifactOperationPack //530
}
};
struct HeroVisit : CPackForClient //531
{
const CGHeroInstance *hero;
const CGObjectInstance *obj;
bool starting; //false -> ending
void applyCl(CClient *cl);
DLL_EXPORT void applyGs(CGameState *gs);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & hero & obj & starting;
}
};
struct NewTurn : public CPackForClient //101
{
enum weekType {NORMAL, DOUBLE_GROWTH, BONUS_GROWTH, DEITYOFFIRE, PLAGUE, CUSTOM, NO_ACTION, NONE};

View File

@@ -710,6 +710,14 @@ DLL_EXPORT void DisassembledArtifact::applyGs( CGameState *gs )
gs->map->eraseArtifactInstance(disassembled);
}
DLL_EXPORT void HeroVisit::applyGs( CGameState *gs )
{
if(starting)
gs->ongoingVisits[hero] = obj;
else
gs->ongoingVisits.erase(hero);
}
DLL_EXPORT void SetAvailableArtifacts::applyGs( CGameState *gs )
{
if(id >= 0)

View File

@@ -173,6 +173,7 @@ void registerTypes2(Serializer &s)
s.template registerType<MoveArtifact>();
s.template registerType<AssembledArtifact>();
s.template registerType<DisassembledArtifact>();
s.template registerType<HeroVisit>();
s.template registerType<SaveGame>();
s.template registerType<SetSelection>();

View File

@@ -50,12 +50,6 @@ DLL_EXPORT void initDLL(CConsoleHandler *Console, std::ostream *Logfile)
{
VLC->init();
} HANDLE_EXCEPTION;
ERMInterpreter ei;
// ei.scanForScripts();
// //ei.printScripts();
// ei.scanScripts();
}
DLL_EXPORT void loadToIt(std::string &dest, const std::string &src, int &iter, int mode)

View File

@@ -183,6 +183,7 @@
<ClCompile Include="CTownHandler.cpp" />
<ClCompile Include="ERMInterpreter.cpp" />
<ClCompile Include="ERMParser.cpp" />
<ClCompile Include="ERMScriptModule.cpp" />
<ClCompile Include="HeroBonus.cpp" />
<ClCompile Include="IGameCallback.cpp" />
<ClCompile Include="map.cpp" />
@@ -209,6 +210,7 @@
<ClInclude Include="CLodHandler.h" />
<ClInclude Include="CMapInfo.h" />
<ClInclude Include="CObjectHandler.h" />
<ClInclude Include="CObstacleInstance.h" />
<ClInclude Include="CondSh.h" />
<ClInclude Include="Connection.h" />
<ClInclude Include="ConstTransitivePtr.h" />
@@ -216,8 +218,10 @@
<ClInclude Include="CTownHandler.h" />
<ClInclude Include="ERMInterpreter.h" />
<ClInclude Include="ERMParser.h" />
<ClInclude Include="ERMScriptModule.h" />
<ClInclude Include="HeroBonus.h" />
<ClInclude Include="IGameCallback.h" />
<ClInclude Include="IGameEventsReceiver.h" />
<ClInclude Include="Interprocess.h" />
<ClInclude Include="map.h" />
<ClInclude Include="NetPacks.h" />

View File

@@ -23,6 +23,7 @@
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/variate_generator.hpp>
#include <boost/random/poisson_distribution.hpp>
#include "../lib/CCreatureSet.h"
/*
* CGameHandler.cpp, part of VCMI engine
@@ -492,7 +493,7 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
sah.army[0].setCreature(0, VLC->creh->nameToID[loserHero->type->refTypeStack[0]],1);
}
if(const CGHeroInstance *another = getPlayerState(loser)->availableHeroes[1])
if(const CGHeroInstance *another = getPlayer(loser)->availableHeroes[1])
sah.hid[1] = another->subID;
else
sah.hid[1] = -1;
@@ -1592,13 +1593,14 @@ void CGameHandler::giveCreatures(const CArmedInstance *obj, const CGHeroInstance
tryJoiningArmy(obj, h, remove, true);
}
void CGameHandler::takeCreatures(int objid, std::vector<CStackBasicDescriptor> creatures)
void CGameHandler::takeCreatures(int objid, const std::vector<CStackBasicDescriptor> &creatures)
{
if (creatures.size() <= 0)
std::vector<CStackBasicDescriptor> cres = creatures;
if (cres.size() <= 0)
return;
const CArmedInstance* obj = static_cast<const CArmedInstance*>(getObj(objid));
BOOST_FOREACH(CStackBasicDescriptor &sbd, creatures)
BOOST_FOREACH(CStackBasicDescriptor &sbd, cres)
{
TQuantity collected = 0;
while(collected < sbd.count)
@@ -1608,14 +1610,14 @@ void CGameHandler::takeCreatures(int objid, std::vector<CStackBasicDescriptor> c
{
if(i->second->type == sbd.type)
{
TQuantity take = std::min(sbd.count - collected, i->second->count); //collect as much creatures as we can
TQuantity take = std::min(sbd.count - collected, i->second->count); //collect as much cres as we can
changeStackCount(StackLocation(obj, i->first), take, false);
collected += take;
break;
}
}
if(i == obj->Slots().end()) //we went through the whole loop and haven't found appropriate creatures
if(i == obj->Slots().end()) //we went through the whole loop and haven't found appropriate cres
{
complain("Unexpected failure during taking creatures!");
return;
@@ -3880,7 +3882,7 @@ bool CGameHandler::isAllowedExchange( int id1, int id2 )
&& distance(o1->pos, o2->pos) < 2) //hero stands on the same tile or on the neighbouring tiles
{
//TODO: it's workaround, we should check if first hero visited second and player hasn't closed exchange window
//(to block moving stacks for free [without visiting] beteen heroes)
//(to block moving stacks for free [without visiting] between heroes)
return true;
}
@@ -3889,7 +3891,17 @@ bool CGameHandler::isAllowedExchange( int id1, int id2 )
void CGameHandler::objectVisited( const CGObjectInstance * obj, const CGHeroInstance * h )
{
HeroVisit hv;
hv.obj = obj;
hv.hero = h;
hv.starting = true;
sendAndApply(&hv);
obj->onHeroVisit(h);
hv.obj = NULL; //not necessary, moreover may have been deleted in the meantime
hv.starting = false;
sendAndApply(&hv);
}
bool CGameHandler::buildBoat( ui32 objid )

View File

@@ -143,8 +143,8 @@ public:
void showThievesGuildWindow(int requestingObjId) OVERRIDE; //TODO: make something more general?
void giveResource(int player, int which, int val) OVERRIDE;
void giveCreatures (const CArmedInstance *objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) OVERRIDE;
void takeCreatures (int objid, std::vector<CStackBasicDescriptor> creatures) OVERRIDE;
void giveCreatures(const CArmedInstance *objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) OVERRIDE;
void takeCreatures(int objid, const std::vector<CStackBasicDescriptor> &creatures) OVERRIDE;
bool changeStackType(const StackLocation &sl, CCreature *c) OVERRIDE;
bool changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false) OVERRIDE;
bool insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count) OVERRIDE;