Subversion Repositories Games.Carmageddon

Rev

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

Rev Author Line No. Line
1 pmbaty 1
#include "oppoproc.h"
2
#include "errors.h"
3
#include "globvars.h"
4
#include "harness/trace.h"
5
#include "opponent.h"
6
#include "pd/sys.h"
20 pmbaty 7
#include <brender/brender.h>
1 pmbaty 8
#include <math.h>
9
#include <stdlib.h>
10
 
11
// IDA: int __usercall StraightestArcForCorner2D@<EAX>(br_vector2 *pCent@<EAX>, br_scalar *pRadius@<EDX>, br_scalar *pEntry_length@<EBX>, int *pLeft_not_right@<ECX>, br_vector2 *p1, br_vector2 *p2, br_vector2 *p3, br_scalar pWidth12, br_scalar pWidth23)
12
int StraightestArcForCorner2D(br_vector2* pCent, br_scalar* pRadius, br_scalar* pEntry_length, int* pLeft_not_right, br_vector2* p1, br_vector2* p2, br_vector2* p3, br_scalar pWidth12, br_scalar pWidth23) {
13
    //br_vector2 rel1; // Pierre-Marie Baty -- unused variable
14
    //br_vector2 rel3; // Pierre-Marie Baty -- unused variable
15
    //br_vector2 rot1; // Pierre-Marie Baty -- unused variable
16
    //br_vector2 rot1u; // Pierre-Marie Baty -- unused variable
17
    //br_scalar len12_squared; // Pierre-Marie Baty -- unused variable
18
    //br_scalar len23_squared; // Pierre-Marie Baty -- unused variable
19
    //br_scalar c; // Pierre-Marie Baty -- unused variable
20
    //br_scalar numerator; // Pierre-Marie Baty -- unused variable
21
    //br_scalar x; // Pierre-Marie Baty -- unused variable
22
    //br_scalar __block0___scale; // Pierre-Marie Baty -- unused variable
23
    LOG_TRACE("(%p, %p, %p, %p, %p, %p, %p, %f, %f)", pCent, pRadius, pEntry_length, pLeft_not_right, p1, p2, p3, pWidth12, pWidth23);
24
    NOT_IMPLEMENTED();
25
}
26
 
