void Update()
 {
     if (currentState == ProjectileState.FIRING)
     {
         float distanceToEndPoint = Vector3.Distance(transform.position, ballisticEndPoint);
         if (speed * Time.deltaTime > distanceToEndPoint)
         {
             myCollider.isTrigger = false;
             transform.position   = ballisticEndPoint;
             currentState         = ProjectileState.RETURNING;
         }
         else
         {
             transform.position = Vector3.MoveTowards(transform.position, ballisticEndPoint, speed * Time.deltaTime);
         }
     }
     if (currentState == ProjectileState.RETURNING)
     {
         float distanceToHome = Vector3.Distance(transform.position, home.position);
         if (speed * Time.deltaTime > distanceToHome)
         {
             myCollider.isTrigger = false;
             transform.position   = home.position;
             transform.rotation   = home.rotation;
             transform.SetParent(home.parent);
             currentState = ProjectileState.WAITING;
         }
         transform.position = Vector3.MoveTowards(transform.position, home.position, speed * Time.deltaTime);
     }
 }
示例#2
0
    private void ChangeState(ProjectileState toState)
    {
        if (toState == state)
        {
            return;
        }

        state = toState;

        switch (state)
        {
        case ProjectileState.None:
            break;

        case ProjectileState.SeekingTarget:
            break;

        case ProjectileState.Destroying:
            Destroy(gameObject);
            break;

        default:
            break;
        }
    }
示例#3
0
    /* working
     * private void OnCollisionEnter(Collision col)
     * {
     *  if (state != ProjectileState.inFlight)
     *      return;
     *
     *  state = ProjectileState.impaled;
     *  trail.enabled = false;
     *
     *  //Fix in position
     *  //projectileBody.MovePosition(col.contacts[0].point);
     *  //projectileBody.velocity = Vector3.zero;
     *  //projectileBody.angularVelocity = Vector3.zero;
     *
     *  //Find out what we hit and fix to it or it's dead version
     *  Collider other = col.contacts[0].otherCollider;
     *  Life life = other.GetComponentInParent<Life>();
     *  Rigidbody otherBody = other.GetComponentInParent<Rigidbody>();
     *
     *  //kill
     *  if (life)
     *      life.Dead();
     *
     *  //apply hit force - do we need?
     *  if (otherBody)
     *  {
     *      stickTo = gameObject.AddComponent<FixedJoint>();
     *      stickTo.connectedBody = otherBody;
     *      otherBody.AddForceAtPosition(transform.forward * 10f, col.contacts[0].point, ForceMode.Impulse);
     *
     *  }
     *
     *  Owner = other.transform.root.gameObject;
     * }
     */


    private void OnCollisionEnter(Collision collision)
    {
        //Can only penetrate something if we are in flight - deflections can't, they are just normal collisions
        if (!enabled || state != ProjectileState.inFlight)
        {
            return;
        }

        //we are going to need a new owner
        Owner = null;

        Impenetrable impenetrable = collision.contacts[0].otherCollider.GetComponent <Impenetrable>();
        Damage       d            = collision.contacts[0].thisCollider.GetComponent <Damage>();


        if (!impenetrable && d && d.type == DamageType.piercing)
        {
            state = ProjectileState.impaled;

            Grabbed(collision.collider.gameObject);
        }
        else
        {
            state = ProjectileState.deflected;
        }

        if (trail)
        {
            trail.enabled = false;
        }
    }
示例#4
0
        public void Initialize(LogicUnit owner, ProjectileProto proto, long id, FixVector3 position, LogicUnit target)
        {
            this.id       = id;
            this.type     = LogicUnitType.Projectile;
            this.owner    = owner;
            this.mark     = owner.mark;
            this.position = position;
            this.target   = target;
            targetId      = target.id;

            metaId      = proto.ID;
            modelId     = proto.Projectile_ResouceId;
            hitEffectId = proto.HitEffect_ResourceId;

            speedFactor = ConvertUtils.ToLogicInt(proto.SpeedFactor);

            damage = owner.damage;

            projectileType     = (ProjectileType)proto.ProjectileType;
            startPosition      = position;
            targetPosition     = target.position;
            speed              = (targetPosition - position).normalized * speedFactor;
            transform.position = position.vector3;
            state              = ProjectileState.Flying;
            targetDistance     = 0;
            destination        = target.position;

            // Temp data
            hurtType = AttackPropertyType.PhysicalAttack;

            DebugUtils.Log(DebugUtils.Type.AI_Projectile, "the projectile " + id + "'s target is " + target.id + ", speed = " + position);
        }
示例#5
0
 public Projectile(Vector3 startPoint, Vector3 endPoint, float timeCons)
 {
     PState       = ProjectileState.Disable;
     StartPoint   = startPoint;
     EndPoint     = endPoint;
     TimeConstant = timeCons;
 }
示例#6
0
    void FixedUpdate()
    {
        if (state == ProjectileState.Fly) {
            var hits = Physics2D.CircleCastAll (transform.position, projectileWidthCollision, transform.forward, preCalculateCollisionDistance, affectLayer);
            if (hits.Length > 0) {
                foreach (RaycastHit2D hit in hits) {
                    Debug.Log ("hit");
                    if (!hit.transform.gameObject.tag.Equals (tag)) {
                        HealthManager hm = hit.transform.gameObject.GetComponent<HealthManager> ();
                        if (hm != null) {
                            hm.TakeDamage (damage);
                            Debug.Log ("Taking damage: " + damage);
                        } else
                            Debug.LogError (hit.transform.GetInstanceID () + " was hit and has no health manager");

                        state = ProjectileState.Destroy;

                        break;
                    }
                }
            }
            Fly ();

        } else if (state != prevState) {
            switch (state) {
            case ProjectileState.Destroy:
                Destroy ();

                break;
            case ProjectileState.Idle:
                break;
            }
            prevState = state;
        }
    }
示例#7
0
        private void Exploding()
        {
            // Keep setting my velocity back to zero
            base.Ball.Velocity.StoreNewValues(new MyVector());

            // See if enough time has gone by
            bool isExpired = false;

            if (_explosion == null)
            {
                isExpired = true;
            }
            else
            {
                // Bump up my elapsed time
                _explosion.ElapsedTime += _curTickElapsedTime;

                if (_explosion.ElapsedTime > _explosion.Duration)
                {
                    isExpired = true;
                }
            }

            if (isExpired)
            {
                // Let myself know that I am in the process of dying
                _state = ProjectileState.Dying;

                // Tell the map to drop me, and drop reference to the map.
                _map.Remove(this.Token);
                _map.Collisions -= new CollisionsDelegate(Map_Collisions);
                _map             = null;
            }
        }
