Skip to content

Commit 6f2403d

Browse files
authored
Activate ragdoll after death (#1412)
All good, will just need to fix the item/body collision I'm opening an issue for that
1 parent d4658dc commit 6f2403d

File tree

5 files changed

+69
-62
lines changed

5 files changed

+69
-62
lines changed

Assets/Scripts/SS3D/Systems/Entities/Human.cs

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ public class Human : Entity
1818
public GameObject Ghost;
1919
private GameObject _spawnedGhost;
2020

21-
22-
/// <summary>
21+
/// <summary>
2322
/// On death, the player should become a ghost.
2423
/// </summary>
2524
[Server]
@@ -32,18 +31,20 @@ private void BecomeGhost(GameObject player, GameObject ghost)
3231
mindSystem.SwapMinds(originEntity, ghostEntity);
3332

3433
RpcUpdateGhostPosition(originEntity, ghostEntity);
35-
RpcDestroyObjects(originEntity);
36-
37-
}
38-
34+
if (TryGetComponent(out Ragdoll ragdoll))
35+
{
36+
ragdoll.KnockdownTimeless();
37+
}
38+
RpcDestroyComponents(originEntity);
39+
}
3940

4041
/// <summary>
41-
/// This method should probably be called turn in corpse, and instead of destroying components it should deactivate them.
42-
/// Should also trigger the ragdoll.
42+
/// Destroys all "human" components, such as Hands and HumanoidController. Also activates ragdoll
4343
/// </summary>
4444
[ObserversRpc(RunLocally = true)]
45-
private void RpcDestroyObjects(Entity originEntity)
45+
private void RpcDestroyComponents(Entity originEntity)
4646
{
47+
// Instead of destroying components it should deactivate them.
4748
GameObject originEntityGameObject = originEntity.gameObject;
4849
originEntityGameObject.GetComponent<Hands>()?.Dispose(true);
4950
originEntityGameObject.GetComponent<HumanInventory>()?.Dispose(true);
@@ -54,25 +55,23 @@ private void RpcDestroyObjects(Entity originEntity)
5455
// TODO: Optimize these GetComponents, this is a temporary solution.
5556
}
5657

57-
/// <summary>
58+
/// <summary>
5859
/// Put Ghost at the same place as the deceased player.
5960
/// </summary>
6061
[ObserversRpc(RunLocally = true)]
6162
private void RpcUpdateGhostPosition(Entity originEntity, Entity ghostEntity)
6263
{
6364
ghostEntity.Transform.SetPositionAndRotation(originEntity.Transform.position, originEntity.Transform.rotation);
64-
// Little rotation to have the ghost starting on the floor. Can be improved.
65-
originEntity.Transform.Rotate(new Vector3(90, 0, 0));
66-
}
65+
}
6766

6867
/// <summary>
6968
/// Kill a player, instantiating a ghost.
7069
/// </summary>
7170
[Server]
7271
public override void Kill()
7372
{
74-
_spawnedGhost = Instantiate(Ghost);
75-
var entitySystem = Subsystems.Get<EntitySystem>();
73+
_spawnedGhost = Instantiate(Ghost);
74+
EntitySystem entitySystem = Subsystems.Get<EntitySystem>();
7675
if(entitySystem.TryTransferEntity(GetComponentInParent<Entity>(), _spawnedGhost.GetComponent<Entity>()))
7776
{
7877
ServerManager.Spawn(_spawnedGhost);
@@ -86,7 +85,7 @@ public override void Kill()
8685

8786
public override void DeactivateComponents()
8887
{
89-
RpcDestroyObjects(this);
88+
RpcDestroyComponents(this);
9089
}
9190
}
9291
}

Assets/Scripts/SS3D/Systems/Entities/Humanoid/Ragdoll.cs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -137,13 +137,15 @@ private void Update()
137137
}
138138

139139
private void WalkingBehavior() { }
140+
140141
/// <summary>
141142
/// Cast knockdown, that isn't going to expire until Recover()
142143
/// </summary>
143144
[ServerRpc(RequireOwnership = false)]
144145
public void KnockdownTimeless()
145146
{
146147
if (!enabled) return;
148+
147149
_isKnockdownTimed = false;
148150
IsKnockedDown = true;
149151
}
@@ -159,14 +161,16 @@ public void Knockdown(float seconds)
159161
_knockdownTimer += seconds;
160162
IsKnockedDown = true;
161163
}
164+
162165
private void Knockdown()
163166
{
164167
_currentState = RagdollState.Ragdoll;
165168
Vector3 movement = _humanoidLivingController.TargetMovement * 3;
166169
ToggleController(false);
167170
ToggleAnimator(false);
171+
if (!IsOwner && Owner.ClientId != -1)
172+
return;
168173

169-
if (!IsOwner) return;
170174
ToggleKinematic(false);
171175
foreach (Transform part in _ragdollParts)
172176
{
@@ -331,16 +335,29 @@ private void ToggleKinematic(bool isKinematic)
331335
}
332336
private void ToggleController(bool enable)
333337
{
334-
_humanoidLivingController.enabled = enable;
335-
_characterController.enabled = enable;
338+
if (_humanoidLivingController != null)
339+
{
340+
_humanoidLivingController.enabled = enable;
341+
}
342+
if (_characterController != null)
343+
{
344+
_characterController.enabled = enable;
345+
}
336346
}
337347
private void ToggleAnimator(bool enable)
338348
{
339349
// Speed=0 prevents animator from choosing Walking animations after enabling it
340350
if (!enable)
341351
_animator.SetFloat("Speed", 0);
342-
_animator.enabled = enable;
343-
_networkAnimator.enabled = enable;
352+
353+
if (_animator != null)
354+
{
355+
_animator.enabled = enable;
356+
}
357+
if (_networkAnimator != null)
358+
{
359+
_networkAnimator.enabled = enable;
360+
}
344361
}
345362
}
346363
}

