959e80cf72
assets upload description.
308 lines
8.9 KiB
C#
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;
|
|
}
|
|
}
|
|
} |