enderalse/source/fs.dll/fs/PhasmalistInventoryFunctions.cpp
Eddoursul ba912c86ab Revised spectralizing cost of spells and weapons:
- Spell costs now directly correlate to their magicka costs.
- Increased importance of base damage and tempering for weapons.
2021-11-29 21:43:22 +01:00

175 lines
5.2 KiB
C++

#include "PhasmalistInventoryFunctions.h"
#include "skse64\GameExtraData.h"
#include "skse64\GameBSExtraData.h"
#include "skse64\GameRTTI.h"
#include "skse64\PapyrusWornObject.h"
#include "skse64\PapyrusEnchantment.h"
#include "skse64\PapyrusWeapon.h"
#include "skse64\PapyrusArmor.h"
#include "skse64\PapyrusBook.h"
#include "skse64\PapyrusSpell.h"
#include <string>
namespace PhasmalistScripts {
static constexpr float magicWeight = 0.1;
EntryDataList * getEntryData(TESObjectREFR *container) {
ExtraContainerChanges * ecc = DYNAMIC_CAST
(container->extraData.GetByType(kExtraData_ContainerChanges), BSExtraData, ExtraContainerChanges);
if (!ecc) {
return 0;
}
return ecc->data->objList;
}
float getMagicEffectStrength(EffectSetting * magicEffect, float magnitude, float area, float duration) {
float result = magicEffect->properties.baseCost;
if (magnitude > 0) {
result *= magnitude;
}
if (area > 0) {
result *= area;
}
if (duration > 0) {
result *= duration;
}
return result;
}
float getEnchantmentStrength(EnchantmentItem * ench) {
if (!ench) {
return 0.0;
}
float result = 0;
for (int i = papyrusEnchantment::GetNumEffects(ench) - 1; i >= 0; i--) {
result += getMagicEffectStrength(
papyrusEnchantment::GetNthEffectMagicEffect(ench, i),
papyrusEnchantment::GetNthEffectMagnitude(ench, i),
papyrusEnchantment::GetNthEffectArea(ench, i),
papyrusEnchantment::GetNthEffectDuration(ench, i)
);
}
return result * magicWeight;
}
float getSpellStrength(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 papyrusSpell::GetMagickaCost(spell) * 1.5;
}
float getAdditionalExtendDataStrength(InventoryEntryData * itemStack, float physicalStrength) {
float strength = 0;
for (int i = itemStack->extendDataList->Count() - 1; i >= 0; i--) {
BaseExtraList * extraData = itemStack->extendDataList->GetNthItem(i);
if (!extraData) {
continue;
}
ExtraCount * exCount = DYNAMIC_CAST(extraData->GetByType(kExtraData_Count), BSExtraData, ExtraCount);
int count = 1;
if (exCount) {
count = exCount->count;
}
if (extraData->HasType(kExtraData_Enchantment)) {
//item has been enchanted
EnchantmentItem * ench = referenceUtils::GetEnchantment(extraData);
strength += getEnchantmentStrength(ench) * count;
}
if (extraData->HasType(kExtraData_Health)) {
//item has been tempered
ExtraHealth * health = DYNAMIC_CAST(extraData->GetByType(kExtraData_Health), BSExtraData, ExtraHealth);
if (health) {
strength += physicalStrength * (health->health - 1.0) * 20 * count;
}
}
}
return strength;
}
float getItemStackStrength(InventoryEntryData * itemStack) {
float strength = 0;
float physicalStrength = 0;
if (itemStack->type->IsWeapon()) {
TESObjectWEAP * asWeapon = static_cast<TESObjectWEAP*>(itemStack->type);
if (asWeapon) {
float baseDmg = papyrusWeapon::GetBaseDamage(asWeapon) * 1.5;
float speed = papyrusWeapon::GetSpeed(asWeapon);
physicalStrength = baseDmg * speed;
strength += physicalStrength;
strength += getEnchantmentStrength(papyrusWeapon::GetEnchantment(asWeapon));
}
}
if (itemStack->type->IsArmor()) {
TESObjectARMO * asArmor = static_cast<TESObjectARMO*>(itemStack->type);
if (asArmor) {
physicalStrength = papyrusArmor::GetArmorRating(asArmor);
strength += physicalStrength;
strength += getEnchantmentStrength(papyrusArmor::GetEnchantment(asArmor));
}
}
if (itemStack->type->formType == kFormType_Book) {
TESObjectBOOK * asBook = static_cast<TESObjectBOOK*>(itemStack->type);
if (asBook) {
SpellItem * spell = papyrusBook::GetSpell(asBook);
return getSpellStrength(spell);
}
}
strength = strength * itemStack->countDelta;
strength += getAdditionalExtendDataStrength(itemStack, physicalStrength);
return strength;
}
float calculateContentStrength(StaticFunctionTag * tag, TESObjectREFR *container) {
if (!container) {
return 0.0;
}
float strength = 0;
for (int i = getEntryData(container)->Count() - 1; i >= 0; --i) {
InventoryEntryData * ed = getEntryData(container)->GetNthItem(i);
if (!ed) {
continue;
}
strength += getItemStackStrength(ed);
}
return strength;
}
bool RegisterFuncs(VMClassRegistry* registry) {
registry->RegisterFunction(
new NativeFunction1<StaticFunctionTag, float, TESObjectREFR *>("calculateContentStrength", "EnderalLib", PhasmalistScripts::calculateContentStrength, registry));
return true;
}
}