Assets/Scripts/SS3D/Systems/Health/BodyParts/Bodypart.cs

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,12 @@ public abstract class BodyPart : InteractionTargetNetworkBehaviour
4848
/// List of body layers composing a body part.
4949
/// </summary>
5050
protected readonly List<BodyLayer> _bodyLayers = new List<BodyLayer>();
51+
52+
private BodyPart _externalBodyPart;
53+
public BodyPart ExternalBodyPart => _externalBodyPart;
54+
public bool IsInsideBodyPart => _externalBodyPart != null;
5155

52-
53-
private BodyPart _externalBodyPart;
54-
55-
public BodyPart ExternalBodyPart => _externalBodyPart;
56-
57-
public bool IsInsideBodyPart => _externalBodyPart != null;
56+
protected virtual bool IsDetachable => true;
5857

5958
/// <summary>
6059
/// A container containing all internal body parts. The head has a brain for an internal body part. Internal body parts should be destroyed
@@ -69,7 +68,6 @@ public abstract class BodyPart : InteractionTargetNetworkBehaviour
6968
protected Collider _bodyCollider;
7069

7170
public Collider BodyCollider => _bodyCollider;
72-
7371
public string Name => gameObject.name;
7472

7573
/// <summary>
@@ -78,20 +76,15 @@ public abstract class BodyPart : InteractionTargetNetworkBehaviour
7876
private bool _isDetached;
7977

8078
protected BodyPart _spawnedCopy;
81-
82-
public HealthController HealthController;
83-
79+
public HealthController HealthController;
8480
public ReadOnlyCollection<BodyLayer> BodyLayers
8581
{
8682
get { return _bodyLayers.AsReadOnly(); }
8783
}
88-
89-
9084
public ReadOnlyCollection<BodyPart> ChildBodyParts
9185
{
9286
get { return _childBodyParts.AsReadOnly(); }
9387
}
94-
9588
public List<BodyPart> InternalBodyParts
9689
{
9790
get
@@ -107,7 +100,6 @@ public List<BodyPart> InternalBodyParts
107100
return bodyParts;
108101
}
109102
}
110-
111103
public bool HasInternalBodyPart => _internalBodyParts != null && _internalBodyParts.Items.Count() != 0;
112104

113105
/// <summary>
@@ -129,7 +121,6 @@ public List<BodyPart> InternalBodyParts
129121

130122
public float TotalDamage => _bodyLayers.Sum(layer => layer.TotalDamage);
131123
public float MaxDamage => 0.5f*_bodyLayers.Sum(layer => layer.MaxDamage);
132-
133124
public float RelativeDamage => TotalDamage/ MaxDamage;
134125

135126
public event EventHandler OnDamageInflicted;
@@ -247,9 +238,9 @@ protected virtual void CopyValuesToBodyPart(BodyPart bodyPart)
247238
{
248239
foreach(BodyLayer layer in bodyPart.BodyLayers)
249240
{
250-
BodyLayer layerToWrite = BodyLayers.Where(x => x.LayerType == layer.LayerType).First();
251-
if (layerToWrite == null) continue;
252-
layer.CopyLayerValues(layerToWrite);
241+
IEnumerable<BodyLayer> layerToWrite = BodyLayers.Where(x => x.LayerType == layer.LayerType);
242+
if (!layerToWrite.Any()) continue;
243+
layer.CopyLayerValues(layerToWrite.First());
253244
}
254245
}
255246

@@ -262,9 +253,8 @@ protected virtual void CopyValuesToBodyPart(BodyPart bodyPart)
262253
private void DestroyBodyPart()
263254
{
264255
BeforeDestroyingBodyPart();
265-
266256
DetachChildBodyParts();
267-
257+
268258
// Destroy all internal body parts i
269259
if (_internalBodyParts != null){
270260

@@ -275,7 +265,7 @@ private void DestroyBodyPart()
275265
}
276266
_internalBodyParts.Purge();
277267
}
278-
268+
279269
// Dispose of this body part
280270
InvokeOnBodyPartDestroyed();
281271
Dispose(true);
@@ -404,7 +394,7 @@ public virtual void AddChildBodyPart(BodyPart bodyPart)
404394
}
405395

