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 "oil.h"
20 pmbaty 2
#include "brender/brender.h"
1 pmbaty 3
#include "finteray.h"
4
#include "globvars.h"
5
#include "globvrpb.h"
6
#include "harness/trace.h"
7
#include "loading.h"
8
#include "network.h"
9
#include "piping.h"
10
#include "utility.h"
11
#include <math.h>
12
#include <stdlib.h>
13
 
14
char* gOil_pixie_names[1] = { "OIL.PIX" };
15
int gNext_oil_pixie = 0;
16
br_scalar gZ_buffer_diff;
17
br_scalar gMin_z_diff;
18
br_pixelmap* gOil_pixies[1];
19
tOil_spill_info gOily_spills[15];
20
 
21
// IDA: void __cdecl InitOilSpills()
22
void InitOilSpills(void) {
23
    int i;
24
    br_model* the_model;
25
    br_material* the_material;
26
    LOG_TRACE("()");
27
 
28
    for (i = 0; i < COUNT_OF(gOil_pixie_names); i++) {
29
        gOil_pixies[i] = LoadPixelmap(gOil_pixie_names[i]);
30
        BrMapAdd(gOil_pixies[i]);
31
    }
32
 
33
    for (i = 0; i < COUNT_OF(gOily_spills); i++) {
34
        the_material = BrMaterialAllocate(NULL);
35
        BrMaterialAdd(the_material);
36
        the_material->ka = 0.99f;
37
        the_material->kd = 0.0f;
38
        the_material->ks = 0.0f;
39
        the_material->power = 0.0f;
40
        the_material->index_base = 0;
41
        the_material->flags |= BR_MATF_LIGHT;
42
        the_material->flags |= BR_MATF_PERSPECTIVE;
43
        the_material->flags |= BR_MATF_SMOOTH;
20 pmbaty 44
        // TODO: added by dethrace, investigate why oil spills in OG do not need this flag set to render correctly
45
        the_material->flags |= BR_MATF_TWO_SIDED;
1 pmbaty 46
        the_material->index_range = 0;
47
        the_material->colour_map = NULL;
48
        BrMatrix23Identity(&the_material->map_transform);
49
        the_material->index_shade = BrTableFind("IDENTITY.TAB");
50
        BrMaterialUpdate(the_material, BR_MATU_ALL);
51
        the_model = BrModelAllocate(NULL, 4, 2);
52
        the_model->flags |= BR_MODF_KEEP_ORIGINAL;
53
 
54
        the_model->faces[0].vertices[0] = 2;
55
        the_model->faces[0].vertices[1] = 1;
56
        the_model->faces[0].vertices[2] = 0;
57
        the_model->faces[0].material = NULL;
58
        the_model->faces[0].smoothing = 1;
59
        the_model->faces[1].vertices[0] = 3;
60
        the_model->faces[1].vertices[1] = 2;
61
        the_model->faces[1].vertices[2] = 0;
62
        the_model->faces[1].material = NULL;
63
        the_model->faces[1].smoothing = 1;
64
        BrVector3Set(&the_model->vertices[0].p, -1.f, 0.f, -1.f);
65
        BrVector2Set(&the_model->vertices[0].map, 0.f, 1.f);
66
        BrVector3Set(&the_model->vertices[1].p, 1.f, 0.f, 1.f);
67
        BrVector2Set(&the_model->vertices[1].map, 0.f, 0.f);
68
        BrVector3Set(&the_model->vertices[2].p, 1.f, 0.f, -1.f);
69
        BrVector2Set(&the_model->vertices[2].map, 1.f, 0.f);
70
        BrVector3Set(&the_model->vertices[3].p, -1.f, 0.f, 1.f);
71
        BrVector2Set(&the_model->vertices[3].map, 1.f, 1.f);
72
        gOily_spills[i].actor = BrActorAllocate(BR_ACTOR_MODEL, NULL);
73
        gOily_spills[i].actor->model = the_model;
74
        gOily_spills[i].actor->render_style = BR_RSTYLE_NONE;
75
        gOily_spills[i].actor->material = the_material;
76
        BrActorAdd(gNon_track_actor, gOily_spills[i].actor);
77
    }
78
}
79
 
