1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-07-15 01:24:45 +02:00

* teleportation implemented

This commit is contained in:
mateuszb
2010-05-07 14:05:48 +00:00
parent 9c7e18e44d
commit 3c72644880
8 changed files with 95 additions and 15 deletions

View File

@ -976,6 +976,11 @@ si8 CCallback::battleHasWallPenalty( int stackID, int destHex )
return gs->curB->hasWallPenalty(stackID, destHex); return gs->curB->hasWallPenalty(stackID, destHex);
} }
si8 CCallback::battleCanTeleportTo(int stackID, int destHex, int telportLevel)
{
return gs->curB->canTeleportTo(stackID, destHex, telportLevel);
}
InfoAboutTown::InfoAboutTown() InfoAboutTown::InfoAboutTown()
{ {
tType = NULL; tType = NULL;

View File

@ -307,6 +307,7 @@ public:
si8 battleGetStackLuck(int stackID); //returns luck of given stack si8 battleGetStackLuck(int stackID); //returns luck of given stack
si8 battleHasDistancePenalty(int stackID, int destHex); //checks if given stack has distance penalty si8 battleHasDistancePenalty(int stackID, int destHex); //checks if given stack has distance penalty
si8 battleHasWallPenalty(int stackID, int destHex); //checks if given stack has wall penalty si8 battleHasWallPenalty(int stackID, int destHex); //checks if given stack has wall penalty
si8 battleCanTeleportTo(int stackID, int destHex, int telportLevel); //checks if teleportation of given stack to given position can take place
//XXX hmmm _tmain on _GNUC_ wtf? //XXX hmmm _tmain on _GNUC_ wtf?
//friends //friends

View File

@ -2324,6 +2324,22 @@ bool CBattleInterface::isCatapultAttackable(int hex) const
return curInt->cb->battleGetWallState(wallUnder) < 3; return curInt->cb->battleGetWallState(wallUnder) < 3;
} }
const CGHeroInstance * CBattleInterface::getActiveHero()
{
const CStack * attacker = curInt->cb->battleGetStackByID(activeStack);
if (!attacker)
{
return NULL;
}
if (attacker->attackerOwned)
{
return attackingHeroInstance;
}
return defendingHeroInstance;
}
void CBattleInterface::hexLclicked(int whichOne) void CBattleInterface::hexLclicked(int whichOne)
{ {
const CStack * actSt = curInt->cb->battleGetStackByID(activeStack); const CStack * actSt = curInt->cb->battleGetStackByID(activeStack);
@ -2355,6 +2371,13 @@ void CBattleInterface::hexLclicked(int whichOne)
case 4: case 4:
if(!blockedByObstacle(whichOne)) if(!blockedByObstacle(whichOne))
allowCasting = false; allowCasting = false;
case 5: //teleport
const CSpell *s = &CGI->spellh->spells[spellToCast->additionalInfo];
ui8 skill = getActiveHero()->getSpellSchoolLevel(s); //skill level
if (!curInt->cb->battleCanTeleportTo(activeStack, whichOne, skill))
{
allowCasting = false;
}
break; break;
} }
//destination checked //destination checked
@ -2750,10 +2773,11 @@ void CBattleInterface::castThisSpell(int spellID)
//choosing possible tragets //choosing possible tragets
const CGHeroInstance * castingHero = (attackingHeroInstance->tempOwner == curInt->playerID) ? attackingHeroInstance : attackingHeroInstance; const CGHeroInstance * castingHero = (attackingHeroInstance->tempOwner == curInt->playerID) ? attackingHeroInstance : attackingHeroInstance;
const CSpell & spell = CGI->spellh->spells[spellID];
spellSelMode = 0; spellSelMode = 0;
if(CGI->spellh->spells[spellID].attributes.find("CREATURE_TARGET") != std::string::npos) //spell to be cast on one specific creature if(spell.attributes.find("CREATURE_TARGET") != std::string::npos) //spell to be cast on one specific creature
{ {
switch(CGI->spellh->spells[spellID].positiveness) switch(spell.positiveness)
{ {
case -1 : case -1 :
spellSelMode = 2; spellSelMode = 2;
@ -2766,12 +2790,12 @@ void CBattleInterface::castThisSpell(int spellID)
break; break;
} }
} }
if(CGI->spellh->spells[spellID].attributes.find("CREATURE_TARGET_1") != std::string::npos || if(spell.attributes.find("CREATURE_TARGET_1") != std::string::npos ||
CGI->spellh->spells[spellID].attributes.find("CREATURE_TARGET_2") != std::string::npos) //spell to be cast on a specific creature but massive on expert spell.attributes.find("CREATURE_TARGET_2") != std::string::npos) //spell to be cast on a specific creature but massive on expert
{ {
if(castingHero && castingHero->getSpellSecLevel(spellID) < 3) if(castingHero && castingHero->getSpellSecLevel(spellID) < 3)
{ {
switch(CGI->spellh->spells[spellID].positiveness) switch(spell.positiveness)
{ {
case -1 : case -1 :
spellSelMode = 2; spellSelMode = 2;
@ -2789,14 +2813,20 @@ void CBattleInterface::castThisSpell(int spellID)
spellSelMode = -1; spellSelMode = -1;
} }
} }
if(CGI->spellh->spells[spellID].attributes.find("OBSTACLE_TARGET") != std::string::npos) //spell to be cast on an obstacle if(spell.attributes.find("OBSTACLE_TARGET") != std::string::npos) //spell to be cast on an obstacle
{ {
spellSelMode = 4; spellSelMode = 4;
} }
if(CGI->spellh->spells[spellID].range[ castingHero->getSpellSchoolLevel(&CGI->spellh->spells[spellID]) ] == "X") //spell has no range if(spell.range[ castingHero->getSpellSchoolLevel(&spell) ] == "X") //spell has no range
{ {
spellSelMode = -1; spellSelMode = -1;
} }
if(spell.id == 63) //teleport
{
spellSelMode = 5;
}
if(spellSelMode == -1) //user does not have to select location if(spellSelMode == -1) //user does not have to select location
{ {
spellToCast->destinationTile = -1; spellToCast->destinationTile = -1;

View File

@ -401,7 +401,8 @@ private:
std::map<int, int> standingFrame; //number of frame in standing animation by stack ID, helps in showing 'random moves' std::map<int, int> standingFrame; //number of frame in standing animation by stack ID, helps in showing 'random moves'
bool spellDestSelectMode; //if true, player is choosing destination for his spell bool spellDestSelectMode; //if true, player is choosing destination for his spell
int spellSelMode; //0 - any location, 1 - any friendly creature, 2 - any hostile creature, 3 - any creature, 4 - obstacle,z -1 - no location int spellSelMode; //0 - any location, 1 - any friendly creature, 2 - any hostile creature, 3 - any creature,
//4 - obstacle, 5 - teleport -1 - no location
BattleAction * spellToCast; //spell for which player is choosing destination BattleAction * spellToCast; //spell for which player is choosing destination
void endCastingSpell(); //ends casting spell (eg. when spell has been cast or canceled) void endCastingSpell(); //ends casting spell (eg. when spell has been cast or canceled)
@ -439,6 +440,7 @@ private:
} * siegeH; } * siegeH;
CPlayerInterface * attackerInt, * defenderInt; //because LOCPLINT is not enough in hotSeat CPlayerInterface * attackerInt, * defenderInt; //because LOCPLINT is not enough in hotSeat
const CGHeroInstance * getActiveHero(); //returns hero that can currently cast a spell
public: public:
CPlayerInterface * curInt; //current player interface CPlayerInterface * curInt; //current player interface
std::list<std::pair<CBattleAnimation *, bool> > pendingAnims; //currently displayed animations <anim, initialized> std::list<std::pair<CBattleAnimation *, bool> > pendingAnims; //currently displayed animations <anim, initialized>

View File

@ -3521,6 +3521,17 @@ si8 BattleInfo::hasDistancePenalty( int stackID, int destHex )
return distance > 8 && !stack->hasBonusOfType(Bonus::NO_DISTANCE_PENALTY); return distance > 8 && !stack->hasBonusOfType(Bonus::NO_DISTANCE_PENALTY);
} }
si8 BattleInfo::sameSideOfWall(int pos1, int pos2)
{
int wallInStackLine = lineToWallHex(pos1/BFIELD_WIDTH);
int wallInDestLine = lineToWallHex(pos2/BFIELD_WIDTH);
bool stackLeft = pos1 < wallInStackLine;
bool destLeft = pos2 < wallInDestLine;
return stackLeft != destLeft;
}
si8 BattleInfo::hasWallPenalty( int stackID, int destHex ) si8 BattleInfo::hasWallPenalty( int stackID, int destHex )
{ {
if (siege == 0) if (siege == 0)
@ -3532,13 +3543,28 @@ si8 BattleInfo::hasWallPenalty( int stackID, int destHex )
{ {
return false; return false;
} }
int wallInStackLine = lineToWallHex(stack->position/BFIELD_WIDTH);
int wallInDestLine = lineToWallHex(destHex/BFIELD_WIDTH);
bool stackLeft = stack->position < wallInStackLine; return !sameSideOfWall(stack->position, destHex);
bool destLeft = destHex < wallInDestLine; }
si8 BattleInfo::canTeleportTo(int stackID, int destHex, int telportLevel)
{
bool ac[BFIELD_SIZE];
const CStack *s = getStack(stackID, false); //this function is called from healedOrResurrected, so our stack can be dead
std::set<int> occupyable;
getAccessibilityMap(ac, s->doubleWide(), s->attackerOwned, false, occupyable, s->hasBonusOfType(Bonus::FLYING), stackID);
if (siege && telportLevel < 2) //check for wall
{
return ac[destHex] && sameSideOfWall(s->position, destHex);
}
else
{
return ac[destHex];
}
return stackLeft != destLeft;
} }
void BattleInfo::getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root /*= NULL*/) const void BattleInfo::getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root /*= NULL*/) const

