mirror of
https://github.com/vcmi/vcmi.git
synced 2025-06-17 00:07:41 +02:00
Implemented Summon Boat spell.
This commit is contained in:
@ -121,7 +121,7 @@ int CCallback::getSpellCost(const CSpell * sp, const CGHeroInstance * caster) co
|
|||||||
return gs->curB->getSpellCost(sp, caster);
|
return gs->curB->getSpellCost(sp, caster);
|
||||||
|
|
||||||
//if there is no battle
|
//if there is no battle
|
||||||
return sp->costs[caster->getSpellSchoolLevel(sp)];
|
return caster->getSpellCost(sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CCallback::estimateSpellDamage(const CSpell * sp) const
|
int CCallback::estimateSpellDamage(const CSpell * sp) const
|
||||||
@ -954,6 +954,15 @@ si8 CCallback::battleGetStackLuck( int stackID )
|
|||||||
return gs->curB->Luck( gs->curB->getStack(stackID) );
|
return gs->curB->Luck( gs->curB->getStack(stackID) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CCallback::castSpell(const CGHeroInstance *hero, int spellID, const int3 &pos)
|
||||||
|
{
|
||||||
|
CastAdvSpell cas;
|
||||||
|
cas.hid = hero->id;
|
||||||
|
cas.sid = spellID;
|
||||||
|
cas.pos = pos;
|
||||||
|
sendRequest(&cas);
|
||||||
|
}
|
||||||
|
|
||||||
InfoAboutTown::InfoAboutTown()
|
InfoAboutTown::InfoAboutTown()
|
||||||
{
|
{
|
||||||
tType = NULL;
|
tType = NULL;
|
||||||
|
@ -128,6 +128,7 @@ public:
|
|||||||
virtual void calculatePaths(const CGHeroInstance *hero, CPathsInfo &out, int3 src = int3(-1,-1,-1), int movement = -1) =0;
|
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 recalculatePaths()=0; //updates main, client pathfinder info (should be called when moving hero is over)
|
||||||
virtual void dig(const CGObjectInstance *hero)=0;
|
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
|
//map
|
||||||
virtual std::vector < const CGObjectInstance * > getBlockingObjs(int3 pos)const =0;
|
virtual std::vector < const CGObjectInstance * > getBlockingObjs(int3 pos)const =0;
|
||||||
@ -227,6 +228,7 @@ public:
|
|||||||
void sendMessage(const std::string &mess);
|
void sendMessage(const std::string &mess);
|
||||||
void buildBoat(const IShipyard *obj);
|
void buildBoat(const IShipyard *obj);
|
||||||
void dig(const CGObjectInstance *hero);
|
void dig(const CGObjectInstance *hero);
|
||||||
|
void castSpell(const CGHeroInstance *hero, int spellID, const int3 &pos = int3(-1, -1, -1));
|
||||||
|
|
||||||
//get info
|
//get info
|
||||||
bool verifyPath(CPath * path, bool blockSea) const;
|
bool verifyPath(CPath * path, bool blockSea) const;
|
||||||
|
@ -668,7 +668,8 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
|
|||||||
{
|
{
|
||||||
if(!down && mySpell!=-1)
|
if(!down && mySpell!=-1)
|
||||||
{
|
{
|
||||||
int spellCost = owner->myInt->cb->getSpellCost(&CGI->spellh->spells[mySpell], owner->myHero);
|
const CSpell *sp = &CGI->spellh->spells[mySpell];
|
||||||
|
int spellCost = owner->myInt->cb->getSpellCost(sp, owner->myHero);
|
||||||
//we will cast a spell
|
//we will cast a spell
|
||||||
if(owner->myInt->battleInt && owner->myInt->cb->battleCanCastSpell() && spellCost <= owner->myHero->mana) //if battle window is open
|
if(owner->myInt->battleInt && owner->myInt->cb->battleCanCastSpell() && spellCost <= owner->myHero->mana) //if battle window is open
|
||||||
{
|
{
|
||||||
@ -676,15 +677,35 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
|
|||||||
owner->fexitb();
|
owner->fexitb();
|
||||||
owner->myInt->battleInt->castThisSpell(spell);
|
owner->myInt->battleInt->castThisSpell(spell);
|
||||||
}
|
}
|
||||||
else
|
else //adventure spell
|
||||||
{
|
{
|
||||||
//insufficient mana
|
//insufficient mana
|
||||||
if(spellCost > owner->myHero->mana)
|
if(spellCost > owner->myHero->mana)
|
||||||
{
|
{
|
||||||
std::vector<SComponent*> comps;
|
|
||||||
char msgBuf[500];
|
char msgBuf[500];
|
||||||
sprintf(msgBuf, CGI->generaltexth->allTexts[206].c_str(), spellCost, owner->myHero->mana);
|
sprintf(msgBuf, CGI->generaltexth->allTexts[206].c_str(), spellCost, owner->myHero->mana);
|
||||||
owner->myInt->showInfoDialog(std::string(msgBuf), comps);
|
owner->myInt->showInfoDialog(std::string(msgBuf));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int spell = mySpell;
|
||||||
|
const CGHeroInstance *h = owner->myHero;
|
||||||
|
owner->fexitb();
|
||||||
|
|
||||||
|
switch(spell)
|
||||||
|
{
|
||||||
|
case 0: //summon boat
|
||||||
|
{
|
||||||
|
int3 pos = h->bestLocation();
|
||||||
|
if(pos.x < 0)
|
||||||
|
{
|
||||||
|
LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[334]); //There is no place to put the boat.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOCPLINT->cb->castSpell(h, spell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -511,5 +511,11 @@ void CClient::handlePack( CPack * pack )
|
|||||||
delete pack;
|
delete pack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CClient::updatePaths()
|
||||||
|
{
|
||||||
|
const CGHeroInstance *h = getHero(getSelectedHero());
|
||||||
|
if (h)//if we have selected hero...
|
||||||
|
gs->calculatePaths(h, *pathInfo);
|
||||||
|
}
|
||||||
template void CClient::serialize( CISer<CLoadFile> &h, const int version );
|
template void CClient::serialize( CISer<CLoadFile> &h, const int version );
|
||||||
template void CClient::serialize( COSer<CSaveFile> &h, const int version );
|
template void CClient::serialize( COSer<CSaveFile> &h, const int version );
|
||||||
|
@ -113,6 +113,7 @@ public:
|
|||||||
void waitForServer();
|
void waitForServer();
|
||||||
CPack * retreivePack(); //gets from server next pack (allocates it with new)
|
CPack * retreivePack(); //gets from server next pack (allocates it with new)
|
||||||
void handlePack( CPack * pack ); //applies the given pack and deletes it
|
void handlePack( CPack * pack ); //applies the given pack and deletes it
|
||||||
|
void updatePaths();
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -107,8 +107,7 @@ void FoWChange::applyCl( CClient *cl )
|
|||||||
else
|
else
|
||||||
cl->playerint[player]->tileHidden(tiles);
|
cl->playerint[player]->tileHidden(tiles);
|
||||||
|
|
||||||
if (cl->IGameCallback::getSelectedHero(player))//if we have selected hero...
|
cl->updatePaths();
|
||||||
GS(cl)->calculatePaths(cl->IGameCallback::getSelectedHero(player), *cl->pathInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetAvailableHeroes::applyCl( CClient *cl )
|
void SetAvailableHeroes::applyCl( CClient *cl )
|
||||||
@ -146,6 +145,8 @@ void ChangeObjPos::applyCl( CClient *cl )
|
|||||||
CGObjectInstance *obj = GS(cl)->map->objects[objid];
|
CGObjectInstance *obj = GS(cl)->map->objects[objid];
|
||||||
if(flags & 1)
|
if(flags & 1)
|
||||||
CGI->mh->printObject(obj);
|
CGI->mh->printObject(obj);
|
||||||
|
|
||||||
|
cl->updatePaths();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerEndsGame::applyCl( CClient *cl )
|
void PlayerEndsGame::applyCl( CClient *cl )
|
||||||
|
@ -47,7 +47,6 @@ BankConfig CGPyramid::pyramidConfig;
|
|||||||
ui8 CGObelisk::obeliskCount; //how many obelisks are on map
|
ui8 CGObelisk::obeliskCount; //how many obelisks are on map
|
||||||
std::map<ui8, ui8> CGObelisk::visited; //map: color_id => how many obelisks has been visited
|
std::map<ui8, ui8> CGObelisk::visited; //map: color_id => how many obelisks has been visited
|
||||||
|
|
||||||
|
|
||||||
void IObjectInterface::onHeroVisit(const CGHeroInstance * h) const
|
void IObjectInterface::onHeroVisit(const CGHeroInstance * h) const
|
||||||
{};
|
{};
|
||||||
|
|
||||||
@ -687,6 +686,7 @@ int CGHeroInstance::getSpellSecLevel(int spell) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
CGHeroInstance::CGHeroInstance()
|
CGHeroInstance::CGHeroInstance()
|
||||||
|
: IBoatGenerator(this)
|
||||||
{
|
{
|
||||||
ID = HEROI_TYPE;
|
ID = HEROI_TYPE;
|
||||||
tacticFormationEnabled = inTownGarrison = false;
|
tacticFormationEnabled = inTownGarrison = false;
|
||||||
@ -1226,6 +1226,34 @@ const BonusList * CGHeroInstance::ownerBonuses() const
|
|||||||
return &p->bonuses;
|
return &p->bonuses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CGHeroInstance::getBoatType() const
|
||||||
|
{
|
||||||
|
int alignment = type->heroType / 6;
|
||||||
|
switch(alignment)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return 1; //good
|
||||||
|
case 1:
|
||||||
|
return 0; //evil
|
||||||
|
case 2:
|
||||||
|
return 2;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGHeroInstance::getOutOffsets(std::vector<int3> &offsets) const
|
||||||
|
{
|
||||||
|
static int3 dirs[] = { int3(0,1,0),int3(0,-1,0),int3(-1,0,0),int3(+1,0,0), int3(1,1,0),int3(-1,1,0),int3(1,-1,0),int3(-1,-1,0) };
|
||||||
|
for (size_t i = 0; i < ARRAY_COUNT(dirs); i++)
|
||||||
|
offsets += dirs[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
int CGHeroInstance::getSpellCost(const CSpell *sp) const
|
||||||
|
{
|
||||||
|
return sp->costs[getSpellSchoolLevel(sp)];
|
||||||
|
}
|
||||||
|
|
||||||
void CGDwelling::initObj()
|
void CGDwelling::initObj()
|
||||||
{
|
{
|
||||||
switch(ID)
|
switch(ID)
|
||||||
@ -5308,13 +5336,6 @@ void CGSirens::onHeroVisit( const CGHeroInstance * h ) const
|
|||||||
cb->showInfoDialog(&iw);
|
cb->showInfoDialog(&iw);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IShipyard::getBoatCost( std::vector<si32> &cost ) const
|
|
||||||
{
|
|
||||||
cost.resize(RESOURCE_QUANTITY);
|
|
||||||
cost[0] = 10;
|
|
||||||
cost[6] = 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
//bool IShipyard::validLocation() const
|
//bool IShipyard::validLocation() const
|
||||||
//{
|
//{
|
||||||
// std::vector<int3> offsets;
|
// std::vector<int3> offsets;
|
||||||
@ -5327,7 +5348,7 @@ void IShipyard::getBoatCost( std::vector<si32> &cost ) const
|
|||||||
// return false;
|
// return false;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
int3 IShipyard::bestLocation() const
|
int3 IBoatGenerator::bestLocation() const
|
||||||
{
|
{
|
||||||
std::vector<int3> offsets;
|
std::vector<int3> offsets;
|
||||||
getOutOffsets(offsets);
|
getOutOffsets(offsets);
|
||||||
@ -5339,12 +5360,7 @@ int3 IShipyard::bestLocation() const
|
|||||||
return int3(-1,-1,-1);
|
return int3(-1,-1,-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
IShipyard::IShipyard(const CGObjectInstance *O)
|
int IBoatGenerator::state() const
|
||||||
: o(O)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int IShipyard::state() const
|
|
||||||
{
|
{
|
||||||
int3 tile = bestLocation();
|
int3 tile = bestLocation();
|
||||||
TerrainTile *t = IObjectInterface::cb->getTile(tile);
|
TerrainTile *t = IObjectInterface::cb->getTile(tile);
|
||||||
@ -5358,6 +5374,30 @@ int IShipyard::state() const
|
|||||||
return 2; //blocked
|
return 2; //blocked
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int IBoatGenerator::getBoatType() const
|
||||||
|
{
|
||||||
|
//We make good ships by default
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IBoatGenerator::IBoatGenerator(const CGObjectInstance *O)
|
||||||
|
: o(O)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void IShipyard::getBoatCost( std::vector<si32> &cost ) const
|
||||||
|
{
|
||||||
|
cost.resize(RESOURCE_QUANTITY);
|
||||||
|
cost[0] = 10;
|
||||||
|
cost[6] = 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
IShipyard::IShipyard(const CGObjectInstance *O)
|
||||||
|
: IBoatGenerator(O)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
IShipyard * IShipyard::castFrom( CGObjectInstance *obj )
|
IShipyard * IShipyard::castFrom( CGObjectInstance *obj )
|
||||||
{
|
{
|
||||||
if(obj->ID == TOWNI_TYPE)
|
if(obj->ID == TOWNI_TYPE)
|
||||||
@ -5380,12 +5420,6 @@ const IShipyard * IShipyard::castFrom( const CGObjectInstance *obj )
|
|||||||
return castFrom(const_cast<CGObjectInstance*>(obj));
|
return castFrom(const_cast<CGObjectInstance*>(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
int IShipyard::getBoatType() const
|
|
||||||
{
|
|
||||||
//We make good ships by default
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
CGShipyard::CGShipyard()
|
CGShipyard::CGShipyard()
|
||||||
:IShipyard(this)
|
:IShipyard(this)
|
||||||
{
|
{
|
||||||
|
@ -115,18 +115,23 @@ public:
|
|||||||
static void postInit();//caleed after objs receive their initObj
|
static void postInit();//caleed after objs receive their initObj
|
||||||
};
|
};
|
||||||
|
|
||||||
class DLL_EXPORT IShipyard
|
class DLL_EXPORT IBoatGenerator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const CGObjectInstance *o;
|
const CGObjectInstance *o;
|
||||||
|
|
||||||
IShipyard(const CGObjectInstance *O);
|
IBoatGenerator(const CGObjectInstance *O);
|
||||||
virtual void getBoatCost(std::vector<si32> &cost) const;
|
|
||||||
virtual int getBoatType() const; //0 - evil (if a ship can be evil...?), 1 - good, 2 - neutral
|
virtual int getBoatType() const; //0 - evil (if a ship can be evil...?), 1 - good, 2 - neutral
|
||||||
virtual void getOutOffsets(std::vector<int3> &offsets) const =0; //offsets to obj pos when we boat can be placed
|
virtual void getOutOffsets(std::vector<int3> &offsets) const =0; //offsets to obj pos when we boat can be placed
|
||||||
//virtual bool validLocation() const; //returns true if there is a water tile near where boat can be placed
|
|
||||||
int3 bestLocation() const; //returns location when the boat should be placed
|
int3 bestLocation() const; //returns location when the boat should be placed
|
||||||
int state() const; //0 - can buid, 1 - there is already a boat at dest tile, 2 - dest tile is blocked, 3 - no water
|
int state() const; //0 - can buid, 1 - there is already a boat at dest tile, 2 - dest tile is blocked, 3 - no water
|
||||||
|
};
|
||||||
|
|
||||||
|
class DLL_EXPORT IShipyard : public IBoatGenerator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IShipyard(const CGObjectInstance *O);
|
||||||
|
virtual void getBoatCost(std::vector<si32> &cost) const;
|
||||||
|
|
||||||
static const IShipyard *castFrom(const CGObjectInstance *obj);
|
static const IShipyard *castFrom(const CGObjectInstance *obj);
|
||||||
static IShipyard *castFrom(CGObjectInstance *obj);
|
static IShipyard *castFrom(CGObjectInstance *obj);
|
||||||
@ -227,7 +232,7 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class DLL_EXPORT CGHeroInstance : public CArmedInstance
|
class DLL_EXPORT CGHeroInstance : public CArmedInstance, public IBoatGenerator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@ -287,6 +292,12 @@ public:
|
|||||||
int3 getSightCenter() const; //"center" tile from which the sight distance is calculated
|
int3 getSightCenter() const; //"center" tile from which the sight distance is calculated
|
||||||
int getSightRadious() const; //sight distance (should be used if player-owned structure)
|
int getSightRadious() const; //sight distance (should be used if player-owned structure)
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int getBoatType() const; //0 - evil (if a ship can be evil...?), 1 - good, 2 - neutral
|
||||||
|
void getOutOffsets(std::vector<int3> &offsets) const; //offsets to obj pos when we boat can be placed
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
const std::string &getBiography() const;
|
const std::string &getBiography() const;
|
||||||
@ -298,6 +309,7 @@ public:
|
|||||||
si32 manaRegain() const; //how many points of mana can hero regain "naturally" in one day
|
si32 manaRegain() const; //how many points of mana can hero regain "naturally" in one day
|
||||||
bool canWalkOnSea() const;
|
bool canWalkOnSea() const;
|
||||||
int getCurrentLuck(int stack=-1, bool town=false) const;
|
int getCurrentLuck(int stack=-1, bool town=false) const;
|
||||||
|
int getSpellCost(const CSpell *sp) const; //do not use during battles -> bonuses from army would be ignored
|
||||||
|
|
||||||
const BonusList *ownerBonuses() const;
|
const BonusList *ownerBonuses() const;
|
||||||
const HeroBonus *getBonus(int from, int id) const;
|
const HeroBonus *getBonus(int from, int id) const;
|
||||||
|
@ -2740,7 +2740,7 @@ CStack * BattleInfo::generateNewStack(const CGHeroInstance * owner, int creature
|
|||||||
|
|
||||||
ui32 BattleInfo::getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const
|
ui32 BattleInfo::getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const
|
||||||
{
|
{
|
||||||
ui32 ret = VLC->spellh->spells[sp->id].costs[caster->getSpellSchoolLevel(sp)];
|
ui32 ret = caster->getSpellCost(sp);
|
||||||
|
|
||||||
//checking for friendly stacks reducing cost of the spell and
|
//checking for friendly stacks reducing cost of the spell and
|
||||||
//enemy stacks increasing it
|
//enemy stacks increasing it
|
||||||
|
@ -380,7 +380,11 @@ struct GiveBonus : public CPackForClient //115
|
|||||||
|
|
||||||
struct ChangeObjPos : public CPackForClient //116
|
struct ChangeObjPos : public CPackForClient //116
|
||||||
{
|
{
|
||||||
ChangeObjPos(){type = 116;};
|
ChangeObjPos()
|
||||||
|
{
|
||||||
|
type = 116;
|
||||||
|
flags = 0;
|
||||||
|
}
|
||||||
void applyFirstCl(CClient *cl);
|
void applyFirstCl(CClient *cl);
|
||||||
void applyCl(CClient *cl);
|
void applyCl(CClient *cl);
|
||||||
DLL_EXPORT void applyGs(CGameState *gs);
|
DLL_EXPORT void applyGs(CGameState *gs);
|
||||||
@ -692,10 +696,11 @@ struct InfoWindow : public CPackForClient //103 - displays simple info window
|
|||||||
{
|
{
|
||||||
h & text & components & player & soundID;
|
h & text & components & player & soundID;
|
||||||
}
|
}
|
||||||
InfoWindow() {
|
InfoWindow()
|
||||||
|
{
|
||||||
type = 103;
|
type = 103;
|
||||||
soundID = 0;
|
soundID = 0;
|
||||||
};
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SetObjectProperty : public CPackForClient//1001
|
struct SetObjectProperty : public CPackForClient//1001
|
||||||
@ -1424,6 +1429,20 @@ struct DigWithHero : public CPackForServer
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CastAdvSpell : public CPackForServer
|
||||||
|
{
|
||||||
|
CastAdvSpell(){}
|
||||||
|
si32 hid; //hero id
|
||||||
|
ui32 sid; //spell id
|
||||||
|
int3 pos; //selected tile (not always used)
|
||||||
|
|
||||||
|
bool applyGh(CGameHandler *gh);
|
||||||
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
{
|
||||||
|
h & hid & sid & pos;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/***********************************************************************************************************/
|
/***********************************************************************************************************/
|
||||||
|
|
||||||
struct SaveGame : public CPackForClient, public CPackForServer
|
struct SaveGame : public CPackForClient, public CPackForServer
|
||||||
|
@ -153,6 +153,7 @@ void registerTypes3(Serializer &s)
|
|||||||
s.template registerType<MakeAction>();
|
s.template registerType<MakeAction>();
|
||||||
s.template registerType<MakeCustomAction>();
|
s.template registerType<MakeCustomAction>();
|
||||||
s.template registerType<DigWithHero>();
|
s.template registerType<DigWithHero>();
|
||||||
|
s.template registerType<CastAdvSpell>();
|
||||||
|
|
||||||
s.template registerType<SaveGame>();
|
s.template registerType<SaveGame>();
|
||||||
s.template registerType<SetSelection>();
|
s.template registerType<SetSelection>();
|
||||||
|
@ -46,6 +46,8 @@ extern bool end2;
|
|||||||
#ifdef max
|
#ifdef max
|
||||||
#undef max
|
#undef max
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define COMPLAIN_RET(txt) {complain(txt); return false;}
|
||||||
#define NEW_ROUND BattleNextRound bnr;\
|
#define NEW_ROUND BattleNextRound bnr;\
|
||||||
bnr.round = gs->curB->round + 1;\
|
bnr.round = gs->curB->round + 1;\
|
||||||
sendAndApply(&bnr);
|
sendAndApply(&bnr);
|
||||||
@ -4197,3 +4199,101 @@ void CGameHandler::handleAfterAttackCasting( const BattleAttack & bat )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CGameHandler::castSpell(const CGHeroInstance *h, int spellID, const int3 &pos)
|
||||||
|
{
|
||||||
|
const CSpell *s = &VLC->spellh->spells[spellID];
|
||||||
|
int cost = h->getSpellCost(s);
|
||||||
|
int schoolLevel = h->getSpellSchoolLevel(s);
|
||||||
|
|
||||||
|
if(!h->canCastThisSpell(s))
|
||||||
|
COMPLAIN_RET("Hero cannot cast this spell!");
|
||||||
|
if(h->mana < cost)
|
||||||
|
COMPLAIN_RET("Hero doesn't have enough spell points to cast this spell!");
|
||||||
|
if(s->combatSpell)
|
||||||
|
COMPLAIN_RET("This function can be used only for adventure map spells!");
|
||||||
|
|
||||||
|
switch(spellID)
|
||||||
|
{
|
||||||
|
case 0: //Summon Boat
|
||||||
|
{
|
||||||
|
//check if spell works at all
|
||||||
|
if(rand() % 100 >= s->powers[schoolLevel]) //power is % chance of success
|
||||||
|
{
|
||||||
|
InfoWindow iw;
|
||||||
|
iw.player = h->tempOwner;
|
||||||
|
iw.text.addTxt(MetaString::GENERAL_TXT, 336); //%s tried to summon a boat, but failed.
|
||||||
|
iw.text.addReplacement(h->name);
|
||||||
|
sendAndApply(&iw);
|
||||||
|
return true; //TODO? or should it be false? request was correct and realized, but spell failed...
|
||||||
|
}
|
||||||
|
|
||||||
|
//try to find unoccupied boat to summon
|
||||||
|
const CGBoat *nearest = NULL;
|
||||||
|
double dist = 0;
|
||||||
|
int3 summonPos = h->bestLocation();
|
||||||
|
if(summonPos.x < 0)
|
||||||
|
COMPLAIN_RET("There is no water tile available!");
|
||||||
|
|
||||||
|
BOOST_FOREACH(const CGObjectInstance *obj, gs->map->objects)
|
||||||
|
{
|
||||||
|
if(obj && obj->ID == 8)
|
||||||
|
{
|
||||||
|
const CGBoat *b = static_cast<const CGBoat*>(obj);
|
||||||
|
if(b->hero) continue; //we're looking for unoccupied boat
|
||||||
|
|
||||||
|
double nDist = distance(b->pos, h->getPosition());
|
||||||
|
if(!nearest || nDist < dist) //it's first boat or closer than previous
|
||||||
|
{
|
||||||
|
nearest = b;
|
||||||
|
dist = nDist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(nearest) //we found boat to summon
|
||||||
|
{
|
||||||
|
ChangeObjPos cop;
|
||||||
|
cop.objid = nearest->id;
|
||||||
|
cop.nPos = summonPos + int3(1,0,0);;
|
||||||
|
cop.flags = 1;
|
||||||
|
sendAndApply(&cop);
|
||||||
|
}
|
||||||
|
else if(schoolLevel < 2) //none or basic level -> cannot create boat :(
|
||||||
|
{
|
||||||
|
InfoWindow iw;
|
||||||
|
iw.player = h->tempOwner;
|
||||||
|
iw.text.addTxt(MetaString::GENERAL_TXT, 335); //There are no boats to summon.
|
||||||
|
sendAndApply(&iw);
|
||||||
|
}
|
||||||
|
else //create boat
|
||||||
|
{
|
||||||
|
NewObject no;
|
||||||
|
no.ID = 8;
|
||||||
|
no.subID = h->getBoatType();
|
||||||
|
no.pos = summonPos + int3(1,0,0);;
|
||||||
|
sendAndApply(&no);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 1: //Scuttle Boat
|
||||||
|
case 2: //Visions
|
||||||
|
case 3: //View Earth
|
||||||
|
case 4: //Disguise
|
||||||
|
case 5: //View Air
|
||||||
|
case 6: //Fly
|
||||||
|
case 7: //Water Walk
|
||||||
|
case 8: //Dimension Door
|
||||||
|
case 9: //Town Portal
|
||||||
|
default:
|
||||||
|
COMPLAIN_RET("This spell is not implemented yet!");
|
||||||
|
}
|
||||||
|
|
||||||
|
SetMana sm;
|
||||||
|
sm.hid = h->id;
|
||||||
|
sm.val = h->mana - cost;
|
||||||
|
sendAndApply(&sm);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
@ -181,6 +181,7 @@ public:
|
|||||||
void objectVisited( const CGObjectInstance * obj, const CGHeroInstance * h );
|
void objectVisited( const CGObjectInstance * obj, const CGHeroInstance * h );
|
||||||
void engageIntoBattle( ui8 player );
|
void engageIntoBattle( ui8 player );
|
||||||
bool dig(const CGHeroInstance *h);
|
bool dig(const CGHeroInstance *h);
|
||||||
|
bool castSpell(const CGHeroInstance *h, int spellID, const int3 &pos);
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
|
@ -160,6 +160,12 @@ bool DigWithHero::applyGh( CGameHandler *gh )
|
|||||||
return gh->dig(gh->getHero(id));
|
return gh->dig(gh->getHero(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CastAdvSpell::applyGh( CGameHandler *gh )
|
||||||
|
{
|
||||||
|
ERROR_IF_NOT_OWNS(hid);
|
||||||
|
return gh->castSpell(gh->getHero(hid), sid, pos);
|
||||||
|
}
|
||||||
|
|
||||||
bool PlayerMessage::applyGh( CGameHandler *gh )
|
bool PlayerMessage::applyGh( CGameHandler *gh )
|
||||||
{
|
{
|
||||||
if(gh->getPlayerAt(c) != player) ERROR_AND_RETURN;
|
if(gh->getPlayerAt(c) != player) ERROR_AND_RETURN;
|
||||||
|
Reference in New Issue
Block a user