80
// IDA: void __cdecl ResetOilSpills()
81
void ResetOilSpills(void) {
82
    int i;
83
    LOG_TRACE("()");
84
 
85
    for (i = 0; i < COUNT_OF(gOily_spills); i++) {
86
        gOily_spills[i].actor->render_style = BR_RSTYLE_NONE;
87
        gOily_spills[i].car = NULL;
88
        gOily_spills[i].stop_time = 0;
89
    }
90
}
91
 
92
// IDA: void __usercall QueueOilSpill(tCar_spec *pCar@<EAX>)
93
void QueueOilSpill(tCar_spec* pCar) {
94
    int i;
95
    int oily_index;
96
    int oldest_one;
97
    tU32 the_time;
98
    tU32 oldest_time;
99
    LOG_TRACE("(%p)", pCar);
100
 
101
    oldest_one = 0;
102
    oily_index = -1;
103
    the_time = GetTotalTime();
104
    oldest_time = GetTotalTime();
105
 
106
    for (i = 0; i < COUNT_OF(gOily_spills); i++) {
107
        if (gOily_spills[i].car == pCar && the_time < gOily_spills[i].spill_time + 5000) {
108
            return;
109
        }
110
    }
111
 
112
    for (i = 0; i < COUNT_OF(gOily_spills); i++) {
113
        if (gOily_spills[i].car == NULL) {
114
            oily_index = i;
115
            break;
116
        }
117
        if (gOily_spills[i].spill_time < oldest_time) {
118
            oldest_time = gOily_spills[i].spill_time;
119
            oldest_one = i;
120
        }
121
    }
122
 
123
    if (oily_index < 0) {
124
        oily_index = oldest_one;
125
    }
126
    gOily_spills[oily_index].car = pCar;
127
    gOily_spills[oily_index].spill_time = the_time + 500;
128
    gOily_spills[oily_index].full_size = SRandomBetween(.35f, .6f);
129
    gOily_spills[oily_index].grow_rate = SRandomBetween(3e-5f, 10e-5f);
130
    gOily_spills[oily_index].current_size = .1f;
131
    gOily_spills[oily_index].actor->render_style = BR_RSTYLE_NONE;
132
}
133
 
134
// IDA: int __usercall OKToSpillOil@<EAX>(tOil_spill_info *pOil@<EAX>)
135
int OKToSpillOil(tOil_spill_info* pOil) {
136
    //br_scalar temp; // Pierre-Marie Baty -- unused variable
137
    //br_scalar size_with_margin; // Pierre-Marie Baty -- unused variable
138
    br_scalar distance;
139
    br_scalar mr_dotty;
140
    br_vector3 v;
141
    br_vector3 ray_pos;
142
    br_vector3 ray_dir;
143
    br_vector3 normal;
144
    tCar_spec* car;
145
    int i;
146
    int face_count;
147
    int found_one;
148
    br_angle angle_to_rotate_by;
149
    tBounds kev_bounds;
150
    tFace_ref the_list[10];
151
    tFace_ref* face_ref;
152
    LOG_TRACE("(%p)", pOil);
153
 
154
    car = pOil->car;
155
    if (car->driver >= eDriver_net_human && car->damage_units[eDamage_engine].damage_level <= 98 && car->damage_units[eDamage_transmission].damage_level <= 98) {
156
        return 0;
157
    }
158
    angle_to_rotate_by = IRandomBetween(0, 0xffff);
159
    kev_bounds.original_bounds.min.v[0] = -pOil->full_size;
160
    kev_bounds.original_bounds.min.v[1] = 1.5f * car->car_model_actors[car->principal_car_actor].actor->model->bounds.min.v[1];
161
    kev_bounds.original_bounds.min.v[2] = -pOil->full_size;
162
    kev_bounds.original_bounds.max.v[0] = pOil->full_size;
163
    kev_bounds.original_bounds.max.v[1] = car->car_model_actors[car->principal_car_actor].actor->model->bounds.max.v[1];
164
    kev_bounds.original_bounds.max.v[2] = pOil->full_size;
165
    BrMatrix34PreRotateY(&pOil->actor->t.t.mat, angle_to_rotate_by);
166
    kev_bounds.mat = &car->car_master_actor->t.t.mat;
167
    face_count = FindFacesInBox(&kev_bounds, the_list, COUNT_OF(the_list));
168
    BrVector3Set(&v, .0f, .2f, .0f);
169
    BrMatrix34ApplyP(&ray_pos, &v, &car->car_master_actor->t.t.mat);
20 pmbaty 170
    BrVector3Set(&ray_dir, 0.f, kev_bounds.original_bounds.min.v[1] - kev_bounds.original_bounds.max.v[1], 0.f);\
1 pmbaty 171
    if (face_count == 0) {
172
        return 0;
173
    }
174
    found_one = 0;
175
    for (i = 0; i < face_count; i++) {
176
        face_ref = &the_list[i];
177
        if (!found_one) {
178
            CheckSingleFace(face_ref, &ray_pos, &ray_dir, &normal, &distance);
179
            if (distance < 100.f) {
180
                found_one = 1;
181
                BrVector3Copy((br_vector3*)pOil->actor->t.t.mat.m[1], &normal);
182
                BrVector3Set(&v, 0.f, 0.f, 1.f);
183
                BrVector3Cross((br_vector3*)pOil->actor->t.t.mat.m[0], &normal, &v);
184
                BrVector3Set(&v, 1.f, 0.f, 0.f);
185
                BrVector3Cross((br_vector3*)pOil->actor->t.t.mat.m[2], &normal, &v);
186
                BrVector3Scale(&v, &ray_dir, distance);
187
                BrVector3Add(&pOil->pos, &ray_pos, &v);
188
                BrMatrix34PreRotateY(&pOil->actor->t.t.mat, angle_to_rotate_by);
189
            }
190
        }
191
    }
192
    if (!found_one || normal.v[1] < .97f) {
193
        return 0;
194
    }
195
    for (i = 0; i < face_count; i++) {
196
        face_ref = &the_list[i];
197
        mr_dotty = BrVector3Dot(&face_ref->normal, &normal);
198
        if (mr_dotty < .98f && (mr_dotty > .8f || !NormalSideOfPlane(&pOil->actor->t.t.translate.t, &face_ref->normal, face_ref->d))) {
199
            return 0;
200
        }
201
    }
202
    return 1;
203
}
204
 
