Firstborn/Assets/RPG Creation Kit/Scripts/Combat System/Player/Scripts/WeaponOnHand.cs
Schaken-Mods 959e80cf72 assets upload
assets upload description.
2023-03-28 12:16:30 -05:00

308 lines
8.9 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using RPGCreationKit;
namespace RPGCreationKit
{
public class WeaponOnHand : MonoBehaviour
{
// The entity who's holding the weapon
public AudioSource audioSource;
public Entity thisEntity;
[SerializeField] private BodyData GFX;
[SerializeField] private GameObject Prefab;
public IMeleeAttacker thisAttacker;
public LayerMask targetLayerMask;
// For debug
[SerializeField] bool debugWeapon = true;
List<Vector3> spheres = new List<Vector3>();
// Settings
public int MAX_COLLISIONS_DETECTABLE = 10;
int numColliders = 0;
public Collider[] results;
[Space(10)]
public WeaponItem weaponItem;
bool casting = false;
bool hasHit = false;
public int numOfHits = 0;
public Transform[] hitMarks;
Vector3 lastPos;
public float tickness = .1f;
List<IHittable> hitInThisSwing = new List<IHittable>();
List<IDamageable> damageableHitInThisSwing = new List<IDamageable>();
List<EntityAttributes> entitiesHitInThisSwing = new List<EntityAttributes>();
private void Start()
{
results = new Collider[MAX_COLLISIONS_DETECTABLE];
// Attempt to take an entity
if(thisEntity == null)
thisEntity = GetComponentInParent<Entity>();
// Take the IMeleeAttacker
if (thisAttacker == null)
thisAttacker = GetComponentInParent<IMeleeAttacker>();
}
public void StartCasting(bool _charged, int _index)
{
charged = _charged;
index = _index;
spheres.Clear();
hitInThisSwing.Clear();
damageableHitInThisSwing.Clear();
entitiesHitInThisSwing.Clear();
numOfHits = 0;
hasHit = false;
casting = true;
}
public void StopCasting()
{
casting = false;
hasHit = true;
}
public void PlayOneShot(AudioClip _clip)
{
if(audioSource.enabled && _clip != null)
audioSource.PlayOneShot(_clip);
}
float damageAmount;
bool charged;
int index;
void FixedUpdate()
{
if (casting)
{
damageAmount = (charged) ? weaponItem.weaponChargedAttacks[index].BaseDamage : weaponItem.weaponAttacks[index].BaseDamage;
// For every hitmark
for (int i = 0; i < hitMarks.Length; i++)
{
if (debugWeapon)
spheres.Add(hitMarks[i].position); // FOR DEBUG
numColliders = Physics.OverlapSphereNonAlloc(hitMarks[i].position, tickness, results, targetLayerMask);
// Used to have priority on Blocks on the same entity
List<string> entitiesThatBlocked = new List<string>();
// Collect all the blocking zone
for(int j = 0; j < numColliders; j++)
{
if (results[j].transform.CompareTag("RPG Creation Kit/BlockingZone"))
{
IDamageable damageable = results[j].transform.GetComponentInParent<IDamageable>();
entitiesThatBlocked.Add(damageable.GetEntityID());
}
}
// For every collision detected on that hitmark
for (int j = 0; j < numColliders; j++)
{
Entity entity = results[j].transform.GetComponent<Entity>();
if (entity == null)
entity = results[j].transform.GetComponentInParent<Entity>();
IHittable hittable = results[j].transform.GetComponent<IHittable>();
IDamageable damageable = results[j].transform.GetComponentInParent<IDamageable>();
// Check if we hit ourself, if we did, ignore (for AI)
if (RCKTransform.IsChildOfRecursive(this.transform.parent, results[j].transform))
continue;
// Check if we hit ourself, if we did, ignore (for Player)
if (this.transform.root.CompareTag("Player") && results[j].transform.parent != null && results[j].transform.parent.CompareTag("Player"))
continue;
if (results[j].transform.CompareTag("RPG Creation Kit/IgnoreWeapons"))
continue;
if (results[j].transform.CompareTag("RPG Creation Kit/AI"))
continue;
if (results[j].transform.CompareTag("RPG Creation Kit/Terrain"))
continue;
if(entity != null && thisEntity != null)
if (entity.GetGuid() == thisEntity.GetGuid())
continue;
if (hittable != null && !hitInThisSwing.Contains(hittable))
{
// Check if we hit a blocking area
if(results[j].transform.CompareTag("RPG Creation Kit/BlockingZone") && hittable != null)
{
DamageContext context = new DamageContext(damageAmount, thisEntity, weaponItem, null, true);
hittable.Hit(thisEntity.gameObject.transform.forward, RCKSettings.MELEE_ONBODY_RIGIDBODY_FORCE, context);
// If an attack is blocked we immediatily stop everything
i = hitMarks.Length+1;
j = numColliders+1;
StopCasting();
if (thisAttacker != null)
thisAttacker.OnAttackIsBlocked();
else
Debug.Log("ATTACKER NULL!!!");
break;
}
// Check for BodyParts, with a single swing we can hit multiple bodyparts but we don't want to be able to hit the same enemy more than once.
if (results[j].transform.CompareTag("RPG Creation Kit/BodyPart"))
{
BodyPart bodyPart = results[j].GetComponent<BodyPart>();
if (!entitiesHitInThisSwing.Contains(bodyPart.entity))
{
// Check if this collision was from an entity that blocked the attack, but for some reasons the block was detected after
if (damageable != null && entitiesThatBlocked.Contains(damageable.GetEntityID()))
continue;
entitiesHitInThisSwing.Add(bodyPart.entity);
// Check for damageable, body part should always be damageable
if (damageable != null && !damageableHitInThisSwing.Contains(damageable))
{
damageableHitInThisSwing.Add(damageable);
LocationalDamage locDamage = bodyPart.GetComponentInParent<LocationalDamage>();
if (locDamage != null)
damageAmount = locDamage.CalculateLocationalDamage(bodyPart, damageAmount);
DamageContext context = new DamageContext(damageAmount, thisEntity, weaponItem, null, false);
damageable.Damage(context);
if(damageable.Bleeds())
damageable.InstantiateBlood(hitMarks[i].position);
}
hittable.Hit(thisEntity.gameObject.transform.forward, RCKSettings.MELEE_ONBODY_RIGIDBODY_FORCE);
hittable.GenerateDecal();
}
else continue; // We've hit the same enemy two times, skip this
}
else // simple hit against an hittable
{
hitInThisSwing.Add(hittable);
// Check for damageable
if (damageable != null && !damageableHitInThisSwing.Contains(damageable))
{
damageableHitInThisSwing.Add(damageable);
DamageContext context = new DamageContext(damageAmount, thisEntity, weaponItem, null, false);
damageable.Damage(context);
if (damageable.Bleeds())
damageable.InstantiateBlood(hitMarks[i].position);
}
hittable.Hit(thisEntity.gameObject.transform.forward, RCKSettings.MELEE_GENERAL_RIGIDBODY_FORCE);
hittable.GenerateDecal();
}
numOfHits++; // increments hits
// Check if the swing is over because it hit all it could
if (numOfHits > (charged ? weaponItem.weaponChargedAttacks[index].howManyHitsCanSustain : weaponItem.weaponAttacks[index].howManyHitsCanSustain))
{
hasHit = true;
StopCasting();
break;
}
}
}
// Stop the for every hit mark if we're not casting anymore
if (!casting)
break;
}
}
}
/// <summary>
/// For debug
/// </summary>
private void OnDrawGizmos()
{
if (hitMarks == null || !debugWeapon)
return;
Gizmos.color = Color.cyan;
for (int i = 0; i < hitMarks.Length; i++)
if (hitMarks[i] != null)
Gizmos.DrawSphere(hitMarks[i].position, tickness);
for (int i = 0; i < spheres.Count; i++)
{
Gizmos.color = Color.red;
Gizmos.DrawSphere(spheres[i], tickness);
}
}
[ContextMenu("Grab Hitmarks")]
public void GrabHitmarks()
{
GameObject hand;
tickness = 0.4f;
Transform[] objs = Resources.FindObjectsOfTypeAll<Transform>() as Transform[];
for (int i = 0; i < objs.Length; i++){
if (objs[i].name == "Hitmark Template") {
Prefab = objs[i].gameObject;
}
}
// GameObject GFXGO = GameObject.Find("GFX");
// BodyData GFXBD = GFXGO.GetComponent<BodyData>();
// GFX = GFXBD;
for (int j = 0; j < hitMarks.Length; j++) {
if (hitMarks[j] != null) {
DestroyImmediate(hitMarks[j].gameObject);
}
}
for (int i = 0; i < 30; i++) {
if (GameObject.Find("Hitmark Template(Clone)") != null) {
hand = GameObject.Find("Hitmark Template(Clone)");
DestroyImmediate(hand.gameObject);
}
}
hitMarks = new Transform[5];
GameObject A;
A = Instantiate(Prefab, GFX.lFoot);
hitMarks[0] = A.transform;
A = Instantiate(Prefab, GFX.rHand);
hitMarks[1] = A.transform;
A = Instantiate(Prefab, GFX.lHand);
hitMarks[2] = A.transform;
A = Instantiate(Prefab, GFX.rFoot);
hitMarks[3] = A.transform;
A = Instantiate(Prefab, GFX.Head);
hitMarks[4] = A.transform;
}
}
}