Skip to content

Commit

Permalink
Reworked agent add/remove from behavior oversight
Browse files Browse the repository at this point in the history
  • Loading branch information
Designer225 committed Dec 30, 2023
1 parent 470a542 commit 1e08cdd
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 47 deletions.
2 changes: 1 addition & 1 deletion BattleRegen/BattleRegen.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<Version>2.2.2.90</Version>
<Version>2.2.3.100</Version>
<DebugType>full</DebugType>
<DocumentationFile>..\bin\Win64_Shipping_Client\BattleRegen.xml</DocumentationFile>
<PackageOutputPath>$(OutputPath)</PackageOutputPath>
Expand Down
17 changes: 10 additions & 7 deletions BattleRegen/BattleRegenAgentData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -187,36 +187,39 @@ public readonly void GiveXpToHealers(
case TroopType.Mount:
case TroopType.Animal:
float riderXpGain = xpGain * settings.XpGain;
Hero? rider = (agent.MountAgent.Character as CharacterObject)?.HeroObject;
var rider = (agent.MountAgent?.Character as CharacterObject)?.HeroObject;
if (rider != null)
xpGains.Push((rider, riderXpGain));

if (settings.VerboseDebug)
messages.Enqueue($"[BattleRegeneration] rider agent {agent.MountAgent.Name} has received {riderXpGain} xp");
if (settings.VerboseDebug && rider != null)
messages.Enqueue($"[BattleRegeneration] rider agent {rider} has received {riderXpGain} xp");
break;
default:
float selfXpGain = xpGain * settings.XpGain;
Hero? hero = (agent.Character as CharacterObject)?.HeroObject;
var hero = (agent.Character as CharacterObject)?.HeroObject;
if (hero != null)
xpGains.Push((hero, selfXpGain));
if (settings.VerboseDebug)
messages.Enqueue($"[BattleRegeneration] agent {agent.Name} has received {selfXpGain} xp");

float cdrXpGain = xpGain * settings.CommanderXpGain;
Hero? commander = default;
var commander = default(Hero);
switch (troopType)
{
case TroopType.Player:
case TroopType.Companion:
case TroopType.Subordinate:
case TroopType.PlayerTroop:
commander = (Agent.Main.Character as CharacterObject)?.HeroObject;
commander = (Agent.Main?.Character as CharacterObject)?.HeroObject;
commander ??= (Mission.Current?.MainAgent?.Character as CharacterObject)?.HeroObject;
commander ??= (Mission.Current?.PlayerTeam?.ActiveAgents?.Find(x => x.IsPlayerUnit)?.Character as CharacterObject)?.HeroObject;
commander ??= Hero.MainHero;
break;
case TroopType.AlliedHero:
case TroopType.AlliedTroop:
case TroopType.EnemyHero:
case TroopType.EnemyTroop:
commander = (agent.Team.GeneralAgent.Character as CharacterObject)?.HeroObject;
commander = (agent.Team?.GeneralAgent?.Character as CharacterObject)?.HeroObject;
break;
}
if (commander != default)
Expand Down
87 changes: 49 additions & 38 deletions BattleRegen/BattleRegenerationBehavior.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ sealed class BattleRegenerationBehavior : MissionBehavior
private readonly Dictionary<Hero, float> _heroXpGainPairs;
private readonly Dictionary<Agent, int> _agentIndexPairs;
private BattleRegenAgentData[] _agentData;
private readonly Stack<int> _freeList;
private Stack<(Agent, bool)> _toAddOrRemove;

public override MissionBehaviorType BehaviorType => MissionBehaviorType.Other;

Expand All @@ -33,7 +33,7 @@ public BattleRegenerationBehavior()
_heroXpGainPairs = new Dictionary<Hero, float>();
_agentIndexPairs = new Dictionary<Agent, int>(AnticipatedAgentCount);
_agentData = new BattleRegenAgentData[AnticipatedAgentCount];
_freeList = new Stack<int>();
_toAddOrRemove = new Stack<(Agent, bool)>();

Debug.Print("[BattleRegeneration] Mission started, data initialized");
Debug.Print($"[BattleRegeneration] Debug mode on, dumping settings: regen mode: {_settings.RegenModel}, " +
Expand All @@ -44,35 +44,6 @@ public BattleRegenerationBehavior()
$"enemy troops:{_settings.RegenAmountEnemyTroops}, animals:{_settings.RegenAmountAnimals}");
}