205
// IDA: void __usercall Vector3Interpolate(br_vector3 *pDst@<EAX>, br_vector3 *pFrom@<EDX>, br_vector3 *pTo@<EBX>, br_scalar pP)
206
void Vector3Interpolate(br_vector3* pDst, br_vector3* pFrom, br_vector3* pTo, br_scalar pP) {
207
    LOG_TRACE("(%p, %p, %p, %f)", pDst, pFrom, pTo, pP);
208
 
209
    pDst->v[0] = (pTo->v[0] - pFrom->v[0]) * pP + pFrom->v[0];
210
    pDst->v[1] = (pTo->v[1] - pFrom->v[1]) * pP + pFrom->v[1];
211
    pDst->v[2] = (pTo->v[2] - pFrom->v[2]) * pP + pFrom->v[2];
212
}
213
 
214
// IDA: void __usercall EnsureGroundDetailVisible(br_vector3 *pNew_pos@<EAX>, br_vector3 *pGround_normal@<EDX>, br_vector3 *pOld_pos@<EBX>)
215
void EnsureGroundDetailVisible(br_vector3* pNew_pos, br_vector3* pGround_normal, br_vector3* pOld_pos) {
216
    br_scalar factor;
217
    br_scalar s;
218
    br_scalar dist;
219
    br_vector3 to_camera;
220
    LOG_TRACE("(%p, %p, %p)", pNew_pos, pGround_normal, pOld_pos);
221
 
222
    to_camera.v[0] = gCamera_to_world.m[3][0] - pOld_pos->v[0];
223
    to_camera.v[1] = gCamera_to_world.m[3][1] - pOld_pos->v[1];
224
    to_camera.v[2] = gCamera_to_world.m[3][2] - pOld_pos->v[2];
225
    dist = BrVector3Length(&to_camera);
226
    if (dist > BR_SCALAR_EPSILON) {
227
        factor = BrVector3Dot(pGround_normal, &to_camera) / dist;
228
        if (fabsf(factor) <= 0.01f) {
229
            s = 0.01f;
230
        } else {
231
            s = 0.01f / factor;
232
            if (s > 0.1f) {
233
                s = 0.1f;
234
            }
235
        }
236
        Vector3Interpolate(pNew_pos, pOld_pos, (br_vector3*)gCamera_to_world.m[3], s);
237
    }
238
}
239
 
