Subversion Repositories Games.Carmageddon

Rev

Rev 11 | Rev 20 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
#include "controls.h"
2
 
18 pmbaty 3
#include "brender.h"
1 pmbaty 4
#include "brucetrk.h"
5
#include "car.h"
6
#include "constants.h"
7
#include "crush.h"
8
#include "depth.h"
9
#include "displays.h"
10
#include "finteray.h"
11
#include "flicplay.h"
12
#include "globvars.h"
13
#include "globvrkm.h"
14
#include "globvrpb.h"
15
#include "grafdata.h"
16
#include "graphics.h"
17
#include "harness/trace.h"
18
#include "init.h"
19
#include "input.h"
20
#include "loadsave.h"
21
#include "mainloop.h"
22
#include "netgame.h"
23
#include "network.h"
24
#include "opponent.h"
25
#include "pd/sys.h"
26
#include "pedestrn.h"
27
#include "piping.h"
28
#include "powerup.h"
29
#include "pratcam.h"
30
#include "raycast.h"
31
#include "replay.h"
32
#include "s3/s3.h"
33
#include "sound.h"
34
#include "spark.h"
35
#include "structur.h"
36
#include "utility.h"
37
#include "world.h"
38
#include <stdlib.h>
39
 
40
tToggle_element gToggle_array[] = {
41
    { KEYMAP_MIRROR, -2, 1, 1, 0, ToggleMirror },
42
    { KEYMAP_MAP, -2, 1, 1, 0, ToggleMap },
43
    { KEYMAP_PRATCAM, -2, 1, 1, 0, TogglePratcam },
44
    { KEYMAP_RECOVERY, -2, 1, 1, 0, SetRecovery },
45
    { KEYMAP_CTRL_ABORT_RACE, 7, 1, 1, 0, AbortRace },
46
    { KEYMAP_COCKPIT, -2, 1, 1, 0, ToggleCockpit },
47
    { KEYMAP_LOOK_LEFT, -2, 1, 1, 0, LookLeft },
48
    { KEYMAP_LOOK_FORWARD, -2, 1, 1, 0, LookForward },
49
    { KEYMAP_LOOK_RIGHT, -2, 1, 1, 0, LookRight },
50
    { KEYMAP_SOUND, -2, 0, 1, 0, ToggleSoundEnable },
51
    { KEYMAP_SHIFT_DUMPSCREEN, KEYMAP_SHIFT_ANY, 0, 1, 0, PrintScreen },
52
    { KEYMAP_CTRL_DRAW_SOME_TEXT, KEYMAP_CONTROL_ANY, 1, 1, 0, DrawSomeText }, // commented out in original executable
53
    { KEYMAP_CTRL_FLY, KEYMAP_CONTROL_ANY, 1, 1, 0, ToggleFlying },
54
    { KEYMAP_PEDESTRIANS, -2, 1, 1, 0, TogglePedestrians },
55
    { KEYMAP_F4, -2, 0, 0, 0, F4Key },
56
    { KEYMAP_F5, -2, 1, 0, 0, F5Key },
57
    { KEYMAP_F6, -2, 1, 0, 0, F6Key },
58
    { KEYMAP_F7, -2, 1, 0, 0, F7Key },
59
    { KEYMAP_F8, -2, 1, 0, 0, F8Key },
60
    { KEYMAP_F10, -2, 1, 0, 0, F10Key },
61
    { KEYMAP_F11, -2, 1, 0, 0, F11Key },
62
    { KEYMAP_F12, -2, 1, 0, 0, F12Key },
63
    { KEYMAP_EDITMODE_0, -2, 1, 0, 0, NumberKey0 },
64
    { KEYMAP_EDITMODE_1, -2, 1, 0, 0, NumberKey1 },
65
    { KEYMAP_EDITMODE_2, -2, 1, 0, 0, NumberKey2 },
66
    { KEYMAP_EDITMODE_3, -2, 1, 0, 0, NumberKey3 },
67
    { KEYMAP_EDITMODE_4, -2, 1, 0, 0, NumberKey4 },
68
    { KEYMAP_EDITMODE_5, -2, 1, 0, 0, NumberKey5 },
69
    { KEYMAP_EDITMODE_6, -2, 1, 0, 0, NumberKey6 },
70
    { KEYMAP_EDITMODE_7, -2, 1, 0, 0, NumberKey7 },
71
    { KEYMAP_EDITMODE_8, -2, 1, 0, 0, NumberKey8 },
72
    { KEYMAP_EDITMODE_9, -2, 1, 0, 0, NumberKey9 },
73
    { KEYMAP_SCREEN_SMALLER, -2, 1, 0, 0, ScreenSmaller },
74
    { KEYMAP_SCREEN_LARGER, -2, 1, 0, 0, ScreenLarger },
75
    { KEYMAP_BUY_ARMOUR, -2, 1, 0, 0, BuyArmour },
76
    { KEYMAP_BUY_POWER, -2, 1, 0, 0, BuyPower },
77
    { KEYMAP_BUY_OFFENSE, -2, 1, 0, 0, BuyOffense },
78
    { KEYMAP_VIEW_NETPLAYER, -2, 1, 0, 0, ViewNetPlayer },
79
    { KEYMAP_SEND_MESSAGE, -2, 1, 0, 0, UserSendMessage },
80
    { KEYMAP_ARROW, -2, 1, 1, 0, ToggleArrow }, // commented out in original executable
81
    { KEYMAP_INFO, -2, 1, 1, 0, ToggleInfo },
82
    { KEYMAP_INFO, KEYMAP_SHIFT_ANY, 1, 1, 0, ToggleInfo },
83
    { KEYMAP_INFO, KEYMAP_CONTROL_ANY, 1, 1, 0, ToggleInfo }
84
};
85
int gRepair_last_time;
86
int gHad_auto_recover;
87
tU32 gLast_repair_time;
88
tEdit_mode gWhich_edit_mode = eEdit_mode_options;
89
char* gEdit_mode_names[10] = {
90
    "Cheat",
91
    "Accessories",
92
    "Special Volumes",
93
    "Pedestrians",
94
    "Opponents",
95
    "Prat-cam",
96
    "Depth effects",
97
    "Damage",
98
    "Bonnet",
99
    "Options",
100
};
101
 
102
// order is: { None, CTRL, ALT, CTRL+ALT, SHIFT, CTRL+SHIFT, ALT+SHIFT, CTRL+ALT+SHIFT }
103
tEdit_func* gEdit_funcs[10][18][8] = {
104
    { // CHEAT EDIT MODE
105
 
106
        // F5
107
        { TotalRepair, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
108
        // F6
109
        { ToggleInvulnerability, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
110
        // F7
111
        { MoreTime, NULL, NULL, NULL, MuchMoreTime, NULL, NULL, NULL },
112
        // F8
113
        { ToggleTimerFreeze, ShadowMode, NULL, NULL, ToggleShadow, NULL, NULL, NULL },
114
        // F10
115
        { IncrementLap, NULL, NULL, NULL, IncrementCheckpoint, NULL, NULL, NULL },
116
        // F11
117
        { EarnDosh, NULL, NULL, NULL, LoseDosh, NULL, NULL, NULL },
118
        // F12
119
        { ViewOpponent, ViewOpponent, ViewOpponent, ViewOpponent, ViewOpponent, ViewOpponent, ViewOpponent, ViewOpponent },
120
        // 0
121
        { GotPowerup0, GotPowerup0, GotPowerup0, GotPowerup0, GotPowerup0, GotPowerup0, GotPowerup0, GotPowerup0 },
122
        // 1
123
        { GotPowerup1, GotPowerup1, GotPowerup1, GotPowerup1, GotPowerup1, GotPowerup1, GotPowerup1, GotPowerup1 },
124
        // 2
125
        { GotPowerup2, GotPowerup2, GotPowerup2, GotPowerup2, GotPowerup2, GotPowerup2, GotPowerup2, GotPowerup2 },
126
        // 3
127
        { GotPowerup3, GotPowerup3, GotPowerup3, GotPowerup3, GotPowerup3, GotPowerup3, GotPowerup3, GotPowerup3 },
128
        // 4
129
        { GotPowerup4, GotPowerup4, GotPowerup4, GotPowerup4, GotPowerup4, GotPowerup4, GotPowerup4, GotPowerup4 },
130
        // 5
131
        { GotPowerup5, GotPowerup5, GotPowerup5, GotPowerup5, GotPowerup5, GotPowerup5, GotPowerup5, GotPowerup5 },
132
        // 6
133
        { GotPowerup6, GotPowerup6, GotPowerup6, GotPowerup6, GotPowerup6, GotPowerup6, GotPowerup6, GotPowerup6 },
134
        // 7
135
        { GotPowerup7, GotPowerup7, GotPowerup7, GotPowerup7, GotPowerup7, GotPowerup7, GotPowerup7, GotPowerup7 },
136
        // 8
137
        { GotPowerup8, GotPowerup8, GotPowerup8, GotPowerup8, GotPowerup8, GotPowerup8, GotPowerup8, GotPowerup8 },
138
        // 9
139
        { GotPowerup9, GotPowerup9, GotPowerup9, GotPowerup9, GotPowerup9, GotPowerup9, GotPowerup9, GotPowerup9 },
140
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } },
141
 
142
    { // ACCESSORIES EDIT MODE
143
 
144
        // F5
145
        { CycleAccRotate, NULL, NULL, NULL, CycleAccScale, NULL, NULL, NULL },
146
        // F6
147
        { IdentifyAcc, ScaleAccUp2, ScaleAccUp3, ScaleAccUp4, IdentifyAcc, ScaleAccDown2, ScaleAccDown3, ScaleAccDown4 },
148
        // F7
149
        { RotateAccL, RotateAccL2, RotateAccL3, RotateAccL4, RotateAccR, RotateAccR2, RotateAccR3, RotateAccR4 },
150
        // F8
151
        { DeleteAcc, NULL, NULL, NULL, SnapAccToVertical, NULL, NULL, NULL },
152
        // F10
153
        { MoveXAccL, MoveXAccL2, MoveXAccL3, MoveXAccL4, MoveXAccR, MoveXAccR2, MoveXAccR3, MoveXAccR4 },
154
        // F11
155
        { MoveYAccL, MoveYAccL2, MoveYAccL3, MoveYAccL4, MoveYAccR, MoveYAccR2, MoveYAccR3, MoveYAccR4 },
156
        // F12
157
        { MoveZAccL, MoveZAccL2, MoveZAccL3, MoveZAccL4, MoveZAccR, MoveZAccR2, MoveZAccR3, MoveZAccR4 },
158
        // 0
159
        { DropActor0, DropActor0, DropActor0, DropActor0, DropActor0, DropActor0, DropActor0, DropActor0 },
160
        // 1
161
        { DropActor1, DropActor1, DropActor1, DropActor1, DropActor1, DropActor1, DropActor1, DropActor1 },
162
        // 2
163
        { DropActor2, DropActor2, DropActor2, DropActor2, DropActor2, DropActor2, DropActor2, DropActor2 },
164
        // 3
165
        { DropActor3, DropActor3, DropActor3, DropActor3, DropActor3, DropActor3, DropActor3, DropActor3 },
166
        // 4
167
        { DropActor4, DropActor4, DropActor4, DropActor4, DropActor4, DropActor4, DropActor4, DropActor4 },
168
        // 5
169
        { DropActor5, DropActor5, DropActor5, DropActor5, DropActor5, DropActor5, DropActor5, DropActor5 },
170
        // 6
171
        { DropActor6, DropActor6, DropActor6, DropActor6, DropActor6, DropActor6, DropActor6, DropActor6 },
172
        // 7
173
        { DropActor7, DropActor7, DropActor7, DropActor7, DropActor7, DropActor7, DropActor7, DropActor7 },
174
        // 8
175
        { DropActor8, DropActor8, DropActor8, DropActor8, DropActor8, DropActor8, DropActor8, DropActor8 },
176
        // 9
177
        { DropActor9, DropActor9, DropActor9, DropActor9, DropActor9, DropActor9, DropActor9, DropActor9 },
178
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } },
179
 
180
    { // SPECVOL EDIT MODE
181
 
182
        // F5
183
        { CycleSpecVolRotate, NULL, NULL, NULL, CycleSpecVolScale, NULL, NULL, NULL },
184
        // F6
185
        { IdentifySpecVol, ScaleSpecVolUp2, ScaleSpecVolUp3, ScaleSpecVolUp4, IdentifySpecVol, ScaleSpecVolDown2, ScaleSpecVolDown3, ScaleSpecVolDown4 },
186
        // F7
187
        { RotateSpecVolL, RotateSpecVolL2, RotateSpecVolL3, RotateSpecVolL4, RotateSpecVolR, RotateSpecVolR2, RotateSpecVolR3, RotateSpecVolR4 },
188
        // F8
189
        { DeleteSpecVol, NULL, NULL, NULL, SnapSpecVolToVertical, NULL, NULL, NULL },
190
        // F10
191
        { MoveXSpecVolL, MoveXSpecVolL2, MoveXSpecVolL3, MoveXSpecVolL4, MoveXSpecVolR, MoveXSpecVolR2, MoveXSpecVolR3, MoveXSpecVolR4 },
192
        // F11
193
        { MoveYSpecVolL, MoveYSpecVolL2, MoveYSpecVolL3, MoveYSpecVolL4, MoveYSpecVolR, MoveYSpecVolR2, MoveYSpecVolR3, MoveYSpecVolR4 },
194
        // F12
195
        { MoveZSpecVolL, MoveZSpecVolL2, MoveZSpecVolL3, MoveZSpecVolL4, MoveZSpecVolR, MoveZSpecVolR2, MoveZSpecVolR3, MoveZSpecVolR4 },
196
        // 0
197
        { DropSpecVol0, DropSpecVol0, DropSpecVol0, DropSpecVol0, DropSpecVol0, DropSpecVol0, DropSpecVol0, DropSpecVol0 },
198
        // 1
199
        { DropSpecVol1, DropSpecVol1, DropSpecVol1, DropSpecVol1, DropSpecVol1, DropSpecVol1, DropSpecVol1, DropSpecVol1 },
200
        // 2
201
        { DropSpecVol2, DropSpecVol2, DropSpecVol2, DropSpecVol2, DropSpecVol2, DropSpecVol2, DropSpecVol2, DropSpecVol2 },
202
        // 3
203
        { DropSpecVol3, DropSpecVol3, DropSpecVol3, DropSpecVol3, DropSpecVol3, DropSpecVol3, DropSpecVol3, DropSpecVol3 },
204
        // 4
205
        { DropSpecVol4, DropSpecVol4, DropSpecVol4, DropSpecVol4, DropSpecVol4, DropSpecVol4, DropSpecVol4, DropSpecVol4 },
206
        // 5
207
        { DropSpecVol5, DropSpecVol5, DropSpecVol5, DropSpecVol5, DropSpecVol5, DropSpecVol5, DropSpecVol5, DropSpecVol5 },
208
        // 6
209
        { DropSpecVol6, DropSpecVol6, DropSpecVol6, DropSpecVol6, DropSpecVol6, DropSpecVol6, DropSpecVol6, DropSpecVol6 },
210
        // 7
211
        { DropSpecVol7, DropSpecVol7, DropSpecVol7, DropSpecVol7, DropSpecVol7, DropSpecVol7, DropSpecVol7, DropSpecVol7 },
212
        // 8
213
        { DropSpecVol8, DropSpecVol8, DropSpecVol8, DropSpecVol8, DropSpecVol8, DropSpecVol8, DropSpecVol8, DropSpecVol8 },
214
        // 09
215
        { DropSpecVol9, DropSpecVol9, DropSpecVol9, DropSpecVol9, DropSpecVol9, DropSpecVol9, DropSpecVol9, DropSpecVol9 },
216
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } },
217
 
