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;
///
/// Where should we spawn bullet
///
public Transform LaunchPoint;
///
/// Where to spawn shell
///
public Transform ShellOutPoint;
///
/// If time.time is bigger than this value, so the gun can shoot
///
[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;
}
///
/// If you are making a shooter game and you want recoil, you can override this functions.
///
///
///
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();
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;
}
///
/// 填充子弹
///
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();
if (component != null)
{
component.velocity = ShellOutPoint.forward * Data["shell_outforce"].FloatValue;
}
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
NetworkServer.Destroy(val.gameObject);
}, Data["shell_despawn_delay"].FloatValue);
}
}
}