240
// IDA: void __usercall MungeOilsHeightAboveGround(tOil_spill_info *pOil@<EAX>)
241
void MungeOilsHeightAboveGround(tOil_spill_info* pOil) {
242
    LOG_TRACE("(%p)", pOil);
243
 
244
    EnsureGroundDetailVisible(&pOil->actor->t.t.look_up.t, &pOil->actor->t.t.look_up.up, &pOil->pos);
245
}
246
 
247
// IDA: void __usercall MungeIndexedOilsHeightAboveGround(int pIndex@<EAX>)
248
void MungeIndexedOilsHeightAboveGround(int pIndex) {
249
    LOG_TRACE("(%d)", pIndex);
250
 
251
    MungeOilsHeightAboveGround(&gOily_spills[pIndex]);
252
}
253
 
254
// IDA: void __usercall SetInitialOilStuff(tOil_spill_info *pOil@<EAX>, br_model *pModel@<EDX>)
255
void SetInitialOilStuff(tOil_spill_info* pOil, br_model* pModel) {
256
    LOG_TRACE("(%p, %p)", pOil, pModel);
257
 
258
    pModel->vertices[0].p.v[0] = -0.1f;
259
    pModel->vertices[0].p.v[2] = -0.1f;
20 pmbaty 260
    pModel->vertices[1].p.v[0] =  0.1f;
1 pmbaty 261
    pModel->vertices[1].p.v[2] = -0.1f;
20 pmbaty 262
    pModel->vertices[2].p.v[0] =  0.1f;
263
    pModel->vertices[2].p.v[2] =  0.1f;
1 pmbaty 264
    pModel->vertices[3].p.v[0] = -0.1f;
20 pmbaty 265
    pModel->vertices[3].p.v[2] =  0.1f;
1 pmbaty 266
    pOil->actor->render_style = BR_RSTYLE_FACES;
267
    BrMaterialUpdate(pOil->actor->material, BR_MATU_ALL);
268
    BrModelUpdate(pModel, BR_MODU_ALL);
269
}
270
 