218
    { // PEDESTRIAN EDIT MODE
219
 
220
        // F5
221
        { TogglePedDetect, NULL, NULL, NULL, DoPedReport, NULL, NULL, NULL },
222
        // F6
223
        { ShowPedPaths, NULL, NULL, NULL, ShowPedPos, NULL, NULL, NULL },
224
        // F7
225
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
226
        // F8
227
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
228
        // F10
229
        { DropPedPoint, DropPedPointAir, NULL, NULL, PullPedPoint, PullPedPointAir, NULL, NULL },
230
        // F11
231
        { DropInitPedPoint, DropInitPedPointAir, NULL, NULL, NULL, NULL, NULL, NULL },
232
        // F12
233
        { ScrubPedestrian, DeletePedPoint, NULL, NULL, DeletePedPath, NULL, NULL, NULL },
234
        // 0
235
        { NewPed0, NewPed0, NewPed0, NewPed0, NewPed0, NewPed0, NewPed0, NewPed0 },
236
        // 1
237
        { NewPed1, NewPed1, NewPed1, NewPed1, NewPed1, NewPed1, NewPed1, NewPed1 },
238
        // 2
239
        { NewPed2, NewPed2, NewPed2, NewPed2, NewPed2, NewPed2, NewPed2, NewPed2 },
240
        // 3
241
        { NewPed3, NewPed3, NewPed3, NewPed3, NewPed3, NewPed3, NewPed3, NewPed3 },
242
        // 4
243
        { NewPed4, NewPed4, NewPed4, NewPed4, NewPed4, NewPed4, NewPed4, NewPed4 },
244
        // 5
245
        { NewPed5, NewPed5, NewPed5, NewPed5, NewPed5, NewPed5, NewPed5, NewPed5 },
246
        // 6
247
        { NewPed6, NewPed6, NewPed6, NewPed6, NewPed6, NewPed6, NewPed6, NewPed6 },
248
        // 7
249
        { NewPed7, NewPed7, NewPed7, NewPed7, NewPed7, NewPed7, NewPed7, NewPed7 },
250
        // 8
251
        { NewPed8, NewPed8, NewPed8, NewPed8, NewPed8, NewPed8, NewPed8, NewPed8 },
252
        // 9
253
        { NewPed9, NewPed9, NewPed9, NewPed9, NewPed9, NewPed9, NewPed9, NewPed9 },
254
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } },
255
 
256
    { // OPPONENTS EDIT MODE
257
 
258
        // F5
259
        { ShowHideOppoPaths, ShowSectionInfo1, NULL, NULL, ShowNodeInfo, ShowSectionInfo2, NULL, NULL },
260
        // F6
261
        { ReverseSectionDirection, ToggleOneWayNess, NULL, NULL, CycleSectionType, NULL, NULL, NULL },
262
        // F7
263
        { DropElasticateyNode, NULL, PullOppoPoint, NULL, InsertAndElasticate, NULL, NULL, NULL },
264
        // F8
265
        { DropNodeOnNodeAndStopElasticating, DropDeadEndNode, NULL, NULL, InsertAndDontElasticate, NULL, NULL, NULL },
266
        // F10
267
        { WidenOppoPathSection, IncreaseSectionMinSpeed, IncreaseSectionMaxSpeed, NULL, NarrowOppoPathSection, DecreaseSectionMinSpeed, DecreaseSectionMaxSpeed, NULL },
268
        // F11
269
        { NULL, DeleteOppoPathNodeAndJoin, NULL, NULL, DeleteOppoPathSection, DeleteOppoPathNodeAndSections, NULL, NULL },
270
        // F12
271
        { ViewOpponent, ViewOpponent, ViewOpponent, ViewOpponent, ViewOpponent, ViewOpponent, ViewOpponent, ViewOpponent },
272
        // 0
273
        { ViewOpponent, ViewOpponent, ViewOpponent, ViewOpponent, ViewOpponent, ViewOpponent, ViewOpponent, ViewOpponent },
274
        // 1
275
        { ToggleOpponentProcessing, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
276
        // 2
277
        { CopStartPointInfo, DeleteCopStartPoint, DropCopStartPoint, NULL, CycleCopStartPointType, NULL, NULL, NULL },
278
        // 3
279
        { ToggleMellowOpponents, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
280
        // 4
281
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
282
        // 5
283
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
284
        // 6
285
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
286
        // 7
287
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
288
        // 8
289
        { AdjustDownForce, NULL, NULL, NULL, PutOpponentsInNeutral, NULL, NULL, NULL },
290
        // 9
291
        { SwapCar, FreezeMechanics, NULL, NULL, ToggleCarToCarCollisions, NULL, NULL, NULL },
292
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } },
293
 
294
    { // PRAT-CAM EDIT MODE
295
 
296
        // F5
297
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
298
        // F6
299
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
300
        // F7
301
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
302
        // F8
303
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
304
        // F10
305
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
306
        // F11
307
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
308
        // F12
309
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
310
        // 0
311
        { PratCam0, PratCam0, PratCam0, PratCam0, PratCam0, PratCam0, PratCam0, PratCam0 },
312
        // 1
313
        { PratCam1, PratCam1, PratCam1, PratCam1, PratCam1, PratCam1, PratCam1, PratCam1 },
314
        // 2
315
        { PratCam2, PratCam2, PratCam2, PratCam2, PratCam2, PratCam2, PratCam2, PratCam2 },
316
        // 3
317
        { PratCam3, PratCam3, PratCam3, PratCam3, PratCam3, PratCam3, PratCam3, PratCam3 },
318
        // 4
319
        { PratCam4, PratCam4, PratCam4, PratCam4, PratCam4, PratCam4, PratCam4, PratCam4 },
320
        // 5
321
        { PratCam5, PratCam5, PratCam5, PratCam5, PratCam5, PratCam5, PratCam5, PratCam5 },
322
        // 6
323
        { PratCam6, PratCam6, PratCam6, PratCam6, PratCam6, PratCam6, PratCam6, PratCam6 },
324
        // 7
325
        { PratCam7, PratCam7, PratCam7, PratCam7, PratCam7, PratCam7, PratCam7, PratCam7 },
326
        // 8
327
        { PratCam8, PratCam8, PratCam8, PratCam8, PratCam8, PratCam8, PratCam8, PratCam8 },
328
        // 9
329
        { PratCam9, PratCam9, PratCam9, PratCam9, PratCam9, PratCam9, PratCam9, PratCam9 },
330
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } },
331
 
