Skip to content

Commit

Permalink
feat: add SweetPieSpellDamageFormula for spell damage modification (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
Pospelove authored Dec 28, 2024
1 parent c26471d commit 6e6ec77
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 1 deletion.
6 changes: 6 additions & 0 deletions skymp5-server/cpp/addon/ScampServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "database_drivers/DatabaseFactory.h"
#include "formulas/DamageMultFormula.h"
#include "formulas/SweetPieDamageFormula.h"
#include "formulas/SweetPieSpellDamageFormula.h"
#include "formulas/TES5DamageFormula.h"
#include "libespm/IterateFields.h"
#include "papyrus-vm/Utils.h"
Expand Down Expand Up @@ -328,6 +329,9 @@ ScampServer::ScampServer(const Napi::CallbackInfo& info)
auto sweetPieDamageFormulaSettings =
serverSettings["sweetPieDamageFormulaSettings"];

auto sweetPieSpellDamageFormulaSettings =
serverSettings["sweetPieSpellDamageFormulaSettings"];

auto damageMultFormulaSettings =
serverSettings["damageMultFormulaSettings"];

Expand All @@ -337,6 +341,8 @@ ScampServer::ScampServer(const Napi::CallbackInfo& info)
damageMultFormulaSettings);
formula = std::make_unique<SweetPieDamageFormula>(
std::move(formula), sweetPieDamageFormulaSettings);
formula = std::make_unique<SweetPieSpellDamageFormula>(
std::move(formula), sweetPieSpellDamageFormulaSettings);
partOne->SetDamageFormula(std::move(formula));

partOne->worldState.AttachScriptStorage(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

#include <nlohmann/json_fwd.hpp>

// Modifies vanilla damage
// Modifies vanilla damage for weapons

struct SweetPieDamageFormulaSettings
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@

#include "SweetPieSpellDamageFormula.h"

#include "archives/JsonInputArchive.h"
#include <limits>
#include <sstream>

namespace SweetPieSpellDamageFormulaPrivate {

bool IsPlayerBaseId(const MpActor& actor)
{
return actor.GetBaseId() == 0x7;
}

float SelectRespectiveMult(
const MpActor& aggressor, const MpActor& target,
const SweetPieSpellDamageFormulaSettingsEntry& entry)
{
const bool isPlayerAggressor = IsPlayerBaseId(aggressor);
const bool isPlayerTarget = IsPlayerBaseId(target);

if (isPlayerAggressor && isPlayerTarget) {
return entry.multPlayerHitsPlayer.has_value() ? *entry.multPlayerHitsPlayer
: 1.f;
}

if (isPlayerAggressor && !isPlayerTarget) {
return entry.multPlayerHitsNpc.has_value() ? *entry.multPlayerHitsNpc
: 1.f;
}

return 1.f;
}

template <class T>
T Clamp(T value, T minValue, T maxValue)
{
if (value < minValue) {
return minValue;
} else if (value > maxValue) {
return maxValue;
} else {
return value;
}
}
}

SweetPieSpellDamageFormulaSettings
SweetPieSpellDamageFormulaSettings::FromJson(const nlohmann::json& j)
{
JsonInputArchive ar(j);
SweetPieSpellDamageFormulaSettings res;
res.Serialize(ar);
return res;
}

SweetPieSpellDamageFormula::SweetPieSpellDamageFormula(
std::unique_ptr<IDamageFormula> baseFormula_, const nlohmann::json& config)
: baseFormula(std::move(baseFormula_))
, settings(std::nullopt)
{
if (config.is_object()) {
settings = ParseConfig(config);
}
}

float SweetPieSpellDamageFormula::CalculateDamage(const MpActor& aggressor,
const MpActor& target,
const HitData& hitData) const
{
return baseFormula->CalculateDamage(aggressor, target, hitData);
}

float SweetPieSpellDamageFormula::CalculateDamage(
const MpActor& aggressor, const MpActor& target,
const SpellCastData& spellCastData) const
{
const float baseDamage =
baseFormula->CalculateDamage(aggressor, target, spellCastData);

if (!settings) {
return baseDamage;
}

float biggestMult = -1;
float defaultMult = 1.f;

for (auto& entry : settings->entries) {
const std::string& itemId = entry.itemId;
const float mult = SweetPieSpellDamageFormulaPrivate::Clamp(
SweetPieSpellDamageFormulaPrivate::SelectRespectiveMult(aggressor,
target, entry),
0.f, std::numeric_limits<float>::infinity());

uint32_t itemIdParsed = 0;

if (itemId.find("0x") == 0 || itemId.find("0X") == 0) {
std::stringstream ss;
ss << std::hex << itemId.substr(2); // Skip "0x"
ss >> itemIdParsed;
} else {
std::stringstream ss(itemId);
ss >> itemIdParsed;
}

if (itemIdParsed == 0) {
defaultMult = mult;
}

if (aggressor.GetInventory().GetItemCount(itemIdParsed) > 0) {
biggestMult = std::max(biggestMult, mult);
}
}

return biggestMult >= 0 ? biggestMult * baseDamage
: defaultMult * baseDamage;
}

SweetPieSpellDamageFormulaSettings SweetPieSpellDamageFormula::ParseConfig(
const nlohmann::json& config) const
{
return SweetPieSpellDamageFormulaSettings::FromJson(config);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#pragma once

#include "IDamageFormula.h"
#include "MpActor.h"

#include <memory>
#include <optional>
#include <vector>

#include <nlohmann/json_fwd.hpp>

// Modifies vanilla damage for spells

struct SweetPieSpellDamageFormulaSettingsEntry
{
template <class Archive>
void Serialize(Archive& archive)
{
archive.Serialize("itemId", itemId)
.Serialize("multPlayerHitsPlayer", multPlayerHitsPlayer)
.Serialize("multPlayerHitsNpc", multPlayerHitsNpc);
}

std::string itemId; // supports hex and decimal ids: "0x000feef1", "0"
std::optional<float> multPlayerHitsPlayer;
std::optional<float> multPlayerHitsNpc;
};

struct SweetPieSpellDamageFormulaSettings
{

template <class Archive>
void Serialize(Archive& archive)
{
archive.Serialize("entries", entries);
}

static SweetPieSpellDamageFormulaSettings FromJson(const nlohmann::json& j);

std::vector<SweetPieSpellDamageFormulaSettingsEntry> entries;
};

class SweetPieSpellDamageFormula : public IDamageFormula
{
public:
SweetPieSpellDamageFormula(std::unique_ptr<IDamageFormula> baseFormula_,
const nlohmann::json& config);

[[nodiscard]] float CalculateDamage(const MpActor& aggressor,
const MpActor& target,
const HitData& hitData) const override;

[[nodiscard]] float CalculateDamage(
const MpActor& aggressor, const MpActor& target,
const SpellCastData& spellCastData) const override;

private:
SweetPieSpellDamageFormulaSettings ParseConfig(
const nlohmann::json& config) const;

private:
std::unique_ptr<IDamageFormula> baseFormula;
std::optional<SweetPieSpellDamageFormulaSettings> settings;
};

0 comments on commit 6e6ec77

Please sign in to comment.