View File

@ -212,7 +212,9 @@ struct DLL_EXPORT BattleInfo : public CBonusSystemNode
std::pair<const CStack *, int> getNearestStack(const CStack * closest, boost::logic::tribool attackerOwned) const; //if attackerOwned is indetermnate, returened stack is of any owner; hex is the number of hex we should be looking from; returns (nerarest creature, predecessorHex) std::pair<const CStack *, int> getNearestStack(const CStack * closest, boost::logic::tribool attackerOwned) const; //if attackerOwned is indetermnate, returened stack is of any owner; hex is the number of hex we should be looking from; returns (nerarest creature, predecessorHex)
ui32 calculateSpellDmg(const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature, int spellSchoolLevel, int usedSpellPower) const; //calculates damage inflicted by spell ui32 calculateSpellDmg(const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature, int spellSchoolLevel, int usedSpellPower) const; //calculates damage inflicted by spell
si8 hasDistancePenalty(int stackID, int destHex); //determines if given stack has distance penalty shooting given pos si8 hasDistancePenalty(int stackID, int destHex); //determines if given stack has distance penalty shooting given pos
si8 sameSideOfWall(int pos1, int pos2); //determines if given positions are on the same side of wall
si8 hasWallPenalty(int stackID, int destHex); //determines if given stack has wall penalty shooting given pos si8 hasWallPenalty(int stackID, int destHex); //determines if given stack has wall penalty shooting given pos
si8 canTeleportTo(int stackID, int destHex, int telportLevel); //determines if given stack can teleport to given place
}; };
class DLL_EXPORT CStack : public CStackInstance class DLL_EXPORT CStack : public CStackInstance

