This commit is contained in:
juliangiebel
2020-08-12 18:27:35 +02:00
67 changed files with 632 additions and 239 deletions

View File

@@ -302,7 +302,8 @@ namespace Content.Client.Chat
case "ALL":
chatBox.LocalButton.Pressed ^= true;
chatBox.OOCButton.Pressed ^= true;
chatBox.AdminButton.Pressed ^= true;
if (chatBox.AdminButton != null)
chatBox.AdminButton.Pressed ^= true;
_allState = !_allState;
break;
}

View File

@@ -19,6 +19,7 @@ namespace Content.Client.GameObjects.Components.Disposal
private string _stateAnchored;
private string _stateUnAnchored;
private string _stateCharging;
private string _overlayCharging;
private string _overlayReady;
private string _overlayFull;
@@ -47,6 +48,9 @@ namespace Content.Client.GameObjects.Components.Disposal
case VisualState.Anchored:
sprite.LayerSetState(DisposalUnitVisualLayers.Base, _stateAnchored);
break;
case VisualState.Charging:
sprite.LayerSetState(DisposalUnitVisualLayers.Base, _stateCharging);
break;
case VisualState.Flushing:
sprite.LayerSetState(DisposalUnitVisualLayers.Base, _stateAnchored);
@@ -111,6 +115,7 @@ namespace Content.Client.GameObjects.Components.Disposal
_stateAnchored = node.GetNode("state_anchored").AsString();
_stateUnAnchored = node.GetNode("state_unanchored").AsString();
_stateCharging = node.GetNode("state_charging").AsString();
_overlayCharging = node.GetNode("overlay_charging").AsString();
_overlayReady = node.GetNode("overlay_ready").AsString();
_overlayFull = node.GetNode("overlay_full").AsString();

View File

@@ -1,6 +1,7 @@
using Content.Shared.GameObjects.Components.Weapons.Ranged;
using Content.Shared.GameObjects.Components.Weapons.Ranged;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Maths;
namespace Content.Client.GameObjects.Components.Weapons.Ranged
{
@@ -30,9 +31,9 @@ namespace Content.Client.GameObjects.Components.Weapons.Ranged
FireRateSelector = rangedState.FireRateSelector;
}
public void SyncFirePos(GridCoordinates worldPos)
public void SyncFirePos(GridId targetGrid, Vector2 targetPosition)
{
SendNetworkMessage(new FirePosComponentMessage(worldPos));
SendNetworkMessage(new FirePosComponentMessage(targetGrid, targetPosition));
}
}
}
}

View File

@@ -11,6 +11,7 @@ using Robust.Shared.Input;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.Interfaces.Timing;
using Robust.Shared.IoC;
using Robust.Shared.Map;
namespace Content.Client.GameObjects.EntitySystems
{
@@ -96,9 +97,13 @@ namespace Content.Client.GameObjects.EntitySystems
var worldPos = _eyeManager.ScreenToMap(_inputManager.MouseScreenPosition);
if (!_mapManager.TryFindGridAt(worldPos, out var grid))
grid = _mapManager.GetDefaultGrid(worldPos.MapId);
weapon.SyncFirePos(grid.MapToGrid(worldPos));
{
weapon.SyncFirePos(GridId.Invalid, worldPos.Position);
}
else
{
weapon.SyncFirePos(grid.Index, grid.MapToGrid(worldPos).Position);
}
}
}
}

View File

@@ -3,11 +3,9 @@ using System.Collections.Generic;
using Content.Server.AI.Operators;
using Content.Server.AI.Operators.Inventory;
using Content.Server.AI.Utility.Considerations;
using Content.Server.AI.Utility.Considerations.Clothing;
using Content.Server.AI.Utility.Considerations.Inventory;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Shared.GameObjects.Components.Inventory;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
@@ -44,9 +42,7 @@ namespace Content.Server.AI.Utility.Actions.Clothing.Gloves
return new[]
{
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.GLOVES, context)
.InverseBoolCurve(context),
considerationsManager.Get<CanPutTargetInHandsCon>()
considerationsManager.Get<CanPutTargetInInventoryCon>()
.BoolCurve(context),
};
}

View File

@@ -5,6 +5,7 @@ using Content.Server.AI.Utility.Considerations;
using Content.Server.AI.Utility.Considerations.Clothing;
using Content.Server.AI.Utility.Considerations.Containers;
using Content.Server.AI.Utility.Considerations.Inventory;
using Content.Server.AI.Utility.Considerations.Movement;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Shared.GameObjects.Components.Inventory;
@@ -40,13 +41,11 @@ namespace Content.Server.AI.Utility.Actions.Clothing.Gloves
return new[]
{
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.GLOVES, context)
.InverseBoolCurve(context),
considerationsManager.Get<CanPutTargetInHandsCon>()
considerationsManager.Get<CanPutTargetInInventoryCon>()
.BoolCurve(context),
considerationsManager.Get<ClothingInInventoryCon>().Slot(EquipmentSlotDefines.SlotFlags.GLOVES, context)
.InverseBoolCurve(context),
considerationsManager.Get<TargetAccessibleCon>()
considerationsManager.Get<TargetDistanceCon>()
.PresetCurve(context, PresetCurve.Distance),
considerationsManager.Get<TargetAccessibleCon>()
.BoolCurve(context),
};
}

View File

@@ -44,9 +44,7 @@ namespace Content.Server.AI.Utility.Actions.Clothing.Head
return new[]
{
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.HEAD, context)
.InverseBoolCurve(context),
considerationsManager.Get<CanPutTargetInHandsCon>()
considerationsManager.Get<CanPutTargetInInventoryCon>()
.BoolCurve(context),
};

View File

@@ -5,6 +5,7 @@ using Content.Server.AI.Utility.Considerations;
using Content.Server.AI.Utility.Considerations.Clothing;
using Content.Server.AI.Utility.Considerations.Containers;
using Content.Server.AI.Utility.Considerations.Inventory;
using Content.Server.AI.Utility.Considerations.Movement;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Shared.GameObjects.Components.Inventory;
@@ -40,13 +41,11 @@ namespace Content.Server.AI.Utility.Actions.Clothing.Head
return new[]
{
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.HEAD, context)
.InverseBoolCurve(context),
considerationsManager.Get<CanPutTargetInHandsCon>()
considerationsManager.Get<CanPutTargetInInventoryCon>()
.BoolCurve(context),
considerationsManager.Get<ClothingInInventoryCon>().Slot(EquipmentSlotDefines.SlotFlags.HEAD, context)
.InverseBoolCurve(context),
considerationsManager.Get<TargetAccessibleCon>()
considerationsManager.Get<TargetDistanceCon>()
.PresetCurve(context, PresetCurve.Distance),
considerationsManager.Get<TargetAccessibleCon>()
.BoolCurve(context),
};
}

View File

@@ -44,9 +44,7 @@ namespace Content.Server.AI.Utility.Actions.Clothing.OuterClothing
return new[]
{
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.OUTERCLOTHING, context)
.InverseBoolCurve(context),
considerationsManager.Get<CanPutTargetInHandsCon>()
considerationsManager.Get<CanPutTargetInInventoryCon>()
.BoolCurve(context),
};
}

View File

@@ -5,6 +5,7 @@ using Content.Server.AI.Utility.Considerations;
using Content.Server.AI.Utility.Considerations.Clothing;
using Content.Server.AI.Utility.Considerations.Containers;
using Content.Server.AI.Utility.Considerations.Inventory;
using Content.Server.AI.Utility.Considerations.Movement;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Shared.GameObjects.Components.Inventory;
@@ -40,12 +41,10 @@ namespace Content.Server.AI.Utility.Actions.Clothing.OuterClothing
return new[]
{
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.OUTERCLOTHING, context)
.InverseBoolCurve(context),
considerationsManager.Get<CanPutTargetInHandsCon>()
considerationsManager.Get<CanPutTargetInInventoryCon>()
.BoolCurve(context),
considerationsManager.Get<ClothingInInventoryCon>().Slot(EquipmentSlotDefines.SlotFlags.OUTERCLOTHING, context)
.InverseBoolCurve(context),
considerationsManager.Get<TargetDistanceCon>()
.PresetCurve(context, PresetCurve.Distance),
considerationsManager.Get<TargetAccessibleCon>()
.BoolCurve(context),
};

View File

@@ -44,9 +44,7 @@ namespace Content.Server.AI.Utility.Actions.Clothing.Shoes
return new[]
{
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.SHOES, context)
.InverseBoolCurve(context),
considerationsManager.Get<CanPutTargetInHandsCon>()
considerationsManager.Get<CanPutTargetInInventoryCon>()
.BoolCurve(context),
};
}

View File

@@ -5,6 +5,7 @@ using Content.Server.AI.Utility.Considerations;
using Content.Server.AI.Utility.Considerations.Clothing;
using Content.Server.AI.Utility.Considerations.Containers;
using Content.Server.AI.Utility.Considerations.Inventory;
using Content.Server.AI.Utility.Considerations.Movement;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Shared.GameObjects.Components.Inventory;
@@ -40,12 +41,10 @@ namespace Content.Server.AI.Utility.Actions.Clothing.Shoes
return new[]
{
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.SHOES, context)
.InverseBoolCurve(context),
considerationsManager.Get<CanPutTargetInHandsCon>()
considerationsManager.Get<CanPutTargetInInventoryCon>()
.BoolCurve(context),
considerationsManager.Get<ClothingInInventoryCon>().Slot(EquipmentSlotDefines.SlotFlags.SHOES, context)
.InverseBoolCurve(context),
considerationsManager.Get<TargetDistanceCon>()
.PresetCurve(context, PresetCurve.Distance),
considerationsManager.Get<TargetAccessibleCon>()
.BoolCurve(context),
};

