Files
MRCS/Assets/_MrCs/Scripts/Guns/Launcher.cs
2025-11-10 18:46:16 +08:00

241 lines
5.8 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using DragonLi.Core;
using Mirror;
using UnityEngine;
public class Launcher : NetworkBehaviour
{
[Header("枪械类型")]
#if UNITY_EDITOR
[DisplayOnly]
#endif
[SyncVar]
public GunType type;
[Header("枪械射速(s)")]
#if UNITY_EDITOR
[DisplayOnly]
#endif
public float shootRate = 10f;
[Header("枪械后坐力")]
#if UNITY_EDITOR
[DisplayOnly]
#endif
public float recoil = 100f;
[Header("子弹创建位置")]
public Transform bulletPoint;
[Header("子弹预制体")]
public GameObject bullet_prefab;
[Header("子弹数量")]
#if UNITY_EDITOR
[DisplayOnly]
#endif
[SyncVar]
public float bullet_amount = 0f;
[Header("枪械持有位置")]
#if UNITY_EDITOR
[DisplayOnly]
#endif
[SyncVar]
public HandType hand = HandType.Right;
[Header("子弹每次射击量")]
#if UNITY_EDITOR
[DisplayOnly]
#endif
public int bullet_per_shoot = 1;
[Header("开火创建位置")]
public Transform muzzlePoint;
[Header("开火预制体")]
public GameObject muzzle_prefab;
[Header("开火销毁时间")]
public float muzzle_despawn_time = 1;
[Header("弹壳创建位置")]
public Transform shellPoint;
[Header("弹壳预制体")]
public GameObject shell_prefab;
[Header("弹壳朝向")]
public float shell_outforce;
[Header("弹壳销毁时间")]
public float shell_despawn_delay;
/// <summary>
/// If time.time is bigger than this value, so the gun can shoot
/// </summary>
[NonSerialized]
[SyncVar]
public float nextShootTime = 0f;
/// <summary>
/// 上子弹时间
/// </summary>
[NonSerialized] [SyncVar]
public float waitBulletTime;
/// <summary>
/// 持续时间
/// </summary>
public float userTime;
private float _curWaitBulletTime = 0f;
private bool _isWaiBulletting = false;
//private float _shootInterval = 0f;
public void Awake()
{
bullet_amount = 0;
}
[Server]
public bool Shoot()
{
return Shoot(-1);
}
[Server]
public bool Shoot(int ownerIndex)
{
return Shoot(bulletPoint.position + bulletPoint.forward * 1f, ownerIndex);
}
[Server]
public virtual bool Shoot(Vector3 target, int ownerIndex)
{
// 未冷却
if (nextShootTime > Time.time)
{
return false;
}
if (bullet_amount > 0)
{
bullet_amount--;
}
// 弹量不够
if (bullet_amount <= 0&&!_isWaiBulletting&& waitBulletTime>0)
{
_isWaiBulletting = true;
PlayWaitBullet();
return false;
}
if (_isWaiBulletting)
{
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
_isWaiBulletting = false;
StopBullet();
SetBulletAmount(GameManager.Ins.GunInfos[type][1].BulletAmount);
},waitBulletTime);
return false;
}
if (bullet_amount <= 0 && bullet_amount != -999)
{
// LauncherEmpty();
}
for (int i = 0; i < bullet_per_shoot; i++)
{
SpawnBullet(ownerIndex, target - bulletPoint.position);
}
SpawnShell();
SpawnMuzzle();
nextShootTime = Time.time + shootRate;
return true;
}
// [TargetRpc]
// public void LauncherEmpty()
// {
// GameInit.Ins.self.DelWeapon();
// }
public int x = 5;
[Server]
public virtual Transform SpawnBullet(int ownerIndex, Vector3 direction)
{
GameObject bullet = Instantiate(bullet_prefab, bulletPoint.position, bulletPoint.rotation);
Transform val = bullet.transform;
NetworkServer.Spawn(val.gameObject);
Bullet component = val.GetComponent<Bullet>();
component.OnSpawn(ownerIndex, direction, shootRate,userTime);
return val;
}
/// <summary>
/// 填充子弹
/// </summary>
public void StuffBullet(int amount)
{
if (amount < 0 && amount != -999)
{
return;
}
bullet_amount = amount;
GunInfo info = GameManager.Ins.GunInfos[type][1];
userTime = info.Time;
}
public void SetBulletAmount(int amount)
{
bullet_amount = amount;
}
public virtual void PlayWaitBullet(){}
public virtual void StopBullet(){}
[Server]
protected void SpawnMuzzle()
{
if (muzzle_prefab != null)
{
Transform val = Instantiate(muzzle_prefab, muzzlePoint.position, new Quaternion(0, 0, 0, 0)).transform;
val.forward = muzzlePoint.forward;
NetworkServer.Spawn(val.gameObject);
if (val == null)
{
this.LogEditorOnly("Failed to spawn muzzle");
return;
}
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
NetworkServer.Destroy(val.gameObject);
}, muzzle_despawn_time);
}
}
[Server]
protected void SpawnShell()
{
if (shell_prefab != null && shellPoint != null)
{
Transform val = Instantiate(shell_prefab, shellPoint.position, Quaternion.Euler(UnityEngine.Random.insideUnitSphere * 360f)).transform;
NetworkServer.Spawn(val.gameObject);
Rigidbody component = val.GetComponent<Rigidbody>();
if (component != null)
{
component.velocity = shellPoint.forward * shell_outforce;
}
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
NetworkServer.Destroy(val.gameObject);
}, shell_despawn_delay);
}
}
}