332
    { // DEPTH EFFECTS EDIT MODE
333
 
334
        // F5
335
        { ToggleDepthMode, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
336
        // F6
337
        { ToggleSky, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
338
        // F7
339
        { LessDepthFactor, NULL, NULL, NULL, LessDepthFactor2, NULL, NULL, NULL },
340
        // F8
341
        { MoreDepthFactor, NULL, NULL, NULL, MoreDepthFactor2, NULL, NULL, NULL },
342
        // F10
343
        { IncreaseYon, NULL, NULL, NULL, DecreaseYon, NULL, NULL, NULL },
344
        // F11
345
        { IncreaseAngle, NULL, NULL, NULL, DecreaseAngle, NULL, NULL, NULL },
346
        // F12
347
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
348
        // 0
349
        { ToggleShadow, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
350
        // 1
351
        { ShadowMode, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
352
        // 2
353
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
354
        // 3
355
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
356
        // 4
357
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
358
        // 5
359
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
360
        // 6
361
        { SelectFaceDown, NULL, NULL, NULL, SelectFaceForward, NULL, NULL, NULL },
362
        // 7
363
        { ScaleUpX, NULL, NULL, NULL, ScaleDnX, NULL, NULL, NULL },
364
        // 8
365
        { ScaleUpY, NULL, NULL, NULL, ScaleDnY, NULL, NULL, NULL },
366
        // 9
367
        { DustRotate, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
368
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } },
369
 
370
    { // DAMAGE EDIT MODE
371
 
372
        // F5
373
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
374
        // F6
375
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
376
        // F7
377
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
378
        // F8
379
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
380
        // F10
381
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
382
        // F11
383
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
384
        // F12
385
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
386
        // 0
387
        { TDamageEngine, NULL, NULL, NULL, TDamageEngine, NULL, NULL, NULL },
388
        // 1
389
        { TDamageTrans, NULL, NULL, NULL, TDamageTrans, NULL, NULL, NULL },
390
        // 2
391
        { TDamageSteering, NULL, NULL, NULL, TDamageSteering, NULL, NULL, NULL },
392
        // 3
393
        { TDamageLFWheel, NULL, NULL, NULL, TDamageLFBrake, NULL, NULL, NULL },
394
        // 4
395
        { TDamageLRWheel, NULL, NULL, NULL, TDamageLRBrake, NULL, NULL, NULL },
396
        // 5
397
        { TDamageRFWheel, NULL, NULL, NULL, TDamageRFBrake, NULL, NULL, NULL },
398
        // 6
399
        { TDamageRRWheel, NULL, NULL, NULL, TDamageRRBrake, NULL, NULL, NULL },
400
        // 7
401
        { TDamageDriver, NULL, NULL, NULL, TDamageDriver, NULL, NULL, NULL },
402
        // 8
403
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
404
        // 9
405
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
406
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } },
407
 
408
    { // BONNET EDIT MODE
409
 
410
        // F5
411
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
412
        // F6
413
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
414
        // F7
415
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
416
        // F8
417
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
418
        // F10
419
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
420
        // F11
421
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
422
        // F12
423
        { SaveBonnet, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
424
        // 0
425
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
426
        // 1
427
        { MoveBonnetForward, NULL, NULL, NULL, MoveBonnetBackward, NULL, NULL, NULL },
428
        // 2
429
        { MoveBonnetLeft, NULL, NULL, NULL, MoveBonnetRight, NULL, NULL, NULL },
430
        // 3
431
        { MoveBonnetUp, NULL, NULL, NULL, MoveBonnetDown, NULL, NULL, NULL },
432
        // 4
433
        { TiltBonnetUpX, NULL, NULL, NULL, TiltBonnetDownX, NULL, NULL, NULL },
434
        // 5
435
        { TiltBonnetUpY, NULL, NULL, NULL, TiltBonnetDownY, NULL, NULL, NULL },
436
        // 6
437
        { TiltBonnetUpZ, NULL, NULL, NULL, TiltBonnetDownZ, NULL, NULL, NULL },
438
        // 7
439
        { ShrinkBonnetX, NULL, NULL, NULL, SwellBonnetX, NULL, NULL, NULL },
440
        // 8
441
        { ShrinkBonnetY, NULL, NULL, NULL, SwellBonnetY, NULL, NULL, NULL },
442
        // 9
443
        { ShrinkBonnetZ, NULL, NULL, NULL, SwellBonnetZ, NULL, NULL, NULL },
444
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } },
445
 
446
    { // OPTIONS EDIT MODE
447
 
448
        // F5
449
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
450
        // F6
451
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
452
        // F7
453
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
454
        // F8
455
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
456
        // F10
457
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
458
        // F11
459
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
460
        // F12
461
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
462
        // 0
463
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
464
        // 1
465
        { CycleCarSimplificationLevel, NULL, NULL, NULL, CycleCarTexturingLevel, NULL, NULL, NULL },
466
        // 2
467
        { ToggleShadow, NULL, NULL, NULL, ToggleSmoke, NULL, NULL, NULL },
468
        // 3
469
        { CycleWallTexturingLevel, NULL, NULL, NULL, CycleRoadTexturingLevel, NULL, NULL, NULL },
470
        // 4
471
        { ToggleSky, NULL, NULL, NULL, ToggleDepthCueing, NULL, NULL, NULL },
472
        // 5
473
        { CycleYonFactor, NULL, NULL, NULL, ToggleAccessoryRendering, NULL, NULL, NULL },
474
        // 6
475
        { DecreaseYon, NULL, NULL, NULL, IncreaseYon, NULL, NULL, NULL },
476
        // 7
477
        { CycleSoundDetailLevel, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
478
        // 8
479
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
480
        // 9
481
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
482
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
483
 
484
    }
485
};
486
 
487
tCheat gKev_keys[44] = {
488
    { .code = 0xa11ee75d, .code2 = 0xf805eddd, .action_proc = SetFlag, .num = 0x0a11ee75d },
489
    { .code = 0x564e78b9, .code2 = 0x99155115, .action_proc = SetFlag, .num = 0x0564e78b9 },
490
    { .code = 0x1f47e5e8, .code2 = 0xa715222c, .action_proc = SetFlag2, .num = 1 },
491
    { .code = 0x39d4c4c4, .code2 = 0xf0a2c5b0, .action_proc = FinishLap, .num = 0 },
492
    { .code = 0x2654216c, .code2 = 0xf8256d15, .action_proc = GetPowerup, .num = 1 },
493
    { .code = 0x4294ec89, .code2 = 0xc38ad60e, .action_proc = GetPowerup, .num = 2 },
494
    { .code = 0x2ceb2850, .code2 = 0xa0c2d27e, .action_proc = GetPowerup, .num = 3 },
495
    { .code = 0x2d5f3125, .code2 = 0x9ce8a541, .action_proc = GetPowerup, .num = 4 },
496
    { .code = 0x2169c78b, .code2 = 0x7f3c9229, .action_proc = GetPowerup, .num = 5 },
497
    { .code = 0x2203c0cb, .code2 = 0x79729be4, .action_proc = GetPowerup, .num = 6 },
498
    { .code = 0x34f4e3ec, .code2 = 0x868c534d, .action_proc = GetPowerup, .num = 7 },
499
    { .code = 0x34010316, .code2 = 0x591d1eb2, .action_proc = GetPowerup, .num = 8 },
500
    { .code = 0x214fe3bc, .code2 = 0x87285111, .action_proc = GetPowerup, .num = 9 },
501
    { .code = 0x2fabc390, .code2 = 0x0c93d9f7, .action_proc = GetPowerup, .num = 10 },
502
    { .code = 0x2902e890, .code2 = 0x40969f67, .action_proc = GetPowerup, .num = 11 },
503
    { .code = 0x2f458288, .code2 = 0x058074e2, .action_proc = GetPowerup, .num = 12 },
504
    { .code = 0x249da152, .code2 = 0x8f287346, .action_proc = GetPowerup, .num = 13 },
505
    { .code = 0x23aae08b, .code2 = 0xa668103d, .action_proc = GetPowerup, .num = 14 },
506
    { .code = 0x32130661, .code2 = 0x56f03459, .action_proc = GetPowerup, .num = 15 },
507
    { .code = 0x2734e944, .code2 = 0xfe1e4639, .action_proc = GetPowerup, .num = 16 },
508
    { .code = 0x28341139, .code2 = 0x355f6d02, .action_proc = GetPowerup, .num = 17 },
509
    { .code = 0x20508831, .code2 = 0x123d1961, .action_proc = GetPowerup, .num = 18 },
510
    { .code = 0x346b8bcb, .code2 = 0x4aba696c, .action_proc = GetPowerup, .num = 19 },
511
    { .code = 0x3fc93df0, .code2 = 0x29fa9efb, .action_proc = GetPowerup, .num = 20 },
512
    { .code = 0x2a80b09b, .code2 = 0x058516f5, .action_proc = GetPowerup, .num = 21 },
513
    { .code = 0x2f548fd1, .code2 = 0x696744da, .action_proc = GetPowerup, .num = 22 },
514
    { .code = 0x3cb74f32, .code2 = 0xb915d88d, .action_proc = GetPowerup, .num = 23 },
515
    { .code = 0x297b53ba, .code2 = 0x218d4d2d, .action_proc = GetPowerup, .num = 24 },
516
    { .code = 0x351bc37d, .code2 = 0xb2a63343, .action_proc = GetPowerup, .num = 25 },
517
    { .code = 0x2b624386, .code2 = 0x9ba6260e, .action_proc = GetPowerup, .num = 26 },
518
    { .code = 0x2ba4ae23, .code2 = 0xc163a76c, .action_proc = GetPowerup, .num = 27 },
519
    { .code = 0x2fb92dca, .code2 = 0x4ad7d54e, .action_proc = GetPowerup, .num = 32 },
520
    { .code = 0x3a42191b, .code2 = 0xeff70f4c, .action_proc = GetPowerup, .num = 35 },
521
    { .code = 0x2aca3190, .code2 = 0xd9004f25, .action_proc = GetPowerup, .num = 36 },
522
    { .code = 0x37c1f613, .code2 = 0xb7faf351, .action_proc = GetPowerup, .num = 37 },
523
    { .code = 0x2ba3f603, .code2 = 0x29f2425c, .action_proc = GetPowerup, .num = 38 },
524
    { .code = 0x416eff61, .code2 = 0x2667df4b, .action_proc = GetPowerup, .num = 39 },
525
    { .code = 0x2554125c, .code2 = 0x393ca35d, .action_proc = GetPowerup, .num = 41 },
526
    { .code = 0x3fff84d5, .code2 = 0x84a42df4, .action_proc = GetPowerup, .num = 42 },
527
    { .code = 0x37e83018, .code2 = 0xb609aee6, .action_proc = GetPowerup, .num = 43 },
528
    { .code = 0x2db03b19, .code2 = 0x924a84b7, .action_proc = GetPowerup, .num = 44 },
529
    { .code = 0x30a19fab, .code2 = 0x2b0c2782, .action_proc = GetPowerup, .num = 45 },
530
    { .code = 0x0, .code2 = 0x0, .action_proc = 0x0, .num = 0x0 }
531
};
532
int gAllow_car_flying;
533
int gEntering_message;
534
tU32 gPalette_fade_time; // was gRecover_timer
535
char* gAbuse_text[10];
536
char gString[84];
537
int gToo_late;
538
int gRecover_timer;
539
int gRecovery_voucher_count;
540
int gInstant_handbrake;
541
int gAuto_repair;
542
 
543
int _unittest_controls_lastGetPowerup = 0;
544
 
545
// IDA: void __cdecl AbortRace()
546
void AbortRace(void) {
547
    LOG_TRACE("()");
548
 
549
    if (!gRace_finished) {
550
        gAbandon_game = 1;
551
    }
552
}
553
 
554
// IDA: void __cdecl F4Key()
555
void F4Key(void) {
556
    char s[256];
557
    tEdit_mode old_edit_mode;
558
    LOG_TRACE("()");
559
 
560
    old_edit_mode = gWhich_edit_mode;
561
    if (gI_am_cheating == 0xa11ee75d || (gI_am_cheating == 0x564e78b9 && gNet_mode == eNet_mode_none)) {
562
        if (PDKeyDown(KEY_SHIFT_ANY)) {
563
            gWhich_edit_mode--;
564
            if ((int)gWhich_edit_mode < 0) {
565
                gWhich_edit_mode = COUNT_OF(gEdit_funcs) - 1;
566
            }
567
        } else {
568
            gWhich_edit_mode++;
569
            if (gWhich_edit_mode >= COUNT_OF(gEdit_funcs)) {
570
                gWhich_edit_mode = 0;
571
            }
572
        }
573
        sprintf(s, "Edit mode: %s", gEdit_mode_names[gWhich_edit_mode]);
574
        NewTextHeadupSlot2(4, 0, 2000, -4, s, 0);
575
        if (gWhich_edit_mode == eEdit_mode_spec_vol && old_edit_mode != eEdit_mode_spec_vol) {
576
            ShowSpecialVolumes();
577
        } else if (gWhich_edit_mode != eEdit_mode_spec_vol && old_edit_mode == eEdit_mode_spec_vol) {
578
            HideSpecialVolumes();
579
        }
580
    } else {
581
        gWhich_edit_mode = eEdit_mode_options;
582
    }
583
}
584
 
585
// IDA: void __usercall SetFlag(int i@<EAX>)
586
void SetFlag(int i) {
587
    LOG_TRACE("(%d)", i);
588
 
589
    if (gNet_mode == eNet_mode_none) {
590
        NewTextHeadupSlot(4, 0, 3000, -4, "You Cheat!");
591
    }
592
    gI_am_cheating = i;
593
    F4Key();
594
}
595
 
596
// IDA: void __usercall FinishLap(int i@<EAX>)
597
void FinishLap(int i) {
598
    LOG_TRACE("(%d)", i);
599
 
600
    IncrementLap();
601
}
602
 
603
// IDA: void __cdecl EnsureSpecialVolumesHidden()
604
void EnsureSpecialVolumesHidden(void) {
605
    LOG_TRACE("()");
606
 
607
    if (gWhich_edit_mode == eEdit_mode_spec_vol) {
608
        HideSpecialVolumes();
609
    }
610
}
611
 
612
// IDA: void __cdecl ShowSpecialVolumesIfRequ()
613
void ShowSpecialVolumesIfRequ(void) {
614
    LOG_TRACE("()");
615
 
616
    if (gWhich_edit_mode == eEdit_mode_spec_vol) {
617
        ShowSpecialVolumes();
618
    }
619
}
620
 
621
// IDA: void __usercall DoEditModeKey(int pIndex@<EAX>)
622
void DoEditModeKey(int pIndex) {
623
    int modifiers;
624
    LOG_TRACE("(%d)", pIndex);
625
 
626
    if (gI_am_cheating == 0xa11ee75d || (gI_am_cheating == 0x564e78b9 && gNet_mode == eNet_mode_none)) {
627
        modifiers = 0;
628
        if (PDKeyDown(KEY_SHIFT_ANY)) {
629
            modifiers |= 4;
630
        }
631
        if (PDKeyDown(KEY_ALT_ANY)) {
632
            modifiers |= 2;
633
        }
634
        if (PDKeyDown(KEY_CTRL_ANY)) {
635
            modifiers |= 1;
636
        }
637
        if (gEdit_funcs[gWhich_edit_mode][pIndex][modifiers] != NULL) {
638
            gEdit_funcs[gWhich_edit_mode][pIndex][modifiers]();
639
        }
640
    } else {
641
        gWhich_edit_mode = eEdit_mode_options;
642
    }
643
}
644
 
645
// IDA: void __cdecl F5Key()
646
void F5Key(void) {
647
    LOG_TRACE("()");
648
 
649
    DoEditModeKey(0);
650
}
651
 
652
// IDA: void __cdecl F6Key()
653
void F6Key(void) {
654
    LOG_TRACE("()");
655
 
656
    DoEditModeKey(1);
657
}
658
 
659
// IDA: void __cdecl F7Key()
660
void F7Key(void) {
661
    LOG_TRACE("()");
662
 
663
    DoEditModeKey(2);
664
}
665
 
666
// IDA: void __cdecl F8Key()
667
void F8Key(void) {
668
    LOG_TRACE("()");
669
 
670
    DoEditModeKey(3);
671
}
672
 
673
// IDA: void __cdecl F10Key()
674
void F10Key(void) {
675
    LOG_TRACE("()");
676
 
677
    DoEditModeKey(4);
678
}
679
 
680
// IDA: void __cdecl F11Key()
681
void F11Key(void) {
682
    LOG_TRACE("()");
683
 
684
    DoEditModeKey(5);
685
}
686
 
687
// IDA: void __cdecl F12Key()
688
void F12Key(void) {
689
    LOG_TRACE("()");
690
 
691
    DoEditModeKey(6);
692
}
693
 
694
// IDA: void __cdecl NumberKey0()
695
void NumberKey0(void) {
696
    LOG_TRACE("()");
697
 
698
    DoEditModeKey(7);
699
}
700
 
701
// IDA: void __cdecl NumberKey1()
702
void NumberKey1(void) {
703
    LOG_TRACE("()");
704
 
705
    DoEditModeKey(8);
706
}
707
 
708
// IDA: void __cdecl NumberKey2()
709
void NumberKey2(void) {
710
    LOG_TRACE("()");
711
 
712
    DoEditModeKey(9);
713
}
714
 
715
// IDA: void __cdecl NumberKey3()
716
void NumberKey3(void) {
717
    LOG_TRACE("()");
718
 
719
    DoEditModeKey(10);
720
}
721
 
722
// IDA: void __cdecl NumberKey4()
723
void NumberKey4(void) {
724
    LOG_TRACE("()");
725
 
726
    DoEditModeKey(11);
727
}
728
 
729
// IDA: void __cdecl NumberKey5()
730
void NumberKey5(void) {
731
    LOG_TRACE("()");
732
 
733
    DoEditModeKey(12);
734
}
735
 
736
// IDA: void __cdecl NumberKey6()
737
void NumberKey6(void) {
738
    LOG_TRACE("()");
739
 
740
    DoEditModeKey(13);
741
}
742
 
743
// IDA: void __cdecl NumberKey7()
744
void NumberKey7(void) {
745
    LOG_TRACE("()");
746
 
747
    DoEditModeKey(14);
748
}
749
 
750
// IDA: void __cdecl NumberKey8()
751
void NumberKey8(void) {
752
    LOG_TRACE("()");
753
 
754
    DoEditModeKey(15);
755
}
756
 
757
// IDA: void __cdecl NumberKey9()
758
void NumberKey9(void) {
759
    LOG_TRACE("()");
760
 
761
    DoEditModeKey(16);
762
}
763
 
764
// IDA: void __cdecl LookLeft()
765
void LookLeft(void) {
766
    LOG_TRACE("()");
767
 
768
    if (gAusterity_mode) {
769
        NewTextHeadupSlot(4, 0, 1000, -4, GetMiscString(kMiscString_NOT_ENOUGH_MEMORY));
770
    } else {
771
        PratcamEvent(27);
772
        gProgram_state.old_view = gProgram_state.which_view;
773
        if (gProgram_state.which_view == eView_left) {
774
            LookForward();
775
        } else if (gProgram_state.which_view == eView_right) {
776
            LookForward();
777
            gProgram_state.pending_view = eView_left;
778
        } else {
779
            ClearWobbles();
780
            gProgram_state.new_view = eView_left;
781
            gProgram_state.view_change_start = PDGetTotalTime();
782
            gProgram_state.pending_view = eView_undefined;
783
        }
784
    }
785
}
786
 
787
// IDA: void __cdecl LookForward()
788
void LookForward(void) {
789
    LOG_TRACE("()");
790
 
791
    if (gProgram_state.which_view == eView_right) {
792
        PratcamEvent(27);
793
    } else if (gProgram_state.which_view == eView_left) {
794
        PratcamEvent(28);
795
    }
796
    if (gProgram_state.which_view != eView_forward) {
797
        gProgram_state.old_view = gProgram_state.which_view;
798
        ClearWobbles();
799
        gProgram_state.new_view = eView_forward;
800
        gProgram_state.view_change_start = PDGetTotalTime();
801
        gProgram_state.pending_view = eView_undefined;
802
    }
803
}
804
 
805
// IDA: void __cdecl LookRight()
806
void LookRight(void) {
807
    LOG_TRACE("()");
808
 
809
    if (gAusterity_mode) {
810
        NewTextHeadupSlot(4, 0, 1000, -4, GetMiscString(kMiscString_NOT_ENOUGH_MEMORY));
811
    } else {
812
        PratcamEvent(28);
813
        gProgram_state.old_view = gProgram_state.which_view;
814
        if (gProgram_state.which_view == eView_right) {
815
            LookForward();
816
        } else if (gProgram_state.which_view == eView_left) {
817
            LookForward();
818
            gProgram_state.pending_view = eView_right;
819
        } else {
820
            ClearWobbles();
821
            gProgram_state.new_view = eView_right;
822
            gProgram_state.view_change_start = PDGetTotalTime();
823
            gProgram_state.pending_view = eView_undefined;
824
        }
825
    }
826
}
827
 
828
// IDA: void __cdecl DamageTest()
829
void DamageTest(void) {
830
    LOG_TRACE("()");
831
}
832
 
833
// IDA: void __cdecl TDamageEngine()
834
void TDamageEngine(void) {
835
    LOG_TRACE("()");
836
 
837
    DamageEngine(21);
838
}
839
 
840
// IDA: void __cdecl TDamageDriver()
841
void TDamageDriver(void) {
842
    LOG_TRACE("()");
843
 
844
    if (gProgram_state.current_car.damage_units[eDamage_driver].damage_level >= 80) {
845
        DamageUnit(&gProgram_state.current_car, eDamage_driver, 2);
846
    } else {
847
        DamageUnit(&gProgram_state.current_car, eDamage_driver, 80 - gProgram_state.current_car.damage_units[2].damage_level);
848
    }
849
}
850
 
851
// IDA: void __cdecl TDamageTrans()
852
void TDamageTrans(void) {
853
    LOG_TRACE("()");
854
 
855
    DamageTrans(21);
856
}
857
 
858
// IDA: void __cdecl TDamageSteering()
859
void TDamageSteering(void) {
860
    LOG_TRACE("()");
861
 
862
    DamageSteering(21);
863
}
864
 
865
// IDA: void __cdecl TDamageLFWheel()
866
void TDamageLFWheel(void) {
867
    LOG_TRACE("()");
868
 
869
    DamageLFWheel(21);
870
}
871
 
872
// IDA: void __cdecl TDamageLFBrake()
873
void TDamageLFBrake(void) {
874
    LOG_TRACE("()");
875
 
876
    DamageLFBrake(21);
877
}
878
 
879
// IDA: void __cdecl TDamageLRBrake()
880
void TDamageLRBrake(void) {
881
    LOG_TRACE("()");
882
 
883
    DamageLRBrake(21);
884
}
885
 
886
// IDA: void __cdecl TDamageLRWheel()
887
void TDamageLRWheel(void) {
888
    LOG_TRACE("()");
889
 
890
    DamageLRWheel(21);
891
}
892
 
893
// IDA: void __cdecl TDamageRFWheel()
894
void TDamageRFWheel(void) {
895
    LOG_TRACE("()");
896
 
897
    DamageRFWheel(21);
898
}
899
 
900
// IDA: void __cdecl TDamageRFBrake()
901
void TDamageRFBrake(void) {
902
    LOG_TRACE("()");
903
 
904
    DamageRFBrake(21);
905
}
906
 
907
// IDA: void __cdecl TDamageRRBrake()
908
void TDamageRRBrake(void) {
909
    LOG_TRACE("()");
910
 
911
    DamageRRBrake(21);
912
}
913
 
914
// IDA: void __cdecl TDamageRRWheel()
915
void TDamageRRWheel(void) {
916
    LOG_TRACE("()");
917
 
918
    DamageRRWheel(21);
919
}
920
 
921
// IDA: void __cdecl MoveBonnetForward()
922
void MoveBonnetForward(void) {
923
    LOG_TRACE("()");
924
 
925
    gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.translate.t.v[2] -= .005f;
926
}
927
 
928
// IDA: void __cdecl SaveBonnet()
929
void SaveBonnet(void) {
930
    br_actor* bonny;
931
    tPath_name the_path;
932
    LOG_TRACE("()");
933
 
934
    bonny = gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor;
935
    PathCat(the_path, gApplication_path, bonny->identifier);
936
    BrActorSave(the_path, bonny);
937
}
938
 
939
// IDA: void __cdecl MoveBonnetBackward()
940
void MoveBonnetBackward(void) {
941
    LOG_TRACE("()");
942
 
943
    gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.translate.t.v[2] += .005f;
944
}
945
 
946
// IDA: void __cdecl MoveBonnetLeft()
947
void MoveBonnetLeft(void) {
948
    LOG_TRACE("()");
949
 
950
    gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.translate.t.v[0] -= .005f;
951
}
952
 
953
// IDA: void __cdecl ShrinkBonnetX()
954
void ShrinkBonnetX(void) {
955
    LOG_TRACE("()");
956
 
957
    gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.mat.m[0][0] *= .98f;
958
}
959
 
960
// IDA: void __cdecl SwellBonnetX()
961
void SwellBonnetX(void) {
962
    LOG_TRACE("()");
963
 
964
    gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.mat.m[0][0] *= 1.02f;
965
}
966
 
967
// IDA: void __cdecl ShrinkBonnetY()
968
void ShrinkBonnetY(void) {
969
    LOG_TRACE("()");
970
 
971
    gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.mat.m[1][1] *= .98f;
972
}
973
 
974
// IDA: void __cdecl SwellBonnetY()
975
void SwellBonnetY(void) {
976
    LOG_TRACE("()");
977
 
978
    gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.mat.m[1][1] *= 1.02f;
979
}
980
 
981
// IDA: void __cdecl ShrinkBonnetZ()
982
void ShrinkBonnetZ(void) {
983
    LOG_TRACE("()");
984
 
985
    gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.mat.m[2][2] *= .98f;
986
}
987
 
988
// IDA: void __cdecl SwellBonnetZ()
989
void SwellBonnetZ(void) {
990
    LOG_TRACE("()");
991
 
992
    gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.mat.m[2][2] *= 1.02f;
993
}
994
 
995
// IDA: void __cdecl MoveBonnetDown()
996
void MoveBonnetDown(void) {
997
    LOG_TRACE("()");
998
 
999
    gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.translate.t.v[1] += .005f;
1000
}
1001
 
1002
// IDA: void __cdecl MoveBonnetRight()
1003
void MoveBonnetRight(void) {
1004
    LOG_TRACE("()");
1005
 
1006
    gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.translate.t.v[0] += .005f;
1007
}
1008
 
1009
// IDA: void __cdecl MoveBonnetUp()
1010
void MoveBonnetUp(void) {
1011
    LOG_TRACE("()");
1012
 
1013
    gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.translate.t.v[1] -= .005f;
1014
}
1015
 
1016
// IDA: void __cdecl TiltBonnetDownX()
1017
void TiltBonnetDownX(void) {
1018
    LOG_TRACE("()");
1019
 
1020
    BrMatrix34PreRotateX(&gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.mat, BR_ANGLE_DEG(.5f));
1021
}
1022
 
1023
// IDA: void __cdecl TiltBonnetUpX()
1024
void TiltBonnetUpX(void) {
1025
    LOG_TRACE("()");
1026
 
1027
    BrMatrix34PreRotateX(&gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.mat, -BR_ANGLE_DEG(.5f));
1028
}
1029
 
1030
// IDA: void __cdecl TiltBonnetDownY()
1031
void TiltBonnetDownY(void) {
1032
    LOG_TRACE("()");
1033
 
1034
    BrMatrix34PreRotateY(&gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.mat, BR_ANGLE_DEG(.5f));
1035
}
1036
 
1037
// IDA: void __cdecl TiltBonnetUpY()
1038
void TiltBonnetUpY(void) {
1039
    LOG_TRACE("()");
1040
 
1041
    BrMatrix34PreRotateY(&gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.mat, -BR_ANGLE_DEG(.5f));
1042
}
1043
 
1044
// IDA: void __cdecl TiltBonnetDownZ()
1045
void TiltBonnetDownZ(void) {
1046
    LOG_TRACE("()");
1047
 
1048
    BrMatrix34PreRotateZ(&gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.mat, BR_ANGLE_DEG(.5f));
1049
}
1050
 
1051
// IDA: void __cdecl TiltBonnetUpZ()
1052
void TiltBonnetUpZ(void) {
1053
    LOG_TRACE("()");
1054
 
1055
    BrMatrix34PreRotateZ(&gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.mat, -BR_ANGLE_DEG(.5f));
1056
}
1057
 
1058
// IDA: void __cdecl ToggleCockpit()
1059
void ToggleCockpit(void) {
1060
    //br_scalar ts; // Pierre-Marie Baty -- unused variable
1061
    LOG_TRACE("()");
1062
 
1063
    if ((&gProgram_state.current_car == gCar_to_view || gProgram_state.cockpit_on) && !gMap_mode) {
1064
        if (!gAusterity_mode || gProgram_state.cockpit_on) {
1065
            gProgram_state.cockpit_on = !gProgram_state.cockpit_on;
1066
            if (gProgram_state.cockpit_on) {
1067
                gCamera = gCamera_list[0];
1068
            } else {
1069
                gCamera = gCamera_list[1];
1070
                InitialiseExternalCamera();
1071
                PositionExternalCamera(&gProgram_state.current_car, 1);
1072
            }
1073
            AdjustRenderScreenSize();
1074
            AdjustHeadups();
1075
            MungeForwardSky();
1076
        } else {
1077
            NewTextHeadupSlot(4, 0, 1000, -4, GetMiscString(kMiscString_NOT_ENOUGH_MEMORY));
1078
        }
1079
    }
1080
}
1081
 
1082
// IDA: void __cdecl ToggleMirror()
1083
void ToggleMirror(void) {
1084
    LOG_TRACE("()");
1085
 
1086
    gProgram_state.mirror_on = !gProgram_state.mirror_on;
1087
    ReinitialiseRearviewCamera();
1088
    if (gProgram_state.mirror_on) {
1089
        NewTextHeadupSlot(4, 0, 500, -4, GetMiscString(kMiscString_MirrorOn));
1090
    } else {
1091
        NewTextHeadupSlot(4, 0, 500, -4, GetMiscString(kMiscString_MirrorOff));
1092
    }
1093
}
1094
 
1095
// IDA: void __cdecl ConcussMe()
1096
// dethrace: this is not referenced in the retail executables. Left over debug code.
1097
void ConcussMe(void) {
1098
    LOG_TRACE("()");
1099
 
1100
    SufferFromConcussion(1.f);
1101
    NewScreenWobble(IRandomPosNeg(15), IRandomPosNeg(10), IRandomBetween(10, 60));
1102
    PratcamEvent(3);
1103
}
1104
 
1105
// IDA: void __cdecl CheckHelp()
1106
void CheckHelp(void) {
1107
    LOG_TRACE("()");
1108
}
1109
 
1110
// IDA: void __cdecl CheckLoadSave()
1111
void CheckLoadSave(void) {
1112
    int save_load_allowed;
1113
    //int switched_res; // Pierre-Marie Baty -- unused variable
1114
    LOG_TRACE8("()");
1115
 
1116
    save_load_allowed = !gProgram_state.saving && !gProgram_state.loading && gProgram_state.prog_status == eProg_game_ongoing && !gProgram_state.dont_save_or_load;
1117
 
1118
    if (CmdKeyDown(KEYMAP_SAVE, KEYMAP_CTRL_SAVE)) {
1119
        if (save_load_allowed) {
1120
            FadePaletteDown();
1121
            ClearEntireScreen();
1122
            if (gProgram_state.racing) {
1123
                GoingToInterfaceFromRace();
1124
            }
1125
            DoSaveGame(gProgram_state.racing == 0);
1126
            if (gProgram_state.racing) {
1127
                GoingBackToRaceFromInterface();
1128
            }
1129
        }
1130
        WaitForNoKeys();
1131
    }
1132
    if (CmdKeyDown(KEYMAP_LOAD, KEYMAP_CTRL_LOAD)) {
1133
        if (save_load_allowed && !gProgram_state.dont_load) {
1134
            FadePaletteDown();
1135
            ClearEntireScreen();
1136
            if (gProgram_state.racing) {
1137
                GoingToInterfaceFromRace();
1138
            }
1139
            if (DoLoadGame() && !gProgram_state.racing) {
1140
                gProgram_state.prog_status = eProg_game_starting;
1141
            }
1142
            if (gProgram_state.racing) {
1143
                GoingBackToRaceFromInterface();
1144
            }
1145
            PlayFlicsFromMemory();
1146
        }
1147
        WaitForNoKeys();
1148
    }
1149
}
1150
 
1151
// IDA: void __usercall CheckToggles(int pRacing@<EAX>)
1152
void CheckToggles(int pRacing) {
1153
    int i;
1154
    int new_state;
1155
 
1156
    for (i = 0; i < COUNT_OF(gToggle_array); i++) {
1157
        if ((!gToggle_array[i].in_game_only || pRacing)
1158
            && ((!gTyping && !gEntering_message) || gToggle_array[i].key2 != -2)) {
1159
            new_state = 0;
1160
            if (gToggle_array[i].key1 == -2 || KeyIsDown(gToggle_array[i].key1)) {
1161
                if (gToggle_array[i].key2 == -2 && gToggle_array[i].exact_modifiers) {
1162
                    if (!PDKeyDown(KEY_SHIFT_ANY) && !PDKeyDown(KEY_ALT_ANY) && !PDKeyDown(KEY_CTRL_ANY) && !PDKeyDown(KEY_CTRL_ANY_2)) {
1163
                        new_state = 1;
1164
                    }
1165
                } else {
1166
                    if (KeyIsDown(gToggle_array[i].key2)) {
1167
                        new_state = 1;
1168
                    }
1169
                }
1170
            }
1171
            if (gToggle_array[i].on_last_time != new_state) {
1172
                gToggle_array[i].on_last_time = new_state;
1173
                if (new_state) {
1174
                    gToggle_array[i].action_proc();
1175
                }
1176
            }
1177
        }
1178
    }
1179
}
1180
 
1181
// IDA: int __usercall CarWorldOffFallenCheckThingy@<EAX>(tCar_spec *pCar@<EAX>, int pCheck_around@<EDX>)
1182
int CarWorldOffFallenCheckThingy(tCar_spec* pCar, int pCheck_around) {
1183
    br_vector3 car_pos;
1184
    br_vector3 offset_c;
1185
    br_vector3 offset_w;
1186
    int result;
1187
    LOG_TRACE("(%p, %d)", pCar, pCheck_around);
1188
 
1189
    if (pCar->number_of_wheels_on_ground != 0) {
1190
        return 0;
1191
    }
1192
    if (pCar->driver == eDriver_local_human && gCar_flying) {
1193
        return 0;
1194
    }
1195
    if (gAction_replay_mode) {
1196
        return 0;
1197
    }
1198
    BrVector3Copy(&car_pos, &pCar->car_master_actor->t.t.translate.t);
1199
    if (FindYVerticallyBelow2(&car_pos) >= -100.f) {
1200
        return 0;
1201
    }
1202
    BrVector3Set(&offset_c, 0.f, 1.f, 0.f);
1203
    BrMatrix34ApplyV(&offset_w, &offset_c, &pCar->car_master_actor->t.t.mat);
1204
    if (FindYVerticallyBelow2(&car_pos) >= -100.f) {
1205
        // FIXME: testing twice using `FindYVerticallyBelow2' is meaningless
1206
        return 0;
1207
    }
1208
    if (!pCheck_around) {
1209
        return 1;
1210
    }
1211
    pCar->car_master_actor->t.t.translate.t.v[0] += 0.05f;
1212
    result = CarWorldOffFallenCheckThingy(pCar, 0);
1213
    pCar->car_master_actor->t.t.translate.t.v[0] -= 0.05f;
1214
    if (!result) {
1215
        return 0;
1216
    }
1217
    pCar->car_master_actor->t.t.translate.t.v[2] += 0.05f;
1218
    result = CarWorldOffFallenCheckThingy(pCar, 0);
1219
    pCar->car_master_actor->t.t.translate.t.v[2] -= 0.05f;
1220
    if (!result) {
1221
        return 0;
1222
    }
1223
    return 1;
1224
}
1225
 
1226
// IDA: int __usercall HasCarFallenOffWorld@<EAX>(tCar_spec *pCar@<EAX>)
1227
int HasCarFallenOffWorld(tCar_spec* pCar) {
1228
    LOG_TRACE("(%p)", pCar);
1229
 
1230
    return CarWorldOffFallenCheckThingy(pCar, 1);
1231
}
1232
 
1233
// IDA: void __cdecl CheckForBeingOutOfThisWorld()
1234
void CheckForBeingOutOfThisWorld(void) {
1235
    static tU32 the_time;
1236
    static tU32 sLast_check;
1237
    //int time_step; // Pierre-Marie Baty -- unused variable
1238
    LOG_TRACE("()");
1239
 
1240
    the_time = PDGetTotalTime();
1241
 
1242
    if (gRecover_timer == 0 || ((gProgram_state.current_car.frame_collision_flag || gProgram_state.current_car.number_of_wheels_on_ground) && !IsCarInTheSea())) {
1243
        gRecover_timer = 0;
1244
        if ((the_time - sLast_check) > 200) {
1245
            sLast_check = the_time;
1246
            if (HasCarFallenOffWorld(&gProgram_state.current_car)) {
1247
                gRecover_timer = 3000;
1248
            }
1249
        }
1250
        if (IsCarInTheSea()) {
1251
            if (!gRecover_timer) {
1252
                gRecover_timer = 3000;
1253
            }
1254
        }
1255
        return;
1256
    }
1257
    gRecover_timer -= gFrame_period;
1258
    if (gRecover_timer <= 0 || IsCarInTheSea() == 2) {
1259
        gRecover_timer = 0;
1260
        RecoverCar();
1261
        gHad_auto_recover = 1;
1262
    }
1263
}
1264
 
1265
// IDA: void __usercall CheckHornLocal(tCar_spec *pCar@<EAX>)
1266
void CheckHornLocal(tCar_spec* pCar) {
1267
    LOG_TRACE("(%p)", pCar);
1268
 
1269
    if (pCar->keys.horn == 1 && pCar->horn_sound_tag == 0) {
1270
        pCar->horn_sound_tag = DRS3StartSound(gEffects_outlet, 5209);
1271
    } else if (pCar->keys.horn == 0 && pCar->horn_sound_tag != 0) {
1272
        if (S3SoundStillPlaying(pCar->horn_sound_tag) != 0) {
1273
            DRS3StopSound(pCar->horn_sound_tag);
1274
            DRS3StopOutletSound(gEffects_outlet);
1275
        }
1276
        if (S3SoundStillPlaying(pCar->horn_sound_tag) == 0) {
1277
            pCar->horn_sound_tag = 0;
1278
        }
1279
    }
1280
}
1281
 
1282
// IDA: void __usercall CheckHorn3D(tCar_spec *pCar@<EAX>)
1283
void CheckHorn3D(tCar_spec* pCar) {
1284
    LOG_TRACE("(%p)", pCar);
18 pmbaty 1285
 
1286
    if (pCar->keys.horn && pCar->horn_sound_tag == 0) {
1287
        pCar->horn_sound_tag = DRS3StartSound3D(gEffects_outlet,
1288
            5209,
1289
            &pCar->car_master_actor->t.t.translate.t,
1290
            &pCar->velocity_bu_per_sec,
1291
            0,
1292
            255,
1293
            ((pCar->car_ID & 7) << 12) + 0xc000,
1294
            0x10000);
1295
    } else {
1296
        if (!pCar->keys.horn && pCar->horn_sound_tag != 0) {
1297
            while (S3SoundStillPlaying(pCar->horn_sound_tag)) {
1298
                DRS3StopSound(pCar->horn_sound_tag);
1299
                DRS3StopOutletSound(gEffects_outlet);
1300
            }
1301
            if (!S3SoundStillPlaying(pCar->horn_sound_tag)) {
1302
                pCar->horn_sound_tag = 0;
1303
            }
1304
        }
1305
    }
1 pmbaty 1306
}
1307
 
1308
// IDA: void __cdecl CheckHorns()
1309
void CheckHorns(void) {
1310
    int i;
1311
    LOG_TRACE("()");
1312
 
1313
    if (gNet_mode != eNet_mode_none) {
1314
        for (i = 0; i < gNumber_of_net_players; i++) {
1315
            CheckHorn3D(gNet_players[i].car);
1316
        }
1317
    } else {
1318
        CheckHornLocal(&gProgram_state.current_car);
1319
    }
1320
}
1321
 
1322
// IDA: void __cdecl SetRecovery()
1323
void SetRecovery(void) {
1324
    LOG_TRACE("()");
1325
 
1326
    if (gRace_finished
1327
        || gProgram_state.current_car.knackered
1328
        || gWait_for_it
1329
        || gHad_auto_recover
1330
        || gPalette_fade_time) {
1331
        return;
1332
    }
1333
 
1334
    if (gNet_mode == eNet_mode_none) {
1335
        gRecover_car = 1;
1336
        gRecover_timer = 0;
1337
        return;
1338
    }
1339
    if (gProgram_state.current_car.time_to_recover) {
1340
        if (GetRaceTime() + 600 >= gProgram_state.current_car.time_to_recover) {
1341
            NewTextHeadupSlot2(4, 0, 2000, -4, GetMiscString(kMiscString_TOO_LATE_TO_CANCEL), 1);
1342
            gToo_late = 1;
1343
        } else {
1344
            gProgram_state.current_car.time_to_recover = 0;
1345
            NewTextHeadupSlot2(4, 0, 2000, -4, GetMiscString(kMiscString_RECOVERY_CANCELLED), 0);
1346
        }
1347
        return;
1348
    }
1349
    if (!CheckRecoverCost()) {
1350
        return;
1351
    }
1352
    if (gCurrent_net_game->type == eNet_game_type_foxy) {
1353
        if (gThis_net_player_index == gIt_or_fox) {
1354
            gProgram_state.current_car.time_to_recover = GetRaceTime() + 5000;
1355
            gRecover_timer = 0;
1356
            gToo_late = 0;
1357
            return;
1358
        }
1359
    } else {
1360
        if (gCurrent_net_game->type != eNet_game_type_tag) {
1361
            gProgram_state.current_car.time_to_recover = GetRaceTime() + 3000;
1362
            gRecover_timer = 0;
1363
            gToo_late = 0;
1364
            return;
1365
        }
1366
        if (gThis_net_player_index != gIt_or_fox) {
1367
            gProgram_state.current_car.time_to_recover = GetRaceTime() + 5000;
1368
            gRecover_timer = 0;
1369
            gToo_late = 0;
1370
            return;
1371
        }
1372
    }
1373
    gProgram_state.current_car.time_to_recover = GetRaceTime() + 1000;
1374
    gRecover_timer = 0;
1375
    gToo_late = 0;
1376
}
1377
 
1378
// IDA: void __cdecl RecoverCar()
1379
void RecoverCar(void) {
1380
    LOG_TRACE("()");
1381
 
1382
    if (gNet_mode == eNet_mode_none || !gPalette_fade_time) {
1383
        gRecover_car = 1;
1384
    }
1385
    gProgram_state.current_car.time_to_recover = 0;
1386
}
1387
 
1388
// IDA: void __cdecl CheckMapRenderMove()
1389
void CheckMapRenderMove(void) {
1390
    //int shift_down; // Pierre-Marie Baty -- unused variable
1391
    int amount;
1392
    float old_x;
1393
    float old_y;
1394
    LOG_TRACE("()");
1395
 
1396
    old_y = gMap_render_y;
1397
    old_x = gMap_render_x;
1398
    if (gMap_mode) {
1399
        amount = gFrame_period * .1f;
18 pmbaty 1400
        if (KeyIsDown(KEYMAP_MOVE_UP)) {
1 pmbaty 1401
            gMap_render_y -= amount;
18 pmbaty 1402
        } else if (KeyIsDown(KEYMAP_MOVE_DOWN)) {
1 pmbaty 1403
            gMap_render_y += amount;
1404
        }
18 pmbaty 1405
        if (KeyIsDown(KEYMAP_MOVE_LEFT)) {
1 pmbaty 1406
            gMap_render_x -= amount;
18 pmbaty 1407
        } else if (KeyIsDown(KEYMAP_MOVE_RIGHT)) {
1 pmbaty 1408
            gMap_render_x += amount;
1409
        }
1410
        if (gMap_render_x != old_x || gMap_render_y != old_y) {
1411
            SetIntegerMapRenders();
1412
            if (gMap_render_x_i < gCurrent_graf_data->map_render_x_marg) {
1413
                if (gReal_graf_data_index == 0) {
1414
                    gMap_render_x = (gCurrent_graf_data->map_render_x_marg + 3) & ~3;
1415
                } else {
1416
                    gMap_render_x = ((gCurrent_graf_data->map_render_x_marg + 3) & ~3) / 2;
1417
                }
1418
            }
1419
            if (gMap_render_y_i < gCurrent_graf_data->map_render_y_marg) {
1420
                if (gReal_graf_data_index == 0) {
1421
                    gMap_render_y = (gCurrent_graf_data->map_render_y_marg + 1) & ~1;
1422
                } else {
1423
                    gMap_render_y = (((gCurrent_graf_data->map_render_y_marg + 1) & ~1) - 40) / 2;
1424
                }
1425
            }
1426
            if (gBack_screen->width - gCurrent_graf_data->map_render_x_marg - gMap_render_width_i < gMap_render_x_i) {
1427
                if (gReal_graf_data_index == 0) {
1428
                    gMap_render_x = (gBack_screen->width - gCurrent_graf_data->map_render_x_marg - gMap_render_width_i) & ~3;
1429
                } else {
1430
                    gMap_render_x = ((gBack_screen->width - gCurrent_graf_data->map_render_x_marg - gMap_render_width_i) & ~3) / 2;
1431
                }
1432
            }
1433
            if (gBack_screen->height - gCurrent_graf_data->map_render_y_marg - gMap_render_height_i < gMap_render_y_i) {
1434
                if (gReal_graf_data_index == 0) {
1435
                    gMap_render_y = (gBack_screen->height - gCurrent_graf_data->map_render_y_marg - gMap_render_height_i) & ~1;
1436
                } else {
1437
                    gMap_render_y = (((gBack_screen->height - gCurrent_graf_data->map_render_y_marg - gMap_render_height_i) & ~3) - 40) / 2;
1438
                }
1439
            }
1440
            SetIntegerMapRenders();
1441
            AdjustRenderScreenSize();
1442
        }
1443
    }
1444
}
1445
 
1446
// IDA: void __usercall ExplodeCar(tCar_spec *pCar@<EAX>)
1447
void ExplodeCar(tCar_spec* pCar) {
1448
    br_vector3 tv;
1449
    br_vector3 pos;
1450
    LOG_TRACE("(%p)", pCar);
1451
 
1452
    pCar->last_car_car_collision = 0;
1453
    pos.v[0] = .1449275f * pCar->cmpos.v[0];
1454
    pos.v[1] = .1449275f * pCar->cmpos.v[1];
1455
    pos.v[2] = pCar->bounds[0].min.v[2] + .3f * (pCar->bounds[0].max.v[2] - pCar->bounds[0].min.v[2]);
1456
    BrMatrix34ApplyP(&tv, &pos, &pCar->car_master_actor->t.t.mat);
1457
    CreatePuffOfSmoke(&tv, &pCar->v, 1.f, 1.f, 7, pCar);
1458
 
1459
    pos.v[2] = pCar->bounds[0].min.v[2] + .7f * (pCar->bounds[0].max.v[2] - pCar->bounds[0].min.v[2]);
1460
    BrMatrix34ApplyP(&tv, &pos, &pCar->car_master_actor->t.t.mat);
1461
    CreatePuffOfSmoke(&tv, &pCar->v, 1.f, 1.f, 7, pCar);
1462
 
1463
    DisableCar(pCar);
1464
}
1465
 
1466
// IDA: void __usercall CheckRecoveryOfCars(tU32 pEndFrameTime@<EAX>)
1467
void CheckRecoveryOfCars(tU32 pEndFrameTime) {
1468
    int i;
1469
    int time;
1470
    char s[256];
1471
    LOG_TRACE("(%d)", pEndFrameTime);
1472
 
1473
    if (gProgram_state.current_car.time_to_recover) {
1474
        if (gProgram_state.current_car.knackered) {
1475
            gProgram_state.current_car.time_to_recover = 0;
1476
        } else {
1477
            time = (gProgram_state.current_car.time_to_recover - pEndFrameTime + 1000) / 1000;
1478
            sprintf(s, "%s %d %s", GetMiscString(kMiscString_RECOVERY_IN), time, time > 1 ? GetMiscString(kMiscString_SECONDS) : GetMiscString(kMiscString_SECOND));
1479
            if (!gToo_late) {
1480
                NewTextHeadupSlot2(4, 0, 2000, -4, s, 0);
1481
            }
1482
            if (gProgram_state.current_car.time_to_recover <= pEndFrameTime) {
1483
                RecoverCar();
1484
            }
1485
        }
1486
    }
1487
    if (gNet_mode) {
1488
        for (i = 0; i < gNumber_of_net_players; i++) {
1489
            if (gThis_net_player_index != i && gNet_players[i].car->time_to_recover && gNet_players[i].car->time_to_recover <= pEndFrameTime) {
1490
                gNet_players[i].player_status = ePlayer_status_recovering;
1491
                gNet_players[i].car->message.type = 32;
1492
                gNet_players[i].car->message.time = pEndFrameTime;
1493
                ExplodeCar(gNet_players[i].car);
1494
                gNet_players[i].car->time_to_recover = 0;
1495
            }
1496
        }
1497
    }
1498
}
1499
 
1500
// IDA: void __usercall LoseSomePSPowerups(int pNumber@<EAX>)
1501
void LoseSomePSPowerups(int pNumber) {
1502
    int index;
1503
    LOG_TRACE("(%d)", pNumber);
1504
 
1505
    if (gNet_mode != eNet_mode_none && pNumber > 0) {
1506
        while (pNumber--) {
1507
            index = IRandomBetween(0, 2);
1508
            if (gProgram_state.current_car.power_up_levels[index]) {
1509
                gProgram_state.current_car.power_up_levels[index]--;
1510
            }
1511
        }
1512
    }
1513
}
1514
 
1515
// IDA: void __cdecl CheckOtherRacingKeys()
1516
void CheckOtherRacingKeys(void) {
1517
    int i;
1518
    int j;
1519
    int new_level;
1520
    int old_level;
1521
    char s[256];
1522
    tU32 cost;
1523
    br_scalar ts;
1524
    //br_vector3 tv; // Pierre-Marie Baty -- unused variable
1525
    //int flip_up_flag; // Pierre-Marie Baty -- unused variable
1526
    tCar_spec* car;
1527
    float bodywork_repair_amount;
1528
    static tU32 total_repair_cost;
1529
    static tS3_sound_tag sound_tag;
1530
    static br_scalar amount;
1531
    static int NeedToExpandBoundingBox;
1532
    static int total_difference;
1533
    static int stopped_repairing;
1534
    LOG_TRACE("()");
1535
 
1536
    car = GetCarSpec(eVehicle_self, 0);
1537
    CheckMapRenderMove();
1538
    CheckHorns();
1539
    CheckForBeingOutOfThisWorld();
1540
    if (gPalette_fade_time) {
1541
        SortOutRecover(car);
1542
    } else if (gNet_mode && NetGetPlayerStatus() == ePlayer_status_recovering) {
1543
        NetPlayerStatusChanged(ePlayer_status_racing);
1544
    }
1545
 
1546
    if ((gAuto_repair || KeyIsDown(KEYMAP_REPAIR)) && !gRace_finished && !gProgram_state.current_car.knackered && !gWait_for_it && !gEntering_message) {
1547
        if (!gAuto_repair && gRepair_last_time == 0 && GetTotalTime() - gLast_repair_time < 1200) {
1548
            gAuto_repair = 1;
1549
        }
1550
        gLast_repair_time = GetTotalTime();
1551
        gRepair_last_time = 1;
1552
        if (!NeedToExpandBoundingBox) {
1553
            if (gFree_repairs
1554
                || gNet_mode == eNet_mode_none
1555
                || gProgram_state.credits_earned - gProgram_state.credits_lost >= 1) {
1556
                bodywork_repair_amount = RepairCar(gProgram_state.current_car.car_ID, gFrame_period, &amount);
1557
                NeedToExpandBoundingBox = bodywork_repair_amount > 0;
1558
                cost = 0;
1559
                for (j = 0; j < COUNT_OF(gProgram_state.current_car.damage_units); j++) {
1560
                    old_level = gProgram_state.current_car.damage_units[j].damage_level;
1561
                    if (amount == 0.0f) {
1562
                        new_level = 0;
1563
                    } else {
1564
                        new_level = ((double)gProgram_state.current_car.damage_units[j].damage_level
1565
                            - floor(bodywork_repair_amount / amount * (double)gProgram_state.current_car.damage_units[j].damage_level));
1566
                    }
1567
                    if (new_level >= 0) {
1568
                        if (new_level < 100) {
1569
                            gProgram_state.current_car.damage_units[j].damage_level = new_level;
1570
                        } else {
1571
                            gProgram_state.current_car.damage_units[j].damage_level = 99;
1572
                        }
1573
                    } else {
1574
                        gProgram_state.current_car.damage_units[j].damage_level = 0;
1575
                    }
1576
                    gProgram_state.current_car.damage_units[j].smoke_last_level = gProgram_state.current_car.damage_units[j].damage_level;
1577
                    if (gNet_mode) {
1578
                        ts = gNet_repair_cost[gCurrent_net_game->type];
1579
                    } else {
1580
                        ts = gRepair_cost[gProgram_state.skill_level];
1581
                    }
1582
                    cost = (old_level - gProgram_state.current_car.damage_units[j].damage_level) * ts + cost;
1583
                    total_difference += old_level - new_level;
1584
                }
1585
                if (!gFree_repairs) {
1586
                    LoseSomePSPowerups(total_difference / 100);
1587
                }
1588
                total_difference %= 100;
1589
                cost = 10 * (cost / 10);
1590
                if (((!total_repair_cost && cost) || bodywork_repair_amount != 0.0f) && !sound_tag) {
1591
                    sound_tag = DRS3StartSound(gCar_outlet, 5200);
1592
                }
1593
                if (gProgram_state.current_car.num_smoke_columns) {
1594
                    StopCarSmoking(&gProgram_state.current_car);
1595
                }
1596
                if (!cost && bodywork_repair_amount == 0.0) {
1597
                    gAuto_repair = 0;
1598
                }
1599
                if (!gFree_repairs) {
1600
                    cost += SpendCredits(cost);
1601
                }
1602
                total_repair_cost += cost;
1603
                if (total_repair_cost) {
1604
                    if (gFree_repairs) {
1605
                        NewTextHeadupSlot(4, 0, 1000, -4, GetMiscString(kMiscString_RepairingForFree));
1606
                    } else {
1607
                        sprintf(s, "%s %d", GetMiscString(kMiscString_RepairCostColon), total_repair_cost);
1608
                        NewTextHeadupSlot(4, 0, 1000, -4, s);
1609
                    }
1610
                }
1611
            } else {
1612
                if (!stopped_repairing) {
1613
                    NewTextHeadupSlot(4, 0, 1000, -4, GetMiscString(kMiscString_CANNOT_AFFORD_TO_REPAIR));
1614
                }
1615
                gAuto_repair = 0;
1616
                stopped_repairing = 1;
1617
            }
1618
        }
1619
 
1620
    } else {
1621
        gRepair_last_time = 0;
1622
        stopped_repairing = 0;
1623
        total_repair_cost = 0;
1624
        total_difference = 0;
1625
        if (sound_tag) {
1626
            for (i = 0; i < 10 && S3SoundStillPlaying(sound_tag); ++i) {
1627
                DRS3StopSound(sound_tag);
1628
            }
1629
            sound_tag = 0;
1630
        }
1631
    }
1632
    if (NeedToExpandBoundingBox) {
1633
        NeedToExpandBoundingBox = ExpandBoundingBox(&gProgram_state.current_car) == 0;
1634
    }
1635
    if (!gRecover_car || gProgram_state.current_car.knackered) {
1636
        gHad_auto_recover = 0;
1637
    } else if (CheckRecoverCost()) {
1638
        gRecover_timer = 0;
1639
        SetFlipUpCar(car);
1640
        if (gNet_mode != eNet_mode_none) {
1641
            NewTextHeadupSlot(4, 0, 1500, -4, " ");
1642
        }
1643
        if (gRecovery_voucher_count != 0) {
1644
            gRecovery_voucher_count--;
1645
            sprintf(s, "%s", GetMiscString(kMiscString_RecoveringForFree));
1646
            NewTextHeadupSlot(4, 0, 1500, -4, s);
1647
        } else {
1648
            if (gNet_mode) {
1649
                cost = gNet_recovery_cost[gCurrent_net_game->type];
1650
            } else {
1651
                cost = gRecovery_cost[gProgram_state.skill_level];
1652
            }
1653
            SpendCredits(cost);
1654
            if (gNet_mode) {
1655
                cost = gNet_recovery_cost[gCurrent_net_game->type];
1656
            } else {
1657
                cost = gRecovery_cost[gProgram_state.skill_level];
1658
            }
1659
            sprintf(s, "%s %d", GetMiscString(kMiscString_RecoveryCostColon), cost);
1660
            NewTextHeadupSlot(4, 0, 1500, -4, s);
1661
            LoseSomePSPowerups(2);
1662
        }
1663
        CancelPendingCunningStunt();
1664
        PipeSingleSpecial(ePipe_special_fade);
1665
    }
1666
    gRecover_car = 0;
1667
}
1668
 
1669
// IDA: int __cdecl CheckRecoverCost()
1670
int CheckRecoverCost(void) {
1671
    LOG_TRACE("()");
1672
 
1673
    if (gProgram_state.current_car.knackered
1674
        || gNet_mode == eNet_mode_none
1675
        || (gProgram_state.credits_earned - gProgram_state.credits_lost) >= gNet_recovery_cost[gCurrent_net_game->type]
1676
        || gRecovery_voucher_count) {
1677
        return 1;
1678
    }
1679
    gProgram_state.credits_earned = 0;
1680
    gProgram_state.credits_lost = 0;
1681
    NewTextHeadupSlot(4, 0, 1000, -4, GetMiscString(kMiscString_CANNOT_AFFORD_TO_RECOVER));
1682
    DoFancyHeadup(kFancyHeadupNetworkRaceNoMoreMoney);
1683
    KnackerThisCar(&gProgram_state.current_car);
1684
    SendGameplayToHost(eNet_gameplay_suicide, 0, 0, 0, 0);
1685
    return 0;
1686
}
1687
 
1688
// IDA: void __usercall SortOutRecover(tCar_spec *pCar@<EAX>)
1689
void SortOutRecover(tCar_spec* pCar) {
1690
    int the_time;
1691
    int val;
1692
    static int old_time;
1693
    LOG_TRACE("(%p)", pCar);
1694
 
1695
    the_time = GetRaceTime() - gPalette_fade_time;
1696
    if (the_time < 0) {
1697
        gPalette_fade_time = 0;
1698
        old_time = 0;
1699
    }
1700
    if (the_time < 500) {
1701
        val = 256 - (the_time * 256) / 500;
1702
    } else {
1703
        if (old_time < 500) {
1704
            FlipUpCar(pCar);
1705
            PipeSingleSpecial(ePipe_special_fade);
1706
        }
1707
        pCar->doing_nothing_flag = 1;
1708
        val = ((the_time - 1000) * 256) / 500;
1709
        if (val >= 256) {
1710
            val = 256;
1711
            gPalette_fade_time = 0;
1712
            old_time = 0;
1713
            pCar->doing_nothing_flag = 0;
1714
        }
1715
    }
1716
    if (val <= 0) {
1717
        val = 0;
1718
    }
1719
    SetFadedPalette(val);
1720
    old_time = the_time;
1721
}
1722
 
1723
// IDA: void __usercall SetFlipUpCar(tCar_spec *pCar@<EAX>)
1724
void SetFlipUpCar(tCar_spec* pCar) {
1725
    LOG_TRACE("(%p)", pCar);
1726
 
1727
    if (gNet_mode != eNet_mode_none && pCar->driver == eDriver_local_human) {
1728
        DisableCar(pCar);
1729
        gPalette_fade_time = GetRaceTime();
1730
        NetPlayerStatusChanged(ePlayer_status_recovering);
1731
    } else {
1732
        FlipUpCar(pCar);
1733
    }
1734
}
1735
 
1736
// IDA: void __usercall FlipUpCar(tCar_spec *car@<EAX>)
1737
void FlipUpCar(tCar_spec* car) {
1738
    br_vector3 tv;
1739
    br_vector3 dir;
1740
    int new_pos;
1741
    int i;
1742
    int j;
1743
    int l;
1744
    int count;
1745
    //br_scalar dist; // Pierre-Marie Baty -- unused variable
1746
    br_material* material;
1747
    br_scalar t;
1748
    LOG_TRACE("(%p)", car);
1749
 
1750
    count = 0;
1751
    if (car->driver == eDriver_local_human && gNet_mode == eNet_mode_none) {
1752
        FadePaletteDown();
18 pmbaty 1753
        while (KeyIsDown(KEYMAP_REPAIR)) {
1 pmbaty 1754
            ;
1755
        }
1756
    }
1757
    car->doing_nothing_flag = 0;
1758
    EnableCar(car);
1759
    new_pos = 1;
1760
    for (i = 0; i < 4; ++i) {
1761
        if (car->susp_height[i >> 1] <= car->oldd[i]) {
1762
            new_pos = 0;
1763
        }
1764
    }
1765
    do {
1766
        tv.v[0] = car->car_master_actor->t.t.mat.m[3][0] - car->last_safe_positions[0].m[3][0];
1767
        tv.v[1] = car->car_master_actor->t.t.mat.m[3][1] - car->last_safe_positions[0].m[3][1];
1768
        tv.v[2] = car->car_master_actor->t.t.mat.m[3][2] - car->last_safe_positions[0].m[3][2];
1769
        if (BrVector3LengthSquared(&tv) > 8.3015966) {
1770
            new_pos = 0;
1771
        }
1772
        BrMatrix34Copy(&car->car_master_actor->t.t.mat, &car->last_safe_positions[new_pos]);
1773
        BrMatrix34Copy(&car->oldmat, &car->last_safe_positions[new_pos]);
1774
        BrMatrix34Copy(&car->old_frame_mat, &car->oldmat);
1775
        car->oldmat.m[3][0] = car->oldmat.m[3][0] * WORLD_SCALE;
1776
        car->oldmat.m[3][1] = car->oldmat.m[3][1] * WORLD_SCALE;
1777
        car->oldmat.m[3][2] = car->oldmat.m[3][2] * WORLD_SCALE;
1778
        dir.v[0] = 0.0;
1779
        dir.v[1] = (br_scalar) 0.28985506; // Pierre-Marie Baty -- added type cast
1780
        dir.v[2] = 0.0;
1781
        FindFace(&car->car_master_actor->t.t.euler.t, &dir, &tv, &t, &material);
1782
        if (t > 1.0) {
1783
            car->car_master_actor->t.t.mat.m[3][0] += dir.v[0];
1784
            car->car_master_actor->t.t.mat.m[3][1] += dir.v[1];
1785
            car->car_master_actor->t.t.mat.m[3][2] += dir.v[2];
1786
            car->oldmat.m[3][0] = car->car_master_actor->t.t.mat.m[3][0] * WORLD_SCALE;
1787
            car->oldmat.m[3][1] = car->car_master_actor->t.t.mat.m[3][1] * WORLD_SCALE;
1788
            car->oldmat.m[3][2] = car->car_master_actor->t.t.mat.m[3][2] * WORLD_SCALE;
1789
            car->old_frame_mat.m[3][0] = car->car_master_actor->t.t.mat.m[3][0];
1790
            car->old_frame_mat.m[3][1] = car->car_master_actor->t.t.mat.m[3][1];
1791
            car->old_frame_mat.m[3][2] = car->car_master_actor->t.t.mat.m[3][2];
1792
        }
1793
        tv.v[0] = 0.0;
1794
        tv.v[1] = 0.0;
1795
        tv.v[2] = (br_scalar) -0.001; // Pierre-Marie Baty -- added type cast
1796
        BrMatrix34ApplyV(&car->v, &tv, &car->car_master_actor->t.t.mat);
1797
        car->omega.v[0] = 0.0;
1798
        car->omega.v[1] = 0.0;
1799
        car->omega.v[2] = 0.0;
1800
        car->direction.v[0] = -car->oldmat.m[2][0];
1801
        car->direction.v[1] = -car->oldmat.m[2][1];
1802
        car->direction.v[2] = -car->oldmat.m[2][2];
1803
        for (i = 0; i <= new_pos; i++) {
1804
            for (j = 0; j < 4; j++) {
1805
                BrMatrix34Copy(&car->last_safe_positions[j], &car->last_safe_positions[j + 1]);
1806
            }
1807
        }
1808
        for (l = 0; l < 10; l++) {
1809
            BrVector3Scale(&car->old_norm, &car->old_norm, 0.072463766);
1810
            BrMatrix34ApplyV(&tv, &car->old_norm, &car->car_master_actor->t.t.mat);
1811
            car->car_master_actor->t.t.mat.m[3][0] = car->car_master_actor->t.t.mat.m[3][0] + tv.v[0];
1812
            car->car_master_actor->t.t.mat.m[3][1] = car->car_master_actor->t.t.mat.m[3][1] + tv.v[1];
1813
            car->car_master_actor->t.t.mat.m[3][2] = car->car_master_actor->t.t.mat.m[3][2] + tv.v[2];
1814
            car->oldmat.m[3][0] = car->car_master_actor->t.t.mat.m[3][0] * WORLD_SCALE;
1815
            car->oldmat.m[3][1] = car->car_master_actor->t.t.mat.m[3][1] * WORLD_SCALE;
1816
            car->oldmat.m[3][2] = car->car_master_actor->t.t.mat.m[3][2] * WORLD_SCALE;
1817
            car->old_frame_mat.m[3][0] = car->car_master_actor->t.t.mat.m[3][0];
1818
            car->old_frame_mat.m[3][1] = car->car_master_actor->t.t.mat.m[3][1];
1819
            car->old_frame_mat.m[3][2] = car->car_master_actor->t.t.mat.m[3][2];
1820
            if (TestForCarInSensiblePlace(car)) {
1821
                break;
1822
            }
1823
        }
1824
        count++;
1825
    } while (l == 10 && count < 3);
1826
    car->oldmat.m[3][0] = car->car_master_actor->t.t.mat.m[3][0] * WORLD_SCALE;
1827
    car->oldmat.m[3][1] = car->car_master_actor->t.t.mat.m[3][1] * WORLD_SCALE;
1828
    car->oldmat.m[3][2] = car->car_master_actor->t.t.mat.m[3][2] * WORLD_SCALE;
1829
    car->curvature = 0.0;
1830
    for (j = 0; j < 4; ++j) {
1831
        car->oldd[j] = car->ride_height;
1832
    }
1833
    car->revs = 0.0;
1834
    car->gear = 0;
1835
    car->auto_special_volume = 0;
1836
    if (car->driver == eDriver_local_human) {
1837
        InitialiseExternalCamera();
1838
        PositionExternalCamera(car, 100u);
1839
    }
1840
}
1841
 
1842
// IDA: void __usercall GetPowerup(int pNum@<EAX>)
1843
void GetPowerup(int pNum) {
1844
    LOG_TRACE("()");
1845
 
1846
    // FIXME: remove unittest variables from dethrace
1847
    _unittest_controls_lastGetPowerup = pNum;
1848
 
1849
    GotPowerup(&gProgram_state.current_car, pNum);
1850
}
1851
 
1852
// IDA: void __usercall CheckSystemKeys(int pRacing@<EAX>)
1853
void CheckSystemKeys(int pRacing) {
1854
    tU32 start_menu_time;
1855
    //int i; // Pierre-Marie Baty -- unused variable
1856
 
1857
    start_menu_time = PDGetTotalTime();
1858
    CheckQuit();
1859
    if (!gAction_replay_mode) {
1860
        CheckLoadSave();
1861
    }
1862
    AddLostTime(PDGetTotalTime() - start_menu_time);
1863
    CheckToggles(pRacing);
1864
    if (pRacing & !gAction_replay_mode) {
1865
        CheckOtherRacingKeys();
1866
    }
1867
}
1868
 
1869
// IDA: void __cdecl CheckKevKeys()
1870
void CheckKevKeys(void) {
1871
    int i;
1872
    tU32* value;
1873
    char s[128];
1874
 
1875
    value = KevKeyService();
1876
    if (value[0] == 0) {
1877
        return;
1878
    }
1879
 
1880
    for (i = 0; gKev_keys[i].action_proc != 0; i++) {
1881
        if (gKev_keys[i].code == value[0] && gKev_keys[i].code2 == value[1]) {
1882
            break;
1883
        }
1884
    }
1885
 
1886
    if (gKev_keys[i].action_proc) {
1887
        if (gNet_mode) {
1888
            if (gKev_keys[i].num == 0xA11EE75D) {
1889
                strcpy(s, gNet_players[gThis_net_player_index].player_name);
1890
                strcat(s, " ");
1891
                strcat(s, GetMiscString(kMiscString_MANAGED_TO_CHEAT));
1892
                NetSendHeadupToEverybody(s);
1893
                gKev_keys[i].action_proc(gKev_keys[i].num);
1894
            } else {
1895
                strcpy(s, gNet_players[gThis_net_player_index].player_name);
1896
                strcat(s, " ");
1897
                strcat(s, GetMiscString(kMiscString_TRIED_TO_CHEAT));
1898
                NetSendHeadupToAllPlayers(s);
1899
            }
1900
        } else {
1901
            gKev_keys[i].action_proc(gKev_keys[i].num);
1902
        }
1903
    }
1904
}
1905
 
1906
// IDA: void __cdecl BrakeInstantly()
1907
void BrakeInstantly(void) {
1908
    int i;
1909
    LOG_TRACE("()");
1910
 
1911
    gProgram_state.current_car.revs = 0.f;
1912
    if (gProgram_state.current_car.number_of_wheels_on_ground != 0 && BrVector3LengthSquared(&gProgram_state.current_car.v) > 0.0001f) {
1913
        PratcamEvent(41);
1914
        for (i = 0; i < 5; i++) {
1915
            DRS3StartSound(gCar_outlet, 9000 + i);
1916
        }
1917
    }
1918
    BrVector3Set(&gProgram_state.current_car.v, 0.f, 0.f, 0.f);
1919
}
1920
 
1921
// IDA: void __usercall PollCarControls(tU32 pTime_difference@<EAX>)
1922
void PollCarControls(tU32 pTime_difference) {
1923
    //int decay_steering; // Pierre-Marie Baty -- unused variable
1924
    //int decay_speed; // Pierre-Marie Baty -- unused variable
1925
    //float decay_rate; // Pierre-Marie Baty -- unused variable
1926
    //tS32 joyX; // Pierre-Marie Baty -- unused variable
1927
    //tS32 joyY; // Pierre-Marie Baty -- unused variable
1928
    tCar_controls keys;
1929
    tJoystick joystick;
1930
    tCar_spec* c;
1931
    LOG_TRACE("(%d)", pTime_difference);
1932
 
1933
    c = &gProgram_state.current_car;
1934
 
1935
    memset(&keys, 0, sizeof(tCar_controls));
1936
    joystick.left = -1;
1937
    joystick.right = -1;
1938
    joystick.acc = -1;
1939
    joystick.dec = -1;
1940
    if (gEntering_message) {
1941
        memset(&c->keys, 0, sizeof(tCar_controls));
1942
        c->joystick.left = -1;
1943
        c->joystick.right = -1;
1944
        c->joystick.acc = -1;
1945
        c->joystick.dec = -1;
1946
    } else {
1947
        if (gKey_mapping[46] >= 115 || gKey_mapping[47] >= 115) {
1948
            joystick.left = gJoy_array[gKey_mapping[46] - 115];
1949
            joystick.right = gJoy_array[gKey_mapping[47] - 115];
1950
            if (joystick.left < 0 && joystick.right < 0) {
1951
                joystick.left = 0;
1952
            }
1953
        } else {
1954
            if (KeyIsDown(46)) {
1955
                keys.left = 1;
1956
            }
1957
            if (KeyIsDown(47)) {
1958
                keys.right = 1;
1959
            }
1960
        }
1961
        if (KeyIsDown(12)) {
1962
            keys.holdw = 1;
1963
        }
1964
        if (KeyIsDown(53) || gRace_finished) {
1965
            if (!gInstant_handbrake || gRace_finished) {
1966
                keys.brake = 1;
1967
            } else {
1968
                BrakeInstantly();
1969
            }
1970
        }
1971
        if (gKey_mapping[48] < 115) {
1972
            if (KeyIsDown(48) && !gRace_finished && !c->knackered && !gWait_for_it) {
1973
                keys.acc = 1;
1974
            }
1975
        } else {
1976
            joystick.acc = gJoy_array[gKey_mapping[48] - 115];
1977
            if (joystick.acc > 0xFFFF) {
1978
                joystick.acc = 0xFFFF;
1979
            }
1980
        }
1981
        if (gKey_mapping[49] < 115) {
1982
            if (KeyIsDown(49) && !gRace_finished && !c->knackered && !gWait_for_it) {
1983
                keys.dec = 1;
1984
            }
1985
        } else {
1986
            joystick.dec = gJoy_array[gKey_mapping[49] - 115];
1987
            if (joystick.dec > 0xFFFF) {
1988
                joystick.dec = 0xFFFF;
1989
            }
1990
        }
1991
        if (KeyIsDown(55) && c->gear >= 0) {
1992
            keys.change_down = 1;
1993
            c->just_changed_gear = 1;
1994
            if (keys.acc || joystick.acc > 32000) {
1995
                c->traction_control = 0;
1996
            } else if (c->gear > 1 && !c->keys.change_down) {
1997
                --c->gear;
1998
            }
1999
            if (gCountdown && !c->keys.change_down) {
2000
                JumpTheStart();
2001
            }
2002
        }
2003
        if (gCar_flying) {
2004
            if (KeyIsDown(13)) {
2005
                keys.up = 1;
2006
            }
2007
            if (KeyIsDown(11)) {
2008
                keys.down = 1;
2009
            }
2010
        }
2011
        if (KeyIsDown(58)) {
2012
            if (!gEntering_message) {
2013
                keys.horn = 1;
2014
            }
2015
        }
2016
        c->keys = keys;
2017
        c->joystick = joystick;
2018
    }
2019
}
2020
 
2021
// IDA: void __usercall PollCameraControls(tU32 pTime_difference@<EAX>)
2022
void PollCameraControls(tU32 pTime_difference) {
2023
    int flag;
2024
    int left;
2025
    int right;
2026
    int swirl_mode;
2027
    int up_and_down_mode;
2028
    int going_up;
2029
    static int last_swirl_mode = 0;
2030
    LOG_TRACE("(%d)", pTime_difference);
2031
 
2032
    flag = 0;
2033
    swirl_mode = gRace_finished && !gAction_replay_mode && (&gProgram_state.current_car == gCar_to_view || gCar_to_view->knackered);
2034
    up_and_down_mode = swirl_mode && !gCamera_has_collided;
2035
    going_up = gCamera_zoom > 1.0;
2036
    if (last_swirl_mode != swirl_mode) {
2037
        if (swirl_mode) {
2038
            SaveCameraPosition(0);
2039
        } else {
2040
            RestoreCameraPosition(0);
2041
        }
2042
        last_swirl_mode = swirl_mode;
2043
    }
2044
    if (!gMap_mode && !gProgram_state.cockpit_on && (!gAction_replay_mode || gAction_replay_camera_mode <= eAction_replay_standard)) {
2045
        if (KeyIsDown(31) || (up_and_down_mode && !going_up)) {
2046
            gCamera_zoom = (double)pTime_difference * TIME_CONV_THING / (double)(2 * swirl_mode + 1) + gCamera_zoom;
2047
            if (gCamera_zoom > 2.0f) {
2048
                gCamera_zoom = 2.0f;
2049
            }
2050
            if (up_and_down_mode && gCamera_zoom > 1.0f) {
2051
                gCamera_zoom = 1.0f;
2052
            }
2053
        }
2054
        if (KeyIsDown(30) || (up_and_down_mode && going_up)) {
2055
            gCamera_zoom = gCamera_zoom - (double)pTime_difference * TIME_CONV_THING / (double)(2 * swirl_mode + 1);
2056
            if (gCamera_zoom < 0.1) {
2057
                gCamera_zoom = (br_scalar) 0.1; // Pierre-Marie Baty -- added type cast
2058
                if (up_and_down_mode) {
2059
                    if (gCamera_zoom < 1.0f) {
2060
                        gCamera_zoom = 1.0f;
2061
                    }
2062
                }
2063
            }
2064
        }
2065
        if (swirl_mode && gProgram_state.current_car.speedo_speed < 0.001449275362318841) {
2066
            left = 1;
2067
            right = 0;
2068
        } else {
2069
            left = KeyIsDown(32);
2070
            right = KeyIsDown(33);
2071
        }
2072
 
2073
        if ((gCamera_sign ? left : right)) {
2074
            if (!gCamera_reset) {
2075
                gCamera_yaw += BrDegreeToAngle(pTime_difference * 0.05f);
2076
            }
2077
            flag = 1;
2078
        }
2079
        if ((gCamera_sign ? right : left)) {
2080
            if (!gCamera_reset) {
2081
                gCamera_yaw -= BrDegreeToAngle(pTime_difference * 0.05f);
2082
            }
2083
            if (flag) {
2084
                gCamera_yaw = 0;
2085
                gCamera_reset = 1;
2086
            }
2087
        } else if (!flag) {
2088
            gCamera_reset = 0;
2089
        }
2090
    }
2091
}
2092
 
2093
// IDA: void __usercall SetFlag2(int i@<EAX>)
2094
void SetFlag2(int i) {
2095
    LOG_TRACE("(%d)", i);
2096
 
2097
    gAllow_car_flying = 1;
2098
    ToggleFlying();
2099
    gAllow_car_flying = gCar_flying;
2100
}
2101
 
2102
// IDA: void __cdecl ToggleFlying()
2103
void ToggleFlying(void) {
2104
    LOG_TRACE("()");
2105
 
2106
    if (gAllow_car_flying && gNet_mode == eNet_mode_none) {
2107
        gCar_flying = !gCar_flying;
2108
        if (gCar_flying) {
2109
            NewTextHeadupSlot(4, 0, 500, -4, "We have lift off!!");
2110
        } else {
2111
            NewTextHeadupSlot(4, 0, 500, -4, "Back down to Earth");
2112
        }
2113
    } else {
2114
        gCar_flying = 0;
2115
    }
2116
}
2117
 
2118
// IDA: void __cdecl ToggleInvulnerability()
2119
void ToggleInvulnerability(void) {
2120
    LOG_TRACE("()");
2121
 
2122
    gProgram_state.current_car.invulnerable = !gProgram_state.current_car.invulnerable;
2123
    if (gProgram_state.current_car.invulnerable) {
2124
        NewTextHeadupSlot(4, 0, 1000, -4, GetMiscString(kMiscString_Invulnerable));
2125
    } else {
2126
        NewTextHeadupSlot(4, 0, 1000, -4, "Vulnerability returns!");
2127
    }
2128
}
2129
 
2130
// IDA: void __cdecl MoreTime()
2131
void MoreTime(void) {
2132
    LOG_TRACE("()");
2133
 
2134
    AwardTime(30);
2135
}
2136
 
2137
// IDA: void __cdecl MuchMoreTime()
2138
void MuchMoreTime(void) {
2139
    LOG_TRACE("()");
2140
 
2141
    AwardTime(300);
2142
}
2143
 
2144
// IDA: void __cdecl ToggleTimerFreeze()
2145
void ToggleTimerFreeze(void) {
2146
    LOG_TRACE("()");
2147
 
2148
    gFreeze_timer = !gFreeze_timer;
2149
    if (gFreeze_timer) {
2150
        NewTextHeadupSlot(4, 0, 1000, -4, GetMiscString(kMiscString_TimerFrozen));
2151
    } else {
2152
        NewTextHeadupSlot(4, 0, 1000, -4, "Timer thawed out");
2153
    }
2154
}
2155
 
2156
// IDA: void __cdecl EarnDosh()
2157
void EarnDosh(void) {
2158
    LOG_TRACE("()");
2159
 
2160
    EarnCredits(5000);
2161
}
2162
 
2163
// IDA: void __cdecl LoseDosh()
2164
void LoseDosh(void) {
2165
    LOG_TRACE("()");
2166
 
2167
    EarnCredits(-5000);
2168
}
2169
 
2170
// IDA: void __cdecl ToggleMap()
2171
void ToggleMap(void) {
2172
    static int old_indent;
2173
    static int was_in_cockpit;
2174
    LOG_TRACE("()");
2175
 
2176
    if (gMap_mode == 0) {
2177
        if (!gAction_replay_mode) {
2178
            if (gNet_mode != eNet_mode_none && gCurrent_net_game->type == eNet_game_type_foxy && gThis_net_player_index == gIt_or_fox) {
2179
                NewTextHeadupSlot(4, 0, 1000, -4, GetMiscString(kMiscString_THE_FOX_CANNOT_DO_THAT));
2180
            } else if (gNet_mode != eNet_mode_none && gCurrent_net_game->type == eNet_game_type_tag && gThis_net_player_index != gIt_or_fox) {
2181
                NewTextHeadupSlot(4, 0, 1000, -4, GetMiscString(kMiscString_ONLY_IT_CAN_DO_THAT));
2182
            } else {
2183
                old_indent = gRender_indent;
2184
                gRender_indent = 0;
2185
                was_in_cockpit = gProgram_state.cockpit_on;
2186
                if (gProgram_state.cockpit_on) {
2187
                    ToggleCockpit();
2188
                }
2189
                gMap_mode = PDGetTotalTime();
2190
            }
2191
        }
2192
    } else {
2193
        gMap_mode = 0;
2194
        gRender_indent = old_indent;
2195
        if (was_in_cockpit) {
2196
            ToggleCockpit();
2197
        }
2198
    }
2199
    AdjustRenderScreenSize();
2200
}
2201
 
2202
// IDA: int __cdecl HornBlowing()
2203
int HornBlowing(void) {
2204
    LOG_TRACE("()");
2205
 
2206
    return gProgram_state.current_car.keys.horn;
2207
}
2208
 
2209
// IDA: void __cdecl ToggleArrow()
2210
void ToggleArrow(void) {
2211
    static br_actor* old_actor;
2212
    LOG_TRACE("()");
2213
 
2214
    return;
2215
 
2216
    if (gArrow_mode) {
2217
        gProgram_state.current_car.car_model_actors[gProgram_state.current_car.principal_car_actor].actor = old_actor;
2218
        BrActorRemove(gArrow_actor);
2219
        BrActorAdd(gProgram_state.current_car.car_master_actor, old_actor);
2220
        gArrow_mode = 0;
2221
        if (gInfo_on) {
2222
            ToggleInfo();
2223
        }
2224
    } else {
2225
        old_actor = gProgram_state.current_car.car_model_actors[gProgram_state.current_car.principal_car_actor].actor;
2226
        BrActorRemove(old_actor);
2227
        BrActorAdd(gProgram_state.current_car.car_master_actor, gArrow_actor);
2228
        gProgram_state.current_car.car_model_actors[gProgram_state.current_car.principal_car_actor].actor = gArrow_actor;
2229
        gArrow_mode = 1;
2230
        if (!gInfo_on) {
2231
            ToggleInfo();
2232
        }
2233
    }
2234
}
2235
 
2236
// IDA: int __cdecl GetRecoverVoucherCount()
2237
int GetRecoverVoucherCount(void) {
2238
    LOG_TRACE("()");
2239
 
2240
    return gRecovery_voucher_count;
2241
}
2242
 
2243
// IDA: void __usercall AddVouchers(int pCount@<EAX>)
2244
void AddVouchers(int pCount) {
2245
    LOG_TRACE("(%d)", pCount);
2246
 
2247
    gRecovery_voucher_count += pCount;
2248
}
2249
 
2250
// IDA: void __cdecl ResetRecoveryVouchers()
2251
void ResetRecoveryVouchers(void) {
2252
    LOG_TRACE("()");
2253
 
2254
    gRecovery_voucher_count = 0;
2255
}
2256
 
2257
// IDA: void __cdecl CycleCarTexturingLevel()
2258
void CycleCarTexturingLevel(void) {
2259
    tCar_texturing_level new_level;
2260
    LOG_TRACE("()");
2261
 
2262
    new_level = (GetCarTexturingLevel() + 1) % eCTL_count;
2263
    SetCarTexturingLevel(new_level);
2264
    switch (new_level) {
2265
    case eCTL_none:
2266
        NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(kMiscString_NoCarTextures));
2267
        break;
2268
    case eCTL_transparent:
2269
        NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(kMiscString_TransparentCarTexturesOnly));
2270
        break;
2271
    case eCTL_full:
2272
        NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(kMiscString_FullCarTextures));
2273
        break;
2274
    case eCTL_count:
2275
        break;
2276
    }
2277
}
2278
 
