mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
handling of Rebirth ability for Phoenix.
However, I've got no idea how to restore its animation to alive state.
This commit is contained in:
parent
1bf9bb4d94
commit
5269e845fd
@ -45,6 +45,7 @@ struct SStackAttackedInfo
|
||||
const CStack * attacker; //attacking stack
|
||||
bool byShooting; //if true, stack has been attacked by shooting
|
||||
bool killed; //if true, stack has been killed
|
||||
bool rebirth; //if true, play rebirth animation after all
|
||||
};
|
||||
|
||||
/// Small struct which contains information about the position and the velocity of a projectile
|
||||
|
@ -796,7 +796,7 @@ void CPlayerInterface::battleStacksAttacked(const std::vector<BattleStackAttacke
|
||||
if (defender && !i->isSecondary())
|
||||
battleInt->displayEffect(i->effect, defender->position);
|
||||
}
|
||||
SStackAttackedInfo to_put = {defender, i->damageAmount, i->killedAmount, attacker, LOCPLINT->curAction->actionType==7, i->killed()};
|
||||
SStackAttackedInfo to_put = {defender, i->damageAmount, i->killedAmount, attacker, LOCPLINT->curAction->actionType==7, i->killed(), i->willRebirth()};
|
||||
arg.push_back(to_put);
|
||||
|
||||
}
|
||||
|
@ -177,6 +177,8 @@
|
||||
+ 125 NON_LIVING 0 0 0 //energy elementals shouldn't get morale
|
||||
+ 127 NON_LIVING 0 0 0
|
||||
+ 129 NON_LIVING 0 0 0 //Crystal Dragons do not fly
|
||||
+ 131 REBIRTH 20 0 0 //20% of stack is resurrected
|
||||
+ 131 CASTS 1 0 0 //Phoenix rebirths once
|
||||
+ 132 DRAGON_NATURE 0 0 0 //azure dragon is a dragon
|
||||
- 133 FLYING
|
||||
+ 133 DRAGON_NATURE 0 0 0 //crystal dragon is a dragon
|
||||
@ -184,19 +186,19 @@
|
||||
+ 135 DRAGON_NATURE 0 0 0 //rust dragon is a dragon
|
||||
+ 135 ACID_BREATH 25 0 20 //20% chance to do 25 damage
|
||||
+ 135 SPELL_AFTER_ATTACK 100 80 0 //always reduce defense
|
||||
+ 136 NO_OBSTACLES_PENALTY 0 0 0 //Enchanter
|
||||
+ 137 NO_DISTANCE_PENALTY 0 0 0 //Sharpshooter
|
||||
+ 137 NO_OBSTACLES_PENALTY 0 0 0 //first aid tent can heal
|
||||
+ 140 DOUBLE_WIDE 0 0 0 //boar should be treated as double-wide //Ammo Cart
|
||||
+ 142 DOUBLE_WIDE 0 0 0 //nomads should be treated as double-wide //arrow turret
|
||||
+ 136 NO_OBSTACLES_PENALTY 0 0 0 //Enchanter //first aid tent can heal
|
||||
+ 137 NO_DISTANCE_PENALTY 0 0 0 //Sharpshooter //Ammo Cart
|
||||
+ 137 NO_OBSTACLES_PENALTY 0 0 0 //arrow turret
|
||||
+ 140 DOUBLE_WIDE 0 0 0 //boar should be treated as double-wide
|
||||
+ 142 DOUBLE_WIDE 0 0 0 //nomads should be treated as double-wide
|
||||
+ 144 FULL_HP_REGENERATION 0 0 0 //troll
|
||||
+ 147 HEALER 0 0 0
|
||||
+ 148 NOT_ACTIVE 0 0 0
|
||||
+ 149 SHOOTER 0 0 0 //Gorynyches fly
|
||||
+ 151 DRAGON_NATURE 0 0 0 //diamond dragon is a dragon //hell hound doesn't fly
|
||||
+ 154 DRAGON_NATURE 0 0 0 //blood dragon is a dragon //cerberus doesn't fly
|
||||
+ 155 DRAGON_NATURE 0 0 0 //darkness dragon is a dragon //psychic elemental
|
||||
+ 168 FLYING 0 0 0 //magic elemental
|
||||
+ 147 HEALER 0 0 0 //Gorynyches fly
|
||||
+ 148 NOT_ACTIVE 0 0 0 //hell hound doesn't fly
|
||||
+ 149 SHOOTER 0 0 0 //cerberus doesn't fly
|
||||
+ 151 DRAGON_NATURE 0 0 0 //diamond dragon is a dragon //psychic elemental
|
||||
+ 154 DRAGON_NATURE 0 0 0 //blood dragon is a dragon //magic elemental
|
||||
+ 155 DRAGON_NATURE 0 0 0 //darkness dragon is a dragon
|
||||
+ 168 FLYING 0 0 0
|
||||
- 46 FLYING
|
||||
- 47 FLYING
|
||||
- 120 DOUBLE_WIDE
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <sstream>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/assign/list_of.hpp>
|
||||
#include <boost/random/linear_congruential.hpp>
|
||||
|
||||
#include "VCMI_Lib.h"
|
||||
#include "CObjectHandler.h"
|
||||
@ -25,7 +26,7 @@
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
extern boost::rand48 ran;
|
||||
|
||||
const CStack * BattleInfo::getNextStack() const
|
||||
{
|
||||
@ -845,10 +846,15 @@ std::set<CStack*> BattleInfo::getAttackedCreatures(const CStack* attacker, THex
|
||||
return attackedCres;
|
||||
}
|
||||
|
||||
int BattleInfo::calculateSpellDuration( const CSpell * spell, const CGHeroInstance * caster, int usedSpellPower )
|
||||
int BattleInfo::calculateSpellDuration( const CSpell * spell, const CGHeroInstance * caster, int usedSpellPower)
|
||||
{
|
||||
if(!caster) //TODO: something better
|
||||
return std::max(5, usedSpellPower);
|
||||
if(!caster)
|
||||
{
|
||||
if (!usedSpellPower)
|
||||
return 3; //default duration of all creature spells
|
||||
else
|
||||
return usedSpellPower; //use creature spell power
|
||||
}
|
||||
switch(spell->id)
|
||||
{
|
||||
case 56: //frenzy
|
||||
@ -2107,9 +2113,9 @@ void CStack::postInit()
|
||||
firstHPleft = valOfBonuses(Bonus::STACK_HEALTH);
|
||||
shots = getCreature()->valOfBonuses(Bonus::SHOTS);
|
||||
counterAttacks = 1 + valOfBonuses(Bonus::ADDITIONAL_RETALIATION);
|
||||
casts = valOfBonuses(Bonus::CASTS); //TODO: set them in cr_abils.txt
|
||||
state.insert(ALIVE); //alive state indication
|
||||
|
||||
|
||||
assert(firstHPleft > 0);
|
||||
}
|
||||
|
||||
@ -2282,15 +2288,15 @@ void CStack::stackEffectToFeature(std::vector<Bonus> & sf, const Bonus & sse)
|
||||
sf.push_back(makeFeatureVal(Bonus::GENERAL_ATTACK_REDUCTION, Bonus::UNTIL_ATTACK | Bonus::N_TURNS, 0, power, Bonus::SPELL_EFFECT, sse.turnsRemain));
|
||||
sf.back().sid = sse.sid;
|
||||
break;
|
||||
case 70: //Stone Gaze //TODO: allow stacks use arbitrary spell power
|
||||
case 70: //Stone Gaze
|
||||
case 74: //Paralyze
|
||||
sf.push_back(makeFeatureVal(Bonus::NOT_ACTIVE, Bonus::UNITL_BEING_ATTACKED | Bonus::N_TURNS, 0, 0, Bonus::SPELL_EFFECT, sse.turnsRemain));
|
||||
sf.back().sid = sse.sid;
|
||||
break;
|
||||
case 71: //Poison
|
||||
sf.push_back(featureGeneratorVT(Bonus::POISON, 0, 30, 3, Bonus::INDEPENDENT_MAX)); //max hp penalty from this source
|
||||
sf.push_back(featureGeneratorVT(Bonus::POISON, 0, 30, sse.turnsRemain, Bonus::INDEPENDENT_MAX)); //max hp penalty from this source
|
||||
sf.back().sid = sse.sid;
|
||||
sf.push_back(featureGeneratorVT(Bonus::STACK_HEALTH, 0, -10, 3, Bonus::PERCENT_TO_ALL));
|
||||
sf.push_back(featureGeneratorVT(Bonus::STACK_HEALTH, 0, -10, sse.turnsRemain, Bonus::PERCENT_TO_ALL));
|
||||
sf.back().sid = sse.sid;
|
||||
break;
|
||||
case 72: //Bind
|
||||
@ -2301,17 +2307,17 @@ void CStack::stackEffectToFeature(std::vector<Bonus> & sf, const Bonus & sse)
|
||||
sf.back().sid = sse.sid;
|
||||
break;
|
||||
case 73: //Disease
|
||||
sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK, -2 ,3));
|
||||
sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK, -2 , sse.turnsRemain));
|
||||
sf.back().sid = sse.sid;
|
||||
sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE, -2 ,3));
|
||||
sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE, -2 , sse.turnsRemain));
|
||||
sf.back().sid = sse.sid;
|
||||
break;
|
||||
case 75: //Age
|
||||
sf.push_back(featureGeneratorVT(Bonus::STACK_HEALTH, 0, -50, 3, Bonus::PERCENT_TO_ALL));
|
||||
sf.push_back(featureGeneratorVT(Bonus::STACK_HEALTH, 0, -50, sse.turnsRemain, Bonus::PERCENT_TO_ALL));
|
||||
sf.back().sid = sse.sid;
|
||||
break;
|
||||
case 80: //Acid Breath
|
||||
sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE, -3, 1));
|
||||
sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE, -sse.turnsRemain, 1));
|
||||
sf.back().sid = sse.sid;
|
||||
sf.back().duration = Bonus::PERMANENT;
|
||||
sf.back().valType = Bonus::ADDITIVE_VALUE;
|
||||
@ -2489,6 +2495,23 @@ void CStack::prepareAttacked(BattleStackAttacked &bsa) const
|
||||
bsa.newAmount = 0;
|
||||
bsa.flags |= BattleStackAttacked::KILLED;
|
||||
bsa.killedAmount = count; //we cannot kill more creatures than we have
|
||||
|
||||
int resurrectFactor = valOfBonuses(Bonus::REBIRTH);
|
||||
if (resurrectFactor > 0 && casts) //there must be casts left
|
||||
{
|
||||
int resurrectedCount = base->count * resurrectFactor / 100;
|
||||
if (resurrectedCount)
|
||||
resurrectedCount += ((base->count % resurrectedCount) * resurrectFactor / 100.0f) > ran()%100 ? 1 : 0; //last stack has proportional chance to rebirth
|
||||
else //only one unit
|
||||
resurrectedCount += (base->count * resurrectFactor / 100.0f) > ran()%100 ? 1 : 0;
|
||||
if (hasBonusOfType(Bonus::REBIRTH, 1));
|
||||
amax (resurrectedCount, 1); //resurrect at least one Sacred Phoenix
|
||||
if (resurrectedCount)
|
||||
{
|
||||
bsa.flags |= BattleStackAttacked::REBIRTH;
|
||||
bsa.newAmount = resurrectedCount; //risky?
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -144,6 +144,7 @@ public:
|
||||
THex position; //position on battlefield; -2 - keep, -3 - lower tower, -4 - upper tower
|
||||
ui8 counterAttacks; //how many counter attacks can be performed more in this turn (by default set at the beginning of the round to 1)
|
||||
si16 shots; //how many shots left
|
||||
ui8 casts; //how many casts left
|
||||
|
||||
std::set<ECombatInfo> state;
|
||||
//overrides
|
||||
@ -199,7 +200,7 @@ public:
|
||||
h & static_cast<CBonusSystemNode&>(*this);
|
||||
h & static_cast<CStackBasicDescriptor&>(*this);
|
||||
h & ID & baseAmount & firstHPleft & owner & slot & attackerOwned & position & state & counterAttacks
|
||||
& shots & count;
|
||||
& shots & casts & count;
|
||||
|
||||
TSlot slot = (base ? base->armyObj->findStack(base) : -1);
|
||||
const CArmedInstance *army = (base ? base->armyObj : NULL);
|
||||
|
@ -167,7 +167,7 @@ namespace PrimarySkill
|
||||
BONUS_NAME(SPECIFIC_SPELL_POWER) /* value used for Thunderbolt and Resurrection casted by units, subtype - spell id */\
|
||||
BONUS_NAME(CREATURE_SPELL_POWER) /* value per unit, divided by 100 (so faerie Dragons have 800)*/ \
|
||||
BONUS_NAME(CREATURE_ENCHANT_POWER) /* total duration of spells casted by creature */ \
|
||||
BONUS_NAME(REBIRTH) /* val - percent of life restored */
|
||||
BONUS_NAME(REBIRTH) /* val - percent of life restored, subtype = 0 - regular, 1 - at least one unit (sacred Phoenix) */
|
||||
|
||||
/// Struct for handling bonuses of several types. Can be transfered to any hero
|
||||
struct DLL_EXPORT Bonus
|
||||
|
@ -1263,7 +1263,7 @@ struct BattleStackAttacked : public CPackForClient//3005
|
||||
|
||||
ui32 stackAttacked, attackerID;
|
||||
ui32 newAmount, newHP, killedAmount, damageAmount;
|
||||
enum EFlags {KILLED = 1, EFFECT = 2, SECONDARY = 4};
|
||||
enum EFlags {KILLED = 1, EFFECT = 2, SECONDARY = 4, REBIRTH = 8};
|
||||
ui8 flags; //uses EFlags (above)
|
||||
ui32 effect; //set only if flag EFFECT is set
|
||||
std::vector<StacksHealedOrResurrected> healedStacks; //used when life drain
|
||||
@ -1281,6 +1281,10 @@ struct BattleStackAttacked : public CPackForClient//3005
|
||||
{
|
||||
return flags & SECONDARY;
|
||||
}
|
||||
bool willRebirth() const//if stack was not a primary target (receives no spell effects)
|
||||
{
|
||||
return flags & REBIRTH;
|
||||
}
|
||||
bool lifeDrain() const //if this attack involves life drain effect
|
||||
{
|
||||
return healedStacks.size() > 0;
|
||||
|
@ -974,14 +974,21 @@ DLL_EXPORT void BattleStackAttacked::applyGs( CGameState *gs )
|
||||
CStack * at = gs->curB->getStack(stackAttacked);
|
||||
at->count = newAmount;
|
||||
at->firstHPleft = newHP;
|
||||
if(killed())
|
||||
at->state -= ALIVE;
|
||||
|
||||
if(killed())
|
||||
{
|
||||
at->state -= ALIVE;
|
||||
}
|
||||
//life drain handling
|
||||
for (int g=0; g<healedStacks.size(); ++g)
|
||||
{
|
||||
healedStacks[g].applyGs(gs);
|
||||
}
|
||||
if (willRebirth())
|
||||
{
|
||||
at->casts--;
|
||||
at->state.insert(ALIVE); //hmm?
|
||||
}
|
||||
}
|
||||
|
||||
DLL_EXPORT void BattleAttack::applyGs( CGameState *gs )
|
||||
|
@ -4366,8 +4366,8 @@ void CGameHandler::handleAfterAttackCasting( const BattleAttack & bat )
|
||||
continue;
|
||||
|
||||
//casting
|
||||
if (castMe)
|
||||
handleSpellCasting(spellID, spellLevel, destination, !attacker->attackerOwned, attacker->owner, NULL, NULL, attacker->count, SpellCasting::AFTER_ATTACK_CASTING, attacker);
|
||||
if (castMe) //stacks use 0 spell power. If needed, default = 3 or custom value is used
|
||||
handleSpellCasting(spellID, spellLevel, destination, !attacker->attackerOwned, attacker->owner, NULL, NULL, 0, SpellCasting::AFTER_ATTACK_CASTING, attacker);
|
||||
}
|
||||
}
|
||||
if (attacker->hasBonusOfType(Bonus::DEATH_STARE)) // spell id 79
|
||||
|
Loading…
Reference in New Issue
Block a user