mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Support for Enchanter ability.
This commit is contained in:
parent
d607d90a91
commit
5e40d3da72
@ -1416,7 +1416,14 @@
|
||||
"level": 6,
|
||||
"name": [ "Enchanter" ],
|
||||
"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",
|
||||
"projectile_defname": "SMBALX.DEF",
|
||||
"projectile_spin": false
|
||||
@ -1427,8 +1434,8 @@
|
||||
"level": 4,
|
||||
"name": [ "Sharpshooter" ],
|
||||
"faction": -1,
|
||||
"ability_add": [ [ "NO_OBSTACLES_PENALTY", 0, 0, 0 ], //arrow turret
|
||||
[ "NO_DISTANCE_PENALTY", 0, 0, 0 ] ], //Sharpshooter //Ammo Cart
|
||||
"ability_add": [ [ "NO_OBSTACLES_PENALTY", 0, 0, 0 ],
|
||||
[ "NO_DISTANCE_PENALTY", 0, 0, 0 ] ], //Sharpshooter
|
||||
"defname": "CSHARP.DEF",
|
||||
"projectile_defname": "PELFX.DEF",
|
||||
"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
|
||||
MAGIC_MIRROR, CREATURE_ACTIVE_CASTING};
|
||||
MAGIC_MIRROR, CREATURE_ACTIVE_CASTING, ENCHANTER_CASTING};
|
||||
}
|
||||
|
||||
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->round = -2;
|
||||
curB->activeStack = -1;
|
||||
curB->enchanterCounter[0] = curB->enchanterCounter[1] = 0; //ready to cast
|
||||
|
||||
if(town)
|
||||
{
|
||||
@ -1915,7 +1916,7 @@ SpellCasting::ESpellCastProblem BattleInfo::battleCanCastThisSpellHere( int play
|
||||
if(moreGeneralProblem != SpellCasting::OK)
|
||||
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);
|
||||
else
|
||||
return battleIsImmune(NULL, spell, mode, dest);
|
||||
|
@ -59,6 +59,7 @@ struct DLL_EXPORT BattleInfo : public CBonusSystemNode
|
||||
std::vector<CObstacleInstance> obstacles;
|
||||
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
|
||||
si16 enchanterCounter[2]; //tends to pass through 0, so sign is needed
|
||||
SiegeInfo si;
|
||||
si32 battlefieldType;
|
||||
|
||||
@ -70,7 +71,7 @@ struct DLL_EXPORT BattleInfo : public CBonusSystemNode
|
||||
h & sides & round & activeStack & siege & town & tile & stacks & belligerents & obstacles
|
||||
& castSpells & si & battlefieldType;
|
||||
h & heroes;
|
||||
h & usedSpellsHistory;
|
||||
h & usedSpellsHistory & enchanterCounter;
|
||||
h & tacticsSide & tacticDistance;
|
||||
h & static_cast<CBonusSystemNode&>(*this);
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ namespace PrimarySkill
|
||||
BONUS_NAME(NO_DISTANCE_PENALTY) \
|
||||
BONUS_NAME(NO_OBSTACLES_PENALTY) \
|
||||
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(SIEGE_WEAPON) \
|
||||
BONUS_NAME(HYPNOTIZED) \
|
||||
|
@ -1506,7 +1506,7 @@ struct BattleSetStackProperty : public CPackForClient //3018
|
||||
{
|
||||
BattleSetStackProperty(){type = 3018;};
|
||||
|
||||
enum BattleStackProperty {CASTS, CURRENT_SPELL};
|
||||
enum BattleStackProperty {CASTS, ENCHANTER_COUNTER};
|
||||
|
||||
DLL_EXPORT void applyGs(CGameState *gs);
|
||||
//void applyCl(CClient *cl){};
|
||||
|
@ -839,6 +839,11 @@ DLL_EXPORT void BattleStart::applyGs( CGameState *gs )
|
||||
DLL_EXPORT void BattleNextRound::applyGs( CGameState *gs )
|
||||
{
|
||||
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;
|
||||
|
||||
BOOST_FOREACH(CStack *s, gs->curB->stacks)
|
||||
@ -1296,6 +1301,16 @@ DLL_EXPORT void BattleSetStackProperty::applyGs(CGameState *gs)
|
||||
amax(stack->casts, 0);
|
||||
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);
|
||||
|
||||
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);
|
||||
break;
|
||||
}
|
||||
@ -3505,11 +3498,28 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, THex destinati
|
||||
sc.attackerType = (stack ? stack->type->idNumber : -1);
|
||||
|
||||
//calculating affected creatures for all spells
|
||||
std::set<CStack*> attackedCres = gs->curB->getAttackedCreatures(spell, spellLvl, casterColor, destination);
|
||||
std::set<CStack*> attackedCres;
|
||||
if (mode != SpellCasting::ENCHANTER_CASTING)
|
||||
{
|
||||
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
|
||||
sc.resisted = gs->curB->calculateResistedStacks(spell, caster, secHero, attackedCres, casterColor, mode);
|
||||
@ -3844,6 +3854,16 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, THex destinati
|
||||
if(!si.stacks.empty()) //after spellcast info shows
|
||||
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
|
||||
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();
|
||||
if (bl->size())
|
||||
BonusList bl = *(st->getBonuses(Selector::type(Bonus::ENCHANTER)));
|
||||
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();
|
||||
bte.val = (*bl)[index]->subtype; //spell ID
|
||||
bte.additionalInfo = (*bl)[index]->val; //spell level
|
||||
sendAndApply(&bte);
|
||||
int index = rand() % bl.size();
|
||||
int spellID = bl[index]->subtype; //spell ID
|
||||
if (gs->curB->battleCanCastThisSpell(st->owner, VLC->spellh->spells[spellID], SpellCasting::ENCHANTER_CASTING)); //TODO: select another?
|
||||
{
|
||||
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