271
// IDA: void __usercall ProcessOilSpills(tU32 pFrame_period@<EAX>)
272
void ProcessOilSpills(tU32 pFrame_period) {
273
    int i;
274
    tU32 time;
275
    br_model* the_model;
276
    br_scalar grow_amount;
277
    //br_scalar initial_size; // Pierre-Marie Baty -- unused variable
278
    br_scalar this_size;
279
    br_vector3 v;
280
    tNet_message* message;
281
    LOG_TRACE("(%d)", pFrame_period);
282
 
283
    time = GetTotalTime();
284
    for (i = 0; i < COUNT_OF(gOily_spills); i++) {
285
        if (gOily_spills[i].car == NULL) {
286
            gOily_spills[i].actor->render_style = BR_RSTYLE_NONE;
287
        } else {
288
            the_model = gOily_spills[i].actor->model;
20 pmbaty 289
            if (gOily_spills[i].actor->render_style == BR_RSTYLE_NONE &&
290
                gOily_spills[i].spill_time <= time &&
291
                fabsf(gOily_spills[i].car->v.v[0]) < .01f &&
292
                fabsf(gOily_spills[i].car->v.v[1]) < .01f &&
293
                fabsf(gOily_spills[i].car->v.v[2]) < .01f) {
1 pmbaty 294
                if (gAction_replay_mode) {
295
                    SetInitialOilStuff(&gOily_spills[i], the_model);
296
                } else {
297
                    if (!OKToSpillOil(&gOily_spills[i])) {
298
                        gOily_spills[i].car = NULL;
299
                    } else {
300
                        gOily_spills[i].spill_time = time;
301
                        gOily_spills[i].actor->material->colour_map = gOil_pixies[gNext_oil_pixie];
302
                        gNext_oil_pixie++;
303
                        if (gNext_oil_pixie >= COUNT_OF(gOil_pixies)) {
304
                            gNext_oil_pixie = 0;
305
                        }
306
                        BrVector3Copy(&gOily_spills[i].original_pos, &gOily_spills[i].car->pos);
307
                        PipeSingleOilSpill(i,
308
                            &gOily_spills[i].actor->t.t.mat,
309
                            gOily_spills[i].full_size,
310
                            gOily_spills[i].grow_rate,
311
                            gOily_spills[i].spill_time,
312
                            gOily_spills[i].stop_time,
313
                            gOily_spills[i].car,
314
                            &gOily_spills[i].original_pos,
315
                            gOily_spills[i].actor->material->colour_map);
316
                        gOily_spills[i].stop_time = 0;
317
                        SetInitialOilStuff(&gOily_spills[i], the_model);
318
                        if (gNet_mode != eNet_mode_none) {
319
                            message = NetBuildMessage(30, 0);
320
                            message->contents.data.oil_spill.player = NetPlayerFromCar(gOily_spills[i].car)->ID;
321
                            message->contents.data.oil_spill.full_size = gOily_spills[i].full_size;
322
                            message->contents.data.oil_spill.grow_rate = gOily_spills[i].grow_rate;
323
                            message->contents.data.oil_spill.current_size = gOily_spills[i].current_size;
324
                            NetGuaranteedSendMessageToAllPlayers(gCurrent_net_game, message, NULL);
325
                        }
326
                    }
327
                }
328
            } else {
20 pmbaty 329
                if (gOily_spills[i].actor->render_style == BR_RSTYLE_FACES &&
330
                    (gOily_spills[i].stop_time == 0 || time < gOily_spills[i].stop_time)) {
1 pmbaty 331
                    BrVector3Sub(&v, &gOily_spills[i].original_pos, &gOily_spills[i].car->pos);
332
                    grow_amount = BrVector3LengthSquared(&v);
333
                    if (gOily_spills[i].stop_time != 0 || grow_amount <= 0.2f) {
334
                        this_size = 0.1f + (time - gOily_spills[i].spill_time) * gOily_spills[i].grow_rate;
335
                        if (this_size >= 0.1f) {
336
                            gOily_spills[i].actor->render_style = BR_RSTYLE_FACES;
337
                            if (this_size <= gOily_spills[i].full_size) {
338
                                the_model->vertices[0].p.v[0] = -this_size;
339
                                the_model->vertices[0].p.v[2] = -this_size;
340
                                the_model->vertices[1].p.v[0] = this_size;
341
                                the_model->vertices[1].p.v[2] = -this_size;
342
                                the_model->vertices[2].p.v[0] = this_size;
343
                                the_model->vertices[2].p.v[2] = this_size;
344
                                the_model->vertices[3].p.v[0] = -this_size;
345
                                the_model->vertices[3].p.v[2] = this_size;
346
                                gOily_spills[i].current_size = this_size;
347
                            } else {
348
                                the_model->vertices[0].p.v[0] = -gOily_spills[i].full_size;
349
                                the_model->vertices[0].p.v[2] = -gOily_spills[i].full_size;
350
                                the_model->vertices[1].p.v[0] = gOily_spills[i].full_size;
351
                                the_model->vertices[1].p.v[2] = -gOily_spills[i].full_size;
352
                                the_model->vertices[2].p.v[0] = gOily_spills[i].full_size;
353
                                the_model->vertices[2].p.v[2] = gOily_spills[i].full_size;
354
                                the_model->vertices[3].p.v[0] = -gOily_spills[i].full_size;
355
                                the_model->vertices[3].p.v[2] = gOily_spills[i].full_size;
356
                                gOily_spills[i].current_size = gOily_spills[i].full_size;
357
                            }
358
                            BrModelUpdate(the_model, BR_MODU_ALL);
359
                        } else {
360
                            gOily_spills[i].actor->render_style = BR_RSTYLE_NONE;
361
                        }
362
                    } else {
363
                        gOily_spills[i].stop_time = time;
364
                        continue;
365
                    }
366
                }
367
            }
368
        }
369
        if (gOily_spills[i].actor->render_style == BR_RSTYLE_FACES) {
370
            MungeOilsHeightAboveGround(&gOily_spills[i]);
371
        }
372
    }
373
}
374
 
375
// IDA: int __cdecl GetOilSpillCount()
376
int GetOilSpillCount(void) {
20 pmbaty 377
    //LOG_TRACE("()");
1 pmbaty 378
 
379
    return COUNT_OF(gOily_spills);
380
}
381
 
