mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-26 22:57:00 +02:00
* next part of stack bonus system
* stacks can shoot again
This commit is contained in:
parent
5ce428cf1d
commit
27ffad3580
@ -2582,21 +2582,19 @@ void CBattleHex::clickRight(boost::logic::tribool down)
|
|||||||
int stID = LOCPLINT->cb->battleGetStack(myNumber); //id of stack being on this tile
|
int stID = LOCPLINT->cb->battleGetStack(myNumber); //id of stack being on this tile
|
||||||
if(hovered && strictHovered && stID!=-1)
|
if(hovered && strictHovered && stID!=-1)
|
||||||
{
|
{
|
||||||
CStack myst = *LOCPLINT->cb->battleGetStackByID(stID); //stack info
|
const CStack & myst = *LOCPLINT->cb->battleGetStackByID(stID); //stack info
|
||||||
if(!myst.alive()) return;
|
if(!myst.alive()) return;
|
||||||
StackState *pom = NULL;
|
StackState *pom = NULL;
|
||||||
if(down)
|
if(down)
|
||||||
{
|
{
|
||||||
pom = new StackState();
|
pom = new StackState();
|
||||||
const CGHeroInstance *h = myst.owner == myInterface->attackingHeroInstance->tempOwner ? myInterface->attackingHeroInstance : myInterface->defendingHeroInstance;
|
const CGHeroInstance *h = myst.owner == myInterface->attackingHeroInstance->tempOwner ? myInterface->attackingHeroInstance : myInterface->defendingHeroInstance;
|
||||||
if(h)
|
|
||||||
{
|
pom->attackBonus = myst.Attack() - myst.creature->attack;
|
||||||
pom->attackBonus = h->getPrimSkillLevel(0);
|
pom->defenseBonus = myst.Defense() - myst.creature->defence;
|
||||||
pom->defenseBonus = h->getPrimSkillLevel(1);
|
|
||||||
pom->luck = myst.Luck();
|
pom->luck = myst.Luck();
|
||||||
pom->morale = myst.Morale();
|
pom->morale = myst.Morale();
|
||||||
pom->speedBonus = myst.Speed() - myst.creature->speed;
|
pom->speedBonus = myst.Speed() - myst.creature->speed;
|
||||||
}
|
|
||||||
|
|
||||||
pom->shotsLeft = myst.shots;
|
pom->shotsLeft = myst.shots;
|
||||||
for(int vb=0; vb<myst.effects.size(); ++vb)
|
for(int vb=0; vb<myst.effects.size(); ++vb)
|
||||||
|
@ -480,35 +480,42 @@ bool CStack::hasFeatureOfType(StackFeature::ECombatFeatures type, int subtype) c
|
|||||||
|
|
||||||
CStack::CStack(CCreature * C, int A, int O, int I, bool AO, int S)
|
CStack::CStack(CCreature * C, int A, int O, int I, bool AO, int S)
|
||||||
:ID(I), creature(C), amount(A), baseAmount(A), firstHPleft(C->hitPoints), owner(O), slot(S), attackerOwned(AO), position(-1),
|
:ID(I), creature(C), amount(A), baseAmount(A), firstHPleft(C->hitPoints), owner(O), slot(S), attackerOwned(AO), position(-1),
|
||||||
counterAttacks(1), shots(C->shots), speed(creature->speed), features(C->abilities), attack(C->attack), defense(C->defence)
|
counterAttacks(1), shots(C->shots), features(C->abilities)
|
||||||
{
|
{
|
||||||
state.insert(ALIVE);
|
state.insert(ALIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
ui32 CStack::Speed() const
|
ui32 CStack::Speed() const
|
||||||
{
|
{
|
||||||
int premy=0;
|
int speed = creature->speed;
|
||||||
const StackEffect *effect = 0;
|
|
||||||
//haste effect check
|
speed += valOfFeatures(StackFeature::SPEED_BONUS);
|
||||||
effect = getEffect(53);
|
|
||||||
if(effect)
|
int percentBonus = 0;
|
||||||
premy += VLC->spellh->spells[effect->id].powers[effect->level];
|
for(int g=0; g<features.size(); ++g)
|
||||||
//slow effect check
|
|
||||||
effect = getEffect(54);
|
|
||||||
if(effect)
|
|
||||||
premy -= (creature->speed * VLC->spellh->spells[effect->id].powers[effect->level])/100;
|
|
||||||
//prayer effect check
|
|
||||||
effect = getEffect(48);
|
|
||||||
if(effect)
|
|
||||||
premy += VLC->spellh->spells[effect->id].powers[effect->level];
|
|
||||||
//bind effect check
|
|
||||||
effect = getEffect(72);
|
|
||||||
if(effect)
|
|
||||||
{
|
{
|
||||||
premy = creature->speed; //don't use '- creature->speed' - speed is unsigned!
|
if(features[g].type == StackFeature::SPEED_BONUS)
|
||||||
premy = -premy;
|
{
|
||||||
|
percentBonus += features[g].additionalInfo;
|
||||||
}
|
}
|
||||||
return speed + premy;
|
}
|
||||||
|
|
||||||
|
if(percentBonus < 0)
|
||||||
|
{
|
||||||
|
speed = (abs(percentBonus) * speed)/100;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
speed = ((100 + percentBonus) * speed)/100;
|
||||||
|
}
|
||||||
|
|
||||||
|
//bind effect check
|
||||||
|
if(getEffect(72))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CStack::StackEffect * CStack::getEffect(ui16 id) const
|
const CStack::StackEffect * CStack::getEffect(ui16 id) const
|
||||||
@ -564,48 +571,28 @@ si8 CStack::Luck() const
|
|||||||
|
|
||||||
si32 CStack::Attack() const
|
si32 CStack::Attack() const
|
||||||
{
|
{
|
||||||
si32 ret = attack; //value to be returned
|
si32 ret = creature->attack; //value to be returned
|
||||||
|
|
||||||
if(getEffect(56)) //frenzy for attacker
|
if(hasFeatureOfType(StackFeature::IN_FRENZY)) //frenzy for attacker
|
||||||
{
|
{
|
||||||
ret += (VLC->spellh->spells[56].powers[getEffect(56)->level]/100.0) * defense;
|
ret += (VLC->spellh->spells[56].powers[getEffect(56)->level]/100.0) * Defense(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(getEffect(48)) //attacker's prayer handling
|
ret += valOfFeatures(StackFeature::ATTACK_BONUS);
|
||||||
{
|
|
||||||
ret += VLC->spellh->spells[48].powers[getEffect(48)->level];
|
|
||||||
}
|
|
||||||
|
|
||||||
if(getEffect(45)) //weakness handling
|
|
||||||
{
|
|
||||||
ret -= VLC->spellh->spells[45].powers[getEffect(45)->level];
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
si32 CStack::Defense() const
|
si32 CStack::Defense(bool withFrenzy /*= true*/) const
|
||||||
{
|
{
|
||||||
si32 ret = defense;
|
si32 ret = creature->defence;
|
||||||
|
|
||||||
if(getEffect(56)) //frenzy for defender
|
if(withFrenzy && getEffect(56)) //frenzy for defender
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(getEffect(48)) //defender's prayer handling
|
ret += valOfFeatures(StackFeature::DEFENCE_BONUS);
|
||||||
{
|
|
||||||
ret += VLC->spellh->spells[48].powers[getEffect(48)->level];
|
|
||||||
}
|
|
||||||
if(getEffect(47)) //defender's disrupting ray handling
|
|
||||||
{
|
|
||||||
int howMany = howManyEffectsSet(47);
|
|
||||||
ret -= VLC->spellh->spells[47].powers[getEffect(47)->level] * howMany;
|
|
||||||
}
|
|
||||||
if(getEffect(46)) //stone skin handling
|
|
||||||
{
|
|
||||||
ret += VLC->spellh->spells[46].powers[getEffect(46)->level];
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
10
CGameState.h
10
CGameState.h
@ -154,9 +154,9 @@ public:
|
|||||||
ui16 position; //position on battlefield
|
ui16 position; //position on battlefield
|
||||||
ui8 counterAttacks; //how many counter attacks can be performed more in this turn (by default set at the beginning of the round to 1)
|
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
|
si16 shots; //how many shots left
|
||||||
ui8 speed; //speed of stack with hero bonus
|
//ui8 speed; //speed of stack with hero bonus
|
||||||
si32 attack; //attack of stack with hero bonus
|
//si32 attack; //attack of stack with hero bonus
|
||||||
si32 defense; //defense of stack with hero bonus
|
//si32 defense; //defense of stack with hero bonus
|
||||||
si8 morale, luck; //base stack luck/morale
|
si8 morale, luck; //base stack luck/morale
|
||||||
|
|
||||||
std::vector<StackFeature> features;
|
std::vector<StackFeature> features;
|
||||||
@ -185,7 +185,7 @@ public:
|
|||||||
si8 Morale() const; //get morale of stack with all modificators
|
si8 Morale() const; //get morale of stack with all modificators
|
||||||
si8 Luck() const; //get luck of stack with all modificators
|
si8 Luck() const; //get luck of stack with all modificators
|
||||||
si32 Attack() const; //get attack of stack with all modificators
|
si32 Attack() const; //get attack of stack with all modificators
|
||||||
si32 Defense() const; //get defense of stack with all modificators
|
si32 Defense(bool withFrenzy = true) const; //get defense of stack with all modificators
|
||||||
template <typename Handler> void save(Handler &h, const int version)
|
template <typename Handler> void save(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & creature->idNumber;
|
h & creature->idNumber;
|
||||||
@ -200,7 +200,7 @@ public:
|
|||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & ID & amount & baseAmount & firstHPleft & owner & slot & attackerOwned & position & state & counterAttacks
|
h & ID & amount & baseAmount & firstHPleft & owner & slot & attackerOwned & position & state & counterAttacks
|
||||||
& shots & morale & luck & speed & attack & defense;
|
& shots & morale & luck;
|
||||||
if(h.saving)
|
if(h.saving)
|
||||||
save(h,version);
|
save(h,version);
|
||||||
else
|
else
|
||||||
|
@ -479,7 +479,7 @@ DLL_EXPORT void BattleNextRound::applyGs( CGameState *gs )
|
|||||||
//the same as above for features
|
//the same as above for features
|
||||||
std::vector<StackFeature> tmpFeatures = s->features;
|
std::vector<StackFeature> tmpFeatures = s->features;
|
||||||
s->features.clear();
|
s->features.clear();
|
||||||
for(int i=0; i < tmpEffects.size(); i++)
|
for(int i=0; i < tmpFeatures.size(); i++)
|
||||||
{
|
{
|
||||||
if(tmpFeatures[i].duration == StackFeature::N_TURNS)
|
if(tmpFeatures[i].duration == StackFeature::N_TURNS)
|
||||||
{
|
{
|
||||||
@ -681,6 +681,41 @@ std::vector<StackFeature> stackEffectToFeature(const CStack::StackEffect & sse)
|
|||||||
return sf;
|
return sf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void actualizeEffect(CStack * s, CStack::StackEffect & ef)
|
||||||
|
{
|
||||||
|
//actualizing effects vector
|
||||||
|
for(int g=0; g<s->effects.size(); ++g)
|
||||||
|
{
|
||||||
|
if(s->effects[g].id == ef.id)
|
||||||
|
{
|
||||||
|
s->effects[g].turnsRemain = std::max(s->effects[g].turnsRemain, ef.turnsRemain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//actualizing features vector
|
||||||
|
std::vector<StackFeature> sf = stackEffectToFeature(ef);
|
||||||
|
for(int b=0; b<sf.size(); ++b)
|
||||||
|
{
|
||||||
|
for(int g=0; g<s->features.size(); ++g)
|
||||||
|
{
|
||||||
|
if(s->features[g].source == StackFeature::SPELL_EFFECT && s->features[g].type == sf[b].type && s->features[g].subtype == sf[b].subtype)
|
||||||
|
{
|
||||||
|
s->features[g].turnsRemain = std::max(s->features[g].turnsRemain, ef.turnsRemain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool containsEff(const std::vector<CStack::StackEffect> & vec, int effectId)
|
||||||
|
{
|
||||||
|
for(int g=0; g<vec.size(); ++g)
|
||||||
|
{
|
||||||
|
if(vec[g].id == effectId)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
DLL_EXPORT void SetStackEffect::applyGs( CGameState *gs )
|
DLL_EXPORT void SetStackEffect::applyGs( CGameState *gs )
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(ui32 id, stacks)
|
BOOST_FOREACH(ui32 id, stacks)
|
||||||
@ -688,32 +723,18 @@ DLL_EXPORT void SetStackEffect::applyGs( CGameState *gs )
|
|||||||
CStack *s = gs->curB->getStack(id);
|
CStack *s = gs->curB->getStack(id);
|
||||||
if(s)
|
if(s)
|
||||||
{
|
{
|
||||||
s->effects.push_back(effect); //adding effect
|
if(effect.id == 42 || !containsEff(s->effects, effect.id))//disrupting ray or not on the list - just add
|
||||||
|
{
|
||||||
|
s->effects.push_back(effect);
|
||||||
std::vector<StackFeature> sf = stackEffectToFeature(effect);
|
std::vector<StackFeature> sf = stackEffectToFeature(effect);
|
||||||
for(int n=0; n<sf.size(); ++n)
|
for(int n=0; n<sf.size(); ++n)
|
||||||
{
|
|
||||||
if(effect.id == 42) //disrupting ray
|
|
||||||
{
|
|
||||||
s->features.push_back(sf[n]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//don't add multiple instances of the same feature from spell source
|
|
||||||
bool added = false;
|
|
||||||
for(int f=0; f<s->features.size(); ++f)
|
|
||||||
{
|
|
||||||
if(s->features[f].source == StackFeature::SPELL_EFFECT && s->features[f].type == sf[n].type)
|
|
||||||
{
|
|
||||||
s->features[f].turnsRemain = std::max(s->features[f].turnsRemain, effect.turnsRemain);
|
|
||||||
added = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!added)
|
|
||||||
{
|
{
|
||||||
s->features.push_back(sf[n]);
|
s->features.push_back(sf[n]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else //just actualize
|
||||||
|
{
|
||||||
|
actualizeEffect(s, effect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -47,7 +47,7 @@ struct StackFeature
|
|||||||
SELF_LUCK /*halfling*/,
|
SELF_LUCK /*halfling*/,
|
||||||
ATTACK_BONUS /*subtype: -1 - any attack, 0 - melee, 1 - ranged*/,
|
ATTACK_BONUS /*subtype: -1 - any attack, 0 - melee, 1 - ranged*/,
|
||||||
DEFENCE_BONUS /*subtype: -1 - any attack, 0 - melee, 1 - ranged*/,
|
DEFENCE_BONUS /*subtype: -1 - any attack, 0 - melee, 1 - ranged*/,
|
||||||
SPEED_BONUS /*additional info - percent of speed bonus applied after direct bonuses; >0 - added, <0 - substracted*/,
|
SPEED_BONUS /*additional info - percent of speed bonus applied after direct bonuses; >0 - added, <0 - substracted to this part*/,
|
||||||
HP_BONUS, ENCHANTER, HEALER, SIEGE_WEAPON, LUCK_BONUS, MORALE_BONUS, HYPNOTIZED,
|
HP_BONUS, ENCHANTER, HEALER, SIEGE_WEAPON, LUCK_BONUS, MORALE_BONUS, HYPNOTIZED,
|
||||||
ADDITIONAL_RETAILATION /*value - number of additional retailations*/,
|
ADDITIONAL_RETAILATION /*value - number of additional retailations*/,
|
||||||
MAGIC_MIRROR /* value - chance of redirecting in %*/,
|
MAGIC_MIRROR /* value - chance of redirecting in %*/,
|
||||||
|
@ -841,13 +841,13 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army
|
|||||||
stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero1->tempOwner, stacks.size(), true,i->first));
|
stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero1->tempOwner, stacks.size(), true,i->first));
|
||||||
if(hero1)
|
if(hero1)
|
||||||
{
|
{
|
||||||
stacks.back()->speed += hero1->valOfBonuses(HeroBonus::STACKS_SPEED);
|
stacks.back()->features.push_back(makeFeature(StackFeature::SPEED_BONUS, StackFeature::WHOLE_BATTLE, 0, hero1->valOfBonuses(HeroBonus::STACKS_SPEED), StackFeature::BONUS_FROM_HERO));
|
||||||
//base luck/morale calculations
|
//base luck/morale calculations
|
||||||
//TODO: check if terrain is native, add bonuses for neutral stacks, bonuses from town
|
//TODO: check if terrain is native, add bonuses for neutral stacks, bonuses from town
|
||||||
stacks.back()->morale = hero1->getCurrentMorale(i->first,false);
|
stacks.back()->morale = hero1->getCurrentMorale(i->first,false);
|
||||||
stacks.back()->luck = hero1->getCurrentLuck(i->first,false);
|
stacks.back()->luck = hero1->getCurrentLuck(i->first,false);
|
||||||
stacks.back()->attack += hero1->getPrimSkillLevel(0);
|
stacks.back()->features.push_back(makeFeature(StackFeature::ATTACK_BONUS, StackFeature::WHOLE_BATTLE, 0, hero1->getPrimSkillLevel(0), StackFeature::BONUS_FROM_HERO));
|
||||||
stacks.back()->defense += hero1->getPrimSkillLevel(1);
|
stacks.back()->features.push_back(makeFeature(StackFeature::DEFENCE_BONUS, StackFeature::WHOLE_BATTLE, 0, hero1->getPrimSkillLevel(1), StackFeature::BONUS_FROM_HERO));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -894,11 +894,11 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army
|
|||||||
//TODO: check if terrain is native, add bonuses for neutral stacks, bonuses from town
|
//TODO: check if terrain is native, add bonuses for neutral stacks, bonuses from town
|
||||||
if(hero2)
|
if(hero2)
|
||||||
{
|
{
|
||||||
stacks.back()->speed += hero2->valOfBonuses(HeroBonus::STACKS_SPEED);
|
stacks.back()->features.push_back(makeFeature(StackFeature::SPEED_BONUS, StackFeature::WHOLE_BATTLE, 0, hero2->valOfBonuses(HeroBonus::STACKS_SPEED), StackFeature::BONUS_FROM_HERO));
|
||||||
stacks.back()->morale = hero2->getCurrentMorale(i->first,false);
|
stacks.back()->morale = hero2->getCurrentMorale(i->first,false);
|
||||||
stacks.back()->luck = hero2->getCurrentLuck(i->first,false);
|
stacks.back()->luck = hero2->getCurrentLuck(i->first,false);
|
||||||
stacks.back()->attack += hero2->getPrimSkillLevel(0);
|
stacks.back()->features.push_back(makeFeature(StackFeature::ATTACK_BONUS, StackFeature::WHOLE_BATTLE, 0, hero2->getPrimSkillLevel(0), StackFeature::BONUS_FROM_HERO));
|
||||||
stacks.back()->defense += hero2->getPrimSkillLevel(1);
|
stacks.back()->features.push_back(makeFeature(StackFeature::DEFENCE_BONUS, StackFeature::WHOLE_BATTLE, 0, hero2->getPrimSkillLevel(1), StackFeature::BONUS_FROM_HERO));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user