2279
// IDA: void __cdecl CycleWallTexturingLevel()
2280
void CycleWallTexturingLevel(void) {
2281
    tWall_texturing_level new_level;
2282
    LOG_TRACE("()");
2283
 
2284
    new_level = (GetWallTexturingLevel() + 1) % eWTL_count;
2285
    ReallySetWallTexturingLevel(new_level);
2286
    SetWallTexturingLevel(new_level);
2287
    switch (new_level) {
2288
    case eWTL_none:
2289
        NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(kMiscString_NoWallTextures));
2290
        break;
2291
    case eWTL_linear:
2292
        NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(kMiscString_LinearWallTextures));
2293
        break;
2294
    case eWTL_full:
2295
        NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(kMiscString_BestWallTextures));
2296
        break;
2297
    case eWTL_count:
2298
        break;
2299
    }
2300
}
2301
 
2302
// IDA: void __cdecl CycleRoadTexturingLevel()
2303
void CycleRoadTexturingLevel(void) {
2304
    tRoad_texturing_level new_level;
2305
    LOG_TRACE("()");
2306
 
2307
    new_level = (GetRoadTexturingLevel() + 1) % 3;
2308
    ReallySetRoadTexturingLevel(new_level);
2309
    SetRoadTexturingLevel(new_level);
2310
    if (new_level == eRTL_none) {
2311
        NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(kMiscString_NoRoadTextures));
2312
    } else if (new_level == eRTL_full) {
2313
        NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(kMiscString_RoadTextures));