382
// IDA: void __usercall GetOilSpillDetails(int pIndex@<EAX>, br_actor **pActor@<EDX>, br_scalar *pSize@<EBX>)
383
void GetOilSpillDetails(int pIndex, br_actor** pActor, br_scalar* pSize) {
384
    LOG_TRACE("(%d, %p, %p)", pIndex, pActor, pSize);
385
 
386
    if (gOily_spills[pIndex].car != NULL) {
387
        *pActor = gOily_spills[pIndex].actor;
388
        *pSize = gOily_spills[pIndex].full_size;
389
    } else {
390
        *pActor = NULL;
391
    }
392
}
393
 
20 pmbaty 394
#define SQR(V) ((V)*(V))
1 pmbaty 395
 
396
// IDA: int __usercall PointInSpill@<EAX>(br_vector3 *pV@<EAX>, int pSpill@<EDX>)
397
int PointInSpill(br_vector3* pV, int pSpill) {
398
    LOG_TRACE("(%p, %d)", pV, pSpill);
399
 
400
    return gOily_spills[pSpill].current_size * gOily_spills[pSpill].current_size * 0.8f > SQR(pV->v[0] / WORLD_SCALE - gOily_spills[pSpill].actor->t.t.translate.t.v[0])
401
        && gOily_spills[pSpill].current_size * gOily_spills[pSpill].current_size * 0.8f > SQR(pV->v[2] / WORLD_SCALE - gOily_spills[pSpill].actor->t.t.translate.t.v[2])
402
        && fabsf(pV->v[1] / WORLD_SCALE - gOily_spills[pSpill].actor->t.t.translate.t.v[1]) < 0.1f;
403
}
404
 
405
// IDA: void __usercall GetOilFrictionFactors(tCar_spec *pCar@<EAX>, br_scalar *pFl_factor@<EDX>, br_scalar *pFr_factor@<EBX>, br_scalar *pRl_factor@<ECX>, br_scalar *pRr_factor)
406
void GetOilFrictionFactors(tCar_spec* pCar, br_scalar* pFl_factor, br_scalar* pFr_factor, br_scalar* pRl_factor, br_scalar* pRr_factor) {
407
    int i;
408
    br_vector3 wheel_world;
409
    LOG_TRACE("(%p, %p, %p, %p, %p)", pCar, pFl_factor, pFr_factor, pRl_factor, pRr_factor);
410
 
411
    *pFl_factor = 1.0f;
412
    *pFr_factor = 1.0f;
413
    *pRl_factor = 1.0f;
414
    *pRr_factor = 1.0f;
415
    switch (pCar->driver) {
416
    case eDriver_non_car_unused_slot:
417
    case eDriver_non_car:
418
        return;
419
    default:
420
        break;
421
    }
422
    if (pCar->shadow_intersection_flags != 0) {
423
        for (i = 0; i < COUNT_OF(gOily_spills); i++) {
424
            if (((1 << i) & pCar->shadow_intersection_flags) != 0 && gOily_spills[i].car != NULL) {
425
                BrMatrix34ApplyP(&wheel_world, &pCar->wpos[2], &pCar->car_master_actor->t.t.mat);
426
                if (PointInSpill(&wheel_world, i)) {
427
                    pCar->oil_remaining[2] = SRandomBetween(1.5f, 2.5f);
428
                }
429
                BrMatrix34ApplyP(&wheel_world, &pCar->wpos[3], &pCar->car_master_actor->t.t.mat);
430
                if (PointInSpill(&wheel_world, i)) {
431
                    pCar->oil_remaining[3] = SRandomBetween(1.5f, 2.5f);
432
                }
433
                BrMatrix34ApplyP(&wheel_world, &pCar->wpos[0], &pCar->car_master_actor->t.t.mat);
434
                if (PointInSpill(&wheel_world, i)) {
435
                    pCar->oil_remaining[0] = SRandomBetween(1.5f, 2.5f);
436
                }
437
                BrMatrix34ApplyP(&wheel_world, &pCar->wpos[1], &pCar->car_master_actor->t.t.mat);
438
                if (PointInSpill(&wheel_world, i)) {
439
                    pCar->oil_remaining[1] = SRandomBetween(1.5f, 2.5f);
440
                }
441
            }
442
        }
443
    }
444
    if (pCar->oil_remaining[2] != 0.0f) {
445
        *pFl_factor = SRandomBetween(0.01f, 0.15f);
446
    }
447
    if (pCar->oil_remaining[3] != 0.0f) {
448
        *pFr_factor = SRandomBetween(0.01f, 0.15f);
449
    }
450
    if (pCar->oil_remaining[0] != 0.0f) {
451
        *pRl_factor = SRandomBetween(0.01f, 0.15f);
452
    }
453
    if (pCar->oil_remaining[1] != 0.0f) {
454
        *pRr_factor = SRandomBetween(0.01f, 0.15f);
455
    }
456
}
457
 