View File

@ -906,7 +906,7 @@ struct BattleResult : public CPackForClient//3003
struct BattleStackMoved : public CPackForClient//3004 struct BattleStackMoved : public CPackForClient//3004
{ {
ui32 stack, tile; ui32 stack, tile;
ui8 ending, distance; ui8 ending, distance, teleporting;
BattleStackMoved(){type = 3004;}; BattleStackMoved(){type = 3004;};
void applyFirstCl(CClient *cl); void applyFirstCl(CClient *cl);
void applyGs(CGameState *gs); void applyGs(CGameState *gs);

View File

@ -812,6 +812,7 @@ int CGameHandler::moveStack(int stack, int dest)
sm.tile = path.first[0]; sm.tile = path.first[0];
sm.distance = path.second; sm.distance = path.second;
sm.ending = true; sm.ending = true;
sm.teleporting = false;
sendAndApply(&sm); sendAndApply(&sm);
} }
} }
@ -826,6 +827,7 @@ int CGameHandler::moveStack(int stack, int dest)
sm.tile = path.first[v]; sm.tile = path.first[v];
sm.distance = path.second; sm.distance = path.second;
sm.ending = v==tilesToMove; sm.ending = v==tilesToMove;
sm.teleporting = false;
sendAndApply(&sm); sendAndApply(&sm);
} }
} }
@ -3666,6 +3668,18 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
sendAndApply(&sse); sendAndApply(&sse);
break; break;
} }
case 63: //teleport
{
BattleStackMoved bsm;
bsm.distance = -1;
bsm.stack = gs->curB->activeStack;
bsm.ending = true;
bsm.tile = destination;
bsm.teleporting = true;
sendAndApply(&bsm);
break;
}
case 37: //cure case 37: //cure
case 38: //resurrection case 38: //resurrection
case 39: //animate dead case 39: //animate dead
@ -3728,7 +3742,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
return false; return false;
} }
CSpell *s = &VLC->spellh->spells[ba.additionalInfo]; const CSpell *s = &VLC->spellh->spells[ba.additionalInfo];
ui8 skill = h->getSpellSchoolLevel(s); //skill level ui8 skill = h->getSpellSchoolLevel(s); //skill level
if( !(h->canCastThisSpell(s)) //hero cannot cast this spell at all if( !(h->canCastThisSpell(s)) //hero cannot cast this spell at all