Tidy up weapon code and data dumper

This commit is contained in:
sardelka9515
2022-11-16 17:37:31 +08:00
parent 822a69573f
commit 50153d860a
35 changed files with 323192 additions and 743 deletions

View File

@ -7,240 +7,97 @@ using GTA;
using GTA.Math;
using GTA.Native;
using Newtonsoft.Json;
using RageCoop.Client.Scripting;
using RageCoop.Core;
using Console = GTA.Console;
using static RageCoop.Client.Shared;
namespace RageCoop.Client
{
#region DUMP
internal class VehicleInfo
{
public VehicleBone[] Bones;
public uint Hash;
public string Name;
public string[] Weapons;
}
internal class VehicleBone
{
public uint BoneID;
public uint BoneIndex;
public string BoneName;
}
internal class WeaponBones
{
public VehicleBone[] Bones;
public string Name;
}
internal class VehicleWeaponInfo
{
public uint Hash;
public string Name;
public Dictionary<uint, WeaponBones> Weapons = new Dictionary<uint, WeaponBones>();
public static void Dump(string input, string output)
{
Console.Info("Generating " + output);
if (!File.Exists(input))
{
Console.Info("Downloading");
HttpHelper.DownloadFile(
"https://raw.githubusercontent.com/DurtyFree/gta-v-data-dumps/master/vehicles.json", input);
}
Console.Info("Deserialising");
var infos = JsonConvert.DeserializeObject<VehicleInfo[]>(File.ReadAllText(input));
Console.Info("Serialising");
File.WriteAllText(output,
JsonConvert.SerializeObject(
infos.Select(x => FromVehicle(x)).Where(x => x != null),
Formatting.Indented));
}
public static VehicleWeaponInfo FromVehicle(VehicleInfo info)
{
if (info.Weapons.Length == 0) return null;
var result = new VehicleWeaponInfo { Hash = info.Hash, Name = info.Name };
for (var i = 0; i < info.Weapons.Length; i++)
result.Weapons.Add((uint)Game.GenerateHash(info.Weapons[i])
, new WeaponBones
{
Name = info.Weapons[i],
Bones = info.Bones.Where(x =>
x.BoneName.StartsWith($"weapon_{i + 1}") && !x.BoneName.EndsWith("rot")).ToArray()
});
return result;
}
}
internal class WeaponInfo
{
public uint Hash;
public string Name;
}
[StructLayout(LayoutKind.Explicit, Size = 312)]
public struct DlcWeaponData
{
}
internal class WeaponFix
{
public Dictionary<uint, string> Bullet = new Dictionary<uint, string>();
public Dictionary<uint, string> Lazer = new Dictionary<uint, string>();
public Dictionary<uint, string> Others = new Dictionary<uint, string>();
}
#endregion
internal static class WeaponUtil
{
public const string VehicleWeaponLocation = @"RageCoop\Data\VehicleWeapons.json";
public const string WeaponFixLocation = @"RageCoop\Data\WeaponFixes.json";
public static Dictionary<uint, VehicleWeaponInfo> VehicleWeapons = new Dictionary<uint, VehicleWeaponInfo>();
public static WeaponFix WeaponFix;
public static readonly HashSet<uint> ExplosiveBullets = new HashSet<uint>
{
(uint)VehicleWeaponHash.PlayerLazer,
(uint)WeaponHash.Railgun,
1638077257
};
public static readonly HashSet<WeaponHash> ProjectileWeapons = new HashSet<WeaponHash>
{
WeaponHash.HomingLauncher,
WeaponHash.RPG,
WeaponHash.Firework,
WeaponHash.UpNAtomizer,
WeaponHash.GrenadeLauncher,
WeaponHash.GrenadeLauncherSmoke,
WeaponHash.CompactGrenadeLauncher,
WeaponHash.FlareGun
};
public static readonly HashSet<VehicleWeaponHash> VehicleProjectileWeapons = new HashSet<VehicleWeaponHash>
{
VehicleWeaponHash.PlaneRocket,
VehicleWeaponHash.SpaceRocket,
VehicleWeaponHash.Tank,
(VehicleWeaponHash)3565779982, // STROMBERG missiles
(VehicleWeaponHash)3169388763 // SCRAMJET missiles
};
public static Dictionary<uint, WeaponInfo> Weapons;
static WeaponUtil()
{
if (!File.Exists(VehicleWeaponLocation))
{
Directory.CreateDirectory(@"RageCoop\Data\tmp");
var input = @"RageCoop\Data\tmp\vehicles.json";
VehicleWeaponInfo.Dump(input, VehicleWeaponLocation);
}
// Parse and load to memory
foreach (var w in JsonConvert.DeserializeObject<VehicleWeaponInfo[]>(
File.ReadAllText(VehicleWeaponLocation))) VehicleWeapons.Add(w.Hash, w);
WeaponFix = JsonConvert.DeserializeObject<WeaponFix>(File.ReadAllText(WeaponFixLocation));
}
File.ReadAllText(VehicleWeaponDataPath))) VehicleWeapons.Add(w.Hash, w);
public static void DumpWeaponFix(string path = WeaponFixLocation)
Weapons = JsonConvert.DeserializeObject<Dictionary<uint, WeaponInfo>>(
File.ReadAllText(WeaponInfoDataPath));
if (File.Exists(WeaponFixDataPath))
{
WeaponFix = JsonConvert.DeserializeObject<WeaponFix>(File.ReadAllText(WeaponFixDataPath));
}
else
{
API.Logger.Warning("Weapon fix data not found");
}
}
public static void DumpWeaponFix(string path)
{
var P = Game.Player.Character;
var pos = P.Position + Vector3.WorldUp * 3;
var types = new HashSet<int> { 3 };
P.IsInvincible = true;
var fix = new WeaponFix();
foreach (VehicleWeaponHash v in Enum.GetValues(typeof(VehicleWeaponHash)))
foreach (var w in Weapons)
{
Console.Info("Testing: " + v);
if (types.Contains(v.GetWeaponDamageType()))
Console.Info("Testing " + w.Value.Name);
if (w.Value.FireType != "PROJECTILE")
{
var asset = new WeaponAsset((int)v);
var asset = new WeaponAsset(w.Key);
asset.Request(1000);
World.ShootBullet(pos, pos + Vector3.WorldUp, P, asset, 0, 1000);
if (!Function.Call<bool>(Hash.IS_BULLET_IN_AREA, pos.X, pos.Y, pos.Z, 10f, true) &&
!Function.Call<bool>(Hash.IS_PROJECTILE_IN_AREA, pos.X - 10, pos.Y - 10, pos.Z - 10, pos.X + 10,
pos.Y + 10, pos.Z + 10, true))
fix.Bullet.Add((uint)v, $"{nameof(VehicleWeaponHash)}.{v}");
{
switch (w.Value.DamageType)
{
case "BULLET":
fix.Bullet.Add(w.Key, w.Value.Name);
break;
case "EXPLOSIVE":
fix.Lazer.Add(w.Key, w.Value.Name);
break;
default:
fix.Others.Add(w.Key, w.Value.Name);
break;
}
}
foreach (var p in World.GetAllProjectiles()) p.Delete();
Script.Wait(50);
}
}
foreach (WeaponHash w in Enum.GetValues(typeof(WeaponHash)))
if (types.Contains(w.GetWeaponDamageType()))
{
Console.Info("Testing: " + w);
var asset = new WeaponAsset((int)w);
asset.Request(1000);
World.ShootBullet(pos, pos + Vector3.WorldUp, P, asset, 0, 1000);
if (!Function.Call<bool>(Hash.IS_BULLET_IN_AREA, pos.X, pos.Y, pos.Z, 10f, true) &&
!Function.Call<bool>(Hash.IS_PROJECTILE_IN_AREA, pos.X - 10, pos.Y - 10, pos.Z - 10, pos.X + 10,
pos.Y + 10, pos.Z + 10, true))
fix.Bullet.Add((uint)w, $"{nameof(WeaponHash)}.{w}");
foreach (var p in World.GetAllProjectiles()) p.Delete();
Script.Wait(50);
}
AddLazer(VehicleWeaponHash.PlayerSavage);
AddLazer(VehicleWeaponHash.StrikeforceCannon);
void AddLazer(dynamic hash)
{
fix.Lazer.Add((uint)hash, $"{hash.GetType().Name}.{hash.ToString()}");
}
File.WriteAllText(path, JsonConvert.SerializeObject(fix, Formatting.Indented));
P.IsInvincible = false;
}
public static void DumpWeaponHashes(string path = VehicleWeaponLocation)
{
var hashes = new Dictionary<uint, string>();
foreach (var wep in JsonConvert.DeserializeObject<WeaponInfo[]>(
HttpHelper.DownloadString(
"https://raw.githubusercontent.com/DurtyFree/gta-v-data-dumps/master/weapons.json")))
{
if (!wep.Name.StartsWith("WEAPON")) continue;
hashes.Add(wep.Hash, wep.Name);
}
var output = "public enum WeaponHash : uint\r\n{";
var lines = new List<string>();
foreach (var hash in hashes)
lines.Add($"{CoreUtils.FormatToSharpStyle(hash.Value, 7)} = {hash.Key.ToHex()}");
lines.Sort();
foreach (var l in lines) output += $"\r\n\t{l},";
output += "\r\n}";
File.WriteAllText(path, output);
}
public static void DumpVehicleWeaponHashes(string path = @"RageCoop\Data\VehicleWeaponHash.cs")
{
var hashes = new Dictionary<uint, string>();
foreach (var veh in VehicleWeapons.Values)
foreach (var hash in veh.Weapons)
if (!hashes.ContainsKey(hash.Key))
hashes.Add(hash.Key, hash.Value.Name);
var output = "public enum VehicleWeaponHash : uint\r\n{\r\n\tInvalid = 0xFFFFFFFF,";
var lines = new List<string>();
foreach (var hash in hashes) lines.Add($"{CoreUtils.FormatToSharpStyle(hash.Value)} = {hash.Key.ToHex()}");
lines.Sort();
foreach (var l in lines) output += $"\r\n\t{l},";
output += "\r\n}";
File.WriteAllText(path, output);
}
public static uint GetWeaponFix(uint hash)
{
if (WeaponFix.Bullet.TryGetValue(hash, out var _)) return (uint)VehicleWeaponHash.SubcarMg;
if (WeaponFix.Lazer.TryGetValue(hash, out var _)) return (uint)VehicleWeaponHash.PlayerLazer;
if (WeaponFix.Bullet.TryGetValue(hash, out _)) return 0x461DDDB0;
if (WeaponFix.Lazer.TryGetValue(hash, out _)) return 0xE2822A29;
return hash;
}
public static Dictionary<uint, bool> GetWeaponComponents(this Weapon weapon)
{
Dictionary<uint, bool> result = null;
@ -289,21 +146,10 @@ namespace RageCoop.Client
public static bool IsUsingProjectileWeapon(this Ped p)
{
var vp = p.VehicleWeapon;
var type = Function.Call<int>(Hash.GET_WEAPON_DAMAGE_TYPE, vp);
if (vp != VehicleWeaponHash.Invalid)
return type == 3
? false
: VehicleProjectileWeapons.Contains(vp) || (type == 5 && !ExplosiveBullets.Contains((uint)vp));
var w = p.Weapons.Current;
return w.Group == WeaponGroup.Thrown || ProjectileWeapons.Contains(w.Hash);
return Weapons.TryGetValue(vp != VehicleWeaponHash.Invalid ?
(uint)vp : (uint)p.Weapons.Current.Hash, out var info)
&& info.FireType == "PROJECTILE";
}
public static int GetWeaponDamageType<T>(this T hash) where T : Enum
{
return Function.Call<int>(Hash.GET_WEAPON_DAMAGE_TYPE, hash);
}
public static string GetFlashFX(this WeaponHash w, bool veh)
{
if (veh)
@ -361,18 +207,4 @@ namespace RageCoop.Client
return Function.Call<WeaponGroup>(Hash.GET_WEAPONTYPE_GROUP, hash);
}
}
/*
class WeaponInfo
{
public string Name;
public string MuzzleFx;
}
public class AimingInfo
{
public string Name;
public float HeadingLimit;
public float SweepPitchMin;
public float SweepPitchMax;
}
*/
}