Fix calling restore_sp to drain SP from an affect special node
This also adds an Allow Resist flag to determine whether the target's Mage Spells or Priest Spells skill can reduce the amount drained. Thanks to @fosnola for spotting this issue.
This commit is contained in:
@@ -820,7 +820,8 @@ health to 0.
|
||||
can be changed to a maximum of 100 or a minimum of 0.
|
||||
<dl>
|
||||
<dt>Extra 1a:</dt><dd>The amount to raise/lower spell points.</dd>
|
||||
<dt>Extra 1b:</dt><dd>If 0, spell points are raised. Otherwise, theyre lowered.</dd></dd>
|
||||
<dt>Extra 1b:</dt><dd>If 0, spell points are raised. Otherwise, they're lowered.</dd></dd>
|
||||
<dt>Extra 1c:</dt><dd>Only used when lowering spell points. If 0, the spell points are lowered by the exact amount specified. If 1, targets with Mage Spells or Priest Spells are allowed to partially resist the effect.</dd>
|
||||
|
||||
<dt>Type 84: Affect Experience</dt><dd>Adds/drains experience. If the target is a monster,
|
||||
this has no effect.
|
||||
|
@@ -857,7 +857,7 @@ void pc_attack_weapon(short who_att,iLiving& target,short hit_adj,short dam_adj,
|
||||
else if(cPlayer* check = dynamic_cast<cPlayer*>(&target))
|
||||
mage = check->skill(eSkill::MAGE_SPELLS), cleric = check->skill(eSkill::PRIEST_SPELLS);
|
||||
if(mage + cleric > 0 && get_ran(1,0,1) == 1)
|
||||
target.drain_sp(weap.abil_strength);
|
||||
target.drain_sp(weap.abil_strength, true);
|
||||
if(before > target.get_magic()) {
|
||||
add_string_to_buf(" Blade drains energy.");
|
||||
attacker.restore_sp(before / 3);
|
||||
@@ -1854,7 +1854,7 @@ void fire_missile(location target) {
|
||||
else if(cPlayer* check = dynamic_cast<cPlayer*>(victim))
|
||||
mage = check->skill(eSkill::MAGE_SPELLS), cleric = check->skill(eSkill::PRIEST_SPELLS);
|
||||
if(mage + cleric > 0 && get_ran(1,0,1) == 1)
|
||||
victim->drain_sp(ammo.abil_strength);
|
||||
victim->drain_sp(ammo.abil_strength, true);
|
||||
if(before > victim->get_magic()) {
|
||||
add_string_to_buf(" Missile drains energy.");
|
||||
missile_firer.restore_sp((before - victim->get_magic()) / 3);
|
||||
|
@@ -2232,7 +2232,7 @@ void general_spec(const runtime_state& ctx) {
|
||||
break;
|
||||
case eSpecType::REST:
|
||||
check_mess = true;
|
||||
do_rest(spec.ex1a, spec.ex1b, spec.ex1b);
|
||||
do_rest(max(spec.ex1a, 0), max(spec.ex1b, 0), max(spec.ex1b, 0));
|
||||
break;
|
||||
case eSpecType::END_SCENARIO:
|
||||
end_scenario = true;
|
||||
@@ -2789,7 +2789,7 @@ void affect_spec(const runtime_state& ctx) {
|
||||
case eSpecType::AFFECT_SP:
|
||||
if(spec.ex1b == 0)
|
||||
pc.restore_sp(spec.ex1a);
|
||||
else pc.restore_sp(-spec.ex1a);
|
||||
else pc.drain_sp(spec.ex1a, spec.ex1c);
|
||||
if(cCreature* who = dynamic_cast<cCreature*>(&pc)) {
|
||||
if(spec.ex1b == 0)
|
||||
who->spell_note(43);
|
||||
|
@@ -105,6 +105,7 @@ void cCreature::cure(int amt) {
|
||||
|
||||
void cCreature::restore_sp(int amt) {
|
||||
if(!is_alive()) return;
|
||||
if(amt <= 0) return;
|
||||
if(mp >= max_mp) return;
|
||||
mp += amt;
|
||||
if(mp > max_mp)
|
||||
@@ -112,16 +113,17 @@ void cCreature::restore_sp(int amt) {
|
||||
if(mp < 0) mp = 0;
|
||||
}
|
||||
|
||||
void cCreature::drain_sp(int drain) {
|
||||
void cCreature::drain_sp(int drain, bool allow_resist) {
|
||||
drain = magic_adjust(drain);
|
||||
if(drain > 0) {
|
||||
if(drain <= 0) return;
|
||||
if(allow_resist) {
|
||||
if(mu > 0 && mp > 4)
|
||||
drain = min(mp, drain / 3);
|
||||
else if(cl > 0 && mp > 10)
|
||||
drain = min(mp, drain / 2);
|
||||
mp -= drain;
|
||||
if(mp < 0) mp = 0;
|
||||
}
|
||||
mp -= drain;
|
||||
if(mp < 0) mp = 0;
|
||||
}
|
||||
|
||||
void cCreature::poison(int how_much) {
|
||||
|
@@ -46,7 +46,7 @@ public:
|
||||
void scare(int how_much);
|
||||
void sleep(eStatus type, int how_much, int adj);
|
||||
void avatar();
|
||||
void drain_sp(int how_much);
|
||||
void drain_sp(int how_much, bool allow_resist);
|
||||
void restore_sp(int how_much);
|
||||
|
||||
int get_health() const;
|
||||
|
@@ -46,7 +46,7 @@ public:
|
||||
virtual void scare(int how_much) = 0;
|
||||
virtual void sleep(eStatus type, int how_much, int adj) = 0; // Also handles paralysis, charm, and forcecage
|
||||
virtual void avatar() = 0;
|
||||
virtual void drain_sp(int how_much) = 0;
|
||||
virtual void drain_sp(int how_much, bool allow_resist) = 0;
|
||||
virtual void restore_sp(int how_much) = 0;
|
||||
|
||||
virtual int get_health() const = 0;
|
||||
|
@@ -561,9 +561,9 @@ void cParty::avatar() {
|
||||
adven[i]->avatar();
|
||||
}
|
||||
|
||||
void cParty::drain_sp(int how_much) {
|
||||
void cParty::drain_sp(int how_much, bool allow_resist) {
|
||||
for(int i = 0; i < 6; i++)
|
||||
adven[i]->drain_sp(how_much);
|
||||
adven[i]->drain_sp(how_much, allow_resist);
|
||||
}
|
||||
|
||||
void cParty::restore_sp(int how_much) {
|
||||
|
@@ -175,7 +175,7 @@ public:
|
||||
void sleep(eStatus type, int how_much, int adj);
|
||||
void clear_bad_status();
|
||||
void avatar();
|
||||
void drain_sp(int how_much);
|
||||
void drain_sp(int how_much, bool allow_resist);
|
||||
void restore_sp(int how_much);
|
||||
|
||||
int get_health() const;
|
||||
|
@@ -97,17 +97,18 @@ void cPlayer::avatar() {
|
||||
status[eStatus::MARTYRS_SHIELD] = 8;
|
||||
}
|
||||
|
||||
void cPlayer::drain_sp(int drain) {
|
||||
void cPlayer::drain_sp(int drain, bool allow_resist) {
|
||||
if(drain <= 0) return;
|
||||
int mu = skills[eSkill::MAGE_SPELLS];
|
||||
int cl = skills[eSkill::PRIEST_SPELLS];
|
||||
if(drain > 0) {
|
||||
if(allow_resist) {
|
||||
if(mu > 0 && cur_sp > 4)
|
||||
drain = min(cur_sp, drain / 3);
|
||||
else if(cl > 0 && cur_sp > 10)
|
||||
drain = min(cur_sp, drain / 2);
|
||||
cur_sp -= drain;
|
||||
if(cur_sp < 0) cur_sp = 0;
|
||||
}
|
||||
cur_sp -= drain;
|
||||
if(cur_sp < 0) cur_sp = 0;
|
||||
}
|
||||
|
||||
void cPlayer::scare(int) {
|
||||
@@ -300,6 +301,7 @@ void cPlayer::acid(int how_much) {
|
||||
|
||||
void cPlayer::restore_sp(int amt) {
|
||||
if(!is_alive()) return;
|
||||
if(amt <= 0) return;
|
||||
if(cur_sp >= max_sp) return;
|
||||
cur_sp += amt;
|
||||
if(cur_sp > max_sp)
|
||||
|
@@ -134,7 +134,7 @@ public:
|
||||
void scare(int how_much);
|
||||
void sleep(eStatus type, int how_much, int adj);
|
||||
void avatar();
|
||||
void drain_sp(int how_much);
|
||||
void drain_sp(int how_much, bool allow_resist);
|
||||
void restore_sp(int how_much);
|
||||
|
||||
void combine_things();
|
||||
|
Reference in New Issue
Block a user