1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +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);
}
si8 CCallback::battleCanTeleportTo(int stackID, int destHex, int telportLevel)
{
return gs->curB->canTeleportTo(stackID, destHex, telportLevel);
}
InfoAboutTown::InfoAboutTown()
{
tType = NULL;

View File

@ -307,6 +307,7 @@ public:
si8 battleGetStackLuck(int stackID); //returns luck of given stack
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 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?
//friends

View File

@ -2324,6 +2324,22 @@ bool CBattleInterface::isCatapultAttackable(int hex) const
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)
{
const CStack * actSt = curInt->cb->battleGetStackByID(activeStack);
@ -2355,6 +2371,13 @@ void CBattleInterface::hexLclicked(int whichOne)
case 4:
if(!blockedByObstacle(whichOne))
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;
}
//destination checked
@ -2750,10 +2773,11 @@ void CBattleInterface::castThisSpell(int spellID)
//choosing possible tragets
const CGHeroInstance * castingHero = (attackingHeroInstance->tempOwner == curInt->playerID) ? attackingHeroInstance : attackingHeroInstance;
const CSpell & spell = CGI->spellh->spells[spellID];
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 :
spellSelMode = 2;
@ -2766,12 +2790,12 @@ void CBattleInterface::castThisSpell(int spellID)
break;
}
}
if(CGI->spellh->spells[spellID].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
if(spell.attributes.find("CREATURE_TARGET_1") != std::string::npos ||
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)
{
switch(CGI->spellh->spells[spellID].positiveness)
switch(spell.positiveness)
{
case -1 :
spellSelMode = 2;
@ -2789,14 +2813,20 @@ void CBattleInterface::castThisSpell(int spellID)
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;
}
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;
}
if(spell.id == 63) //teleport
{
spellSelMode = 5;
}
if(spellSelMode == -1) //user does not have to select location
{
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'
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
void endCastingSpell(); //ends casting spell (eg. when spell has been cast or canceled)
@ -439,6 +440,7 @@ private:
} * siegeH;
CPlayerInterface * attackerInt, * defenderInt; //because LOCPLINT is not enough in hotSeat
const CGHeroInstance * getActiveHero(); //returns hero that can currently cast a spell
public:
CPlayerInterface * curInt; //current player interface
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);
}
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 )
{
if (siege == 0)
@ -3532,13 +3543,28 @@ si8 BattleInfo::hasWallPenalty( int stackID, int destHex )
{
return false;
}
int wallInStackLine = lineToWallHex(stack->position/BFIELD_WIDTH);
int wallInDestLine = lineToWallHex(destHex/BFIELD_WIDTH);
bool stackLeft = stack->position < wallInStackLine;
bool destLeft = destHex < wallInDestLine;
return !sameSideOfWall(stack->position, destHex);
}
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

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)
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 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 canTeleportTo(int stackID, int destHex, int telportLevel); //determines if given stack can teleport to given place
};
class DLL_EXPORT CStack : public CStackInstance

View File

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

View File

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