/// <summary> /// /// </summary> void OnTriggerEnter(Collider col) { // return if this is not a relevant object. TIP: this check can be expanded if (col.gameObject.layer == vp_Layer.Debris || col.gameObject.layer == vp_Layer.Pickup) return; // try to find a damagehandler on the target and abort on fail m_TargetDamageHandler = vp_DamageHandler.GetDamageHandlerOfCollider(col); if (m_TargetDamageHandler == null) return; // abort if target is already dead // NOTE: this deals with cases of multiple 'OnTriggerEnter' calls on contact if (m_TargetDamageHandler.CurrentHealth <= 0) return; // try to find a respawner on the target to see if it's currently OK to kill it m_TargetRespawner = vp_Respawner.GetByCollider(col); if (m_TargetRespawner != null) { // abort if target has respawned within one second before this call. // NOTE: this addresses a case where 'OnTriggerEnter' is called when // teleporting (respawning) away from the trigger, resulting in the // object getting insta-killed on respawn. it will only work if the // target gameobject has a vp_Respawner-derived component if (Time.time < m_TargetRespawner.LastRespawnTime + 1.0f) return; } m_TargetDamageHandler.Damage(new vp_DamageInfo(m_TargetDamageHandler.CurrentHealth, m_TargetDamageHandler.Transform, vp_DamageInfo.DamageType.KillZone)); }
public virtual void ReceiveObjectRespawn(int viewId, Vector3 position, Quaternion rotation, PhotonMessageInfo info) { if (info.sender != PhotonNetwork.masterClient) { return; } vp_Respawner r = GetRespawnerOfViewID(viewId); if ((r == null) || (r is vp_PlayerRespawner)) { return; } // make object temporarily invisible so we don't see it 'pos-lerping' // across the map to its respawn position if (r.Renderer != null) { r.Renderer.enabled = false; } r.Respawn(); // restore visibility in half a sec if (r.Renderer != null) { vp_Timer.In(0.5f, () => { r.Renderer.enabled = true; }); } }
/// <summary> /// retrieves, finds and caches target respawners for more /// efficient fetching in the future /// </summary> public static vp_Respawner GetByCollider(Collider col) { // try to fetch a known respawner on this target if (!Instances.TryGetValue(col, out m_GetInstanceResult)) { // no respawners on record: see if there is one m_GetInstanceResult = col.transform.root.GetComponentInChildren <vp_Respawner>(); Instances.Add(col, m_GetInstanceResult); // add result to the dictionary (even if null) } return(m_GetInstanceResult); }
/// <summary> /// registers a pickup under a position-based ID /// </summary> protected virtual void RegisterPickup(vp_ItemPickup p) { // since a single gameobject may have several vp_Pickup components // on them, pickups are stored in a dictionary with id keys and // pickup list values. (an example of a multi-pickup object is a // grenade, which has both a grenade thrower pickup and an ammo // pickup on the same object) if (!vp_MPPickupManager.Instance.Pickups.ContainsKey(p.ID)) { // if the pickup does not exist, we add a list with a single pickup // under the position based ID List <vp_ItemPickup> ip = new List <vp_ItemPickup>(); ip.Add(p); vp_MPPickupManager.Instance.Pickups.Add(p.ID, ip); vp_Respawner r = p.GetComponent <vp_Respawner>(); if ((r != null) && !vp_MPPickupManager.Instance.PickupRespawners.ContainsKey(p.ID)) { vp_MPPickupManager.Instance.PickupRespawners.Add(p.ID, r); r.m_SpawnMode = vp_Respawner.SpawnMode.SamePosition; } //else TODO: warn } else { // if a pickup already exists with this id, we unpack the list, // remove it from the dictionary, add the new pickup and re-add // it under the same id List <vp_ItemPickup> ip; if (vp_MPPickupManager.Instance.Pickups.TryGetValue(p.ID, out ip) && ip != null) { vp_MPPickupManager.Instance.Pickups.Remove(p.ID); ip.Add(p); vp_MPPickupManager.Instance.Pickups.Add(p.ID, ip); } } //else TODO: warn }
/// <summary> /// /// </summary> static void CreateRespawnerForDamageHandler(vp_DamageHandler damageHandler) { if (damageHandler.gameObject.GetComponent <vp_Respawner>() || damageHandler.gameObject.GetComponent <vp_PlayerRespawner>()) { return; } vp_Respawner respawner = null; if (damageHandler is vp_FPPlayerDamageHandler) { respawner = damageHandler.gameObject.AddComponent <vp_PlayerRespawner>(); } else { respawner = damageHandler.gameObject.AddComponent <vp_Respawner>(); } if (respawner == null) { return; } if (damageHandler.MinRespawnTime != -99999.0f) { respawner.MinRespawnTime = damageHandler.MinRespawnTime; } if (damageHandler.MaxRespawnTime != -99999.0f) { respawner.MaxRespawnTime = damageHandler.MaxRespawnTime; } if (damageHandler.RespawnCheckRadius != -99999.0f) { respawner.ObstructionRadius = damageHandler.RespawnCheckRadius; } if (damageHandler.RespawnSound != null) { respawner.SpawnSound = damageHandler.RespawnSound; } }
/// <summary> /// /// </summary> void OnTriggerEnter(Collider col) { // return if this is not a relevant object. TIP: this check can be expanded if (col.gameObject.layer == vp_Layer.Debris || col.gameObject.layer == vp_Layer.Pickup) { return; } // try to find a damagehandler on the target and abort on fail m_TargetDamageHandler = vp_DamageHandler.GetDamageHandlerOfCollider(col); if (m_TargetDamageHandler == null) { return; } // abort if target is already dead // NOTE: this deals with cases of multiple 'OnTriggerEnter' calls on contact if (m_TargetDamageHandler.CurrentHealth <= 0) { return; } // try to find a respawner on the target to see if it's currently OK to kill it m_TargetRespawner = vp_Respawner.GetByCollider(col); if (m_TargetRespawner != null) { // abort if target has respawned within one second before this call. // NOTE: this addresses a case where 'OnTriggerEnter' is called when // teleporting (respawning) away from the trigger, resulting in the // object getting insta-killed on respawn. it will only work if the // target gameobject has a vp_Respawner-derived component if (Time.time < m_TargetRespawner.LastRespawnTime + 1.0f) { return; } } m_TargetDamageHandler.Damage(new vp_DamageInfo(m_TargetDamageHandler.CurrentHealth, m_TargetDamageHandler.Transform, vp_DamageInfo.DamageType.KillZone)); }
/// <summary> /// caches and returns the respawner of the given photonview id. /// respawners are stored in a dictionary that resets on level load /// </summary> public static vp_Respawner GetRespawnerOfViewID(int id) { vp_Respawner d = null; if (!m_RespawnersByViewID.TryGetValue(id, out d)) { PhotonView p = PhotonView.Find(id); if (p != null) { d = p.transform.GetComponent <vp_Respawner>(); if (d != null) { m_RespawnersByViewID.Add(id, d); } return(d); } // NOTE: we do not add null results, since photonviews come and go } return(d); }
/// <summary> /// retrieves, finds and caches target respawners for more /// efficient fetching in the future /// </summary> public static vp_Respawner GetByCollider(Collider col) { // try to fetch a known respawner on this target if (!Instances.TryGetValue(col, out m_GetInstanceResult)) { // no respawners on record: see if there is one m_GetInstanceResult = col.transform.root.GetComponentInChildren<vp_Respawner>(); Instances.Add(col, m_GetInstanceResult); // add result to the dictionary (even if null) } return m_GetInstanceResult; }
/// <summary> /// creates a deactivated clone template of a pickup object that is /// adapted for instantiation and dropping in the scene. templates are /// stored in a scene group called 'Droppables' /// </summary> protected virtual GameObject ClonePickup(string name, vp_ItemPickup i) { GameObject template = (GameObject)vp_Utility.Instantiate(i.gameObject, Vector3.zero, i.gameObject.transform.rotation); template.name = name; // if there is a remover on the pickup, override its lifetime // if not, add a remover with our own lifetime, even if 0 vp_Remover rm = template.GetComponent <vp_Remover>(); if (rm == null) { rm = template.AddComponent <vp_Remover>(); } rm.LifeTime = ItemLifeTime; // if there is a respawner on the pickup and our lifetime is 0, // use the max respawn time of the respawner as lifetime. // however, kill the respawner afterwards // NOTE: this will make dropped pickups be destroyed (or pooled) // when picked up, unlike scene pickups that have respawners (which // are merely temp-deactivated) vp_Respawner rs = template.GetComponent <vp_Respawner>(); if (rs != null) { if (ItemLifeTime == 0.0f) { rm.LifeTime = rs.MaxRespawnTime; } Object.Destroy(rs); } // if lifetime is 0 at this point, fallback to 10 secs if (rm.LifeTime == 0.0f) { rm.LifeTime = 10.0f; } // add 0-2 seconds randomly to lifetime, so clusters of pickups won't // pop away exactly at the same time vp_MathUtility.SetSeed(i.ID); rm.LifeTime += Random.value * 2; // disable rigidbodiy and colliders (trigger colliders will be reactivated later) Rigidbody rb = template.GetComponent <Rigidbody>(); if (rb != null) { rb.isKinematic = true; } Collider[] cs = template.GetComponents <Collider>(); foreach (Collider c in cs) { c.enabled = false; } // set up item pickup vp_ItemPickup ip = template.GetComponent <vp_ItemPickup>(); if (ip != null) { ip.ID = 0; } ip.Amount = i.Amount; // disable object and child it to the 'Droppables' group vp_Utility.Activate(template, false); template.transform.parent = m_DroppablesGroup; return(template); }