Skip to content

Commit

Permalink
#69 Revisited spawn adjustment
Browse files Browse the repository at this point in the history
  • Loading branch information
cptn-solo committed Mar 11, 2023
1 parent 44525a2 commit 64fbe26
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 61 deletions.
51 changes: 48 additions & 3 deletions Assets/Scripts/Data/OpponentTeamMemberSpawnConfig.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace Assets.Scripts.Data
{
using SortedByStrength = IOrderedEnumerable<KeyValuePair<int, StrengthSpawnInfo>>;
public delegate void SpawnPassCallback(int strength);

public struct OpponentTeamMemberSpawnConfig
{
public Dictionary<int, StrengthSpawnInfo> OveralStrengthLevels { get; set; }

public static OpponentTeamMemberSpawnConfig DefaultConfig =>
new()
public SortedByStrength SortedSpawnRateInfo { get; set; }

public int RunOnePass(int teamStrength, SpawnPassCallback callback = null, int treshold = -1)
{
foreach (var item in SortedSpawnRateInfo)
{
OveralStrengthLevels = new () {
if (item.Key > teamStrength ||
(treshold > 0 && item.Key > treshold))
continue;

var adjustedSpawnRate = item.Value.SpawnRate;

foreach (var adj in item.Value.TeamStrengthWeightedSpawnRates)
{
if (adj.Key.Item1 < teamStrength &&
adj.Key.Item2 >= teamStrength)
{
adjustedSpawnRate += adj.Value;
break;
}
}

if (!adjustedSpawnRate.RatedRandomBool())
continue;

callback?.Invoke(item.Key);

return item.Key;
}

return 0;
}
public static OpponentTeamMemberSpawnConfig DefaultConfig()
{
var retval = new OpponentTeamMemberSpawnConfig()
{
OveralStrengthLevels = new() {
{ 1, new () {
OveralStrenght = 1,
TintColor = new Color(77f/255f, 131f/255f, 207f/255f, 1f),
Expand Down Expand Up @@ -54,5 +91,13 @@ public struct OpponentTeamMemberSpawnConfig
} },
}
};

retval.SortedSpawnRateInfo =
retval.OveralStrengthLevels
.OrderByDescending(x => x.Key);

return retval;
}

}
}
9 changes: 8 additions & 1 deletion Assets/Scripts/ECS/Data/RefComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,10 @@ public struct RaidComp
public EcsPackedEntityWithWorld[] PlayerHeroConfigs { get; internal set; }
public EcsPackedEntityWithWorld[] OpponentHeroConfigs { get; internal set; }
public Asset[] Assets { get; set; }
public Dictionary<int, List<EcsPackedEntityWithWorld>> OpponentsIndexedByStrength { get; internal set; }
public Dictionary<int, List<EcsPackedEntityWithWorld>>
OpponentsIndexedByStrength { get; internal set; }
public OpponentTeamMemberSpawnConfig
OppenentMembersSpawnConfig { get; internal set; }
}

public struct BattlePotComp
Expand All @@ -110,6 +113,10 @@ public struct PlayerComp

public struct OpponentComp
{
/// <summary>
/// Maximum strength value available after cover hero have being assigned
/// </summary>
public int CoverHeroStrength { get; set; }
}

public struct StrengthComp : IIntValue
Expand Down
62 changes: 23 additions & 39 deletions Assets/Scripts/ECS/Systems/Raid/BattleLaunchSystem.cs
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Assets.Scripts.Data;
using Assets.Scripts.ECS.Data;
using Assets.Scripts.Services;
using Leopotam.EcsLite;
using Leopotam.EcsLite.Di;
using UnityEngine;
using Random = UnityEngine.Random;

