Merge branch 'master' into mathmerge

This commit is contained in:
Pieter-Jan Briers
2020-08-20 20:33:43 +02:00
808 changed files with 18173 additions and 5666 deletions

View File

@@ -112,19 +112,14 @@ namespace Content.Server.AI.Utility.Actions
UpdateBlackboard(context);
var considerations = GetConsiderations(context);
DebugTools.Assert(considerations.Count > 0);
// I used the IAUS video although I did have some confusion on how to structure it overall
// as some of the slides seemed contradictory
// Ideally we should early-out each action as cheaply as possible if it's not valid
// We also need some way to tell if the action isn't going to
// have a better score than the current action (if applicable) and early-out that way as well.
// 23:00 Building a better centaur
// Overall structure is based on Building a better centaur
// Ideally we should early-out each action as cheaply as possible if it's not valid, thus
// the finalScore can only go down over time.
var finalScore = 1.0f;
var minThreshold = min / Bonus;
context.GetState<ConsiderationState>().SetValue(considerations.Count);
// See 10:09 for this and the adjustments
foreach (var consideration in considerations)
{

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Threading;
using Content.Server.AI.Operators;
@@ -6,11 +6,13 @@ using Content.Server.AI.Utility.Actions;
using Content.Server.AI.Utility.BehaviorSets;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States.Utility;
using Content.Server.GameObjects.Components.Damage;
using Content.Server.GameObjects.Components.Mobs;
using Content.Server.GameObjects.EntitySystems.AI;
using Content.Server.GameObjects.EntitySystems.AI.LoadBalancer;
using Content.Server.GameObjects.EntitySystems.JobQueues;
using Content.Shared.GameObjects.Components.Damage;
using Robust.Server.AI;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Log;
@@ -63,6 +65,13 @@ namespace Content.Server.AI.Utility.AiLogic
{
SortActions();
}
if (BehaviorSets.Count == 1 && !EntitySystem.Get<AiSystem>().IsAwake(this))
{
IoCManager.Resolve<IEntityManager>()
.EventBus
.RaiseEvent(EventSource.Local, new SleepAiMessage(this, false));
}
}
public void RemoveBehaviorSet(Type behaviorSet)
@@ -74,6 +83,13 @@ namespace Content.Server.AI.Utility.AiLogic
BehaviorSets.Remove(behaviorSet);
SortActions();
}
if (BehaviorSets.Count == 0)
{
IoCManager.Resolve<IEntityManager>()
.EventBus
.RaiseEvent(EventSource.Local, new SleepAiMessage(this, true));
}
}
/// <summary>
@@ -114,38 +130,42 @@ namespace Content.Server.AI.Utility.AiLogic
_planCooldownRemaining = PlanCooldown;
_blackboard = new Blackboard(SelfEntity);
_planner = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<AiActionSystem>();
if (SelfEntity.TryGetComponent(out DamageableComponent damageableComponent))
if (SelfEntity.TryGetComponent(out IDamageableComponent damageableComponent))
{
damageableComponent.DamageThresholdPassed += DamageThresholdHandle;
damageableComponent.HealthChangedEvent += DeathHandle;
}
}
public override void Shutdown()
{
// TODO: If DamageableComponent removed still need to unsubscribe?
if (SelfEntity.TryGetComponent(out DamageableComponent damageableComponent))
if (SelfEntity.TryGetComponent(out IDamageableComponent damageableComponent))
{
damageableComponent.DamageThresholdPassed -= DamageThresholdHandle;
damageableComponent.HealthChangedEvent -= DeathHandle;
}
var currentOp = CurrentAction?.ActionOperators.Peek();
currentOp?.Shutdown(Outcome.Failed);
}
private void DamageThresholdHandle(object sender, DamageThresholdPassedEventArgs eventArgs)
private void DeathHandle(HealthChangedEventArgs eventArgs)
{
if (!SelfEntity.TryGetComponent(out SpeciesComponent speciesComponent))
{
return;
}
var oldDeadState = _isDead;
_isDead = eventArgs.Damageable.CurrentDamageState == DamageState.Dead || eventArgs.Damageable.CurrentDamageState == DamageState.Critical;
if (speciesComponent.CurrentDamageState is DeadState)
if (oldDeadState != _isDead)
{
_isDead = true;
}
else
{
_isDead = false;
var entityManager = IoCManager.Resolve<IEntityManager>();
switch (_isDead)
{
case true:
entityManager.EventBus.RaiseEvent(EventSource.Local, new SleepAiMessage(this, true));
break;
case false:
entityManager.EventBus.RaiseEvent(EventSource.Local, new SleepAiMessage(this, false));
break;
}
}
}
@@ -180,16 +200,6 @@ namespace Content.Server.AI.Utility.AiLogic
public override void Update(float frameTime)
{
// If we can't do anything then there's no point thinking
if (_isDead || BehaviorSets.Count == 0)
{
_actionCancellation?.Cancel();
_blackboard.GetState<LastUtilityScoreState>().SetValue(0.0f);
CurrentAction?.Shutdown();
CurrentAction = null;
return;
}
// If we asked for a new action we don't want to dump the existing one.
if (_actionRequest != null)
{

View File

@@ -1,4 +1,4 @@
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Server.GameObjects.Components.Damage;
using Content.Shared.GameObjects.Components.Damage;
@@ -11,13 +11,12 @@ namespace Content.Server.AI.Utility.Considerations.Combat
{
var target = context.GetState<TargetEntityState>().GetValue();
if (target == null || !target.TryGetComponent(out DamageableComponent damageableComponent))
if (target == null || !target.TryGetComponent(out IDamageableComponent damageableComponent))
{
return 0.0f;
}
// Just went with max health
return damageableComponent.CurrentDamage[DamageType.Total] / 300.0f;
return damageableComponent.TotalDamage / 300.0f;
}
}
}

