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); } }
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; } }
/* 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; } }
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); }
public Projectile(Vector3 startPoint, Vector3 endPoint, float timeCons) { PState = ProjectileState.Disable; StartPoint = startPoint; EndPoint = endPoint; TimeConstant = timeCons; }
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; } }
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; } }
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; } }
public void SetState(ProjectileState state) { if (currentState != null) { currentState.OnStateLeave(); } currentState = state; currentState.OnStateEntered(); }
public virtual void Destroy() { state = ProjectileState.Idle; StopAllCoroutines (); if (CachePool<Projectile>.Instance.ReturnObject (this)) { gameObject.SetActive (false); } else { DestroyObject (gameObject); } }
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; } }
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; } }
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; }
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; }
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; } }
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; }
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(); } }
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; }
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(); } }
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); } }
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 }; }
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; } }
public void Pause() { Utilities.DebugLog("Projectile.Pause ()"); this.currentState = ProjectileState.PROJECTILE_STATE_PAUSED; }
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; } }
// Use this for initialization void Awake() { _fxHelper = GetComponent <MoveEditor.FXHelper>(); _state = ProjectileState.kInactive; }
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 }; }
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; } }
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; } }
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(); }
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; } }