/// <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;
        }
    }
Exemple #6
0
    /// <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);
    }