示例#8
0
        private void Explode()
        {
            if (_state != ProjectileState.Flying)
            {
                throw new InvalidOperationException("Explode was called when not in a flying state: " + _state.ToString());
            }

            // Drop my velocity to zero (In case somebody asks what my velocity is)
            //TODO:  May want to go into a ghost state, but if I do, the map won't do any collision detection, and nothing will know
            // to add more pain
            base.Ball.Velocity.StoreNewValues(new MyVector());

            // Explode myself
            if (_explosion != null)
            {
                base.Ball.Radius = _explosion.Radius;
            }

            // Store my new state
            _state = ProjectileState.Exploding;

            // Don't do any other collision physics
            base.CollisionStyle = CollisionStyle.Ghost;

            if (_explosion == null)
            {
                // This will put me straight into a dying state (after removing me from the map)
                Exploding();
            }
        }
 private void OnTriggerEnter(Collider other)
 {
     if (other.tag == "Pirate")
     {
         other.gameObject.GetComponent <Pirate>().Donk();
         currentState = ProjectileState.RETURNING;
     }
 }
示例#10
0
    public void SetState(ProjectileState state)
    {
        if (currentState != null)
        {
            currentState.OnStateLeave();
        }

        currentState = state;
        currentState.OnStateEntered();
    }
示例#11
0
 public virtual void Destroy()
 {
     state = ProjectileState.Idle;
     StopAllCoroutines ();
     if (CachePool<Projectile>.Instance.ReturnObject (this)) {
         gameObject.SetActive (false);
     } else {
         DestroyObject (gameObject);
     }
 }
示例#12
0
    public virtual void Launch(Transform origin)
    {
        tag = origin.gameObject.tag;
        transform.rotation = origin.rotation;
        transform.position = origin.position;
        gameObject.SetActive (true);

        state = ProjectileState.Fly;
        StartCoroutine (AutoDestroy ());
    }
 public void Fire()
 {
     if (currentState == ProjectileState.WAITING)
     {
         myCollider.isTrigger = true;
         ballisticEndPoint    = transform.position + transform.forward + transform.forward.normalized * maxDistance;
         transform.SetParent(null);
         currentState = ProjectileState.FIRING;
     }
 }
示例#14
0
    public void Launch(float force)
    {
        state     = ProjectileState.inFlight;
        restTimer = 0.5f;

        lastPosition = transform.position;

        Release();

        projectileBody.velocity = transform.forward * force;
        if (trail)
        {
            trail.enabled = true;
        }
    }
示例#15
0
            public SpitProjectile(Vector2 launch_position, float angle)
            {
                this.position     = launch_position;
                original_position = Vector2.Zero;
                velocity          = new Vector2((float)(8 * Math.Cos(angle)), (float)(8 * Math.Sin(angle)));
                dimensions        = new Vector2(10, 10);
                scale             = 0.0f;

                projectile_state = ProjectileState.Travel;
                alive_timer      = 0.0f;
                damage_timer     = 0.0f;

                on_wall       = false;
                nextStep_temp = Vector2.Zero;
                active        = true;
            }
示例#16
0
        internal void DestroyProjectile()
        {
            if (State == ProjectileState.Destroy)
            {
                Info.Hit = new Hit {
                    Block = null, Entity = null, SurfaceHit = Position, LastHit = Position, HitVelocity = Info.InPlanetGravity ? Velocity * 0.33f : Velocity, HitTick = Info.System.Session.Tick
                };
                if (EnableAv || Info.ConsumableDef.Const.VirtualBeams)
                {
                    Info.AvShot.ForceHitParticle = true;
                    Info.AvShot.Hit = Info.Hit;
                }

                Intersecting = true;
            }

            State = ProjectileState.Depleted;
        }
示例#17
0
    public void Deactivate()
    {
        if (_fxHelper != null)
        {
            //_fxHelper.StopAll();
        }

        _state = ProjectileState.kInactive;

        transform.position   = Vector3.zero;
        transform.rotation   = Quaternion.identity;
        transform.localScale = Vector3.one;

        if (_deactivateCallback != null)
        {
            _deactivateCallback();
            _deactivateCallback = null;
        }
    }
示例#18
0
        public override void Reset()
        {
            id       = -1;
            state    = ProjectileState.None;
            speed    = FixVector3.zero;
            mark     = ForceMark.NoneForce;
            position = FixVector3.zero;
            owner    = null;
            target   = null;
            targetId = 0;

            lifeTimer = 0;
            changeDataWhenTargetDeath = false;
            maxDistance = -1;
            attributEffects.Clear();

            PostRenderMessage = null;
            PostDestroy       = null;
            GetRandomNumber   = null;
        }
示例#19
0
        protected virtual void FlyingOperation(int deltaTime)
        {
            if (IsHit())
            {
                state = ProjectileState.Hit;
            }
            else if (IsTimeOut(deltaTime))
            {
                lifeTimer = 0;

                TimeOut();
            }
            else if (IsDistanceOut())
            {
                targetDistance = 0;

                DebugUtils.Log(DebugUtils.Type.AI_Projectile, string.Format("Projectile {0} enter Distance state", id));

                DistanceOut();
            }
        }
示例#20
0
    void Update()
    {
        switch (state)
        {
        case ProjectileState.Flying:
            var flightResult = Fly();
            transform.rotation = flightResult.Item1;
            var pos = flightResult.Item2;

            if (Vector3.Distance(pos, targetPosition) < 2)
            {
                state = ProjectileState.StartsFalling;

                if (transform.position == lastPosition)
                {
                    Destroy(this);
                }
                lastPosition = transform.position;
            }

            transform.position = pos;
            break;

        case ProjectileState.StartsFalling:
            rigidbody.constraints = RigidbodyConstraints.None;
            rigidbody.velocity    = (transform.position - lastPosition) / Time.deltaTime;
            this.enabled          = false;
            Destroy(this);
            Destroy(gameObject, 12f);

            break;

        case ProjectileState.Stuck:
            // to ewentualnie jak bedzie smok, zobaczymy czy chcemy żeby się wbijały
            break;

        default:
            throw new UnityException("Switch case unhandled");
        }
    }
 private void Start()
 {
     currentState = new InitialState(this);
     actions      = new IAction[0];
     // playerChar = GameObject.FindGameObjectWithTag("Player");
     initialState     = new InitialState(this);
     advanceState     = new AdvanceState(this);
     retreatState     = new RetreatState(this);
     projectileState  = new ProjectileState(this);
     antiAirState     = new AntiAirState(this);
     aerialState      = new AerialState(this);
     jumpState        = new JumpState(this);
     aggression       = 0.0f;
     jumpChance       = 0;
     aerialChance     = 0;
     dpChance         = 0;
     projectileChance = 0;
     idleChance       = 0;
     retreatChance    = 0;
     advanceChance    = 0;
     totalTime        = 0;
 }
