1
0
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:
DjWarmonger 2011-07-08 14:54:20 +00:00
parent 1bf9bb4d94
commit 5269e845fd
9 changed files with 70 additions and 32 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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
{

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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 )

View File

@ -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