Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c8829d2

Browse files
authored
Defib Harm Interaction + Better interaction clarity (unitystation#11115)
* NRE fix for paddle spring behavior * Communicate to the player why the defib is not working. * defib harm interaction * Update GUI_DevDestroyer.cs
1 parent b2481b5 commit c8829d2

4 files changed

Lines changed: 165 additions & 22 deletions

File tree

UnityProject/Assets/Scripts/US13/Items/AddBackToStorageOnDropOrThrow.cs

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
namespace US13.Items
88
{
99
/// <summary>
10-
/// Component that houses functionality for the OnDrop and OnThrow events too hook onto via the unity inspector,
10+
/// Component that houses functionality for the OnDrop and OnThrow events to hook onto via the unity inspector,
1111
/// or dynamically. Does not do anything on its own and requires the OnDropOrThrow function to be subscribed to an event.
1212
/// Re-adds this item back to an item storage when dropped, mainly used for things like the Defib Paddles.
1313
/// </summary>
@@ -18,24 +18,42 @@ public class AddBackToStorageOnDropOrThrow : MonoBehaviour, IServerInventoryMove
1818

1919
private void Start()
2020
{
21-
if (storage == null) storage = gameObject.PickupableOrNull().ItemSlot.ItemStorage;
21+
if (storage == null) Setup();
22+
}
23+
24+
private void Setup()
25+
{
26+
var itemSlot = gameObject.PickupableOrNull()?.ItemSlot;
27+
if (itemSlot == null)
28+
{
29+
Loggy.Error($"No ItemSlot defined on {gameObject.name} for AddBackToStorageOnDropOrThrow");
30+
return;
31+
}
32+
storage = itemSlot.ItemStorage;
33+
if (storage == null)
34+
{
35+
Loggy.Error($"No ItemStorage defined on {gameObject.name} for AddBackToStorageOnDropOrThrow.");
36+
}
2237
}
2338

2439
void IServerInventoryMove.OnInventoryMoveServer(InventoryMove info)
2540
{
26-
//TODO forever loop?!?!
27-
if (storage == null) return;
28-
if (info?.MovedObject.OrNull()?.gameObject == this.gameObject && info?.ToSlot?.ItemStorage != storage)
41+
if (storage == null)
2942
{
30-
if ((info?.ToSlot?.NamedSlot is NamedSlot.leftHand or NamedSlot.rightHand) == false)
31-
{
32-
if (storage.ServerTryAdd(gameObject))
33-
{
34-
Chat.AddActionMsgToChat(gameObject, OnAddBackMessage);
35-
return;
36-
}
43+
Setup();
44+
return;
45+
}
3746

38-
Loggy.Error($"[{gameObject.name}/AddBackToStorageOnDropOrThrow] - Something went wrong while trying to re-add this item back to their item storage.");
47+
if (info?.MovedObject.OrNull()?.gameObject != this.gameObject || info?.ToSlot?.ItemStorage == storage) return;
48+
if (info?.ToSlot?.NamedSlot is not (NamedSlot.leftHand or NamedSlot.rightHand))
49+
{
50+
if (storage.ServerTryAdd(gameObject))
51+
{
52+
Chat.AddActionMsgToChat(gameObject, OnAddBackMessage);
53+
}
54+
else
55+
{
56+
Loggy.Error($"Something went wrong while trying to re-add this item back to their item storage on {gameObject.name}.\n {InventoryMove.ToString(info)}");
3957
}
4058
}
4159
}

UnityProject/Assets/Scripts/US13/Items/Medical/DefibrillatorPaddles.cs

Lines changed: 125 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,32 @@
11
using System.Collections;
2+
using System.Collections.Generic;
3+
using System.Text;
24
using UnityEngine;
35
using US13.Core.Addressables.Types;
46
using US13.Core.Chat;
57
using US13.Core.Input_System.InteractionV2;
68
using US13.Core.Input_System.InteractionV2.Interactions;
79
using US13.Core.Input_System.InteractionV2.Interfaces;
10+
using US13.Core.Physics;
11+
using US13.Health.Objects;
12+
using US13.HealthV2;
813
using US13.HealthV2.Living;
914
using US13.Items.Traits;
1015
using US13.Managers;
1116
using US13.Messages.Server.SoundMessages;
1217
using US13.Mobs.Equipment;
18+
using US13.Player.MovementV2;
19+
using US13.Systems.Explosions;
1320
using US13.Systems.Inventory;
1421
using US13.UI.Core.ProgressBar;
22+
using US13.UI.Systems.MainHUD.UI_Bottom;
23+
using US13.UI.Systems.Tooltips.HoverTooltips;
1524
using Util;
25+
using Util.Independent.FluentRichText;
1626

1727
namespace US13.Items.Medical
1828
{
19-
public class DefibrillatorPaddles : MonoBehaviour, ICheckedInteractable<HandApply>, IInteractable<HandActivate>
29+
public class DefibrillatorPaddles : MonoBehaviour, ICheckedInteractable<HandApply>, IInteractable<HandActivate>, IHoverTooltip, IExaminable
2030
{
2131
public ItemTrait DefibrillatorTrait;
2232

@@ -34,29 +44,31 @@ public class DefibrillatorPaddles : MonoBehaviour, ICheckedInteractable<HandAppl
3444
private bool onCooldown;
3545
private readonly float cooldown = 5;
3646

47+
private const float PUSHBACK_FORCE = 5550f;
48+
private const float SPIN_FACTOR = 10f;
49+
private const float INAIR_TIME = 0.1f;
50+
private const float DAMAGE_AMOUNT = 25f;
51+
3752
public bool WillInteract(HandApply interaction, NetworkSide side)
3853
{
39-
if (DefaultWillInteract.Default(interaction, side) == false)
40-
return false;
41-
var livingHealthMaster = interaction.TargetObject.GetComponent<LivingHealthMasterBase>();
42-
if (livingHealthMaster == null)
43-
return false;
54+
if (DefaultWillInteract.Default(interaction, side) == false) return false;
55+
if (interaction.Intent == Intent.Harm) return true;
56+
if (interaction.TargetObject.TryGetComponent<LivingHealthMasterBase>(out var livingHealthMaster) is false) return false;
4457
if (side == NetworkSide.Server && DoesntRequireBackpack == false)
4558
{
46-
4759
var equipment = interaction.Performer.GetComponent<Equipment>();
4860
var ObjectInSlot = equipment.GetClothingItem(NamedSlot.back).ServerGameObjectReference;
4961
if (Validations.HasItemTrait(ObjectInSlot, DefibrillatorTrait) == false)
5062
{
5163
ObjectInSlot = equipment.GetClothingItem(NamedSlot.belt).ServerGameObjectReference;
5264
if (Validations.HasItemTrait(ObjectInSlot, DefibrillatorTrait) == false)
5365
{
66+
Chat.AddExamineMsg(interaction.Performer, "You need to place the defibrillator unit on your back or belt to use the paddles!".Color(Color.yellow));
5467
return false;
5568
}
5669
}
5770
}
5871

59-
6072
if (CanDefibrillate(livingHealthMaster, interaction.Performer) == false && side == NetworkSide.Server)
6173
{
6274
return false;
@@ -81,6 +93,11 @@ private bool CanDefibrillate(LivingHealthMasterBase livingHealthMaster, GameObje
8193

8294
public void ServerPerformInteraction(HandApply interaction)
8395
{
96+
if (interaction.Intent == Intent.Harm)
97+
{
98+
HarmInteraction(interaction);
99+
return;
100+
}
84101
void Perform()
85102
{
86103
var livingHealthMaster = interaction.TargetObject.GetComponent<LivingHealthMasterBase>();
@@ -145,5 +162,105 @@ public void ServerPerformInteraction(HandActivate interaction)
145162
Chat.AddExamineMsg(interaction.Performer,
146163
$"<color=green>The {gameObject.ExpensiveName()} is charged and ready to be used.</color>");
147164
}
165+
166+
private void HarmInteraction(HandApply interaction)
167+
{
168+
if (interaction.Intent != Intent.Harm) return;
169+
if (onCooldown)
170+
{
171+
Chat.AddExamineMsg(interaction.Performer, $"The {gameObject.ExpensiveName()} is still charging!".Color(RichTextColor.Yellow));
172+
return;
173+
}
174+
if (isReady is false)
175+
{
176+
Chat.AddExamineMsg(interaction.Performer, $"You need to prepare the {gameObject.ExpensiveName()} first!".Color(RichTextColor.Yellow));
177+
return;
178+
}
179+
if (interaction.TargetObject.TryGetComponent<LivingHealthMasterBase>(out var livingHealthMaster) == false) return;
180+
if (interaction.Performer.TryGetComponent<UniversalObjectPhysics>(out var interactor) == false) return;
181+
var targetPos = livingHealthMaster.playerScript.AssumedWorldPos;
182+
var interactorPos = interaction.PerformerPlayerScript.AssumedWorldPos;
183+
var pushVector = (interactorPos - targetPos).To2();
184+
185+
SparkUtil.TrySpark(interaction.Performer);
186+
interactor.NewtonianNewtonPush( pushVector, PUSHBACK_FORCE, inAirTime: INAIR_TIME, spinFactor: SPIN_FACTOR );
187+
188+
//push perpetrator and victim away from each other
189+
livingHealthMaster.ApplyDamageToBodyPart(interaction.PerformerPlayerScript.gameObject, DAMAGE_AMOUNT,
190+
AttackType.Energy, DamageType.Burn, interaction.TargetBodyPart);
191+
livingHealthMaster.playerScript.playerMove.NewtonianNewtonPush(-pushVector, PUSHBACK_FORCE, inAirTime: INAIR_TIME, spinFactor: SPIN_FACTOR);
192+
193+
HandlePullingActorsDuringHarmInteraction(livingHealthMaster, pushVector, interactor);
194+
StartCoroutine(Cooldown());
195+
Chat.AddAttackMsgToChat(interactor.gameObject, livingHealthMaster.gameObject, interaction.TargetBodyPart, gameObject, "shocked");
196+
}
197+
198+
private void HandlePullingActorsDuringHarmInteraction(LivingHealthMasterBase victim, Vector2 pushVector, UniversalObjectPhysics perp)
199+
{
200+
if (victim.playerScript.playerMove.PulledBy.HasComponent == false) return;
201+
victim.playerScript.playerMove.PulledBy.Component.NewtonianNewtonPush(-pushVector, PUSHBACK_FORCE, inAirTime: INAIR_TIME, spinFactor: SPIN_FACTOR);
202+
if (victim.playerScript.playerMove.PulledBy.Component is MovementSynchronisation sync && sync == perp)
203+
{
204+
sync.playerScript.playerHealth.ApplyDamageToBodyPart(sync.gameObject, DAMAGE_AMOUNT,
205+
AttackType.Energy, DamageType.Burn);
206+
}
207+
}
208+
209+
public string HoverTip()
210+
{
211+
return Examine();
212+
}
213+
214+
public string CustomTitle()
215+
{
216+
return null;
217+
}
218+
219+
public Sprite CustomIcon()
220+
{
221+
return null;
222+
}
223+
224+
public List<Sprite> IconIndicators()
225+
{
226+
return null;
227+
}
228+
229+
public List<TextColor> InteractionsStrings()
230+
{
231+
return new List<TextColor>()
232+
{
233+
new TextColor()
234+
{
235+
Text = "Hand-Activate to prepare the paddles.".Color(Color.green),
236+
Color = Color.green
237+
},
238+
new TextColor()
239+
{
240+
Text = "Apply on a person to attempt to revive them while charged.".Color(Color.green),
241+
Color = Color.green
242+
},
243+
new TextColor()
244+
{
245+
Text = "Attack while charged to shock your victim.".Color(Color.red),
246+
Color = Color.red
247+
}
248+
};
249+
}
250+
251+
public string Examine(Vector3 worldPos = default)
252+
{
253+
var SB = new StringBuilder();
254+
if (DoesntRequireBackpack)
255+
{
256+
SB.AppendLine("It doesn't require its unit to be placed on your back or belt to be used.".Color(Color.yellow));
257+
}
258+
else
259+
{
260+
SB.AppendLine("It requires the unit to be equipped on your back or belt to be used.".Color(Color.yellow));
261+
}
262+
263+
return SB.ToString();
264+
}
148265
}
149266
}

UnityProject/Assets/Scripts/US13/Systems/Inventory/InventoryMoveType.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Text;
12
using Logs;
23
using UnityEngine;
34
using US13.HealthV2;
@@ -194,6 +195,13 @@ public static InventoryMove Throw(ItemSlot fromSlot, Vector2 worldTargetVector,
194195
{
195196
return new InventoryMove(InventoryMoveType.Remove, fromSlot.Item, fromSlot, null, InventoryRemoveType.Throw, aim, worldTargetVector);
196197
}
198+
199+
public static string ToString(InventoryMove move)
200+
{
201+
StringBuilder sb = new StringBuilder();
202+
sb.AppendFormat("InventoryMove of type {0} for object {1} from slot {2} to slot {3}. ", move.InventoryMoveType, move.MovedObject, move.FromSlot, move.ToSlot);
203+
return sb.ToString();
204+
}
197205
}
198206

199207
/// <summary>

UnityProject/Assets/Scripts/US13/UI/Systems/AdminTools/DevTools/GUI_DevDestroyer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ private void UpdateMe()
5151
var hits = MouseUtils.GetOrderedObjectsUnderMouse(layerMask,
5252
go => go.GetComponent<UniversalObjectPhysics>() != null, useMappedItems : DevCameraControls.Instance.MappingItemState).ToArray();
5353
if (hits.Any() == false) return;
54-
var target = hits.First().GetComponentInParent<UniversalObjectPhysics>().gameObject;
54+
var target = hits.First().GetComponentInParent<UniversalObjectPhysics>()?.gameObject;
5555
if (target == null) return;
5656
if (CustomNetworkManager.IsServer)
5757
{

0 commit comments

Comments
 (0)