Subversion Repositories Games.Carmageddon

Rev

Rev 20 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
// car.c + stuff.c
2
 
3
#include "car.h"
20 pmbaty 4
#include "brender/brender.h"
1 pmbaty 5
#include "brucetrk.h"
6
#include "car.h"
7
#include "constants.h"
8
#include "controls.h"
9
#include "crush.h"
10
#include "displays.h"
11
#include "finteray.h"
12
#include "globvars.h"
13
#include "globvrkm.h"
14
#include "globvrme.h"
15
#include "globvrpb.h"
16
#include "graphics.h"
17
#include "harness/config.h"
18
#include "harness/trace.h"
19
#include "netgame.h"
20
#include "network.h"
21
#include "oil.h"
22
#include "opponent.h"
23
#include "pd/sys.h"
24
#include "pedestrn.h"
25
#include "piping.h"
26
#include "pratcam.h"
27
#include "raycast.h"
28
#include "replay.h"
29
#include "skidmark.h"
30
#include "sound.h"
31
#include "spark.h"
32
#include "trig.h"
33
#include "utility.h"
34
#include "world.h"
35
#include <math.h>
36
#include <stdlib.h>
37
 
38
int gDoing_physics = 0;
39
br_scalar gDt = 0.f;
40
// suffix added to avoid duplicate symbol
41
int gCollision_detection_on__car = 1;
42
// suffix added to avoid duplicate symbol
43
br_vector3 gGround_normal__car = { { 0.0f, 1.0f, 0.0f } };
44
// suffix added to avoid duplicate symbol
45
void (*ControlCar[6])(tCar_spec*, br_scalar) = {
46
    &ControlCar1,
47
    &ControlCar2,
48
    &ControlCar3,
49
    &ControlCar4,
50
    &ControlCar5,
51
    NULL,
52
};
53
int gControl__car = 3;      // suffix added to avoid duplicate symbol
54
int gFace_num__car = 1;     // suffix added to avoid duplicate symbol
55
br_angle gOld_yaw__car = 0; // suffix added to avoid duplicate symbol
56
br_angle gOld_zoom = 0;
57
br_vector3 gCamera_pos_before_collide = { { 0 } };
58
int gMetal_crunch_sound_id__car[5] = {
59
    // suffix added to avoid duplicate symbol
60
    5000,
61
    5001,
62
    5002,
63
    5003,
64
    5004,
65
};
66
int gMetal_scrape_sound_id__car[3] = {
67
    // suffix added to avoid duplicate symbol
68
    5010,
69
    5011,
70
    5012,
71
};
72
int gCar_car_collisions = 1;
73
int gFreeze_mechanics = 0;
74
tU32 gLast_cunning_stunt = 0;
75
tU32 gWild_start = 0;
76
tU32 gQuite_wild_start = 0;
77
tU32 gQuite_wild_end = 0;
78
tU32 gOn_me_wheels_start = 0;
79
int gWoz_upside_down_at_all = 0;
80
tS3_sound_tag gSkid_tag[2] = { 0, 0 };
81
tCar_spec* gLast_car_to_skid[2] = { NULL, NULL };
82
int gEliminate_faces = 0;
83
br_vector3 gZero_v__car = { { 0 } }; // suffix added to avoid duplicate symbol
84
tU32 gSwitch_time = 0;
85
tSave_camera gSave_camera[2];
86
tU32 gLast_mechanics_time;
87
int gOpponent_viewing_mode;
88
int gNet_player_to_view_index = -1;
89
int gDouble_pling_water = 0;
90
int gStop_opponents_moving = 0;
91
float gDefensive_powerup_factor[6] = { 1.0f, 0.825f, 0.65f, 0.475f, 0.3f, 0.01f };
92
float gOffensive_powerup_factor[6] = { 1.0f, 1.5f, 2.0f, 3.0f, 5.0f, 10.0f };
93
float gEngine_powerup_factor[6] = { 1.3f, 1.9f, 2.5f, 3.2f, 4.0f, 10.0f };
94
br_angle gPanning_camera_angle;
95
br_scalar gPanning_camera_height;
96
int gFace_count;
97
float gCar_simplification_factor[2][5] = {
98
    { 10.0f, 3.0f, 1.5f, 0.75f, 0.0f },
99
    { 10.0f, 5.0f, 2.5f, 1.5f, 0.0f }
100
};
101
int gCar_simplification_level = 0;
102
int gNum_active_non_cars = 0;
103
int gCamera_has_collided = 0;
104
tFace_ref gFace_list__car[150]; // suffix added to avoid duplicate symbol
105
tNon_car_spec* gActive_non_car_list[50];
106
int gOver_shoot;
107
br_scalar gMin_world_y;
108
br_scalar gAccel;
109
br_vector3 gAverage_grid_position;
110
br_actor* gPed_actor;
111
int gCollision_count;
112
int gCamera_frozen;
113
int gMaterial_index;
114
int gInTheSea;
115
int gCamera_mode;
116
br_scalar gOur_yaw__car;            // suffix added to avoid duplicate symbol
117
br_scalar gGravity__car;            // suffix added to avoid duplicate symbol
118
br_vector3 gNew_ground_normal__car; // suffix added to avoid duplicate symbol
119
char gNon_car_spec_list[100];
120
tU32 gMechanics_time_sync;
121
int gNum_cars_and_non_cars;
122
 
123
// IDA: void __usercall DamageUnit(tCar_spec *pCar@<EAX>, int pUnit_type@<EDX>, int pDamage_amount@<EBX>)
124
void DamageUnit(tCar_spec* pCar, int pUnit_type, int pDamage_amount) {
125
    tDamage_unit* the_damage;
126
    LOG_TRACE("(%p, %d, %d)", pCar, pUnit_type, pDamage_amount);
127
 
128
    if (pDamage_amount > 0) {
129
        the_damage = &pCar->damage_units[pUnit_type];
130
        the_damage->damage_level += pDamage_amount;
131
        if (the_damage->damage_level >= 100) {
132
            the_damage->damage_level = 99;
133
        }
134
    }
135
}
136
 
137
// IDA: void __usercall DamageUnitWithSmoke(tCar_spec *pCar@<EAX>, int pUnit_type@<EDX>, int pDamage_amount@<EBX>)
138
void DamageUnitWithSmoke(tCar_spec* pCar, int pUnit_type, int pDamage_amount) {
139
    LOG_TRACE("(%p, %d, %d)", pCar, pUnit_type, pDamage_amount);
140
 
141
    DamageUnit(pCar, pUnit_type, pDamage_amount);
142
    SortOutSmoke(pCar);
143
}
144
 
145
// IDA: void __usercall DamageEngine(int pDamage_amount@<EAX>)
146
void DamageEngine(int pDamage_amount) {
147
    LOG_TRACE("(%d)", pDamage_amount);
148
 
149
    DamageUnitWithSmoke(&gProgram_state.current_car, eDamage_engine, pDamage_amount);
150
}
151
 
152
// IDA: void __usercall DamageTrans(int pDamage_amount@<EAX>)
153
void DamageTrans(int pDamage_amount) {
154
    LOG_TRACE("(%d)", pDamage_amount);
155
 
156
    DamageUnitWithSmoke(&gProgram_state.current_car, eDamage_transmission, pDamage_amount);
157
}
158
 
159
// IDA: void __usercall DamageSteering(int pDamage_amount@<EAX>)
160
void DamageSteering(int pDamage_amount) {
161
    LOG_TRACE("(%d)", pDamage_amount);
162
 
163
    DamageUnitWithSmoke(&gProgram_state.current_car, eDamage_steering, pDamage_amount);
164
}
165
 
166
// IDA: void __usercall DamageLFWheel(int pDamage_amount@<EAX>)
167
void DamageLFWheel(int pDamage_amount) {
168
    LOG_TRACE("(%d)", pDamage_amount);
169
 
170
    DamageUnitWithSmoke(&gProgram_state.current_car, eDamage_lf_wheel, pDamage_amount);
171
}
172
 
173
// IDA: void __usercall DamageLFBrake(int pDamage_amount@<EAX>)
174
void DamageLFBrake(int pDamage_amount) {
175
    LOG_TRACE("(%d)", pDamage_amount);
176
 
177
    DamageUnitWithSmoke(&gProgram_state.current_car, eDamage_lf_brake, pDamage_amount);
178
}
179
 
180
// IDA: void __usercall DamageLRBrake(int pDamage_amount@<EAX>)
181
void DamageLRBrake(int pDamage_amount) {
182
    LOG_TRACE("(%d)", pDamage_amount);
183
 
184
    DamageUnitWithSmoke(&gProgram_state.current_car, eDamage_lr_brake, pDamage_amount);
185
}
186
 
187
// IDA: void __usercall DamageLRWheel(int pDamage_amount@<EAX>)
188
void DamageLRWheel(int pDamage_amount) {
189
    LOG_TRACE("(%d)", pDamage_amount);
190
 
191
    DamageUnitWithSmoke(&gProgram_state.current_car, eDamage_lr_wheel, pDamage_amount);
192
}
193
 
194
// IDA: void __usercall DamageRFWheel(int pDamage_amount@<EAX>)
195
void DamageRFWheel(int pDamage_amount) {
196
    LOG_TRACE("(%d)", pDamage_amount);
197
 
198
    DamageUnitWithSmoke(&gProgram_state.current_car, eDamage_rf_wheel, pDamage_amount);
199
}
200
 
201
// IDA: void __usercall DamageRFBrake(int pDamage_amount@<EAX>)
202
void DamageRFBrake(int pDamage_amount) {
203
    LOG_TRACE("(%d)", pDamage_amount);
204
 
205
    DamageUnitWithSmoke(&gProgram_state.current_car, eDamage_rf_brake, pDamage_amount);
206
}
207
 
208
// IDA: void __usercall DamageRRBrake(int pDamage_amount@<EAX>)
209
void DamageRRBrake(int pDamage_amount) {
210
    LOG_TRACE("(%d)", pDamage_amount);
211
 
212
    DamageUnitWithSmoke(&gProgram_state.current_car, eDamage_rr_brake, pDamage_amount);
213
}
214
 
215
// IDA: void __usercall DamageRRWheel(int pDamage_amount@<EAX>)
216
void DamageRRWheel(int pDamage_amount) {
217
    LOG_TRACE("(%d)", pDamage_amount);
218
 
219
    DamageUnitWithSmoke(&gProgram_state.current_car, eDamage_rr_wheel, pDamage_amount);
220
}
221
 
222
// IDA: void __usercall CalculatePlaneNormal(br_vector3 *pP1@<EAX>, br_vector3 *pP2@<EDX>, br_vector3 *pP3@<EBX>, br_vector3 *pNormal@<ECX>)
223
void CalculatePlaneNormal(br_vector3* pP1, br_vector3* pP2, br_vector3* pP3, br_vector3* pNormal) {
224
    //br_vector3 p0; // Pierre-Marie Baty -- unused variable
225
    //br_vector3 p1; // Pierre-Marie Baty -- unused variable
226
    //br_vector3 cross_product; // Pierre-Marie Baty -- unused variable
227
    //br_vector3 temp_vector; // Pierre-Marie Baty -- unused variable
228
    LOG_TRACE("(%p, %p, %p, %p)", pP1, pP2, pP3, pNormal);
229
    NOT_IMPLEMENTED();
230
}
231
 
232
// IDA: void __usercall CalculateGroundNormal(br_model *pThe_model@<EAX>, int pFace_index@<EDX>)
233
void CalculateGroundNormal(br_model* pThe_model, int pFace_index) {
234
    LOG_TRACE("(%p, %d)", pThe_model, pFace_index);
235
    NOT_IMPLEMENTED();
236
}
237
 
238
// IDA: void __cdecl ChangeYCoordinate(br_scalar pNew_y, tU32 pTime_taken, br_model *pThe_model, int pFace_index)
239
void ChangeYCoordinate(br_scalar pNew_y, tU32 pTime_taken, br_model* pThe_model, int pFace_index) {
240
    //br_scalar y_change; // Pierre-Marie Baty -- unused variable
241
    //br_transform new_transform; // Pierre-Marie Baty -- unused variable
242
    //br_vector3 side_window; // Pierre-Marie Baty -- unused variable
243
    LOG_TRACE("(%f, %d, %p, %d)", pNew_y, pTime_taken, pThe_model, pFace_index);
244
    NOT_IMPLEMENTED();
245
}
246
 
247
// IDA: void __usercall SwitchCarActor(tCar_spec *pCar_spec@<EAX>, int pModel_index@<EDX>)
248
void SwitchCarActor(tCar_spec* pCar_spec, int pModel_index) {
249
    int i;
250
    LOG_TRACE("(%p, %d)", pCar_spec, pModel_index);
251
 
252
    for (i = 0; i < pCar_spec->car_actor_count; i++) {
253
        if (i == pModel_index) {
254
            pCar_spec->car_model_actors[i].actor->render_style = BR_RSTYLE_FACES;
255
        } else {
256
            pCar_spec->car_model_actors[i].actor->render_style = BR_RSTYLE_NONE;
257
        }
258
    }
259
    pCar_spec->current_car_actor = pModel_index;
260
}
261
 
262
// IDA: void __usercall InitialiseCar2(tCar_spec *pCar@<EAX>, int pClear_disabled_flag@<EDX>)
263
void InitialiseCar2(tCar_spec* pCar, int pClear_disabled_flag) {
264
    int index;
265
    int j;
266
    //int cat; // Pierre-Marie Baty -- unused variable
267
    //int car_count; // Pierre-Marie Baty -- unused variable
268
    br_actor* car_actor;
269
    //br_angle initial_yaw; // Pierre-Marie Baty -- unused variable
270
    //br_scalar nearest_y_above; // Pierre-Marie Baty -- unused variable
271
    //br_scalar nearest_y_below; // Pierre-Marie Baty -- unused variable
272
    //br_scalar speed; // Pierre-Marie Baty -- unused variable
273
    //int below_face_index; // Pierre-Marie Baty -- unused variable
274
    //int above_face_index; // Pierre-Marie Baty -- unused variable
275
    //br_model* below_model; // Pierre-Marie Baty -- unused variable
276
    //br_model* above_model; // Pierre-Marie Baty -- unused variable
277
    //br_vector3 grid_offset; // Pierre-Marie Baty -- unused variable
278
    //br_matrix34 initial_yaw_matrix; // Pierre-Marie Baty -- unused variable
279
    br_matrix34 safe_position;
280
    LOG_TRACE("(%p, %d)", pCar, pClear_disabled_flag);
281
 
282
    PossibleService();
283
    if (pCar->disabled && pClear_disabled_flag) {
284
        EnableCar(pCar);
285
    }
286
    car_actor = pCar->car_master_actor;
287
    InitCarSkidStuff(pCar);
288
    if (pCar->current_car_actor >= 0) {
289
        pCar->car_model_actors[pCar->current_car_actor].actor->render_style = BR_RSTYLE_NONE;
290
    }
291
    SwitchCarActor(pCar, pCar->current_car_actor);
292
    if (strcmp(pCar->name, "STELLA.TXT") == 0) {
293
        pCar->proxy_ray_distance = 6.0f;
294
    } else {
295
        pCar->proxy_ray_distance = 0.0f;
296
    }
297
    pCar->last_special_volume = NULL;
298
    pCar->auto_special_volume = NULL;
299
    pCar->num_smoke_columns = 0;
300
    pCar->who_last_hit_me = NULL;
301
    pCar->screen_material_source = NULL;
302
    if (pCar->screen_material != NULL) {
303
        pCar->screen_material->colour_map = NULL;
304
        pCar->screen_material->index_shade = gRender_shade_table;
305
        BrMaterialUpdate(pCar->screen_material, BR_MATU_ALL);
306
    }
307
    if (pCar->driver == eDriver_local_human) {
308
        ResetRecoveryVouchers();
309
    }
310
    BrVector3SetFloat(&pCar->v, 0.0f, 0.0f, 0.0f);
311
    BrVector3SetFloat(&pCar->omega, 0.0f, 0.0f, 0.0f);
312
    pCar->curvature = 0.0f;
313
    BrMatrix34Copy(&safe_position, &car_actor->t.t.mat);
314
    if (safe_position.m[3][0] > 500.0f) {
315
        safe_position.m[3][0] -= 1000.0f;
316
        safe_position.m[3][1] -= 1000.0f;
317
        safe_position.m[3][2] -= 1000.0f;
318
    }
319
    BrMatrix34Copy(&pCar->old_frame_mat, &safe_position);
320
    BrMatrix34Copy(&pCar->oldmat, &safe_position);
321
    BrVector3Scale((br_vector3*)pCar->oldmat.m[3], (br_vector3*)pCar->oldmat.m[3], WORLD_SCALE);
322
    BrMatrix34ApplyP(&pCar->pos, &pCar->cmpos, &pCar->oldmat);
323
    BrVector3InvScale(&pCar->pos, &pCar->pos, WORLD_SCALE);
324
    for (j = 0; j < COUNT_OF(pCar->oldd); j++) {
325
        pCar->oldd[j] = pCar->ride_height;
326
    }
327
    pCar->gear = 0;
328
    pCar->revs = 0.f;
329
    pCar->traction_control = 1;
330
    BrVector3Negate(&pCar->direction, (br_vector3*)car_actor->t.t.mat.m[2]);
331
    for (j = 0; j < COUNT_OF(pCar->last_safe_positions); j++) {
332
        BrMatrix34Copy(&pCar->last_safe_positions[j], &safe_position);
333
    }
334
    pCar->message.type = 0;
335
    pCar->message.time = 0;
336
    pCar->dt = -1.f;
337
    pCar->last_car_car_collision = 1;
338
    pCar->time_to_recover = 0;
339
    pCar->repair_time = 0;
340
 
341
    switch (pCar->driver) {
342
 
343
    case eDriver_oppo:
344
        index = 0;
345
        for (j = 0; j < gCurrent_race.number_of_racers; j++) {
346
            if (gCurrent_race.opponent_list[j].car_spec->driver == eDriver_oppo) {
347
                if (gCurrent_race.opponent_list[j].car_spec == pCar) {
348
                    pCar->car_ID = index + 512;
349
                }
350
                index++;
351
            }
352
        }
353
        break;
354
 
355
    case eDriver_net_human:
356
        index = 0;
357
        for (j = 0; j < gCurrent_race.number_of_racers; j++) {
358
            if (gCurrent_race.opponent_list[j].car_spec
359
                && gCurrent_race.opponent_list[j].car_spec->driver == eDriver_net_human) {
360
                if (gCurrent_race.opponent_list[j].car_spec == pCar) {
361
                    pCar->car_ID = index + 256;
362
                }
363
                index++;
364
            }
365
        }
366
        break;
367
 
368
    case eDriver_local_human:
369
        pCar->car_ID = 0;
370
        break;
371
 
372
    default:
373
        LOG_WARN("Case %d not handled", pCar->driver);
374
        break;
375
    }
376
    PossibleService();
377
    pCar->box_face_ref = gFace_num__car - 2;
378
    pCar->doing_nothing_flag = 0;
379
    pCar->end_steering_damage_effect = 0;
380
    pCar->end_trans_damage_effect = 0;
381
    pCar->wheel_dam_offset[0] = 0.f;
382
    pCar->wheel_dam_offset[1] = 0.f;
383
    pCar->wheel_dam_offset[2] = 0.f;
384
    pCar->wheel_dam_offset[3] = 0.f;
385
    pCar->shadow_intersection_flags = 0;
386
    pCar->underwater_ability = 0;
387
    pCar->invulnerable = 0;
388
    pCar->wall_climber_mode = 0;
389
    pCar->grip_multiplier = 1.f;
390
    pCar->damage_multiplier = 1.f;
391
    pCar->collision_mass_multiplier = 1.f;
392
    pCar->engine_power_multiplier = 1.f;
393
    pCar->bounce_rate = 0.f;
394
    pCar->bounce_amount = 0.f;
395
    pCar->knackered = 0;
396
    TotallyRepairACar(pCar);
397
    SetCarSuspGiveAndHeight(pCar, 1.f, 1.f, 1.f, 0.f, 0.f);
398
    for (j = 0; j < COUNT_OF(pCar->powerups); ++j) {
399
        pCar->powerups[j] = 0;
400
    }
401
    if (gNet_mode != eNet_mode_none) {
402
        for (j = 0; j < COUNT_OF(pCar->power_up_levels); j++) {
403
            pCar->power_up_levels[j] = 0;
404
        }
405
    }
406
}
407
 
408
// IDA: void __usercall InitialiseCar(tCar_spec *pCar@<EAX>)
409
void InitialiseCar(tCar_spec* pCar) {
410
    LOG_TRACE("(%p)", pCar);
411
 
412
    InitialiseCar2(pCar, 1);
413
}
414
 
415
// IDA: void __usercall InitialiseCarsEtc(tRace_info *pThe_race@<EAX>)
416
void InitialiseCarsEtc(tRace_info* pThe_race) {
417
    int i;
418
    int cat;
419
    int car_count;
420
    tCar_spec* car;
421
    br_bounds bnds;
422
    LOG_TRACE("(%p)", pThe_race);
423
 
424
    gProgram_state.initial_position = pThe_race->initial_position;
425
    gProgram_state.initial_yaw = pThe_race->initial_yaw;
426
    BrActorToBounds(&bnds, gProgram_state.track_spec.the_actor);
427
    gMin_world_y = bnds.min.v[1];
428
    gNum_active_non_cars = 0;
429
    for (cat = eVehicle_self; cat <= eVehicle_not_really; cat++) {
430
        if (cat == eVehicle_self) {
431
            car_count = 1;
432
        } else {
433
            car_count = GetCarCount(cat);
434
        }
435
        for (i = 0; i < car_count; i++) {
436
            PossibleService();
437
            if (cat == eVehicle_self) {
438
                car = &gProgram_state.current_car;
439
            } else {
440
                car = GetCarSpec(cat, i);
441
            }
442
            if (cat != eVehicle_not_really) {
443
                InitialiseCar(car);
444
            }
445
        }
446
    }
447
    gCamera_yaw = 0;
448
    InitialiseExternalCamera();
449
    gLast_mechanics_time = 0;
450
}
451
 
452
// IDA: void __usercall GetAverageGridPosition(tRace_info *pThe_race@<EAX>)
453
void GetAverageGridPosition(tRace_info* pThe_race) {
454
    int i;
455
    br_scalar total_cars;
456
    tCar_spec* car;
457
    LOG_TRACE("(%p)", pThe_race);
458
 
459
    total_cars = 0.0f;
460
    BrVector3SetFloat(&gAverage_grid_position, 0.0f, 0.0f, 0.0f);
461
    for (i = 0; i < pThe_race->number_of_racers; i++) {
462
        car = pThe_race->opponent_list[i].car_spec;
463
        BrVector3Accumulate(&gAverage_grid_position, &car->pos);
464
        total_cars += 1.0f;
465
    }
466
    BrVector3InvScale(&gAverage_grid_position, &gAverage_grid_position, total_cars);
467
}
468
 
469
// IDA: void __usercall SetInitialPosition(tRace_info *pThe_race@<EAX>, int pCar_index@<EDX>, int pGrid_index@<EBX>)
470
void SetInitialPosition(tRace_info* pThe_race, int pCar_index, int pGrid_index) {
471
    int place_on_grid;
472
    int i;
473
    int start_i;
474
    int j;
475
    br_actor* car_actor;
476
    br_angle initial_yaw;
477
    br_scalar nearest_y_above;
478
    br_scalar nearest_y_below;
479
    //br_scalar speed; // Pierre-Marie Baty -- unused variable
480
    int below_face_index;
481
    int above_face_index;
482
    br_model* below_model;
483
    br_model* above_model;
484
    tCar_spec* car;
485
    br_vector3 grid_offset;
486
    br_vector3 dist;
487
    br_vector3 real_pos;
488
    br_matrix34 initial_yaw_matrix;
489
    //br_bounds bnds; // Pierre-Marie Baty -- unused variable
490
    LOG_TRACE("(%p, %d, %d)", pThe_race, pCar_index, pGrid_index);
491
 
492
    initial_yaw = 0;
493
    car_actor = pThe_race->opponent_list[pCar_index].car_spec->car_master_actor;
494
    car = pThe_race->opponent_list[pCar_index].car_spec;
495
    BrMatrix34Identity(&car_actor->t.t.mat);
496
    place_on_grid = 1;
497
    if (gNet_mode != eNet_mode_none && !gCurrent_net_game->options.grid_start && pThe_race->number_of_net_start_points != 0) {
498
        start_i = i = IRandomBetween(0, pThe_race->number_of_net_start_points - 1);
499
        do {
500
            PossibleService();
501
            for (j = 0; j < gNumber_of_net_players; j++) {
502
                if (j != pCar_index) {
503
                    BrVector3Copy(&real_pos, &pThe_race->opponent_list[j].car_spec->car_master_actor->t.t.translate.t);
504
                    if (real_pos.v[0] > 500.f) {
505
                        real_pos.v[0] -= 1000.f;
506
                        real_pos.v[1] -= 1000.f;
507
                        real_pos.v[2] -= 1000.f;
508
                    }
509
                    BrVector3Sub(&dist, &real_pos, &pThe_race->net_starts[i].pos);
510
                    if (BrVector3LengthSquared(&dist) < 16.f) {
511
                        break;
512
                    }
513
                }
514
            }
515
            if (j == gNumber_of_net_players) {
516
                BrVector3Copy(&car_actor->t.t.translate.t, &pThe_race->net_starts[i].pos);
517
                initial_yaw = BrDegreeToAngle(pThe_race->net_starts[i].yaw);
518
                place_on_grid = 0;
519
            }
520
            i++;
521
            if (i == pThe_race->number_of_net_start_points) {
522
                i = 0;
523
            }
524
        } while (start_i != i);
525
    }
526
    if (place_on_grid) {
527
        initial_yaw = BrDegreeToAngle(pThe_race->initial_yaw);
528
        BrMatrix34RotateY(&initial_yaw_matrix, initial_yaw);
529
        grid_offset.v[0] = 0.0f - pGrid_index % 2;
530
        grid_offset.v[1] = 0.0f;
531
        grid_offset.v[2] = (br_scalar)(pGrid_index / 2) * 2.0f + (br_scalar)(pGrid_index % 2) * 0.4f;
532
        BrMatrix34ApplyV(&car_actor->t.t.translate.t, &grid_offset, &initial_yaw_matrix);
533
        BrVector3Accumulate(&car_actor->t.t.translate.t, &pThe_race->initial_position);
534
    }
535
    FindBestY(
536
        &car_actor->t.t.translate.t,
537
        gTrack_actor,
538
        10.0f,
539
        &nearest_y_above,
540
        &nearest_y_below,
541
        &above_model,
542
        &below_model,
543
        &above_face_index,
544
        &below_face_index);
545
    if (nearest_y_above != 30000.0f) {
546
        car_actor->t.t.translate.t.v[1] = nearest_y_above;
547
    } else if (nearest_y_below != -30000.0f) {
548
        car_actor->t.t.translate.t.v[1] = nearest_y_below;
549
    } else {
550
        car_actor->t.t.translate.t.v[1] = 0.0f;
551
    }
552
    BrMatrix34PreRotateY(&car_actor->t.t.mat, initial_yaw);
553
    if (gNet_mode) {
554
        BrMatrix34Copy(
555
            &gNet_players[pThe_race->opponent_list[pCar_index].net_player_index].initial_position,
556
            &car->car_master_actor->t.t.mat);
557
    }
558
    if (gNet_mode != eNet_mode_none && car->disabled && car_actor->t.t.translate.t.v[0] < 500.0f) {
559
        DisableCar(car);
560
    }
561
    // Enable to start all opponent cars upside down ;)
562
    // if (strstr(car->name, "EAGLE") == 0) {
563
    //     car_actor->t.t.translate.t.v[1] += 2;
564
    //     car_actor->t.t.look_up.up.v[1] = -1;
565
    // }
566
}
567
 
568
// IDA: void __usercall SetInitialPositions(tRace_info *pThe_race@<EAX>)
569
void SetInitialPositions(tRace_info* pThe_race) {
570
    int i;
571
    LOG_TRACE("(%p)", pThe_race);
572
 
573
    for (i = 0; i < pThe_race->number_of_racers; i++) {
574
        SetInitialPosition(pThe_race, i, i);
575
    }
576
}
577
 
578
// IDA: void __usercall InitialiseNonCar(tNon_car_spec *non_car@<EAX>)
579
void InitialiseNonCar(tNon_car_spec* non_car) {
580
    tCollision_info* c;
581
    LOG_TRACE("(%p)", non_car);
582
 
583
    c = &non_car->collision_info;
584
    BrMatrix34Copy(&c->oldmat, &c->car_master_actor->t.t.mat);
585
    non_car->collision_info.box_face_ref = gFace_num__car - 2;
586
    non_car->collision_info.doing_nothing_flag = 1;
587
    non_car->collision_info.disabled = 0;
588
    BrVector3SetFloat(&c->v, 0.0f, 0.0f, 0.0f);
589
    BrVector3SetFloat(&c->omega, 0.0f, 0.0f, 0.0f);
590
    BrVector3SetFloat(&c->oldomega, 0.0f, 0.0f, 0.0f);
591
    non_car->collision_info.box_face_ref = gFace_num__car - 2;
592
    c->collision_flag = 0;
593
    c->who_last_hit_me = NULL;
594
    if (c->car_master_actor->identifier[3] == '!') {
595
        c->M = non_car->free_mass;
596
        c->min_torque_squared = 0.0f;
597
        BrVector3Copy(&c->cmpos, &non_car->free_cmpos);
598
    } else {
599
        c->M = non_car->attached_mass;
600
        BrVector3Copy(&c->cmpos, &non_car->attached_cmpos);
601
        c->min_torque_squared = non_car->min_torque_squared;
602
    }
603
    BrVector3Scale(&c->I, &non_car->I_over_M, c->M);
604
    c->message.type = 0;
605
    c->message.time = 0;
606
    c->dt = -1.0f;
607
    c->last_car_car_collision = 1;
608
}
609
 
610
// IDA: void __usercall GetFacesInBox(tCollision_info *c@<EAX>)
611
void GetFacesInBox(tCollision_info* c) {
612
    tBounds bnds;
613
    br_bounds new_in_old;
614
    br_bounds predicted_bounds;
615
    br_matrix34 mat;
616
    br_matrix34 mat2;
617
    br_matrix34 mat3;
618
    br_matrix34 mat4;
619
    br_matrix34 mat5;
620
    br_matrix34 mat6;
621
    br_scalar old_d;
622
    int i;
623
    br_bounds current_bounds;
624
    LOG_TRACE("(%p)", c);
625
 
626
    BrMatrix34Copy(&mat, &c->car_master_actor->t.t.mat);
627
    BrMatrix34Copy(&mat2, &c->oldmat);
628
    BrVector3InvScale((br_vector3*)mat.m[3], (br_vector3*)mat.m[3], WORLD_SCALE);
629
    BrVector3InvScale((br_vector3*)mat2.m[3], (br_vector3*)mat2.m[3], WORLD_SCALE);
630
    BrMatrix34LPInverse(&mat3, &mat);
631
    BrMatrix34Mul(&mat4, &mat2, &mat3);
632
    GetNewBoundingBox(&bnds.original_bounds, c->bounds, &mat4);
633
    for (i = 0; i < 3; i++) {
634
        if (bnds.original_bounds.min.v[i] > c->bounds[0].min.v[i]) {
635
            bnds.original_bounds.min.v[i] = c->bounds[0].min.v[i];
636
        }
637
        if (bnds.original_bounds.max.v[i] < c->bounds[0].max.v[i]) {
638
            bnds.original_bounds.max.v[i] = c->bounds[0].max.v[i];
639
        }
640
        bnds.original_bounds.min.v[i] -= 0.002f;
641
        bnds.original_bounds.max.v[i] += 0.002f;
642
    }
643
    GetNewBoundingBox(&c->bounds_world_space, &bnds.original_bounds, &mat);
644
    c->bounds_ws_type = eBounds_ws;
645
    if ((c->box_face_ref != gFace_num__car && (c->box_face_ref != gFace_num__car - 1 || c->box_face_start <= gFace_count))
646
        || (BrMatrix34Mul(&mat5, &mat, &c->last_box_inv_mat),
647
            GetNewBoundingBox(&new_in_old, &bnds.original_bounds, &mat5),
648
            c->last_box.max.v[0] <= new_in_old.max.v[0])
649
        || c->last_box.max.v[1] <= new_in_old.max.v[1]
650
        || c->last_box.max.v[2] <= new_in_old.max.v[2]
651
        || c->last_box.min.v[0] >= new_in_old.min.v[0]
652
        || c->last_box.min.v[1] >= new_in_old.min.v[1]
653
        || c->last_box.min.v[2] >= new_in_old.min.v[2]) {
654
        BrMatrix34Mul(&mat5, &mat4, &mat4);
655
        BrMatrix34Mul(&mat6, &mat5, &mat4);
656
        BrMatrix34LPInverse(&mat5, &mat6);
657
        GetNewBoundingBox(&predicted_bounds, c->bounds, &mat5);
658
        for (i = 0; i < 3; i++) {
659
            if (bnds.original_bounds.min.v[i] > predicted_bounds.min.v[i]) {
660
                bnds.original_bounds.min.v[i] = predicted_bounds.min.v[i];
661
            }
662
            if (bnds.original_bounds.max.v[i] < predicted_bounds.max.v[i]) {
663
                bnds.original_bounds.max.v[i] = predicted_bounds.max.v[i];
664
            }
665
            bnds.original_bounds.min.v[i] -= 0.02f;
666
            bnds.original_bounds.max.v[i] += 0.02f;
667
        }
668
        c->last_box = bnds.original_bounds;
669
        BrMatrix34Copy(&c->last_box_inv_mat, &mat3);
670
        bnds.mat = &mat;
671
        c->box_face_start = gFace_count;
672
        gPling_face = NULL;
673
        gFace_count += FindFacesInBox(&bnds, &gFace_list__car[gFace_count], COUNT_OF(gFace_list__car) - gFace_count);
674
        if (gFace_count >= COUNT_OF(gFace_list__car)) {
675
            c->box_face_start = 0;
676
            gFace_count = FindFacesInBox(&bnds, gFace_list__car, COUNT_OF(gFace_list__car));
677
            gFace_num__car++;
678
        }
679
        old_d = c->water_d;
680
        if (c->driver == eDriver_local_human
681
            && c->water_d != 10000.f
682
            && gDouble_pling_water
683
            && BrVector3Dot(&c->bounds_world_space.max, &c->water_normal) - c->water_d <= 0.f) {
684
            gInTheSea = 1;
685
            FreezeCamera();
686
        }
687
        if (gPling_face != NULL && fabsf(gPling_face->normal.v[1]) >= 0.9f) {
688
            BrVector3Copy(&c->water_normal, &gPling_face->normal);
689
            if (c->water_normal.v[1] < 0.f) {
690
                BrVector3Negate(&c->water_normal, &c->water_normal);
691
            }
692
            c->water_d = BrVector3Dot(&gPling_face->v[0], &c->water_normal);
693
            if (c->driver == eDriver_local_human) {
694
                if (gPling_face->material->identifier[1] != '!') {
695
                    gDouble_pling_water = 0;
696
                } else {
697
                    if (BrVector3Dot(&c->bounds_world_space.min, &c->water_normal) - c->water_d < 0.0f) {
698
                        GetNewBoundingBox(&current_bounds, &c->bounds[1], &c->car_master_actor->t.t.mat);
699
                        if (BrVector3Dot(&current_bounds.min, &c->water_normal) / WORLD_SCALE - c->water_d < 0.0f) {
700
                            gInTheSea = 1;
701
                            FreezeCamera();
702
                        }
703
                    }
704
                    gDouble_pling_water = 1;
705
                }
706
            }
707
        } else {
708
            c->water_d = 10000.0;
709
            if (c->driver == eDriver_local_human) {
710
                if (gInTheSea == 1) {
711
                    gInTheSea = 2;
712
                } else {
713
                    gInTheSea = 0;
714
                }
715
            }
716
        }
717
        if (c->water_d != old_d) {
718
            StartPipingSession(ePipe_chunk_splash);
719
            AddSplashToPipingSession(c);
720
            EndPipingSession();
721
        }
722
        c->box_face_end = gFace_count;
723
        c->box_face_ref = gFace_num__car;
724
    }
725
}
726
 
727
// IDA: int __cdecl IsCarInTheSea()
728
int IsCarInTheSea(void) {
729
    LOG_TRACE("()");
730
 
731
    return gInTheSea;
732
}
733
 
734
// IDA: void __usercall RememberSafePosition(tCar_spec *car@<EAX>, tU32 pTime@<EDX>)
735
void RememberSafePosition(tCar_spec* car, tU32 pTime) {
736
    static tU32 time_count;
737
    int j;
738
    br_vector3 r;
739
    //br_scalar ts; // Pierre-Marie Baty -- unused variable
740
    LOG_TRACE("(%p, %d)", car, pTime);
741
 
742
    if (car->disabled) {
743
        return;
744
    }
745
    time_count += pTime;
746
    if (time_count < 5000) {
747
        return;
748
    }
749
    time_count = 4000;
750
    for (j = 0; j < 4; j++) {
751
        if (car->susp_height[j >> 1] <= car->oldd[j]) {
752
            return;
753
        }
754
    }
755
    if ((car->last_special_volume == NULL || car->last_special_volume->gravity_multiplier == 1.f)
756
        && gCurrent_race.material_modifiers[car->material_index[0]].tyre_road_friction >= 0.1f
757
        && gCurrent_race.material_modifiers[car->material_index[1]].tyre_road_friction >= 0.1f
758
        && gCurrent_race.material_modifiers[car->material_index[2]].tyre_road_friction >= 0.1f
759
        && gCurrent_race.material_modifiers[car->material_index[3]].tyre_road_friction >= 0.1f
760
        && car->car_master_actor->t.t.mat.m[1][1] > 0.8f) {
761
 
762
        for (j = 0; j < 5; j++) {
763
            BrVector3Sub(&r, &car->car_master_actor->t.t.translate.t, (br_vector3*)car->last_safe_positions[j].m[3]);
764
 
765
            if (BrVector3LengthSquared(&r) < 8.4015961f) {
766
                return;
767
            }
768
        }
769
        for (j = 3; j > 0; j--) {
770
            BrMatrix34Copy(&car->last_safe_positions[j], &car->last_safe_positions[j - 1]);
771
        }
772
        BrMatrix34Copy(&car->last_safe_positions[0], &car->car_master_actor->t.t.mat);
773
        time_count = 0;
774
    }
775
}
776
 
777
// IDA: void __usercall ControlOurCar(tU32 pTime_difference@<EAX>)
778
void ControlOurCar(tU32 pTime_difference) {
779
    br_scalar ts;
780
    br_vector3 minus_k;
781
    tCar_spec* car;
782
    static int steering_locked;
783
    //int i; // Pierre-Marie Baty -- unused variable
784
    tU32 time;
785
    LOG_TRACE("(%d)", pTime_difference);
786
 
787
    car = &gProgram_state.current_car;
788
    if (gCar_flying) {
789
        if (gNet_mode != eNet_mode_none) {
790
            gCar_flying = 0;
791
        } else {
792
            BrVector3Scale(&car->car_master_actor->t.t.translate.t, &car->car_master_actor->t.t.translate.t, WORLD_SCALE);
793
            FlyCar(car, pTime_difference / 1000.f);
794
            BrVector3InvScale(&car->car_master_actor->t.t.translate.t, &car->car_master_actor->t.t.translate.t, WORLD_SCALE);
795
        }
796
        return;
797
    }
798
    time = GetTotalTime();
799
    if (car->damage_units[eDamage_steering].damage_level > 40) {
800
        if (car->end_steering_damage_effect) {
801
            if (time < car->end_steering_damage_effect || car->damage_units[eDamage_steering].damage_level == 99) {
802
                car->keys.left = car->false_key_left;
803
                car->keys.right = car->false_key_right;
804
            } else {
805
                car->end_steering_damage_effect = 0;
806
            }
807
        } else {
808
            ts = pTime_difference * (car->damage_units[eDamage_steering].damage_level - 40) * 0.0045f;
809
            if (PercentageChance(ts) && fabsf(car->velocity_car_space.v[2]) > 0.0001f) {
810
                if (car->keys.left || car->keys.right) {
811
                    car->false_key_left = !car->keys.left;
812
                    car->false_key_right = !car->keys.right;
813
                } else if (PercentageChance(50)) {
814
                    car->false_key_left = 1;
815
                } else {
816
                    car->false_key_right = 1;
817
                }
818
                ts = 5 * (5 * car->damage_units[eDamage_steering].damage_level - 200);
819
                car->end_steering_damage_effect = FRandomBetween(0.0f, ts) + time;
820
            }
821
        }
822
    }
823
    if (car->damage_units[eDamage_transmission].damage_level > 40) {
824
        if (car->end_trans_damage_effect) {
825
            if (time < car->end_trans_damage_effect || car->damage_units[eDamage_transmission].damage_level == 99) {
826
                car->gear = 0;
827
                car->just_changed_gear = 1;
828
            } else {
829
                car->end_trans_damage_effect = 0;
830
            }
831
        } else {
832
            ts = pTime_difference * (car->damage_units[eDamage_transmission].damage_level - 40) * 0.006;
833
            if (PercentageChance(ts) != 0) {
834
                ts = 10 * (5 * car->damage_units[eDamage_transmission].damage_level - 200);
835
                car->end_trans_damage_effect = FRandomBetween(0.f, ts) + time;
836
            }
837
        }
838
    }
839
    ts = pTime_difference / 1000.0f;
840
    ControlCar[gControl__car](car, ts);
841
    RememberSafePosition(car, pTime_difference);
842
    if (gCamera_reset) {
843
        BrVector3SetFloat(&minus_k, 0.0f, 0.0f, -1.0f);
844
        gCamera_sign = 0;
845
        BrMatrix34ApplyV(&car->direction, &minus_k, &car->car_master_actor->t.t.mat);
846
    }
847
}
848
 
849
// IDA: void __usercall CalcEngineForce(tCar_spec *c@<EAX>, br_scalar dt)
850
void CalcEngineForce(tCar_spec* c, br_scalar dt) {
851
    br_scalar torque;
852
    br_scalar ts;
853
    br_scalar ts2;
854
    //br_scalar brake_temp; // Pierre-Marie Baty -- unused variable
855
    int sign;
856
    tS32 temp_for_swap;
857
    LOG_TRACE("(%p, %f)", c, dt);
858
 
859
    c->acc_force = 0.0f;
860
    if (c->revs == 0.0f) {
861
        c->gear = 0;
862
    }
863
    sign = c->gear < 0 || (c->gear == 0 && c->velocity_car_space.v[2] > 0.5f);
864
    if (c->keys.backwards != sign) {
865
        c->keys.backwards = !c->keys.backwards;
866
        temp_for_swap = c->keys.acc;
867
        c->keys.acc = c->keys.dec;
868
        c->keys.dec = temp_for_swap;
869
 
870
        temp_for_swap = c->joystick.acc;
871
        c->joystick.acc = c->joystick.dec;
872
        c->joystick.dec = temp_for_swap;
873
    }
874
    if (!c->gear && !c->keys.acc && c->joystick.acc <= 0 && (c->keys.dec || c->joystick.dec > 0) && !c->keys.backwards && fabs(c->velocity_car_space.v[2]) < 1.0) {
875
        c->keys.backwards = 1;
876
        c->keys.acc = c->keys.dec;
877
        c->keys.dec = 0;
878
        temp_for_swap = c->joystick.acc;
879
        c->joystick.acc = c->joystick.dec;
880
        c->joystick.dec = temp_for_swap;
881
    }
882
    c->torque = -(c->revs * c->revs / 100000000.0f) - 0.2f;
883
    if (c->keys.acc || c->joystick.acc >= 0) {
884
        if (fabsf(c->curvature) > c->maxcurve / 2.0f && c->gear < 2 && c->gear && c->traction_control) {
885
            ts = 0.7f;
886
        } else if (c->joystick.acc < 0) {
887
            ts = (br_scalar) 1.2; // Pierre-Marie Baty -- added type cast
888
        } else {
20 pmbaty 889
            ts = c->joystick.acc / 54613.0;
890
            LOG_PANIC("ooo");
1 pmbaty 891
        }
892
 
893
        torque = c->engine_power_multiplier * ts * gEngine_powerup_factor[c->power_up_levels[1]];
894
        if (c->damage_units[0].damage_level > 10) {
895
            torque = (1.0f - (double)(c->damage_units[0].damage_level - 10) / 100.0f) * torque;
896
        }
897
        c->torque += torque;
898
    } else {
899
        c->traction_control = 1;
900
    }
901
    if (!c->keys.dec && (!c->keys.acc || c->gear) && c->joystick.dec <= 0 && (c->joystick.acc <= 0 || c->gear)) {
902
        c->brake_force = 0.0f;
903
    } else {
904
        if (c->joystick.dec > 0) {
905
            c->brake_force = (double)(c->joystick.dec / 0x10000) * c->brake_increase + c->initial_brake;
906
        }
907
        if (c->brake_force == 0.0f) {
908
            c->brake_force = c->initial_brake;
909
        } else {
910
            c->brake_force += c->brake_increase * dt;
911
            if (c->initial_brake + c->brake_increase < c->brake_force) {
912
                c->brake_force = c->initial_brake + c->brake_increase;
913
            }
914
        }
915
    }
916
    if (c->gear) {
917
        c->acc_force = c->force_torque_ratio * c->torque / (float)c->gear;
918
        if (c->brake_force == 0.0f) {
919
            if (c->revs - 1.0f > c->target_revs || c->revs + 1.0f < c->target_revs) {
920
                ts2 = c->torque * dt / 0.0002 + c->revs - c->target_revs;
921
                c->acc_force += ts2 / ((1.0f / (c->speed_revs_ratio * c->M) / (float)c->gear + 1.0 / (c->force_torque_ratio * 0.0002) * (double)c->gear) * dt);
922
            }
923
        } else {
924
            c->revs = c->target_revs;
925
        }
926
    }
927
}
928
 
929
// IDA: void __usercall PrepareCars(tU32 pFrame_start_time@<EAX>)
930
void PrepareCars(tU32 pFrame_start_time) {
931
    tCar_spec* car;
932
    int i;
933
    static tU32 last_frame_start;
934
    LOG_TRACE("(%d)", pFrame_start_time);
935
 
936
    last_frame_start = pFrame_start_time;
937
    for (i = 0; i < gNum_cars_and_non_cars; i++) {
938
        car = gActive_car_list[i];
939
        BrVector3Scale(&car->car_master_actor->t.t.translate.t, &car->car_master_actor->t.t.translate.t, WORLD_SCALE);
940
        BrVector3Scale(&car->velocity_car_space, &car->velocity_car_space, WORLD_SCALE * 1000.f);
941
        car->frame_collision_flag = gOver_shoot && car->collision_flag;
942
        if (car->driver > eDriver_non_car) {
943
            RecordLastDamage(car);
944
            if (car->driver == eDriver_oppo && gStop_opponents_moving) {
945
                car->acc_force = 0.0f;
946
                car->brake_force = 0.0f;
947
                car->keys.acc = 0;
948
                car->keys.dec = 0;
949
                car->joystick.acc = -1;
950
                car->joystick.dec = -1;
951
            }
952
            if (!car->wheel_slip) {
953
                StopSkid(car);
954
            }
955
            if (car->driver == eDriver_net_human && car->message.time < pFrame_start_time - 1000) {
956
                car->keys.acc = 0;
957
                car->keys.dec = 0;
958
                car->joystick.acc = -1;
959
                car->joystick.dec = -1;
960
                car->keys.horn = 0;
961
            }
962
            SetSmokeLastDamageLevel(car);
963
        }
964
        BrMatrix34Copy(&car->car_master_actor->t.t.mat, &car->oldmat);
965
    }
966
}
967
 
968
// IDA: void __usercall FinishCars(tU32 pLast_frame_time@<EAX>, tU32 pTime@<EDX>)
969
void FinishCars(tU32 pLast_frame_time, tU32 pTime) {
970
    tCar_spec* car;
971
    br_vector3 minus_k;
972
    int i;
973
    int wheel;
974
    //br_scalar scale; // Pierre-Marie Baty -- unused variable
975
    LOG_TRACE("(%d, %d)", pLast_frame_time, pTime);
976
 
977
    for (i = 0; i < gNum_cars_and_non_cars; i++) {
978
        car = gActive_car_list[i];
979
        if (fabsf(car->omega.v[0]) > 10000.f
980
            || fabsf(car->omega.v[1]) > 10000.f
981
            || fabsf(car->omega.v[2]) > 10000.f) {
982
            BrVector3SetFloat(&car->omega, 0.f, 0.f, 0.f);
983
            BrVector3SetFloat(&car->v, 0.f, 0.f, 0.f);
984
        }
985
        BrVector3InvScale(&car->velocity_car_space, &car->velocity_car_space, WORLD_SCALE * 1000.0f);
986
        BrVector3InvScale(&car->car_master_actor->t.t.translate.t, &car->car_master_actor->t.t.translate.t, WORLD_SCALE);
987
 
988
        car->speed = BR_LENGTH2(car->v.v[0], car->v.v[2]) / (WORLD_SCALE * 1000.0f);
989
        BrVector3Negate(&minus_k, (br_vector3*)car->car_master_actor->t.t.mat.m[2]);
990
        if (car->speed <= 0.0001f) {
991
            if (BrVector3Dot(&car->direction, &minus_k) < 0.f) {
992
                BrVector3SetFloat(&minus_k, 0.f, 0.f, 1.f);
993
            } else {
994
                BrVector3SetFloat(&minus_k, 0.f, 0.f, -1.f);
995
            }
996
            BrMatrix34ApplyV(&car->direction, &minus_k, &car->car_master_actor->t.t.mat);
997
        } else if (gLast_mechanics_time > pLast_frame_time && gCar_to_view == car) {
998
            BrVector3Sub(&car->old_v, &car->old_v, &car->v);
999
            BrVector3Scale(&car->old_v, &car->old_v, (gLast_mechanics_time - pLast_frame_time) / harness_game_config.physics_step_time);
1000
            BrVector3Accumulate(&car->old_v, &car->v);
1001
            BrVector3Normalise(&car->direction, &car->old_v);
1002
        } else {
1003
            BrVector3Normalise(&car->direction, &car->v);
1004
        }
1005
        if (car->driver >= eDriver_oppo) {
1006
            car->speedo_speed = BrVector3Dot(&minus_k, &car->v) / (WORLD_SCALE * 1000.0f);
1007
 
1008
            car->steering_angle = BrRadianToDegree(atanf((car->wpos[0].v[2] - car->wpos[2].v[2]) * car->curvature));
1009
 
1010
            car->lr_sus_position = (car->ride_height - car->oldd[0]) / WORLD_SCALE;
1011
            car->rr_sus_position = (car->ride_height - car->oldd[1]) / WORLD_SCALE;
1012
            car->lf_sus_position = (car->ride_height - car->oldd[2]) / WORLD_SCALE;
1013
            car->rf_sus_position = (car->ride_height - car->oldd[3]) / WORLD_SCALE;
1014
            for (wheel = 0; wheel < 4; wheel++) {
1015
                if (car->oldd[wheel] < car->susp_height[wheel >> 1] && gCurrent_race.material_modifiers[car->material_index[wheel]].smoke_type >= 2 && !car->doing_nothing_flag) {
1016
                    GenerateContinuousSmoke(car, wheel, pTime);
1017
                }
1018
            }
1019
        }
1020
    }
1021
}
1022
 
1023
// IDA: void __usercall InterpolateCars(tU32 pLast_frame_time@<EAX>, tU32 pTime@<EDX>)
1024
void InterpolateCars(tU32 pLast_frame_time, tU32 pTime) {
1025
    br_scalar dt;
1026
    tCar_spec* car;
1027
    int i;
1028
    LOG_TRACE("(%d, %d)", pLast_frame_time, pTime);
1029
 
1030
    dt = ((int)(gLast_mechanics_time - pLast_frame_time)) / 1000.0;
1031
    if (dt > 0.04 || dt < 0)
1032
        dt = 0;
1033
 
1034
    gOver_shoot = dt > 0.0;
1035
 
1036
    for (i = 0; i < gNum_cars_and_non_cars; i++) {
1037
        car = gActive_car_list[i];
1038
        BrMatrix34Copy(&car->oldmat, &car->car_master_actor->t.t.mat);
1039
        SimpleRotate((tCollision_info*)car, -dt);
1040
        TranslateCar((tCollision_info*)car, -dt);
1041
        BrMatrix34ApplyP(&car->pos, &car->cmpos, &car->car_master_actor->t.t.mat);
1042
        BrVector3InvScale(&car->pos, &car->pos, WORLD_SCALE);
1043
    }
1044
}
1045
 
1046
// IDA: void __cdecl ResetOldmat()
1047
void ResetOldmat(void) {
1048
    tCar_spec* car;
1049
    int i;
1050
    br_matrix34 mat;
1051
    static int normalise_count = 0;
1052
    LOG_TRACE("()");
1053
 
1054
    for (i = 0; i < gNum_cars_and_non_cars; i++) {
1055
        BrMatrix34Copy(&gActive_car_list[i]->oldmat, &gActive_car_list[i]->car_master_actor->t.t.mat);
1056
    }
1057
    normalise_count++;
1058
    if (normalise_count > 50) {
1059
        normalise_count = 0;
1060
        for (i = 0; i < gNum_cars_and_non_cars; i++) {
1061
            car = gActive_car_list[i];
1062
            BrMatrix34LPNormalise(&mat, &car->car_master_actor->t.t.mat);
1063
            BrMatrix34Copy(&car->car_master_actor->t.t.mat, &mat);
1064
        }
1065
    }
1066
}
1067
 
1068
// IDA: void __cdecl GetNonCars()
1069
void GetNonCars(void) {
1070
    int i;
1071
    int j;
1072
    LOG_TRACE("()");
1073
 
1074
    gNum_cars_and_non_cars = gNum_active_non_cars + gNum_active_cars;
1075
    j = 0;
1076
    for (i = gNum_active_cars; i < gNum_cars_and_non_cars; i++) {
1077
        gActive_car_list[i] = (tCar_spec*)gActive_non_car_list[j];
1078
        j++;
1079
    }
1080
}
1081
 
1082
// IDA: void __usercall GetNetPos(tCar_spec *pCar@<EAX>)
1083
void GetNetPos(tCar_spec* pCar) {
20 pmbaty 1084
    //int j; // Pierre-Marie Baty -- unused variable
1085
    //float amount; // Pierre-Marie Baty -- unused variable
1086
    //br_scalar total_deflection; // Pierre-Marie Baty -- unused variable
1 pmbaty 1087
    LOG_TRACE("(%p)", pCar);
20 pmbaty 1088
    NOT_IMPLEMENTED();
1 pmbaty 1089
}
1090
 
1091
// IDA: void __usercall ApplyPhysicsToCars(tU32 last_frame_time@<EAX>, tU32 pTime_difference@<EDX>)
1092
void ApplyPhysicsToCars(tU32 last_frame_time, tU32 pTime_difference) {
1093
    //br_vector3 minus_k; // Pierre-Marie Baty -- unused variable
1094
    int i;
1095
    int old_num_cars;
1096
    int step_number;
1097
    int dam_index;
1098
    static int steering_locked;
1099
    tCar_spec* car = NULL;
1100
    tCollision_info* car_info;
1101
    tNon_car_spec* non_car;
1102
    //tU32 time_step; // Pierre-Marie Baty -- unused variable
1103
    tU32 frame_end_time;
1104
    LOG_TRACE("(%d, %d)", last_frame_time, pTime_difference);
1105
 
1106
    step_number = 0;
1107
    frame_end_time = last_frame_time + pTime_difference;
1108
    if (gFreeze_mechanics) {
1109
        return;
1110
    }
1111
    if (gNet_mode == eNet_mode_client) {
1112
        ForceRebuildActiveCarList();
1113
    }
1114
    if (gLast_mechanics_time < last_frame_time) {
1115
        gLast_mechanics_time = harness_game_config.physics_step_time * (last_frame_time / harness_game_config.physics_step_time);
1116
    }
1117
    GetNonCars();
1118
    if (frame_end_time <= gLast_mechanics_time) {
1119
        PrepareCars(last_frame_time);
1120
        InterpolateCars(frame_end_time, pTime_difference);
1121
        FinishCars(frame_end_time, pTime_difference);
1122
        return;
1123
    }
1124
 
1125
    gDoing_physics = 1;
1126
    PrepareCars(last_frame_time);
1127
    gDt = harness_game_config.physics_step_time / 1000.0; // 0.04;
1128
    gMechanics_time_sync = pTime_difference - (gLast_mechanics_time - last_frame_time);
1129
    while (gLast_mechanics_time < frame_end_time && step_number < 5) {
1130
        step_number++;
1131
        ResetOldmat();
1132
        BrVector3Copy(&gProgram_state.current_car.old_v, &gProgram_state.current_car.v);
1133
        if (&gProgram_state.current_car != gCar_to_view) {
1134
            BrVector3Copy(&gCar_to_view->old_v, &gCar_to_view->v);
1135
        }
1136
        for (i = 0; i < gNum_active_cars; i++) {
1137
            car = gActive_car_list[i];
1138
            car->dt = -1.f;
20 pmbaty 1139
            if (car->message.type == 15 && car->message.time >= gLast_mechanics_time && gLast_mechanics_time + harness_game_config.physics_step_time >= car->message.time) {
1140
                car->dt = (double)(gLast_mechanics_time + harness_game_config.physics_step_time - car->message.time) / 1000.0;
1141
                if (gDt - 0.0001f <= car->dt) {
1 pmbaty 1142
                    GetNetPos(car);
1143
                } else if (gNet_mode == eNet_mode_host) {
1144
                    car->dt = -1.f;
1145
                } else {
1146
                    for (dam_index = 0; dam_index < COUNT_OF(car->damage_units); dam_index++) {
1147
                        if (car->damage_units[dam_index].damage_level < car->message.damage[dam_index]) {
1148
                            car->dt = -1.f;
1149
                            break;
1150
                        }
1151
                    }
1152
                    if (car->dt >= 0.f) {
1153
                        GetNetPos(car);
1154
                    }
1155
                }
1156
            }
1157
            if (!car->disabled
1158
                && (!car->doing_nothing_flag || (car->driver >= eDriver_net_human && (!gPalette_fade_time || car->driver != eDriver_local_human)))) {
1159
                if (car->box_face_ref != gFace_num__car
1160
                    && (car->box_face_ref != gFace_num__car - 1 || car->box_face_start <= gFace_count)) {
1161
                    car_info = (tCollision_info*)car;
1162
                    GetFacesInBox(car_info);
1163
                }
1164
                if (car->dt != 0.f) {
1165
                    MoveAndCollideCar(car, gDt);
1166
                }
1167
            }
1168
        }
1169
        for (i = 0; i < gNum_active_non_cars; i++) {
1170
            non_car = gActive_non_car_list[i];
1171
            if (!non_car->collision_info.doing_nothing_flag) {
1172
                non_car->collision_info.dt = -1.f;
20 pmbaty 1173
                if (non_car->collision_info.message.type == 16 && non_car->collision_info.message.time >= gLast_mechanics_time && gLast_mechanics_time + harness_game_config.physics_step_time >= non_car->collision_info.message.time) {
1 pmbaty 1174
                    non_car->collision_info.dt = (gLast_mechanics_time + harness_game_config.physics_step_time - non_car->collision_info.message.time) / 1000.0f;
1175
                    GetNetPos((tCar_spec*)non_car);
1176
                }
1177
                if (non_car->collision_info.box_face_ref != gFace_num__car
1178
                    && (non_car->collision_info.box_face_ref != gFace_num__car - 1
1179
                        || non_car->collision_info.box_face_start <= gFace_count)) {
1180
                    GetFacesInBox(&non_car->collision_info);
1181
                }
1182
                if (non_car->collision_info.dt != 0.0f) {
1183
                    MoveAndCollideNonCar(non_car, gDt);
1184
                }
1185
            }
1186
        }
1187
        do {
1188
            old_num_cars = gNum_cars_and_non_cars;
1189
            CrashCarsTogether(gDt);
1190
        } while (old_num_cars < gNum_cars_and_non_cars);
1191
        gMechanics_time_sync -= harness_game_config.physics_step_time;
1192
        gLast_mechanics_time += harness_game_config.physics_step_time;
1193
    }
1194
    gMechanics_time_sync = 1;
1195
    SendCarData(gLast_mechanics_time);
1196
    InterpolateCars(frame_end_time, pTime_difference);
1197
    FinishCars(frame_end_time, pTime_difference);
1198
    gDoing_physics = 0;
1199
    CheckForDeAttachmentOfNonCars(pTime_difference);
1200
}
1201
 
1202
// IDA: void __usercall MungeSpecialVolume(tCollision_info *pCar@<EAX>)
1203
void MungeSpecialVolume(tCollision_info* pCar) {
1204
    tSpecial_volume* new_special_volume;
1205
    //tCar_spec* car; // Pierre-Marie Baty -- unused variable
1206
    LOG_TRACE("(%p)", pCar);
1207
 
1208
    new_special_volume = FindSpecialVolume(&pCar->pos, pCar->last_special_volume);
1209
    if (pCar->auto_special_volume != NULL && (new_special_volume == NULL || new_special_volume->gravity_multiplier == 1.f)) {
1210
        if (pCar->water_d == 10000.f && pCar->water_depth_factor != 1.f) {
1211
            pCar->auto_special_volume = NULL;
1212
        } else {
1213
            new_special_volume = pCar->auto_special_volume;
1214
        }
1215
    }
1216
    if (pCar->last_special_volume != new_special_volume && pCar->driver == eDriver_local_human) {
1217
        if (pCar->last_special_volume != NULL && pCar->last_special_volume->exit_noise >= 0 && (new_special_volume == NULL || pCar->last_special_volume->exit_noise != new_special_volume->exit_noise)) {
1218
            DRS3StartSound(gCar_outlet, pCar->last_special_volume->exit_noise);
1219
        }
1220
        if (new_special_volume != NULL && new_special_volume->entry_noise >= 0 && (pCar->last_special_volume == NULL || pCar->last_special_volume->entry_noise != new_special_volume->entry_noise)) {
1221
            DRS3StartSound(gCar_outlet, new_special_volume->entry_noise);
1222
        }
1223
    }
1224
    pCar->last_special_volume = new_special_volume;
1225
    if (new_special_volume != NULL && pCar->num_smoke_columns != 0 && pCar->last_special_volume != NULL && pCar->last_special_volume->gravity_multiplier < 1.f) {
1226
        StopCarSmoking((tCar_spec*)pCar);
1227
    }
1228
}
1229
 
1230
// IDA: void __usercall ResetCarSpecialVolume(tCollision_info *pCar@<EAX>)
1231
void ResetCarSpecialVolume(tCollision_info* pCar) {
1232
    br_vector3 cast_v;
1233
    br_vector3 norm;
1234
    br_scalar t;
1235
    int id_len;
1236
    char* mat_id;
1237
    tSpecial_volume* new_special_volume;
1238
    br_material* material;
1239
    LOG_TRACE("(%p)", pCar);
1240
 
1241
    new_special_volume = NULL;
1242
    BrVector3Set(&cast_v, 0.f, 200.f, 0.f);
1243
    DisablePlingMaterials();
1244
    FindFace(&pCar->car_master_actor->t.t.translate.t, &cast_v, &norm, &t, &material);
1245
    EnablePlingMaterials();
1246
    if (t < 100.0f && material != NULL) {
1247
        mat_id = material->identifier;
1248
        if (mat_id) {
1249
            id_len = strlen(mat_id);
1250
            if (id_len > 0 && (*mat_id == '!' || *mat_id == '#')) {
1251
                new_special_volume = GetDefaultSpecialVolumeForWater();
1252
            }
1253
        }
1254
    }
1255
    pCar->auto_special_volume = new_special_volume;
1256
    pCar->water_depth_factor = 1.0f;
1257
}
1258
 
1259
// IDA: void __usercall TestAutoSpecialVolume(tCollision_info *pCar@<EAX>)
1260
void TestAutoSpecialVolume(tCollision_info* pCar) {
1261
    br_vector3 pos;
1262
    //br_scalar car_d; // Pierre-Marie Baty -- unused variable
1263
    br_scalar d;
1264
    br_scalar d2;
1265
    br_vector3 dir;
1266
    br_vector3 tv;
1267
    br_vector3 lp;
1268
    br_vector3 hp;
1269
    tSpecial_volume* vol;
1270
    br_matrix34* mat;
1271
    br_scalar lowest_p;
1272
    br_scalar highest_p;
1273
    br_scalar val;
1274
    int i;
1275
    LOG_TRACE("(%p)", pCar);
1276
 
1277
    mat = &pCar->car_master_actor->t.t.mat;
1278
    highest_p = 0.f;
1279
    for (i = 0; i < 3; i++) {
1280
        highest_p += BrVector3Dot((br_vector3*)mat->m[i], &pCar->water_normal) * pCar->bounds[0].min.v[i];
1281
    }
1282
    highest_p += BrVector3Dot((br_vector3*)mat->m[3], &pCar->water_normal) / WORLD_SCALE;
1283
    lowest_p = highest_p;
1284
    for (i = 0; i < 3; i++) {
1285
        val = (pCar->bounds[0].max.v[i] - pCar->bounds[0].min.v[i]) * BrVector3Dot((br_vector3*)mat->m[i], &pCar->water_normal);
1286
        if (val >= 0.f) {
1287
            highest_p += val;
1288
        } else {
1289
            lowest_p += val;
1290
        }
1291
    }
1292
 
1293
    if (pCar->water_d > lowest_p) {
1294
        if (pCar->water_d >= highest_p) {
1295
            pCar->water_depth_factor = 1.f;
1296
        } else {
1297
            pCar->water_depth_factor = (pCar->water_d - lowest_p) / (highest_p - lowest_p);
1298
        }
1299
        if (pCar->auto_special_volume == NULL) {
1300
            vol = GetDefaultSpecialVolumeForWater();
1301
            if (vol == NULL) {
1302
                pCar->water_depth_factor = 1.f;
1303
                pCar->auto_special_volume = NULL;
1304
            } else {
1305
                BrVector3Scale(&tv, &pCar->bounds[0].min, WORLD_SCALE);
1306
                BrMatrix34ApplyP(&lp, &tv, mat);
1307
                BrVector3InvScale(&lp, &lp, WORLD_SCALE);
1308
                BrVector3Copy(&hp, &lp);
1309
                for (i = 0; i < 3; i++) {
1310
                    val = pCar->bounds[0].max.v[i] - pCar->bounds[0].min.v[i];
1311
                    BrVector3Scale(&tv, (br_vector3*)mat->m[i], val);
1312
                    if (BrVector3Dot(&pCar->water_normal, &tv) > 0.f) {
1313
                        BrVector3Accumulate(&hp, &tv);
1314
                    } else {
1315
                        BrVector3Accumulate(&lp, &tv);
1316
                    }
1317
                }
1318
                BrVector3Sub(&dir, &hp, &lp);
1319
                DisablePlingMaterials();
1320
                FindFloorInBoxBU(&lp, &dir, &tv, &d, pCar);
1321
                EnablePlingMaterials();
1322
                FindFloorInBoxBU(&pos, &dir, &tv, &d2, pCar);
1323
                if (d2 <= d) {
1324
                    pCar->water_depth_factor = 1.f;
1325
                    pCar->auto_special_volume = NULL;
1326
                } else {
1327
                    pCar->auto_special_volume = vol;
1328
                }
1329
            }
1330
        }
1331
    } else {
1332
        pCar->auto_special_volume = NULL;
1333
        pCar->water_depth_factor = 1.f;
1334
    }
1335
}
1336
 
1337
// IDA: void __usercall MoveAndCollideCar(tCar_spec *car@<EAX>, br_scalar dt)
1338
void MoveAndCollideCar(tCar_spec* car, br_scalar dt) {
1339
    tCollision_info* car_info;
1340
    int wheel;
1341
    LOG_TRACE("(%p, %f)", car, dt);
1342
 
1343
    if (car->dt >= 0.f) {
1344
        dt = car->dt;
1345
    }
1346
    if (dt != 0.f && (!gCar_flying || &gProgram_state.current_car != car)) {
1347
        car_info = (tCollision_info*)car;
1348
        car->new_skidding = 0;
1349
        if (car->water_d != 10000.0f) {
1350
            TestAutoSpecialVolume(car_info);
1351
        }
1352
        MungeSpecialVolume(car_info);
1353
        if (car->driver <= eDriver_oppo) {
1354
            CalcForce(car, dt);
1355
        } else {
1356
            CalcEngineForce(car, dt);
1357
            CalcForce(car, dt);
1358
            DoRevs(car, dt);
1359
        }
1360
        RotateCar(car_info, dt);
1361
        TranslateCar(car_info, dt);
1362
        CollideCarWithWall(car_info, dt);
1363
        BrMatrix34ApplyP(&car->pos, &car->cmpos, &car->car_master_actor->t.t.mat);
1364
        BrVector3InvScale(&car->pos, &car->pos, WORLD_SCALE);
1365
        for (wheel = 0; wheel < 4; wheel++) {
1366
            SkidMark(car, wheel);
1367
        }
1368
    }
1369
}
1370
 
1371
// IDA: void __usercall MoveAndCollideNonCar(tNon_car_spec *non_car@<EAX>, br_scalar dt)
1372
void MoveAndCollideNonCar(tNon_car_spec* non_car, br_scalar dt) {
1373
    tCollision_info* car_info;
1374
    LOG_TRACE("(%p, %f)", non_car, dt);
1375
 
1376
    car_info = &non_car->collision_info;
1377
    if (car_info->water_d != 10000.f) {
1378
        TestAutoSpecialVolume(&non_car->collision_info);
1379
    }
1380
    MungeSpecialVolume(&non_car->collision_info);
1381
    if (car_info->dt >= 0.f) {
1382
        dt = car_info->dt;
1383
    }
1384
    NonCarCalcForce(non_car, dt);
1385
    RotateCar(&non_car->collision_info, dt);
1386
    TranslateCar(&non_car->collision_info, dt);
1387
    CollideCarWithWall(&non_car->collision_info, dt);
1388
    BrMatrix34ApplyP(&car_info->pos, &car_info->cmpos, &car_info->car_master_actor->t.t.mat);
1389
    BrVector3InvScale(&car_info->pos, &car_info->pos, WORLD_SCALE);
1390
}
1391
 
1392
// IDA: int __usercall CollideCarWithWall@<EAX>(tCollision_info *car@<EAX>, br_scalar dt)
1393
int CollideCarWithWall(tCollision_info* car, br_scalar dt) {
1394
    LOG_TRACE("(%p, %f)", car, dt);
1395
 
1396
    GetFacesInBox(car);
1397
    if (gCollision_detection_on__car) {
1398
        car->collision_flag = 0;
1399
        while (CollCheck(car, dt)) {
1400
            car->collision_flag++;
1401
            if (car->collision_flag - 1 > 20) {
1402
                car->collision_flag = 1;
1403
                BrVector3Set(&car->v, 0.f, 0.f, 0.f);
1404
                BrVector3Set(&car->omega, 0.f, 0.f, 0.f);
1405
                break;
1406
            }
1407
            RotateCar(car, dt);
1408
            TranslateCar(car, dt);
1409
            GetFacesInBox(car);
1410
        }
1411
        if (car->collision_flag) {
1412
            CrashEarnings(CAR(car), NULL);
1413
        }
1414
        BrMatrix34TApplyV(&car->velocity_car_space, &car->v, &car->oldmat);
1415
        car->frame_collision_flag += car->collision_flag;
1416
    }
1417
    return car->collision_flag;
1418
}
1419
 
1420
// IDA: void __cdecl ToggleControls()
1421
void ToggleControls(void) {
1422
    LOG_TRACE("()");
1423
 
1424
    gControl__car++;
20 pmbaty 1425
    if (ControlCar[gControl__car] == 0) {
1 pmbaty 1426
        gControl__car = 0;
1427
    }
1428
    switch (gControl__car) {
1429
    case 0:
21 pmbaty 1430
        NewTextHeadupSlot(eHeadupSlot_misc, 0, 500, -1, "Original Controls");
1 pmbaty 1431
        break;
1432
    case 1:
21 pmbaty 1433
        NewTextHeadupSlot(eHeadupSlot_misc, 0, 500, -1, "Accelerated steering");
1 pmbaty 1434
        break;
1435
    case 2:
21 pmbaty 1436
        NewTextHeadupSlot(eHeadupSlot_misc, 0, 500, -1, "0.75 Accelerated");
1 pmbaty 1437
        break;
1438
    case 3:
21 pmbaty 1439
        NewTextHeadupSlot(eHeadupSlot_misc, 0, 500, -1, "0.5 Accelerated");
1 pmbaty 1440
        break;
1441
    default:
21 pmbaty 1442
        NewTextHeadupSlot(eHeadupSlot_misc, 0, 500, -1, "New controls");
1 pmbaty 1443
        break;
1444
    }
1445
}
1446
 
1447
// IDA: void __usercall ControlCar2(tCar_spec *c@<EAX>, br_scalar dt)
1448
void ControlCar2(tCar_spec* c, br_scalar dt) {
1449
    LOG_TRACE("(%p, %f)", c, dt);
20 pmbaty 1450
    NOT_IMPLEMENTED();
1 pmbaty 1451
}
1452
 
1453
// IDA: void __usercall ControlCar3(tCar_spec *c@<EAX>, br_scalar dt)
1454
void ControlCar3(tCar_spec* c, br_scalar dt) {
1455
    LOG_TRACE("(%p, %f)", c, dt);
20 pmbaty 1456
    NOT_IMPLEMENTED();
1 pmbaty 1457
}
1458
 
1459
// IDA: void __usercall ControlCar4(tCar_spec *c@<EAX>, br_scalar dt)
1460
void ControlCar4(tCar_spec* c, br_scalar dt) {
1461
    //br_scalar ts; // Pierre-Marie Baty -- unused variable
1462
    LOG_TRACE("(%p, %f)", c, dt);
1463
 
1464
    if (c->keys.left) {
1465
        if (c->turn_speed < 0.f) {
1466
            c->turn_speed = 0.f;
1467
        }
1468
        if (c->velocity_car_space.v[2] > 0.f) {
1469
            c->turn_speed += dt * 0.01f / .04f / 2.f * 2.f;
1470
        } else if ((c->curvature >= 0.f && c->omega.v[1] >= -.001f) || c->turn_speed != 0.f) {
1471
            c->turn_speed += dt / .04f * (0.05f / (BrVector3Length(&c->v) + 5.f)) / 2.f * .5f;
1472
        } else {
1473
            c->turn_speed = dt / .04f * (.05f / (BrVector3Length(&c->v) + 5.f)) * 4.f / 2.f * .5f;
1474
            if (c->omega.v[1] < -.01f) {
1475
                c->turn_speed -= dt * .01f / (harness_game_config.physics_step_time / 1000.f) / 2.f * c->omega.v[1] * 2.f;
1476
            }
1477
        }
1478
    }
1479
    if (c->keys.right) {
1480
        if (c->turn_speed > 0.f) {
1481
            c->turn_speed = 0.f;
1482
        }
1483
        if (c->velocity_car_space.v[2] > 0.f) {
1484
            c->turn_speed -= dt * .01f / .04f / 2.f * 2.f;
1485
        } else if ((c->curvature <= 0.f && c->omega.v[1] <= .001f) || c->turn_speed != 0.f) {
1486
            c->turn_speed -= dt / .04f * (.05f / (BrVector3Length(&c->v) + 5.f)) / 2.f * .5f;
1487
        } else {
1488
            c->turn_speed = dt / .04f * (.05f / (BrVector3Length(&c->v) + 5.f)) * -4.f / 2.f * .5f;
1489
            if (c->omega.v[1] < -.01f) {
1490
                c->turn_speed -= dt * .01f / (harness_game_config.physics_step_time / 1000.f) / 2.f * c->omega.v[1] * 2.f;
1491
            }
1492
        }
1493
    }
1494
    if (!c->keys.left && !c->keys.right) {
1495
        c->turn_speed = 0.f;
1496
    } else if (fabsf(c->turn_speed) < fabsf(dt * 2.f * c->curvature) && c->curvature * c->turn_speed < 0.f) {
1497
        c->turn_speed = -(dt * 2.f * c->curvature);
1498
    }
1499
    c->curvature += c->turn_speed;
1500
    if (c->joystick.left > 0) {
1501
        c->curvature = (float)c->joystick.left * (float)c->joystick.left / 4294967300.f * c->maxcurve;
1502
    } else if (c->joystick.right >= 0) {
1503
        c->curvature = -((float)c->joystick.right * (float)c->joystick.right / 4294967300.f) * c->maxcurve;
1504
    }
1505
    if (c->curvature > c->maxcurve) {
1506
        c->curvature = c->maxcurve;
1507
    }
1508
    if (c->curvature < -c->maxcurve) {
1509
        c->curvature = -c->maxcurve;
1510
    }
1511
}
1512
 
1513
// IDA: void __usercall ControlCar5(tCar_spec *c@<EAX>, br_scalar dt)
1514
void ControlCar5(tCar_spec* c, br_scalar dt) {
1515
    LOG_TRACE("(%p, %f)", c, dt);
20 pmbaty 1516
    NOT_IMPLEMENTED();
1 pmbaty 1517
}
1518
 
1519
// IDA: void __usercall ControlCar1(tCar_spec *c@<EAX>, br_scalar dt)
1520
void ControlCar1(tCar_spec* c, br_scalar dt) {
1521
    LOG_TRACE("(%p, %f)", c, dt);
20 pmbaty 1522
    NOT_IMPLEMENTED();
1 pmbaty 1523
}
1524
 
1525
// IDA: void __usercall setrotate(br_vector3 *wdt@<EAX>, br_matrix34 *m@<EDX>)
1526
void setrotate(br_vector3* wdt, br_matrix34* m) {
20 pmbaty 1527
    //br_euler e; // Pierre-Marie Baty -- unused variable
1 pmbaty 1528
    LOG_TRACE("(%p, %p)", wdt, m);
20 pmbaty 1529
    NOT_IMPLEMENTED();
1 pmbaty 1530
}
1531
 
1532
// IDA: void __usercall RotateCar2(tCollision_info *c@<EAX>, br_scalar dt)
1533
void RotateCar2(tCollision_info* c, br_scalar dt) {
20 pmbaty 1534
    //br_vector3 wdt; // Pierre-Marie Baty -- unused variable
1535
    //br_vector3 wdt2; // Pierre-Marie Baty -- unused variable
1536
    //br_vector3 L; // Pierre-Marie Baty -- unused variable
1537
    //br_vector3 L2; // Pierre-Marie Baty -- unused variable
1538
    //br_matrix34 m; // Pierre-Marie Baty -- unused variable
1 pmbaty 1539
    LOG_TRACE("(%p, %f)", c, dt);
20 pmbaty 1540
    NOT_IMPLEMENTED();
1 pmbaty 1541
}
1542
 
1543
// IDA: void __usercall RotateCarSecondOrder(tCollision_info *c@<EAX>, br_scalar dt)
1544
void RotateCarSecondOrder(tCollision_info* c, br_scalar dt) {
1545
    br_vector3 L;
1546
    br_vector3 L2;
1547
    br_vector3 axis;
1548
    br_vector3 omega;
1549
    br_scalar rad;
1550
    br_scalar rad_rate;
1551
    br_matrix34 m;
1552
    LOG_TRACE("(%p, %f)", c, dt);
1553
 
1554
    rad_rate = BrVector3Length(&c->omega);
1555
    rad = rad_rate * dt;
1556
 
1557
    BrVector3InvScale(&axis, &c->omega, rad_rate);
1558
    BrVector3Mul(&L, &c->I, &c->omega);
1559
 
1560
    BrMatrix34Rotate(&m, BrRadianToAngle(rad) / 2, &axis);
1561
    BrMatrix34TApplyV(&L2, &L, &m);
1562
    omega.v[0] = L2.v[0] / c->I.v[0];
1563
    omega.v[1] = L2.v[1] / c->I.v[1];
1564
    omega.v[2] = L2.v[2] / c->I.v[2];
1565
 
1566
    rad_rate = BrVector3Length(&omega);
1567
    rad = rad_rate * dt;
1568
 
1569
    BrVector3InvScale(&axis, &omega, rad_rate);
1570
    BrMatrix34Rotate(&m, BrRadianToAngle(rad), &axis);
1571
    BrMatrix34PreTranslate(&m, -c->cmpos.v[0], -c->cmpos.v[1], -c->cmpos.v[2]);
1572
    BrMatrix34PostTranslate(&m, c->cmpos.v[0], c->cmpos.v[1], c->cmpos.v[2]);
1573
    BrMatrix34Pre(&c->car_master_actor->t.t.mat, &m);
1574
    BrMatrix34TApplyV(&L2, &L, &m);
1575
    c->omega.v[0] = L2.v[0] / c->I.v[0];
1576
    c->omega.v[1] = L2.v[1] / c->I.v[1];
1577
    c->omega.v[2] = L2.v[2] / c->I.v[2];
1578
}
1579
 
1580
// IDA: void __usercall RotateCarFirstOrder(tCollision_info *c@<EAX>, br_scalar dt)
1581
void RotateCarFirstOrder(tCollision_info* c, br_scalar dt) {
1582
    br_vector3 axis;
1583
    br_vector3 L;
1584
    br_vector3 L2;
1585
    br_matrix34 m;
1586
    br_scalar rad_rate;
1587
    br_scalar rad;
1588
    //br_scalar e1; // Pierre-Marie Baty -- unused variable
1589
    //br_scalar e2; // Pierre-Marie Baty -- unused variable
1590
    static br_scalar max_rad;
1591
    LOG_TRACE("(%p, %f)", c, dt);
1592
 
1593
    rad_rate = BrVector3Length(&c->omega);
1594
    rad = rad_rate * dt;
1595
 
1596
    if (rad < .0001f) {
1597
        return;
1598
    }
1599
    BrVector3InvScale(&axis, &c->omega, rad_rate);
1600
    BrVector3Mul(&L, &c->I, &c->omega);
1601
    BrMatrix34Rotate(&m, BrRadianToAngle(rad), &axis);
1602
    BrMatrix34TApplyV(&L2, &L, &m);
1603
    BrMatrix34PreTranslate(&m, -c->cmpos.v[0], -c->cmpos.v[1], -c->cmpos.v[2]);
1604
    BrMatrix34PostTranslate(&m, c->cmpos.v[0], c->cmpos.v[1], c->cmpos.v[2]);
1605
    BrMatrix34Pre(&c->car_master_actor->t.t.mat, &m);
1606
    c->omega.v[0] = L2.v[0] / c->I.v[0];
1607
    c->omega.v[1] = L2.v[1] / c->I.v[1];
1608
    c->omega.v[2] = L2.v[2] / c->I.v[2];
1609
}
1610
 
1611
// IDA: void __usercall SimpleRotate(tCollision_info *c@<EAX>, br_scalar dt)
1612
void SimpleRotate(tCollision_info* c, br_scalar dt) {
1613
    br_vector3 axis;
1614
    br_scalar rad_rate;
1615
    br_scalar rad;
1616
    LOG_TRACE("(%p, %f)", c, dt);
1617
 
1618
    rad_rate = BrVector3Length(&c->omega);
1619
    BrVector3InvScale(&axis, &c->omega, rad_rate);
1620
    rad = rad_rate * dt;
1621
    if (rad >= 0.0001) {
1622
        BrMatrix34PreRotate(&c->car_master_actor->t.t.mat, BrRadianToAngle(rad), &axis);
1623
    }
1624
}
1625
 
1626
// IDA: void __usercall RotateCar(tCollision_info *c@<EAX>, br_scalar dt)
1627
void RotateCar(tCollision_info* c, br_scalar dt) {
1628
    br_scalar rad_squared;
1629
    int steps;
1630
    int i;
1631
    LOG_TRACE("(%p, %f)", c, dt);
1632
 
1633
    rad_squared = BrVector3LengthSquared(&c->omega) * dt;
1634
    BrVector3Copy(&c->oldomega, &c->omega);
1635
 
1636
    if (rad_squared < .0000001f) {
1637
        return;
1638
    }
1639
 
1640
    if (rad_squared > .008f) {
1641
        steps = sqrtf(rad_squared / .032f) + 1;
1642
        dt = dt / steps;
1643
 
1644
        for (i = 0; i < steps && i < 20; i++) {
1645
            RotateCarSecondOrder(c, dt);
1646
        }
1647
    } else {
1648
        RotateCarFirstOrder(c, dt);
1649
    }
1650
}
1651
 
1652
// IDA: void __usercall SteeringSelfCentre(tCar_spec *c@<EAX>, br_scalar dt, br_vector3 *n)
1653
void SteeringSelfCentre(tCar_spec* c, br_scalar dt, br_vector3* n) {
1654
    br_scalar ts;
1655
    br_scalar ts2;
1656
    LOG_TRACE("(%p, %f, %p)", c, dt, n);
1657
 
1658
    if (c->curvature > c->maxcurve) {
1659
        c->curvature = c->maxcurve;
1660
    }
1661
    if (-c->maxcurve > c->curvature) {
1662
        c->curvature = -c->maxcurve;
1663
    }
1664
    if (!c->keys.left && c->joystick.left <= 0 && !c->keys.right && c->joystick.right <= 0 && !c->keys.holdw) {
1665
        if (c->susp_height[1] > c->oldd[2] || c->susp_height[1] > c->oldd[3]) {
1666
            ts = -((c->omega.v[2] * n->v[2] + c->omega.v[1] * n->v[1] + c->omega.v[0] * n->v[0]) * (dt / (c->wpos[0].v[2] - c->wpos[2].v[2])));
1667
            ts2 = -(c->curvature * dt);
1668
            if (fabs(ts) < fabs(ts2) || (ts * ts2 < 0.0)) {
1669
                ts = ts2;
1670
            }
1671
            c->curvature = c->curvature + ts;
1672
            if (c->curvature * ts > 0.0) {
1673
                c->curvature = 0.0;
1674
            }
1675
        }
1676
    }
1677
}
1678
 
1679
// IDA: void __usercall NonCarCalcForce(tNon_car_spec *nc@<EAX>, br_scalar dt)
1680
void NonCarCalcForce(tNon_car_spec* nc, br_scalar dt) {
1681
    tCollision_info* c;
1682
    tSpecial_volume* vol;
1683
    br_scalar ts;
1684
    br_vector3 tv;
1685
    br_vector3 v;
1686
    LOG_TRACE("(%p, %f)", nc, dt);
1687
 
1688
    c = &nc->collision_info;
1689
    vol = nc->collision_info.last_special_volume;
1690
    if (nc->collision_info.car_master_actor->identifier[3] != '!') {
1691
        if (c->car_master_actor->t.t.mat.m[1][1] < nc->snap_off_cosine || c->min_torque_squared == 0.0f) {
1692
            c->car_master_actor->identifier[3] = '!';
1693
            c->M = nc->free_mass;
1694
            c->min_torque_squared = 0.0f;
1695
            BrVector3Sub(&v, &nc->free_cmpos, &c->cmpos);
1696
            BrVector3Cross(&tv, &c->omega, &v);
1697
            BrMatrix34ApplyV(&v, &tv, &c->car_master_actor->t.t.mat);
1698
            BrVector3Accumulate(&c->v, &v);
1699
            c->cmpos = nc->free_cmpos;
1700
        } else {
1701
            BrVector3SetFloat(&c->v, 0.0f, 0.0f, 0.0f);
1702
            ts = BrVector3LengthSquared(&c->omega);
1703
            BrVector3SetFloat(&c->omega, 0.0f, 0.0f, 0.0f);
1704
            c->doing_nothing_flag = 1;
1705
        }
1706
    }
1707
    if (c->car_master_actor->identifier[3] == '!') {
1708
        if (vol != NULL) {
1709
            c->v.v[1] = c->v.v[1] - dt * 10.0f * vol->gravity_multiplier;
1710
        } else {
1711
            c->v.v[1] = c->v.v[1] - dt * 10.0f;
1712
        }
1713
        ts = BrVector3Length(&c->v);
1714
        if (vol != NULL) {
1715
            ts = vol->viscosity_multiplier * ts;
1716
        }
1717
        ts = -(dt * 0.0005f * ts) / c->M;
1718
        BrVector3Scale(&v, &c->v, ts);
1719
        BrVector3Accumulate(&c->v, &v);
1720
        ts = BrVector3Length(&c->omega);
1721
        if (vol != NULL) {
1722
            ts = vol->viscosity_multiplier * ts;
1723
        }
1724
        ts = -(dt * 0.0005 * ts);
1725
        BrVector3Scale(&v, &c->omega, ts);
1726
        ApplyTorque(CAR(c), &v);
1727
    }
1728
}
1729
 
1730
// IDA: void __usercall AddDrag(tCar_spec *c@<EAX>, br_scalar dt)
1731
void AddDrag(tCar_spec* c, br_scalar dt) {
1732
    br_scalar drag_multiplier;
1733
    br_scalar ts;
1734
    tSpecial_volume* vol;
1735
    br_vector3 b;
1736
    LOG_TRACE("(%p, %f)", c, dt);
1737
 
1738
    vol = c->last_special_volume;
1739
    drag_multiplier = -(dt * TIME_CONV_THING);
1740
    if (vol != NULL) {
1741
        if (c->underwater_ability) {
1742
            drag_multiplier = vol->viscosity_multiplier * drag_multiplier * .6f;
1743
        } else {
1744
            drag_multiplier = vol->viscosity_multiplier * drag_multiplier;
1745
        }
1746
        drag_multiplier = c->water_depth_factor * drag_multiplier;
1747
    }
1748
    ts = BrVector3Length(&c->v) * drag_multiplier / c->M;
1749
    BrVector3Scale(&b, &c->v, ts);
1750
    BrVector3Accumulate(&c->v, &b);
1751
    ts = BrVector3Length(&c->omega) * drag_multiplier;
1752
    BrVector3Scale(&b, &c->omega, ts);
1753
    ApplyTorque(c, &b);
1754
}
1755
 
1756
// IDA: void __usercall DoBumpiness(tCar_spec *c@<EAX>, br_vector3 *wheel_pos@<EDX>, br_vector3 *norm@<EBX>, br_scalar *d@<ECX>, int n)
1757
void DoBumpiness(tCar_spec* c, br_vector3* wheel_pos, br_vector3* norm, br_scalar* d, int n) {
1758
    br_vector3 tv;
1759
    int delta;
1760
    int x;
1761
    int y;
1762
    tMaterial_modifiers* mat_list;
1763
    LOG_TRACE("(%p, %p, %p, %p, %d)", c, wheel_pos, norm, d, n);
1764
 
1765
    tv.v[0] = c->nor[n].v[0] * d[n] + wheel_pos[n].v[0];
1766
    tv.v[2] = c->nor[n].v[2] * d[n] + wheel_pos[n].v[2];
1767
 
1768
    x = abs((int)(512.0f * tv.v[0])) % 2048;
1769
    y = abs((int)(512.0f * tv.v[2])) % 2048;
1770
 
1771
    if (x > 1024) {
1772
        x = 2048 - x;
1773
    }
1774
    if (y > 1024) {
1775
        y = 2048 - y;
1776
    }
1777
    if (x + y <= 1024) {
1778
        delta = x + y;
1779
    } else {
1780
        delta = 2048 - x - y;
1781
    }
1782
    delta -= 400;
1783
    if (delta < 0) {
1784
        delta = 0;
1785
    }
1786
    mat_list = gCurrent_race.material_modifiers;
1787
    d[n] = delta * mat_list[c->material_index[n]].bumpiness / 42400.0f * norm[n].v[1] + d[n];
1788
}
1789
 
1790
// IDA: void __usercall CalcForce(tCar_spec *c@<EAX>, br_scalar dt)
1791
void CalcForce(tCar_spec* c, br_scalar dt) {
1792
    //int n; // Pierre-Marie Baty -- unused variable
1793
    int normnum;
1794
    int i;
1795
    //int x; // Pierre-Marie Baty -- unused variable
1796
    //int y; // Pierre-Marie Baty -- unused variable
1797
    br_scalar force[4];
1798
    br_scalar d[4];
1799
    br_scalar ts;
1800
    br_scalar ts2;
1801
    br_scalar ts3;
1802
    br_scalar ts4;
1803
    //br_scalar ts5; // Pierre-Marie Baty -- unused variable
1804
    //br_scalar ts6; // Pierre-Marie Baty -- unused variable
1805
    br_scalar deltaomega;
1806
    br_scalar wheelratio;
1807
    //br_scalar modf; // Pierre-Marie Baty -- unused variable
1808
    br_scalar maxfl;
1809
    br_scalar maxfr;
1810
    //br_scalar max_retardation; // Pierre-Marie Baty -- unused variable
1811
    //br_scalar front_retardation; // Pierre-Marie Baty -- unused variable
1812
    br_scalar friction_number;
1813
    br_vector3 a;
1814
    br_vector3 b;
1815
    //br_vector3 tv; // Pierre-Marie Baty -- unused variable
1816
    //br_vector3 tv2; // Pierre-Marie Baty -- unused variable
1817
    br_vector3 norm[4];
1818
    //br_vector3 v_batwick; // Pierre-Marie Baty -- unused variable
1819
    br_vector3 vplane;
1820
    br_vector3 rightplane;
1821
    //br_vector3 t; // Pierre-Marie Baty -- unused variable
1822
    br_vector3 f;
1823
    //br_vector3 ff; // Pierre-Marie Baty -- unused variable
1824
    //br_vector3 fb; // Pierre-Marie Baty -- unused variable
1825
    //br_scalar ffi; // Pierre-Marie Baty -- unused variable
1826
    //br_scalar ffk; // Pierre-Marie Baty -- unused variable
1827
    //br_scalar fbi; // Pierre-Marie Baty -- unused variable
1828
    //br_scalar fbk; // Pierre-Marie Baty -- unused variable
1829
    br_vector3 wheel_pos[4];
1830
    //br_scalar direction; // Pierre-Marie Baty -- unused variable
1831
    //br_scalar wheel_spin_force; // Pierre-Marie Baty -- unused variable
1832
    //br_scalar d_damage; // Pierre-Marie Baty -- unused variable
1833
    br_scalar fl_oil_factor;
1834
    br_scalar fr_oil_factor;
1835
    br_scalar rl_oil_factor;
1836
    br_scalar rr_oil_factor;
1837
    br_matrix34* mat;
1838
    tMaterial_modifiers* mat_list;
1839
    static br_scalar stop_timer;
1840
    static br_scalar slide_dist;
1841
    //tDamage_type dam; // Pierre-Marie Baty -- unused variable
1842
    //br_scalar v; // Pierre-Marie Baty -- unused variable
1843
    tSpecial_volume* vol;
1844
    //br_scalar scale; // Pierre-Marie Baty -- unused variable
1845
    LOG_TRACE("(%p, %f)", c, dt);
1846
 
1847
    int v72;         // [esp+24h] [ebp-1C8h]
1848
    double v73;      // [esp+2Ch] [ebp-1C0h]
1849
    float v74;       // [esp+34h] [ebp-1B8h]
1850
    float v75;       // [esp+38h] [ebp-1B4h]
1851
    float v76;       // [esp+3Ch] [ebp-1B0h]
1852
    float v77;       // [esp+40h] [ebp-1ACh]
1853
    float v78;       // [esp+44h] [ebp-1A8h]
1854
    float v79;       // [esp+48h] [ebp-1A4h]
1855
    //float v80;       // [esp+4Ch] [ebp-1A0h] MAPDST // Pierre-Marie Baty -- unused variable
1856
    //float v82;       // [esp+50h] [ebp-19Ch] MAPDST // Pierre-Marie Baty -- unused variable
1857
    //float v84;       // [esp+54h] [ebp-198h] // Pierre-Marie Baty -- unused variable
1858
    //float v85;       // [esp+58h] [ebp-194h] MAPDST // Pierre-Marie Baty -- unused variable
1859
    float v87;       // [esp+5Ch] [ebp-190h] MAPDST
1860
    float v98;       // [esp+88h] [ebp-164h]
1861
    float v99;       // [esp+8Ch] [ebp-160h]
1862
    br_vector3 v102; // [esp+98h] [ebp-154h]
1863
    br_vector3 v103; // [esp+A4h] [ebp-148h]
1864
    int v105;        // [esp+B8h] [ebp-134h]
1865
    float v106;      // [esp+C0h] [ebp-12Ch]
1866
    br_vector3 v107; // [esp+C4h] [ebp-128h]
1867
    float v108;      // [esp+D0h] [ebp-11Ch]
1868
    float v109;      // [esp+D4h] [ebp-118h]
1869
    float v116;      // [esp+F8h] [ebp-F4h]
1870
    br_vector3 B;    // [esp+FCh] [ebp-F0h] BYREF
1871
    br_scalar pV;    // [esp+10Ch] [ebp-E0h]
1872
    br_vector3 v123; // [esp+130h] [ebp-BCh]
1873
    float v125;      // [esp+16Ch] [ebp-80h]
1874
    float v128;      // [esp+18Ch] [ebp-60h]
1875
    float v129;      // [esp+190h] [ebp-5Ch]
1876
    float v134;      // [esp+1D8h] [ebp-14h]
1877
    float v135;      // [esp+1DCh] [ebp-10h]
1878
    br_vector3 v136; // [esp+1E0h] [ebp-Ch]
1879
 
1880
    BrVector3Set(&v136, 0, 0, 0);
1881
    normnum = 0;
1882
    BrVector3Set(&f, 0, 0, 0);
1883
    BrVector3Set(&B, 0, 0, 0);
1884
    mat = &c->car_master_actor->t.t.mat;
1885
    mat_list = gCurrent_race.material_modifiers;
1886
    vol = c->last_special_volume;
1887
    b.v[0] = -mat->m[1][0];
1888
    b.v[1] = -mat->m[1][1];
1889
    b.v[2] = -mat->m[1][2];
1890
    c->material_index[0] = 0;
1891
    c->material_index[1] = 0;
1892
    c->material_index[2] = 0;
1893
    c->material_index[3] = 0;
1894
    wheelratio = (c->wpos[2].v[2] - c->cmpos.v[2]) / (c->wpos[0].v[2] - c->cmpos.v[2]);
1895
    BrVector3Set(&c->road_normal, 0, 0, 0);
1896
    for (i = 0; i < 4; ++i) {
1897
        BrMatrix34ApplyP(&wheel_pos[i], &c->wpos[i], mat);
1898
    }
1899
    MultiFindFloorInBoxM(4, wheel_pos, &b, c->nor, d, c, c->material_index);
1900
    if (c->last_special_volume && c->last_special_volume->material_modifier_index) {
1901
        c->material_index[0] = c->last_special_volume->material_modifier_index;
1902
        c->material_index[1] = c->material_index[0];
1903
        c->material_index[2] = c->material_index[1];
1904
        c->material_index[3] = c->material_index[2];
1905
    }
1906
    for (i = 0; i < 4; ++i) {
1907
        BrMatrix34TApplyV(&norm[i], &c->nor[i], mat);
1908
        if (mat_list[c->material_index[i]].bumpiness != 0.0) {
1909
            DoBumpiness(c, wheel_pos, norm, d, i);
1910
        }
1911
        if (d[i] < -0.5 || c->wheel_dam_offset[i ^ 2] * 6.9 + c->susp_height[i / 2] < d[i]) {
1912
            force[i] = 0.0;
1913
            d[i] = c->susp_height[i / 2];
1914
        } else {
1915
            BrVector3Accumulate(&c->road_normal, &norm[i]);
1916
            normnum++;
1917
            d[i] = d[i] - c->wheel_dam_offset[i ^ 2] * 6.9;
1918
            force[i] = (c->susp_height[i / 2] - d[i]) * c->sk[1 / 2];
1919
            force[i] = force[i] - (d[i] - c->oldd[i]) / dt * c->sb[i / 2];
1920
            if (c->susp_height[i / 2] == c->oldd[i]
1921
                && c->nor[i].v[2] * c->v.v[2] + c->nor[i].v[1] * c->v.v[1] + c->nor[i].v[0] * c->v.v[0] > -0.0099999998
1922
                && c->M * 20.0 / 4.0 < force[i]) {
1923
                d[i] = c->susp_height[i / 2];
1924
                force[i] = c->M * 20.0 / 4.0;
1925
            }
1926
            if (force[i] < 0.0) {
1927
                force[i] = 0.0;
1928
            }
1929
            B.v[1] = force[i] + B.v[1];
1930
            f.v[0] = f.v[0] - (c->wpos[i].v[2] - c->cmpos.v[2]) * force[i];
1931
            f.v[2] = (c->wpos[i].v[0] - c->cmpos.v[0]) * force[i] + f.v[2];
1932
        }
1933
        c->oldd[i] = d[i];
1934
    }
1935
    if (c->driver <= eDriver_non_car || !c->wall_climber_mode || (c->road_normal.v[0] == 0.0 && c->road_normal.v[1] == 0.0 && c->road_normal.v[2] == 0.0)) {
1936
        if (vol) {
1937
            friction_number = (1.0 - vol->gravity_multiplier) * c->water_depth_factor;
1938
            if (c->underwater_ability) {
1939
                friction_number = friction_number * 0.6;
1940
            }
1941
            friction_number = (1.0 - friction_number) * c->M;
1942
        } else {
1943
            friction_number = c->M;
1944
        }
1945
        friction_number = friction_number * gGravity_multiplier * 10.0;
1946
        B.v[0] = B.v[0] - mat->m[0][1] * friction_number;
1947
        B.v[1] = B.v[1] - mat->m[1][1] * friction_number;
1948
        B.v[2] = B.v[2] - mat->m[2][1] * friction_number;
1949
    } else {
1950
        BrVector3Normalise(&v107, &c->road_normal);
1951
        BrVector3Scale(&v107, &v107, -(c->M * 10.0));
1952
        BrVector3Accumulate(&B, &v107);
1953
    }
1954
    if (c->driver >= eDriver_net_human) {
1955
        SteeringSelfCentre(c, dt, &c->road_normal);
1956
    }
1957
    if (normnum) {
1958
        // ts = 1.0 / sqrt(1.0); <- looked like this in the windows build definitely wrong
1959
        // ts = 1.0 / sqrt(c->road_normal.v[0] * c->road_normal.v[0] + c->road_normal.v[1] * c->road_normal.v[1] + c->road_normal.v[2] * c->road_normal.v[2]);
1960
        // c->road_normal.v[0] = c->road_normal.v[0] * ts;
1961
        // c->road_normal.v[1] = c->road_normal.v[1] * ts;
1962
        // c->road_normal.v[2] = c->road_normal.v[2] * ts;
1963
        BrVector3NormaliseQuick(&c->road_normal, &c->road_normal);
1964
 
1965
        friction_number = c->road_normal.v[1] * mat->m[1][1] + c->road_normal.v[2] * mat->m[2][1] + c->road_normal.v[0] * mat->m[0][1];
1966
        if (c->driver > eDriver_non_car && c->wall_climber_mode) {
1967
            friction_number = 1.0;
1968
        }
1969
        friction_number = gCurrent_race.material_modifiers[c->material_index[0]].down_force * friction_number;
1970
        if (friction_number > 0.0f) {
1971
            friction_number = fabs(c->velocity_car_space.v[2]) * c->M * 10.0 * friction_number / c->down_force_speed;
1972
            if (c->M * 10.0 < friction_number) {
1973
                friction_number = c->M * 10.0;
1974
            }
1975
            if (c->number_of_wheels_on_ground == 4 && c->oldd[2] == c->susp_height[1] && c->oldd[3] == c->susp_height[1]) {
1976
                a.v[0] = c->wpos[2].v[2] * mat->m[2][0];
1977
                a.v[1] = c->wpos[2].v[2] * mat->m[2][1];
1978
                a.v[2] = c->wpos[2].v[2] * mat->m[2][2];
1979
                a.v[0] = mat->m[3][0] + a.v[0];
1980
                a.v[1] = mat->m[3][1] + a.v[1];
1981
                a.v[2] = mat->m[3][2] + a.v[2];
1982
                BrVector3Scale(&b, &b, (c->wpos[0].v[2] - c->wpos[2].v[2]));
1983
                findfloor(&a, &b, norm, &ts2);
1984
                if (ts2 > 1.0) {
1985
                    c->down_force_flag = 1;
1986
                }
1987
            } else if (c->down_force_flag && (c->oldd[2] < c->susp_height[1] || c->oldd[3] < c->susp_height[1])) {
1988
                c->down_force_flag = 0;
1989
            }
1990
            if (c->down_force_flag) {
1991
                friction_number = (c->wpos[2].v[2] - c->cmpos.v[2]) / (c->wpos[2].v[2] - c->wpos[0].v[2]) * friction_number;
1992
                f.v[0] = (c->wpos[0].v[2] - c->cmpos.v[2]) * friction_number + f.v[0];
1993
            }
1994
            B.v[1] = B.v[1] - friction_number;
1995
        }
1996
        vplane.v[0] = BrVector3Dot(&c->velocity_car_space, &c->road_normal) * c->road_normal.v[0];
1997
        vplane.v[1] = BrVector3Dot(&c->velocity_car_space, &c->road_normal) * c->road_normal.v[1];
1998
        vplane.v[2] = BrVector3Dot(&c->velocity_car_space, &c->road_normal) * c->road_normal.v[2];
1999
        BrVector3Sub(&vplane, &c->velocity_car_space, &vplane);
2000
        if (vplane.v[2] < 0.0) {
2001
            ts = 1.0;
2002
        } else {
2003
            ts = -1.0;
2004
        }
2005
        ts3 = BrVector3Length(&vplane);
2006
        deltaomega = ts3 * c->curvature * ts;
2007
        deltaomega = deltaomega - BrVector3Dot(&c->omega, &c->road_normal);
2008
        BrVector3Set(&v103, c->road_normal.v[1], -c->road_normal.v[0], 0);
2009
        BrVector3Normalise(&v103, &v103);
2010
 
2011
        friction_number = c->I.v[1] / dt * deltaomega;
2012
        ts = friction_number / (c->wpos[2].v[2] - c->wpos[0].v[2]);
2013
        v108 = ts;
2014
        v109 = -ts;
2015
        BrVector3Set(&rightplane, 0, c->road_normal.v[2], -c->road_normal.v[1]);
2016
        BrVector3Normalise(&rightplane, &rightplane);
2017
        v99 = c->acc_force;
2018
        friction_number = BrVector3Dot(&rightplane, &vplane);
2019
        v87 = BrVector3Dot(&v103, &vplane);
2020
        ts2 = fabs(v87);
2021
        friction_number = (c->wpos[0].v[2] - c->cmpos.v[2]) * friction_number * fabs(c->curvature);
2022
        if (c->curvature <= 0.0) {
2023
            friction_number = v87 - friction_number;
2024
        } else {
2025
            friction_number = v87 + friction_number;
2026
        }
2027
        friction_number = -(c->M / dt * friction_number);
2028
        friction_number = friction_number - BrVector3Dot(&B, &v103);
2029
 
2030
        friction_number = friction_number / (1.0 - wheelratio);
2031
        v108 = friction_number + v108;
2032
        v109 = -wheelratio * friction_number + v109;
2033
        friction_number = (c->wpos[0].v[2] - c->wpos[2].v[2]) * v108;
2034
        v98 = friction_number * c->curvature;
2035
        friction_number = BrVector3Dot(&c->velocity_car_space, &rightplane) * c->M / dt;
2036
        v129 = BrVector3Dot(&rightplane, &B) + friction_number;
2037
        v128 = c->mu[0] * c->brake_force / (c->mu[1] / c->friction_elipticity + c->mu[0]);
2038
        v125 = c->brake_force - v128;
2039
        v105 = (c->damage_units[7].damage_level + c->damage_units[6].damage_level) / 2;
2040
        if (v105 > 20) {
2041
            v128 = (1.0 - (double)(v105 - 20) / 80.0) * (1.0 - (double)(v105 - 20) / 80.0) * v128;
2042
        }
2043
        v105 = (c->damage_units[5].damage_level + c->damage_units[4].damage_level) / 2;
2044
        if (v105 > 20) {
2045
            v125 = (1.0 - (double)(v105 - 20) / 80.0) * (1.0 - (double)(v105 - 20) / 80.0) * v125;
2046
        }
2047
        ts2 = (force[1] + force[0]) * c->rolling_r_back + v128;
2048
        v87 = (force[2] + force[3]) * c->rolling_r_front + v125;
2049
        v128 = c->wpos[0].v[2] - c->wpos[2].v[2];
2050
        v128 = sqrt(v128 * v128 * c->curvature * c->curvature + 1.0);
2051
        v106 = v87 / v128;
2052
        v134 = v106 + ts2;
2053
        if (fabs(v129) < fabs(v134)) {
2054
            ts2 = v129 / v134 * ts2;
2055
            v106 = v129 / v134 * v106;
2056
        }
2057
        if ((v87 + ts2) * v129 < 0.0) {
2058
            ts2 = -ts2;
2059
            v106 = -v106;
2060
        }
2061
        v129 = v129 - (ts2 + v106);
2062
        v99 = v99 - ts2;
2063
        if (c->keys.brake && c->damage_units[eDamage_lr_brake].damage_level < 60 && c->damage_units[eDamage_rr_brake].damage_level < 60) {
2064
            v99 = v99 - v129;
2065
            c->gear = 0;
2066
        }
2067
        v99 = v99 / c->friction_elipticity;
2068
        v135 = sqrt(v99 * v99 + v109 * v109) / 2.0;
2069
 
2070
        GetOilFrictionFactors(c, &fl_oil_factor, &fr_oil_factor, &rl_oil_factor, &rr_oil_factor);
2071
        if (c->driver <= eDriver_non_car) {
2072
            v116 = 1.0;
2073
        } else {
2074
            v116 = c->grip_multiplier;
2075
        }
2076
        BrVector3Sub(&v102, &c->wpos[0], &c->cmpos);
2077
        BrVector3Cross(&a, &c->omega, &v102);
2078
        BrVector3Accumulate(&a, &c->velocity_car_space);
2079
        if (c->driver >= eDriver_net_human
2080
            && (((c->keys.left || c->joystick.left > 0x8000) && c->curvature > 0.0 && deltaomega > 0.1 && a.v[0] > 0.0)
2081
                || ((c->keys.right || c->joystick.right > 0x8000) && c->curvature < 0.0 && deltaomega < 0.1 && a.v[0] < 0.0))
2082
            && ts > 0.0) {
2083
            friction_number = c->mu[0];
2084
        } else {
2085
            friction_number = c->mu[2];
2086
            ts2 = fabs(a.v[0]) / 10.0;
2087
            if (ts2 > 1) {
2088
                ts2 = 1.0;
2089
            }
2090
            friction_number = (c->mu[2] - c->mu[0]) * ts2 + friction_number;
2091
        }
2092
 
2093
        maxfl = sqrt(force[0]) * friction_number * (rl_oil_factor * v116) * mat_list[c->material_index[0]].tyre_road_friction;
2094
        maxfr = sqrt(force[1]) * friction_number * (rr_oil_factor * v116) * mat_list[c->material_index[1]].tyre_road_friction;
2095
        c->max_force_rear = maxfr + maxfl;
2096
        if (rl_oil_factor == 1.0 && rr_oil_factor == 1.0 && c->traction_control && v135 * 2.0 > c->max_force_rear && c->acc_force > 0.0
2097
            && (c->driver < eDriver_net_human || (c->target_revs > 1000.0 && c->gear > 0))) {
2098
            ts2 = v99;
2099
            if (v99 * v99 <= v135 * v135 * 4.0) {
2100
                v87 = sqrt(v135 * v135 * 4.0 - v99 * v99);
2101
            } else {
2102
                v87 = 0.0;
2103
            }
2104
            if (c->max_force_rear <= v87) {
2105
                c->torque = -(c->revs * c->revs / 100000000.0) - 0.1;
2106
            } else {
2107
                float v177 = sqrt(c->max_force_rear * c->max_force_rear - v87 * v87);
2108
                ts3 = ts2 < 0.0 ? -1.0 : 1.0;
2109
                // ts4 = (ts2 - ts3 * sqrt(ts3)) * 1.01;
2110
                // if (fabs(ts2) > fabs(ts4)) {
2111
                //     v87 = ts4;
2112
                //     ts2 = v87;
2113
                // }
2114
 
2115
                ts4 = (ts2 - ts3 * v177) * 1.01;
2116
                if (fabs(ts2) > fabs(ts4)) {
2117
                    ts2 = ts4;
2118
                }
2119
            }
2120
            v99 = v99 - ts2;
2121
            v135 = sqrt(v99 * v99 + v109 * v109) / 2.0;
2122
 
2123
        } else if (c->driver >= eDriver_net_human && c->gear > 0 && c->revs > c->target_revs && !c->traction_control) {
2124
            if (!c->keys.change_down) {
2125
                c->traction_control = 1;
2126
            }
2127
            friction_number = 1.0 - (c->revs - c->target_revs) / (double)(400 * c->gear);
2128
            if (friction_number < 0.40000001) {
2129
                friction_number = (br_scalar) 0.40000001; // Pierre-Marie Baty -- added type cast
2130
            }
2131
            maxfl = friction_number * maxfl;
2132
            maxfr = friction_number * maxfr;
2133
        }
2134
        if (fabs(v109) > maxfr + maxfl && maxfr + maxfl > 0.1) {
2135
            v87 = (maxfr + maxfl) / fabs(v109) * dt;
2136
            v109 = v87 * v109;
2137
            v99 = c->friction_elipticity * v87 * v99;
2138
            friction_number = -((c->wpos[2].v[2] - c->cmpos.v[2]) * v108 * ((c->wpos[2].v[2] - c->cmpos.v[2]) * v108) / c->I.v[1] + (v98 * v98 + v108 * v108) / c->M);
2139
            ts2 = (BrVector3Dot(&v103, &vplane) + v109 / c->M) * v108;
2140
            ts2 = BrVector3Dot(&rightplane, &vplane) * v98 + ts2;
2141
            ts2 = BrVector3Dot(&c->omega, &c->road_normal) * (c->wpos[2].v[2] - c->cmpos.v[2]) * v108 + ts2;
2142
            ts2 = (c->wpos[0].v[2] - c->cmpos.v[2]) * (c->wpos[2].v[2] - c->cmpos.v[2]) * v109 / c->I.v[1] * v108 + ts2;
2143
            if (fabs(friction_number) > 0.1) {
2144
                friction_number = ts2 / (friction_number * dt);
2145
                v108 = friction_number * v108;
2146
                v98 = friction_number * v98;
2147
            }
2148
            v109 = v109 / v87;
2149
            v99 = v99 / (c->friction_elipticity * v87);
2150
        }
2151
        v98 = v98 - v106;
2152
        v108 = (c->wpos[0].v[2] - c->wpos[2].v[2]) * c->curvature * v106 + v108;
2153
        if (v135 > 0.000099999997) {
2154
            v109 = v109 / (v135 * 2.0);
2155
            v99 = v99 / (v135 * 2.0);
2156
        }
2157
        v99 = c->friction_elipticity * v99;
2158
        force[0] = v135;
2159
        force[1] = v135;
2160
        c->wheel_slip = 0;
2161
        switch ((force[0] > maxfl) + 2 * (force[1] > maxfr)) {
2162
        case 0:
2163
            slide_dist = 0;
2164
            break;
2165
        case 1:
2166
            force[0] = c->freduction * maxfl;
2167
            force[1] = v135 - force[0] + force[1];
2168
            if (force[1] <= maxfr) {
2169
                slide_dist = 0;
2170
            } else {
2171
                if (maxfr > 0.1) {
2172
                    pV = (force[1] - maxfr) / maxfr;
2173
                    if (&gProgram_state.current_car == c) {
2174
                        v78 = 20.0;
2175
                    } else {
2176
                        v78 = 60.0;
2177
                    }
2178
                    if (v78 <= pV) {
2179
                        c->new_skidding |= 2u;
2180
                    }
2181
                    SkidNoise(c, 1, pV, c->material_index[1]);
2182
                }
2183
                force[1] = c->freduction * maxfr;
2184
                c->wheel_slip |= 2u;
2185
            }
2186
            break;
2187
        case 2:
2188
            force[1] = c->freduction * maxfr;
2189
            force[0] = v135 - force[1] + force[0];
2190
            if (force[0] <= maxfl) {
2191
                slide_dist = 0;
2192
            } else {
2193
                if (maxfl > 0.1) {
2194
                    pV = (force[0] - maxfl) / maxfl;
2195
                    if (&gProgram_state.current_car == c) {
2196
                        v77 = 20.0;
2197
                    } else {
2198
                        v77 = 60.0;
2199
                    }
2200
                    if (v77 <= pV) {
2201
                        c->new_skidding |= 1u;
2202
                    }
2203
                    SkidNoise(c, 0, pV, c->material_index[0]);
2204
                }
2205
                force[0] = c->freduction * maxfl;
2206
                c->wheel_slip |= 2u;
2207
            }
2208
            break;
2209
        case 3:
2210
            force[0] = c->freduction * maxfl;
2211
            force[1] = c->freduction * maxfr;
2212
            c->wheel_slip |= 2u;
2213
            pV = (v135 * 2.0 - maxfl - maxfr) / (maxfr + maxfl);
2214
            if (&gProgram_state.current_car == c) {
2215
                v79 = 20.0;
2216
            } else {
2217
                v79 = 60.0;
2218
            }
2219
            if (v79 <= pV) {
2220
                if (maxfl > 0.1) {
2221
                    c->new_skidding |= 1u;
2222
                }
2223
                if (maxfr > 0.1) {
2224
                    c->new_skidding |= 2u;
2225
                }
2226
            }
2227
            if (IRandomBetween(0, 1)) {
2228
                if (maxfl > 0.1) {
2229
                    SkidNoise(c, 0, pV, c->material_index[0]);
2230
                }
2231
            } else if (maxfr > 0.1) {
2232
                SkidNoise(c, 1, pV, c->material_index[1]);
2233
            }
2234
            break;
2235
        default:
2236
            break;
2237
        }
2238
        if (c->wheel_slip && c->curvature * c->turn_speed > 0.0 && fabs(v109) > 0.0099999998 && c->curvature * v109 < 0.0 && !c->keys.brake && !c->keys.change_down) {
2239
            c->turn_speed = 0.0;
2240
        }
2241
        v135 = sqrt(v108 * v108 + v98 * v98) / 2.0;
2242
        if (v135 > 0.000099999997) {
2243
            v108 = v108 / (v135 * 2.0);
2244
            v98 = v98 / (v135 * 2.0);
2245
        }
2246
        maxfl = sqrt(force[2]) * c->mu[1] * (fl_oil_factor * v116) * mat_list[c->material_index[2]].tyre_road_friction;
2247
        maxfr = sqrt(force[3]) * c->mu[1] * (fr_oil_factor * v116) * mat_list[c->material_index[3]].tyre_road_friction;
2248
        c->max_force_front = maxfr + maxfl;
2249
        force[2] = v135;
2250
        force[3] = v135;
2251
        v72 = (v135 > maxfl) + 2 * (v135 > maxfr);
2252
        switch (v72) {
2253
        case 1:
2254
            force[2] = c->freduction * maxfl;
2255
            force[3] = v135 - force[2] + force[3];
2256
            if (force[3] > maxfr) {
2257
                if (maxfr > 0.1) {
2258
                    pV = (force[3] - maxfr) / maxfr;
2259
                    if (&gProgram_state.current_car == c) {
2260
                        v75 = 20.0;
2261
                    } else {
2262
                        v75 = 60.0;
2263
                    }
2264
                    if (v75 <= pV) {
2265
                        c->new_skidding |= 8u;
2266
                    }
2267
                    SkidNoise(c, 3, pV, c->material_index[3]);
2268
                }
2269
                force[3] = c->freduction * maxfr;
2270
                c->wheel_slip |= 1u;
2271
            }
2272
            break;
2273
        case 2:
2274
            force[3] = c->freduction * maxfr;
2275
            force[2] = v135 - force[3] + force[2];
2276
            if (force[2] > maxfl) {
2277
                if (maxfl > 0.1) {
2278
                    pV = (force[2] - maxfl) / maxfl;
2279
                    if (&gProgram_state.current_car == c) {
2280
                        v74 = 20.0;
2281
                    } else {
2282
                        v74 = 60.0;
2283
                    }
2284
                    if (v74 <= pV) {
2285
                        c->new_skidding |= 4u;
2286
                    }
2287
                    SkidNoise(c, 2, pV, c->material_index[2]);
2288
                }
2289
                force[2] = c->freduction * maxfl;
2290
                c->wheel_slip |= 1u;
2291
            }
2292
            break;
2293
        case 3:
2294
            force[2] = c->freduction * maxfl;
2295
            force[3] = c->freduction * maxfr;
2296
            c->wheel_slip |= 1u;
2297
            pV = (v135 * 2.0 - maxfl - maxfr) / (maxfr + maxfl);
2298
            if (&gProgram_state.current_car == c) {
2299
                v76 = 20.0;
2300
            } else {
2301
                v76 = 60.0;
2302
            }
2303
            if (v76 <= pV) {
2304
                if (maxfl > 0.1) {
2305
                    c->new_skidding |= 4u;
2306
                }
2307
                if (maxfr > 0.1) {
2308
                    c->new_skidding |= 8u;
2309
                }
2310
            }
2311
            if (IRandomBetween(0, 1)) {
2312
                if (maxfl > 0.1) {
2313
                    SkidNoise(c, 2, pV, c->material_index[2]);
2314
                }
2315
            } else if (maxfr > 0.1) {
2316
                SkidNoise(c, 3, pV, c->material_index[3]);
2317
            }
2318
            break;
2319
        }
2320
        BrVector3Scale(&v136, &rightplane, v99);
2321
        BrVector3Scale(&a, &v103, v109);
2322
        BrVector3Accumulate(&v136, &a);
2323
        BrVector3Scale(&v123, &rightplane, v98);
2324
        BrVector3Scale(&a, &v103, v108);
2325
        BrVector3Accumulate(&v123, &a);
2326
 
2327
        rightplane = c->wpos[0];
2328
        rightplane.v[1] = rightplane.v[1] - c->oldd[0];
2329
        BrVector3Sub(&rightplane, &rightplane, &c->cmpos);
2330
        BrVector3Scale(&b, &v136, force[0]);
2331
        BrVector3Accumulate(&B, &b);
2332
        BrVector3Cross(&a, &rightplane, &b);
2333
        BrVector3Accumulate(&f, &a);
2334
 
2335
        rightplane = c->wpos[1];
2336
        rightplane.v[1] = rightplane.v[1] - c->oldd[1];
2337
        BrVector3Sub(&rightplane, &rightplane, &c->cmpos);
2338
        BrVector3Scale(&b, &v136, force[1]);
2339
        BrVector3Accumulate(&B, &b);
2340
        BrVector3Cross(&a, &rightplane, &b);
2341
        BrVector3Accumulate(&f, &a);
2342
 
2343
        rightplane = c->wpos[2];
2344
        rightplane.v[1] = rightplane.v[1] - c->oldd[2];
2345
        BrVector3Sub(&rightplane, &rightplane, &c->cmpos);
2346
        BrVector3Scale(&b, &v123, force[2]);
2347
        BrVector3Accumulate(&B, &b);
2348
        BrVector3Cross(&a, &rightplane, &b);
2349
        BrVector3Accumulate(&f, &a);
2350
 
2351
        rightplane = c->wpos[3];
2352
        rightplane.v[1] = rightplane.v[1] - c->oldd[3];
2353
        BrVector3Sub(&rightplane, &rightplane, &c->cmpos);
2354
        BrVector3Scale(&b, &v123, force[3]);
2355
        BrVector3Accumulate(&B, &b);
2356
        BrVector3Cross(&a, &rightplane, &b);
2357
        BrVector3Accumulate(&f, &a);
2358
 
2359
    } else {
2360
        c->max_force_front = 0.0;
2361
        c->max_force_rear = 0.0;
2362
        StopSkid(c);
2363
    }
2364
    c->number_of_wheels_on_ground = normnum;
2365
    BrMatrix34ApplyV(&b, &B, mat);
2366
    BrVector3Scale(&rightplane, &f, dt);
2367
    ApplyTorque(c, &rightplane);
2368
    BrVector3Scale(&rightplane, &b, dt / c->M);
2369
    BrVector3Accumulate(&c->v, &rightplane);
2370
    if (c->speed < 0.000099999997
2371
        && ((!c->keys.acc && c->joystick.acc <= 0) || !c->gear)
2372
        && !c->keys.dec
2373
        && c->joystick.dec <= 0
2374
        && c->bounce_rate == 0.0
2375
        && BrVector3Length(&c->omega) < 0.05) {
2376
        if (vol) {
2377
            v73 = c->driver > eDriver_non_car && c->underwater_ability ? 1.0 - (1.0 - vol->gravity_multiplier) * 0.6 : vol->gravity_multiplier;
2378
            friction_number = BrVector3Length(&b) / v73 / gGravity_multiplier;
2379
        } else {
2380
            friction_number = BrVector3Length(&b);
2381
        }
2382
        if (c->M > friction_number || (c->keys.brake && normnum >= 3)) {
2383
            if (stop_timer == 100.0) {
2384
                stop_timer = 0.0;
2385
            }
2386
            if (stop_timer > 0.5) {
2387
                BrVector3SetFloat(&c->v, 0.0, 0.0, 0.0);
2388
                BrVector3SetFloat(&c->omega, 0.0, 0.0, 0.0);
2389
                stop_timer = 0.5;
2390
            }
2391
        }
2392
    }
2393
    stop_timer = dt + stop_timer;
2394
    if (stop_timer > 1.0) {
2395
        stop_timer = 100.0;
2396
    }
2397
    AddDrag(c, dt);
2398
    if (c->driver >= eDriver_net_human) {
2399
        c->acc_force = -(v136.v[2] * force[0]) - v136.v[2] * force[1];
2400
        // LOG_DEBUG("old %f new %f", old, c->acc_force);
2401
    }
2402
}
2403
 
2404
// IDA: void __usercall DoRevs(tCar_spec *c@<EAX>, br_scalar dt)
2405
void DoRevs(tCar_spec* c, br_scalar dt) {
2406
    br_scalar wheel_spin_force;
2407
    br_scalar ts;
2408
    //int revs_increase; // Pierre-Marie Baty -- unused variable
2409
    LOG_TRACE("(%p, %f)", c, dt);
2410
 
2411
    ts = -BrVector3Dot((br_vector3*)c->car_master_actor->t.t.mat.m[2], &c->v);
2412
 
2413
    if (c->gear) {
2414
        c->target_revs = ts / c->speed_revs_ratio / (double)c->gear;
2415
    } else {
2416
        c->target_revs = 0.0;
2417
    }
2418
    if (c->target_revs < 0.0) {
2419
        c->target_revs = 0.0;
2420
        c->gear = 0;
2421
    }
2422
    if (!c->number_of_wheels_on_ground || ((c->wheel_slip & 2) + 1) != 0 || !c->gear) {
2423
        if (c->number_of_wheels_on_ground) {
2424
            wheel_spin_force = c->force_torque_ratio * c->torque - (double)c->gear * c->acc_force;
2425
        } else {
2426
            wheel_spin_force = c->force_torque_ratio * c->torque;
2427
        }
2428
        if (c->gear) {
2429
            if (c->gear < 2 && (c->keys.dec || c->joystick.dec > 0) && fabs(ts) < 1.0 && c->revs > 1000.0) {
2430
                c->gear = -c->gear;
2431
            }
2432
        } else {
2433
            if (c->revs > 1000.0 && !c->keys.brake && (c->keys.acc || c->joystick.acc > 0) && !gCountdown) {
2434
                if (c->keys.backwards) {
2435
                    c->gear = -1;
2436
                } else {
2437
                    c->gear = 1;
2438
                }
2439
            }
2440
            wheel_spin_force = c->force_torque_ratio * c->torque;
2441
        }
2442
        c->revs = wheel_spin_force / c->force_torque_ratio * dt / 0.0002 + c->revs;
2443
 
2444
        if (c->traction_control && wheel_spin_force > 0.0 && c->revs > c->target_revs && c->gear && c->target_revs > 1000.0) {
2445
            c->revs = c->target_revs;
2446
        }
2447
        if (c->revs <= 0.0) {
2448
            c->revs = 0.0;
2449
        }
2450
    }
2451
    if ((c->wheel_slip & 2) == 0 && c->target_revs > 6000.0 && c->revs > 6000.0 && c->gear < c->max_gear && c->gear > 0 && !c->just_changed_gear) {
2452
        c->gear++;
2453
    }
2454
    if (c->gear > 1 && c->target_revs < 3000.0 && !c->just_changed_gear) {
2455
        c->gear--;
2456
    }
2457
    if (c->revs < 200.0 && c->target_revs < 200.0 && c->gear <= 1 && !c->keys.acc && c->joystick.acc <= 0 && !c->just_changed_gear) {
2458
        c->gear = 0;
2459
    }
2460
    if (c->just_changed_gear && c->revs < 6000.0 && c->revs > 200.0 && (c->gear < 2 || c->revs >= 3000.0)) {
2461
        c->just_changed_gear = 0;
2462
    }
2463
    if (c->revs >= 6000.0 && (c->keys.acc || c->joystick.acc > 0)) {
2464
        c->just_changed_gear = 0;
2465
    }
2466
}
2467
 
2468
// IDA: void __usercall ApplyTorque(tCar_spec *c@<EAX>, br_vector3 *tdt@<EDX>)
2469
void ApplyTorque(tCar_spec* c, br_vector3* tdt) {
2470
    LOG_TRACE("(%p, %p)", c, tdt);
2471
 
2472
    c->omega.v[0] = tdt->v[0] / c->I.v[0] + c->omega.v[0];
2473
    c->omega.v[1] = tdt->v[1] / c->I.v[1] + c->omega.v[1];
2474
    c->omega.v[2] = tdt->v[2] / c->I.v[2] + c->omega.v[2];
2475
}
2476
 
2477
// IDA: void __usercall TranslateCar(tCollision_info *c@<EAX>, br_scalar dt)
2478
void TranslateCar(tCollision_info* c, br_scalar dt) {
2479
    br_vector3 t;
2480
    LOG_TRACE("(%p, %f)", c, dt);
2481
 
2482
    t.v[0] = c->v.v[0] * dt;
2483
    t.v[1] = c->v.v[1] * dt;
2484
    t.v[2] = c->v.v[2] * dt;
2485
    c->car_master_actor->t.t.mat.m[3][0] = c->car_master_actor->t.t.mat.m[3][0] + t.v[0];
2486
    c->car_master_actor->t.t.mat.m[3][1] = c->car_master_actor->t.t.mat.m[3][1] + t.v[1];
2487
    c->car_master_actor->t.t.mat.m[3][2] = c->car_master_actor->t.t.mat.m[3][2] + t.v[2];
2488
}
2489
 
2490
// IDA: int __usercall CollCheck@<EAX>(tCollision_info *c@<EAX>, br_scalar dt)
2491
int CollCheck(tCollision_info* c, br_scalar dt) {
2492
    br_vector3 a;
2493
    br_vector3 a1;
2494
    br_vector3 aa;
2495
    br_vector3 bb;
2496
    br_vector3 cc;
2497
    br_vector3 pos;
2498
    br_vector3 r[8];
2499
    br_vector3 norm;
2500
    br_vector3 n[8];
2501
    br_vector3 dir;
2502
    br_vector3 tv;
2503
    br_vector3 tv2;
2504
    br_vector3 tau[4];
2505
    //br_vector3 old_val; // Pierre-Marie Baty -- unused variable
2506
    //br_vector3 ftau; // Pierre-Marie Baty -- unused variable
2507
    br_vector3 max_friction;
2508
    br_vector3 vel;
2509
    br_vector3 p_vel;
2510
    br_vector3 normal_force;
2511
    br_vector3 friction_force;
2512
    br_scalar d[4];
2513
    br_scalar f[4];
2514
    br_scalar total_force;
2515
    br_scalar point_vel;
2516
    br_scalar batwick_length;
2517
    br_matrix4 M;
2518
    br_scalar dist;
2519
    //br_scalar min_d; // Pierre-Marie Baty -- unused variable
2520
    br_scalar ts;
2521
    br_scalar ts2;
2522
    br_scalar v_diff;
2523
    br_matrix34* mat;
2524
    br_matrix34* oldmat;
2525
    br_matrix34 mat_to_oldmat;
2526
    br_matrix34 oldmat_to_mat;
2527
    br_matrix34 tm;
2528
    int collision;
2529
    br_bounds bnds;
2530
    tFace_ref* f_ref;
2531
    int i;
2532
    int j;
2533
    //int l; // Pierre-Marie Baty -- unused variable
2534
    int k;
2535
    int material;
2536
    int noise_defeat;
2537
    static int oldk;
2538
    br_scalar min;
2539
    br_scalar max;
2540
    br_vector3 edges[3];
2541
    //br_vector3 corner; // Pierre-Marie Baty -- unused variable
2542
    //br_vector3 test_dir; // Pierre-Marie Baty -- unused variable
2543
    //br_scalar min_acc; // Pierre-Marie Baty -- unused variable
2544
    //br_scalar max_acc; // Pierre-Marie Baty -- unused variable
2545
    br_matrix34 message_mat;
2546
    LOG_TRACE("(%p, %f)", c, dt);
2547
 
2548
    tCar_spec* car_spec; // added for readability
2549
 
2550
    // v34 = 0;
2551
    // v35 = 0;
2552
    // v36 = 0x3F800000;
2553
    // v48 = 0x3F800347;
2554
    car_spec = (tCar_spec*)c;
2555
    mat = &c->car_master_actor->t.t.mat;
2556
    oldmat = &c->oldmat;
2557
    k = 0;
2558
    gMaterial_index = 0;
2559
    if (c->dt >= 0.0f && gNet_mode == eNet_mode_host) {
2560
        oldmat = &message_mat;
2561
        GetExpandedMatrix(&message_mat, &c->message.mat);
2562
    }
2563
    if (dt < 0.0f) {
2564
        mat = oldmat;
2565
    }
2566
    BrMatrix34LPInverse(&tm, mat);
2567
    BrMatrix34Mul(&oldmat_to_mat, oldmat, &tm);
2568
 
2569
    oldmat_to_mat.m[3][0] = oldmat_to_mat.m[3][0] / WORLD_SCALE;
2570
    oldmat_to_mat.m[3][1] = oldmat_to_mat.m[3][1] / WORLD_SCALE;
2571
    oldmat_to_mat.m[3][2] = oldmat_to_mat.m[3][2] / WORLD_SCALE;
2572
    GetNewBoundingBox(&bnds, &c->bounds[2], &oldmat_to_mat);
2573
    for (i = 0; i < 3; ++i) {
2574
        if (c->bounds[2].min.v[i] < bnds.min.v[i]) {
2575
            bnds.min.v[i] = c->bounds[2].min.v[i];
2576
        }
2577
        if (c->bounds[2].max.v[i] > bnds.max.v[i]) {
2578
            bnds.max.v[i] = c->bounds[2].max.v[i];
2579
        }
2580
    }
2581
    a1.v[0] = mat->m[3][0] / WORLD_SCALE;
2582
    a1.v[1] = mat->m[3][1] / WORLD_SCALE;
2583
    a1.v[2] = mat->m[3][2] / WORLD_SCALE;
2584
    BrMatrix34ApplyV(&aa, &bnds.min, mat);
2585
    BrVector3Accumulate(&aa, &a1);
2586
    for (j = 0; j < 3; ++j) {
2587
        edges[j].v[0] = (bnds.max.v[j] - bnds.min.v[j]) * mat->m[j][0];
2588
        edges[j].v[1] = (bnds.max.v[j] - bnds.min.v[j]) * mat->m[j][1];
2589
        edges[j].v[2] = (bnds.max.v[j] - bnds.min.v[j]) * mat->m[j][2];
2590
    }
2591
    for (i = 0; i < 50 && i < c->box_face_end - c->box_face_start; i++) {
2592
        f_ref = &gFace_list__car[c->box_face_start + i];
2593
        BrVector3Sub(&bb, &aa, &f_ref->v[0]);
2594
        max = BrVector3Dot(&bb, &f_ref->normal);
2595
        min = max;
2596
        for (j = 0; j < 3; ++j) {
2597
            ts = BrVector3Dot(&edges[j], &f_ref->normal);
2598
            if (ts >= 0) {
2599
                max = max + ts;
2600
            } else {
2601
                min = min + ts;
2602
            }
2603
        }
2604
        if ((max <= 0.001f || min <= 0.001f) && (max >= -0.001f || min >= -0.001f)) {
2605
            f_ref->flags &= ~0x80u;
2606
            k++;
2607
        } else {
2608
            f_ref->flags |= 0x80u;
2609
        }
2610
    }
2611
    if (k == 0) {
2612
        return 0;
2613
    }
2614
    k = 0;
2615
    BrMatrix34LPInverse(&tm, oldmat);
2616
    BrMatrix34Mul(&mat_to_oldmat, mat, &tm);
2617
    gEliminate_faces = 1;
2618
    for (i = 0; i < 8 + c->extra_point_num; i++) {
2619
        if (i >= 8) {
2620
            tv = c->extra_points[i - 8];
2621
        } else {
2622
            tv.v[0] = ((i & 2) == 0) * c->bounds[1].min.v[0] + ((i & 2) >> 1) * c->bounds[1].max.v[0];
2623
            tv.v[1] = ((i & 1) == 0) * c->bounds[1].min.v[1] + ((i & 1) >> 0) * c->bounds[1].max.v[1];
2624
            tv.v[2] = ((i & 4) == 0) * c->bounds[1].max.v[2] + ((i & 4) >> 2) * c->bounds[1].min.v[2];
2625
        }
2626
        BrMatrix34ApplyP(&dir, &tv, mat);
2627
        if (dt >= 0.0f) {
2628
            BrMatrix34ApplyP(&a, &tv, oldmat);
2629
        } else {
2630
            BrVector3Scale(&a, &c->pos, WORLD_SCALE);
2631
        }
2632
        BrVector3Sub(&dir, &dir, &a);
2633
        BrVector3Normalise(&normal_force, &dir);
2634
        BrVector3Scale(&normal_force, &normal_force, 0.0072463769f);
2635
        BrVector3Accumulate(&dir, &normal_force);
2636
        material = FindFloorInBoxM2(&a, &dir, &norm, &dist, c);
2637
        if (dist >= 0.0f && dist < 1.0001f) {
2638
            BrVector3Scale(&cc, &c->pos, WORLD_SCALE);
2639
            BrVector3Sub(&cc, &cc, &a);
2640
            FindFloorInBoxM(&a, &cc, &bb, &ts, c);
2641
            if (i < 8 || ts > 1.0f) {
2642
                BrMatrix34TApplyV(&a, &norm, oldmat);
2643
                AddCollPoint(dist, &tv, &a, r, n, &dir, k, c);
2644
                k++;
2645
                if (gMaterial_index == 0) {
2646
                    gMaterial_index = material;
2647
                }
2648
            }
2649
        }
2650
    }
2651
    gEliminate_faces = 0;
2652
    if (k < 1) {
2653
        k += BoxFaceIntersect(&c->bounds[1], mat, &mat_to_oldmat, &r[k], &n[k], &d[k], 8 - k, c);
2654
    }
2655
    if (k > 4) {
2656
        k = 4;
2657
    }
2658
    for (i = 0; i < k; i++) {
2659
        if (fabsf(r[i].v[1]) + fabsf(r[i].v[2]) + fabsf(r[i].v[0]) > 500.0f) {
2660
            for (j = i + 1; j < k; j++) {
2661
                if (fabsf(r[j].v[1]) + fabsf(r[j].v[2]) + fabsf(r[j].v[0]) < 500.0f) {
2662
                    r[i] = r[j];
2663
                    n[i] = n[j];
2664
                    i++;
2665
                }
2666
            }
2667
            k = i;
2668
            break;
2669
        }
2670
    }
2671
    if (dt >= 0.0f) {
2672
        if (k > 0 && c->collision_flag && k < 4
2673
            && (fabsf(r[0].v[0] - c->old_point.v[0]) > 0.05f
2674
                || fabsf(r[0].v[1] - c->old_point.v[1]) > 0.05f
2675
                || fabsf(r[0].v[2] - c->old_point.v[2]) > 0.05f)) {
2676
            r[k] = c->old_point;
2677
            n[k] = c->old_norm;
2678
            k++;
2679
        }
2680
        if (k > 0) {
2681
            c->old_point = r[0];
2682
            c->old_norm = n[0];
2683
            BrMatrix34Copy(mat, oldmat);
2684
            c->omega = c->oldomega;
2685
            BrMatrix34TApplyV(&c->velocity_car_space, &c->v, mat);
2686
            memset(&norm, 0, sizeof(norm));
2687
            collision = 0;
2688
            for (i = 0; i < k; i++) {
2689
                BrVector3Cross(&tau[i], &r[i], &n[i]);
2690
                tau[i].v[0] = tau[i].v[0] / c->I.v[0];
2691
                tau[i].v[1] = tau[i].v[1] / c->I.v[1];
2692
                tau[i].v[2] = tau[i].v[2] / c->I.v[2];
2693
                BrVector3Cross(&normal_force, &c->omega, &r[i]);
2694
                BrVector3Accumulate(&normal_force, &c->velocity_car_space);
2695
                d[i] = -(BrVector3Dot(&n[i], &normal_force));
2696
                BrVector3Add(&normal_force, &r[i], &c->cmpos);
2697
                BrMatrix34ApplyP(&dir, &normal_force, &mat_to_oldmat);
2698
                BrVector3Sub(&dir, &dir, &normal_force);
2699
                ts = -(BrVector3Dot(&n[i], &dir) / dt);
2700
                if (ts > d[i]) {
2701
                    d[i] = ts;
2702
                }
2703
                if (d[i] > 0.0f) {
2704
                    collision = 1;
2705
                }
2706
            }
2707
            if (!collision) {
2708
                d[0] = 0.5f;
2709
            }
2710
            for (i = 0; i < k; i++) {
2711
                for (j = 0; j < k; j++) {
2712
                    BrVector3Cross(&normal_force, &tau[j], &r[i]);
2713
                    BrVector3InvScale(&norm, &n[j], c->M);
2714
                    BrVector3Accumulate(&normal_force, &norm);
2715
                    M.m[i][j] = BrVector3Dot(&n[i], &normal_force);
2716
                }
2717
            }
2718
            switch (k) {
2719
            case 1:
2720
                ts = SinglePointColl(f, &M, d);
2721
                break;
2722
            case 2:
2723
                ts = TwoPointColl(f, &M, d, tau, n);
2724
                break;
2725
            case 3:
2726
                d[3] = 0.0f;
2727
                ts = ThreePointCollRec(f, &M, d, tau, n, c);
2728
                break;
2729
            case 4:
2730
                ts = FourPointColl(f, &M, d, tau, n, c);
2731
                break;
2732
            default:
2733
                break;
2734
            }
2735
            if (k > 3) {
2736
                k = 3;
2737
            }
2738
            // if (f[0] > 10.0f || f[1] > 10.0f || f[2] > 10.0f) {
2739
            //     v31 = 0;
2740
            // }
2741
            if (fabsf(ts) <= 0.000001f) {
2742
                BrVector3Set(&c->v, 0.f, 0.f, 0.f);
2743
                BrVector3Set(&c->omega, 0.f, 0.f, 0.f);
2744
                BrVector3Set(&c->oldomega, 0.f, 0.f, 0.f);
2745
                return k;
2746
            }
2747
            BrVector3Set(&p_vel, 0.f, 0.f, 0.f);
2748
            BrVector3Set(&dir, 0.f, 0.f, 0.f);
2749
            BrVector3Set(&friction_force, 0.f, 0.f, 0.f);
2750
            total_force = 0.f;
2751
            for (i = 0; i < k; i++) {
2752
                if (f[i] < 0.001f) {
2753
                    f[i] = 0.001f;
2754
                }
2755
                f[i] = f[i] * 1.001f;
2756
                BrVector3Scale(&tau[i], &tau[i], f[i]);
2757
                BrVector3Accumulate(&c->omega, &tau[i]);
2758
                f[i] = f[i] / c->M;
2759
                BrVector3Scale(&n[i], &n[i], f[i]);
2760
                BrVector3Accumulate(&p_vel, &n[i]);
2761
                BrVector3Add(&bb, &r[i], &c->cmpos);
2762
                BrVector3Scale(&bb, &bb, f[i]);
2763
                BrVector3Accumulate(&dir, &bb);
2764
                total_force = f[i] + total_force;
2765
            }
2766
            if (gPinball_factor != 0.0f) {
2767
                BrVector3Scale(&p_vel, &p_vel, gPinball_factor);
2768
                point_vel = BrVector3LengthSquared(&p_vel);
2769
                if (point_vel > 10.0f) {
2770
                    noise_defeat = 1;
2771
                    if (c->driver == eDriver_local_human) {
2772
                        DRS3StartSound(gCar_outlet, 9011);
2773
                    } else {
2774
                        DRS3StartSound3D(gCar_outlet, 9011, &c->pos, &gZero_v__car, 1, 255, 0x10000, 0x10000);
2775
                    }
2776
                    if (point_vel > 10000.0f) {
2777
                        BrVector3Normalise(&p_vel, &p_vel);
2778
                        BrVector3Scale(&p_vel, &p_vel, 100);
2779
                    }
2780
                }
2781
            }
2782
            BrVector3Accumulate(&c->velocity_car_space, &p_vel);
2783
            BrVector3InvScale(&dir, &dir, total_force);
2784
            BrVector3Cross(&tv, &c->omega, &dir);
2785
            BrVector3Accumulate(&tv, &c->velocity_car_space);
2786
            batwick_length = BrVector3Length(&tv);
2787
            if (!c->collision_flag || (c->collision_flag == 1 && oldk < k)) {
2788
                for (i = 0; i < k; i++) {
2789
                    BrVector3Cross(&vel, &c->omega, &r[i]);
2790
                    BrVector3Accumulate(&vel, &c->velocity_car_space);
2791
                    AddFriction(c, &vel, &n[i], &r[i], f[i], &max_friction);
2792
                    BrVector3Accumulate(&friction_force, &max_friction);
2793
                    BrVector3Accumulate(&c->velocity_car_space, &max_friction);
2794
                }
2795
            }
2796
            oldk = k;
2797
            BrMatrix34ApplyP(&pos, &dir, &c->car_master_actor->t.t.mat);
2798
            BrVector3InvScale(&pos, &pos, WORLD_SCALE);
2799
            noise_defeat = 0;
2800
            BrVector3Add(&normal_force, &friction_force, &p_vel);
2801
            BrMatrix34ApplyV(&norm, &normal_force, mat);
2802
            min = dt * 90.0f / 10.0f;
2803
            max = dt * 110.0f / 10.0f;
2804
            if (c->last_special_volume != NULL) {
2805
                min *= c->last_special_volume->gravity_multiplier;
2806
                max *= c->last_special_volume->gravity_multiplier;
2807
            }
2808
            if (BrVector3LengthSquared(&c->velocity_car_space) < 0.05f
2809
                && 0.1f * total_force > BrVector3Dot(&c->omega, &tv)
2810
                && k >= 3
2811
                && norm.v[1] > min
2812
                && norm.v[1] < max) {
2813
                if (c->driver <= eDriver_non_car || fabsf(normal_force.v[2]) <= total_force * 0.9f) {
2814
                    BrVector3Set(&c->v, 0.f, 0.f, 0.f);
2815
                    BrVector3Set(&norm, 0.f, 0.f, 0.f);
2816
                    BrVector3Set(&normal_force, 0.f, 0.f, 0.f);
2817
                    BrVector3Set(&c->omega, 0.f, 0.f, 0.f);
2818
                    BrVector3Set(&c->oldomega, 0.f, 0.f, 0.f);
2819
                    if (c->driver <= eDriver_non_car || car_spec->max_force_rear == 0.0f) {
2820
                        if (c->driver <= eDriver_non_car) {
2821
                            PipeSingleNonCar(c);
2822
                        }
2823
                        c->doing_nothing_flag = 1;
2824
                    }
2825
                } else {
2826
                    BrVector3SetFloat(&tv2, 0.0f, -1.0f, 0.0f);
2827
                    bb.v[0] = mat->m[1][2] * tv2.v[1] - mat->m[1][1] * tv2.v[2];
2828
                    bb.v[1] = mat->m[1][0] * tv2.v[2] - mat->m[1][2] * tv2.v[0];
2829
                    bb.v[2] = mat->m[1][1] * tv2.v[0] - mat->m[1][0] * tv2.v[1];
2830
                    if (BrVector3Dot(&bb, (br_vector3*)&mat->m[0][1]) <= 0.0f) {
2831
                        c->omega.v[0] = -0.5f;
2832
                    } else {
2833
                        c->omega.v[0] = 0.5f;
2834
                    }
2835
                }
2836
            }
2837
            BrVector3Accumulate(&c->v, &norm);
2838
            if (c->driver >= eDriver_net_human) {
2839
                BrVector3Scale(&normal_force, &normal_force, gDefensive_powerup_factor[car_spec->power_up_levels[0]]);
2840
            }
2841
            if (c->driver < eDriver_net_human) {
2842
                BrVector3Scale(&normal_force, &normal_force, 0.01f);
2843
            } else {
2844
                BrVector3Scale(&normal_force, &normal_force, 0.75f);
2845
            }
2846
            if (CAR(c)->invulnerable
2847
                || (c->driver < eDriver_net_human && (c->driver != eDriver_oppo || PointOutOfSight(&c->pos, 150.0f)))
2848
                || ((v_diff = (car_spec->pre_car_col_velocity.v[1] - c->v.v[1]) * gDefensive_powerup_factor[car_spec->power_up_levels[0]]) >= -20.0f)
2849
                || CAR(c)->number_of_wheels_on_ground >= 3) {
2850
                CrushAndDamageCar(CAR(c), &dir, &normal_force, NULL);
2851
            } else {
2852
                // Cops Special Forces is always stolen if destroyed!
2853
                if (c->driver == eDriver_oppo && c->index == 4 && v_diff < -40.0f) {
2854
                    KnackerThisCar(CAR(c));
2855
                    StealCar(CAR(c));
2856
                    v_diff = v_diff * 5.0f;
2857
                }
2858
                for (i = 0; i < CAR(c)->car_actor_count; i++) {
2859
                    ts2 = (v_diff + 20.0f) * -0.01f;
2860
                    TotallySpamTheModel(CAR(c), i, CAR(c)->car_model_actors[i].actor, &CAR(c)->car_model_actors[i].crush_data, ts2);
2861
                }
2862
                for (i = 0; i < COUNT_OF(CAR(c)->damage_units); i++) {
2863
                    DamageUnit(CAR(c), i, IRandomPosNeg(5) + (v_diff + 20.0f) * -1.5f);
2864
                }
2865
            }
2866
            if (!noise_defeat) {
2867
                CrashNoise(&norm, &pos, gMaterial_index);
2868
                ScrapeNoise(batwick_length, &pos, gMaterial_index);
2869
            }
2870
            BrVector3InvScale(&tv, &tv, WORLD_SCALE);
2871
            BrMatrix34ApplyV(&bb, &tv, &c->car_master_actor->t.t.mat);
2872
            BrMatrix34ApplyV(&norm, &p_vel, &c->car_master_actor->t.t.mat);
2873
            CreateSparks(&pos, &bb, &norm, gCurrent_race.material_modifiers[gMaterial_index].sparkiness, car_spec);
2874
        }
2875
        return k;
2876
    } else {
2877
        if (k != 0) {
2878
            c->old_point = r[0];
2879
            c->old_norm = n[0];
2880
        }
2881
        return k;
2882
    }
2883
}
2884
 
2885
// IDA: br_scalar __usercall AddFriction@<ST0>(tCollision_info *c@<EAX>, br_vector3 *vel@<EDX>, br_vector3 *normal_force@<EBX>, br_vector3 *pos@<ECX>, br_scalar total_force, br_vector3 *max_friction)
2886
br_scalar AddFriction(tCollision_info* c, br_vector3* vel, br_vector3* normal_force, br_vector3* pos, br_scalar total_force, br_vector3* max_friction) {
2887
    br_vector3 norm;
2888
    br_vector3 tv;
2889
    br_vector3 ftau;
2890
    br_scalar ts;
2891
    br_scalar point_vel;
2892
    LOG_TRACE("(%p, %p, %p, %p, %f, %p)", c, vel, normal_force, pos, total_force, max_friction);
2893
 
2894
    ts = BrVector3Dot(normal_force, vel) / BrVector3Dot(normal_force, normal_force);
2895
    BrVector3Scale(&tv, normal_force, ts);
2896
    BrVector3Sub(vel, vel, &tv);
2897
    point_vel = total_force * 0.35f * gCurrent_race.material_modifiers[gMaterial_index].car_wall_friction;
2898
    ts = BrVector3Length(vel);
2899
    if (ts < 0.0001f) {
2900
        BrVector3Set(max_friction, 0.f, 0.f, 0.f);
2901
        return 0.0;
2902
    }
2903
    BrVector3InvScale(max_friction, vel, -ts);
2904
    BrVector3Cross(&ftau, pos, max_friction);
2905
    BrVector3Scale(&ftau, &ftau, c->M);
2906
    ftau.v[0] = ftau.v[0] / c->I.v[0];
2907
    ftau.v[1] = ftau.v[1] / c->I.v[1];
2908
    ftau.v[2] = ftau.v[2] / c->I.v[2];
2909
    ts = 1.0 / c->M;
2910
    norm.v[0] = pos->v[2] * ftau.v[1] - pos->v[1] * ftau.v[2];
2911
    norm.v[1] = pos->v[0] * ftau.v[2] - pos->v[2] * ftau.v[0];
2912
    norm.v[2] = pos->v[1] * ftau.v[0] - pos->v[0] * ftau.v[1];
2913
    ts = max_friction->v[0] * norm.v[0] + max_friction->v[1] * norm.v[1] + max_friction->v[2] * norm.v[2] + ts;
2914
    if (fabsf(ts) <= 0.0001f) {
2915
        ts = 0.0f;
2916
    } else {
2917
        ts = -BrVector3Dot(max_friction, vel) / ts;
2918
    }
2919
    if (ts > point_vel) {
2920
        ts = point_vel;
2921
    }
2922
    BrVector3Scale(max_friction, max_friction, ts);
2923
    BrVector3Cross(&tv, pos, max_friction);
2924
    BrVector3Scale(&tv, &tv, c->M);
2925
    ApplyTorque((tCar_spec*)c, &tv);
2926
    return point_vel;
2927
}
2928
 
2929
// IDA: void __usercall AddFrictionCarToCar(tCollision_info *car1@<EAX>, tCollision_info *car2@<EDX>, br_vector3 *vel1@<EBX>, br_vector3 *vel2@<ECX>, br_vector3 *normal_force1, br_vector3 *pos1, br_vector3 *pos2, br_scalar total_force, br_vector3 *max_friction)
2930
void AddFrictionCarToCar(tCollision_info* car1, tCollision_info* car2, br_vector3* vel1, br_vector3* vel2, br_vector3* normal_force1, br_vector3* pos1, br_vector3* pos2, br_scalar total_force, br_vector3* max_friction) {
2931
    br_vector3 v_diff1;
2932
    br_vector3 v_diff2;
2933
    br_vector3 tau1;
2934
    br_vector3 tau2;
2935
    br_vector3 tv;
2936
    br_vector3 tv2;
2937
    br_vector3 vel2_in_frame_1;
2938
    br_scalar ts;
2939
    br_scalar ts2;
2940
    br_scalar v_diff;
2941
    br_scalar stopping_impulse;
2942
    br_scalar total_friction;
2943
    int i;
2944
    LOG_TRACE("(%p, %p, %p, %p, %p, %p, %p, %f, %p)", car1, car2, vel1, vel2, normal_force1, pos1, pos2, total_force, max_friction);
2945
 
2946
    BrMatrix34TApplyV(&tv, vel2, &car2->oldmat);
2947
    BrMatrix34ApplyV(&vel2_in_frame_1, &tv, &car1->oldmat);
2948
    BrVector3Sub(&v_diff1, &vel2_in_frame_1, vel1);
2949
    ts = BrVector3LengthSquared(normal_force1);
2950
    ts2 = BrVector3Dot(normal_force1, &v_diff1) / ts;
2951
    BrVector3Scale(&tv, normal_force1, ts2);
2952
    BrVector3Sub(&v_diff1, &v_diff1, &tv);
2953
    v_diff = BrVector3Length(&v_diff1);
2954
    if (v_diff < 0.01f) {
2955
        BrVector3Set(max_friction, 0.f, 0.f, 0.f);
2956
    } else {
2957
        BrVector3InvScale(&v_diff1, &v_diff1, v_diff);
2958
        BrMatrix34ApplyV(&tv, &v_diff1, &car1->oldmat);
2959
        BrMatrix34TApplyV(&v_diff2, &tv, &car2->oldmat);
2960
        BrVector3Negate(&v_diff2, &v_diff2);
2961
        BrVector3Cross(&tau1, pos1, &v_diff1);
2962
        BrVector3Cross(&tau2, pos2, &v_diff2);
2963
        for (i = 0; i < 3; ++i) {
2964
            tau1.v[i] /= car1->I.v[i];
2965
            tau2.v[i] /= car2->I.v[i];
2966
        }
2967
        BrVector3Cross(&tv, &tau1, pos1);
2968
        BrVector3Cross(&tv2, &tau2, pos2);
2969
        ts = BrVector3Dot(&tv, &v_diff1) + BrVector3Dot(&tv2, &v_diff2) + 1.f / car2->M + 1.f / car1->M;
2970
        if (ts < 0.0001f) {
2971
            BrVector3Set(max_friction, 0.f, 0.f, 0.f);
2972
        } else {
2973
            stopping_impulse = v_diff / ts;
2974
            total_friction = total_force * 0.35f;
2975
            if (stopping_impulse < total_friction) {
2976
                total_friction = stopping_impulse;
2977
            }
2978
            if (!car1->infinite_mass) {
2979
                BrVector3Scale(&tau1, &tau1, total_friction);
2980
                BrVector3Accumulate(&car1->omega, &tau1);
2981
            }
2982
            if (!car2->infinite_mass) {
2983
                BrVector3Scale(&tau2, &tau2, total_friction);
2984
                BrVector3Accumulate(&car2->omega, &tau2);
2985
            }
2986
            BrVector3Scale(max_friction, &v_diff1, total_friction);
2987
        }
2988
    }
2989
}
2990
 
2991
// IDA: void __cdecl ScrapeNoise(br_scalar vel, br_vector3 *position, int material)
2992
void ScrapeNoise(br_scalar vel, br_vector3* position, int material) {
2993
    tS3_volume vol;
2994
    static tS3_sound_tag scrape_tag;
2995
    static tS3_volume last_scrape_vol;
2996
    br_vector3 velocity;
2997
    //br_vector3 position_in_br; // Pierre-Marie Baty -- unused variable
2998
    LOG_TRACE("(%f, %p, %d)", vel, position, material);
2999
 
3000
    vol = vel * 7.0;
3001
    if (gCurrent_race.material_modifiers[material].scrape_noise_index == -1) {
3002
        return;
3003
    }
3004
    if ((scrape_tag && DRS3SoundStillPlaying(scrape_tag)) || vol <= 30) {
3005
        if (last_scrape_vol < vol) {
3006
            DRS3ChangeVolume(scrape_tag, vol);
3007
            last_scrape_vol = vol;
3008
        }
3009
    } else {
3010
        BrVector3Set(&velocity, 0.f, 0.f, 0.f);
3011
        scrape_tag = DRS3StartSound3D(
3012
            gCar_outlet,
3013
            gMetal_scrape_sound_id__car[IRandomBetween(0, COUNT_OF(gMetal_scrape_sound_id__car) - 1)],
3014
            position,
3015
            &velocity,
3016
            1,
3017
            vol,
3018
            IRandomBetween(49152, 81920),
3019
            0x10000);
3020
        last_scrape_vol = vol;
3021
    }
3022
}
3023
 
3024
// IDA: void __usercall SkidNoise(tCar_spec *pC@<EAX>, int pWheel_num@<EDX>, br_scalar pV, int material)
3025
void SkidNoise(tCar_spec* pC, int pWheel_num, br_scalar pV, int material) {
3026
    br_vector3 pos;
3027
    br_vector3 world_pos;
3028
    br_vector3 wv;
3029
    br_vector3 wvw;
3030
    br_scalar ts;
3031
    static tS3_volume last_skid_vol[2];
3032
    int i;
3033
    LOG_TRACE("(%p, %d, %f, %d)", pC, pWheel_num, pV, material);
3034
 
3035
    i = IRandomBetween(0, 1);
3036
    if (gCurrent_race.material_modifiers[material].tyre_noise_index == -1) {
3037
        return;
3038
    }
3039
    if (IRandomBetween(0, 4) != 0) {
3040
        return;
3041
    }
3042
 
3043
    last_skid_vol[i] = pV * 10.0;
3044
    if ((pWheel_num & 1) != 0) {
3045
        pos.v[0] = pC->bounds[1].max.v[0];
3046
    } else {
3047
        pos.v[0] = pC->bounds[1].min.v[0];
3048
    }
3049
    pos.v[1] = pC->wpos[pWheel_num].v[1] - pC->oldd[pWheel_num];
3050
    pos.v[2] = pC->wpos[pWheel_num].v[2];
3051
    BrMatrix34ApplyP(&world_pos, &pos, &pC->car_master_actor->t.t.mat);
3052
    BrVector3InvScale(&world_pos, &world_pos, WORLD_SCALE);
3053
    if (!DRS3SoundStillPlaying(gSkid_tag[i]) || (pC->driver == eDriver_local_human && gLast_car_to_skid[i] != pC)) {
3054
        gSkid_tag[i] = DRS3StartSound3D(
3055
            gCar_outlet,
3056
            IRandomBetween(0, 4) + 9000,
3057
            &world_pos,
3058
            &pC->velocity_bu_per_sec,
3059
            1,
3060
            last_skid_vol[i],
3061
            IRandomBetween(49152, 81920),
3062
            0x10000);
3063
        gLast_car_to_skid[i] = pC;
3064
    }
3065
    if (gCurrent_race.material_modifiers[material].smoke_type == 1) {
3066
        BrVector3Cross(&wv, &pC->omega, &pos);
3067
        BrVector3Add(&wv, &wv, &pC->velocity_car_space);
3068
        ts = -(BrVector3Dot(&wv, &pC->road_normal));
3069
        BrVector3Scale(&wvw, &pC->road_normal, ts);
3070
        BrVector3Add(&wv, &wv, &wvw);
3071
        BrMatrix34ApplyV(&wvw, &wv, &pC->car_master_actor->t.t.mat);
3072
        CreatePuffOfSmoke(&world_pos, &wvw, pV / 25.0, 1.0, 4, pC);
3073
    }
3074
}
3075
 
3076
// IDA: void __usercall StopSkid(tCar_spec *pC@<EAX>)
3077
void StopSkid(tCar_spec* pC) {
3078
    LOG_TRACE("(%p)", pC);
3079
 
3080
    if (gLast_car_to_skid[0] == pC) {
3081
        DRS3StopSound(gSkid_tag[0]);
3082
    }
3083
    if (gLast_car_to_skid[1] == pC) {
3084
        DRS3StopSound(gSkid_tag[1]);
3085
    }
3086
}
3087
 
3088
// IDA: void __usercall CrashNoise(br_vector3 *pForce@<EAX>, br_vector3 *position@<EDX>, int material@<EBX>)
3089
void CrashNoise(br_vector3* pForce, br_vector3* position, int material) {
3090
    static tS3_sound_tag crunch_tag;
3091
    static tS3_volume last_crunch_vol;
3092
    tS3_volume vol;
3093
    br_vector3 velocity;
3094
    LOG_TRACE("(%p, %p, %d)", pForce, position, material);
3095
 
3096
    vol = 60.f * BrVector3Length(pForce);
3097
    if (gCurrent_race.material_modifiers[material].crash_noise_index != -1) {
3098
        if (vol >= 256) {
3099
            vol = 255;
3100
        }
3101
        if (crunch_tag == 0 || (!DRS3SoundStillPlaying(crunch_tag) && vol > 30)) {
3102
            last_crunch_vol = vol;
3103
            (void)last_crunch_vol;
3104
            BrVector3Set(&velocity, 0.f, 0.f, 0.f);
3105
            crunch_tag = DRS3StartSound3D(gCar_outlet,
3106
                gMetal_crunch_sound_id__car[IRandomBetween(0, COUNT_OF(gMetal_crunch_sound_id__car) - 1)],
3107
                position, &velocity, 1, vol, IRandomBetween(49152, 81920), 0x10000);
3108
        }
3109
    }
3110
}
3111
 
3112
// IDA: void __usercall CrushAndDamageCar(tCar_spec *c@<EAX>, br_vector3 *pPosition@<EDX>, br_vector3 *pForce_car_space@<EBX>, tCar_spec *car2@<ECX>)
3113
void CrushAndDamageCar(tCar_spec* c, br_vector3* pPosition, br_vector3* pForce_car_space, tCar_spec* car2) {
3114
    br_vector3 force;
3115
    //br_vector3 force2; // Pierre-Marie Baty -- unused variable
3116
    br_vector3 position;
3117
    br_vector3 pos_w;
3118
    br_vector3 car_to_cam;
3119
    br_vector3 force_for_bodywork;
3120
    br_scalar ts;
3121
    int i;
3122
    br_matrix34 m;
3123
    br_scalar fudge_multiplier;
3124
    LOG_TRACE("(%p, %p, %p, %p)", c, pPosition, pForce_car_space, car2);
3125
 
3126
    if (car2 != NULL) {
3127
        car2->who_last_hit_me = c;
3128
        c->who_last_hit_me = car2;
3129
    }
3130
 
3131
    if (c->driver == eDriver_non_car_unused_slot || c->driver == eDriver_non_car) {
3132
        return;
3133
    }
3134
    fudge_multiplier = gNet_mode == eNet_mode_none || gNet_softness[gCurrent_net_game->type] == 1.0f ? 1.0f : gNet_softness[gCurrent_net_game->type];
3135
    BrVector3Sub(&car_to_cam, &c->pos, (br_vector3*)gCamera_to_world.m[3]);
3136
    ts = BrVector3LengthSquared(&car_to_cam);
3137
    if (c->driver == eDriver_oppo && ts > 200.0f) {
3138
        return;
3139
    }
3140
    if (car2 != NULL) {
3141
        if (car2->driver > eDriver_non_car) {
3142
            TwoCarsHitEachOther(c, car2);
3143
        }
3144
        if (c->driver >= eDriver_net_human) {
3145
            fudge_multiplier = gDefensive_powerup_factor[c->power_up_levels[0]] * 1.2f * fudge_multiplier;
3146
        }
3147
        if (car2->driver >= eDriver_net_human) {
3148
            if (gNet_mode != eNet_mode_none
3149
                && (gCurrent_net_game->type == eNet_game_type_fight_to_death || gCurrent_net_game->type == eNet_game_type_car_crusher)) {
3150
                fudge_multiplier = gOffensive_powerup_factor[car2->power_up_levels[2]] * gNet_offensive[gCurrent_net_game->type] * car2->damage_multiplier * fudge_multiplier;
3151
            } else {
3152
                fudge_multiplier = gOffensive_powerup_factor[car2->power_up_levels[2]] * car2->damage_multiplier * fudge_multiplier;
3153
            }
3154
        }
3155
        if (c->driver == eDriver_oppo && car2->driver == eDriver_oppo) {
3156
            fudge_multiplier = fudge_multiplier * 0.2f;
3157
        }
3158
        if (car2->driver <= eDriver_non_car) {
3159
            car2 = NULL;
3160
        } else {
3161
            fudge_multiplier /= ((car2->car_model_actors[car2->principal_car_actor].crush_data.softness_factor + 0.7f) / 0.7f);
3162
        }
3163
    }
3164
    BrVector3InvScale(&position, pPosition, WORLD_SCALE);
3165
    BrVector3Scale(&force, pForce_car_space, fudge_multiplier * 0.03f);
3166
    ts = BrVector3LengthSquared(&force);
3167
    if (c->driver <= eDriver_non_car || !c->invulnerable) {
3168
        c->damage_magnitude_accumulator += ts;
3169
    }
3170
    if (c->driver < eDriver_net_human) {
3171
        BrVector3Scale(&force_for_bodywork, &force, 1.5f);
3172
    } else {
3173
        if (c->collision_mass_multiplier != 1.0) {
3174
            BrVector3InvScale(&force, &force, c->collision_mass_multiplier);
3175
        }
3176
        BrVector3Scale(&force_for_bodywork, &force, 0.5f);
3177
        if (c->driver == eDriver_local_human) {
3178
            DoPratcamHit(&force);
3179
        }
3180
    }
3181
    if (gNet_mode == eNet_mode_host && (gCurrent_net_game->type == eNet_game_type_tag || gCurrent_net_game->type == eNet_game_type_foxy) && car2 != NULL
3182
        && c->driver >= eDriver_net_human && car2->driver >= eDriver_net_human) {
3183
        if (gNet_players[gIt_or_fox].car == c && car2->knackered) {
3184
            CarInContactWithItOrFox(NetPlayerFromCar(car2));
3185
        } else if (gNet_players[gIt_or_fox].car == car2 && !c->knackered) {
3186
            CarInContactWithItOrFox(NetPlayerFromCar(c));
3187
        }
3188
    }
3189
    if (gNet_mode != eNet_mode_client || car2 == NULL) {
3190
        DamageSystems(c, &position, &force, car2 != NULL);
3191
    }
3192
    if (c->driver <= eDriver_non_car || !c->invulnerable) {
3193
        for (i = 0; i < c->car_actor_count; i++) {
3194
            if (c->car_model_actors[i].min_distance_squared != -1.0f || (pForce_car_space->v[1] >= 0.0f && pForce_car_space->v[2] >= 0.0f)) {
3195
                CrushModel(c, i, c->car_model_actors[i].actor, &position, &force_for_bodywork, &c->car_model_actors[i].crush_data);
3196
            }
3197
        }
3198
        if (car2 && car2->driver == eDriver_local_human && ts > 0.003f) {
3199
            PipeSingleCarIncident(ts, c, &position);
3200
        }
3201
        if (!car2 && c->driver == eDriver_local_human && ts > 0.003f) {
3202
            BrMatrix34Copy(&m, &c->car_master_actor->t.t.mat);
3203
            m.m[3][0] /= WORLD_SCALE;
3204
            m.m[3][1] /= WORLD_SCALE;
3205
            m.m[3][2] /= WORLD_SCALE;
3206
            BrMatrix34ApplyP(&pos_w, &position, &m);
3207
            PipeSingleWallIncident(ts, &pos_w);
3208
        }
3209
    }
3210
    if (car2 != NULL && car2->driver == eDriver_local_human && ts > 0.003f) {
3211
        PipeSingleCarIncident(ts, c, &position);
3212
    }
3213
    if (car2 == NULL && c->driver == eDriver_local_human && ts > 0.003f) {
3214
        BrMatrix34Copy(&m, &c->car_master_actor->t.t.mat);
3215
        m.m[3][0] /= WORLD_SCALE;
3216
        m.m[3][1] /= WORLD_SCALE;
3217
        m.m[3][2] /= WORLD_SCALE;
3218
        BrMatrix34ApplyP(&pos_w, &position, &m);
3219
        PipeSingleWallIncident(ts, &pos_w);
3220
    }
3221
}
3222
 
3223
// IDA: int __usercall ExpandBoundingBox@<EAX>(tCar_spec *c@<EAX>)
3224
int ExpandBoundingBox(tCar_spec* c) {
3225
    br_scalar min_z;
3226
    br_scalar max_z;
3227
    br_scalar dist;
3228
    br_vector3 tv;
3229
    br_vector3 old_pos;
3230
    int l;
3231
    //br_matrix34 mat; // Pierre-Marie Baty -- unused variable
3232
    LOG_TRACE("(%p)", c);
3233
 
3234
    l = 0;
3235
    min_z = c->bounds[1].min.v[2];
3236
    max_z = c->bounds[1].max.v[2];
3237
    old_pos = *(br_vector3*)&c->oldmat.m[3][0];
3238
    CrushBoundingBox(c, 0);
3239
    for (l = 0; l < 5; l++) {
3240
        if (TestForCarInSensiblePlace(c)) {
3241
            break;
3242
        }
3243
        if (c->old_point.v[2] <= 0.0f) {
3244
            dist = min_z - c->bounds[1].min.v[2];
3245
        } else {
3246
            dist = c->bounds[1].max.v[2] - max_z;
3247
        }
3248
        if (dist >= 0.0f) {
3249
            dist += 0.005f;
3250
            BrVector3Scale(&c->old_norm, &c->old_norm, dist);
3251
            BrMatrix34ApplyV(&tv, &c->old_norm, &c->car_master_actor->t.t.mat);
3252
            c->oldmat.m[3][0] += tv.v[0];
3253
            c->oldmat.m[3][1] += tv.v[1];
3254
            c->oldmat.m[3][2] += tv.v[2];
3255
            l++;
3256
        } else {
3257
            l = 5;
3258
        }
3259
    }
3260
    if (l < 5) {
3261
        return 1;
3262
    }
3263
    *(br_vector3*)&c->oldmat.m[3][0] = old_pos;
3264
    c->bounds[1].min.v[2] = min_z;
3265
    c->bounds[1].max.v[2] = max_z;
3266
    if (c->driver == eDriver_local_human) {
21 pmbaty 3267
        NewTextHeadupSlot(eHeadupSlot_misc, 0, 1000, -4, GetMiscString(kMiscString_RepairObstructed));
1 pmbaty 3268
    }
3269
    return 0;
3270
}
3271
 
3272
// IDA: void __usercall CrushBoundingBox(tCar_spec *c@<EAX>, int crush_only@<EDX>)
3273
void CrushBoundingBox(tCar_spec* c, int crush_only) {
3274
    br_vector3 min;
3275
    br_vector3 max;
3276
    int i;
3277
    br_actor* actor;
3278
    LOG_TRACE("(%p, %d)", c, crush_only);
3279
 
3280
    if (c == NULL) {
3281
        return;
3282
    }
3283
    actor = c->car_model_actors[c->principal_car_actor].actor;
3284
    max.v[0] = c->wpos[2].v[2] - c->non_driven_wheels_circum / 6.2f;
3285
    min.v[0] = c->driven_wheels_circum / 6.2f + c->wpos[0].v[2];
3286
    max.v[0] /= WORLD_SCALE;
3287
    min.v[0] /= WORLD_SCALE;
3288
    for (i = 0; i < actor->model->nvertices; i++) {
3289
        if (actor->model->vertices[i].p.v[2] < max.v[0]) {
3290
            max.v[0] = actor->model->vertices[i].p.v[2];
3291
        }
3292
        if (actor->model->vertices[i].p.v[2] > min.v[0]) {
3293
            min.v[0] = actor->model->vertices[i].p.v[2];
3294
        }
3295
    }
3296
    max.v[0] *= WORLD_SCALE;
3297
    min.v[0] *= WORLD_SCALE;
3298
    if (crush_only) {
3299
        if (c->bounds[1].min.v[2] > max.v[0]) {
3300
            max.v[0] = c->bounds[1].min.v[2];
3301
        }
3302
        if (c->bounds[1].max.v[2] < min.v[0]) {
3303
            min.v[0] = c->bounds[1].max.v[2];
3304
        }
3305
    } else {
3306
        if (c->max_bounds[1].min.v[2] > max.v[0]) {
3307
            max.v[0] = c->max_bounds[1].min.v[2];
3308
        }
3309
        if (c->max_bounds[1].max.v[2] < min.v[0]) {
3310
            min.v[0] = c->max_bounds[1].max.v[2];
3311
        }
3312
    }
3313
    c->bounds[1].min.v[2] = max.v[0];
3314
    c->bounds[1].max.v[2] = min.v[0];
3315
    for (i = 0; i < c->extra_point_num; i++) {
3316
        if (c->max_bounds[1].max.v[2] + 0.01f >= c->original_extra_points_z[i] && c->max_bounds[1].min.v[2] - 0.01f <= c->original_extra_points_z[i]) {
3317
            if (c->original_extra_points_z[i] > min.v[0]) {
3318
                c->extra_points[i].v[2] = min.v[0];
3319
            } else if (c->original_extra_points_z[i] >= max.v[0]) {
3320
                c->extra_points[i].v[2] = c->original_extra_points_z[i];
3321
            } else {
3322
                c->extra_points[i].v[2] = max.v[0];
3323
            }
3324
            if (c->extra_points[i].v[2] > min.v[0]) {
3325
                c->extra_points[i].v[2] = min.v[0];
3326
            }
3327
            if (c->extra_points[i].v[2] < max.v[0]) {
3328
                c->extra_points[i].v[2] = max.v[0];
3329
            }
3330
        } else {
3331
            c->extra_points[i].v[2] = c->original_extra_points_z[i];
3332
        }
3333
    }
3334
}
3335
 
3336
// IDA: void __cdecl AddCollPoint(br_scalar dist, br_vector3 *p, br_vector3 *norm, br_vector3 *r, br_vector3 *n, br_vector3 *dir, int num, tCollision_info *c)
3337
void AddCollPoint(br_scalar dist, br_vector3* p, br_vector3* norm, br_vector3* r, br_vector3* n, br_vector3* dir, int num, tCollision_info* c) {
3338
    static br_scalar d[4];
3339
    int i;
3340
    int furthest;
3341
    LOG_TRACE("(%f, %p, %p, %p, %p, %p, %d, %p)", dist, p, norm, r, n, dir, num, c);
3342
 
3343
    if (num < 4) {
3344
        d[num] = dist;
3345
        n[num] = *norm;
3346
        BrVector3Sub(&r[num], p, &c->cmpos);
3347
        return;
3348
    }
3349
    furthest = 0;
3350
    for (i = 1; i < 4; i++) {
3351
        if (d[furthest] < d[i]) {
3352
            furthest = i;
3353
        }
3354
    }
3355
    if (d[furthest] >= dist) {
3356
        num = furthest;
3357
        d[num] = dist;
3358
        n[num] = *norm;
3359
        BrVector3Sub(&r[num], p, &c->cmpos);
3360
    }
3361
}
3362
 
3363
// IDA: br_scalar __usercall SinglePointColl@<ST0>(br_scalar *f@<EAX>, br_matrix4 *m@<EDX>, br_scalar *d@<EBX>)
3364
br_scalar SinglePointColl(br_scalar* f, br_matrix4* m, br_scalar* d) {
3365
    LOG_TRACE("(%p, %p, %p)", f, m, d);
3366
 
3367
    f[0] = d[0] / m->m[0][0];
3368
    if (f[0] < 0.0f) {
3369
        f[0] = 0.f;
3370
    }
3371
    return fabsf(m->m[0][0]);
3372
}
3373
 
3374
// IDA: br_scalar __usercall TwoPointColl@<ST0>(br_scalar *f@<EAX>, br_matrix4 *m@<EDX>, br_scalar *d@<EBX>, br_vector3 *tau@<ECX>, br_vector3 *n)
3375
br_scalar TwoPointColl(br_scalar* f, br_matrix4* m, br_scalar* d, br_vector3* tau, br_vector3* n) {
3376
    br_scalar ts;
3377
    LOG_TRACE("(%p, %p, %p, %p, %p)", f, m, d, tau, n);
3378
 
3379
    ts = m->m[1][1] * m->m[0][0] - m->m[0][1] * m->m[1][0];
3380
 
3381
    if (fabsf(ts) >= 0.000001f) {
3382
        f[0] = (m->m[1][1] * d[0] - m->m[0][1] * d[1]) / ts;
3383
        f[1] = (m->m[1][0] * d[0] - m->m[0][0] * d[1]) / -ts;
3384
    }
3385
    if (f[1] < 0.0f || fabs(ts) < 0.000001f) {
3386
        ts = SinglePointColl(f, m, d);
3387
        f[1] = 0.0f;
3388
    } else if (f[0] < 0.0f) {
3389
        m->m[0][0] = m->m[1][1];
3390
        tau[0] = tau[1];
3391
        n[0] = n[1];
3392
        d[0] = d[1];
3393
        ts = SinglePointColl(f, m, d);
3394
        f[1] = 0.0;
3395
    }
3396
    return fabsf(ts);
3397
}
3398
 
3399
// IDA: br_scalar __usercall DrMatrix4Inverse@<ST0>(br_matrix4 *mi@<EAX>, br_matrix4 *mc@<EDX>)
3400
br_scalar DrMatrix4Inverse(br_matrix4* mi, br_matrix4* mc) {
3401
    LOG_TRACE("(%p, %p)", mi, mc);
3402
 
3403
    return BrMatrix4Inverse(mi, mc);
3404
}
3405
 
3406
// IDA: br_scalar __usercall ThreePointColl@<ST0>(br_scalar *f@<EAX>, br_matrix4 *m@<EDX>, br_scalar *d@<EBX>)
3407
br_scalar ThreePointColl(br_scalar* f, br_matrix4* m, br_scalar* d) {
3408
    br_matrix4 mc;
3409
    br_matrix4 mi;
3410
    br_scalar ts;
3411
    LOG_TRACE("(%p, %p, %p)", f, m, d);
3412
 
3413
    BrMatrix4Copy(&mc, m);
3414
    memset(&mc.m[2][3], 0, 16);
3415
    mc.m[1][3] = 0.0f;
3416
    mc.m[0][3] = 0.0f;
3417
    mc.m[3][3] = 1.0f;
3418
    ts = DrMatrix4Inverse(&mi, &mc);
3419
    BrMatrix4TApply((br_vector4*)f, (br_vector4*)d, &mi);
3420
    f[3] = 0.0f;
3421
    return fabs(ts);
3422
}
3423
 
3424
// IDA: br_scalar __usercall ThreePointCollRec@<ST0>(br_scalar *f@<EAX>, br_matrix4 *m@<EDX>, br_scalar *d@<EBX>, br_vector3 *tau@<ECX>, br_vector3 *n, tCollision_info *c)
3425
br_scalar ThreePointCollRec(br_scalar* f, br_matrix4* m, br_scalar* d, br_vector3* tau, br_vector3* n, tCollision_info* c) {
3426
    int i;
3427
    int j;
3428
    br_scalar ts;
3429
    LOG_TRACE("(%p, %p, %p, %p, %p, %p)", f, m, d, tau, n, c);
3430
 
3431
    ts = ThreePointColl(f, m, d);
3432
    if (f[0] >= 0.0f && f[1] >= 0.0f && f[2] >= 0.0f && ts >= 0.000001f) {
3433
        c->infinite_mass = 256;
3434
        return ts;
3435
    }
3436
    if (ts < 0.000001f) {
3437
        i = 0;
3438
        j = 1;
3439
    } else if (f[0] < 0.0f) {
3440
        i = 1;
3441
        j = 2;
3442
    } else if (f[1] < 0.0f) {
3443
        i = 0;
3444
        j = 2;
3445
    } else if (f[2] < 0.0f) {
3446
        i = 0;
3447
        j = 1;
3448
    } else {
3449
        return 0.0f;
3450
    }
3451
    m->m[0][0] = ((float*)m->m)[5 * i];
3452
    m->m[1][0] = m->m[j][i];
3453
    m->m[0][1] = m->m[i][j];
3454
    m->m[1][1] = ((float*)m->m)[5 * j];
3455
    tau[0] = tau[i];
3456
    tau[1] = tau[j];
3457
    n[0] = n[i];
3458
    n[1] = n[j];
3459
    d[0] = d[i];
3460
    d[1] = d[j];
3461
    ts = TwoPointColl(f, m, d, tau, n);
3462
    f[2] = 0.0f;
3463
    return ts;
3464
}
3465
 
3466
// IDA: br_scalar __usercall FourPointColl@<ST0>(br_scalar *f@<EAX>, br_matrix4 *m@<EDX>, br_scalar *d@<EBX>, br_vector3 *tau@<ECX>, br_vector3 *n, tCollision_info *c)
3467
br_scalar FourPointColl(br_scalar* f, br_matrix4* m, br_scalar* d, br_vector3* tau, br_vector3* n, tCollision_info* c) {
3468
    int i;
3469
    int j;
3470
    int l;
3471
    br_scalar ts;
3472
    LOG_TRACE("(%p, %p, %p, %p, %p, %p)", f, m, d, tau, n, c);
3473
 
3474
    ts = ThreePointColl(f, m, d);
3475
    if (f[0] < 0.0 || f[1] < 0.0 || f[2] < 0.0 || ts < 0.000001) {
3476
        if (ts < 0.000001) {
3477
            j = 3;
3478
        } else if (f[0] < 0.0) {
3479
            j = 0;
3480
        } else if (f[1] >= 0.0) {
3481
            j = 2;
3482
        } else {
3483
            j = 1;
3484
        }
3485
        for (i = j; i < 3; ++i) {
3486
            for (l = 0; l < 4; ++l) {
3487
                m->m[i][l] = m->m[i + 1][l];
3488
            }
3489
            d[i] = d[i + 1];
3490
            tau[i] = tau[i + 1];
3491
            n[i] = n[i + 1];
3492
            d[i] = d[i + 1];
3493
        }
3494
        for (i = j; i < 3; ++i) {
3495
            for (l = 0; l < 3; ++l) {
3496
                m->m[l][i] = m->m[l][i + 1];
3497
            }
3498
        }
3499
        return ThreePointCollRec(f, m, d, tau, n, c);
3500
    } else {
3501
        c->infinite_mass = 256;
3502
        return ts;
3503
    }
3504
}
3505
 
3506
// IDA: void __usercall MultiFindFloorInBoxM(int pNum_rays@<EAX>, br_vector3 *a@<EDX>, br_vector3 *b@<EBX>, br_vector3 *nor@<ECX>, br_scalar *d, tCar_spec *c, int *mat_ref)
3507
void MultiFindFloorInBoxM(int pNum_rays, br_vector3* a, br_vector3* b, br_vector3* nor, br_scalar* d, tCar_spec* c, int* mat_ref) {
3508
    br_vector3 aa[4];
3509
    br_vector3 bb;
3510
    int i;
3511
    LOG_TRACE("(%d, %p, %p, %p, %p, %p, %p)", pNum_rays, a, b, nor, d, c, mat_ref);
3512
 
3513
    for (i = 0; i < pNum_rays; i++) {
3514
        aa[i].v[0] = a[i].v[0] / WORLD_SCALE;
3515
        aa[i].v[1] = a[i].v[1] / WORLD_SCALE;
3516
        aa[i].v[2] = a[i].v[2] / WORLD_SCALE;
3517
        d[i] = 2.0;
3518
    }
3519
    bb.v[0] = b->v[0] / WORLD_SCALE;
3520
    bb.v[1] = b->v[1] / WORLD_SCALE;
3521
    bb.v[2] = b->v[2] / WORLD_SCALE;
3522
    MultiFindFloorInBoxBU(pNum_rays, aa, &bb, nor, d, c, mat_ref);
3523
}
3524
 
3525
// IDA: void __usercall MultiFindFloorInBoxBU(int pNum_rays@<EAX>, br_vector3 *a@<EDX>, br_vector3 *b@<EBX>, br_vector3 *nor@<ECX>, br_scalar *d, tCar_spec *c, int *mat_ref)
3526
void MultiFindFloorInBoxBU(int pNum_rays, br_vector3* a, br_vector3* b, br_vector3* nor, br_scalar* d, tCar_spec* c, int* mat_ref) {
3527
    br_vector3 nor2;
3528
    int i;
3529
    int j;
3530
    int l;
3531
    br_scalar dist[4];
3532
    tFace_ref* face_ref;
3533
    LOG_TRACE("(%d, %p, %p, %p, %p, %p, %p)", pNum_rays, a, b, nor, d, c, mat_ref);
3534
 
3535
    for (i = c->box_face_start; i < c->box_face_end; i++) {
3536
        face_ref = &gFace_list__car[i];
3537
        if (!gEliminate_faces || (face_ref->flags & 0x80) == 0x0) {
3538
            MultiRayCheckSingleFace(pNum_rays, face_ref, a, b, &nor2, dist);
3539
            for (j = 0; j < pNum_rays; ++j) {
3540
                if (d[j] > dist[j]) {
3541
                    d[j] = dist[j];
3542
                    nor[j] = nor2;
3543
                    l = *gFace_list__car[i].material->identifier - 47;
3544
                    if (l >= 0 && l < 11) {
3545
                        mat_ref[j] = l;
3546
                    }
3547
                }
3548
            }
3549
        }
3550
    }
3551
}
3552
 
3553
// IDA: void __usercall findfloor(br_vector3 *a@<EAX>, br_vector3 *b@<EDX>, br_vector3 *nor@<EBX>, br_scalar *d@<ECX>)
3554
void findfloor(br_vector3* a, br_vector3* b, br_vector3* nor, br_scalar* d) {
3555
    br_material* material;
3556
    br_vector3 aa;
3557
    br_vector3 bb;
3558
    LOG_TRACE("(%p, %p, %p, %p)", a, b, nor, d);
3559
 
3560
    BrVector3InvScale(&aa, a, WORLD_SCALE);
3561
    BrVector3InvScale(&bb, b, WORLD_SCALE);
3562
    FindFace(&aa, &bb, nor, d, &material);
3563
}
3564
 
3565
// IDA: int __usercall FindFloorInBoxM@<EAX>(br_vector3 *a@<EAX>, br_vector3 *b@<EDX>, br_vector3 *nor@<EBX>, br_scalar *d@<ECX>, tCollision_info *c)
3566
int FindFloorInBoxM(br_vector3* a, br_vector3* b, br_vector3* nor, br_scalar* d, tCollision_info* c) {
3567
    br_vector3 aa;
3568
    br_vector3 bb;
3569
    LOG_TRACE("(%p, %p, %p, %p, %p)", a, b, nor, d, c);
3570
 
3571
    aa.v[0] = a->v[0] / WORLD_SCALE;
3572
    aa.v[1] = a->v[1] / WORLD_SCALE;
3573
    aa.v[2] = a->v[2] / WORLD_SCALE;
3574
    bb.v[0] = b->v[0] / WORLD_SCALE;
3575
    bb.v[1] = b->v[1] / WORLD_SCALE;
3576
    bb.v[2] = b->v[2] / WORLD_SCALE;
3577
    return FindFloorInBoxBU(&aa, &bb, nor, d, c);
3578
}
3579
 
3580
// IDA: int __usercall FindFloorInBoxBU@<EAX>(br_vector3 *a@<EAX>, br_vector3 *b@<EDX>, br_vector3 *nor@<EBX>, br_scalar *d@<ECX>, tCollision_info *c)
3581
int FindFloorInBoxBU(br_vector3* a, br_vector3* b, br_vector3* nor, br_scalar* d, tCollision_info* c) {
3582
    br_vector3 nor2;
3583
    int i;
3584
    int j;
3585
    br_scalar dist;
3586
    tFace_ref* face_ref;
3587
    LOG_TRACE("(%p, %p, %p, %p, %p)", a, b, nor, d, c);
3588
 
3589
#if defined(DETHRACE_FIX_BUGS)
3590
    j = 0; // added to keep compiler happy
3591
#endif
3592
    *d = 2.0;
3593
    for (i = c->box_face_start; i < c->box_face_end; i++) {
3594
        face_ref = &gFace_list__car[i];
3595
        if (!gEliminate_faces || SLOBYTE(face_ref->flags) >= 0) {
3596
            CheckSingleFace(face_ref, a, b, &nor2, &dist);
3597
            if (*d > dist) {
3598
                *d = dist;
3599
                j = i;
3600
                BrVector3Copy(nor, &nor2);
3601
            }
3602
        }
3603
    }
3604
    if (*d >= 2.f) {
3605
        return 0;
3606
    }
3607
    i = gFace_list__car[j].material->identifier[0] - ('0' - 1);
3608
    if (i < 0 || i >= 11) {
3609
        return 0;
3610
    } else {
3611
        return i;
3612
    }
3613
}
3614
 
3615
// IDA: int __usercall FindFloorInBoxBU2@<EAX>(br_vector3 *a@<EAX>, br_vector3 *b@<EDX>, br_vector3 *nor@<EBX>, br_scalar *d@<ECX>, tCollision_info *c)
3616
int FindFloorInBoxBU2(br_vector3* a, br_vector3* b, br_vector3* nor, br_scalar* d, tCollision_info* c) {
3617
    br_vector3 nor2;
3618
    br_vector3 tv;
3619
    int i;
3620
    int j;
3621
    br_scalar dist;
3622
    tFace_ref* face_ref;
3623
    LOG_TRACE("(%p, %p, %p, %p, %p)", a, b, nor, d, c);
3624
 
3625
#if defined(DETHRACE_FIX_BUGS)
3626
    j = 0; // added to keep compiler happy
3627
#endif
3628
    *d = 2.f;
3629
    for (i = c->box_face_start; i < c->box_face_end; i++) {
3630
        face_ref = &gFace_list__car[i];
3631
        if (!gEliminate_faces || SLOBYTE(face_ref->flags) >= 0) {
3632
            CheckSingleFace(face_ref, a, b, &nor2, &dist);
3633
            if (*d > dist) {
3634
                if (face_ref->material->user == DOUBLESIDED_USER_FLAG || (face_ref->material->flags & (BR_MATF_ALWAYS_VISIBLE | BR_MATF_TWO_SIDED)) != 0) {
3635
                    BrVector3Sub(&tv, &c->pos, a);
3636
                    if (BrVector3Dot(&tv, &nor2) >= 0.f) {
3637
                        *d = dist;
3638
                        j = i;
3639
                        BrVector3Copy(nor, &nor2);
3640
                    }
3641
                } else {
3642
                    *d = dist;
3643
                    j = i;
3644
                    BrVector3Copy(nor, &nor2);
3645
                }
3646
            }
3647
        }
3648
        face_ref++;
3649
    }
3650
    if (*d >= 2.f) {
3651
        return 0;
3652
    }
3653
    i = gFace_list__car[j].material->identifier[0] - ('0' - 1);
3654
    if (i < 0 || i >= 11) {
3655
        return 0;
3656
    } else {
3657
        return i;
3658
    }
3659
}
3660
 
3661
// IDA: int __usercall FindFloorInBoxM2@<EAX>(br_vector3 *a@<EAX>, br_vector3 *b@<EDX>, br_vector3 *nor@<EBX>, br_scalar *d@<ECX>, tCollision_info *c)
3662
int FindFloorInBoxM2(br_vector3* a, br_vector3* b, br_vector3* nor, br_scalar* d, tCollision_info* c) {
3663
    br_vector3 aa;
3664
    br_vector3 bb;
3665
    LOG_TRACE("(%p, %p, %p, %p, %p)", a, b, nor, d, c);
3666
 
3667
    aa.v[0] = a->v[0] / WORLD_SCALE;
3668
    aa.v[1] = a->v[1] / WORLD_SCALE;
3669
    aa.v[2] = a->v[2] / WORLD_SCALE;
3670
    bb.v[0] = b->v[0] / WORLD_SCALE;
3671
    bb.v[1] = b->v[1] / WORLD_SCALE;
3672
    bb.v[2] = b->v[2] / WORLD_SCALE;
3673
    return FindFloorInBoxBU2(&aa, &bb, nor, d, c);
3674
}
3675
 
3676
// IDA: int __usercall BoxFaceIntersect@<EAX>(br_bounds *pB@<EAX>, br_matrix34 *pM@<EDX>, br_matrix34 *pMold@<EBX>, br_vector3 *pPoint_list@<ECX>, br_vector3 *pNorm_list, br_scalar *pDist_list, int pMax_pnts, tCollision_info *c)
3677
int BoxFaceIntersect(br_bounds* pB, br_matrix34* pM, br_matrix34* pMold, br_vector3* pPoint_list, br_vector3* pNorm_list, br_scalar* pDist_list, int pMax_pnts, tCollision_info* c) {
3678
    br_vector3 p[3];
3679
    br_vector3 tv;
3680
    br_vector3 pos;
3681
    br_bounds bnds;
3682
    int i;
3683
    int j;
3684
    int n;
3685
    int flag;
3686
    int m;
3687
    tFace_ref* f_ref;
3688
    //br_face* face; // Pierre-Marie Baty -- unused variable
3689
    LOG_TRACE("(%p, %p, %p, %p, %p, %p, %d, %p)", pB, pM, pMold, pPoint_list, pNorm_list, pDist_list, pMax_pnts, c);
3690
 
3691
    n = 0;
3692
    BrVector3InvScale(&bnds.min, &pB->min, WORLD_SCALE);
3693
    BrVector3InvScale(&bnds.max, &pB->max, WORLD_SCALE);
3694
    BrVector3InvScale(&pos, (br_vector3*)pM->m[3], WORLD_SCALE);
3695
    BrVector3InvScale((br_vector3*)pMold->m[3], (br_vector3*)pMold->m[3], WORLD_SCALE);
3696
 
3697
    for (i = c->box_face_start; i < c->box_face_end && i < c->box_face_start + 50; i++) {
3698
        f_ref = &gFace_list__car[i];
3699
        if (SLOBYTE(f_ref->flags) >= 0 && f_ref->material->identifier[0] != '!') {
3700
            BrVector3Sub(&tv, &f_ref->v[0], &pos);
3701
            BrMatrix34TApplyV(&p[0], &tv, pM);
3702
            BrVector3Sub(&tv, &f_ref->v[1], &pos);
3703
            BrMatrix34TApplyV(&p[1], &tv, pM);
3704
            BrVector3Sub(&tv, &f_ref->v[2], &pos);
3705
            BrMatrix34TApplyV(&p[2], &tv, pM);
3706
            j = n;
3707
            if ((f_ref->flags & 1) == 0) {
3708
                n += AddEdgeCollPoints(&p[0], &p[1], &bnds, pMold, pPoint_list, pNorm_list, n, pMax_pnts, c);
3709
            }
3710
            if ((f_ref->flags & 2) == 0) {
3711
                n += AddEdgeCollPoints(&p[1], &p[2], &bnds, pMold, pPoint_list, pNorm_list, n, pMax_pnts, c);
3712
            }
3713
            if ((f_ref->flags & 4) == 0) {
3714
                n += AddEdgeCollPoints(&p[2], &p[0], &bnds, pMold, pPoint_list, pNorm_list, n, pMax_pnts, c);
3715
            }
3716
            if (n > j) {
3717
                if (gMaterial_index == 0) {
3718
                    m = f_ref->material->identifier[0] - '/';
3719
                    if (m > 0 && m < 11) {
3720
                        gMaterial_index = m;
3721
                    }
3722
                }
3723
                while (j < n) {
3724
                    BrVector3Scale(&pPoint_list[j], &pPoint_list[j], WORLD_SCALE);
3725
                    BrVector3Sub(&pPoint_list[j], &pPoint_list[j], &c->cmpos);
3726
                    j++;
3727
                }
3728
            }
3729
        }
3730
    }
3731
    if (n) {
3732
        m = 0;
3733
        for (i = 0; i < n - 1; i++) {
3734
            flag = 1;
3735
            for (j = i + 1; j < n; j++) {
3736
                if (fabsf(pPoint_list[i].v[0] - pPoint_list[j].v[0]) <= 0.001f
3737
                    && fabsf(pPoint_list[i].v[1] - pPoint_list[j].v[1]) <= 0.001f
3738
                    && fabsf(pPoint_list[i].v[2] - pPoint_list[j].v[2]) <= 0.001f) {
3739
                    flag = 0;
3740
                    break;
3741
                }
3742
            }
3743
            if (flag) {
3744
                BrVector3Copy(&pPoint_list[m], &pPoint_list[i]);
3745
                m++;
3746
            }
3747
        }
3748
        BrVector3Copy(&pPoint_list[m], &pPoint_list[n - 1]);
3749
        n = m + 1;
3750
    }
3751
    BrVector3Scale((br_vector3*)pMold->m[3], (br_vector3*)pMold->m[3], WORLD_SCALE);
3752
    return n;
3753
}
3754
 
3755
// IDA: int __usercall AddEdgeCollPoints@<EAX>(br_vector3 *p1@<EAX>, br_vector3 *p2@<EDX>, br_bounds *pB@<EBX>, br_matrix34 *pMold@<ECX>, br_vector3 *pPoint_list, br_vector3 *pNorm_list, int n, int pMax_pnts, tCollision_info *c)
3756
int AddEdgeCollPoints(br_vector3* p1, br_vector3* p2, br_bounds* pB, br_matrix34* pMold, br_vector3* pPoint_list, br_vector3* pNorm_list, int n, int pMax_pnts, tCollision_info* c) {
3757
    br_vector3 op1;
3758
    br_vector3 op2;
3759
    br_vector3 a;
3760
    br_vector3 b;
3761
    br_vector3 edge;
3762
    br_vector3 hp1;
3763
    br_vector3 hp2;
3764
    br_vector3 hp3;
3765
    int plane1;
3766
    int plane2;
3767
    int plane3;
3768
    int d;
3769
    LOG_TRACE("(%p, %p, %p, %p, %p, %p, %d, %d, %p)", p1, p2, pB, pMold, pPoint_list, pNorm_list, n, pMax_pnts, c);
3770
 
3771
    //float scale; // Pierre-Marie Baty -- unused variable
3772
 
3773
    plane1 = LineBoxColl(p1, p2, pB, &hp1);
3774
    if (plane1 == 0) {
3775
        return 0;
3776
    }
3777
    if (n + 2 > pMax_pnts) {
3778
        return 0;
3779
    }
3780
    plane2 = LineBoxColl(p2, p1, pB, &hp2);
3781
    if (plane2 == 0) {
3782
        return 0;
3783
    }
3784
    if (plane1 != 8 && plane2 != 8 && (plane1 ^ plane2) == 4) {
3785
        BrVector3Add(&op1, &hp2, &hp1);
3786
        BrVector3Scale(&op1, &op1, .5f);
3787
        BrMatrix34ApplyP(&op2, &op1, pMold);
3788
        plane3 = LineBoxColl(&op2, &op1, pB, &hp3);
3789
        if (plane3 == 8) {
3790
            return 0;
3791
        }
3792
        GetBoundsEdge(&pPoint_list[n], &edge, pB, plane1, plane3, &op2, &hp1, &hp2, c->collision_flag);
3793
        GetBoundsEdge(&pPoint_list[n + 1], &edge, pB, plane2, plane3, &op2, &hp1, &hp2, c->collision_flag);
3794
        GetPlaneNormal(&pNorm_list[n], plane3);
3795
        BrVector3Copy(&pNorm_list[n + 1], &pNorm_list[n]);
3796
        return 2;
3797
    } else if (plane1 == 8 && plane2 != 8) {
3798
        BrMatrix34ApplyP(&a, p1, pMold);
3799
        plane3 = LineBoxColl(&a, p1, pB, &hp3);
3800
        if (plane3 == 8) {
3801
            return 0;
3802
        }
3803
        BrVector3Copy(&pPoint_list[n], &hp3);
3804
        GetPlaneNormal(&pNorm_list[n], plane2);
3805
        if (plane2 == plane3 || (plane3 ^ plane2) == 4) {
3806
            return 1;
3807
        }
3808
        GetBoundsEdge(&pPoint_list[n + 1], &edge, pB, plane2, plane3, p1, &hp2, &hp3, c->collision_flag);
3809
        BrVector3Sub(&op1, p1, p2);
3810
        BrVector3Cross(&pNorm_list[n + 1], &edge, &op1);
3811
        BrVector3Normalise(&pNorm_list[n + 1], &pNorm_list[n + 1]);
3812
        d = (plane2 - 1) & 3;
3813
        if ((pNorm_list[n + 1].v[d] < 0.f) == (plane2 & 4) >> 2) {
3814
            BrVector3Negate(&pNorm_list[n + 1], &pNorm_list[n + 1]);
3815
        }
3816
        BrVector3Copy(&op1, &pNorm_list[n + 1]);
3817
        BrMatrix34ApplyV(&pNorm_list[n + 1], &op1, pMold);
3818
        return 2;
3819
    } else if (plane2 == 8 && plane1 != 8) {
3820
        BrMatrix34ApplyP(&b, p2, pMold);
3821
        plane3 = LineBoxColl(&b, p2, pB, &hp3);
3822
        if (plane3 == 8) {
3823
            return 0;
3824
        }
3825
        pPoint_list[n] = hp3;
3826
        GetPlaneNormal(&pNorm_list[n], plane1);
3827
        if (plane1 == plane3 || (plane3 ^ plane1) == 4) {
3828
            return 1;
3829
        }
3830
        GetBoundsEdge(&pPoint_list[n + 1], &edge, pB, plane1, plane3, p2, &hp1, &hp3, c->collision_flag);
3831
        BrVector3Sub(&op1, p1, p2);
3832
        BrVector3Cross(&pNorm_list[n + 1], &edge, &op1);
3833
        BrVector3Normalise(&pNorm_list[n + 1], &pNorm_list[n + 1]);
3834
        d = (plane1 - 1) & 3;
3835
        if ((pNorm_list[n + 1].v[d] < 0.f) == (plane1 & 4) >> 2) {
3836
            BrVector3Negate(&pNorm_list[n + 1], &pNorm_list[n + 1]);
3837
        }
3838
        BrVector3Copy(&op1, &pNorm_list[n + 1]);
3839
        BrMatrix34ApplyV(&pNorm_list[n + 1], &op1, pMold);
3840
        return 2;
3841
    } else if (plane1 != 8 && plane2 != 8) {
3842
        BrVector3Add(&op1, &hp2, &hp1);
3843
        BrVector3Scale(&op1, &op1, .5f);
3844
        BrMatrix34ApplyP(&op2, &op1, pMold);
3845
        plane3 = LineBoxColl(&op2, &op1, pB, &hp3);
3846
        if (plane3 == 8 || plane3 == 0) {
3847
            return 0;
3848
        }
3849
        if (plane1 == plane3 || plane2 == plane3) {
3850
            GetBoundsEdge(&pPoint_list[n], &edge, pB, plane1, plane2, &op2, &hp1, &hp2, c->collision_flag);
3851
            BrVector3Sub(&op1, &hp1, &hp2);
3852
            BrVector3Cross(&op2, &edge, &op1);
3853
            BrVector3Normalise(&pNorm_list[n], &op2);
3854
            BrVector3Add(&op1, &pB->max, &pB->min);
3855
            BrVector3Scale(&op1, &op1, .5f);
3856
            BrVector3Sub(&op1, &pPoint_list[n], &op1);
3857
            if (BrVector3Dot(&pNorm_list[n], &op1) > 0.f) {
3858
                BrVector3Negate(&pNorm_list[n], &pNorm_list[n]);
3859
            }
3860
            BrVector3Copy(&op1, &pNorm_list[n]);
3861
            BrMatrix34ApplyV(&pNorm_list[n], &op1, pMold);
3862
            return 1;
3863
        } else {
3864
            GetBoundsEdge(&pPoint_list[n], &edge, pB, plane1, plane3, &hp3, &hp1, &hp2, c->collision_flag);
3865
            GetBoundsEdge(&pPoint_list[n + 1], &edge, pB, plane2, plane3, &hp3, &hp1, &hp2, c->collision_flag);
3866
            GetPlaneNormal(&pNorm_list[n], plane3);
3867
            BrVector3Copy(&pNorm_list[n + 1], &pNorm_list[n]);
3868
            return 2;
3869
        }
3870
    } else if (plane1 == 8 && plane2 == 8) {
3871
        BrMatrix34ApplyP(&op1, p1, pMold);
3872
        plane3 = LineBoxColl(&op1, p1, pB, &pPoint_list[n]);
3873
        GetPlaneNormal(&pNorm_list[n], plane3);
3874
        d = n + (plane3 != 8);
3875
        BrMatrix34ApplyP(&op1, p2, pMold);
3876
        plane3 = LineBoxColl(&op1, p2, pB, &pPoint_list[d]);
3877
        GetPlaneNormal(&pNorm_list[d], plane3);
3878
        return (n != d) + (plane3 != 8);
3879
    } else {
3880
        return 0;
3881
    }
3882
}
3883
 
3884
// IDA: void __usercall GetPlaneNormal(br_vector3 *n@<EAX>, int p@<EDX>)
3885
void GetPlaneNormal(br_vector3* n, int p) {
3886
    int d;
3887
    LOG_TRACE("(%p, %d)", n, p);
3888
 
3889
    d = (p - 1) & 3;
3890
    BrVector3Set(n, 0.f, 0.f, 0.f);
3891
    if ((p & 4) != 0) {
3892
        n->v[d] = 1.0f;
3893
    } else {
3894
        n->v[d] = -1.0f;
3895
    }
3896
}
3897
 
3898
// IDA: int __usercall GetBoundsEdge@<EAX>(br_vector3 *pos@<EAX>, br_vector3 *edge@<EDX>, br_bounds *pB@<EBX>, int plane1@<ECX>, int plane2, br_vector3 *a, br_vector3 *b, br_vector3 *c, int flag)
3899
int GetBoundsEdge(br_vector3* pos, br_vector3* edge, br_bounds* pB, int plane1, int plane2, br_vector3* a, br_vector3* b, br_vector3* c, int flag) {
3900
    int d1;
3901
    int d2;
3902
    int d3;
3903
    br_vector3 n;
3904
    br_vector3 p;
3905
    br_vector3 q;
3906
    LOG_TRACE("(%p, %p, %p, %d, %d, %p, %p, %p, %d)", pos, edge, pB, plane1, plane2, a, b, c, flag);
3907
 
3908
    d1 = (plane1 - 1) & 3;
3909
    d2 = (plane2 - 1) & 3;
3910
    BrVector3Sub(&n, b, a);
3911
    BrVector3Sub(&p, c, a);
3912
    BrVector3Cross(&q, &n, &p);
3913
    if ((plane1 & 4) != 0) {
3914
        pos->v[d1] = pB->min.v[d1];
3915
    } else {
3916
        pos->v[d1] = pB->max.v[d1];
3917
    }
3918
    if ((plane2 & 4) != 0) {
3919
        pos->v[d2] = pB->min.v[d2];
3920
    } else {
3921
        pos->v[d2] = pB->max.v[d2];
3922
    }
3923
    d3 = 3 - d1 - d2;
3924
    edge->v[d1] = 0.f;
3925
    edge->v[d2] = 0.f;
3926
    edge->v[d3] = 1.f;
3927
    if ((flag & 1) != 0) {
3928
        pos->v[d3] = (c->v[d3] + b->v[d3]) / 2.f;
3929
    } else {
3930
        pos->v[d3] = a->v[d3] - ((pos->v[d2] - a->v[d2]) * q.v[d2] + (pos->v[d1] - a->v[d1]) * q.v[d1]) / q.v[d3];
3931
    }
3932
    return 1;
3933
}
3934
 
3935
// IDA: void __usercall oldMoveOurCar(tU32 pTime_difference@<EAX>)
3936
void oldMoveOurCar(tU32 pTime_difference) {
3937
    //br_vector3 thrust_vector; // Pierre-Marie Baty -- unused variable
3938
    //br_matrix34 direction_matrix; // Pierre-Marie Baty -- unused variable
3939
    //br_matrix34 old_mat; // Pierre-Marie Baty -- unused variable
3940
    //double rotate_amount; // Pierre-Marie Baty -- unused variable
3941
    //br_scalar nearest_y_above; // Pierre-Marie Baty -- unused variable
3942
    //br_scalar nearest_y_below; // Pierre-Marie Baty -- unused variable
3943
    //br_scalar speed; // Pierre-Marie Baty -- unused variable
3944
    //int below_face_index; // Pierre-Marie Baty -- unused variable
3945
    //int above_face_index; // Pierre-Marie Baty -- unused variable
3946
    //br_model* below_model; // Pierre-Marie Baty -- unused variable
3947
    //br_model* above_model; // Pierre-Marie Baty -- unused variable
3948
    LOG_TRACE("(%d)", pTime_difference);
3949
    NOT_IMPLEMENTED();
3950
}
3951
 
3952
// IDA: void __cdecl ToggleCollisionDetection()
3953
void ToggleCollisionDetection(void) {
3954
    LOG_TRACE("()");
3955
    NOT_IMPLEMENTED();
3956
}
3957
 
3958
// IDA: void __cdecl CancelPendingCunningStunt()
3959
void CancelPendingCunningStunt(void) {
3960
    LOG_TRACE("()");
3961
 
3962
    gQuite_wild_end = 0;
3963
    gQuite_wild_start = 0;
3964
    gOn_me_wheels_start = 0;
3965
    gWoz_upside_down_at_all = 0;
3966
    gWild_start = 0;
3967
}
3968
 
3969
// IDA: float __cdecl frac(float pN)
3970
float frac(float pN) {
3971
    LOG_TRACE("(%f)", pN);
3972
 
3973
    return pN - (float)(int)pN;
3974
}
3975
 
3976
// IDA: void __usercall SetAmbientPratCam(tCar_spec *pCar@<EAX>)
3977
void SetAmbientPratCam(tCar_spec* pCar) {
3978
    br_scalar vcs_x;
3979
    br_scalar vcs_y;
3980
    br_scalar vcs_z;
3981
    br_scalar abs_vcs_x;
3982
    br_scalar abs_vcs_y;
3983
    br_scalar abs_vcs_z;
3984
    br_scalar abs_omega_x;
3985
    br_scalar abs_omega_y;
3986
    br_scalar abs_omega_z;
3987
    tU32 the_time;
3988
    static tU32 last_time_on_ground;
3989
    LOG_TRACE("(%p)", pCar);
3990
 
3991
    if (gRace_finished) {
3992
        return;
3993
    }
3994
    the_time = GetTotalTime();
3995
    if (pCar->number_of_wheels_on_ground != 0) {
3996
        last_time_on_ground = the_time;
3997
    }
3998
    vcs_x = pCar->velocity_car_space.v[0];
3999
    vcs_y = pCar->velocity_car_space.v[1];
4000
    vcs_z = pCar->velocity_car_space.v[2];
4001
    abs_vcs_x = fabsf(vcs_x);
4002
    abs_vcs_y = fabsf(vcs_y);
4003
    abs_vcs_z = fabsf(vcs_z);
4004
    abs_omega_x = fabsf(pCar->omega.v[0]);
4005
    abs_omega_y = fabsf(pCar->omega.v[1]);
4006
    abs_omega_z = fabsf(pCar->omega.v[2]);
4007
 
4008
    if (abs_omega_x > 4.5f || abs_omega_z > 4.5f) {
4009
        ChangeAmbientPratcam(9);
4010
    } else if (abs_omega_y > 4.5f) {
4011
        ChangeAmbientPratcam(12);
4012
    } else if (abs_omega_x > 3.f || abs_omega_z > 3.f) {
4013
        ChangeAmbientPratcam(8);
4014
    } else if (abs_omega_y > 3.f) {
4015
        ChangeAmbientPratcam(11);
4016
    } else if (pCar->car_master_actor->t.t.mat.m[1][1] < 0.1f) {
4017
        ChangeAmbientPratcam(44);
4018
    } else if (abs_vcs_y > abs_vcs_z && abs_vcs_y > abs_vcs_x && vcs_y < -.004f) {
4019
        ChangeAmbientPratcam(6);
4020
    } else if (the_time - last_time_on_ground > 500) {
4021
        ChangeAmbientPratcam(5);
4022
    } else if (abs_vcs_x > abs_vcs_z && vcs_x > .001f) {
4023
        ChangeAmbientPratcam(26);
4024
    } else if (abs_vcs_x > abs_vcs_z && vcs_x < -.001f) {
4025
        ChangeAmbientPratcam(25);
4026
    } else if (abs_omega_x > 1.5f || abs_omega_z > 1.5f) {
4027
        ChangeAmbientPratcam(7);
4028
    } else if (abs_omega_y > 1.5f) {
4029
        ChangeAmbientPratcam(10);
4030
    } else if (abs_vcs_z > .01f) {
4031
        ChangeAmbientPratcam(3);
4032
    } else if (abs_vcs_z > .004f) {
4033
        ChangeAmbientPratcam(2);
4034
    } else if (abs_vcs_z > .0015f) {
4035
        ChangeAmbientPratcam(1);
4036
    } else {
4037
        ChangeAmbientPratcam(0);
4038
    }
4039
}
4040
 
4041
// IDA: void __usercall MungeCarGraphics(tU32 pFrame_period@<EAX>)
4042
void MungeCarGraphics(tU32 pFrame_period) {
4043
    int i;
4044
    //int j; // Pierre-Marie Baty -- unused variable
4045
    int update_mat;
4046
    int spinning_wildly;
4047
    int spinning_mildly;
4048
    int car_count;
4049
    int oily_count;
4050
    int car;
4051
    int cat;
4052
    //int new_special_screen; // Pierre-Marie Baty -- unused variable
4053
    tCar_spec* the_car;
4054
    br_scalar distance_from_camera;
4055
    br_scalar car_x;
4056
    br_scalar car_z;
4057
    br_scalar oily_size;
4058
    br_scalar car_radius;
4059
    br_scalar abs_omega_x;
4060
    br_scalar abs_omega_y;
4061
    br_scalar abs_omega_z;
4062
    float wheel_speed;
4063
    //float speed_mph; // Pierre-Marie Baty -- unused variable
4064
    //float rev_angle; // Pierre-Marie Baty -- unused variable
4065
    float sine_angle;
4066
    float raw_revs;
4067
    float rev_reducer;
4068
    //tSpecial_screen* the_special_screen; // Pierre-Marie Baty -- unused variable
4069
    br_material* the_material;
4070
    tU32 the_time;
4071
    br_actor* oily_actor;
4072
    LOG_TRACE("(%d)", pFrame_period);
4073
 
4074
    if (gNet_mode != eNet_mode_none
4075
        && ((gCurrent_net_game->type == eNet_game_type_foxy && gThis_net_player_index == gIt_or_fox)
4076
            || (gCurrent_net_game->type == eNet_game_type_tag && gThis_net_player_index != gIt_or_fox))) {
4077
        gProgram_state.current_car.power_up_levels[1] = 0;
4078
    }
4079
    SetAmbientPratCam(&gProgram_state.current_car);
4080
    if (gProgram_state.cockpit_on) {
4081
        SwitchCarActor(&gProgram_state.current_car, gProgram_state.current_car.car_actor_count - 1);
4082
    } else {
4083
        SwitchCarActor(&gProgram_state.current_car, gProgram_state.current_car.car_actor_count - 2);
4084
    }
4085
 
4086
    the_time = PDGetTotalTime();
4087
    for (cat = eVehicle_self; cat <= eVehicle_rozzer; cat++) {
4088
        if (cat == eVehicle_self) {
4089
            car_count = 1;
4090
        } else {
4091
            car_count = GetCarCount(cat);
4092
        }
4093
        for (car = 0; car < car_count; car++) {
4094
            if (cat == eVehicle_self) {
4095
                the_car = &gProgram_state.current_car;
4096
            } else {
4097
                the_car = GetCarSpec(cat, car);
4098
            }
4099
            the_car->car_master_actor->render_style = (the_car->driver == eDriver_local_human || !PointOutOfSight(&the_car->pos, gYon_squared)) ? BR_RSTYLE_DEFAULT : BR_RSTYLE_NONE;
4100
        }
4101
    }
4102
    for (car = 0; car < gNum_active_cars; car++) {
4103
        the_car = gActive_car_list[car];
4104
        if (the_car->car_master_actor->render_style != BR_RSTYLE_NONE) {
4105
            car_x = the_car->car_master_actor->t.t.translate.t.v[0];
4106
            car_z = the_car->car_master_actor->t.t.translate.t.v[2];
4107
            the_car->shadow_intersection_flags = 0;
4108
            oily_count = GetOilSpillCount();
4109
            for (i = 0; i < oily_count; i++) {
4110
                GetOilSpillDetails(i, &oily_actor, &oily_size);
4111
                if (oily_actor != NULL) {
4112
                    car_radius = the_car->bounds[1].max.v[2] / WORLD_SCALE * 1.5f;
4113
                    if (oily_actor->t.t.translate.t.v[0] - oily_size < car_x + car_radius
4114
                        && oily_actor->t.t.translate.t.v[0] + oily_size > car_x - car_radius
4115
                        && oily_actor->t.t.translate.t.v[2] - oily_size < car_z + car_radius
4116
                        && oily_actor->t.t.translate.t.v[2] + oily_size > car_z - car_radius) {
4117
                        the_car->shadow_intersection_flags |= 1 << i;
4118
                    }
4119
                }
4120
            }
4121
            if (the_car->driver < eDriver_net_human && (!gAction_replay_mode || !ReplayIsPaused())) {
4122
                if (gCountdown) {
4123
                    sine_angle = FRandomBetween(0.4f, 1.6f) * ((double)GetTotalTime() / ((double)gCountdown * 100.0f));
4124
                    sine_angle = frac(sine_angle) * 360.0f;
4125
                    sine_angle = FastScalarSin(sine_angle);
4126
                    raw_revs = the_car->red_line * fabsf(sine_angle);
4127
                    rev_reducer = (11.0 - (double)gCountdown) / 10.0;
4128
                    the_car->revs = rev_reducer * raw_revs;
4129
                } else {
4130
                    the_car->revs = (the_car->speedo_speed / 0.003
4131
                                        - (double)(int)(the_car->speedo_speed / 0.003))
4132
                            * (double)(the_car->red_line - 800)
4133
                        + 800.0;
4134
                }
4135
            }
4136
            for (i = 0; i < the_car->number_of_steerable_wheels; i++) {
4137
                ControlBoundFunkGroove(the_car->steering_ref[i], the_car->steering_angle);
4138
            }
4139
            for (i = 0; i < COUNT_OF(the_car->rf_sus_ref); i++) {
4140
                ControlBoundFunkGroove(the_car->rf_sus_ref[i], the_car->rf_sus_position);
4141
                if ((i & 1) != 0) {
4142
                    ControlBoundFunkGroove(the_car->lf_sus_ref[i], -the_car->lf_sus_position);
4143
                } else {
4144
                    ControlBoundFunkGroove(the_car->lf_sus_ref[i], the_car->lf_sus_position);
4145
                }
4146
            }
4147
            for (i = 0; i < COUNT_OF(the_car->rr_sus_ref); i++) {
4148
                ControlBoundFunkGroove(the_car->rr_sus_ref[i], the_car->rr_sus_position);
4149
                if ((i & 1) != 0) {
4150
                    ControlBoundFunkGroove(the_car->lr_sus_ref[i], -the_car->lr_sus_position);
4151
                } else {
4152
                    ControlBoundFunkGroove(the_car->lr_sus_ref[i], the_car->lr_sus_position);
4153
                }
4154
            }
4155
            if (!gAction_replay_mode || !ReplayIsPaused()) {
4156
                wheel_speed = -(the_car->speedo_speed / the_car->non_driven_wheels_circum * (float)gFrame_period);
4157
                ControlBoundFunkGroovePlus(the_car->non_driven_wheels_spin_ref_1, wheel_speed);
4158
                ControlBoundFunkGroovePlus(the_car->non_driven_wheels_spin_ref_2, wheel_speed);
4159
                ControlBoundFunkGroovePlus(the_car->non_driven_wheels_spin_ref_3, wheel_speed);
4160
                ControlBoundFunkGroovePlus(the_car->non_driven_wheels_spin_ref_4, wheel_speed);
4161
                if (the_car->driver >= eDriver_net_human) {
4162
                    if (the_car->gear) {
4163
                        wheel_speed = -(the_car->revs
4164
                            * the_car->speed_revs_ratio
4165
                            / 6900.f
4166
                            * (double)the_car->gear
4167
                            / the_car->driven_wheels_circum
4168
                            * (double)gFrame_period);
4169
                    } else if (the_car->keys.brake) {
4170
                        wheel_speed = 0.0;
4171
                    } else {
4172
                        wheel_speed = -(the_car->speedo_speed / the_car->driven_wheels_circum * (double)gFrame_period);
4173
                    }
4174
                }
4175
                ControlBoundFunkGroovePlus(the_car->driven_wheels_spin_ref_1, wheel_speed);
4176
                ControlBoundFunkGroovePlus(the_car->driven_wheels_spin_ref_2, wheel_speed);
4177
                ControlBoundFunkGroovePlus(the_car->driven_wheels_spin_ref_3, wheel_speed);
4178
                ControlBoundFunkGroovePlus(the_car->driven_wheels_spin_ref_4, wheel_speed);
4179
            }
4180
            if (gAction_replay_mode) {
4181
                MungeSpecialVolume((tCollision_info*)the_car);
4182
            } else if (the_car->driver == eDriver_local_human) {
4183
                abs_omega_x = (fabsf(the_car->I.v[0]) + 3.3f) / 2.0f * fabsf(the_car->omega.v[0]);
4184
                abs_omega_y = (fabsf(the_car->I.v[1]) + 3.57f) / 2.0f * fabsf(the_car->omega.v[1]);
4185
                abs_omega_z = (fabsf(the_car->I.v[2]) + 0.44f) / 2.0f * fabsf(the_car->omega.v[2]);
4186
                spinning_wildly = abs_omega_x > 26.4f || abs_omega_y > 49.98f || abs_omega_z > 3.52f;
4187
                if (spinning_wildly && the_time - gLast_cunning_stunt > 10000) {
4188
                    if (!gWild_start
4189
                        || (the_car->last_special_volume != NULL && the_car->last_special_volume->gravity_multiplier != 1.f)) {
4190
                        gWild_start = the_time;
4191
                    } else if (the_time - gWild_start >= 500) {
4192
                        DoFancyHeadup(kFancyHeadupCunningStuntBonus);
4193
                        EarnCredits(gCunning_stunt_bonus[gProgram_state.skill_level]);
4194
                        gLast_cunning_stunt = the_time;
4195
                        gOn_me_wheels_start = 0;
4196
                        gQuite_wild_end = 0;
4197
                        gQuite_wild_start = 0;
4198
                        gWoz_upside_down_at_all = 0;
4199
                    }
4200
                } else {
4201
                    gWild_start = 0;
4202
                    spinning_mildly = abs_omega_x > 1.65f || abs_omega_z > 0.22f;
4203
                    if (the_car->number_of_wheels_on_ground <= 3) {
4204
                        gOn_me_wheels_start = 0;
4205
                        if (the_car->number_of_wheels_on_ground || !spinning_mildly) {
4206
                            gQuite_wild_end = the_time;
4207
                        } else {
4208
                            if (!gQuite_wild_start) {
4209
                                gQuite_wild_start = the_time;
4210
                            }
4211
                            if (the_car->car_master_actor->t.t.mat.m[1][1] < -0.8f) {
4212
                                gWoz_upside_down_at_all = the_time;
4213
                            }
4214
                        }
4215
                    } else {
4216
                        if (!gQuite_wild_end) {
4217
                            gQuite_wild_end = the_time;
4218
                        }
4219
                        if (!gQuite_wild_start
4220
                            || the_time - gLast_cunning_stunt <= 10000
4221
                            || gQuite_wild_end - gQuite_wild_start < 2000
4222
                            || gWoz_upside_down_at_all < (int) gQuite_wild_start // Pierre-Marie Baty -- added type cast
4223
                            || gWoz_upside_down_at_all > (int) gQuite_wild_end // Pierre-Marie Baty -- added type cast
4224
                            || (!gOn_me_wheels_start && the_time - gQuite_wild_end >= 300)) {
4225
                            gQuite_wild_end = 0;
4226
                            gQuite_wild_start = 0;
4227
                            gOn_me_wheels_start = 0;
4228
                            gWoz_upside_down_at_all = 0;
4229
                        } else if (!gOn_me_wheels_start) {
4230
                            gOn_me_wheels_start = the_time;
4231
                        } else if (the_time - gOn_me_wheels_start > 500
4232
                            && (the_car->last_special_volume == NULL
4233
                                || the_car->last_special_volume->gravity_multiplier == 1.0f)) {
4234
                            DoFancyHeadup(kFancyHeadupCunningStuntBonus);
4235
                            EarnCredits(gCunning_stunt_bonus[gProgram_state.skill_level]);
4236
                            gLast_cunning_stunt = PDGetTotalTime();
4237
                            gQuite_wild_end = 0;
4238
                            gQuite_wild_start = 0;
4239
                            gOn_me_wheels_start = 0;
4240
                            gWoz_upside_down_at_all = 0;
4241
                        }
4242
                    }
4243
                }
4244
            }
4245
            if (the_car->driver != eDriver_local_human && the_car->car_model_variable) {
4246
                distance_from_camera = Vector3DistanceSquared(&the_car->car_master_actor->t.t.translate.t,
4247
                                           (br_vector3*)gCamera_to_world.m[3])
4248
                    / gCar_simplification_factor[gGraf_spec_index][gCar_simplification_level];
4249
                if (gNet_mode != eNet_mode_none && gNet_players[gIt_or_fox].car == the_car) {
4250
                    distance_from_camera = 0.f;
4251
                }
4252
                for (i = 0; i < the_car->car_actor_count; i++) {
4253
                    if (the_car->car_model_actors[i].min_distance_squared <= distance_from_camera) {
4254
                        SwitchCarActor(the_car, i);
4255
                        break;
4256
                    }
4257
                }
4258
            }
4259
            if (the_car->screen_material != NULL) {
4260
                the_material = NULL;
4261
                if (the_car->last_special_volume != NULL && the_car->last_special_volume->screen_material != NULL) {
4262
                    if (!gAction_replay_mode && the_car->last_special_volume != gDefault_water_spec_vol) {
4263
                        the_material = the_car->last_special_volume->screen_material;
4264
                    } else if (gProgram_state.current_depth_effect.type == eDepth_effect_fog) {
4265
                        the_material = gProgram_state.standard_screen_fog;
4266
                    } else if (gProgram_state.current_depth_effect.sky_texture != NULL) {
4267
                        the_material = gProgram_state.standard_screen;
4268
                    } else {
4269
                        the_material = gProgram_state.standard_screen_dark;
4270
                    }
4271
                } else {
4272
                    if (gProgram_state.current_depth_effect.type == eDepth_effect_fog) {
4273
                        the_material = gProgram_state.standard_screen_fog;
4274
                    } else if (gProgram_state.current_depth_effect.sky_texture != NULL) {
4275
                        the_material = gProgram_state.standard_screen;
4276
                    } else {
4277
                        the_material = gProgram_state.standard_screen_dark;
4278
                    }
4279
                }
4280
                update_mat = 0;
4281
                if (the_material != NULL && the_car->screen_material_source != the_material) {
4282
                    the_car->screen_material->flags = the_material->flags;
4283
                    the_car->screen_material->ka = the_material->ka;
4284
                    the_car->screen_material->kd = the_material->kd;
4285
                    the_car->screen_material->ks = the_material->ks;
4286
                    the_car->screen_material->power = the_material->power;
4287
                    the_car->screen_material->index_base = the_material->index_base;
4288
                    the_car->screen_material->index_range = the_material->index_range;
4289
                    the_car->screen_material->colour_map = the_material->colour_map;
4290
 
4291
                    the_car->screen_material->map_transform = the_material->map_transform;
4292
                    the_car->screen_material->index_shade = gRender_shade_table;
4293
                    the_car->screen_material_source = the_material;
4294
                    update_mat = 1;
4295
                }
4296
                if (the_car->screen_material->colour_map != NULL) {
4297
                    the_car->screen_material->map_transform.m[2][0] = fmodf(car_x, 1.f);
4298
                    the_car->screen_material->map_transform.m[2][1] = fmodf(car_z, 1.f);
4299
                    if (!update_mat) {
4300
                        BrMaterialUpdate(the_car->screen_material, BR_MATU_MAP_TRANSFORM);
4301
                    }
4302
                }
4303
                if (update_mat) {
4304
                    BrMaterialUpdate(the_car->screen_material, BR_MATU_ALL);
4305
                }
4306
            }
4307
        }
4308
    }
4309
}
4310
 
4311
// IDA: void __cdecl ResetCarScreens()
4312
void ResetCarScreens(void) {
4313
    int cat;
4314
    int car_count;
4315
    int i;
4316
    tCar_spec* the_car;
4317
    LOG_TRACE("()");
4318
 
4319
    for (cat = eVehicle_self; cat < eVehicle_drone; cat++) {
4320
        car_count = (cat == eVehicle_self) ? 1 : GetCarCount(cat);
4321
        for (i = 0; i < car_count; i++) {
4322
            the_car = (cat == eVehicle_self) ? &gProgram_state.current_car : GetCarSpec(cat, i);
4323
            the_car->last_special_volume = NULL;
4324
        }
4325
    }
4326
    MungeCarGraphics(gFrame_period);
4327
}
4328
 
4329
// IDA: tCar_spec* __cdecl GetRaceLeader()
4330
tCar_spec* GetRaceLeader(void) {
20 pmbaty 4331
    //int i; // Pierre-Marie Baty -- unused variable
4332
    //int score; // Pierre-Marie Baty -- unused variable
4333
    //tCar_spec* car; // Pierre-Marie Baty -- unused variable
1 pmbaty 4334
    LOG_TRACE("()");
20 pmbaty 4335
    NOT_IMPLEMENTED();
1 pmbaty 4336
}
4337
 
4338
// IDA: void __cdecl AmIGettingBoredWatchingCameraSpin()
4339
void AmIGettingBoredWatchingCameraSpin(void) {
20 pmbaty 4340
    //static tU32 time_of_death; // Pierre-Marie Baty -- unused variable
4341
    //static tU32 headup_timer; // Pierre-Marie Baty -- unused variable
4342
    //tCar_spec* car; // Pierre-Marie Baty -- unused variable
4343
    //char s[256]; // Pierre-Marie Baty -- unused variable
1 pmbaty 4344
    LOG_TRACE("()");
4345
 
20 pmbaty 4346
    STUB_ONCE();
1 pmbaty 4347
}
4348
 
4349
// IDA: void __cdecl ViewNetPlayer()
4350
void ViewNetPlayer(void) {
4351
    LOG_TRACE("()");
4352
 
4353
    if (gOpponent_viewing_mode) {
4354
        if (gProgram_state.cockpit_on) {
4355
            ToggleCockpit();
4356
        }
4357
        gNet_player_to_view_index++;
4358
        if (gNumber_of_net_players <= gNet_player_to_view_index) {
4359
            gNet_player_to_view_index = -1;
4360
        }
4361
        if (gNet_player_to_view_index < 0) {
4362
            gCar_to_view = GetRaceLeader();
4363
        } else {
4364
            gCar_to_view = gNet_players[gNet_player_to_view_index].car;
4365
        }
4366
        gCamera_yaw = 0;
4367
        InitialiseExternalCamera();
4368
        PositionExternalCamera(gCar_to_view, 200u);
4369
    }
4370
}
4371
 
4372
// IDA: void __cdecl ViewOpponent()
4373
void ViewOpponent(void) {
4374
    static int n;
4375
    LOG_TRACE("()");
4376
 
4377
    n++;
4378
    if (gNet_mode != eNet_mode_none) {
4379
        if (n >= gNumber_of_net_players) {
4380
            n = 0;
4381
        }
4382
        gCar_to_view = gNet_players[n].car;
21 pmbaty 4383
        NewTextHeadupSlot(eHeadupSlot_misc, 0, 2000, -3, gNet_players[n].player_name);
1 pmbaty 4384
    } else {
4385
        if (n >= gNum_viewable_cars) {
4386
            n = 0;
4387
        }
4388
        gCar_to_view = gViewable_car_list[n];
21 pmbaty 4389
        NewTextHeadupSlot(eHeadupSlot_misc, 0, 2000, -3, gViewable_car_list[n]->driver_name);
1 pmbaty 4390
    }
4391
    gCamera_yaw = 0;
4392
    InitialiseExternalCamera();
4393
    PositionExternalCamera(gCar_to_view, 200);
4394
}
4395
 
4396
// IDA: void __cdecl ToggleCarToCarCollisions()
4397
void ToggleCarToCarCollisions(void) {
4398
    LOG_TRACE("()");
4399
 
4400
    gCar_car_collisions = !gCar_car_collisions;
4401
    if (gCar_car_collisions) {
21 pmbaty 4402
        NewTextHeadupSlot(eHeadupSlot_misc, 0, 3000, -4, "Car Car Collisions");
1 pmbaty 4403
    } else {
21 pmbaty 4404
        NewTextHeadupSlot(eHeadupSlot_misc, 0, 3000, -4, "Ghost Cars");
1 pmbaty 4405
    }
4406
}
4407
 
4408
// IDA: void __cdecl SwapCar()
4409
void SwapCar(void) {
4410
    LOG_TRACE("()");
4411
}
4412
 
4413
// IDA: void __cdecl AdjustDownForce()
4414
void AdjustDownForce(void) {
4415
    char s[100];
4416
    tCar_spec* c;
4417
    LOG_TRACE("()");
4418
 
4419
    c = gCar_to_view;
4420
    c->down_force_speed += 50.f;
4421
    if (c->down_force_speed > 2000.f) {
4422
        c->down_force_speed = 50.f;
4423
    }
4424
    if (c->down_force_speed > 300.f) {
4425
        c->down_force_speed = 2000.0;
4426
    }
4427
    sprintf(s, "DownForceSpeed %f", c->down_force_speed);
21 pmbaty 4428
    NewTextHeadupSlot(eHeadupSlot_misc, 0, 1500, -4, s);
1 pmbaty 4429
}
4430
 
4431
// IDA: void __cdecl FreezeMechanics()
4432
void FreezeMechanics(void) {
4433
    LOG_TRACE("()");
4434
 
4435
    gFreeze_mechanics = !gFreeze_mechanics;
4436
    if (gFreeze_mechanics) {
21 pmbaty 4437
        NewTextHeadupSlot(eHeadupSlot_misc, 0, 3000, -4, "Mechanics Frozen");
1 pmbaty 4438
    } else {
21 pmbaty 4439
        NewTextHeadupSlot(eHeadupSlot_misc, 0, 3000, -4, "Thawed Mechanics");
1 pmbaty 4440
    }
4441
}
4442
 
4443
// IDA: void __cdecl PutOpponentsInNeutral()
4444
void PutOpponentsInNeutral(void) {
4445
    LOG_TRACE("()");
4446
 
4447
    gStop_opponents_moving = !gStop_opponents_moving;
4448
    if (gStop_opponents_moving == 0) {
21 pmbaty 4449
        NewTextHeadupSlot(eHeadupSlot_misc, 0, 3000, -4, "Opponents in neutral");
1 pmbaty 4450
    } else {
21 pmbaty 4451
        NewTextHeadupSlot(eHeadupSlot_misc, 0, 3000, -4, "Back in gear");
1 pmbaty 4452
    }
4453
}
4454
 
4455
// IDA: void __cdecl SetPanningFieldOfView()
4456
void SetPanningFieldOfView(void) {
4457
    br_camera* camera_ptr;
4458
    static br_angle panning_angle = 0; // Added by DethRace
4459
    LOG_TRACE("()");
4460
 
4461
    camera_ptr = gCamera->type_data;
4462
    if (panning_angle == 0) {
4463
        panning_angle = BrDegreeToAngle(gCamera_angle) * 0.7f;
4464
    }
4465
    camera_ptr->field_of_view = panning_angle;
4466
}
4467
 
4468
// IDA: void __usercall CheckDisablePlingMaterials(tCar_spec *pCar@<EAX>)
4469
void CheckDisablePlingMaterials(tCar_spec* pCar) {
4470
    br_matrix34* mat;
4471
    br_scalar height;
4472
    int i;
4473
    LOG_TRACE("(%p)", pCar);
4474
 
4475
    height = 0.f;
4476
    if (pCar->water_d == 10000.f) {
4477
        DisablePlingMaterials();
4478
    } else {
4479
        mat = &pCar->car_master_actor->t.t.mat;
4480
        for (i = 0; i < 3; i++) {
4481
            if (mat->m[i][1] > 0.f) {
4482
                height += pCar->bounds[0].max.v[i] * mat->m[i][1];
4483
            } else {
4484
                height += pCar->bounds[0].min.v[i] * mat->m[i][1];
4485
            }
4486
        }
4487
        if (mat->m[3][1] / WORLD_SCALE + height < pCar->water_d) {
4488
            DisablePlingMaterials();
4489
        }
4490
    }
4491
}
4492
 
4493
// IDA: void __usercall PositionExternalCamera(tCar_spec *c@<EAX>, tU32 pTime@<EDX>)
4494
void PositionExternalCamera(tCar_spec* c, tU32 pTime) {
4495
    static int old_camera_mode;
4496
    br_camera* camera_ptr;
4497
    LOG_TRACE("(%p, %d)", c, pTime);
4498
 
4499
    camera_ptr = (br_camera*)gCamera->type_data;
4500
    CheckCameraHither();
4501
    AmIGettingBoredWatchingCameraSpin();
4502
    if ((!gAction_replay_mode || gAction_replay_camera_mode == eAction_replay_standard) && old_camera_mode != -1) {
4503
        camera_ptr->field_of_view = BrDegreeToAngle(gCamera_angle);
4504
        old_camera_mode = -1;
4505
    }
4506
    if (!gProgram_state.cockpit_on) {
4507
        if (gOpponent_viewing_mode && gAction_replay_mode) {
4508
            c = &gProgram_state.current_car;
4509
        } else {
4510
            c = gCar_to_view;
4511
        }
4512
        if (c->car_master_actor->t.t.translate.t.v[0] <= 500.0) {
4513
            if (gAction_replay_mode && gAction_replay_camera_mode) {
4514
                if (gAction_replay_camera_mode == eAction_replay_action) {
4515
                    CheckDisablePlingMaterials(c);
4516
                    if (IncidentCam(c, pTime)) {
4517
                        SetPanningFieldOfView();
4518
                        EnablePlingMaterials();
4519
                        old_camera_mode = gAction_replay_camera_mode;
4520
                        return;
4521
                    }
4522
                }
4523
                CheckDisablePlingMaterials(c);
4524
                SetPanningFieldOfView();
4525
                if (gAction_replay_camera_mode != old_camera_mode) {
4526
                    SetUpPanningCamera(c);
4527
                    old_camera_mode = gAction_replay_camera_mode;
4528
                }
4529
                PanningExternalCamera(c, pTime);
4530
                EnablePlingMaterials();
4531
            } else {
4532
                NormalPositionExternalCamera(c, pTime);
4533
            }
4534
        }
4535
    }
4536
}
4537
 
4538
// IDA: void __usercall CameraBugFix(tCar_spec *c@<EAX>, tU32 pTime@<EDX>)
4539
void CameraBugFix(tCar_spec* c, tU32 pTime) {
4540
    //br_matrix34 mat; // Pierre-Marie Baty -- unused variable
4541
    //br_matrix34* m2; // Pierre-Marie Baty -- unused variable
4542
    //br_vector3 tv; // Pierre-Marie Baty -- unused variable
4543
    LOG_TRACE("(%p, %d)", c, pTime);
4544
 
4545
    if (gAction_replay_mode && gAction_replay_camera_mode != eAction_replay_standard && gPed_actor != NULL && !gProgram_state.cockpit_on) {
4546
        IncidentCam(c, pTime);
4547
    }
4548
}
20 pmbaty 4549
 
1 pmbaty 4550
// IDA: int __usercall PossibleRemoveNonCarFromWorld@<EAX>(br_actor *pActor@<EAX>)
4551
int PossibleRemoveNonCarFromWorld(br_actor* pActor) {
4552
    tU8 cx;
4553
    tU8 cz;
4554
    tTrack_spec* track_spec;
4555
    LOG_TRACE("(%p)", pActor);
4556
 
4557
    track_spec = &gProgram_state.track_spec;
4558
    XZToColumnXZ(&cx, &cz, pActor->t.t.translate.t.v[0], pActor->t.t.translate.t.v[2], track_spec);
4559
    if (track_spec->columns[cz][cx] == pActor->parent) {
4560
        BrActorRemove(pActor);
4561
        return 1;
4562
    }
4563
    return 0;
4564
}
4565
 
4566
// IDA: void __usercall PutNonCarBackInWorld(br_actor *pActor@<EAX>)
4567
void PutNonCarBackInWorld(br_actor* pActor) {
4568
    tU8 cx;
4569
    tU8 cz;
4570
    tTrack_spec* track_spec;
4571
    LOG_TRACE("(%p)", pActor);
4572
 
4573
    track_spec = &gProgram_state.track_spec;
4574
    XZToColumnXZ(&cx, &cz, pActor->t.t.translate.t.v[0], pActor->t.t.translate.t.v[2], track_spec);
4575
    BrActorAdd(track_spec->columns[cz][cx], pActor);
4576
}
4577
 
4578
// IDA: int __usercall IncidentCam@<EAX>(tCar_spec *c@<EAX>, tU32 pTime@<EDX>)
4579
int IncidentCam(tCar_spec* c, tU32 pTime) {
4580
    br_matrix34* m2;
4581
    br_matrix34 mat;
4582
    br_vector3 tv;
4583
    //br_vector3 tv2; // Pierre-Marie Baty -- unused variable
4584
    br_vector3 perp;
4585
    br_vector3 vertical;
4586
    br_vector3 murderer_pos;
4587
    br_scalar ts;
4588
    //tCar_spec* car2; // Pierre-Marie Baty -- unused variable
4589
    static tU32 next_incident_time = 0;
4590
    static tIncident_type type = eNo_incident;
4591
    static float severity;
4592
    static tIncident_info info;
4593
    static int random = 1;
4594
    static int count = 0;
4595
    //br_scalar temp; // Pierre-Marie Baty -- unused variable
4596
    br_vector3 old_cam_pos;
4597
    int removed;
4598
    LOG_TRACE("(%p, %d)", c, pTime);
4599
 
4600
    gPed_actor = NULL;
4601
    m2 = &gCamera->t.t.mat;
4602
    if (type == eNo_incident) {
4603
        MoveCamToIncident(c, &type, &severity, &info, &next_incident_time);
4604
    }
4605
    if (type == eNo_incident) {
4606
        return 0;
4607
    }
4608
    if (type == eIncident_ped) {
4609
        BrVector3Copy(&old_cam_pos, &gCamera->t.t.translate.t);
4610
        gPed_actor = info.ped_info.ped_actor;
4611
        removed = PossibleRemoveNonCarFromWorld(info.ped_info.murderer_actor);
4612
        BrMatrix34Mul(&mat, &gPed_actor->t.t.mat, &gPed_actor->parent->t.t.mat);
4613
        info.ped_info.murderer_actor = c->car_master_actor;
4614
        if (info.ped_info.murderer_actor != NULL) {
4615
            BrVector3Copy(&murderer_pos, &c->pos);
4616
        } else if (info.ped_info.murderer_actor->model != NULL) {
4617
            BrVector3Add(&murderer_pos, &info.ped_info.murderer_actor->model->bounds.max, &info.ped_info.murderer_actor->model->bounds.min);
4618
            BrVector3Scale(&murderer_pos, &murderer_pos, 0.5f);
4619
            BrMatrix34ApplyP(&murderer_pos, &murderer_pos, &info.ped_info.murderer_actor->t.t.mat);
4620
        } else {
4621
            BrVector3Copy(&murderer_pos, &info.ped_info.murderer_actor->t.t.translate.t);
4622
        }
4623
        BrVector3Normalise(&vertical, (br_vector3*)mat.m[1]);
4624
        BrVector3Scale(&vertical, &vertical, PedHeightFromActor(info.ped_info.ped_actor) / 2.f);
4625
        BrVector3Accumulate((br_vector3*)mat.m[3], &vertical);
4626
        if (next_incident_time > GetTotalTime() || !PipeSearchForwards()) {
4627
            BrVector3Sub(&tv, (br_vector3*)mat.m[3], &murderer_pos);
4628
            tv.v[1] = 0.f;
4629
            BrVector3Normalise(&tv, &tv);
4630
            BrVector3Set(&vertical, .0f, .4f, .0f);
4631
            BrVector3Cross(&perp, &tv, &vertical);
4632
            if (random) {
4633
                BrVector3Negate(&perp, &perp);
4634
            }
4635
            if (PipeSearchForwards()) {
4636
                BrVector3Accumulate(&perp, &tv);
4637
            }
4638
            BrVector3Add(&gCamera->t.t.translate.t, (br_vector3*)mat.m[3], &perp);
4639
            CollideCamera2(&murderer_pos, &gCamera->t.t.translate.t, NULL, 1);
4640
        }
4641
        PointCamera((br_vector3*)mat.m[3], m2);
4642
        BrVector3Sub(&tv, &gCamera->t.t.translate.t, &info.ped_info.murderer_actor->t.t.translate.t);
4643
        ts = BrVector3LengthSquared(&tv);
4644
        if (/*abs*/(GetTotalTime() - next_incident_time) > 2500) { // Pierre-Marie Baty -- useless call (already unsigned)
4645
            type = eNo_incident;
4646
        }
4647
        if ((PipeSearchForwards() ? (next_incident_time < GetTotalTime()) : (next_incident_time > GetTotalTime()))
4648
            && (ts > 25.f || CheckForWall(&info.ped_info.murderer_actor->t.t.translate.t, &gCamera->t.t.translate.t))) {
4649
            type = eNo_incident;
4650
        }
4651
        if (removed) {
4652
            PutNonCarBackInWorld(info.ped_info.murderer_actor);
4653
        }
4654
        if (Vector3DistanceSquared((br_vector3*)mat.m[3], &gCamera->t.t.translate.t) < .15f * .15f) {
4655
            BrVector3Copy(&gCamera->t.t.translate.t, &old_cam_pos);
4656
            gPed_actor = NULL;
4657
            return 0;
4658
        }
4659
    } else if (type == eIncident_car) {
4660
        BrVector3Sub(&tv, &info.car_info.car->pos, &c->pos);
4661
        tv.v[1] = 0.f;
4662
        BrVector3Normalise(&tv, &tv);
4663
        BrVector3Scale(&tv, &tv, 2.f);
4664
        BrVector3Add(&gCamera->t.t.translate.t, &info.car_info.car->pos, &tv);
4665
        gCamera->t.t.translate.t.v[1] += 1.f;
4666
        CollideCamera2(&info.car_info.car->pos, &gCamera->t.t.translate.t, NULL, 1);
4667
        PointCamera(&info.car_info.car->pos, m2);
4668
        BrVector3Sub(&tv, &gCamera->t.t.translate.t, &c->pos);
4669
        ts = BrVector3LengthSquared(&tv);
4670
        if (/*abs*/(GetTotalTime() - next_incident_time) > 2500) { // Pierre-Marie Baty -- useless call (already unsigned)
4671
            type = eNo_incident;
4672
        }
4673
        if ((PipeSearchForwards() ? (next_incident_time < GetTotalTime()) : (next_incident_time > GetTotalTime()))
4674
            && (ts > 25.f || CheckForWall(&c->pos, &gCamera->t.t.translate.t))) {
4675
            type = eNo_incident;
4676
        }
4677
    } else if (type == eIncident_wall) {
4678
        PointCamera(&c->pos, m2);
4679
        BrVector3Sub(&tv, &gCamera->t.t.translate.t, &c->pos);
4680
        ts = BrVector3LengthSquared(&tv);
4681
        if (/*abs*/(GetTotalTime() - next_incident_time) > 2500) { // Pierre-Marie Baty -- useless call (already unsigned)
4682
            type = eNo_incident;
4683
        }
4684
        if ((PipeSearchForwards() ? (next_incident_time < GetTotalTime()) : (next_incident_time > GetTotalTime()))
4685
            && (ts > 25.f || CheckForWall(&c->pos, &gCamera->t.t.translate.t))) {
4686
            type = eNo_incident;
4687
        }
4688
    } else {
4689
        type = eNo_incident;
4690
    }
4691
    if (type == eNo_incident) {
4692
        if (count > 1) {
4693
            SetUpPanningCamera(c);
4694
            return 0;
4695
        } else {
4696
            count++;
4697
            if (IncidentCam(c, pTime)) {
4698
                count--;
4699
                return 1;
4700
            } else {
4701
                count--;
4702
                return 0;
4703
            }
4704
        }
4705
    } else {
4706
        return 1;
4707
    }
4708
}
4709
 
4710
// IDA: int __usercall MoveCamToIncident@<EAX>(tCar_spec *c@<EAX>, tIncident_type *type@<EDX>, float *severity@<EBX>, tIncident_info *info@<ECX>, tU32 *next_incident_time)
4711
int MoveCamToIncident(tCar_spec* c, tIncident_type* type, float* severity, tIncident_info* info, tU32* next_incident_time) {
4712
    tU32 next_incident_time2;
4713
    tU32 t;
4714
    tIncident_type type2;
4715
    float severity2;
4716
    tIncident_info info2;
4717
    br_vector3 pos;
4718
    br_vector3 left;
4719
    br_vector3 right;
4720
    br_vector3 vertical;
4721
    br_vector3 tv;
4722
    //br_vector3 tv2; // Pierre-Marie Baty -- unused variable
4723
    br_vector3 perp;
4724
    int test;
4725
    LOG_TRACE("(%p, %p, %p, %p, %p)", c, type, severity, info, next_incident_time);
4726
 
4727
    test = 0;
4728
    if (!GetNextIncident(-1, type, severity, info, next_incident_time)) {
4729
        *type = eNo_incident;
4730
    } else {
4731
        if (/*abs*/(*next_incident_time) > 2500) { // Pierre-Marie Baty -- useless call (already unsigned)
4732
            *type = eNo_incident;
4733
        } else {
4734
            t = *next_incident_time;
4735
            for (test = 0; GetNextIncident(/*abs*/(t), &type2, &severity2, &info2, &next_incident_time2) && test <= 10 && /*abs*/(next_incident_time2) <= 3500; test++) { // Pierre-Marie Baty -- useless calls (already unsigned)
4736
                if ((*type != type2 && type2 < *type) || (*type == type2 && *severity <= severity2)) {
4737
                    *info = info2;
4738
                    *severity = severity2;
4739
                    *type = type2;
4740
                    *next_incident_time = next_incident_time2;
4741
                }
4742
                t = next_incident_time2;
4743
            }
4744
            if (/*abs*/(*next_incident_time) > 2500) { // Pierre-Marie Baty -- useless call (already unsigned)
4745
                *type = eNo_incident;
4746
            } else {
4747
                if (*type == eIncident_wall) {
4748
                    if (*severity < 0.1f) {
4749
                        *type = eNo_incident;
4750
                        return 0;
4751
                    }
4752
                    ScanCarsPositions(c, &c->pos, 100000.f, -1, /*abs*/(*next_incident_time), &pos, &t); // Pierre-Marie Baty -- useless call (already unsigned)
4753
                    if (t == 0) {
4754
                        *type = eNo_incident;
4755
                    } else {
4756
                        BrVector3Sub(&tv, &pos, &c->pos);
4757
                        if (BrVector3LengthSquared(&tv) > 102.91955471539592f) {
4758
                            *type = eNo_incident;
4759
                        } else {
4760
                            BrVector3Sub(&tv, &pos, &info->wall_info.pos);
4761
                            BrVector3Normalise(&tv, &tv);
4762
                            BrVector3Scale(&tv, &tv, 2.f);
4763
                            BrVector3Set(&vertical, 0.f, 1.f, 0.f);
4764
                            BrVector3Cross(&perp, &vertical, &tv);
4765
                            BrVector3Add(&left, &pos, &tv);
4766
                            BrVector3Add(&left, &left, &perp);
4767
                            left.v[1] += 2.f;
4768
                            BrVector3Add(&right, &pos, &tv);
4769
                            BrVector3Sub(&right, &right, &perp);
4770
                            right.v[1] += 2.f;
4771
                            CollideCamera2(&pos, &left, NULL, 1);
4772
                            CollideCamera2(&pos, &right, NULL, 1);
4773
                            if (Vector3DistanceSquared(&left, &pos) <= Vector3DistanceSquared(&right, &pos)) {
4774
                                BrVector3Copy(&tv, &right);
4775
                            } else {
4776
                                BrVector3Copy(&tv, &left);
4777
                            }
4778
                            BrVector3Copy(&gCamera->t.t.translate.t, &tv);
4779
                        }
4780
                    }
4781
                }
4782
                *next_incident_time += GetTotalTime();
4783
            }
4784
        }
4785
    }
4786
    return 0;
4787
}
4788
 
4789
// IDA: void __usercall PanningExternalCamera(tCar_spec *c@<EAX>, tU32 pTime@<EDX>)
4790
void PanningExternalCamera(tCar_spec* c, tU32 pTime) {
4791
    br_matrix34* m2;
4792
    br_matrix34* m1;
4793
    br_vector3 tv;
4794
    br_scalar ts;
4795
    static int inside_camera_zone = 1;
4796
    LOG_TRACE("(%p, %d)", c, pTime);
4797
 
4798
    BrVector3Sub(&tv, &gCamera->t.t.translate.t, &c->pos);
4799
    ts = BrVector3LengthSquared(&tv);
4800
    if (ts > 102.91955471539592f || (gSwitch_time != 0 && (PipeSearchForwards() ? (gSwitch_time <= GetTotalTime()) : (gSwitch_time >= GetTotalTime())))) {
4801
        if ((inside_camera_zone || ts > 205.83910943079184f) && (ts > 25.f || CheckForWall(&c->pos, &gCamera->t.t.translate.t))) {
4802
            SetUpPanningCamera(c);
4803
            inside_camera_zone = 0;
4804
        }
4805
    } else {
4806
        inside_camera_zone = 1;
4807
    }
4808
    m1 = &c->car_master_actor->t.t.mat;
4809
    m2 = &gCamera->t.t.mat;
4810
    PointCameraAtCar(c, m1, m2);
4811
}
4812
 
4813
// IDA: int __usercall CheckForWall@<EAX>(br_vector3 *start@<EAX>, br_vector3 *end@<EDX>)
4814
int CheckForWall(br_vector3* start, br_vector3* end) {
4815
    br_vector3 dir;
4816
    br_material* material;
4817
    br_vector3 normal;
4818
    br_scalar d;
4819
    LOG_TRACE("(%p, %p)", start, end);
4820
 
4821
    BrVector3Sub(&dir, end, start);
4822
    FindFace(start, &dir, &normal, &d, &material);
4823
    return d <= 1.f;
4824
}
4825
 
4826
// IDA: void __usercall SetUpPanningCamera(tCar_spec *c@<EAX>)
4827
void SetUpPanningCamera(tCar_spec* c) {
4828
    br_vector3 pos;
4829
    br_vector3 perp;
4830
    br_vector3 dir;
4831
    br_vector3 tv;
4832
    br_vector3 tv2;
4833
    br_scalar ts;
4834
    tU32 time;
4835
    tU32 t;
4836
    tU32 t2;
4837
    tU32 time_step;
4838
    //br_matrix34* m2; // Pierre-Marie Baty -- unused variable
4839
    //br_matrix34* m1; // Pierre-Marie Baty -- unused variable
4840
    br_vector3 left;
4841
    br_vector3 right;
4842
    br_vector3 car_centre;
4843
    //int left_score; // Pierre-Marie Baty -- unused variable
4844
    //int right_score; // Pierre-Marie Baty -- unused variable
4845
    LOG_TRACE("(%p)", c);
4846
 
4847
    ScanCarsPositions(c, &c->pos, 411.6782f, -1, 5000, &car_centre, &t);
4848
    BrVector3Sub(&dir, &car_centre, &c->pos);
4849
    time_step = ((t > GetTotalTime()) ? t - GetTotalTime() : GetTotalTime() - t) * SRandomBetween(0.8f, 1.5f);
4850
    if (BrVector3LengthSquared(&dir) >= .01f && t != 0) {
4851
        ScanCarsPositions(c, &c->pos, 102.9196f, -1, time_step / 2, &pos, &t2);
4852
        if (t2 == 0) {
4853
            BrVector3Copy(&pos, &c->pos);
4854
        }
4855
    } else {
4856
        BrVector3Negate(&dir, (br_vector3*)&c->car_master_actor->t.t.mat.m[2]);
4857
        BrVector3Copy(&pos, &c->pos);
4858
        time_step = 0;
4859
    }
4860
    BrVector3SetFloat(&tv, 0.f, 1.f, 0.f);
4861
    BrVector3Cross(&perp, &tv, &dir);
4862
    ts = BrVector3Length(&perp);
4863
    if (ts >= .1f) {
4864
        BrVector3Scale(&perp, &perp, 2.f / ts * SRandomBetween(0.3333333f, 1.f));
4865
        BrVector3Set(&tv2, 0.f, 2 * SRandomBetween(0.3333333f, 1.f), 0.f);
4866
        BrVector3Add(&tv, &pos, &tv2);
4867
        BrVector3Add(&left, &tv, &perp);
4868
        BrVector3Sub(&right, &tv, &perp);
4869
        CollideCamera2(&pos, &left, NULL, 1);
4870
        CollideCamera2(&pos, &right, NULL, 1);
4871
        BrVector3Sub(&tv, &left, &pos);
4872
        BrVector3Sub(&tv2, &right, &pos);
4873
        if (BrVector3LengthSquared(&tv) + SRandomPosNeg(.01f) <= BrVector3LengthSquared(&tv2)) {
4874
            BrVector3Copy(&gCamera->t.t.translate.t, &right);
4875
        } else {
4876
            BrVector3Copy(&gCamera->t.t.translate.t, &left);
4877
        }
4878
        if (t != 0 && CheckForWall(&c->pos, &gCamera->t.t.translate.t)) {
4879
            ScanCarsPositions(c, &c->pos, 10000.f, -1, 1000, &tv, &time);
4880
            CollideCamera2(&tv, &gCamera->t.t.translate.t, NULL, 1);
4881
        }
4882
        if (t != 0 && CheckForWall(&car_centre, &gCamera->t.t.translate.t)) {
4883
            time_step = time_step / 16;
4884
            BrVector3Copy(&tv, &pos);
4885
            while (1) {
4886
                ScanCarsPositions(c, &tv, 10000.f, /*abs*/(t2 - GetTotalTime()), time_step, &tv2, &time); // Pierre-Marie Baty -- useless call (already unsigned)
4887
                t2 += (GetReplayDirection() ? 1 : -1) * time_step;
4888
                BrVector3Copy(&tv, &tv2);
4889
                if (CheckForWall(&tv, &gCamera->t.t.translate.t)) {
4890
                    break;
4891
                }
4892
                if (t2 >= GetTotalTime() + 5000) {
4893
                    break;
4894
                }
4895
            }
4896
            gSwitch_time = t2;
4897
        } else {
4898
            if (t == 0) {
4899
                t = 5000;
4900
            }
4901
            gSwitch_time = t;
4902
        }
4903
    }
4904
}
4905
 
4906
// IDA: void __usercall SaveCameraPosition(int i@<EAX>)
4907
void SaveCameraPosition(int i) {
4908
    LOG_TRACE("(%d)", i);
4909
 
4910
    if (gSave_camera[i].saved != 1) {
4911
        gSave_camera[i].zoom = gCamera_zoom;
4912
        gSave_camera[i].yaw = gCamera_yaw;
4913
        gSave_camera[i].saved = 1;
4914
    }
4915
}
4916
 
4917
// IDA: void __usercall RestoreCameraPosition(int i@<EAX>)
4918
void RestoreCameraPosition(int i) {
4919
    LOG_TRACE("(%d)", i);
4920
 
4921
    if (gSave_camera[i].saved != 0) {
4922
        gCamera_zoom = gSave_camera[i].zoom;
4923
        gCamera_yaw = gSave_camera[i].yaw;
4924
        gSave_camera[i].saved = 0;
4925
    }
4926
}
4927
 
4928
// IDA: void __usercall NormalPositionExternalCamera(tCar_spec *c@<EAX>, tU32 pTime@<EDX>)
4929
void NormalPositionExternalCamera(tCar_spec* c, tU32 pTime) {
4930
    br_matrix34* m2;
4931
    br_matrix34* m1;
4932
    br_scalar time;
4933
    //br_scalar ts; // Pierre-Marie Baty -- unused variable
4934
    //br_scalar ts2; // Pierre-Marie Baty -- unused variable
4935
    br_scalar dist;
4936
    br_scalar height_inc;
4937
    br_scalar l;
4938
    //br_scalar frac; // Pierre-Marie Baty -- unused variable
4939
    br_vector3 vn;
4940
    br_vector3 a;
4941
    //br_vector3 b; // Pierre-Marie Baty -- unused variable
4942
    //br_vector3 tv; // Pierre-Marie Baty -- unused variable
4943
    //br_angle yaw; // Pierre-Marie Baty -- unused variable
4944
    //br_angle theta; // Pierre-Marie Baty -- unused variable
4945
    br_scalar d;
4946
    //int face; // Pierre-Marie Baty -- unused variable
4947
    //int i; // Pierre-Marie Baty -- unused variable
4948
    int swoop;
4949
    int manual_swing;
4950
    int manual_zoom;
4951
    br_vector3 old_camera_pos;
4952
    //br_scalar scale; // Pierre-Marie Baty -- unused variable
4953
    LOG_TRACE("(%p, %d)", c, pTime);
4954
 
4955
    m1 = &gCamera->t.t.mat;
4956
    m2 = &c->car_master_actor->t.t.mat;
4957
    swoop = gCountdown && c->pos.v[1] + 0.001f < gCamera_height;
4958
    manual_swing = gOld_yaw__car != gCamera_yaw || swoop;
4959
    manual_zoom = (double)gOld_zoom != gCamera_zoom;
4960
    BrVector3Copy(&old_camera_pos, &gCamera->t.t.translate.t);
4961
    if (!gProgram_state.cockpit_on) {
4962
        if (swoop) {
4963
            gCamera_yaw = 0;
4964
            manual_swing = 1;
4965
        }
4966
        if (fabsf(c->speedo_speed) > 0.0006f && gCamera_mode > 0) {
4967
            gCamera_mode = -1;
4968
            gCamera_sign = BrVector3Dot((br_vector3*)m2->m[2], &c->direction) > 0.0f;
4969
        }
4970
        if (c->frame_collision_flag && gCamera_mode != -2) {
4971
            gCamera_mode = 1;
4972
        }
4973
        if (gCar_flying || gCamera_reset || gCamera_mode == -2) {
4974
            gCamera_mode = 0;
4975
        }
4976
        d = sqrtf(gCamera_zoom) + 4.f / WORLD_SCALE;
4977
        if (!gCamera_mode || gCamera_mode == -1) {
4978
            BrVector3Copy(&vn, &c->direction);
4979
            MoveWithWheels(c, &vn, manual_swing);
4980
            vn.v[1] = 0.0f;
4981
            BrVector3Normalise(&vn, &vn);
4982
            if (gCar_flying) {
4983
                gCamera_sign = 0;
4984
            }
4985
            SwingCamera(c, m2, m1, &vn, pTime);
4986
            BrVector3Scale(&a, &vn, d);
4987
            BrVector3Sub(&gCamera->t.t.translate.t, &c->pos, &a);
4988
            BrVector3Copy(&gView_direction, &vn);
4989
        }
4990
        if (gCamera_mode == 1) {
4991
            if (manual_swing || manual_zoom) {
4992
                BrVector3Copy(&old_camera_pos, &gCamera_pos_before_collide);
4993
            }
4994
            BrVector3Sub(&a, &c->pos, &old_camera_pos);
4995
            a.v[1] = 0.0f;
4996
            if (manual_swing) {
4997
                DrVector3RotateY(&a, (gCamera_sign == 0 ? 1 : -1) * (gCamera_yaw - gOld_yaw__car));
4998
                gCamera_yaw = gOld_yaw__car;
4999
            }
5000
            BrVector3Normalise(&vn, &a);
5001
            BrVector3Copy(&gView_direction, &vn);
5002
            BrVector3Scale(&vn, &vn, -d);
5003
            BrVector3Accumulate(&a, &vn);
5004
            dist = BrVector3Length(&a);
5005
            l = (float)pTime / 1000.0f * (dist + 1.0f) / dist;
5006
            if (l < 1.0f && BrVector3Dot(&a, &vn) > 0.0f) {
5007
                BrVector3Scale(&a, &a, (l - 1.f));
5008
                BrVector3Accumulate(&vn, &a);
5009
            }
5010
            BrVector3Add(&gCamera->t.t.translate.t, &c->pos, &vn);
5011
        }
5012
        height_inc = gCamera_zoom * gCamera_zoom + 0.3f;
5013
        time = pTime * 0.001f;
5014
        if (!gCamera_frozen || gAction_replay_mode) {
5015
            if (pTime >= 5000) {
5016
                gCamera_height = c->pos.v[1];
5017
            } else if (swoop) {
5018
                if (time > 0.2f) {
5019
                    time = 0.2f;
5020
                }
5021
                gCamera_height -= time * 5.0f;
5022
                if (gCamera_height < c->pos.v[1]) {
5023
                    gCamera_height = c->pos.v[1];
5024
                }
5025
            } else {
5026
                gCamera_height = time * 5.0f * c->pos.v[1] + gCamera_height;
5027
                gCamera_height = gCamera_height / (time * 5.0f + 1.0f);
5028
            }
5029
        }
5030
        l = c->direction.v[1] * d;
5031
        if (l > 0) {
5032
            if (c->pos.v[1] - l - height_inc / 2.0f > gCamera_height) {
5033
                gCamera_height = c->pos.v[1] - l - height_inc / 2.0f;
5034
            }
5035
        }
5036
 
5037
        gCamera->t.t.translate.t.v[1] = height_inc + gCamera_height;
5038
        BrVector3Copy(&gCamera_pos_before_collide, &gCamera->t.t.translate.t);
5039
        CollideCameraWithOtherCars(&c->pos, &gCamera->t.t.translate.t);
5040
        CollideCamera2(&c->pos, &gCamera->t.t.translate.t, &old_camera_pos, manual_swing || manual_zoom);
5041
        if (gCamera_has_collided && swoop) {
5042
            gCamera_height = c->pos.v[1];
5043
        }
5044
        PointCameraAtCar(c, m2, m1);
5045
    }
5046
    gOld_yaw__car = gCamera_yaw;
5047
    gOld_zoom = (br_angle)gCamera_zoom;
5048
}
5049
 
5050
// IDA: void __usercall MoveWithWheels(tCar_spec *c@<EAX>, br_vector3 *vn@<EDX>, int manual_swing@<EBX>)
5051
void MoveWithWheels(tCar_spec* c, br_vector3* vn, int manual_swing) {
5052
    br_angle yaw;
5053
    br_angle theta;
5054
    static int move_with_wheels;
5055
    LOG_TRACE("(%p, %p, %d)", c, vn, manual_swing);
5056
 
5057
    if (c->speed < 0.0001f && !gCamera_mode) {
5058
        if (manual_swing) {
5059
            if (gCamera_yaw <= 32760u) {
5060
                yaw = gCamera_yaw;
5061
            } else {
5062
                yaw = gCamera_yaw - 32760;
5063
            }
5064
            if (yaw <= BrDegreeToAngle(45) || yaw >= BrDegreeToAngle(135)) {
5065
                if (!move_with_wheels) {
5066
                    theta = BrRadianToAngle(atan2f(c->wpos[0].v[2] * c->curvature, 1.0f));
5067
                    gCamera_yaw -= (-2 * gCamera_sign + 1) * theta;
5068
                    move_with_wheels = 1;
5069
                }
5070
            } else if (move_with_wheels) {
5071
                theta = BrRadianToAngle(atan2(c->wpos[0].v[2] * c->curvature, 1.0));
5072
                gCamera_yaw += (-2 * gCamera_sign + 1) * theta;
5073
                move_with_wheels = 0;
5074
            }
5075
        }
5076
        if (move_with_wheels) {
5077
            if (!gCar_flying) {
5078
                theta = BrRadianToAngle(atan2(c->wpos[0].v[2] * c->curvature, 1.0));
5079
                DrVector3RotateY(vn, theta);
5080
            }
5081
        }
5082
    }
5083
}
5084
 
5085
// IDA: void __usercall SwingCamera(tCar_spec *c@<EAX>, br_matrix34 *m1@<EDX>, br_matrix34 *m2@<EBX>, br_vector3 *vn@<ECX>, tU32 pTime)
5086
void SwingCamera(tCar_spec* c, br_matrix34* m1, br_matrix34* m2, br_vector3* vn, tU32 pTime) {
5087
    //int i; // Pierre-Marie Baty -- unused variable
5088
    br_scalar ts;
5089
    br_angle yaw;
5090
    br_angle theta;
5091
    //br_angle alpha; // Pierre-Marie Baty -- unused variable
5092
    br_scalar sin_dtheta;
5093
    br_scalar cos_dtheta;
5094
    br_scalar sign;
5095
    int manual_swing;
5096
    static br_angle omega = 0;
5097
    static int elapsed_time = -1;
5098
    static br_vector3 old_vn;
5099
    LOG_TRACE("(%p, %p, %p, %p, %d)", c, m1, m2, vn, pTime);
5100
 
5101
    manual_swing = gOld_yaw__car != gCamera_yaw;
5102
    if (elapsed_time > 500) {
5103
        elapsed_time = -1;
5104
    }
5105
    if (elapsed_time >= 0) {
5106
        elapsed_time += pTime;
5107
    }
5108
    sign = -BrVector3Dot((br_vector3*)m1->m[2], vn);
5109
    ts = BrVector3Dot(vn, &old_vn);
5110
 
5111
    BrVector3Copy(&old_vn, vn);
5112
    if ((sign < 0.0f) == gCamera_sign) {
5113
        elapsed_time = -1;
5114
    } else if (ts <= 0.0 || elapsed_time >= 0) {
5115
        if (elapsed_time < 0) {
5116
            elapsed_time = 0;
5117
        }
5118
        if (elapsed_time < 500 && sign <= 0.0f) {
5119
            BrVector3Negate(vn, vn);
5120
        } else {
5121
            elapsed_time = 500;
5122
            if (sign <= 0.0) {
5123
                ts = 0.0006f;
5124
            } else {
5125
                ts = 0.0001f;
5126
            }
5127
            if (fabsf(c->speedo_speed) <= ts || gCar_flying) {
5128
                BrVector3Negate(vn, vn);
5129
            } else {
5130
                gCamera_sign = gCamera_sign == 0;
5131
                omega = BrDegreeToAngle(pTime * 0.03f);
5132
                if (gCamera_yaw <= 32760) {
5133
                    yaw = gCamera_yaw;
5134
                } else {
5135
                    yaw = gCamera_yaw - 32760;
5136
                }
5137
                if ((uint16_t)(gCamera_yaw + 16380) <= 32760) {
5138
                    if (yaw > 8190 && yaw < 24570) {
5139
                        gCamera_yaw = 32760 - gCamera_yaw;
5140
                    }
5141
                } else {
5142
                    gCamera_yaw = 32760 - gCamera_yaw;
5143
                }
5144
            }
5145
        }
5146
    } else {
5147
        gCamera_sign = gCamera_sign == 0;
5148
        if (gCamera_yaw <= 32760) {
5149
            yaw = gCamera_yaw;
5150
        } else {
5151
            yaw = gCamera_yaw - 32760;
5152
        }
5153
        if (yaw > 8190 && yaw < 24570) {
5154
            gCamera_yaw = -gCamera_yaw;
5155
        }
5156
    }
5157
    if (gCamera_sign) {
5158
        yaw = -gCamera_yaw;
5159
    } else {
5160
        yaw = gCamera_yaw;
5161
    }
5162
    if (!gCar_flying) {
5163
        DrVector3RotateY(vn, yaw);
5164
    }
5165
    sin_dtheta = 0.0;
5166
    br_scalar v16 = vn->v[0] * gView_direction.v[2] - vn->v[2] * gView_direction.v[0];
5167
    br_scalar v17 = vn->v[0] * gView_direction.v[0] + vn->v[2] * gView_direction.v[2];
5168
 
5169
    br_angle v8 = BrRadianToAngle(sqrt(c->omega.v[2] * c->omega.v[2] + c->omega.v[0] * c->omega.v[0] + c->omega.v[1] * c->omega.v[1]) * pTime / 1000.0);
5170
    sin_dtheta = sin(BrAngleToRadian(v8)) + 0.1;
5171
 
5172
    if (omega || gCamera_reset || (c->speed < 0.0001f && !manual_swing) || gCamera_mode == -1 || (v17 > 0.0 && !manual_swing && fabs(v16) > sin_dtheta)) {
5173
        if (!gCar_flying) {
5174
            theta = BrRadianToAngle(asin(sin_dtheta));
5175
            if (omega < theta) {
5176
                omega = theta;
5177
            }
5178
            if (!omega) {
5179
                omega = BrDegreeToAngle(pTime * 0.03); // (__int64)((double)(int)pTime * 0.03 * 182.0444444444445);
5180
            }
5181
            cos_dtheta = cos(BrAngleToRadian(omega));
5182
            if (cos_dtheta <= v17) {
5183
                omega = 0;
5184
                gCamera_mode = 0;
5185
            } else {
5186
                ts = BrAngleToRadian(omega);
5187
                if (v16 <= 0.0) {
5188
                    vn->v[0] = cosf(ts) * gView_direction.v[0] - sinf(ts) * gView_direction.v[2];
5189
                    vn->v[2] = sinf(ts) * gView_direction.v[0] + cosf(ts) * gView_direction.v[2];
5190
                } else {
5191
                    vn->v[0] = sinf(ts) * gView_direction.v[2] + cosf(ts) * gView_direction.v[0];
5192
                    vn->v[2] = cosf(ts) * gView_direction.v[2] - sinf(ts) * gView_direction.v[0];
5193
                }
5194
                omega += BrDegreeToAngle(pTime * 0.03f);
5195
                if (BrDegreeToAngle(pTime * 0.1f) < omega) {
5196
                    omega = BrDegreeToAngle(pTime * 0.1f);
5197
                }
5198
                if (omega < theta) {
5199
                    omega = theta;
5200
                }
5201
            }
5202
        }
5203
    }
5204
}
5205
 
5206
// IDA: void __usercall PointCameraAtCar(tCar_spec *c@<EAX>, br_matrix34 *m1@<EDX>, br_matrix34 *m2@<EBX>)
5207
void PointCameraAtCar(tCar_spec* c, br_matrix34* m1, br_matrix34* m2) {
5208
    br_vector3 vn;
5209
    br_vector3 tv;
5210
    br_vector3 tv2;
5211
    br_scalar dist;
5212
    br_scalar frac;
5213
    br_angle theta;
5214
    br_vector3* pos;
5215
    br_camera* camera_ptr;
5216
    //br_angle off_centre_angle; // Pierre-Marie Baty -- unused variable
5217
    int swoop;
5218
    //br_scalar scale; // Pierre-Marie Baty -- unused variable
5219
    LOG_TRACE("(%p, %p, %p)", c, m1, m2);
5220
 
5221
    camera_ptr = gCamera->type_data;
5222
    theta = camera_ptr->field_of_view / 5;
5223
    swoop = gCountdown && c->pos.v[1] + 0.01f < gCamera_height;
5224
    if (0) {
5225
        BrVector3Sub(&tv, &gAverage_grid_position, &c->pos);
5226
        frac = (gCamera_height - c->pos.v[1]) / 10.0f;
5227
        BrVector3Scale(&tv, &tv, frac);
5228
        BrVector3Accumulate(&tv, &c->pos);
5229
        pos = &tv;
5230
        theta = (1.0f - frac) * (float)theta;
5231
    } else {
5232
        pos = &c->pos;
5233
    }
5234
    BrVector3Set(&vn, c->pos.v[0] - m2->m[3][0], 0.f, c->pos.v[2] - m2->m[3][2]);
5235
    BrVector3Normalise(&vn, &vn);
5236
    m2->m[0][0] = -vn.v[2];
5237
    m2->m[0][1] = 0.0f;
5238
    m2->m[0][2] = vn.v[0];
5239
    m2->m[1][0] = 0.0f;
5240
    m2->m[1][1] = 1.0f;
5241
    m2->m[1][2] = 0.0f;
5242
    m2->m[2][0] = -vn.v[0];
5243
    m2->m[2][1] = 0.0f;
5244
    m2->m[2][2] = -vn.v[2];
5245
    BrVector3Sub(&tv2, pos, (br_vector3*)m2->m[3]);
5246
    dist = BrVector3Dot(&tv2, &vn);
5247
    BrMatrix34PreRotateX(m2, theta - BrRadianToAngle(atan2f(m2->m[3][1] - pos->v[1], dist)));
5248
}
5249
 
5250
// IDA: void __usercall PointCamera(br_vector3 *pos@<EAX>, br_matrix34 *m2@<EDX>)
5251
void PointCamera(br_vector3* pos, br_matrix34* m2) {
5252
    br_vector3 vn;
5253
    br_scalar dist;
5254
    br_angle theta;
5255
    br_camera* camera_ptr;
5256
    LOG_TRACE("(%p, %p)", pos, m2);
5257
 
5258
    camera_ptr = gCamera->type_data;
5259
    BrVector3Sub(&vn, pos, (br_vector3*)m2->m[3]);
5260
    vn.v[1] = 0.f;
5261
    BrVector3Normalise(&vn, &vn);
5262
    m2->m[0][0] = -vn.v[2];
5263
    m2->m[0][1] = 0.f;
5264
    m2->m[0][2] = vn.v[0];
5265
    m2->m[1][0] = 0.f;
5266
    m2->m[1][1] = 1.f;
5267
    m2->m[1][2] = 0.f;
5268
    m2->m[2][0] = -vn.v[0];
5269
    m2->m[2][1] = 0.f;
5270
    m2->m[2][2] = -vn.v[2];
5271
    dist = BrVector3LengthSquared(&vn);
5272
    theta = BR_ATAN2(m2->m[3][1] - pos->v[1], dist);
5273
    BrMatrix34PreRotateX(m2, camera_ptr->field_of_view / 5 - theta);
5274
}
5275
 
5276
// IDA: int __usercall CollideCamera2@<EAX>(br_vector3 *car_pos@<EAX>, br_vector3 *cam_pos@<EDX>, br_vector3 *old_camera_pos@<EBX>, int manual_move@<ECX>)
5277
int CollideCamera2(br_vector3* car_pos, br_vector3* cam_pos, br_vector3* old_camera_pos, int manual_move) {
5278
    int i;
5279
    int k;
5280
    br_vector3 a;
5281
    br_vector3 b;
5282
    //br_vector3 vn; // Pierre-Marie Baty -- unused variable
5283
    br_vector3 tv;
5284
    br_vector3 tv2;
5285
    br_scalar l;
5286
    br_scalar d;
5287
    br_scalar ts;
5288
    br_scalar ts2;
5289
    br_scalar dist;
5290
    br_scalar hither;
5291
    //br_angle theta; // Pierre-Marie Baty -- unused variable
5292
    tBounds bnds;
5293
    br_matrix34 mat;
5294
    br_material* material;
5295
    br_scalar alpha;
5296
    br_scalar sa;
5297
    br_scalar sb;
5298
    br_scalar sc;
5299
    tFace_ref face_list[3];
5300
    LOG_TRACE("(%p, %p, %p, %d)", car_pos, cam_pos, old_camera_pos, manual_move);
5301
 
5302
#ifdef DETHRACE_FIX_BUGS
5303
    ts2 = 0.f;
5304
#endif
5305
    hither = ((br_camera*)gCamera->type_data)->hither_z * 3.0f;
5306
    gCamera_has_collided = 0;
5307
    for (i = 0; i < 1; i++) {
5308
        BrVector3Sub(&tv, cam_pos, car_pos);
5309
        dist = BrVector3Length(&tv);
5310
        BrVector3Scale(&tv, &tv, 1.2f);
5311
        FindFace(car_pos, &tv, &a, &ts, &material);
5312
        if (ts <= 1.0) {
5313
            gCamera_has_collided = 1;
5314
            if (BrVector3Dot(&a, &tv) > 0.0f) {
5315
                BrVector3Negate(&a, &a);
5316
            }
5317
            if (gCamera_mode == 1 && !manual_move) {
5318
                BrVector3Sub(&tv2, car_pos, old_camera_pos);
5319
                FindFace(old_camera_pos, &tv2, &b, &ts2, &material);
5320
                if (ts2 > 1.0f) {
5321
                    BrVector3Copy(cam_pos, old_camera_pos);
5322
                    return i;
5323
                }
5324
            }
5325
            BrVector3Scale(&tv, &tv, ts);
5326
            BrVector3Scale(&tv2, &a, hither);
5327
            BrVector3Accumulate(&tv, &tv2);
5328
            dist = BrVector3Length(&tv);
5329
            BrVector3Add(cam_pos, car_pos, &tv);
5330
            if (gMin_camera_car_distance > dist && i == 0 && a.v[1] > -0.7) {
5331
                BrVector3Scale(&tv2, &a, -a.v[1]);
5332
                tv2.v[1] += 1.f;
5333
                if (gProgram_state.current_car.car_master_actor->t.t.mat.m[1][1] < 0.f) {
5334
                    BrVector3Negate(&tv2, &tv2);
5335
                }
5336
                d = BrVector3LengthSquared(&tv2);
5337
                l = BrVector3Dot(&tv2, &tv);
5338
                alpha = BrVector3LengthSquared(&tv) - gMin_camera_car_distance * gMin_camera_car_distance;
5339
                ts2 = l * l - alpha * d * 4.0;
5340
                if (ts2 >= 0.f && d != 0.f) {
5341
                    sa = (sqrtf(ts2) - l) / (d * 2.0f);
5342
                    BrVector3Scale(&tv2, &tv2, sa);
5343
                    FindFace(cam_pos, &tv2, &a, &ts, &material);
5344
                    if (ts < 1.0f) {
5345
                        BrVector3Scale(&tv2, &tv2, ts);
5346
                    }
5347
                    BrVector3Set(&b, tv.v[0], 0.f, tv.v[2]);
5348
                    BrVector3Normalise(&b, &b);
5349
                    BrVector3Accumulate(&tv, &tv2);
5350
                    ts2 = BrVector3Dot(&tv, &b);
5351
                    if (ts2 < 0.03f && !gAction_replay_mode) {
5352
                        BrVector3Normalise(&tv2, &tv2);
5353
                        alpha = BrVector3Dot(&tv2, &b);
5354
                        if (alpha < -0.03f) {
5355
                            alpha = (0.03f - ts2) / alpha;
5356
                            BrVector3Scale(&tv2, &tv2, alpha);
5357
                            BrVector3Add(&tv, &tv2, &tv);
5358
                        }
5359
                    }
5360
                }
5361
                BrVector3Add(cam_pos, car_pos, &tv);
5362
            }
5363
        }
5364
 
5365
        bnds.mat = &mat;
5366
        BrMatrix34Identity(&mat);
5367
        BrVector3Set(&tv2, hither, hither, hither);
5368
        bnds.original_bounds.min.v[0] = cam_pos->v[0] - hither;
5369
        bnds.original_bounds.min.v[1] = cam_pos->v[1] - hither;
5370
        bnds.original_bounds.min.v[2] = cam_pos->v[2] - hither;
5371
        bnds.original_bounds.max.v[0] = cam_pos->v[0] + hither;
5372
        bnds.original_bounds.max.v[1] = cam_pos->v[1] + hither;
5373
        bnds.original_bounds.max.v[2] = cam_pos->v[2] + hither;
5374
        k = FindFacesInBox(&bnds, face_list, 3);
5375
        if (k > 0) {
5376
            BrVector3Sub(&tv2, cam_pos, &face_list[0].v[0]);
5377
            sa = BrVector3Dot(&face_list[0].normal, &tv2);
5378
            // ts2 = sa;
5379
            if (sa < hither && sa >= 0.0) {
5380
                BrVector3Scale(&tv2, &face_list[0].normal, hither - sa);
5381
                BrVector3Accumulate(cam_pos, &tv2);
5382
            }
5383
            if (k > 1) {
5384
                sb = BrVector3Dot(&face_list[0].normal, &face_list[1].normal);
5385
                if (sb > 0.95f && k > 2) {
5386
                    BrVector3Copy(&face_list[1].normal, &face_list[2].normal);
5387
                    BrVector3Copy(&face_list[1].v[0], &face_list[2].v[0]);
5388
                    sb = BrVector3Dot(&face_list[0].normal, &face_list[2].normal);
5389
                    k = 2;
5390
                }
5391
                if (sb <= 0.95f) {
5392
                    BrVector3Sub(&tv2, cam_pos, &face_list[1].v[0]);
5393
                    sc = BrVector3Dot(&face_list[1].normal, &tv2);
5394
                    if (sc < hither && sc >= 0.0) {
5395
                        sc = BrVector3Dot(&face_list[0].normal, &face_list[1].normal);
5396
                        BrVector3Scale(&b, &face_list[0].normal, sc);
5397
                        BrVector3Sub(&face_list[1].normal, &face_list[1].normal, &b);
5398
                        BrVector3Scale(&tv2, &face_list[1].normal, hither - ts2);
5399
                        BrVector3Accumulate(cam_pos, &tv2);
5400
                    }
5401
                }
5402
            }
5403
        }
5404
        i += k;
5405
    }
5406
    return i;
5407
}
5408
 
5409
// IDA: int __usercall BoundsTest@<EAX>(br_bounds *bnds@<EAX>, br_vector3 *p@<EDX>)
5410
int BoundsTest(br_bounds* bnds, br_vector3* p) {
20 pmbaty 5411
    //int j; // Pierre-Marie Baty -- unused variable
1 pmbaty 5412
    LOG_TRACE("(%p, %p)", bnds, p);
20 pmbaty 5413
    NOT_IMPLEMENTED();
1 pmbaty 5414
}
5415
 
5416
// IDA: int __usercall CollideCameraWithOtherCars@<EAX>(br_vector3 *car_pos@<EAX>, br_vector3 *cam_pos@<EDX>)
5417
int CollideCameraWithOtherCars(br_vector3* car_pos, br_vector3* cam_pos) {
20 pmbaty 5418
    //int i; // Pierre-Marie Baty -- unused variable
5419
    //int plane; // Pierre-Marie Baty -- unused variable
5420
    //br_scalar ts; // Pierre-Marie Baty -- unused variable
5421
    //tCar_spec* c; // Pierre-Marie Baty -- unused variable
5422
    //br_vector3 tv; // Pierre-Marie Baty -- unused variable
5423
    //br_vector3 pos_car_space; // Pierre-Marie Baty -- unused variable
5424
    //br_vector3 dir; // Pierre-Marie Baty -- unused variable
5425
    //br_vector3 p; // Pierre-Marie Baty -- unused variable
5426
    //br_vector3 n; // Pierre-Marie Baty -- unused variable
5427
    //br_bounds bnds; // Pierre-Marie Baty -- unused variable
1 pmbaty 5428
    LOG_TRACE("(%p, %p)", car_pos, cam_pos);
5429
 
20 pmbaty 5430
    STUB_ONCE();
1 pmbaty 5431
    return 0;
5432
}
5433
 
5434
// IDA: void __cdecl InitialiseExternalCamera()
5435
void InitialiseExternalCamera(void) {
5436
    br_scalar ts;
5437
    tCar_spec* c;
5438
    //br_vector3 r; // Pierre-Marie Baty -- unused variable
5439
    br_angle yaw;
5440
    LOG_TRACE("()");
5441
 
5442
    c = gCar_to_view;
5443
    if (!gProgram_state.racing) {
5444
        c = &gProgram_state.current_car;
5445
    }
5446
    gCamera_height = c->pos.v[1];
5447
    BrVector3Set(&gView_direction, c->direction.v[0], 0.0f, c->direction.v[2]);
5448
    BrVector3Normalise(&gView_direction, &gView_direction);
5449
    ts = -BrVector3Dot(&gView_direction, (br_vector3*)c->car_master_actor->t.t.mat.m[2]);
5450
    gCamera_sign = ts < 0;
5451
    gCamera_mode = 0;
5452
    if (gCamera_sign) {
5453
        yaw = -gCamera_yaw;
5454
    } else {
5455
        yaw = gCamera_yaw;
5456
    }
5457
    DrVector3RotateY(&gView_direction, yaw);
5458
    gMin_camera_car_distance = 0.6f;
5459
    gCamera_frozen = 0;
5460
    gCamera_mode = -2;
5461
    if (gCountdown && (gNet_mode == eNet_mode_none || gCurrent_net_game->options.grid_start) && gCountdown > 4) {
5462
        gCamera_height = gCamera_height + 10.0f;
5463
    }
5464
}
5465
 
5466
// IDA: void __cdecl FreezeCamera()
5467
void FreezeCamera(void) {
5468
    LOG_TRACE("()");
5469
 
5470
    gCamera_frozen = 1;
5471
}
5472
 
5473
// IDA: void __usercall FlyCar(tCar_spec *c@<EAX>, br_scalar dt)
5474
void FlyCar(tCar_spec* c, br_scalar dt) {
5475
    int accflag;
5476
    int turnflag;
5477
    br_vector3 step;
5478
    br_matrix34* mat;
5479
    br_angle theta;
5480
    static br_scalar vel = 0.f;
5481
    tFace_ref faces[20];
5482
    tBounds bnds;
5483
    int i;                 // Added by DethRace
5484
    br_scalar tmp_scalar1; // Added by DethRace
5485
    br_scalar tmp_scalar2; // Added by DethRace
5486
    br_vector3 tmp1;       // Added by DethRace
5487
    br_vector3 tmp2;       // Added by DethRace
5488
    br_vector3 tmp3;       // Added by DethRace
5489
    LOG_TRACE("(%p, %f)", c, dt);
5490
 
5491
    accflag = 0;
5492
    turnflag = 0;
5493
    mat = &c->car_master_actor->t.t.mat;
5494
    bnds.mat = mat;
5495
    BrVector3InvScale(&bnds.original_bounds.min, &c->bounds[1].min, WORLD_SCALE);
5496
    BrVector3InvScale(&bnds.original_bounds.max, &c->bounds[1].max, WORLD_SCALE);
5497
    BrVector3InvScale((br_vector3*)bnds.mat->m[3], (br_vector3*)bnds.mat->m[3], WORLD_SCALE);
5498
    FindFacesInBox(&bnds, faces, COUNT_OF(faces));
5499
    BrVector3Scale((br_vector3*)bnds.mat->m[3], (br_vector3*)bnds.mat->m[3], WORLD_SCALE);
5500
    if (c->keys.acc || c->joystick.acc > 0) {
5501
        vel += 10.f * dt;
5502
        accflag = 1;
5503
    }
5504
    if (c->keys.dec || c->joystick.dec > 0) {
5505
        vel -= 10.f * dt;
5506
        accflag = 1;
5507
    }
5508
    if (!accflag) {
5509
        if (vel >= 20.f * dt || vel <= -20.f * dt) {
5510
            vel -= 20.f * vel / fabsf(vel) * dt;
5511
        } else {
5512
            vel = 0.f;
5513
        }
5514
    }
5515
    BrVector3Scale(&step, &c->v, dt);
5516
    BrVector3Accumulate((br_vector3*)mat->m[3], &step);
5517
    BrVector3Scale(&step, (br_vector3*)mat->m[1], dt);
5518
    if (c->keys.left || c->joystick.left > 0) {
5519
        BrVector3Accumulate(&c->omega, &step);
5520
        turnflag = 1;
5521
    }
5522
    if (c->keys.right || c->joystick.right > 0) {
5523
        BrVector3Sub(&c->omega, &c->omega, &step);
5524
        turnflag = 1;
5525
    }
5526
    if (!turnflag) {
5527
        BrVector3SetFloat(&c->omega, 0.f, 0.f, 0.f);
5528
    }
5529
    theta = BrRadianToAngle(c->omega.v[1] * dt);
5530
    DrVector3RotateY(&c->v, theta);
5531
    BrMatrix34PreRotateY(mat, theta);
5532
    if (c->keys.up) {
5533
        BrMatrix34PreRotateX(mat, BrDegreeToAngle(5));
5534
    }
5535
    if (c->keys.down) {
5536
        BrMatrix34PreRotateX(mat, BrDegreeToAngle(360 - 5));
5537
    }
5538
    BrVector3Scale(&c->v, (br_vector3*)mat->m[2], -vel);
5539
    BrVector3Scale(&step, &c->v, dt);
5540
    BrVector3Accumulate((br_vector3*)&mat->m[3], &step);
5541
    if (c->keys.holdw) {
5542
        BrVector3Copy(&step, (br_vector3*)mat->m[3]);
5543
        BrMatrix34RotateY(mat, BrDegreeToAngle(90) - BrRadianToAngle(atan2f(mat->m[2][2], mat->m[2][0])));
5544
        BrVector3Copy((br_vector3*)mat->m[3], &step);
5545
        BrVector3SetFloat(&step, 0.f, -100.f, 0.f);
5546
        BrVector3Copy(&tmp1, (br_vector3*)&mat->m[3]);
5547
        findfloor(&tmp1, &step, &tmp2, &tmp_scalar1);
5548
        tmp1.v[1] += 100.f;
5549
        findfloor(&tmp1, &step, &tmp3, &tmp_scalar2);
5550
        if (tmp_scalar2 <= 1.f) {
5551
            BrVector3SetFloat(&step, 0.f, -5.01f, 0.f);
5552
            tmp1.v[1] -= 20 * 5.f;
5553
            for (i = 0; i < 20; i++) {
5554
                tmp1.v[1] += 5.f;
5555
                findfloor(&tmp1, &step, &tmp3, &tmp_scalar2);
5556
                if (tmp_scalar2 <= 1.f) {
5557
                    break;
5558
                }
5559
            }
5560
            tmp_scalar2 = -tmp_scalar2 / 20.f + (i + 1) * 0.05f;
5561
        }
5562
        if (tmp_scalar2 < tmp_scalar1) {
5563
            tmp_scalar1 = -tmp_scalar2;
5564
            BrVector3Copy(&tmp2, &tmp3);
5565
        }
5566
        if (tmp_scalar1 <= 1.f) {
5567
            mat->m[3][1] -= tmp_scalar1 * 100.f;
5568
            BrMatrix34PreRotateX(mat, BrRadianToAngle(asinf(BrVector3Dot((br_vector3*)mat->m[2], &tmp2))));
5569
            BrMatrix34PreRotateZ(mat, -BrRadianToAngle(asinf(BrVector3Dot((br_vector3*)mat->m[0], &tmp2))));
5570
        }
5571
    }
5572
    BrVector3Negate((br_vector3*)&c->direction, (br_vector3*)mat->m[2]);
5573
    BrMatrix34Copy(&c->oldmat, mat);
5574
    BrMatrix34ApplyP(&c->pos, &c->cmpos, mat);
5575
    BrVector3InvScale(&c->pos, &c->pos, WORLD_SCALE);
5576
    BrVector3InvScale((br_vector3*)bnds.mat->m[3], (br_vector3*)bnds.mat->m[3], WORLD_SCALE);
5577
    GetNewBoundingBox(&c->bounds_world_space, c->bounds, bnds.mat);
5578
    BrVector3Scale((br_vector3*)bnds.mat->m[3], (br_vector3*)bnds.mat->m[3], WORLD_SCALE);
5579
}
5580
 
5581
// IDA: void __usercall DrVector3RotateY(br_vector3 *v@<EAX>, br_angle t@<EDX>)
5582
void DrVector3RotateY(br_vector3* v, br_angle t) {
5583
    br_scalar c;
5584
    br_scalar s;
5585
    br_scalar ts;
5586
    LOG_TRACE("(%p, %d)", v, t);
5587
 
5588
    c = cos(BrAngleToRadian(t));
5589
    s = sin(BrAngleToRadian(t));
5590
    ts = v->v[0] * c + v->v[2] * s;
5591
    v->v[2] = v->v[2] * c - v->v[0] * s;
5592
    v->v[0] = ts;
5593
}
5594
 
5595
// IDA: void __cdecl CrashCarsTogether(br_scalar dt)
5596
void CrashCarsTogether(br_scalar dt) {
5597
    int pass;
5598
    int k;
5599
    int i;
5600
    tCollison_data collide_list[32];
5601
    LOG_TRACE("(%f)", dt);
5602
 
5603
    for (i = 0; i < gNum_cars_and_non_cars; i++) {
5604
        collide_list[i].car = NULL;
5605
        collide_list[i].ref = gNum_cars_and_non_cars - 1;
5606
        gActive_car_list[i]->infinite_mass = 0;
5607
    }
5608
    for (pass = 0; pass < 5; pass++) {
5609
        k = CrashCarsTogetherSinglePass(dt, pass, collide_list);
5610
        if (k <= 0) {
5611
            break;
5612
        }
5613
    }
5614
    if (k > 0) {
5615
        for (i = 0; i < gNum_cars_and_non_cars; i++) {
5616
            BringCarToAGrindingHalt((tCollision_info*)gActive_car_list[i]);
5617
        }
5618
    }
5619
}
5620
 
5621
// IDA: int __cdecl CrashCarsTogetherSinglePass(br_scalar dt, int pPass, tCollison_data *collide_list)
5622
int CrashCarsTogetherSinglePass(br_scalar dt, int pPass, tCollison_data* collide_list) {
5623
    int i;
5624
    int j;
5625
    //int l; // Pierre-Marie Baty -- unused variable
5626
    //int m; // Pierre-Marie Baty -- unused variable
5627
    //int n; // Pierre-Marie Baty -- unused variable
5628
    int collided;
5629
    int k;
5630
    //int ref1; // Pierre-Marie Baty -- unused variable
5631
    //int ref2; // Pierre-Marie Baty -- unused variable
5632
    int c1im;
5633
    int c2im;
5634
    tCollision_info* car_1;
5635
    tCollision_info* car_2;
5636
    tCollision_info* car_3;
5637
    tCollision_info* car_in_middle;
5638
    tCollision_info* car_on_wall;
5639
    LOG_TRACE("(%f, %d, %p)", dt, pPass, collide_list);
5640
 
5641
    collided = 0;
5642
    for (i = 0; i < gNum_cars_and_non_cars - 1; i++) {
5643
        car_1 = (tCollision_info*)gActive_car_list[i];
5644
        for (j = i + 1; j < gNum_cars_and_non_cars; j++) {
5645
            car_2 = (tCollision_info*)gActive_car_list[j];
5646
            if (collide_list[i].ref > 0 || collide_list[j].ref > 0) {
5647
                collide_list[i].ref--;
5648
                collide_list[j].ref--;
5649
                if (SimpleCarCarCollisionTest(car_1, car_2)) {
5650
                    if (car_1->infinite_mass == -1 && car_2->infinite_mass > 0) {
5651
                        if (CollideTwoCars(car_1, car_2, -1)) {
5652
                            if (car_2->infinite_mass >= 256 || pPass >= 4) {
5653
                                BringCarToAGrindingHalt(car_2);
5654
                            } else {
5655
                                car_2->infinite_mass = 0;
5656
                                k = CollideTwoCarsWithWalls(car_1, car_2, dt);
5657
                                car_2->infinite_mass = 256;
5658
                                if (k < 0) {
5659
                                    BringCarToAGrindingHalt(car_2);
5660
                                }
5661
                            }
5662
                            collide_list[j].ref = gNum_cars_and_non_cars - 2;
5663
                            collide_list[j].car = car_1;
5664
                            collided++;
5665
                        }
5666
                    } else if (car_2->infinite_mass == -1 && car_1->infinite_mass > 0) {
5667
                        if (CollideTwoCars(car_1, car_2, -1)) {
5668
                            if (car_1->infinite_mass >= 256 || pPass >= 4) {
5669
                                BringCarToAGrindingHalt(car_1);
5670
                            } else {
5671
                                car_1->infinite_mass = 0;
5672
                                k = CollideTwoCarsWithWalls(car_1, car_2, dt);
5673
                                car_1->infinite_mass = 256;
5674
                                if (k < 0) {
5675
                                    BringCarToAGrindingHalt(car_1);
5676
                                }
5677
                            }
5678
                            collide_list[i].ref = gNum_cars_and_non_cars - 2;
5679
                            collide_list[i].car = car_2;
5680
                            collided++;
5681
                        }
5682
                    } else if (collide_list[i].car || collide_list[j].car) {
5683
                        if ((collide_list[j].car == NULL) == (collide_list[i].car == NULL)) {
5684
                            if (collide_list[j].car != collide_list[i].car || (car_1->infinite_mass && car_2->infinite_mass)) {
5685
                                if (collide_list[i].car && collide_list[j].car) {
5686
                                    if (car_1->infinite_mass && car_2->infinite_mass) {
5687
                                        if ((car_1->infinite_mass != -1 || car_2->infinite_mass != -1) && CollideTwoCars(car_1, car_2, -1)) {
5688
                                            collide_list[i].ref = gNum_cars_and_non_cars - 2;
5689
                                            collide_list[j].ref = gNum_cars_and_non_cars - 2;
5690
                                            if (car_1->infinite_mass && car_2->infinite_mass) {
5691
                                                BringCarToAGrindingHalt(car_1);
5692
                                                BringCarToAGrindingHalt(car_2);
5693
                                            } else {
5694
                                                k = CollideTwoCarsWithWalls(car_1, car_2, dt);
5695
                                                if (k >= 0) {
5696
                                                    if (k) {
5697
                                                        if (car_1->infinite_mass >= 0) {
5698
                                                            car_1->infinite_mass++;
5699
                                                        }
5700
                                                        if (car_2->infinite_mass >= 0) {
5701
                                                            car_2->infinite_mass++;
5702
                                                        }
5703
                                                        collided++;
5704
                                                    }
5705
                                                } else {
5706
                                                    BringCarToAGrindingHalt(car_1);
5707
                                                    BringCarToAGrindingHalt(car_2);
5708
                                                    collided++;
5709
                                                }
5710
                                            }
5711
                                            collided++;
5712
                                        }
5713
                                    } else {
5714
                                        c1im = car_1->infinite_mass;
5715
                                        c2im = car_2->infinite_mass;
5716
                                        k = CollideTwoCarsWithWalls(car_1, car_2, dt);
5717
                                        if (k > -1) {
5718
                                            if (k) {
5719
                                                if (!c2im) {
5720
                                                    collide_list[j].ref = gNum_cars_and_non_cars - 2;
5721
                                                }
5722
                                                if (!c1im) {
5723
                                                    collide_list[i].ref = gNum_cars_and_non_cars - 2;
5724
                                                }
5725
                                                collided++;
5726
                                                if (car_1->infinite_mass >= 0) {
5727
                                                    car_1->infinite_mass++;
5728
                                                }
5729
                                                if (car_2->infinite_mass >= 0) {
5730
                                                    car_2->infinite_mass++;
5731
                                                }
5732
                                            }
5733
                                        } else {
5734
                                            BringCarToAGrindingHalt(car_1);
5735
                                            BringCarToAGrindingHalt(car_2);
5736
                                            if (c1im >= 0) {
5737
                                                collide_list[i].ref = gNum_cars_and_non_cars - 2;
5738
                                            }
5739
                                            if (c2im >= 0) {
5740
                                                collide_list[j].ref = gNum_cars_and_non_cars - 2;
5741
                                            }
5742
                                            collided++;
5743
                                        }
5744
                                    }
5745
                                }
5746
                            } else {
5747
                                k = CollideTwoCarsWithWalls(car_1, car_2, dt);
5748
                                if (k) {
5749
                                    collide_list[i].ref = gNum_cars_and_non_cars - 2;
5750
                                    collide_list[j].ref = gNum_cars_and_non_cars - 2;
5751
                                    if (k == -1) {
5752
                                        BringCarToAGrindingHalt(car_1);
5753
                                        BringCarToAGrindingHalt(car_2);
5754
                                    }
5755
                                    collided++;
5756
                                    if (car_1->infinite_mass >= 0) {
5757
                                        car_1->infinite_mass++;
5758
                                    }
5759
                                    if (car_2->infinite_mass >= 0) {
5760
                                        car_2->infinite_mass++;
5761
                                    }
5762
                                }
5763
                            }
5764
                        } else {
5765
                            c1im = car_1->infinite_mass;
5766
                            c2im = car_2->infinite_mass;
5767
                            k = CollideTwoCarsWithWalls(car_1, car_2, dt);
5768
                            if (k == -1) {
5769
                                if (collide_list[i].car) {
5770
                                    car_3 = collide_list[i].car;
5771
                                } else {
5772
                                    car_3 = collide_list[j].car;
5773
                                }
5774
                                if (collide_list[i].car) {
5775
                                    car_in_middle = car_1;
5776
                                } else {
5777
                                    car_in_middle = car_2;
5778
                                }
5779
                                if (car_3->infinite_mass > 1 || car_3->infinite_mass == -1 || (tU8)(car_in_middle->infinite_mass) > 1 || car_in_middle->infinite_mass == -1) {
5780
                                    BringCarToAGrindingHalt(car_1);
5781
                                    BringCarToAGrindingHalt(car_2);
5782
                                    collide_list[i].ref = gNum_cars_and_non_cars - 2;
5783
                                    collide_list[j].ref = gNum_cars_and_non_cars - 2;
5784
                                } else {
5785
                                    if (collide_list[i].car) {
5786
                                        car_on_wall = car_2;
5787
                                    } else {
5788
                                        car_on_wall = car_1;
5789
                                    }
5790
                                    car_in_middle->infinite_mass = 0;
5791
                                    car_3->infinite_mass = 0;
5792
                                    k = CollideTwoCarsWithWalls(car_on_wall, car_in_middle, dt);
5793
                                    car_in_middle->infinite_mass = 2;
5794
                                    car_on_wall->infinite_mass++;
5795
                                    collide_list[i].ref = gNum_cars_and_non_cars - 2;
5796
                                    collide_list[j].ref = gNum_cars_and_non_cars - 2;
5797
                                    if (k < 0) {
5798
                                        BringCarToAGrindingHalt(car_1);
5799
                                        BringCarToAGrindingHalt(car_2);
5800
                                    }
5801
                                }
5802
                                collide_list[i].car = car_2;
5803
                                collide_list[j].car = car_1;
5804
                                collided++;
5805
                            } else if (k) {
5806
                                collide_list[i].car = car_2;
5807
                                collide_list[j].car = car_1;
5808
                                if (!c2im) {
5809
                                    collide_list[j].ref = gNum_cars_and_non_cars - 2;
5810
                                }
5811
                                if (!c1im) {
5812
                                    collide_list[i].ref = gNum_cars_and_non_cars - 2;
5813
                                }
5814
                                collided++;
5815
                                if (car_1->infinite_mass >= 0) {
5816
                                    car_1->infinite_mass++;
5817
                                }
5818
                                if (car_2->infinite_mass >= 0) {
5819
                                    car_2->infinite_mass++;
5820
                                }
5821
                            }
5822
                        }
5823
                    } else {
5824
                        k = CollideTwoCarsWithWalls(car_1, car_2, dt);
5825
                        if (k) {
5826
                            collide_list[i].car = car_2;
5827
                            collide_list[j].car = car_1;
5828
                            collide_list[i].ref = gNum_cars_and_non_cars - 2;
5829
                            collide_list[j].ref = gNum_cars_and_non_cars - 2;
5830
                            if (k == -1) {
5831
                                BringCarToAGrindingHalt(car_1);
5832
                                BringCarToAGrindingHalt(car_2);
5833
                                collide_list[i].ref = gNum_cars_and_non_cars - 2;
5834
                                collide_list[j].ref = gNum_cars_and_non_cars - 2;
5835
                            }
5836
                            collided++;
5837
                        }
5838
                    }
5839
                    CrashEarnings((tCar_spec*)car_1, (tCar_spec*)car_2);
5840
                }
5841
            }
5842
        }
5843
    }
5844
    return collided;
5845
}
5846
 
5847
// IDA: void __usercall BringCarToAGrindingHalt(tCollision_info *car@<EAX>)
5848
void BringCarToAGrindingHalt(tCollision_info* car) {
5849
    LOG_TRACE("(%p)", car);
5850
 
5851
    BrVector3SetFloat(&car->v, 0.0f, 0.0f, 0.0f);
5852
    BrVector3SetFloat(&car->omega, 0.0f, 0.0f, 0.0f);
5853
    BrVector3SetFloat(&car->oldomega, 0.0f, 0.0f, 0.0f);
5854
    BrMatrix34Copy(&car->car_master_actor->t.t.mat, &car->oldmat);
5855
    car->infinite_mass = -1;
5856
}
5857
 
5858
// IDA: int __usercall BoundsOverlapTest@<EAX>(br_bounds *b1@<EAX>, br_bounds *b2@<EDX>)
5859
int BoundsOverlapTest_car(br_bounds* b1, br_bounds* b2) {
5860
    LOG_TRACE("(%p, %p)", b1, b2);
5861
 
5862
    return b2->max.v[0] >= b1->min.v[0]
5863
        && b1->max.v[0] >= b2->min.v[0]
5864
        && b2->max.v[1] >= b1->min.v[1]
5865
        && b1->max.v[1] >= b2->min.v[1]
5866
        && b2->max.v[2] >= b1->min.v[2]
5867
        && b1->max.v[2] >= b2->min.v[2];
5868
}
5869
 
5870
// IDA: int __usercall SimpleCarCarCollisionTest@<EAX>(tCollision_info *car1@<EAX>, tCollision_info *car2@<EDX>)
5871
int SimpleCarCarCollisionTest(tCollision_info* car1, tCollision_info* car2) {
5872
    LOG_TRACE("(%p, %p)", car1, car2);
5873
 
5874
    if (car1->bounds_ws_type == eBounds_ws && car2->bounds_ws_type == eBounds_ws) {
5875
        return BoundsOverlapTest_car(&car1->bounds_world_space, &car2->bounds_world_space);
5876
    } else {
5877
        return 1;
5878
    }
5879
}
5880
 
5881
// IDA: int __usercall CollideTwoCarsWithWalls@<EAX>(tCollision_info *car1@<EAX>, tCollision_info *car2@<EDX>, br_scalar dt)
5882
int CollideTwoCarsWithWalls(tCollision_info* car1, tCollision_info* car2, br_scalar dt) {
5883
    br_vector3 mom1;
5884
    br_vector3 mom2;
5885
    int l;
5886
    int m;
5887
    int n;
5888
    int p;
5889
    int im1;
5890
    int im2;
5891
    LOG_TRACE("(%p, %p, %f)", car1, car2, dt);
5892
 
5893
    l = 0;
5894
    m = 0;
5895
    p = 0;
5896
    im1 = car1->infinite_mass;
5897
    im2 = car2->infinite_mass;
5898
    do {
5899
        n = CollideTwoCarsRepeatedly(car1, car2, dt);
5900
        if (n <= 0) {
5901
            if (n == -1) {
5902
                return -1;
5903
            }
5904
            l = 0;
5905
            m = 0;
5906
        } else {
5907
            ++p;
5908
            if (n >= 5) {
5909
                if (p >= 10 || car1->infinite_mass || car2->infinite_mass) {
5910
                    return -1;
5911
                }
5912
                BrVector3Set(&car1->omega, 0.0f, 0.0f, 0.0f);
5913
                BrVector3Set(&car2->omega, 0.0f, 0.0f, 0.0f);
5914
                BrVector3Scale(&mom1, &car1->v, car1->M);
5915
                BrVector3Scale(&mom2, &car2->v, car2->M);
5916
                BrVector3Accumulate(&mom1, &mom2);
5917
                BrVector3InvScale(&car1->v, &mom1, car2->M + car1->M);
5918
                car2->v = car1->v;
5919
                RotateCar(car1, dt);
5920
                TranslateCar(car1, dt);
5921
                RotateCar(car2, dt);
5922
                TranslateCar(car2, dt);
5923
                if (CollideTwoCars(car1, car2, -1)) {
5924
                    return -1;
5925
                }
5926
                if (im1 || im2) {
5927
                    return -1;
5928
                }
5929
            }
5930
            if (!im1) {
5931
                l = CollideCarWithWall(car1, dt);
5932
            }
5933
            if (!im2) {
5934
                m = CollideCarWithWall(car2, dt);
5935
            }
5936
            if (p < 3) {
5937
                car1->infinite_mass = im1;
5938
                car2->infinite_mass = im2;
5939
            }
5940
            if (p > 5) {
5941
                if (l) {
5942
                    car1->infinite_mass |= 0x100u;
5943
                }
5944
                if (m) {
5945
                    car2->infinite_mass |= 0x100u;
5946
                }
5947
            }
5948
            if (car1->infinite_mass && car2->infinite_mass) {
5949
                return -1;
5950
            }
5951
        }
5952
    } while ((l || m) && p < 10);
5953
    if (p < 10) {
5954
        return p;
5955
    } else {
5956
        return -1;
5957
    }
5958
}
5959
 
5960
// IDA: int __usercall CollideTwoCarsRepeatedly@<EAX>(tCollision_info *car1@<EAX>, tCollision_info *car2@<EDX>, br_scalar dt)
5961
int CollideTwoCarsRepeatedly(tCollision_info* car1, tCollision_info* car2, br_scalar dt) {
5962
    int l;
5963
    int collide;
5964
    //br_scalar ts; // Pierre-Marie Baty -- unused variable
5965
    LOG_TRACE("(%p, %p, %f)", car1, car2, dt);
5966
 
5967
    l = 0;
5968
    ModifyCarsMass(car1, car2);
5969
    while (1) {
5970
        collide = CollideTwoCars(car1, car2, l);
5971
        if (!collide) {
5972
            break;
5973
        }
5974
        if (collide == -1) {
5975
            ResetCarsMass(car1, car2);
5976
            return -1;
5977
        }
5978
        if (++l >= 5) {
5979
            break;
5980
        }
5981
        RotateCar(car1, dt);
5982
        TranslateCar(car1, dt);
5983
        RotateCar(car2, dt);
5984
        TranslateCar(car2, dt);
5985
    }
5986
    if (l > 0) {
5987
        car1->frame_collision_flag += 256;
5988
        car2->frame_collision_flag += 256;
5989
        if (gNet_mode == eNet_mode_host) {
5990
            car1->last_car_car_collision = gLast_mechanics_time + 40;
5991
            car2->last_car_car_collision = gLast_mechanics_time + 40;
5992
        }
5993
    }
5994
    ResetCarsMass(car1, car2);
5995
    return l;
5996
}
5997
 
5998
// IDA: int __usercall CollideTwoCars@<EAX>(tCollision_info *car1@<EAX>, tCollision_info *car2@<EDX>, int pPass@<EBX>)
5999
int CollideTwoCars(tCollision_info* car1, tCollision_info* car2, int pPass) {
6000
    int k;
6001
    int old_k;
6002
    int i;
6003
    int j;
6004
    //br_scalar dist; // Pierre-Marie Baty -- unused variable
6005
    //br_scalar ts; // Pierre-Marie Baty -- unused variable
6006
    br_bounds new_car1_bnds;
6007
    br_bounds new_car2_bnds;
6008
    br_bounds bnds;
6009
    br_matrix34* mat1;
6010
    br_matrix34* mat2;
6011
    br_matrix34* oldmat1;
6012
    br_matrix34* oldmat2;
6013
    br_matrix34 inv_mat1;
6014
    br_matrix34 inv_mat2;
6015
    br_matrix34 inv_oldmat1;
6016
    br_matrix34 inv_oldmat2;
6017
    br_matrix34 car2_to_car1;
6018
    br_matrix34 car1_to_car2;
6019
    br_matrix34 old_car2_to_car1;
6020
    br_matrix34 old_car1_to_car2;
6021
    br_matrix34 car1_to_old_car1;
6022
    br_matrix34 car2_to_old_car2;
6023
    br_vector3 r[16];
6024
    br_vector3 n[16];
6025
    //br_vector3 sep; // Pierre-Marie Baty -- unused variable
6026
    br_vector3 tv;
6027
    int add_point;
6028
    static br_vector3 oldr1;
6029
    static br_vector3 oldr2;
6030
    static br_vector3 oldn1;
6031
    static br_vector3 oldn2;
6032
    static int is_old_point_available;
6033
    LOG_TRACE("(%p, %p, %d)", car1, car2, pPass);
6034
 
6035
#ifdef DETHRACE_FIX_BUGS
6036
    // this variable is used uninitialized
6037
    add_point = 0;
6038
#endif
6039
 
6040
    if (!gCar_car_collisions) {
6041
        return 0;
6042
    }
6043
    if (pPass < 0 && !SimpleCarCarCollisionTest(car1, car2)) {
6044
        return 0;
6045
    }
6046
 
6047
    mat1 = &car1->car_master_actor->t.t.mat;
6048
    mat2 = &car2->car_master_actor->t.t.mat;
6049
    oldmat1 = &car1->oldmat;
6050
    oldmat2 = &car2->oldmat;
6051
    BrMatrix34LPInverse(&inv_oldmat1, &car1->oldmat);
6052
    BrMatrix34LPInverse(&inv_oldmat2, &car2->oldmat);
6053
    BrMatrix34Mul(&car1_to_old_car1, mat1, &inv_oldmat1);
6054
    BrMatrix34Mul(&car2_to_old_car2, mat2, &inv_oldmat2);
6055
    BrMatrix34Mul(&old_car2_to_car1, oldmat2, &inv_oldmat1);
6056
    GetNewBoundingBox(&new_car1_bnds, &car1->bounds[1], &car1_to_old_car1);
6057
    GetNewBoundingBox(&new_car2_bnds, &car2->bounds[1], &car2_to_old_car2);
6058
 
6059
    for (i = 0; i < 3; ++i) {
6060
        new_car1_bnds.min.v[i] = MIN(car1->bounds[1].min.v[i], new_car1_bnds.min.v[i]);
6061
        new_car1_bnds.max.v[i] = MAX(car1->bounds[1].max.v[i], new_car1_bnds.max.v[i]);
6062
 
6063
        new_car2_bnds.min.v[i] = MIN(car2->bounds[1].min.v[i], new_car2_bnds.min.v[i]);
6064
        new_car2_bnds.max.v[i] = MAX(car2->bounds[1].max.v[i], new_car2_bnds.max.v[i]);
6065
    }
6066
    GetNewBoundingBox(&bnds, &new_car2_bnds, &old_car2_to_car1);
6067
 
6068
    if (new_car1_bnds.max.v[0] < bnds.min.v[0]
6069
        || bnds.max.v[0] < new_car1_bnds.min.v[0]
6070
        || new_car1_bnds.max.v[1] < bnds.min.v[1]
6071
        || bnds.max.v[1] < new_car1_bnds.min.v[1]
6072
        || new_car1_bnds.max.v[2] < bnds.min.v[2]
6073
        || bnds.max.v[2] < new_car1_bnds.min.v[2]) {
6074
        return 0;
6075
    }
6076
    BrMatrix34LPInverse(&inv_mat1, mat1);
6077
    BrMatrix34LPInverse(&inv_mat2, mat2);
6078
    BrMatrix34Mul(&car2_to_car1, mat2, &inv_mat1);
6079
    BrMatrix34Mul(&car1_to_car2, mat1, &inv_mat2);
6080
    BrMatrix34Mul(&old_car2_to_car1, oldmat2, &inv_oldmat1);
6081
    BrMatrix34Mul(&old_car1_to_car2, oldmat1, &inv_oldmat2);
6082
    BrMatrix34Mul(&car1_to_old_car1, mat1, &inv_oldmat1);
6083
    BrMatrix34Mul(&car2_to_old_car2, mat2, &inv_oldmat2);
6084
    do {
6085
        k = 0;
6086
        k += FacePointCarCarCollide(car1, car2, &car2_to_car1, &old_car2_to_car1, &car1_to_old_car1, r, n, 8, 0);
6087
        k += FacePointCarCarCollide(car2, car1, &car1_to_car2, &old_car1_to_car2, &car2_to_old_car2, &r[2 * k], &n[2 * k], 8 - k, 1);
6088
        old_k = k;
6089
 
6090
        if (k < 3 || add_point) {
6091
            k += GetEdgeEdgeCollisions(&car1->bounds[1], &car2->bounds[1], &car2_to_car1, &car1_to_car2, &old_car2_to_car1, &old_car1_to_car2, &car1_to_old_car1, &r[2 * k], &n[2 * k], 8 - k);
6092
        }
6093
        if (k == -1) {
6094
            TestOldMats(car1, car2, 1);
6095
        }
6096
        if (!k) {
6097
            return 0;
6098
        }
6099
        if (k > 4) {
6100
            i = old_k;
6101
            j = old_k;
6102
            while (i < k) {
6103
                if (BrVector3Dot(&n[2 * i + 1], &r[2 * i + 1]) <= 0.0f || i - j >= k - 4) {
6104
                    if (j != i) {
6105
                        r[2 * j] = r[2 * i];
6106
                    }
6107
                    n[2 * j] = n[2 * i];
6108
                    r[2 * j + 1] = r[2 * i + 1];
6109
                    n[2 * j + 1] = n[2 * i + 1];
6110
                } else {
6111
                    j--;
6112
                }
6113
                i++;
6114
                j++;
6115
            }
6116
            k = j;
6117
        }
6118
        for (i = 0; i < k; ++i) {
6119
            BrVector3Sub(&r[2 * i], &r[2 * i], &car1->cmpos);
6120
            BrVector3Sub(&r[2 * i + 1], &r[2 * i + 1], &car2->cmpos);
6121
        }
6122
        if (add_point == -1) {
6123
            return k;
6124
        }
6125
        car1->doing_nothing_flag = 0;
6126
        car2->doing_nothing_flag = 0;
6127
        if (k < 3 && add_point) {
6128
            for (i = 0; i < k; i++) {
6129
                BrVector3Sub(&tv, &r[2 * i], &oldr1);
6130
                if (BrVector3LengthSquared(&tv) < 0.01f) {
6131
                    add_point = 0;
6132
                }
6133
            }
6134
            if (add_point) {
6135
                r[2 * k] = oldr1;
6136
                r[2 * k + 1] = oldr2;
6137
                n[2 * k] = oldn1;
6138
                n[2 * k + 1] = oldn2;
6139
                k++;
6140
            }
6141
        }
6142
        oldr1 = r[0];
6143
        oldr2 = r[1];
6144
        oldn1 = n[0];
6145
        oldn2 = n[1];
6146
        if (k < 3) {
6147
            if (car1->collision_flag && !car1->infinite_mass) {
6148
 
6149
                for (i = 0; i < k; i++) {
6150
                    if (BrVector3Dot(&n[2 * i], &car1->old_norm) < -0.9f) {
6151
                        car1->infinite_mass |= 0x100u;
6152
                    }
6153
                }
6154
                if (!car1->infinite_mass) {
6155
                    r[2 * k] = car1->old_point;
6156
                    n[2 * k] = car1->old_norm;
6157
                    BrVector3SetFloat(&n[2 * k + 1], 0.0f, 0.0f, 0.0f);
6158
                    BrVector3SetFloat(&r[2 * k + 1], 0.0f, 0.0f, 0.0f);
6159
                    k++;
6160
                }
6161
            }
6162
            if (car2->collision_flag && !car2->infinite_mass) {
6163
                for (i = 0; i < k; i++) {
6164
                    if (BrVector3Dot(&n[2 * i + 1], &car2->old_norm) < -0.9f) {
6165
                        car2->infinite_mass |= 0x100u;
6166
                    }
6167
                }
6168
                if (!car2->infinite_mass) {
6169
                    r[2 * k + 1] = car2->old_point;
6170
                    n[2 * k + 1] = car2->old_norm;
6171
                    BrVector3SetFloat(&n[2 * k], 0.0f, 0.0f, 0.0f);
6172
                    BrVector3SetFloat(&r[2 * k], 0.0f, 0.0f, 0.0f);
6173
                    k++;
6174
                }
6175
            }
6176
        }
6177
        if (car1->infinite_mass && car2->infinite_mass) {
6178
            return -1;
6179
        }
6180
    } while (DoCollide(car1, car2, r, n, k, pPass, &car1_to_car2));
6181
    return k;
6182
}
6183
 
6184
// IDA: int __usercall GetEdgeEdgeCollisions@<EAX>(br_bounds *pB1@<EAX>, br_bounds *pB2@<EDX>, br_matrix34 *pM21@<EBX>, br_matrix34 *pM12@<ECX>, br_matrix34 *pMo21, br_matrix34 *pMo12, br_matrix34 *pM1o1, br_vector3 *pPoint_list, br_vector3 *pNorm_list, int pMax)
6185
int GetEdgeEdgeCollisions(br_bounds* pB1, br_bounds* pB2, br_matrix34* pM21, br_matrix34* pM12, br_matrix34* pMo21, br_matrix34* pMo12, br_matrix34* pM1o1, br_vector3* pPoint_list, br_vector3* pNorm_list, int pMax) {
6186
    br_vector3 p1;
6187
    br_vector3 p2;
6188
    br_vector3 tp1;
6189
    br_vector3 tp2;
6190
    br_vector3 tp3;
6191
    br_vector3 hp1;
6192
    br_vector3 hp2;
6193
    br_vector3 hp3;
6194
    br_vector3 shp1;
6195
    br_vector3 shp2;
6196
    br_vector3 edge;
6197
    int plane1;
6198
    int plane2;
6199
    int plane3;
6200
    br_scalar ts;
6201
    int i;
6202
    int j;
6203
    int n;
6204
    LOG_TRACE("(%p, %p, %p, %p, %p, %p, %p, %p, %p, %d)", pB1, pB2, pM21, pM12, pMo21, pMo12, pM1o1, pPoint_list, pNorm_list, pMax);
6205
 
6206
    // EdgeEdge final version
6207
    n = 0;
6208
    if (pMax < 1) {
6209
        return 0;
6210
    }
6211
    for (i = 0; i < 4; i++) {
6212
        if (i == 3) {
6213
            tp1 = pB2->min;
6214
        } else {
6215
            tp1 = pB2->max;
6216
            tp1.v[i] = pB2->min.v[i];
6217
        }
6218
        for (j = 0; j < 3; j++) {
6219
            tp2 = tp1;
6220
            if (pB2->max.v[j] == tp2.v[j]) {
6221
                tp2.v[j] = pB2->min.v[j];
6222
            } else {
6223
                tp2.v[j] = pB2->max.v[j];
6224
            }
6225
 
6226
            BrMatrix34ApplyP(&p1, &tp1, pM21);
6227
            BrMatrix34ApplyP(&p2, &tp2, pM21);
6228
            plane1 = LineBoxColl(&p1, &p2, pB1, &hp1);
6229
            if (plane1 == 0) {
6230
                continue;
6231
            }
6232
            plane2 = LineBoxColl(&p2, &p1, pB1, &hp2);
6233
            if (plane1 == 8 || plane2 == 8 || plane2 == 0) {
6234
                continue;
6235
            }
6236
            BrVector3Add(&p1, &hp1, &hp2);
6237
            BrVector3Scale(&p1, &p1, 0.5f);
6238
            BrMatrix34ApplyP(&tp3, &p1, pM12);
6239
            BrMatrix34ApplyP(&p2, &tp3, pMo21);
6240
            plane3 = LineBoxColl(&p2, &p1, pB1, &hp3);
6241
            // if (plane3 != 8 && plane3 != 0) {
6242
            //     goto LABEL_25;
6243
            // }
6244
            if (plane3 == 8 || plane3 == 0) {
6245
                BrVector3Sub(&tp3, &p2, &p1);
6246
                ts = BrVector3Length(&tp3);
6247
                ts = ts / 0.01f;
6248
                if (ts == 0.0f) {
6249
                    continue;
6250
                }
6251
                BrVector3InvScale(&tp3, &tp3, ts);
6252
                BrVector3Accumulate(&p2, &tp3);
6253
                plane3 = LineBoxColl(&p2, &p1, pB1, &hp3);
6254
                if (plane3 == 8) {
6255
                    continue;
6256
                }
6257
            }
6258
            if (plane3 == 0) {
6259
                continue;
6260
            }
6261
 
6262
            BrMatrix34ApplyP(&shp1, &hp1, pM12);
6263
            BrMatrix34ApplyP(&shp2, &hp2, pM12);
6264
            if ((plane1 ^ plane2) != 4 && (plane3 == plane1 || plane3 == plane2)) {
6265
                if (n >= pMax) {
6266
                    return n;
6267
                }
6268
                GetBoundsEdge(&pPoint_list[2 * n], &edge, pB1, plane1, plane2, &p2, &hp1, &hp2, 0);
6269
                BrVector3Accumulate(&shp1, &shp2);
6270
                BrVector3Scale(&pPoint_list[2 * n + 1], &shp1, 0.5f);
6271
                BrVector3Sub(&p1, &hp1, &hp2);
6272
                BrVector3Cross(&p2, &edge, &p1);
6273
                BrVector3Normalise(&p2, &p2);
6274
                BrVector3Add(&p1, &pB1->max, &pB1->min);
6275
                BrVector3Scale(&p1, &p1, 0.5f);
6276
                BrVector3Sub(&p1, &pPoint_list[2 * n], &p1);
6277
                if (BrVector3Dot(&p1, &p2) > 0.0) {
6278
                    BrVector3Negate(&p2, &p2);
6279
                }
6280
                BrMatrix34ApplyV(&p1, &p2, pM12);
6281
                BrMatrix34TApplyV(&pNorm_list[2 * n], &p1, pMo12);
6282
                BrMatrix34TApplyV(&pNorm_list[2 * n + 1], &p2, pMo21);
6283
                BrVector3Negate(&pNorm_list[2 * n + 1], &pNorm_list[2 * n + 1]);
6284
                n++;
6285
            } else if ((plane1 ^ plane2) == 4) {
6286
                if (pMax - 1 <= n) {
6287
                    return n;
6288
                }
6289
                GetBoundsEdge(&pPoint_list[2 * n], &edge, pB1, plane1, plane3, &p2, &hp1, &hp2, 0);
6290
                GetBoundsEdge(&pPoint_list[2 * n + 2], &edge, pB1, plane2, plane3, &p2, &hp1, &hp2, 0);
6291
                pPoint_list[2 * n + 1] = shp1;
6292
                pPoint_list[2 * n + 3] = shp2;
6293
                BrVector3Sub(&p1, &hp1, &hp2);
6294
                BrMatrix34ApplyV(&p2, &p1, pM12);
6295
                BrMatrix34ApplyV(&p1, &p2, pMo21);
6296
                BrVector3Cross(&p2, &edge, &p1);
6297
                BrVector3Normalise(&pNorm_list[2 * n], &p2);
6298
                GetPlaneNormal(&edge, plane3);
6299
                if (BrVector3Dot(&pNorm_list[2 * n], &edge) < 0.0f) {
6300
                    BrVector3Negate(&pNorm_list[2 * n], &pNorm_list[2 * n]);
6301
                }
6302
                BrMatrix34ApplyV(&pNorm_list[2 * n + 1], &pNorm_list[2 * n], pMo12);
6303
                BrVector3Negate(&pNorm_list[2 * n + 1], &pNorm_list[2 * n + 1]);
6304
                BrMatrix34ApplyV(&tp3, &pNorm_list[2 * n], pM12);
6305
                BrMatrix34ApplyV(&pNorm_list[2 * n], &tp3, pMo21);
6306
                pNorm_list[2 * n + 2] = pNorm_list[2 * n];
6307
                pNorm_list[2 * n + 3] = pNorm_list[2 * n + 1];
6308
                n += 2;
6309
            } else {
6310
                if (pMax - 1 <= n) {
6311
                    return n;
6312
                }
6313
                GetBoundsEdge(&pPoint_list[2 * n], &edge, pB1, plane1, plane3, &p2, &hp1, &hp2, 0);
6314
                GetBoundsEdge(&pPoint_list[2 * n + 2], &edge, pB1, plane2, plane3, &p2, &hp1, &hp2, 0);
6315
                BrMatrix34ApplyP(&pPoint_list[2 * n + 1], &hp1, pM12);
6316
                BrMatrix34ApplyP(&pPoint_list[2 * n + 3], &hp2, pM12);
6317
                GetPlaneNormal(&pNorm_list[2 * n], plane3);
6318
                BrMatrix34ApplyV(&pNorm_list[2 * n + 2], &pNorm_list[2 * n], pM1o1);
6319
                BrMatrix34ApplyV(&pNorm_list[2 * n + 1], &pNorm_list[2 * n + 2], pMo12);
6320
                pNorm_list[2 * n] = pNorm_list[2 * n + 2];
6321
                BrVector3Negate(&pNorm_list[2 * n + 1], &pNorm_list[2 * n + 1]);
6322
                pNorm_list[2 * n + 3] = pNorm_list[2 * n + 1];
6323
                n += 2;
6324
            }
6325
        }
6326
    }
6327
    return n;
6328
}
6329
 
6330
// IDA: int __usercall FacePointCarCarCollide@<EAX>(tCollision_info *car1@<EAX>, tCollision_info *car2@<EDX>, br_matrix34 *pMms@<EBX>, br_matrix34 *pMoms@<ECX>, br_matrix34 *pMsos, br_vector3 *pPoint_list, br_vector3 *pNorm_list, int pMax, int order)
6331
int FacePointCarCarCollide(tCollision_info* car1, tCollision_info* car2, br_matrix34* pMms, br_matrix34* pMoms, br_matrix34* pMsos, br_vector3* pPoint_list, br_vector3* pNorm_list, int pMax, int order) {
6332
    int k;
6333
    int i;
6334
    int j;
6335
    int l;
6336
    int plane;
6337
    br_vector3 a;
6338
    br_vector3 a1;
6339
    br_vector3 aa;
6340
    br_vector3 bb;
6341
    br_vector3 norm;
6342
    br_vector3 hp;
6343
    br_vector3 centre;
6344
    br_scalar dist;
6345
    br_bounds* pStat_box;
6346
    //br_bounds* pMove_box; // Pierre-Marie Baty -- unused variable
6347
    LOG_TRACE("(%p, %p, %p, %p, %p, %p, %p, %d, %d)", car1, car2, pMms, pMoms, pMsos, pPoint_list, pNorm_list, pMax, order);
6348
 
6349
    k = 0;
6350
    pStat_box = &car2->bounds[1];
6351
    BrVector3Add(&centre, &car2->bounds[1].max, &car2->bounds[1].min);
6352
    BrVector3InvScale(&centre, &centre, 2.0f);
6353
    for (i = 0; i < car2->extra_point_num + 8; i++) {
6354
        if (i >= 8) {
6355
            a = car2->extra_points[i - 8];
6356
        } else {
6357
            a.v[0] = ((i & 2) == 0) * pStat_box->min.v[0] + ((i & 2) >> 1) * pStat_box->max.v[0];
6358
            a.v[1] = ((i & 1) == 0) * pStat_box->min.v[1] + (i & 1) * pStat_box->max.v[1];
6359
            a.v[2] = ((i & 4) == 0) * pStat_box->max.v[2] + ((i & 4) >> 2) * pStat_box->min.v[2];
6360
        }
6361
        BrMatrix34ApplyP(&aa, &a, pMms);
6362
        BrMatrix34ApplyP(&bb, &a, pMoms);
6363
        BrVector3Sub(&aa, &aa, &bb);
6364
        dist = BrVector3Length(&aa);
6365
        if (dist >= 0.00001f) {
6366
            BrVector3Scale(&a1, &aa, (0.05f / WORLD_SCALE) / dist); // 0.0072463769 * 6.9 = 0.05
6367
            BrVector3Accumulate(&aa, &a1);
6368
            BrVector3Accumulate(&aa, &bb);
6369
            plane = LineBoxCollWithSphere(&bb, &aa, &car1->bounds[1], &hp);
6370
            if ((plane & 7) != 0) {
6371
                GetPlaneNormal(&norm, plane);
6372
 
6373
                j = 2 * k + order;
6374
                l = 2 * k + (order == 0);
6375
                BrMatrix34ApplyV(&pNorm_list[j], &norm, pMsos);
6376
                BrMatrix34TApplyV(&pNorm_list[l], &pNorm_list[j], pMoms);
6377
                BrVector3Negate(&pNorm_list[l], &pNorm_list[l]);
6378
                if ((pNorm_list[l].v[0] >= 0.0f) != (centre.v[0] <= a.v[0]) || (pNorm_list[l].v[1] >= 0.0f) != (centre.v[1] <= a.v[1]) || (pNorm_list[l].v[2] >= 0.0f) != (a.v[2] >= centre.v[2])
6379
                    || !TestOldMats(car1, car2, 0)) {
6380
                    pPoint_list[l] = a;
6381
                    pPoint_list[j] = hp;
6382
                    k++;
6383
                    if (pMax == k) {
6384
                        return k;
6385
                    }
6386
                }
6387
            }
6388
        }
6389
    }
6390
    return k;
6391
}
6392
 
6393
// IDA: void __usercall MungeCarsMass(tCollision_info *pCar@<EAX>, br_scalar pFactor)
6394
void MungeCarsMass(tCollision_info* pCar, br_scalar pFactor) {
6395
    LOG_TRACE("(%p, %f)", pCar, pFactor);
6396
 
6397
    pCar->M = pCar->M * pFactor;
6398
    BrVector3Scale(&pCar->I, &pCar->I, pFactor);
6399
}
6400
 
6401
// IDA: void __usercall ModifyCarsMass(tCollision_info *pCar_1@<EAX>, tCollision_info *pCar_2@<EDX>)
6402
void ModifyCarsMass(tCollision_info* pCar_1, tCollision_info* pCar_2) {
6403
    LOG_TRACE("(%p, %p)", pCar_1, pCar_2);
6404
 
6405
    if (pCar_1->driver > eDriver_non_car && ((tCar_spec*)pCar_1)->collision_mass_multiplier != 1.0f) {
6406
        MungeCarsMass(pCar_1, ((tCar_spec*)pCar_1)->collision_mass_multiplier);
6407
    }
6408
    if (pCar_2->driver > eDriver_non_car && ((tCar_spec*)pCar_2)->collision_mass_multiplier != 1.0f) {
6409
        MungeCarsMass(pCar_2, ((tCar_spec*)pCar_2)->collision_mass_multiplier);
6410
    }
6411
}
6412
 
6413
// IDA: void __usercall ResetCarsMass(tCollision_info *pCar_1@<EAX>, tCollision_info *pCar_2@<EDX>)
6414
void ResetCarsMass(tCollision_info* pCar_1, tCollision_info* pCar_2) {
6415
    LOG_TRACE("(%p, %p)", pCar_1, pCar_2);
6416
 
6417
    if (pCar_1->driver > eDriver_non_car && ((tCar_spec*)pCar_1)->collision_mass_multiplier != 1.0f) {
6418
        MungeCarsMass(pCar_1, 1.0f / ((tCar_spec*)pCar_1)->collision_mass_multiplier);
6419
    }
6420
    if (pCar_2->driver > eDriver_non_car && ((tCar_spec*)pCar_2)->collision_mass_multiplier != 1.0f) {
6421
        MungeCarsMass(pCar_2, 1.0f / ((tCar_spec*)pCar_2)->collision_mass_multiplier);
6422
    }
6423
}
6424
 
6425
// IDA: int __usercall DoCollide@<EAX>(tCollision_info *car1@<EAX>, tCollision_info *car2@<EDX>, br_vector3 *r@<EBX>, br_vector3 *n@<ECX>, int k, int pPass, br_matrix34 *mat1_to_mat2)
6426
int DoCollide(tCollision_info* car1, tCollision_info* car2, br_vector3* r, br_vector3* n, int k, int pPass, br_matrix34* mat1_to_mat2) {
6427
    br_matrix34* mat1;
6428
    br_matrix34* mat2;
6429
    br_matrix34* oldmat1;
6430
    br_matrix34* oldmat2;
6431
    br_matrix4 M;
6432
    br_vector3 tau1[8];
6433
    br_vector3 a;
6434
    br_vector3 norm;
6435
    br_vector3 f1;
6436
    br_vector3 f2;
6437
    br_vector3 pos1;
6438
    br_vector3 pos2;
6439
    br_vector3 max_friction;
6440
    br_vector3 tv;
6441
    br_vector3 tv2;
6442
    br_vector3* tau2;
6443
    br_vector3 torque1;
6444
    br_vector3 torque2;
6445
    br_scalar f[4];
6446
    br_scalar d[4];
6447
    br_scalar ts;
6448
    br_scalar tforce;
6449
    int i;
6450
    int j;
6451
    int car1_point;
6452
    int car2_point;
6453
    int plane;
6454
    int move_car1;
6455
    int move_car2;
6456
    //br_vector3 a2; // Pierre-Marie Baty -- unused variable
6457
    br_vector3 f12;
6458
    br_vector3 f22;
6459
    br_vector3 point_vel1;
6460
    br_vector3 point_vel2;
6461
    //br_scalar fudge_multiplier; // Pierre-Marie Baty -- unused variable
6462
    br_scalar factor;
6463
    int need_to_fudge;
6464
    LOG_TRACE("(%p, %p, %p, %p, %d, %d, %p)", car1, car2, r, n, k, pPass, mat1_to_mat2);
6465
 
6466
    mat1 = &car1->car_master_actor->t.t.mat;
6467
    mat2 = &car2->car_master_actor->t.t.mat;
6468
    oldmat1 = &car1->oldmat;
6469
    oldmat2 = &car2->oldmat;
6470
    tau2 = &tau1[4];
6471
    move_car1 = !car1->infinite_mass && car1->min_torque_squared == 0.0f;
6472
    move_car2 = !car2->infinite_mass && car2->min_torque_squared == 0.0f;
6473
    if (k > 4) {
6474
        k = 4;
6475
    }
6476
    BrMatrix34Copy(mat1, oldmat1);
6477
    BrMatrix34Copy(mat2, oldmat2);
6478
    BrVector3Copy(&car1->omega, &car1->oldomega);
6479
    BrVector3Copy(&car2->omega, &car2->oldomega);
6480
    BrMatrix34TApplyV(&car1->velocity_car_space, &car1->v, mat1);
6481
    BrMatrix34TApplyV(&car2->velocity_car_space, &car2->v, mat2);
6482
    need_to_fudge = 1;
6483
    for (i = 0; i < k; ++i) {
6484
        BrVector3Cross(&tau1[i], &r[2 * i], &n[2 * i]);
6485
        BrVector3Cross(&tau2[i], &r[2 * i + 1], &n[2 * i + 1]);
6486
        Vector3Div(&tau1[i], &tau1[i], &car1->I);
6487
        Vector3Div(&tau2[i], &tau2[i], &car2->I);
6488
        BrVector3Cross(&tv, &car1->omega, &r[2 * i]);
6489
        BrVector3Accumulate(&tv, &car1->velocity_car_space);
6490
        d[i] = -BrVector3Dot(&n[2 * i], &tv);
6491
        BrVector3Cross(&tv, &car2->omega, &r[2 * i + 1]);
6492
        BrVector3Accumulate(&tv, &car2->velocity_car_space);
6493
        d[i] -= BrVector3Dot(&n[2 * i + 1], &tv);
6494
        if (d[i] > 0.0f) {
6495
            need_to_fudge = 0;
6496
        }
6497
    }
6498
    if (need_to_fudge) {
6499
        d[0] = 0.5f;
6500
    }
6501
    factor = 0.0f;
6502
    if (move_car1) {
6503
        factor = car1->M + factor;
6504
    }
6505
    if (move_car2) {
6506
        factor = car2->M + factor;
6507
    }
6508
    for (i = 0; i < k; i++) {
6509
        for (j = 0; j < k; j++) {
6510
            if (move_car1) {
6511
                BrVector3Cross(&tv, &tau1[j], &r[2 * i]);
6512
                BrVector3InvScale(&norm, &n[2 * j], car1->M);
6513
                BrVector3Accumulate(&tv, &norm);
6514
                M.m[i][j] = BrVector3Dot(&n[2 * i], &tv);
6515
            } else {
6516
                M.m[i][j] = 0.0f;
6517
            }
6518
            if (move_car2) {
6519
                BrVector3Cross(&tv, &tau2[j], &r[2 * i + 1]);
6520
                BrVector3InvScale(&norm, &n[2 * j + 1], car2->M);
6521
                BrVector3Accumulate(&tv, &norm);
6522
                M.m[i][j] += BrVector3Dot(&n[2 * i + 1], &tv);
6523
            }
6524
            M.m[i][j] *= factor;
6525
        }
6526
    }
6527
    switch (k) {
6528
    case 1:
6529
        ts = SinglePointColl(f, &M, d);
6530
        break;
6531
    case 2:
6532
        ts = TwoPointCollB(f, &M, d, tau1, n);
6533
        break;
6534
    case 3:
6535
        d[3] = 0.f;
6536
        ts = ThreePointCollRecB(f, &M, d, tau1, n);
6537
        break;
6538
    case 4:
6539
        ts = FourPointCollB(f, &M, d, tau1, n);
6540
        break;
6541
    default:
6542
        ts = 0;
6543
        break;
6544
    }
6545
    if (k > 3) {
6546
        k = 3;
6547
    }
6548
    if (fabsf(ts) <= 0.000001f) {
6549
        return 0;
6550
    }
6551
    BrVector3SetFloat(&f1, 0.0f, 0.0f, 0.0f);
6552
    BrVector3SetFloat(&f2, 0.0f, 0.0f, 0.0f);
6553
    BrVector3SetFloat(&pos1, 0.0f, 0.0f, 0.0f);
6554
    BrVector3SetFloat(&pos2, 0.0f, 0.0f, 0.0f);
6555
    BrVector3SetFloat(&torque1, 0.0f, 0.0f, 0.0f);
6556
    BrVector3SetFloat(&torque2, 0.0f, 0.0f, 0.0f);
6557
    tforce = 0.0f;
6558
    car1_point = -1;
6559
    car2_point = -1;
6560
    for (i = 0; i < k; i++) {
6561
        f[i] = f[i] * factor;
6562
        if (f[i] == 0.0f && k != 0) {
6563
            break;
6564
        }
6565
        if (f[i] < 0.001f) {
6566
            f[i] = 0.001f;
6567
        }
6568
        if (f[i] > 10.0f) {
6569
            ts = 0.0f;
6570
        }
6571
        f[i] += 0.1f;
6572
        BrVector3Scale(&tau1[i], &tau1[i], f[i]);
6573
        BrVector3Scale(&tau2[i], &tau2[i], f[i]);
6574
        BrVector3Accumulate(&torque1, &tau1[i]);
6575
        BrVector3Accumulate(&torque2, &tau2[i]);
6576
        if (!pPass && Vector3IsZero(&n[2 * i])) {
6577
            car2_point = i;
6578
        } else if (!pPass && Vector3IsZero(&n[2 * i + 1])) {
6579
            car1_point = i;
6580
        } else {
6581
            ts = f[i] / car1->M;
6582
            BrVector3Scale(&tv2, &n[2 * i], ts);
6583
            BrVector3Accumulate(&f1, &tv2);
6584
            ts = f[i] / car2->M;
6585
            BrVector3Scale(&tv2, &n[2 * i + 1], ts);
6586
            BrVector3Accumulate(&f2, &tv2);
6587
            BrVector3Scale(&tv2, &r[2 * i], f[i]);
6588
            BrVector3Accumulate(&pos1, &tv2);
6589
            BrVector3Scale(&tv2, &r[2 * i + 1], f[i]);
6590
            BrVector3Accumulate(&pos2, &tv2);
6591
            tforce += f[i];
6592
        }
6593
    }
6594
    if (car1->min_torque_squared != 0.0f && !car1->infinite_mass && BrVector3LengthSquared(&torque1) > car1->min_torque_squared) {
6595
        BrVector3Scale(&car1->omega, &car1->omega, gDt);
6596
        car1->omega.v[0] += torque1.v[0] * 0.04f;
6597
        car1->omega.v[2] += torque1.v[2] * 0.04f;
6598
        if (BrVector3LengthSquared(&car1->omega) > car1->break_off_radians_squared) {
6599
            car1->min_torque_squared = 0.0f;
6600
            return 1;
6601
        }
6602
        BrVector3InvScale(&car1->omega, &car1->omega, gDt);
6603
    }
6604
    if (car2->min_torque_squared != 0.0f && !car2->infinite_mass && BrVector3LengthSquared(&torque2) > car2->min_torque_squared) {
6605
        BrVector3Scale(&car2->omega, &car2->omega, gDt);
6606
        car2->omega.v[0] += torque2.v[0] * 0.04f;
6607
        car2->omega.v[2] += torque2.v[2] * 0.04f;
6608
        if (BrVector3LengthSquared(&car2->omega) > car2->break_off_radians_squared) {
6609
            car2->min_torque_squared = 0.0f;
6610
            return 1;
6611
        }
6612
        BrVector3InvScale(&car2->omega, &car2->omega, gDt);
6613
    }
6614
    if (move_car1) {
6615
        BrVector3Accumulate(&car1->omega, &torque1);
6616
    }
6617
    if (move_car2) {
6618
        BrVector3Accumulate(&car2->omega, &torque2);
6619
    }
6620
    BrVector3InvScale(&pos1, &pos1, tforce);
6621
    BrVector3InvScale(&pos2, &pos2, tforce);
6622
    if (pPass == 0) {
6623
        if (car1_point >= 0 && move_car1) {
6624
            f[car1_point] = f[car1_point] / car1->M;
6625
            BrVector3Scale(&n[2 * car1_point], &n[2 * car1_point], f[car1_point]);
6626
            BrVector3Cross(&tv2, &car1->oldomega, &r[2 * car1_point]);
6627
            BrVector3Accumulate(&tv2, &car1->velocity_car_space);
6628
            ts = BrVector3Length(&tv2);
6629
            if (ts > 0.0001f && (car1->driver <= eDriver_non_car || !CAR(car1)->wall_climber_mode)) {
6630
                AddFriction(car1, &tv2, &n[2 * car1_point], &r[2 * car1_point], f[car1_point], &max_friction);
6631
                BrVector3Accumulate(&n[2 * car1_point], &max_friction);
6632
            }
6633
            BrMatrix34ApplyV(&tv, &n[2 * car1_point], mat1);
6634
            BrVector3Accumulate(&car1->v, &tv);
6635
        }
6636
        if (car2_point >= 0 && move_car2) {
6637
            f[car2_point] = f[car2_point] / car2->M;
6638
            BrVector3Scale(&n[2 * car2_point + 1], &n[2 * car2_point + 1], f[car2_point]);
6639
            BrVector3Cross(&tv2, &car2->oldomega, &r[2 * car2_point + 1]);
6640
            BrVector3Accumulate(&tv2, &car2->velocity_car_space);
6641
            ts = BrVector3Length(&tv2);
6642
 
6643
            if (ts > 0.0001f && (car1->driver <= eDriver_non_car || !(CAR(car1)->wall_climber_mode))) {
6644
                AddFriction(car2, &tv2, &n[2 * car2_point + 1], &r[2 * car2_point + 1], f[car2_point], &max_friction);
6645
                BrVector3Accumulate(&n[2 * car2_point + 1], &max_friction);
6646
            }
6647
            BrMatrix34ApplyV(&tv, &n[2 * car2_point + 1], mat2);
6648
            BrVector3Accumulate(&car2->v, &tv);
6649
        }
6650
        if (tforce != 0.0f) {
6651
            BrVector3Cross(&point_vel1, &car1->oldomega, &pos1);
6652
            BrVector3Sub(&a, &car1->v, &car2->v);
6653
            BrMatrix34TApplyV(&tv2, &a, mat1);
6654
            BrVector3Accumulate(&point_vel1, &tv2);
6655
            BrVector3Cross(&point_vel2, &car2->oldomega, &pos2);
6656
            AddFrictionCarToCar(car1, car2, &point_vel1, &point_vel2, &f1, &pos1, &pos2, tforce, &max_friction);
6657
            if (TestForNan(max_friction.v) || TestForNan(&max_friction.v[1]) || TestForNan(&max_friction.v[2])) {
6658
                BrVector3SetFloat(&max_friction, 0.0f, 0.0f, 0.0f);
6659
            }
6660
            BrVector3InvScale(&tv2, &max_friction, car1->M);
6661
            BrVector3Accumulate(&f1, &tv2);
6662
            BrMatrix34ApplyV(&tv2, &max_friction, mat1);
6663
            BrMatrix34TApplyV(&max_friction, &tv2, mat2);
6664
            BrVector3InvScale(&tv2, &max_friction, car2->M);
6665
            BrVector3Accumulate(&f2, &tv2);
6666
        }
6667
    }
6668
    if (tforce == 0.0f) {
6669
        return 0;
6670
    }
6671
    BrMatrix34ApplyV(&tv, &f1, mat1);
6672
    if (move_car1) {
6673
        BrVector3Accumulate(&car1->v, &tv);
6674
    }
6675
    CrushAndDamageCar(CAR(car1), &pos1, &f1, CAR(car2));
6676
    if ((car1->infinite_mass & 0x100) != 0) {
6677
        BrVector3Sub(&tv2, &car1->cmpos, &pos1);
6678
        BrVector3Accumulate(&tv2, &car1->cmpos);
6679
        ts = BrVector3Length(&f1);
6680
        if (ts > 0.0001f) {
6681
            ts = 5.0f / ts;
6682
            BrVector3Scale(&a, &f1, ts);
6683
            BrVector3Accumulate(&tv2, &a);
6684
            plane = LineBoxColl(&tv2, &pos1, &car1->bounds[1], &a);
6685
            if (plane) {
6686
                BrVector3Negate(&f12, &f1);
6687
                CrushAndDamageCar(CAR(car1), &a, &f12, CAR(car2));
6688
            }
6689
        }
6690
    }
6691
    BrMatrix34ApplyV(&tv, &f2, mat2);
6692
    if (move_car2) {
6693
        BrVector3Accumulate(&car2->v, &tv);
6694
    }
6695
    CrushAndDamageCar(CAR(car2), &pos2, &f2, CAR(car1));
6696
    if ((car2->infinite_mass & 0x100) != 0) {
6697
        BrVector3Sub(&tv2, &car2->cmpos, &pos2);
6698
        BrVector3Accumulate(&tv2, &car2->cmpos);
6699
        ts = BrVector3Length(&f2);
6700
        if (ts > 0.0001f) {
6701
            ts = 5.0f / ts;
6702
            BrVector3Scale(&a, &f2, ts);
6703
            BrVector3Accumulate(&tv2, &a);
6704
            plane = LineBoxColl(&tv2, &pos2, &car2->bounds[1], &a);
6705
            if (plane) {
6706
                BrVector3Negate(&f22, &f2);
6707
                CrushAndDamageCar(CAR(car2), &a, &f22, CAR(car1));
6708
            }
6709
        }
6710
    }
6711
    BrMatrix34ApplyP(&tv2, &pos1, mat1);
6712
    BrVector3InvScale(&tv2, &tv2, WORLD_SCALE);
6713
    BrVector3Scale(&f1, &f1, 5.0f);
6714
    CrashNoise(&f1, &tv2, 0);
6715
    BrVector3Add(&a, &car2->v, &car1->v);
6716
    BrVector3Scale(&a, &a, 0.25f / WORLD_SCALE);
6717
    BrVector3Scale(&tv, &tv, car2->M * 3.0f);
6718
    CreateSparkShower(&tv2, &a, &tv, CAR(car1), CAR(car2));
6719
    return 0;
6720
}
6721
 
6722
// IDA: br_scalar __usercall TwoPointCollB@<ST0>(br_scalar *f@<EAX>, br_matrix4 *m@<EDX>, br_scalar *d@<EBX>, br_vector3 *tau@<ECX>, br_vector3 *n)
6723
br_scalar TwoPointCollB(br_scalar* f, br_matrix4* m, br_scalar* d, br_vector3* tau, br_vector3* n) {
6724
    br_scalar ts;
6725
    LOG_TRACE("(%p, %p, %p, %p, %p)", f, m, d, tau, n);
6726
 
6727
    ts = m->m[1][1] * m->m[0][0] - m->m[0][1] * m->m[1][0];
6728
    if (fabsf(ts) > 0.000001f) {
6729
        f[0] = (m->m[1][1] * d[0] - m->m[0][1] * d[1]) / ts;
6730
        f[1] = (m->m[1][0] * d[0] - m->m[0][0] * d[1]) / -ts;
6731
    }
6732
    if (f[1] < 0.0f) {
6733
        ts = SinglePointColl(f, m, d);
6734
        f[1] = 0.f;
6735
    } else if (f[0] < 0.f) {
6736
        m->m[0][0] = m->m[1][1];
6737
        BrVector3Copy(&tau[0], &tau[1]);
6738
        BrVector3Copy(&tau[4], &tau[5]);
6739
        BrVector3Copy(&n[0], &n[2]);
6740
        BrVector3Copy(&n[1], &n[3]);
6741
        d[0] = d[1];
6742
        ts = SinglePointColl(f, m, d);
6743
        f[1] = 0.0f;
6744
    }
6745
    return ts;
6746
}
6747
 
6748
// IDA: br_scalar __usercall ThreePointCollRecB@<ST0>(br_scalar *f@<EAX>, br_matrix4 *m@<EDX>, br_scalar *d@<EBX>, br_vector3 *tau@<ECX>, br_vector3 *n)
6749
br_scalar ThreePointCollRecB(br_scalar* f, br_matrix4* m, br_scalar* d, br_vector3* tau, br_vector3* n) {
6750
    int i;
6751
    int j;
6752
    br_scalar ts;
6753
    LOG_TRACE("(%p, %p, %p, %p, %p)", f, m, d, tau, n);
6754
 
6755
    ts = ThreePointColl(f, m, d);
6756
    if (f[0] >= 0.0f && f[1] >= 0.0f && f[2] >= 0.0f) {
6757
        return ts;
6758
    }
6759
    if (f[2] < 0.f) {
6760
        i = 0;
6761
        j = 1;
6762
    } else if (f[1] < 0.f) {
6763
        i = 0;
6764
        j = 2;
6765
    } else if (f[0] < 0.f) {
6766
        i = 1;
6767
        j = 2;
6768
    } else {
6769
        return 0.0f;
6770
    }
6771
    m->m[0][0] = ((br_scalar*)(m->m))[5 * i];
6772
    m->m[1][0] = m->m[j][i];
6773
    m->m[0][1] = m->m[i][j];
6774
    m->m[1][1] = ((br_scalar*)(m->m))[5 * j];
6775
    BrVector3Copy(&tau[0], &tau[i]);
6776
    BrVector3Copy(&tau[1], &tau[j]);
6777
    BrVector3Copy(&tau[4], &tau[i + 4]);
6778
    BrVector3Copy(&tau[5], &tau[j + 4]);
6779
    BrVector3Copy(&n[0], &n[2 * i]);
6780
    BrVector3Copy(&n[2], &n[2 * j]);
6781
    BrVector3Copy(&n[1], &n[2 * i + 1]);
6782
    BrVector3Copy(&n[3], &n[2 * j + 1]);
6783
    d[0] = d[i];
6784
    d[1] = d[j];
6785
    ts = TwoPointCollB(f, m, d, tau, n);
6786
    f[2] = 0.0;
6787
    return ts;
6788
}
6789
 
6790
// IDA: br_scalar __usercall FourPointCollB@<ST0>(br_scalar *f@<EAX>, br_matrix4 *m@<EDX>, br_scalar *d@<EBX>, br_vector3 *tau@<ECX>, br_vector3 *n)
6791
br_scalar FourPointCollB(br_scalar* f, br_matrix4* m, br_scalar* d, br_vector3* tau, br_vector3* n) {
6792
    int i;
6793
    int j;
6794
    int l;
6795
    br_scalar ts;
6796
    LOG_TRACE("(%p, %p, %p, %p, %p)", f, m, d, tau, n);
6797
 
6798
    ts = ThreePointColl(f, m, d);
6799
    if (f[0] >= 0.0f && f[1] >= 0.0f && f[2] >= 0.0f) {
6800
        return ts;
6801
    }
6802
    if (f[0] < 0.0f) {
6803
        l = 0;
6804
    } else if (f[1] < 0.0f) {
6805
        l = 1;
6806
    } else {
6807
        l = 2;
6808
    }
6809
    for (i = l; i < 3; i++) {
6810
        for (j = 0; j < 4; j++) {
6811
            m->m[i][j] = m->m[i + 1][j];
6812
        }
6813
        d[i] = d[i + 1];
6814
        tau[i] = tau[i + 1];
6815
        tau[i + 4] = tau[i + 5];
6816
        n[2 * i] = n[2 * i + 2];
6817
        n[2 * i + 1] = n[2 * i + 3];
6818
        d[i] = d[i + 1];
6819
    }
6820
    for (i = l; i < 3; i++) {
6821
        for (j = 0; j < 3; j++) {
6822
            m->m[j][i] = m->m[j][i + 1];
6823
        }
6824
    }
6825
    return ThreePointCollRecB(f, m, d, tau, n);
6826
}
6827
 
6828
// IDA: int __usercall TestForNan@<EAX>(float *f@<EAX>)
6829
int TestForNan(float* f) {
6830
    //tU32 i; // Pierre-Marie Baty -- unused variable
6831
    LOG_TRACE("(%p)", f);
6832
    // i = *f;
6833
    // LOG_DEBUG("i %x", i);
6834
    return isnan(*f);
6835
    // return (~i & 0x7F800000) == 0;
6836
}
6837
 
6838
// IDA: void __cdecl CheckCameraHither()
6839
void CheckCameraHither(void) {
6840
    br_camera* cam;
6841
    static int old_hither;
6842
    LOG_TRACE("()");
6843
 
6844
    cam = (br_camera*)gCamera->type_data;
6845
    if (TestForNan(&cam->hither_z)) {
6846
        cam->hither_z = (float)old_hither;
6847
    }
6848
    old_hither = (int)cam->hither_z;
6849
}
6850
 
6851
// IDA: void __usercall SetCarSuspGiveAndHeight(tCar_spec *pCar@<EAX>, br_scalar pFront_give_factor, br_scalar pRear_give_factor, br_scalar pDamping_factor, br_scalar pExtra_front_height, br_scalar pExtra_rear_height)
6852
void SetCarSuspGiveAndHeight(tCar_spec* pCar, br_scalar pFront_give_factor, br_scalar pRear_give_factor, br_scalar pDamping_factor, br_scalar pExtra_front_height, br_scalar pExtra_rear_height) {
6853
    br_scalar front_give;
6854
    br_scalar rear_give;
6855
    br_scalar damping;
6856
    br_scalar ratio;
6857
    //int i; // Pierre-Marie Baty -- unused variable
6858
    LOG_TRACE("(%p, %f, %f, %f, %f, %f)", pCar, pFront_give_factor, pRear_give_factor, pDamping_factor, pExtra_front_height, pExtra_rear_height);
6859
 
6860
#define UNK_SUSPENION_FACTOR 5.0f
6861
 
6862
    front_give = pCar->susp_give[1] * pFront_give_factor * WORLD_SCALE;
6863
    rear_give = pCar->susp_give[0] * pRear_give_factor * WORLD_SCALE;
6864
    damping = pCar->damping * pDamping_factor;
6865
    ratio = fabsf((pCar->wpos[0].v[2] - pCar->cmpos.v[2]) / (pCar->wpos[2].v[2] - pCar->cmpos.v[2]));
6866
    pCar->sk[0] = pCar->M / (ratio + 1.0f) * UNK_SUSPENION_FACTOR / rear_give;
6867
    pCar->sb[0] = pCar->M / (ratio + 1.0f) * sqrtf(UNK_SUSPENION_FACTOR) / sqrt(rear_give);
6868
    ratio = 1.0f / ratio;
6869
    pCar->sk[1] = pCar->M / (ratio + 1.0f) * UNK_SUSPENION_FACTOR / front_give;
6870
    pCar->sb[1] = pCar->M / (ratio + 1.0f) * sqrtf(UNK_SUSPENION_FACTOR) / sqrt(front_give);
6871
 
6872
    pCar->sb[0] *= damping;
6873
    pCar->sb[1] *= damping;
6874
    pCar->susp_height[0] = pCar->ride_height + rear_give + pExtra_rear_height;
6875
    pCar->susp_height[1] = pCar->ride_height + front_give + pExtra_front_height;
6876
 
6877
    pCar->bounds[0].min.v[1] = -MAX(rear_give, front_give) + -MAX(pExtra_rear_height, pExtra_front_height);
6878
    pCar->bounds[0].min.v[1] /= WORLD_SCALE;
6879
 
6880
#undef UNK_SUSPENION_FACTOR
6881
}
6882
 
6883
// IDA: int __usercall TestForCarInSensiblePlace@<EAX>(tCar_spec *car@<EAX>)
6884
int TestForCarInSensiblePlace(tCar_spec* car) {
6885
    //br_bounds bnds; // Pierre-Marie Baty -- unused variable
6886
    //br_matrix34 mat; // Pierre-Marie Baty -- unused variable
6887
    br_matrix34* mat1;
6888
    br_matrix34* mat2;
6889
    int i;
6890
    //int j; // Pierre-Marie Baty -- unused variable
6891
    int k;
6892
    tCollision_info* c2;
6893
    tCollision_info* car_info;
6894
    br_vector3 sep;
6895
    br_vector3 tv;
6896
    br_vector3 tv2;
6897
    LOG_TRACE("(%p)", car);
6898
 
6899
    car_info = (tCollision_info*)car;
6900
    if (!gProgram_state.racing) {
6901
        return 1;
6902
    }
6903
    mat1 = &car_info->car_master_actor->t.t.mat;
6904
    if (!gDoing_physics) {
6905
        BrVector3Scale((br_vector3*)mat1->m[3], (br_vector3*)mat1->m[3], WORLD_SCALE);
6906
    }
6907
    GetFacesInBox(car_info);
6908
    BrMatrix34ApplyP(&car_info->pos, &car_info->cmpos, mat1);
6909
    BrVector3InvScale(&car_info->pos, &car_info->pos, WORLD_SCALE);
6910
    k = CollCheck(car_info, -2.f);
6911
    if (!k) {
6912
        if (gNum_active_non_cars + gNum_active_cars != gNum_cars_and_non_cars) {
6913
            GetNonCars();
6914
        }
6915
        for (i = 0; i < gNum_cars_and_non_cars; i++) {
6916
            c2 = (tCollision_info*)gActive_car_list[i];
6917
            if (car_info != c2) {
6918
                mat2 = &c2->car_master_actor->t.t.mat;
6919
                BrVector3Scale((br_vector3*)mat2->m[3], (br_vector3*)mat2->m[3], WORLD_SCALE);
6920
                BrVector3Sub(&sep, (br_vector3*)mat1->m[3], (br_vector3*)mat2->m[3]);
6921
                if (BrVector3LengthSquared(&sep) <= 100.0) {
6922
                    k += TestOldMats(car_info, c2, 0);
6923
                    k += TestOldMats(c2, car_info, 0);
6924
                }
6925
                if (k != 0) {
6926
                    BrMatrix34ApplyP(&tv, &car_info->cmpos, mat1);
6927
                    BrMatrix34ApplyP(&tv2, &c2->cmpos, mat2);
6928
                    BrVector3Sub(&tv, &tv2, &tv);
6929
                    BrMatrix34TApplyV(&car_info->old_point, &tv, mat1);
6930
                    BrVector3Normalise(&car_info->old_norm, &car_info->old_point);
6931
                    BrVector3Negate(&car_info->old_norm, &car_info->old_norm);
6932
                }
6933
                BrVector3InvScale((br_vector3*)mat2->m[3], (br_vector3*)mat2->m[3], WORLD_SCALE);
6934
                if (k != 0) {
6935
                    break;
6936
                }
6937
            }
6938
        }
6939
    }
6940
    if (!gDoing_physics) {
6941
        BrVector3InvScale((br_vector3*)mat1->m[3], (br_vector3*)mat1->m[3], WORLD_SCALE);
6942
    }
6943
    if (k != 0) {
6944
        return 0;
6945
    } else {
6946
        return -1;
6947
    }
6948
}
6949
 
6950
// IDA: int __usercall TestOldMats@<EAX>(tCollision_info *c1@<EAX>, tCollision_info *c2@<EDX>, int newmats@<EBX>)
6951
int TestOldMats(tCollision_info* c1, tCollision_info* c2, int newmats) {
6952
    br_vector3 p1;
6953
    br_vector3 p2;
6954
    br_vector3 tp1;
6955
    //br_vector3 tp2; // Pierre-Marie Baty -- unused variable
6956
    //br_vector3 tp3; // Pierre-Marie Baty -- unused variable
6957
    br_vector3 hp1;
6958
    //br_vector3 hp2; // Pierre-Marie Baty -- unused variable
6959
    //br_vector3 hp3; // Pierre-Marie Baty -- unused variable
6960
    //br_vector3 shp1; // Pierre-Marie Baty -- unused variable
6961
    //br_vector3 shp2; // Pierre-Marie Baty -- unused variable
6962
    br_vector3 edge;
6963
    //int plane1; // Pierre-Marie Baty -- unused variable
6964
    //int plane2; // Pierre-Marie Baty -- unused variable
6965
    //int plane3; // Pierre-Marie Baty -- unused variable
6966
    //br_scalar ts; // Pierre-Marie Baty -- unused variable
6967
    int i;
6968
    int j;
6969
    int n;
6970
    br_bounds* b1;
6971
    br_bounds* b2;
6972
    br_matrix34 invmat1;
6973
    br_matrix34 mat21;
6974
    LOG_TRACE("(%p, %p, %d)", c1, c2, newmats);
6975
 
6976
    n = 0;
6977
    b1 = &c1->bounds[1];
6978
    b2 = &c2->bounds[1];
6979
    if (newmats) {
6980
        BrMatrix34LPInverse(&invmat1, &c1->car_master_actor->t.t.mat);
6981
        BrMatrix34Mul(&mat21, &c2->car_master_actor->t.t.mat, &invmat1);
6982
    } else {
6983
        BrMatrix34LPInverse(&invmat1, &c1->oldmat);
6984
        BrMatrix34Mul(&mat21, &c2->oldmat, &invmat1);
6985
    }
6986
    for (i = 0; i < 4; i++) {
6987
        if (i == 3) {
6988
            BrVector3Copy(&edge, &b2->min);
6989
        } else {
6990
            BrVector3Copy(&edge, &b2->max);
6991
            edge.v[i] = b2->min.v[i];
6992
        }
6993
        for (j = 0; j < 3; j++) {
6994
            BrVector3Copy(&tp1, &edge);
6995
            if (b2->max.v[j] == tp1.v[j]) {
6996
                tp1.v[j] = b2->min.v[j];
6997
            } else {
6998
                tp1.v[j] = b2->max.v[j];
6999
            }
7000
            BrMatrix34ApplyP(&p1, &edge, &mat21);
7001
            BrMatrix34ApplyP(&p2, &tp1, &mat21);
7002
            if (LineBoxColl(&p1, &p2, b1, &hp1)) {
7003
                n++;
7004
            }
7005
        }
7006
    }
7007
    return n;
7008
}
7009
 
7010
// IDA: int __usercall PullActorFromWorld@<EAX>(br_actor *pActor@<EAX>)
7011
int PullActorFromWorld(br_actor* pActor) {
7012
    LOG_TRACE("(%p)", pActor);
7013
 
7014
    if (gDoing_physics) {
7015
        return DoPullActorFromWorld(pActor);
7016
    }
7017
    return 0;
7018
}
7019
 
7020
// IDA: int __usercall DoPullActorFromWorld@<EAX>(br_actor *pActor@<EAX>)
7021
int DoPullActorFromWorld(br_actor* pActor) {
7022
    int num;
7023
    int i;
7024
    tCollision_info* c;
7025
    tNon_car_spec* non_car;
7026
    LOG_TRACE("(%p)", pActor);
7027
 
7028
    non_car = NULL;
7029
    num = 10 * (pActor->identifier[1] - '0') + 1 * (pActor->identifier[2] - '0');
7030
    if (gNon_car_spec_list[num]) {
7031
        non_car = &gProgram_state.non_cars[gNon_car_spec_list[num] + 4];
7032
    }
7033
    if (non_car && non_car->collision_info.driver == eDriver_non_car) {
7034
        non_car = gProgram_state.non_cars;
7035
        for (i = 0; i < NONCAR_UNUSED_SLOTS; i++) {
7036
            if (non_car->collision_info.driver == eDriver_non_car_unused_slot) {
7037
                break;
7038
            }
7039
            non_car++;
7040
        }
7041
        if (i == NONCAR_UNUSED_SLOTS) {
7042
            non_car = NULL;
7043
        } else {
7044
            memcpy(non_car, &gProgram_state.non_cars[gNon_car_spec_list[num] + NONCAR_UNUSED_SLOTS - 1], sizeof(tNon_car_spec));
7045
        }
7046
    }
7047
    if (non_car != NULL) {
7048
        pActor->type_data = non_car;
7049
        c = &non_car->collision_info;
7050
        c->driver = eDriver_non_car;
7051
        c->doing_nothing_flag = 1;
7052
        BrActorRemove(pActor);
7053
        BrActorAdd(gNon_track_actor, pActor);
7054
        c->car_master_actor = pActor;
7055
        c->car_ID = 100 * (pActor->identifier[5] - '0') + 10 * (pActor->identifier[6] - '0') + 1 * (pActor->identifier[7] - '0');
7056
        gActive_non_car_list[gNum_active_non_cars] = non_car;
7057
        gNum_active_non_cars++;
7058
        gActive_car_list[gNum_cars_and_non_cars] = (tCar_spec*)non_car;
7059
        gNum_cars_and_non_cars++;
7060
        GetNewBoundingBox(&c->bounds_world_space, c->bounds, &pActor->t.t.mat);
7061
        non_car->collision_info.bounds_ws_type = eBounds_ws;
7062
        InitialiseNonCar(non_car);
7063
        ResetCarSpecialVolume((tCollision_info*)non_car);
7064
        if (gDoing_physics) {
7065
            BrVector3Scale((br_vector3*)&pActor->t.t.mat.m[3][0], (br_vector3*)&pActor->t.t.mat.m[3][0], WORLD_SCALE);
7066
        }
7067
        BrMatrix34Copy(&c->oldmat, &pActor->t.t.mat);
7068
        if (!gDoing_physics) {
7069
            BrVector3Scale((br_vector3*)&c->oldmat.m[3][0], (br_vector3*)&c->oldmat.m[3][0], WORLD_SCALE);
7070
        }
7071
        PipeSingleNonCar((tCollision_info*)non_car);
7072
        return 1;
7073
    } else {
7074
        pActor->identifier[1] = 'x';
7075
        return 0;
7076
    }
7077
}
7078
 
7079
// IDA: void __usercall CheckForDeAttachmentOfNonCars(tU32 pTime@<EAX>)
7080
void CheckForDeAttachmentOfNonCars(tU32 pTime) {
7081
    static tU32 total_time;
7082
    br_bounds bnds;
7083
    int i;
7084
    int j;
7085
    int last_free_slot;
7086
    int drop;
7087
    tCollision_info* c;
7088
    tCollision_info* c2;
7089
    br_actor* actor;
7090
    tU8 cx;
7091
    tU8 cz;
7092
    tTrack_spec* track_spec;
7093
    br_matrix34 mat;
7094
    LOG_TRACE("(%d)", pTime);
7095
 
7096
    if (gNum_active_non_cars == 0) {
7097
        return;
7098
    }
7099
 
7100
    last_free_slot = 0;
7101
    track_spec = &gProgram_state.track_spec;
7102
 
7103
    StartPipingSession(ePipe_chunk_non_car);
7104
    for (i = 0; i < gNum_active_non_cars; i++) {
7105
        if (!gActive_non_car_list[i]->collision_info.doing_nothing_flag) {
7106
            AddNonCarToPipingSession(gActive_non_car_list[i]->collision_info.car_ID, gActive_non_car_list[i]->collision_info.car_master_actor);
7107
        }
7108
    }
7109
    EndPipingSession();
7110
 
7111
    total_time += pTime;
7112
    if (total_time < 1000) {
7113
        return;
7114
    }
7115
    total_time = 0;
7116
    for (i = 0; i < gNum_active_non_cars; i++) {
7117
        c = &gActive_non_car_list[i]->collision_info;
7118
        if (c->car_master_actor->t.t.translate.t.v[1] < gMin_world_y) {
7119
            c->doing_nothing_flag = 1;
7120
        }
7121
        if (TestForNan(&c->car_master_actor->t.t.mat.m[3][1])) {
7122
            BrVector3Set(&c->omega, 0.0f, 0.0f, 0.0f);
7123
            BrMatrix34Identity(&c->car_master_actor->t.t.mat);
7124
            BrVector3Set(&c->car_master_actor->t.t.translate.t, 2000.f, 0.f, 0.f);
7125
            c->doing_nothing_flag = 1;
7126
        }
7127
        actor = c->car_master_actor;
7128
        gActive_non_car_list[last_free_slot] = gActive_non_car_list[i];
7129
        if (c->doing_nothing_flag) {
7130
            drop = 1;
7131
            for (j = 0; j < gNum_cars_and_non_cars; j++) {
7132
                c2 = (tCollision_info*)gActive_car_list[j];
7133
                if (c2 != c && !c2->doing_nothing_flag) {
7134
                    BrMatrix34Mul(&mat, &actor->t.t.mat, &c2->last_box_inv_mat);
7135
                    GetNewBoundingBox(&bnds, &actor->model->bounds, &mat);
7136
                    if (c2->last_box.max.v[0] >= bnds.min.v[0]
7137
                        && c2->last_box.max.v[1] >= bnds.min.v[1]
7138
                        && c2->last_box.max.v[2] >= bnds.min.v[2]
7139
                        && c2->last_box.min.v[0] <= bnds.max.v[0]
7140
                        && c2->last_box.min.v[1] <= bnds.max.v[1]
7141
                        && c2->last_box.min.v[2] <= bnds.max.v[2]) {
7142
                        drop = 0;
7143
                        break;
7144
                    }
7145
                }
7146
            }
7147
            if (drop) {
7148
                BrActorRemove(actor);
7149
                c->driver = eDriver_non_car_unused_slot;
7150
                last_free_slot--;
7151
                XZToColumnXZ(&cx, &cz, actor->t.t.mat.m[3][0], actor->t.t.mat.m[3][2], track_spec);
7152
                if (track_spec->columns[cz][cx] != NULL) {
7153
                    BrActorAdd(track_spec->columns[cz][cx], actor);
7154
                } else {
7155
                    BrActorAdd(gTrack_actor, actor);
7156
                }
7157
            }
7158
        }
7159
        last_free_slot++;
7160
    }
7161
    gNum_active_non_cars = last_free_slot;
7162
}
7163
 
7164
// IDA: void __usercall AdjustNonCar(br_actor *pActor@<EAX>, br_matrix34 *pMat@<EDX>)
7165
void AdjustNonCar(br_actor* pActor, br_matrix34* pMat) {
7166
    tU8 cx;
7167
    tU8 cz;
7168
    tTrack_spec* track_spec;
7169
    LOG_TRACE("(%p, %p)", pActor, pMat);
7170
 
7171
    track_spec = &gProgram_state.track_spec;
7172
    BrMatrix34Copy(&pActor->t.t.mat, pMat);
7173
    if (pActor->parent != gNon_track_actor) {
7174
        XZToColumnXZ(&cx, &cz, pActor->t.t.translate.t.v[0], pActor->t.t.translate.t.v[2], track_spec);
7175
        if (track_spec->columns[cz][cx] != pActor->parent && track_spec->columns[cz][cx] != NULL) {
7176
            BrActorRemove(pActor);
7177
            BrActorAdd(track_spec->columns[cz][cx], pActor);
7178
        }
7179
    }
7180
}
7181
 
7182
// IDA: void __usercall PipeSingleNonCar(tCollision_info *c@<EAX>)
7183
void PipeSingleNonCar(tCollision_info* c) {
7184
    LOG_TRACE("(%p)", c);
7185
 
7186
    StartPipingSession(ePipe_chunk_non_car);
7187
    if (gDoing_physics) {
7188
        BrVector3InvScale(&c->car_master_actor->t.t.translate.t, &c->car_master_actor->t.t.translate.t, WORLD_SCALE);
7189
    }
7190
    AddNonCarToPipingSession(c->car_ID, c->car_master_actor);
7191
    if (gDoing_physics) {
7192
        BrVector3Scale(&c->car_master_actor->t.t.translate.t, &c->car_master_actor->t.t.translate.t, WORLD_SCALE);
7193
    }
7194
    EndPipingSession();
7195
}
7196
 
7197
// IDA: int __usercall GetPrecalculatedFacesUnderCar@<EAX>(tCar_spec *pCar@<EAX>, tFace_ref **pFace_refs@<EDX>)
7198
int GetPrecalculatedFacesUnderCar(tCar_spec* pCar, tFace_ref** pFace_refs) {
7199
    LOG_TRACE("(%p, %p)", pCar, pFace_refs);
7200
 
7201
    if (pCar->box_face_ref == gFace_num__car
7202
        || (pCar->box_face_ref == gFace_num__car - 1 && pCar->box_face_start > gFace_count)) {
7203
        *pFace_refs = &gFace_list__car[pCar->box_face_start];
7204
        return pCar->box_face_end - pCar->box_face_start;
7205
    }
7206
    return 0;
7207
}
7208
 
7209
// IDA: br_material* __cdecl SomeNearbyMaterial()
7210
br_material* SomeNearbyMaterial(void) {
7211
    LOG_TRACE("()");
7212
    NOT_IMPLEMENTED();
7213
}