View File

@@ -44,9 +44,7 @@ namespace Content.Server.AI.Utility.Actions.Combat.Melee
return new[]
{
considerationsManager.Get<MeleeWeaponEquippedCon>()
.InverseBoolCurve(context),
considerationsManager.Get<CanPutTargetInHandsCon>()
considerationsManager.Get<CanPutTargetInInventoryCon>()
.BoolCurve(context),
considerationsManager.Get<MeleeWeaponSpeedCon>()
.QuadraticCurve(context, 1.0f, 0.5f, 0.0f, 0.0f),

View File

@@ -66,16 +66,14 @@ namespace Content.Server.AI.Utility.Actions.Combat.Melee
return new[]
{
considerationsManager.Get<MeleeWeaponEquippedCon>()
.BoolCurve(context),
considerationsManager.Get<TargetIsDeadCon>()
.InverseBoolCurve(context),
considerationsManager.Get<TargetIsCritCon>()
.QuadraticCurve(context, -0.8f, 1.0f, 1.0f, 0.0f),
considerationsManager.Get<DistanceCon>()
.QuadraticCurve(context, 1.0f, 1.0f, 0.02f, 0.0f),
considerationsManager.Get<TargetDistanceCon>()
.PresetCurve(context, PresetCurve.Distance),
considerationsManager.Get<TargetHealthCon>()
.QuadraticCurve(context, 1.0f, 0.4f, 0.0f, -0.02f),
.PresetCurve(context, PresetCurve.TargetHealth),
considerationsManager.Get<MeleeWeaponSpeedCon>()
.QuadraticCurve(context, 1.0f, 0.5f, 0.0f, 0.0f),
considerationsManager.Get<MeleeWeaponDamageCon>()

View File

@@ -42,12 +42,8 @@ namespace Content.Server.AI.Utility.Actions.Combat.Melee
return new[]
{
considerationsManager.Get<FreeHandCon>()
.BoolCurve(context),
considerationsManager.Get<HasMeleeWeaponCon>()
.InverseBoolCurve(context),
considerationsManager.Get<DistanceCon>()
.QuadraticCurve(context, 1.0f, 1.0f, 0.02f, 0.0f),
considerationsManager.Get<TargetDistanceCon>()
.PresetCurve(context, PresetCurve.Distance),
considerationsManager.Get<MeleeWeaponDamageCon>()
.QuadraticCurve(context, 1.0f, 0.25f, 0.0f, 0.0f),
considerationsManager.Get<MeleeWeaponSpeedCon>()

View File

@@ -64,16 +64,14 @@ namespace Content.Server.AI.Utility.Actions.Combat.Melee
return new[]
{
considerationsManager.Get<CanUnarmedCombatCon>()
.BoolCurve(context),
considerationsManager.Get<TargetIsDeadCon>()
.InverseBoolCurve(context),
considerationsManager.Get<TargetIsCritCon>()
.QuadraticCurve(context, -0.8f, 1.0f, 1.0f, 0.0f),
considerationsManager.Get<DistanceCon>()
.QuadraticCurve(context, -1.0f, 1.0f, 1.02f, 0.0f),
considerationsManager.Get<TargetDistanceCon>()
.PresetCurve(context, PresetCurve.Distance),
considerationsManager.Get<TargetHealthCon>()
.QuadraticCurve(context, 1.0f, 0.4f, 0.0f, -0.02f),
.PresetCurve(context, PresetCurve.TargetHealth),
considerationsManager.Get<TargetAccessibleCon>()
.BoolCurve(context),
// TODO: Consider our Speed and Damage to compare this to using a weapon
@@ -81,4 +79,4 @@ namespace Content.Server.AI.Utility.Actions.Combat.Melee
};
}
}
}
}

View File

@@ -20,7 +20,7 @@ namespace Content.Server.AI.Utility.Actions.Idle
/// </summary>
public sealed class CloseLastEntityStorage : UtilityAction
{
public override float Bonus => 1.5f;
public override float Bonus => IdleBonus + 0.01f;
public CloseLastEntityStorage(IEntity owner) : base(owner) {}
@@ -50,12 +50,12 @@ namespace Content.Server.AI.Utility.Actions.Idle
{
considerationsManager.Get<StoredStateEntityIsNullCon>().Set(typeof(LastOpenedStorageState), context)
.InverseBoolCurve(context),
considerationsManager.Get<DistanceCon>()
.QuadraticCurve(context, 1.0f, 1.0f, 0.02f, 0.0f),
considerationsManager.Get<TargetAccessibleCon>()
considerationsManager.Get<TargetDistanceCon>()
.PresetCurve(context, PresetCurve.Distance),
considerationsManager.Get<TargetAccessibleCon>()
.BoolCurve(context),
};
}
}
}
}

View File

@@ -43,9 +43,9 @@ namespace Content.Server.AI.Utility.Actions.Nutrition.Drink
considerationsManager.Get<FreeHandCon>()
.BoolCurve(context),
considerationsManager.Get<ThirstCon>()
.LogisticCurve(context, 1000f, 1.3f, -1.0f, 0.5f),
considerationsManager.Get<DistanceCon>()
.QuadraticCurve(context, 1.0f, 1.0f, 0.02f, 0.0f),
.PresetCurve(context, PresetCurve.Nutrition),
considerationsManager.Get<TargetDistanceCon>()
.PresetCurve(context, PresetCurve.Distance),
considerationsManager.Get<DrinkValueCon>()
.QuadraticCurve(context, 1.0f, 0.4f, 0.0f, 0.0f),
considerationsManager.Get<TargetAccessibleCon>()

View File

@@ -3,7 +3,7 @@ using System.Collections.Generic;
using Content.Server.AI.Operators;
using Content.Server.AI.Operators.Inventory;
using Content.Server.AI.Utility.Considerations;
using Content.Server.AI.Utility.Considerations.Hands;
using Content.Server.AI.Utility.Considerations.Inventory;
using Content.Server.AI.Utility.Considerations.Nutrition.Drink;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
@@ -43,10 +43,8 @@ namespace Content.Server.AI.Utility.Actions.Nutrition.Drink
return new[]
{
considerationsManager.Get<TargetInOurHandsCon>()
considerationsManager.Get<TargetInOurInventoryCon>()
.BoolCurve(context),
considerationsManager.Get<ThirstCon>()
.LogisticCurve(context, 1000f, 1.3f, -0.3f, 0.5f),
considerationsManager.Get<DrinkValueCon>()
.QuadraticCurve(context, 1.0f, 0.4f, 0.0f, 0.0f),
};

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using Content.Server.AI.Operators.Sequences;
using Content.Server.AI.Utility.Considerations;
using Content.Server.AI.Utility.Considerations.Containers;
using Content.Server.AI.Utility.Considerations.Hands;
using Content.Server.AI.Utility.Considerations.Movement;
using Content.Server.AI.Utility.Considerations.Nutrition.Food;
using Content.Server.AI.WorldState;
@@ -40,12 +39,8 @@ namespace Content.Server.AI.Utility.Actions.Nutrition.Food
return new[]
{
considerationsManager.Get<FreeHandCon>()
.BoolCurve(context),
considerationsManager.Get<HungerCon>()
.LogisticCurve(context, 1000f, 1.3f, -1.0f, 0.5f),
considerationsManager.Get<DistanceCon>()
.QuadraticCurve(context, 1.0f, 1.0f, 0.02f, 0.0f),
considerationsManager.Get<TargetDistanceCon>()
.PresetCurve(context, PresetCurve.Distance),
considerationsManager.Get<FoodValueCon>()
.QuadraticCurve(context, 1.0f, 0.4f, 0.0f, 0.0f),
considerationsManager.Get<TargetAccessibleCon>()

View File

@@ -3,8 +3,7 @@ using System.Collections.Generic;
using Content.Server.AI.Operators;
using Content.Server.AI.Operators.Inventory;
using Content.Server.AI.Utility.Considerations;
using Content.Server.AI.Utility.Considerations.Containers;
using Content.Server.AI.Utility.Considerations.Hands;
using Content.Server.AI.Utility.Considerations.Inventory;
using Content.Server.AI.Utility.Considerations.Nutrition.Food;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
@@ -44,13 +43,10 @@ namespace Content.Server.AI.Utility.Actions.Nutrition.Food
return new[]
{
considerationsManager.Get<TargetInOurHandsCon>()
considerationsManager.Get<TargetInOurInventoryCon>()
.BoolCurve(context),
considerationsManager.Get<HungerCon>()
.LogisticCurve(context, 1000f, 1.3f, -0.3f, 0.5f),
considerationsManager.Get<FoodValueCon>()
.QuadraticCurve(context, 1.0f, 0.4f, 0.0f, 0.0f),
};
}
}

View File

@@ -106,7 +106,6 @@ namespace Content.Server.AI.Utility.Actions
/// This is where the magic happens
/// </summary>
/// <param name="context"></param>
/// <param name="bonus"></param>
/// <param name="min"></param>
/// <returns></returns>
public float GetScore(Blackboard context, float min)

View File