2314
    }
2315
}
2316
 
2317
// IDA: void __cdecl CycleYonFactor()
2318
void CycleYonFactor(void) {
2319
    br_scalar new_factor;
2320
    //char factor_str[5]; // Pierre-Marie Baty -- unused variable
2321
    LOG_TRACE("()");
2322
 
2323
    new_factor = GetYonFactor() / 2.f;
2324
    if (new_factor < .1f) {
2325
        new_factor = 1.f;
2326
    }
2327
    SetYonFactor(new_factor);
2328
    if (new_factor > .75f) {
2329
        NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(kMiscString_TrackAppearsVeryQuickly));
2330
    } else if (new_factor > .375f) {
2331
        NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(kMiscString_TrackAppearsQuiteQuickly));
2332
    } else if (new_factor > .187f) {
2333
        NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(kMiscString_TrackQppearsQuiteLate));
2334
    } else {
2335
        NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(kMiscString_TrackAppearsVeryLate));
2336
    }
2337
}
2338
 
2339
// IDA: void __usercall SetSoundDetailLevel(int pLevel@<EAX>)
2340
void SetSoundDetailLevel(int pLevel) {
2341
    LOG_TRACE("(%d)", pLevel);
2342
 
2343
    gSound_detail_level = pLevel;
2344
}
2345
 
