4
Fork 0
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

159 lines
4.1 KiB

#pragma once
namespace Papyrus::PhasmalistFunctions
{
static constexpr float magicWeight = 0.1;
float getMagicEffectStrength(RE::EffectSetting* magicEffect, float magnitude, float area, float duration)
{
float result = magicEffect->data.baseCost;
if (magnitude > 0) {
result *= magnitude;
}
if (area > 0) {
result *= area;
}
if (duration > 0) {
result *= duration;
}
return result;
}
float getEnchantmentStrength(RE::EnchantmentItem* ench)
{
if (!ench) {
return 0.0;
}
float result = 0;
const auto effects = ench->As<RE::MagicItem>()->effects;
for (int i = effects.size() - 1; i >= 0; i--) {
result += getMagicEffectStrength(
effects[i]->baseEffect,
effects[i]->GetMagnitude(),
effects[i]->GetArea(),
effects[i]->GetDuration());
}
return result * magicWeight;
}
float getSpellStrength(RE::SpellItem* spell)
{
if (!spell) {
return 0.0;
}
/*
* // Sum of effect costs
float result = 0;
for (int i = papyrusSpell::GetNumEffects(spell) - 1; i >= 0; i--) {
result += getMagicEffectStrength(
papyrusSpell::GetNthEffectMagicEffect(spell, i),
papyrusSpell::GetNthEffectMagnitude(spell, i),
papyrusSpell::GetNthEffectDuration(spell, i),
papyrusSpell::GetNthEffectArea(spell, i));
}
*/
/*
* // The costliest effect
int iCostliestEffect = papyrusSpell::GetCostliestEffectIndex(spell);
float result = getMagicEffectStrength(
papyrusSpell::GetNthEffectMagicEffect(spell, iCostliestEffect),
papyrusSpell::GetNthEffectMagnitude(spell, iCostliestEffect),
papyrusSpell::GetNthEffectDuration(spell, iCostliestEffect),
papyrusSpell::GetNthEffectArea(spell, iCostliestEffect)
);
*/
// 2.0.10: Switch to flat magicka correlation
return spell->GetData1()->costOverride * 1.5;
}
float getAdditionalExtendDataStrength(RE::InventoryEntryData* itemStack, float physicalStrength)
{
float strength = 0;
if (!itemStack->extraLists) {
return strength;
}
for (const auto& xList : *itemStack->extraLists) {
const auto xEnch = xList->GetByType<RE::ExtraEnchantment>();
if (xEnch && xEnch->enchantment) {
strength += getEnchantmentStrength(xEnch->enchantment) * xList->GetCount();
}
const auto xTempered = xList->GetByType<RE::ExtraHealth>();
if (xTempered && xTempered->health > 1.0) {
strength += physicalStrength * (xTempered->health - 1.0) * 20 * xList->GetCount();
}
}
return strength;
}
float getItemStackStrength(RE::InventoryEntryData* itemStack)
{
float strength = 0;
float physicalStrength = 0;
if (itemStack->object) {
if (itemStack->object->IsWeapon()) {
RE::TESObjectWEAP* asWeapon = itemStack->object->As<RE::TESObjectWEAP>();
if (asWeapon) {
float baseDmg = asWeapon->GetAttackDamage() * 1.5;
float speed = asWeapon->GetSpeed();
physicalStrength = baseDmg * speed;
strength += physicalStrength;
strength += getEnchantmentStrength(asWeapon->As<RE::TESEnchantableForm>()->formEnchanting);
}
}
if (itemStack->object->IsArmor()) {
RE::TESObjectARMO* asArmor = itemStack->object->As<RE::TESObjectARMO>();
if (asArmor) {
physicalStrength = asArmor->GetArmorRating();
strength += physicalStrength;
strength += getEnchantmentStrength(asArmor->As<RE::TESEnchantableForm>()->formEnchanting);
}
}
if (itemStack->object->IsBook()) {
RE::TESObjectBOOK* asBook = itemStack->object->As<RE::TESObjectBOOK>();
if (asBook && asBook->TeachesSpell()) {
return getSpellStrength(asBook->GetSpell());
}
}
}
strength = strength * itemStack->countDelta;
strength += getAdditionalExtendDataStrength(itemStack, physicalStrength);
return strength;
}
float calculateContentStrength(RE::StaticFunctionTag* tag, RE::TESObjectREFR* container)
{
if (!container) {
return 0.0;
}
float strength = 0;
const auto inv = container->GetInventory();
for (const auto& [item, data] : inv) {
const auto& [count, entry] = data;
if (count > 0) {
strength += getItemStackStrength(entry.get());
}
}
return strength;
}
inline void Bind(VM& a_vm)
{
BIND(calculateContentStrength);
logger::info("{}", "Registered calculateContentStrength"sv);
}
}