250 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			250 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using System;
 | 
						|
using System.Collections;
 | 
						|
using System.Collections.Generic;
 | 
						|
using System.Runtime.CompilerServices;
 | 
						|
using UnityEngine;
 | 
						|
 | 
						|
[Serializable]
 | 
						|
public class Rocket : MonoBehaviour
 | 
						|
{
 | 
						|
	public float lag;
 | 
						|
	public Transform explosion;
 | 
						|
	public Vehicle launchVehicle;
 | 
						|
	public Vehicle targetVehicle;
 | 
						|
	public int speedX;
 | 
						|
	public string laserID;
 | 
						|
	private Vector3 strtPos;
 | 
						|
	private int stage = -1;
 | 
						|
	public LayerMask mask = -1;
 | 
						|
	public LayerMask maskOpt = -1;
 | 
						|
 | 
						|
    public IEnumerator Start()
 | 
						|
    { 
 | 
						|
        //Init
 | 
						|
        name = "lsr#" + laserID;
 | 
						|
        float velocity = Game.Settings.laserSpeed * speedX + Mathf.Max(
 | 
						|
            0,
 | 
						|
            launchVehicle.transform.InverseTransformDirection(
 | 
						|
                launchVehicle.velocity).z *
 | 
						|
                (targetVehicle ?
 | 
						|
                    1 :
 | 
						|
                    Vector3.Dot(
 | 
						|
                        transform.forward,
 | 
						|
                        launchVehicle.transform.forward)));
 | 
						|
 | 
						|
        //AutoTargeting
 | 
						|
        if (targetVehicle)
 | 
						|
        {
 | 
						|
            Vector3 bgn = transform.position;
 | 
						|
            Vector3 pos;
 | 
						|
            Vector3 vel;
 | 
						|
            Vector3 accel;
 | 
						|
            if (targetVehicle.networkView.isMine) //Local vehicle, high precision
 | 
						|
            {
 | 
						|
                Vector3 refvel = targetVehicle.gameObject.rigidbody.velocity;
 | 
						|
                float reftme = Time.time;
 | 
						|
                yield return new WaitForSeconds(Time.fixedDeltaTime * 0.5f); //Allow target to move so we can analyze it's acceleration
 | 
						|
                pos = targetVehicle.transform.position;
 | 
						|
                vel = targetVehicle.gameObject.rigidbody.velocity;
 | 
						|
                accel = (vel - refvel) / (Time.time - reftme); ////Accelleration over 1 second
 | 
						|
            }
 | 
						|
            else //Remote vehicle, just make it look good
 | 
						|
            {
 | 
						|
                Vector3 refpos = targetVehicle.transform.position;
 | 
						|
                float reftme = Time.time;
 | 
						|
                yield return new WaitForSeconds(Time.fixedDeltaTime * 0.5f); //Allow target to move so we can analyze it's velocity
 | 
						|
                Vector3 refvel = (targetVehicle.transform.position - refpos) / (Time.time - reftme); //velocity over 1 second
 | 
						|
                refpos = targetVehicle.transform.position;
 | 
						|
                reftme = Time.time;
 | 
						|
                yield return new WaitForSeconds(Time.fixedDeltaTime * 0.5f); //Allow target to move so we can analyze it's acceleration
 | 
						|
                pos = targetVehicle.transform.position;
 | 
						|
                vel = (targetVehicle.transform.position - refpos) / (Time.time - reftme); //velocity over 1 second
 | 
						|
                accel = (vel - refvel) / (Time.time - reftme); //Accelleration over 1 second
 | 
						|
            }
 | 
						|
 | 
						|
            float dur = 0f;
 | 
						|
            while (true)
 | 
						|
            {
 | 
						|
                pos += vel * Time.fixedDeltaTime;
 | 
						|
                vel += accel * Time.fixedDeltaTime;
 | 
						|
                dur += Time.fixedDeltaTime;
 | 
						|
                if (
 | 
						|
                    dur > 10 ||
 | 
						|
                    Vector3.Distance(bgn, pos) < dur * velocity)
 | 
						|
                {
 | 
						|
                    break;
 | 
						|
                }
 | 
						|
                transform.LookAt(pos);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        //Lag Compensation
 | 
						|
        //Unnecessary when autotargeting, as hits are calculated on target client
 | 
						|
        else if (lag > 0f)
 | 
						|
        {
 | 
						|
            rigidbody.position += rigidbody.transform.TransformDirection(
 | 
						|
                0f,
 | 
						|
                0f,
 | 
						|
                velocity * lag); //Position extrapolation for non authoratative firing instances
 | 
						|
        }
 | 
						|
 | 
						|
        //Begin Run
 | 
						|
        rigidbody.velocity = rigidbody.transform.TransformDirection(
 | 
						|
            0f,
 | 
						|
            0f,
 | 
						|
            velocity);
 | 
						|
        strtPos = rigidbody.position;
 | 
						|
        stage = 0;
 | 
						|
 | 
						|
        //Cleanup
 | 
						|
        yield return new WaitForSeconds(Mathf.Lerp(
 | 
						|
            13f,
 | 
						|
            5f,
 | 
						|
            Game.Settings.laserSpeed * speedX * 0.003f));
 | 
						|
        Destroy(gameObject);
 | 
						|
    }
 | 
						|
 | 
						|
	public void FixedUpdate()
 | 
						|
	{
 | 
						|
		if (stage != 0 || !launchVehicle || !Game.Settings)
 | 
						|
		{
 | 
						|
			return;
 | 
						|
		}
 | 
						|
		if (Game.Settings.laserGrav != 0f)
 | 
						|
		{
 | 
						|
			Vector3 rigvel = rigidbody.velocity;
 | 
						|
			rigvel.y -= Game.Settings.laserGrav *
 | 
						|
                (float)speedX *
 | 
						|
                Time.deltaTime *
 | 
						|
                20f;
 | 
						|
			rigidbody.velocity = rigvel;
 | 
						|
		}
 | 
						|
        Vector3 vector = transform.position - strtPos;
 | 
						|
		RaycastHit[] hits = Physics.RaycastAll(
 | 
						|
            strtPos,
 | 
						|
            vector,
 | 
						|
            vector.magnitude,
 | 
						|
            (Game.Settings.lasersOptHit) ? maskOpt : mask);
 | 
						|
		for (int i = 0; i < hits.Length; i++)
 | 
						|
		{
 | 
						|
            RaycastHit collision = hits[i];
 | 
						|
 | 
						|
            //Launch vehicle is immune to hits
 | 
						|
            if (collision.collider.transform.root.gameObject == launchVehicle.gameObject)
 | 
						|
            {
 | 
						|
                continue;
 | 
						|
            }
 | 
						|
 | 
						|
            //Non-authoratative game instances DO NOT detect vehicle laser hits. Hits are detected on authoratative instance, and then broadcast to other clients with lH RPC
 | 
						|
            if (
 | 
						|
                ((targetVehicle && !targetVehicle.networkView.isMine) ||
 | 
						|
                    (!targetVehicle && !launchVehicle.networkView.isMine)) &&
 | 
						|
                collision.rigidbody)
 | 
						|
            {
 | 
						|
                continue;
 | 
						|
            }
 | 
						|
 | 
						|
            //We are the instance if this laser on the firer's computer, & we tagged another vehicle
 | 
						|
            if (
 | 
						|
                ((targetVehicle && targetVehicle.networkView.isMine) ||
 | 
						|
                    (!targetVehicle && launchVehicle.networkView.isMine)) &&
 | 
						|
                collision.rigidbody)
 | 
						|
            {
 | 
						|
                Vehicle veh = (Vehicle)collision.transform.root.gameObject.GetComponent(typeof(Vehicle));
 | 
						|
                if (veh && veh.isResponding)
 | 
						|
                {
 | 
						|
                    //Determine where we hit them
 | 
						|
                    veh.gameObject.networkView.RPC(
 | 
						|
                        "lH",
 | 
						|
                        RPCMode.Others,
 | 
						|
                        laserID,
 | 
						|
                        collision.transform.InverseTransformDirection(collision.point));
 | 
						|
                    //We are quarry, and made a tag
 | 
						|
                    if (
 | 
						|
                        launchVehicle.isIt == 1 &&
 | 
						|
                        (Time.time - veh.lastTag) > 3f)
 | 
						|
                    {
 | 
						|
                        launchVehicle.gameObject.networkView.RPC(
 | 
						|
                            "iS",
 | 
						|
                            RPCMode.All,
 | 
						|
                            veh.gameObject.name);
 | 
						|
                        veh.lastTag = Time.time;
 | 
						|
                    }
 | 
						|
                    //They were quarry, and we tagged them
 | 
						|
                    else if (
 | 
						|
                        veh.isIt == 1 &&
 | 
						|
                        (Time.time - launchVehicle.lastTag) > 3 &&
 | 
						|
                        (Time.time - veh.lastTag) > 3)
 | 
						|
                    {
 | 
						|
                        launchVehicle.gameObject.networkView.RPC(
 | 
						|
                            "sQ",
 | 
						|
                            RPCMode.All,
 | 
						|
                            2);
 | 
						|
                    }
 | 
						|
                    //They weren't quarry, and we weren't supposed to shoot them
 | 
						|
                    else if (
 | 
						|
                        veh.isIt == 0 &&
 | 
						|
                        launchVehicle.isIt == 0)
 | 
						|
                    {
 | 
						|
                        launchVehicle.gameObject.networkView.RPC(
 | 
						|
                            "dS",
 | 
						|
                            RPCMode.All,
 | 
						|
                            veh.gameObject.name);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            if ((bool)collision.rigidbody || Game.Settings.laserRico == 0f)
 | 
						|
            {
 | 
						|
                laserHit(
 | 
						|
                    collision.transform.root.gameObject,
 | 
						|
                    collision.point,
 | 
						|
                    collision.normal);
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                rigidbody.position = collision.point;
 | 
						|
                rigidbody.velocity = Game.Settings.laserRico *
 | 
						|
                    Vector3.Lerp(
 | 
						|
                        Vector3.Scale(
 | 
						|
                            rigidbody.velocity,
 | 
						|
                            collision.normal),
 | 
						|
                        Vector3.Reflect(
 | 
						|
                            rigidbody.velocity,
 | 
						|
                            collision.normal),
 | 
						|
                        Game.Settings.laserRico);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
		strtPos = rigidbody.position;
 | 
						|
	}
 | 
						|
 | 
						|
	public void laserHit(GameObject go, Vector3 pos, Vector3 norm)
 | 
						|
	{
 | 
						|
		stage = 1;
 | 
						|
 | 
						|
		rigidbody.position = pos;
 | 
						|
		rigidbody.velocity = Vector3.zero;
 | 
						|
		go.BroadcastMessage(
 | 
						|
            "OnLaserHit",
 | 
						|
            launchVehicle.networkView.isMine,
 | 
						|
            SendMessageOptions.DontRequireReceiver);
 | 
						|
		Collider[] colliders = Physics.OverlapSphere(pos, 10f);
 | 
						|
        foreach (Collider hit in colliders)
 | 
						|
        {
 | 
						|
            if (hit.attachedRigidbody)
 | 
						|
            {
 | 
						|
                hit.attachedRigidbody.AddExplosionForce(
 | 
						|
                    350f + speedX * 300f,
 | 
						|
                    pos,
 | 
						|
                    1f,
 | 
						|
                    2f);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        Instantiate(
 | 
						|
            explosion,
 | 
						|
            pos,
 | 
						|
            Quaternion.FromToRotation(Vector3.up, norm)); //transform.rotation
 | 
						|
	}
 | 
						|
}
 |