public override void OnLaunch() { if (projectiles.Count > 0) { foreach (ProjectileData d in projectiles) { if (d.proj != null) { ForceDestroyProjectile(d.proj); } } } projectiles.Clear(); DeleteCastingEffect(); GameObject activeProjectile; for (int i = 0; i < projectilesCount; i++) { activeProjectile = CreateSkillProjectile("projectile_00", true); if (activeProjectile != null) { Rigidbody2D rb = activeProjectile.GetComponent <Rigidbody2D>(); rb.velocity = (GetOwnerData().GetForwardVector((Random.Range(-randomAngle, randomAngle) + CalcAngleForProjectile(i, projectilesCount, projectilesAngle))) * force); Object.Destroy(activeProjectile, GetProjectileLifetime(force)); if (SaveProjectiles()) { ProjectileData data = new ProjectileData(); data.proj = activeProjectile; data.target = null; data.interpolTimer = 0; data.rb = rb; data.penetratedTargets = 0; data.maxPenetrateTargets = maxPenetratedTargets; if (maxPenetratedTargets > 0) { data.hits = new GameObject[maxPenetratedTargets]; } if (returnBack) { data.waypoints.Push(Owner.GetData().GetBody().transform.position); } projectiles.Add(data); MonoUpdate(rb.gameObject, true); } } } }
public override void DestroyProjectile(GameObject proj, float delay = 1) { if (!returnBack) { base.DestroyProjectile(proj, delay); } else { returningBack = true; ProjectileData d = GetProjectileData(proj); if (d != null) { AdjustToTarget(d); } } }
public override void MonoUpdate(GameObject gameObject, bool fixedUpdate) { bool saveProjectiles = projectilesAim || selectTargetOnLaunch || maxPenetratedTargets > 0; if (saveProjectiles && fixedUpdate) { // updates: 10/sec if (System.Environment.TickCount % 10 == 0) { ProjectileData d = GetData(gameObject); if (d == null || d.proj == null) { return; } if (d.target == null && projectilesAim) { float angle = d.proj.transform.rotation.eulerAngles.z; foreach (RaycastHit2D hit in Physics2D.BoxCastAll(d.proj.transform.position, new Vector2(aimArea, aimArea), angle, d.rb.velocity, aimArea)) { if (hit.collider.gameObject.Equals(d.proj)) { continue; } Character targetCh = hit.collider.gameObject.GetChar(); if (targetCh == null || !Owner.CanAttack(targetCh)) { continue; } d.target = targetCh; break; } } if (d.target != null) { AdjustToTarget(d); } } } }
private void AdjustToTarget(ProjectileData data) { if (data.target.Status.IsDead) { data.target = null; return; } Vector3 currentVelocity = data.rb.velocity.normalized; Vector3 targetDir = Utils.GetDirectionVector(data.target.GetData().GetBody().transform.position, data.proj.transform.position).normalized; data.interpolTimer += interpolAdd; if (data.interpolTimer > 1) { data.interpolTimer = 1f; } Vector3 newDir = Vector3.Lerp(currentVelocity, targetDir, data.interpolTimer); data.rb.velocity = newDir * force; }
public override void MonoTriggerEnter(GameObject gameObject, Collider2D coll) { if (coll.gameObject.Equals(GetOwnerData().GetBody())) { return; } Character ch = coll.gameObject.GetChar(); ProjectileData d = GetProjectileData(gameObject); // if projectile was saved, it means special effects are to be applied if (d != null) { if (penetrateFriendly) { if (ch == null) { Destroyable des = coll.gameObject.GetComponent <Destroyable>(); if (des != null && !Owner.CanAttack(des)) { return; } } else if (!Owner.CanAttack(ch)) { return; } } // missile hit target if (d.target != null) { if (coll.gameObject.Equals(d.target.GetData().GetBody())) { d.target = null; } } if (penetrateTargets > 0 && d.penetratedTargets > 0 && (penetrateChangeDamage < 0 || penetrateChangeDamage > 0)) { ApplyEffects(Owner, coll.gameObject, false, d.penetratedTargets); } else { ApplyEffects(Owner, coll.gameObject); } bool destroy = false; if (penetrateTargets > 0) { // check if penetrated too many d.penetratedTargets++; if (d.penetratedTargets >= penetrateTargets) { destroy = true; } // find next target if (!destroy && navigateChangeTargetAfterHit) { float angle = d.proj.transform.rotation.eulerAngles.z; if (!navigateLookOnlyForward) { /*foreach (Collider2D hit in Physics2D.OverlapCircleAll(d.proj.transform.position, navigateAimArea)) * { * if (hit.gameObject.Equals(d.proj)) * continue; * * Character targetCh = hit.gameObject.GetChar(); * if (targetCh == null || !Owner.CanAttack(targetCh) || hit.gameObject.Equals(coll.gameObject)) * continue; * * d.target = targetCh; * AdjustToTarget(d); * break; * }*/ foreach (Collider2D c in Physics2D.OverlapCircleAll(d.proj.transform.position, navigateAimArea)) { if (c.gameObject.Equals(d.proj)) { continue; } Character targetCh = c.gameObject.GetChar(); if (targetCh == null || !Owner.CanAttack(targetCh) || c.gameObject.Equals(coll.gameObject)) { continue; } d.target = targetCh; AdjustToTarget(d); break; } } else { Vector3 direction = new Vector3(d.rb.velocity.x, d.rb.velocity.y); Vector3 perpend = Utils.GetPerpendicularVector(d.proj.transform.position, direction + d.proj.transform.position); foreach (Collider2D c in Physics2D.OverlapAreaAll(d.proj.transform.position + perpend * navigateAimArea / 2f + direction.normalized * navigateAimArea, d.proj.transform.position + perpend * (-navigateAimArea / 2f))) { if (c.gameObject.Equals(d.proj)) { continue; } Character targetCh = c.gameObject.GetChar(); if (targetCh == null || !Owner.CanAttack(targetCh) || c.gameObject.Equals(coll.gameObject)) { continue; } d.target = targetCh; AdjustToTarget(d); break; } } } } if (penetrateTargets == 0 || destroy) { if (explodeEffect) { GameObject explosion = CreateParticleEffect(explodeEffectName, false, gameObject.transform.position); explosion.GetComponent <ParticleSystem>().Play(); Object.Destroy(explosion, 2f); } DestroyProjectile(gameObject); } } else { if (penetrateFriendly) { if (ch == null) { Destroyable des = coll.gameObject.GetComponent <Destroyable>(); if (des != null && !Owner.CanAttack(des)) { return; } } else if (!Owner.CanAttack(ch)) { return; } } if (explodeEffect) { GameObject explosion = CreateParticleEffect(explodeEffectName, false, gameObject.transform.position); explosion.GetComponent <ParticleSystem>().Play(); Object.Destroy(explosion, 2f); } ApplyEffects(Owner, coll.gameObject); DestroyProjectile(gameObject); } }
public override void MonoUpdate(GameObject gameObject, bool fixedUpdate) { if (navigateToTarget) { if (fixedUpdate) { if (lastUpdate + updateInterval <= Time.time) { ProjectileData d = GetProjectileData(gameObject); if (d == null || d.proj == null) { return; } lastUpdate = Time.time; // find new target if (d.target == null) { if (d.lastChooseTarget + chooseTargetInterval < Time.time) { d.lastChooseTarget = Time.time; if (!navigateLookOnlyForward) { float angle = d.proj.transform.rotation.eulerAngles.z; foreach (Collider2D c in Physics2D.OverlapCircleAll(d.proj.transform.position, navigateAimArea)) { if (c.gameObject.Equals(d.proj)) { continue; } Character targetCh = c.gameObject.GetChar(); if (targetCh == null || !Owner.CanAttack(targetCh)) { continue; } d.target = targetCh; break; } } else // scan only forward targets { float angle = d.proj.transform.rotation.eulerAngles.z; Vector3 direction = new Vector3(d.rb.velocity.x, d.rb.velocity.y); Vector3 perpend = Utils.GetPerpendicularVector(d.proj.transform.position, direction + d.proj.transform.position); Debug.DrawRay(d.proj.transform.position, perpend * 10, Color.red, 1f); Debug.DrawLine(d.proj.transform.position, d.proj.transform.position + perpend * navigateAimArea / 2f + direction.normalized * navigateAimArea, Color.green, 1f); Debug.DrawLine(d.proj.transform.position, d.proj.transform.position + perpend * (-navigateAimArea / 2f), Color.blue, 1f); foreach (Collider2D c in Physics2D.OverlapAreaAll(d.proj.transform.position + perpend * navigateAimArea / 2f + direction.normalized * navigateAimArea, d.proj.transform.position + perpend * (-navigateAimArea / 2f))) { if (c.gameObject.Equals(d.proj)) { continue; } Character targetCh = c.gameObject.GetChar(); if (targetCh == null || !Owner.CanAttack(targetCh)) { continue; } d.target = targetCh; break; } } } } if (d.target != null) { AdjustToTarget(d); } } } } }
public override void MonoTriggerEnter(GameObject gameObject, Collider2D coll) { if (coll.gameObject.Equals(GetOwnerData().GetBody())) { return; } ProjectileData d = GetData(gameObject); if (d != null && d.target != null) { if (coll.gameObject.Equals(d.target.GetData().GetBody())) { d.target = null; } } if (d != null && maxPenetratedTargets > 0 && d.penetratedTargets > 0 && secondDamage > 0) { ApplyEffects(Owner, coll.gameObject, false, 1); } else { if (!areaEffect) { ApplyEffects(Owner, coll.gameObject); } else { Collider2D[] colls = Physics2D.OverlapCircleAll(gameObject.transform.position, areaEffectRange); // explosion effect GameObject explosion = CreateParticleEffect("AreaTargetExplosion", false, gameObject.transform.position); explosion.GetComponent <ParticleSystem>().Play(); Object.Destroy(explosion, 2f); // give damages foreach (Collider2D col in colls) { if (col != null && col.gameObject != null) { Character targetCh = col.gameObject.GetChar(); if (targetCh != null) { if (Owner.CanAttack(targetCh)) { ApplyEffects(Owner, col.gameObject); } } } } } } bool destroy = false; if (penetrateTargets) { if (d != null) { // check if penetrated too many if (maxPenetratedTargets > 0) { d.penetratedTargets++; if (d.penetratedTargets >= maxPenetratedTargets) { destroy = true; } } if (!destroy && navigateAfterPenetration) { float angle = d.proj.transform.rotation.eulerAngles.z; foreach (Collider2D hit in Physics2D.OverlapCircleAll(d.proj.transform.position, aimArea)) { if (hit.gameObject.Equals(d.proj)) { continue; } Character targetCh = hit.gameObject.GetChar(); if (targetCh == null || !Owner.CanAttack(targetCh) || hit.gameObject.Equals(coll.gameObject)) { continue; } d.target = targetCh; AdjustToTarget(d); break; } } } } if (!penetrateTargets || destroy) { if (explodeEffect) { GameObject explosion = CreateParticleEffect("Explosion", false, gameObject.transform.position); explosion.GetComponent <ParticleSystem>().Play(); Object.Destroy(explosion, 2f); } DestroyProjectile(gameObject); } }
public override void OnLaunch() { bool saveProjectiles = projectilesAim || selectTargetOnLaunch || maxPenetratedTargets > 0; if (saveProjectiles) { projectiles.Clear(); } DeleteCastingEffect(); GameObject activeProjectile; for (int i = 0; i < projectilesCount; i++) { activeProjectile = CreateSkillProjectile("projectile_00", true); if (activeProjectile != null) { Rigidbody2D rb = activeProjectile.GetComponent <Rigidbody2D>(); rb.velocity = (GetOwnerData().GetForwardVector((Random.Range(-randomAngle, randomAngle) + CalcAngleForProjectile(i, projectilesCount, 10))) * force); Object.Destroy(activeProjectile, 5f); if (saveProjectiles) { ProjectileData data = new ProjectileData(); data.proj = activeProjectile; data.target = null; data.interpolTimer = 0; data.rb = rb; data.penetratedTargets = 0; projectiles.Add(data); } } } // vybere target pri vypusteni if (selectTargetOnLaunch) { int range = GetRange(); List <RaycastHit2D> hits = Utils.CastBoxInDirection(Owner.GetData().GetBody(), GetPlayerData().GetForwardVector(), range, range * 2).ToList(); List <Character> targets = new List <Character>(); for (int i = 0; i < hits.Count; i++) { RaycastHit2D hit = hits[i]; Character targetCh = hit.collider.gameObject.GetChar(); if (targetCh == null || !Owner.CanAttack(targetCh)) { continue; } targets.Add(targetCh); } if (targets.Count > 0) { foreach (ProjectileData d in projectiles) { if (d.target == null) { int randomIndex = Random.Range(0, targets.Count); d.target = targets[randomIndex]; } } } } }
public override void MonoTriggerEnter(GameObject gameObject, Collider2D coll) { if (coll.gameObject.Equals(GetOwnerData().GetBody())) { return; } Character ch = coll.gameObject.GetChar(); ProjectileData d = GetProjectileData(gameObject); // if projectile was saved, it means special effects are to be applied if (d != null) { if (ch == null) { Destroyable des = coll.gameObject.GetComponent <Destroyable>(); if (des == null) { ForceDestroyProjectile(d.proj); return; } if (!Owner.CanAttack(des)) { return; } } else if (!Owner.CanAttack(ch)) { return; } // missile hit target if (d.target != null) { if (coll.gameObject.Equals(d.target.GetData().GetBody())) { d.target = null; } } if (d.ignore != null && d.ignore.Equals(coll.gameObject)) { return; } if (chainEffect && !d.chained) { for (int i = 0; i < chainProjectilesCount; i++) { GameObject activeProjectile; activeProjectile = CreateSkillProjectile("projectile_00", true, d.proj.transform); if (activeProjectile != null) { Rigidbody2D rb = activeProjectile.GetComponent <Rigidbody2D>(); Vector3 nv = Quaternion.Euler(new Vector3(0, 0, Random.Range(-90, 90))) * d.rb.velocity.normalized; rb.velocity = nv * force; Object.Destroy(activeProjectile, GetProjectileLifetime(force)); if (SaveProjectiles()) { ProjectileData data = new ProjectileData(); data.proj = activeProjectile; data.target = null; data.interpolTimer = 0; data.rb = rb; data.penetratedTargets = 0; data.maxPenetrateTargets = chainPenetrations + 1; data.chained = true; data.ignore = coll.gameObject; if (chainPenetrations > 0) { data.hits = new GameObject[chainPenetrations + 1]; } if (returnBack) { data.waypoints.Push(activeProjectile.transform.position); } data.SaveHit(coll.gameObject); data.penetratedTargets++; projectiles.Add(data); MonoUpdate(rb.gameObject, true); } } } } if (d.maxPenetrateTargets > 0 && d.penetratedTargets > 0 && (penetrateChangeDamage < 0 || penetrateChangeDamage > 0)) { ApplyEffects(Owner, coll.gameObject, false, d.penetratedTargets); } else { ApplyEffects(Owner, coll.gameObject); } bool destroy = false; if (maxPenetratedTargets > 0 && d.maxPenetrateTargets > 0) { // check if penetrated too many d.penetratedTargets++; if (d.penetratedTargets >= d.maxPenetrateTargets) { destroy = true; } // find next target if (!destroy && navigateChangeTargetAfterHit) { ProjectileHitAnimation(d.proj); float angle = d.proj.transform.rotation.eulerAngles.z; if (!navigateLookOnlyForward) { /*foreach (Collider2D hit in Physics2D.OverlapCircleAll(d.proj.transform.position, navigateAimArea)) * { * if (hit.gameObject.Equals(d.proj)) * continue; * * Character targetCh = hit.gameObject.GetChar(); * if (targetCh == null || !Owner.CanAttack(targetCh) || hit.gameObject.Equals(coll.gameObject)) * continue; * * d.target = targetCh; * AdjustToTarget(d); * break; * }*/ List <GameObject> candidates = new List <GameObject>(); foreach (Collider2D c in Physics2D.OverlapCircleAll(d.proj.transform.position, navigateAimArea)) { if (c.gameObject.Equals(d.proj)) { continue; } if (d.HasHit(c.gameObject)) { continue; } if (!Utils.CanSee(c.gameObject, d.proj.transform.position)) { continue; } Character targetCh = c.gameObject.GetChar(); if (targetCh == null || !Owner.CanAttack(targetCh)) { continue; } candidates.Add(c.gameObject); } candidates.Sort((x, y) => (int)Utils.DistanceSqr(Owner.GetData().GetBody().transform.position, x.transform.position) - (int)Utils.DistanceSqr(Owner.GetData().GetBody().transform.position, y.transform.position)); foreach (GameObject c in candidates) { Character targetCh = c.GetChar(); if (targetCh == null || !Owner.CanAttack(targetCh)) { continue; } d.target = targetCh; d.SaveHit(c.gameObject); AdjustToTarget(d); break; } } else { Vector3 direction = new Vector3(d.rb.velocity.x, d.rb.velocity.y); Vector3 perpend = Utils.GetPerpendicularVector(d.proj.transform.position, direction + d.proj.transform.position); List <GameObject> candidates = new List <GameObject>(); foreach (Collider2D c in Physics2D.OverlapAreaAll(d.proj.transform.position + perpend * navigateAimArea / 2f + direction.normalized * navigateAimArea, d.proj.transform.position + perpend * (-navigateAimArea / 2f))) { if (c.gameObject.Equals(d.proj)) { continue; } if (d.HasHit(c.gameObject)) { continue; } if (!Utils.CanSee(c.gameObject, d.proj.transform.position)) { continue; } candidates.Add(c.gameObject); break; } candidates.Sort((x, y) => (int)Utils.DistanceSqr(Owner.GetData().GetBody().transform.position, x.transform.position) - (int)Utils.DistanceSqr(Owner.GetData().GetBody().transform.position, y.transform.position)); foreach (GameObject c in candidates) { Character targetCh = c.GetChar(); if (targetCh == null || !Owner.CanAttack(targetCh)) { continue; } d.target = targetCh; d.SaveHit(c.gameObject); AdjustToTarget(d); break; } } } } if (maxPenetratedTargets == 0 || destroy) { if (returnBack) { returningBack = true; AdjustToTarget(d); } else { if (explodeEffect) { GameObject explosion = CreateParticleEffect(explodeEffectName, false, gameObject.transform.position); explosion.GetComponent <ParticleSystem>().Play(); Object.Destroy(explosion, 2f); } DestroyProjectile(gameObject); } } } else { if (ch == null) { Destroyable des = coll.gameObject.GetComponent <Destroyable>(); if (des != null && !Owner.CanAttack(des)) { return; } } else if (!Owner.CanAttack(ch)) { return; } ApplyEffects(Owner, coll.gameObject); DestroyProjectile(gameObject); } }
private void AdjustToTarget(ProjectileData data) { if (returningBack) { if (!data.hasNextWaypoint && data.waypoints.Count > 0) { data.nextWaypoint = data.waypoints.Pop(); data.hasNextWaypoint = true; } if (data.hasNextWaypoint) { Vector3 target = data.nextWaypoint; Vector3 currentVelocity = data.rb.velocity.normalized; Vector3 targetDir = Utils.GetDirectionVector(target, data.proj.transform.position).normalized; data.interpolTimer += navigateAimRate; if (data.interpolTimer > 1) { data.interpolTimer = 1f; } Vector3 newDir = Vector3.Lerp(currentVelocity, targetDir, data.interpolTimer); if (navigateUnreliable) { newDir = Utils.RotateDirectionVector(newDir, Random.Range(-30, 30)); } data.rb.velocity = newDir * 15; } } else { if (data.target.Status.IsDead || (data.ignore != null && data.ignore.Equals(data.target.GetData().GetBody()))) { data.target = null; return; } Vector3 currentVelocity = data.rb.velocity.normalized; Vector3 targetDir = Utils.GetDirectionVector(data.target.GetData().GetBody().transform.position, data.proj.transform.position).normalized; data.interpolTimer += navigateAimRate; if (data.interpolTimer > 1) { data.interpolTimer = 1f; } Vector3 newDir = Vector3.Lerp(currentVelocity, targetDir, data.interpolTimer); if (navigateUnreliable) { newDir = Utils.RotateDirectionVector(newDir, Random.Range(-30, 30)); } data.rb.velocity = newDir * 15; } }
public override void MonoUpdate(GameObject gameObject, bool fixedUpdate) { if (returningBack) { ProjectileData d = GetProjectileData(gameObject); if (d == null || d.proj == null) { return; } if (d.lastUpdateTime + updateInterval <= Time.time) { d.lastUpdateTime = Time.time; if (!d.hasNextWaypoint) { AdjustToTarget(d); } if (d.hasNextWaypoint) { float dist = Utils.DistanceSqr(d.nextWaypoint, d.proj.transform.position); if (dist < 2 * 2) { d.hasNextWaypoint = false; } } else { returningBack = false; if (explodeEffect) { GameObject explosion = CreateParticleEffect(explodeEffectName, false, gameObject.transform.position); explosion.GetComponent <ParticleSystem>().Play(); Object.Destroy(explosion, 2f); } ForceDestroyProjectile(gameObject); return; } } } if (navigateToTarget) { //if (fixedUpdate) { ProjectileData d = GetProjectileData(gameObject); if (d == null || d.proj == null) { return; } if (d.lastUpdateTime + updateInterval <= Time.time) { d.lastUpdateTime = Time.time; // find new target if (d.target == null) { //if (d.lastChooseTarget + chooseTargetInterval < Time.time) { d.lastChooseTarget = Time.time; if (!navigateLookOnlyForward) { float angle = d.proj.transform.rotation.eulerAngles.z; List <GameObject> candidates = new List <GameObject>(); foreach (Collider2D c in Physics2D.OverlapCircleAll(d.proj.transform.position, navigateAimArea)) { if (c.gameObject.Equals(d.proj)) { continue; } if (d.HasHit(c.gameObject)) { continue; } if (!Utils.CanSee(c.gameObject, d.proj.transform.position)) { continue; } Character targetCh = c.gameObject.GetChar(); if (targetCh == null || !Owner.CanAttack(targetCh)) { continue; } candidates.Add(c.gameObject); } candidates.Sort((x, y) => (int)Utils.DistanceSqr(Owner.GetData().GetBody().transform.position, x.transform.position) - (int)Utils.DistanceSqr(Owner.GetData().GetBody().transform.position, y.transform.position)); foreach (GameObject c in candidates) { Character targetCh = c.GetChar(); if (targetCh == null || !Owner.CanAttack(targetCh)) { continue; } d.target = targetCh; d.SaveHit(c.gameObject); AdjustToTarget(d); break; } } else // scan only forward targets { float angle = d.proj.transform.rotation.eulerAngles.z; Vector3 direction = new Vector3(d.rb.velocity.x, d.rb.velocity.y); Vector3 perpend = Utils.GetPerpendicularVector(d.proj.transform.position, direction + d.proj.transform.position); Debug.DrawRay(d.proj.transform.position, perpend * 10, Color.red, 1f); Debug.DrawLine(d.proj.transform.position, d.proj.transform.position + perpend * navigateAimArea / 2f + direction.normalized * navigateAimArea, Color.green, 1f); Debug.DrawLine(d.proj.transform.position, d.proj.transform.position + perpend * (-navigateAimArea / 2f), Color.blue, 1f); List <GameObject> candidates = new List <GameObject>(); foreach (Collider2D c in Physics2D.OverlapAreaAll(d.proj.transform.position + perpend * navigateAimArea / 2f + direction.normalized * navigateAimArea, d.proj.transform.position + perpend * (-navigateAimArea / 2f))) { if (c.gameObject.Equals(d.proj)) { continue; } if (d.HasHit(c.gameObject)) { continue; } if (!Utils.CanSee(c.gameObject, d.proj.transform.position)) { continue; } candidates.Add(c.gameObject); } candidates.Sort((x, y) => (int)Utils.DistanceSqr(Owner.GetData().GetBody().transform.position, x.transform.position) - (int)Utils.DistanceSqr(Owner.GetData().GetBody().transform.position, y.transform.position)); foreach (GameObject c in candidates) { Character targetCh = c.GetChar(); if (targetCh == null || !Owner.CanAttack(targetCh)) { continue; } d.target = targetCh; d.SaveHit(c.gameObject); AdjustToTarget(d); break; } } } } if (d.target != null) { AdjustToTarget(d); } } } } }