Vehicle damage (#116)

* implement damage and repair

* clang format align trailing comments

* damage HUD

* wheel rotation damage wobbles
This commit is contained in:
Dethrace Engineering Department 2022-04-01 10:52:09 +13:00 committed by GitHub
parent 4115ce64eb
commit 3ea4dc83fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 1844 additions and 878 deletions

View File

@ -7,7 +7,7 @@ AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: false
AlignOperands: false
AlignTrailingComments: false
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false

View File

@ -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 <assert.h>
@ -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 : "<NULL>");
}
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 : "<NULL>");
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@<EAX>)

View File

@ -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)

View File

@ -3,7 +3,9 @@
// Inspired by BRender SDK includes (https://rr2000.cwaboard.co.uk/R4/BRENDER/BRENDER.zip)
#define PI 3.14159265358979323846
#include <math.h> // sqrtf
#define PI 3.14159265358979323846
#define TAU 6.283185307179586
#define BR_MAC3(a, b, c, d, e, f) ((a) * (b) + (c) * (d) + (e) * (f))

View File

@ -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);

View File

@ -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@<EAX>(tCar_spec *c@<EAX>)
@ -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@<EAX>, int crush_only@<EDX>)
@ -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)

View File

@ -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@<EAX>)
void SetSoundDetailLevel(int pLevel) {
LOG_TRACE("(%d)", pLevel);
gSound_detail_level = pLevel;
}

View File

@ -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 <stdlib.h>
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@<EAX>(FILE *pF@<EAX>, tCrush_data *pCrush_data@<EDX>)
@ -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@<EAX>, int pModel_index@<EDX>, br_actor *pActor@<EBX>, br_vector3 *pImpact_point@<ECX>, 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@<ST0>(tCar_spec *pCar@<EAX>, int pModel_index@<EDX>, br_actor *pActor@<EBX>, br_vertex *pUndamaged_vertices@<ECX>, 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@<ST0>(tCar_spec *pCar@<EAX>, tU32 pFrame_period@<EDX>, br_scalar *pTotal_deflection@<EBX>)
@ -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@<ST0>(tU16 pCar_ID@<EAX>, tU32 pFrame_period@<EDX>, br_scalar *pTotal_deflection@<EBX>)
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@<EAX>)
@ -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@<EAX>)
@ -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@<EAX>, tDamage_type pDamage_type@<EDX>, 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@<EAX>, br_vector3 *pImpact_point@<EDX>, br_vector3 *pEnergy@<EBX>)
@ -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@<EAX>(tCar_spec *pCar@<EAX>)
@ -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@<EAX>, br_vector3 *pImpact_point@<EDX>, br_vector3 *pEnergy_vector@<EBX>, int pWas_hitting_a_car@<ECX>)
@ -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@<EAX>(br_vector3 *pVelocity@<EAX>)
@ -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@<EAX>)
@ -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@<EAX>)
@ -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@<EAX>, tCar_spec *pCar2@<EDX>)
void CrashEarnings(tCar_spec* pCar1, tCar_spec* pCar2) {
LOG_TRACE("(%p, %p)", pCar1, pCar2);
STUB_ONCE();
if (DoCrashEarnings(pCar1, pCar2)) {
SortOutSmoke(pCar1);
SortOutSmoke(pCar2);
}
}

View File

@ -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@<EAX>, int pLeft@<EDX>, int pTop@<EBX>, int pRight@<ECX>, 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@<EAX>, char *pText@<EDX>, br_pixelmap *pPixelmap@<EBX>, int pLeft@<ECX>, int pTop, int pRight, int pBottom, int pCentred)

View File

@ -32,6 +32,7 @@
#include "trig.h"
#include "utility.h"
#include "world.h"
#include <limits.h>
#include <stdlib.h>
#include <math.h>
@ -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@<EAX>, int pWobble_y@<EDX>)

View File

@ -310,7 +310,7 @@ void WaitForAKey() {
while (1) {
CheckQuit();
if (AnyKeyDown( )) {
if (AnyKeyDown()) {
break;
}
if (EitherMouseButtonDown()) {

View File

@ -10,7 +10,7 @@
#include <stdlib.h>
#include <string.h>
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@<EAX>)

View File

@ -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 <stdlib.h>
#include <string.h>
@ -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@<EAX>)
@ -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@<EAX>, int pWobble_y@<EDX>)
@ -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();

View File

@ -15,7 +15,6 @@
#include "utility.h"
#include "world.h"
#include <math.h>
#include <stdlib.h>
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@<EAX>, tU32 pTime@<EDX>, br_vector3 *pRet_car_pos@<EBX>)
@ -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@<EAX>)
@ -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@<EAX>, br_vector3 *sp@<EDX>, br_vector3 *normal@<EBX>, tU32 pTime@<ECX>)
@ -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;

View File

@ -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

View File

@ -3,6 +3,7 @@
#include "brender/br_types.h"
#include "constants.h"
#include "macros.h"
#include "s3/s3_types.h"
#include <assert.h>
#include <stdarg.h>
@ -10,15 +11,6 @@
#include <stdint.h>
#include <stdio.h>
/*
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 <windows.h>
#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 {

21
src/DETHRACE/macros.h Normal file
View File

@ -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

View File

@ -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) {

View File

@ -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);

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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
};

View File

@ -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;