Пример #1
0
    // for human agents
    bool ApplyDamage(AgentHuman inAgent, Vector3 inExplosionPos, float inDmgMultiplier)
    {
        Vector3 tmp  = ClosestPoint.PointBounds(inExplosionPos, inAgent.CharacterController.bounds);
        float   dist = (inExplosionPos - tmp).sqrMagnitude;

        if (dist > damageRadius * damageRadius)
        {
            return(false);
        }

#if DEBUG
        DebugDraw.Diamond(Color.grey, 0.02f, tmp);
        DebugDraw.LineOriented(Color.grey, inExplosionPos, tmp, 0.04f);
#endif

        int idx = inAgent.ExplosionHitTargets != null ? inAgent.ExplosionHitTargets.Length : 0;

        while (idx-- > 0)
        {
            if (CheckHit(inAgent.ExplosionHitTargets[idx], inExplosionPos, ref tmp))
            {
                float coef = 1.0f - Mathf.Clamp01(Mathf.Sqrt(dist) / damageRadius);

                Damage  = BaseDamage * coef * inDmgMultiplier;
                Impulse = tmp;

                inAgent.SendMessage("OnExplosionHit", this, SendMessageOptions.DontRequireReceiver);

                return(true);
            }
        }

        return(false);
    }
Пример #2
0
    internal void SpawnExplosion()
    {
        if (m_Explosion != null)
        {
            //Debug.Log("ProjectileRocket.SpawnExplosion " + name);

            float   dot       = -Vector3.Dot(HitNormal, Transform.forward);
            float   offNormal = 0.1f + 0.6f * (dot / 2.0f);
            float   offDir    = 0.0f + 0.3f * (1.0f - dot);
            Vector3 pos       = Transform.position + m_ExplosionOffset - offDir * Transform.forward + offNormal * HitNormal;

            //	Explosion explosion = Object.Instantiate(m_Explosion, transform.position, transform.rotation) as Explosion;
            //	Explosion explosion = Mission.Instance.ExplosionCache.Get(m_Explosion, Transform.position + m_ExplosionOffset, Transform.rotation);
            Explosion explosion = Mission.Instance.ExplosionCache.Get(m_Explosion, pos, Transform.rotation);

            if (null != explosion && Agent != null)
            {
                explosion.Agent           = Agent;
                explosion.BaseDamage      = Damage;
                explosion.m_WeaponID      = WeaponID;
                explosion.m_WeaponImpulse = Settings.Impulse;

#if DEBUG
                DebugDraw.DepthTest   = true;
                DebugDraw.DisplayTime = 10.0f;
                DebugDraw.Diamond(Color.yellow, 0.04f, explosion.Position);
#endif
            }
        }

        // destroy projectile ...
        // Destroy(gameObject); - !!! Don't do it. This object is cached now.
    }
Пример #3
0
    private static float ProceedOneCoverDistanceCast(Vector3 fromPos, Vector3 forward, float distance, ref MinMaxPair minMax, float invertDistance = -1)
    {
        RaycastHit hit;

        int Default      = 1 << LayerMask.NameToLayer("Default");
        int PhysicsMetal = 1 << LayerMask.NameToLayer("PhysicsMetal");

        if (true == Physics.Raycast(fromPos, forward, out hit, distance, Default | PhysicsMetal))
        {
            DebugDraw.LineOriented(Color.red, fromPos, fromPos + forward * distance, 0.05f);

            distance = (fromPos - hit.point).magnitude;

            if (Vector3.Dot(hit.normal, forward) > -0.1f)
            {
                if (invertDistance < 0)
                {
                    distance = 0;
                }
                else
                {
                    distance = invertDistance;
                }
            }
            else
            {
                if (true == VisualizeTests)
                {
                    DebugDraw.DisplayTime = 0.00f;
                    DebugDraw.Diamond(Color.green, 0.03f, hit.point);
                    DebugDraw.LineOriented(VisualizationColor, hit.point, hit.point + hit.normal * 0.25f, 0.05f);
                }
            }
        }
        else
        {
            if (invertDistance < 0)
            {
                Debug.LogWarning("CoverUtils : Expected collision hit not found, position :" + fromPos);
            }
            return(distance);
        }

        if (invertDistance > 0)
        {
            minMax.Absorb(invertDistance - distance);
        }
        else
        {
            minMax.Absorb(distance);
        }

        return(distance);
    }
