Skip to content

Commit

Permalink
feat: Add mixin module
Browse files Browse the repository at this point in the history
Added a mixin module which is used to collect various scripts which
implement common functionality shared across the server and other
scripts.
  • Loading branch information
pacampbell committed Dec 24, 2024
1 parent f832406 commit 976ff45
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 1 deletion.
14 changes: 13 additions & 1 deletion Arrowgene.Ddon.GameServer/Handler/InstanceEnemyKillHandler.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Arrowgene.Ddon.GameServer.Characters;
using Arrowgene.Ddon.GameServer.Party;
using Arrowgene.Ddon.GameServer.Quests;
using Arrowgene.Ddon.GameServer.Scripting.Interfaces;
using Arrowgene.Ddon.Server;
using Arrowgene.Ddon.Server.Network;
using Arrowgene.Ddon.Shared.Entity.PacketStructure;
Expand Down Expand Up @@ -173,7 +174,18 @@ public override S2CInstanceEnemyKillRes Handle(GameClient client, C2SInstanceEne
}
}

uint baseEnemyExp = _gameServer.ExpManager.GetScaledPointAmount(RewardSource.Enemy, ExpType.ExperiencePoints, enemyKilled.GetDroppedExperience());
uint baseEnemyExp = 0;
if (Server.GameLogicSettings.Get<bool>("GameLogicSettings", "EnableExpCalculationMixin"))
{
var expCurveMixin = Server.ScriptManager.MixinModule.Get<IExpCurveMixin>("exp_curve");
baseEnemyExp = expCurveMixin.GetExpValue(enemyKilled);
}
else
{
baseEnemyExp = enemyKilled.GetDroppedExperience();
}

baseEnemyExp = _gameServer.ExpManager.GetScaledPointAmount(RewardSource.Enemy, ExpType.ExperiencePoints, baseEnemyExp);
uint calcExp = _gameServer.ExpManager.GetAdjustedExp(client.GameMode, RewardSource.Enemy, client.Party, baseEnemyExp, enemyKilled.Lv);
uint calcPP = _gameServer.ExpManager.GetScaledPointAmount(RewardSource.Enemy, ExpType.PlayPoints, enemyKilled.GetDroppedPlayPoints());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public class GameServerScriptManager : ScriptManager<GlobalVariables>
private GlobalVariables Globals { get; }
public NpcExtendedFacilityModule NpcExtendedFacilityModule { get; private set; } = new NpcExtendedFacilityModule();
public GameItemModule GameItemModule { get; private set; } = new GameItemModule();
public MixinModule MixinModule { get; private set; } = new MixinModule();

public GameServerScriptManager(DdonGameServer server) : base(server.AssetRepository.AssetsPath)
{
Expand All @@ -31,6 +32,7 @@ public GameServerScriptManager(DdonGameServer server) : base(server.AssetReposit
// Add modules to the list so the generic logic can iterate over all scripting modules
ScriptModules[NpcExtendedFacilityModule.ModuleRoot] = NpcExtendedFacilityModule;
ScriptModules[GameItemModule.ModuleRoot] = GameItemModule;
ScriptModules[MixinModule.ModuleRoot] = MixinModule;
}

public override void Initialize()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Arrowgene.Ddon.Shared.Model;

namespace Arrowgene.Ddon.GameServer.Scripting.Interfaces
{
public abstract class IExpCurveMixin
{
public abstract uint GetExpValue(InstancedEnemy enemy);
}
}
69 changes: 69 additions & 0 deletions Arrowgene.Ddon.GameServer/Scripting/Modules/MixinModule.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using Arrowgene.Ddon.Shared;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Scripting;
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.IO;
using System.Runtime.CompilerServices;

namespace Arrowgene.Ddon.GameServer.Scripting
{
public class MixinModule : ScriptModule
{
public override string ModuleRoot => "mixins";
public override string Filter => "*.csx";
public override bool ScanSubdirectories => true;
public override bool EnableHotLoad => true;

private Dictionary<string, object> Mixins { get; set; }

public MixinModule()
{
Mixins = new Dictionary<string, object>();
}

public T Get<T>(string scriptName)
{
if (!Mixins.ContainsKey(scriptName))
{
throw new Exception($"A mixin with the name '{scriptName}' doesn't exist");
}

return (T) Mixins[scriptName];
}

public override ScriptOptions Options()
{
return ScriptOptions.Default
.AddReferences(MetadataReference.CreateFromFile(typeof(DdonGameServer).Assembly.Location))
.AddReferences(MetadataReference.CreateFromFile(typeof(AssetRepository).Assembly.Location))
.AddReferences(MetadataReference.CreateFromFile(typeof(DynamicAttribute).Assembly.Location))
.AddImports("System", "System.Collections", "System.Collections.Generic")
.AddImports("System.Runtime.CompilerServices")
.AddImports("Arrowgene.Ddon.Shared")
.AddImports("Arrowgene.Ddon.Shared.Model")
.AddImports("Arrowgene.Ddon.GameServer")
.AddImports("Arrowgene.Ddon.GameServer.Characters")
.AddImports("Arrowgene.Ddon.GameServer.Scripting")
.AddImports("Arrowgene.Ddon.GameServer.Scripting.Interfaces")
.AddImports("Arrowgene.Ddon.Shared.Entity.PacketStructure")
.AddImports("Arrowgene.Ddon.Shared.Entity.Structure")
.AddImports("Arrowgene.Ddon.Shared.Model.Quest");
}

public override bool EvaluateResult(string path, ScriptState<object> result)
{
if (result == null)
{
return false;
}

// Mixins are c# Func<> with arbitary return and params based on the functionality
string mixinName = Path.GetFileNameWithoutExtension(path);
Mixins[mixinName] = result.ReturnValue;

return true;
}
}
}
3 changes: 3 additions & 0 deletions Arrowgene.Ddon.Shared/Files/Assets/scripts/mixins/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Mixins

Mixins are a collection of configurable functionality which can be shared across various server components and scripts, but is not tied to a particular feature.
17 changes: 17 additions & 0 deletions Arrowgene.Ddon.Shared/Files/Assets/scripts/mixins/exp_curve.csx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* @breif This mixin is used to calculate the exp amount for a given
* enemy based on observations from realworld exp data. It should be
* possible to call this script directly from the server code or from
* other scripts.
*/

public class Mixin : IExpCurveMixin
{
public override uint GetExpValue(InstancedEnemy enemy)
{
// TODO: Implement algorithm to calculate exp amount
return enemy.GetDroppedExperience();
}
}

return new Mixin();
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ bool EnableVisualEquip = true;
uint DefaultWarpFavorites = 3;
uint LaternBurnTimeInSeconds = 1500;

/**
* @brief If enabled, overrides default EXP values assigned to enemies
* in the InstanceEnemyKillHandler and uses the calculations inside of
* <scriptroot>/mixins/exp_curve.csx.
*
* @note Currently returns same exp amount as the default setting.
*/
bool EnableExpCalculationMixin = false;

// Crafting Settings
double AdditionalProductionSpeedFactor = 1.0;
double AdditionalCostPerformanceFactor = 1.0;
Expand Down

0 comments on commit 976ff45

Please sign in to comment.