2346
// IDA: void __usercall ReallySetSoundDetailLevel(int pLevel@<EAX>)
2347
void ReallySetSoundDetailLevel(int pLevel) {
2348
    LOG_TRACE("(%d)", pLevel);
2349
 
2350
    DRS3StopAllOutletSounds();
2351
    DisposeSoundSources();
2352
    gSound_detail_level = pLevel;
2353
    InitSound();
2354
    InitSoundSources();
2355
}
2356
 
2357
// IDA: int __cdecl GetSoundDetailLevel()
2358
int GetSoundDetailLevel(void) {
2359
    LOG_TRACE("()");
2360
 
2361
    return gSound_detail_level;
2362
}
2363
 
2364
// IDA: void __cdecl CycleSoundDetailLevel()
2365
void CycleSoundDetailLevel(void) {
2366
    int new_level;
2367
    LOG_TRACE("()");
2368
 
2369
    new_level = (gSound_detail_level + 1) % 3;
2370
    ReallySetSoundDetailLevel(new_level);
2371
    SetSoundDetailLevel(new_level);
2372
    switch (new_level) {
2373
    case 0:
2374
        NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(kMiscString_FewestSounds));
2375
        break;
2376
    case 1:
2377
        NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(kMiscString_PartialSound));
2378
        break;
