Handle running stats extensions on non-actors gracefully (#7770)

ini_importer_tests
Alexei Kotov 4 months ago
parent 78d8cf86c3
commit ccbc02abc3

@ -126,6 +126,7 @@
Bug #7742: Governing attribute training limit should use the modified attribute
Bug #7758: Water walking is not taken into account to compute path cost on the water
Bug #7761: Rain and ambient loop sounds are mutually exclusive
Bug #7770: Sword of the Perithia: Script execution failure
Feature #2566: Handle NAM9 records for manual cell references
Feature #3537: Shader-based water ripples
Feature #5173: Support for NiFogProperty

@ -85,7 +85,9 @@ namespace MWScript
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value = ptr.getClass().getCreatureStats(ptr).getLevel();
Interpreter::Type_Integer value = -1;
if (ptr.getClass().isActor())
value = ptr.getClass().getCreatureStats(ptr).getLevel();
runtime.push(value);
}
@ -102,7 +104,8 @@ namespace MWScript
Interpreter::Type_Integer value = runtime[0].mInteger;
runtime.pop();
ptr.getClass().getCreatureStats(ptr).setLevel(value);
if (ptr.getClass().isActor())
ptr.getClass().getCreatureStats(ptr).setLevel(value);
}
};
@ -121,7 +124,9 @@ namespace MWScript
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Float value = ptr.getClass().getCreatureStats(ptr).getAttribute(mIndex).getModified();
Interpreter::Type_Float value = 0.f;
if (ptr.getClass().isActor())
value = ptr.getClass().getCreatureStats(ptr).getAttribute(mIndex).getModified();
runtime.push(value);
}
@ -145,6 +150,9 @@ namespace MWScript
Interpreter::Type_Float value = runtime[0].mFloat;
runtime.pop();
if (!ptr.getClass().isActor())
return;
MWMechanics::AttributeValue attribute = ptr.getClass().getCreatureStats(ptr).getAttribute(mIndex);
attribute.setBase(value, true);
ptr.getClass().getCreatureStats(ptr).setAttribute(mIndex, attribute);
@ -169,6 +177,9 @@ namespace MWScript
Interpreter::Type_Float value = runtime[0].mFloat;
runtime.pop();
if (!ptr.getClass().isActor())
return;
MWMechanics::AttributeValue attribute = ptr.getClass().getCreatureStats(ptr).getAttribute(mIndex);
modStat(attribute, value);
ptr.getClass().getCreatureStats(ptr).setAttribute(mIndex, attribute);
@ -189,14 +200,14 @@ namespace MWScript
void execute(Interpreter::Runtime& runtime) override
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Float value;
Interpreter::Type_Float value = 0.f;
if (mIndex == 0 && ptr.getClass().hasItemHealth(ptr))
{
// health is a special case
value = static_cast<Interpreter::Type_Float>(ptr.getClass().getItemMaxHealth(ptr));
}
else
else if (ptr.getClass().isActor())
{
value = ptr.getClass().getCreatureStats(ptr).getDynamic(mIndex).getCurrent();
// GetMagicka shouldn't return negative values
@ -225,6 +236,9 @@ namespace MWScript
Interpreter::Type_Float value = runtime[0].mFloat;
runtime.pop();
if (!ptr.getClass().isActor())
return;
MWMechanics::DynamicStat<float> stat(ptr.getClass().getCreatureStats(ptr).getDynamic(mIndex));
stat.setBase(value);
@ -254,6 +268,9 @@ namespace MWScript
Interpreter::Type_Float diff = runtime[0].mFloat;
runtime.pop();
if (!ptr.getClass().isActor())
return;
// workaround broken endgame scripts that kill dagoth ur
if (!R::implicit && ptr.getCellRef().getRefId() == "dagoth_ur_1")
{
@ -301,6 +318,9 @@ namespace MWScript
Interpreter::Type_Float diff = runtime[0].mFloat;
runtime.pop();
if (!ptr.getClass().isActor())
return;
MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
Interpreter::Type_Float current = stats.getDynamic(mIndex).getCurrent();
@ -336,6 +356,13 @@ namespace MWScript
void execute(Interpreter::Runtime& runtime) override
{
MWWorld::Ptr ptr = R()(runtime);
if (!ptr.getClass().isActor())
{
runtime.push(0.f);
return;
}
const MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
runtime.push(stats.getDynamic(mIndex).getRatio());
@ -357,6 +384,12 @@ namespace MWScript
{
MWWorld::Ptr ptr = R()(runtime);
if (!ptr.getClass().isActor())
{
runtime.push(0.f);
return;
}
Interpreter::Type_Float value = ptr.getClass().getSkill(ptr, mId);
runtime.push(value);
@ -381,6 +414,9 @@ namespace MWScript
Interpreter::Type_Float value = runtime[0].mFloat;
runtime.pop();
if (!ptr.getClass().isNpc())
return;
MWMechanics::NpcStats& stats = ptr.getClass().getNpcStats(ptr);
stats.getSkill(mId).setBase(value, true);
@ -405,6 +441,9 @@ namespace MWScript
Interpreter::Type_Float value = runtime[0].mFloat;
runtime.pop();
if (!ptr.getClass().isNpc())
return;
MWMechanics::SkillValue& skill = ptr.getClass().getNpcStats(ptr).getSkill(mId);
modStat(skill, value);
}
@ -465,6 +504,9 @@ namespace MWScript
ESM::RefId id = ESM::RefId::stringRefId(runtime.getStringLiteral(runtime[0].mInteger));
runtime.pop();
if (!ptr.getClass().isActor())
return;
const ESM::Spell* spell = MWBase::Environment::get().getESMStore()->get<ESM::Spell>().find(id);
MWMechanics::CreatureStats& creatureStats = ptr.getClass().getCreatureStats(ptr);
@ -491,6 +533,9 @@ namespace MWScript
ESM::RefId id = ESM::RefId::stringRefId(runtime.getStringLiteral(runtime[0].mInteger));
runtime.pop();
if (!ptr.getClass().isActor())
return;
MWMechanics::CreatureStats& creatureStats = ptr.getClass().getCreatureStats(ptr);
creatureStats.getSpells().remove(id);
@ -514,7 +559,8 @@ namespace MWScript
ESM::RefId spellid = ESM::RefId::stringRefId(runtime.getStringLiteral(runtime[0].mInteger));
runtime.pop();
ptr.getClass().getCreatureStats(ptr).getActiveSpells().removeEffects(ptr, spellid);
if (ptr.getClass().isActor())
ptr.getClass().getCreatureStats(ptr).getActiveSpells().removeEffects(ptr, spellid);
}
};
@ -529,7 +575,8 @@ namespace MWScript
Interpreter::Type_Integer effectId = runtime[0].mInteger;
runtime.pop();
ptr.getClass().getCreatureStats(ptr).getActiveSpells().purgeEffect(ptr, effectId);
if (ptr.getClass().isActor())
ptr.getClass().getCreatureStats(ptr).getActiveSpells().purgeEffect(ptr, effectId);
}
};
@ -845,7 +892,10 @@ namespace MWScript
{
MWWorld::Ptr ptr = R()(runtime);
runtime.push(ptr.getClass().getCreatureStats(ptr).hasCommonDisease());
if (ptr.getClass().isActor())
runtime.push(ptr.getClass().getCreatureStats(ptr).hasCommonDisease());
else
runtime.push(0);
}
};
@ -857,7 +907,10 @@ namespace MWScript
{
MWWorld::Ptr ptr = R()(runtime);
runtime.push(ptr.getClass().getCreatureStats(ptr).hasBlightDisease());
if (ptr.getClass().isActor())
runtime.push(ptr.getClass().getCreatureStats(ptr).hasBlightDisease());
else
runtime.push(0);
}
};
@ -872,9 +925,16 @@ namespace MWScript
ESM::RefId race = ESM::RefId::stringRefId(runtime.getStringLiteral(runtime[0].mInteger));
runtime.pop();
const ESM::RefId& npcRace = ptr.get<ESM::NPC>()->mBase->mRace;
if (ptr.getClass().isNpc())
{
const ESM::RefId& npcRace = ptr.get<ESM::NPC>()->mBase->mRace;
runtime.push(race == npcRace);
runtime.push(race == npcRace);
}
else
{
runtime.push(0);
}
}
};
@ -1043,10 +1103,15 @@ namespace MWScript
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value = ptr.getClass().getCreatureStats(ptr).hasDied();
Interpreter::Type_Integer value = 0;
if (ptr.getClass().isActor())
{
auto& stats = ptr.getClass().getCreatureStats(ptr);
value = stats.hasDied();
if (value)
ptr.getClass().getCreatureStats(ptr).clearHasDied();
if (value)
stats.clearHasDied();
}
runtime.push(value);
}
@ -1060,10 +1125,15 @@ namespace MWScript
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value = ptr.getClass().getCreatureStats(ptr).hasBeenMurdered();
Interpreter::Type_Integer value = 0;
if (ptr.getClass().isActor())
{
auto& stats = ptr.getClass().getCreatureStats(ptr);
value = stats.hasBeenMurdered();
if (value)
ptr.getClass().getCreatureStats(ptr).clearHasBeenMurdered();
if (value)
stats.clearHasBeenMurdered();
}
runtime.push(value);
}
@ -1077,7 +1147,9 @@ namespace MWScript
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value = ptr.getClass().getCreatureStats(ptr).getKnockedDownOneFrame();
Interpreter::Type_Integer value = 0;
if (ptr.getClass().isActor())
value = ptr.getClass().getCreatureStats(ptr).getKnockedDownOneFrame();
runtime.push(value);
}
@ -1090,7 +1162,10 @@ namespace MWScript
void execute(Interpreter::Runtime& runtime) override
{
MWWorld::Ptr ptr = R()(runtime);
runtime.push(ptr.getClass().getNpcStats(ptr).isWerewolf());
if (ptr.getClass().isNpc())
runtime.push(ptr.getClass().getNpcStats(ptr).isWerewolf());
else
runtime.push(0);
}
};
@ -1101,7 +1176,8 @@ namespace MWScript
void execute(Interpreter::Runtime& runtime) override
{
MWWorld::Ptr ptr = R()(runtime);
MWBase::Environment::get().getMechanicsManager()->setWerewolf(ptr, set);
if (ptr.getClass().isNpc())
MWBase::Environment::get().getMechanicsManager()->setWerewolf(ptr, set);
}
};
@ -1112,7 +1188,8 @@ namespace MWScript
void execute(Interpreter::Runtime& runtime) override
{
MWWorld::Ptr ptr = R()(runtime);
MWBase::Environment::get().getMechanicsManager()->applyWerewolfAcrobatics(ptr);
if (ptr.getClass().isNpc())
MWBase::Environment::get().getMechanicsManager()->applyWerewolfAcrobatics(ptr);
}
};
@ -1124,6 +1201,9 @@ namespace MWScript
{
MWWorld::Ptr ptr = R()(runtime);
if (!ptr.getClass().isActor())
return;
if (ptr == MWMechanics::getPlayer())
{
MWBase::Environment::get().getMechanicsManager()->resurrect(ptr);
@ -1192,6 +1272,12 @@ namespace MWScript
{
MWWorld::Ptr ptr = R()(runtime);
if (!ptr.getClass().isActor())
{
runtime.push(0);
return;
}
const MWMechanics::MagicEffects& effects = ptr.getClass().getCreatureStats(ptr).getMagicEffects();
float currentValue = effects.getOrDefault(mPositiveEffect).getMagnitude();
if (mNegativeEffect != -1)
@ -1226,6 +1312,13 @@ namespace MWScript
void execute(Interpreter::Runtime& runtime) override
{
MWWorld::Ptr ptr = R()(runtime);
int arg = runtime[0].mInteger;
runtime.pop();
if (!ptr.getClass().isActor())
return;
MWMechanics::MagicEffects& effects = ptr.getClass().getCreatureStats(ptr).getMagicEffects();
float currentValue = effects.getOrDefault(mPositiveEffect).getMagnitude();
if (mNegativeEffect != -1)
@ -1239,8 +1332,6 @@ namespace MWScript
if (mPositiveEffect == ESM::MagicEffect::ResistFrost)
currentValue += effects.getOrDefault(ESM::MagicEffect::FrostShield).getMagnitude();
int arg = runtime[0].mInteger;
runtime.pop();
effects.modifyBase(mPositiveEffect, (arg - static_cast<int>(currentValue)));
}
};
@ -1261,10 +1352,14 @@ namespace MWScript
void execute(Interpreter::Runtime& runtime) override
{
MWWorld::Ptr ptr = R()(runtime);
MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
int arg = runtime[0].mInteger;
runtime.pop();
if (!ptr.getClass().isActor())
return;
MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
stats.getMagicEffects().modifyBase(mPositiveEffect, arg);
}
};

Loading…
Cancel
Save