private void AddAgent(Agent agent)
{
int index;
if (_freeList.Count > 0) index = _freeList.Pop();
else
{
EnsureCapacity();
index = _agentIndexPairs.Count;
}
_agentIndexPairs[agent] = index;
_agentData[index] = new BattleRegenAgentData(agent);

if (_settings.Debug)
Debug.Print($"[BattleRegen] agent {agent.Name} registered");
}

private void RemoveAgent(Agent agent)
{
if (_agentIndexPairs.TryGetValue(agent, out var index))
{
_agentIndexPairs.Remove(agent);
_agentData[index] = default;
_freeList.Push(index);

if (_settings.Debug)
Debug.Print($"[BattleRegen] agent {agent.Name} unregistered");
}
}

private void EnsureCapacity(int add = 1)
{
int capacity = _agentIndexPairs.Count + add;
Expand All @@ -84,15 +55,12 @@ private void EnsureCapacity(int add = 1)
}
}

public override void OnAgentBuild(Agent agent, Banner banner)
{
AddAgent(agent);
}
public override void OnAgentBuild(Agent agent, Banner banner) => _toAddOrRemove.Push((agent, true));

public override void OnAgentRemoved(Agent affectedAgent, Agent affectorAgent, AgentState agentState, KillingBlow blow)
=> RemoveAgent(affectedAgent);
=> _toAddOrRemove.Push((affectedAgent, false));

public override void OnAgentDeleted(Agent affectedAgent) => RemoveAgent(affectedAgent);
public override void OnAgentDeleted(Agent affectedAgent) => _toAddOrRemove.Push((affectedAgent, false));

public override void OnRegisterBlow(Agent attacker, Agent victim, GameEntity realHitEntity, Blow b, ref AttackCollisionData collisionData, in MissionWeapon attackerWeapon)
{
Expand All @@ -109,12 +77,19 @@ public override void OnRegisterBlow(Agent attacker, Agent victim, GameEntity rea

public override void OnMissionTick(float dt)
{
while (_toAddOrRemove.Count > 0)
{
var (agent, addIfTrue) = _toAddOrRemove.Pop();
if (addIfTrue) AddAgent(agent);
else RemoveAgent(agent);
}

var arenaController = Mission.GetMissionBehavior<ArenaPracticeFightMissionController>();
if (arenaController != default && arenaController.AfterPractice) return;

int messageCount = 0;
const int infoMessageCap = 10, messageCap = 100;
foreach (var (messages, xpGains) in _agentIndexPairs.Values.AsParallel().Select(x => _agentData[x].AttemptRegeneration(dt, _settings)))
foreach (var (messages, xpGains) in ParallelEnumerable.Range(0, _agentIndexPairs.Count).Select(x => _agentData[x].AttemptRegeneration(dt, _settings)))
{
if (messages != null)
for (; messageCount < messageCap; ++messageCount)
Expand All @@ -137,6 +112,42 @@ public override void OnMissionTick(float dt)
}
}

private void AddAgent(Agent agent)
{
EnsureCapacity();
int index = _agentIndexPairs.Count;
_agentIndexPairs[agent] = index;
_agentData[index] = new BattleRegenAgentData(agent);

if (_settings.Debug)
Debug.Print($"[BattleRegen] agent {agent.Name} registered");
}

private void RemoveAgent(Agent agent)
{
if (_agentIndexPairs.TryGetValue(agent, out var index))
{
_agentIndexPairs.Remove(agent);
ref var dataRef = ref _agentData[index];
// since index < Count always, after removal from dictionary index <= Count always.
// we do not need to swap if index == Count (since the last item removed is the last added)
// otherwise we swap and update accordingly
var lastIndex = _agentIndexPairs.Count;
if (index < lastIndex)
{
// swap with last item
ref var lastDataRef = ref _agentData[lastIndex];
dataRef = lastDataRef;
lastDataRef = default;
_agentIndexPairs[dataRef.Agent] = index;
}
else dataRef = default;

if (_settings.Debug)
Debug.Print($"[BattleRegen] agent {agent.Name} unregistered");
}
}

protected override void OnEndMission()
{
base.OnEndMission();
Expand Down
2 changes: 1 addition & 1 deletion SubModule.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Module>
<Name value="Battle Regeneration"/>
<Id value="BattleRegeneration"/>
<Version value="v2.2.2.90"/>
<Version value="v2.2.3.100"/>
<SingleplayerModule value="true"/>
<MultiplayerModule value="false"/>
<Official value="false"/>
Expand Down

0 comments on commit 1e08cdd

Please sign in to comment.