示例#22
0
    private void OnHit()
    {
        if (_owner != null)
        {
            Vector3 hitPosition = transform.position;

            AttributeData attr = _owner.OnGetAttributeData("GetHitPoint");
            hitPosition.z = attr.HitPoint.z;              // this will move the hit point to the center of the body, much more accurate for "spawn at hit point" effects
        }

        StopEffects(_onSpawnEvents);
        PlayEffects(_onHitEvents);

        if (_projectileEventInfo._projectileProperties._isBoomerang)
        {
            _state = ProjectileState.kReturn;
        }
        else
        {
            Deactivate();
        }
    }
示例#23
0
    void ExplodeProjectile()
    {
        Utilities.DebugLog("Projectile.ExplodeProjectile ()");
        if (this.tcScript)
        {
            GameObject explosion = (GameObject)Instantiate(this.tcScript.explosionPrefab, this.gameObject.transform.position, this.gameObject.transform.rotation);
            explosion.transform.position = new Vector3(explosion.transform.position.x, explosion.transform.position.y, -0.1f);
            ParticleSystem particleSystem = explosion.GetComponent <ParticleSystem> ();
            if (particleSystem)
            {
                particleSystem.GetComponent <Renderer> ().sortingOrder = 32767;
            }
            this.currentState = ProjectileState.PROJECTILE_STATE_PENDING_DESTROY;
            //Destroy (explosion, 1.0f);
            Destroy(gameObject, 0.0f);

            // Deal splash damage
            float damageRange = BALLISTIC_PROJECTILE_SPLASH_DAMAGE_RANGE;
            if (this.isBazooka)
            {
                damageRange *= 0.4f;
                if (particleSystem)
                {
                    particleSystem.startSize = 0.85f;
                }
            }
            if (this.isGrenadeLauncher)
            {
                damageRange *= 0.3f;
                if (particleSystem)
                {
                    particleSystem.startSize = 0.7f;
                }
            }
            this.tcScript.DealDamageWithFalloffToUnitsWithinRange(this.gameObject.transform.position, damageRange, this.attack * BALLISTIC_PROJECTILE_SPLASH_DAMAGE_PERCENTAGE, this.gameObject);
        }
    }
示例#24
0
    void FixedUpdate()
    {
        if (state == ProjectileState.inFlight)
        {
            Transform t = transform;
            if (transformToSpin)
            {
                t = transformToSpin;
            }

            if (hasFeathers && spinInFlight.magnitude.RoughlyEquals(0f))
            {
                t.forward = Vector3.Slerp(transform.forward, projectileBody.velocity.normalized, Time.fixedDeltaTime * 5f);
            }
            else
            {
                t.Rotate(spinInFlight * Time.fixedDeltaTime, Space.Self);
            }
        }

        if (state == ProjectileState.deflected)
        {
            if (projectileBody.velocity.magnitude.RoughlyEquals(0f))
            {
                restTimer -= Time.fixedDeltaTime;
            }

            if (restTimer <= 0f)
            {
                state = ProjectileState.atRest;
            }
        }

        lastPosition = transform.position;
        lastVel      = projectileBody.velocity;
        lastAngVel   = projectileBody.angularVelocity;
    }
 // Performs actions for tracing state.
 IList<IAction> Trace()
 {
     // Delimit time of tracing state expiration.
     float explosionTime = Time.time + this.LifeTime;
     // Set current state to tracing.
     ProjectileState currentState = ProjectileState.Tracing;
     // Create single-step action triggering tracing action on.
     IAction goTrace = new CustomAction(
         () => {
             // Set current state to tracing.
             this.state = currentState;
             // Stop audio source.
             this.audio.Stop();
         });
     // Create continuous action steering projectile motion.
     IAction tracing = new CustomAction(
         () => {
             // Moves projectile position to approximate target point.
             this.StepToTarget();
         },
         // Action is active while:
         () => this.IsInCurrentState(currentState)			// state of projectile hasn't been modified,
             && !this.IsTimeOut(explosionTime));				// tracing timeout doesn't occured.
     // Create single-step action choosing next state.
     IAction next = new CustomAction(
         () => {
             // If skeleton has remained in flying state
             if (this.IsInCurrentState(currentState)
                 // or got hit
                 || this.state == ProjectileState.Hit) {
                 // then explode.
                 this.actionQueue.Enqueue(this.Explode());
             } else {
                 throw new InvalidProgramException("Unreacheable code");
             }
         });
     return new List<IAction> { goTrace, tracing, next };
 }
示例#26
0
        private void Exploding()
        {
            // Keep setting my velocity back to zero
            base.Ball.Velocity.StoreNewValues(new MyVector());

            // See if enough time has gone by
            bool isExpired = false;
            if (_explosion == null)
            {
                isExpired = true;
            }
            else
            {
                // Bump up my elapsed time
                _explosion.ElapsedTime += _curTickElapsedTime;

                if (_explosion.ElapsedTime > _explosion.Duration)
                {
                    isExpired = true;
                }
            }

            if (isExpired)
            {
                // Let myself know that I am in the process of dying
                _state = ProjectileState.Dying;

                // Tell the map to drop me, and drop reference to the map.
                _map.Remove(this.Token);
                _map.Collisions -= new CollisionsDelegate(Map_Collisions);
                _map = null;
            }
        }
示例#27
0
        private void Explode()
        {
            if (_state != ProjectileState.Flying)
            {
                throw new InvalidOperationException("Explode was called when not in a flying state: " + _state.ToString());
            }

            // Drop my velocity to zero (In case somebody asks what my velocity is)
            //TODO:  May want to go into a ghost state, but if I do, the map won't do any collision detection, and nothing will know
            // to add more pain
            base.Ball.Velocity.StoreNewValues(new MyVector());

            // Explode myself
            if (_explosion != null)
            {
                base.Ball.Radius = _explosion.Radius;
            }

            // Store my new state
            _state = ProjectileState.Exploding;

            // Don't do any other collision physics
            base.CollisionStyle = CollisionStyle.Ghost;

            if (_explosion == null)
            {
                // This will put me straight into a dying state (after removing me from the map)
                Exploding();
            }
        }
