2020-06-20 14:16:11 +00:00
|
|
|
|
using System.Linq;
|
|
|
|
|
using SanAndreasUnity.Utilities;
|
2020-06-09 16:34:15 +00:00
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
|
|
namespace SanAndreasUnity.Behaviours.Vehicles
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
public partial class Vehicle
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
public Damageable Damageable { get; private set; }
|
|
|
|
|
|
2020-06-09 17:45:25 +00:00
|
|
|
|
public float Health { get; set; } = 1000;
|
2020-06-09 16:34:15 +00:00
|
|
|
|
|
|
|
|
|
public float MaxHealth { get; set; } = 1000;
|
|
|
|
|
|
|
|
|
|
public bool IsUnderFlame { get; private set; } = false;
|
|
|
|
|
public bool IsUnderSmoke { get; private set; } = false;
|
|
|
|
|
|
2020-06-09 17:45:25 +00:00
|
|
|
|
bool m_alreadyExploded = false;
|
|
|
|
|
|
2020-06-09 16:34:15 +00:00
|
|
|
|
public float TimeWhenBecameUnderFlame { get; private set; } = float.NegativeInfinity;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Awake_Damage()
|
|
|
|
|
{
|
2020-06-09 17:45:25 +00:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SetupDamagable()
|
|
|
|
|
{
|
|
|
|
|
this.Damageable = this.HighDetailMeshesParent.gameObject.AddComponent<Damageable>();
|
2020-06-09 16:34:15 +00:00
|
|
|
|
this.Damageable.OnDamageEvent.AddListener(() => this.OnDamaged());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OnDamaged()
|
|
|
|
|
{
|
|
|
|
|
var damageInfo = this.Damageable.LastDamageInfo;
|
|
|
|
|
|
|
|
|
|
if (this.Health <= 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
this.Health -= damageInfo.amount;
|
|
|
|
|
|
|
|
|
|
if (this.Health <= 0)
|
|
|
|
|
{
|
|
|
|
|
this.Explode();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Update_Damage()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
bool shouldBeUnderSmoke = this.MaxHealth * 0.33f >= this.Health;
|
|
|
|
|
if (shouldBeUnderSmoke != this.IsUnderSmoke)
|
|
|
|
|
{
|
|
|
|
|
// smoke status changed
|
|
|
|
|
this.IsUnderSmoke = shouldBeUnderSmoke;
|
|
|
|
|
// update vfx
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool shouldBeUnderFlame = this.MaxHealth * 0.1f >= this.Health;
|
|
|
|
|
if (shouldBeUnderFlame != this.IsUnderFlame)
|
|
|
|
|
{
|
|
|
|
|
// flame status changed
|
|
|
|
|
this.IsUnderFlame = shouldBeUnderFlame;
|
|
|
|
|
if (this.IsUnderFlame)
|
|
|
|
|
this.TimeWhenBecameUnderFlame = Time.time;
|
|
|
|
|
// update vfx
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this.IsUnderFlame && Time.time - this.TimeWhenBecameUnderFlame >= 5)
|
|
|
|
|
{
|
|
|
|
|
// enough time passed since vehicle flamed - explode it
|
|
|
|
|
this.Explode();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Explode()
|
|
|
|
|
{
|
2020-06-09 17:45:25 +00:00
|
|
|
|
if (m_alreadyExploded)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
m_alreadyExploded = true;
|
|
|
|
|
|
2020-06-20 15:56:17 +00:00
|
|
|
|
// destroy this game object before doing anything else
|
2020-06-09 17:45:25 +00:00
|
|
|
|
|
|
|
|
|
Object.Destroy(this.gameObject);
|
2020-06-09 16:34:15 +00:00
|
|
|
|
|
2020-06-20 14:16:11 +00:00
|
|
|
|
// detach the following parts:
|
|
|
|
|
// - doors
|
|
|
|
|
// - wheels
|
|
|
|
|
// - bonnet
|
|
|
|
|
// - boot
|
|
|
|
|
// - windscreen
|
|
|
|
|
// - exhaust
|
|
|
|
|
|
|
|
|
|
string[] startingNames = new string[] { "door_", "wheel_", "bonnet_", "boot_", "windscreen_", "exhaust_" };
|
|
|
|
|
Vector3 explosionCenter = this.transform.position;
|
|
|
|
|
float explosionForce = Mathf.Sqrt(this.HandlingData.Mass) * VehicleManager.Instance.explosionForceMultiplier;
|
|
|
|
|
float explosionRadius = 10f;
|
|
|
|
|
|
|
|
|
|
foreach (var frame in _frames)
|
|
|
|
|
{
|
|
|
|
|
if (!frame.gameObject.activeInHierarchy)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (!startingNames.Any(n => frame.gameObject.name.StartsWith(n)))
|
|
|
|
|
continue;
|
|
|
|
|
|
2020-06-20 15:56:17 +00:00
|
|
|
|
DetachFrameDuringExplosion(frame, explosionCenter, explosionForce, explosionRadius);
|
|
|
|
|
}
|
2020-06-20 14:16:11 +00:00
|
|
|
|
|
2020-06-20 15:56:17 +00:00
|
|
|
|
// chassis need to be handled after all other objects are detached, because chassis can sometimes
|
|
|
|
|
// have other objects as children
|
2020-06-20 14:16:11 +00:00
|
|
|
|
|
2020-06-20 15:56:17 +00:00
|
|
|
|
Frame chassisFrame = _frames.FirstOrDefault(f => f.Name == "chassis");
|
2020-06-20 14:16:11 +00:00
|
|
|
|
|
2020-06-20 15:56:17 +00:00
|
|
|
|
if (null == chassisFrame)
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError($"Chassis object not found on vehicle {this.DescriptionForLogging}");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DetachFrameDuringExplosion(chassisFrame, explosionCenter, explosionForce, explosionRadius);
|
|
|
|
|
}
|
2020-06-20 14:16:11 +00:00
|
|
|
|
|
|
|
|
|
// create explosion effect
|
|
|
|
|
|
|
|
|
|
|
2020-06-09 16:34:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-06-20 15:56:17 +00:00
|
|
|
|
void DetachFrameDuringExplosion(Frame frame, Vector3 explosionCenter, float explosionForce, float explosionRadius)
|
|
|
|
|
{
|
|
|
|
|
var meshFilter = frame.GetComponentInChildren<MeshFilter>();
|
|
|
|
|
if (null == meshFilter)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (!meshFilter.gameObject.activeInHierarchy)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
meshFilter.transform.SetParent(null, true);
|
|
|
|
|
meshFilter.gameObject.name = "vehicle_part_" + meshFilter.gameObject.name;
|
|
|
|
|
meshFilter.gameObject.layer = UnityEngine.LayerMask.NameToLayer("Default");
|
|
|
|
|
var meshCollider = meshFilter.gameObject.GetOrAddComponent<MeshCollider>();
|
|
|
|
|
meshCollider.convex = true;
|
|
|
|
|
meshCollider.sharedMesh = meshFilter.sharedMesh;
|
|
|
|
|
var rigidBody = meshFilter.gameObject.GetOrAddComponent<Rigidbody>();
|
|
|
|
|
rigidBody.mass = VehicleManager.Instance.explosionLeftoverPartsMass;
|
|
|
|
|
rigidBody.drag = 0.05f;
|
|
|
|
|
rigidBody.maxDepenetrationVelocity = VehicleManager.Instance.explosionLeftoverPartsMaxDepenetrationVelocity;
|
|
|
|
|
rigidBody.AddExplosionForce(explosionForce, explosionCenter, explosionRadius);
|
|
|
|
|
|
|
|
|
|
Object.Destroy(meshFilter.gameObject, VehicleManager.Instance.explosionLeftoverPartsLifetime);
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-09 16:34:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|