mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
* teleportation implemented
This commit is contained in:
parent
9c7e18e44d
commit
3c72644880
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user