示例#28
0
            public void update(LevelState parentWorld, GameTime currentTime, Entity parent)
            {
                if (active)
                {
                    parentWorld.Particles.pushDotParticle(position + new Vector2((float)Game1.rand.NextDouble() * dimensions.X, (float)Game1.rand.NextDouble() * dimensions.Y), (float)(1.5 * Math.PI), Color.DarkGreen);
                }

                switch (projectile_state)
                {
                case ProjectileState.Travel:
                    alive_timer += currentTime.ElapsedGameTime.Milliseconds;
                    position    += velocity;

                    if (alive_timer > max_alive_timer)
                    {
                        alive_timer       = 0.0f;
                        projectile_state  = ProjectileState.GrowPool;
                        original_position = CenterPoint;
                    }
                    else
                    {
                        nextStep_temp = new Vector2(position.X - (dimensions.X / 2) + velocity.X, (position.Y + velocity.X));

                        on_wall = parentWorld.Map.hitTestWall(nextStep_temp);
                        int check_corners = 0;
                        while (check_corners != 4)
                        {
                            if (on_wall == false)
                            {
                                if (check_corners == 0)
                                {
                                    nextStep_temp = new Vector2(position.X + (dimensions.X / 2) + velocity.X, position.Y + velocity.Y);
                                }
                                else if (check_corners == 1)
                                {
                                    nextStep_temp = new Vector2(position.X + velocity.X, position.Y - (dimensions.Y / 2) + velocity.Y);
                                }
                                else if (check_corners == 2)
                                {
                                    nextStep_temp = new Vector2(position.X + velocity.X, position.Y + dimensions.Y + velocity.Y);
                                }
                                else
                                {
                                    position += velocity;
                                }
                                on_wall = parentWorld.Map.hitTestWall(nextStep_temp);
                            }
                            else
                            {
                                projectile_state  = ProjectileState.GrowPool;
                                alive_timer       = 0.0f;
                                original_position = CenterPoint;
                                break;
                            }
                            check_corners++;
                        }

                        if (on_wall == false)
                        {
                            foreach (Entity en in parentWorld.EntityList)
                            {
                                if (en == parent || (en.Enemy_Type == EnemyType.Alien))
                                {
                                    continue;
                                }
                                else if (spitHitTest(en))
                                {
                                    projectile_state  = ProjectileState.GrowPool;
                                    alive_timer       = 0.0f;
                                    original_position = CenterPoint;
                                }
                            }
                        }
                    }
                    break;

                case ProjectileState.GrowPool:
                    damage_timer += currentTime.ElapsedGameTime.Milliseconds;
                    if (dimensions.X < max_dimensions && dimensions.Y < max_dimensions)
                    {
                        scale       = (dimensions.X + 1) / scale_factor;
                        dimensions += new Vector2(1, 1);
                        position    = original_position - (dimensions / 2);
                        alive_timer = 0.0f;
                        if (damage_timer > damage_timer_threshold)
                        {
                            foreach (Entity en in parentWorld.EntityList)
                            {
                                if (spitHitTest(en))
                                {
                                    if (en is Enemy && !(en is MutantAcidSpitter))
                                    {
                                        ((Enemy)en).Enemy_Life -= acid_damage;
                                    }
                                    else if (en is Player)
                                    {
                                        if (((Player)en).Index == InputDevice2.PPG_Player.Player_1)
                                        {
                                            GameCampaign.Player_Health -= acid_damage;
                                        }
                                        else if (((Player)en).Index == InputDevice2.PPG_Player.Player_2)
                                        {
                                            GameCampaign.Player2_Health -= acid_damage;
                                        }
                                    }
                                }
                            }
                            damage_timer = 0.0f;
                        }
                    }
                    else
                    {
                        projectile_state = ProjectileState.IdlePool;

                        /*alive_timer += currentTime.ElapsedGameTime.Milliseconds;
                         * if (alive_timer > max_pool_alive_timer)
                         * {
                         *  alive_timer = 0.0f;
                         *  projectile_state = ProjectileState.Reset;
                         * }*/
                    }
                    break;

                case ProjectileState.IdlePool:
                    alive_timer  += currentTime.ElapsedGameTime.Milliseconds;
                    damage_timer += currentTime.ElapsedGameTime.Milliseconds;
                    if (damage_timer > damage_timer_threshold)
                    {
                        foreach (Entity en in parentWorld.EntityList)
                        {
                            if (spitHitTest(en))
                            {
                                if (en is Enemy && !(en is MutantAcidSpitter))
                                {
                                    ((Enemy)en).Enemy_Life -= acid_damage;
                                }
                                else if (en is Player)
                                {
                                    if (((Player)en).Index == InputDevice2.PPG_Player.Player_1)
                                    {
                                        GameCampaign.Player_Health -= acid_damage;
                                    }
                                    else if (((Player)en).Index == InputDevice2.PPG_Player.Player_2)
                                    {
                                        GameCampaign.Player2_Health -= acid_damage;
                                    }
                                }
                            }
                        }
                        damage_timer = 0.0f;
                    }
                    if (alive_timer > max_pool_alive_timer)
                    {
                        alive_timer      = 0.0f;
                        projectile_state = ProjectileState.DecreasePool;
                    }
                    break;

                case ProjectileState.DecreasePool:
                    damage_timer += currentTime.ElapsedGameTime.Milliseconds;
                    if (dimensions.X > 0 && dimensions.Y > 0)
                    {
                        if (dimensions.X - 1 != 0)
                        {
                            scale = (dimensions.X - 1) / scale_factor;
                        }
                        else
                        {
                            scale = 0.0f;
                        }
                        dimensions -= new Vector2(1, 1);
                        position    = original_position - (dimensions / 2);
                        if (damage_timer > damage_timer_threshold)
                        {
                            foreach (Entity en in parentWorld.EntityList)
                            {
                                if (spitHitTest(en))
                                {
                                    if (en is Enemy && !(en is MutantAcidSpitter))
                                    {
                                        ((Enemy)en).Enemy_Life -= acid_damage;
                                    }
                                    else if (en is Player)
                                    {
                                        if (((Player)en).Index == InputDevice2.PPG_Player.Player_1)
                                        {
                                            GameCampaign.Player_Health -= acid_damage;
                                        }
                                        else if (((Player)en).Index == InputDevice2.PPG_Player.Player_2)
                                        {
                                            GameCampaign.Player2_Health -= acid_damage;
                                        }
                                    }
                                }
                            }
                            damage_timer = 0.0f;
                        }
                    }
                    else
                    {
                        active = false;
                    }
                    break;

                default:
                    break;
                }
            }
    void Run()
    {
        activationTime = 0;

        // Create a base GameObject to attach the projectile particle and/or object to
        projectile = new GameObject();
        projectile.name = name;

        // If we have a projectile particle, create an instance of it then attach it to the projectile
        if (projectileParticle != null) {
            GameObject effectParticle = (GameObject)Instantiate (projectileParticle.gameObject);
            effectParticle.transform.position = projectile.transform.position;
            effectParticle.transform.parent = projectile.transform;
        }

        // If we have a projectile particle, create an instance of it then attach it to the projectile
        if (projectileObject != null) {
            GameObject effectObject = (GameObject)Instantiate (projectileObject);
            effectObject.transform.position = projectile.transform.position;
            effectObject.transform.parent = projectile.transform;
        }

        // If we have a projectile particle, create an instance of it then attach it to the projectile
        if (projectileSound != null) {
            AudioSource audioSource = projectile.AddComponent<AudioSource>();
            audioSource.clip = projectileSound;
            audioSource.Play();
        }

        // Set the starting position to the specified slot of the caster
        ObjectNode node = ClientAPI.WorldManager.GetObjectNode(casterOid);
        Vector3 projectilePosition = node.GameObject.GetComponent<AtavismMobAppearance>().GetSocketTransform(casterSlot).position;
        projectile.transform.position = projectilePosition;

        // Get the target transform
        node = ClientAPI.WorldManager.GetObjectNode(targetOid);
        targetTransform = node.GameObject.GetComponent<AtavismMobAppearance>().GetSocketTransform(targetSlot);
        state = ProjectileState.Moving;
    }
    // Update is called once per frame
    void Update()
    {
        if (activationTime != 0 && Time.time > activationTime) {
            Run();
        }

        // If the projectile is moving, move it towards the target
        if (state == ProjectileState.Moving) {
            // Work out how far it should travel this frame
            float distanceToTravel = speed * Time.deltaTime;
            Vector3 newLoc = Vector3.MoveTowards(projectile.transform.position, targetTransform.position, distanceToTravel);
            projectile.transform.position = newLoc;
            Debug.Log("Moving " + name + " to loc: " + newLoc);
            // Check if we have hit the target
            if (newLoc == targetTransform.position) {
                state = ProjectileState.Hit;
                Destroy(projectile);
                PlayHit();
            }
        }
    }
 // Determines whether specified state equals projectile state.
 bool IsInCurrentState(ProjectileState currentState)
 {
     return this.state == currentState;
 }
 // Reacts on collision with projectile collider.
 void OnCollisionEnter(Collision collision)
 {
     if (this.state != ProjectileState.Hit) {
         this.state = ProjectileState.Hit;
     }
 }