458
// IDA: void __usercall AdjustOilSpill(int pIndex@<EAX>, br_matrix34 *pMat@<EDX>, br_scalar pFull_size, br_scalar pGrow_rate, tU32 pSpill_time, tU32 pStop_time, tCar_spec *pCar, br_vector3 *pOriginal_pos, br_pixelmap *pPixelmap)
459
void AdjustOilSpill(int pIndex, br_matrix34* pMat, br_scalar pFull_size, br_scalar pGrow_rate, tU32 pSpill_time, tU32 pStop_time, tCar_spec* pCar, br_vector3* pOriginal_pos, br_pixelmap* pPixelmap) {
460
    LOG_TRACE("(%d, %p, %f, %f, %d, %d, %p, %p, %p)", pIndex, pMat, pFull_size, pGrow_rate, pSpill_time, pStop_time, pCar, pOriginal_pos, pPixelmap);
461
 
462
    BrMatrix34Copy(&gOily_spills[pIndex].actor->t.t.mat, pMat);
463
    gOily_spills[pIndex].full_size = pFull_size;
464
    gOily_spills[pIndex].grow_rate = pGrow_rate;
465
    gOily_spills[pIndex].spill_time = pSpill_time;
466
    gOily_spills[pIndex].stop_time = pStop_time;
467
    gOily_spills[pIndex].car = pCar;
468
    BrVector3Copy(&gOily_spills[pIndex].original_pos, pOriginal_pos);
469
    gOily_spills[pIndex].actor->material->colour_map = pPixelmap;
470
    gOily_spills[pIndex].actor->render_style = BR_RSTYLE_NONE;
471
}
472
 
473
// IDA: void __usercall ReceivedOilSpill(tNet_contents *pContents@<EAX>)
474
void ReceivedOilSpill(tNet_contents* pContents) {
475
    int i;
476
    int oily_index;
477
    int oldest_one;
478
    tU32 the_time;
479
    tU32 oldest_time;
480
    tCar_spec* car;
481
    LOG_TRACE("(%p)", pContents);
482
 
483
    oldest_one = 0;
484
    car = NetCarFromPlayerID(pContents->data.oil_spill.player);
485
    if (car == NULL) {
486
        return;
487
    }
488
    oily_index = -1;
489
    the_time = GetTotalTime();
490
    oldest_time = GetTotalTime();
491
    for (i = 0; i < COUNT_OF(gOily_spills); i++) {
492
        if (gOily_spills[i].car == car && the_time < gOily_spills[i].spill_time + 5000) {
493
            return;
494
        }
495
    }
496
    for (i = 0; i < COUNT_OF(gOily_spills); i++) {
497
        if (gOily_spills[i].car == NULL) {
498
            oily_index = i;
499
            break;
500
        }
501
        if (gOily_spills[i].spill_time < oldest_time) {
502
            oldest_time = gOily_spills[i].spill_time;
503
            oldest_one = i;
504
        }
505
    }
506
    if (oily_index < 0) {
507
        oily_index = oldest_one;
508
    }
509
    gOily_spills[oily_index].car = car;
510
    gOily_spills[oily_index].spill_time = the_time;
511
    gOily_spills[oily_index].full_size = pContents->data.oil_spill.full_size;
512
    gOily_spills[oily_index].grow_rate = pContents->data.oil_spill.grow_rate;
513
    gOily_spills[oily_index].current_size = pContents->data.oil_spill.current_size;
514
    gOily_spills[oily_index].actor->render_style = BR_RSTYLE_NONE;
515
}