Browse files

implemented iwd2 saving throw system (to best of my knowledge)

  • Loading branch information...
1 parent a1a8512 commit fe62c9d11024194f0776c199807bf6e150d0338d @lynxlynxlynx lynxlynxlynx committed Jan 12, 2014
View
7 gemrb/core/EffectQueue.cpp
@@ -1087,7 +1087,12 @@ static bool check_resistance(Actor* actor, Effect* fx)
bool saved = false;
for (int i=0;i<5;i++) {
if( fx->SavingThrowType&(1<<i)) {
- saved = actor->GetSavingThrow(i, bonus);
+ // FIXME: first bonus handling for iwd2 is just a guess
+ if (iwd2fx) {
+ saved = actor->GetSavingThrow(i, bonus-fx->SavingThrowBonus, fx->SpellLevel, fx->SavingThrowBonus);
+ } else {
+ saved = actor->GetSavingThrow(i, bonus);
+ }
if( saved) {
break;
}
View
26 gemrb/core/Scriptable/Actor.cpp
@@ -3222,21 +3222,39 @@ void Actor::RollSaves()
// in adnd, the stat represents the limit (DC) that the roll with all the boni has to pass
// since it is a derived stat, we also store the direct effect bonus/malus in it, but make sure to do it negated
-// FIXME: in 3ed, the stat is added to the roll and boni (not negated), then compared to some predefined value (DC)
+// in 3ed, the stat is added to the roll and boni (not negated), then compared to some predefined value (DC)
#define SAVECOUNT 5
static int savingthrows[SAVECOUNT]={IE_SAVEVSSPELL, IE_SAVEVSBREATH, IE_SAVEVSDEATH, IE_SAVEVSWANDS, IE_SAVEVSPOLY};
/** returns true if actor made the save against saving throw type */
-bool Actor::GetSavingThrow(ieDword type, int modifier)
+bool Actor::GetSavingThrow(ieDword type, int modifier, int spellLevel, int saveBonus)
{
assert(type<SAVECOUNT);
InternalFlags|=IF_USEDSAVE;
int ret = SavingThrow[type];
if (ret == 1) return false;
if (ret == SAVEROLL) return true;
- ret += modifier + GetStat(IE_LUCK);
- return ret > (int) GetStat(savingthrows[type]);
+
+ if (!third) {
+ ret += modifier + GetStat(IE_LUCK);
+ return ret > (int) GetStat(savingthrows[type]);
+ }
+
+ int roll = ret;
+ // NOTE: assuming criticals apply to iwd2 too
+ // NOTE: we use GetStat, assuming the stat save bonus can never be negated like some others
+ int save = GetStat(savingthrows[type]);
+ ret = roll + save + modifier;
+ if (ret > 10 + spellLevel + saveBonus) {
+ // ~Saving throw result: (d20 + save + bonuses) %d + %d + %d vs. (10 + spellLevel + saveMod) 10 + %d + %d - Success!~
+ displaymsg->DisplayRollStringName(40974, DMC_LIGHTGREY, this, roll, save, modifier, spellLevel, saveBonus);
+ return true;
+ } else {
+ // ~Saving throw result: (d20 + save + bonuses) %d + %d + %d vs. (10 + spellLevel + saveMod) 10 + %d + %d - Failed!~
+ displaymsg->DisplayRollStringName(40975, DMC_LIGHTGREY, this, roll, save, modifier, spellLevel, saveBonus);
+ return false;
+ }
}
/** implements a generic opcode function, modify modified stats
View
2 gemrb/core/Scriptable/Actor.h
@@ -440,7 +440,7 @@ class GEM_EXPORT Actor : public Movable {
/** gets saving throws */
void RollSaves();
/** returns a saving throw */
- bool GetSavingThrow(ieDword type, int modifier);
+ bool GetSavingThrow(ieDword type, int modifier, int spellLevel=0, int saveBonus=0);
/** Returns true if the actor is targetable */
bool ValidTarget(int ga_flags, Scriptable *checker = NULL) const;
/** Clamps a stat value to the valid range for the respective stat */
View
29 gemrb/plugins/IWDOpcodes/IWDOpcodes.cpp
@@ -553,10 +553,21 @@ static int check_iwd_targeting(Scriptable* Owner, Actor* target, ieDword value,
case STI_CIRCLESIZE:
return DiffCore((ieDword) target->GetAnims()->GetCircleSize(), val, rel);
case STI_EVASION:
- if (target->GetThiefLevel() < 7 ) {
- return 0;
+ if (enhanced_effects) {
+ // NOTE: no idea if this is used in iwd2 too
+ // FIXME: check for evasion itself
+ if (target->GetThiefLevel() < 2 && target->GetMonkLevel() < 1) {
+ return 0;
+ }
+ // FIXME: if it is used, make sure to pass correct values here (pulled from the effect)
+ val = target->GetSavingThrow(4, 0); // reflex
+ } else {
+ if (target->GetThiefLevel() < 7 ) {
+ return 0;
+ }
+ val = target->GetSavingThrow(1,0); //breath
}
- val = target->GetSavingThrow(1,0); //breath
+
if (val) {
return 1;
}
@@ -1195,7 +1206,13 @@ int fx_blinding_orb (Scriptable* Owner, Actor* target, Effect* fx)
damage *= 2;
}
//check saving throw
- bool st = target->GetSavingThrow(0,0); //spell
+ bool st;
+ if (enhanced_effects) {
+ st = target->GetSavingThrow(2, 0, fx->SpellLevel, fx->SavingThrowBonus); // fortitude
+ } else {
+ st = target->GetSavingThrow(0,0); //spell
+ }
+
if (st) {
target->Damage(damage/2, DAMAGE_FIRE, Owner, fx->IsVariable, fx->SavingThrowType);
return FX_NOT_APPLIED;
@@ -2659,7 +2676,9 @@ int fx_control (Scriptable* Owner, Actor* target, Effect* fx)
if (fx->Parameter3 && fx->Parameter4<game->GameTime) {
fx->Parameter3 = 0;
- if (target->GetSavingThrow(IE_SAVEWILL, 0)) return FX_NOT_APPLIED;
+ if (target->GetSavingThrow(IE_SAVEWILL, 0, fx->SpellLevel, fx->SavingThrowBonus)) {
+ return FX_NOT_APPLIED;
+ }
}
if(0) print("fx_control(%2d)", fx->Opcode);
bool enemyally = true;

0 comments on commit fe62c9d

Please sign in to comment.