2379
    case 2:
2380
        NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(kMiscString_AllSounds));
2381
        break;
2382
    }
2383
}
2384
 
2385
// IDA: void __cdecl CycleCarSimplificationLevel()
2386
void CycleCarSimplificationLevel(void) {
2387
    char* src;
2388
    char* dst;
2389
    LOG_TRACE("()");
2390
 
2391
    gCar_simplification_level = (gCar_simplification_level + 1) % 5;
2392
    src = GetMiscString(kMiscString_CarSimplificationLevel_D);
2393
    dst = BrMemAllocate(strlen(src), kMem_simp_level);
2394
    sprintf(dst, src, gCar_simplification_level);
2395
    NewTextHeadupSlot(4, 0, 2000, -4, dst);
2396
    BrMemFree(dst);
2397
}
2398
 
2399
// IDA: void __cdecl ToggleAccessoryRendering()
2400
void ToggleAccessoryRendering(void) {
2401
    int on;
2402
    LOG_TRACE("()");
2403
 
2404
    if (gNet_mode == eNet_mode_none) {
2405
        on = !GetAccessoryRendering();
2406
        SetAccessoryRendering(on);
2407
        if (on) {
2408
            NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(kMiscString_AccessoriesOn));
2409
        } else {
2410
            NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(kMiscString_AccessoriesOff));
2411
        }
