1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-02-03 13:01:33 +02:00

Support for Bind ability.

This commit is contained in:
DjWarmonger 2011-10-17 08:24:51 +00:00
parent 4c2bbad18e
commit 95f23cf20f
6 changed files with 64 additions and 14 deletions

View File

@ -4129,7 +4129,7 @@ void CBattleInterface::bEndTacticPhase()
static bool immobile(const CStack *s) static bool immobile(const CStack *s)
{ {
return !s->Speed(); return !s->Speed(0, true); //should bound stacks be immobile?
} }
void CBattleInterface::bTacticNextStack() void CBattleInterface::bTacticNextStack()

View File

@ -315,15 +315,17 @@ std::vector<THex> BattleInfo::getAccessibility( const CStack * stack, bool addOc
} }
} }
for (int i=0; i < BFIELD_SIZE ; ++i) for (int i = 0; i < BFIELD_SIZE; ++i)
{ {
bool rangeFits = tacticDistance bool rangeFits;
? isInTacticRange(i) if (tacticDistance)
: dist[i] <= stack->Speed(); rangeFits = isInTacticRange(i);
else
rangeFits = dist[i] <= stack->Speed(0, true); //we can reach the stack
if( ( !addOccupiable && rangeFits && ac[i] ) if( ( !addOccupiable && rangeFits && ac[i] )
|| ( addOccupiable && rangeFits && isAccessible(i, ac, stack->doubleWide(), stack->attackerOwned, stack->hasBonusOfType(Bonus::FLYING), true) )//we can reach it || ( addOccupiable && rangeFits && isAccessible(i, ac, stack->doubleWide(), stack->attackerOwned, stack->hasBonusOfType(Bonus::FLYING), true) )//we can reach it
|| (vstd::contains(occupyable, i) && (!tacticDistance && dist[ i + (stack->attackerOwned ? 1 : -1 ) ] <= stack->Speed() ) && ac[i + (stack->attackerOwned ? 1 : -1 )] ) //it's occupyable and we can reach adjacent hex || (vstd::contains(occupyable, i) && (!tacticDistance && dist[ i + (stack->attackerOwned ? 1 : -1 ) ] <= stack->Speed(0, true) ) && ac[i + (stack->attackerOwned ? 1 : -1 )] ) //it's occupyable and we can reach adjacent hex
) )
{ {
ret.push_back(i); ret.push_back(i);
@ -918,6 +920,20 @@ std::set<THex> BattleInfo::getAttackedHexes(const CStack* attacker, THex destina
return attackedHexes; return attackedHexes;
} }
std::set<CStack*> BattleInfo::getAdjacentCreatures (const CStack * stack)
{
std::set<CStack*> stacks;
CStack * localStack;
BOOST_FOREACH (THex hex, stack->getSurroundingHexes())
{
localStack = getStackT(hex, true); //only alive?
if (localStack)
stacks.insert(localStack);
}
return stacks;
}
int BattleInfo::calculateSpellDuration( const CSpell * spell, const CGHeroInstance * caster, int usedSpellPower) int BattleInfo::calculateSpellDuration( const CSpell * spell, const CGHeroInstance * caster, int usedSpellPower)
{ {
if(!caster) if(!caster)
@ -2306,7 +2322,7 @@ void CStack::postInit()
state.insert(ALIVE); //alive state indication state.insert(ALIVE); //alive state indication
} }
ui32 CStack::Speed( int turn /*= 0*/ ) const ui32 CStack::Speed( int turn /*= 0*/ , bool useBind /* = false*/) const
{ {
if(hasBonus(Selector::type(Bonus::SIEGE_WEAPON) && Selector::turns(turn))) //war machines cannot move if(hasBonus(Selector::type(Bonus::SIEGE_WEAPON) && Selector::turns(turn))) //war machines cannot move
return 0; return 0;
@ -2324,8 +2340,8 @@ ui32 CStack::Speed( int turn /*= 0*/ ) const
speed = ((100 + percentBonus) * speed)/100; speed = ((100 + percentBonus) * speed)/100;
//bind effect check //bind effect check - doesn't influence stack initiative
if(getEffect(72)) if (useBind && getEffect(72))
{ {
return 0; return 0;
} }
@ -2493,9 +2509,7 @@ void CStack::stackEffectToFeature(std::vector<Bonus> & sf, const Bonus & sse)
sf.back().sid = sse.sid; sf.back().sid = sse.sid;
break; break;
case 72: //Bind case 72: //Bind
sf.push_back(featureGeneratorVT(Bonus::STACKS_SPEED, 0, -100, 1, Bonus::PERCENT_TO_ALL)); //sets speed to zero sf.push_back(featureGenerator(Bonus::BIND_EFFECT, 0, 0, 1)); //marker
sf.back().sid = sse.sid;
sf.push_back(featureGenerator(Bonus::BIND_EFFECT, 0, 0, 0)); //marker, TODO: handle it
sf.back().duration = Bonus::PERMANENT; sf.back().duration = Bonus::PERMANENT;
sf.back().sid = sse.sid; sf.back().sid = sse.sid;
break; break;

View File

@ -103,6 +103,7 @@ struct DLL_EXPORT BattleInfo : public CBonusSystemNode
void getPotentiallyAttackableHexes(AttackableTiles &at, const CStack* attacker, THex destinationTile, THex attackerPos); //hexes around target that could be attacked in melee void getPotentiallyAttackableHexes(AttackableTiles &at, const CStack* attacker, THex destinationTile, THex attackerPos); //hexes around target that could be attacked in melee
std::set<CStack*> getAttackedCreatures(const CStack* attacker, THex destinationTile, THex attackerPos = THex::INVALID); //calculates range of multi-hex attacks std::set<CStack*> getAttackedCreatures(const CStack* attacker, THex destinationTile, THex attackerPos = THex::INVALID); //calculates range of multi-hex attacks
std::set<THex> getAttackedHexes(const CStack* attacker, THex destinationTile, THex attackerPos = THex::INVALID); //calculates range of multi-hex attacks std::set<THex> getAttackedHexes(const CStack* attacker, THex destinationTile, THex attackerPos = THex::INVALID); //calculates range of multi-hex attacks
std::set<CStack*> getAdjacentCreatures (const CStack * stack);
static int calculateSpellDuration(const CSpell * spell, const CGHeroInstance * caster, int usedSpellPower); static int calculateSpellDuration(const CSpell * spell, const CGHeroInstance * caster, int usedSpellPower);
CStack * generateNewStack(const CStackInstance &base, int stackID, bool attackerOwned, int slot, THex position) const; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield CStack * generateNewStack(const CStackInstance &base, int stackID, bool attackerOwned, int slot, THex position) const; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield
CStack * generateNewStack(const CStackBasicDescriptor &base, int stackID, bool attackerOwned, int slot, THex position) const; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield CStack * generateNewStack(const CStackBasicDescriptor &base, int stackID, bool attackerOwned, int slot, THex position) const; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield
@ -180,7 +181,7 @@ public:
bool ableToRetaliate() const; //if stack can retaliate after attacked bool ableToRetaliate() const; //if stack can retaliate after attacked
bool moved(int turn = 0) const; //if stack was already moved this turn bool moved(int turn = 0) const; //if stack was already moved this turn
bool canMove(int turn = 0) const; //if stack can move bool canMove(int turn = 0) const; //if stack can move
ui32 Speed(int turn = 0) const; //get speed of creature with all modificators ui32 Speed(int turn = 0, bool useBind = false) const; //get speed of creature with all modificators
static void stackEffectToFeature(std::vector<Bonus> & sf, const Bonus & sse); static void stackEffectToFeature(std::vector<Bonus> & sf, const Bonus & sse);
std::vector<si32> activeSpells() const; //returns vector of active spell IDs sorted by time of cast std::vector<si32> activeSpells() const; //returns vector of active spell IDs sorted by time of cast
const CGHeroInstance *getMyHero() const; //if stack belongs to hero (directly or was by him summoned) returns hero, NULL otherwise const CGHeroInstance *getMyHero() const; //if stack belongs to hero (directly or was by him summoned) returns hero, NULL otherwise

View File

@ -1508,7 +1508,7 @@ struct BattleSetStackProperty : public CPackForClient //3018
{ {
BattleSetStackProperty(){type = 3018;}; BattleSetStackProperty(){type = 3018;};
enum BattleStackProperty {CASTS, ENCHANTER_COUNTER}; enum BattleStackProperty {CASTS, ENCHANTER_COUNTER, UNBIND};
DLL_EXPORT void applyGs(CGameState *gs); DLL_EXPORT void applyGs(CGameState *gs);
//void applyCl(CClient *cl){}; //void applyCl(CClient *cl){};

View File

@ -1304,6 +1304,11 @@ DLL_EXPORT void BattleSetStackProperty::applyGs(CGameState *gs)
amax(gs->curB->enchanterCounter[side], 0); amax(gs->curB->enchanterCounter[side], 0);
break; break;
} }
case UNBIND:
{
stack->popBonuses(Selector::type(Bonus::BIND_EFFECT));
break;
}
} }
} }

View File

@ -3663,6 +3663,10 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, THex destinati
pseudoBonus.val = spellLvl; pseudoBonus.val = spellLvl;
pseudoBonus.turnsRemain = gs->curB->calculateSpellDuration(spell, caster, stackSpellPower ? stackSpellPower : usedSpellPower); pseudoBonus.turnsRemain = gs->curB->calculateSpellDuration(spell, caster, stackSpellPower ? stackSpellPower : usedSpellPower);
CStack::stackEffectToFeature(sse.effect, pseudoBonus); CStack::stackEffectToFeature(sse.effect, pseudoBonus);
if (spellID == 72 && stack)//bind
{
sse.effect.back().additionalInfo = stack->ID; //we need to know who casted Bind
}
const Bonus * bonus = NULL; const Bonus * bonus = NULL;
if (caster) if (caster)
bonus = caster->getBonus(Selector::typeSubtype(Bonus::SPECIAL_PECULIAR_ENCHANT, spellID)); bonus = caster->getBonus(Selector::typeSubtype(Bonus::SPECIAL_PECULIAR_ENCHANT, spellID));
@ -3984,6 +3988,32 @@ void CGameHandler::stackTurnTrigger(const CStack * st)
bte.additionalInfo = 0; bte.additionalInfo = 0;
if (st->alive()) if (st->alive())
{ {
//unbind
if (st->getEffect(72))
{
bool unbind = true;
BonusList bl = *(st->getBonuses(Selector::type(Bonus::BIND_EFFECT)));
std::set<CStack*> stacks = gs->curB->getAdjacentCreatures(st);
BOOST_FOREACH(Bonus * b, bl)
{
const CStack * stack = gs->curB->getStack(b->additionalInfo); //binding stack must be alive and adjacent
if (stack)
{
if (vstd::contains(stacks, stack)) //binding stack is still present
{
unbind = false;
}
}
}
if (unbind)
{
BattleSetStackProperty ssp;
ssp.which = BattleSetStackProperty::UNBIND;
ssp.stackID = st->ID;
sendAndApply(&ssp);
}
}
//regeneration //regeneration
if(st->hasBonusOfType(Bonus::HP_REGENERATION)) if(st->hasBonusOfType(Bonus::HP_REGENERATION))
{ {