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:
parent
4c2bbad18e
commit
95f23cf20f
@ -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()
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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){};
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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))
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user