Files
unity/Assets/Game/Scripts/Combat/EnemyUnit.cs
T

141 lines
5.8 KiB
C#
Raw Normal View History

using UnityEngine;
namespace Ironspore
{
public sealed class EnemyUnit : MonoBehaviour
{
GameSession game;
float health, cooldown, age;
int type;
public void Initialize(GameSession session, int enemyType, GameObject mech, Transform world)
{
game = session;
type = enemyType;
health = type == 3 ? 650 : type == 2 ? 140 : 60;
var model = Instantiate(mech, transform);
model.transform.localScale = Vector3.one * (type == 3 ? 1.7f : type == 0 ? .65f : 1);
foreach (var renderer in model.GetComponentsInChildren<Renderer>())
renderer.sharedMaterial = WorldFactory.Material(new Color(.5f, .2f, .12f));
foreach (var node in model.GetComponentsInChildren<Transform>())
node.gameObject.layer = 9;
var capsule = gameObject.AddComponent<CapsuleCollider>();
capsule.height = type == 3 ? 5.2f : 3;
capsule.radius = type == 3 ? 1.5f : .8f;
capsule.center = Vector3.up * capsule.height * .5f;
WorldFactory.Label(type == 3 ? "world.overseer" : type == 2 ? "world.bulwark" : type == 0 ? "world.skimmer" : "world.sentinel", transform.position + Vector3.up * (capsule.height + 1), new Color(1, .5f, .25f), transform);
cooldown = 1 + Random.value;
}
void Update()
{
if (!game.InField || game.Paused || game.Trial || !game.World.Player)
return;
age += Time.deltaTime;
Vector3 target = game.World.Player.transform.position + Vector3.up * 1.5f;
if (game.World.Escort && game.World.Escort.Health > 0 && Vector3.Distance(transform.position, game.World.Escort.transform.position) < 15)
target = game.World.Escort.transform.position;
Vector3 flat = target - transform.position;
flat.y = 0;
if (flat.sqrMagnitude > .1f)
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(flat), Time.deltaTime * 2);
float distance = flat.magnitude;
if (type != 1 && distance > 10)
{
Vector3 step = flat.normalized * Time.deltaTime * (type == 3 ? 1.4f : type == 0 ? 2.5f : 1.2f);
if (!Physics.Raycast(transform.position + Vector3.up, step.normalized, 1.1f, 1, QueryTriggerInteraction.Ignore))
transform.position += step;
}
if (type == 0)
{
Vector3 p = transform.position;
p.y = 1.8f + Mathf.Sin(age) * .4f;
transform.position = p;
}
cooldown -= Time.deltaTime;
if (cooldown <= 0 && distance < 42)
{
Vector3 origin = transform.position + Vector3.up * (type == 3 ? 3.5f : 2);
if (!Physics.Linecast(origin, target, 1, QueryTriggerInteraction.Ignore))
{
var bolt = WorldFactory.Primitive(PrimitiveType.Sphere, "EnemyBolt", origin, Vector3.one * .3f, new Color(1, .35f, .08f), null, false, true);
bolt.AddComponent<EnemyBolt>().Initialize((target - origin).normalized, type == 3 ? 23 : 12);
}
cooldown = type == 3 ? .7f : type == 1 ? 1.7f : 2.5f;
}
}
public void Damage(float damage)
{
health -= damage;
if (health > 0)
return;
if (type == 3)
game.CompleteTerminal();
GameAudio.Cue(95, .15f);
Destroy(gameObject);
}
}
public sealed class EnemyBolt : MonoBehaviour
{
Vector3 direction;
float damage, life;
public void Initialize(Vector3 travel, float amount)
{
direction = travel;
damage = amount;
}
void Update()
{
if (!GameSession.Active || !GameSession.Active.InField)
{
Destroy(gameObject);
return;
}
float distance = Time.deltaTime * 17;
if (Physics.SphereCast(transform.position, .12f, direction, out var hit, distance, ~(1 << 9), QueryTriggerInteraction.Ignore))
{
var pilot = hit.collider.GetComponentInParent<MechPilot>();
if (pilot)
pilot.Damage(damage);
var escort = hit.collider.GetComponentInParent<EscortUnit>();
if (escort)
escort.Damage(damage);
Destroy(gameObject);
return;
}
transform.position += direction * distance;
life += Time.deltaTime;
if (life > 5)
Destroy(gameObject);
}
}
public sealed class EscortUnit : MonoBehaviour
{
GameSession game;
public float Health { get; private set; } = 250;
public void Initialize(GameSession session)
{
game = session;
Health = game.Run.escortArmor;
WorldFactory.Label("world.escort", transform.position + Vector3.up * 3, Color.cyan, transform);
}
void Update()
{
if (!game.InField || game.Paused || Health <= 0 || game.Run.routeCompleted)
return;
if (Vector3.Distance(game.World.Player.transform.position, transform.position) < 14)
transform.position += Vector3.forward * Time.deltaTime * 1.5f;
if (transform.position.z >= 33)
game.CompleteTerminal();
}
public void Damage(float amount)
{
Health = Mathf.Max(0, Health - amount);
game.Run.escortArmor = Health;
if (Health <= 0)
{
game.Store.Commit(s => true);
game.Notify("notice.escortLost");
}
}
}
}