1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Callback jugglery, part 1.

Fixed #252.
This commit is contained in:
Michał W. Urbańczyk 2011-05-03 03:14:18 +00:00
parent aca90abd38
commit b4144dc616
24 changed files with 1218 additions and 1216 deletions

View File

@ -43,7 +43,7 @@ ui8 side; //who made this action: false - left, true - right player
/**
* Implementation of CBattleLogic class.
*/
CBattleLogic::CBattleLogic(ICallback *cb, const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side) :
CBattleLogic::CBattleLogic(CCallback *cb, const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side) :
m_iCurrentTurn(-2),
m_bIsAttacker(!side),
m_cb(cb),

View File

@ -63,7 +63,7 @@ private:
int leftHitPoint_for_min; // scenario
};
public:
CBattleLogic(ICallback *cb, const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side);
CBattleLogic(CCallback *cb, const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side);
~CBattleLogic();
void SetCurrentTurn(int turn);
@ -76,7 +76,7 @@ private:
//BattleInfo m_battleInfo;
int m_iCurrentTurn;
bool m_bIsAttacker;
ICallback *m_cb;
CCallback *m_cb;
const CCreatureSet *m_army1;
const CCreatureSet *m_army2;
int3 m_tile;

View File

@ -84,7 +84,7 @@ CGeniusAI::HypotheticalGameState::HypotheticalGameState(CGeniusAI& ai)
if (ai.m_cb->howManyTowns() != 0) {
AvailableHeroesToBuy =
ai.m_cb->getAvailableHeroes(ai.m_cb->getTownInfo(0,0));
ai.m_cb->getAvailableHeroes(ai.m_cb->getTownBySerial(0));
}
for (int i = 0; i < 8; i++)
@ -126,7 +126,7 @@ void CGeniusAI::HypotheticalGameState::update(CGeniusAI& ai)
if (ai.m_cb->howManyTowns())
{
AvailableHeroesToBuy = ai.m_cb->getAvailableHeroes(ai.m_cb->getTownInfo(0,0));
AvailableHeroesToBuy = ai.m_cb->getAvailableHeroes(ai.m_cb->getTownBySerial(0));
}
resourceAmounts.clear();
@ -317,7 +317,8 @@ float CGeniusAI::TownObjective::getValue() const
break;
case upgradeCreatures:
UpgradeInfo ui = AI->m_cb->getUpgradeInfo(whichTown->t,which);
UpgradeInfo ui;
AI->m_cb->getUpgradeInfo(whichTown->t,which, ui);
ID = whichTown->t->getCreature(which)->idNumber;
howMany = whichTown->t->getStackCount(which);
@ -425,7 +426,8 @@ void CGeniusAI::TownObjective::print() const
break; // case recruitCreatures.
case upgradeCreatures:
UpgradeInfo ui = AI->m_cb->getUpgradeInfo (whichTown->t, which);
UpgradeInfo ui;
AI->m_cb->getUpgradeInfo (whichTown->t, which, ui);
ID = whichTown->t->getCreature(which)->idNumber;
tlog6 << "upgrade " << VLC->creh->creatures[ID]->namePl;
//ui.cost
@ -446,7 +448,7 @@ CGeniusAI::~CGeniusAI()
}
void CGeniusAI::init(ICallback *CB)
void CGeniusAI::init(CCallback *CB)
{
m_cb = CB;
m_generalAI.init(CB);
@ -749,7 +751,8 @@ void CGeniusAI::HeroObjective::fulfill(CGeniusAI& cg, HypotheticalGameState& hgs
tlog6 << "visiting town" << endl;
for (TSlots::const_iterator i = h->h->Slots().begin(); i != h->h->Slots().end(); i++)
{ // For each hero slot.
UpgradeInfo ui = cg.m_cb->getUpgradeInfo(h->h,i->first);
UpgradeInfo ui;
cg.m_cb->getUpgradeInfo(h->h,i->first, ui);
bool canUpgrade = false;
if (ui.newID.size() != 0)
@ -878,7 +881,8 @@ void CGeniusAI::addTownObjectives (HypotheticalGameState::TownModel& t, Hypothet
// Upgrade creatures.
for (TSlots::const_iterator i = t.t->Slots().begin(); i != t.t->Slots().end(); i++)
{
UpgradeInfo ui = m_cb->getUpgradeInfo(t.t, i->first);
UpgradeInfo ui;
m_cb->getUpgradeInfo(t.t, i->first, ui);
if (ui.newID.size())
{
bool canAfford = true;
@ -952,7 +956,8 @@ void CGeniusAI::TownObjective::fulfill(CGeniusAI& cg,
break;
case upgradeCreatures:
UpgradeInfo ui = cg.m_cb->getUpgradeInfo(whichTown->t, which);
UpgradeInfo ui;
cg.m_cb->getUpgradeInfo(whichTown->t, which, ui);
ID = whichTown->t->getCreature(which)->idNumber;
newID = ui.newID.back();
// TODO: reduce resources in hgs
@ -1070,8 +1075,8 @@ void CGeniusAI::startFirstTurn()
{
HypotheticalGameState hgs(*this);
const CGTownInstance * town = m_cb->getTownInfo(0,0);
const CGHeroInstance * heroInst = m_cb->getHeroInfo(0,0);
const CGTownInstance * town = m_cb->getTownBySerial(0);
const CGHeroInstance * heroInst = m_cb->getHeroBySerial(0);
TownObjective(hgs, AIObjective::recruitHero, &hgs.townModels.front(), 0, this).fulfill(*this, hgs);

View File

@ -28,7 +28,7 @@ class CGeniusAI : public CGlobalAI
{
private:
// TODO: cb... come back, croach busters!?
ICallback* m_cb;
CCallback* m_cb;
geniusai::BattleAI::CBattleLogic* m_battleLogic;
geniusai::GeneralAI::CGeneralAI m_generalAI;
geniusai::Priorities* m_priorities;
@ -180,7 +180,7 @@ public:
CGeniusAI();
virtual ~CGeniusAI();
virtual void init(ICallback * CB);
virtual void init(CCallback * CB);
virtual void yourTurn();
virtual void heroKilled(const CGHeroInstance *);
virtual void heroCreated(const CGHeroInstance *);

View File

@ -12,7 +12,7 @@ CGeneralAI::~CGeneralAI()
{
}
void CGeneralAI::init(ICallback *CB)
void CGeneralAI::init(CCallback *CB)
{
assert(CB != NULL);
m_cb = CB;

View File

@ -11,9 +11,9 @@ namespace geniusai { namespace GeneralAI {
CGeneralAI();
~CGeneralAI();
void init(ICallback* CB);
void init(CCallback* CB);
private:
ICallback *m_cb;
CCallback *m_cb;
};
}}

View File

@ -8,7 +8,7 @@
#include <algorithm>
//#include <boost/thread.hpp>
IBattleCallback * cbc;
CBattleCallback * cbc;
CStupidAI::CStupidAI(void)
: side(-1), cb(NULL)
@ -22,7 +22,7 @@ CStupidAI::~CStupidAI(void)
print("destroyed");
}
void CStupidAI::init( IBattleCallback * CB )
void CStupidAI::init( CBattleCallback * CB )
{
print("init called, saving ptr to IBattleCallback");
cbc = cb = CB;
@ -105,7 +105,7 @@ BattleAction CStupidAI::activeStack( const CStack * stack )
std::vector<int> dists = cb->battleGetDistances(stack);
std::vector<EnemyInfo> enemiesShootable, enemiesReachable, enemiesUnreachable;
BOOST_FOREACH(const CStack *s, cb->battleGetStacks(IBattleCallback::ONLY_ENEMY))
BOOST_FOREACH(const CStack *s, cb->battleGetStacks(CBattleCallback::ONLY_ENEMY))
{
if(cb->battleCanShoot(stack, s->position))
{

View File

@ -3,14 +3,14 @@
class CStupidAI : public CBattleGameInterface
{
int side;
IBattleCallback *cb;
CBattleCallback *cb;
void print(const std::string &text) const;
public:
CStupidAI(void);
~CStupidAI(void);
void init(IBattleCallback * CB) OVERRIDE;
void init(CBattleCallback * CB) OVERRIDE;
void actionFinished(const BattleAction *action) OVERRIDE;//occurs AFTER every action taken by any stack or by the hero
void actionStarted(const BattleAction *action) OVERRIDE;//occurs BEFORE every action taken by any stack or by the hero
BattleAction activeStack(const CStack * stack) OVERRIDE; //called when it's turn of that stack

View File

@ -69,7 +69,6 @@ void CCallback::recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amou
sendRequest(&pack);
}
bool CCallback::dismissCreature(const CArmedInstance *obj, int stackPos)
{
if(((player>=0) && obj->tempOwner != player) || (obj->stacksCount()<2 && obj->needsLastStack()))
@ -79,322 +78,20 @@ bool CCallback::dismissCreature(const CArmedInstance *obj, int stackPos)
sendRequest(&pack);
return true;
}
bool CCallback::upgradeCreature(const CArmedInstance *obj, int stackPos, int newID)
{
UpgradeCreature pack(stackPos,obj->id,newID);
sendRequest(&pack);
return false;
}
void CCallback::endTurn()
{
tlog5 << "Player " << (unsigned)player << " ended his turn." << std::endl;
EndTurn pack;
sendRequest(&pack); //report that we ended turn
}
UpgradeInfo CCallback::getUpgradeInfo(const CArmedInstance *obj, int stackPos) const
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
return gs->getUpgradeInfo(obj->getStack(stackPos));
}
const StartInfo * CCallback::getStartInfo() const
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
return gs->scenarioOps;
}
int CCallback::getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
//if there is a battle
if(gs->curB)
return gs->curB->getSpellCost(sp, caster);
//if there is no battle
return caster->getSpellCost(sp);
}
int CCallback::estimateSpellDamage(const CSpell * sp, const CGHeroInstance * hero) const
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
if(!gs->curB) //no battle
{
if (hero) //but we see hero's spellbook
return gs->curB->calculateSpellDmg(sp, hero, NULL, hero->getSpellSchoolLevel(sp), hero->getPrimSkillLevel(2));
else
return 0; //mage guild
}
//gs->getHero(gs->currentPlayer)
const CGHeroInstance * ourHero = gs->curB->heroes[0]->tempOwner == player ? gs->curB->heroes[0] : gs->curB->heroes[1];
return gs->curB->calculateSpellDmg(sp, ourHero, NULL, ourHero->getSpellSchoolLevel(sp), ourHero->getPrimSkillLevel(2));
}
void CCallback::getThievesGuildInfo(SThievesGuildInfo & thi, const CGObjectInstance * obj)
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
if(obj == NULL)
return;
if(obj->ID == TOWNI_TYPE || obj->ID == 95) //it is a town or adv map tavern
{
gs->obtainPlayersStats(thi, gs->players[player].towns.size());
}
else if(obj->ID == 97) //Den of Thieves
{
gs->obtainPlayersStats(thi, 20);
}
}
int CCallback::howManyTowns() const
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
return gs->players[player].towns.size();
}
const CGTownInstance * CCallback::getTownInfo(int val, bool mode) const //mode = 0 -> val = serial; mode = 1 -> val = ID
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
if (!mode)
{
const std::vector<ConstTransitivePtr<CGTownInstance> > &towns = gs->players[gs->currentPlayer].towns;
if(val < towns.size())
return towns[val];
else
return NULL;
}
else if(mode == 1)
{
const CGObjectInstance *obj = getObjectInfo(val);
if(!obj)
return NULL;
if(obj->ID != TOWNI_TYPE)
return NULL;
else
return static_cast<const CGTownInstance *>(obj);
}
return NULL;
}
bool CCallback::getTownInfo( const CGObjectInstance *town, InfoAboutTown &dest ) const
{
if(!isVisible(town, player)) //it's not a town or it's not visible for layer
return false;
bool detailed = hasAccess(town->tempOwner);
//TODO vision support
if(town->ID == TOWNI_TYPE)
dest.initFromTown(static_cast<const CGTownInstance *>(town), detailed);
else if(town->ID == 33 || town->ID == 219)
dest.initFromGarrison(static_cast<const CGGarrison *>(town), detailed);
else
return false;
return true;
}
int3 CCallback::guardingCreaturePosition (int3 pos) const
{
return gs->guardingCreaturePosition(pos);
}
int CCallback::howManyHeroes(bool includeGarrisoned) const
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
return cl->getHeroCount(player,includeGarrisoned);
}
const CGHeroInstance * CCallback::getHeroInfo(int val, int mode) const //mode = 0 -> val = serial; mode = 1 -> val = ID
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx); //TODO use me?
//if (gs->currentPlayer!=player) //TODO: checking if we are allowed to give that info
// return NULL;
if (!mode) //esrial id
{
if(val<gs->players[player].heroes.size())
{
return gs->players[player].heroes[val];
}
else
{
return NULL;
}
}
else if(mode==1) //it's hero type id
{
for (size_t i=0; i < gs->players[player].heroes.size(); ++i)
{
if (gs->players[player].heroes[i]->type->ID==val)
{
return gs->players[player].heroes[i];
}
}
}
else //object id
{
return static_cast<const CGHeroInstance*>(gs->map->objects[val].get());
}
return NULL;
}
const CGObjectInstance * CCallback::getObjectInfo(int ID) const
{
//TODO: check for visibility
return gs->map->objects[ID];
}
bool CCallback::getHeroInfo( const CGObjectInstance *hero, InfoAboutHero &dest ) const
{
const CGHeroInstance *h = dynamic_cast<const CGHeroInstance *>(hero);
if(!h || !isVisible(h->getPosition(false))) //it's not a hero or it's not visible for layer
return false;
//TODO vision support
dest.initFromHero(h, hasAccess(h->tempOwner));
return true;
}
int CCallback::getResourceAmount(int type) const
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
return gs->players[player].resources[type];
}
std::vector<si32> CCallback::getResourceAmount() const
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
return gs->players[player].resources;
}
int CCallback::getDate(int mode) const
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
return gs->getDate(mode);
}
std::vector < std::string > CCallback::getObjDescriptions(int3 pos) const
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
std::vector<std::string> ret;
if(!isVisible(pos,player))
return ret;
BOOST_FOREACH(const CGObjectInstance * obj, gs->map->terrain[pos.x][pos.y][pos.z].blockingObjects)
ret.push_back(obj->getHoverText());
return ret;
}
bool CCallback::verifyPath(CPath * path, bool blockSea) const
{
for (size_t i=0; i < path->nodes.size(); ++i)
{
if ( CGI->mh->map->terrain[path->nodes[i].coord.x][path->nodes[i].coord.y][path->nodes[i].coord.z].blocked
&& (! (CGI->mh->map->terrain[path->nodes[i].coord.x][path->nodes[i].coord.y][path->nodes[i].coord.z].visitable)))
return false; //path is wrong - one of the tiles is blocked
if (blockSea)
{
if (i==0)
continue;
if (
((CGI->mh->map->terrain[path->nodes[i].coord.x][path->nodes[i].coord.y][path->nodes[i].coord.z].tertype==TerrainTile::water)
&&
(CGI->mh->map->terrain[path->nodes[i-1].coord.x][path->nodes[i-1].coord.y][path->nodes[i-1].coord.z].tertype!=TerrainTile::water))
||
((CGI->mh->map->terrain[path->nodes[i].coord.x][path->nodes[i].coord.y][path->nodes[i].coord.z].tertype!=TerrainTile::water)
&&
(CGI->mh->map->terrain[path->nodes[i-1].coord.x][path->nodes[i-1].coord.y][path->nodes[i-1].coord.z].tertype==TerrainTile::water))
||
(CGI->mh->map->terrain[path->nodes[i-1].coord.x][path->nodes[i-1].coord.y][path->nodes[i-1].coord.z].tertype==TerrainTile::rock)
)
return false;
}
}
return true;
}
std::vector< std::vector< std::vector<unsigned char> > > & CCallback::getVisibilityMap() const
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
return gs->getPlayerTeam(player)->fogOfWarMap;
}
bool CCallback::isVisible(int3 pos, int Player) const
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
return gs->map->isInTheMap(pos) && gs->isVisible(pos, Player);
}
std::vector < const CGTownInstance *> CCallback::getTownsInfo(bool onlyOur) const
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
std::vector < const CGTownInstance *> ret = std::vector < const CGTownInstance *>();
for ( std::map<ui8, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
{
for (size_t j=0; j < (*i).second.towns.size(); ++j)
{
if ((*i).first==player
|| (isVisible((*i).second.towns[j],player) && !onlyOur))
{
ret.push_back((*i).second.towns[j]);
}
}
} // for ( std::map<int, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
return ret;
}
std::vector < const CGHeroInstance *> CCallback::getHeroesInfo(bool onlyOur) const
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
std::vector < const CGHeroInstance *> ret;
for(size_t i=0;i<gs->map->heroes.size();i++)
{
if( (gs->map->heroes[i]->tempOwner==player) ||
(isVisible(gs->map->heroes[i]->getPosition(false),player) && !onlyOur) )
{
ret.push_back(gs->map->heroes[i]);
}
}
return ret;
}
bool CCallback::isVisible(int3 pos) const
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
return isVisible(pos,player);
}
bool CCallback::isVisible( const CGObjectInstance *obj, int Player ) const
{
return gs->isVisible(obj, Player);
}
int CCallback::getMyColor() const
{
return player;
}
int CCallback::getHeroSerial(const CGHeroInstance * hero) const
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
for (size_t i=0; i<gs->players[player].heroes.size();i++)
{
if (gs->players[player].heroes[i]==hero)
return i;
}
return -1;
}
const CCreatureSet* CCallback::getGarrison(const CGObjectInstance *obj) const
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
const CArmedInstance *armi = dynamic_cast<const CArmedInstance*>(obj);
if(!armi)
return NULL;
else
return armi;
}
int CCallback::swapCreatures(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2)
{
ArrangeStacks pack(1,p1,p2,s1->id,s2->id,0);
@ -474,41 +171,6 @@ bool CCallback::buildBuilding(const CGTownInstance *town, si32 buildingID)
return true;
}
int CBattleCallback::battleGetBattlefieldType()
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
//return gs->battleGetBattlefieldType();
if(!gs->curB)
{
tlog2<<"battleGetBattlefieldType called when there is no battle!"<<std::endl;
return -1;
}
return gs->curB->battlefieldType;
}
int CBattleCallback::battleGetObstaclesAtTile(THex tile) //returns bitfield
{
//TODO - write
return -1;
}
std::vector<CObstacleInstance> CBattleCallback::battleGetAllObstacles()
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
if(gs->curB)
return gs->curB->obstacles;
else
return std::vector<CObstacleInstance>();
}
const CStack* CBattleCallback::battleGetStackByID(int ID, bool onlyAlive)
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
if(!gs->curB) return NULL;
return gs->curB->getStack(ID, onlyAlive);
}
int CBattleCallback::battleMakeAction(BattleAction* action)
{
assert(action->actionType == BattleAction::HERO_SPELL);
@ -517,177 +179,6 @@ int CBattleCallback::battleMakeAction(BattleAction* action)
return 0;
}
const CStack* CBattleCallback::battleGetStackByPos(THex pos, bool onlyAlive)
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
return gs->curB->battleGetStack(pos, onlyAlive);
}
THex CBattleCallback::battleGetPos(int stack)
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
if(!gs->curB)
{
tlog2<<"battleGetPos called when there is no battle!"<<std::endl;
return THex::INVALID;
}
for(size_t g=0; g<gs->curB->stacks.size(); ++g)
{
if(gs->curB->stacks[g]->ID == stack)
return gs->curB->stacks[g]->position;
}
return THex::INVALID;
}
TStacks CBattleCallback::battleGetStacks(EStackOwnership whose /*= MINE_AND_ENEMY*/, bool onlyAlive /*= true*/)
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
TStacks ret;
if(!gs->curB) //there is no battle
{
tlog2<<"battleGetStacks called when there is no battle!"<<std::endl;
return ret;
}
BOOST_FOREACH(const CStack *s, gs->curB->stacks)
{
bool ownerMatches = whose == MINE_AND_ENEMY || whose == ONLY_MINE && s->owner == player || whose == ONLY_ENEMY && s->owner != player;
bool alivenessMatches = s->alive() || !onlyAlive;
if(ownerMatches && alivenessMatches)
ret.push_back(s);
}
return ret;
}
void CBattleCallback::getStackQueue( std::vector<const CStack *> &out, int howMany )
{
if(!gs->curB)
{
tlog2 << "battleGetStackQueue called when there is not battle!" << std::endl;
return;
}
gs->curB->getStackQueue(out, howMany);
}
std::vector<THex> CBattleCallback::battleGetAvailableHexes(const CStack * stack, bool addOccupiable, std::vector<THex> * attackable)
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
if(!gs->curB)
{
tlog2<<"battleGetAvailableHexes called when there is no battle!"<<std::endl;
return std::vector<THex>();
}
return gs->curB->getAccessibility(stack, addOccupiable, attackable);
//return gs->battleGetRange(ID);
}
bool CBattleCallback::battleCanShoot(const CStack * stack, THex dest)
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
if(!gs->curB) return false;
return gs->curB->battleCanShoot(stack, dest);
}
bool CBattleCallback::battleCanCastSpell()
{
if(!gs->curB) //there is no battle
return false;
return gs->curB->battleCanCastSpell(player, SpellCasting::HERO_CASTING) == SpellCasting::OK;
}
bool CBattleCallback::battleCanFlee()
{
return gs->curB->battleCanFlee(player);
}
const CGTownInstance *CBattleCallback::battleGetDefendedTown()
{
if(!gs->curB || gs->curB->town == NULL)
return NULL;
return gs->curB->town;
}
ui8 CBattleCallback::battleGetWallState(int partOfWall)
{
if(!gs->curB || gs->curB->siege == 0)
{
return 0;
}
return gs->curB->si.wallState[partOfWall];
}
int CBattleCallback::battleGetWallUnderHex(THex hex)
{
if(!gs->curB || gs->curB->siege == 0)
{
return -1;
}
return gs->curB->hexToWallPart(hex);
}
TDmgRange CBattleCallback::battleEstimateDamage(const CStack * attacker, const CStack * defender, TDmgRange * retaliationDmg)
{
if(!gs->curB)
return std::make_pair(0, 0);
const CGHeroInstance * attackerHero, * defenderHero;
bool shooting = battleCanShoot(attacker, defender->position);
if(gs->curB->sides[0] == player)
{
attackerHero = gs->curB->heroes[0];
defenderHero = gs->curB->heroes[1];
}
else
{
attackerHero = gs->curB->heroes[1];
defenderHero = gs->curB->heroes[0];
}
TDmgRange ret = gs->curB->calculateDmgRange(attacker, defender, attackerHero, defenderHero, shooting, 0, false, false);
if(retaliationDmg)
{
if(shooting)
{
retaliationDmg->first = retaliationDmg->second = 0;
}
else
{
ui32 TDmgRange::* pairElems[] = {&TDmgRange::first, &TDmgRange::second};
for (int i=0; i<2; ++i)
{
BattleStackAttacked bsa;
bsa.damageAmount = ret.*pairElems[i];
retaliationDmg->*pairElems[!i] = gs->curB->calculateDmgRange(defender, attacker, bsa.newAmount, attacker->count, attackerHero, defenderHero, false, false, false, false).*pairElems[!i];
}
}
}
return ret;
}
ui8 CBattleCallback::battleGetSiegeLevel()
{
if(!gs->curB)
return 0;
return gs->curB->siege;
}
const CGHeroInstance * CBattleCallback::battleGetFightingHero(ui8 side) const
{
if(!gs->curB)
return 0;
return gs->curB->heroes[side];
}
template <typename T>
void CBattleCallback::sendRequest(const T* request)
{
@ -717,49 +208,6 @@ void CCallback::buyArtifact(const CGHeroInstance *hero, int aid)
sendRequest(&pack);
}
std::vector < const CGObjectInstance * > CCallback::getBlockingObjs( int3 pos ) const
{
std::vector<const CGObjectInstance *> ret;
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
if(!gs->map->isInTheMap(pos) || !isVisible(pos))
return ret;
BOOST_FOREACH(const CGObjectInstance * obj, gs->map->terrain[pos.x][pos.y][pos.z].blockingObjects)
ret.push_back(obj);
return ret;
}
std::vector < const CGObjectInstance * > CCallback::getVisitableObjs( int3 pos ) const
{
std::vector<const CGObjectInstance *> ret;
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
if(!gs->map->isInTheMap(pos) || !isVisible(pos))
return ret;
BOOST_FOREACH(const CGObjectInstance * obj, gs->map->terrain[pos.x][pos.y][pos.z].visitableObjects)
ret.push_back(obj);
return ret;
}
std::vector < const CGObjectInstance * > CCallback::getFlaggableObjects(int3 pos) const
{
if(!isVisible(pos))
return std::vector < const CGObjectInstance * >();
std::vector < const CGObjectInstance * > ret;
const std::vector < std::pair<const CGObjectInstance*,SDL_Rect> > & objs = CGI->mh->ttiles[pos.x][pos.y][pos.z].objects;
for(size_t b=0; b<objs.size(); ++b)
{
if(objs[b].first->tempOwner!=254 && !((objs[b].first->defInfo->blockMap[pos.y - objs[b].first->pos.y + 5] >> (objs[b].first->pos.x - pos.x)) & 1))
ret.push_back(CGI->mh->ttiles[pos.x][pos.y][pos.z].objects[b].first);
}
return ret;
}
int3 CCallback::getMapSize() const
{
return CGI->mh->sizes;
}
void CCallback::trade(const CGObjectInstance *market, int mode, int id1, int id2, int val1, const CGHeroInstance *hero/* = NULL*/)
{
TradeOnMarketplace pack;
@ -809,35 +257,6 @@ void CCallback::recruitHero(const CGObjectInstance *townOrTavern, const CGHeroIn
}
}
std::vector<const CGHeroInstance *> CCallback::getAvailableHeroes(const CGObjectInstance * townOrTavern) const
{
std::vector<const CGHeroInstance *> ret(gs->players[player].availableHeroes.size());
std::copy(gs->players[player].availableHeroes.begin(),gs->players[player].availableHeroes.end(),ret.begin());
return ret;
}
const TerrainTile * CCallback::getTileInfo( int3 tile ) const
{
if(!gs->map->isInTheMap(tile))
{
tlog1 << tile << "is outside the map! (call to getTileInfo)\n";
return NULL;
}
if(!isVisible(tile, player)) return NULL;
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
return &gs->map->getTile(tile);
}
int CCallback::canBuildStructure( const CGTownInstance *t, int ID )
{
return gs->canBuildStructure(t,ID);
}
std::set<int> CCallback::getBuildingRequiments( const CGTownInstance *t, int ID )
{
return gs->getBuildingRequiments(t,ID);
}
bool CCallback::getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath &ret)
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
@ -869,11 +288,6 @@ CCallback::CCallback( CGameState * GS, int Player, CClient *C )
waitTillRealize = false;
}
const CMapHeader * CCallback::getMapHeader() const
{
return gs->map;
}
const CGPathNode * CCallback::getPathInfo( int3 tile )
{
return &cl->pathInfo->nodes[tile.x][tile.y][tile.z];
@ -903,19 +317,6 @@ void CCallback::calculatePaths( const CGHeroInstance *hero, CPathsInfo &out, int
gs->calculatePaths(hero, out, src, movement);
}
int3 CCallback::getGrailPos( float &outKnownRatio )
{
if (CGObelisk::obeliskCount == 0)
{
outKnownRatio = 0.0f;
}
else
{
outKnownRatio = (float)CGObelisk::visited[gs->getPlayerTeam(player)->id] / CGObelisk::obeliskCount;
}
return gs->map->grailPos;
}
void CCallback::dig( const CGObjectInstance *hero )
{
DigWithHero dwh;
@ -931,129 +332,6 @@ void CCallback::castSpell(const CGHeroInstance *hero, int spellID, const int3 &p
cas.pos = pos;
sendRequest(&cas);
}
bool CCallback::hasAccess(int playerId) const
{
return gs->getPlayerRelations( playerId, player ) || player < 0;
}
si8 CBattleCallback::battleHasDistancePenalty( const CStack * stack, THex destHex )
{
return gs->curB->hasDistancePenalty(stack, destHex);
}
si8 CBattleCallback::battleHasWallPenalty( const CStack * stack, THex destHex )
{
return gs->curB->hasWallPenalty(stack, destHex);
}
si8 CBattleCallback::battleCanTeleportTo(const CStack * stack, THex destHex, int telportLevel)
{
return gs->curB->canTeleportTo(stack, destHex, telportLevel);
}
int CCallback::getPlayerStatus(int player) const
{
const PlayerState *ps = gs->getPlayer(player, false);
if(!ps)
return -1;
return ps->status;
}
std::string CCallback::getTavernGossip(const CGObjectInstance * townOrTavern) const
{
return "GOSSIP TEST";
}
std::vector < const CGObjectInstance * > CCallback::getMyObjects() const
{
std::vector < const CGObjectInstance * > ret;
for (int g=0; g<gs->map->objects.size(); ++g)
{
if (gs->map->objects[g] && gs->map->objects[g]->tempOwner == LOCPLINT->playerID)
{
ret.push_back(gs->map->objects[g]);
}
}
return ret;
}
std::vector < const CGDwelling * > CCallback::getMyDwellings() const
{
std::vector < const CGDwelling * > ret;
BOOST_FOREACH(CGDwelling * dw, gs->getPlayer(player)->dwellings)
{
ret.push_back(dw);
}
return ret;
}
int CCallback::getPlayerRelations( ui8 color1, ui8 color2 ) const
{
return gs->getPlayerRelations(color1, color2);
}
InfoAboutTown::InfoAboutTown()
{
tType = NULL;
details = NULL;
fortLevel = 0;
owner = -1;
}
InfoAboutTown::~InfoAboutTown()
{
delete details;
}
void InfoAboutTown::initFromTown( const CGTownInstance *t, bool detailed )
{
obj = t;
army = ArmyDescriptor(t->getUpperArmy(), detailed);
built = t->builded;
fortLevel = t->fortLevel();
name = t->name;
tType = t->town;
owner = t->tempOwner;
if(detailed)
{
//include details about hero
details = new Details;
details->goldIncome = t->dailyIncome();
details->customRes = vstd::contains(t->builtBuildings, 15);
details->hallLevel = t->hallLevel();
details->garrisonedHero = t->garrisonHero;
}
//TODO: adjust undetailed info about army to our count of thieves guilds
}
void InfoAboutTown::initFromGarrison(const CGGarrison *garr, bool detailed)
{
obj = garr;
fortLevel = 0;
army = ArmyDescriptor(garr, detailed);
name = CGI->generaltexth->names[33]; // "Garrison"
owner = garr->tempOwner;
built = false;
tType = NULL;
// Show detailed info only to owning player.
if(detailed)
{
details = new InfoAboutTown::Details;
details->customRes = false;
details->garrisonedHero = false;
details->goldIncome = -1;
details->hallLevel = -1;
}
}
bool CBattleCallback::hasAccess( int playerId ) const
{
return playerId == player || player < 0;
}
CBattleCallback::CBattleCallback(CGameState *GS, int Player, CClient *C )
{
gs = GS;
@ -1061,73 +339,6 @@ CBattleCallback::CBattleCallback(CGameState *GS, int Player, CClient *C )
cl = C;
}
std::vector<int> CBattleCallback::battleGetDistances(const CStack * stack, THex hex /*= THex::INVALID*/, THex * predecessors /*= NULL*/)
{
if(!hex.isValid())
hex = stack->position;
std::vector<int> ret;
bool ac[BFIELD_SIZE] = {0};
std::set<THex> occupyable;
gs->curB->getAccessibilityMap(ac, stack->doubleWide(), stack->attackerOwned, false, occupyable, stack->hasBonusOfType(Bonus::FLYING), stack);
THex pr[BFIELD_SIZE];
int dist[BFIELD_SIZE];
gs->curB->makeBFS(stack->position, ac, pr, dist, stack->doubleWide(), stack->attackerOwned, stack->hasBonusOfType(Bonus::FLYING), false);
for(int i=0; i<BFIELD_SIZE; ++i)
{
if(pr[i] == -1)
ret.push_back(-1);
else
ret.push_back(dist[i]);
}
if(predecessors)
{
memcpy(predecessors, pr, BFIELD_SIZE * sizeof(THex));
}
return ret;
}
SpellCasting::ESpellCastProblem CBattleCallback::battleCanCastThisSpell( const CSpell * spell )
{
if(!gs->curB)
{
tlog1 << "battleCanCastThisSpell called when there is no battle!\n";
return SpellCasting::NO_HERO_TO_CAST_SPELL;
}
return gs->curB->battleCanCastThisSpell(player, spell, SpellCasting::HERO_CASTING);
}
si8 CBattleCallback::battleGetTacticDist()
{
if (!gs->curB)
{
tlog1 << "battleGetTacticDist called when no battle!\n";
return 0;
}
if (gs->curB->sides[gs->curB->tacticsSide] == player)
{
return gs->curB->tacticDistance;
}
return 0;
}
ui8 CBattleCallback::battleGetMySide()
{
if (!gs->curB)
{
tlog1 << "battleGetMySide called when no battle!\n";
return 0;
}
return gs->curB->sides[1] == player;
}
bool CBattleCallback::battleMakeTacticAction( BattleAction * action )
{
MakeAction ma;
@ -1135,14 +346,3 @@ bool CBattleCallback::battleMakeTacticAction( BattleAction * action )
sendRequest(&ma);
return true;
}
int CBattleCallback::battleGetSurrenderCost()
{
if (!gs->curB)
{
tlog1 << "battleGetSurrenderCost called when no battle!\n";
return -1;
}
return gs->curB->getSurrenderingCost(player);
}

View File

@ -9,7 +9,8 @@
//support of unicode we should use ICU or some boost wraper areound it
//(boost using this lib during compilation i dont know what for exactly)
#endif
#include "lib/CGameState.h"
#include "lib/IGameCallback.h"
/*
* CCallback.h, part of VCMI engine
@ -26,119 +27,49 @@ class CGameState;
struct CPath;
class CGObjectInstance;
class CArmedInstance;
class SComponent;
class IChosen;
class CSelectableComponent;
struct BattleAction;
class CGTownInstance;
struct StartInfo;
class CStack;
struct lua_State;
class CClient;
struct TerrainTile;
class CHeroClass;
class IShipyard;
struct CPackForServer;
class CMapHeader;
struct CGPathNode;
struct CGPath;
class CGGarrison;
class CObstacleInstance;
typedef std::vector<const CStack*> TStacks;
/// Struct which holds a short information about a town
struct InfoAboutTown
{
struct Details
{
int hallLevel, goldIncome;
bool customRes;
bool garrisonedHero;
} *details;
const CArmedInstance * obj;
char fortLevel; //0 - none
char owner;
std::string name;
CTown *tType;
bool built;
ArmyDescriptor army; //numbers of creatures are valid only if details
InfoAboutTown();
~InfoAboutTown();
void initFromTown(const CGTownInstance *t, bool detailed);
void initFromGarrison(const CGGarrison *garr, bool detailed);
};
struct CPathsInfo;
class IBattleCallback
{
public:
///describes why player cannot cast a specific spell
enum EStackOwnership
{
ONLY_MINE, ONLY_ENEMY, MINE_AND_ENEMY
};
bool waitTillRealize; //if true, request functions will return after they are realized by server
//battle
virtual int battleGetBattlefieldType()=0; // 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
virtual int battleGetObstaclesAtTile(THex tile)=0; //returns bitfield
virtual std::vector<CObstacleInstance> battleGetAllObstacles()=0; //returns all obstacles on the battlefield
virtual const CStack * battleGetStackByID(int ID, bool onlyAlive = true)=0; //returns stack info by given ID
virtual const CStack * battleGetStackByPos(THex pos, bool onlyAlive = true)=0; //returns stack info by given pos
virtual THex battleGetPos(int stack)=0; //returns position (tile ID) of stack
virtual int battleMakeAction(BattleAction* action)=0;//for casting spells by hero - DO NOT use it for moving active stack
virtual TStacks battleGetStacks(EStackOwnership whose = MINE_AND_ENEMY, bool onlyAlive = true)=0; //returns stacks on battlefield
virtual void getStackQueue( std::vector<const CStack *> &out, int howMany )=0; //returns vector of stack in order of their move sequence
virtual std::vector<THex> battleGetAvailableHexes(const CStack * stack, bool addOccupiable, std::vector<THex> * attackable = NULL)=0; //returns numbers of hexes reachable by creature with id ID
virtual std::vector<int> battleGetDistances(const CStack * stack, THex hex = THex::INVALID, THex * predecessors = NULL)=0; //returns vector of distances to [dest hex number]
virtual bool battleCanShoot(const CStack * stack, THex dest)=0; //returns true if unit with id ID can shoot to dest
virtual bool battleCanCastSpell()=0; //returns true, if caller can cast a spell
virtual SpellCasting::ESpellCastProblem battleCanCastThisSpell(const CSpell * spell)=0; //determines if given spell can be casted (and returns problem description)
virtual bool battleCanFlee()=0; //returns true if caller can flee from the battle
virtual int battleGetSurrenderCost()=0; //returns cost of surrendering battle, -1 if surrendering is not possible
virtual const CGTownInstance * battleGetDefendedTown()=0; //returns defended town if current battle is a siege, NULL instead
virtual ui8 battleGetWallState(int partOfWall)=0; //for determining state of a part of the wall; format: parameter [0] - keep, [1] - bottom tower, [2] - bottom wall, [3] - below gate, [4] - over gate, [5] - upper wall, [6] - uppert tower, [7] - gate; returned value: 1 - intact, 2 - damaged, 3 - destroyed; 0 - no battle
virtual int battleGetWallUnderHex(THex hex)=0; //returns part of destructible wall / gate / keep under given hex or -1 if not found
virtual TDmgRange battleEstimateDamage(const CStack * attacker, const CStack * defender, TDmgRange * retaliationDmg = NULL)=0; //estimates damage dealt by attacker to defender; it may be not precise especially when stack has randomly working bonuses; returns pair <min dmg, max dmg>
virtual ui8 battleGetSiegeLevel()=0; //returns 0 when there is no siege, 1 if fort, 2 is citadel, 3 is castle
virtual const CGHeroInstance * battleGetFightingHero(ui8 side) const =0; //returns hero corresponding to given side (0 - attacker, 1 - defender)
virtual si8 battleHasDistancePenalty(const CStack * stack, THex destHex) =0; //checks if given stack has distance penalty
virtual si8 battleHasWallPenalty(const CStack * stack, THex destHex) =0; //checks if given stack has wall penalty
virtual si8 battleCanTeleportTo(const CStack * stack, THex destHex, int telportLevel) =0; //checks if teleportation of given stack to given position can take place
virtual si8 battleGetTacticDist() =0; //returns tactic distance for calling player or 0 if player is not in tactic phase
virtual ui8 battleGetMySide() =0; //return side of player in battle (attacker/defender)
virtual bool battleMakeTacticAction(BattleAction * action) =0; // performs tactic phase actions
//convienience methods using the ones above
TStacks battleGetAllStacks() //returns all stacks, alive or dead or undead or mechanical :)
{
return battleGetStacks(MINE_AND_ENEMY, false);
}
};
class ICallback : public virtual IBattleCallback
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)
virtual bool dismissHero(const CGHeroInstance * hero)=0; //dismisses given hero; true - successfuly, false - not successfuly
virtual void dig(const CGObjectInstance *hero)=0;
virtual void castSpell(const CGHeroInstance *hero, int spellID, const int3 &pos = int3(-1, -1, -1))=0; //cast adventure map spell
//town
virtual void recruitHero(const CGObjectInstance *townOrTavern, const CGHeroInstance *hero)=0;
virtual bool buildBuilding(const CGTownInstance *town, si32 buildingID)=0;
virtual void recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount, si32 level=-1)=0;
virtual bool upgradeCreature(const CArmedInstance *obj, int stackPos, int newID=-1)=0; //if newID==-1 then best possible upgrade will be made
virtual void swapGarrisonHero(const CGTownInstance *town)=0;
virtual void trade(const CGObjectInstance *market, int mode, int id1, int id2, int val1, const CGHeroInstance *hero = NULL)=0; //mode==0: sell val1 units of id1 resource for id2 resiurce
virtual void selectionMade(int selection, int asker) =0;
virtual int swapCreatures(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2)=0;//swaps creatures between two posiibly different garrisons // TODO: AI-unsafe code - fix it!
virtual int mergeStacks(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2)=0;//joins first stack tothe second (creatures must be same type)
virtual int swapCreatures(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2)=0;//swaps creatures between two possibly different garrisons // TODO: AI-unsafe code - fix it!
virtual int mergeStacks(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2)=0;//joins first stack to the second (creatures must be same type)
virtual int splitStack(const CArmedInstance *s1, const CArmedInstance *s2, int p1, int p2, int val)=0;//split creatures from the first stack
virtual bool swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHeroInstance * hero2, ui16 pos2)=0; //swaps artifacts between two given heroes
virtual bool assembleArtifacts(const CGHeroInstance * hero, ui16 artifactSlot, bool assemble, ui32 assembleTo)=0;
@ -148,124 +79,43 @@ public:
virtual void setFormation(const CGHeroInstance * hero, bool tight)=0;
virtual void setSelection(const CArmedInstance * obj)=0;
virtual void save(const std::string &fname) = 0;
virtual void sendMessage(const std::string &mess) = 0;
virtual void buildBoat(const IShipyard *obj) = 0;
//get info
virtual bool verifyPath(CPath * path, bool blockSea)const =0;
virtual int getDate(int mode=0)const =0; //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month
virtual std::vector< std::vector< std::vector<unsigned char> > > & getVisibilityMap()const =0; //returns visibility map (TODO: make it const)
virtual int getResourceAmount(int type)const =0;
virtual bool isVisible(int3 pos)const =0;
virtual int getMyColor()const =0;
virtual int getHeroSerial(const CGHeroInstance * hero)const =0;
virtual const StartInfo * getStartInfo()const =0;
virtual const CMapHeader * getMapHeader()const =0;
virtual int getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const =0; //when called during battle, takes into account creatures' spell cost reduction
virtual int estimateSpellDamage(const CSpell * sp, const CGHeroInstance * hero) const =0; //estimates damage of given spell; returns 0 if spell causes no dmg
virtual void getThievesGuildInfo(SThievesGuildInfo & thi, const CGObjectInstance * obj)=0; //get thieves' guild info obtainable while visiting given object
virtual int3 getGrailPos(float &outKnownRatio)=0;
virtual int getPlayerStatus(int player) const = 0; //-1 if no such player
//hero
virtual int howManyHeroes(bool includeGarrisoned = true)const =0;
virtual const CGHeroInstance * getHeroInfo(int val, int mode=2)const =0; //mode = 0 -> val = serial; mode = 1 -> val = ID
virtual std::vector < const CGHeroInstance *> getHeroesInfo(bool onlyOur=true)const =0;
virtual bool getHeroInfo(const CGObjectInstance *hero, InfoAboutHero &dest) const = 0;
virtual bool getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath &ret)=0;
virtual const CGPathNode *getPathInfo(int3 tile)=0; //uses main, client pathfinder info
virtual bool getPath2(int3 dest, CGPath &ret)=0; //uses main, client pathfinder info
virtual void calculatePaths(const CGHeroInstance *hero, CPathsInfo &out, int3 src = int3(-1,-1,-1), int movement = -1) =0;
virtual void recalculatePaths()=0; //updates main, client pathfinder info (should be called when moving hero is over)
virtual void dig(const CGObjectInstance *hero)=0;
virtual void castSpell(const CGHeroInstance *hero, int spellID, const int3 &pos = int3(-1, -1, -1))=0; //cast adventure map spell
//map
virtual std::vector < const CGDwelling * > getMyDwellings() const =0; //returns all dwellings that belong to player
virtual std::vector < const CGObjectInstance * > getMyObjects() const =0; //returns all objects flagged by belonging player
virtual std::vector < const CGObjectInstance * > getBlockingObjs(int3 pos)const =0;
virtual std::vector < const CGObjectInstance * > getVisitableObjs(int3 pos)const =0;
virtual std::vector < const CGObjectInstance * > getFlaggableObjects(int3 pos) const =0;
virtual std::vector < std::string > getObjDescriptions(int3 pos)const =0; //returns descriptions of objects at pos in order from the lowest to the highest
//town
virtual int howManyTowns()const =0;
virtual const CGTownInstance * getTownInfo(int val, bool mode)const =0; //mode = 0 -> val = player town serial; mode = 1 -> val = object id (serial)
virtual std::vector < const CGTownInstance *> getTownsInfo(bool onlyOur=true) const=0;
virtual std::vector<const CGHeroInstance *> getAvailableHeroes(const CGObjectInstance * townOrTavern) const =0; //heroes that can be recruited
virtual std::string getTavernGossip(const CGObjectInstance * townOrTavern) const =0;
virtual int canBuildStructure(const CGTownInstance *t, int ID) =0;//// 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
virtual std::set<int> getBuildingRequiments(const CGTownInstance *t, int ID) =0;
virtual bool getTownInfo(const CGObjectInstance *town, InfoAboutTown &dest) const = 0;
virtual UpgradeInfo getUpgradeInfo(const CArmedInstance *obj, int stackPos)const =0;
virtual const CCreatureSet* getGarrison(const CGObjectInstance *obj)const =0;
virtual int3 getMapSize() const =0; //returns size of map - z is 1 for one - level map and 2 for two level map
virtual const TerrainTile * getTileInfo(int3 tile) const = 0;
virtual int getPlayerRelations(ui8 color1, ui8 color2) const =0;// 0 = enemy, 1 = ally, 2 = same player
};
class CBattleCallback : public virtual IBattleCallback
class CBattleCallback : public IBattleCallback, public CBattleInfoCallback
{
private:
CGameState * gs;
CBattleCallback(CGameState *GS, int Player, CClient *C);
protected:
template <typename T> void sendRequest(const T*request);
CClient *cl;
virtual bool hasAccess(int playerId) const;
int player;
//virtual bool hasAccess(int playerId) const;
public:
//battle
int battleGetBattlefieldType() OVERRIDE; // 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
int battleGetObstaclesAtTile(THex tile) OVERRIDE; //returns bitfield
std::vector<CObstacleInstance> battleGetAllObstacles() OVERRIDE; //returns all obstacles on the battlefield
const CStack * battleGetStackByID(int ID, bool onlyAlive = true) OVERRIDE; //returns stack info by given ID
const CStack * battleGetStackByPos(THex pos, bool onlyAlive = true) OVERRIDE; //returns stack info by given pos
THex battleGetPos(int stack) OVERRIDE; //returns position (tile ID) of stack
int battleMakeAction(BattleAction* action) OVERRIDE;//for casting spells by hero - DO NOT use it for moving active stack
TStacks battleGetStacks(EStackOwnership whose = MINE_AND_ENEMY, bool onlyAlive = true) OVERRIDE; //returns stacks on battlefield
void getStackQueue( std::vector<const CStack *> &out, int howMany ) OVERRIDE; //returns vector of stack in order of their move sequence
std::vector<THex> battleGetAvailableHexes(const CStack * stack, bool addOccupiable, std::vector<THex> * attackable = NULL) OVERRIDE; //returns numbers of hexes reachable by creature with id ID
std::vector<int> battleGetDistances(const CStack * stack, THex hex = THex::INVALID, THex * predecessors = NULL) OVERRIDE; //returns vector of distances to [dest hex number]; if predecessors is not null, it must point to BFIELD_SIZE * sizeof(int) of allocated memory
bool battleCanShoot(const CStack * stack, THex dest) OVERRIDE; //returns true if unit with id ID can shoot to dest
bool battleCanCastSpell() OVERRIDE; //returns true, if caller can cast a spell
SpellCasting::ESpellCastProblem battleCanCastThisSpell(const CSpell * spell) OVERRIDE; //determines if given spell can be casted (and returns problem description)
bool battleCanFlee() OVERRIDE; //returns true if caller can flee from the battle
int battleGetSurrenderCost() OVERRIDE; //returns cost of surrendering battle, -1 if surrendering is not possible
const CGTownInstance * battleGetDefendedTown() OVERRIDE; //returns defended town if current battle is a siege, NULL instead
ui8 battleGetWallState(int partOfWall) OVERRIDE; //for determining state of a part of the wall; format: parameter [0] - keep, [1] - bottom tower, [2] - bottom wall, [3] - below gate, [4] - over gate, [5] - upper wall, [6] - uppert tower, [7] - gate; returned value: 1 - intact, 2 - damaged, 3 - destroyed; 0 - no battle
int battleGetWallUnderHex(THex hex) OVERRIDE; //returns part of destructible wall / gate / keep under given hex or -1 if not found
TDmgRange battleEstimateDamage(const CStack * attacker, const CStack * defender, TDmgRange * retaliationDmg = NULL) OVERRIDE; //estimates damage dealt by attacker to defender; it may be not precise especially when stack has randomly working bonuses; returns pair <min dmg, max dmg>
ui8 battleGetSiegeLevel() OVERRIDE; //returns 0 when there is no siege, 1 if fort, 2 is citadel, 3 is castle
const CGHeroInstance * battleGetFightingHero(ui8 side) const OVERRIDE; //returns hero corresponding ot given side (0 - attacker, 1 - defender)
si8 battleHasDistancePenalty(const CStack * stack, THex destHex) OVERRIDE; //checks if given stack has distance penalty
si8 battleHasWallPenalty(const CStack * stack, THex destHex) OVERRIDE; //checks if given stack has wall penalty
si8 battleCanTeleportTo(const CStack * stack, THex destHex, int telportLevel) OVERRIDE; //checks if teleportation of given stack to given position can take place
si8 battleGetTacticDist() OVERRIDE; //returns tactic distance for calling player or 0 if player is not in tactic phase
ui8 battleGetMySide() OVERRIDE; //return side of player in battle (attacker/defender)
bool battleMakeTacticAction(BattleAction * action) OVERRIDE; // performs tactic phase actions
friend class CCallback;
friend class CClient;
};
class CCallback : public ICallback, public CBattleCallback
class CCallback : public CPlayerSpecificInfoCallback, public IGameActionCallback, public CBattleCallback
{
private:
CCallback(CGameState * GS, int Player, CClient *C);
bool isVisible(int3 pos, int Player) const;
bool isVisible(const CGObjectInstance *obj, int Player) const;
protected:
virtual bool hasAccess(int playerId) const OVERRIDE;
public:
//client-specific functionalities (pathfinding)
virtual bool getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath &ret); //DEPRACATED!!!
virtual const CGPathNode *getPathInfo(int3 tile); //uses main, client pathfinder info
virtual bool getPath2(int3 dest, CGPath &ret); //uses main, client pathfinder info
virtual void calculatePaths(const CGHeroInstance *hero, CPathsInfo &out, int3 src = int3(-1,-1,-1), int movement = -1);
virtual void recalculatePaths(); //updates main, client pathfinder info (should be called when moving hero is over)
//commands
bool moveHero(const CGHeroInstance *h, int3 dst); //dst must be free, neighbouring tile (this function can move hero only by one tile)
bool teleportHero(const CGHeroInstance *who, const CGTownInstance *where);
@ -293,64 +143,8 @@ public:
void dig(const CGObjectInstance *hero);
void castSpell(const CGHeroInstance *hero, int spellID, const int3 &pos = int3(-1, -1, -1));
//get info
bool verifyPath(CPath * path, bool blockSea) const;
int getDate(int mode=0) const; //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month
std::vector< std::vector< std::vector<unsigned char> > > & getVisibilityMap() const; //returns visibility map (TODO: make it const)
const CGHeroInstance * getHeroInfo(int val, int mode=2) const; //mode = 0 -> val = serial; mode = 1 -> val = hero type id (subID); mode = 2 -> val = global object serial id (id)
const CGObjectInstance * getObjectInfo(int ID) const; //global object serial id (ID)
int getResourceAmount(int type) const;
std::vector<si32> getResourceAmount() const;
int howManyHeroes(bool includeGarrisoned = true) const;
const CGTownInstance * getTownInfo(int val, bool mode) const; //mode = 0 -> val = player town serial; mode = 1 -> val = object id (serial)
std::vector < const CGTownInstance *> getTownsInfo(bool onlyOur=true) const;
int howManyTowns()const;
std::vector < std::string > getObjDescriptions(int3 pos) const; //returns descriptions of objects at pos in order from the lowest to the highest
std::vector < const CGHeroInstance *> getHeroesInfo(bool onlyOur=true) const;
bool isVisible(int3 pos) const;
int getMyColor() const;
int getHeroSerial(const CGHeroInstance * hero) const;
//int getMySerial() const;
const CCreatureSet* getGarrison(const CGObjectInstance *obj) const;
UpgradeInfo getUpgradeInfo(const CArmedInstance *obj, int stackPos) const;
const StartInfo * getStartInfo() const;
const CMapHeader * getMapHeader()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
void getThievesGuildInfo(SThievesGuildInfo & thi, const CGObjectInstance * obj); //get thieves' guild info obtainable while visiting given object
int3 getGrailPos(float &outKnownRatio); //returns pos and (via arg) percent of discovered obelisks; TODO: relies on fairness of GUI/AI... :/
std::vector < const CGDwelling * > getMyDwellings() const; //returns all dwellings that belong to player
std::vector < const CGObjectInstance * > getMyObjects() const; //returns all objects flagged by belonging player
std::vector < const CGObjectInstance * > getBlockingObjs(int3 pos) const;
std::vector < const CGObjectInstance * > getVisitableObjs(int3 pos) const;
std::vector < const CGObjectInstance * > getFlaggableObjects(int3 pos) const;
int3 getMapSize() const; //returns size of map - z is 1 for one - level map and 2 for two level map
std::vector<const CGHeroInstance *> getAvailableHeroes(const CGObjectInstance * townOrTavern) const; //heroes that can be recruited
std::string getTavernGossip(const CGObjectInstance * townOrTavern) const;
const TerrainTile * getTileInfo(int3 tile) const;
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);
bool getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath &ret);
const CGPathNode *getPathInfo(int3 tile);
bool getPath2(int3 dest, CGPath &ret);
void calculatePaths(const CGHeroInstance *hero, CPathsInfo &out, int3 src = int3(-1,-1,-1), int movement = -1); //calculates possible paths for hero, by default uses current hero position and movement left;
void recalculatePaths(); //updates pathfinder info (should be called when moving hero is over)
bool getHeroInfo(const CGObjectInstance *hero, InfoAboutHero &dest) const;
bool getTownInfo(const CGObjectInstance *town, InfoAboutTown &dest) const;
int3 guardingCreaturePosition (int3 pos) const;
int getPlayerStatus(int player) const;
int getPlayerRelations(ui8 color1, ui8 color2) const;// 0 = enemy, 1 = ally, 2 = same player
//XXX hmmm _tmain on _GNUC_ wtf?
//friends
friend class CClient;
#ifndef __GNUC__
friend int _tmain(int argc, _TCHAR* argv[]);
#else
friend int main(int argc, char** argv);
#endif
};
#endif // __CCALLBACK_H__

View File

@ -18,7 +18,7 @@
using namespace boost::logic;
class CCallback;
class IBattleCallback;
class CBattleCallback;
class ICallback;
class CGlobalAI;
struct Component;
@ -63,7 +63,7 @@ public:
virtual ~CBattleGameInterface() {};
virtual void init(IBattleCallback * CB){};
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
@ -74,7 +74,7 @@ public:
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 beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
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
@ -118,7 +118,7 @@ public:
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(ICallback * CB){};
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){}

View File

@ -1771,6 +1771,9 @@ void CAdvMapInt::startTurn()
void CAdvMapInt::tileLClicked(const int3 &mp)
{
if(!LOCPLINT->cb->isVisible(mp))
return;
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);
@ -1852,6 +1855,13 @@ void CAdvMapInt::tileLClicked(const int3 &mp)
void CAdvMapInt::tileHovered(const int3 &tile)
{
if(!LOCPLINT->cb->isVisible(tile))
{
CCS->curh->changeGraphic(0, 0);
statusbar.clear();
return;
}
std::vector<std::string> temp = LOCPLINT->cb->getObjDescriptions(tile);
if (temp.size())
{
@ -2040,6 +2050,11 @@ void CAdvMapInt::tileRClicked(const int3 &mp)
leaveCastingMode();
return;
}
if(!LOCPLINT->cb->isVisible(mp))
{
CRClickPopup::createAndPush(VLC->generaltexth->allTexts[61]); //Uncharted Territory
return;
}
std::vector < const CGObjectInstance * > objs = LOCPLINT->cb->getBlockingObjs(mp);
if(!objs.size())

View File

@ -3452,7 +3452,7 @@ void CBattleInterface::endAction(const BattleAction* action)
// std::set<const CStack *> stacks;
// stacks.insert(LOCPLINT->cb->battleGetStackByID(action->stackNumber));
// stacks.insert(LOCPLINT->cb->battleGetStackByPos(action->destinationTile));
TStacks stacks = curInt->cb->battleGetStacks(IBattleCallback::MINE_AND_ENEMY);
TStacks stacks = curInt->cb->battleGetStacks(CBattleCallback::MINE_AND_ENEMY);
BOOST_FOREACH(const CStack *s, stacks)
{
@ -3612,7 +3612,7 @@ static bool immobile(const CStack *s)
void CBattleInterface::bTacticNextStack()
{
TStacks stacksOfMine = curInt->cb->battleGetStacks(IBattleCallback::ONLY_MINE);
TStacks stacksOfMine = curInt->cb->battleGetStacks(CBattleCallback::ONLY_MINE);
stacksOfMine.erase(std::remove_if(stacksOfMine.begin(), stacksOfMine.end(), &immobile), stacksOfMine.end());
TStacks::iterator it = vstd::find(stacksOfMine, activeStack);
if(it != stacksOfMine.end() && ++it != stacksOfMine.end())

View File

@ -976,7 +976,7 @@ void CCastleInterface::showAll(SDL_Surface *to)
void CCastleInterface::castleTeleport(int where)
{
const CGTownInstance * dest = LOCPLINT->cb->getTownInfo(where, 1);
const CGTownInstance * dest = LOCPLINT->cb->getTown(where);
LOCPLINT->cb->teleportHero(town->visitingHero, dest);
}
@ -1815,7 +1815,7 @@ CBlacksmithDialog::CBlacksmithDialog(bool possible, int creMachineID, int aid, i
cancel = new AdventureMapButton(text,"",boost::bind(&CBlacksmithDialog::close, this), 224, 312,"ICANCEL.DEF",SDLK_ESCAPE);
if(possible)
buy->callback += boost::bind(&CCallback::buyArtifact,LOCPLINT->cb,LOCPLINT->cb->getHeroInfo(hid,2),aid);
buy->callback += boost::bind(&CCallback::buyArtifact,LOCPLINT->cb,LOCPLINT->cb->getHero(hid),aid);
else
buy->block(true);

View File

@ -130,7 +130,7 @@ CPlayerInterface::~CPlayerInterface()
LOCPLINT = NULL;
}
void CPlayerInterface::init(ICallback * CB)
void CPlayerInterface::init(CCallback * CB)
{
cb = dynamic_cast<CCallback*>(CB);
if(observerInDuelMode)
@ -234,7 +234,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
if(LOCPLINT != this)
return;
boost::unique_lock<boost::recursive_mutex> un(*pim);
const CGHeroInstance * ho = cb->getHeroInfo(details.id); //object representing this hero
const CGHeroInstance * ho = cb->getHero(details.id); //object representing this hero
int3 hp = details.start;
adventureInt->centerOn(ho); //actualizing screen pos
@ -1194,7 +1194,7 @@ void CPlayerInterface::objectPropertyChanged(const SetObjectProperty * sop)
boost::unique_lock<boost::recursive_mutex> un(*pim);
if(sop->what == ObjProperty::OWNER)
{
const CGObjectInstance * obj = cb->getObjectInfo(sop->id);
const CGObjectInstance * obj = cb->getObj(sop->id);
std::set<int3> pos = obj->getBlockedPos();
for(std::set<int3>::const_iterator it = pos.begin(); it != pos.end(); ++it)
{

View File

@ -244,7 +244,7 @@ public:
void openHeroWindow(const CGHeroInstance * hero); //shows hero window with given hero
SDL_Surface * infoWin(const CGObjectInstance * specific); //specific=0 => draws info about selected town/hero
void updateInfo(const CGObjectInstance * specific);
void init(ICallback * CB);
void init(CCallback * CB);
int3 repairScreenPos(int3 pos); //returns position closest to pos we can center screen on
void showInfoDialog(const std::string &text, const std::vector<SComponent*> & components = std::vector<SComponent*>(), int soundID = 0, bool delComps = false);
void showYesNoDialog(const std::string &text, const std::vector<SComponent*> & components, CFunctionList<void()> onYes, CFunctionList<void()> onNo, bool DelComps); //deactivateCur - whether current main interface should be deactivated; delComps - if components will be deleted on window close

View File

@ -581,7 +581,7 @@ Uint8 CSpellWindow::pagesWithinCurrentTab()
void CSpellWindow::teleportTo( int town, const CGHeroInstance * hero )
{
const CGTownInstance * dest = LOCPLINT->cb->getTownInfo(town, 1);
const CGTownInstance * dest = LOCPLINT->cb->getTown(town);
LOCPLINT->cb->castSpell(hero, Spells::TOWN_PORTAL, dest->visitablePos());
}
@ -718,7 +718,7 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
double dist = -1;
for (int g=0; g<Towns.size(); ++g)
{
const CGTownInstance * dest = LOCPLINT->cb->getTownInfo(Towns[g]->id, 1);
const CGTownInstance * dest = LOCPLINT->cb->getTown(Towns[g]->id);
double curDist = dest->pos.dist2d(h->pos);
if (nearest == -1 || curDist < dist)
{
@ -730,7 +730,7 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[123]);
else
{
const CGTownInstance * town = LOCPLINT->cb->getTownInfo(Towns[nearest]->id, 1);
const CGTownInstance * town = LOCPLINT->cb->getTown(Towns[nearest]->id);
LOCPLINT->cb->castSpell(h, spell, town->visitablePos());// - town->getVisitableOffset());
}
}

View File

@ -184,7 +184,8 @@ void CGarrisonSlot::clickLeft(tribool down, bool previousState)
{
if(owner->highlighted == this) //view info
{
UpgradeInfo pom = LOCPLINT->cb->getUpgradeInfo(getObj(), ID);
UpgradeInfo pom;
LOCPLINT->cb->getUpgradeInfo(getObj(), ID, pom);
bool canUpgrade = getObj()->tempOwner == LOCPLINT->playerID && pom.oldID>=0; //upgrade is possible
bool canDismiss = getObj()->tempOwner == LOCPLINT->playerID && (getObj()->stacksCount()>1 || !getObj()->needsLastStack());
@ -999,7 +1000,7 @@ CSelWindow::CSelWindow(const std::string &Text, int player, int charperline, con
buttons.back()->assignedKeys.insert(SDLK_ESCAPE); //last button - reacts on escape
if(buttons.size() > 1 && askID >= 0) //cancel button functionality
buttons.back()->callback += boost::bind(&ICallback::selectionMade,LOCPLINT->cb,0,askID);
buttons.back()->callback += boost::bind(&CCallback::selectionMade,LOCPLINT->cb,0,askID);
for(int i=0;i<comps.size();i++)
{
@ -5729,8 +5730,8 @@ void CExchangeWindow::prepareBackground()
CExchangeWindow::CExchangeWindow(si32 hero1, si32 hero2) : bg(NULL)
{
char bufor[400];
heroInst[0] = LOCPLINT->cb->getHeroInfo(hero1, 2);
heroInst[1] = LOCPLINT->cb->getHeroInfo(hero2, 2);
heroInst[0] = LOCPLINT->cb->getHero(hero1);
heroInst[1] = LOCPLINT->cb->getHero(hero2);
prepareBackground();
pos.x = screen->w/2 - bg->w/2;
@ -6388,7 +6389,8 @@ void CHillFortWindow::updateGarrisons()
int newState = getState(i);
if (newState != -1)
{
UpgradeInfo info = LOCPLINT->cb->getUpgradeInfo(hero, i);
UpgradeInfo info;
LOCPLINT->cb->getUpgradeInfo(hero, i, info);
if (info.newID.size())//we have upgrades here - update costs
for(std::set<std::pair<int,int> >::iterator it=info.cost[0].begin(); it!=info.cost[0].end(); it++)
{
@ -6427,7 +6429,8 @@ void CHillFortWindow::makeDeal(int slot)
for (int i=0; i<slotsCount; i++)
if ( slot ==i || ( slot == slotsCount && currState[i] == 2 ) )//this is activated slot or "upgrade all"
{
UpgradeInfo info = LOCPLINT->cb->getUpgradeInfo(hero, i);
UpgradeInfo info;
LOCPLINT->cb->getUpgradeInfo(hero, i, info);
LOCPLINT->cb->upgradeCreature(hero, i, info.newID[0]);
}
break;
@ -6506,7 +6509,8 @@ int CHillFortWindow::getState(int slot)
if (hero->slotEmpty(slot))//no creature here
return -1;
UpgradeInfo info = LOCPLINT->cb->getUpgradeInfo(hero, slot);
UpgradeInfo info;
LOCPLINT->cb->getUpgradeInfo(hero, slot, info);
if (!info.newID.size())//already upgraded
return 1;

View File

@ -145,6 +145,62 @@ public:
}
} *objCaller = NULL;
InfoAboutTown::InfoAboutTown()
{
tType = NULL;
details = NULL;
fortLevel = 0;
owner = -1;
}
InfoAboutTown::~InfoAboutTown()
{
delete details;
}
void InfoAboutTown::initFromTown( const CGTownInstance *t, bool detailed )
{
obj = t;
army = ArmyDescriptor(t->getUpperArmy(), detailed);
built = t->builded;
fortLevel = t->fortLevel();
name = t->name;
tType = t->town;
owner = t->tempOwner;
if(detailed)
{
//include details about hero
details = new Details;
details->goldIncome = t->dailyIncome();
details->customRes = vstd::contains(t->builtBuildings, 15);
details->hallLevel = t->hallLevel();
details->garrisonedHero = t->garrisonHero;
}
//TODO: adjust undetailed info about army to our count of thieves guilds
}
void InfoAboutTown::initFromGarrison(const CGGarrison *garr, bool detailed)
{
obj = garr;
fortLevel = 0;
army = ArmyDescriptor(garr, detailed);
name = VLC->generaltexth->names[33]; // "Garrison"
owner = garr->tempOwner;
built = false;
tType = NULL;
// Show detailed info only to owning player.
if(detailed)
{
details = new InfoAboutTown::Details;
details->customRes = false;
details->garrisonedHero = false;
details->goldIncome = -1;
details->hallLevel = -1;
}
}
void MetaString::getLocalString(const std::pair<ui8,ui32> &txt, std::string &dst) const
{
int type = txt.first, ser = txt.second;
@ -2376,7 +2432,10 @@ bool CGameState::isVisible(int3 pos, int player)
bool CGameState::isVisible( const CGObjectInstance *obj, int player )
{
if(player == 255) //neutral player
if(player == -1)
return true;
if(player == 255) //neutral player -> TODO ??? needed?
return false;
//object is visible when at least one blocked tile is visible
for(int fx=0; fx<8; ++fx)

View File

@ -64,6 +64,7 @@ class CHeroClass;
class CCampaign;
class CCampaignState;
class IModableArt;
class CGGarrison;
namespace boost
{
@ -102,6 +103,32 @@ public:
void initFromHero(const CGHeroInstance *h, bool detailed);
};
/// Struct which holds a short information about a town
struct DLL_EXPORT InfoAboutTown
{
struct Details
{
int hallLevel, goldIncome;
bool customRes;
bool garrisonedHero;
} *details;
const CArmedInstance * obj;
char fortLevel; //0 - none
char owner;
std::string name;
CTown *tType;
bool built;
ArmyDescriptor army; //numbers of creatures are valid only if details
InfoAboutTown();
~InfoAboutTown();
void initFromTown(const CGTownInstance *t, bool detailed);
void initFromGarrison(const CGGarrison *garr, bool detailed);
};
// typedef si32 TResourceUnit;
// typedef std::vector<si32> TResourceVector;
// typedef std::set<si32> TResourceSet;
@ -177,8 +204,6 @@ public:
};
struct UpgradeInfo
{
int oldID; //creature to be upgraded

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,7 @@
#include <set>
#include "../client/FunctionList.h"
#include "CCreatureSet.h"
#include "BattleState.h"
/*
* IGameCallback.h, part of VCMI engine
@ -40,42 +41,192 @@ class CTown;
struct StackLocation;
struct ArtifactLocation;
class CArtifactInstance;
struct StartInfo;
struct InfoAboutTown;
struct UpgradeInfo;
struct SThievesGuildInfo;
struct CPath;
class CGDwelling;
struct InfoAboutHero;
class CMapHeader;
struct BattleAction;
class CStack;
/// Interface class for handling general game logic and actions
class DLL_EXPORT IGameCallback
typedef std::vector<const CStack*> TStacks;
class CCallbackBase
{
protected:
CGameState *gs;
int player; // -1 gives access to all information, otherwise limited to knowledge of given player
CCallbackBase(CGameState *GS, int Player)
: gs(GS), player(Player)
{}
CCallbackBase()
: gs(NULL), player(-1)
{}
};
class DLL_EXPORT CBattleInfoCallback : public virtual CCallbackBase
{
public:
enum EStackOwnership
{
ONLY_MINE, ONLY_ENEMY, MINE_AND_ENEMY
};
//battle
int battleGetBattlefieldType(); // 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
int battleGetObstaclesAtTile(THex tile); //returns bitfield
std::vector<CObstacleInstance> battleGetAllObstacles(); //returns all obstacles on the battlefield
const CStack * battleGetStackByID(int ID, bool onlyAlive = true); //returns stack info by given ID
const CStack * battleGetStackByPos(THex pos, bool onlyAlive = true); //returns stack info by given pos
THex battleGetPos(int stack); //returns position (tile ID) of stack
TStacks battleGetStacks(EStackOwnership whose = MINE_AND_ENEMY, bool onlyAlive = true); //returns stacks on battlefield
void getStackQueue( std::vector<const CStack *> &out, int howMany ); //returns vector of stack in order of their move sequence
std::vector<THex> battleGetAvailableHexes(const CStack * stack, bool addOccupiable, std::vector<THex> * attackable = NULL); //returns numbers of hexes reachable by creature with id ID
std::vector<int> battleGetDistances(const CStack * stack, THex hex = THex::INVALID, THex * predecessors = NULL); //returns vector of distances to [dest hex number]
bool battleCanShoot(const CStack * stack, THex dest); //returns true if unit with id ID can shoot to dest
bool battleCanCastSpell(); //returns true, if caller can cast a spell
SpellCasting::ESpellCastProblem battleCanCastThisSpell(const CSpell * spell); //determines if given spell can be casted (and returns problem description)
bool battleCanFlee(); //returns true if caller can flee from the battle
int battleGetSurrenderCost(); //returns cost of surrendering battle, -1 if surrendering is not possible
const CGTownInstance * battleGetDefendedTown(); //returns defended town if current battle is a siege, NULL instead
ui8 battleGetWallState(int partOfWall); //for determining state of a part of the wall; format: parameter [0] - keep, [1] - bottom tower, [2] - bottom wall, [3] - below gate, [4] - over gate, [5] - upper wall, [6] - uppert tower, [7] - gate; returned value: 1 - intact, 2 - damaged, 3 - destroyed; 0 - no battle
int battleGetWallUnderHex(THex hex); //returns part of destructible wall / gate / keep under given hex or -1 if not found
TDmgRange battleEstimateDamage(const CStack * attacker, const CStack * defender, TDmgRange * retaliationDmg = NULL); //estimates damage dealt by attacker to defender; it may be not precise especially when stack has randomly working bonuses; returns pair <min dmg, max dmg>
ui8 battleGetSiegeLevel(); //returns 0 when there is no siege, 1 if fort, 2 is citadel, 3 is castle
const CGHeroInstance * battleGetFightingHero(ui8 side) const; //returns hero corresponding to given side (0 - attacker, 1 - defender)
si8 battleHasDistancePenalty(const CStack * stack, THex destHex); //checks if given stack has distance penalty
si8 battleHasWallPenalty(const CStack * stack, THex destHex); //checks if given stack has wall penalty
si8 battleCanTeleportTo(const CStack * stack, THex destHex, int telportLevel); //checks if teleportation of given stack to given position can take place
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
TStacks battleGetAllStacks() //returns all stacks, alive or dead or undead or mechanical :)
{
return battleGetStacks(MINE_AND_ENEMY, false);
}
};
class DLL_EXPORT CGameInfoCallback : public virtual CCallbackBase
{
protected:
CGameInfoCallback();
CGameInfoCallback(CGameState *GS, int Player);
bool hasAccess(int playerId) const;
bool isVisible(int3 pos, int Player) const;
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 isOwnedOrVisited(const CGObjectInstance *obj) const;
public:
//various
int getDate(int mode=0)const; //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month
const StartInfo * getStartInfo()const;
bool isAllowed(int type, int id); //type: 0 - spell; 1- artifact; 2 - secondary skill
//player
const PlayerState * getPlayerState(int color) 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
void getThievesGuildInfo(SThievesGuildInfo & thi, const CGObjectInstance * obj); //get thieves' guild info obtainable while visiting given object
int getPlayerStatus(int player) const; //-1 if no such player
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
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;
//objects
const CGObjectInstance* getObj(int objid, bool verbose = true) const;
std::vector <const CGObjectInstance * > getBlockingObjs(int3 pos)const;
std::vector <const CGObjectInstance * > getVisitableObjs(int3 pos)const;
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;
//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;
//town
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
std::string getTavernGossip(const CGObjectInstance * townOrTavern) const;
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;
};
class DLL_EXPORT CPlayerSpecificInfoCallback : public CGameInfoCallback
{
public:
int howManyTowns() const;
int howManyHeroes(bool includeGarrisoned = true) const;
int3 getGrailPos(float &outKnownRatio);
int getMyColor() const;
std::vector <const CGTownInstance *> getTownsInfo(bool onlyOur = true) const; //true -> only owned; false -> all visible
int getHeroSerial(const CGHeroInstance * hero)const;
const CGTownInstance* getTownBySerial(int serialId) const; // serial id is [0, number of towns)
const CGHeroInstance* getHeroBySerial(int serialId) const; // serial id is [0, number of heroes)
std::vector <const CGHeroInstance *> getHeroesInfo(bool onlyOur = true) const; //true -> only owned; false -> all visible
std::vector <const CGDwelling *> getMyDwellings() const; //returns all dwellings that belong to player
std::vector <const CGObjectInstance * > getMyObjects() const; //returns all objects flagged by belonging player
int getResourceAmount(int type)const;
std::vector<si32> getResourceAmount() const;
const std::vector< std::vector< std::vector<unsigned char> > > & getVisibilityMap()const; //returns visibility map
const PlayerSettings * getPlayerSettings(int color) const;
};
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
ui16 getRandomArt (int flags);
ui16 getArtSync (ui32 rand, int flags); //synchronous
void pickAllowedArtsSet(std::vector<const CArtifact*> &out); //gives 3 treasures, 3 minors, 1 major -> used by Black Market and Artifact Merchant
void erasePickedArt (si32 id);
void getAllowedSpells(std::vector<ui16> &out, ui16 level);
};
/// Interface class for handling general game logic and actions
class DLL_EXPORT IGameCallback : public CPrivilagedInfoCallback
{
public:
virtual ~IGameCallback(){};
CGameState *const gameState ();
virtual int getOwner(int heroID);
virtual int getResource(int player, int which);
virtual int getDate(int mode=0); ////mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month
virtual const CGObjectInstance* getObj(int objid, bool verbose = true);
virtual const CGHeroInstance* getHero(int objid);
virtual const CGTownInstance* getTown(int objid);
virtual const CGHeroInstance* getSelectedHero(int player); //NULL if no hero is selected
virtual const CGObjectInstance *getObjByQuestIdentifier(int identifier); //NULL if object has been removed (eg. killed)
virtual int getCurrentPlayer()=0;
virtual int getSelectedHero()=0;
virtual const PlayerSettings * getPlayerSettings(int color);
virtual int getHeroCount(int player, bool includeGarrisoned);
virtual void getTilesInRange(boost::unordered_set<int3, ShashInt3> &tiles, int3 pos, int radious, int player=-1, int mode=0); //mode 1 - only unrevealed tiles; mode 0 - all, mode -1 - only unrevealed
virtual void getAllTiles (boost::unordered_set<int3, ShashInt3> &tiles, int player=-1, int level=-1, int surface=0); //returns all tiles on given level (-1 - both levels, otherwise number of level); surface: 0 - land and water, 1 - only land, 2 - only water
virtual void getFreeTiles (std::vector<int3> &tiles); //used for random spawns
virtual bool isAllowed(int type, int id); //type: 0 - spell; 1- artifact; 2 - secondary skill
virtual ui16 getRandomArt (int flags);
virtual ui16 getArtSync (ui32 rand, int flags); //synchronic
virtual void pickAllowedArtsSet(std::vector<const CArtifact*> &out); //gives 3 treasures, 3 minors, 1 major -> used by Black Market and Artifact Merchant
virtual void erasePickedArt (si32 id);
virtual void getAllowedSpells(std::vector<ui16> &out, ui16 level);
virtual int3 getMapSize(); //returns size of the map
virtual TerrainTile * getTile(int3 pos);
virtual const PlayerState * getPlayerState(int color);
virtual const CTown *getNativeTown(int color);
//do sth
virtual void changeSpells(int hid, bool give, const std::set<ui32> &spells)=0;
virtual bool removeObject(int objid)=0;
@ -112,13 +263,9 @@ public:
virtual void showCompInfo(ShowInInfobox * comp)=0;
virtual void heroVisitCastle(int obj, int heroID)=0;
virtual void stopHeroVisitCastle(int obj, int heroID)=0;
//virtual void giveHeroArtifact(int artid, int hid, int position)=0; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack
//virtual void giveNewArtifact(int hid, int position)=0;
//virtual bool removeArtifact(const CArtifact* art, int hid) = 0;
virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank = false, boost::function<void(BattleResult*)> cb = 0, const CGTownInstance *town = NULL)=0; //use hero=NULL for no hero
virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false)=0; //if any of armies is hero, hero will be used
virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, boost::function<void(BattleResult*)> cb = 0, bool creatureBank = false)=0; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle
//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 bool moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255)=0;
virtual void giveHeroBonus(GiveBonus * bonus)=0;

View File

@ -735,7 +735,7 @@ int CGameHandler::moveStack(int stack, THex dest)
CGameHandler::CGameHandler(void)
{
QID = 1;
gs = NULL;
//gs = NULL;
IObjectInterface::cb = this;
applier = new CApplier<CBaseForGHApply>;
registerTypes3(*applier);
@ -1563,11 +1563,6 @@ ui32 CGameHandler::showBlockingDialog( BlockingDialog *iw )
return 0;
}
int CGameHandler::getCurrentPlayer()
{
return gs->currentPlayer;
}
void CGameHandler::giveResource(int player, int which, int val)
{
if(!val) return; //don't waste time on empty call
@ -1710,11 +1705,6 @@ void CGameHandler::changeSpells( int hid, bool give, const std::set<ui32> &spell
sendAndApply(&cs);
}
int CGameHandler::getSelectedHero()
{
return IGameCallback::getSelectedHero(getCurrentPlayer())->id;
}
void CGameHandler::setObjProperty( int objid, int prop, si64 val )
{
SetObjectProperty sob;
@ -2476,8 +2466,8 @@ bool CGameHandler::garrisonSwap( si32 tid )
// Function moves artifact from src to dst. If dst is not a backpack and is already occupied, old dst art goes to backpack and is replaced.
bool CGameHandler::moveArtifact(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, ui16 destSlot)
{
CGHeroInstance *srcHero = gs->getHero(srcHeroID);
CGHeroInstance *destHero = gs->getHero(destHeroID);
const CGHeroInstance *srcHero = getHero(srcHeroID);
const CGHeroInstance *destHero = getHero(destHeroID);
ArtifactLocation src(srcHero, srcSlot), dst(destHero, destSlot);
// Make sure exchange is even possible between the two heroes.

View File

@ -127,11 +127,6 @@ public:
//////////////////////////////////////////////////////////////////////////
//from IGameCallback
//get info
int getCurrentPlayer() OVERRIDE;
int getSelectedHero() OVERRIDE;
//do sth
void changeSpells(int hid, bool give, const std::set<ui32> &spells) OVERRIDE;
bool removeObject(int objid) OVERRIDE;