@@ -11,7 +11,7 @@ namespace Content.Server.AI.Utility.BehaviorSets
Actions = new IAiUtility[]
{
new PickUpNearbyDrinkExp(),
new UseDrinkInHandsExp(),
new UseDrinkInInventoryExp(),
};
}
}

View File

@@ -1,6 +1,7 @@
using System;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States.Utility;
using JetBrains.Annotations;
namespace Content.Server.AI.Utility.Considerations
{
@@ -18,50 +19,114 @@ namespace Content.Server.AI.Utility.Considerations
return Math.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;
}
public Func<float> BoolCurve(Blackboard context)
{
float Result()
{
var adjustedScore = GetAdjustedScore(context);
// ReSharper disable once CompareOfFloatsByEqualityOperator
return adjustedScore == 1.0f ? 1.0f : 0.0f;
return BoolCurve(adjustedScore);
}
return Result;
}
[Pure]
private static float InverseBoolCurve(float x)
{
// ReSharper disable once CompareOfFloatsByEqualityOperator
return x == 1.0f ? 0.0f : 1.0f;
}
public Func<float> InverseBoolCurve(Blackboard context)
{
float Result()
{
var adjustedScore = GetAdjustedScore(context);
// ReSharper disable once CompareOfFloatsByEqualityOperator
return adjustedScore == 1.0f ? 0.0f : 1.0f;
return InverseBoolCurve(adjustedScore);
}
return Result;
}
[Pure]
private static float LogisticCurve(float x, float slope, float exponent, float yOffset, float xOffset)
{
return Math.Clamp(
exponent * (1 / (1 + (float) Math.Pow(Math.Log(1000) * slope, -1 * x + xOffset))) + yOffset, 0.0f, 1.0f);
}
public Func<float> LogisticCurve(Blackboard context, float slope, float exponent, float yOffset, float xOffset)
{
float Result()
{
var adjustedScore = GetAdjustedScore(context);
return Math.Clamp(exponent * (1 / (1 + (float) Math.Pow(Math.Log(1000) * slope, -1 * adjustedScore + xOffset))) + yOffset, 0.0f, 1.0f);
return LogisticCurve(adjustedScore, slope, exponent, yOffset, xOffset);
}
return Result;
}
[Pure]
private static float QuadraticCurve(float x, float slope, float exponent, float yOffset, float xOffset)
{
return Math.Clamp(slope * (float) Math.Pow(x - xOffset, exponent) + yOffset, 0.0f, 1.0f);
}
public Func<float> QuadraticCurve(Blackboard context, float slope, float exponent, float yOffset, float xOffset)
{
float Result()
{
var adjustedScore = GetAdjustedScore(context);
return Math.Clamp(slope * (float) Math.Pow(adjustedScore - xOffset, exponent) + yOffset, 0.0f, 1.0f);
return QuadraticCurve(adjustedScore, slope, exponent, yOffset, xOffset);
}
return Result;
}
/// <summary>
/// For any curves that are re-used across actions so you only need to update it once.
/// </summary>
/// <param name="context"></param>
/// <param name="preset"></param>
/// <returns></returns>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public Func<float> PresetCurve(Blackboard context, PresetCurve preset)
{
float Result()
{
var adjustedScore = GetAdjustedScore(context);
switch (preset)
{
case Considerations.PresetCurve.Distance:
return QuadraticCurve(adjustedScore, -1.0f, 1.0f, 1.0f, 0.02f);
case Considerations.PresetCurve.Nutrition:
return QuadraticCurve(adjustedScore, 2.0f, 1.0f, -1.0f, -0.2f);
case Considerations.PresetCurve.TargetHealth:
return QuadraticCurve(adjustedScore, 1.0f, 0.4f, 0.0f, -0.02f);
default:
throw new ArgumentOutOfRangeException(nameof(preset), preset, null);
}
}
return Result;
}
}
/// <summary>
/// Preset response curves for considerations
/// </summary>
public enum PresetCurve
{
Distance,
Nutrition,
TargetHealth,
}
}

View File

@@ -1,28 +0,0 @@
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Server.GameObjects.Components;
using Content.Server.GameObjects.Components.GUI;
namespace Content.Server.AI.Utility.Considerations.Hands
{
/// <summary>
/// Returns 1 if in our hands else 0
/// </summary>
public sealed class TargetInOurHandsCon : Consideration
{
protected override float GetScore(Blackboard context)
{
var owner = context.GetState<SelfState>().GetValue();
var target = context.GetState<TargetEntityState>().GetValue();
if (target == null ||
!target.HasComponent<ItemComponent>() ||
!owner.TryGetComponent(out HandsComponent handsComponent))
{
return 0.0f;
}
return handsComponent.IsHolding(target) ? 1.0f : 0.0f;
}
}
}

View File

