1
0
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:
mateuszb 2009-05-17 15:24:50 +00:00
parent 5ce428cf1d
commit 27ffad3580
6 changed files with 99 additions and 93 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -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 %*/,

View File

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