示例#33
0
 public void Pause()
 {
     Utilities.DebugLog("Projectile.Pause ()");
     this.currentState = ProjectileState.PROJECTILE_STATE_PAUSED;
 }
示例#34
0
    private void DefaultUpdate()
    {
        // don't update if player's frozen
        //if( _owner != null && _owner.Animator.speed == 0.0f )
        //{
        //return;
        //}

        //_previousPosition = GetCenter();

        switch (_state)
        {
        case ProjectileState.kSpwaned:
            _state = ProjectileState.kActive;
            break;

        case ProjectileState.kActive:
        {
            AttributeData attr = _owner.OnGetAttributeData("GetTargetPosition");
            Vector3       dir  = _owner != null ? attr.TargetPosition - GetCenter() : Vector3.right;
            //dir.y = 0.0f;//set y to zero to calculate motion on xoz plane.
            Vector3 displacement = dir * _speed * Time.deltaTime;
            Vector3 pos          = transform.position;
            pos += displacement;
            //caculate motion on y
            float offset_y = _motionCurve.Evaluate(System.Math.Min(Time.realtimeSinceStartup - _startTime / _duration, 1.0f));
            pos.y += offset_y;
            Quaternion rotation = Quaternion.LookRotation(pos - transform.position);
            transform.rotation = rotation;
            transform.position = pos;

            if (_owner != null)
            {
                //float prevPosX = _previousPosition.x;
                //float currPosX = GetCenter().x;

                //float minPosX = Mathf.Min(prevPosX, currPosX);
                //float maxPosX = Mathf.Max(prevPosX, currPosX);
                float distance = Vector3.Distance(GetCenter(), attr.TargetPosition);

                if (distance < 0.05f)
                {
                    OnHit();
                    break;
                }
            }

            // TODO: is it safe to assume that projectiles will never hit walls - since it'll always hit a player first?

            break;
        }

        case ProjectileState.kReturn:
        {
            if (UpdateReturn())
            {
                Deactivate();
            }
            break;
        }

        default:
            break;
        }
    }
示例#35
0
 // Use this for initialization
 void Awake()
 {
     _fxHelper = GetComponent <MoveEditor.FXHelper>();
     _state    = ProjectileState.kInactive;
 }
示例#36
0
 public void Resume()
 {
     Utilities.DebugLog("Projectile.Resume ()");
     this.currentState = ProjectileState.PROJECTILE_STATE_ACTIVE;
 }
 // Performs actions for exploding state.
 IList<IAction> Explode()
 {
     // Delimit time of exploding state expiration.
     float destructionTime = Time.time + this.TimeToDestroy;
     // Set current state to exploding.
     ProjectileState currentState = ProjectileState.Exploding;
     // Create single-step action triggering explode action on.
     IAction goExploding = new CustomAction(
         () => {
             // Set current state to exploding.
             this.state = currentState;
             // Obtain emmiter of smoke trail effect.
             ParticleEmitter emitter = GameObject.Find("/Projectile/Smoke Trail").particleEmitter;
             // Shut the emmision down.
             emitter.minEmission = 0;
             emitter.maxEmission = 0;
             // Obtain emmiter of fireworks effect.
             emitter = GameObject.Find("/Projectile/Fireworks").particleEmitter;
             // Turn the emmision on.
             emitter.minEmission = 200;
             emitter.maxEmission = 300;
             // Play explosion sound.
             audio.Play();
         });
     // Create continuous action doing nothing.
     IAction exploding = new CustomAction(
         () => { },		// Does nothing but waiting for termination condition come into being.
         // Action is active while:
         () => this.IsInCurrentState(currentState)			// state of projectile hasn't been modified,
             && !this.IsTimeOut(destructionTime));			// exploding timeout doesn't occured.
     // Create single-step action destructing current projectile.
     IAction destroy = new CustomAction(
         () => {
             // Destroy current projectile GameObject.
             Destroy(gameObject);
         });
     return new List<IAction> { goExploding, exploding, destroy };
 }
