Skip to content

Commit

Permalink
implemented proper concentration checks
Browse files Browse the repository at this point in the history
  • Loading branch information
lynxlynxlynx committed May 8, 2014
1 parent 0a8af6c commit cbfa777
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 0 deletions.
52 changes: 52 additions & 0 deletions gemrb/core/Scriptable/Actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9700,5 +9700,57 @@ void Actor::ReleaseCurrentAction()
Scriptable::ReleaseCurrentAction();
}

// concentration is annoying: besides special cases, every caster should
// check if there's an enemy nearby
bool Actor::ConcentrationCheck() const
{
if (!core->HasFeature(GF_3ED_RULES)) return true;

// anyone in a 5' radius?
// 9 is from the GetSpellDistance estimate
Actor **neighbours = area->GetAllActorsInRadius(Pos, GA_NO_DEAD|GA_NO_ALLY|GA_NO_SELF|GA_NO_UNSCHEDULED|GA_NO_HIDDEN, 5*9);
Actor **poi = neighbours;
bool enemyFound = false;
while (*poi) {
Actor *neighbour = *poi;
if (neighbour->GetStat(IE_EA) > EA_EVILCUTOFF) {
enemyFound = true;
break;
}
poi++;
}
free(neighbours);
if (!enemyFound) return true;

// so there is someone out to get us and we should do the real concentration check
int roll = LuckyRoll(1, 20, 0);
// TODO: the manual replaces the con bonus with an int one (verify!)
int concentration = GetStat(IE_CONCENTRATION);
int bonus = GetAbilityBonus(IE_INT);
if (HasFeat(FEAT_COMBAT_CASTING)) {
bonus += 4;
}

Spell* spl = gamedata->GetSpell(SpellResRef, true);
if (!spl) return true;
int spellLevel = spl->SpellLevel;
gamedata->FreeSpell(spl, SpellResRef, false);

if (roll + concentration + bonus < 15 + spellLevel) {
if (InParty) {
displaymsg->DisplayRollStringName(39258, DMC_LIGHTGREY, this, roll + concentration, 15 + spellLevel, bonus);
} else {
displaymsg->DisplayRollStringName(39265, DMC_LIGHTGREY, this);
}
return false;
} else {
if (InParty) {
// ~Successful spell casting concentration check! Check roll %d vs. difficulty %d (%d bonus)~
displaymsg->DisplayRollStringName(39257, DMC_LIGHTGREY, this, roll + concentration, 15 + spellLevel, bonus);
}
}
return true;
}

}

1 change: 1 addition & 0 deletions gemrb/core/Scriptable/Actor.h
Original file line number Diff line number Diff line change
Expand Up @@ -881,6 +881,7 @@ class GEM_EXPORT Actor : public Movable {
void SetDisarmingTrap(ieDword trapId) { disarmTrap = trapId; }
ieDword GetDisarmingTrap() const { return disarmTrap; }
void ReleaseCurrentAction();
bool ConcentrationCheck() const;
};
}

Expand Down
5 changes: 5 additions & 0 deletions gemrb/core/Scriptable/Scriptable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1163,6 +1163,11 @@ int Scriptable::CanCast(const ieResRef SpellResRef, bool verbose) {
displaymsg->DisplayConstantStringName(STR_MISCASTMAGIC, DMC_WHITE, this);
return 0;
}

// iwd2: make a concentration check if needed
if (!actor->ConcentrationCheck()) {
return 0;
}
}

return 1;
Expand Down

0 comments on commit cbfa777

Please sign in to comment.