-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathGameStructs.cs
319 lines (263 loc) · 10.6 KB
/
GameStructs.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
namespace Spotlight.Core.Memory
{
using System;
using System.Runtime.InteropServices;
using Rage;
internal enum eBoneRefId : int
{
extralight_1 = 124,
extralight_2 = 125,
extralight_3 = 126,
extralight_4 = 127,
turret_1base = 297,
turret_2base = 299,
turret_3base = 301,
turret_4base = 303,
turret_1barrel = 298,
turret_2barrel = 300,
turret_3barrel = 302,
turret_4barrel = 304,
}
[StructLayout(LayoutKind.Explicit)]
internal unsafe struct CVehicle
{
[FieldOffset(0x0030)] public fragInst* inst;
public CVehicleWeaponMgr* GetWeaponMgr()
{
fixed (CVehicle* v = &this)
{
return *(CVehicleWeaponMgr**)((IntPtr)v + GameOffsets.CVehicle_WeaponMgr);
}
}
public byte* GetBoneRefsArray()
{
fixed (CVehicle* v = &this)
{
//vehicle->modelInfo->unkStructB0->struct->boneRefs;
IntPtr modelInfo = *(IntPtr*)((IntPtr)v + 0x20);
IntPtr unkStruct = *(IntPtr*)(modelInfo + 0xB0);
IntPtr vehicleStruct = *(IntPtr*)(unkStruct);
IntPtr boneRefs = (vehicleStruct + 0x10);
return (byte*)boneRefs;
}
}
public byte GetBoneIndex(eBoneRefId boneRefId)
{
return GetBoneRefsArray()[(int)boneRefId];
}
public IntPtr GetMakeName()
{
fixed (CVehicle* v = &this)
{
IntPtr modelInfo = *(IntPtr*)((IntPtr)v + 0x20);
IntPtr makeName = modelInfo + GameOffsets.CVehicleModelInfo_VehicleMakeName;
return makeName;
}
}
public IntPtr GetGameName()
{
fixed (CVehicle* v = &this)
{
IntPtr modelInfo = *(IntPtr*)((IntPtr)v + 0x20);
IntPtr gameName = modelInfo + GameOffsets.CVehicleModelInfo_GameName;
return gameName;
}
}
public void SetLightEmissive(int index, float value)
{
fixed (CVehicle* v = &this)
{
IntPtr drawHandler = *(IntPtr*)((IntPtr)v + 0x48);
if (drawHandler == IntPtr.Zero)
{
return;
}
IntPtr customShaderEffect = *(IntPtr*)(drawHandler + 0x20);
if (customShaderEffect == IntPtr.Zero)
{
return;
}
float* lightEmissives = (float*)(customShaderEffect + 0x20);
lightEmissives[index] = value;
}
}
}
[StructLayout(LayoutKind.Explicit)]
internal unsafe struct CVehicleWeaponMgr
{
[FieldOffset(0x110)] public int TurretCount;
[FieldOffset(0x114)] public int WeaponCount;
public int GetMaxTurrets() { return 6; }
public int GetMaxWeapons() { return 6; }
public CTurret* GetTurret(int index)
{
fixed (CVehicleWeaponMgr* v = &this)
{
IntPtr* turrets = (IntPtr*)((IntPtr)v + 0x8);
return (CTurret*)(turrets[index]);
}
}
public CVehicleWeapon* GetWeapon(int index)
{
fixed (CVehicleWeaponMgr* v = &this)
{
IntPtr* weapons = (IntPtr*)((IntPtr)v + 0x68);
return (CVehicleWeapon*)(weapons[index]);
}
}
}
[StructLayout(LayoutKind.Explicit)]
internal unsafe struct CTurret
{
[FieldOffset(0x0010)] public eBoneRefId baseBoneRefId;
[FieldOffset(0x0014)] public eBoneRefId barrelBoneRefId;
[FieldOffset(0x20)] public Quaternion rot1;
[FieldOffset(0x30)] public Quaternion rot2;
[FieldOffset(0x40)] public Quaternion rot3;
}
[StructLayout(LayoutKind.Explicit)]
internal unsafe struct CVehicleWeapon
{
[FieldOffset(0x0020)] public eBoneRefId weaponBoneRefId;
public uint GetName()
{
//vehWeapon->weapon->info->nameHash;
fixed (CVehicleWeapon* v = &this)
{
IntPtr weapon = *(IntPtr*)((IntPtr)v + 0x18);
if (weapon != IntPtr.Zero)
{
IntPtr info = *(IntPtr*)(weapon + 0x40);
if (info != IntPtr.Zero)
{
uint name = *(uint*)(info + 0x10);
return name;
}
}
}
return 0xFFFFFFFF;
}
}
[StructLayout(LayoutKind.Explicit)]
internal unsafe struct fragInst
{
[FieldOffset(0x68)] public fragCacheEntry* entry;
}
[StructLayout(LayoutKind.Explicit)]
internal unsafe struct fragCacheEntry
{
[FieldOffset(0x148 + 0x30)] public crSkeleton* skeleton;
}
[StructLayout(LayoutKind.Explicit)]
internal unsafe struct crSkeleton
{
[FieldOffset(0x0000)] public crSkeletonData* skeletonData;
[FieldOffset(0x0008)] public Matrix* entityTransform;
[FieldOffset(0x0010)] public Matrix* desiredBonesTransformsArray;
[FieldOffset(0x0018)] public Matrix* currentBonesTransformsArray;
[FieldOffset(0x0020)] public int bonesCount;
}
[StructLayout(LayoutKind.Explicit)]
internal unsafe struct crSkeletonData
{
[FieldOffset(0x0020)] public crSkeletonBoneData* bones;
[FieldOffset(0x0028)] public Matrix* bonesTransformationsInverted;
[FieldOffset(0x0030)] public Matrix* bonesTransformations;
[FieldOffset(0x0038)] public ushort* bonesParentIndices;
[FieldOffset(0x005E)] public ushort bonesCount;
public string GetBoneNameForIndex(uint index)
{
if (index >= bonesCount)
return null;
return bones[index].GetName();
}
}
[StructLayout(LayoutKind.Explicit, Size = 0x50)]
internal unsafe struct crSkeletonBoneData
{
[FieldOffset(0x0000)] public Quaternion rotation;
[FieldOffset(0x0010)] public NativeVector3 translation;
[FieldOffset(0x0032)] public ushort parentIndex;
[FieldOffset(0x0038)] public IntPtr namePtr;
[FieldOffset(0x0042)] public ushort index;
public string GetName() => namePtr == null ? null : Marshal.PtrToStringAnsi(namePtr);
}
[StructLayout(LayoutKind.Explicit)]
internal unsafe struct CCoronas
{
public void Draw(Vector3 position, float size, int color, float intensity, float zBias, Vector3 direction, float innerAngle, float outerAngle, ushort flags)
{
fixed (CCoronas* self = &this)
{
*tmpPos = position;
*tmpDir = direction;
GameFunctions.CCoronas_Draw(self, tmpPos, size, color, intensity, zBias, tmpDir, 1.0f, innerAngle, outerAngle, flags);
}
}
/*
* Allocate 16-byte aligned vectors since having Pack = 16 in NativeVector3's StructLayout does not ensure that it is 16-byte aligned
* and CCoronos::Draw expects the vectors to be 16-byte aligned.
* So copying the vector values here and passing these pointers to CCoronas::Draw should be good enough.
*
* TODO: does C# have some way to force aligment of structs? Couldn't find it so far...
*/
private static readonly NativeVector3* tmpPos = (NativeVector3*)(16 * (((long)Marshal.AllocHGlobal(sizeof(NativeVector3) + 8) + 15) / 16));
private static readonly NativeVector3* tmpDir = (NativeVector3*)(16 * (((long)Marshal.AllocHGlobal(sizeof(NativeVector3) + 8) + 15) / 16));
}
[StructLayout(LayoutKind.Explicit, Size = 0x1C0)]
internal unsafe struct CLightDrawData
{
[FieldOffset(0x0000)] public NativeVector3 Position;
[FieldOffset(0x0010)] public NativeColorRGBAFloat Color;
[FieldOffset(0x0020)] private NativeVector3 unk1;
[FieldOffset(0x0030)] private NativeVector3 unk2;
[FieldOffset(0x0040)] public NativeColorRGBAFloat VolumeOuterColor;
[FieldOffset(0x0050)] private NativeVector3 unk3;
[FieldOffset(0x0060)] public eLightType LightType;
[FieldOffset(0x0064)] public eLightFlags Flags;
[FieldOffset(0x0068)] public float Intensity;
[FieldOffset(0x0070)] public int TextureDictIndex;
[FieldOffset(0x0074)] public uint TextureNameHash;
[FieldOffset(0x0078)] public float VolumeIntensity;
[FieldOffset(0x007C)] public float VolumeSize;
[FieldOffset(0x0080)] public float VolumeExponent;
[FieldOffset(0x0088)] public ulong ShadowRenderId;
[FieldOffset(0x0090)] public uint ShadowUnkValue;
[FieldOffset(0x0098)] public float Range;
[FieldOffset(0x009C)] public float FalloffExponent;
[FieldOffset(0x00D4)] public float ShadowNearClip; // default: 0.1
public static CLightDrawData* New(eLightType type, eLightFlags flags, Vector3 position, RGB color, float intensity)
{
const float ByteToFloatFactor = 1.0f / 255.0f;
CLightDrawData* d = GameFunctions.GetFreeLightDrawDataSlotFromQueue();
NativeVector3 pos = position;
NativeColorRGBAFloat col = new NativeColorRGBAFloat { R = color.R * ByteToFloatFactor, G = color.G * ByteToFloatFactor, B = color.B * ByteToFloatFactor };
GameFunctions.InitializeLightDrawData(d, type, (uint)flags, &pos, &col, intensity, 0xFFFFFF);
return d;
}
}
internal enum eLightType
{
RANGE = 1,
SPOT_LIGHT = 2,
RANGE_2 = 4,
}
[Flags]
internal enum eLightFlags : uint
{
None = 0,
CanRenderUnderground = 0x8, // if not set the light won't render in underground parts of the map, such as tunnels
IgnoreArtificialLightsState = 0x10, // if set, keeps drawing the light after calling SET_ARTIFICIAL_LIGHTS_STATE(false)
HasTexture = 0x20,
ShadowsFlag1 = 0x40, // needed
ShadowsFlag2 = 0x80, // needed
ShadowsFlag3 = 0x100, // needed, otherwise shadow flickers
ShadowsFlag4 = 0x4000000, // needed, otherwise the shadow doesn't render properly sometimes
EnableShadows = ShadowsFlag1 | ShadowsFlag2 | ShadowsFlag3 | ShadowsFlag4,
EnableVolume = 0x1000,
UseVolumeOuterColor = 0x80000,
DisableSpecular = 0x2000,
IgnoreGlass = 0x800000, // if set the light won't affect glass
DisableLight = 0x40000000, // if set the light isn't rendered, can be used to draw only the volume
}
}