159 lines
4.1 KiB
C
159 lines
4.1 KiB
C
|
#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);
|
||
|
}
|
||
|
}
|