Пример #4
0
    bool IsCollisionBetween(Vector3 inFrom, Vector3 inTo, Collider inVictim)
    {
        Vector3 dir = inTo - inFrom;
        float   lng = dir.magnitude;

        dir    /= lng;
        inFrom -= dir * 0.04f;

        int mask = ~(ObjectLayerMask.IgnoreRayCast | ObjectLayerMask.Ragdoll | ObjectLayerMask.PhysicBody | ObjectLayerMask.Hat);

        RaycastHit[] hits = Physics.RaycastAll(inFrom, dir, lng, mask);

        if (hits.Length > 1)
        {
            System.Array.Sort(hits, CollisionUtils.CompareHits);
        }

        foreach (RaycastHit hit in hits)
        {
            if ((hit.collider.isTrigger == true) || (hit.collider == inVictim))
            {
                continue;
            }

            if (noBlocking != null && IgnoreInBlockingTest(hit.collider.transform) == true)
            {
                continue;
            }

            m_ObstacleNormalAccum += hit.normal;

#if DEBUG
            DebugDraw.LineOriented(ColMiss, inFrom, inTo);
            DebugDraw.Collider(ColMiss, inVictim, 0.96f);
            DebugDraw.Diamond(ColMiss, 0.02f, hit.point);
#endif

            return(true);
        }

#if DEBUG
        DebugDraw.LineOriented(ColHit, inFrom, inTo);
        DebugDraw.Collider(ColHit, inVictim, 0.96f);
#endif

        return(false);
    }
Пример #5
0
    void ApplyDamage()
    {
        if (uLink.Network.isServer == false)
        {
            return;
        }

        // enumerate victims...
        Vector3 tmp;
        Vector3 pos  = Position;
        int     mask = ~(ObjectLayerMask.IgnoreRayCast | ObjectLayerMask.Ragdoll | ObjectLayerMask.Hat);

        Collider[] colliders = Physics.OverlapSphere(Position, damageRadius, mask);

#if DEBUG
        DebugDraw.DepthTest   = true;
        DebugDraw.DisplayTime = 8.0f;
        DebugDraw.Diamond(ColExp, 0.04f, pos);
#endif

        // categorize victims...
        foreach (Collider c in colliders)
        {
            AgentHuman a = c.gameObject.GetFirstComponentUpward <AgentHuman>();

            if (a == null)
            {
                m_Others.Add(c);
            }
            else if (m_Agents.Contains(a) == false)
            {
                m_Agents.Add(a);
            }
        }

        // process human-agents...
        foreach (AgentHuman a in m_Agents)
        {
            m_ObstacleNormalAccum = Vector3.zero;

            a.SampleDominantAnim();

            if (ApplyDamage(a, pos, 1.0f) == false)
            {
                if ((m_ObstacleDamageReduction > 0.0f) && (m_ObstacleNormalAccum.sqrMagnitude > 0.0f))
                {
                    Vector3 u = Vector3.up;
                    Vector3 v = Vector3.zero;
                    Vector3 n = m_ObstacleNormalAccum;

                    Vector3.OrthoNormalize(ref n, ref u, ref v);

                    tmp  = pos;
                    tmp += 0.5f * n;
                    //	tmp += 1.0f * u;

                    Vector3 diff = a.Position - pos;
                    float   dot  = Vector3.Dot(diff, v);

                    //	if (Mathf.Abs(dot) > 0.3f)
                    {
                        tmp += 0.5f * Mathf.Sign(dot) * v;
                    }

#if DEBUG
                    DebugDraw.LineOriented(ColExp, pos, tmp, 0.04f);
#endif

                    ApplyDamage(a, tmp, m_ObstacleDamageReduction);
                }
            }
        }

        // process other objects...
        foreach (Collider c in m_Others)
        {
            ApplyDamage(c, pos);
        }

        // clean-up...
        m_Agents.Clear();
        m_Others.Clear();
    }