示例#38
0
        internal void Start()
        {
            Position = Info.Origin;
            AccelDir = Info.Direction;
            var cameraStart = Info.System.Session.CameraPos;

            Vector3D.DistanceSquared(ref cameraStart, ref Info.Origin, out DistanceFromCameraSqr);
            GenerateShrapnel = Info.ConsumableDef.Const.ShrapnelId > -1;
            var probability = Info.ConsumableDef.AmmoGraphics.VisualProbability;

            EnableAv                  = !Info.ConsumableDef.Const.VirtualBeams && !Info.System.Session.DedicatedServer && DistanceFromCameraSqr <= Info.System.Session.SyncDistSqr && (probability >= 1 || probability >= MyUtils.GetRandomDouble(0.0f, 1f));
            ModelState                = EntityState.None;
            LastEntityPos             = Position;
            LastHitEntVel             = null;
            Info.AvShot               = null;
            Info.Age                  = -1;
            ChaseAge                  = 0;
            NewTargets                = 0;
            ZombieLifeTime            = 0;
            LastOffsetTime            = 0;
            PruningProxyId            = -1;
            EntitiesNear              = false;
            CachedPlanetHit           = false;
            PositionChecked           = false;
            MineSeeking               = false;
            MineActivated             = false;
            MineTriggered             = false;
            LinePlanetCheck           = false;
            AtMaxRange                = false;
            ShieldBypassed            = false;
            FakeGravityNear           = false;
            HadTarget                 = false;
            WasTracking               = false;
            Intersecting              = false;
            EndStep                   = 0;
            Info.PrevDistanceTraveled = 0;
            Info.DistanceTraveled     = 0;
            PrevEndPointToCenterSqr   = double.MaxValue;


            CachedId        = Info.MuzzleId == -1 ? Info.WeaponCache.VirutalId : Info.MuzzleId;
            Guidance        = Info.ConsumableDef.Trajectory.Guidance;
            DynamicGuidance = Guidance != GuidanceType.None && Guidance != GuidanceType.TravelTo && !Info.ConsumableDef.Const.IsBeamWeapon && Info.EnableGuidance;
            if (DynamicGuidance)
            {
                DynTrees.RegisterProjectile(this);
            }
            FeelsGravity = Info.ConsumableDef.Const.FeelsGravity;

            Info.MyPlanet = Info.Ai.MyPlanet;
            if (!Info.System.Session.VoxelCaches.TryGetValue(Info.UniqueMuzzleId, out Info.VoxelCache))
            {
                Log.Line($"ProjectileStart VoxelCache Failure with Id:{Info.UniqueMuzzleId} BlockMarked:{Info.Target.FiringCube?.MarkedForClose}, setting to default cache:");
                Info.VoxelCache = Info.System.Session.VoxelCaches[ulong.MaxValue];
            }
            if (Info.MyPlanet != null)
            {
                Info.VoxelCache.PlanetSphere.Center = Info.Ai.ClosestPlanetCenter;
            }

            Info.MyShield            = Info.Ai.MyShield;
            Info.InPlanetGravity     = Info.Ai.InPlanetGravity;
            Info.AiVersion           = Info.Ai.Version;
            Info.Ai.ProjectileTicker = Info.Ai.Session.Tick;

            if (Guidance == GuidanceType.Smart && DynamicGuidance)
            {
                SmartsOn     = true;
                MaxChaseTime = Info.ConsumableDef.Const.MaxChaseTime;
                SmartSlot    = Info.WeaponRng.ClientProjectileRandom.Next(10);
                Info.WeaponRng.ClientProjectileCurrentCounter++;
            }
            else
            {
                MaxChaseTime = int.MaxValue;
                SmartsOn     = false;
                SmartSlot    = 0;
            }

            if (Info.Target.IsProjectile)
            {
                OriginTargetPos = Info.Target.Projectile.Position;
                Info.Target.Projectile.Seekers.Add(this);
            }
            else if (Info.Target.Entity != null)
            {
                OriginTargetPos = Info.Target.Entity.PositionComp.WorldAABB.Center;
            }
            else
            {
                OriginTargetPos = Vector3D.Zero;
            }
            LockedTarget = !Vector3D.IsZero(OriginTargetPos);

            if (SmartsOn && Info.ConsumableDef.Const.TargetOffSet && (LockedTarget || Info.Target.IsFakeTarget))
            {
                OffSetTarget();
                OffsetSqr = Info.ConsumableDef.Trajectory.Smarts.Inaccuracy * Info.ConsumableDef.Trajectory.Smarts.Inaccuracy;
            }
            else
            {
                TargetOffSet = Vector3D.Zero;
                OffsetSqr    = 0;
            }
            PrevTargetOffset = Vector3D.Zero;

            var targetSpeed = (float)(!Info.ConsumableDef.Const.IsBeamWeapon ? Info.ConsumableDef.Trajectory.DesiredSpeed : Info.MaxTrajectory * MyEngineConstants.UPDATE_STEPS_PER_SECOND);

            if (Info.ConsumableDef.Const.SpeedVariance && !Info.ConsumableDef.Const.IsBeamWeapon)
            {
                var min           = Info.ConsumableDef.Trajectory.SpeedVariance.Start;
                var max           = Info.ConsumableDef.Trajectory.SpeedVariance.End;
                var speedVariance = (float)Info.WeaponRng.ClientProjectileRandom.NextDouble() * (max - min) + min;
                Info.WeaponRng.ClientProjectileCurrentCounter++;
                DesiredSpeed = targetSpeed + speedVariance;
            }
            else
            {
                DesiredSpeed = targetSpeed;
            }

            float variance = 0;

            if (Info.ConsumableDef.Const.RangeVariance)
            {
                var min = Info.ConsumableDef.Trajectory.RangeVariance.Start;
                var max = Info.ConsumableDef.Trajectory.RangeVariance.End;
                variance            = (float)Info.WeaponRng.ClientProjectileRandom.NextDouble() * (max - min) + min;
                Info.MaxTrajectory -= variance;
                Info.WeaponRng.ClientProjectileCurrentCounter++;
            }

            if (Vector3D.IsZero(PredictedTargetPos))
            {
                PredictedTargetPos = Position + (AccelDir * Info.MaxTrajectory);
            }
            PrevTargetPos       = PredictedTargetPos;
            PrevTargetVel       = Vector3D.Zero;
            Info.ObjectsHit     = 0;
            Info.BaseHealthPool = Info.ConsumableDef.Health;
            Info.BaseEwarPool   = Info.ConsumableDef.Health;
            Info.TracerLength   = Info.ConsumableDef.Const.TracerLength <= Info.MaxTrajectory ? Info.ConsumableDef.Const.TracerLength : Info.MaxTrajectory;

            MaxTrajectorySqr = Info.MaxTrajectory * Info.MaxTrajectory;

            if (!Info.IsShrapnel)
            {
                StartSpeed = Info.ShooterVel;
            }

            MoveToAndActivate = LockedTarget && !Info.ConsumableDef.Const.IsBeamWeapon && Guidance == GuidanceType.TravelTo;

            if (MoveToAndActivate)
            {
                var distancePos = !Vector3D.IsZero(PredictedTargetPos) ? PredictedTargetPos : OriginTargetPos;
                if (variance > 0)
                {
                    var forward = Info.WeaponRng.ClientProjectileRandom.Next(100) < 50;
                    Info.WeaponRng.ClientProjectileCurrentCounter++;
                    distancePos = forward ? distancePos + (AccelDir * variance) : distancePos + (-AccelDir * variance);
                }
                Vector3D.DistanceSquared(ref Info.Origin, ref distancePos, out DistanceToTravelSqr);
            }
            else
            {
                DistanceToTravelSqr = MaxTrajectorySqr;
            }

            PickTarget = Info.ConsumableDef.Trajectory.Smarts.OverideTarget && !Info.Target.IsFakeTarget && !Info.LockOnFireState;
            if (PickTarget || LockedTarget)
            {
                NewTargets++;
            }

            var staticIsInRange  = Info.Ai.ClosestStaticSqr * 0.5 < MaxTrajectorySqr;
            var pruneStaticCheck = Info.Ai.ClosestPlanetSqr * 0.5 < MaxTrajectorySqr || Info.Ai.StaticGridInRange;

            PruneQuery = (DynamicGuidance && pruneStaticCheck) || FeelsGravity && staticIsInRange || !DynamicGuidance && !FeelsGravity && staticIsInRange ? MyEntityQueryType.Both : MyEntityQueryType.Dynamic;

            if (Info.Ai.PlanetSurfaceInRange && Info.Ai.ClosestPlanetSqr <= MaxTrajectorySqr)
            {
                LinePlanetCheck = true;
                PruneQuery      = MyEntityQueryType.Both;
            }

            if (DynamicGuidance && PruneQuery == MyEntityQueryType.Dynamic && staticIsInRange)
            {
                CheckForNearVoxel(60);
            }

            var accelPerSec = Info.ConsumableDef.Trajectory.AccelPerSec;

            ConstantSpeed       = accelPerSec <= 0;
            AccelInMetersPerSec = accelPerSec > 0 ? accelPerSec : DesiredSpeed;
            var desiredSpeed     = (AccelDir * DesiredSpeed);
            var relativeSpeedCap = StartSpeed + desiredSpeed;

            MaxVelocity          = relativeSpeedCap;
            MaxSpeed             = MaxVelocity.Length();
            MaxSpeedSqr          = MaxSpeed * MaxSpeed;
            DeltaVelocityPerTick = accelPerSec * StepConst;
            AccelVelocity        = (AccelDir * DeltaVelocityPerTick);

            if (ConstantSpeed)
            {
                Velocity          = MaxVelocity;
                VelocityLengthSqr = MaxSpeed * MaxSpeed;
            }
            else
            {
                Velocity = StartSpeed + AccelVelocity;
            }

            if (Info.IsShrapnel)
            {
                Vector3D.Normalize(ref Velocity, out Info.Direction);
            }

            InitalStep = !Info.IsShrapnel && ConstantSpeed ? desiredSpeed * StepConst : Velocity * StepConst;

            TravelMagnitude = Velocity * StepConst;
            FieldTime       = Info.ConsumableDef.Const.Ewar || Info.ConsumableDef.Const.IsMine ? Info.ConsumableDef.Trajectory.FieldTime : 0;
            State           = !Info.ConsumableDef.Const.IsBeamWeapon ? ProjectileState.Alive : ProjectileState.OneAndDone;

            if (EnableAv)
            {
                Info.AvShot = Info.System.Session.Av.AvShotPool.Get();
                Info.AvShot.Init(Info, AccelInMetersPerSec * StepConst, MaxSpeed, ref AccelDir);
                Info.AvShot.SetupSounds(DistanceFromCameraSqr); //Pool initted sounds per Projectile type... this is expensive
                if (Info.ConsumableDef.Const.HitParticle && !Info.ConsumableDef.Const.IsBeamWeapon || Info.ConsumableDef.Const.AreaEffect == AreaEffectType.Explosive && !Info.ConsumableDef.AreaEffect.Explosions.NoVisuals && Info.ConsumableDef.Const.AreaEffectSize > 0 && Info.ConsumableDef.Const.AreaEffectDamage > 0)
                {
                    var hitPlayChance = Info.ConsumableDef.AmmoGraphics.Particles.Hit.Extras.HitPlayChance;
                    Info.AvShot.HitParticleActive = hitPlayChance >= 1 || hitPlayChance >= MyUtils.GetRandomDouble(0.0f, 1f);
                }
                Info.AvShot.FakeExplosion = Info.AvShot.HitParticleActive && Info.ConsumableDef.Const.AreaEffect == AreaEffectType.Explosive && Info.ConsumableDef.AmmoGraphics.Particles.Hit.Name == string.Empty;
            }

            if (!Info.ConsumableDef.Const.PrimeModel && !Info.ConsumableDef.Const.TriggerModel)
            {
                ModelState = EntityState.None;
            }
            else
            {
                if (EnableAv)
                {
                    ModelState = EntityState.Exists;

                    double triggerModelSize = 0;
                    double primeModelSize   = 0;
                    if (Info.ConsumableDef.Const.TriggerModel)
                    {
                        triggerModelSize = Info.AvShot.TriggerEntity.PositionComp.WorldVolume.Radius;
                    }
                    if (Info.ConsumableDef.Const.PrimeModel)
                    {
                        primeModelSize = Info.AvShot.PrimeEntity.PositionComp.WorldVolume.Radius;
                    }
                    var largestSize = triggerModelSize > primeModelSize ? triggerModelSize : primeModelSize;

                    Info.AvShot.ModelSphereCurrent.Radius = largestSize * 2;
                }
            }

            if (EnableAv)
            {
                LineOrNotModel        = Info.ConsumableDef.Const.DrawLine || ModelState == EntityState.None && Info.ConsumableDef.Const.AmmoParticle;
                Info.AvShot.ModelOnly = !LineOrNotModel && ModelState == EntityState.Exists;
            }
        }
