290 lines
8.4 KiB
C#
290 lines
8.4 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using DragonLi.Core;
|
|
using DragonLi.Frame;
|
|
using Mirror;
|
|
using UnityEngine;
|
|
using UnityEngine.XR;
|
|
|
|
public class Launcher : Entity
|
|
{
|
|
[Header("子弹")]
|
|
public GameObject bullet_prefab;
|
|
public float bullet_speed = 100f;
|
|
[SyncVar]
|
|
public float bullet_amount = 0f;
|
|
public float damage = 10f;
|
|
public float shootrate = 10f;
|
|
|
|
public int bullet_per_shoot = 1;
|
|
|
|
public bool nature_recoil = false;
|
|
public Vector2 recoil_mutiply;
|
|
public Vector2 recoil_recover_rate = Vector2.one * 10f;
|
|
[Header("开火")]
|
|
public GameObject muzzle_prefab;
|
|
public float muzzle_despawn_time;
|
|
[Header("弹壳")]
|
|
public GameObject shell_key;
|
|
public float shell_outforce;
|
|
public float shell_despawn_delay;
|
|
|
|
/// <summary>
|
|
/// Where should we spawn bullet
|
|
/// </summary>
|
|
public Transform LaunchPoint;
|
|
|
|
/// <summary>
|
|
/// Where to spawn shell
|
|
/// </summary>
|
|
public Transform ShellOutPoint;
|
|
|
|
/// <summary>
|
|
/// If time.time is bigger than this value, so the gun can shoot
|
|
/// </summary>
|
|
[NonSerialized]
|
|
[SyncVar]
|
|
public float nextShootTime = 0f;
|
|
|
|
[NonSerialized]
|
|
[SyncVar]
|
|
public float Interval = 0f;
|
|
|
|
[NonSerialized]
|
|
public float shootInterval = 0f;
|
|
|
|
[NonSerialized]
|
|
[SyncVar]
|
|
public HandType hand = HandType.Right;
|
|
|
|
private float recoilVert = 0f;
|
|
|
|
private float recoilHori = 0f;
|
|
|
|
public override void OnEnable()
|
|
{
|
|
base.OnEnable();
|
|
}
|
|
|
|
public sealed override void InitData()
|
|
{
|
|
Data.Add("bullet_prefab", new DataRow(SupportDataType.UObject)
|
|
{
|
|
Name = "bullet_prefab"
|
|
});
|
|
Data.Add("bullet_speed", new DataRow(SupportDataType.Float)
|
|
{
|
|
Name = "bullet_speed",
|
|
FloatValue = 100f
|
|
});
|
|
Data.Add("damage", new DataRow(SupportDataType.Float)
|
|
{
|
|
Name = "damage",
|
|
FloatValue = 1000f
|
|
});
|
|
Data.Add("shootrate", new DataRow(SupportDataType.Float)
|
|
{
|
|
Name = "shootrate",
|
|
FloatValue = 10f
|
|
});
|
|
Data.Add("bullet_per_shoot", new DataRow(SupportDataType.Int)
|
|
{
|
|
Name = "bullet_per_shoot",
|
|
IntValue = 1
|
|
});
|
|
Data.Add("nature_recoil", new DataRow(SupportDataType.Boolean)
|
|
{
|
|
Name = "nature_recoil",
|
|
BooleanValue = false
|
|
});
|
|
Data.Add("recoil_mutiply", new DataRow(SupportDataType.Vector2)
|
|
{
|
|
Name = "recoil_mutiply"
|
|
});
|
|
Data.Add("recoil_recover_rate", new DataRow(SupportDataType.Vector2)
|
|
{
|
|
Name = "recoil_recover_rate",
|
|
Vector2Value = Vector2.one * 10f
|
|
});
|
|
Data.Add("muzzle_prefab", new DataRow(SupportDataType.UObject)
|
|
{
|
|
Name = "muzzle_prefab"
|
|
});
|
|
Data.Add("muzzle_despawn_time", new DataRow(SupportDataType.Float)
|
|
{
|
|
Name = "muzzle_despawn_time"
|
|
});
|
|
Data.Add("shell_key", new DataRow(SupportDataType.UObject)
|
|
{
|
|
Name = "shell_key"
|
|
});
|
|
Data.Add("shell_outforce", new DataRow(SupportDataType.Float)
|
|
{
|
|
Name = "shell_outforce"
|
|
});
|
|
Data.Add("shell_despawn_delay", new DataRow(SupportDataType.Float)
|
|
{
|
|
Name = "shell_despawn_delay"
|
|
});
|
|
Data["bullet_prefab"].ObjectValue = bullet_prefab;
|
|
Data["bullet_speed"].FloatValue = bullet_speed;
|
|
|
|
|
|
//Data["damage"].FloatValue = 1000.0f;
|
|
Data["shootrate"].FloatValue = shootrate;
|
|
Data["bullet_per_shoot"].IntValue = bullet_per_shoot;
|
|
Data["nature_recoil"].BooleanValue = nature_recoil;
|
|
Data["recoil_mutiply"].Vector2Value = recoil_mutiply;
|
|
Data["recoil_recover_rate"].Vector2Value = recoil_recover_rate;
|
|
Data["muzzle_prefab"].ObjectValue = muzzle_prefab;
|
|
Data["muzzle_despawn_time"].FloatValue = muzzle_despawn_time;
|
|
Data["shell_key"].ObjectValue = shell_key;
|
|
Data["shell_outforce"].FloatValue = shell_outforce;
|
|
Data["shell_despawn_delay"].FloatValue = shell_despawn_delay;
|
|
base.InitData();
|
|
}
|
|
|
|
[Server]
|
|
public void Shoot()
|
|
{
|
|
Shoot(-1);
|
|
}
|
|
|
|
[Server]
|
|
public void Shoot(int ownerIndex)
|
|
{
|
|
Shoot(LaunchPoint.position + LaunchPoint.forward * 1f, ownerIndex);
|
|
}
|
|
|
|
[Server]
|
|
public virtual bool Shoot(Vector3 target, int ownerIndex)
|
|
{
|
|
|
|
// 弹量不够
|
|
if (bullet_amount <= 0 && bullet_amount != -999)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// 未冷却
|
|
if (nextShootTime > Time.time)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (bullet_amount > 0)
|
|
{
|
|
bullet_amount--;
|
|
}
|
|
|
|
if (bullet_amount <= 0 && bullet_amount != -999)
|
|
{
|
|
LauncherEmpty();
|
|
}
|
|
|
|
for (int i = 0; i < Data["bullet_per_shoot"].IntValue; i++)
|
|
{
|
|
SpawnBullet(LaunchPoint.position, target - LaunchPoint.position, ownerIndex);
|
|
}
|
|
|
|
SpawnShell();
|
|
SpawnMuzzle(LaunchPoint.position);
|
|
nextShootTime = Time.time + shootInterval;
|
|
return true;
|
|
}
|
|
|
|
[TargetRpc]
|
|
public void LauncherEmpty()
|
|
{
|
|
// GameInit.Ins.self.DelWeapon();
|
|
}
|
|
|
|
public override void Awake()
|
|
{
|
|
base.Awake();
|
|
shootInterval = 1f / Data["shootrate"].FloatValue;
|
|
}
|
|
|
|
/// <summary>
|
|
/// If you are making a shooter game and you want recoil, you can override this functions.
|
|
/// </summary>
|
|
/// <param name="direction"></param>
|
|
/// <returns></returns>
|
|
protected virtual Vector3 CalculateRecoil(Vector3 direction)
|
|
{
|
|
if (Data["nature_recoil"].BooleanValue)
|
|
{
|
|
|
|
return direction + Vector3.up * UnityEngine.Random.Range(0f - Data["recoil_mutiply"].Vector2Value.y, Data["recoil_mutiply"].Vector2Value.y) + LaunchPoint.right * UnityEngine.Random.Range(0f - Data["recoil_mutiply"].Vector2Value.x, Data["recoil_mutiply"].Vector2Value.x);
|
|
}
|
|
return direction;
|
|
}
|
|
|
|
[Server]
|
|
public virtual Transform SpawnBullet(Vector3 startPoint, Vector3 direction, int ownerIndex)
|
|
{
|
|
GameObject bullet = Instantiate(bullet_prefab, startPoint, LaunchPoint.rotation);
|
|
Transform val = bullet.transform;
|
|
NetworkServer.Spawn(val.gameObject);
|
|
Bullet component = val.GetComponent<Bullet>();
|
|
component.Init(ownerIndex);
|
|
Rigidbody rigidbodyComponent = component.RigidbodyComponent;
|
|
Vector3 vector = CalculateRecoil(direction);
|
|
rigidbodyComponent.velocity = vector.normalized * Data["bullet_speed"].FloatValue;
|
|
rigidbodyComponent.rotation = Quaternion.LookRotation(vector.normalized);
|
|
return val;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 填充子弹
|
|
/// </summary>
|
|
public void StuffBullet(int amount)
|
|
{
|
|
if (amount < 0 && amount != -999)
|
|
{
|
|
return;
|
|
}
|
|
bullet_amount += amount;
|
|
}
|
|
|
|
[Server]
|
|
protected void SpawnMuzzle(Vector3 startPoint)
|
|
{
|
|
if (muzzle_prefab != null)
|
|
{
|
|
Transform val = Instantiate(muzzle_prefab, startPoint, new Quaternion(0, 0, 0, 0)).transform;
|
|
val.forward = LaunchPoint.forward;
|
|
NetworkServer.Spawn(val.gameObject);
|
|
if (val == null)
|
|
{
|
|
this.LogEditorOnly("Failed to spawn muzzle");
|
|
return;
|
|
}
|
|
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
|
|
{
|
|
NetworkServer.Destroy(val.gameObject);
|
|
}, Data["muzzle_despawn_time"].FloatValue);
|
|
}
|
|
}
|
|
|
|
[Server]
|
|
protected void SpawnShell()
|
|
{
|
|
if (shell_key != null && ShellOutPoint != null)
|
|
{
|
|
Transform val = Instantiate(shell_key, ShellOutPoint.position, Quaternion.Euler(UnityEngine.Random.insideUnitSphere * 360f)).transform;
|
|
NetworkServer.Spawn(val.gameObject);
|
|
Rigidbody component = ((Component)val).GetComponent<Rigidbody>();
|
|
if (component != null)
|
|
{
|
|
component.velocity = ShellOutPoint.forward * Data["shell_outforce"].FloatValue;
|
|
}
|
|
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
|
|
{
|
|
NetworkServer.Destroy(val.gameObject);
|
|
}, Data["shell_despawn_delay"].FloatValue);
|
|
}
|
|
}
|
|
}
|