Пример #6
0
    //collide camera and place it to the best position
    void CollideCamera5()
    {
        //
#if CAMERA_DEBUG_DRAW
        Color col;
#endif

        Transform desiredTransform = CameraBehaviour.GetDesiredCameraTransform();
        if (desiredTransform)
        {
            Vector3    desiredPosition = desiredTransform.position;
            Quaternion desiredRotation = desiredTransform.rotation;

            float dif = (desiredPosition - PrevPos).sqrMagnitude;

#if !CAMERA_DEBUG_DRAW //disable the optimization when Debug Draw is on
            //exit if the camera didn't move or rotate
            if (dif < 0.0001f &&
                Mathf.Approximately(PrevRot.x, desiredRotation.x) &&
                Mathf.Approximately(PrevRot.y, desiredRotation.y) &&
                Mathf.Approximately(PrevRot.z, desiredRotation.z) &&
                Mathf.Approximately(PrevRot.w, desiredRotation.w))
            {
                return;
            }
#endif

            //blend the transform (this is useful especially when the CameraState changes or when the camera moves very fast)
            if (dif > 0.1f)
            {
                desiredPosition = Vector3.Lerp(PrevPos, desiredPosition, Time.deltaTime * 20);
                desiredRotation = Quaternion.Slerp(PrevRot, desiredRotation, Time.deltaTime * 20);
            }

            PrevPos = desiredPosition;
            PrevRot = desiredRotation;

            Vector3 FinalPos;

            //pokud je jiny CameraState nez CameraState3RD, tak muzeme nasledujici testy preskocit a jen nastavit CameraTransform.position a CameraTransform.rotation a zavolat UpdateLocalPlayerInstance();
//			if ( (CameraBehaviour.State is CameraState3RD) || (CameraBehaviour.State is CameraStateCover) || (CameraBehaviour.State is CameraStateDeath) )
            {
                LayerMask mask = ObjectLayerMask.Default | ObjectLayerMask.PhysicsMetal;
                //~( ObjectLayerMask.Ragdoll | ObjectLayerMask.IgnoreRayCast | ObjectLayerMask.PhysicBody );
                const float minNear   = 0.02f;               //0.05f still penetrates walls while rolling
                const float minRadius = 0.12f;               //0.1f
                const float maxRadius = 0.3f;                //with 0.5f the camera collides too often when player runs close to obstacles
                bool        IsRolling = CameraBehaviour.Owner.PlayerComponent.IsRolling;
                bool        IsAlive   = CameraBehaviour.Owner.IsAlive;
                float       radius    = IsRolling ? minRadius : maxRadius;        //in dodge, use minRadius for collisions

                //for testing collision between Head and TargetPos ("CameraTargetDir" node)
                Vector3 HeadPos   = CameraBehaviour.Owner.EyePosition;
                Vector3 TargetPos = CameraBehaviour.CameraOrigin.position;
                Vector3 headDir   = TargetPos - HeadPos;

                //shift the HeadPos to not allow the camera to move into player's head
                HeadPos += headDir * 0.5f;               //middle point between head and target
                headDir  = TargetPos - HeadPos;

                float      headLength = headDir.magnitude;
                RaycastHit headHit;

#if CAMERA_DEBUG_DRAW
                DebugDraw.Line(Color.magenta, HeadPos, TargetPos + headDir.normalized * radius);                                //c
                DebugDraw.Diamond(Color.magenta, 0.03f, TargetPos);
                DebugDraw.Diamond(Color.green, 0.03f, desiredPosition);
#endif

                //check whether the TargetPos is behind collision or not (it is controlled by animation and usually is outside the player's capsule collider)
                //this happens when players 'shoulder' (i.e. the "CameraTargetDir") gets behind a wall
                if (Physics.Raycast(HeadPos, headDir, out headHit, headLength + radius, mask))
                {
                    float m = Mathf.Max(0, headHit.distance - radius);
                    TargetPos = HeadPos + headDir.normalized * m;                   //move the TargetPos along the line to a safe place

                    if (headHit.distance < radius)
                    {
                        radius = Mathf.Max(minRadius, headHit.distance - 0.001f);                         //change the radius based on the collision distance
                    }
#if CAMERA_DEBUG_DRAW
                    DebugDraw.Diamond(Color.cyan, 0.03f, headHit.point);
                    DebugDraw.Diamond(Color.white, 0.03f, TargetPos);                                              //new TargetPos

                    DebugDraw.Line(Color.green, headHit.point, headHit.point + headHit.normal * (radius + 0.01f)); //b
                    DebugDraw.Line(Color.yellow, headHit.point + headHit.normal * (radius + 0.01f), TargetPos);
#endif
                }

                //
                Vector3     dir = desiredPosition - TargetPos;
                Vector3     dirN = dir.normalized;
                float       length = dir.magnitude;
                float       q, dist;
                const float safeDist = maxRadius + 0.1f;                 //shift the capsule in front of the TargetPos a little

                //do the sphere (capsule) collision with scene
                RaycastHit[] hits = Physics.SphereCastAll(TargetPos - dirN * safeDist, radius, dirN, length + safeDist, mask);

                //sort by distance
                if (hits.Length > 1)
                {
                    System.Array.Sort(hits, CollisionUtils.CompareHits);
                }

                //			FinalPos        = desiredPosition;
                dist = length;                                             //default position at the desiredPosition if we will not collide
                MainCamera.nearClipPlane = Mathf.Max(0.2f, radius * 0.5f); //radius * 0.5f;				//was 0.3f;

                foreach (RaycastHit hit in hits)
                {
                    if (hit.collider.gameObject.layer == InteractionObject.UseLayer)
                    {
                        continue;
                    }

                    if (hit.collider.isTrigger)
                    {
                        continue;
                    }

                    if (hit.collider == IgnoredCollider)
                    {
                        continue;
                    }

                    //				FinalPos = hit.point + hit.normal * minRadius;		//was 0.3f; changed to 0.1f to help fix the camera-player intersection (when player was running backwards against wall)
                    dist = Mathf.Min(length, hit.distance + radius - safeDist - minRadius);

                    if (dist < 0)                     //can become < 0 due to safeDist
                    {
                        dist = 0;
                    }

                    //				FinalPos = TargetPos + dirN * q;
                    MainCamera.nearClipPlane = (IsRolling || !IsAlive) ? minNear : 0.2f;
                    //0.02f;							//was 0.05f; the new value needs testing on devices (check z-fight)

#if CAMERA_DEBUG_DRAW
                    col = Color.grey; col.a = 0.5f;
                    Debug.DrawLine(desiredPosition, TargetPos, col, 0.5f);
                    DebugDraw.Diamond(Color.red, 0.03f, hit.point);

                    col = Color.gray; col.a = 0.5f;
                    DebugDraw.Capsule(col, radius, TargetPos - dirN * safeDist, TargetPos + dirN * length);
#endif

                    break;                     //need to care just about the nearest valid hit
                }

                //
                float ratio = (Mathf.Abs(PrevDist - dist) / length) + (1 - (radius - minRadius) / maxRadius);

                if (PrevDist < dist)                 //we're returning back - do it slower
                {
                    ratio *= 0.5f;
                }

                float speed = Mathf.Clamp(ratio, 0.2f, 1.0f) * 25;
                //change the blend speed based on the distance between actual and computed distance (position)

                q = Mathf.Lerp(PrevDist, dist, Time.deltaTime * speed);               //smoothly blend between previous and current position

                //			if ( Mathf.Abs(PrevDist - dist) > 0.01f )
                //				Debug.Log ("radius=" + radius + ", dist=" + dist + ", PrevDist=" + PrevDist + ", ratio=" + ratio + ", q=" + q + ", speed=" + speed);

                PrevDist = q;

#if CAMERA_DEBUG_DRAW
                DebugDraw.Diamond(Color.yellow, 0.03f, TargetPos + dirN * dist);                                //where we need to be (we're interpolating to this pos)
#endif

                //set Final Position
                FinalPos = TargetPos + dirN * q;
            }
//			else
//			{
//				FinalPos = desiredPosition;
//			}

            //set Final Position
            CameraTransform.position = FinalPos;

            //CameraTransform.rotation = Quaternion.Lerp(CameraTransform.rotation, desiredRotation, 15.0f * Time.deltaTime);
            CameraTransform.rotation = desiredRotation;

            //
#if CAMERA_DEBUG_DRAW
            col = Color.yellow; col.a = 0.5f;
            DebugDraw.Diamond(col, 0.03f, FinalPos);
#endif

            UpdateLocalPlayerInstance();
        }
    }