示例#39
0
    private void AutoVelocityUpdate()
    {
        // don't update if player's frozen
        //if( _owner != null && _owner.Animator.speed == 0.0f )
        //{
        //return;
        //}

        //_previousPosition = GetCenter();

        switch (_state)
        {
        case ProjectileState.kSpwaned: _state = ProjectileState.kActive; break;                 // don't displace on spawn frame

        case ProjectileState.kActive:
        {
            #region [GM]

            /*Vector3 dir = _owner != null ? _owner.transform.forward : Vector3.right;
             * dir.y = 0.0f;//set y to zero to calculate motion on xoz plane.*/

            AttributeData attr = _owner.OnGetAttributeData("GetTargetRadius");

            Vector3 dir = (attr.TargetPosition + new Vector3(0, attr.TargetRadius, 0) - transform.position).normalized;
            #endregion

            Vector3 displacement = dir * _speed * Time.deltaTime;
            Vector3 pos          = transform.position;
            pos += displacement;
            //calculate motion on y
            float offset_y = _motionCurve.Evaluate(System.Math.Min(Time.realtimeSinceStartup - _startTime / _duration, 1.0f));
            pos.y += offset_y;
            Quaternion rotation = Quaternion.LookRotation(pos - transform.position);
            transform.rotation = rotation;
            transform.position = pos;

            if (_owner != null)
            {
                #region [GM]

                /*float prevPosX = _previousPosition.x;
                 * float currPosX = GetCenter().x;
                 *
                 * float minPosX = Mathf.Min(prevPosX, currPosX);
                 * float maxPosX = Mathf.Max(prevPosX, currPosX);
                 * float opponentPosX = _owner.GetTargetPosition().x;
                 * float opponentRadius = _owner.GetTargetRadius();
                 *
                 * if( GameplayUtils.RangeIntersect( minPosX, maxPosX, opponentPosX - opponentRadius, opponentPosX + opponentRadius ) )
                 * {
                 *      OnHit();
                 *      break;
                 * }*/

                // [GM] to simplify hit detection, we check the time in place of complicated distance measurement
                if (Time.time >= impactTime)
                {
                    OnHit();
                    break;
                }
                #endregion
            }

            // TODO: is it safe to assume that projectiles will never hit walls - since it'll always hit a player first?

            break;
        }

        case ProjectileState.kReturn:
        {
            if (UpdateReturn())
            {
                Deactivate();
            }
            break;
        }

        default:
            break;
        }
    }
