diff --git a/.clang-format b/.clang-format index 03f98ce7..8a558bf5 100644 --- a/.clang-format +++ b/.clang-format @@ -7,7 +7,7 @@ AlignConsecutiveAssignments: false AlignConsecutiveDeclarations: false AlignEscapedNewlinesLeft: false AlignOperands: false -AlignTrailingComments: false +AlignTrailingComments: true AllowAllParametersOfDeclarationOnNextLine: true AllowShortBlocksOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false diff --git a/src/BRSRC13/CORE/V1DB/prepmesh.c b/src/BRSRC13/CORE/V1DB/prepmesh.c index e634841f..ddd68c39 100644 --- a/src/BRSRC13/CORE/V1DB/prepmesh.c +++ b/src/BRSRC13/CORE/V1DB/prepmesh.c @@ -8,6 +8,7 @@ #include "CORE/MATH/vector.h" #include "CORE/STD/brmath.h" #include "CORE/STD/brstdlib.h" +#include "harness/hooks.h" #include "harness/trace.h" #include @@ -600,139 +601,104 @@ void BrModelUpdate(br_model* model, br_uint_16 flags) { br_face* fp; LOG_TRACE("(%p, %d)", model, flags); - if (!(model->flags & BR_MODF_PREPREPARED)) { + if (model->flags & BR_MODF_PREPREPARED) { + return; + } + if (!model->faces || !model->vertices) { + BrFailure("BrModelUpdate: model has no faces or vertices (%s)", model->identifier ? model->identifier : ""); + } + if (flags & BR_MODU_UNKNOWN) { + flags |= BR_MODU_NORMALS; + } + if (model->flags & (BR_MODF_KEEP_ORIGINAL | BR_MODF_GENERATE_TAGS)) { + model->flags |= BR_MODF_UPDATEABLE; + } + if (!(model->flags & BR_MODF_CUSTOM_BOUNDS) && (flags & (BR_MODU_MATERIALS | BR_MODU_GROUPS | BR_MODU_NORMALS))) { + PrepareBoundingRadius(model); + PrepareBoundingBox(model); + } + if (!model->prepared || flags & 0xFFD0) { if (!model->faces || !model->vertices) { - BrFailure("BrModelUpdate: model has no faces or vertices (%s)", model->identifier ? model->identifier : ""); + return; } - if (flags & BR_MODU_UNKNOWN) { - flags |= BR_MODU_NORMALS; - } - if (model->flags & (BR_MODF_KEEP_ORIGINAL | BR_MODF_GENERATE_TAGS)) { - model->flags |= BR_MODF_UPDATEABLE; - } - if (!(model->flags & 0x400) && (flags & (BR_MODU_MATERIALS | BR_MODU_GROUPS | BR_MODU_NORMALS))) { - PrepareBoundingRadius(model); - PrepareBoundingBox(model); - } - if (!model->prepared || flags & 0xFFD0) { - if (!model->faces || !model->vertices) { - return; + PrepareFaceNormals(model); + f = 0; + fp = model->faces; + model->flags &= ~MODF_USES_DEFAULT; + for (f = 0; f < model->nfaces; f++) { + fp = &model->faces[f]; + if (!fp->material) { + model->flags |= MODF_USES_DEFAULT; } - PrepareFaceNormals(model); - f = 0; - fp = model->faces; - model->flags &= ~MODF_USES_DEFAULT; - for (f = 0; f < model->nfaces; f++) { - fp = &model->faces[f]; - if (!fp->material) { - model->flags |= MODF_USES_DEFAULT; - } - for (v = 0; v < 3; v++) { - if (fp->vertices[v] >= model->nvertices) { - BrFailure("face references invalid vertex f=%d v=%d", f, v); + for (v = 0; v < 3; v++) { + if (fp->vertices[v] >= model->nvertices) { + BrFailure("face references invalid vertex f=%d v=%d", f, v); + } + } + } + + PrepareGroups(model); + v11m = model->prepared; + + if (v11m) { + for (g = 0; g < v11m->ngroups; g++) { + // prepareEdges(&v11m->groups[g], model); + } + } else { + LOG_DEBUG("has prepared model FALSE"); + } + } else { + + // some additional code paths might exist, but maybe not used? + if (flags != BR_MODU_NORMALS) { + TELL_ME_IF_WE_PASS_THIS_WAY(); + } + + v11m = model->prepared; + + if (model->vertices && (flags & BR_MODU_NORMALS)) { + for (g = 0; g < v11m->ngroups; g++) { + for (v = 0; v < v11m->groups[g].nvertices; v++) { + fvp = &v11m->groups[g].vertices[v]; + vp = model->vertices + v11m->groups[g].vertex_user[v]; + + if (flags & BR_MODU_NORMALS) { + fvp->p.v[0] = vp->p.v[0] - model->pivot.v[0]; + fvp->p.v[1] = vp->p.v[1] - model->pivot.v[1]; + fvp->p.v[2] = vp->p.v[2] - model->pivot.v[2]; } } } - - PrepareGroups(model); - v11m = (v11model*)model->prepared; - - if (v11m) { - for (g = 0; g < v11m->ngroups; g++) { - // prepareEdges(&v11m->groups[g], model); - } - } else { - LOG_DEBUG("has prepared model FALSE"); - } - } else { - TELL_ME_IF_WE_PASS_THIS_WAY(); - // v11m = (v11model*)model->prepared; - // if (model->vertices && flags & 0xF) { - // for (g = 0; g < v11m->ngroups; g++) { - // // v5 = 0; - // // v39 = 0; - // // v30 = 0; - // // v40 = 0; - // // v29 = 36 * i; - - // for (v = 0; v < v11m->groups[g].nvertices; v++) { - // fvp = &v11m->groups[g].vertices[v]; - // vp = &model->vertices[v11m->groups[g].vertex_user[v]]; // v8->vertex_user[v5]]; - // if (flags & BR_MODU_NORMALS) { - // fvp->p.v[0] = vp->p.v[0] - model->pivot.v[0]; - // fvp->p.v[1] = vp->p.v[1] - model->pivot.v[1]; - // fvp->p.v[2] = vp->p.v[2] - model->pivot.v[2]; - // } - // if (flags & BR_MODU_EDGES) { - // v31 = _byteswap_ulong(*(_DWORD*)&vp->index); - // v11m->groups[g].vertex_colours[v] = v31; - // } - // if (flags & BR_MODU_RADIUS) { - // fvp->map.v[0] = vp->map.v[0]; - // fvp->map.v[1] = vp->map.v[1]; - // } - // if (flags & BR_MODU_GROUPS && model->flags & 0x200) { - // fvp->n.v[0] = vp->n.v[0]; - // fvp->n.v[1] = vp->n.v[1]; - // fvp->n.v[2] = vp->n.v[2]; - // } - // ++v5; - // v39 += 32; - // v30 += 4; - - // ++v; - // } - // } - // } - // if (model->faces && flags & BR_MODU_MATERIALS) { - // v35 = 0; - // v27 = 0; - // while (v11m->ngroups > v27) { - // v9 = 0; - // v10 = 0; - // v28 = v35; - // for (j = 0;; j += 4) { - // v12 = (v11group*)((char*)v11m->groups + v28); // not sure about this one - // if (v9 >= v12->nfaces) { - // break; - // } - // v31 = 40 * v12->face_user[v10]; - // fp = (br_face*)((char*)model->faces + v31); - // if (flags & 0x20) { - // v32 = fp->index << 24; - // v31 = (fp->red << 16) | v32; - // v32 = fp->grn << 8; - // v12->face_colours[j / 4] = fp->blu | v32 | v31; - // } - // ++v9; - // ++v10; - // } - // ++v27; - // v35 += 36; - // } - // } - // if (flags & 1) { - // if (!(model->flags & 0x200)) { - // RegenerateVertexNormals(v11m); - // } - // RegenerateFaceNormals(v11m); - // } } - if (!(model->flags & BR_MODF_UPDATEABLE)) { - if (model->faces) { - BrResFree(model->faces); + if (flags & BR_MODU_NORMALS) { + if (!(model->flags & BR_MODF_CUSTOM_NORMALS)) { + RegenerateVertexNormals(v11m); } - if (model->vertices) { - BrResFree(model->vertices); - } - model->vertices = 0; - model->nfaces = 0; - model->nvertices = 0; - model->faces = 0; + RegenerateFaceNormals(v11m); } } + + if (!(model->flags & BR_MODF_UPDATEABLE)) { + if (model->faces) { + BrResFree(model->faces); + } + if (model->vertices) { + BrResFree(model->vertices); + } + model->vertices = NULL; + model->nfaces = 0; + model->nvertices = 0; + model->faces = NULL; + } + + if (model->stored) { + ((br_object*)model->stored)->dispatch->_free((br_object*)model->stored); + model->stored = NULL; + } + + Harness_Hook_BrModelUpdate(model); } // IDA: void __usercall BrModelClear(br_model *model@) diff --git a/src/BRSRC13/CORE/V1DB/render.c b/src/BRSRC13/CORE/V1DB/render.c index b3b54bd1..28d178b1 100644 --- a/src/BRSRC13/CORE/V1DB/render.c +++ b/src/BRSRC13/CORE/V1DB/render.c @@ -17,15 +17,8 @@ void BrDbModelRender(br_actor* actor, br_model* model, br_material* material, vo br_token_value tv[5]; LOG_TRACE("(%p, %p, %p, %p, %d, %d, %d)", actor, model, material, render_data, style, on_screen, use_custom); - // if (strcmp(model->identifier, "NEWEAGLE.DAT") == 0) { - // LOG_DEBUG("rendering eagle!"); - // } else { - // return; - // } - v1db.model_to_screen_valid = 0; if (use_custom && (model->flags & BR_MODF_CUSTOM)) { - TELL_ME_IF_WE_PASS_THIS_WAY(); model->custom(actor, model, material, render_data, style, on_screen); return; } @@ -296,21 +289,21 @@ void SetViewport(br_pixelmap* buffer) { // IDA: void __cdecl BrZbSceneRenderBegin(br_actor *world, br_actor *camera, br_pixelmap *colour_buffer, br_pixelmap *depth_buffer) void BrZbSceneRenderBegin(br_actor* world, br_actor* camera, br_pixelmap* colour_buffer, br_pixelmap* depth_buffer) { - //LOG_TRACE("(%p, %p, %p, %p)", world, camera, colour_buffer, depth_buffer); + // LOG_TRACE("(%p, %p, %p, %p)", world, camera, colour_buffer, depth_buffer); - //BrDbSceneRenderBegin(world, camera); + // BrDbSceneRenderBegin(world, camera); Harness_Hook_BrZbSceneRenderBegin(world, camera, colour_buffer, depth_buffer); } // IDA: void __cdecl BrZbSceneRenderAdd(br_actor *tree) void BrZbSceneRenderAdd(br_actor* tree) { - //LOG_TRACE("(%p)", tree); + // LOG_TRACE("(%p)", tree); sceneRenderAdd(tree); } // IDA: void __cdecl BrZbSceneRenderEnd() void BrZbSceneRenderEnd() { - //LOG_TRACE("()"); + // LOG_TRACE("()"); Harness_Hook_BrZbSceneRenderEnd(); } @@ -357,7 +350,8 @@ br_primitive_cbfn* BrZsPrimitiveCallbackSet(br_primitive_cbfn* new_cbfn) { // IDA: void __cdecl BrZbModelRender(br_actor *actor, br_model *model, br_material *material, br_uint_8 style, int on_screen, int use_custom) void BrZbModelRender(br_actor* actor, br_model* model, br_material* material, br_uint_8 style, int on_screen, int use_custom) { LOG_TRACE("(%p, %p, %p, %d, %d, %d)", actor, model, material, style, on_screen, use_custom); - NOT_IMPLEMENTED(); + + BrDbModelRender(actor, model, material, 0, style, on_screen, use_custom); } // IDA: void __cdecl BrZsModelRender(br_actor *actor, br_model *model, br_material *material, br_order_table *order_table, br_uint_8 style, int on_screen, int use_custom) diff --git a/src/BRSRC13/include/brender/br_defs.h b/src/BRSRC13/include/brender/br_defs.h index fa38fc0a..cfd2a735 100644 --- a/src/BRSRC13/include/brender/br_defs.h +++ b/src/BRSRC13/include/brender/br_defs.h @@ -3,7 +3,9 @@ // Inspired by BRender SDK includes (https://rr2000.cwaboard.co.uk/R4/BRENDER/BRENDER.zip) -#define PI 3.14159265358979323846 +#include // sqrtf + +#define PI 3.14159265358979323846 #define TAU 6.283185307179586 #define BR_MAC3(a, b, c, d, e, f) ((a) * (b) + (c) * (d) + (e) * (f)) diff --git a/src/BRSRC13/include/brender/brender.h b/src/BRSRC13/include/brender/brender.h index 520485ea..73636bba 100644 --- a/src/BRSRC13/include/brender/brender.h +++ b/src/BRSRC13/include/brender/brender.h @@ -88,6 +88,8 @@ void BrMatrix34PostShearX(br_matrix34* mat, br_scalar sy, br_scalar sz); void BrMatrix34PostShearY(br_matrix34* mat, br_scalar sx, br_scalar sz); void BrMatrix34PostShearZ(br_matrix34* mat, br_scalar sx, br_scalar sy); void BrMatrix34PreShearX(br_matrix34* mat, br_scalar sy, br_scalar sz); +void BrMatrix34PreRotateY(br_matrix34* mat, br_angle ry); +void BrMatrix34PreRotateZ(br_matrix34* mat, br_angle rz); // BrMatrix4 void BrMatrix4Copy(br_matrix4* A, br_matrix4* B); diff --git a/src/DETHRACE/common/car.c b/src/DETHRACE/common/car.c index 24617bbd..395e9f71 100644 --- a/src/DETHRACE/common/car.c +++ b/src/DETHRACE/common/car.c @@ -15,6 +15,7 @@ #include "harness/config.h" #include "harness/trace.h" #include "netgame.h" +#include "network.h" #include "oil.h" #include "opponent.h" #include "pd/sys.h" @@ -45,7 +46,7 @@ void (*ControlCar[6])(tCar_spec*, br_scalar) = { &ControlCar5, NULL }; -int gControl__car = 3; // suffix added to avoid duplicate symbol +int gControl__car = 3; // suffix added to avoid duplicate symbol int gFace_num__car = 1; // suffix added to avoid duplicate symbol br_angle gOld_yaw__car; // suffix added to avoid duplicate symbol br_angle gOld_zoom; @@ -83,9 +84,9 @@ int gOpponent_viewing_mode; int gNet_player_to_view_index; int gDouble_pling_water; int gStop_opponents_moving; -float gDefensive_powerup_factor[6]; -float gOffensive_powerup_factor[6]; -float gEngine_powerup_factor[6] = { 1.3, 1.9, 2.5, 3.2, 4.0, 10.0 }; +float gDefensive_powerup_factor[6] = { 1.0f, 0.825f, 0.65f, 0.475f, 0.3f, 0.01f }; +float gOffensive_powerup_factor[6] = { 1.0f, 1.5f, 2.0f, 3.0f, 5.0f, 10.0f }; +float gEngine_powerup_factor[6] = { 1.3f, 1.9f, 2.5f, 3.2f, 4.0f, 10.0f }; br_angle gPanning_camera_angle; br_scalar gPanning_camera_height; int gFace_count; @@ -108,8 +109,8 @@ int gCamera_frozen; int gMaterial_index; int gInTheSea; int gCamera_mode; -br_scalar gOur_yaw__car; // suffix added to avoid duplicate symbol -br_scalar gGravity__car; // suffix added to avoid duplicate symbol +br_scalar gOur_yaw__car; // suffix added to avoid duplicate symbol +br_scalar gGravity__car; // suffix added to avoid duplicate symbol br_vector3 gNew_ground_normal__car; // suffix added to avoid duplicate symbol char gNon_car_spec_list[100]; tU32 gMechanics_time_sync; @@ -749,7 +750,6 @@ void ControlOurCar(tU32 pTime_difference) { } time = GetTotalTime(); if (car->damage_units[eDamage_steering].damage_level > 40) { - LOG_PANIC("this is not expected"); if (car->end_steering_damage_effect) { if (car->end_steering_damage_effect > time || car->damage_units[eDamage_steering].damage_level == 99) { car->keys.left = car->false_key_left; @@ -774,7 +774,6 @@ void ControlOurCar(tU32 pTime_difference) { } } if (car->damage_units[eDamage_transmission].damage_level > 40) { - LOG_PANIC("this is not expected"); if (car->end_trans_damage_effect) { if (car->end_trans_damage_effect > time || car->damage_units[eDamage_transmission].damage_level == 99) { car->gear = 0; @@ -1273,7 +1272,7 @@ int CollideCarWithWall(tCollision_info* car, br_scalar dt) { GetFacesInBox(car); } if (car->collision_flag) { - CrashEarnings((tCar_spec*)car, 0); + CrashEarnings((tCar_spec*)car, NULL); } BrMatrix34TApplyV(&car->velocity_car_space, &car->v, &car->oldmat); car->frame_collision_flag += car->collision_flag; @@ -1661,37 +1660,37 @@ void CalcForce(tCar_spec* c, br_scalar dt) { br_scalar scale; LOG_TRACE("(%p, %f)", c, dt); - int v72; // [esp+24h] [ebp-1C8h] - double v73; // [esp+2Ch] [ebp-1C0h] - float v74; // [esp+34h] [ebp-1B8h] - float v75; // [esp+38h] [ebp-1B4h] - float v76; // [esp+3Ch] [ebp-1B0h] - float v77; // [esp+40h] [ebp-1ACh] - float v78; // [esp+44h] [ebp-1A8h] - float v79; // [esp+48h] [ebp-1A4h] - float v80; // [esp+4Ch] [ebp-1A0h] MAPDST - float v82; // [esp+50h] [ebp-19Ch] MAPDST - float v84; // [esp+54h] [ebp-198h] - float v85; // [esp+58h] [ebp-194h] MAPDST - float v87; // [esp+5Ch] [ebp-190h] MAPDST - float v98; // [esp+88h] [ebp-164h] - float v99; // [esp+8Ch] [ebp-160h] + int v72; // [esp+24h] [ebp-1C8h] + double v73; // [esp+2Ch] [ebp-1C0h] + float v74; // [esp+34h] [ebp-1B8h] + float v75; // [esp+38h] [ebp-1B4h] + float v76; // [esp+3Ch] [ebp-1B0h] + float v77; // [esp+40h] [ebp-1ACh] + float v78; // [esp+44h] [ebp-1A8h] + float v79; // [esp+48h] [ebp-1A4h] + float v80; // [esp+4Ch] [ebp-1A0h] MAPDST + float v82; // [esp+50h] [ebp-19Ch] MAPDST + float v84; // [esp+54h] [ebp-198h] + float v85; // [esp+58h] [ebp-194h] MAPDST + float v87; // [esp+5Ch] [ebp-190h] MAPDST + float v98; // [esp+88h] [ebp-164h] + float v99; // [esp+8Ch] [ebp-160h] br_vector3 v102; // [esp+98h] [ebp-154h] br_vector3 v103; // [esp+A4h] [ebp-148h] - int v105; // [esp+B8h] [ebp-134h] - float v106; // [esp+C0h] [ebp-12Ch] + int v105; // [esp+B8h] [ebp-134h] + float v106; // [esp+C0h] [ebp-12Ch] br_vector3 v107; // [esp+C4h] [ebp-128h] - float v108; // [esp+D0h] [ebp-11Ch] - float v109; // [esp+D4h] [ebp-118h] - float v116; // [esp+F8h] [ebp-F4h] - br_vector3 B; // [esp+FCh] [ebp-F0h] BYREF - br_scalar pV; // [esp+10Ch] [ebp-E0h] + float v108; // [esp+D0h] [ebp-11Ch] + float v109; // [esp+D4h] [ebp-118h] + float v116; // [esp+F8h] [ebp-F4h] + br_vector3 B; // [esp+FCh] [ebp-F0h] BYREF + br_scalar pV; // [esp+10Ch] [ebp-E0h] br_vector3 v123; // [esp+130h] [ebp-BCh] - float v125; // [esp+16Ch] [ebp-80h] - float v128; // [esp+18Ch] [ebp-60h] - float v129; // [esp+190h] [ebp-5Ch] - float v134; // [esp+1D8h] [ebp-14h] - float v135; // [esp+1DCh] [ebp-10h] + float v125; // [esp+16Ch] [ebp-80h] + float v128; // [esp+18Ch] [ebp-60h] + float v129; // [esp+190h] [ebp-5Ch] + float v134; // [esp+1D8h] [ebp-14h] + float v135; // [esp+1DCh] [ebp-10h] br_vector3 v136; // [esp+1E0h] [ebp-Ch] BrVector3Set(&v136, 0, 0, 0); @@ -2914,7 +2913,90 @@ void CrushAndDamageCar(tCar_spec* c, br_vector3* pPosition, br_vector3* pForce_c br_matrix34 m; br_scalar fudge_multiplier; LOG_TRACE("(%p, %p, %p, %p)", c, pPosition, pForce_car_space, car2); - STUB_ONCE(); + + if (car2 != NULL) { + car2->who_last_hit_me = c; + c->who_last_hit_me = car2; + } + if (c->driver > eDriver_non_car) { + fudge_multiplier = gNet_mode == eNet_mode_none || gNet_softness[gCurrent_net_game->type] == 1.0f ? 1.0f : gNet_softness[gCurrent_net_game->type]; + BrVector3Sub(&car_to_cam, &c->pos, (br_vector3*)gCamera_to_world.m[3]); + ts = BrVector3LengthSquared(&car_to_cam); + if (c->driver != eDriver_oppo || ts <= 200.0f) { + if (car2) { + if (car2->driver > eDriver_non_car) { + TwoCarsHitEachOther(c, car2); + } + if (c->driver >= eDriver_net_human) { + fudge_multiplier = gDefensive_powerup_factor[c->power_up_levels[0]] * 1.2f * fudge_multiplier; + } + if (car2->driver >= eDriver_net_human) { + if (gNet_mode + && (gCurrent_net_game->type == eNet_game_type_fight_to_death || gCurrent_net_game->type == eNet_game_type_car_crusher)) { + fudge_multiplier = gOffensive_powerup_factor[car2->power_up_levels[2]] * gNet_offensive[gCurrent_net_game->type] * car2->damage_multiplier * fudge_multiplier; + } else { + fudge_multiplier = gOffensive_powerup_factor[car2->power_up_levels[2]] * car2->damage_multiplier * fudge_multiplier; + } + } + if (c->driver == eDriver_oppo && car2->driver == eDriver_oppo) { + fudge_multiplier = fudge_multiplier * 0.2f; + } + if (car2->driver <= eDriver_non_car) { + car2 = NULL; + } else { + fudge_multiplier = fudge_multiplier / ((car2->car_model_actors[car2->principal_car_actor].crush_data.softness_factor + 0.7f) / 0.7f); + } + } + BrVector3InvScale(&position, pPosition, WORLD_SCALE); + BrVector3Scale(&force, pForce_car_space, fudge_multiplier * 0.03f); + ts = BrVector3LengthSquared(&force); + if (c->driver <= eDriver_non_car || !c->invulnerable) { + c->damage_magnitude_accumulator = c->damage_magnitude_accumulator + ts; + } + if (c->driver < eDriver_net_human) { + BrVector3Scale(&force_for_bodywork, &force, 1.5f); + } else { + if (c->collision_mass_multiplier != 1.0) { + BrVector3InvScale(&force, &force, c->collision_mass_multiplier); + } + BrVector3Scale(&force_for_bodywork, &force, 0.5f); + if (c->driver == eDriver_local_human) { + DoPratcamHit(&force); + } + } + if (gNet_mode == eNet_mode_host && (gCurrent_net_game->type == eNet_game_type_tag || gCurrent_net_game->type == eNet_game_type_foxy) && car2 + && c->driver >= eDriver_net_human && car2->driver >= eDriver_net_human) { + if (gNet_players[gIt_or_fox].car != c || car2->knackered) { + if (gNet_players[gIt_or_fox].car == car2 && !c->knackered) { + CarInContactWithItOrFox(NetPlayerFromCar(c)); + } + } else { + CarInContactWithItOrFox(NetPlayerFromCar(car2)); + } + } + if (gNet_mode != eNet_mode_client || !car2) { + DamageSystems(c, &position, &force, car2 != NULL); + } + if (c->driver <= eDriver_non_car || !c->invulnerable) { + for (i = 0; i < c->car_actor_count; i++) { + 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)) { + CrushModel(c, i, c->car_model_actors[i].actor, &position, &force_for_bodywork, &c->car_model_actors[i].crush_data); + } + } + } + if (car2 && car2->driver == eDriver_local_human && ts > 0.003f) { + PipeSingleCarIncident(ts, c, &position); + } + if (!car2 && c->driver == eDriver_local_human && ts > 0.003f) { + BrMatrix34Copy(&m, &c->car_master_actor->t.t.mat); + m.m[3][0] /= WORLD_SCALE; + m.m[3][1] /= WORLD_SCALE; + m.m[3][2] /= WORLD_SCALE; + BrMatrix34ApplyP(&pos_w, &position, &m); + PipeSingleWallIncident(ts, &pos_w); + } + } + } } // IDA: int __usercall ExpandBoundingBox@(tCar_spec *c@) @@ -2927,7 +3009,43 @@ int ExpandBoundingBox(tCar_spec* c) { int l; br_matrix34 mat; LOG_TRACE("(%p)", c); - NOT_IMPLEMENTED(); + + l = 0; + min_z = c->bounds[1].min.v[2]; + max_z = c->bounds[1].max.v[2]; + old_pos = *(br_vector3*)&c->oldmat.m[3][0]; + CrushBoundingBox(c, 0); + for (l = 0; l < 5; l++) { + if (TestForCarInSensiblePlace(c)) { + break; + } + if (c->old_point.v[2] <= 0.0f) { + dist = min_z - c->bounds[1].min.v[2]; + } else { + dist = c->bounds[1].max.v[2] - max_z; + } + if (dist >= 0.0f) { + dist = dist + 0.005f; + BrVector3Scale(&c->old_norm, &c->old_norm, dist); + BrMatrix34ApplyV(&tv, &c->old_norm, &c->car_master_actor->t.t.mat); + c->oldmat.m[3][0] = c->oldmat.m[3][0] + tv.v[0]; + c->oldmat.m[3][1] = c->oldmat.m[3][1] + tv.v[1]; + c->oldmat.m[3][2] = c->oldmat.m[3][2] + tv.v[2]; + l++; + } else { + l = 5; + } + } + if (l < 5) { + return 1; + } + *(br_vector3*)&c->oldmat.m[3][0] = old_pos; + c->bounds[1].min.v[2] = min_z; + c->bounds[1].max.v[2] = max_z; + if (c->driver == eDriver_local_human) { + NewTextHeadupSlot(4, 0, 1000, -4, GetMiscString(6)); + } + return 0; } // IDA: void __usercall CrushBoundingBox(tCar_spec *c@, int crush_only@) @@ -2937,7 +3055,63 @@ void CrushBoundingBox(tCar_spec* c, int crush_only) { int i; br_actor* actor; LOG_TRACE("(%p, %d)", c, crush_only); - NOT_IMPLEMENTED(); + + if (c == NULL) { + return; + } + actor = c->car_model_actors[c->principal_car_actor].actor; + max.v[0] = c->wpos[2].v[2] - c->non_driven_wheels_circum / 6.2f; + min.v[0] = c->driven_wheels_circum / 6.2f + c->wpos[0].v[2]; + max.v[0] = max.v[0] / WORLD_SCALE; + min.v[0] = min.v[0] / WORLD_SCALE; + for (i = 0; i < actor->model->nvertices; i++) { + if (actor->model->vertices[i].p.v[2] < max.v[0]) { + max.v[0] = actor->model->vertices[i].p.v[2]; + } + if (actor->model->vertices[i].p.v[2] > min.v[0]) { + min.v[0] = actor->model->vertices[i].p.v[2]; + } + } + max.v[0] = max.v[0] * WORLD_SCALE; + min.v[0] = min.v[0] * WORLD_SCALE; + if (crush_only) { + if (c->bounds[1].min.v[2] > max.v[0]) { + max.v[0] = c->bounds[1].min.v[2]; + } + if (c->bounds[1].max.v[2] < min.v[0]) { + min.v[0] = c->bounds[1].max.v[2]; + } + } else { + if (c->max_bounds[1].min.v[2] > max.v[0]) { + max.v[0] = c->max_bounds[1].min.v[2]; + } + if (c->max_bounds[1].max.v[2] < min.v[0]) { + min.v[0] = c->max_bounds[1].max.v[2]; + } + } + c->bounds[1].min.v[2] = max.v[0]; + c->bounds[1].max.v[2] = min.v[0]; + for (i = 0; i < c->extra_point_num; i++) { + 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]) { + if (c->original_extra_points_z[i] <= min.v[0]) { + if (c->original_extra_points_z[i] >= max.v[0]) { + c->extra_points[i].v[2] = c->original_extra_points_z[i]; + } else { + c->extra_points[i].v[2] = max.v[0]; + } + } else { + c->extra_points[i].v[2] = min.v[0]; + } + if (c->extra_points[i].v[2] > min.v[0]) { + c->extra_points[i].v[2] = min.v[0]; + } + if (c->extra_points[i].v[2] < max.v[0]) { + c->extra_points[i].v[2] = max.v[0]; + } + } else { + c->extra_points[i].v[2] = c->original_extra_points_z[i]; + } + } } // 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) diff --git a/src/DETHRACE/common/controls.c b/src/DETHRACE/common/controls.c index 2958c6ea..311223d7 100644 --- a/src/DETHRACE/common/controls.c +++ b/src/DETHRACE/common/controls.c @@ -96,207 +96,256 @@ char* gEdit_mode_names[10] = { "Bonnet", "Options", }; + // order is: { None, CTRL, ALT, CTRL+ALT, SHIFT, CTRL+SHIFT, ALT+SHIFT, CTRL+ALT+SHIFT } tEdit_func* gEdit_funcs[10][18][8] = { - { // eEdit_mode_cheat - { 0 }, // F5 - { 0 }, // F6 - { 0 }, // F7 - { 0 }, // F8 - { 0 }, // F10 - { 0 }, // F11 - { 0 }, // F12 - { 0 }, // 0 - { 0 }, // 1 - { 0 }, // 2 - { 0 }, // 3 - { 0 }, // 4 - { 0 }, // 5 - { 0 }, // 6 - { 0 }, // 7 - { 0 }, // 8 - { 0 }, // 9 - { 0 }, // not used + { + // eEdit_mode_cheat + { 0 }, // F5 + { 0 }, // F6 + { 0 }, // F7 + { 0 }, // F8 + { 0 }, // F10 + { 0 }, // F11 + { 0 }, // F12 + { 0 }, // 0 + { 0 }, // 1 + { 0 }, // 2 + { 0 }, // 3 + { 0 }, // 4 + { 0 }, // 5 + { 0 }, // 6 + { 0 }, // 7 + { 0 }, // 8 + { 0 }, // 9 + { 0 }, // not used }, - { // eEdit_mode_acc - { 0 }, // F5 - { 0 }, // F6 - { 0 }, // F7 - { 0 }, // F8 - { 0 }, // F10 - { 0 }, // F11 - { 0 }, // F12 - { 0 }, // 0 - { 0 }, // 1 - { 0 }, // 2 - { 0 }, // 3 - { 0 }, // 4 - { 0 }, // 5 - { 0 }, // 6 - { 0 }, // 7 - { 0 }, // 8 - { 0 }, // 9 - { 0 }, // not used + { + // eEdit_mode_acc + { 0 }, // F5 + { 0 }, // F6 + { 0 }, // F7 + { 0 }, // F8 + { 0 }, // F10 + { 0 }, // F11 + { 0 }, // F12 + { 0 }, // 0 + { 0 }, // 1 + { 0 }, // 2 + { 0 }, // 3 + { 0 }, // 4 + { 0 }, // 5 + { 0 }, // 6 + { 0 }, // 7 + { 0 }, // 8 + { 0 }, // 9 + { 0 }, // not used }, - { // eEdit_mode_spec_vol - { 0 }, // F5 - { 0 }, // F6 - { 0 }, // F7 - { 0 }, // F8 - { 0 }, // F10 - { 0 }, // F11 - { 0 }, // F12 - { 0 }, // 0 - { 0 }, // 1 - { 0 }, // 2 - { 0 }, // 3 - { 0 }, // 4 - { 0 }, // 5 - { 0 }, // 6 - { 0 }, // 7 - { 0 }, // 8 - { 0 }, // 9 - { 0 }, // not used + { + // eEdit_mode_spec_vol + { 0 }, // F5 + { 0 }, // F6 + { 0 }, // F7 + { 0 }, // F8 + { 0 }, // F10 + { 0 }, // F11 + { 0 }, // F12 + { 0 }, // 0 + { 0 }, // 1 + { 0 }, // 2 + { 0 }, // 3 + { 0 }, // 4 + { 0 }, // 5 + { 0 }, // 6 + { 0 }, // 7 + { 0 }, // 8 + { 0 }, // 9 + { 0 }, // not used }, - { // eEdit_mode_ped - { 0 }, // F5 - { 0 }, // F6 - { 0 }, // F7 - { 0 }, // F8 - { 0 }, // F10 - { 0 }, // F11 - { 0 }, // F12 - { 0 }, // 0 - { 0 }, // 1 - { 0 }, // 2 - { 0 }, // 3 - { 0 }, // 4 - { 0 }, // 5 - { 0 }, // 6 - { 0 }, // 7 - { 0 }, // 8 - { 0 }, // 9 - { 0 }, // not used + { + // eEdit_mode_ped + { 0 }, // F5 + { 0 }, // F6 + { 0 }, // F7 + { 0 }, // F8 + { 0 }, // F10 + { 0 }, // F11 + { 0 }, // F12 + { 0 }, // 0 + { 0 }, // 1 + { 0 }, // 2 + { 0 }, // 3 + { 0 }, // 4 + { 0 }, // 5 + { 0 }, // 6 + { 0 }, // 7 + { 0 }, // 8 + { 0 }, // 9 + { 0 }, // not used }, - { // eEdit_mode_opp - { 0 }, // F5 - { 0 }, // F6 - { 0 }, // F7 - { 0 }, // F8 - { 0 }, // F10 - { 0 }, // F11 - { 0 }, // F12 - { 0 }, // 0 - { 0 }, // 1 - { 0 }, // 2 - { 0 }, // 3 - { 0 }, // 4 - { 0 }, // 5 - { 0 }, // 6 - { 0 }, // 7 - { 0 }, // 8 - { 0 }, // 9 - { 0 }, // not used + { + // eEdit_mode_opp + { 0 }, // F5 + { 0 }, // F6 + { 0 }, // F7 + { 0 }, // F8 + { 0 }, // F10 + { 0 }, // F11 + { 0 }, // F12 + { 0 }, // 0 + { 0 }, // 1 + { 0 }, // 2 + { 0 }, // 3 + { 0 }, // 4 + { 0 }, // 5 + { 0 }, // 6 + { 0 }, // 7 + { 0 }, // 8 + { 0 }, // 9 + { 0 }, // not used }, - { // eEdit_mode_pratcam - { 0 }, // F5 - { 0 }, // F6 - { 0 }, // F7 - { 0 }, // F8 - { 0 }, // F10 - { 0 }, // F11 - { 0 }, // F12 - { 0 }, // 0 - { 0 }, // 1 - { 0 }, // 2 - { 0 }, // 3 - { 0 }, // 4 - { 0 }, // 5 - { 0 }, // 6 - { 0 }, // 7 - { 0 }, // 8 - { 0 }, // 9 - { 0 }, // not used + { + // eEdit_mode_pratcam + { 0 }, // F5 + { 0 }, // F6 + { 0 }, // F7 + { 0 }, // F8 + { 0 }, // F10 + { 0 }, // F11 + { 0 }, // F12 + { 0 }, // 0 + { 0 }, // 1 + { 0 }, // 2 + { 0 }, // 3 + { 0 }, // 4 + { 0 }, // 5 + { 0 }, // 6 + { 0 }, // 7 + { 0 }, // 8 + { 0 }, // 9 + { 0 }, // not used }, - { // eEdit_mode_depth - { 0 }, // F5 - { 0 }, // F6 - { 0 }, // F7 - { 0 }, // F8 - { 0 }, // F10 - { 0 }, // F11 - { 0 }, // F12 - { 0 }, // 0 - { 0 }, // 1 - { 0 }, // 2 - { 0 }, // 3 - { 0 }, // 4 - { 0 }, // 5 - { 0 }, // 6 - { 0 }, // 7 - { 0 }, // 8 - { 0 }, // 9 - { 0 }, // not used + { + // eEdit_mode_depth + { 0 }, // F5 + { 0 }, // F6 + { 0 }, // F7 + { 0 }, // F8 + { 0 }, // F10 + { 0 }, // F11 + { 0 }, // F12 + { 0 }, // 0 + { 0 }, // 1 + { 0 }, // 2 + { 0 }, // 3 + { 0 }, // 4 + { 0 }, // 5 + { 0 }, // 6 + { 0 }, // 7 + { 0 }, // 8 + { 0 }, // 9 + { 0 }, // not used }, - { // eEdit_mode_damage - { 0 }, // F5 - { 0 }, // F6 - { 0 }, // F7 - { 0 }, // F8 - { 0 }, // F10 - { 0 }, // F11 - { 0 }, // F12 - { 0 }, // 0 - { 0 }, // 1 - { 0 }, // 2 - { 0 }, // 3 - { 0 }, // 4 - { 0 }, // 5 - { 0 }, // 6 - { 0 }, // 7 - { 0 }, // 8 - { 0 }, // 9 - { 0 }, // not used + { + // eEdit_mode_damage + { 0 }, // F5 + { 0 }, // F6 + { 0 }, // F7 + { 0 }, // F8 + { 0 }, // F10 + { 0 }, // F11 + { 0 }, // F12 + { 0 }, // 0 + { 0 }, // 1 + { 0 }, // 2 + { 0 }, // 3 + { 0 }, // 4 + { 0 }, // 5 + { 0 }, // 6 + { 0 }, // 7 + { 0 }, // 8 + { 0 }, // 9 + { 0 }, // not used }, - { // eEdit_mode_bonnet - { 0 }, // F5 - { 0 }, // F6 - { 0 }, // F7 - { 0 }, // F8 - { 0 }, // F10 - { 0 }, // F11 - { 0 }, // F12 - { 0 }, // 0 - { 0 }, // 1 - { 0 }, // 2 - { 0 }, // 3 - { 0 }, // 4 - { 0 }, // 5 - { 0 }, // 6 - { 0 }, // 7 - { 0 }, // 8 - { 0 }, // 9 - { 0 }, // not used + { + // eEdit_mode_bonnet + { 0 }, // F5 + { 0 }, // F6 + { 0 }, // F7 + { 0 }, // F8 + { 0 }, // F10 + { 0 }, // F11 + { 0 }, // F12 + { 0 }, // 0 + { 0 }, // 1 + { 0 }, // 2 + { 0 }, // 3 + { 0 }, // 4 + { 0 }, // 5 + { 0 }, // 6 + { 0 }, // 7 + { 0 }, // 8 + { 0 }, // 9 + { 0 }, // not used }, - { // eEdit_mode_options - { 0 }, // F5 - { 0 }, // F6 - { 0 }, // F7 - { 0 }, // F8 - { 0 }, // F10 - { 0 }, // F11 - { 0 }, // F12 - { 0 }, // 0 - { CycleCarSimplificationLevel, NULL, NULL, NULL, CycleCarTexturingLevel, }, // 1 - { ToggleShadow, NULL, NULL, NULL, ToggleSmoke, }, // 2 - { CycleWallTexturingLevel, NULL, NULL, NULL, CycleRoadTexturingLevel, }, // 3 - { ToggleSky, NULL, NULL, NULL, ToggleDepthCueing, }, // 4 - { CycleYonFactor, NULL, NULL, NULL, ToggleAccessoryRendering, }, // 5 - { DecreaseYon, NULL, NULL, NULL, IncreaseYon, }, // 6 - { CycleSoundDetailLevel, }, // 7 - { 0 }, // 8 - { 0 }, // 9 - { 0 }, // not used + { + // eEdit_mode_options + { 0 }, // F5 + { 0 }, // F6 + { 0 }, // F7 + { 0 }, // F8 + { 0 }, // F10 + { 0 }, // F11 + { 0 }, // F12 + { 0 }, // 0 + { + CycleCarSimplificationLevel, + NULL, + NULL, + NULL, + CycleCarTexturingLevel, + }, // 1 + { + ToggleShadow, + NULL, + NULL, + NULL, + ToggleSmoke, + }, // 2 + { + CycleWallTexturingLevel, + NULL, + NULL, + NULL, + CycleRoadTexturingLevel, + }, // 3 + { + ToggleSky, + NULL, + NULL, + NULL, + ToggleDepthCueing, + }, // 4 + { + CycleYonFactor, + NULL, + NULL, + NULL, + ToggleAccessoryRendering, + }, // 5 + { + DecreaseYon, + NULL, + NULL, + NULL, + IncreaseYon, + }, // 6 + { + CycleSoundDetailLevel, + }, // 7 + { 0 }, // 8 + { 0 }, // 9 + { 0 }, // not used }, }; tCheat gKev_keys[44] = { @@ -1152,7 +1201,7 @@ void CheckMapRenderMove() { if (gReal_graf_data_index == 0) { gMap_render_y = (gBack_screen->height - gCurrent_graf_data->map_render_y_marg - gMap_render_height_i) & ~1; } else { - gMap_render_y = (((gBack_screen->height - gCurrent_graf_data->map_render_y_marg - gMap_render_height_i) & ~3) - 40 ) / 2; + gMap_render_y = (((gBack_screen->height - gCurrent_graf_data->map_render_y_marg - gMap_render_height_i) & ~3) - 40) / 2; } } SetIntegerMapRenders(); @@ -1248,23 +1297,9 @@ void CheckOtherRacingKeys() { } else if (gNet_mode && NetGetPlayerStatus() == ePlayer_status_recovering) { NetPlayerStatusChanged(ePlayer_status_racing); } - if ((!gAuto_repair && !KeyIsDown(44)) - || gRace_finished - || gProgram_state.current_car.knackered - || gWait_for_it - || gEntering_message) { - gRepair_last_time = 0; - stopped_repairing = 0; - total_repair_cost = 0; - total_difference = 0; - if (sound_tag) { - for (i = 0; i < 10 && S3SoundStillPlaying(sound_tag); ++i) { - DRS3StopSound(sound_tag); - } - sound_tag = 0; - } - } else { - if (!gAuto_repair && !gRepair_last_time && GetTotalTime() - gLast_repair_time < 1200) { + + if ((gAuto_repair || KeyIsDown(KEYMAP_REPAIR)) && !gRace_finished && !gProgram_state.current_car.knackered && !gWait_for_it && !gEntering_message) { + if (!gAuto_repair && gRepair_last_time == 0 && GetTotalTime() - gLast_repair_time < 1200) { gAuto_repair = 1; } gLast_repair_time = GetTotalTime(); @@ -1278,7 +1313,7 @@ void CheckOtherRacingKeys() { cost = 0; for (j = 0; j < COUNT_OF(gProgram_state.current_car.damage_units); j++) { old_level = gProgram_state.current_car.damage_units[j].damage_level; - if (amount == 0.0) { + if (amount == 0.0f) { new_level = 0; } else { new_level = ((double)gProgram_state.current_car.damage_units[j].damage_level @@ -1336,6 +1371,18 @@ void CheckOtherRacingKeys() { stopped_repairing = 1; } } + + } else { + gRepair_last_time = 0; + stopped_repairing = 0; + total_repair_cost = 0; + total_difference = 0; + if (sound_tag) { + for (i = 0; i < 10 && S3SoundStillPlaying(sound_tag); ++i) { + DRS3StopSound(sound_tag); + } + sound_tag = 0; + } } if (NeedToExpandBoundingBox) { NeedToExpandBoundingBox = ExpandBoundingBox(&gProgram_state.current_car) == 0; @@ -1986,7 +2033,7 @@ void CycleYonFactor() { // IDA: void __usercall SetSoundDetailLevel(int pLevel@) void SetSoundDetailLevel(int pLevel) { LOG_TRACE("(%d)", pLevel); - + gSound_detail_level = pLevel; } diff --git a/src/DETHRACE/common/crush.c b/src/DETHRACE/common/crush.c index 1100ba0f..c615ad03 100644 --- a/src/DETHRACE/common/crush.c +++ b/src/DETHRACE/common/crush.c @@ -2,15 +2,25 @@ #include "brender/brender.h" #include "car.h" #include "globvars.h" +#include "globvrkm.h" +#include "globvrpb.h" +#include "graphics.h" #include "harness/trace.h" #include "loading.h" +#include "netgame.h" +#include "oil.h" +#include "opponent.h" +#include "piping.h" +#include "replay.h" +#include "spark.h" #include "utility.h" +#include "world.h" #include -float gWobble_spam_y[8]; -float gWobble_spam_z[8]; -br_scalar gWheel_circ_to_width; -tU8 gSmoke_damage_step[12]; +float gWobble_spam_y[8] = { 0.0f, -0.15f, 0.4f, 0.15f, -0.4f, 0.25f, 0.0f, -0.25f }; +float gWobble_spam_z[8] = { 0.4f, -0.25f, 0.0f, 0.25f, 0.0f, 0.15f, -0.4f, -0.15f }; +br_scalar gWheel_circ_to_width = 0.16f; +tU8 gSmoke_damage_step[12] = { 20u, 20u, 0u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 10u }; int gSteal_ranks[5]; // IDA: int __usercall ReadCrushData@(FILE *pF@, tCrush_data *pCrush_data@) @@ -150,7 +160,95 @@ void CrushModelPoint(tCar_spec* pCar, int pModel_index, br_model* pModel, int pC tChanged_vertex pipe_array[600]; tCar_spec* car; LOG_TRACE("(%p, %d, %p, %d, %p, %f, %p)", pCar, pModel_index, pModel, pCrush_point_index, pEnergy_vector, total_energy, pCrush_data); - NOT_IMPLEMENTED(); + + pipe_vertex_count = 0; + if (gNet_mode == eNet_mode_host && pCar->car_model_actors[pModel_index].min_distance_squared == 0.0f) { + NetSendPointCrush(pCar, pCrush_point_index, pEnergy_vector); + } + working_min_fold = pCrush_data->min_fold_factor * gCar_crush_min_fold; + working_max_fold = pCrush_data->max_fold_factor * gCar_crush_max_fold; + working_wibble = pCrush_data->wibble_factor * gCar_crush_wibble; + working_limit_deviant = pCrush_data->limit_deviant * gCar_crush_limit_deviant; + working_split_chance = pCrush_data->split_chance * gCar_crush_split_chance; + min_y_fold_down = pCrush_data->min_y_fold_down; + the_crush_point = &pCrush_data->crush_points[pCrush_point_index]; + if (pModel->nvertices <= the_crush_point->vertex_index) { + return; + } + target_point = &pModel->vertices[the_crush_point->vertex_index].p; + old_vector = *target_point; + for (i = 0; i < 3; i++) { + pEnergy_vector->v[i] = SRandomPosNeg(working_wibble * total_energy) + pEnergy_vector->v[i]; + random_range = (the_crush_point->limits_pos.v[i] - the_crush_point->limits_neg.v[i]) * working_limit_deviant; + if (pEnergy_vector->v[i] >= 0.0f) { + softnesss.v[i] = the_crush_point->softness_pos.v[i]; + } else { + softnesss.v[i] = the_crush_point->softness_neg.v[i]; + } + movement.v[i] = target_point->v[i]; + target_point->v[i] += pEnergy_vector->v[i] * softnesss.v[i]; + if (the_crush_point->limits_neg.v[i] <= target_point->v[i]) { + if (target_point->v[i] > the_crush_point->limits_pos.v[i]) { + target_point->v[i] = SRandomPosNeg(random_range) + the_crush_point->limits_pos.v[i]; + } + } else { + target_point->v[i] = SRandomPosNeg(random_range) + the_crush_point->limits_neg.v[i]; + } + movement.v[i] = target_point->v[i] - movement.v[i]; + if (pEnergy_vector->v[i] * movement.v[i] < 0.0f) { + movement.v[i] = 0.0f; + target_point->v[i] = old_vector.v[i]; + } + } + + if (IsActionReplayAvailable()) { + pipe_array[pipe_vertex_count].vertex_index = the_crush_point->vertex_index; + BrVector3Sub(&pipe_array[pipe_vertex_count].delta_coordinates, target_point, &old_vector); + pipe_vertex_count++; + } + neighbour_index = -1; + for (bend_axis = 0; bend_axis < 3; bend_axis++) { + default_bend_axis[bend_axis] = (bend_axis + IRandomBetween(1, 2)) % 3; + default_bend_factor[bend_axis] = FRandomBetween(working_min_fold, working_max_fold); + } + + the_neighbour = the_crush_point->neighbours; + for (j = 0; j < the_crush_point->number_of_neighbours; j++, the_neighbour++) { + if (the_neighbour->vertex_index) { + neighbour_index += the_neighbour->vertex_index; + if (neighbour_index < 0 || pModel->nvertices <= neighbour_index) { + return; + } + target_point = &pModel->vertices[neighbour_index].p; + old_vector = *target_point; + for (bend_axis = 0; bend_axis < 3; bend_axis++) { + target_point->v[bend_axis] += (1.0f - the_neighbour->factor / 256.0f) * movement.v[bend_axis]; + float v12; + if (the_neighbour->factor <= 128) { + v12 = the_neighbour->factor / 128.0f; + } else { + v12 = 2.0 - the_neighbour->factor / 128.0f; + } + if (((int)((target_point->v[2] + target_point->v[1] + target_point->v[0]) * 63.0f) & 1) * v12 == 0.0) { + bend_amount = -default_bend_factor[bend_axis]; + } else { + bend_amount = default_bend_factor[bend_axis]; + } + int axis_tmp = (((int)((target_point->v[2] + target_point->v[1] + target_point->v[0]) * 100.0f) + bend_axis - 1) & 1) % 3; + target_point->v[axis_tmp] += fabs(movement.v[bend_axis]) * bend_amount; + } + if (IsActionReplayAvailable() && pipe_vertex_count < 600) { + pipe_array[pipe_vertex_count].vertex_index = neighbour_index; + BrVector3Sub(&pipe_array[pipe_vertex_count].delta_coordinates, target_point, &old_vector); + pipe_vertex_count++; + } + } else { + neighbour_index += the_neighbour->factor; + } + } + if (IsActionReplayAvailable() && pipe_vertex_count) { + PipeSingleModelGeometry(pCar->car_ID, pModel_index, pipe_vertex_count, pipe_array); + } } // IDA: void __usercall CrushModel(tCar_spec *pCar@, int pModel_index@, br_actor *pActor@, br_vector3 *pImpact_point@, br_vector3 *pEnergy_vector, tCrush_data *pCrush_data) @@ -167,7 +265,35 @@ void CrushModel(tCar_spec* pCar, int pModel_index, br_actor* pActor, br_vector3* br_vertex* the_vertex; br_matrix34 inverse_transform; LOG_TRACE("(%p, %d, %p, %p, %p, %p)", pCar, pModel_index, pActor, pImpact_point, pEnergy_vector, pCrush_data); - NOT_IMPLEMENTED(); + + if (gArrow_mode) { + return; + } + if (pCrush_data->number_of_crush_points == 0) { + return; + } + BrVector3Sub(&impact_point_model, pImpact_point, (br_vector3*)pActor->t.t.mat.m[3]); + BrVector3Scale(&energy_vector_model, pEnergy_vector, pCrush_data->softness_factor * gCar_crush_softness); + total_energy = BrVector3Length(&energy_vector_model); + if (total_energy < 0.06f) { + return; + } + BrVector3Scale(&energy_vector_scaled, &energy_vector_model, (total_energy - 0.06f) / total_energy); + nearest_so_far = BR_SCALAR_MAX; + vertices = pActor->model->vertices; + nearest_index = -1; + for (i = 0; i < pCrush_data->number_of_crush_points; i++) { + the_vertex = &vertices[pCrush_data->crush_points[i].vertex_index]; + this_distance = (impact_point_model.v[2] - the_vertex->p.v[2]) * (impact_point_model.v[2] - the_vertex->p.v[2]) + (impact_point_model.v[1] - the_vertex->p.v[1]) * (impact_point_model.v[1] - the_vertex->p.v[1]) + (impact_point_model.v[0] - the_vertex->p.v[0]) * (impact_point_model.v[0] - the_vertex->p.v[0]); + if (this_distance < nearest_so_far) { + nearest_so_far = this_distance; + nearest_index = i; + } + } + if (nearest_index >= 0) { + CrushModelPoint(pCar, pModel_index, pActor->model, nearest_index, &energy_vector_scaled, total_energy, pCrush_data); + SetModelForUpdate(pActor->model, pCar, 1); + } } // IDA: void __cdecl JitModelUpdate(br_actor *actor, br_model *model, br_material *material, void *render_data, br_uint_8 style, int on_screen) @@ -175,7 +301,7 @@ void JitModelUpdate(br_actor* actor, br_model* model, br_material* material, voi LOG_TRACE("(%p, %p, %p, %p, %d, %d)", actor, model, material, render_data, style, on_screen); BrModelUpdate(model, BR_MODU_NORMALS); - model->flags &= ~(BR_MODF_QUICK_UPDATE | BR_MODF_CUSTOM); + model->flags &= ~(BR_MODF_CUSTOM); BrZbModelRender(actor, model, material, style, BrOnScreenCheck(&model->bounds), 0); } @@ -203,7 +329,19 @@ void TotallySpamTheModel(tCar_spec* pCar, int pModel_index, br_actor* pActor, tC br_vertex* the_vertex; br_vertex* vertices; LOG_TRACE("(%p, %d, %p, %p, %f)", pCar, pModel_index, pActor, pCrush_data, pMagnitude); - NOT_IMPLEMENTED(); + + if (gArrow_mode || pCrush_data->number_of_crush_points == 0) { + return; + } + the_vertex = pActor->model->vertices; + for (i = 0; i < 15; i++) { + the_index = IRandomBetween(0, pCrush_data->number_of_crush_points - 1); + energy_vector_model = the_vertex[pCrush_data->crush_points[the_index].vertex_index].p; + BrVector3Normalise(&energy_vector_model, &energy_vector_model); + BrVector3Scale(&energy_vector_model, &energy_vector_model, -pMagnitude); + CrushModelPoint(pCar, pModel_index, pActor->model, the_index, &energy_vector_model, pMagnitude, pCrush_data); + } + SetModelForUpdate(pActor->model, pCar, 1); } // IDA: br_scalar __usercall RepairModel@(tCar_spec *pCar@, int pModel_index@, br_actor *pActor@, br_vertex *pUndamaged_vertices@, br_scalar pAmount, br_scalar *pTotal_deflection) @@ -217,7 +355,44 @@ br_scalar RepairModel(tCar_spec* pCar, int pModel_index, br_actor* pActor, br_ve br_scalar deviation; tChanged_vertex pipe_array[600]; LOG_TRACE("(%p, %d, %p, %p, %f, %p)", pCar, pModel_index, pActor, pUndamaged_vertices, pAmount, pTotal_deflection); - NOT_IMPLEMENTED(); + + pipe_vertex_count = 0; + amount = 0.0f; + *pTotal_deflection = 0.0f; + + for (i = 0; i < pActor->model->nvertices; i++) { + model_vertex = &pActor->model->vertices[i]; + old_point = model_vertex->p; + for (j = 0; j < 3; ++j) { + *pTotal_deflection = fabsf(pUndamaged_vertices->p.v[j] - old_point.v[j]) + *pTotal_deflection; + if (pUndamaged_vertices->p.v[j] >= old_point.v[j]) { + if (pUndamaged_vertices->p.v[j] > old_point.v[j]) { + model_vertex->p.v[j] = model_vertex->p.v[j] + pAmount; + if (pUndamaged_vertices->p.v[j] < model_vertex->p.v[j]) { + model_vertex->p.v[j] = pUndamaged_vertices->p.v[j]; + } + amount = model_vertex->p.v[j] - old_point.v[j] + amount; + } + } else { + model_vertex->p.v[j] = model_vertex->p.v[j] - pAmount; + if (pUndamaged_vertices->p.v[j] > model_vertex->p.v[j]) { + model_vertex->p.v[j] = pUndamaged_vertices->p.v[j]; + } + amount = old_point.v[j] - model_vertex->p.v[j] + amount; + } + } + if (amount != 0.0 && IsActionReplayAvailable() && pipe_vertex_count < COUNT_OF(pipe_array)) { + pipe_array[pipe_vertex_count].vertex_index = i; + BrVector3Sub(&pipe_array[pipe_vertex_count].delta_coordinates, &model_vertex->p, &old_point); + pipe_vertex_count++; + } + pUndamaged_vertices++; + } + SetModelForUpdate(pActor->model, pCar, 0); + if (IsActionReplayAvailable() && pipe_vertex_count) { + PipeSingleModelGeometry(pCar->car_ID, pModel_index, pipe_vertex_count, pipe_array); + } + return amount; } // IDA: float __usercall RepairCar2@(tCar_spec *pCar@, tU32 pFrame_period@, br_scalar *pTotal_deflection@) @@ -227,13 +402,36 @@ float RepairCar2(tCar_spec* pCar, tU32 pFrame_period, br_scalar* pTotal_deflecti br_scalar amount; br_scalar dummy; LOG_TRACE("(%p, %d, %p)", pCar, pFrame_period, pTotal_deflection); - NOT_IMPLEMENTED(); + + if (gArrow_mode) { + return 0.0f; + } + *pTotal_deflection = 0.0; + amount = 0.0; + + for (i = 0; i < gProgram_state.current_car.car_actor_count; i++) { + the_car_actor = &pCar->car_model_actors[i]; + if (the_car_actor->min_distance_squared == 0.0 || !the_car_actor->undamaged_vertices) { + if (the_car_actor->undamaged_vertices) { + amount = RepairModel(pCar, i, the_car_actor->actor, the_car_actor->undamaged_vertices, pFrame_period * 0.00005f, pTotal_deflection); + } + } else { + RepairModel(pCar, i, the_car_actor->actor, the_car_actor->undamaged_vertices, pFrame_period * 0.00005f, &dummy); + } + } + pCar->repair_time += pFrame_period; + return amount; } // IDA: float __usercall RepairCar@(tU16 pCar_ID@, tU32 pFrame_period@, br_scalar *pTotal_deflection@) float RepairCar(tU16 pCar_ID, tU32 pFrame_period, br_scalar* pTotal_deflection) { LOG_TRACE("(%d, %d, %p)", pCar_ID, pFrame_period, pTotal_deflection); - NOT_IMPLEMENTED(); + + if (VEHICLE_TYPE_FROM_ID(pCar_ID) == eVehicle_self) { + return RepairCar2(&gProgram_state.current_car, pFrame_period, pTotal_deflection); + } + + return RepairCar2(GetCarSpec(VEHICLE_TYPE_FROM_ID(pCar_ID), VEHICLE_INDEX_FROM_ID(pCar_ID)), pFrame_period, pTotal_deflection); } // IDA: void __usercall TotallyRepairACar(tCar_spec *pCar@) @@ -282,7 +480,25 @@ void DamageUnit2(tCar_spec* pCar, int pUnit_type, int pDamage_amount) { tDamage_unit* the_damage; int last_level; LOG_TRACE("(%p, %d, %d)", pCar, pUnit_type, pDamage_amount); - NOT_IMPLEMENTED(); + + the_damage = &pCar->damage_units[pUnit_type]; + if ((pCar->driver < eDriver_net_human || pUnit_type != eDamage_driver) && pDamage_amount >= 5 && !pCar->invulnerable) { + last_level = the_damage->damage_level; + the_damage->damage_level = pDamage_amount + last_level; + if (the_damage->damage_level >= 99) { + if (pDamage_amount >= 10) { + the_damage->damage_level = 99; + } else { + the_damage->damage_level = last_level; + } + } + if (pCar->driver == eDriver_oppo || gNet_mode != eNet_mode_none) { + SetKnackeredFlag(pCar); + } else if ((pCar->damage_units[eDamage_engine].damage_level >= 99 && pCar->damage_units[eDamage_engine].last_level < 99 && pCar->damage_units[eDamage_transmission].last_level < 99) + || (pCar->damage_units[eDamage_transmission].damage_level >= 99 && pCar->damage_units[eDamage_engine].last_level < 99 && pCar->damage_units[eDamage_transmission].last_level < 99)) { + QueueOilSpill(pCar); + } + } } // IDA: void __usercall RecordLastDamage(tCar_spec *pCar@) @@ -290,13 +506,30 @@ void RecordLastDamage(tCar_spec* pCar) { int i; LOG_TRACE("(%p)", pCar); - STUB_ONCE(); + for (i = 0; i < COUNT_OF(pCar->damage_units); i++) { + pCar->damage_units[i].last_level = pCar->damage_units[i].damage_level; + } + pCar->damage_magnitude_accumulator = 0.0; + pCar->last_impact_location = eImpact_unknown; + pCar->pre_car_col_mat = pCar->car_master_actor->t.t.mat; + pCar->pre_car_col_speed = pCar->speed; + pCar->pre_car_col_knackered = pCar->knackered; + pCar->pre_car_col_direction = pCar->direction; + pCar->pre_car_col_velocity = pCar->v; + pCar->pre_car_col_velocity_car_space = pCar->velocity_car_space; } // IDA: void __usercall DoDamage(tCar_spec *pCar@, tDamage_type pDamage_type@, float pMagnitude, float pNastiness) void DoDamage(tCar_spec* pCar, tDamage_type pDamage_type, float pMagnitude, float pNastiness) { LOG_TRACE("(%p, %d, %f, %f)", pCar, pDamage_type, pMagnitude, pNastiness); - NOT_IMPLEMENTED(); + + if (pCar->driver < eDriver_net_human) { + DamageUnit2(pCar, pDamage_type, ((gCurrent_race.suggested_rank < 10 ? 0.5f : gCurrent_race.suggested_rank) / 20.0f + 1.0f) * (pNastiness * pMagnitude * 10.0f)); + } else if (gNet_mode != eNet_mode_none) { + DamageUnit2(pCar, pDamage_type, pNastiness * pMagnitude * 15.0f); + } else if (PercentageChance(pNastiness * pMagnitude * 1500.0f)) { + DamageUnit2(pCar, pDamage_type, pNastiness * pMagnitude * 30.0); + } } // IDA: void __usercall CheckPiledriverBonus(tCar_spec *pCar@, br_vector3 *pImpact_point@, br_vector3 *pEnergy@) @@ -307,7 +540,8 @@ void CheckPiledriverBonus(tCar_spec* pCar, br_vector3* pImpact_point, br_vector3 br_vector3 norm_energy; br_scalar dp; LOG_TRACE("(%p, %p, %p)", pCar, pImpact_point, pEnergy); - NOT_IMPLEMENTED(); + + STUB(); } // IDA: tImpact_location __usercall CalcModifiedLocation@(tCar_spec *pCar@) @@ -321,7 +555,8 @@ void DoPratcamHit(br_vector3* pHit_vector) { int strength_modifier; br_scalar strength; LOG_TRACE("(%p)", pHit_vector); - NOT_IMPLEMENTED(); + + STUB_ONCE(); } // IDA: void __usercall DamageSystems(tCar_spec *pCar@, br_vector3 *pImpact_point@, br_vector3 *pEnergy_vector@, int pWas_hitting_a_car@) @@ -352,7 +587,156 @@ void DamageSystems(tCar_spec* pCar, br_vector3* pImpact_point, br_vector3* pEner tDamage_effect* the_effect; tImpact_location modified_location; LOG_TRACE("(%p, %p, %p, %d)", pCar, pImpact_point, pEnergy_vector, pWas_hitting_a_car); - NOT_IMPLEMENTED(); + + pure_energy_magnitude = BrVector3Length(pEnergy_vector); + if (pure_energy_magnitude == 0.0f && !pWas_hitting_a_car) { + return; + } + + energy_magnitude = pCar->car_model_actors[pCar->principal_car_actor].crush_data.softness_factor * pure_energy_magnitude / 0.7f; + BrVector3InvScale(&crushed_car_bounds.min, &pCar->bounds[1].min, WORLD_SCALE); + BrVector3InvScale(&crushed_car_bounds.max, &pCar->bounds[1].max, WORLD_SCALE); + + x1 = pImpact_point->v[0] - crushed_car_bounds.min.v[0]; + x2 = crushed_car_bounds.max.v[0] - pImpact_point->v[0]; + if (x1 >= x2) { + x = x2; + } else { + x = x1; + } + y1 = pImpact_point->v[1] - crushed_car_bounds.min.v[1]; + y2 = crushed_car_bounds.max.v[1] - pImpact_point->v[1]; + if (y1 >= y2) { + y = y2; + } else { + y = y1; + } + z1 = pImpact_point->v[2] - crushed_car_bounds.min.v[2]; + z2 = crushed_car_bounds.max.v[2] - pImpact_point->v[2]; + if (z1 >= z2) { + z = z2; + } else { + z = z1; + } + if (z > x || z > y) { + if (x > y || x > z) { + impact_location = y1 < y2 ? eImpact_bottom : eImpact_top; + proportion_z = z1 / (crushed_car_bounds.max.v[2] - crushed_car_bounds.min.v[2]); + proportion_x = x1 / (crushed_car_bounds.max.v[0] - crushed_car_bounds.min.v[0]); + } else { + impact_location = x1 >= x2 ? eImpact_right : eImpact_left; + proportion_z = z1 / (crushed_car_bounds.max.v[2] - crushed_car_bounds.min.v[2]); + proportion_y = y1 / (crushed_car_bounds.max.v[1] - crushed_car_bounds.min.v[1]); + } + } else { + impact_location = z1 >= z2 ? eImpact_back : eImpact_front; + proportion_x = x1 / (crushed_car_bounds.max.v[0] - crushed_car_bounds.min.v[0]); + proportion_y = y1 / (crushed_car_bounds.max.v[1] - crushed_car_bounds.min.v[1]); + } + if (pWas_hitting_a_car && pCar->last_impact_location == eImpact_unknown) { + pCar->last_impact_location = impact_location; + pCar->last_col_prop_x = proportion_x; + pCar->last_col_prop_y = proportion_y; + pCar->last_col_prop_z = proportion_z; + } + + if (energy_magnitude != 0.0f && !pCar->invulnerable) { + if (!pWas_hitting_a_car && impact_location == eImpact_bottom) { + energy_magnitude = energy_magnitude / 2.0f; + } + + the_program = &pCar->damage_programs[impact_location]; + the_clause = the_program->clauses; + for (i = 0; i < the_program->clause_count; i++) { + result = 1; + the_condition = the_clause->conditions; + for (j = 0; j < the_clause->condition_count; j++) { + switch (the_condition->axis_comp) { + case eAxis_x: + if (the_condition->condition_operator == eCondition_greater_than) { + if (the_condition->comparitor >= proportion_x) { + result = 0; + } + } else if (the_condition->comparitor <= proportion_x) { + result = 0; + } + break; + + case eAxis_y: + if (the_condition->condition_operator == eCondition_greater_than) { + if (the_condition->comparitor >= proportion_y) { + result = 0; + } + } else if (the_condition->comparitor <= proportion_y) { + result = 0; + } + break; + + case eAxis_z: + if (the_condition->condition_operator == eCondition_greater_than) { + if (the_condition->comparitor >= proportion_z) { + result = 0; + } + } else if (the_condition->comparitor <= proportion_z) { + result = 0; + } + break; + } + + if (!result) { + break; + } + the_condition++; + } + if (result) { + the_effect = the_clause->effects; + for (j = 0; j < the_clause->effect_count; j++) { + DoDamage(pCar, the_effect->type, energy_magnitude, the_effect->weakness_factor); + the_effect++; + } + } + the_clause++; + } + if (pCar->driver == eDriver_local_human) { + switch (impact_location) { + case eImpact_top: + case eImpact_bottom: + NewScreenWobble( + FRandomBetween(energy_magnitude * 5.0f, energy_magnitude * 20.0f), + FRandomBetween(energy_magnitude * 30.0f, energy_magnitude * 60.0f), + FRandomBetween(1.0f / energy_magnitude, 5.0f / energy_magnitude)); + break; + case eImpact_left: + NewScreenWobble( + FRandomBetween(energy_magnitude * 50.0f, energy_magnitude * 100.0f), + FRandomBetween(energy_magnitude * 5.0f, energy_magnitude * 20.0f), + FRandomBetween(4.0f / energy_magnitude, 7.0 / energy_magnitude)); + break; + case eImpact_right: + NewScreenWobble( + -FRandomBetween(energy_magnitude * 50.0f, energy_magnitude * 100.0f), + FRandomBetween(energy_magnitude * 5.0f, energy_magnitude * 20.0f), + FRandomBetween(4.0f / energy_magnitude, 7.0f / energy_magnitude)); + + break; + case eImpact_front: + NewScreenWobble( + FRandomBetween(energy_magnitude * 5.0f, energy_magnitude * 20.0f), + FRandomBetween(energy_magnitude * 50.0f, energy_magnitude * 150.0f), + FRandomBetween(7.0f / energy_magnitude, 25.0f / energy_magnitude)); + break; + case eImpact_back: + NewScreenWobble( + FRandomBetween(energy_magnitude * 5.0f, energy_magnitude * 20.0f), + FRandomBetween(-energy_magnitude * 50.0f, energy_magnitude * 150.0f), + FRandomBetween(7.0f / energy_magnitude, 25.0f / energy_magnitude)); + break; + default: + break; + } + CheckPiledriverBonus(pCar, pImpact_point, pEnergy_vector); + } + } } // IDA: tImpact_location __usercall GetDirection@(br_vector3 *pVelocity@) @@ -383,7 +767,25 @@ void SortOutSmoke(tCar_spec* pCar) { int pass; int repeat; LOG_TRACE("(%p)", pCar); - NOT_IMPLEMENTED(); + + if (!pCar || pCar->driver <= eDriver_non_car) { + return; + } + for (i = 0; i < COUNT_OF(pCar->damage_units); i++) { + if (pCar->damage_units[i].damage_level != pCar->damage_units[i].smoke_last_level) { + step = gSmoke_damage_step[i]; + if (step) { + if (pCar->damage_units[i].damage_level > pCar->damage_units[i].smoke_last_level) { + old_colour = (99 - pCar->damage_units[i].smoke_last_level) / step; + colour = (99 - pCar->damage_units[i].damage_level) / step; + if (old_colour != colour && colour <= 2) { + ConditionalSmokeColumn(pCar, i, colour); + } + } + } + } + } + SetSmokeLastDamageLevel(pCar); } // IDA: void __usercall StealCar(tCar_spec *pCar@) @@ -434,7 +836,8 @@ int DoCrashEarnings(tCar_spec* pCar1, tCar_spec* pCar2) { br_vector3 car_2_offset; tNet_message* message; LOG_TRACE("(%p, %p)", pCar1, pCar2); - NOT_IMPLEMENTED(); + + STUB(); } // IDA: void __usercall DoWheelDamage(tU32 pFrame_period@) @@ -451,11 +854,83 @@ void DoWheelDamage(tU32 pFrame_period) { br_vector3 wonky_vector; static int kev_index[4]; LOG_TRACE("(%d)", pFrame_period); - STUB_ONCE(); + + if (gAction_replay_mode && ReplayIsPaused()) { + return; + } + + for (i = 0; i < gNum_active_cars; i++) { + car = gActive_car_list[i]; + for (j = 0; j < COUNT_OF(car->wheel_actors); j++) { + if (!car->wheel_actors[j]) { + continue; + } + old_offset = car->wheel_dam_offset[j]; + damage = car->damage_units[j + 8].damage_level; + if (damage <= 30 || gRace_finished) { + car->wheel_dam_offset[j] = 0.0f; + continue; + } + if (PointOutOfSight(&car->pos, 32.0f)) { + break; + } + y_amount = (damage - 30) * gWobble_spam_y[damage & 7]; + z_amount = (damage - 30) * gWobble_spam_z[damage & 7]; + BrMatrix34PreRotateY(&car->wheel_actors[j]->t.t.mat, BrDegreeToAngle(y_amount < 0 ? y_amount + 360.f : y_amount)); + BrMatrix34PreRotateZ(&car->wheel_actors[j]->t.t.mat, BrDegreeToAngle(z_amount < 0 ? z_amount + 360.f : z_amount)); + if (j < 2 && car->wheel_actors[j + 4] != NULL) { + BrMatrix34PreRotateY(&car->wheel_actors[j + 4]->t.t.mat, BrDegreeToAngle(y_amount < 0 ? y_amount + 360.f : y_amount)); + BrMatrix34PreRotateZ(&car->wheel_actors[j + 4]->t.t.mat, BrDegreeToAngle(z_amount < 0 ? z_amount + 360.f : z_amount)); + } + switch (j) { + case 0: + if (car->driven_wheels_spin_ref_1 < 0) { + wheel_circum = car->non_driven_wheels_circum; + } else { + wheel_circum = car->driven_wheels_circum; + } + break; + case 1: + if (car->driven_wheels_spin_ref_2 < 0) { + wheel_circum = car->non_driven_wheels_circum; + } else { + wheel_circum = car->driven_wheels_circum; + } + break; + case 2: + if (car->driven_wheels_spin_ref_3 < 0) { + wheel_circum = car->non_driven_wheels_circum; + } else { + wheel_circum = car->driven_wheels_circum; + } + break; + case 3: + if (car->driven_wheels_spin_ref_4 < 0) { + wheel_circum = car->non_driven_wheels_circum; + } else { + wheel_circum = car->driven_wheels_circum; + } + break; + default: + break; + } + if (gNet_mode == eNet_mode_none || car->driver == eDriver_local_human) { + temp_vector.v[0] = wheel_circum * gWheel_circ_to_width; + temp_vector.v[1] = 0.0f; + temp_vector.v[2] = 0.0f; + BrMatrix34ApplyV(&wonky_vector, &temp_vector, &car->wheel_actors[j]->t.t.mat); + car->wheel_dam_offset[j] = fabsf(wonky_vector.v[1]); + } + } + } } // IDA: void __usercall CrashEarnings(tCar_spec *pCar1@, tCar_spec *pCar2@) void CrashEarnings(tCar_spec* pCar1, tCar_spec* pCar2) { LOG_TRACE("(%p, %p)", pCar1, pCar2); - STUB_ONCE(); + + if (DoCrashEarnings(pCar1, pCar2)) { + SortOutSmoke(pCar1); + SortOutSmoke(pCar2); + } } diff --git a/src/DETHRACE/common/displays.c b/src/DETHRACE/common/displays.c index 1ea2ffe8..f81514e0 100644 --- a/src/DETHRACE/common/displays.c +++ b/src/DETHRACE/common/displays.c @@ -5,11 +5,10 @@ #include "depth.h" #include "flicplay.h" #include "globvars.h" -#include "globvars.h" #include "globvrkm.h" #include "globvrpb.h" -#include "graphics.h" #include "grafdata.h" +#include "graphics.h" #include "harness/trace.h" #include "netgame.h" #include "pd/sys.h" @@ -38,7 +37,7 @@ int gTimer_headup; int gTime_awarded_headup; int gPed_kill_count_headup; int gDim_amount; -br_pixelmap* gHeadup_images[32]; // Modified by DethRace for the demo +br_pixelmap* gHeadup_images[32]; // Modified by DethRace for the demo int gNet_cash_headup; int gNet_ped_headup; int gCredits_lost_headup; @@ -661,7 +660,6 @@ int DRTextCleverWidth(tDR_font* pFont, signed char* pText) { } else { pFont = &gFonts[256 - *c]; } - } return result; } @@ -984,7 +982,48 @@ void DoDamageScreen(tU32 pThe_time) { br_pixelmap* the_image; tDamage_unit* the_damage; LOG_TRACE("(%d)", pThe_time); - STUB_ONCE(); + + if (&gProgram_state.current_car != gCar_to_view || gProgram_state.current_car_index != gProgram_state.current_car.index) { + return; + } + if (gProgram_state.cockpit_on && gProgram_state.cockpit_image_index >= 0) { + if (gProgram_state.which_view != eView_forward) { + return; + } + the_wobble_y = gScreen_wobble_x; + the_wobble_x = gScreen_wobble_y; + } else { + the_wobble_y = gProgram_state.current_car.damage_x_offset; + the_wobble_x = gProgram_state.current_car.damage_y_offset; + if (gProgram_state.current_car.damage_background) { + DRPixelmapRectangleMaskedCopy( + gBack_screen, + gProgram_state.current_car.damage_background_x, + gProgram_state.current_car.damage_background_y, + gProgram_state.current_car.damage_background, + 0, + 0, + gProgram_state.current_car.damage_background->width, + gProgram_state.current_car.damage_background->height); + } + } + for (i = 0; i < COUNT_OF(gProgram_state.current_car.damage_units); i++) { + the_damage = &gProgram_state.current_car.damage_units[i]; + if (i != 2) { + the_image = the_damage->images; + the_step = 5 * the_damage->damage_level / 100; + y_pitch = (the_image->height / 2) / 5; + DRPixelmapRectangleMaskedCopy( + gBack_screen, + the_wobble_y + gProgram_state.current_car.damage_units[i].x_coord, + the_wobble_x + gProgram_state.current_car.damage_units[i].y_coord, + the_image, + 0, + y_pitch * (2 * (5 * the_damage->damage_level / 100) + ((pThe_time / the_damage->periods[5 * the_damage->damage_level / 100]) & 1)), + the_image->width, + y_pitch); + } + } } // IDA: void __cdecl PoshDrawLine(float pAngle, br_pixelmap *pDestn, int pX1, int pY1, int pX2, int pY2, int pColour) @@ -1412,20 +1451,20 @@ void AwardTime(tU32 pTime) { void DrawRectangle(br_pixelmap* pPixelmap, int pLeft, int pTop, int pRight, int pBottom, int pColour) { LOG_TRACE("(%p, %d, %d, %d, %d, %d)", pPixelmap, pLeft, pTop, pRight, pBottom, pColour); - BrPixelmapLine(pPixelmap, pLeft, pTop, pRight, pTop, pColour); - BrPixelmapLine(pPixelmap, pLeft, pBottom, pRight, pBottom, pColour); - BrPixelmapLine(pPixelmap, pLeft, pTop, pLeft, pBottom, pColour); - BrPixelmapLine(pPixelmap, pRight, pTop, pRight, pBottom, pColour); + BrPixelmapLine(pPixelmap, pLeft, pTop, pRight, pTop, pColour); + BrPixelmapLine(pPixelmap, pLeft, pBottom, pRight, pBottom, pColour); + BrPixelmapLine(pPixelmap, pLeft, pTop, pLeft, pBottom, pColour); + BrPixelmapLine(pPixelmap, pRight, pTop, pRight, pBottom, pColour); } // IDA: void __usercall DrawRRectangle(br_pixelmap *pPixelmap@, int pLeft@, int pTop@, int pRight@, int pBottom, int pColour) void DrawRRectangle(br_pixelmap* pPixelmap, int pLeft, int pTop, int pRight, int pBottom, int pColour) { LOG_TRACE("(%p, %d, %d, %d, %d, %d)", pPixelmap, pLeft, pTop, pRight, pBottom, pColour); - BrPixelmapLine(pPixelmap, pLeft + 1, pTop, pRight - 1, pTop, pColour); - BrPixelmapLine(pPixelmap, pLeft + 1, pBottom, pRight - 1, pBottom, pColour); - BrPixelmapLine(pPixelmap, pLeft, pTop + 1, pLeft, pBottom - 1, pColour); - BrPixelmapLine(pPixelmap, pRight, pTop + 1, pRight, pBottom - 1, pColour); + BrPixelmapLine(pPixelmap, pLeft + 1, pTop, pRight - 1, pTop, pColour); + BrPixelmapLine(pPixelmap, pLeft + 1, pBottom, pRight - 1, pBottom, pColour); + BrPixelmapLine(pPixelmap, pLeft, pTop + 1, pLeft, pBottom - 1, pColour); + BrPixelmapLine(pPixelmap, pRight, pTop + 1, pRight, pBottom - 1, pColour); } // IDA: void __usercall OoerrIveGotTextInMeBoxMissus(int pFont_index@, char *pText@, br_pixelmap *pPixelmap@, int pLeft@, int pTop, int pRight, int pBottom, int pCentred) diff --git a/src/DETHRACE/common/graphics.c b/src/DETHRACE/common/graphics.c index 32775861..bde2361e 100644 --- a/src/DETHRACE/common/graphics.c +++ b/src/DETHRACE/common/graphics.c @@ -32,6 +32,7 @@ #include "trig.h" #include "utility.h" #include "world.h" +#include #include #include @@ -689,7 +690,23 @@ void NewScreenWobble(double pAmplitude_x, double pAmplitude_y, double pPeriod) { int oldest_time; int oldest_index; LOG_TRACE("(%d, %d, %d)", pAmplitude_x, pAmplitude_y, pPeriod); - NOT_IMPLEMENTED(); + + oldest_index = -1; + oldest_time = INT_MAX; + for (i = 0; i < COUNT_OF(gWobble_array); i++) { + if (!gWobble_array[i].time_started) { + oldest_index = i; + break; + } + if (gWobble_array[i].time_started < oldest_time) { + oldest_time = gWobble_array[i].time_started; + oldest_index = i; + } + } + gWobble_array[oldest_index].time_started = GetTotalTime(); + gWobble_array[oldest_index].amplitude_x = pAmplitude_x; + gWobble_array[oldest_index].amplitude_y = pAmplitude_y; + gWobble_array[oldest_index].period = pPeriod; } // IDA: void __usercall SetScreenWobble(int pWobble_x@, int pWobble_y@) diff --git a/src/DETHRACE/common/input.c b/src/DETHRACE/common/input.c index 73bdcaaf..3bc9b730 100644 --- a/src/DETHRACE/common/input.c +++ b/src/DETHRACE/common/input.c @@ -310,7 +310,7 @@ void WaitForAKey() { while (1) { CheckQuit(); - if (AnyKeyDown( )) { + if (AnyKeyDown()) { break; } if (EitherMouseButtonDown()) { diff --git a/src/DETHRACE/common/netgame.c b/src/DETHRACE/common/netgame.c index c0cee9f7..02bcd133 100644 --- a/src/DETHRACE/common/netgame.c +++ b/src/DETHRACE/common/netgame.c @@ -10,7 +10,7 @@ #include #include -int gPowerup_cost[4] = {1500, 2500, 4000, 6000}; +int gPowerup_cost[4] = { 1500, 2500, 4000, 6000 }; int gGame_scores[6]; int gPed_target; int gNot_shown_race_type_headup; @@ -381,7 +381,7 @@ void BuyPower() { LOG_TRACE("()"); if (gNet_mode != eNet_mode_none && gCurrent_net_game->type == eNet_game_type_foxy && gThis_net_player_index == gIt_or_fox) { - NewTextHeadupSlot(4, 0, 1000,-4, GetMiscString(214)); + NewTextHeadupSlot(4, 0, 1000, -4, GetMiscString(214)); } else if (gNet_mode != eNet_mode_none && gCurrent_net_game->type == eNet_game_type_tag && gThis_net_player_index != gIt_or_fox) { NewTextHeadupSlot(4, 0, 1000, -4, GetMiscString(215)); } else { @@ -463,7 +463,8 @@ void DefaultNetName() { void NetSendPointCrush(tCar_spec* pCar, tU16 pCrush_point_index, br_vector3* pEnergy_vector) { tNet_contents* contents; LOG_TRACE("(%p, %d, %p)", pCar, pCrush_point_index, pEnergy_vector); - NOT_IMPLEMENTED(); + + STUB_ONCE(); } // IDA: void __usercall RecievedCrushPoint(tNet_contents *pContents@) diff --git a/src/DETHRACE/common/piping.c b/src/DETHRACE/common/piping.c index b93a25d7..358f8db3 100644 --- a/src/DETHRACE/common/piping.c +++ b/src/DETHRACE/common/piping.c @@ -1,10 +1,10 @@ #include "piping.h" +#include "brender/brender.h" #include "globvars.h" #include "harness/trace.h" #include "opponent.h" #include "pedestrn.h" #include "sound.h" -#include "brender/brender.h" #include #include @@ -74,7 +74,8 @@ int PipeSearchForwards() { // IDA: int __cdecl IsActionReplayAvailable() int IsActionReplayAvailable() { LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + return gPipe_buffer_start != NULL; } // IDA: int __cdecl SomeReplayLeft() @@ -325,7 +326,7 @@ void AddOilSpillToPipingSession(int pIndex, br_matrix34* pMat, br_scalar pFull_s data.car = pCar; BrVector3Copy(&data.original_pos, pOriginal_pos); data.pixelmap = pPixelmap; - AddDataToSession(pIndex,&data,sizeof(tPipe_oil_spill_data)); + AddDataToSession(pIndex, &data, sizeof(tPipe_oil_spill_data)); } // IDA: void __usercall AddFrameFinishToPipingSession(tU32 pThe_time@) @@ -502,7 +503,7 @@ void PipeSingleOilSpill(int pIndex, br_matrix34* pMat, br_scalar pFull_size, br_ 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); StartPipingSession(ePipe_chunk_oil_spill); - AddOilSpillToPipingSession(pIndex, pMat, pFull_size, pGrow_rate, + AddOilSpillToPipingSession(pIndex, pMat, pFull_size, pGrow_rate, pSpill_time, pStop_time, pCar, pOriginal_pos, pPixelmap); EndPipingSession(); } @@ -552,7 +553,7 @@ void PipeSinglePedIncident(int pPed_index, br_actor* pActor) { // IDA: void __cdecl PipeSingleWallIncident(float pSeverity, br_vector3 *pImpact_point) void PipeSingleWallIncident(float pSeverity, br_vector3* pImpact_point) { LOG_TRACE("(%f, %p)", pSeverity, pImpact_point); - NOT_IMPLEMENTED(); + STUB_ONCE(); } // IDA: void __usercall PipeSingleScreenShake(int pWobble_x@, int pWobble_y@) @@ -703,7 +704,7 @@ void PipeCarPositions() { AddCarToPipingSession(cat * 0x100 + i, &car->car_master_actor->t.t.mat, &car->v, car->speedo_speed, car->lf_sus_position, car->rf_sus_position, car->lr_sus_position, car->rr_sus_position, - car->steering_angle, car->revs,car->gear, car->frame_collision_flag); + car->steering_angle, car->revs, car->gear, car->frame_collision_flag); } } EndPipingSession(); diff --git a/src/DETHRACE/common/spark.c b/src/DETHRACE/common/spark.c index 9b901982..5a1b6b9f 100644 --- a/src/DETHRACE/common/spark.c +++ b/src/DETHRACE/common/spark.c @@ -15,7 +15,6 @@ #include "utility.h" #include "world.h" -#include #include int gNext_spark; @@ -57,6 +56,15 @@ br_camera* gSpark_cam; br_material* gBlack_material; tShrapnel gShrapnel[15]; +// gSmoke_column has 25 elements but all the code just checks the first 5 elements +#define MAX_SMOKE_COLUMNS 5 + +// Bugfix: At higher FPS, flame animation runs too quickly, so introduce a new frame timer +#define FLAME_ANIMATION_FRAME_INTERVAL 40 + +// Bugfix: At higher FPS, `CreatePuffOfSmoke` is called too often and causes smoke cirlces to be recycled too quickly so assume around 25fps +#define SMOKE_COLUMN_NEW_PUFF_INTERVAL 30 + // IDA: void __cdecl DrawDot(br_scalar z, tU8 *scr_ptr, tU16 *depth_ptr, tU8 *shade_ptr) void DrawDot(br_scalar z, tU8* scr_ptr, tU16* depth_ptr, tU8* shade_ptr) { LOG_TRACE("(%f, %p, %p, %p)", z, scr_ptr, depth_ptr, shade_ptr); @@ -1282,7 +1290,63 @@ void CreateSmokeColumn(tCar_spec* pCar, int pColour, int pVertex_index, tU32 pLi br_actor* actor; tSmoke_column* col; LOG_TRACE("(%p, %d, %d, %d)", pCar, pColour, pVertex_index, pLifetime); - NOT_IMPLEMENTED(); + + col = &gSmoke_column[gNext_column]; + if (pCar->last_special_volume && pCar->last_special_volume->gravity_multiplier < 1.0f) { + return; + } + SmudgeCar(pCar, pVertex_index); + if (pCar->knackered) { + SmudgeCar(pCar, pCar->fire_vertex[IRandomBetween(0, 11)]); + } + if (!gSmoke_on) { + return; + } + if (((1 << gNext_column) & gColumn_flags) != 0) { + if (gSmoke_column[gNext_column].car) { + gSmoke_column[gNext_column].car->num_smoke_columns--; + } + StartPipingSession(ePipe_chunk_smoke_column); + AddSmokeColumnToPipingSession(gNext_column, gSmoke_column[gNext_column].car, gSmoke_column[gNext_column].vertex_index, gSmoke_column[gNext_column].colour); + EndPipingSession(); + if (!gSmoke_column[gNext_column].colour) { + StartPipingSession(ePipe_chunk_flame); + actor = col->flame_actor->children; + for (i = 0; i < 3; i++) { + if (actor->type == BR_ACTOR_MODEL) { + AddFlameToPipingSession(i + 16 * gNext_column, col->frame_count[i], col->scale_x[i], col->scale_y[i], col->offset_x[i], col->offset_z[i]); + } + actor->type = BR_ACTOR_NONE; + actor = actor->next; + } + EndPipingSession(); + } + } + if (!pColour && (((1 << gNext_column) & gColumn_flags) == 0 || gSmoke_column[gNext_column].colour)) { + BrActorAdd(gNon_track_actor, gSmoke_column[gNext_column].flame_actor); + } + if (pColour && ((1 << gNext_column) & gColumn_flags) != 0 && !gSmoke_column[gNext_column].colour) { + BrActorRemove(gSmoke_column[gNext_column].flame_actor); + } + StartPipingSession(ePipe_chunk_smoke_column); + AddSmokeColumnToPipingSession(gNext_column, pCar, pVertex_index, pColour); + EndPipingSession(); + gSmoke_column[gNext_column].car = pCar; + gSmoke_column[gNext_column].colour = pColour; + gSmoke_column[gNext_column].lifetime = pLifetime; + gSmoke_column[gNext_column].time = 0; + gSmoke_column[gNext_column].smudge_timer = 1000; + gSmoke_column[gNext_column].vertex_index = pVertex_index; + gSmoke_column[gNext_column].upright = 1; + gColumn_flags |= 1 << gNext_column; + pCar->num_smoke_columns++; + for (i = 0; i < COUNT_OF(gSmoke_column[gNext_column].frame_count); i++) { + gSmoke_column[gNext_column].frame_count[i] = 100; + } + gNext_column++; + if (gNext_column >= MAX_SMOKE_COLUMNS) { + gNext_column = 0; + } } // IDA: void __cdecl GenerateSmokeShades() @@ -1342,7 +1406,59 @@ void FlameAnimate(int c, br_vector3* pPos, tU32 pTime) { br_actor* actor; int i; LOG_TRACE("(%d, %p, %d)", c, pPos, pTime); - NOT_IMPLEMENTED(); + + col = &gSmoke_column[c]; + actor = col->flame_actor; + DRMatrix34RotateY(&actor->t.t.mat, FastScalarArcTan2Angle(gCamera_to_world.m[2][0], gCamera_to_world.m[2][2])); + actor->t.t.translate.t = *pPos; + actor = actor->children; + + if (gAction_replay_mode) { + ReplayFlame(col, actor); + return; + } + for (i = 0; i < COUNT_OF(col->frame_count); i++) { + +#ifdef DETHRACE_FIX_BUGS + col->frame_time[i] += pTime; + if (col->frame_time[i] > FLAME_ANIMATION_FRAME_INTERVAL) { + col->frame_time[i] = 0; + col->frame_count[i]++; + } +#else + col->frame_count[i]++; +#endif + + if (col->frame_count[i] >= COUNT_OF(gFlame_map)) { + StartPipingSession(ePipe_chunk_flame); + AddFlameToPipingSession(i + 16 * c, col->frame_count[i] + 1, col->scale_x[i], col->scale_y[i], col->offset_x[i], col->offset_z[i]); + EndPipingSession(); + col->frame_count[i] = IRandomBetween(-5, -1); + col->scale_x[i] = (2 * IRandomBetween(0, 1) - 1) * SRandomBetween(1.0f, 1.5f) * 0.003f; + col->scale_y[i] = SRandomBetween(0.5f, 1.0f) * 0.003f; + col->offset_x[i] = SRandomPosNeg(0.03f); + col->offset_z[i] = SRandomBetween(-0.03f, 0.0); + actor->type = BR_ACTOR_NONE; + } + if (col->frame_count[i] == 0) { + if (BrVector3LengthSquared(&col->car->v) >= 80.0f || col->lifetime <= 30 * pTime) { + col->frame_count[i] = -5; + } else { + actor->type = BR_ACTOR_MODEL; + StartPipingSession(ePipe_chunk_flame); + AddFlameToPipingSession(i + 16 * c, col->frame_count[i] - 1, col->scale_x[i], col->scale_y[i], col->offset_x[i], col->offset_z[i]); + EndPipingSession(); + } + } + if (col->frame_count[i] >= 0) { + actor->material->colour_map = gFlame_map[col->frame_count[i]]; + BrMaterialUpdate(actor->material, BR_MATU_ALL); + BrMatrix34Scale(&actor->t.t.mat, gFlame_map[col->frame_count[i]]->width * col->scale_x[i], gFlame_map[col->frame_count[i]]->height * col->scale_y[i], 1.0); + actor->t.t.mat.m[3][0] = col->offset_x[i]; + actor->t.t.mat.m[3][2] = col->offset_z[i]; + } + actor = actor->next; + } } // IDA: void __usercall DoSmokeColumn(int i@, tU32 pTime@, br_vector3 *pRet_car_pos@) @@ -1352,7 +1468,30 @@ void DoSmokeColumn(int i, tU32 pTime, br_vector3* pRet_car_pos) { br_actor* bonny; int group; LOG_TRACE("(%d, %d, %p)", i, pTime, pRet_car_pos); - NOT_IMPLEMENTED(); + + c = gSmoke_column[i].car; + if (c->car_master_actor->t.t.mat.m[1][1] > 0.1f) { + gSmoke_column[i].upright = 1; + } + if (c->car_master_actor->t.t.mat.m[1][1] < -0.1f) { + gSmoke_column[i].upright = 0; + } + actor = c->car_model_actors[c->principal_car_actor].actor; + bonny = c->car_model_actors[c->car_actor_count - 1].actor; + + BrVector3Add(pRet_car_pos, &V11MODEL(actor->model)->groups->vertices[gSmoke_column[i].vertex_index].p, (br_vector3*)actor->t.t.mat.m[3]); + if (gProgram_state.cockpit_on && c->driver == eDriver_local_human) { + if (c->driver_z_offset + 0.2f <= pRet_car_pos->v[2]) { + pRet_car_pos->v[1] -= -0.07f; + } else { + BrMatrix34ApplyP(pRet_car_pos, &V11MODEL(actor->model)->groups->vertices[gSmoke_column[i].vertex_index].p, &bonny->t.t.mat); + } + } + if (!gSmoke_column[i].upright) { + pRet_car_pos->v[1] = c->bounds[1].min.v[1] / WORLD_SCALE; + } + BrMatrix34ApplyP(&gSmoke_column[i].pos, pRet_car_pos, &c->car_master_actor->t.t.mat); + gSmoke_column[i].pos.v[1] -= 0.03f; } // IDA: void __usercall ReplaySmokeColumn(tU32 pTime@) @@ -1380,7 +1519,83 @@ void MungeSmokeColumn(tU32 pTime) { tCar_spec* c; LOG_TRACE("(%d)", pTime); - STUB_ONCE(); + if (gColumn_flags == 0) { + return; + } + if (gAction_replay_mode) { + ReplaySmokeColumn(pTime); + return; + } + + gMechanics_time_sync = 1; + for (i = 0; i < MAX_SMOKE_COLUMNS; i++) { + if (((1 << i) & gColumn_flags) == 0) { + continue; + } + if (gSmoke_column[i].lifetime >= pTime) { + gSmoke_column[i].lifetime -= pTime; + c = gSmoke_column[i].car; + DoSmokeColumn(i, pTime, &car_pos); + if (!gSmoke_column[i].colour) { + FlameAnimate(i, &gSmoke_column[i].pos, pTime); + if (gSmoke_column[i].smudge_timer >= pTime) { + gSmoke_column[i].smudge_timer -= pTime; + } else { + gSmoke_column[i].smudge_timer += 2000; + SmudgeCar(gSmoke_column[i].car, gSmoke_column[i].vertex_index); + if (gSmoke_column[i].car->knackered) { + plane = IRandomBetween(0, COUNT_OF(gSmoke_column[i].car->fire_vertex) - 1); + SmudgeCar(gSmoke_column[i].car, gSmoke_column[i].car->fire_vertex[plane]); + } + } + } + gSmoke_column[i].time += pTime; + if (gSmoke_column[i].time > 200) { +#ifdef DETHRACE_FIX_BUGS + gSmoke_column[i].time -= fmaxf(SMOKE_COLUMN_NEW_PUFF_INTERVAL, pTime); +#else + gSmoke_column[i].time -= pTime; +#endif + gSmoke_column[i].count++; + BrVector3Cross(&v, &c->omega, &car_pos); + BrMatrix34ApplyV(&car_pos, &v, &c->car_master_actor->t.t.mat); + BrVector3Add(&v, &c->v, &car_pos); + v.v[1] = v.v[1] + 2.898550724637681f; // 100 / 34.5 ? + pos.v[0] = SRandomBetween(-0.03f, 0.03f) + gSmoke_column[i].pos.v[0]; + pos.v[1] = (gSmoke_column[i].colour == 0) * 0.05f + gSmoke_column[i].pos.v[1]; + pos.v[2] = SRandomBetween(-0.03f, 0.03f) + gSmoke_column[i].pos.v[2]; + if ((gSmoke_column[i].whiter & 2) == 0 || IRandomBetween(0, 3)) { + if (gSmoke_column[i].whiter < 1) { + gSmoke_column[i].whiter = -1; + } else { + gSmoke_column[i].whiter = 2; + } + } else { + gSmoke_column[i].whiter &= 1; + } + decay_factor = ((gSmoke_column[i].whiter > 0) + 1.0f) / 2.0f; + if (gSmoke_column[i].lifetime < 4000) { + decay_factor = gSmoke_column[i].lifetime * decay_factor / 4000.0f; + } + CreatePuffOfSmoke(&pos, &v, decay_factor, decay_factor, gSmoke_column[i].colour + 16, c); + } + } else { + if (gSmoke_column[i].car) { + StartPipingSession(ePipe_chunk_smoke_column); + AddSmokeColumnToPipingSession(i, gSmoke_column[i].car, gSmoke_column[i].vertex_index, gSmoke_column[i].colour); + EndPipingSession(); + } + gColumn_flags &= ~(1 << i); + if (!gSmoke_column[i].colour) { + BrActorRemove(gSmoke_column[i].flame_actor); + } + if (gSmoke_column[i].car) { + if (gSmoke_column[i].car->num_smoke_columns) { + gSmoke_column[i].car->num_smoke_columns--; + } + } + } + } } // IDA: void __cdecl DisposeFlame() @@ -1396,7 +1611,7 @@ void DisposeFlame() { BrPixelmapFree(gFlame_map[i]); } - for (i = 0; i < 5; i++) { + for (i = 0; i < MAX_SMOKE_COLUMNS; i++) { if ((gColumn_flags & (1 << i)) && (gSmoke_column[i].colour == 0)) { BrActorRemove(gSmoke_column[i].flame_actor); } @@ -1431,7 +1646,7 @@ void InitFlame() { FatalError(79, the_path); } BrMapAddMany(gFlame_map, COUNT_OF(gFlame_map)); - for (i = 0; i < 5; i++) { + for (i = 0; i < MAX_SMOKE_COLUMNS; i++) { gSmoke_column[i].flame_actor = BrActorAllocate(BR_ACTOR_NONE, NULL); for (j = 0; j < COUNT_OF(gSmoke_column[0].frame_count); j++) { actor = BrActorAllocate(BR_ACTOR_MODEL, NULL); @@ -1580,7 +1795,7 @@ void DrawTheGlow(br_pixelmap* pRender_screen, br_pixelmap* pDepth_buffer, br_act if (gColumn_flags) { seed = rand(); srand(GetTotalTime()); - for (i = 0; i < 5; i++) { + for (i = 0; i < MAX_SMOKE_COLUMNS; i++) { if (((1 << i) & gColumn_flags) != 0 && gSmoke_column[i].colour <= 1) { strength = 0.5; if (gSmoke_column[i].lifetime < 4000) { @@ -1626,7 +1841,8 @@ void SmudgeCar(tCar_spec* pCar, int fire_point) { tSmudged_vertex data[30]; int n; LOG_TRACE("(%p, %d)", pCar, fire_point); - NOT_IMPLEMENTED(); + + STUB_ONCE(); } // IDA: void __cdecl ResetSmokeColumns() @@ -1669,7 +1885,7 @@ void StopCarSmoking(tCar_spec* pCar) { int i; LOG_TRACE("(%p)", pCar); - for (i = 0; i < 5; i++) { + for (i = 0; i < MAX_SMOKE_COLUMNS; i++) { if (gSmoke_column[i].car == pCar && gSmoke_column[i].lifetime > 2000) { gSmoke_column[i].lifetime = 2000; } @@ -1681,7 +1897,7 @@ void StopCarSmokingInstantly(tCar_spec* pCar) { int i; LOG_TRACE("(%p)", pCar); - for (i = 0; i < 5; i++) { + for (i = 0; i < MAX_SMOKE_COLUMNS; i++) { if (gSmoke_column[i].car == pCar) { gSmoke_column[i].lifetime = 0; } @@ -1692,7 +1908,21 @@ void StopCarSmokingInstantly(tCar_spec* pCar) { void ConditionalSmokeColumn(tCar_spec* pCar, int pDamage_index, int pColour) { int i; LOG_TRACE("(%p, %d, %d)", pCar, pDamage_index, pColour); - NOT_IMPLEMENTED(); + + if (!pColour) { + pColour = pCar->driver < eDriver_net_human; + } + if (pCar->num_smoke_columns != 0) { + for (i = 0; i < MAX_SMOKE_COLUMNS; i++) { + if (gSmoke_column[i].car == pCar) { + if (((1 << i) & gColumn_flags) != 0 && gSmoke_column[i].colour <= pColour && gSmoke_column[i].lifetime) { + return; + } + gSmoke_column[i].lifetime = 2000; + } + } + } + CreateSmokeColumn(pCar, pColour, pCar->fire_vertex[pDamage_index], 10000000u); } // IDA: void __usercall SingleSplash(tCar_spec *pCar@, br_vector3 *sp@, br_vector3 *normal@, tU32 pTime@) @@ -2081,7 +2311,7 @@ void DisposeKevStuffCar(tCar_spec* pCar) { int i; LOG_TRACE("(%p)", pCar); - for (i = 0; i < 5; i++) { + for (i = 0; i < MAX_SMOKE_COLUMNS; i++) { if (gSmoke_column[i].car == pCar) { gSmoke_column[i].lifetime = 0; gSmoke_column[i].car = NULL; diff --git a/src/DETHRACE/constants.h b/src/DETHRACE/constants.h index eb6e0d22..41eae03e 100644 --- a/src/DETHRACE/constants.h +++ b/src/DETHRACE/constants.h @@ -1,246 +1,244 @@ #ifndef CONSTANTS_H #define CONSTANTS_H -#define V11MODEL(model) (((v11model*)model->prepared)) - -// Jeff: These names are not part of the symbol dump, so the names in this file are not original, except as noted. +// These names are not part of the symbol dump, so the names in this file are not original, except as noted. // Names from `gMem_names`. See also: `CreateStainlessClasses` typedef enum dr_memory_classes { - kMem_intf_pix_copy = 129, // 0x81 - kMem_intf_pal_copy = 130, // 0x82 - kMem_nodes_array = 131, // 0x83 - kMem_sections_array = 132, // 0x84 - kMem_key_names = 133, // 0x85 - kMem_columns_z = 134, // 0x86 - kMem_columns_x = 135, // 0x87 - kMem_non_car_list = 136, // 0x88 - kMem_simp_level = 137, // 0x89 - kMem_crush_data = 138, // 0x8a - kMem_crush_neighbours = 139, // 0x8b - kMem_temp_fs = 140, // 0x8c - kMem_error_pix_copy = 141, // 0x8d - kMem_error_pal_copy = 142, // 0x8e - kMem_flic_pal = 143, // 0x8f - kMem_flic_data = 144, // 0x90 - kMem_flic_data_2 = 145, // 0x91 - kMem_queued_flic = 146, // 0x92 - kFlic_panel_pixels = 147, // 0x93 - kMem_translations = 148, // 0x94 - kMem_translations_text = 149, // 0x95 - kMem_cur_pal_pixels = 150, // 0x96 - kMem_render_pal_pixels = 151, // 0x97 - kMem_scratch_pal_pixels = 152, // 0x98 - kMem_shade_table_copy = 153, // 0x99 - kMem_rear_screen_pixels = 154, // 0x9a - kMem_rolling_letters = 155, // 0x9b - kMem_intf_copy_areas = 156, // 0x9c - kMem_strip_image = 157, // 0x9d - kMem_strip_image_perm = 158, // 0x9e - kMem_damage_clauses = 159, // 0x9f - kMem_undamaged_vertices = 160, // 0xa0 - kMem_race_text_chunk = 161, // 0xa1 - kMem_race_text_str = 162, // 0xa2 - kMem_oppo_array = 163, // 0xa3 - kMem_oppo_text_chunk = 164, // 0xa4 - kMem_oppo_text_str = 165, // 0xa5 - kMem_br_font = 166, // 0xa6 - kMem_br_font_wid = 167, // 0xa7 - kMem_br_font_enc = 168, // 0xa8 - kMem_br_font_glyphs = 169, // 0xa9 - kMem_oppo_car_spec = 170, // 0xaa - kMem_misc_string = 171, // 0xab - kMem_mac_host_buffer_1 = 172, // 0xac - kMem_mac_host_buffer_2 = 173, // 0xad - kMem_mac_net_details = 174, // 0xae - kMem_back_pixels = 175, // 0xaf - kMem_quit_vfy_pixels = 176, // 0xb0 - kMem_quit_vfy_pal = 177, // 0xb1 - kMem_net_min_messages = 178, // 0xb2 - kMem_net_mid_messages = 179, // 0xb3 - kMem_net_max_messages = 180, // 0xb4 - kMem_net_pid_details = 181, // 0xb5 - kMem_net_car_spec = 182, // 0xb6 - kMem_dynamic_message = 183, // 0xb7 - kMem_player_list_join = 184, // 0xb8 - kMem_player_list_leave = 185, // 0xb9 - kMem_oppo_new_nodes = 186, // 0xba - kMem_oppo_new_sections = 187, // 0xbb - kMem_cop_car_spec = 188, // 0xbc - kMem_oppo_bit_per_node = 189, // 0xbd - kMem_ped_action_list = 190, // 0xbe - kMem_ped_sequences = 191, // 0xbf - kMem_ped_array_stain = 192, // 0xc0 - kMem_ped_array = 193, // 0xc1 - kMem_ped_instructions = 194, // 0xc2 - kMem_ped_new_instruc = 195, // 0xc3 - kMem_pipe_model_geometry = 196, // 0xc4 - kMem_powerup_array = 197, // 0xc5 - kMem_powerup_float_parms = 198, // 0xc6 - kMem_powerup_int_parms = 199, // 0xc7 - kMem_drugs_palette = 200, // 0xc8 - kMem_pratcam_flic_array = 201, // 0xc9 - kMem_pratcam_flic_data = 202, // 0xca - kMem_pratcam_sequence_array = 203, // 0xcb - kMem_pratcam_pixelmap = 204, // 0xcc - kMem_video_pixels = 205, // 0xcd - kMem_funk_prox_array = 206, // 0xce - kMem_new_mat_id = 207, // 0xcf - kMem_new_mat_id_2 = 208, // 0xd0 - kMem_new_mat_id_3 = 209, // 0xd1 - kMem_special_volume = 210, // 0xd2 - kMem_special_screen = 211, // 0xd3 - kMem_new_special_vol = 212, // 0xd4 - kMem_saved_game = 213, // 0xd5 - kMem_new_save_game = 214, // 0xd6 - kMem_stor_space_pix = 215, // 0xd7 - kMem_stor_space_tab = 216, // 0xd8 - kMem_stor_space_mat = 217, // 0xd9 - kMem_stor_space_mod = 218, // 0xda - kMem_stor_space_save = 219, // 0xdb - kMem_funk_spec = 220, // 0xdc - kMem_groove_spec = 221, // 0xdd - kMem_non_car_spec = 222, // 0xde - kMem_S3_scan_name = 223, // 0xdf - kMem_S3_sound_header = 224, // 0xe0 - kMem_S3_sample = 225, // 0xe1 - kMem_S3_mac_channel = 226, // 0xe2 - kMem_S3_mac_path = 227, // 0xe3 - kMem_S3_sentinel = 228, // 0xe4 - kMem_S3_outlet = 229, // 0xe5 - kMem_S3_channel = 230, // 0xe6 - kMem_S3_descriptor = 231, // 0xe7 - kMem_S3_reverse_buffer = 232, // 0xe8 - kMem_S3_source = 233, // 0xe9 - kMem_S3_DOS_SOS_channel = 234, // 0xea - kMem_S3_PC_DOS_path = 235, // 0xeb - kMem_S3_DOS_SOS_patch = 236, // 0xec - kMem_S3_DOS_SOS_song_structure = 237, // 0xed - kMem_S3_DOS_SOS_song_data = 238, // 0xee - kMem_S3_Windows_95_load_WAV_file = 239, // 0xef + kMem_intf_pix_copy = 129, // 0x81 + kMem_intf_pal_copy = 130, // 0x82 + kMem_nodes_array = 131, // 0x83 + kMem_sections_array = 132, // 0x84 + kMem_key_names = 133, // 0x85 + kMem_columns_z = 134, // 0x86 + kMem_columns_x = 135, // 0x87 + kMem_non_car_list = 136, // 0x88 + kMem_simp_level = 137, // 0x89 + kMem_crush_data = 138, // 0x8a + kMem_crush_neighbours = 139, // 0x8b + kMem_temp_fs = 140, // 0x8c + kMem_error_pix_copy = 141, // 0x8d + kMem_error_pal_copy = 142, // 0x8e + kMem_flic_pal = 143, // 0x8f + kMem_flic_data = 144, // 0x90 + kMem_flic_data_2 = 145, // 0x91 + kMem_queued_flic = 146, // 0x92 + kFlic_panel_pixels = 147, // 0x93 + kMem_translations = 148, // 0x94 + kMem_translations_text = 149, // 0x95 + kMem_cur_pal_pixels = 150, // 0x96 + kMem_render_pal_pixels = 151, // 0x97 + kMem_scratch_pal_pixels = 152, // 0x98 + kMem_shade_table_copy = 153, // 0x99 + kMem_rear_screen_pixels = 154, // 0x9a + kMem_rolling_letters = 155, // 0x9b + kMem_intf_copy_areas = 156, // 0x9c + kMem_strip_image = 157, // 0x9d + kMem_strip_image_perm = 158, // 0x9e + kMem_damage_clauses = 159, // 0x9f + kMem_undamaged_vertices = 160, // 0xa0 + kMem_race_text_chunk = 161, // 0xa1 + kMem_race_text_str = 162, // 0xa2 + kMem_oppo_array = 163, // 0xa3 + kMem_oppo_text_chunk = 164, // 0xa4 + kMem_oppo_text_str = 165, // 0xa5 + kMem_br_font = 166, // 0xa6 + kMem_br_font_wid = 167, // 0xa7 + kMem_br_font_enc = 168, // 0xa8 + kMem_br_font_glyphs = 169, // 0xa9 + kMem_oppo_car_spec = 170, // 0xaa + kMem_misc_string = 171, // 0xab + kMem_mac_host_buffer_1 = 172, // 0xac + kMem_mac_host_buffer_2 = 173, // 0xad + kMem_mac_net_details = 174, // 0xae + kMem_back_pixels = 175, // 0xaf + kMem_quit_vfy_pixels = 176, // 0xb0 + kMem_quit_vfy_pal = 177, // 0xb1 + kMem_net_min_messages = 178, // 0xb2 + kMem_net_mid_messages = 179, // 0xb3 + kMem_net_max_messages = 180, // 0xb4 + kMem_net_pid_details = 181, // 0xb5 + kMem_net_car_spec = 182, // 0xb6 + kMem_dynamic_message = 183, // 0xb7 + kMem_player_list_join = 184, // 0xb8 + kMem_player_list_leave = 185, // 0xb9 + kMem_oppo_new_nodes = 186, // 0xba + kMem_oppo_new_sections = 187, // 0xbb + kMem_cop_car_spec = 188, // 0xbc + kMem_oppo_bit_per_node = 189, // 0xbd + kMem_ped_action_list = 190, // 0xbe + kMem_ped_sequences = 191, // 0xbf + kMem_ped_array_stain = 192, // 0xc0 + kMem_ped_array = 193, // 0xc1 + kMem_ped_instructions = 194, // 0xc2 + kMem_ped_new_instruc = 195, // 0xc3 + kMem_pipe_model_geometry = 196, // 0xc4 + kMem_powerup_array = 197, // 0xc5 + kMem_powerup_float_parms = 198, // 0xc6 + kMem_powerup_int_parms = 199, // 0xc7 + kMem_drugs_palette = 200, // 0xc8 + kMem_pratcam_flic_array = 201, // 0xc9 + kMem_pratcam_flic_data = 202, // 0xca + kMem_pratcam_sequence_array = 203, // 0xcb + kMem_pratcam_pixelmap = 204, // 0xcc + kMem_video_pixels = 205, // 0xcd + kMem_funk_prox_array = 206, // 0xce + kMem_new_mat_id = 207, // 0xcf + kMem_new_mat_id_2 = 208, // 0xd0 + kMem_new_mat_id_3 = 209, // 0xd1 + kMem_special_volume = 210, // 0xd2 + kMem_special_screen = 211, // 0xd3 + kMem_new_special_vol = 212, // 0xd4 + kMem_saved_game = 213, // 0xd5 + kMem_new_save_game = 214, // 0xd6 + kMem_stor_space_pix = 215, // 0xd7 + kMem_stor_space_tab = 216, // 0xd8 + kMem_stor_space_mat = 217, // 0xd9 + kMem_stor_space_mod = 218, // 0xda + kMem_stor_space_save = 219, // 0xdb + kMem_funk_spec = 220, // 0xdc + kMem_groove_spec = 221, // 0xdd + kMem_non_car_spec = 222, // 0xde + kMem_S3_scan_name = 223, // 0xdf + kMem_S3_sound_header = 224, // 0xe0 + kMem_S3_sample = 225, // 0xe1 + kMem_S3_mac_channel = 226, // 0xe2 + kMem_S3_mac_path = 227, // 0xe3 + kMem_S3_sentinel = 228, // 0xe4 + kMem_S3_outlet = 229, // 0xe5 + kMem_S3_channel = 230, // 0xe6 + kMem_S3_descriptor = 231, // 0xe7 + kMem_S3_reverse_buffer = 232, // 0xe8 + kMem_S3_source = 233, // 0xe9 + kMem_S3_DOS_SOS_channel = 234, // 0xea + kMem_S3_PC_DOS_path = 235, // 0xeb + kMem_S3_DOS_SOS_patch = 236, // 0xec + kMem_S3_DOS_SOS_song_structure = 237, // 0xed + kMem_S3_DOS_SOS_song_data = 238, // 0xee + kMem_S3_Windows_95_load_WAV_file = 239, // 0xef kMem_S3_Windows_95_create_temp_buffer_space_to_reverse_sample = 240, // 0xf0 - kMem_S3_Windows_95_path = 241, // 0xf1 - kMem_DOS_HMI_file_open = 242, // 0xf2 - kMem_abuse_text = 243, // 0xf3 - kMem_action_replay_buffer = 244, // 0xf4 - kMem_misc = 245 // 0xf5 + kMem_S3_Windows_95_path = 241, // 0xf1 + kMem_DOS_HMI_file_open = 242, // 0xf2 + kMem_abuse_text = 243, // 0xf3 + kMem_action_replay_buffer = 244, // 0xf4 + kMem_misc = 245 // 0xf5 } dr_memory_classes; typedef enum keycodes { - KEY_SHIFT_ANY = 0, // 0x0 - KEY_ALT_ANY = 1, // 0x1 - KEY_CTRL_ANY = 2, // 0x2 - KEY_CTRL_ANY_2 = 3, // 0x3 - KEY_CAPSLOCK = 4, // 0x4 - KEY_RSHIFT = 5, // 0x5 - KEY_RALT = 6, // 0x6 - KEY_RCTRL = 7, // 0x7 - KEY_LSHIFT = 8, // 0x8 - KEY_LALT = 9, // 0x9 - KEY_LCTRL = 10, // 0xa - KEY_0 = 11, // 0xb - KEY_1 = 12, // 0xc - KEY_2 = 13, // 0xd - KEY_3 = 14, // 0xe - KEY_4 = 15, // 0xf - KEY_5 = 16, // 0x10 - KEY_6 = 17, // 0x11 - KEY_7 = 18, // 0x12 - KEY_8 = 19, // 0x13 - KEY_9 = 20, // 0x14 - KEY_A = 21, // 0x15 - KEY_B = 22, // 0x16 - KEY_C = 23, // 0x17 - KEY_D = 24, // 0x18 - KEY_E = 25, // 0x19 - KEY_F = 26, // 0x1a - KEY_G = 27, // 0x1b - KEY_H = 28, // 0x1c - KEY_I = 29, // 0x1d - KEY_J = 30, // 0x1e - KEY_K = 31, // 0x1f - KEY_L = 32, // 0x20 - KEY_M = 33, // 0x21 - KEY_N = 34, // 0x22 - KEY_O = 35, // 0x23 - KEY_P = 36, // 0x24 - KEY_Q = 37, // 0x25 - KEY_R = 38, // 0x26 - KEY_S = 39, // 0x27 - KEY_T = 40, // 0x28 - KEY_U = 41, // 0x29 - KEY_V = 42, // 0x2a - KEY_W = 43, // 0x2b - KEY_X = 44, // 0x2c - KEY_Y = 45, // 0x2d - KEY_Z = 46, // 0x2e - KEY_GRAVE = 47, // 0x2f - KEY_MINUS = 48, // 0x30 - KEY_EQUALS = 49, // 0x31 - KEY_BACKSPACE = 50, // 0x32 - KEY_RETURN = 51, // 0x33 - KEY_KP_ENTER = 52, // 0x34 - KEY_TAB = 53, // 0x35 - KEY_SLASH = 54, // 0x36 - KEY_UNKNOWN_55 = 55, // 0x37 - KEY_SEMICOLON = 56, // 0x38 - KEY_APOSTROPHE = 57, // 0x39 - KEY_PERIOD = 58, // 0x3a - KEY_COMMA = 59, // 0x3b - KEY_LBRACKET = 60, // 0x3c - KEY_RBRACKET = 61, // 0x3d - KEY_BACKSLASH = 62, // 0x3e - KEY_ESCAPE = 63, // 0x3f - KEY_INSERT = 64, // 0x40 - KEY_DELETE = 65, // 0x41 - KEY_HOME = 66, // 0x42 - KEY_END = 67, // 0x43 - KEY_PAGEUP = 68, // 0x44 - KEY_PAGEDOWN = 69, // 0x45 - KEY_LEFT = 70, // 0x46 - KEY_RIGHT = 71, // 0x47 - KEY_UP = 72, // 0x48 - KEY_DOWN = 73, // 0x49 - KEY_KP_NUMLOCK = 74, // 0x4a - KEY_KP_DIVIDE = 75, // 0x4b + KEY_SHIFT_ANY = 0, // 0x0 + KEY_ALT_ANY = 1, // 0x1 + KEY_CTRL_ANY = 2, // 0x2 + KEY_CTRL_ANY_2 = 3, // 0x3 + KEY_CAPSLOCK = 4, // 0x4 + KEY_RSHIFT = 5, // 0x5 + KEY_RALT = 6, // 0x6 + KEY_RCTRL = 7, // 0x7 + KEY_LSHIFT = 8, // 0x8 + KEY_LALT = 9, // 0x9 + KEY_LCTRL = 10, // 0xa + KEY_0 = 11, // 0xb + KEY_1 = 12, // 0xc + KEY_2 = 13, // 0xd + KEY_3 = 14, // 0xe + KEY_4 = 15, // 0xf + KEY_5 = 16, // 0x10 + KEY_6 = 17, // 0x11 + KEY_7 = 18, // 0x12 + KEY_8 = 19, // 0x13 + KEY_9 = 20, // 0x14 + KEY_A = 21, // 0x15 + KEY_B = 22, // 0x16 + KEY_C = 23, // 0x17 + KEY_D = 24, // 0x18 + KEY_E = 25, // 0x19 + KEY_F = 26, // 0x1a + KEY_G = 27, // 0x1b + KEY_H = 28, // 0x1c + KEY_I = 29, // 0x1d + KEY_J = 30, // 0x1e + KEY_K = 31, // 0x1f + KEY_L = 32, // 0x20 + KEY_M = 33, // 0x21 + KEY_N = 34, // 0x22 + KEY_O = 35, // 0x23 + KEY_P = 36, // 0x24 + KEY_Q = 37, // 0x25 + KEY_R = 38, // 0x26 + KEY_S = 39, // 0x27 + KEY_T = 40, // 0x28 + KEY_U = 41, // 0x29 + KEY_V = 42, // 0x2a + KEY_W = 43, // 0x2b + KEY_X = 44, // 0x2c + KEY_Y = 45, // 0x2d + KEY_Z = 46, // 0x2e + KEY_GRAVE = 47, // 0x2f + KEY_MINUS = 48, // 0x30 + KEY_EQUALS = 49, // 0x31 + KEY_BACKSPACE = 50, // 0x32 + KEY_RETURN = 51, // 0x33 + KEY_KP_ENTER = 52, // 0x34 + KEY_TAB = 53, // 0x35 + KEY_SLASH = 54, // 0x36 + KEY_UNKNOWN_55 = 55, // 0x37 + KEY_SEMICOLON = 56, // 0x38 + KEY_APOSTROPHE = 57, // 0x39 + KEY_PERIOD = 58, // 0x3a + KEY_COMMA = 59, // 0x3b + KEY_LBRACKET = 60, // 0x3c + KEY_RBRACKET = 61, // 0x3d + KEY_BACKSLASH = 62, // 0x3e + KEY_ESCAPE = 63, // 0x3f + KEY_INSERT = 64, // 0x40 + KEY_DELETE = 65, // 0x41 + KEY_HOME = 66, // 0x42 + KEY_END = 67, // 0x43 + KEY_PAGEUP = 68, // 0x44 + KEY_PAGEDOWN = 69, // 0x45 + KEY_LEFT = 70, // 0x46 + KEY_RIGHT = 71, // 0x47 + KEY_UP = 72, // 0x48 + KEY_DOWN = 73, // 0x49 + KEY_KP_NUMLOCK = 74, // 0x4a + KEY_KP_DIVIDE = 75, // 0x4b KEY_KP_MULTIPLY = 76, // 0x4c - KEY_KP_MINUS = 77, // 0x4d - KEY_KP_PLUS = 78, // 0x4e - KEY_KP_PERIOD = 79, // 0x4f - KEY_KP_EQUALS = 80, // 0x50 - KEY_KP_0 = 81, // 0x51 - KEY_KP_1 = 82, // 0x52 - KEY_KP_2 = 83, // 0x53 - KEY_KP_3 = 84, // 0x54 - KEY_KP_4 = 85, // 0x55 - KEY_KP_5 = 86, // 0x56 - KEY_KP_6 = 87, // 0x57 - KEY_KP_7 = 88, // 0x58 - KEY_KP_8 = 89, // 0x59 - KEY_KP_9 = 90, // 0x5a - KEY_F1 = 91, // 0x5b - KEY_F2 = 92, // 0x5c - KEY_F3 = 93, // 0x5d - KEY_F4 = 94, // 0x5e - KEY_F5 = 95, // 0x5f - KEY_F6 = 96, // 0x60 - KEY_F7 = 97, // 0x61 - KEY_F8 = 98, // 0x62 - KEY_F9 = 99, // 0x63 - KEY_F10 = 100, // 0x64 - KEY_F11 = 101, // 0x65 - KEY_F12 = 102, // 0x66 - KEY_PRTSCN = 103, // 0x67 - KEY_SCRLK = 104, // 0x68 - KEY_PAUSE = 105, // 0x69 - KEY_SPACE = 106, // 0x6a + KEY_KP_MINUS = 77, // 0x4d + KEY_KP_PLUS = 78, // 0x4e + KEY_KP_PERIOD = 79, // 0x4f + KEY_KP_EQUALS = 80, // 0x50 + KEY_KP_0 = 81, // 0x51 + KEY_KP_1 = 82, // 0x52 + KEY_KP_2 = 83, // 0x53 + KEY_KP_3 = 84, // 0x54 + KEY_KP_4 = 85, // 0x55 + KEY_KP_5 = 86, // 0x56 + KEY_KP_6 = 87, // 0x57 + KEY_KP_7 = 88, // 0x58 + KEY_KP_8 = 89, // 0x59 + KEY_KP_9 = 90, // 0x5a + KEY_F1 = 91, // 0x5b + KEY_F2 = 92, // 0x5c + KEY_F3 = 93, // 0x5d + KEY_F4 = 94, // 0x5e + KEY_F5 = 95, // 0x5f + KEY_F6 = 96, // 0x60 + KEY_F7 = 97, // 0x61 + KEY_F8 = 98, // 0x62 + KEY_F9 = 99, // 0x63 + KEY_F10 = 100, // 0x64 + KEY_F11 = 101, // 0x65 + KEY_F12 = 102, // 0x66 + KEY_PRTSCN = 103, // 0x67 + KEY_SCRLK = 104, // 0x68 + KEY_PAUSE = 105, // 0x69 + KEY_SPACE = 106, // 0x6a } keycodes; typedef enum keymapcodes { - KEYMAP_ESCAPE = 0, // default: ESC + KEYMAP_ESCAPE = 0, // default: ESC - KEYMAP_CONTROL_ANY = 7, // default: LCTRL or RCTRL (any) - KEYMAP_SHIFT_ANY = 8, // default: LSHIFT or RSHIFT (any) + KEYMAP_CONTROL_ANY = 7, // default: LCTRL or RCTRL (any) + KEYMAP_SHIFT_ANY = 8, // default: LSHIFT or RSHIFT (any) // // The following items are meant to be combined with KEYMAP_CONTROL_ANY @@ -257,55 +255,56 @@ typedef enum keymapcodes { // The following items are meant to be combined with KEYMAP_SHIFT_ANY // - KEYMAP_SHIFT_DUMPSCREEN = 5, // default: D + KEYMAP_SHIFT_DUMPSCREEN = 5, // default: D // // The following items are meant to be used standalone // - KEYMAP_COCKPIT = 45, // default C - KEYMAP_SAVE = 28, // default F2 - KEYMAP_LOAD = 29, // default F3 - KEYMAP_MOVE_UP = 30, // default UP - KEYMAP_MOVE_DOWN = 31, // default DOWN - KEYMAP_MOVE_LEFT = 32, // default LEFT - KEYMAP_MOVE_RIGHT = 33, // default RIGHT - KEYMAP_MIRROR = 34, // default M - KEYMAP_PRATCAM = 35, // default P - KEYMAP_LOOK_LEFT = 50, // default Q - KEYMAP_LOOK_FORWARD = 51, // default W - KEYMAP_LOOK_RIGHT = 52, // default E - KEYMAP_SOUND = 36, // default S - KEYMAP_PEDESTRIANS = 54, // default KP_MINUS - KEYMAP_F4 = 17, // default F4 - KEYMAP_F5 = 18, // default F5 - KEYMAP_F6 = 19, // default F6 - KEYMAP_F7 = 20, // default F7 - KEYMAP_F8 = 21, // default F8 - KEYMAP_F10 = 22, // default F10 - KEYMAP_F11 = 23, // default F1 - KEYMAP_F12 = 24, // default F12 - KEYMAP_EDITMODE_0 = 14, // default 0 - KEYMAP_EDITMODE_1 = 37, // default 1 - KEYMAP_EDITMODE_2 = 38, // default 2 - KEYMAP_EDITMODE_3 = 39, // default 3 - KEYMAP_EDITMODE_4 = 40, // default 4 - KEYMAP_EDITMODE_5 = 41, // default 5 - KEYMAP_EDITMODE_6 = 42, // default 6 - KEYMAP_EDITMODE_7 = 43, // default 7 - KEYMAP_EDITMODE_8 = 15, // default 8 - KEYMAP_EDITMODE_9 = 16, // default 9 - KEYMAP_SCREEN_SMALLER = 60, // default - - KEYMAP_SCREEN_LARGER = 61, // default = - KEYMAP_MAP = 56, // default TAB - KEYMAP_RECOVERY = 59, // default Insert - KEYMAP_BUY_ARMOUR = 62, // default Delete - KEYMAP_BUY_POWER = 63, // default End - KEYMAP_BUY_OFFENSE = 64, // default PgDn - KEYMAP_VIEW_NETPLAYER = 65, // default Space - KEYMAP_SEND_MESSAGE = 66, // default ` - KEYMAP_ARROW = 25, // default R - KEYMAP_INFO = 26, // default I + KEYMAP_COCKPIT = 45, // default C + KEYMAP_SAVE = 28, // default F2 + KEYMAP_LOAD = 29, // default F3 + KEYMAP_MOVE_UP = 30, // default UP + KEYMAP_MOVE_DOWN = 31, // default DOWN + KEYMAP_MOVE_LEFT = 32, // default LEFT + KEYMAP_MOVE_RIGHT = 33, // default RIGHT + KEYMAP_MIRROR = 34, // default M + KEYMAP_PRATCAM = 35, // default P + KEYMAP_LOOK_LEFT = 50, // default Q + KEYMAP_LOOK_FORWARD = 51, // default W + KEYMAP_LOOK_RIGHT = 52, // default E + KEYMAP_SOUND = 36, // default S + KEYMAP_REPAIR = 44, // default BACKSPACE + KEYMAP_PEDESTRIANS = 54, // default KP_MINUS + KEYMAP_F4 = 17, // default F4 + KEYMAP_F5 = 18, // default F5 + KEYMAP_F6 = 19, // default F6 + KEYMAP_F7 = 20, // default F7 + KEYMAP_F8 = 21, // default F8 + KEYMAP_F10 = 22, // default F10 + KEYMAP_F11 = 23, // default F1 + KEYMAP_F12 = 24, // default F12 + KEYMAP_EDITMODE_0 = 14, // default 0 + KEYMAP_EDITMODE_1 = 37, // default 1 + KEYMAP_EDITMODE_2 = 38, // default 2 + KEYMAP_EDITMODE_3 = 39, // default 3 + KEYMAP_EDITMODE_4 = 40, // default 4 + KEYMAP_EDITMODE_5 = 41, // default 5 + KEYMAP_EDITMODE_6 = 42, // default 6 + KEYMAP_EDITMODE_7 = 43, // default 7 + KEYMAP_EDITMODE_8 = 15, // default 8 + KEYMAP_EDITMODE_9 = 16, // default 9 + KEYMAP_SCREEN_SMALLER = 60, // default - + KEYMAP_SCREEN_LARGER = 61, // default = + KEYMAP_MAP = 56, // default TAB + KEYMAP_RECOVERY = 59, // default Insert + KEYMAP_BUY_ARMOUR = 62, // default Delete + KEYMAP_BUY_POWER = 63, // default End + KEYMAP_BUY_OFFENSE = 64, // default PgDn + KEYMAP_VIEW_NETPLAYER = 65, // default Space + KEYMAP_SEND_MESSAGE = 66, // default ` + KEYMAP_ARROW = 25, // default R + KEYMAP_INFO = 26, // default I } keymapcodes; #define FONT_TYPEABLE 0 @@ -338,14 +337,6 @@ typedef enum keymapcodes { #define NONCAR_UNUSED_SLOTS 5 -#define STR_STARTS_WITH(haystack, needle) strncmp(haystack, needle, strlen(needle)) -#define STR_ENDS_WITH(haystack, needle) strcmp(haystack + strlen(haystack) - strlen(needle), needle) -#define MAX(a, b) ((a) > (b) ? a : b) -#define COUNT_OF(array) (sizeof((array)) / sizeof((array)[0])) -#define LEN(array) (sizeof((array)) / sizeof((array)[0])) - -#define DEG_TO_RAD(degrees) ((degrees)*3.141592653589793 / 180.0) - #define ONEEIGHTTWO 182.0444444444444 #define d180_OVER_PI 57.29577951308232 // (180 / PI) @@ -362,6 +353,4 @@ typedef enum keymapcodes { #define DOUBLESIDED_FLAG_COLOR_MAP (br_pixelmap*)12345 -#define SLOBYTE(x) (*((signed char*)&(x))) - #endif diff --git a/src/DETHRACE/dr_types.h b/src/DETHRACE/dr_types.h index 165c1d60..66e1c018 100644 --- a/src/DETHRACE/dr_types.h +++ b/src/DETHRACE/dr_types.h @@ -3,6 +3,7 @@ #include "brender/br_types.h" #include "constants.h" +#include "macros.h" #include "s3/s3_types.h" #include #include @@ -10,15 +11,6 @@ #include #include -/* -typedef char * va_list[1]; -typedef unsigned short wchar_t; -typedef unsigned int size_t; -typedef char * __va_list[1]; -typedef __iobuf FILE; -typedef long fpos_t; -typedef void * onexit_t(); -*/ #ifdef _WIN32 #include #else @@ -780,7 +772,7 @@ typedef struct tCar_controls { unsigned int right : 1; // 0x20000 bit 18 unsigned int acc : 1; // 0x40000 bit 19 unsigned int dec : 1; // 0x80000 bit 20 - unsigned int brake : 1; //0x100000 bit 21 + unsigned int brake : 1; // 0x100000 bit 21 unsigned int up : 1; // 0x200000 bit 22 unsigned int down : 1; // 0x400000 bit 23 unsigned int holdw : 1; // 0x800000 bit 24 @@ -3095,8 +3087,6 @@ typedef struct tQueued_headup { char text[256]; } tQueued_headup; -//typedef unsigned long time_t; -//typedef unsigned long clock_t; typedef struct tFlicette { int flic_index; int x[2]; @@ -3663,6 +3653,11 @@ typedef struct tSmoke_column { tU32 smudge_timer; int vertex_index; int upright; + +#ifdef DETHRACE_FIX_BUGS + // Flames textures are animated per frame. At higher FPS, this happens too quickly + br_scalar frame_time[3]; +#endif } tSmoke_column; typedef struct tSplash { diff --git a/src/DETHRACE/macros.h b/src/DETHRACE/macros.h new file mode 100644 index 00000000..4f4f9c7a --- /dev/null +++ b/src/DETHRACE/macros.h @@ -0,0 +1,21 @@ +#ifndef MACROS_H +#define MACROS_H + +#define VEHICLE_TYPE_FROM_ID(id) ((tVehicle_type)(id >> 8)) +#define VEHICLE_INDEX_FROM_ID(id) (id & 0x00ff) + +//#define VEC3_TRANSLATE(mat) (*(br_vector3*)(&mat->m[3][0])) + +#define SLOBYTE(x) (*((signed char*)&(x))) + +#define STR_STARTS_WITH(haystack, needle) strncmp(haystack, needle, strlen(needle)) +#define STR_ENDS_WITH(haystack, needle) strcmp(haystack + strlen(haystack) - strlen(needle), needle) +#define MAX(a, b) ((a) > (b) ? a : b) +#define COUNT_OF(array) (sizeof((array)) / sizeof((array)[0])) +#define LEN(array) (sizeof((array)) / sizeof((array)[0])) + +#define DEG_TO_RAD(degrees) ((degrees)*3.141592653589793 / 180.0) + +#define V11MODEL(model) (((v11model*)model->prepared)) + +#endif \ No newline at end of file diff --git a/src/DETHRACE/pc-dos/dossys.c b/src/DETHRACE/pc-dos/dossys.c index b334e74e..dfabe835 100644 --- a/src/DETHRACE/pc-dos/dossys.c +++ b/src/DETHRACE/pc-dos/dossys.c @@ -228,8 +228,7 @@ void PDSetKeyArray(int* pKeys, int pMark) { gKeys_pressed = 0; for (i = 0; i < COUNT_OF(gScan_code); i++) { - if (KeyDown(gScan_code[i][0])) { //} || KeyDown(gScan_code[i][1])) { - + if (KeyDown(gScan_code[i][0])) { //} || KeyDown(gScan_code[i][1])) { gKeys_pressed = (gKeys_pressed << 8) + i + 1; pKeys[i] = pMark; } else if (pKeys[i] == pMark) { diff --git a/src/harness/harness.c b/src/harness/harness.c index 9ac449ed..4a57b752 100644 --- a/src/harness/harness.c +++ b/src/harness/harness.c @@ -34,7 +34,7 @@ tHarness_game_info harness_game_info; // Configuration options tHarness_game_config harness_game_config; - +/* clang-format off */ // German ASCII codes static int carmageddon_german_ascii_table[128] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, @@ -76,6 +76,7 @@ static int splatpack_xmasdemo_ascii_shift_table[128] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 42, 45, 43, 46, 0, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 8, }; +/* clang-format on */ int Harness_ProcessCommandLine(int* argc, char* argv[]); @@ -109,12 +110,11 @@ void Harness_DetectGameMode() { harness_game_info.defines.GERMAN_LOADSCRN = "COWLESS.PIX"; harness_game_info.mode = eGame_carmageddon_demo; LOG_INFO("\"%s\"", "Carmageddon demo"); - } - else { + } else { goto carmageddon; } } else { -carmageddon: + carmageddon: if (access("DATA/CUTSCENE/Mix_intr.smk", F_OK) == -1) { harness_game_info.defines.INTRO_SMK_FILE = "Mix_intr.smk"; } else { @@ -127,11 +127,11 @@ carmageddon: harness_game_info.localization = eGameLocalization_none; if (access("DATA/TRNSLATE.TXT", F_OK) != -1) { - FILE *f = fopen("DATA/TRNSLATE.TXT", "rb"); + FILE* f = fopen("DATA/TRNSLATE.TXT", "rb"); fseek(f, 0, SEEK_END); int filesize = ftell(f); fseek(f, 0, SEEK_SET); - char *buffer = malloc(filesize + 1); + char* buffer = malloc(filesize + 1); int nb = fread(buffer, 1, filesize, f); if (nb != filesize) { LOG_PANIC("Unable to read DATA/TRNSLATE.TXT"); @@ -224,7 +224,6 @@ void Harness_ForceNullRenderer() { renderer = &null_renderer; } - int Harness_ProcessCommandLine(int* argc, char* argv[]) { for (int i = 1; i < *argc; i++) { int handled = 0; @@ -393,6 +392,10 @@ void Harness_Hook_BrBufferUpdate(br_pixelmap* pm, br_token use, br_uint_16 flags } } +void Harness_Hook_BrModelUpdate(br_model* model) { + renderer->BufferModel(model); +} + // Input hooks void Harness_Hook_GetMousePosition(int* pX, int* pY) { Input_GetMousePosition(pX, pY); diff --git a/src/harness/include/harness/hooks.h b/src/harness/include/harness/hooks.h index 795da1b8..889126a9 100644 --- a/src/harness/include/harness/hooks.h +++ b/src/harness/include/harness/hooks.h @@ -28,6 +28,7 @@ void Harness_Hook_renderFaces(br_actor* actor, br_model* model, br_material* mat void Harness_Hook_BrZbSceneRenderEnd(); void Harness_Hook_BrBufferUpdate(br_pixelmap* pm, br_token use, br_uint_16 flags); void Harness_Hook_BrMaterialUpdate(br_material* mat, br_uint_16 flags); +void Harness_Hook_BrModelUpdate(br_model* model); // Input hooks void Harness_Hook_GetMousePosition(int* pX, int* pY); diff --git a/src/harness/io_platforms/sdl_gl.c b/src/harness/io_platforms/sdl_gl.c index 3d0e9f47..f531ae7a 100644 --- a/src/harness/io_platforms/sdl_gl.c +++ b/src/harness/io_platforms/sdl_gl.c @@ -12,113 +12,113 @@ int scancode_map[123]; const int scancodes_dethrace2sdl[123] = { - -1, // 0 (LSHIFT || RSHIFT) - -1, // 1 (LALT || RALT) - -1, // 2 (LCTRL || RCTRL) - -1, // 3 (LCTRL || RCTRL) - SDL_SCANCODE_CAPSLOCK, // 4 - SDL_SCANCODE_RSHIFT, // 5 - SDL_SCANCODE_RALT, // 6 - SDL_SCANCODE_RCTRL, // 7 - SDL_SCANCODE_LSHIFT, // 8 - SDL_SCANCODE_LALT, // 9 - SDL_SCANCODE_LCTRL, // 10 - SDL_SCANCODE_0, // 11 - SDL_SCANCODE_1, // 12 - SDL_SCANCODE_2, // 13 - SDL_SCANCODE_3, // 14 - SDL_SCANCODE_4, // 15 - SDL_SCANCODE_5, // 16 - SDL_SCANCODE_6, // 17 - SDL_SCANCODE_7, // 18 - SDL_SCANCODE_8, // 19 - SDL_SCANCODE_9, // 20 - SDL_SCANCODE_A, // 21 - SDL_SCANCODE_B, // 22 - SDL_SCANCODE_C, // 23 - SDL_SCANCODE_D, // 24 - SDL_SCANCODE_E, // 25 - SDL_SCANCODE_F, // 26 - SDL_SCANCODE_G, // 27 - SDL_SCANCODE_H, // 28 - SDL_SCANCODE_I, // 29 - SDL_SCANCODE_J, // 30 - SDL_SCANCODE_K, // 31 - SDL_SCANCODE_L, // 32 - SDL_SCANCODE_M, // 33 - SDL_SCANCODE_N, // 34 - SDL_SCANCODE_O, // 35 - SDL_SCANCODE_P, // 36 - SDL_SCANCODE_Q, // 37 - SDL_SCANCODE_R, // 38 - SDL_SCANCODE_S, // 39 - SDL_SCANCODE_T, // 40 - SDL_SCANCODE_U, // 41 - SDL_SCANCODE_V, // 42 - SDL_SCANCODE_W, // 43 - SDL_SCANCODE_X, // 44 - SDL_SCANCODE_Y, // 45 - SDL_SCANCODE_Z, // 46 - SDL_SCANCODE_GRAVE, // 47 - SDL_SCANCODE_MINUS, // 48 - SDL_SCANCODE_EQUALS, // 49 - SDL_SCANCODE_BACKSPACE, // 50 - SDL_SCANCODE_RETURN, // 51 - SDL_SCANCODE_KP_ENTER, // 52 - SDL_SCANCODE_TAB, // 53 - SDL_SCANCODE_SLASH, // 54 - -1, // 55 - SDL_SCANCODE_SEMICOLON, // 56 - SDL_SCANCODE_APOSTROPHE, // 57 - SDL_SCANCODE_PERIOD, // 58 - SDL_SCANCODE_COMMA, // 59 - SDL_SCANCODE_LEFTBRACKET, // 60 - SDL_SCANCODE_RIGHTBRACKET, // 61 - SDL_SCANCODE_BACKSLASH, // 62 - SDL_SCANCODE_ESCAPE, // 63 - SDL_SCANCODE_INSERT, // 64 - SDL_SCANCODE_DELETE, // 65 - SDL_SCANCODE_HOME, // 66 - SDL_SCANCODE_END, // 67 - SDL_SCANCODE_PAGEUP, // 68 - SDL_SCANCODE_PAGEDOWN, // 69 - SDL_SCANCODE_LEFT, // 70 - SDL_SCANCODE_RIGHT, // 71 - SDL_SCANCODE_UP, // 72 - SDL_SCANCODE_DOWN, // 73 - SDL_SCANCODE_NUMLOCKCLEAR, // 74 - SDL_SCANCODE_KP_DIVIDE, // 75 - SDL_SCANCODE_KP_MULTIPLY, // 76 - SDL_SCANCODE_KP_MINUS, // 77 - SDL_SCANCODE_KP_PLUS, // 78 - SDL_SCANCODE_KP_PERIOD, // 79 - SDL_SCANCODE_KP_EQUALS, // 80 - SDL_SCANCODE_KP_0, // 81 - SDL_SCANCODE_KP_1, // 82 - SDL_SCANCODE_KP_2, // 83 - SDL_SCANCODE_KP_3, // 84 - SDL_SCANCODE_KP_4, // 85 - SDL_SCANCODE_KP_5, // 86 - SDL_SCANCODE_KP_6, // 87 - SDL_SCANCODE_KP_7, // 88 - SDL_SCANCODE_KP_8, // 89 - SDL_SCANCODE_KP_9, // 90 - SDL_SCANCODE_F1, // 91 - SDL_SCANCODE_F2, // 92 - SDL_SCANCODE_F3, // 93 - SDL_SCANCODE_F4, // 94 - SDL_SCANCODE_F5, // 95 - SDL_SCANCODE_F6, // 96 - SDL_SCANCODE_F7, // 97 - SDL_SCANCODE_F8, // 98 - SDL_SCANCODE_F9, // 99 - SDL_SCANCODE_F10, // 100 - SDL_SCANCODE_F11, // 101 - SDL_SCANCODE_F12, // 102 - SDL_SCANCODE_PRINTSCREEN, // 103 - SDL_SCANCODE_SCROLLLOCK, // 104 - SDL_SCANCODE_PAUSE, // 105 - SDL_SCANCODE_SPACE, // 106 + -1, // 0 (LSHIFT || RSHIFT) + -1, // 1 (LALT || RALT) + -1, // 2 (LCTRL || RCTRL) + -1, // 3 (LCTRL || RCTRL) + SDL_SCANCODE_CAPSLOCK, // 4 + SDL_SCANCODE_RSHIFT, // 5 + SDL_SCANCODE_RALT, // 6 + SDL_SCANCODE_RCTRL, // 7 + SDL_SCANCODE_LSHIFT, // 8 + SDL_SCANCODE_LALT, // 9 + SDL_SCANCODE_LCTRL, // 10 + SDL_SCANCODE_0, // 11 + SDL_SCANCODE_1, // 12 + SDL_SCANCODE_2, // 13 + SDL_SCANCODE_3, // 14 + SDL_SCANCODE_4, // 15 + SDL_SCANCODE_5, // 16 + SDL_SCANCODE_6, // 17 + SDL_SCANCODE_7, // 18 + SDL_SCANCODE_8, // 19 + SDL_SCANCODE_9, // 20 + SDL_SCANCODE_A, // 21 + SDL_SCANCODE_B, // 22 + SDL_SCANCODE_C, // 23 + SDL_SCANCODE_D, // 24 + SDL_SCANCODE_E, // 25 + SDL_SCANCODE_F, // 26 + SDL_SCANCODE_G, // 27 + SDL_SCANCODE_H, // 28 + SDL_SCANCODE_I, // 29 + SDL_SCANCODE_J, // 30 + SDL_SCANCODE_K, // 31 + SDL_SCANCODE_L, // 32 + SDL_SCANCODE_M, // 33 + SDL_SCANCODE_N, // 34 + SDL_SCANCODE_O, // 35 + SDL_SCANCODE_P, // 36 + SDL_SCANCODE_Q, // 37 + SDL_SCANCODE_R, // 38 + SDL_SCANCODE_S, // 39 + SDL_SCANCODE_T, // 40 + SDL_SCANCODE_U, // 41 + SDL_SCANCODE_V, // 42 + SDL_SCANCODE_W, // 43 + SDL_SCANCODE_X, // 44 + SDL_SCANCODE_Y, // 45 + SDL_SCANCODE_Z, // 46 + SDL_SCANCODE_GRAVE, // 47 + SDL_SCANCODE_MINUS, // 48 + SDL_SCANCODE_EQUALS, // 49 + SDL_SCANCODE_BACKSPACE, // 50 + SDL_SCANCODE_RETURN, // 51 + SDL_SCANCODE_KP_ENTER, // 52 + SDL_SCANCODE_TAB, // 53 + SDL_SCANCODE_SLASH, // 54 + -1, // 55 + SDL_SCANCODE_SEMICOLON, // 56 + SDL_SCANCODE_APOSTROPHE, // 57 + SDL_SCANCODE_PERIOD, // 58 + SDL_SCANCODE_COMMA, // 59 + SDL_SCANCODE_LEFTBRACKET, // 60 + SDL_SCANCODE_RIGHTBRACKET, // 61 + SDL_SCANCODE_BACKSLASH, // 62 + SDL_SCANCODE_ESCAPE, // 63 + SDL_SCANCODE_INSERT, // 64 + SDL_SCANCODE_DELETE, // 65 + SDL_SCANCODE_HOME, // 66 + SDL_SCANCODE_END, // 67 + SDL_SCANCODE_PAGEUP, // 68 + SDL_SCANCODE_PAGEDOWN, // 69 + SDL_SCANCODE_LEFT, // 70 + SDL_SCANCODE_RIGHT, // 71 + SDL_SCANCODE_UP, // 72 + SDL_SCANCODE_DOWN, // 73 + SDL_SCANCODE_NUMLOCKCLEAR, // 74 + SDL_SCANCODE_KP_DIVIDE, // 75 + SDL_SCANCODE_KP_MULTIPLY, // 76 + SDL_SCANCODE_KP_MINUS, // 77 + SDL_SCANCODE_KP_PLUS, // 78 + SDL_SCANCODE_KP_PERIOD, // 79 + SDL_SCANCODE_KP_EQUALS, // 80 + SDL_SCANCODE_KP_0, // 81 + SDL_SCANCODE_KP_1, // 82 + SDL_SCANCODE_KP_2, // 83 + SDL_SCANCODE_KP_3, // 84 + SDL_SCANCODE_KP_4, // 85 + SDL_SCANCODE_KP_5, // 86 + SDL_SCANCODE_KP_6, // 87 + SDL_SCANCODE_KP_7, // 88 + SDL_SCANCODE_KP_8, // 89 + SDL_SCANCODE_KP_9, // 90 + SDL_SCANCODE_F1, // 91 + SDL_SCANCODE_F2, // 92 + SDL_SCANCODE_F3, // 93 + SDL_SCANCODE_F4, // 94 + SDL_SCANCODE_F5, // 95 + SDL_SCANCODE_F6, // 96 + SDL_SCANCODE_F7, // 97 + SDL_SCANCODE_F8, // 98 + SDL_SCANCODE_F9, // 99 + SDL_SCANCODE_F10, // 100 + SDL_SCANCODE_F11, // 101 + SDL_SCANCODE_F12, // 102 + SDL_SCANCODE_PRINTSCREEN, // 103 + SDL_SCANCODE_SCROLLLOCK, // 104 + SDL_SCANCODE_PAUSE, // 105 + SDL_SCANCODE_SPACE, // 106 }; int scancodes_sdl2dethrace[SDL_NUM_SCANCODES]; @@ -140,6 +140,7 @@ tRenderer gl_renderer = { GLRenderer_ClearBuffers, GLRenderer_BufferTexture, GLRenderer_BufferMaterial, + GLRenderer_BufferModel, GLRenderer_FlushBuffers }; @@ -232,7 +233,7 @@ void Input_Init() { scancodes_sdl2dethrace[i] = -1; } for (size_t i = 0; i < ARRAY_LEN(scancodes_dethrace2sdl); i++) { - if (scancodes_dethrace2sdl[i] != -1 ) { + if (scancodes_dethrace2sdl[i] != -1) { scancodes_sdl2dethrace[scancodes_dethrace2sdl[i]] = i; } } diff --git a/src/harness/renderers/gl/gl_renderer.c b/src/harness/renderers/gl/gl_renderer.c index 2664e1af..df09dec8 100644 --- a/src/harness/renderers/gl/gl_renderer.c +++ b/src/harness/renderers/gl/gl_renderer.c @@ -193,7 +193,6 @@ void GLRenderer_Init(int width, int height, int pRender_width, int pRender_heigh glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDepthFunc(GL_LESS); - glEnable(GL_CULL_FACE); glClearColor(0, 0, 0, 1.0f); glClear(GL_COLOR_BUFFER_BIT); @@ -357,10 +356,14 @@ void GLRenderer_ClearBuffers() { CHECK_GL_ERROR("GLRenderer_Swap"); } -void build_model(br_model* model) { +void GLRenderer_BufferModel(br_model* model) { tStored_model_context* ctx; v11model* v11; + if (model->stored != NULL) { + LOG_PANIC("trying to build a stored model"); + } + v11 = model->prepared; ctx = NewStoredModelContext(); @@ -450,25 +453,33 @@ void build_model(br_model* model) { CHECK_GL_ERROR("after build model"); } +tStored_material* current_material; void setActiveMaterial(tStored_material* material) { - if (material) { - glUniform1i(uniforms_3d.palette_index_override, material->index_base); - if (material->shade_table) { - GLRenderer_SetShadeTable(material->shade_table); - } - if ((material->flags & BR_MATF_LIGHT) && !(material->flags & BR_MATF_PRELIT) && material->shade_table) { - // TODO: light value shouldn't always be 0? Works for shadows, not sure about other things. - glUniform1i(uniforms_3d.light_value, 0); - } else { - glUniform1i(uniforms_3d.light_value, -1); - } + if (material == NULL || material == current_material) { + return; + } - if (material->pixelmap) { - tStored_pixelmap* stored_px = material->pixelmap->stored; - if (stored_px) { - glBindTexture(GL_TEXTURE_2D, stored_px->id); - glUniform1i(uniforms_3d.palette_index_override, -1); - } + glUniform1i(uniforms_3d.palette_index_override, material->index_base); + if (material->shade_table) { + GLRenderer_SetShadeTable(material->shade_table); + } + if ((material->flags & BR_MATF_LIGHT) && !(material->flags & BR_MATF_PRELIT) && material->shade_table) { + // TODO: light value shouldn't always be 0? Works for shadows, not sure about other things. + glUniform1i(uniforms_3d.light_value, 0); + } else { + glUniform1i(uniforms_3d.light_value, -1); + } + if (material->flags & BR_MATF_ALWAYS_VISIBLE) { + glDisable(GL_CULL_FACE); + } else { + glEnable(GL_CULL_FACE); + } + + if (material->pixelmap) { + tStored_pixelmap* stored_px = material->pixelmap->stored; + if (stored_px) { + glBindTexture(GL_TEXTURE_2D, stored_px->id); + glUniform1i(uniforms_3d.palette_index_override, -1); } } } @@ -484,12 +495,6 @@ void GLRenderer_Model(br_actor* actor, br_model* model, br_matrix34 model_matrix return; } - if (ctx == NULL) { - build_model(model); - ctx = model->stored; - - // DebugCamera_SetPosition(model_matrix.m[3][0], model_matrix.m[3][1], model_matrix.m[3][2]); - } CHECK_GL_ERROR("rm1"); glEnable(GL_DEPTH_TEST); diff --git a/src/harness/renderers/gl/gl_renderer.h b/src/harness/renderers/gl/gl_renderer.h index 1eb426c5..cb85841b 100644 --- a/src/harness/renderers/gl/gl_renderer.h +++ b/src/harness/renderers/gl/gl_renderer.h @@ -41,6 +41,7 @@ void GLRenderer_FullScreenQuad(uint8_t* screen_buffer, int width, int height); void GLRenderer_Model(br_actor* actor, br_model* model, br_matrix34 model_matrix); void GLRenderer_BufferTexture(br_pixelmap* pm); void GLRenderer_BufferMaterial(br_material* mat); +void GLRenderer_BufferModel(br_model* model); void GLRenderer_ClearBuffers(); void GLRenderer_FlushBuffers(br_pixelmap* color_buffer, br_pixelmap* depth_buffer); diff --git a/src/harness/renderers/null.h b/src/harness/renderers/null.h index 88737bfa..d8f8a641 100644 --- a/src/harness/renderers/null.h +++ b/src/harness/renderers/null.h @@ -10,6 +10,7 @@ void Null_RenderFrameBuffer() {} void Null_ClearBuffers() {} void Null_BufferTexture(br_pixelmap* pm) {} void Null_BufferMaterial(br_material* mat) {} +void Null_BufferModel(br_model* model) {} void Null_FlushBuffers(br_pixelmap* color_buffer, br_pixelmap* depth_buffer) {} tRenderer null_renderer = { @@ -22,5 +23,6 @@ tRenderer null_renderer = { Null_ClearBuffers, Null_BufferTexture, Null_BufferMaterial, + Null_BufferModel, Null_FlushBuffers }; \ No newline at end of file diff --git a/src/harness/renderers/renderer.h b/src/harness/renderers/renderer.h index 7c8936d6..bf89705e 100644 --- a/src/harness/renderers/renderer.h +++ b/src/harness/renderers/renderer.h @@ -13,6 +13,7 @@ typedef struct tRenderer { void (*ClearBuffers)(); void (*BufferTexture)(br_pixelmap* pm); void (*BufferMaterial)(br_material* mat); + void (*BufferModel)(br_model* model); void (*FlushBuffers)(br_pixelmap* color_buffer, br_pixelmap* depth_buffer); } tRenderer;