@@ -6,7 +6,7 @@ using Content.Server.GameObjects.Components;
namespace Content.Server.AI.Utility.Considerations.Inventory
{
public class CanPutTargetInHandsCon : Consideration
public class CanPutTargetInInventoryCon : Consideration
{
protected override float GetScore(Blackboard context)
{

View File

@@ -1,6 +1,7 @@
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Server.AI.WorldState.States.Inventory;
using Content.Server.GameObjects;
using Content.Server.GameObjects.Components;
namespace Content.Server.AI.Utility.Considerations.Inventory

View File

@@ -3,7 +3,7 @@ using Content.Server.AI.WorldState.States;
namespace Content.Server.AI.Utility.Considerations.Movement
{
public sealed class DistanceCon : Consideration
public sealed class TargetDistanceCon : Consideration
{
protected override float GetScore(Blackboard context)
{
@@ -14,8 +14,8 @@ namespace Content.Server.AI.Utility.Considerations.Movement
return 0.0f;
}
// Kind of just pulled a max distance out of nowhere. Add 0.01 just in case it's reaally far and we have no choice so it'll still be considered at least.
return (target.Transform.GridPosition.Position - self.Transform.GridPosition.Position).Length / 100 + 0.01f;
// Anything further than 100 tiles gets clamped
return (target.Transform.GridPosition.Position - self.Transform.GridPosition.Position).Length / 100;
}
}
}

View File

@@ -2,12 +2,14 @@ using System;
using System.Collections.Generic;
using Content.Server.AI.Utility.Actions;
using Content.Server.AI.Utility.Actions.Clothing.Gloves;
using Content.Server.AI.Utility.Considerations;
using Content.Server.AI.Utility.Considerations.Clothing;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Server.AI.WorldState.States.Inventory;
using Content.Server.GameObjects;
using Content.Server.GameObjects.Components.Movement;
using Content.Shared.GameObjects.Components.Inventory;
using Robust.Shared.IoC;
namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Gloves
{
@@ -18,6 +20,17 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Gloves
{
public override float Bonus => UtilityAction.NormalBonus;
protected override IEnumerable<Func<float>> GetCommonConsiderations(Blackboard context)
{
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
return new []
{
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.GLOVES, context)
.InverseBoolCurve(context),
};
}
public override IEnumerable<UtilityAction> GetActions(Blackboard context)
{
var owner = context.GetState<SelfState>().GetValue();

View File

@@ -1,11 +1,16 @@
using System;
using System.Collections.Generic;
using Content.Server.AI.Utility.Actions;
using Content.Server.AI.Utility.Actions.Clothing.Gloves;
using Content.Server.AI.Utility.Considerations;
using Content.Server.AI.Utility.Considerations.Clothing;
using Content.Server.AI.Utility.Considerations.Inventory;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Server.AI.WorldState.States.Clothing;
using Content.Server.GameObjects;
using Content.Shared.GameObjects.Components.Inventory;
using Robust.Shared.IoC;
namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Gloves
{
@@ -13,9 +18,22 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Gloves
{
public override float Bonus => UtilityAction.NormalBonus;
protected override IEnumerable<Func<float>> GetCommonConsiderations(Blackboard context)
{
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
return new[]
{
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.GLOVES, context)
.InverseBoolCurve(context),
considerationsManager.Get<ClothingInInventoryCon>().Slot(EquipmentSlotDefines.SlotFlags.GLOVES, context)
.InverseBoolCurve(context),
};
}
public override IEnumerable<UtilityAction> GetActions(Blackboard context)
{
var owner = context.GetState<SelfState>().GetValue();
foreach (var entity in context.GetState<NearbyClothingState>().GetValue())
{
if (entity.TryGetComponent(out ClothingComponent clothing) &&

View File

@@ -1,11 +1,15 @@
using System;
using System.Collections.Generic;
using Content.Server.AI.Utility.Actions;
using Content.Server.AI.Utility.Actions.Clothing.Head;
using Content.Server.AI.Utility.Considerations;
using Content.Server.AI.Utility.Considerations.Clothing;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Server.AI.WorldState.States.Inventory;
using Content.Server.GameObjects;
using Content.Shared.GameObjects.Components.Inventory;
using Robust.Shared.IoC;
namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Head
{
@@ -16,6 +20,16 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Head
{
public override float Bonus => UtilityAction.NormalBonus;
protected override IEnumerable<Func<float>> GetCommonConsiderations(Blackboard context)
{
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
return new[] {
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.HEAD, context)
.InverseBoolCurve(context),
};
}
public override IEnumerable<UtilityAction> GetActions(Blackboard context)
{
var owner = context.GetState<SelfState>().GetValue();

View File

@@ -2,12 +2,15 @@ using System;
using System.Collections.Generic;
using Content.Server.AI.Utility.Actions;
using Content.Server.AI.Utility.Actions.Clothing.Head;
using Content.Server.AI.Utility.Considerations;
using Content.Server.AI.Utility.Considerations.Clothing;
using Content.Server.AI.Utility.Considerations.Inventory;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Server.AI.WorldState.States.Clothing;
using Content.Server.GameObjects;
using Content.Server.GameObjects.Components.Movement;
using Content.Shared.GameObjects.Components.Inventory;
using Robust.Shared.IoC;
namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Head
{
@@ -15,6 +18,18 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Head
{
public override float Bonus => UtilityAction.NormalBonus;
protected override IEnumerable<Func<float>> GetCommonConsiderations(Blackboard context)
{
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
return new[]
{
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.HEAD, context)
.InverseBoolCurve(context),
considerationsManager.Get<ClothingInInventoryCon>().Slot(EquipmentSlotDefines.SlotFlags.HEAD, context)
.InverseBoolCurve(context)
};
}
public override IEnumerable<UtilityAction> GetActions(Blackboard context)
{
var owner = context.GetState<SelfState>().GetValue();

View File

@@ -2,12 +2,14 @@ using System;
using System.Collections.Generic;
using Content.Server.AI.Utility.Actions;
using Content.Server.AI.Utility.Actions.Clothing.OuterClothing;
using Content.Server.AI.Utility.Considerations;
using Content.Server.AI.Utility.Considerations.Clothing;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Server.AI.WorldState.States.Inventory;
using Content.Server.GameObjects;
using Content.Server.GameObjects.Components.Movement;
using Content.Shared.GameObjects.Components.Inventory;
using Robust.Shared.IoC;
namespace Content.Server.AI.Utility.ExpandableActions.Clothing.OuterClothing
{
@@ -18,6 +20,17 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.OuterClothing
{
public override float Bonus => UtilityAction.NormalBonus;
protected override IEnumerable<Func<float>> GetCommonConsiderations(Blackboard context)
{
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
return new[]
{
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.OUTERCLOTHING, context)
.InverseBoolCurve(context),
};
}
public override IEnumerable<UtilityAction> GetActions(Blackboard context)
{
var owner = context.GetState<SelfState>().GetValue();

View File

@@ -1,11 +1,16 @@
using System;
using System.Collections.Generic;
using Content.Server.AI.Utility.Actions;
using Content.Server.AI.Utility.Actions.Clothing.OuterClothing;
using Content.Server.AI.Utility.Considerations;
using Content.Server.AI.Utility.Considerations.Clothing;
using Content.Server.AI.Utility.Considerations.Inventory;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Server.AI.WorldState.States.Clothing;
using Content.Server.GameObjects;
using Content.Shared.GameObjects.Components.Inventory;
using Robust.Shared.IoC;
namespace Content.Server.AI.Utility.ExpandableActions.Clothing.OuterClothing
{
@@ -13,6 +18,19 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.OuterClothing
{
public override float Bonus => UtilityAction.NormalBonus;
protected override IEnumerable<Func<float>> GetCommonConsiderations(Blackboard context)
{
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
return new[]
{
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.OUTERCLOTHING, context)
.InverseBoolCurve(context),
considerationsManager.Get<ClothingInInventoryCon>().Slot(EquipmentSlotDefines.SlotFlags.OUTERCLOTHING, context)
.InverseBoolCurve(context)
};
}
public override IEnumerable<UtilityAction> GetActions(Blackboard context)
{
var owner = context.GetState<SelfState>().GetValue();

View File

@@ -2,12 +2,14 @@ using System;
using System.Collections.Generic;
using Content.Server.AI.Utility.Actions;
using Content.Server.AI.Utility.Actions.Clothing.Shoes;
using Content.Server.AI.Utility.Considerations;
using Content.Server.AI.Utility.Considerations.Clothing;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Server.AI.WorldState.States.Inventory;
using Content.Server.GameObjects;
using Content.Server.GameObjects.Components.Movement;
using Content.Shared.GameObjects.Components.Inventory;
using Robust.Shared.IoC;
namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Shoes
{
@@ -18,6 +20,17 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Shoes
{
public override float Bonus => UtilityAction.NormalBonus;
protected override IEnumerable<Func<float>> GetCommonConsiderations(Blackboard context)
{
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
return new[]
{
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.SHOES, context)
.InverseBoolCurve(context),
};
}
public override IEnumerable<UtilityAction> GetActions(Blackboard context)
{
var owner = context.GetState<SelfState>().GetValue();

View File

@@ -1,11 +1,16 @@
using System;
using System.Collections.Generic;
using Content.Server.AI.Utility.Actions;
using Content.Server.AI.Utility.Actions.Clothing.Shoes;
using Content.Server.AI.Utility.Considerations;
using Content.Server.AI.Utility.Considerations.Clothing;
using Content.Server.AI.Utility.Considerations.Inventory;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Server.AI.WorldState.States.Clothing;
using Content.Server.GameObjects;
using Content.Shared.GameObjects.Components.Inventory;
using Robust.Shared.IoC;
namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Shoes
{
@@ -13,6 +18,19 @@ namespace Content.Server.AI.Utility.ExpandableActions.Clothing.Shoes
{
public override float Bonus => UtilityAction.NormalBonus;
protected override IEnumerable<Func<float>> GetCommonConsiderations(Blackboard context)
{
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
return new[]
{
considerationsManager.Get<ClothingInSlotCon>().Slot(EquipmentSlotDefines.Slots.SHOES, context)
.InverseBoolCurve(context),
considerationsManager.Get<ClothingInInventoryCon>().Slot(EquipmentSlotDefines.SlotFlags.SHOES, context)
.InverseBoolCurve(context)
};
}
public override IEnumerable<UtilityAction> GetActions(Blackboard context)
{
var owner = context.GetState<SelfState>().GetValue();

View File

@@ -1,10 +1,15 @@
using System;
using System.Collections.Generic;
using Content.Server.AI.Utility.Actions;
using Content.Server.AI.Utility.Actions.Combat.Melee;
using Content.Server.AI.Utility.Considerations;
using Content.Server.AI.Utility.Considerations.Combat.Melee;
using Content.Server.AI.Utility.Considerations.Inventory;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Server.AI.WorldState.States.Inventory;
using Content.Server.GameObjects.Components.Weapon.Melee;
using Robust.Shared.IoC;
namespace Content.Server.AI.Utility.ExpandableActions.Combat.Melee
{
@@ -12,6 +17,17 @@ namespace Content.Server.AI.Utility.ExpandableActions.Combat.Melee
{
public override float Bonus => UtilityAction.CombatPrepBonus;
protected override IEnumerable<Func<float>> GetCommonConsiderations(Blackboard context)
{
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
return new[]
{
considerationsManager.Get<MeleeWeaponEquippedCon>()
.InverseBoolCurve(context),
};
}
public override IEnumerable<UtilityAction> GetActions(Blackboard context)
{
var owner = context.GetState<SelfState>().GetValue();

View File

@@ -2,12 +2,15 @@ using System;
using System.Collections.Generic;
using Content.Server.AI.Utility.Actions;
using Content.Server.AI.Utility.Actions.Combat.Melee;
using Content.Server.AI.Utility.Considerations;
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;
using Content.Server.GameObjects.Components.Movement;
using Robust.Server.GameObjects;
using Robust.Shared.IoC;
namespace Content.Server.AI.Utility.ExpandableActions.Combat.Melee
{
@@ -15,6 +18,17 @@ namespace Content.Server.AI.Utility.ExpandableActions.Combat.Melee
{
public override float Bonus => UtilityAction.CombatBonus;
protected override IEnumerable<Func<float>> GetCommonConsiderations(Blackboard context)
{
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
return new[]
{
considerationsManager.Get<MeleeWeaponEquippedCon>()
.BoolCurve(context),
};
}
public override IEnumerable<UtilityAction> GetActions(Blackboard context)
{
var owner = context.GetState<SelfState>().GetValue();

View File

@@ -1,9 +1,11 @@
using System;
using System.Collections.Generic;
using Content.Server.AI.Utility.Actions;
using Content.Server.AI.Utility.Actions.Combat.Melee;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Server.AI.WorldState.States.Mobs;
using Content.Server.GameObjects.Components.Movement;
namespace Content.Server.AI.Utility.ExpandableActions.Combat.Melee
{
@@ -14,6 +16,7 @@ namespace Content.Server.AI.Utility.ExpandableActions.Combat.Melee
public override IEnumerable<UtilityAction> GetActions(Blackboard context)
{
var owner = context.GetState<SelfState>().GetValue();
foreach (var entity in context.GetState<NearbySpeciesState>().GetValue())
{
yield return new MeleeWeaponAttackEntity(owner, entity, Bonus);

View File

@@ -1,9 +1,14 @@
using System;
using System.Collections.Generic;
using Content.Server.AI.Utility.Actions;
using Content.Server.AI.Utility.Actions.Combat.Melee;
using Content.Server.AI.Utility.Considerations;
using Content.Server.AI.Utility.Considerations.Combat.Melee;
using Content.Server.AI.Utility.Considerations.Hands;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Server.AI.WorldState.States.Combat.Nearby;
using Robust.Shared.IoC;
namespace Content.Server.AI.Utility.ExpandableActions.Combat.Melee
{
@@ -11,6 +16,19 @@ namespace Content.Server.AI.Utility.ExpandableActions.Combat.Melee
{
public override float Bonus => UtilityAction.CombatPrepBonus;
protected override IEnumerable<Func<float>> GetCommonConsiderations(Blackboard context)
{
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
return new[]
{
considerationsManager.Get<FreeHandCon>()
.BoolCurve(context),
considerationsManager.Get<HasMeleeWeaponCon>()
.InverseBoolCurve(context),
};
}
public override IEnumerable<UtilityAction> GetActions(Blackboard context)
{
var owner = context.GetState<SelfState>().GetValue();

View File

@@ -2,12 +2,15 @@ using System;
using System.Collections.Generic;
using Content.Server.AI.Utility.Actions;
using Content.Server.AI.Utility.Actions.Combat.Melee;
using Content.Server.AI.Utility.Considerations;
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;
using Content.Server.GameObjects.Components.Movement;
using Robust.Server.GameObjects;
using Robust.Shared.IoC;
namespace Content.Server.AI.Utility.ExpandableActions.Combat.Melee
{
@@ -15,6 +18,17 @@ namespace Content.Server.AI.Utility.ExpandableActions.Combat.Melee
{
public override float Bonus => UtilityAction.CombatBonus;
protected override IEnumerable<Func<float>> GetCommonConsiderations(Blackboard context)
{
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
return new[]
{
considerationsManager.Get<CanUnarmedCombatCon>()
.BoolCurve(context),
};
}
public override IEnumerable<UtilityAction> GetActions(Blackboard context)
{
var owner = context.GetState<SelfState>().GetValue();

View File

@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using Content.Server.AI.Utility.Actions;
using Content.Server.AI.WorldState;
@@ -12,6 +13,37 @@ namespace Content.Server.AI.Utility.ExpandableActions
{
public abstract float Bonus { get; }
/// <summary>
/// No point expanding nodes if none of them can ever be valid.
/// Fails if any of the common considerations is 0.0f (i.e. invalid)
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public bool IsValid(Blackboard context)
{
foreach (var con in GetCommonConsiderations(context))
{
// ReSharper disable once CompareOfFloatsByEqualityOperator
if (con.Invoke() == 0.0f) return false;
}
return true;
}
/// <summary>
/// Called by IsValid to try and early-out the expandable action.
/// No point going through all nearby clothes if we can't fit it in a slot.
/// </summary>
/// Similar to HTN's compound tasks where they can have overall conditions that have to be met before the actions are considered.
/// Ideally any binary early-outs that are common to all expanded actions would be checked once, e.g. a boolean free hand check
/// Use this if you want to optimise the expandable further.
/// <param name="context"></param>
/// <returns></returns>
protected virtual IEnumerable<Func<float>> GetCommonConsiderations(Blackboard context)
{
yield break;
}
// e.g. you may have a "PickupFood" action for all nearby food sources if you have the "Hungry" BehaviorSet.
public abstract IEnumerable<UtilityAction> GetActions(Blackboard context);
}

View File

@@ -1,9 +1,14 @@
using System;
using System.Collections.Generic;
using Content.Server.AI.Utility.Actions;
using Content.Server.AI.Utility.Actions.Nutrition.Drink;
using Content.Server.AI.Utility.Considerations;
using Content.Server.AI.Utility.Considerations.Hands;
using Content.Server.AI.Utility.Considerations.Nutrition.Drink;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Server.AI.WorldState.States.Nutrition;
using Robust.Shared.IoC;
namespace Content.Server.AI.Utility.ExpandableActions.Nutrition
{
@@ -11,6 +16,16 @@ namespace Content.Server.AI.Utility.ExpandableActions.Nutrition
{
public override float Bonus => UtilityAction.NeedsBonus;
protected override IEnumerable<Func<float>> GetCommonConsiderations(Blackboard context)
{
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
return new[]
{
considerationsManager.Get<ThirstCon>().PresetCurve(context, PresetCurve.Nutrition),
considerationsManager.Get<FreeHandCon>().BoolCurve(context),
};
}
public override IEnumerable<UtilityAction> GetActions(Blackboard context)
{
var owner = context.GetState<SelfState>().GetValue();

View File

@@ -1,9 +1,14 @@
using System;
using System.Collections.Generic;
using Content.Server.AI.Utility.Actions;
using Content.Server.AI.Utility.Actions.Nutrition.Food;
using Content.Server.AI.Utility.Considerations;
using Content.Server.AI.Utility.Considerations.Hands;
using Content.Server.AI.Utility.Considerations.Nutrition.Food;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Server.AI.WorldState.States.Nutrition;
using Robust.Shared.IoC;
namespace Content.Server.AI.Utility.ExpandableActions.Nutrition
{
@@ -11,6 +16,16 @@ namespace Content.Server.AI.Utility.ExpandableActions.Nutrition
{
public override float Bonus => UtilityAction.NeedsBonus;
protected override IEnumerable<Func<float>> GetCommonConsiderations(Blackboard context)
{
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
return new[]
{
considerationsManager.Get<HungerCon>().PresetCurve(context, PresetCurve.Nutrition),
considerationsManager.Get<FreeHandCon>().BoolCurve(context),
};
}
public override IEnumerable<UtilityAction> GetActions(Blackboard context)
{
var owner = context.GetState<SelfState>().GetValue();

View File

@@ -1,16 +1,29 @@
using System;
using System.Collections.Generic;
using Content.Server.AI.Utility.Actions;
using Content.Server.AI.Utility.Actions.Nutrition.Drink;
using Content.Server.AI.Utility.Considerations;
using Content.Server.AI.Utility.Considerations.Nutrition.Drink;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Server.AI.WorldState.States.Inventory;
using Content.Server.GameObjects.Components.Nutrition;
using Robust.Shared.IoC;
namespace Content.Server.AI.Utility.ExpandableActions.Nutrition
{
public sealed class UseDrinkInHandsExp : ExpandableUtilityAction
public sealed class UseDrinkInInventoryExp : ExpandableUtilityAction
{
public override float Bonus => UtilityAction.NeedsBonus;
protected override IEnumerable<Func<float>> GetCommonConsiderations(Blackboard context)
{
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
return new[]
{
considerationsManager.Get<ThirstCon>().PresetCurve(context, PresetCurve.Nutrition)
};
}
public override IEnumerable<UtilityAction> GetActions(Blackboard context)
{

View File

@@ -1,10 +1,14 @@
using System;
using System.Collections.Generic;
using Content.Server.AI.Utility.Actions;
using Content.Server.AI.Utility.Actions.Nutrition.Food;
using Content.Server.AI.Utility.Considerations;
using Content.Server.AI.Utility.Considerations.Nutrition.Food;
using Content.Server.AI.WorldState;
using Content.Server.AI.WorldState.States;
using Content.Server.AI.WorldState.States.Inventory;
using Content.Server.GameObjects.Components.Nutrition;
using Robust.Shared.IoC;
namespace Content.Server.AI.Utility.ExpandableActions.Nutrition
{
@@ -12,6 +16,15 @@ namespace Content.Server.AI.Utility.ExpandableActions.Nutrition
{
public override float Bonus => UtilityAction.NeedsBonus;
protected override IEnumerable<Func<float>> GetCommonConsiderations(Blackboard context)
{
var considerationsManager = IoCManager.Resolve<ConsiderationsManager>();
return new[]
{
considerationsManager.Get<HungerCon>().PresetCurve(context, PresetCurve.Nutrition)
};
}
public override IEnumerable<UtilityAction> GetActions(Blackboard context)
{
var owner = context.GetState<SelfState>().GetValue();

View File

@@ -0,0 +1,25 @@
using Content.Server.GameObjects.EntitySystems;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Map;
#nullable enable
namespace Content.Server.Atmos
{
public static class AtmosHelpers
{
public static TileAtmosphere? GetTileAtmosphere(this GridCoordinates coordinates)
{
var gridAtmos = EntitySystem.Get<AtmosphereSystem>().GetGridAtmosphere(coordinates.GridID);
return gridAtmos?.GetTile(coordinates);
}
public static TileAtmosphere? GetTileAtmosphere(this MapIndices indices, GridId gridId)
{
var gridAtmos = EntitySystem.Get<AtmosphereSystem>().GetGridAtmosphere(gridId);
return gridAtmos?.GetTile(indices);
}
}
}

View File

@@ -1,15 +1,17 @@
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
namespace Content.Server.GameObjects.Components.Access
{
public sealed class AccessReaderChangeMessage : EntitySystemMessage
{
public EntityUid Uid { get; }
public IEntity Sender { get; }
public bool Enabled { get; }
public AccessReaderChangeMessage(EntityUid uid, bool enabled)
public AccessReaderChangeMessage(IEntity entity, bool enabled)
{
Uid = uid;
Sender = entity;
Enabled = enabled;
}
}

View File

@@ -356,6 +356,10 @@ namespace Content.Server.GameObjects.Components.Disposal
appearance.SetData(Visuals.Light, LightState.Off);
return;
}
else if (_pressure < 1)
{
appearance.SetData(Visuals.VisualState, VisualState.Charging);
}
else
{
appearance.SetData(Visuals.VisualState, VisualState.Anchored);

View File

@@ -188,7 +188,7 @@ namespace Content.Server.GameObjects
SetAppearance(DoorVisualState.Open);
}, _cancellationTokenSource.Token);
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new AccessReaderChangeMessage(Owner.Uid, false));
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new AccessReaderChangeMessage(Owner, false));
}
public virtual bool CanClose()
@@ -284,7 +284,7 @@ namespace Content.Server.GameObjects
State = DoorState.Closed;
SetAppearance(DoorVisualState.Closed);
}, _cancellationTokenSource.Token);
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new AccessReaderChangeMessage(Owner.Uid, true));
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new AccessReaderChangeMessage(Owner, true));
return true;
}

View File

@@ -1,6 +1,8 @@
#nullable enable
using System;
using Content.Server.Atmos;
using Content.Server.GameObjects.Components.Chemistry;
using Content.Server.GameObjects.EntitySystems;
using Content.Server.GameObjects.EntitySystems.Click;
using Content.Server.Interfaces.GameObjects.Components.Interaction;
using Content.Server.Interfaces;
@@ -19,6 +21,7 @@ using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
using Robust.Shared.Serialization;
using Content.Shared.GameObjects.EntitySystems;
using Robust.Shared.GameObjects.Systems;
namespace Content.Server.GameObjects.Components.Interactable
{
@@ -179,6 +182,10 @@ namespace Content.Server.GameObjects.Components.Interactable
PlaySoundCollection("WelderOn", -5);
_welderSystem.Subscribe(this);
Owner.Transform.GridPosition
.GetTileAtmosphere()?.HotspotExpose(700f, 50f, true);
return true;
}

View File

@@ -50,9 +50,6 @@ namespace Content.Server.GameObjects.Components.Items
var desiredTile = _tileDefinitionManager[_outputTile];
mapGrid.SetTile(eventArgs.ClickLocation, new Tile(desiredTile.TileId));
EntitySystem.Get<AudioSystem>().PlayAtCoords("/Audio/Items/genhit.ogg", eventArgs.ClickLocation);
if(_stack.Count < 1){
Owner.Delete();
}
}

View File

@@ -28,15 +28,7 @@ namespace Content.Server.GameObjects.Components.Stack
public override int Count
{
get => base.Count;
set
{
base.Count = value;
if (Count <= 0)
{
Owner.Delete();
}
}
set => base.Count = value;
}
[ViewVariables(VVAccess.ReadWrite)]

View File

@@ -159,10 +159,10 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
public override void OnAdd()
{
base.OnAdd();
var rangedWeapon = Owner.GetComponent<ServerRangedWeaponComponent>();
rangedWeapon.Barrel = this;
rangedWeapon.FireHandler += Fire;
rangedWeapon.WeaponCanFireHandler += WeaponCanFire;
var rangedWeaponComponent = Owner.GetComponent<ServerRangedWeaponComponent>();
rangedWeaponComponent.Barrel = this;
rangedWeaponComponent.FireHandler += Fire;
rangedWeaponComponent.WeaponCanFireHandler += WeaponCanFire;
}
public override void OnRemove()
@@ -208,7 +208,12 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
return true;
}
private void Fire(IEntity shooter, GridCoordinates target)
/// <summary>
/// Fires a round of ammo out of the weapon.
/// </summary>
/// <param name="shooter">Entity that is operating the weapon, usually the player.</param>
/// <param name="targetPos">Target position on the map to shoot at.</param>
private void Fire(IEntity shooter, Vector2 targetPos)
{
var soundSystem = EntitySystem.Get<AudioSystem>();
if (ShotsLeft == 0)
@@ -229,8 +234,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
}
// At this point firing is confirmed
var worldPosition = IoCManager.Resolve<IMapManager>().GetGrid(target.GridID).LocalToWorld(target).Position;
var direction = (worldPosition - shooter.Transform.WorldPosition).ToAngle();
var direction = (targetPos - shooter.Transform.WorldPosition).ToAngle();
var angle = GetRecoilAngle(direction);
// This should really be client-side but for now we'll just leave it here
if (shooter.TryGetComponent(out CameraRecoilComponent recoilComponent))

View File

@@ -1,4 +1,4 @@
using System;
using System;
using Content.Server.GameObjects.Components.GUI;
using Content.Server.GameObjects.Components.Mobs;
using Content.Server.GameObjects.Components.Weapon.Ranged.Barrels;
@@ -12,6 +12,7 @@ using Robust.Shared.Audio;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.Interfaces.Network;
using Robust.Shared.Interfaces.Random;
using Robust.Shared.Interfaces.Timing;
@@ -19,6 +20,7 @@ using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Log;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Players;
using Robust.Shared.Random;
using Robust.Shared.Serialization;
@@ -38,7 +40,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged
public Func<bool> WeaponCanFireHandler;
public Func<IEntity, bool> UserCanFireHandler;
public Action<IEntity, GridCoordinates> FireHandler;
public Action<IEntity, Vector2> FireHandler;
public ServerRangedBarrelComponent Barrel
{
@@ -77,6 +79,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged
serializer.DataField(this, p => p.ClumsyExplodeChance, "clumsyExplodeChance", 0.5f);
}
/// <inheritdoc />
public override void HandleNetworkMessage(ComponentMessage message, INetChannel channel, ICommonSession session = null)
{
base.HandleNetworkMessage(message, channel, session);
@@ -95,7 +98,24 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged
return;
}
_tryFire(user, msg.Target);
if (msg.TargetGrid != GridId.Invalid)
{
// grid pos
if (!IoCManager.Resolve<IMapManager>().TryGetGrid(msg.TargetGrid, out var grid))
{
// Client sent us a message with an invalid grid.
break;
}
var targetPos = grid.LocalToWorld(msg.TargetPosition);
TryFire(user, targetPos);
}
else
{
// map pos
TryFire(user, msg.TargetPosition);
}
break;
}
}
@@ -105,7 +125,12 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged
return new RangedWeaponComponentState(FireRateSelector);
}
private void _tryFire(IEntity user, GridCoordinates coordinates)
/// <summary>
/// Tries to fire a round of ammo out of the weapon.
/// </summary>
/// <param name="user">Entity that is operating the weapon, usually the player.</param>
/// <param name="targetPos">Target position on the map to shoot at.</param>
private void TryFire(IEntity user, Vector2 targetPos)
{
if (!user.TryGetComponent(out HandsComponent hands) || hands.GetActiveHand?.Owner != Owner)
{
@@ -158,7 +183,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged
return;
}
FireHandler?.Invoke(user, coordinates);
FireHandler?.Invoke(user, targetPos);
}
// Probably a better way to do this.

View File

@@ -79,6 +79,11 @@ namespace Content.Server.GameObjects.EntitySystems.AI.LoadBalancer
switch (action)
{
case ExpandableUtilityAction expandableUtilityAction:
if (!expandableUtilityAction.IsValid(_request.Context))
{
break;
}
foreach (var expanded in expandableUtilityAction.GetActions(_request.Context))
{
actions.Push(expanded);
@@ -86,7 +91,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.LoadBalancer
break;
case UtilityAction utilityAction:
consideredTaskCount++;
var bonus = (float) utilityAction.Bonus;
var bonus = utilityAction.Bonus;
if (bonus < cutoff)
{

View File

@@ -25,17 +25,17 @@ namespace Content.Server.GameObjects.EntitySystems.Pathfinding
/// Whenever there's a change in the collision layers we update the mask as the graph has more reads than writes
/// </summary>
public int BlockedCollisionMask { get; private set; }
private readonly Dictionary<EntityUid, int> _blockedCollidables = new Dictionary<EntityUid, int>(0);
private readonly Dictionary<IEntity, int> _blockedCollidables = new Dictionary<IEntity, int>(0);
public IReadOnlyDictionary<EntityUid, int> PhysicsLayers => _physicsLayers;
private readonly Dictionary<EntityUid, int> _physicsLayers = new Dictionary<EntityUid, int>(0);
public IReadOnlyDictionary<IEntity, int> PhysicsLayers => _physicsLayers;
private readonly Dictionary<IEntity, int> _physicsLayers = new Dictionary<IEntity, int>(0);
/// <summary>
/// The entities on this tile that require access to traverse
/// </summary>
/// We don't store the ICollection, at least for now, as we'd need to replicate the access code here
public IReadOnlyCollection<AccessReader> AccessReaders => _accessReaders.Values;
private readonly Dictionary<EntityUid, AccessReader> _accessReaders = new Dictionary<EntityUid, AccessReader>(0);
private readonly Dictionary<IEntity, AccessReader> _accessReaders = new Dictionary<IEntity, AccessReader>(0);
public PathfindingNode(PathfindingChunk parent, TileRef tileRef)
{
@@ -44,6 +44,17 @@ namespace Content.Server.GameObjects.EntitySystems.Pathfinding
GenerateMask();
}
public static bool IsRelevant(IEntity entity, ICollidableComponent collidableComponent)
{
if (entity.Transform.GridID == GridId.Invalid ||
(PathfindingSystem.TrackedCollisionLayers & collidableComponent.CollisionLayer) == 0)
{
return false;
}
return true;
}
/// <summary>
/// Return our neighboring nodes (even across chunks)
/// </summary>
@@ -249,7 +260,7 @@ namespace Content.Server.GameObjects.EntitySystems.Pathfinding
/// <param name="entity"></param>
/// TODO: These 2 methods currently don't account for a bunch of changes (e.g. airlock unpowered, wrenching, etc.)
/// TODO: Could probably optimise this slightly more.
public void AddEntity(IEntity entity)
public void AddEntity(IEntity entity, ICollidableComponent collidableComponent)
{
// If we're a door
if (entity.HasComponent<AirlockComponent>() || entity.HasComponent<ServerDoorComponent>())
@@ -258,27 +269,25 @@ namespace Content.Server.GameObjects.EntitySystems.Pathfinding
// TODO: Check for powered I think (also need an event for when it's depowered
// AccessReader calls this whenever opening / closing but it can seem to get called multiple times
// Which may or may not be intended?
if (entity.TryGetComponent(out AccessReader accessReader) && !_accessReaders.ContainsKey(entity.Uid))
if (entity.TryGetComponent(out AccessReader accessReader) && !_accessReaders.ContainsKey(entity))
{
_accessReaders.Add(entity.Uid, accessReader);
_accessReaders.Add(entity, accessReader);
ParentChunk.Dirty();
}
return;
}
if (entity.TryGetComponent(out ICollidableComponent collidableComponent) &&
(PathfindingSystem.TrackedCollisionLayers & collidableComponent.CollisionLayer) != 0)
DebugTools.Assert((PathfindingSystem.TrackedCollisionLayers & collidableComponent.CollisionLayer) != 0);
if (!collidableComponent.Anchored)
{
if (entity.TryGetComponent(out IPhysicsComponent physicsComponent) && !physicsComponent.Anchored)
{
_physicsLayers.Add(entity.Uid, collidableComponent.CollisionLayer);
}
else
{
_blockedCollidables.TryAdd(entity.Uid, collidableComponent.CollisionLayer);
GenerateMask();
ParentChunk.Dirty();
}
_physicsLayers.Add(entity, collidableComponent.CollisionLayer);
}
else
{
_blockedCollidables.Add(entity, collidableComponent.CollisionLayer);
GenerateMask();
ParentChunk.Dirty();
}
}
@@ -292,18 +301,18 @@ namespace Content.Server.GameObjects.EntitySystems.Pathfinding
// There's no guarantee that the entity isn't deleted
// 90% of updates are probably entities moving around
// Entity can't be under multiple categories so just checking each once is fine.
if (_physicsLayers.ContainsKey(entity.Uid))
if (_physicsLayers.ContainsKey(entity))
{
_physicsLayers.Remove(entity.Uid);
_physicsLayers.Remove(entity);
}
else if (_accessReaders.ContainsKey(entity.Uid))
else if (_accessReaders.ContainsKey(entity))
{
_accessReaders.Remove(entity.Uid);
_accessReaders.Remove(entity);
ParentChunk.Dirty();
}
else if (_blockedCollidables.ContainsKey(entity.Uid))
else if (_blockedCollidables.ContainsKey(entity))
{
_blockedCollidables.Remove(entity.Uid);
_blockedCollidables.Remove(entity);
GenerateMask();
ParentChunk.Dirty();
}

View File

@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using Content.Server.GameObjects.Components.Access;
using Content.Server.GameObjects.Components.GUI;
using Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Pathfinders;
using Content.Server.GameObjects.EntitySystems.JobQueues;
using Content.Server.GameObjects.EntitySystems.JobQueues.Queues;
@@ -20,9 +22,10 @@ using Robust.Shared.Utility;
namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding
{
/*
// TODO: IMO use rectangular symmetry reduction on the nodes with collision at all., or
// TODO: IMO use rectangular symmetry reduction on the nodes with collision at all. (currently planned to be implemented via AiReachableSystem and expanded later).
alternatively store all rooms and have an alternative graph for humanoid mobs (same collision mask, needs access etc). You could also just path from room to room as needed.
// TODO: Longer term -> Handle collision layer changes?
TODO: Handle container entities so they're not tracked.
*/
/// <summary>
/// This system handles pathfinding graph updates as well as dispatches to the pathfinder
@@ -30,10 +33,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding
/// </summary>
public class PathfindingSystem : EntitySystem
{
#pragma warning disable 649
[Dependency] private readonly IEntityManager _entitymanager;
[Dependency] private readonly IMapManager _mapManager;
#pragma warning restore 649
[Dependency] private readonly IMapManager _mapManager = default!;
public IReadOnlyDictionary<GridId, Dictionary<MapIndices, PathfindingChunk>> Graph => _graph;
private readonly Dictionary<GridId, Dictionary<MapIndices, PathfindingChunk>> _graph = new Dictionary<GridId, Dictionary<MapIndices, PathfindingChunk>>();
@@ -47,7 +47,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding
private readonly Queue<TileRef> _tileUpdateQueue = new Queue<TileRef>();
// Need to store previously known entity positions for collidables for when they move
private readonly Dictionary<EntityUid, PathfindingNode> _lastKnownPositions = new Dictionary<EntityUid, PathfindingNode>();
private readonly Dictionary<IEntity, PathfindingNode> _lastKnownPositions = new Dictionary<IEntity, PathfindingNode>();
public const int TrackedCollisionLayers = (int)
(CollisionGroup.Impassable |
@@ -86,7 +86,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding
foreach (var update in _collidableUpdateQueue)
{
var entity = _entitymanager.GetEntity(update.Owner);
var entity = EntityManager.GetEntity(update.Owner);
if (update.CanCollide)
{
HandleEntityAdd(entity);
@@ -103,14 +103,13 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding
foreach (var update in _accessReaderUpdateQueue)
{
var entity = _entitymanager.GetEntity(update.Uid);
if (update.Enabled)
{
HandleEntityAdd(entity);
HandleEntityAdd(update.Sender);
}
else
{
HandleEntityRemove(entity);
HandleEntityRemove(update.Sender);
}
totalUpdates++;
@@ -138,7 +137,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding
for (var i = 0; i < moveUpdateCount; i++)
{
HandleCollidableMove(_moveUpdateQueue.Dequeue());
HandleEntityMove(_moveUpdateQueue.Dequeue());
}
DebugTools.Assert(_moveUpdateQueue.Count < 1000);
@@ -204,9 +203,6 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding
public override void Initialize()
{
// TODO: Remove this once the memory leaks are solved.
return;
SubscribeLocalEvent<CollisionChangeMessage>(QueueCollisionChangeMessage);
SubscribeLocalEvent<MoveEvent>(QueueMoveEvent);
SubscribeLocalEvent<AccessReaderChangeMessage>(QueueAccessChangeMessage);
@@ -279,7 +275,10 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding
/// <param name="entity"></param>
private void HandleEntityAdd(IEntity entity)
{
if (entity.Deleted || _lastKnownPositions.ContainsKey(entity.Uid))
if (entity.Deleted ||
_lastKnownPositions.ContainsKey(entity) ||
!entity.TryGetComponent(out ICollidableComponent collidableComponent) ||
!PathfindingNode.IsRelevant(entity, collidableComponent))
{
return;
}
@@ -289,19 +288,19 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding
var chunk = GetChunk(tileRef);
var node = chunk.GetNode(tileRef);
node.AddEntity(entity);
_lastKnownPositions.Add(entity.Uid, node);
node.AddEntity(entity, collidableComponent);
_lastKnownPositions.Add(entity, node);
}
private void HandleEntityRemove(IEntity entity)
{
if (!_lastKnownPositions.TryGetValue(entity.Uid, out var node))
if (!_lastKnownPositions.TryGetValue(entity, out var node))
{
return;
}
node.RemoveEntity(entity);
_lastKnownPositions.Remove(entity.Uid);
_lastKnownPositions.Remove(entity);
}
private void QueueMoveEvent(MoveEvent moveEvent)
@@ -313,35 +312,47 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Pathfinding
/// When an entity moves around we'll remove it from its old node and add it to its new node (if applicable)
/// </summary>
/// <param name="moveEvent"></param>
private void HandleCollidableMove(MoveEvent moveEvent)
private void HandleEntityMove(MoveEvent moveEvent)
{
var entityUid = moveEvent.Sender.Uid;
if (!_lastKnownPositions.TryGetValue(entityUid, out var oldNode))
// If we've moved to space or the likes then remove us.
if (moveEvent.Sender.Deleted ||
!moveEvent.Sender.TryGetComponent(out ICollidableComponent collidableComponent) ||
!PathfindingNode.IsRelevant(moveEvent.Sender, collidableComponent))
{
HandleEntityRemove(moveEvent.Sender);
return;
}
// Memory leak protection until grid parenting confirmed fix / you REALLY need the performance
var gridBounds = _mapManager.GetGrid(moveEvent.Sender.Transform.GridID).WorldBounds;
if (!gridBounds.Contains(moveEvent.Sender.Transform.WorldPosition))
{
HandleEntityRemove(moveEvent.Sender);
return;
}
// If we move from space to a grid we may need to start tracking it.
if (!_lastKnownPositions.TryGetValue(moveEvent.Sender, out var oldNode))
{
HandleEntityAdd(moveEvent.Sender);
return;
}
// The pathfinding graph is tile-based so first we'll check if they're on a different tile and if we need to update.
// If you get entities bigger than 1 tile wide you'll need some other system so god help you.
if (moveEvent.Sender.Deleted)
{
HandleEntityRemove(moveEvent.Sender);
return;
}
var newTile = _mapManager.GetGrid(moveEvent.NewPosition.GridID).GetTileRef(moveEvent.NewPosition);
if (oldNode == null || oldNode.TileRef == newTile)
{
return;
}
var newNode = GetNode(newTile);
_lastKnownPositions[entityUid] = newNode;
_lastKnownPositions[moveEvent.Sender] = newNode;
oldNode.RemoveEntity(moveEvent.Sender);
newNode.AddEntity(moveEvent.Sender);
newNode.AddEntity(moveEvent.Sender, collidableComponent);
}
private void QueueCollisionChangeMessage(CollisionChangeMessage collisionMessage)

View File

@@ -320,7 +320,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Steering
return SteeringStatus.Pending;
}
var ignoredCollision = new List<EntityUid>();
var ignoredCollision = new List<IEntity>();
// Check if the target entity has moved - If so then re-path
// TODO: Patch the path from the target's position back towards us, stopping if it ever intersects the current path
// Probably need a separate "PatchPath" job
@@ -339,7 +339,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Steering
RequestPath(entity, steeringRequest);
}
ignoredCollision.Add(entitySteer.Target.Uid);
ignoredCollision.Add(entitySteer.Target);
}
HandleStuck(entity);
@@ -597,7 +597,7 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Steering
/// <param name="direction">entity's travel direction</param>
/// <param name="ignoredTargets"></param>
/// <returns></returns>
private Vector2 CollisionAvoidance(IEntity entity, Vector2 direction, ICollection<EntityUid> ignoredTargets)
private Vector2 CollisionAvoidance(IEntity entity, Vector2 direction, ICollection<IEntity> ignoredTargets)
{
if (direction == Vector2.Zero || !entity.TryGetComponent(out ICollidableComponent collidableComponent))
{
@@ -627,26 +627,25 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Steering
{
var node = _pathfindingSystem.GetNode(tile);
// Assume the immovables have already been checked
foreach (var (uid, layer) in node.PhysicsLayers)
foreach (var (physicsEntity, layer) in node.PhysicsLayers)
{
// Ignore myself / my target if applicable / if my mask doesn't collide
if (uid == entity.Uid || ignoredTargets.Contains(uid) || (entityCollisionMask & layer) == 0) continue;
if (physicsEntity == entity || ignoredTargets.Contains(physicsEntity) || (entityCollisionMask & layer) == 0) continue;
// God there's so many ways to do this
// err for now we'll just assume the first entity is the center and just add a vector for it
var collisionEntity = _entityManager.GetEntity(uid);
//Pathfinding updates are deferred so this may not be done yet.
if (collisionEntity.Deleted) continue;
if (physicsEntity.Deleted) continue;
// if we're moving in the same direction then ignore
// So if 2 entities are moving towards each other and both detect a collision they'll both move in the same direction
// i.e. towards the right
if (collisionEntity.TryGetComponent(out IPhysicsComponent physicsComponent) &&
if (physicsEntity.TryGetComponent(out IPhysicsComponent physicsComponent) &&
Vector2.Dot(physicsComponent.LinearVelocity, direction) > 0)
{
continue;
}
var centerGrid = collisionEntity.Transform.GridPosition;
var centerGrid = physicsEntity.Transform.GridPosition;
// Check how close we are to center of tile and get the inverse; if we're closer this is stronger
var additionalVector = (centerGrid.Position - entityGridCoords.Position);
var distance = additionalVector.Length;

View File

@@ -5,7 +5,5 @@ namespace Content.Server.Interfaces
public interface IGasMixtureHolder
{
public GasMixture Air { get; set; }
bool AssumeAir(GasMixture giver);
}
}

View File

@@ -22,7 +22,8 @@ namespace Content.Shared.GameObjects.Components.Disposal
{
UnAnchored,
Anchored,
Flushing
Flushing,
Charging
}
[Serializable, NetSerializable]

View File

@@ -1,4 +1,5 @@
using System;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.Reflection;
using Robust.Shared.IoC;
@@ -26,6 +27,10 @@ namespace Content.Shared.GameObjects.Components
_count = value;
if (_count <= 0)
{
if (ContainerHelpers.TryGetContainerMan(Owner, out var containerManager))
{
containerManager.Remove(Owner);
}
Owner.Delete();
}

View File

@@ -1,6 +1,7 @@
using System;
using System;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Serialization;
namespace Content.Shared.GameObjects.Components.Weapons.Ranged
@@ -26,14 +27,33 @@ namespace Content.Shared.GameObjects.Components.Weapons.Ranged
}
}
/// <summary>
/// A component message raised when the weapon is fired at a position on the map.
/// </summary>
[Serializable, NetSerializable]
public sealed class FirePosComponentMessage : ComponentMessage
{
public GridCoordinates Target { get; }
/// <summary>
/// If this is not invalid, the target position is relative to the grid.
/// Otherwise, it is a map position.
/// </summary>
public GridId TargetGrid { get; }
public FirePosComponentMessage(GridCoordinates target)
/// <summary>
/// If Target Grid is not invalid, this is relative to the grid, otherwise
/// it is a map position.
/// </summary>
public Vector2 TargetPosition { get; }
/// <summary>
/// Constructs a new instance of <see cref="FirePosComponentMessage"/>.
/// </summary>
/// <param name="targetGrid">The grid that the target position is on, if any.</param>
/// <param name="targetPosition">Target position relative to the grid, or a map position if the grid is invalid.</param>
public FirePosComponentMessage(GridId targetGrid, Vector2 targetPosition)
{
Target = target;
TargetGrid = targetGrid;
TargetPosition = targetPosition;
}
}
}

View File

@@ -17,7 +17,6 @@
- !type:PhysShapeAabb
layer:
- SmallImpassable
- MobImpassable
- type: SnapGrid
offset: Center
- type: IconSmooth

View File

@@ -118,6 +118,7 @@
- type: DisposalUnitVisualizer
state_unanchored: condisposal
state_anchored: disposal
state_charging: disposal-charging
overlay_charging: dispover-charge
overlay_ready: dispover-ready
overlay_full: dispover-full

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 B

View File

@@ -1 +1 @@
{"version": 1, "size": {"x": 32, "y": 32}, "license": "CC-BY-SA-3.0", "copyright": "https://github.com/discordia-space/CEV-Eris/blob/bbe32606902c90f5290b57d905a3f31b84dc6d7d/icons/obj/pipes/disposal.dmi and modified by DrSmugleaf", "states": [{"name": "condisposal", "directions": 1, "delays": [[1.0]]}, {"name": "conpipe-c", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-j1", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-j1s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-j2", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-j2s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-t", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-y", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "disposal", "directions": 1, "delays": [[1.0]]}, {"name": "disposal-flush", "directions": 1, "delays": [[0.1, 0.1, 0.1, 0.1, 0.1, 0.5, 0.1, 0.1, 0.1]]}, {"name": "dispover-charge", "directions": 1, "delays": [[0.4, 0.4]]}, {"name": "dispover-full", "directions": 1, "delays": [[0.2, 0.2]]}, {"name": "dispover-handle", "directions": 1, "delays": [[1.0]]}, {"name": "dispover-ready", "directions": 1, "delays": [[1.0]]}, {"name": "intake", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "intake-closing", "directions": 4, "delays": [[0.5, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1], [0.5, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1], [0.5, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1], [0.5, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]]}, {"name": "outlet", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "outlet-open", "directions": 4, "delays": [[0.5, 0.5, 0.5, 0.5, 0.5, 0.1, 1.5, 0.1], [0.5, 0.5, 0.5, 0.5, 0.5, 0.1, 1.5, 0.1], [0.5, 0.5, 0.5, 0.5, 0.5, 0.1, 1.5, 0.1], [0.5, 0.5, 0.5, 0.5, 0.5, 0.1, 1.5, 0.1]]}, {"name": "pipe-b", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-bf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-c", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-cf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-d", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j1", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j1f", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j1s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j1sf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j2", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j2f", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j2s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j2sf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-sf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-t", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-tagger", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-tagger-partial", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-tf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-u", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-y", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-yf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}]}
{"version": 1, "size": {"x": 32, "y": 32}, "license": "CC-BY-SA-3.0", "copyright": "https://github.com/discordia-space/CEV-Eris/blob/bbe32606902c90f5290b57d905a3f31b84dc6d7d/icons/obj/pipes/disposal.dmi and modified by DrSmugleaf", "states": [{"name": "condisposal", "directions": 1, "delays": [[1.0]]}, {"name": "conpipe-c", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-j1", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-j1s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-j2", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-j2s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-t", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "conpipe-y", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "disposal", "directions": 1, "delays": [[1.0]]}, {"name": "disposal-charging", "directions": 1, "delays": [[1.0]]}, {"name": "disposal-flush", "directions": 1, "delays": [[0.1, 0.1, 0.1, 0.1, 0.1, 0.5, 0.1, 0.1, 0.1]]}, {"name": "dispover-charge", "directions": 1, "delays": [[0.4, 0.4]]}, {"name": "dispover-full", "directions": 1, "delays": [[0.2, 0.2]]}, {"name": "dispover-handle", "directions": 1, "delays": [[1.0]]}, {"name": "dispover-ready", "directions": 1, "delays": [[1.0]]}, {"name": "intake", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "intake-closing", "directions": 4, "delays": [[0.5, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1], [0.5, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1], [0.5, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1], [0.5, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]]}, {"name": "outlet", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "outlet-open", "directions": 4, "delays": [[0.5, 0.5, 0.5, 0.5, 0.5, 0.1, 1.5, 0.1], [0.5, 0.5, 0.5, 0.5, 0.5, 0.1, 1.5, 0.1], [0.5, 0.5, 0.5, 0.5, 0.5, 0.1, 1.5, 0.1], [0.5, 0.5, 0.5, 0.5, 0.5, 0.1, 1.5, 0.1]]}, {"name": "pipe-b", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-bf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-c", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-cf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-d", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j1", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j1f", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j1s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j1sf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j2", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j2f", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j2s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-j2sf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-s", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-sf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-t", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-tagger", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-tagger-partial", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-tf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-u", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-y", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "pipe-yf", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}]}