mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-26 22:57:00 +02:00
Support for Enchanter ability.
This commit is contained in:
parent
d607d90a91
commit
5e40d3da72
@ -1416,7 +1416,14 @@
|
|||||||
"level": 6,
|
"level": 6,
|
||||||
"name": [ "Enchanter" ],
|
"name": [ "Enchanter" ],
|
||||||
"faction": -1,
|
"faction": -1,
|
||||||
"ability_add": [ [ "NO_OBSTACLES_PENALTY", 0, 0, 0 ] ], //Enchanter //first aid tent can heal
|
"ability_add": [ [ "NO_OBSTACLES_PENALTY", 0, 0, 0 ],
|
||||||
|
[ "ENCHANTER", 3, 28, 3], //air shield
|
||||||
|
[ "ENCHANTER", 3, 41, 3], //bless
|
||||||
|
[ "ENCHANTER", 3, 45, 3], //wealness
|
||||||
|
[ "ENCHANTER", 3, 46, 3], //stone skin
|
||||||
|
[ "ENCHANTER", 3, 53, 3], //slow
|
||||||
|
[ "ENCHANTER", 3, 54, 3], //haster
|
||||||
|
[ "CASTS", 5, 0, 0]], //Enchanter
|
||||||
"defname": "CENCH.DEF",
|
"defname": "CENCH.DEF",
|
||||||
"projectile_defname": "SMBALX.DEF",
|
"projectile_defname": "SMBALX.DEF",
|
||||||
"projectile_spin": false
|
"projectile_spin": false
|
||||||
@ -1427,8 +1434,8 @@
|
|||||||
"level": 4,
|
"level": 4,
|
||||||
"name": [ "Sharpshooter" ],
|
"name": [ "Sharpshooter" ],
|
||||||
"faction": -1,
|
"faction": -1,
|
||||||
"ability_add": [ [ "NO_OBSTACLES_PENALTY", 0, 0, 0 ], //arrow turret
|
"ability_add": [ [ "NO_OBSTACLES_PENALTY", 0, 0, 0 ],
|
||||||
[ "NO_DISTANCE_PENALTY", 0, 0, 0 ] ], //Sharpshooter //Ammo Cart
|
[ "NO_DISTANCE_PENALTY", 0, 0, 0 ] ], //Sharpshooter
|
||||||
"defname": "CSHARP.DEF",
|
"defname": "CSHARP.DEF",
|
||||||
"projectile_defname": "PELFX.DEF",
|
"projectile_defname": "PELFX.DEF",
|
||||||
"projectile_spin": false
|
"projectile_spin": false
|
||||||
|
2
global.h
2
global.h
@ -327,7 +327,7 @@ namespace SpellCasting
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum ECastingMode {HERO_CASTING, AFTER_ATTACK_CASTING, //also includes cast before attack
|
enum ECastingMode {HERO_CASTING, AFTER_ATTACK_CASTING, //also includes cast before attack
|
||||||
MAGIC_MIRROR, CREATURE_ACTIVE_CASTING};
|
MAGIC_MIRROR, CREATURE_ACTIVE_CASTING, ENCHANTER_CASTING};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Buildings
|
namespace Buildings
|
||||||
|
@ -1462,6 +1462,7 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int terType, const
|
|||||||
curB->heroes[1] = const_cast<CGHeroInstance*>(heroes[1]);
|
curB->heroes[1] = const_cast<CGHeroInstance*>(heroes[1]);
|
||||||
curB->round = -2;
|
curB->round = -2;
|
||||||
curB->activeStack = -1;
|
curB->activeStack = -1;
|
||||||
|
curB->enchanterCounter[0] = curB->enchanterCounter[1] = 0; //ready to cast
|
||||||
|
|
||||||
if(town)
|
if(town)
|
||||||
{
|
{
|
||||||
@ -1915,7 +1916,7 @@ SpellCasting::ESpellCastProblem BattleInfo::battleCanCastThisSpellHere( int play
|
|||||||
if(moreGeneralProblem != SpellCasting::OK)
|
if(moreGeneralProblem != SpellCasting::OK)
|
||||||
return moreGeneralProblem;
|
return moreGeneralProblem;
|
||||||
|
|
||||||
if (mode != SpellCasting::CREATURE_ACTIVE_CASTING)
|
if (mode != SpellCasting::CREATURE_ACTIVE_CASTING && mode != SpellCasting::ENCHANTER_CASTING)
|
||||||
return battleIsImmune(getHero(player), spell, mode, dest);
|
return battleIsImmune(getHero(player), spell, mode, dest);
|
||||||
else
|
else
|
||||||
return battleIsImmune(NULL, spell, mode, dest);
|
return battleIsImmune(NULL, spell, mode, dest);
|
||||||
|
@ -59,6 +59,7 @@ struct DLL_EXPORT BattleInfo : public CBonusSystemNode
|
|||||||
std::vector<CObstacleInstance> obstacles;
|
std::vector<CObstacleInstance> obstacles;
|
||||||
ui8 castSpells[2]; //how many spells each side has cast this turn [0] - attacker, [1] - defender
|
ui8 castSpells[2]; //how many spells each side has cast this turn [0] - attacker, [1] - defender
|
||||||
std::vector<const CSpell *> usedSpellsHistory[2]; //each time hero casts spell, it's inserted here -> eagle eye skill
|
std::vector<const CSpell *> usedSpellsHistory[2]; //each time hero casts spell, it's inserted here -> eagle eye skill
|
||||||
|
si16 enchanterCounter[2]; //tends to pass through 0, so sign is needed
|
||||||
SiegeInfo si;
|
SiegeInfo si;
|
||||||
si32 battlefieldType;
|
si32 battlefieldType;
|
||||||
|
|
||||||
@ -70,7 +71,7 @@ struct DLL_EXPORT BattleInfo : public CBonusSystemNode
|
|||||||
h & sides & round & activeStack & siege & town & tile & stacks & belligerents & obstacles
|
h & sides & round & activeStack & siege & town & tile & stacks & belligerents & obstacles
|
||||||
& castSpells & si & battlefieldType;
|
& castSpells & si & battlefieldType;
|
||||||
h & heroes;
|
h & heroes;
|
||||||
h & usedSpellsHistory;
|
h & usedSpellsHistory & enchanterCounter;
|
||||||
h & tacticsSide & tacticDistance;
|
h & tacticsSide & tacticDistance;
|
||||||
h & static_cast<CBonusSystemNode&>(*this);
|
h & static_cast<CBonusSystemNode&>(*this);
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ namespace PrimarySkill
|
|||||||
BONUS_NAME(NO_DISTANCE_PENALTY) \
|
BONUS_NAME(NO_DISTANCE_PENALTY) \
|
||||||
BONUS_NAME(NO_OBSTACLES_PENALTY) \
|
BONUS_NAME(NO_OBSTACLES_PENALTY) \
|
||||||
BONUS_NAME(SELF_LUCK) /*halfling*/ \
|
BONUS_NAME(SELF_LUCK) /*halfling*/ \
|
||||||
BONUS_NAME(ENCHANTER)/* for Enchanter spells, subtype - spell id */ \
|
BONUS_NAME(ENCHANTER)/* for Enchanter spells, val - skill level, subtype - spell id, additionalInfo - cooldown */ \
|
||||||
BONUS_NAME(HEALER) \
|
BONUS_NAME(HEALER) \
|
||||||
BONUS_NAME(SIEGE_WEAPON) \
|
BONUS_NAME(SIEGE_WEAPON) \
|
||||||
BONUS_NAME(HYPNOTIZED) \
|
BONUS_NAME(HYPNOTIZED) \
|
||||||
|
@ -1506,7 +1506,7 @@ struct BattleSetStackProperty : public CPackForClient //3018
|
|||||||
{
|
{
|
||||||
BattleSetStackProperty(){type = 3018;};
|
BattleSetStackProperty(){type = 3018;};
|
||||||
|
|
||||||
enum BattleStackProperty {CASTS, CURRENT_SPELL};
|
enum BattleStackProperty {CASTS, ENCHANTER_COUNTER};
|
||||||
|
|
||||||
DLL_EXPORT void applyGs(CGameState *gs);
|
DLL_EXPORT void applyGs(CGameState *gs);
|
||||||
//void applyCl(CClient *cl){};
|
//void applyCl(CClient *cl){};
|
||||||
|
@ -839,6 +839,11 @@ DLL_EXPORT void BattleStart::applyGs( CGameState *gs )
|
|||||||
DLL_EXPORT void BattleNextRound::applyGs( CGameState *gs )
|
DLL_EXPORT void BattleNextRound::applyGs( CGameState *gs )
|
||||||
{
|
{
|
||||||
gs->curB->castSpells[0] = gs->curB->castSpells[1] = 0;
|
gs->curB->castSpells[0] = gs->curB->castSpells[1] = 0;
|
||||||
|
for (int i = 0; i < 2; ++i)
|
||||||
|
{
|
||||||
|
amax(--gs->curB->enchanterCounter[i], 0);
|
||||||
|
}
|
||||||
|
|
||||||
gs->curB->round = round;
|
gs->curB->round = round;
|
||||||
|
|
||||||
BOOST_FOREACH(CStack *s, gs->curB->stacks)
|
BOOST_FOREACH(CStack *s, gs->curB->stacks)
|
||||||
@ -1296,6 +1301,16 @@ DLL_EXPORT void BattleSetStackProperty::applyGs(CGameState *gs)
|
|||||||
amax(stack->casts, 0);
|
amax(stack->casts, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ENCHANTER_COUNTER:
|
||||||
|
{
|
||||||
|
int side = gs->curB->whatSide(stack->owner);
|
||||||
|
if (absolute)
|
||||||
|
gs->curB->enchanterCounter[side] = val;
|
||||||
|
else
|
||||||
|
gs->curB->enchanterCounter[side] += val;
|
||||||
|
amax(gs->curB->enchanterCounter[side], 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3344,13 +3344,6 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|||||||
|
|
||||||
handleSpellCasting(spellID, spellLvl, destination, casterSide, stack->owner, NULL, secHero, 0, SpellCasting::CREATURE_ACTIVE_CASTING, stack);
|
handleSpellCasting(spellID, spellLvl, destination, casterSide, stack->owner, NULL, secHero, 0, SpellCasting::CREATURE_ACTIVE_CASTING, stack);
|
||||||
|
|
||||||
BattleSetStackProperty ssp;
|
|
||||||
ssp.stackID = ba.stackNumber;
|
|
||||||
ssp.which = BattleSetStackProperty::CASTS; //reduce number of casts
|
|
||||||
ssp.val = -1;
|
|
||||||
ssp.absolute = false;
|
|
||||||
sendAndApply(&ssp);
|
|
||||||
|
|
||||||
sendAndApply(&end_action);
|
sendAndApply(&end_action);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -3505,10 +3498,27 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, THex destinati
|
|||||||
sc.attackerType = (stack ? stack->type->idNumber : -1);
|
sc.attackerType = (stack ? stack->type->idNumber : -1);
|
||||||
|
|
||||||
//calculating affected creatures for all spells
|
//calculating affected creatures for all spells
|
||||||
std::set<CStack*> attackedCres = gs->curB->getAttackedCreatures(spell, spellLvl, casterColor, destination);
|
std::set<CStack*> attackedCres;
|
||||||
for(std::set<CStack*>::const_iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
|
if (mode != SpellCasting::ENCHANTER_CASTING)
|
||||||
{
|
{
|
||||||
sc.affectedCres.insert((*it)->ID);
|
attackedCres = gs->curB->getAttackedCreatures(spell, spellLvl, casterColor, destination);
|
||||||
|
for(std::set<CStack*>::const_iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
|
||||||
|
{
|
||||||
|
sc.affectedCres.insert((*it)->ID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else //enchanter - hit all possible stacks
|
||||||
|
{
|
||||||
|
BOOST_FOREACH (CStack * stack, gs->curB->stacks)
|
||||||
|
{
|
||||||
|
/*if it's non negative spell and our unit or non positive spell and hostile unit */
|
||||||
|
if((spell->positiveness >= 0 && stack->owner == casterColor)
|
||||||
|
||(spell->positiveness <= 0 && stack->owner != casterColor ))
|
||||||
|
{
|
||||||
|
if(stack->alive()) //TODO: allow dead targets somewhere in the future
|
||||||
|
attackedCres.insert(stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//checking if creatures resist
|
//checking if creatures resist
|
||||||
@ -3844,6 +3854,16 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, THex destinati
|
|||||||
if(!si.stacks.empty()) //after spellcast info shows
|
if(!si.stacks.empty()) //after spellcast info shows
|
||||||
sendAndApply(&si);
|
sendAndApply(&si);
|
||||||
|
|
||||||
|
if (mode == SpellCasting::CREATURE_ACTIVE_CASTING || mode == SpellCasting::ENCHANTER_CASTING) //reduce number of casts remaining
|
||||||
|
{
|
||||||
|
BattleSetStackProperty ssp;
|
||||||
|
ssp.stackID = stack->ID;
|
||||||
|
ssp.which = BattleSetStackProperty::CASTS;
|
||||||
|
ssp.val = -1;
|
||||||
|
ssp.absolute = false;
|
||||||
|
sendAndApply(&ssp);
|
||||||
|
}
|
||||||
|
|
||||||
//Magic Mirror effect
|
//Magic Mirror effect
|
||||||
if (spell->positiveness < 0 && mode != SpellCasting::MAGIC_MIRROR && spell->level && spell->range[0] == "0") //it is actual spell and can be reflected to single target, no recurrence
|
if (spell->positiveness < 0 && mode != SpellCasting::MAGIC_MIRROR && spell->level && spell->range[0] == "0") //it is actual spell and can be reflected to single target, no recurrence
|
||||||
{
|
{
|
||||||
@ -4007,14 +4027,25 @@ void CGameHandler::stackTurnTrigger(const CStack * st)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BonusList * bl = st->getBonuses(Selector::type(Bonus::ENCHANTER)).get();
|
BonusList bl = *(st->getBonuses(Selector::type(Bonus::ENCHANTER)));
|
||||||
if (bl->size())
|
int side = gs->curB->whatSide(st->owner);
|
||||||
|
if (bl.size() && st->casts && !gs->curB->enchanterCounter[side])
|
||||||
{
|
{
|
||||||
bte.effect = Bonus::ENCHANTER;
|
int index = rand() % bl.size();
|
||||||
int index = rand() % bl->size();
|
int spellID = bl[index]->subtype; //spell ID
|
||||||
bte.val = (*bl)[index]->subtype; //spell ID
|
if (gs->curB->battleCanCastThisSpell(st->owner, VLC->spellh->spells[spellID], SpellCasting::ENCHANTER_CASTING)); //TODO: select another?
|
||||||
bte.additionalInfo = (*bl)[index]->val; //spell level
|
{
|
||||||
sendAndApply(&bte);
|
int spellLeveL = bl[index]->val; //spell level
|
||||||
|
const CGHeroInstance * enemyHero = gs->curB->getHero(gs->curB->theOtherPlayer(st->owner));
|
||||||
|
handleSpellCasting(spellID, spellLeveL, -1, side, st->owner, NULL, enemyHero, 0, SpellCasting::ENCHANTER_CASTING, st);
|
||||||
|
|
||||||
|
BattleSetStackProperty ssp;
|
||||||
|
ssp.which = BattleSetStackProperty::ENCHANTER_COUNTER;
|
||||||
|
ssp.absolute = false;
|
||||||
|
ssp.val = bl[index]->additionalInfo; //increase cooldown counter
|
||||||
|
ssp.stackID = st->ID;
|
||||||
|
sendAndApply(&ssp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user