11using System . Collections ;
2+ using System . Collections . Generic ;
3+ using System . Text ;
24using UnityEngine ;
35using US13 . Core . Addressables . Types ;
46using US13 . Core . Chat ;
57using US13 . Core . Input_System . InteractionV2 ;
68using US13 . Core . Input_System . InteractionV2 . Interactions ;
79using US13 . Core . Input_System . InteractionV2 . Interfaces ;
10+ using US13 . Core . Physics ;
11+ using US13 . Health . Objects ;
12+ using US13 . HealthV2 ;
813using US13 . HealthV2 . Living ;
914using US13 . Items . Traits ;
1015using US13 . Managers ;
1116using US13 . Messages . Server . SoundMessages ;
1217using US13 . Mobs . Equipment ;
18+ using US13 . Player . MovementV2 ;
19+ using US13 . Systems . Explosions ;
1320using US13 . Systems . Inventory ;
1421using US13 . UI . Core . ProgressBar ;
22+ using US13 . UI . Systems . MainHUD . UI_Bottom ;
23+ using US13 . UI . Systems . Tooltips . HoverTooltips ;
1524using Util ;
25+ using Util . Independent . FluentRichText ;
1626
1727namespace 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}
0 commit comments