View File

@@ -1,6 +1,6 @@
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Server.GameObjects.Components.Mobs;
using Content.Shared.GameObjects.Components.Damage;
namespace Content.Server.AI.Utility.Considerations.Combat
{
@@ -10,12 +10,12 @@ namespace Content.Server.AI.Utility.Considerations.Combat
{
var target = context.GetState<TargetEntityState>().GetValue();
if (target == null || !target.TryGetComponent(out SpeciesComponent speciesComponent))
if (target == null || !target.TryGetComponent(out IDamageableComponent damageableComponent))
{
return 0.0f;
}
if (speciesComponent.CurrentDamageState is CriticalState)
if (damageableComponent.CurrentDamageState == DamageState.Critical)
{
return 1.0f;
}

View File

@@ -1,6 +1,6 @@
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Server.GameObjects.Components.Mobs;
using Content.Shared.GameObjects.Components.Damage;
namespace Content.Server.AI.Utility.Considerations.Combat
{
@@ -10,12 +10,12 @@ namespace Content.Server.AI.Utility.Considerations.Combat
{
var target = context.GetState<TargetEntityState>().GetValue();
if (target == null || !target.TryGetComponent(out SpeciesComponent speciesComponent))
if (target == null || !target.TryGetComponent(out IDamageableComponent damageableComponent))
{
return 0.0f;
}
if (speciesComponent.CurrentDamageState is DeadState)
if (damageableComponent.CurrentDamageState == DamageState.Dead)
{
return 1.0f;
}

View File

@@ -13,18 +13,27 @@ namespace Content.Server.AI.Utility.Considerations
private float GetAdjustedScore(Blackboard context)
{
var score = GetScore(context);
/*
* Now using the geometric mean
* for n scores you take the n-th root of the scores multiplied
* e.g. a, b, c scores you take Math.Pow(a * b * c, 1/3)
* To get the ACTUAL geometric mean at any one stage you'd need to divide by the running consideration count
* however, the downside to this is it will fluctuate up and down over time.
* For our purposes if we go below the minimum threshold we want to cut it off, thus we take a
* "running geometric mean" which can only ever go down (and by the final value will equal the actual geometric mean).
*/
// Previously we used a makeupvalue method although the geometric mean is less punishing for more considerations
var considerationsCount = context.GetState<ConsiderationState>().GetValue();
var modificationFactor = 1.0f - 1.0f / considerationsCount;
var makeUpValue = (1.0f - score) * modificationFactor;
var adjustedScore = score + makeUpValue * score;
return MathHelper.Clamp(adjustedScore, 0.0f, 1.0f);
var adjustedScore = MathF.Pow(score, 1 / (float) considerationsCount);
return FloatMath.Clamp(adjustedScore, 0.0f, 1.0f);
}
[Pure]
private static float BoolCurve(float x)
{
// ReSharper disable once CompareOfFloatsByEqualityOperator
return x == 1.0f ? 1.0f : 0.0f;
return x > 0.0f ? 1.0f : 0.0f;
}
public Func<float> BoolCurve(Blackboard context)
@@ -42,7 +51,7 @@ namespace Content.Server.AI.Utility.Considerations
private static float InverseBoolCurve(float x)
{
// ReSharper disable once CompareOfFloatsByEqualityOperator
return x == 1.0f ? 0.0f : 1.0f;
return x == 0.0f ? 1.0f : 0.0f;
}
public Func<float> InverseBoolCurve(Blackboard context)

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using Content.Server.AI.Utility.Actions;
using Content.Server.AI.Utility.Actions.Combat.Melee;
@@ -7,8 +7,8 @@ using Content.Server.AI.Utility.Considerations.Combat.Melee;
using Content.Server.AI.Utils;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Server.GameObjects.Components.Mobs;
using Content.Server.GameObjects.Components.Movement;
using Content.Shared.GameObjects.Components.Damage;
using Robust.Server.GameObjects;
using Robust.Shared.IoC;
@@ -37,7 +37,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Combat.Melee
throw new InvalidOperationException();
}
foreach (var entity in Visibility.GetEntitiesInRange(owner.Transform.GridPosition, typeof(SpeciesComponent),
foreach (var entity in Visibility.GetEntitiesInRange(owner.Transform.GridPosition, typeof(IDamageableComponent),
controller.VisionRadius))
{
if (entity.HasComponent<BasicActorComponent>() && entity != owner)

View File

@@ -15,7 +15,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Combat.Melee
{
var owner = context.GetState<SelfState>().GetValue();
foreach (var entity in context.GetState<NearbySpeciesState>().GetValue())
foreach (var entity in context.GetState<NearbyBodiesState>().GetValue())
{
yield return new MeleeWeaponAttackEntity(owner, entity, Bonus);
}

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using Content.Server.AI.Utility.Actions;
using Content.Server.AI.Utility.Actions.Combat.Melee;
@@ -7,8 +7,8 @@ using Content.Server.AI.Utility.Considerations.Combat.Melee;
using Content.Server.AI.Utils;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Server.GameObjects.Components.Mobs;
using Content.Server.GameObjects.Components.Movement;
using Content.Shared.GameObjects.Components.Body;
using Robust.Server.GameObjects;
using Robust.Shared.IoC;
@@ -37,7 +37,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Combat.Melee
throw new InvalidOperationException();
}
foreach (var entity in Visibility.GetEntitiesInRange(owner.Transform.GridPosition, typeof(SpeciesComponent),
foreach (var entity in Visibility.GetEntitiesInRange(owner.Transform.GridPosition, typeof(IBodyManagerComponent),
controller.VisionRadius))
{
if (entity.HasComponent<BasicActorComponent>() && entity != owner)

View File

@@ -16,6 +16,9 @@ namespace Content.Server.AI.WorldState.States.Inventory
{
foreach (var item in handsComponent.GetAllHeldItems())
{
if (item.Owner.Deleted)
continue;
yield return item.Owner;
}
}

View File

@@ -1,16 +1,16 @@
using System.Collections.Generic;
using System.Collections.Generic;
using Content.Server.AI.Utils;
using Content.Server.GameObjects.Components.Mobs;
using Content.Server.GameObjects.Components.Movement;
using Content.Shared.GameObjects.Components.Body;
using JetBrains.Annotations;
using Robust.Shared.Interfaces.GameObjects;
namespace Content.Server.AI.WorldState.States.Mobs
{
[UsedImplicitly]
public sealed class NearbySpeciesState : CachedStateData<List<IEntity>>
public sealed class NearbyBodiesState : CachedStateData<List<IEntity>>
{
public override string Name => "NearbySpecies";
public override string Name => "NearbyBodies";
protected override List<IEntity> GetTrueValue()
{
@@ -21,7 +21,7 @@ namespace Content.Server.AI.WorldState.States.Mobs
return result;
}
foreach (var entity in Visibility.GetEntitiesInRange(Owner.Transform.GridPosition, typeof(SpeciesComponent), controller.VisionRadius))
foreach (var entity in Visibility.GetEntitiesInRange(Owner.Transform.GridPosition, typeof(IBodyManagerComponent), controller.VisionRadius))
{
if (entity == Owner) continue;
result.Add(entity);

View File

@@ -1,6 +1,6 @@
using System.Collections.Generic;
using Content.Server.GameObjects.Components.Mobs;
using System.Collections.Generic;
using Content.Server.GameObjects.Components.Movement;
using Content.Shared.GameObjects.Components.Damage;
using JetBrains.Annotations;
using Robust.Server.Interfaces.Player;
using Robust.Shared.Interfaces.GameObjects;
@@ -27,7 +27,7 @@ namespace Content.Server.AI.WorldState.States.Mobs
foreach (var player in nearbyPlayers)
{
if (player.AttachedEntity != Owner && player.AttachedEntity.HasComponent<SpeciesComponent>())
if (player.AttachedEntity != Owner && player.AttachedEntity.HasComponent<IDamageableComponent>())
{
result.Add(player.AttachedEntity);
}