diff --git a/src/DETHRACE/common/finteray.c b/src/DETHRACE/common/finteray.c index 5aaf91c9..16170ca0 100644 --- a/src/DETHRACE/common/finteray.c +++ b/src/DETHRACE/common/finteray.c @@ -4,6 +4,7 @@ #include "car.h" #include "globvars.h" #include "harness/trace.h" +#include "raycast.h" #include "world.h" #include #include @@ -419,12 +420,13 @@ void CheckSingleFace(tFace_ref* pFace, br_vector3* ray_pos, br_vector3* ray_dir, this_material = pFace->material; *rt = 100.0; + d = pFace->normal.v[1] * ray_dir->v[1] + ray_dir->v[2] * pFace->normal.v[2] + ray_dir->v[0] * pFace->normal.v[0]; - if ((!this_material || (this_material->flags & 0x1800) != 0 || d <= 0.0) + if ((this_material == NULL || (this_material->flags & (BR_MATF_TWO_SIDED | BR_MATF_ALWAYS_VISIBLE )) != 0 || d <= 0.0) && (!this_material || !this_material->identifier || *this_material->identifier != '!' || !gPling_materials) && fabs(d) >= 0.00000023841858) { BrVector3Sub(&p, ray_pos, &pFace->v[0]); - numerator = pFace->normal.v[1] * p.v[1] + pFace->normal.v[2] * p.v[2] + pFace->normal.v[0] * p.v[0]; + numerator = BrVector3Dot(&pFace->normal, &p); if (!BadDiv__finteray(numerator, d)) { if (d > 0.0) { if (-numerator < -0.001 || -numerator > d + 0.003) { @@ -437,12 +439,8 @@ void CheckSingleFace(tFace_ref* pFace, br_vector3* ray_pos, br_vector3* ray_dir, if (t > 1.0) { t = 1.0; } - tv.v[0] = ray_dir->v[0] * t; - tv.v[1] = ray_dir->v[1] * t; - tv.v[2] = ray_dir->v[2] * t; - tv.v[0] = ray_pos->v[0] + tv.v[0]; - tv.v[1] = ray_pos->v[1] + tv.v[1]; - tv.v[2] = ray_pos->v[2] + tv.v[2]; + BrVector3Scale(&tv, ray_dir, t); + BrVector3Accumulate(&tv, ray_pos); axis_m = fabs(pFace->normal.v[0]) < fabs(pFace->normal.v[1]); if (fabs(pFace->normal.v[2]) > fabs(pFace->normal.v[axis_m])) { axis_m = 2; @@ -481,9 +479,7 @@ void CheckSingleFace(tFace_ref* pFace, br_vector3* ray_pos, br_vector3* ray_dir, *rt = t; *normal = pFace->normal; if (d > 0.0) { - normal->v[0] = -normal->v[0]; - normal->v[1] = -normal->v[1]; - normal->v[2] = -normal->v[2]; + BrVector3Negate(normal, normal); } } } @@ -663,61 +659,53 @@ int FindFacesInBox(tBounds* bnds, tFace_ref* face_list, int max_face) { j = 0; track_spec = &gProgram_state.track_spec; - a.v[0] = bnds->original_bounds.min.v[0] + bnds->original_bounds.max.v[0]; - a.v[1] = bnds->original_bounds.min.v[1] + bnds->original_bounds.max.v[1]; - a.v[2] = bnds->original_bounds.min.v[2] + bnds->original_bounds.max.v[2]; - b.v[0] = a.v[0] * 0.5; - b.v[1] = a.v[1] * 0.5; - b.v[2] = a.v[2] * 0.5; - BrMatrix34ApplyP(&bnds->box_centre, &b, bnds->mat); - b.v[0] = bnds->original_bounds.max.v[0] - bnds->original_bounds.min.v[0]; - b.v[1] = bnds->original_bounds.max.v[1] - bnds->original_bounds.min.v[1]; - b.v[2] = bnds->original_bounds.max.v[2] - bnds->original_bounds.min.v[2]; - bnds->radius = sqrt(b.v[1] * b.v[1] + b.v[2] * b.v[2] + b.v[0] * b.v[0]) / 2.0; + BrVector3Add(&a, &bnds->original_bounds.min, &bnds->original_bounds.max); + BrVector3Scale(&a, &a, 0.5f); + BrMatrix34ApplyP(&bnds->box_centre, &a, bnds->mat); + BrVector3Sub(&b, &bnds->original_bounds.max, &bnds->original_bounds.min); + bnds->radius = BrVector3Length(&b) / 2.f; BrMatrix34ApplyP(&bnds->real_bounds.min, &bnds->original_bounds.min, bnds->mat); - bnds->real_bounds.max = bnds->real_bounds.min; + BrVector3Copy(&bnds->real_bounds.max, &bnds->real_bounds.min); for (i = 0; i < 3; ++i) { c[i].v[0] = bnds->mat->m[i][0] * b.v[i]; c[i].v[1] = bnds->mat->m[i][1] * b.v[i]; c[i].v[2] = bnds->mat->m[i][2] * b.v[i]; } for (i = 0; i < 3; ++i) { - bnds->real_bounds.min.v[i] = (double)(c[2].v[i] < 0.0) * c[2].v[i] - + (double)(c[1].v[i] < 0.0) * c[1].v[i] - + (double)(c[0].v[i] < 0.0) * c[0].v[i] - + bnds->real_bounds.min.v[i]; - bnds->real_bounds.max.v[i] = (double)(c[2].v[i] > 0.0) * c[2].v[i] - + (double)(c[1].v[i] > 0.0) * c[1].v[i] - + (double)(c[0].v[i] > 0.0) * c[0].v[i] - + bnds->real_bounds.max.v[i]; + bnds->real_bounds.min.v[i] += MIN(c[0].v[i], 0.f) + + MIN(c[1].v[i], 0.f) + + MIN(c[2].v[i], 0.f); + bnds->real_bounds.max.v[i] += MAX(c[0].v[i], 0.f) + + MAX(c[1].v[i], 0.f) + + MAX(c[2].v[i], 0.f); } XZToColumnXZ(&cx_min, &cz_min, bnds->real_bounds.min.v[0], bnds->real_bounds.min.v[2], track_spec); XZToColumnXZ(&cx_max, &cz_max, bnds->real_bounds.max.v[0], bnds->real_bounds.max.v[2], track_spec); - if (cx_min) { + if (cx_min != 0) { cx_min--; } - if (cz_min) { + if (cz_min != 0) { cz_min--; } - if (track_spec->ncolumns_x > cx_max + 1) { + if (cx_max + 1 < track_spec->ncolumns_x) { cx_max++; } - if (track_spec->ncolumns_z > cz_max + 1) { + if (cz_max + 1 < track_spec->ncolumns_z) { cz_max++; } - for (x = cx_min; cx_max >= x; ++x) { - for (z = cz_min; cz_max >= z; ++z) { - if (track_spec->columns[z][x]) { - if (track_spec->blends[z][x]) { + for (x = cx_min; x <= cx_max; x++) { + for (z = cz_min; z <= cz_max; z++) { + if (track_spec->columns[z][x] != NULL) { + if (track_spec->blends[z][x] != NULL) { track_spec->blends[z][x]->render_style = BR_RSTYLE_FACES; } - j = max_face - ActorBoxPick(bnds, track_spec->columns[z][x], NULL, NULL, &face_list[j], max_face - j, 0); - if (track_spec->blends[z][x]) { + j = max_face - ActorBoxPick(bnds, track_spec->columns[z][x], model_unk1, material_unk1, &face_list[j], max_face - j, NULL); + if (track_spec->blends[z][x] != NULL) { track_spec->blends[z][x]->render_style = BR_RSTYLE_NONE; } } - if (track_spec->lollipops[z][x]) { - j = max_face - ActorBoxPick(bnds, track_spec->lollipops[z][x], NULL, NULL, &face_list[j], max_face - j, 0); + if (track_spec->lollipops[z][x] != NULL) { + j = max_face - ActorBoxPick(bnds, track_spec->lollipops[z][x], model_unk1, material_unk1, &face_list[j], max_face - j, NULL); } } } @@ -754,25 +742,29 @@ int ActorBoxPick(tBounds* bnds, br_actor* ap, br_model* model, br_material* mate i = 0; test_children = 1; - if (ap->model) { + if (ap->model != NULL) { this_model = ap->model; } else { this_model = model; } - if (ap->material) { + if (ap->material != NULL) { this_material = ap->material; } else { this_material = material; } - if (ap->render_style == 1) { + if (ap->render_style == BR_RSTYLE_NONE) { return max_face; } - if (ap->identifier && *ap->identifier == '&') { - if (!ap->children - && (ap->type != BR_ACTOR_MODEL || !BoundsTransformTest(&this_model->bounds, &bnds->real_bounds, &ap->t.t.mat))) { - return max_face; + if (ap->identifier != NULL && ap->identifier[0] == '&') { + if (ap->children == NULL) { + if (ap->type != BR_ACTOR_MODEL) { + return max_face; + } + if (!BoundsTransformTest(&this_model->bounds, &bnds->real_bounds, &ap->t.t.mat)) { + return max_face; + } } - if (pMat) { + if (pMat != NULL) { BrMatrix34Mul(&mat, &ap->t.t.mat, pMat); pMat = &mat; } else { @@ -781,7 +773,8 @@ int ActorBoxPick(tBounds* bnds, br_actor* ap, br_model* model, br_material* mate BrMatrix34LPInverse(&invmat, &ap->t.t.mat); BrMatrix34Mul(&mat2, bnds->mat, &invmat); new_bounds.mat = &mat2; - new_bounds.original_bounds = bnds->original_bounds; + BrVector3Copy(&new_bounds.original_bounds.min, &bnds->original_bounds.min); + BrVector3Copy(&new_bounds.original_bounds.max, &bnds->original_bounds.max); BrMatrix34ApplyP(&new_bounds.box_centre, &bnds->box_centre, &invmat); new_bounds.radius = bnds->radius; GetNewBoundingBox(&new_bounds.real_bounds, &new_bounds.original_bounds, new_bounds.mat); @@ -810,11 +803,11 @@ int ActorBoxPick(tBounds* bnds, br_actor* ap, br_model* model, br_material* mate i += max_face - n; max_face = n; } - } else if (ap->type >= 5u && ap->type <= 6u) { + } else if (ap->type == BR_ACTOR_BOUNDS || ap->type == BR_ACTOR_BOUNDS_CORRECT) { test_children = BoundsOverlapTest__finteray(&bnds->real_bounds, (br_bounds*)ap->type_data); } if (test_children) { - for (a = ap->children; a; a = next_a) { + for (a = ap->children; a != NULL; a = next_a) { next_a = a->next; n = ActorBoxPick(bnds, a, this_model, this_material, &face_list[i], max_face, pMat); i += max_face - n; diff --git a/src/DETHRACE/common/oil.c b/src/DETHRACE/common/oil.c index 041ef0b0..b3857227 100644 --- a/src/DETHRACE/common/oil.c +++ b/src/DETHRACE/common/oil.c @@ -1,14 +1,18 @@ #include "oil.h" #include "brender/brender.h" +#include "finteray.h" #include "globvars.h" +#include "globvrpb.h" #include "harness/trace.h" #include "loading.h" +#include "network.h" +#include "piping.h" #include "utility.h" #include #include char* gOil_pixie_names[1] = { "OIL.PIX" }; -int gNext_oil_pixie; +int gNext_oil_pixie = 0; br_scalar gZ_buffer_diff; br_scalar gMin_z_diff; br_pixelmap* gOil_pixies[1]; @@ -32,11 +36,11 @@ void InitOilSpills() { the_material->ka = 0.99f; the_material->kd = 0.0f; the_material->ks = 0.0f; - the_material->power = 0.0; + the_material->power = 0.0f; the_material->index_base = 0; the_material->flags |= BR_MATF_LIGHT; the_material->flags |= BR_MATF_PERSPECTIVE; - the_material->flags |= 0x00000004; + the_material->flags |= BR_MATF_SMOOTH; the_material->index_range = 0; the_material->colour_map = NULL; BrMatrix23Identity(&the_material->map_transform); @@ -45,36 +49,24 @@ void InitOilSpills() { the_model = BrModelAllocate(NULL, 4, 2); the_model->flags |= BR_MODF_KEEP_ORIGINAL; - the_model->faces->vertices[0] = 2; - the_model->faces->vertices[1] = 1; - the_model->faces->vertices[2] = 0; - the_model->faces->material = NULL; - the_model->faces->smoothing = 1; + the_model->faces[0].vertices[0] = 2; + the_model->faces[0].vertices[1] = 1; + the_model->faces[0].vertices[2] = 0; + the_model->faces[0].material = NULL; + the_model->faces[0].smoothing = 1; the_model->faces[1].vertices[0] = 3; the_model->faces[1].vertices[1] = 2; the_model->faces[1].vertices[2] = 0; the_model->faces[1].material = NULL; the_model->faces[1].smoothing = 1; - the_model->vertices[0].p.v[0] = -1.0f; - the_model->vertices[0].p.v[1] = 0.0f; - the_model->vertices[0].p.v[2] = -1.0f; - the_model->vertices->map.v[0] = 0.0f; - the_model->vertices->map.v[1] = 1.0f; - the_model->vertices[1].p.v[0] = 1.0f; - the_model->vertices[1].p.v[1] = 0.0f; - the_model->vertices[1].p.v[2] = 1.0f; - the_model->vertices[1].map.v[0] = 0.0f; - the_model->vertices[1].map.v[1] = 0.0f; - the_model->vertices[2].p.v[0] = 1.0f; - the_model->vertices[2].p.v[1] = 0.0f; - the_model->vertices[2].p.v[2] = -1.0f; - the_model->vertices[2].map.v[0] = 1.0f; - the_model->vertices[2].map.v[1] = 0.0f; - the_model->vertices[3].p.v[0] = -1.0f; - the_model->vertices[3].p.v[1] = 0.0f; - the_model->vertices[3].p.v[2] = 1.0f; - the_model->vertices[3].map.v[0] = 1.0f; - the_model->vertices[3].map.v[1] = 1.0f; + BrVector3Set(&the_model->vertices[0].p, -1.f, 0.f, -1.f); + BrVector2Set(&the_model->vertices[0].map, 0.f, 1.f); + BrVector3Set(&the_model->vertices[1].p, 1.f, 0.f, 1.f); + BrVector2Set(&the_model->vertices[1].map, 0.f, 0.f); + BrVector3Set(&the_model->vertices[2].p, 1.f, 0.f, -1.f); + BrVector2Set(&the_model->vertices[2].map, 1.f, 0.f); + BrVector3Set(&the_model->vertices[3].p, -1.f, 0.f, 1.f); + BrVector2Set(&the_model->vertices[3].map, 1.f, 1.f); gOily_spills[i].actor = BrActorAllocate(BR_ACTOR_MODEL, NULL); gOily_spills[i].actor->model = the_model; gOily_spills[i].actor->render_style = BR_RSTYLE_NONE; @@ -110,7 +102,7 @@ void QueueOilSpill(tCar_spec* pCar) { oldest_time = GetTotalTime(); for (i = 0; i < COUNT_OF(gOily_spills); i++) { - if (gOily_spills[i].car == pCar && the_time < (gOily_spills[i].spill_time + 5000)) { + if (gOily_spills[i].car == pCar && the_time < gOily_spills[i].spill_time + 5000) { return; } } @@ -132,7 +124,7 @@ void QueueOilSpill(tCar_spec* pCar) { gOily_spills[oily_index].car = pCar; gOily_spills[oily_index].spill_time = the_time + 500; gOily_spills[oily_index].full_size = SRandomBetween(.35f, .6f); - gOily_spills[oily_index].grow_rate = SRandomBetween(30e-4f, 1e-4f); + gOily_spills[oily_index].grow_rate = SRandomBetween(3e-5f, 10e-5f); gOily_spills[oily_index].current_size = .1f; gOily_spills[oily_index].actor->render_style = BR_RSTYLE_NONE; } @@ -156,7 +148,56 @@ int OKToSpillOil(tOil_spill_info* pOil) { tFace_ref the_list[10]; tFace_ref* face_ref; LOG_TRACE("(%p)", pOil); - NOT_IMPLEMENTED(); + + car = pOil->car; + if (car->driver >= eDriver_net_human && car->damage_units[eDamage_engine].damage_level <= 98 && car->damage_units[eDamage_transmission].damage_level <= 98) { + return 0; + } + angle_to_rotate_by = IRandomBetween(0, 0xffff); + kev_bounds.original_bounds.min.v[0] = -pOil->full_size; + kev_bounds.original_bounds.min.v[1] = 1.5f * car->car_model_actors[car->principal_car_actor].actor->model->bounds.min.v[1]; + kev_bounds.original_bounds.min.v[2] = -pOil->full_size; + kev_bounds.original_bounds.max.v[0] = pOil->full_size; + kev_bounds.original_bounds.max.v[1] = car->car_model_actors[car->principal_car_actor].actor->model->bounds.max.v[1]; + kev_bounds.original_bounds.max.v[2] = pOil->full_size; + BrMatrix34PreRotateY(&pOil->actor->t.t.mat, angle_to_rotate_by); + kev_bounds.mat = &car->car_master_actor->t.t.mat; + face_count = FindFacesInBox(&kev_bounds, the_list, COUNT_OF(the_list)); + BrVector3Set(&v, .0f, .2f, .0f); + BrMatrix34ApplyP(&ray_pos, &v, &car->car_master_actor->t.t.mat); + BrVector3Set(&ray_dir, 0.f, kev_bounds.original_bounds.min.v[1] - kev_bounds.original_bounds.max.v[1], 0.f);\ + if (face_count == 0) { + return 0; + } + found_one = 0; + for (i = 0; i < face_count; i++) { + face_ref = &the_list[i]; + if (!found_one) { + CheckSingleFace(face_ref, &ray_pos, &ray_dir, &normal, &distance); + if (distance < 100.f) { + found_one = 1; + BrVector3Copy((br_vector3*)pOil->actor->t.t.mat.m[1], &normal); + BrVector3Set(&v, 0.f, 0.f, 1.f); + BrVector3Cross((br_vector3*)pOil->actor->t.t.mat.m[0], &normal, &v); + BrVector3Set(&v, 1.f, 0.f, 0.f); + BrVector3Cross((br_vector3*)pOil->actor->t.t.mat.m[2], &normal, &v); + BrVector3Scale(&v, &ray_dir, distance); + BrVector3Add(&pOil->pos, &ray_pos, &v); + BrMatrix34PreRotateY(&pOil->actor->t.t.mat, angle_to_rotate_by); + } + } + } + if (!found_one || normal.v[1] < .97f) { + return 0; + } + for (i = 0; i < face_count; i++) { + face_ref = &the_list[i]; + mr_dotty = BrVector3Dot(&face_ref->normal, &normal); + if (mr_dotty < .98f && (mr_dotty > .8f || !NormalSideOfPlane(&pOil->actor->t.t.translate.t, &face_ref->normal, face_ref->d))) { + return 0; + } + } + return 1; } // IDA: void __usercall Vector3Interpolate(br_vector3 *pDst@, br_vector3 *pFrom@, br_vector3 *pTo@, br_scalar pP) @@ -182,7 +223,7 @@ void EnsureGroundDetailVisible(br_vector3* pNew_pos, br_vector3* pGround_normal, dist = BrVector3Length(&to_camera); if (dist > BR_SCALAR_EPSILON) { factor = BrVector3Dot(pGround_normal, &to_camera) / dist; - if (fabs(factor) <= 0.01f) { + if (fabsf(factor) <= 0.01f) { s = 0.01f; } else { s = 0.01f / factor; @@ -236,7 +277,97 @@ void ProcessOilSpills(tU32 pFrame_period) { br_vector3 v; tNet_message* message; LOG_TRACE("(%d)", pFrame_period); - STUB_ONCE(); + + time = GetTotalTime(); + for (i = 0; i < COUNT_OF(gOily_spills); i++) { + if (gOily_spills[i].car == NULL) { + gOily_spills[i].actor->render_style = BR_RSTYLE_NONE; + } else { + the_model = gOily_spills[i].actor->model; + if (gOily_spills[i].actor->render_style == BR_RSTYLE_NONE && + gOily_spills[i].spill_time <= time && + fabsf(gOily_spills[i].car->v.v[0]) < .01f && + fabsf(gOily_spills[i].car->v.v[1]) < .01f && + fabsf(gOily_spills[i].car->v.v[2]) < .01f) { + if (gAction_replay_mode) { + SetInitialOilStuff(&gOily_spills[i], the_model); + } else { + if (!OKToSpillOil(&gOily_spills[i])) { + gOily_spills[i].car = NULL; + } else { + gOily_spills[i].spill_time = time; + gOily_spills[i].actor->material->colour_map = gOil_pixies[gNext_oil_pixie]; + gNext_oil_pixie++; + if (gNext_oil_pixie >= COUNT_OF(gOil_pixies)) { + gNext_oil_pixie = 0; + } + BrVector3Copy(&gOily_spills[i].original_pos, &gOily_spills[i].car->pos); + PipeSingleOilSpill(i, + &gOily_spills[i].actor->t.t.mat, + gOily_spills[i].full_size, + gOily_spills[i].grow_rate, + gOily_spills[i].spill_time, + gOily_spills[i].stop_time, + gOily_spills[i].car, + &gOily_spills[i].original_pos, + gOily_spills[i].actor->material->colour_map); + gOily_spills[i].stop_time = 0; + SetInitialOilStuff(&gOily_spills[i], the_model); + if (gNet_mode != eNet_mode_none) { + message = NetBuildMessage(30, 0); + message->contents.data.oil_spill.player = NetPlayerFromCar(gOily_spills[i].car)->ID; + message->contents.data.oil_spill.full_size = gOily_spills[i].full_size; + message->contents.data.oil_spill.grow_rate = gOily_spills[i].grow_rate; + message->contents.data.oil_spill.current_size = gOily_spills[i].current_size; + NetGuaranteedSendMessageToAllPlayers(gCurrent_net_game, message, NULL); + } + } + } + } else { + if (gOily_spills[i].actor->render_style == BR_RSTYLE_FACES && + (gOily_spills[i].stop_time == 0 || time < gOily_spills[i].stop_time)) { + BrVector3Sub(&v, &gOily_spills[i].original_pos, &gOily_spills[i].car->pos); + grow_amount = BrVector3LengthSquared(&v); + if (gOily_spills[i].stop_time != 0 || grow_amount <= 0.2f) { + this_size = 0.1f + (time - gOily_spills[i].spill_time) * gOily_spills[i].grow_rate; + if (this_size >= 0.1f) { + gOily_spills[i].actor->render_style = BR_RSTYLE_FACES; + if (this_size <= gOily_spills[i].full_size) { + the_model->vertices[0].p.v[0] = -this_size; + the_model->vertices[0].p.v[2] = -this_size; + the_model->vertices[1].p.v[0] = this_size; + the_model->vertices[1].p.v[2] = -this_size; + the_model->vertices[2].p.v[0] = this_size; + the_model->vertices[2].p.v[2] = this_size; + the_model->vertices[3].p.v[0] = -this_size; + the_model->vertices[3].p.v[2] = this_size; + gOily_spills[i].current_size = this_size; + } else { + the_model->vertices[0].p.v[0] = -gOily_spills[i].full_size; + the_model->vertices[0].p.v[2] = -gOily_spills[i].full_size; + the_model->vertices[1].p.v[0] = gOily_spills[i].full_size; + the_model->vertices[1].p.v[2] = -gOily_spills[i].full_size; + the_model->vertices[2].p.v[0] = gOily_spills[i].full_size; + the_model->vertices[2].p.v[2] = gOily_spills[i].full_size; + the_model->vertices[3].p.v[0] = -gOily_spills[i].full_size; + the_model->vertices[3].p.v[2] = gOily_spills[i].full_size; + gOily_spills[i].current_size = gOily_spills[i].full_size; + } + BrModelUpdate(the_model, BR_MODU_ALL); + } else { + gOily_spills[i].actor->render_style = BR_RSTYLE_NONE; + } + } else { + gOily_spills[i].stop_time = time; + continue; + } + } + } + } + if (gOily_spills[i].actor->render_style == BR_RSTYLE_FACES) { + MungeOilsHeightAboveGround(&gOily_spills[i]); + } + } } // IDA: int __cdecl GetOilSpillCount() @@ -254,17 +385,19 @@ void GetOilSpillDetails(int pIndex, br_actor** pActor, br_scalar* pSize) { *pActor = gOily_spills[pIndex].actor; *pSize = gOily_spills[pIndex].full_size; } else { - *pActor = 0; + *pActor = NULL; } } +#define SQR(V) ((V)*(V)) + // IDA: int __usercall PointInSpill@(br_vector3 *pV@, int pSpill@) int PointInSpill(br_vector3* pV, int pSpill) { LOG_TRACE("(%p, %d)", pV, pSpill); - return gOily_spills[pSpill].current_size * gOily_spills[pSpill].current_size * 0.8f > (pV->v[0] / WORLD_SCALE - gOily_spills[pSpill].actor->t.t.mat.m[3][0]) * (pV->v[0] / WORLD_SCALE - gOily_spills[pSpill].actor->t.t.mat.m[3][0]) - && gOily_spills[pSpill].current_size * gOily_spills[pSpill].current_size * 0.8f > (pV->v[2] / WORLD_SCALE - gOily_spills[pSpill].actor->t.t.mat.m[3][2]) * (pV->v[2] / WORLD_SCALE - gOily_spills[pSpill].actor->t.t.mat.m[3][2]) - && fabs(pV->v[1] / WORLD_SCALE - gOily_spills[pSpill].actor->t.t.mat.m[3][1]) < 0.1f; + 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]) + && 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]) + && fabsf(pV->v[1] / WORLD_SCALE - gOily_spills[pSpill].actor->t.t.translate.t.v[1]) < 0.1f; } // IDA: void __usercall GetOilFrictionFactors(tCar_spec *pCar@, br_scalar *pFl_factor@, br_scalar *pFr_factor@, br_scalar *pRl_factor@, br_scalar *pRr_factor) @@ -273,10 +406,10 @@ void GetOilFrictionFactors(tCar_spec* pCar, br_scalar* pFl_factor, br_scalar* pF br_vector3 wheel_world; LOG_TRACE("(%p, %p, %p, %p, %p)", pCar, pFl_factor, pFr_factor, pRl_factor, pRr_factor); - *pFl_factor = 1.0; - *pFr_factor = 1.0; - *pRl_factor = 1.0; - *pRr_factor = 1.0; + *pFl_factor = 1.0f; + *pFr_factor = 1.0f; + *pRl_factor = 1.0f; + *pRr_factor = 1.0f; switch (pCar->driver) { case eDriver_non_car_unused_slot: case eDriver_non_car: @@ -286,7 +419,7 @@ void GetOilFrictionFactors(tCar_spec* pCar, br_scalar* pFl_factor, br_scalar* pF } if (pCar->shadow_intersection_flags != 0) { for (i = 0; i < COUNT_OF(gOily_spills); i++) { - if (((1 << i) & pCar->shadow_intersection_flags) != 0 && gOily_spills[i].car) { + if (((1 << i) & pCar->shadow_intersection_flags) != 0 && gOily_spills[i].car != NULL) { BrMatrix34ApplyP(&wheel_world, &pCar->wpos[2], &pCar->car_master_actor->t.t.mat); if (PointInSpill(&wheel_world, i)) { pCar->oil_remaining[2] = SRandomBetween(1.5f, 2.5f); @@ -323,7 +456,16 @@ void GetOilFrictionFactors(tCar_spec* pCar, br_scalar* pFl_factor, br_scalar* pF // IDA: void __usercall 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) 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) { 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); - NOT_IMPLEMENTED(); + + BrMatrix34Copy(&gOily_spills[pIndex].actor->t.t.mat, pMat); + gOily_spills[pIndex].full_size = pFull_size; + gOily_spills[pIndex].grow_rate = pGrow_rate; + gOily_spills[pIndex].spill_time = pSpill_time; + gOily_spills[pIndex].stop_time = pStop_time; + gOily_spills[pIndex].car = pCar; + BrVector3Copy(&gOily_spills[pIndex].original_pos, pOriginal_pos); + gOily_spills[pIndex].actor->material->colour_map = pPixelmap; + gOily_spills[pIndex].actor->render_style = BR_RSTYLE_NONE; } // IDA: void __usercall ReceivedOilSpill(tNet_contents *pContents@) @@ -335,5 +477,37 @@ void ReceivedOilSpill(tNet_contents* pContents) { tU32 oldest_time; tCar_spec* car; LOG_TRACE("(%p)", pContents); - NOT_IMPLEMENTED(); + + oldest_one = 0; + car = NetCarFromPlayerID(pContents->data.oil_spill.player); + if (car == NULL) { + return; + } + oily_index = -1; + the_time = GetTotalTime(); + oldest_time = GetTotalTime(); + for (i = 0; i < COUNT_OF(gOily_spills); i++) { + if (gOily_spills[i].car == car && the_time < gOily_spills[i].spill_time + 5000) { + return; + } + } + for (i = 0; i < COUNT_OF(gOily_spills); i++) { + if (gOily_spills[i].car == NULL) { + oily_index = i; + break; + } + if (gOily_spills[i].spill_time < oldest_time) { + oldest_time = gOily_spills[i].spill_time; + oldest_one = i; + } + } + if (oily_index < 0) { + oily_index = oldest_one; + } + gOily_spills[oily_index].car = car; + gOily_spills[oily_index].spill_time = the_time; + gOily_spills[oily_index].full_size = pContents->data.oil_spill.full_size; + gOily_spills[oily_index].grow_rate = pContents->data.oil_spill.grow_rate; + gOily_spills[oily_index].current_size = pContents->data.oil_spill.current_size; + gOily_spills[oily_index].actor->render_style = BR_RSTYLE_NONE; } diff --git a/src/DETHRACE/common/raycast.c b/src/DETHRACE/common/raycast.c index 57115c4f..702581b7 100644 --- a/src/DETHRACE/common/raycast.c +++ b/src/DETHRACE/common/raycast.c @@ -252,8 +252,7 @@ int DRScenePick2D(br_actor* world, br_actor* camera, dr_pick2d_cbfn* callback, v camera_data = (br_camera*)camera->type_data; DRActorToRoot(camera, world, &camera_tfm); BrMatrix34Inverse(&gPick_model_to_view__raycast, &camera_tfm); - scale = cos(BrAngleToRadian(camera_data->field_of_view / 2)); - scale = scale / sin(BrAngleToRadian(camera_data->field_of_view / 2)); + scale = cosf(BrAngleToRadian(camera_data->field_of_view / 2)) / sinf(BrAngleToRadian(camera_data->field_of_view / 2)); BrMatrix34PostScale(&gPick_model_to_view__raycast, scale / camera_data->aspect, scale, 1.0f); return ActorPick2D(world, model_unk1, material_unk1, callback, arg); diff --git a/src/DETHRACE/common/raycast.h b/src/DETHRACE/common/raycast.h index 54dff509..1b134056 100644 --- a/src/DETHRACE/common/raycast.h +++ b/src/DETHRACE/common/raycast.h @@ -14,6 +14,10 @@ extern br_scalar gHighest_y_below; extern br_actor* gY_picking_camera; extern br_scalar gLowest_y_above; +// Added, probably can be replaced with NULL +extern br_model* model_unk1; +extern br_material* material_unk1; + int DRActorToRoot(br_actor* a, br_actor* world, br_matrix34* m); void InitRayCasting();