示例#40
0
        internal void ProjectileClose()
        {
            if (GenerateShrapnel && Info.Age >= Info.ConsumableDef.Const.MinArmingTime)
            {
                SpawnShrapnel();
            }

            for (int i = 0; i < Watchers.Count; i++)
            {
                Watchers[i].DeadProjectiles.Add(this);
            }
            Watchers.Clear();

            foreach (var seeker in Seekers)
            {
                seeker.Info.Target.Reset(Info.System.Session.Tick, Target.States.ProjectileClosed);
            }
            Seekers.Clear();

            if (EnableAv && Info.AvShot.ForceHitParticle)
            {
                Info.AvShot.HitEffects(true);
            }

            State = ProjectileState.Dead;

            var detInfo = Info.ConsumableDef.AreaEffect.Detonation;
            var afInfo  = Info.ConsumableDef.AreaEffect;
            var detExp  = !afInfo.Explosions.NoVisuals && (afInfo.AreaEffect == AreaEffectType.Explosive || afInfo.AreaEffect == AreaEffectType.Radiant && afInfo.Explosions.CustomParticle != string.Empty) && detInfo.DetonateOnEnd && (!detInfo.ArmOnlyOnHit || Info.ObjectsHit > 0);

            if (EnableAv)
            {
                if (ModelState == EntityState.Exists)
                {
                    ModelState = EntityState.None;
                }
                if (!Info.AvShot.Active)
                {
                    Info.System.Session.Av.AvShotPool.Return(Info.AvShot);
                }
                else
                {
                    Info.AvShot.EndState = new AvClose {
                        EndPos = Position, Dirty = true, DetonateFakeExp = detExp
                    }
                };
            }
            else if (Info.ConsumableDef.Const.VirtualBeams)
            {
                for (int i = 0; i < VrPros.Count; i++)
                {
                    var vp = VrPros[i];
                    if (!vp.AvShot.Active)
                    {
                        Info.System.Session.Av.AvShotPool.Return(vp.AvShot);
                    }
                    else
                    {
                        vp.AvShot.EndState = new AvClose {
                            EndPos = Position, Dirty = true, DetonateFakeExp = detExp
                        }
                    };

                    Info.System.Session.Projectiles.VirtInfoPool.Return(vp);
                }
                VrPros.Clear();
            }
            if (DynamicGuidance)
            {
                DynTrees.UnregisterProjectile(this);
            }

            PruningProxyId = -1;
            Info.Clean();
        }
示例#41
0
    public void Activate(Animator ownerAnimator, MoveEditor.ProjectileEventInfo projectileEventInfo, OnProjectileDeactivated callback, bool flipped)
    {
        _projectileEventInfo = projectileEventInfo;
        _deactivateCallback  = callback;
        MoveEditor.ProjectileEventProperties projectileProperties = projectileEventInfo._projectileProperties;

        Transform spawnTransform = MoveEditor.MoveUtils.GetBodyPartTransform(ownerAnimator, projectileProperties._spawnAttachment, projectileProperties._spawnAttachmentPath);

        _speed = projectileProperties._initialVelocity;

        transform.parent        = spawnTransform;
        transform.localPosition = projectileProperties._spawnOffset;

        if (projectileProperties._worldSpace)
        {
            transform.eulerAngles = projectileProperties._spawnAngles;

            if (flipped)
            {
                // rotate this by 180
                transform.RotateAround(transform.position, Vector3.up, 180.0f);
            }
        }
        else
        {
            transform.localEulerAngles = projectileProperties._spawnAngles;
        }

        // mirror the effect, for parented effects, this is done inside the attach transform
        if (flipped)
        {
            transform.rotation = FlipRotation(transform.rotation);
        }

        transform.parent     = null;
        transform.localScale = Vector3.one;

        // play all on spawn events
        PlayEffects(_onSpawnEvents);

        //_previousPosition = transform.position;

        _state = ProjectileState.kSpwaned;

        #region [GM] Projectile.
        if (_projectileEventInfo._projectileProperties._autoVelocity)
        {
            CalculateAutoVelocity();
            _state = ProjectileState.kSpwaned;             // don't displace on kSpwaned (will go to kActive on next frame)
        }
        #endregion

        _startTime = Time.realtimeSinceStartup;
        _duration  = 1.0f;
        if (_owner != null)
        {
            AttributeData attr     = _owner.OnGetAttributeData("GetTargetPosition");
            float         distance = Vector3.Distance(GetCenter(), attr.TargetPosition);
            _duration = distance / _speed;
        }
    }