2412
    } else {
2413
        NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(kMiscString_NetGamesAlwaysAccessorized));
2414
    }
2415
}
2416
 
2417
// IDA: void __cdecl ToggleSmoke()
2418
void ToggleSmoke(void) {
2419
    int on;
2420
    LOG_TRACE("()");
2421
 
2422
    on = !GetSmokeOn();
2423
    ReallySetSmokeOn(on);
2424
    SetSmokeOn(on);
2425
    if (on) {
2426
        NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(kMiscString_SmokeOn));
2427
    } else {
2428
        NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(kMiscString_SmokeOff));
2429
    }
2430
}
2431
 
2432
// IDA: void __usercall DrawSomeText2(tDR_font *pFont@<EAX>)
2433
void DrawSomeText2(tDR_font* pFont) {
2434
    int y;
2435
    int i;
2436
    char* txt[15] = {
2437
        "Cops    Show all racers on map    Show peds on map",
2438
        "Random pick-up generation    Pick-up respawn",
2439
        "Open game    Closed game",
2440
        "Grid start    Random start",
2441
        "Random races    Sequential races",
2442
        "Include opponents' cars in car choices",
2443
        "Choose cars    manually    randomly    include Big APC",
2444
        "Starting credits    0    2000    5000    10000    20000",
2445
        "Driven to Destruction",
2446
        "Car Crusher",
2447
        "Carnage Accumulator",
2448
        "Checkpoint Stampede",
2449
        "Sudden Death",
2450
        "Terminal Tag",
2451
        "Fox 'n' Hounds"
2452
    };
2453
 
2454
    ClearEntireScreen();
2455
    y = 0;
2456
    for (i = 0; i < 15; i++) {
2457
        TransDRPixelmapText(gBack_screen, 0, y, pFont, txt[i], 320);
2458
        y += pFont->height + 1;
2459
    }
2460
 
2461
    PDScreenBufferSwap(0);
2462
    PrintScreen();
2463
}
2464
 
2465
// IDA: void __cdecl DrawSomeText()
2466
void DrawSomeText(void) {
11 pmbaty 2467
    DrawSomeText2(&gFonts[kFont_ORANGHED]);
2468
    DrawSomeText2(&gFonts[kFont_BLUEHEAD]);
2469
    DrawSomeText2(&gFonts[kFont_GREENHED]);
2470
    DrawSomeText2(&gFonts[kFont_MEDIUMHD]);
2471
    DrawSomeText2(&gFonts[kFont_NEWHITE]);
2472
    DrawSomeText2(&gFonts[kFont_NEWRED]);
2473
    DrawSomeText2(&gFonts[kFont_NEWBIGGR]);
1 pmbaty 2474
}
2475
 
2476
// IDA: void __cdecl SaySorryYouLittleBastard()
2477
void SaySorryYouLittleBastard(void) {
2478
    LOG_TRACE("()");
2479
    NOT_IMPLEMENTED();
2480
}
2481
 
2482
// IDA: void __cdecl UserSendMessage()
2483
void UserSendMessage(void) {
2484
    LOG_TRACE("()");
2485
 
2486
    if (gNet_mode != eNet_mode_none && gCurrent_net_game->options.enable_text_messages) {
2487
        gEntering_message = 1;
2488
    }
2489
}
2490
 
2491
// IDA: void __cdecl EnterUserMessage()
2492
void EnterUserMessage(void) {
18 pmbaty 2493
    static int last_key;
2494
    static int about_to_die;
2495
    static tU32 next_time;
2496
    char* the_message;
2497
    char* p;
2498
    int len;
2499
    int the_key;
2500
    int abuse_num;
1 pmbaty 2501
    LOG_TRACE("()");
18 pmbaty 2502
 
2503
    if (!gEntering_message) {
2504
        return;
2505
    }
2506
    if (gNet_mode == eNet_mode_none) {
2507
        return;
2508
    }
2509
    if (!gCurrent_net_game->options.enable_text_messages) {
2510
        return;
2511
    }
2512
    the_key = PDAnyKeyDown();
2513
    if (gEntering_message == 1) {
2514
        if (the_key != -1) {
2515
            return;
2516
        }
2517
        gEntering_message = 2;
2518
    }
2519
    if (about_to_die) {
2520
        if (the_key != -1) {
2521
            return;
2522
        }
2523
        gEntering_message = 0;
2524
        about_to_die = 0;
2525
        return;
2526
    }
2527
    if (the_key == last_key) {
2528
        if (next_time < PDGetTotalTime()) {
2529
            next_time += 100;
2530
        } else {
2531
            the_key = -1;
2532
        }
2533
    } else {
2534
        last_key = the_key;
2535
        next_time = PDGetTotalTime() + 500;
2536
    }
2537
    switch (the_key) {
2538
    case -1:
2539
    case KEY_SHIFT_ANY:
2540
        break;
2541
    case KEY_CTRL_ANY:
2542
    case KEY_CTRL_ANY_2:
2543
    case KEY_TAB:
2544
    case KEY_ESCAPE:
2545
        about_to_die = 1;
2546
        break;
2547
    case KEY_BACKSPACE:
2548
    case KEY_DELETE:
2549
    case KEY_LEFT:
2550
        len = strlen(&gString[20]);
2551
        if (len > 0) {
2552
            gString[20 + len - 1] = '\0';
2553
        }
2554
        break;
2555
    case KEY_RETURN:
2556
    case KEY_KP_ENTER:
2557
        len = strlen(gNet_players[gThis_net_player_index].player_name);
2558
        if (len <= 18) {
2559
            the_message = gString + 18 - len;
2560
            strcpy(the_message, gNet_players[gThis_net_player_index].player_name);
2561
            the_message[len + 0] = ':';
2562
            the_message[len + 1] = ' ';
2563
            gString[COUNT_OF(gString) - 1] = '\0';
2564
            NetSendHeadupToAllPlayers(the_message);
2565
            gString[20] = '\0';
2566
            NewTextHeadupSlot(4, 0, 1000, -4, GetMiscString(kMiscString_MESSAGE_SENT));
2567
            about_to_die = 1;
2568
        }
2569
        break;
2570
    default:
2571
        if (gKey_mapping[KEYMAP_SEND_MESSAGE] == the_key) {
2572
            about_to_die = 1;
2573
        } else if (the_key <= KEY_KP_NUMLOCK || the_key >= KEY_SPACE) {
2574
            len = strlen(&gString[20]);
2575
            if (len < 64 - 1) {
2576
                gString[20 + len] = PDGetASCIIFromKey(the_key);
2577
                if (gString[20 + len] < gFonts[4].offset || gString[20 + len] >= gFonts[4].offset + gFonts[4].num_entries) {
2578
                    gString[20 + len] = '\0';
2579
                }
2580
                gString[20 + len + 1] = '\0';
2581
            }
2582
        } else if (the_key < KEY_KP_0 || the_key >  KEY_KP_9) {
2583
            gEntering_message = 0;
2584
        } else {
2585
            if (the_key == KEY_KP_0) {
2586
                abuse_num = 9;
2587
            } else {
2588
                abuse_num = the_key - KEY_KP_1;
2589
            }
2590
            if (gAbuse_text[abuse_num] != NULL) {
2591
                strcpy(&gString[20], gAbuse_text[abuse_num]);
2592
            }
2593
        }
2594
    }
1 pmbaty 2595
}
2596
 
2597
// IDA: void __cdecl DisplayUserMessage()
2598
void DisplayUserMessage(void) {
18 pmbaty 2599
    char* the_message;
2600
    int len;
2601
    tDR_font* font;
1 pmbaty 2602
    LOG_TRACE("()");
18 pmbaty 2603
 
2604
    font = &gFonts[FONT_NEWHITE];
2605
    the_message = &gString[20];
2606
    if (!gEntering_message || gNet_mode == eNet_mode_none) {
2607
        return;
2608
    }
2609
 
2610
    len = strlen(the_message);
2611
    if (len < 63 && (PDGetTotalTime() & 512) != 0) {
2612
        the_message[len] = '_';
2613
        the_message[len + 1] = '\0';
2614
    }
2615
    DimRectangle(gBack_screen,
2616
        15 * gBack_screen->width / 100,
2617
        gCurrent_graf_data->net_message_enter_y - font->height,
2618
        85 * gBack_screen->width / 100,
2619
        gCurrent_graf_data->net_message_enter_y + 6 * font->height,
2620
        1);
2621
 
2622
    TransDRPixelmapText(gBack_screen, 20 * gBack_screen->width / 100, gCurrent_graf_data->net_message_enter_y, font, GetMiscString(kMiscString_ENTER_MESSAGE), 100);
2623
    OoerrIveGotTextInMeBoxMissus(
2624
        FONT_NEWHITE,
2625
        the_message,
2626
        gBack_screen,
2627
        20 * gBack_screen->width / 100,
2628
        gCurrent_graf_data->net_message_enter_y + 2 * font->height,
2629
        80 * gBack_screen->width / 100,
2630
        gCurrent_graf_data->net_message_enter_y + 6 * font->height,
2631
        0);
2632
    the_message[len] = 0;
1 pmbaty 2633
}
2634
 
2635
// IDA: void __cdecl InitAbuseomatic()
2636
void InitAbuseomatic(void) {
2637
    char path[256];
2638
    char s[256];
2639
    FILE* f;
2640
    int i;
2641
    int len;
2642
    LOG_TRACE("()");
2643
 
2644
    gString[20] = '\0';
2645
    PDBuildAppPath(path);
2646
    strcat(path, "ABUSE.TXT");
2647
    for (i = 0; i < COUNT_OF(gAbuse_text); i++) {
2648
        gAbuse_text[i] = NULL;
2649
    }
2650
    f = fopen(path, "rt");
2651
    if (f == NULL) {
2652
        return;
2653
    }
2654
    for (i = 0; i < COUNT_OF(gAbuse_text); i++) {
2655
        if (fgets(s, COUNT_OF(s) - 1, f) == NULL) {
2656
            break;
2657
        }
2658
        len = strlen(s);
2659
        if (len > 63) {
2660
            s[63] = '\0';
2661
        }
2662
        len = strlen(s);
2663
        while (len != 0 && s[len - 1] < ' ') {
2664
            s[len - 1] = '\0';
2665
            len--;
2666
        }
2667
        gAbuse_text[i] = BrMemAllocate(strlen(s) + 1, kMem_abuse_text);
2668
        strcpy(gAbuse_text[i], s);
2669
    }
2670
    fclose(f);
2671
}
2672
 
2673
// IDA: void __cdecl DisposeAbuseomatic()
2674
void DisposeAbuseomatic(void) {
2675
    int i;
2676
    LOG_TRACE("()");
2677
 
2678
    for (i = 0; i < COUNT_OF(gAbuse_text); i++) {
2679
        if (gAbuse_text[i] != NULL) {
2680
            BrMemFree(gAbuse_text[i]);
2681
        }
2682
    }
2683
}