/// <summary> /// Handles taking damage from another entity; use nDirect true to directly damage health or false to obey restrictions /// </summary> public override bool TakeDmg(LiveEntity damageEnt, int nType, int nDmg, bool nDirect) { bool wasDamaged = base.TakeDmg(damageEnt, nType, nDmg, nDirect); if (wasDamaged) { PlaySound(SndT.HURT); if (damageEnt != null) { GameObject damageObj = damageEnt.transform.root.gameObject; if (TargetObj == null) { SetTargetObj(damageObj, damageEnt); } else { if (damageObj != TargetObj) { if (Util.IsCloser(this.transform.position, damageObj.transform.position, TargetPos)) { SetTargetObj(damageObj, damageEnt); } } } } } return(wasDamaged); }
/// <summary> /// Handles taking damage from another entity; use nDirect true to directly damage health or false to obey restrictions /// </summary> public virtual bool TakeDmg(LiveEntity src, int nType, int nDmg, bool nDirect) { // Handle damageEnt specific code like changing targets on damage in derived classes DmgType dmgType = (DmgType)nType; if (dmgType == DmgType.STAMINA) { return(Stats.ReduceStamina(nDmg)); } else if (dmgType == DmgType.ARMOR) { return(Stats.ReduceArmor(nDmg)); } int modDmg = nDmg; // modDmg will change if armor takes any of the hit, leaving less to hit health bool armorCheck; if (!nDirect) { if (Stats.Armor > 0) { int armorLast = Stats.Armor; armorCheck = Stats.ReduceArmor((int)(modDmg * ARMOR_ABSORB)); if (armorCheck) { modDmg = modDmg - (armorLast - Stats.Armor); } } } return(Stats.ReduceHealth(modDmg)); }
/// <summary> /// Performs a SphereCast for the initial population of the TrackDict /// </summary> protected virtual void InitTrackDict() { Collider[] localEnts = Physics.OverlapSphere(this.transform.position, Params.AwareMax, EntMask); if (localEnts != null && localEnts.Length > 0) { foreach (Collider col in localEnts) { GameObject obj = col.transform.root.gameObject; LiveEntity ent = obj.GetComponent <LiveEntity>(); if (ent == null) { Debug.LogWarning($"{this.gameObject.name} couldn't find a LiveEntity script for a detected object ({obj.name}), can't add to TrackDict"); continue; } // Check if we found ourselves if (ent.UniqueId == UniqueId) { continue; } // Ignore if the entity is dead or invisible if (ent.Stats.IsDead || ent.Stats.Invisible) { continue; } TrackEntity(ent); } } }
///-------------------------------------------------------------------- /// Sound Event methods ///-------------------------------------------------------------------- public SoundEvent(LiveEntity src, Vector3 pos, float rad, SoundIntensity val = SoundIntensity.NORMAL) { _source = src; _origin = pos; _radius = rad; _intensity = val; }
protected virtual void OnTriggerEnter(Collider col) { GameObject obj = col.transform.root.gameObject; // Bitshift 1 left by obj.layer ( for 1 * 2^obj.Layer, if obj.layer = 8 then 1 * 2^8 = binary 100000000 = decimal 256 ) // to check against the EntMask.value (Only Entity (User Layer 8), equivalent to binary 100000000 = decimal 256) if (1 << obj.layer != EntMask.value) { return; } LiveEntity ent = obj.GetComponent <LiveEntity>(); if (ent == null) { Debug.LogWarning($"{this.gameObject.name} couldn't find a LiveEntity script for a detected object ({obj.name}), can't add to trackList"); return; } // Check if we found ourselves if (ent.UniqueId == UniqueId) { return; } TrackEntity(ent); }
/// <summary> /// Returns null if no object is found /// </summary> public GameObject TryGetRootObj(LiveEntity ent) { if (_rootObjDict.TryGetValue(ent, out GameObject obj)) { return(obj); } return(null); }
public override bool Interact1(Camera pCam, LayerMask mask, LiveEntity owner) { if (_alt == null) { return(false); } _alt.Invoke(pCam, mask, this, owner); return(true); }
/// <summary> /// Attempts to send damage to the specified entity; use if you have the LiveEntity UID /// </summary> public virtual bool TrySendDmg(ulong id, int nType, int nDmg, bool nDirect) { LiveEntity ent = TryGetEnt(id); if (ent == null) { return(false); } return(ent.TakeDmg(null, nType, nDmg, nDirect)); }
/// <summary> /// Attempt to unregister a LiveEntity/root GameObject combo by unique Id /// </summary> public bool UnregisterEnt(ulong id) { LiveEntity ent = null; GameObject obj = null; if (_entDict.TryGetValue(id, out ent)) { _rootObjDict.TryGetValue(ent, out obj); } return(_entDict.Remove(id) && _rootObjDict.Remove(ent) && _objToEntDict.Remove(obj)); }
public virtual void Invoke(Camera pCam, LayerMask mask, WeaponBase weapon, LiveEntity owner) { switch (_type) { case WeaponAltType.CREATE_SOUND: if (Physics.Raycast(pCam.transform.position, pCam.transform.forward, out RaycastHit hit, weapon.Range, mask)) { owner.EmitSoundEvent(new SoundEvent(null, hit.point, weapon.Range, SoundIntensity.NOTEWORTHY)); } break; } }
public virtual bool TakeDmg(LiveEntity damager, int nType, int nDmg, bool nDirect) { if (Active && Hp > 0 && (DmgType)nType != DmgType.STAMINA) { Hp -= nDmg; return(true); } else { return(false); } }
/// <summary> /// Creates a sound event and calls EmitSoundEvent on the specified ISoundEmitter; applies SND_DIST_MOD to the AudioSource.maxDistance /// </summary> public void CreateSoundEvent(LiveEntity ent, AudioSource src, SoundIntensity type = SoundIntensity.NORMAL) { if (ent == null) { return; } if (src == null) { return; } ent.EmitSoundEvent(new SoundEvent(ent, src.transform.position, src.maxDistance * SND_DIST_MOD, type)); }
///-------------------------------------------------------------------- /// Destination methods ///-------------------------------------------------------------------- void OnTriggerStay(Collider other) { if (Active) { LiveEntity ent = other.gameObject.GetComponent <LiveEntity>(); if (ent != null) { if (ent.EntType == EntityType.PLAYER) { NotifyObservers(true); Deactivate(); } } } }
/// <summary> /// Attempts to send damage to the specified entity; use if you only have the GameObject of the target /// </summary> public virtual bool TrySendDmg(GameObject target, LiveEntity src, int nType, int nDmg, bool nDirect) { if (target == null) { return(false); } LiveEntity ent = TryGetEnt(target); if (ent == null) { return(false); } return(ent.TakeDmg(src, nType, nDmg, nDirect)); }
/// <summary> /// Adds the specified LiveEntity to the track list if it's not null, and if we're not already tracking it /// </summary> public void TrackEntity(LiveEntity ent) { // Null check if (ent == null) { return; } // Check if we're already tracking this entity if (TrackDict.ContainsKey(ent.UniqueId)) { return; } TrackDict.Add(ent.UniqueId, ent); }
/// <summary> /// Register the LiveEntity and its root GameObject in their respective dictionaries and return the unique Id assigned /// </summary> public ulong RegisterEnt(LiveEntity ent, GameObject root = null) { ulong id = PullUniqueId(); GameObject obj = root; if (obj == null && ent != null) { obj = ent.transform.root.gameObject; } _entDict.Add(id, ent); _rootObjDict.Add(ent, obj); _objToEntDict.Add(obj, ent); return(id); }
public override bool Interact0(Camera pCam, LayerMask mask, LiveEntity owner) { if (Physics.Raycast(pCam.transform.position, pCam.transform.forward, out RaycastHit hit, Range, mask)) { GameObject target = hit.transform.root.gameObject; // Grab root because hitboxes IDamageable ent = target.GetComponent <IDamageable>(); if (ent != null) { ent.TakeDmg(owner, (int)DamageType, Damage, false); } return(true); } return(false); }
/// <summary> /// Attempt to unregister a HubrisPlayer by unique Id /// </summary> public bool UnregisterPlayer(ulong id) { LiveEntity ent = TryGetEnt(id); if (ent == null) { return(false); } GameObject root = TryGetRootObj(id); if (root == null) { return(false); } return(_playerDict.Remove(id) && _entDict.Remove(id) && _objToEntDict.Remove(root) && _rootObjDict.Remove(ent)); }
public void SetTargetObj(GameObject obj, LiveEntity ent) { if (TargetObj == obj) { return; } TargetObj = obj; TargetEnt = ent; // TargetPos is now the TargetObj's position if (TargetObj != null) { TargetPos = Vector3.zero; } if (TargetEnt != null) { TargetStats = TargetEnt.Stats; } }
/// <summary> /// Process the entities in the TrackDict, finds closest and removes ents that are beyond MAX_DIST or dead /// </summary> public void ProcessTrackDict(Npc a, BhvTree b) { if (a.TrackDict != null && a.TrackDict.Count > 0) { float closestEntDistSqr = 0.0f; LiveEntity closestEnt = null; bool fresh = true; foreach (ulong id in a.TrackDict.Keys) { LiveEntity ent; a.TrackDict.TryGetValue(id, out ent); // If the entity dies and is cleaned up before the trackBook is processed, it will be null if (ent == null) { a.RemoveList.Add(id); continue; } // Check if the entity is invisible if (ent.Stats.Invisible) { continue; } // Check if the entity is dead if (ent.Stats.IsDead) { // If the entity is dead and the same type as this one, set behavior to aggro or hunt or something continue; } if (ent is Npc npc) { // Check if we want to make a squad with other entities of the same type // // // If we're prey if (!a.Params.Predator) { // Prey should ignore other prey if (!npc.Params.Predator) { continue; } } } float maxDist = a.Params.AwareMax; float entDist = Util.CheckDistSqr(a.transform.position, ent.transform.position); // Check if it's beyond our max awareness distance if (entDist > Util.GetSquare(maxDist)) { a.RemoveList.Add(id); continue; } // Field-of-view and Line-of-sight check if (!a.SightCheck(ent.gameObject, Util.GetSquare(maxDist))) { continue; } // If we haven't set our closest entity info yet if (fresh) { closestEntDistSqr = entDist; closestEnt = ent; fresh = false; } else { if (entDist < closestEntDistSqr) { closestEntDistSqr = maxDist; closestEnt = ent; } } } if (closestEnt != null) { // If we don't currently have a target if (a.TargetObj == null) { a.SetTargetObj(closestEnt.gameObject, closestEnt); } else { if (a.TargetObj != closestEnt.gameObject && closestEntDistSqr < (a.TargetDistSqr * a.Params.ProxPct)) { a.SetTargetObj(closestEnt.gameObject, closestEnt); } } } } else { // There's no entities within range, so reset our target if (a.TargetObj != null) { a.ResetTargetObj(); } } if (a.RemoveList != null && a.RemoveList.Count > 0) { for (int i = 0; i < a.RemoveList.Count; i++) { LiveEntity ent = null; a.TrackDict.TryGetValue(a.RemoveList[i], out ent); Untrack(a, a.RemoveList[i]); } a.RemoveList.Clear(); } }
public virtual bool Interact1(Camera pCam, LayerMask mask, LiveEntity owner) { // Override with unique implementation return(true); }
///-------------------------------------------------------------------- /// SoundManager methods ///-------------------------------------------------------------------- public bool InitSoundManager(LiveEntity a, GameObject obj = null) { owner = a; ownerObj = obj; if (!init) { init = true; if (footSource != null && voxSource != null && atkSource != null) { return(init); } if (footHolder != null) { footSource = footHolder.GetComponent <AudioSource>(); if (footSource == null) { Debug.LogWarning(this.gameObject + " SoundManager InitSoundManager(): footSource is null"); } } Debug.LogWarning(this.gameObject + " SoundManager InitSoundManager(): footHolder is null, likely needs to be assigned in Editor"); if (voxHolder != null) { voxSource = voxHolder.GetComponent <AudioSource>(); if (voxSource == null) { Debug.LogWarning(this.gameObject + " SoundManager InitSoundManager(): voxSource is null"); } } else { Debug.LogWarning(this.gameObject + " SoundManager InitSoundManager(): voxHolder is null, likely needs to be assigned in Editor"); } if (atkHolder != null) { atkSource = atkHolder.GetComponent <AudioSource>(); if (atkSource == null) { Debug.LogWarning(this.gameObject + " SoundManager InitSoundManager(): atkSource is null"); } } else { Debug.LogWarning(this.gameObject + " SoundManager InitSoundManager(): atkHolder is null, likely needs to be assigned in Editor"); } } else { Debug.LogWarning(this.gameObject + " SoundManager InitSoundManager(): Attempting to initialize SoundManager when it has already been initialized..."); } footQueue = new List <AudioClip>(); voxQueue = new List <AudioClip>(); atkQueue = new List <AudioClip>(); return(init); }
/// <summary> /// Do something with received sound events /// </summary> protected override void ProcessSoundEvents() { if (SoundEventList != null && SoundEventList.Count > 0) { for (int i = 0; i < SoundEventList.Count; i++) { Vector3 origin = SoundEventList[i].Origin; float rad = SoundEventList[i].Radius; // Check if it's in range; if not, continue if (!Util.CheckDistSqr(origin, this.transform.position, rad)) { continue; } // Check if we're already interested in something closer to us if (TargetPos != Vector3.zero) { if (Util.CheckDistSqr(origin, this.transform.position) > Util.CheckDistSqr(TargetPos, this.transform.position)) { continue; } } LiveEntity ent = SoundEventList[i].Source; GameObject src = SoundEventList[i].Source?.gameObject; SoundIntensity intensity = SoundEventList[i].Intensity; // Predators investigate sounds if they don't currently have a target and the source did not come from an object if (TargetObj == null && Params.Predator) { if (src == null) { if (intensity >= SoundIntensity.NOTEWORTHY || (MovePos == Vector3.zero && TargetPos == Vector3.zero)) { SetTargetPos(origin); } continue; } } // If the heard entity is another Npc if (ent is Npc npc) { // Prey ignore other prey if (!Params.Predator && !npc.Params.Predator) { continue; } } if (ent != null) { TrackEntity(ent); if (intensity >= SoundIntensity.NOTEWORTHY) { Behavior.SetIgnoreSightCheck(true); SetTargetObj(src, ent); } } } SoundEventList.Clear(); } }