406396
/// <summary>
407-
/// Inflic damages of a certain kind on a certain body layer type if the layer is present.
397+
/// Inflict damages of a certain kind on a certain body layer type if the layer is present.
408398
/// </summary>
409399
/// <returns>True if the damage could be inflicted</returns>
410400
[Server]
@@ -415,18 +405,23 @@ public bool TryInflictDamage(BodyLayerType type, DamageTypeQuantity damageTypeQu
415405

416406
BodyLayer layer = FirstBodyLayerOfType(type);
417407
if (!BodyLayers.Contains(layer)) return false;
408+
InflictDamage(layer, damageTypeQuantity);
409+
410+
OnDamageInflicted?.Invoke(this, EventArgs.Empty);
411+
return true;
412+
}
413+
414+
private void InflictDamage(BodyLayer layer, DamageTypeQuantity damageTypeQuantity)
415+
{
418416
layer.InflictDamage(damageTypeQuantity);
419417
if (IsDestroyed)
420418
{
421419
DestroyBodyPart();
422420
}
423-
else if (IsSevered && !_isDetached)
421+
else if (IsDetachable && IsSevered && !_isDetached)
424422
{
425423
DetachBodyPart();
426424
}
427-
428-
OnDamageInflicted?.Invoke(this, EventArgs.Empty);
429-
return true;
430425
}
431426

432427
/// <summary>
@@ -450,7 +445,9 @@ public void InflictDamageToAllLayerButOne<T>(DamageTypeQuantity damageTypeQuanti
450445
foreach (BodyLayer layer in BodyLayers)
451446
{
452447
if (!(layer is T))
453-
TryInflictDamage(layer.LayerType, damageTypeQuantity);
448+
{
449+
TryInflictDamage(layer.LayerType, damageTypeQuantity);
450+
}
454451
}
455452
}
456453

@@ -576,7 +573,6 @@ protected void InvokeOnBodyPartLayerAdded()
576573
OnBodyPartLayerAdded?.Invoke(this, EventArgs.Empty);
577574
}
578575

579-
580576
/// <summary>
581577
/// Add the body layers in their initial states on the player.
582578
/// </summary>

Assets/Scripts/SS3D/Systems/Health/BodyParts/HeadBodyPart.cs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using SS3D.Core;
33
using SS3D.Data.Generated;
44
using SS3D.Systems.Entities;
5+
using SS3D.Systems.Entities.Humanoid;
56
using System.Collections;
67
using UnityEngine;
78
using UnityEngine.Serialization;
@@ -16,11 +17,6 @@ public class HeadBodyPart : BodyPart
1617
[FormerlySerializedAs("brain")]
1718
public Brain Brain;
1819

19-
public override void Init(BodyPart parent)
20-
{
21-
base.Init(parent);
22-
}
23-
2420
public override void OnStartServer()
2521
{
2622
base.OnStartServer();
@@ -58,15 +54,15 @@ protected void DeactivateWholeBody()
5854

5955
protected override void AfterSpawningCopiedBodyPart()
6056
{
61-
57+
GetComponentInParent<Ragdoll>().KnockdownTimeless();
6258
GetComponentInParent<Human>()?.DeactivateComponents();
6359

6460
// When detached, spawn a head and set player's mind to be in the head,
6561
// so that player can still play as a head (death is near though..).
6662
MindSystem mindSystem = Subsystems.Get<MindSystem>();
6763

68-
var EntityControllingHead = GetComponentInParent<Entity>();
69-
if (EntityControllingHead.Mind != null)
64+
Entity entityControllingHead = GetComponentInParent<Entity>();
65+
if (entityControllingHead.Mind != null)
7066
{
7167
mindSystem.SwapMinds(GetComponentInParent<Entity>(), _spawnedCopy.GetComponent<Entity>());
7268
_spawnedCopy.GetComponent<NetworkObject>().RemoveOwnership();
@@ -86,9 +82,7 @@ protected override void SpawnOrgans()
8682
GameObject brainPrefab = Items.HumanBrain;
8783
GameObject brainGameObject = Instantiate(brainPrefab);
8884
Brain = brainGameObject.GetComponent<Brain>();
89-
9085
Brain.HealthController = HealthController;
91-
9286
Spawn(brainGameObject, Owner);
9387
}
9488
}

Assets/Scripts/SS3D/Systems/Health/BodyParts/HumanTorso.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1-
using SS3D.Data;
2-
using SS3D.Data.Generated;
1+
using SS3D.Data.Generated;
2+
using SS3D.Systems.Entities;
33
using SS3D.Systems.Health;
44
using System.Collections;
55
using UnityEngine;
6-
using UnityEngine.Serialization;
76

87
public class HumanTorso : BodyPart
98
{
109
public Heart Heart;
1110
public Lungs LeftLung;
1211
public Lungs RightLung;
1312

13+
protected override bool IsDetachable => false;
14+
1415
public override void OnStartServer()
1516
{
1617
base.OnStartServer();

0 commit comments

Comments
 (0)