namespace Assets.Scripts.ECS.Systems
{

public class BattleLaunchSystem : IEcsRunSystem
{
private readonly EcsWorldInject ecsWorld;

private readonly EcsPoolInject<BattleComp> battlePool;
private readonly EcsPoolInject<RaidComp> raidPool;
private readonly EcsPoolInject<HeroComp> heroPool;
private readonly EcsPoolInject<StrengthComp> strengthPool;
private readonly EcsPoolInject<DestroyTag> destroyTagPool;

private readonly EcsPoolInject<OpponentComp> opponentPool;
private readonly EcsPoolInject<HeroComp> heroCompPool;
private readonly EcsFilterInject<Inc<BattleComp, DraftTag>> battleFilter;
private readonly EcsFilterInject<Inc<EntityViewRef<Hero>>> unitFilter;
private readonly EcsFilterInject<Inc<EntityViewRef<bool>>> overlayFilter;
private readonly EcsFilterInject<Inc<PlayerTeamTag, HeroConfigRefComp>> teamHeroesFilter;

private readonly EcsCustomInject<RaidService> raidService;
Expand Down Expand Up @@ -50,45 +48,30 @@ public void Run(IEcsSystems systems)

ref var raidComp = ref raidPool.Value.Get(raidEntity);
ref var strengthComp = ref strengthPool.Value.Get(enemyEntity);
ref var opponentComp = ref opponentPool.Value.Get(enemyEntity);
ref var heroComp = ref heroCompPool.Value.Get(enemyEntity);

var config = OpponentTeamMemberSpawnConfig.DefaultConfig;
enemyBuffer.Add(heroComp.Hero);

var initialStrength = strengthComp.Value;
var memberCount = 0;

var sortedByStrength = config.OveralStrengthLevels.OrderByDescending(x => x.Key);
int teamStrength = strengthComp.Value;
var remainingStrength = teamStrength - opponentComp.CoverHeroStrength;
var memberCount = 1;
var indexed = raidComp.OpponentsIndexedByStrength;

while (initialStrength > 0 && memberCount < 8)
void callback(int strength)
{
foreach (var item in sortedByStrength)
{
if (item.Key > strengthComp.Value)
continue;

var adjustedSpawnRate = item.Value.SpawnRate;

foreach (var adj in item.Value.TeamStrengthWeightedSpawnRates)
{
if (adj.Key.Item1 < strengthComp.Value &&
adj.Key.Item2 >= strengthComp.Value)
{
adjustedSpawnRate += adj.Value;
break;
}
}

if (!adjustedSpawnRate.RatedRandomBool())
continue;

var spawnOptions = raidComp.OpponentsIndexedByStrength[item.Key];
var spawned = spawnOptions[Random.Range(0, spawnOptions.Count)];

enemyBuffer.Add(spawned);
initialStrength -= item.Key;
memberCount++;
}
var spawnOptions = indexed[strength];
var spawned = spawnOptions[Random.Range(0, spawnOptions.Count)];

enemyBuffer.Add(spawned);
remainingStrength -= strength;
memberCount++;
}

while (remainingStrength > 0 && memberCount < 8)
raidComp.OppenentMembersSpawnConfig.RunOnePass(
remainingStrength, callback, opponentComp.CoverHeroStrength);

var enemyWrappedHeroes = libraryService.Value.WrapForBattle(
enemyBuffer.ToArray(), ecsWorld.Value);

Expand All @@ -98,6 +81,7 @@ public void Run(IEcsSystems systems)

ListPool<EcsPackedEntityWithWorld>.Add(playerBuffer);
ListPool<EcsPackedEntityWithWorld>.Add(enemyBuffer);

raidService.Value.StartBattle();
}

Expand Down
51 changes: 38 additions & 13 deletions Assets/Scripts/ECS/Systems/Raid/OpponentInitSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

namespace Assets.Scripts.ECS.Systems
{
using static Leopotam.EcsLite.EcsWorld;
using static UnityEditor.Progress;
using HeroIndexByStrength = Dictionary<int, List<EcsPackedEntityWithWorld>>;

public class OpponentInitSystem : IEcsInitSystem
Expand Down Expand Up @@ -47,41 +49,64 @@ public void Init(IEcsSystems systems)
Debug.Log($"enemyNumber: {enemyNumber}");

var indexed = IndexHeroesByStrength(raidComp.OpponentHeroConfigs);
var config = OpponentTeamMemberSpawnConfig.DefaultConfig();
raidComp.OpponentsIndexedByStrength = indexed;

raidComp.OppenentMembersSpawnConfig = config;

for (int idx = 0; idx < enemyNumber; idx++)
{
var teamStrength = enemySpawnConfig.RandomRangedTeamStrength(Random.Range(1, 101));
Debug.Log($"teamStrength: {teamStrength}");

var opponentEntity = ecsWorld.Value.NewEntity();

ref var opponentComp = ref opponentPool.Value.Add(opponentEntity);
var coverHeroStrenth = CoverHeroForTeamStrength(teamStrength, indexed, config);

var spawnOptions = indexed[coverHeroStrenth];
var spawned = spawnOptions[Random.Range(0, spawnOptions.Count)];

ref var strength = ref strengthPool.Value.Add(opponentEntity);
strength.Value = teamStrength;

ref var heroComp = ref heroPool.Value.Add(opponentEntity);
heroComp.Hero = StrongestHeroForTeamStrength(teamStrength, indexed);
ref var heroComp = ref heroPool.Value.Add(opponentEntity);
heroComp.Hero = spawned;

ref var opponentComp = ref opponentPool.Value.Add(opponentEntity);
opponentComp.CoverHeroStrength = coverHeroStrenth;
}
}

private EcsPackedEntityWithWorld StrongestHeroForTeamStrength(
private int CoverHeroForTeamStrength(
int teamStrength, HeroIndexByStrength indexed,
OpponentTeamMemberSpawnConfig config)
{
if (config.RunOnePass(teamStrength) is var strength && strength > 0)
return strength;

return StrongestHeroForTeamStrength(teamStrength, indexed);
}

/// <summary>
/// Fallback method of cover hero selection - just picks 1st hero who's
/// strength is smaller than overal team strength (while the list is sorted
/// descending the strength so most strong heroes go 1st)
/// </summary>
/// <param name="teamStrength"></param>
/// <param name="indexed">heroes indexed by their respective strength</param>
/// <returns>strength value used as a key in the hero index</returns>
/// <exception cref="Exception"></exception>
private int StrongestHeroForTeamStrength(
int teamStrength, HeroIndexByStrength indexed)
{
foreach (var item in indexed.Keys.OrderByDescending(x => x))
{
if (teamStrength < item)
continue;
if (teamStrength >= item)
return item;

var options = indexed[item];
return options[Random.Range(0, options.Count)];
}
throw new Exception($"No available options for team strength {teamStrength}");
}

private static HeroIndexByStrength IndexHeroesByStrength(EcsPackedEntityWithWorld[] configs)
{
var heroIndexByStrength = new Dictionary<int, List<EcsPackedEntityWithWorld>>();
var heroIndexByStrength = new HeroIndexByStrength();
foreach (var item in configs)
{
if (!item.Unpack(out var libWorld, out var entity))
Expand Down
20 changes: 18 additions & 2 deletions Assets/Scripts/ECS/Systems/Raid/UpdateUnitStrengthSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,37 @@
using Assets.Scripts.Data;
using System.Linq;
using UnityEngine;
using Assets.Scripts.Services;
using System;

namespace Assets.Scripts.ECS.Systems
{
public class UpdateUnitStrengthSystem : IEcsRunSystem
{
private readonly EcsWorldInject ecsWorld;

private readonly EcsPoolInject<StrengthComp> strengthPool;
private readonly EcsPoolInject<RaidComp> raidPool;
private readonly EcsPoolInject<DataViewRef<BagedIconInfo>> pool;
private readonly EcsPoolInject<UpdateTag<StrengthComp>> updateTagPool;

private readonly EcsFilterInject<
Inc<StrengthComp, DataViewRef<BagedIconInfo>,
UpdateTag<StrengthComp>>> filter;

private readonly EcsCustomInject<RaidService> raidService;

public void Run(IEcsSystems systems)
{
if (filter.Value.GetEntitiesCount() == 0)
return;

if (!raidService.Value.RaidEntity.Unpack(ecsWorld.Value, out var raidEntity))
throw new Exception("No Raid");

ref var raidComp = ref raidPool.Value.Get(raidEntity);
var config = raidComp.OppenentMembersSpawnConfig;

foreach (var entity in filter.Value)
{
ref var strength = ref strengthPool.Value.Get(entity);
Expand All @@ -30,8 +46,8 @@ public void Run(IEcsSystems systems)
BadgeText = $"{strength.Value}",
BackgroundColor = null
};
var config = OpponentTeamMemberSpawnConfig.DefaultConfig;
foreach (var item in config.OveralStrengthLevels.OrderByDescending(x => x.Key))

foreach (var item in config.SortedSpawnRateInfo)
{
if (item.Key <= strength.Value)
{
Expand Down
5 changes: 2 additions & 3 deletions ProjectSettings/ProjectSettings.asset
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,8 @@ PlayerSettings:
16:10: 0
16:9: 1
Others: 0
bundleVersion: 0.40.0
preloadedAssets:
- {fileID: 11400000, guid: 5b1b838f37b4a1849991ee2a63c92918, type: 2}
bundleVersion: 0.40.1
preloadedAssets: []
metroInputSource: 0
wsaTransparentSwapchain: 0
m_HolographicPauseOnTrackingLoss: 1
Expand Down

0 comments on commit 64fbe26

Please sign in to comment.