Пример #7
0
    void ProceedHits(RaycastHit[] hits, bool softInit, Vector3 newPos)
    {
        // launched from cover (fast dirty solution)
        Cover cover      = null;
        bool  hitIsValid = false;

        if ((Agent != null) && (Agent.IsInCover == true) && (Agent.BlackBoard.Cover != null))
        {
            cover = Agent.BlackBoard.Cover;
        }

        // sort hits by distance
        if (hits.Length > 1)
        {
            System.Array.Sort(hits, CollisionUtils.CompareHits);
        }

        // process hits
        foreach (RaycastHit hit in hits)
        {
            //Debug.Log("ProjectileUpdate Hit" + hit.transform.name);
            if (hit.transform == Settings.IgnoreTransform)
            {
                continue;
            }

            //skip the Owner of this shot when his HitZone got hit
            HitZone zone = hit.transform.GetComponent <HitZone>();
            if (zone && (zone.HitZoneOwner is AgentHuman) && (zone.HitZoneOwner as AgentHuman).transform == Settings.IgnoreTransform)
            {
                continue;
            }

            //HACK The projectile belongs to the "Default" collision layer.
            //This is probably bug but we do not want to modify the data at the moment.
            //The only chance now is to ignore such hits
            if (hit.transform.gameObject.name.StartsWith("Projectile"))
            {
                continue;
            }

            //skip friends when the projectile should explode near the player (this solves the unwanted suicide when a friend suddenly enters the area in front of me)
            AgentHuman hitAgent = hit.transform.gameObject.GetFirstComponentUpward <AgentHuman>();
            if (Agent != null && hitAgent != null)
            {
                float dist = Vector3.Distance(Agent.Position, hitAgent.Position);
                if (dist < 3)                 //ignore only if the projectile is still within X m radius
                {
                    if (Agent.IsFriend(hitAgent))
                    {
                        continue;
                    }
                }
            }

            Transform.position = hit.point;

            if (hit.collider.isTrigger)
            {
                if (!softInit)
                {
                    hit.transform.SendMessage("OnProjectileHit", this, SendMessageOptions.DontRequireReceiver);
                    continue;
                }
            }

            if ((cover != null) && (cover.IsPartOfCover(hit.collider.gameObject) == true))
            {
                continue;
            }

            newPos = hit.point;

#if DEBUG
            DebugDraw.DepthTest   = true;
            DebugDraw.DisplayTime = 10.0f;
            DebugDraw.Diamond(Color.red, 0.02f, newPos);
#endif

            Hit        = true;
            HitNormal  = hit.normal;
            hitIsValid = ValidateHit(hit);

            break;
        }

        if (false == softInit)
        {
            Transform.position = newPos;
        }

        if (Hit)
        {
            if (hitIsValid)
            {
                HitReaction();
            }
            else
            {
                //This function probably has no effect here but I want to be sure that I did not miss anything important
                //This code is triggered on the server side and only in the case when attacker is cheating
                InvalidHitReaction();
            }
        }
    }