27
// There appears to be two different implementations of this function in different binaries.
28
// One does calculations in 2d space, this one calculates in 3d space.
29
static void StraightestArcForCorner(float* p1, float* p2, float* p3, br_vector3* p4, br_vector3* p5, br_vector3* p6, br_vector3* p7, br_vector3* p8, float p9, float p10) {
30
    br_vector3 rel1;
31
    br_vector3 rel3;
32
    br_vector3 rot1;
33
    br_scalar tmp;
34
    br_scalar tmp2;
35
    br_scalar tmp3;
36
    br_scalar tmp4;
37
    LOG_TRACE("(%p, %p, %p, %p, %p, %p, %p, %p, %f, %f)", p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
38
 
39
    BrVector3Sub(&rel1, p6, p5);
40
    rel1.v[1] = 0.f;
41
    BrVector3Sub(&rel3, p4, p5);
42
    rel3.v[1] = 0.f;
43
    *p3 = BrVector3Length(&rel3);
44
    if (*p3 <= BR_SCALAR_EPSILON) {
45
        *p2 = 0.001f;
46
        *p3 = 0.001f;
47
    }
48
    tmp = BrVector3Dot(&rel1, &rel3);
49
    BrVector3Cross(&rot1, &rel1, &rel3);
50
    tmp2 = sqrtf(tmp * tmp + rot1.v[1] * rot1.v[1]);
51
    tmp3 = fabsf(rot1.v[1] / tmp2);
52
    tmp4 = p10 * tmp / tmp2 + p9;
53
    if ((tmp3 < 1.f && fabsf(tmp4) > tmp3 * 1000.f) || tmp3 < 0.001f) {
54
        *p1 = 1000.f;
55
        *p2 = 1000.f;
56
    } else {
57
        tmp4 = tmp4 / tmp3;
58
        tmp3 = tmp3 / (tmp / tmp2 + 1.f);
59
        *p2 = tmp3 * p10 + sqrtf(tmp3 * p10) + tmp4;
60
        *p1 = *p2 * tmp3;
61
    }
62
}
63
 
64
// IDA: br_scalar __usercall CornerFudge@<ST0>(tCar_spec *pCar_spec@<EAX>)
65
br_scalar CornerFudge(tCar_spec* pCar_spec) {
66
    LOG_TRACE("(%p)", pCar_spec);
67
 
68
    return 1.4f;
69
}
70
 
71
// IDA: br_scalar __usercall MaxCurvatureForCarSpeed@<ST0>(tCar_spec *pCar@<EAX>, br_scalar pSpeed)
72
br_scalar MaxCurvatureForCarSpeed(tCar_spec* pCar, br_scalar pSpeed) {
73
    br_scalar curv;
74
    LOG_TRACE("(%p, %f)", pCar, pSpeed);
75
 
76
    if (pSpeed >= 12.5f) {
77
        curv = pCar->maxcurve * 12.5f / pSpeed;
78
    } else {
79
        curv = pCar->maxcurve;
80
    }
81
    return curv;
82
}
83
 
84
// IDA: br_scalar __usercall Vector2Cross@<ST0>(br_vector2 *pA@<EAX>, br_vector2 *pB@<EDX>)
85
br_scalar Vector2Cross(br_vector2* pA, br_vector2* pB) {
86
    LOG_TRACE("(%p, %p)", pA, pB);
87
    NOT_IMPLEMENTED();
88
}
89
 
90
// IDA: tFollow_path_result __usercall EndOfPath@<EAX>(tOpponent_spec *pOpponent_spec@<EAX>)
91
tFollow_path_result EndOfPath(tOpponent_spec* pOpponent_spec) {
92
    //tCar_spec* car_spec; // Pierre-Marie Baty -- unused variable
93
    LOG_TRACE("(%p)", pOpponent_spec);
94
    NOT_IMPLEMENTED();
95
}
96
 
97
// IDA: int __usercall RoughlyColinear@<EAX>(br_vector2 *p1@<EAX>, br_vector2 *p2@<EDX>, br_vector2 *p3@<EBX>)
98
int RoughlyColinear(br_vector2* p1, br_vector2* p2, br_vector2* p3) {
99
    //br_vector2 rel1; // Pierre-Marie Baty -- unused variable
100
    //br_vector2 rel2; // Pierre-Marie Baty -- unused variable
101
    //br_vector2 sum; // Pierre-Marie Baty -- unused variable
102
    //br_scalar cross; // Pierre-Marie Baty -- unused variable
103
    //br_scalar dot; // Pierre-Marie Baty -- unused variable
104
    //br_scalar wibble; // Pierre-Marie Baty -- unused variable
105
    LOG_TRACE("(%p, %p, %p)", p1, p2, p3);
106
    NOT_IMPLEMENTED();
107
}
108
 
109
// IDA: int __usercall GetStraight@<EAX>(br_vector2 *pStart@<EAX>, br_vector2 *pFinish@<EDX>, br_scalar *pWidth@<EBX>, int section1@<ECX>, tOpponent_spec *pOpponent_spec, tFollow_path_data *data)
110
int GetStraight(br_vector2* pStart, br_vector2* pFinish, br_scalar* pWidth, int section1, tOpponent_spec* pOpponent_spec, tFollow_path_data* data) {
111
    //int section; // Pierre-Marie Baty -- unused variable
112
    //br_vector2 next; // Pierre-Marie Baty -- unused variable
113
    //br_scalar next_width; // Pierre-Marie Baty -- unused variable
114
    LOG_TRACE("(%p, %p, %p, %d, %p, %p)", pStart, pFinish, pWidth, section1, pOpponent_spec, data);
115
    NOT_IMPLEMENTED();
116
}
117
 
118
// IDA: tFollow_path_result __usercall ProcessFollowPath@<EAX>(tOpponent_spec *pOpponent_spec@<EAX>, tProcess_objective_command pCommand@<EDX>, int pPursuit_mode@<EBX>, int pIgnore_end@<ECX>, int pNever_struggle)
119
tFollow_path_result ProcessFollowPath(tOpponent_spec* pOpponent_spec, tProcess_objective_command pCommand, int pPursuit_mode, int pIgnore_end, int pNever_struggle) {
120
    tS16 real_section_no;
121
    tFollow_path_data* data;
122
    br_vector3 wank;
123
    br_vector3 wank2;
124
    br_vector3* not_our_dir;
125
    br_vector3 section_dir;
126
    br_vector3 section_v;
127
    br_vector3 start;
128
    //br_vector3 corner; // Pierre-Marie Baty -- unused variable
129
    br_vector3 next;
130
    br_vector3 goal_dir;
131
    //br_vector3 intersect; // Pierre-Marie Baty -- unused variable
132
    br_vector3 a;
133
    br_vector3 p;
134
    br_vector3 car_to_end;
135
    br_actor* car_master_actor;
136
    br_scalar stopped_speed;
137
    br_scalar dist_to_end;
138
    br_scalar t;
139
    br_scalar acc;
140
    br_scalar speed;
141
    br_scalar dist_to_goal;
142
    br_scalar section_width;
143
    br_scalar goal_width;
144
    br_scalar desired_speed;
145
    br_scalar dist_along;
146
    br_scalar acc_factor;
147
    br_scalar max_acc;
148
    //br_scalar speed_to_goal; // Pierre-Marie Baty -- unused variable
149
    br_scalar error;
150
    br_scalar radius;
151
    //br_scalar entry_len; // Pierre-Marie Baty -- unused variable
152
    br_scalar corner_speed2;
153
    //br_scalar distance; // Pierre-Marie Baty -- unused variable
154
    br_scalar stopping_distance;
155
    br_scalar corner_speed;
156
    br_scalar dot_a;
157
    br_scalar dot_d;
158
    //br_scalar further_along; // Pierre-Marie Baty -- unused variable
159
    tCar_spec* car_spec;
160
    int engine_damage;
161
    int trans_damage;
162
    int section_no;
163
    int sx;
164
    int just_fucking_brake;
165
    //br_vector2 oppo_pos2d; // Pierre-Marie Baty -- unused variable
166
    //br_vector2 start2d; // Pierre-Marie Baty -- unused variable
167
    //br_vector2 finish2d; // Pierre-Marie Baty -- unused variable
168
    //br_vector2 next2d; // Pierre-Marie Baty -- unused variable
169
    //br_vector2 oppo_pos_rel; // Pierre-Marie Baty -- unused variable
170
    //br_vector2 oppo_pos_rel_next; // Pierre-Marie Baty -- unused variable
171
    //br_vector2 section_rel; // Pierre-Marie Baty -- unused variable
172
    //br_vector2 section_rel_next; // Pierre-Marie Baty -- unused variable
173
    //br_vector2 v2d; // Pierre-Marie Baty -- unused variable
174
    //br_vector2 corner2d; // Pierre-Marie Baty -- unused variable
175
    //br_vector2 after_corner2d; // Pierre-Marie Baty -- unused variable
176
    //br_vector2 next_turning_cent; // Pierre-Marie Baty -- unused variable
177
    //br_vector2 temp2d; // Pierre-Marie Baty -- unused variable
178
    //br_scalar section_len; // Pierre-Marie Baty -- unused variable
179
    //br_scalar section_len_next; // Pierre-Marie Baty -- unused variable
180
    //br_scalar pos_error; // Pierre-Marie Baty -- unused variable
181
    //br_scalar pos_error_next; // Pierre-Marie Baty -- unused variable
182
    //br_scalar pos_error_factor; // Pierre-Marie Baty -- unused variable
183
    //br_scalar sin_error; // Pierre-Marie Baty -- unused variable
184
    //br_scalar corner_radius; // Pierre-Marie Baty -- unused variable
185
    //br_scalar corner_entry_length; // Pierre-Marie Baty -- unused variable
186
    //br_scalar corner_distance; // Pierre-Marie Baty -- unused variable
187
    br_scalar speed2d;
188
    //br_scalar stemp1; // Pierre-Marie Baty -- unused variable
189
    br_scalar width;
190
    br_scalar next_width;
191
    br_scalar next_turning_radius;
192
    br_scalar next_corner_size;
193
    //br_scalar later_width; // Pierre-Marie Baty -- unused variable
194
    br_scalar effective_speed_factor;
195
    //int first_straight; // Pierre-Marie Baty -- unused variable
196
    //int next_straight; // Pierre-Marie Baty -- unused variable
197
    //int left_not_right; // Pierre-Marie Baty -- unused variable
198
    //int later_straight; // Pierre-Marie Baty -- unused variable
199
    //int next_left_not_right; // Pierre-Marie Baty -- unused variable
200
    LOG_TRACE("(%p, %d, %d, %d, %d)", pOpponent_spec, pCommand, pPursuit_mode, pIgnore_end, pNever_struggle);
201
 
202
    car_spec = pOpponent_spec->car_spec;
203
    engine_damage = car_spec->damage_units[0].damage_level;
204
    trans_damage = car_spec->damage_units[1].damage_level;
205
    data = &pOpponent_spec->follow_path_data;
206
    car_master_actor = car_spec->car_master_actor;
207
 
208
    if (pCommand == ePOC_start) {
209
        data->first_section_no = GetOpponentsFirstSection(pOpponent_spec);
210
        data->section_no = data->first_section_no;
211
        dr_dprintf("%s: ProcessFollowPath() - new task started, first real section #%d", pOpponent_spec->car_spec->driver_name, GetOpponentsRealSection(pOpponent_spec, data->first_section_no));
212
        data->has_moved_during_this_task = 0;
213
        data->struggle_time = 0;
214
        data->last_finished_struggle_time = gTime_stamp_for_this_munging;
215
        data->prev_acc = 0.f;
216
        data->prev_acc_error = 0.f;
217
        data->borrowed_time_start = gTime_stamp_for_this_munging;
218
        data->last_struggle_section = -1;
219
        data->made_it = 1;
220
        data->cheating = 0;
221
        data->cornering = 0;
222
        if (!pOpponent_spec->cheating && !pOpponent_spec->physics_me) {
223
            dr_dprintf("%s: Rematerialising from ePOC_start in ProcessFollowPath()...", pOpponent_spec->car_spec->driver_name);
224
            RematerialiseOpponentOnNearestSection(pOpponent_spec, BrVector3Length(&car_spec->v));
225
        }
226
        return eFPR_OK;
227
    } else if (pCommand == ePOC_run) {
228
        if (pOpponent_spec->follow_path_data.cheating || pOpponent_spec->cheating) {
229
            return FollowCheatyPath(pOpponent_spec);
230
        }
231
        if (!pIgnore_end && !data->made_it && data->borrowed_time_start + 1000 < gTime_stamp_for_this_munging && gTime_stamp_for_this_munging < data->borrowed_time_start + 10000) {
232
            BrVector3Sub(&section_dir, GetOpponentsSectionFinishNodePoint(pOpponent_spec, data->section_no), GetOpponentsSectionStartNodePoint(pOpponent_spec, data->section_no));
233
            BrVector3Sub(&goal_dir, &car_master_actor->t.t.translate.t, GetOpponentsSectionStartNodePoint(pOpponent_spec, data->section_no));
234
            dist_along = BrVector3LengthSquared(&goal_dir) / BrVector3LengthSquared(&section_dir);
235
            BrVector3Scale(&section_v, &section_dir, dist_along);
236
            BrVector3Sub(&wank, &goal_dir, &section_v);
237
            goal_width = BrVector3Length(&wank);
238
            if (GetOpponentsSectionWidth(pOpponent_spec, data->section_no) >= goal_width) {
239
                data->made_it = 1;
240
            }
241
        }
242
        if (data->borrowed_time_start + 10000 < gTime_stamp_for_this_munging && !data->made_it) {
243
            dr_dprintf("%s: ProcessFollowPath() giving up due to not making the corner", pOpponent_spec->car_spec->driver_name);
244
            return eFPR_given_up;
245
        }
246
        car_spec->keys.acc = 1;
247
        speed = BrVector3Length(&car_spec->v);
248
        if (speed > 0.2f) {
249
            data->has_moved_during_this_task = 1;
250
            pOpponent_spec->has_moved_at_some_point = 1;
251
        }
252
        if (data->struggle_time) {
253
            if (data->struggle_time + 150 * (5 * data->number_of_struggles - 5) + 2750 >= gTime_stamp_for_this_munging) {
254
                if (data->struggle_time + 150 * (5 * data->number_of_struggles - 5) + 2000 >= gTime_stamp_for_this_munging) {
255
                    car_spec->brake_force = 0.0f;
256
                    car_spec->acc_force = car_spec->M * -6.0f;
257
                } else {
258
                    car_spec->acc_force = 0.0f;
259
                    car_spec->brake_force = car_spec->M * 15.0f;
260
                }
261
                car_spec->curvature = 0.0f;
262
                return eFPR_OK;
263
            }
264
            dr_dprintf("%s: done struggling. speed = %.2f m/s", pOpponent_spec->car_spec->driver_name, speed);
265
            data->made_it = 0;
266
            data->borrowed_time_start = gTime_stamp_for_this_munging;
267
            data->struggle_time = 0;
268
            data->last_finished_struggle_time = gTime_stamp_for_this_munging;
269
            car_spec->brake_force = 0.0f;
270
            car_spec->acc_force = 0.0f;
271
        } else {
272
            if (pIgnore_end) {
273
                stopped_speed = 0.06666667f;
274
            } else {
275
                stopped_speed = 0.2f;
276
            }
277
            if (!pNever_struggle && stopped_speed >= speed && data->last_finished_struggle_time + 2000 < gTime_stamp_for_this_munging && (pPursuit_mode || data->has_moved_during_this_task != 0)) {
278
                dr_dprintf("%s: 'Stopped,' section #%d, speed = %.2f m/s, about to start a-strugglin'", pOpponent_spec->car_spec->driver_name, data->section_no, speed);
279
                data->struggle_time = gTime_stamp_for_this_munging;
280
                if (pIgnore_end || data->section_no != data->last_struggle_section) {
281
                    data->last_struggle_section = data->section_no;
282
                    data->number_of_struggles = 0;
283
                } else {
284
                    if (data->number_of_struggles >= 3) {
285
                        car_spec->acc_force = 0.0f;
286
                        car_spec->brake_force = 0.0f;
287
                        dr_dprintf("%s: Giving up trying to follow path 'cos we've struggled too much", pOpponent_spec->car_spec->driver_name);
288
                        return eFPR_given_up;
289
                    }
290
                    data->number_of_struggles++;
291
                }
292
            }
293
        }
294
        BrVector3Sub(&car_to_end, GetOpponentsSectionFinishNodePoint(pOpponent_spec, data->section_no), &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t);
295
        car_to_end.v[1] = 0.0f;
296
        dist_to_end = BrVector3Length(&car_to_end) * WORLD_SCALE;
297
        dist_to_goal = dist_to_end;
298
        if (dist_to_end > 15.0f) {
299
            BrVector3Sub(&wank, GetOpponentsSectionFinishNodePoint(pOpponent_spec, data->section_no), GetOpponentsSectionStartNodePoint(pOpponent_spec, data->section_no));
300
            BrVector3Normalise(&a, &wank);
301
            BrVector3Sub(&wank, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t, GetOpponentsSectionStartNodePoint(pOpponent_spec, data->section_no));
302
 
303
            dot_a = BrVector3Dot(&a, &wank); // v62.v[2] * wank.v[2] + v62.v[1] * wank.v[1] + v62.v[0] * wank.v[0];
304
            wank2.v[0] = a.v[0] * dot_a;
305
            wank2.v[2] = a.v[2] * dot_a;
306
            car_to_end.v[0] = wank2.v[0] - wank.v[0];
307
            car_to_end.v[2] = wank2.v[2] - wank.v[2];
308
            car_to_end.v[1] = 0.0f;
309
            dist_to_end = BrVector3Length(&car_to_end) * WORLD_SCALE;
310
            if (dist_to_end < 15.0f) {
311
                t = sqrtf(225.0f - dist_to_end * dist_to_end) / WORLD_SCALE;
312
                if (t + dot_a >= 0.0) {
313
                    wank.v[0] = a.v[0] * t;
314
                    wank.v[2] = a.v[2] * t;
315
                    wank.v[1] = 0.0f;
316
                    BrVector3Accumulate(&car_to_end, &wank);
317
                } else {
318
                    BrVector3Sub(&car_to_end, GetOpponentsSectionStartNodePoint(pOpponent_spec, data->section_no), &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t);
319
                    dist_to_end = BrVector3Length(&car_to_end) * WORLD_SCALE;
320
                    BrVector3Scale(&car_to_end, &car_to_end, 15.0f / dist_to_end);
321
                }
322
                dist_to_end = 15.0f;
323
            } else if (dot_a < 0.0f) {
324
                BrVector3Sub(&car_to_end, GetOpponentsSectionStartNodePoint(pOpponent_spec, data->section_no), &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t);
325
                dist_to_end = BrVector3Length(&car_to_end) * WORLD_SCALE;
326
                BrVector3Scale(&car_to_end, &car_to_end, 15.0f / dist_to_end);
327
            }
328
        }
329
        section_width = GetOpponentsSectionWidth(pOpponent_spec, data->section_no) * WORLD_SCALE;
330
        if (!pIgnore_end && speed * 1.5f > dist_to_goal) {
331
            dr_dprintf("%s: ProcessFollowPath() - *** CHANGING SECTIONS ***", pOpponent_spec->car_spec->driver_name);
332
            dr_dprintf("%s: ProcessFollowPath() - current section %d(#%d)", pOpponent_spec->car_spec->driver_name, data->section_no, GetOpponentsRealSection(pOpponent_spec, data->section_no));
333
            data->section_no = GetOpponentsNextSection(pOpponent_spec, data->section_no);
334
            if (data->section_no == -1) {
335
                car_spec->acc_force = 0.0f;
336
                car_spec->brake_force = 0.0f;
337
                dr_dprintf("%s: ProcessFollowPath() - reached end of path", pOpponent_spec->car_spec->driver_name);
338
                return eFPR_end_of_path;
339
            }
340
            car_to_end.v[1] = 0.0f;
341
            real_section_no = GetOpponentsRealSection(pOpponent_spec, data->section_no);
342
            dr_dprintf("%s: ProcessFollowPath() - next section %d(#%d)", pOpponent_spec->car_spec->driver_name, data->section_no, GetOpponentsRealSection(pOpponent_spec, data->section_no));
343
            data->last_struggle_section = -1;
344
            data->borrowed_time_start = gTime_stamp_for_this_munging;
345
            data->made_it = 1;
346
            data->last_distance = 0.0f;
347
        }
348
        not_our_dir = (br_vector3*)&car_master_actor->t.t.mat.m[2];
349
 
350
        BrVector3Cross(&wank, &car_to_end, not_our_dir);
351
 
352
        radius = GetOpponentsSectionWidth(pOpponent_spec, data->section_no) * 0.5f;
353
        just_fucking_brake = 0;
354
        dot_d = BrVector3Dot(&car_to_end, not_our_dir);
355
        if (dot_d > 0.0f && speed > 10.0f) {
356
            data->desired_speed = 6.0f;
357
            car_spec->curvature = 0.0f;
358
            just_fucking_brake = 1;
359
        } else {
360
            if ((wank.v[1] > 0.0f && dot_d > 0.0f) || GetOpponentsSectionWidth(pOpponent_spec, data->section_no) < wank.v[1]) {
361
                car_spec->curvature = MaxCurvatureForCarSpeed(car_spec, speed);
362
                data->desired_speed = 6.0f;
363
            } else if ((wank.v[1] < 0.0f && dot_d > 0.0) || -GetOpponentsSectionWidth(pOpponent_spec, data->section_no) > wank.v[1]) {
364
                car_spec->curvature = -MaxCurvatureForCarSpeed(car_spec, speed);
365
                data->desired_speed = 6.0f;
366
            } else if (wank.v[1] > radius) {
367
                car_spec->curvature = MaxCurvatureForCarSpeed(car_spec, speed) * 0.05f;
368
                data->desired_speed = 80.0f;
369
            } else if (-radius > wank.v[1]) {
370
                car_spec->curvature = -(MaxCurvatureForCarSpeed(car_spec, speed) * 0.05f);
371
                data->desired_speed = 80.0f;
372
            } else {
373
                car_spec->curvature = 0.0f;
374
                data->desired_speed = 80.0f;
375
            }
376
        }
377
        if (just_fucking_brake) {
378
            car_spec->brake_force = car_spec->M * 15.0f;
379
            car_spec->acc_force = 0.0f;
380
        } else {
381
            if (GetOpponentsNextSection(pOpponent_spec, data->section_no) != -1) {
382
                next_turning_radius = pOpponent_spec->car_spec->car_master_actor->t.t.translate.t.v[0] * -wank.v[2] + pOpponent_spec->car_spec->car_master_actor->t.t.translate.t.v[2] * wank.v[0];
383
                next_corner_size = GetOpponentsSectionFinishNodePoint(pOpponent_spec, data->section_no)->v[0] * -wank.v[2];
384
                next_turning_radius = next_turning_radius - (GetOpponentsSectionFinishNodePoint(pOpponent_spec, data->section_no)->v[2] * wank.v[0] + next_corner_size);
385
                // FIXME: added temporary variable
386
                float v104 = -wank.v[2] * not_our_dir->v[0] + not_our_dir->v[2] * wank.v[0];
387
                if (v104 * next_turning_radius > 0.0f) {
388
                    goal_width = 0.0f;
389
                    speed2d = speed * speed / 24.0f + speed * 1.5f;
390
                    BrVector3Copy(&p, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t);
391
                    BrVector3Scale(&start, not_our_dir, -(next_turning_radius / v104));
392
                    BrVector3Accumulate(&start, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t);
393
                    section_no = data->section_no;
394
                    for (sx = 0; GetOpponentsNextSection(pOpponent_spec, section_no) != -1 && sx < 4; sx++) {
395
                        BrVector3Copy(&next, GetOpponentsSectionFinishNodePoint(pOpponent_spec, GetOpponentsNextSection(pOpponent_spec, section_no)));
396
                        next_width = GetOpponentsSectionWidth(pOpponent_spec, GetOpponentsNextSection(pOpponent_spec, section_no));
397
                        width = GetOpponentsSectionWidth(pOpponent_spec, data->section_no);
398
                        StraightestArcForCorner(&corner_speed, &corner_speed2, &dot_a, &p, &start, &next, &p, &start, width, next_width);
399
                        dot_a *= WORLD_SCALE;
400
                        goal_width += dot_a;
401
                        if (goal_width > speed2d) {
402
                            break;
403
                        }
404
                        corner_speed *= WORLD_SCALE;
405
                        corner_speed2 *= WORLD_SCALE;
406
                        stopping_distance = CornerFudge(car_spec) * CornerFudge(car_spec) * (corner_speed * 10.0);
407
                        desired_speed = sqrtf(stopping_distance);
408
                        if (GetOpponentsSectionMaxSpeed(pOpponent_spec, data->section_no, 1) < desired_speed) {
409
                            desired_speed = GetOpponentsSectionMaxSpeed(pOpponent_spec, data->section_no, 1);
410
                            stopping_distance = desired_speed * desired_speed;
411
                        }
412
                        if (goal_width - corner_speed2 < (speed * speed - stopping_distance) / 24.0f + desired_speed * 1.5f && data->desired_speed > desired_speed) {
413
                            data->desired_speed = desired_speed;
414
                        }
415
                        BrVector3Copy(&p, &start);
416
                        BrVector3Copy(&start, &next);
417
                        section_no = GetOpponentsNextSection(pOpponent_spec, section_no);
418
                    }
419
                }
420
            }
421
            effective_speed_factor = CAR_SPEC_GET_SPEED_FACTOR(car_spec);
422
            acc_factor = MAX(1.0f, effective_speed_factor);
423
            if (engine_damage > 50 && engine_damage < 98) {
424
                acc_factor -= (engine_damage - 50) * 0.0125f;
425
            } else if (engine_damage >= 98) {
426
                acc_factor -= 0.6f;
427
            }
428
            if (trans_damage > 50 && trans_damage < 98) {
429
                acc_factor -= (trans_damage - 50) * 0.00625f;
430
            } else if (trans_damage >= 98) {
431
                acc_factor -= 0.3f;
432
            }
433
            if (engine_damage >= 99 || trans_damage >= 99) {
434
                acc_factor = 0.0f;
435
            }
436
            max_acc = acc_factor * 10.0f;
437
            // TODO: ?? corner_speed2[10] = v30;
438
            error = data->desired_speed * effective_speed_factor - speed;
439
            acc = (error - data->prev_acc_error) * 1000.0f / gFrame_period_for_this_munging * 0.1f + error + data->prev_acc;
440
            if (acc > max_acc) {
441
                acc = max_acc;
442
            }
443
            if (acc < -max_acc) {
444
                acc = -max_acc;
445
            }
446
            data->prev_acc = acc;
447
            data->prev_acc_error = error;
448
            acc = car_spec->M * acc;
449
            if (acc <= 0.0f) {
450
                car_spec->acc_force = 0.0f;
451
                car_spec->brake_force = -acc;
452
            } else {
453
                car_spec->acc_force = acc;
454
                car_spec->brake_force = 0.0f;
455
            }
456
        }
457
        return eFPR_OK;
458
    }
459
 
460
    BrFatal("C:\\Msdev\\Projects\\DethRace\\OPPOPROC.C", 1420, "C:\\Msdev\\Projects\\DethRace\\OPPOPROC.C line %d", 140);
461
    return eFPR_OK;
462
}
463
 
464
// IDA: tFollow_path_result __usercall FollowCheatyPath@<EAX>(tOpponent_spec *pOpponent_spec@<EAX>)
465
tFollow_path_result FollowCheatyPath(tOpponent_spec* pOpponent_spec) {
466
    tFollow_path_data* data;
467
    br_vector3 a;
468
    br_vector3 p;
469
    br_vector3 section_v;
470
    br_vector3 car_to_end;
471
    br_vector3 car_to_intersect;
472
    br_vector3* start;
473
    br_vector3* finish;
474
    br_scalar t;
475
    br_scalar frame_period_in_secs;
476
    //br_scalar distance_left; // Pierre-Marie Baty -- unused variable
477
    br_scalar distance_to_end;
478
    br_scalar distance_to_intersect;
479
    br_scalar section_min;
480
    br_scalar section_max;
481
    br_scalar desired_speed_BRU;
482
    LOG_TRACE("(%p)", pOpponent_spec);
483
 
484
    data = &pOpponent_spec->follow_path_data;
485
    start = GetOpponentsSectionStartNodePoint(pOpponent_spec, pOpponent_spec->follow_path_data.section_no);
486
    finish = GetOpponentsSectionFinishNodePoint(pOpponent_spec, pOpponent_spec->follow_path_data.section_no);
487
    if ((pOpponent_spec->follow_path_data.cheating ^ pOpponent_spec->cheating) != 0) {
488
        data->cheating = pOpponent_spec->cheating;
489
        if (data->cheating) {
490
            dr_dprintf("%s: Dematerialising", pOpponent_spec->car_spec->driver_name);
491
            BrVector3Sub(&section_v, finish, start);
492
            BrVector3Sub(&car_to_end, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t, start);
493
            t = BrVector3Dot(&section_v, &car_to_end) / BrVector3LengthSquared(&section_v);
494
            if (t < 0.0f) {
495
                BrVector3Copy(&data->cheaty_intersect, start);
496
            } else if (t > 1.f) {
497
                BrVector3Copy(&data->cheaty_intersect, finish);
498
            } else {
499
                BrVector3Scale(&data->cheaty_intersect, &section_v, t);
500
                BrVector3Accumulate(&data->cheaty_intersect, start);
501
            }
502
            BrVector3Sub(&car_to_intersect, &data->cheaty_intersect, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t);
503
            distance_to_intersect = BrVector3Length(&car_to_intersect);
504
            frame_period_in_secs = gFrame_period_for_this_munging / 1000.0f * 20.0f;
505
            TurnOpponentPhysicsOff(pOpponent_spec);
506
            if (distance_to_intersect >= frame_period_in_secs) {
507
                data->moving_to_intersect = 1;
508
                BrVector3Normalise(&car_to_intersect, &car_to_intersect);
509
                BrVector3Scale(&car_to_intersect, &car_to_intersect, frame_period_in_secs);
510
                BrVector3Accumulate(&pOpponent_spec->car_spec->car_master_actor->t.t.translate.t, &car_to_intersect);
511
                return eFPR_OK;
512
            } else {
513
                data->moving_to_intersect = 0;
514
                BrVector3Copy(&pOpponent_spec->car_spec->car_master_actor->t.t.translate.t, &data->cheaty_intersect);
515
                return eFPR_OK;
516
            }
517
        }
518
        BrVector3Sub(&p, finish, start);
519
        PointActorAlongThisBloodyVector(pOpponent_spec->car_spec->car_master_actor, &p);
520
        BrVector3Sub(&a, finish, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t);
521
        distance_to_end = BrVector3Length(&a);
522
        dr_dprintf("%s: Rematerialising from FollowCheatyPath()...", pOpponent_spec->car_spec->driver_name);
523
        if (data->section_no < 0) {
524
            PDEnterDebugger("No useful section number in ProcessCheatyPath()");
525
        }
526
 
527
        section_max = GetOpponentsSectionMaxSpeed(pOpponent_spec, data->section_no, 1);
528
        section_min = GetOpponentsSectionMinSpeed(pOpponent_spec, data->section_no, 1);
529
 
530
        if (section_max < 255) {
531
            desired_speed_BRU = section_max / WORLD_SCALE;
532
        } else if (section_min > 0) {
533
            desired_speed_BRU = section_min / WORLD_SCALE;
534
        } else {
535
            desired_speed_BRU = MIN(7.0f, MAX(1.0f, distance_to_end * 2.0f));
536
        }
537
        if (RematerialiseOpponentOnNearestSection(pOpponent_spec, desired_speed_BRU)) {
538
            pOpponent_spec->car_spec->brake_force = 0.0f;
539
            pOpponent_spec->car_spec->acc_force = 0.0f;
540
            if (distance_to_end >= 5.0f) {
541
                pOpponent_spec->car_spec->acc_force = pOpponent_spec->car_spec->M / 2.0f;
542
            } else {
543
                pOpponent_spec->car_spec->brake_force = pOpponent_spec->car_spec->M * 15.0f;
544
            }
545
            return eFPR_OK;
546
        }
547
        data->cheating = 1;
548
    }
549
    frame_period_in_secs = gFrame_period_for_this_munging / 1000.0f * 20.0f;
550
    if (data->moving_to_intersect) {
551
        BrVector3Sub(&car_to_intersect, &data->cheaty_intersect, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t);
552
        distance_to_intersect = BrVector3Length(&car_to_intersect);
553
        if (distance_to_intersect < frame_period_in_secs) {
554
            data->moving_to_intersect = 0;
555
            BrVector3Copy(&pOpponent_spec->car_spec->car_master_actor->t.t.translate.t, &data->cheaty_intersect);
556
        } else {
557
            BrVector3Normalise(&car_to_intersect, &car_to_intersect);
558
            BrVector3Scale(&car_to_intersect, &car_to_intersect, frame_period_in_secs);
559
            BrVector3Accumulate(&pOpponent_spec->car_spec->car_master_actor->t.t.translate.t, &car_to_intersect);
560
        }
561
        return eFPR_OK;
562
    }
563
 
564
    BrVector3Sub(&p, finish, start);
565
    BrVector3Normalise(&p, &p);
566
    while (frame_period_in_secs > 0.0f) {
567
        BrVector3Sub(&a, finish, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t);
568
        distance_to_end = BrVector3Length(&a);
569
        if (distance_to_end < frame_period_in_secs) {
570
            BrVector3Accumulate(&pOpponent_spec->car_spec->car_master_actor->t.t.translate.t, &a);
571
            frame_period_in_secs -= distance_to_end;
572
            dr_dprintf("%s: ProcessFollowPath() - current section %d(#%d) (cheating)", pOpponent_spec->car_spec->driver_name, data->section_no, GetOpponentsRealSection(pOpponent_spec, data->section_no));
573
            data->section_no = GetOpponentsNextSection(pOpponent_spec, data->section_no);
574
            if (data->section_no == -1) {
575
                pOpponent_spec->car_spec->acc_force = 0.0f;
576
                pOpponent_spec->car_spec->brake_force = 0.0f;
577
                dr_dprintf("%s: ProcessFollowPath() - reached end of path while cheating", pOpponent_spec->car_spec->driver_name);
578
                return eFPR_end_of_path;
579
            }
580
            dr_dprintf("%s: ProcessFollowPath() - next section %d(#%d) (cheating)", pOpponent_spec->car_spec->driver_name, data->section_no, GetOpponentsRealSection(pOpponent_spec, data->section_no));
581
            start = GetOpponentsSectionStartNodePoint(pOpponent_spec, data->section_no);
582
            finish = GetOpponentsSectionFinishNodePoint(pOpponent_spec, data->section_no);
583
            BrVector3Sub(&p, finish, start);
584
            BrVector3Normalise(&p, &p);
585
        } else {
586
            BrVector3Scale(&p, &p, frame_period_in_secs);
587
            BrVector3Accumulate(&pOpponent_spec->car_spec->car_master_actor->t.t.translate.t, &p);
588
            frame_period_in_secs = 0.0;
589
        }
590
    }
591
    return eFPR_OK;
592
}