using System; using System.Collections.Generic; using UnityEngine; namespace ProjectI.Combat { public static class LocalWeaponPreference { public static int First { get; set; } = 1; public static int Second { get; set; } = 2; } public static class WeaponRoster { private static readonly List entries = new List(); public static IReadOnlyList Entries { get { Ensure(); return entries; } } public static WeaponDefinition Get(int id) { Ensure(); foreach (var entry in entries) if (entry.weaponId == id) return entry; return null; } private static void Ensure() { if (entries.Count != 0 && entries[0] != null) return; entries.Clear(); var authored = Resources.Load("WeaponRoster"); if (authored != null && authored.weapons != null && authored.weapons.Length == 5) { entries.AddRange(authored.weapons); return; } Add(1,"Carbine",20,6,30,1.8,true,25,55,.5f,1.5f,.7f,60); Add(2,"Marksman rifle",40,2.8,12,2,false,40,80,.65f,1.5f,1.8f,45); Add(3,"Hand cannon",60,2,8,1.8,false,18,40,.4f,1.5f,2.6f,65); Add(4,"Shotgun",12,1.25,6,2.4,false,7,18,.15f,1.5f,3.2f,65,8,6); Add(5,"SMG",11,10,36,1.65,true,10,25,.35f,1.5f,.5f,65,1,1.2f); } private static void Add(int id,string name,float damage,double rate,int magazine,double reload,bool automatic,float start,float end,float floor,float weak,float recoil,float aim,int pellets=1,float spread=0) { var definition = ScriptableObject.CreateInstance(); definition.hideFlags = HideFlags.HideAndDontSave; definition.name = name; definition.weaponId = id; definition.displayName = name; definition.damage = damage; definition.rateOfFire = rate; definition.magazineSize = magazine; definition.reloadDuration = reload; definition.automatic = automatic; definition.range = Math.Max(60,end + 20); definition.falloffStart = start; definition.falloffEnd = end; definition.minimumDamageFraction = floor; definition.headshotMultiplier = weak; definition.recoilDegrees = recoil; definition.aimFieldOfView = aim; definition.pelletCount = pellets; definition.spreadDegrees = spread; definition.tracerColor = id == 3 ? new Color(1,.6f,.2f) : id == 4 ? new Color(1,.8f,.4f) : id == 5 ? new Color(.8f,.4f,1) : new Color(.4f,1,.8f); entries.Add(definition); } public static void ClearCache() => entries.Clear(); } public static class WeaponPattern { public static Vector3 Direction(Vector3 forward, ulong attackId, int pellet, int count, float degrees) { if (count <= 1 && degrees <= 0) return forward.normalized; uint bits = unchecked((uint)(attackId * 747796405UL + (ulong)pellet * 2891336453UL)); float phase = (bits % 10000) * .0001f * Mathf.PI * 2; float radius = count > 1 ? Mathf.Sqrt((pellet + .5f)/count) : .5f; var right = Vector3.Cross(Vector3.up,forward).normalized; if (right.sqrMagnitude < .1f) right = Vector3.right; var up = Vector3.Cross(forward,right).normalized; return (forward + (right*Mathf.Cos(phase)+up*Mathf.Sin(phase))*Mathf.Tan(degrees*Mathf.Deg2Rad)*radius).normalized; } public static float Falloff(float distance,float start,float end,float floor) => Mathf.Lerp(1,Mathf.Clamp(floor,.01f,1),Mathf.InverseLerp(start,Mathf.Max(start+.01f,end),distance)); } }