forked from kapuragu/FoxEngineTemplates
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfrt_gz.bt
350 lines (313 loc) · 9.95 KB
/
frt_gz.bt
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
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
//------------------------------------------------
// Note: Values hardcoded from e20020_area.frt
//------------------------------------------------
LittleEndian();
local byte legacyParam = 1;
struct Vector3
{
float x;
float y;
float z;
};
enum <ubyte> IsNodeEvent
{
EDGE = 0,
NODE = 1,
};
enum <ubyte> IsLoop
{
CONTINUE = 0,
LOOP = 1,
};
enum <ubyte> RouteAimTargetType
{
ROUTE_AIM_NO_TARGET = 0,
ROUTE_AIM_STATIC_POINT = 1,
ROUTE_AIM_CHARACTER = 2,
ROUTE_AIM_ROUTE_AS_SIGHT_MOVE_PATH = 3,
ROUTE_AIM_ROUTE_AS_OBJECT = 4,
// AIM_TARGET_TYPE_NO_TARGET = 0,
// AIM_TARGET_TYPE_POSITION = 1,
// AIM_TARGET_TYPE_CHARA = 2,
// AIM_TARGET_TYPE_AIM_ROUTE_AS_SIGHT_MOVE_PATH = 3,
// AIM_TARGET_TYPE_AIM_ROUTE_AS_OBJECT = 4,
// AIM_TARGET_TYPE_TPP_TWO_POINTS_ROUND_TRIP = 5,
// AIM_TARGET_TYPE_TPP_RANDOM_MOVE_INC_CIRCLE = 6,
};
enum <uint> EventType
{
Wait = 561913624,
SetTargetSpeed = 1375828191,
RelaxedStandWalkAct = 3641577009,
Conversation = 3952237029,
ForwardChangeSpeed = 4126739186,
Move = 4202868537,
CautionSquatIdleAim = 199044653,
RouteMoveFree = 225225504,
RelaxedStandWalk = 357669894,
Vanish = 518500859,
VehicleGetOff = 857869852,
Back = 895949676,
Forward = 1264107696,
RideVehicle = 1654546587,
StandDash = 1969779497,
CautionStandIdleReady = 2091872133,
SquatIdle = 2156064302,
OpenDoor = 2445979707,
CloseDoor = 2628821024,
Stop = 2686021750,
RouteMoveRun = 2913611970,
CautionStandIdleAim = 3031653810,
CautionSearchStandWalkReady = 3132068007,
VehicleFire = 3156094081,
RouteMove = 3186624026,
Hovering = 3396619717,
CautionStandWalkReady = 3754167279,
RelaxedStandIdle = 3942535391,
hashed_CautionIdleSearchNode = 3129891228,
hashed_RelaxedStandIdle = 1521517928,
hashed_EnterVehicle = 1597064337,
hashed_UsingSearchLight = 1847252103,
hashed_RelaxedWalk = 710958087,
hashed_RelaxedWalk2 = 32956284,
hashed_UsingFlashLight = 1014362962,
EMPTY_STRING = 3205930904,
};
// Route Aim Params
struct RouteAimStaticPointParams
{
Vector3 aimPos;
FSkip(sizeof(uint));
};
struct RouteAimCharacterParams
{
uint64 characterId; //Does TPP use a 64-bit has too?
FSkip(sizeof(uint) * 2);
};
struct RouteAimRouteAsSightParams
{
uint sightRouteAId;
uint sightRouteBId; //Almost always the rest are empty string hashes
uint sightRouteCId;
uint sightRouteDId;
};
struct RouteAimRouteAsObjectParams
{
uint objectRouteAId; //No idea how this differs from Route As Sight Move
uint objectRouteBId; //Almost always the rest are empty string hashes
uint objectRouteCId;
uint objectRouteDId;
};
// Event Type Params
struct EventTypeWaitParams
{
int eventWaitTime;
FSkip(sizeof(uint) * 3);
};
struct EventType_1179698897_Params
{
int eventParam0;
int eventParam1;
int eventParam2;
FSkip(sizeof(uint));
};
struct EventTypeSetTargetSpeedParams
{
int eventSpeed0;
int eventSpeed1;
FSkip(sizeof(uint) * 2);
};
struct EventType_1521517928_Params
{
int eventParam0;
FSkip(sizeof(uint) * 3);
};
struct EventType_1597064337_Params
{
int eventParam0;
int eventParam1;
FSkip(sizeof(uint) * 2);
};
struct EventType_3240040728_Params
{
int eventParam0;
int eventParam1;
int eventParam2;
int eventParam3;
};
struct EventTypeRelaxedStandWalkActParams
{
int eventParam0;
FSkip(sizeof(uint) * 3);
};
struct EventTypeConversationParams
{
uint conversationList; //Hash of a string found in EnemyConversationList .json files.
FSkip(sizeof(uint)); //With both hashes, they're read and written as 32-bit hashes on PC and PS3, but...
uint friendCharacterId; //...presumably the extra two bytes are just leftovers, as endianness is flipped independently on them.
FSkip(sizeof(uint)); //These could be swapped for two StrCode64 hashes in exchange for PS3 routes not being readable, which is fine.
};
struct EventTypeForwardChangeSpeedParams
{
int eventSpeed;
FSkip(sizeof(uint) * 3);
};
struct EventTypeMoveParams
{
int eventSpeed;
int eventEulerAngle; //Values include -45, -90, 180, etc.
FSkip(sizeof(uint) * 2);
};
struct Event
{
if (legacyParam==1)
{
//Less detailed ones for unity:
EventType eventType;
uint param0;
uint param1;
FSkip(sizeof(uint));
uint param2;
uint param3;
uint param4;
uint param5;
uint param6;
uint param7;
uint param8;
uint param9;
}
else
{
EventType eventType;
//"Param0" in TPP
IsNodeEvent isNodeEvent;
RouteAimTargetType aimPointType;
FSkip(sizeof(byte));
IsLoop isLoop; //Assumption that this bool is responsible for soldiers looping on an event node of a route, like searchlights
//"Param1" in TPP
ushort time; //A common wait time is 479 or 299.
short dir <hidden=true>; local float eulerDir = (float)dir / 180; //Counter-clockwise from 0 to ushort max, in Unity looking at blue/Z. Negative
//"Param1.5". This isn't in TPP. Its removal in TPP could have caused the "snippet" memory leak param bytes to appear.
byte isNotNodeEvent <hidden=true>; Assert(isNotNodeEvent==-isNodeEvent); FSkip(sizeof(byte)*3);
//"Param2 to Param5" in TPP. Possibly identical to TPP too.
if (aimPointType == ROUTE_AIM_NO_TARGET)
FSkip(sizeof(uint) * 4);
else if (aimPointType == ROUTE_AIM_STATIC_POINT)
RouteAimStaticPointParams aimParams;
else if (aimPointType == ROUTE_AIM_CHARACTER)
RouteAimCharacterParams aimParams;
else if (aimPointType == ROUTE_AIM_ROUTE_AS_SIGHT_MOVE_PATH)
RouteAimRouteAsSightParams aimParams;
else if (aimPointType == ROUTE_AIM_ROUTE_AS_OBJECT)
RouteAimRouteAsObjectParams aimParams;
else
Assert(2+2==5,"Unknown aimpointtype!!!");
//"Param6-Param9" in TPP. Fully depends on the event type, currently 48 of them, though most are empty. Sometimes hashes, sometimes ints.
if (eventType==Wait)
EventTypeWaitParams eventParams;
else if (eventType==1179698897)
EventType_1179698897_Params eventParams;
else if (eventType==SetTargetSpeed)
EventTypeSetTargetSpeedParams eventParams;
else if (eventType==1521517928)
EventType_1521517928_Params eventParams;
else if (eventType==1597064337)
EventType_1597064337_Params eventParams;
else if (eventType==3240040728)
EventType_3240040728_Params eventParams;
else if (eventType==RelaxedStandWalkAct)
EventTypeRelaxedStandWalkActParams eventParams;
else if (eventType==Conversation)
EventTypeConversationParams eventParams;
else if (eventType==ForwardChangeSpeed)
EventTypeForwardChangeSpeedParams eventParams;
else if (eventType==Move)
EventTypeMoveParams eventParams;
else
FSkip(sizeof(uint) * 4);
}
};
struct RouteDefinitions
{
uint nodesOffset;
uint eventTableOffset;
uint eventsOffset;
ushort nodeCount;
ushort eventCount;
};
struct EventTable
{
ushort eventNodeCount;
ushort eventStartIndex;
};
struct NodeUnpacked
{
//Vector3 Bit Unpacking by Joey:
//https://discord.com/channels/364177293133873153/364178190588968970/894215344099573760
//https://cdn.discordapp.com/attachments/364178190588968970/894215342069538907/unknown.png
int64 nodeBits;
local int packed_x = nodeBits & 0x003FFFFF; // Bits [0, 21]
if (packed_x & (1 << 21)) // Is bit 21 (the most significant packed) set?
packed_x |= 0xFFC00000; // Set the rest of the bits, [22, 31], in the int.
local int packed_y = (nodeBits >> 22) & 0x000FFFFF; // Bits [22, 41]
if (packed_y & (1 << 19)) // Is bit 19 (the most significant packed) set?
packed_y |= 0xFFF00000; // Set the rest of the bits, [20, 31], in the int.
local int packed_z = (nodeBits >> 42) & 0x003FFFFF; // Bits [42, 63]
if (packed_z & (1 << 21)) // Is bit 21 (the most significant packed) set?
packed_z |= 0xFFC00000; // Set the rest of the bits, [22, 31], in the int.
local Vector3 unpackedPos;
unpackedPos.x = (float)packed_x/1024;
unpackedPos.y = (float)packed_y/1024;
unpackedPos.z = (float)packed_z/1024;
};
struct Header
{
char ROUT[4] <bgcolor=0xFCE7A3, hidden=true>;
ushort version; if (version == 512) {BigEndian();}
ushort routeCount;
FSkip(0x4 * 2); //Irrelevant memory leak bytes
Vector3 origin;
FSkip(0x4);
uint routeIdsOffset;
uint routeDefinitionsOffset;
uint routeNodesOffset;
uint routeEventTablesOffset;
uint routeEventsOffset;
uint fileSize; Assert(fileSize==FileSize());
FSkip(0x4 * 2); //Irrelevant memory leak bytes
} header <bgcolor=0x85C426>;
local int routeIndex = 0;
struct Route
{
//Get route id first for Jump to Template Variable
FSeek(header.routeIdsOffset + ( routeIndex * sizeof(uint) ) );
uint routeId <bgcolor=0x8F9032>;
//Offset to the start of current route definitions
local int routeDefinitionsPosition = header.routeDefinitionsOffset + ( routeIndex * sizeof(RouteDefinitions) );
FSeek(routeDefinitionsPosition);
RouteDefinitions routeDefinitions <hidden=true>;
local int nodeIndex = 0;
local int eventIndex = 0;
struct Node
{
// Maps nodes to events
FSeek(routeDefinitionsPosition + routeDefinitions.eventTableOffset + (nodeIndex * sizeof(EventTable)));
EventTable eventTable <hidden=true>;
FSeek(routeDefinitionsPosition + routeDefinitions.nodesOffset + (nodeIndex * sizeof(int64)));
NodeUnpacked nodeUnpacked <optimize=false, hidden=true>;
local Vector3 pos;
pos.x = header.origin.x+nodeUnpacked.unpackedPos.x;
pos.y = header.origin.y+nodeUnpacked.unpackedPos.y;
pos.z = header.origin.z+nodeUnpacked.unpackedPos.z;
if (legacyParam==1)
pos.x = -pos.x; // for unity
FSeek(routeDefinitionsPosition + routeDefinitions.eventsOffset + (eventIndex * 0x30)); //sizeof Event
Event edgeEvent <optimize=false>;
Event nodeEvent[eventTable.eventNodeCount-1] <optimize=false>;
eventIndex+=eventTable.eventNodeCount;
nodeIndex++;
FSeek(routeDefinitionsPosition + routeDefinitions.eventTableOffset + (nodeIndex * sizeof(EventTable))); //Reset to next start position
} node[routeDefinitions.nodeCount] <bgcolor=0x01062F, optimize=false>;
routeIndex++;
FSeek(header.routeIdsOffset + ( routeIndex * sizeof(uint) ) ); //Reset to next start position so Jump to Template Variable works on hashes
} route[header.routeCount] <bgcolor=0x413A55, fgcolor=0xFFFFFF, optimize=false>;