5698 lines
212 KiB
C
5698 lines
212 KiB
C
// car.c + stuff.c
|
|
|
|
#include "car.h"
|
|
#include "brender/brender.h"
|
|
#include "car.h"
|
|
#include "constants.h"
|
|
#include "controls.h"
|
|
#include "crush.h"
|
|
#include "displays.h"
|
|
#include "finteray.h"
|
|
#include "globvars.h"
|
|
#include "globvrkm.h"
|
|
#include "globvrpb.h"
|
|
#include "graphics.h"
|
|
#include "harness/config.h"
|
|
#include "harness/trace.h"
|
|
#include "netgame.h"
|
|
#include "network.h"
|
|
#include "oil.h"
|
|
#include "opponent.h"
|
|
#include "pd/sys.h"
|
|
#include "piping.h"
|
|
#include "raycast.h"
|
|
#include "replay.h"
|
|
#include "skidmark.h"
|
|
#include "sound.h"
|
|
#include "spark.h"
|
|
#include "trig.h"
|
|
#include "utility.h"
|
|
#include "world.h"
|
|
#include <math.h>
|
|
#include <stdlib.h>
|
|
|
|
int gDoing_physics;
|
|
br_scalar gDt;
|
|
// suffix added to avoid duplicate symbol
|
|
int gCollision_detection_on__car = 1;
|
|
// suffix added to avoid duplicate symbol
|
|
br_vector3 gGround_normal__car;
|
|
// suffix added to avoid duplicate symbol
|
|
void (*ControlCar[6])(tCar_spec*, br_scalar) = {
|
|
&ControlCar1,
|
|
&ControlCar2,
|
|
&ControlCar3,
|
|
&ControlCar4,
|
|
&ControlCar5,
|
|
NULL
|
|
};
|
|
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;
|
|
br_vector3 gCamera_pos_before_collide;
|
|
int gMetal_crunch_sound_id__car[5] = {
|
|
// suffix added to avoid duplicate symbol
|
|
5000,
|
|
5001,
|
|
5002,
|
|
5003,
|
|
5004,
|
|
};
|
|
int gMetal_scrape_sound_id__car[3] = {
|
|
// suffix added to avoid duplicate symbol
|
|
5010,
|
|
5011,
|
|
5012,
|
|
};
|
|
int gCar_car_collisions;
|
|
int gFreeze_mechanics;
|
|
tU32 gLast_cunning_stunt;
|
|
tU32 gWild_start;
|
|
tU32 gQuite_wild_start;
|
|
tU32 gQuite_wild_end;
|
|
tU32 gOn_me_wheels_start;
|
|
int gWoz_upside_down_at_all;
|
|
tS3_sound_tag gSkid_tag[2];
|
|
tCar_spec* gLast_car_to_skid[2];
|
|
int gEliminate_faces;
|
|
br_vector3 gZero_v__car; // suffix added to avoid duplicate symbol
|
|
tU32 gSwitch_time;
|
|
tSave_camera gSave_camera[2];
|
|
tU32 gLast_mechanics_time;
|
|
int gOpponent_viewing_mode;
|
|
int gNet_player_to_view_index;
|
|
int gDouble_pling_water;
|
|
int gStop_opponents_moving;
|
|
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;
|
|
float gCar_simplification_factor[2][5] = {
|
|
{ 10.0, 3.0, 1.5, 0.75, 0.0 },
|
|
{ 10.0, 5.0, 2.5, 1.5, 0.0 }
|
|
};
|
|
int gCar_simplification_level;
|
|
int gNum_active_non_cars;
|
|
int gCamera_has_collided;
|
|
tFace_ref gFace_list__car[150]; // suffix added to avoid duplicate symbol
|
|
tNon_car_spec* gActive_non_car_list[50];
|
|
int gOver_shoot;
|
|
br_scalar gMin_world_y;
|
|
br_scalar gAccel;
|
|
br_vector3 gAverage_grid_position;
|
|
br_actor* gPed_actor;
|
|
int gCollision_count;
|
|
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_vector3 gNew_ground_normal__car; // suffix added to avoid duplicate symbol
|
|
char gNon_car_spec_list[100];
|
|
tU32 gMechanics_time_sync;
|
|
int gNum_cars_and_non_cars;
|
|
|
|
// IDA: void __usercall DamageUnit(tCar_spec *pCar@<EAX>, int pUnit_type@<EDX>, int pDamage_amount@<EBX>)
|
|
void DamageUnit(tCar_spec* pCar, int pUnit_type, int pDamage_amount) {
|
|
tDamage_unit* the_damage;
|
|
LOG_TRACE("(%p, %d, %d)", pCar, pUnit_type, pDamage_amount);
|
|
|
|
if (pDamage_amount > 0) {
|
|
the_damage = &pCar->damage_units[pUnit_type];
|
|
the_damage->damage_level += pDamage_amount;
|
|
if (the_damage->damage_level >= 100) {
|
|
the_damage->damage_level = 99;
|
|
}
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall DamageUnitWithSmoke(tCar_spec *pCar@<EAX>, int pUnit_type@<EDX>, int pDamage_amount@<EBX>)
|
|
void DamageUnitWithSmoke(tCar_spec* pCar, int pUnit_type, int pDamage_amount) {
|
|
LOG_TRACE("(%p, %d, %d)", pCar, pUnit_type, pDamage_amount);
|
|
|
|
DamageUnit(pCar, pUnit_type, pDamage_amount);
|
|
SortOutSmoke(pCar);
|
|
}
|
|
|
|
// IDA: void __usercall DamageEngine(int pDamage_amount@<EAX>)
|
|
void DamageEngine(int pDamage_amount) {
|
|
LOG_TRACE("(%d)", pDamage_amount);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall DamageTrans(int pDamage_amount@<EAX>)
|
|
void DamageTrans(int pDamage_amount) {
|
|
LOG_TRACE("(%d)", pDamage_amount);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall DamageSteering(int pDamage_amount@<EAX>)
|
|
void DamageSteering(int pDamage_amount) {
|
|
LOG_TRACE("(%d)", pDamage_amount);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall DamageLFWheel(int pDamage_amount@<EAX>)
|
|
void DamageLFWheel(int pDamage_amount) {
|
|
LOG_TRACE("(%d)", pDamage_amount);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall DamageLFBrake(int pDamage_amount@<EAX>)
|
|
void DamageLFBrake(int pDamage_amount) {
|
|
LOG_TRACE("(%d)", pDamage_amount);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall DamageLRBrake(int pDamage_amount@<EAX>)
|
|
void DamageLRBrake(int pDamage_amount) {
|
|
LOG_TRACE("(%d)", pDamage_amount);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall DamageLRWheel(int pDamage_amount@<EAX>)
|
|
void DamageLRWheel(int pDamage_amount) {
|
|
LOG_TRACE("(%d)", pDamage_amount);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall DamageRFWheel(int pDamage_amount@<EAX>)
|
|
void DamageRFWheel(int pDamage_amount) {
|
|
LOG_TRACE("(%d)", pDamage_amount);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall DamageRFBrake(int pDamage_amount@<EAX>)
|
|
void DamageRFBrake(int pDamage_amount) {
|
|
LOG_TRACE("(%d)", pDamage_amount);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall DamageRRBrake(int pDamage_amount@<EAX>)
|
|
void DamageRRBrake(int pDamage_amount) {
|
|
LOG_TRACE("(%d)", pDamage_amount);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall DamageRRWheel(int pDamage_amount@<EAX>)
|
|
void DamageRRWheel(int pDamage_amount) {
|
|
LOG_TRACE("(%d)", pDamage_amount);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall CalculatePlaneNormal(br_vector3 *pP1@<EAX>, br_vector3 *pP2@<EDX>, br_vector3 *pP3@<EBX>, br_vector3 *pNormal@<ECX>)
|
|
void CalculatePlaneNormal(br_vector3* pP1, br_vector3* pP2, br_vector3* pP3, br_vector3* pNormal) {
|
|
br_vector3 p0;
|
|
br_vector3 p1;
|
|
br_vector3 cross_product;
|
|
br_vector3 temp_vector;
|
|
LOG_TRACE("(%p, %p, %p, %p)", pP1, pP2, pP3, pNormal);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall CalculateGroundNormal(br_model *pThe_model@<EAX>, int pFace_index@<EDX>)
|
|
void CalculateGroundNormal(br_model* pThe_model, int pFace_index) {
|
|
LOG_TRACE("(%p, %d)", pThe_model, pFace_index);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __cdecl ChangeYCoordinate(br_scalar pNew_y, tU32 pTime_taken, br_model *pThe_model, int pFace_index)
|
|
void ChangeYCoordinate(br_scalar pNew_y, tU32 pTime_taken, br_model* pThe_model, int pFace_index) {
|
|
br_scalar y_change;
|
|
br_transform new_transform;
|
|
br_vector3 side_window;
|
|
LOG_TRACE("(%f, %d, %p, %d)", pNew_y, pTime_taken, pThe_model, pFace_index);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall SwitchCarActor(tCar_spec *pCar_spec@<EAX>, int pModel_index@<EDX>)
|
|
void SwitchCarActor(tCar_spec* pCar_spec, int pModel_index) {
|
|
int i;
|
|
LOG_TRACE("(%p, %d)", pCar_spec, pModel_index);
|
|
|
|
for (i = 0; i < pCar_spec->car_actor_count; i++) {
|
|
if (i == pModel_index) {
|
|
pCar_spec->car_model_actors[i].actor->render_style = BR_RSTYLE_FACES;
|
|
} else {
|
|
pCar_spec->car_model_actors[i].actor->render_style = BR_RSTYLE_NONE;
|
|
}
|
|
}
|
|
pCar_spec->current_car_actor = pModel_index;
|
|
}
|
|
|
|
// IDA: void __usercall InitialiseCar2(tCar_spec *pCar@<EAX>, int pClear_disabled_flag@<EDX>)
|
|
void InitialiseCar2(tCar_spec* pCar, int pClear_disabled_flag) {
|
|
int index;
|
|
int j;
|
|
int cat;
|
|
int car_count;
|
|
br_actor* car_actor;
|
|
br_angle initial_yaw;
|
|
br_scalar nearest_y_above;
|
|
br_scalar nearest_y_below;
|
|
br_scalar speed;
|
|
int below_face_index;
|
|
int above_face_index;
|
|
br_model* below_model;
|
|
br_model* above_model;
|
|
br_vector3 grid_offset;
|
|
br_matrix34 initial_yaw_matrix;
|
|
br_matrix34 safe_position;
|
|
LOG_TRACE("(%p, %d)", pCar, pClear_disabled_flag);
|
|
|
|
PossibleService();
|
|
if (pCar->disabled && pClear_disabled_flag) {
|
|
EnableCar(pCar);
|
|
}
|
|
car_actor = pCar->car_master_actor;
|
|
InitCarSkidStuff(pCar);
|
|
if (pCar->current_car_actor >= 0) {
|
|
pCar->car_model_actors[pCar->current_car_actor].actor->render_style = BR_RSTYLE_NONE;
|
|
}
|
|
SwitchCarActor(pCar, pCar->current_car_actor);
|
|
if (strcmp(pCar->name, "STELLA.TXT") == 0) {
|
|
pCar->proxy_ray_distance = 6.0f;
|
|
} else {
|
|
pCar->proxy_ray_distance = 0.0f;
|
|
}
|
|
pCar->last_special_volume = NULL;
|
|
pCar->auto_special_volume = NULL;
|
|
pCar->num_smoke_columns = 0;
|
|
pCar->who_last_hit_me = NULL;
|
|
pCar->screen_material_source = NULL;
|
|
if (pCar->screen_material) {
|
|
pCar->screen_material->colour_map = NULL;
|
|
pCar->screen_material->index_shade = gRender_shade_table;
|
|
BrMaterialUpdate(pCar->screen_material, BR_MATU_ALL);
|
|
}
|
|
if (pCar->driver == eDriver_local_human) {
|
|
ResetRecoveryVouchers();
|
|
}
|
|
BrVector3SetFloat(&pCar->v, 0.0f, 0.0f, 0.0f);
|
|
BrVector3SetFloat(&pCar->omega, 0.0f, 0.0f, 0.0f);
|
|
pCar->curvature = 0.0f;
|
|
BrMatrix34Copy(&safe_position, &car_actor->t.t.mat);
|
|
if (safe_position.m[3][0] > 500.0f) {
|
|
safe_position.m[3][0] -= 1000.0f;
|
|
safe_position.m[3][1] -= 1000.0f;
|
|
safe_position.m[3][2] -= 1000.0f;
|
|
}
|
|
BrMatrix34Copy(&pCar->old_frame_mat, &safe_position);
|
|
BrMatrix34Copy(&pCar->oldmat, &safe_position);
|
|
pCar->oldmat.m[3][0] *= WORLD_SCALE;
|
|
pCar->oldmat.m[3][1] *= WORLD_SCALE;
|
|
pCar->oldmat.m[3][2] *= WORLD_SCALE;
|
|
BrMatrix34ApplyP(&pCar->pos, &pCar->cmpos, &pCar->oldmat);
|
|
pCar->pos.v[0] /= WORLD_SCALE;
|
|
pCar->pos.v[1] /= WORLD_SCALE;
|
|
pCar->pos.v[2] /= WORLD_SCALE;
|
|
for (j = 0; j < COUNT_OF(pCar->oldd); j++) {
|
|
pCar->oldd[j] = pCar->ride_height;
|
|
}
|
|
pCar->gear = 0;
|
|
pCar->revs = 0.0;
|
|
pCar->traction_control = 1;
|
|
pCar->direction.v[0] = -car_actor->t.t.mat.m[2][0];
|
|
pCar->direction.v[1] = -car_actor->t.t.mat.m[2][1];
|
|
pCar->direction.v[2] = -car_actor->t.t.mat.m[2][2];
|
|
for (j = 0; j < COUNT_OF(pCar->last_safe_positions); j++) {
|
|
BrMatrix34Copy(&pCar->last_safe_positions[j], &safe_position);
|
|
}
|
|
pCar->message.type = 0;
|
|
pCar->message.time = 0;
|
|
pCar->dt = -1.0;
|
|
pCar->last_car_car_collision = 1;
|
|
pCar->time_to_recover = 0;
|
|
pCar->repair_time = 0;
|
|
|
|
switch (pCar->driver) {
|
|
|
|
case eDriver_oppo:
|
|
index = 0;
|
|
for (j = 0; gCurrent_race.number_of_racers > j; ++j) {
|
|
if (gCurrent_race.opponent_list[j].car_spec->driver == eDriver_oppo) {
|
|
if (gCurrent_race.opponent_list[j].car_spec == pCar) {
|
|
pCar->car_ID = index + 512;
|
|
}
|
|
index++;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eDriver_net_human:
|
|
index = 0;
|
|
for (j = 0; gCurrent_race.number_of_racers > j; ++j) {
|
|
if (gCurrent_race.opponent_list[j].car_spec
|
|
&& gCurrent_race.opponent_list[j].car_spec->driver == eDriver_net_human) {
|
|
if (gCurrent_race.opponent_list[j].car_spec == pCar) {
|
|
pCar->car_ID = index + 256;
|
|
}
|
|
index++;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case eDriver_local_human:
|
|
pCar->car_ID = 0;
|
|
break;
|
|
|
|
default:
|
|
LOG_WARN("Case %d not handled", pCar->driver);
|
|
break;
|
|
}
|
|
PossibleService();
|
|
pCar->box_face_ref = gFace_num__car - 2;
|
|
pCar->doing_nothing_flag = 0;
|
|
pCar->end_steering_damage_effect = 0;
|
|
pCar->end_trans_damage_effect = 0;
|
|
pCar->wheel_dam_offset[0] = 0.0;
|
|
pCar->wheel_dam_offset[1] = 0.0;
|
|
pCar->wheel_dam_offset[2] = 0.0;
|
|
pCar->wheel_dam_offset[3] = 0.0;
|
|
pCar->shadow_intersection_flags = 0;
|
|
pCar->underwater_ability = 0;
|
|
pCar->invulnerable = 0;
|
|
pCar->wall_climber_mode = 0;
|
|
pCar->grip_multiplier = 1.0;
|
|
pCar->damage_multiplier = 1.0;
|
|
pCar->collision_mass_multiplier = 1.0;
|
|
pCar->engine_power_multiplier = 1.0;
|
|
pCar->bounce_rate = 0.0;
|
|
pCar->bounce_amount = 0.0;
|
|
pCar->knackered = 0;
|
|
TotallyRepairACar(pCar);
|
|
SetCarSuspGiveAndHeight(pCar, 1.0, 1.0, 1.0, 0.0, 0.0);
|
|
for (j = 0; j < 64; ++j) {
|
|
pCar->powerups[j] = 0;
|
|
}
|
|
if (gNet_mode) {
|
|
for (j = 0; j < 3; ++j) {
|
|
pCar->power_up_levels[j] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall InitialiseCar(tCar_spec *pCar@<EAX>)
|
|
void InitialiseCar(tCar_spec* pCar) {
|
|
LOG_TRACE("(%p)", pCar);
|
|
|
|
InitialiseCar2(pCar, 1);
|
|
}
|
|
|
|
// IDA: void __usercall InitialiseCarsEtc(tRace_info *pThe_race@<EAX>)
|
|
void InitialiseCarsEtc(tRace_info* pThe_race) {
|
|
int i;
|
|
int cat;
|
|
int car_count;
|
|
tCar_spec* car;
|
|
br_bounds bnds;
|
|
LOG_TRACE("(%p)", pThe_race);
|
|
|
|
gProgram_state.initial_position = pThe_race->initial_position;
|
|
gProgram_state.initial_yaw = pThe_race->initial_yaw;
|
|
BrActorToBounds(&bnds, gProgram_state.track_spec.the_actor);
|
|
gMin_world_y = bnds.min.v[1];
|
|
gNum_active_non_cars = 0;
|
|
for (cat = eVehicle_self; cat <= eVehicle_not_really; ++cat) {
|
|
if (cat) {
|
|
car_count = GetCarCount(cat);
|
|
} else {
|
|
car_count = 1;
|
|
}
|
|
for (i = 0; car_count > i; i++) {
|
|
PossibleService();
|
|
if (cat) {
|
|
car = GetCarSpec(cat, i);
|
|
} else {
|
|
car = &gProgram_state.current_car;
|
|
}
|
|
if (cat != eVehicle_not_really) {
|
|
InitialiseCar(car);
|
|
}
|
|
}
|
|
}
|
|
gCamera_yaw = 0;
|
|
InitialiseExternalCamera();
|
|
gLast_mechanics_time = 0;
|
|
}
|
|
|
|
// IDA: void __usercall GetAverageGridPosition(tRace_info *pThe_race@<EAX>)
|
|
void GetAverageGridPosition(tRace_info* pThe_race) {
|
|
int i;
|
|
br_scalar total_cars;
|
|
tCar_spec* car;
|
|
LOG_TRACE("(%p)", pThe_race);
|
|
|
|
total_cars = 0.0;
|
|
BrVector3SetFloat(&gAverage_grid_position, 0.0, 0.0, 0.0);
|
|
for (i = 0; pThe_race->number_of_racers > i; i++) {
|
|
car = pThe_race->opponent_list[i].car_spec;
|
|
gAverage_grid_position.v[0] = car->pos.v[0] + gAverage_grid_position.v[0];
|
|
gAverage_grid_position.v[1] = car->pos.v[1] + gAverage_grid_position.v[1];
|
|
gAverage_grid_position.v[2] = car->pos.v[2] + gAverage_grid_position.v[2];
|
|
total_cars = total_cars + 1.0;
|
|
}
|
|
gAverage_grid_position.v[0] = gAverage_grid_position.v[0] / total_cars;
|
|
gAverage_grid_position.v[1] = gAverage_grid_position.v[1] / total_cars;
|
|
gAverage_grid_position.v[2] = gAverage_grid_position.v[2] / total_cars;
|
|
}
|
|
|
|
// IDA: void __usercall SetInitialPosition(tRace_info *pThe_race@<EAX>, int pCar_index@<EDX>, int pGrid_index@<EBX>)
|
|
void SetInitialPosition(tRace_info* pThe_race, int pCar_index, int pGrid_index) {
|
|
int place_on_grid;
|
|
int i;
|
|
int start_i;
|
|
int j;
|
|
br_actor* car_actor;
|
|
br_angle initial_yaw = 0;
|
|
br_scalar nearest_y_above;
|
|
br_scalar nearest_y_below;
|
|
br_scalar speed;
|
|
int below_face_index;
|
|
int above_face_index;
|
|
br_model* below_model;
|
|
br_model* above_model;
|
|
tCar_spec* car;
|
|
br_vector3 grid_offset;
|
|
br_vector3 dist;
|
|
br_vector3 real_pos;
|
|
br_matrix34 initial_yaw_matrix;
|
|
br_bounds bnds;
|
|
LOG_TRACE("(%p, %d, %d)", pThe_race, pCar_index, pGrid_index);
|
|
|
|
car_actor = pThe_race->opponent_list[pCar_index].car_spec->car_master_actor;
|
|
car = pThe_race->opponent_list[pCar_index].car_spec;
|
|
BrMatrix34Identity(&car_actor->t.t.mat);
|
|
place_on_grid = 1;
|
|
if (gNet_mode && !gCurrent_net_game->options.grid_start && pThe_race->number_of_net_start_points) {
|
|
TELL_ME_IF_WE_PASS_THIS_WAY();
|
|
}
|
|
if (place_on_grid) {
|
|
initial_yaw = (pThe_race->initial_yaw * 182.0444444444445);
|
|
BrMatrix34RotateY(&initial_yaw_matrix, initial_yaw);
|
|
grid_offset.v[0] = 0.0 - pGrid_index % 2;
|
|
grid_offset.v[1] = 0.0;
|
|
grid_offset.v[2] = (double)(pGrid_index / 2) * 2.0 + (double)(pGrid_index % 2) * 0.40000001;
|
|
LOG_DEBUG("grid offset: %f, %f, %f", grid_offset.v[0], grid_offset.v[1], grid_offset.v[2]);
|
|
BrMatrix34ApplyV(&car_actor->t.t.translate.t, &grid_offset, &initial_yaw_matrix);
|
|
BrVector3Accumulate(&car_actor->t.t.translate.t, &pThe_race->initial_position);
|
|
}
|
|
LOG_DEBUG("grid pos: %d, pos: x=%f, z=%f", pGrid_index, car_actor->t.t.translate.t.v[0], car_actor->t.t.translate.t.v[2]);
|
|
FindBestY(
|
|
&car_actor->t.t.translate.t,
|
|
gTrack_actor,
|
|
10.0,
|
|
&nearest_y_above,
|
|
&nearest_y_below,
|
|
&above_model,
|
|
&below_model,
|
|
&above_face_index,
|
|
&below_face_index);
|
|
if (nearest_y_above == 30000.0) {
|
|
if (nearest_y_below == -30000.0) {
|
|
car_actor->t.t.translate.t.v[1] = 0.0;
|
|
} else {
|
|
car_actor->t.t.translate.t.v[1] = nearest_y_below;
|
|
}
|
|
} else {
|
|
car_actor->t.t.translate.t.v[1] = nearest_y_above;
|
|
}
|
|
BrMatrix34PreRotateY(&car_actor->t.t.mat, initial_yaw);
|
|
if (gNet_mode) {
|
|
BrMatrix34Copy(
|
|
&gNet_players[pThe_race->opponent_list[pCar_index].net_player_index].initial_position,
|
|
&car->car_master_actor->t.t.mat);
|
|
}
|
|
if (gNet_mode && car->disabled && car_actor->t.t.translate.t.v[0] < 500.0) {
|
|
DisableCar(car);
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall SetInitialPositions(tRace_info *pThe_race@<EAX>)
|
|
void SetInitialPositions(tRace_info* pThe_race) {
|
|
int i;
|
|
LOG_TRACE("(%p)", pThe_race);
|
|
|
|
for (i = 0; i < pThe_race->number_of_racers; i++) {
|
|
SetInitialPosition(pThe_race, i, i);
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall InitialiseNonCar(tNon_car_spec *non_car@<EAX>)
|
|
void InitialiseNonCar(tNon_car_spec* non_car) {
|
|
tCollision_info* c;
|
|
LOG_TRACE("(%p)", non_car);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall GetFacesInBox(tCollision_info *c@<EAX>)
|
|
void GetFacesInBox(tCollision_info* c) {
|
|
tBounds bnds;
|
|
br_bounds new_in_old;
|
|
br_bounds predicted_bounds;
|
|
br_matrix34 mat;
|
|
br_matrix34 mat2;
|
|
br_matrix34 mat3;
|
|
br_matrix34 mat4;
|
|
br_matrix34 mat5;
|
|
br_matrix34 mat6;
|
|
br_scalar old_d;
|
|
int i;
|
|
br_bounds current_bounds;
|
|
LOG_TRACE("(%p)", c);
|
|
|
|
BrMatrix34Copy(&mat, &c->car_master_actor->t.t.mat);
|
|
BrMatrix34Copy(&mat2, &c->oldmat);
|
|
mat.m[3][0] = mat.m[3][0] / 6.9;
|
|
mat.m[3][1] = mat.m[3][1] / 6.9;
|
|
mat.m[3][2] = mat.m[3][2] / 6.9;
|
|
mat2.m[3][0] = mat2.m[3][0] / 6.9;
|
|
mat2.m[3][1] = mat2.m[3][1] / 6.9;
|
|
mat2.m[3][2] = mat2.m[3][2] / 6.9;
|
|
BrMatrix34LPInverse(&mat3, &mat);
|
|
BrMatrix34Mul(&mat4, &mat2, &mat3);
|
|
GetNewBoundingBox(&bnds.original_bounds, c->bounds, &mat4);
|
|
for (i = 0; i < 3; ++i) {
|
|
if (bnds.original_bounds.min.v[i] > c->bounds[0].min.v[i]) {
|
|
bnds.original_bounds.min.v[i] = c->bounds[0].min.v[i];
|
|
}
|
|
if (bnds.original_bounds.max.v[i] < c->bounds[0].max.v[i]) {
|
|
bnds.original_bounds.max.v[i] = c->bounds[0].max.v[i];
|
|
}
|
|
bnds.original_bounds.min.v[i] = bnds.original_bounds.min.v[i] - 0.0020000001;
|
|
bnds.original_bounds.max.v[i] = bnds.original_bounds.max.v[i] + 0.0020000001;
|
|
}
|
|
GetNewBoundingBox(&c->bounds_world_space, &bnds.original_bounds, &mat);
|
|
c->bounds_ws_type = eBounds_ws;
|
|
if ((c->box_face_ref != gFace_num__car && (c->box_face_ref != gFace_num__car - 1 || c->box_face_start <= gFace_count))
|
|
|| (BrMatrix34Mul(&mat5, &mat, &c->last_box_inv_mat),
|
|
GetNewBoundingBox(&new_in_old, &bnds.original_bounds, &mat5),
|
|
c->last_box.max.v[0] <= new_in_old.max.v[0])
|
|
|| c->last_box.max.v[1] <= new_in_old.max.v[1]
|
|
|| c->last_box.max.v[2] <= new_in_old.max.v[2]
|
|
|| c->last_box.min.v[0] >= new_in_old.min.v[0]
|
|
|| c->last_box.min.v[1] >= new_in_old.min.v[1]
|
|
|| c->last_box.min.v[2] >= new_in_old.min.v[2]) {
|
|
BrMatrix34Mul(&mat5, &mat4, &mat4);
|
|
BrMatrix34Mul(&mat6, &mat5, &mat4);
|
|
BrMatrix34LPInverse(&mat5, &mat6);
|
|
GetNewBoundingBox(&predicted_bounds, c->bounds, &mat5);
|
|
for (i = 0; i < 3; ++i) {
|
|
if (bnds.original_bounds.min.v[i] > predicted_bounds.min.v[i]) {
|
|
bnds.original_bounds.min.v[i] = predicted_bounds.min.v[i];
|
|
}
|
|
if (bnds.original_bounds.max.v[i] < predicted_bounds.max.v[i]) {
|
|
bnds.original_bounds.max.v[i] = predicted_bounds.max.v[i];
|
|
}
|
|
bnds.original_bounds.min.v[i] = bnds.original_bounds.min.v[i] - 0.02;
|
|
bnds.original_bounds.max.v[i] = bnds.original_bounds.max.v[i] + 0.02;
|
|
}
|
|
c->last_box = bnds.original_bounds;
|
|
BrMatrix34Copy(&c->last_box_inv_mat, &mat3);
|
|
bnds.mat = &mat;
|
|
c->box_face_start = gFace_count;
|
|
gPling_face = NULL;
|
|
gFace_count += FindFacesInBox(&bnds, &gFace_list__car[gFace_count], 150 - gFace_count);
|
|
if (gFace_count >= 150) {
|
|
c->box_face_start = 0;
|
|
gFace_count = FindFacesInBox(&bnds, gFace_list__car, 150);
|
|
++gFace_num__car;
|
|
}
|
|
old_d = c->water_d;
|
|
if (c->driver == eDriver_local_human
|
|
&& c->water_d != 10000.0
|
|
&& gDouble_pling_water
|
|
&& c->bounds_world_space.max.v[2] * c->water_normal.v[2] + c->bounds_world_space.max.v[1] * c->water_normal.v[1] + c->water_normal.v[0] * c->bounds_world_space.max.v[0] - c->water_d <= 0.0) {
|
|
gInTheSea = 1;
|
|
FreezeCamera();
|
|
}
|
|
if (gPling_face && fabs(gPling_face->normal.v[1]) > 0.89999998) {
|
|
c->water_normal = gPling_face->normal;
|
|
if (c->water_normal.v[1] < 0.0) {
|
|
BrVector3Negate(&c->water_normal, &c->water_normal);
|
|
}
|
|
c->water_d = gPling_face->v[0].v[1] * c->water_normal.v[1] + gPling_face->v[0].v[2] * c->water_normal.v[2] + gPling_face->v[0].v[0] * c->water_normal.v[0];
|
|
if (c->driver == eDriver_local_human) {
|
|
if (gPling_face->material->identifier[1] == '!') {
|
|
if (BrVector3Dot(&c->bounds_world_space.min, &c->water_normal) - c->water_d < 0.0) {
|
|
GetNewBoundingBox(¤t_bounds, &c->bounds[1], &c->car_master_actor->t.t.mat);
|
|
if (BrVector3Dot(¤t_bounds.min, &c->water_normal) / 6.9 - c->water_d < 0.0) {
|
|
gInTheSea = 1;
|
|
FreezeCamera();
|
|
}
|
|
}
|
|
gDouble_pling_water = 1;
|
|
} else {
|
|
gDouble_pling_water = 0;
|
|
}
|
|
}
|
|
} else {
|
|
c->water_d = 10000.0;
|
|
if (c->driver == eDriver_local_human) {
|
|
if (gInTheSea == 1) {
|
|
gInTheSea = 2;
|
|
} else {
|
|
gInTheSea = 0;
|
|
}
|
|
}
|
|
}
|
|
if (c->water_d != old_d) {
|
|
StartPipingSession(ePipe_chunk_splash);
|
|
AddSplashToPipingSession(c);
|
|
EndPipingSession();
|
|
}
|
|
c->box_face_end = gFace_count;
|
|
c->box_face_ref = gFace_num__car;
|
|
}
|
|
}
|
|
|
|
// IDA: int __cdecl IsCarInTheSea()
|
|
int IsCarInTheSea() {
|
|
LOG_TRACE("()");
|
|
|
|
return gInTheSea;
|
|
}
|
|
|
|
// IDA: void __usercall RememberSafePosition(tCar_spec *car@<EAX>, tU32 pTime@<EDX>)
|
|
void RememberSafePosition(tCar_spec* car, tU32 pTime) {
|
|
static tU32 time_count;
|
|
int j;
|
|
br_vector3 r;
|
|
br_scalar ts;
|
|
LOG_TRACE("(%p, %d)", car, pTime);
|
|
|
|
if (car->disabled) {
|
|
return;
|
|
}
|
|
time_count += pTime;
|
|
if (time_count < 5000) {
|
|
return;
|
|
}
|
|
time_count = 4000;
|
|
for (j = 0; j < 4; j++) {
|
|
if (car->susp_height[j >> 1] <= car->oldd[j]) {
|
|
return;
|
|
}
|
|
}
|
|
if ((!car->last_special_volume || car->last_special_volume->gravity_multiplier == 1.0)
|
|
&& gCurrent_race.material_modifiers[car->material_index[0]].tyre_road_friction >= 0.1
|
|
&& gCurrent_race.material_modifiers[car->material_index[1]].tyre_road_friction >= 0.1
|
|
&& gCurrent_race.material_modifiers[car->material_index[2]].tyre_road_friction >= 0.1
|
|
&& gCurrent_race.material_modifiers[car->material_index[3]].tyre_road_friction >= 0.1
|
|
&& car->car_master_actor->t.t.mat.m[1][1] >= 0.80000001) {
|
|
|
|
for (j = 0; j < 5; j++) {
|
|
r.v[0] = car->car_master_actor->t.t.mat.m[3][0] - car->last_safe_positions[j].m[3][0];
|
|
r.v[1] = car->car_master_actor->t.t.mat.m[3][1] - car->last_safe_positions[j].m[3][1];
|
|
r.v[2] = car->car_master_actor->t.t.mat.m[3][2] - car->last_safe_positions[j].m[3][2];
|
|
|
|
if (BrVector3LengthSquared(&r) < 8.4015961) {
|
|
return;
|
|
}
|
|
}
|
|
for (j = 3; j > 0; j--) {
|
|
BrMatrix34Copy(&car->last_safe_positions[j], &car->last_safe_positions[j - 1]);
|
|
}
|
|
BrMatrix34Copy(&car->last_safe_positions[0], &car->car_master_actor->t.t.mat);
|
|
time_count = 0;
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall ControlOurCar(tU32 pTime_difference@<EAX>)
|
|
void ControlOurCar(tU32 pTime_difference) {
|
|
br_scalar ts;
|
|
br_vector3 minus_k;
|
|
tCar_spec* car;
|
|
static int steering_locked;
|
|
int i;
|
|
tU32 time;
|
|
LOG_TRACE("(%d)", pTime_difference);
|
|
|
|
car = &gProgram_state.current_car;
|
|
if (gCar_flying) {
|
|
if (gNet_mode) {
|
|
gCar_flying = 0;
|
|
} else {
|
|
car->car_master_actor->t.t.mat.m[3][0] = car->car_master_actor->t.t.mat.m[3][0] * WORLD_SCALE;
|
|
car->car_master_actor->t.t.mat.m[3][1] = car->car_master_actor->t.t.mat.m[3][1] * WORLD_SCALE;
|
|
car->car_master_actor->t.t.mat.m[3][2] = car->car_master_actor->t.t.mat.m[3][2] * WORLD_SCALE;
|
|
ts = (double)pTime_difference / 1000.0;
|
|
FlyCar(car, ts);
|
|
car->car_master_actor->t.t.mat.m[3][0] = car->car_master_actor->t.t.mat.m[3][0] / WORLD_SCALE;
|
|
car->car_master_actor->t.t.mat.m[3][1] = car->car_master_actor->t.t.mat.m[3][1] / WORLD_SCALE;
|
|
car->car_master_actor->t.t.mat.m[3][2] = car->car_master_actor->t.t.mat.m[3][2] / WORLD_SCALE;
|
|
}
|
|
return;
|
|
}
|
|
time = GetTotalTime();
|
|
if (car->damage_units[eDamage_steering].damage_level > 40) {
|
|
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;
|
|
car->keys.right = car->false_key_right;
|
|
} else {
|
|
car->end_steering_damage_effect = 0;
|
|
}
|
|
} else {
|
|
ts = pTime_difference * (car->damage_units[eDamage_steering].damage_level - 40) * 0.0045;
|
|
if (PercentageChance(ts) && fabs(car->velocity_car_space.v[2]) > 0.0001) {
|
|
if (car->keys.left || car->keys.right) {
|
|
car->false_key_left = !car->keys.left;
|
|
car->false_key_right = !car->keys.right;
|
|
} else if (PercentageChance(50)) {
|
|
car->false_key_left = 1;
|
|
} else {
|
|
car->false_key_right = 1;
|
|
}
|
|
ts = 5 * (5 * car->damage_units[eDamage_steering].damage_level - 200);
|
|
car->end_steering_damage_effect = FRandomBetween(0.0, ts) + time;
|
|
}
|
|
}
|
|
}
|
|
if (car->damage_units[eDamage_transmission].damage_level > 40) {
|
|
if (car->end_trans_damage_effect) {
|
|
if (car->end_trans_damage_effect > time || car->damage_units[eDamage_transmission].damage_level == 99) {
|
|
car->gear = 0;
|
|
car->just_changed_gear = 1;
|
|
} else {
|
|
car->end_trans_damage_effect = 0;
|
|
}
|
|
} else {
|
|
ts = pTime_difference * (car->damage_units[eDamage_transmission].damage_level - 40);
|
|
if (PercentageChance(ts) * 0.006 != 0) {
|
|
ts = 10 * (5 * car->damage_units[eDamage_transmission].damage_level - 200);
|
|
car->end_trans_damage_effect = FRandomBetween(0.0, ts) + time;
|
|
}
|
|
}
|
|
}
|
|
ts = (double)pTime_difference / 1000.0;
|
|
ControlCar[gControl__car](car, ts);
|
|
RememberSafePosition(car, pTime_difference);
|
|
if (gCamera_reset) {
|
|
BrVector3SetFloat(&minus_k, 0.0, 0.0, -1.0);
|
|
gCamera_sign = 0;
|
|
BrMatrix34ApplyV(&car->direction, &minus_k, &car->car_master_actor->t.t.mat);
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall CalcEngineForce(tCar_spec *c@<EAX>, br_scalar dt)
|
|
void CalcEngineForce(tCar_spec* c, br_scalar dt) {
|
|
br_scalar torque;
|
|
br_scalar ts;
|
|
br_scalar ts2;
|
|
br_scalar brake_temp;
|
|
int sign;
|
|
tS32 temp_for_swap;
|
|
LOG_TRACE("(%p, %f)", c, dt);
|
|
|
|
c->acc_force = 0.0;
|
|
if (c->revs == 0.0) {
|
|
c->gear = 0;
|
|
}
|
|
sign = c->gear < 0 || (!c->gear && c->velocity_car_space.v[2] > 0.5);
|
|
if (c->keys.backwards != sign) {
|
|
c->keys.backwards = !c->keys.backwards;
|
|
temp_for_swap = c->keys.acc;
|
|
c->keys.acc = c->keys.dec;
|
|
c->keys.dec = temp_for_swap;
|
|
|
|
temp_for_swap = c->joystick.acc;
|
|
c->joystick.acc = c->joystick.dec;
|
|
c->joystick.dec = temp_for_swap;
|
|
}
|
|
if (!c->gear && !c->keys.acc && c->joystick.acc <= 0 && (c->keys.dec || c->joystick.dec > 0) && !c->keys.backwards && fabs(c->velocity_car_space.v[2]) < 1.0) {
|
|
c->keys.backwards = 1;
|
|
c->keys.acc = c->keys.dec;
|
|
c->keys.dec = 0;
|
|
temp_for_swap = c->joystick.acc;
|
|
c->joystick.acc = c->joystick.dec;
|
|
c->joystick.dec = temp_for_swap;
|
|
}
|
|
c->torque = -(c->revs * c->revs / 100000000.0) - 0.2;
|
|
if (c->keys.acc || c->joystick.acc >= 0) {
|
|
if (fabs(c->curvature) > c->maxcurve / 2.0 && c->gear < 2 && c->gear && c->traction_control) {
|
|
ts = 0.69999999;
|
|
} else if (c->joystick.acc < 0) {
|
|
ts = 1.2;
|
|
} else {
|
|
ts = c->joystick.acc / 54613.0;
|
|
LOG_PANIC("ooo");
|
|
}
|
|
|
|
torque = c->engine_power_multiplier * ts * gEngine_powerup_factor[c->power_up_levels[1]];
|
|
if (c->damage_units[0].damage_level > 10) {
|
|
torque = (1.0 - (double)(c->damage_units[0].damage_level - 10) / 100.0) * torque;
|
|
}
|
|
c->torque = c->torque + torque;
|
|
} else {
|
|
c->traction_control = 1;
|
|
}
|
|
if (!c->keys.dec && (!c->keys.acc || c->gear) && c->joystick.dec <= 0 && (c->joystick.acc <= 0 || c->gear)) {
|
|
c->brake_force = 0.0;
|
|
} else {
|
|
if (c->joystick.dec > 0) {
|
|
c->brake_force = (double)(c->joystick.dec / 0x10000) * c->brake_increase + c->initial_brake;
|
|
}
|
|
if (c->brake_force == 0.0) {
|
|
c->brake_force = c->initial_brake;
|
|
} else {
|
|
c->brake_force = c->brake_increase * dt + c->brake_force;
|
|
if (c->initial_brake + c->brake_increase < c->brake_force) {
|
|
c->brake_force = c->initial_brake + c->brake_increase;
|
|
}
|
|
}
|
|
}
|
|
if (c->gear) {
|
|
c->acc_force = c->force_torque_ratio * c->torque / (double)c->gear;
|
|
if (c->brake_force == 0.0) {
|
|
if (c->revs - 1.0 > c->target_revs || c->revs + 1.0 < c->target_revs) {
|
|
ts2 = c->torque * dt / 0.0002 + c->revs - c->target_revs;
|
|
c->acc_force = ts2 / ((1.0 / (c->speed_revs_ratio * c->M) / (double)c->gear + 1.0 / (c->force_torque_ratio * 0.0002) * (double)c->gear) * dt) + c->acc_force;
|
|
}
|
|
} else {
|
|
c->revs = c->target_revs;
|
|
}
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall PrepareCars(tU32 pFrame_start_time@<EAX>)
|
|
void PrepareCars(tU32 pFrame_start_time) {
|
|
tCar_spec* car;
|
|
int i;
|
|
static tU32 last_frame_start;
|
|
LOG_TRACE("(%d)", pFrame_start_time);
|
|
|
|
last_frame_start = pFrame_start_time;
|
|
for (i = 0; i < gNum_cars_and_non_cars; i++) {
|
|
car = gActive_car_list[i];
|
|
car->car_master_actor->t.t.mat.m[3][0] = car->car_master_actor->t.t.mat.m[3][0] * WORLD_SCALE;
|
|
car->car_master_actor->t.t.mat.m[3][1] = car->car_master_actor->t.t.mat.m[3][1] * WORLD_SCALE;
|
|
car->car_master_actor->t.t.mat.m[3][2] = car->car_master_actor->t.t.mat.m[3][2] * WORLD_SCALE;
|
|
car->velocity_car_space.v[0] = car->velocity_car_space.v[0] * WORLD_SCALE * 1000.0f;
|
|
car->velocity_car_space.v[1] = car->velocity_car_space.v[1] * WORLD_SCALE * 1000.0f;
|
|
car->velocity_car_space.v[2] = car->velocity_car_space.v[2] * WORLD_SCALE * 1000.0f;
|
|
car->frame_collision_flag = gOver_shoot && car->collision_flag;
|
|
if (car->driver > eDriver_non_car) {
|
|
RecordLastDamage(car);
|
|
if (car->driver == eDriver_oppo && gStop_opponents_moving) {
|
|
car->acc_force = 0.0;
|
|
car->brake_force = 0.0;
|
|
car->keys.acc = 0;
|
|
car->keys.dec = 0;
|
|
car->joystick.acc = -1;
|
|
car->joystick.dec = -1;
|
|
}
|
|
if (!car->wheel_slip) {
|
|
StopSkid(car);
|
|
}
|
|
if (car->driver == eDriver_net_human && car->message.time < pFrame_start_time - 1000) {
|
|
car->keys.acc = 0;
|
|
car->keys.dec = 0;
|
|
car->joystick.acc = -1;
|
|
car->joystick.dec = -1;
|
|
car->keys.horn = 0;
|
|
}
|
|
SetSmokeLastDamageLevel(car);
|
|
}
|
|
BrMatrix34Copy(&car->car_master_actor->t.t.mat, &car->oldmat);
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall FinishCars(tU32 pLast_frame_time@<EAX>, tU32 pTime@<EDX>)
|
|
void FinishCars(tU32 pLast_frame_time, tU32 pTime) {
|
|
tCar_spec* car;
|
|
br_vector3 minus_k;
|
|
int i;
|
|
int wheel;
|
|
br_scalar scale;
|
|
LOG_TRACE("(%d, %d)", pLast_frame_time, pTime);
|
|
|
|
for (i = 0; i < gNum_cars_and_non_cars; i++) {
|
|
car = gActive_car_list[i];
|
|
if (fabs(car->omega.v[0]) > 10000.0
|
|
|| fabs(car->omega.v[1]) > 10000.0
|
|
|| fabs(car->omega.v[2]) > 10000.0) {
|
|
BrVector3SetFloat(&car->omega, 0.0, 0.0, 0.0);
|
|
BrVector3SetFloat(&car->v, 0.0, 0.0, 0.0);
|
|
}
|
|
BrVector3InvScale(&car->velocity_car_space, &car->velocity_car_space, WORLD_SCALE * 1000.0f);
|
|
car->car_master_actor->t.t.mat.m[3][0] = car->car_master_actor->t.t.mat.m[3][0] / WORLD_SCALE;
|
|
car->car_master_actor->t.t.mat.m[3][1] = car->car_master_actor->t.t.mat.m[3][1] / WORLD_SCALE;
|
|
car->car_master_actor->t.t.mat.m[3][2] = car->car_master_actor->t.t.mat.m[3][2] / WORLD_SCALE;
|
|
|
|
car->speed = BR_LENGTH2(car->v.v[0], car->v.v[2]) / (WORLD_SCALE * 1000.0f);
|
|
minus_k.v[0] = -car->car_master_actor->t.t.mat.m[2][0];
|
|
minus_k.v[1] = -car->car_master_actor->t.t.mat.m[2][1];
|
|
minus_k.v[2] = -car->car_master_actor->t.t.mat.m[2][2];
|
|
if (car->speed <= 0.000099999997) {
|
|
if (car->direction.v[1] * minus_k.v[1] + car->direction.v[2] * minus_k.v[2] + car->direction.v[0] * minus_k.v[0] < 0.0) {
|
|
BrVector3SetFloat(&minus_k, 0.0, 0.0, 1.0);
|
|
} else {
|
|
BrVector3SetFloat(&minus_k, 0.0, 0.0, -1.0);
|
|
}
|
|
BrMatrix34ApplyV(&car->direction, &minus_k, &car->car_master_actor->t.t.mat);
|
|
} else if (gLast_mechanics_time > pLast_frame_time && gCar_to_view == car) {
|
|
BrVector3Sub(&car->old_v, &car->old_v, &car->v);
|
|
BrVector3Scale(&car->old_v, &car->old_v, (gLast_mechanics_time - pLast_frame_time) / harness_game_config.physics_step_time);
|
|
BrVector3Accumulate(&car->old_v, &car->v);
|
|
BrVector3Normalise(&car->direction, &car->old_v);
|
|
} else {
|
|
BrVector3Normalise(&car->direction, &car->v);
|
|
}
|
|
if (car->driver > eDriver_non_car) {
|
|
car->speedo_speed = BrVector3Dot(&minus_k, &car->v) / (WORLD_SCALE * 1000.0f);
|
|
|
|
car->steering_angle = d180_OVER_PI * atan((car->wpos[0].v[2] - car->wpos[2].v[2]) * car->curvature);
|
|
|
|
car->lr_sus_position = (car->ride_height - car->oldd[0]) / WORLD_SCALE;
|
|
car->rr_sus_position = (car->ride_height - car->oldd[1]) / WORLD_SCALE;
|
|
car->lf_sus_position = (car->ride_height - car->oldd[2]) / WORLD_SCALE;
|
|
car->rf_sus_position = (car->ride_height - car->oldd[3]) / WORLD_SCALE;
|
|
for (wheel = 0; wheel < 4; wheel++) {
|
|
if (car->oldd[wheel] < car->susp_height[wheel >> 1] && gCurrent_race.material_modifiers[car->material_index[wheel]].smoke_type >= 2
|
|
&& !car->doing_nothing_flag)
|
|
GenerateContinuousSmoke(car, wheel, pTime);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall InterpolateCars(tU32 pLast_frame_time@<EAX>, tU32 pTime@<EDX>)
|
|
void InterpolateCars(tU32 pLast_frame_time, tU32 pTime) {
|
|
br_scalar dt;
|
|
tCar_spec* car;
|
|
int i;
|
|
LOG_TRACE("(%d, %d)", pLast_frame_time, pTime);
|
|
|
|
dt = ((int)(gLast_mechanics_time - pLast_frame_time)) / 1000.0;
|
|
if (dt > 0.04 || dt < 0)
|
|
dt = 0;
|
|
|
|
gOver_shoot = dt > 0.0;
|
|
|
|
for (i = 0; i < gNum_cars_and_non_cars; i++) {
|
|
car = gActive_car_list[i];
|
|
BrMatrix34Copy(&car->oldmat, &car->car_master_actor->t.t.mat);
|
|
SimpleRotate((tCollision_info*)car, -dt);
|
|
TranslateCar((tCollision_info*)car, -dt);
|
|
BrMatrix34ApplyP(&car->pos, &car->cmpos, &car->car_master_actor->t.t.mat);
|
|
BrVector3InvScale(&car->pos, &car->pos, WORLD_SCALE);
|
|
}
|
|
}
|
|
|
|
// IDA: void __cdecl ResetOldmat()
|
|
void ResetOldmat() {
|
|
tCar_spec* car;
|
|
int i;
|
|
br_matrix34 mat;
|
|
static int normalise_count = 0;
|
|
LOG_TRACE("()");
|
|
|
|
for (i = 0; i < gNum_cars_and_non_cars; i++) {
|
|
BrMatrix34Copy(&gActive_car_list[i]->oldmat, &gActive_car_list[i]->car_master_actor->t.t.mat);
|
|
}
|
|
normalise_count++;
|
|
if (normalise_count > 50) {
|
|
normalise_count = 0;
|
|
for (i = 0; i < gNum_cars_and_non_cars; i++) {
|
|
car = gActive_car_list[i];
|
|
BrMatrix34LPNormalise(&mat, &car->car_master_actor->t.t.mat);
|
|
BrMatrix34Copy(&car->car_master_actor->t.t.mat, &mat);
|
|
}
|
|
}
|
|
}
|
|
|
|
// IDA: void __cdecl GetNonCars()
|
|
void GetNonCars() {
|
|
int i;
|
|
int j;
|
|
LOG_TRACE("()");
|
|
|
|
gNum_cars_and_non_cars = gNum_active_non_cars + gNum_active_cars;
|
|
j = 0;
|
|
for (i = gNum_active_cars; i < gNum_cars_and_non_cars; i++) {
|
|
gActive_car_list[i] = (tCar_spec*)gActive_non_car_list[j];
|
|
j++;
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall GetNetPos(tCar_spec *pCar@<EAX>)
|
|
void GetNetPos(tCar_spec* pCar) {
|
|
int j;
|
|
float amount;
|
|
br_scalar total_deflection;
|
|
LOG_TRACE("(%p)", pCar);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall ApplyPhysicsToCars(tU32 last_frame_time@<EAX>, tU32 pTime_difference@<EDX>)
|
|
void ApplyPhysicsToCars(tU32 last_frame_time, tU32 pTime_difference) {
|
|
br_vector3 minus_k;
|
|
int i;
|
|
int old_num_cars;
|
|
int step_number;
|
|
int dam_index;
|
|
static int steering_locked;
|
|
tCar_spec* car = NULL;
|
|
tCollision_info* car_info;
|
|
tNon_car_spec* non_car;
|
|
tU32 time_step;
|
|
tU32 frame_end_time;
|
|
LOG_TRACE("(%d, %d)", last_frame_time, pTime_difference);
|
|
|
|
step_number = 0;
|
|
frame_end_time = last_frame_time + pTime_difference;
|
|
if (gFreeze_mechanics) {
|
|
return;
|
|
}
|
|
if (gNet_mode == eNet_mode_client) {
|
|
ForceRebuildActiveCarList();
|
|
}
|
|
if (gLast_mechanics_time < last_frame_time) {
|
|
gLast_mechanics_time = harness_game_config.physics_step_time * (last_frame_time / harness_game_config.physics_step_time);
|
|
}
|
|
GetNonCars();
|
|
if (frame_end_time <= gLast_mechanics_time) {
|
|
PrepareCars(last_frame_time);
|
|
InterpolateCars(frame_end_time, pTime_difference);
|
|
FinishCars(frame_end_time, pTime_difference);
|
|
return;
|
|
}
|
|
|
|
gDoing_physics = 1;
|
|
PrepareCars(last_frame_time);
|
|
gDt = harness_game_config.physics_step_time / 1000.0; // 0.039999999;
|
|
gMechanics_time_sync = pTime_difference - (gLast_mechanics_time - last_frame_time);
|
|
while (gLast_mechanics_time < frame_end_time && step_number < 5) {
|
|
step_number++;
|
|
ResetOldmat();
|
|
gProgram_state.current_car.old_v = gProgram_state.current_car.v;
|
|
if (&gProgram_state.current_car != gCar_to_view) {
|
|
gCar_to_view->old_v.v[0] = gCar_to_view->v.v[0];
|
|
gCar_to_view->old_v.v[1] = gCar_to_view->v.v[1];
|
|
gCar_to_view->old_v.v[2] = gCar_to_view->v.v[2];
|
|
}
|
|
for (i = 0; gNum_active_cars > i; ++i) {
|
|
car = gActive_car_list[i];
|
|
car->dt = -1.0;
|
|
if (car->message.type == 15 && car->message.time >= gLast_mechanics_time && gLast_mechanics_time + harness_game_config.physics_step_time >= car->message.time) {
|
|
car->dt = (double)(gLast_mechanics_time + harness_game_config.physics_step_time - car->message.time) / 1000.0;
|
|
if (gDt - 0.0001 <= car->dt) {
|
|
GetNetPos(car);
|
|
} else if (gNet_mode == eNet_mode_host) {
|
|
car->dt = -1.0;
|
|
} else {
|
|
for (dam_index = 0; dam_index < 12; ++dam_index) {
|
|
if (car->damage_units[dam_index].damage_level < car->message.damage[dam_index]) {
|
|
car->dt = -1.0;
|
|
break;
|
|
}
|
|
}
|
|
if (car->dt >= 0.0) {
|
|
GetNetPos(car);
|
|
}
|
|
}
|
|
}
|
|
if (!car->disabled
|
|
&& (!car->doing_nothing_flag || (car->driver >= eDriver_net_human && (!gPalette_fade_time || car->driver != eDriver_local_human)))) {
|
|
if (car->box_face_ref != gFace_num__car
|
|
&& (car->box_face_ref != gFace_num__car - 1 || car->box_face_start <= gFace_count)) {
|
|
car_info = (tCollision_info*)car;
|
|
GetFacesInBox(car_info);
|
|
}
|
|
if (car->dt != 0.0) {
|
|
MoveAndCollideCar(car, gDt);
|
|
}
|
|
}
|
|
}
|
|
for (i = 0; i < gNum_active_non_cars; ++i) {
|
|
non_car = gActive_non_car_list[i];
|
|
if (!non_car->collision_info.doing_nothing_flag) {
|
|
non_car->collision_info.dt = -1.0;
|
|
if (non_car->collision_info.message.type == 16 && non_car->collision_info.message.time >= gLast_mechanics_time && gLast_mechanics_time + harness_game_config.physics_step_time >= non_car->collision_info.message.time) {
|
|
non_car->collision_info.dt = (double)(gLast_mechanics_time + harness_game_config.physics_step_time - non_car->collision_info.message.time) / 1000.0;
|
|
GetNetPos((tCar_spec*)non_car);
|
|
}
|
|
if (non_car->collision_info.box_face_ref != gFace_num__car
|
|
&& (non_car->collision_info.box_face_ref != gFace_num__car - 1
|
|
|| non_car->collision_info.box_face_start <= gFace_count)) {
|
|
GetFacesInBox(&non_car->collision_info);
|
|
}
|
|
if (non_car->collision_info.dt != 0.0) {
|
|
MoveAndCollideNonCar(non_car, gDt);
|
|
}
|
|
}
|
|
}
|
|
do {
|
|
old_num_cars = gNum_cars_and_non_cars;
|
|
CrashCarsTogether(gDt);
|
|
} while (old_num_cars < gNum_cars_and_non_cars);
|
|
gMechanics_time_sync -= harness_game_config.physics_step_time;
|
|
gLast_mechanics_time += harness_game_config.physics_step_time;
|
|
}
|
|
gMechanics_time_sync = 1;
|
|
SendCarData(gLast_mechanics_time);
|
|
InterpolateCars(frame_end_time, pTime_difference);
|
|
FinishCars(frame_end_time, pTime_difference);
|
|
gDoing_physics = 0;
|
|
CheckForDeAttachmentOfNonCars(pTime_difference);
|
|
}
|
|
|
|
// IDA: void __usercall MungeSpecialVolume(tCollision_info *pCar@<EAX>)
|
|
void MungeSpecialVolume(tCollision_info* pCar) {
|
|
tSpecial_volume* new_special_volume;
|
|
tCar_spec* car;
|
|
LOG_TRACE("(%p)", pCar);
|
|
|
|
STUB_ONCE();
|
|
}
|
|
|
|
// IDA: void __usercall ResetCarSpecialVolume(tCollision_info *pCar@<EAX>)
|
|
void ResetCarSpecialVolume(tCollision_info* pCar) {
|
|
br_vector3 cast_v;
|
|
br_vector3 norm;
|
|
br_scalar t;
|
|
int id_len;
|
|
char* mat_id;
|
|
tSpecial_volume* new_special_volume;
|
|
br_material* material;
|
|
LOG_TRACE("(%p)", pCar);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall TestAutoSpecialVolume(tCollision_info *pCar@<EAX>)
|
|
void TestAutoSpecialVolume(tCollision_info* pCar) {
|
|
br_vector3 pos;
|
|
br_scalar car_d;
|
|
br_scalar d;
|
|
br_scalar d2;
|
|
br_vector3 dir;
|
|
br_vector3 tv;
|
|
br_vector3 lp;
|
|
br_vector3 hp;
|
|
tSpecial_volume* vol;
|
|
br_matrix34* mat;
|
|
br_scalar lowest_p;
|
|
br_scalar highest_p;
|
|
br_scalar val;
|
|
int i;
|
|
LOG_TRACE("(%p)", pCar);
|
|
|
|
STUB_ONCE();
|
|
}
|
|
|
|
// IDA: void __usercall MoveAndCollideCar(tCar_spec *car@<EAX>, br_scalar dt)
|
|
void MoveAndCollideCar(tCar_spec* car, br_scalar dt) {
|
|
tCollision_info* car_info;
|
|
int wheel;
|
|
LOG_TRACE("(%p, %f)", car, dt);
|
|
|
|
if (car->dt >= 0.0) {
|
|
dt = car->dt;
|
|
}
|
|
if (dt != 0.0 && (!gCar_flying || &gProgram_state.current_car != car)) {
|
|
car_info = (tCollision_info*)car;
|
|
car->new_skidding = 0;
|
|
if (car->water_d != 10000.0) {
|
|
TestAutoSpecialVolume(car_info);
|
|
}
|
|
MungeSpecialVolume(car_info);
|
|
if (car->driver < eDriver_net_human) {
|
|
CalcForce(car, dt);
|
|
} else {
|
|
CalcEngineForce(car, dt);
|
|
CalcForce(car, dt);
|
|
DoRevs(car, dt);
|
|
}
|
|
RotateCar(car_info, dt);
|
|
TranslateCar(car_info, dt);
|
|
CollideCarWithWall(car_info, dt);
|
|
BrMatrix34ApplyP(&car->pos, &car->cmpos, &car->car_master_actor->t.t.mat);
|
|
car->pos.v[0] = car->pos.v[0] / WORLD_SCALE;
|
|
car->pos.v[1] = car->pos.v[1] / WORLD_SCALE;
|
|
car->pos.v[2] = car->pos.v[2] / WORLD_SCALE;
|
|
for (wheel = 0; wheel < 4; wheel++) {
|
|
SkidMark(car, wheel);
|
|
}
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall MoveAndCollideNonCar(tNon_car_spec *non_car@<EAX>, br_scalar dt)
|
|
void MoveAndCollideNonCar(tNon_car_spec* non_car, br_scalar dt) {
|
|
tCollision_info* car_info;
|
|
LOG_TRACE("(%p, %f)", non_car, dt);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: int __usercall CollideCarWithWall@<EAX>(tCollision_info *car@<EAX>, br_scalar dt)
|
|
int CollideCarWithWall(tCollision_info* car, br_scalar dt) {
|
|
LOG_TRACE("(%p, %f)", car, dt);
|
|
|
|
GetFacesInBox(car);
|
|
if (gCollision_detection_on__car) {
|
|
car->collision_flag = 0;
|
|
while (CollCheck(car, dt)) {
|
|
car->collision_flag++;
|
|
if (car->collision_flag - 1 > 20) {
|
|
car->collision_flag = 1;
|
|
car->v.v[0] = 0.0;
|
|
car->v.v[1] = 0.0;
|
|
car->v.v[2] = 0.0;
|
|
car->omega.v[0] = 0.0;
|
|
car->omega.v[1] = 0.0;
|
|
car->omega.v[2] = 0.0;
|
|
break;
|
|
}
|
|
RotateCar(car, dt);
|
|
TranslateCar(car, dt);
|
|
GetFacesInBox(car);
|
|
}
|
|
if (car->collision_flag) {
|
|
CrashEarnings((tCar_spec*)car, NULL);
|
|
}
|
|
BrMatrix34TApplyV(&car->velocity_car_space, &car->v, &car->oldmat);
|
|
car->frame_collision_flag += car->collision_flag;
|
|
}
|
|
return car->collision_flag;
|
|
}
|
|
|
|
// IDA: void __cdecl ToggleControls()
|
|
void ToggleControls() {
|
|
LOG_TRACE("()");
|
|
|
|
if (!ControlCar[++gControl__car]) {
|
|
gControl__car = 0;
|
|
}
|
|
switch (gControl__car) {
|
|
case 0:
|
|
NewTextHeadupSlot(4, 0, 500, -1, "Original Controls");
|
|
break;
|
|
case 1:
|
|
NewTextHeadupSlot(4, 0, 500, -1, "Accelerated steering");
|
|
break;
|
|
case 2:
|
|
NewTextHeadupSlot(4, 0, 500, -1, "0.75 Accelerated");
|
|
break;
|
|
case 3:
|
|
NewTextHeadupSlot(4, 0, 500, -1, "0.5 Accelerated");
|
|
break;
|
|
default:
|
|
NewTextHeadupSlot(4, 0, 500, -1, "New controls");
|
|
break;
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall ControlCar2(tCar_spec *c@<EAX>, br_scalar dt)
|
|
void ControlCar2(tCar_spec* c, br_scalar dt) {
|
|
LOG_TRACE("(%p, %f)", c, dt);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall ControlCar3(tCar_spec *c@<EAX>, br_scalar dt)
|
|
void ControlCar3(tCar_spec* c, br_scalar dt) {
|
|
LOG_TRACE("(%p, %f)", c, dt);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall ControlCar4(tCar_spec *c@<EAX>, br_scalar dt)
|
|
void ControlCar4(tCar_spec* c, br_scalar dt) {
|
|
br_scalar ts;
|
|
LOG_TRACE("(%p, %f)", c, dt);
|
|
|
|
if (c->keys.left) {
|
|
if (c->turn_speed < 0.0) {
|
|
c->turn_speed = 0.0;
|
|
}
|
|
if (c->velocity_car_space.v[2] <= 0.0) {
|
|
if ((c->curvature < 0.0 || c->omega.v[1] < -0.001) && c->turn_speed == 0.0) {
|
|
c->turn_speed = 0.050000001 / (BrVector3Length(&c->v) + 5.0) * (dt * 25.0) * 4.0 / 2.0 * 0.5;
|
|
if (c->omega.v[1] < -0.01) {
|
|
c->turn_speed = c->turn_speed - dt * 0.01 / 0.04 / 2.0 * c->omega.v[1] * 2.0;
|
|
}
|
|
} else {
|
|
c->turn_speed = 0.050000001 / (BrVector3Length(&c->v) + 5.0) * (dt * 25.0) / 2.0 * 0.5 + c->turn_speed;
|
|
}
|
|
} else {
|
|
c->turn_speed = dt * 0.01 / 0.04 / 2.0 * 2.0 + c->turn_speed;
|
|
}
|
|
}
|
|
if (c->keys.right) {
|
|
if (c->turn_speed > 0.0) {
|
|
c->turn_speed = 0.0;
|
|
}
|
|
if (c->velocity_car_space.v[2] <= 0.0) {
|
|
if ((c->curvature > 0.0 || c->omega.v[1] > 0.001) && c->turn_speed == 0.0) {
|
|
c->turn_speed = 0.050000001
|
|
/ (BrVector3Length(&c->v) + 5.0) * (dt * 25.0) * -4.0 / 2.0 * 0.5;
|
|
if (c->omega.v[1] < -0.01) {
|
|
c->turn_speed = c->turn_speed - dt * 0.01 / 0.04 / 2.0 * c->omega.v[1] * 2.0;
|
|
}
|
|
} else {
|
|
c->turn_speed = c->turn_speed
|
|
- 0.050000001
|
|
/ (BrVector3Length(&c->v) + 5.0) * (dt * 25.0) / 2.0 * 0.5;
|
|
}
|
|
} else {
|
|
c->turn_speed = c->turn_speed - dt * 0.01 / 0.04 / 2.0 * 2.0;
|
|
}
|
|
}
|
|
if (c->keys.left || c->keys.right) {
|
|
if (fabs(c->turn_speed) < fabs(dt * 2.0 * c->curvature) && c->curvature * c->turn_speed < 0.0) {
|
|
c->turn_speed = -(dt * 2.0 * c->curvature);
|
|
}
|
|
} else {
|
|
c->turn_speed = 0.0;
|
|
}
|
|
c->curvature = c->curvature + c->turn_speed;
|
|
if (c->joystick.left <= 0) {
|
|
if (c->joystick.right >= 0) {
|
|
ts = (double)c->joystick.right * (double)c->joystick.right / 4294967300.0;
|
|
c->curvature = c->maxcurve * -ts;
|
|
}
|
|
} else {
|
|
c->curvature = (double)c->joystick.left * (double)c->joystick.left / 4294967300.0 * c->maxcurve;
|
|
}
|
|
if (c->curvature > (double)c->maxcurve) {
|
|
c->curvature = c->maxcurve;
|
|
}
|
|
if (-c->maxcurve > c->curvature) {
|
|
c->curvature = -c->maxcurve;
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall ControlCar5(tCar_spec *c@<EAX>, br_scalar dt)
|
|
void ControlCar5(tCar_spec* c, br_scalar dt) {
|
|
LOG_TRACE("(%p, %f)", c, dt);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall ControlCar1(tCar_spec *c@<EAX>, br_scalar dt)
|
|
void ControlCar1(tCar_spec* c, br_scalar dt) {
|
|
LOG_TRACE("(%p, %f)", c, dt);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall setrotate(br_vector3 *wdt@<EAX>, br_matrix34 *m@<EDX>)
|
|
void setrotate(br_vector3* wdt, br_matrix34* m) {
|
|
br_euler e;
|
|
LOG_TRACE("(%p, %p)", wdt, m);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall RotateCar2(tCollision_info *c@<EAX>, br_scalar dt)
|
|
void RotateCar2(tCollision_info* c, br_scalar dt) {
|
|
br_vector3 wdt;
|
|
br_vector3 wdt2;
|
|
br_vector3 L;
|
|
br_vector3 L2;
|
|
br_matrix34 m;
|
|
LOG_TRACE("(%p, %f)", c, dt);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall RotateCarSecondOrder(tCollision_info *c@<EAX>, br_scalar dt)
|
|
void RotateCarSecondOrder(tCollision_info* c, br_scalar dt) {
|
|
br_vector3 L;
|
|
br_vector3 L2;
|
|
br_vector3 axis;
|
|
br_vector3 omega;
|
|
br_scalar rad;
|
|
br_scalar rad_rate;
|
|
br_matrix34 m;
|
|
LOG_TRACE("(%p, %f)", c, dt);
|
|
|
|
rad_rate = BrVector3Length(&c->omega);
|
|
rad = rad_rate * dt;
|
|
|
|
BrVector3InvScale(&axis, &c->omega, rad_rate);
|
|
L.v[0] = c->I.v[0] * c->omega.v[0];
|
|
L.v[1] = c->I.v[1] * c->omega.v[1];
|
|
L.v[2] = c->I.v[2] * c->omega.v[2];
|
|
|
|
BrMatrix34Rotate(&m, BrRadianToAngle(rad) / 2, &axis);
|
|
BrMatrix34TApplyV(&L2, &L, &m);
|
|
omega.v[0] = L2.v[0] / c->I.v[0];
|
|
omega.v[1] = L2.v[1] / c->I.v[1];
|
|
omega.v[2] = L2.v[2] / c->I.v[2];
|
|
|
|
rad_rate = BrVector3Length(&omega);
|
|
rad = rad_rate * dt;
|
|
|
|
BrVector3InvScale(&axis, &omega, rad_rate);
|
|
BrMatrix34Rotate(&m, BrRadianToAngle(rad), &axis);
|
|
BrMatrix34PreTranslate(&m, -c->cmpos.v[0], -c->cmpos.v[1], -c->cmpos.v[2]);
|
|
BrMatrix34PostTranslate(&m, c->cmpos.v[0], c->cmpos.v[1], c->cmpos.v[2]);
|
|
BrMatrix34Pre(&c->car_master_actor->t.t.mat, &m);
|
|
BrMatrix34TApplyV(&L2, &L, &m);
|
|
c->omega.v[0] = L2.v[0] / c->I.v[0];
|
|
c->omega.v[1] = L2.v[1] / c->I.v[1];
|
|
c->omega.v[2] = L2.v[2] / c->I.v[2];
|
|
}
|
|
|
|
// IDA: void __usercall RotateCarFirstOrder(tCollision_info *c@<EAX>, br_scalar dt)
|
|
void RotateCarFirstOrder(tCollision_info* c, br_scalar dt) {
|
|
br_vector3 axis;
|
|
br_vector3 L;
|
|
br_vector3 L2;
|
|
br_matrix34 m;
|
|
br_scalar rad_rate;
|
|
br_scalar rad;
|
|
br_scalar e1;
|
|
br_scalar e2;
|
|
static br_scalar max_rad;
|
|
LOG_TRACE("(%p, %f)", c, dt);
|
|
|
|
rad_rate = BrVector3Length(&c->omega);
|
|
rad = rad_rate * dt;
|
|
|
|
if (rad < 0.0001) {
|
|
return;
|
|
}
|
|
BrVector3InvScale(&axis, &c->omega, rad_rate);
|
|
L.v[0] = c->I.v[0] * c->omega.v[0];
|
|
L.v[1] = c->I.v[1] * c->omega.v[1];
|
|
L.v[2] = c->I.v[2] * c->omega.v[2];
|
|
BrMatrix34Rotate(&m, BrRadianToAngle(rad), &axis);
|
|
BrMatrix34TApplyV(&L2, &L, &m);
|
|
BrMatrix34PreTranslate(&m, -c->cmpos.v[0], -c->cmpos.v[1], -c->cmpos.v[2]);
|
|
BrMatrix34PostTranslate(&m, c->cmpos.v[0], c->cmpos.v[1], c->cmpos.v[2]);
|
|
BrMatrix34Pre(&c->car_master_actor->t.t.mat, &m);
|
|
c->omega.v[0] = L2.v[0] / c->I.v[0];
|
|
c->omega.v[1] = L2.v[1] / c->I.v[1];
|
|
c->omega.v[2] = L2.v[2] / c->I.v[2];
|
|
}
|
|
|
|
// IDA: void __usercall SimpleRotate(tCollision_info *c@<EAX>, br_scalar dt)
|
|
void SimpleRotate(tCollision_info* c, br_scalar dt) {
|
|
br_vector3 axis;
|
|
br_scalar rad_rate;
|
|
br_scalar rad;
|
|
LOG_TRACE("(%p, %f)", c, dt);
|
|
|
|
rad_rate = BrVector3Length(&c->omega);
|
|
BrVector3InvScale(&axis, &c->omega, rad_rate);
|
|
rad = rad_rate * dt;
|
|
if (rad >= 0.0001) {
|
|
BrMatrix34PreRotate(&c->car_master_actor->t.t.mat, BrRadianToAngle(rad), &axis);
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall RotateCar(tCollision_info *c@<EAX>, br_scalar dt)
|
|
void RotateCar(tCollision_info* c, br_scalar dt) {
|
|
br_scalar rad_squared;
|
|
int steps;
|
|
int i;
|
|
LOG_TRACE("(%p, %f)", c, dt);
|
|
|
|
rad_squared = BrVector3LengthSquared(&c->omega) * dt;
|
|
c->oldomega = c->omega;
|
|
|
|
if (rad_squared < 0.0000001) {
|
|
return;
|
|
}
|
|
|
|
if (rad_squared > 0.008f) {
|
|
steps = sqrt(rad_squared / 0.032) + 1;
|
|
dt = dt / steps;
|
|
|
|
for (i = 0; i < steps && i < 20; i++) {
|
|
RotateCarSecondOrder(c, dt);
|
|
}
|
|
} else {
|
|
RotateCarFirstOrder(c, dt);
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall SteeringSelfCentre(tCar_spec *c@<EAX>, br_scalar dt, br_vector3 *n)
|
|
void SteeringSelfCentre(tCar_spec* c, br_scalar dt, br_vector3* n) {
|
|
br_scalar ts;
|
|
br_scalar ts2;
|
|
LOG_TRACE("(%p, %f, %p)", c, dt, n);
|
|
|
|
if (c->curvature > c->maxcurve) {
|
|
c->curvature = c->maxcurve;
|
|
}
|
|
if (-c->maxcurve > c->curvature) {
|
|
c->curvature = -c->maxcurve;
|
|
}
|
|
if (!c->keys.left && c->joystick.left <= 0 && !c->keys.right && c->joystick.right <= 0 && !c->keys.holdw) {
|
|
if (c->susp_height[1] > c->oldd[2] || c->susp_height[1] > c->oldd[3]) {
|
|
ts = -((c->omega.v[2] * n->v[2] + c->omega.v[1] * n->v[1] + c->omega.v[0] * n->v[0]) * (dt / (c->wpos[0].v[2] - c->wpos[2].v[2])));
|
|
ts2 = -(c->curvature * dt);
|
|
if (fabs(ts) < fabs(ts2) || (ts * ts2 < 0.0)) {
|
|
ts = ts2;
|
|
}
|
|
c->curvature = c->curvature + ts;
|
|
if (c->curvature * ts > 0.0) {
|
|
c->curvature = 0.0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall NonCarCalcForce(tNon_car_spec *nc@<EAX>, br_scalar dt)
|
|
void NonCarCalcForce(tNon_car_spec* nc, br_scalar dt) {
|
|
tCollision_info* c;
|
|
tSpecial_volume* vol;
|
|
br_scalar ts;
|
|
br_vector3 tv;
|
|
br_vector3 v;
|
|
LOG_TRACE("(%p, %f)", nc, dt);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall AddDrag(tCar_spec *c@<EAX>, br_scalar dt)
|
|
void AddDrag(tCar_spec* c, br_scalar dt) {
|
|
br_scalar drag_multiplier;
|
|
br_scalar ts;
|
|
tSpecial_volume* vol;
|
|
br_vector3 b;
|
|
LOG_TRACE("(%p, %f)", c, dt);
|
|
|
|
vol = c->last_special_volume;
|
|
drag_multiplier = -(dt * TIME_CONV_THING);
|
|
if (vol) {
|
|
if (c->underwater_ability) {
|
|
drag_multiplier = vol->viscosity_multiplier * drag_multiplier * 0.6;
|
|
} else {
|
|
drag_multiplier = vol->viscosity_multiplier * drag_multiplier;
|
|
}
|
|
drag_multiplier = c->water_depth_factor * drag_multiplier;
|
|
}
|
|
ts = BrVector3Length(&c->v) * drag_multiplier / c->M;
|
|
BrVector3Scale(&b, &c->v, ts);
|
|
BrVector3Accumulate(&c->v, &b);
|
|
ts = BrVector3Length(&c->omega) * drag_multiplier;
|
|
BrVector3Scale(&b, &c->omega, ts);
|
|
ApplyTorque(c, &b);
|
|
}
|
|
|
|
// IDA: void __usercall DoBumpiness(tCar_spec *c@<EAX>, br_vector3 *wheel_pos@<EDX>, br_vector3 *norm@<EBX>, br_scalar *d@<ECX>, int n)
|
|
void DoBumpiness(tCar_spec* c, br_vector3* wheel_pos, br_vector3* norm, br_scalar* d, int n) {
|
|
br_vector3 tv;
|
|
int delta;
|
|
int x;
|
|
int y;
|
|
tMaterial_modifiers* mat_list;
|
|
LOG_TRACE("(%p, %p, %p, %p, %d)", c, wheel_pos, norm, d, n);
|
|
|
|
STUB_ONCE();
|
|
}
|
|
|
|
// IDA: void __usercall CalcForce(tCar_spec *c@<EAX>, br_scalar dt)
|
|
void CalcForce(tCar_spec* c, br_scalar dt) {
|
|
int n;
|
|
int normnum;
|
|
int i;
|
|
int x;
|
|
int y;
|
|
br_scalar force[4];
|
|
br_scalar d[4];
|
|
br_scalar ts;
|
|
br_scalar ts2;
|
|
br_scalar ts3;
|
|
br_scalar ts4;
|
|
br_scalar ts5;
|
|
br_scalar ts6;
|
|
br_scalar deltaomega;
|
|
br_scalar wheelratio;
|
|
br_scalar modf;
|
|
br_scalar maxfl;
|
|
br_scalar maxfr;
|
|
br_scalar max_retardation;
|
|
br_scalar front_retardation;
|
|
br_scalar friction_number;
|
|
br_vector3 a;
|
|
br_vector3 b;
|
|
br_vector3 tv;
|
|
br_vector3 tv2;
|
|
br_vector3 norm[4];
|
|
br_vector3 v_batwick;
|
|
br_vector3 vplane;
|
|
br_vector3 rightplane;
|
|
br_vector3 t;
|
|
br_vector3 f;
|
|
br_vector3 ff;
|
|
br_vector3 fb;
|
|
br_scalar ffi;
|
|
br_scalar ffk;
|
|
br_scalar fbi;
|
|
br_scalar fbk;
|
|
br_vector3 wheel_pos[4];
|
|
br_scalar direction;
|
|
br_scalar wheel_spin_force;
|
|
br_scalar d_damage;
|
|
br_scalar fl_oil_factor;
|
|
br_scalar fr_oil_factor;
|
|
br_scalar rl_oil_factor;
|
|
br_scalar rr_oil_factor;
|
|
br_matrix34* mat;
|
|
tMaterial_modifiers* mat_list;
|
|
static br_scalar stop_timer;
|
|
static br_scalar slide_dist;
|
|
tDamage_type dam;
|
|
br_scalar v;
|
|
tSpecial_volume* vol;
|
|
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]
|
|
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]
|
|
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]
|
|
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]
|
|
br_vector3 v136; // [esp+1E0h] [ebp-Ch]
|
|
|
|
BrVector3Set(&v136, 0, 0, 0);
|
|
normnum = 0;
|
|
BrVector3Set(&f, 0, 0, 0);
|
|
BrVector3Set(&B, 0, 0, 0);
|
|
mat = &c->car_master_actor->t.t.mat;
|
|
mat_list = gCurrent_race.material_modifiers;
|
|
vol = c->last_special_volume;
|
|
b.v[0] = -mat->m[1][0];
|
|
b.v[1] = -mat->m[1][1];
|
|
b.v[2] = -mat->m[1][2];
|
|
c->material_index[0] = 0;
|
|
c->material_index[1] = 0;
|
|
c->material_index[2] = 0;
|
|
c->material_index[3] = 0;
|
|
wheelratio = (c->wpos[2].v[2] - c->cmpos.v[2]) / (c->wpos[0].v[2] - c->cmpos.v[2]);
|
|
BrVector3Set(&c->road_normal, 0, 0, 0);
|
|
for (i = 0; i < 4; ++i) {
|
|
BrMatrix34ApplyP(&wheel_pos[i], &c->wpos[i], mat);
|
|
}
|
|
MultiFindFloorInBoxM(4, wheel_pos, &b, c->nor, d, c, c->material_index);
|
|
if (c->last_special_volume && c->last_special_volume->material_modifier_index) {
|
|
c->material_index[0] = c->last_special_volume->material_modifier_index;
|
|
c->material_index[1] = c->material_index[0];
|
|
c->material_index[2] = c->material_index[1];
|
|
c->material_index[3] = c->material_index[2];
|
|
}
|
|
for (i = 0; i < 4; ++i) {
|
|
BrMatrix34TApplyV(&norm[i], &c->nor[i], mat);
|
|
if (mat_list[c->material_index[i]].bumpiness != 0.0) {
|
|
DoBumpiness(c, wheel_pos, norm, d, i);
|
|
}
|
|
if (d[i] < -0.5 || c->wheel_dam_offset[i ^ 2] * 6.9 + c->susp_height[i / 2] < d[i]) {
|
|
force[i] = 0.0;
|
|
d[i] = c->susp_height[i / 2];
|
|
} else {
|
|
BrVector3Accumulate(&c->road_normal, &norm[i]);
|
|
normnum++;
|
|
d[i] = d[i] - c->wheel_dam_offset[i ^ 2] * 6.9;
|
|
force[i] = (c->susp_height[i / 2] - d[i]) * c->sk[1 / 2];
|
|
force[i] = force[i] - (d[i] - c->oldd[i]) / dt * c->sb[i / 2];
|
|
if (c->susp_height[i / 2] == c->oldd[i]
|
|
&& c->nor[i].v[2] * c->v.v[2] + c->nor[i].v[1] * c->v.v[1] + c->nor[i].v[0] * c->v.v[0] > -0.0099999998
|
|
&& c->M * 20.0 / 4.0 < force[i]) {
|
|
d[i] = c->susp_height[i / 2];
|
|
force[i] = c->M * 20.0 / 4.0;
|
|
}
|
|
if (force[i] < 0.0) {
|
|
force[i] = 0.0;
|
|
}
|
|
B.v[1] = force[i] + B.v[1];
|
|
f.v[0] = f.v[0] - (c->wpos[i].v[2] - c->cmpos.v[2]) * force[i];
|
|
f.v[2] = (c->wpos[i].v[0] - c->cmpos.v[0]) * force[i] + f.v[2];
|
|
}
|
|
c->oldd[i] = d[i];
|
|
}
|
|
if (c->driver <= eDriver_non_car || !c->wall_climber_mode || (c->road_normal.v[0] == 0.0 && c->road_normal.v[1] == 0.0 && c->road_normal.v[2] == 0.0)) {
|
|
if (vol) {
|
|
friction_number = (1.0 - vol->gravity_multiplier) * c->water_depth_factor;
|
|
if (c->underwater_ability) {
|
|
friction_number = friction_number * 0.6;
|
|
}
|
|
friction_number = (1.0 - friction_number) * c->M;
|
|
} else {
|
|
friction_number = c->M;
|
|
}
|
|
friction_number = friction_number * gGravity_multiplier * 10.0;
|
|
B.v[0] = B.v[0] - mat->m[0][1] * friction_number;
|
|
B.v[1] = B.v[1] - mat->m[1][1] * friction_number;
|
|
B.v[2] = B.v[2] - mat->m[2][1] * friction_number;
|
|
} else {
|
|
BrVector3Normalise(&v107, &c->road_normal);
|
|
BrVector3Scale(&v107, &v107, -(c->M * 10.0));
|
|
BrVector3Accumulate(&B, &v107);
|
|
}
|
|
if (c->driver >= eDriver_net_human) {
|
|
SteeringSelfCentre(c, dt, &c->road_normal);
|
|
}
|
|
if (normnum) {
|
|
// ts = 1.0 / sqrt(1.0); <- looked like this in the windows build definitely wrong
|
|
// ts = 1.0 / sqrt(c->road_normal.v[0] * c->road_normal.v[0] + c->road_normal.v[1] * c->road_normal.v[1] + c->road_normal.v[2] * c->road_normal.v[2]);
|
|
// c->road_normal.v[0] = c->road_normal.v[0] * ts;
|
|
// c->road_normal.v[1] = c->road_normal.v[1] * ts;
|
|
// c->road_normal.v[2] = c->road_normal.v[2] * ts;
|
|
BrVector3NormaliseQuick(&c->road_normal, &c->road_normal);
|
|
|
|
friction_number = c->road_normal.v[1] * mat->m[1][1] + c->road_normal.v[2] * mat->m[2][1] + c->road_normal.v[0] * mat->m[0][1];
|
|
if (c->driver > eDriver_non_car && c->wall_climber_mode) {
|
|
friction_number = 1.0;
|
|
}
|
|
friction_number = gCurrent_race.material_modifiers[c->material_index[0]].down_force * friction_number;
|
|
if (friction_number > 0.0f) {
|
|
friction_number = fabs(c->velocity_car_space.v[2]) * c->M * 10.0 * friction_number / c->down_force_speed;
|
|
if (c->M * 10.0 < friction_number) {
|
|
friction_number = c->M * 10.0;
|
|
}
|
|
if (c->number_of_wheels_on_ground == 4 && c->oldd[2] == c->susp_height[1] && c->oldd[3] == c->susp_height[1]) {
|
|
a.v[0] = c->wpos[2].v[2] * mat->m[2][0];
|
|
a.v[1] = c->wpos[2].v[2] * mat->m[2][1];
|
|
a.v[2] = c->wpos[2].v[2] * mat->m[2][2];
|
|
a.v[0] = mat->m[3][0] + a.v[0];
|
|
a.v[1] = mat->m[3][1] + a.v[1];
|
|
a.v[2] = mat->m[3][2] + a.v[2];
|
|
BrVector3Scale(&b, &b, (c->wpos[0].v[2] - c->wpos[2].v[2]));
|
|
findfloor(&a, &b, norm, &ts2);
|
|
if (ts2 > 1.0) {
|
|
c->down_force_flag = 1;
|
|
}
|
|
} else if (c->down_force_flag && (c->oldd[2] < c->susp_height[1] || c->oldd[3] < c->susp_height[1])) {
|
|
c->down_force_flag = 0;
|
|
}
|
|
if (c->down_force_flag) {
|
|
friction_number = (c->wpos[2].v[2] - c->cmpos.v[2]) / (c->wpos[2].v[2] - c->wpos[0].v[2]) * friction_number;
|
|
f.v[0] = (c->wpos[0].v[2] - c->cmpos.v[2]) * friction_number + f.v[0];
|
|
}
|
|
B.v[1] = B.v[1] - friction_number;
|
|
}
|
|
vplane.v[0] = BrVector3Dot(&c->velocity_car_space, &c->road_normal) * c->road_normal.v[0];
|
|
vplane.v[1] = BrVector3Dot(&c->velocity_car_space, &c->road_normal) * c->road_normal.v[1];
|
|
vplane.v[2] = BrVector3Dot(&c->velocity_car_space, &c->road_normal) * c->road_normal.v[2];
|
|
BrVector3Sub(&vplane, &c->velocity_car_space, &vplane);
|
|
if (vplane.v[2] < 0.0) {
|
|
ts = 1.0;
|
|
} else {
|
|
ts = -1.0;
|
|
}
|
|
ts3 = BrVector3Length(&vplane);
|
|
deltaomega = ts3 * c->curvature * ts;
|
|
deltaomega = deltaomega - BrVector3Dot(&c->omega, &c->road_normal);
|
|
BrVector3Set(&v103, c->road_normal.v[1], -c->road_normal.v[0], 0);
|
|
BrVector3Normalise(&v103, &v103);
|
|
|
|
friction_number = c->I.v[1] / dt * deltaomega;
|
|
ts = friction_number / (c->wpos[2].v[2] - c->wpos[0].v[2]);
|
|
v108 = ts;
|
|
v109 = -ts;
|
|
BrVector3Set(&rightplane, 0, c->road_normal.v[2], -c->road_normal.v[1]);
|
|
BrVector3Normalise(&rightplane, &rightplane);
|
|
v99 = c->acc_force;
|
|
friction_number = BrVector3Dot(&rightplane, &vplane);
|
|
v87 = BrVector3Dot(&v103, &vplane);
|
|
ts2 = fabs(v87);
|
|
friction_number = (c->wpos[0].v[2] - c->cmpos.v[2]) * friction_number * fabs(c->curvature);
|
|
if (c->curvature <= 0.0) {
|
|
friction_number = v87 - friction_number;
|
|
} else {
|
|
friction_number = v87 + friction_number;
|
|
}
|
|
friction_number = -(c->M / dt * friction_number);
|
|
friction_number = friction_number - BrVector3Dot(&B, &v103);
|
|
|
|
friction_number = friction_number / (1.0 - wheelratio);
|
|
v108 = friction_number + v108;
|
|
v109 = -wheelratio * friction_number + v109;
|
|
friction_number = (c->wpos[0].v[2] - c->wpos[2].v[2]) * v108;
|
|
v98 = friction_number * c->curvature;
|
|
friction_number = BrVector3Dot(&c->velocity_car_space, &rightplane) * c->M / dt;
|
|
v129 = BrVector3Dot(&rightplane, &B) + friction_number;
|
|
v128 = c->mu[0] * c->brake_force / (c->mu[1] / c->friction_elipticity + c->mu[0]);
|
|
v125 = c->brake_force - v128;
|
|
v105 = (c->damage_units[7].damage_level + c->damage_units[6].damage_level) / 2;
|
|
if (v105 > 20) {
|
|
v128 = (1.0 - (double)(v105 - 20) / 80.0) * (1.0 - (double)(v105 - 20) / 80.0) * v128;
|
|
}
|
|
v105 = (c->damage_units[5].damage_level + c->damage_units[4].damage_level) / 2;
|
|
if (v105 > 20) {
|
|
v125 = (1.0 - (double)(v105 - 20) / 80.0) * (1.0 - (double)(v105 - 20) / 80.0) * v125;
|
|
}
|
|
ts2 = (force[1] + force[0]) * c->rolling_r_back + v128;
|
|
v87 = (force[2] + force[3]) * c->rolling_r_front + v125;
|
|
v128 = c->wpos[0].v[2] - c->wpos[2].v[2];
|
|
v128 = sqrt(v128 * v128 * c->curvature * c->curvature + 1.0);
|
|
v106 = v87 / v128;
|
|
v134 = v106 + ts2;
|
|
if (fabs(v129) < fabs(v134)) {
|
|
ts2 = v129 / v134 * ts2;
|
|
v106 = v129 / v134 * v106;
|
|
}
|
|
if ((v87 + ts2) * v129 < 0.0) {
|
|
ts2 = -ts2;
|
|
v106 = -v106;
|
|
}
|
|
v129 = v129 - (ts2 + v106);
|
|
v99 = v99 - ts2;
|
|
if (c->keys.brake && c->damage_units[eDamage_lr_brake].damage_level < 60 && c->damage_units[eDamage_rr_brake].damage_level < 60) {
|
|
v99 = v99 - v129;
|
|
c->gear = 0;
|
|
}
|
|
v99 = v99 / c->friction_elipticity;
|
|
v135 = sqrt(v99 * v99 + v109 * v109) / 2.0;
|
|
|
|
GetOilFrictionFactors(c, &fl_oil_factor, &fr_oil_factor, &rl_oil_factor, &rr_oil_factor);
|
|
if (c->driver <= eDriver_non_car) {
|
|
v116 = 1.0;
|
|
} else {
|
|
v116 = c->grip_multiplier;
|
|
}
|
|
BrVector3Sub(&v102, &c->wpos[0], &c->cmpos);
|
|
BrVector3Cross(&a, &c->omega, &v102);
|
|
BrVector3Accumulate(&a, &c->velocity_car_space);
|
|
if (c->driver >= eDriver_net_human
|
|
&& (((c->keys.left || c->joystick.left > 0x8000) && c->curvature > 0.0 && deltaomega > 0.1 && a.v[0] > 0.0)
|
|
|| ((c->keys.right || c->joystick.right > 0x8000) && c->curvature < 0.0 && deltaomega < 0.1 && a.v[0] < 0.0))
|
|
&& ts > 0.0) {
|
|
friction_number = c->mu[0];
|
|
} else {
|
|
friction_number = c->mu[2];
|
|
ts2 = fabs(a.v[0]) / 10.0;
|
|
if (ts2 > 1) {
|
|
ts2 = 1.0;
|
|
}
|
|
friction_number = (c->mu[2] - c->mu[0]) * ts2 + friction_number;
|
|
}
|
|
|
|
maxfl = sqrt(force[0]) * friction_number * (rl_oil_factor * v116) * mat_list[c->material_index[0]].tyre_road_friction;
|
|
maxfr = sqrt(force[1]) * friction_number * (rr_oil_factor * v116) * mat_list[c->material_index[1]].tyre_road_friction;
|
|
c->max_force_rear = maxfr + maxfl;
|
|
if (rl_oil_factor == 1.0 && rr_oil_factor == 1.0 && c->traction_control && v135 * 2.0 > c->max_force_rear && c->acc_force > 0.0
|
|
&& (c->driver < eDriver_net_human || (c->target_revs > 1000.0 && c->gear > 0))) {
|
|
ts2 = v99;
|
|
if (v99 * v99 <= v135 * v135 * 4.0) {
|
|
v87 = sqrt(v135 * v135 * 4.0 - v99 * v99);
|
|
} else {
|
|
v87 = 0.0;
|
|
}
|
|
if (c->max_force_rear <= v87) {
|
|
c->torque = -(c->revs * c->revs / 100000000.0) - 0.1;
|
|
} else {
|
|
float v177 = sqrt(c->max_force_rear * c->max_force_rear - v87 * v87);
|
|
ts3 = ts2 < 0.0 ? -1.0 : 1.0;
|
|
// ts4 = (ts2 - ts3 * sqrt(ts3)) * 1.01;
|
|
// if (fabs(ts2) > fabs(ts4)) {
|
|
// v87 = ts4;
|
|
// ts2 = v87;
|
|
// }
|
|
|
|
ts4 = (ts2 - ts3 * v177) * 1.01;
|
|
if (fabs(ts2) > fabs(ts4)) {
|
|
ts2 = ts4;
|
|
}
|
|
}
|
|
v99 = v99 - ts2;
|
|
v135 = sqrt(v99 * v99 + v109 * v109) / 2.0;
|
|
|
|
} else if (c->driver >= eDriver_net_human && c->gear > 0 && c->revs > c->target_revs && !c->traction_control) {
|
|
if (!c->keys.change_down) {
|
|
c->traction_control = 1;
|
|
}
|
|
friction_number = 1.0 - (c->revs - c->target_revs) / (double)(400 * c->gear);
|
|
if (friction_number < 0.40000001) {
|
|
friction_number = 0.40000001;
|
|
}
|
|
maxfl = friction_number * maxfl;
|
|
maxfr = friction_number * maxfr;
|
|
}
|
|
if (fabs(v109) > maxfr + maxfl && maxfr + maxfl > 0.1) {
|
|
v87 = (maxfr + maxfl) / fabs(v109) * dt;
|
|
v109 = v87 * v109;
|
|
v99 = c->friction_elipticity * v87 * v99;
|
|
friction_number = -((c->wpos[2].v[2] - c->cmpos.v[2]) * v108 * ((c->wpos[2].v[2] - c->cmpos.v[2]) * v108) / c->I.v[1] + (v98 * v98 + v108 * v108) / c->M);
|
|
ts2 = (BrVector3Dot(&v103, &vplane) + v109 / c->M) * v108;
|
|
ts2 = BrVector3Dot(&rightplane, &vplane) * v98 + ts2;
|
|
ts2 = BrVector3Dot(&c->omega, &c->road_normal) * (c->wpos[2].v[2] - c->cmpos.v[2]) * v108 + ts2;
|
|
ts2 = (c->wpos[0].v[2] - c->cmpos.v[2]) * (c->wpos[2].v[2] - c->cmpos.v[2]) * v109 / c->I.v[1] * v108 + ts2;
|
|
if (fabs(friction_number) > 0.1) {
|
|
friction_number = ts2 / (friction_number * dt);
|
|
v108 = friction_number * v108;
|
|
v98 = friction_number * v98;
|
|
}
|
|
v109 = v109 / v87;
|
|
v99 = v99 / (c->friction_elipticity * v87);
|
|
}
|
|
v98 = v98 - v106;
|
|
v108 = (c->wpos[0].v[2] - c->wpos[2].v[2]) * c->curvature * v106 + v108;
|
|
if (v135 > 0.000099999997) {
|
|
v109 = v109 / (v135 * 2.0);
|
|
v99 = v99 / (v135 * 2.0);
|
|
}
|
|
v99 = c->friction_elipticity * v99;
|
|
force[0] = v135;
|
|
force[1] = v135;
|
|
c->wheel_slip = 0;
|
|
switch ((force[0] > maxfl) + 2 * (force[1] > maxfr)) {
|
|
case 0:
|
|
slide_dist = 0;
|
|
break;
|
|
case 1:
|
|
force[0] = c->freduction * maxfl;
|
|
force[1] = v135 - force[0] + force[1];
|
|
if (force[1] <= maxfr) {
|
|
slide_dist = 0;
|
|
} else {
|
|
if (maxfr > 0.1) {
|
|
pV = (force[1] - maxfr) / maxfr;
|
|
if (&gProgram_state.current_car == c) {
|
|
v78 = 20.0;
|
|
} else {
|
|
v78 = 60.0;
|
|
}
|
|
if (v78 <= pV) {
|
|
c->new_skidding |= 2u;
|
|
}
|
|
SkidNoise(c, 1, pV, c->material_index[1]);
|
|
}
|
|
force[1] = c->freduction * maxfr;
|
|
c->wheel_slip |= 2u;
|
|
}
|
|
break;
|
|
case 2:
|
|
force[1] = c->freduction * maxfr;
|
|
force[0] = v135 - force[1] + force[0];
|
|
if (force[0] <= maxfl) {
|
|
slide_dist = 0;
|
|
} else {
|
|
if (maxfl > 0.1) {
|
|
pV = (force[0] - maxfl) / maxfl;
|
|
if (&gProgram_state.current_car == c) {
|
|
v77 = 20.0;
|
|
} else {
|
|
v77 = 60.0;
|
|
}
|
|
if (v77 <= pV) {
|
|
c->new_skidding |= 1u;
|
|
}
|
|
SkidNoise(c, 0, pV, c->material_index[0]);
|
|
}
|
|
force[0] = c->freduction * maxfl;
|
|
c->wheel_slip |= 2u;
|
|
}
|
|
break;
|
|
case 3:
|
|
force[0] = c->freduction * maxfl;
|
|
force[1] = c->freduction * maxfr;
|
|
c->wheel_slip |= 2u;
|
|
pV = (v135 * 2.0 - maxfl - maxfr) / (maxfr + maxfl);
|
|
if (&gProgram_state.current_car == c) {
|
|
v79 = 20.0;
|
|
} else {
|
|
v79 = 60.0;
|
|
}
|
|
if (v79 <= pV) {
|
|
if (maxfl > 0.1) {
|
|
c->new_skidding |= 1u;
|
|
}
|
|
if (maxfr > 0.1) {
|
|
c->new_skidding |= 2u;
|
|
}
|
|
}
|
|
if (IRandomBetween(0, 1)) {
|
|
if (maxfl > 0.1) {
|
|
SkidNoise(c, 0, pV, c->material_index[0]);
|
|
}
|
|
} else if (maxfr > 0.1) {
|
|
SkidNoise(c, 1, pV, c->material_index[1]);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (c->wheel_slip && c->curvature * c->turn_speed > 0.0 && fabs(v109) > 0.0099999998 && c->curvature * v109 < 0.0 && !c->keys.brake && !c->keys.change_down) {
|
|
c->turn_speed = 0.0;
|
|
}
|
|
v135 = sqrt(v108 * v108 + v98 * v98) / 2.0;
|
|
if (v135 > 0.000099999997) {
|
|
v108 = v108 / (v135 * 2.0);
|
|
v98 = v98 / (v135 * 2.0);
|
|
}
|
|
maxfl = sqrt(force[2]) * c->mu[1] * (fl_oil_factor * v116) * mat_list[c->material_index[2]].tyre_road_friction;
|
|
maxfr = sqrt(force[3]) * c->mu[1] * (fr_oil_factor * v116) * mat_list[c->material_index[3]].tyre_road_friction;
|
|
c->max_force_front = maxfr + maxfl;
|
|
force[2] = v135;
|
|
force[3] = v135;
|
|
v72 = (v135 > maxfl) + 2 * (v135 > maxfr);
|
|
switch (v72) {
|
|
case 1:
|
|
force[2] = c->freduction * maxfl;
|
|
force[3] = v135 - force[2] + force[3];
|
|
if (force[3] > maxfr) {
|
|
if (maxfr > 0.1) {
|
|
pV = (force[3] - maxfr) / maxfr;
|
|
if (&gProgram_state.current_car == c) {
|
|
v75 = 20.0;
|
|
} else {
|
|
v75 = 60.0;
|
|
}
|
|
if (v75 <= pV) {
|
|
c->new_skidding |= 8u;
|
|
}
|
|
SkidNoise(c, 3, pV, c->material_index[3]);
|
|
}
|
|
force[3] = c->freduction * maxfr;
|
|
c->wheel_slip |= 1u;
|
|
}
|
|
break;
|
|
case 2:
|
|
force[3] = c->freduction * maxfr;
|
|
force[2] = v135 - force[3] + force[2];
|
|
if (force[2] > maxfl) {
|
|
if (maxfl > 0.1) {
|
|
pV = (force[2] - maxfl) / maxfl;
|
|
if (&gProgram_state.current_car == c) {
|
|
v74 = 20.0;
|
|
} else {
|
|
v74 = 60.0;
|
|
}
|
|
if (v74 <= pV) {
|
|
c->new_skidding |= 4u;
|
|
}
|
|
SkidNoise(c, 2, pV, c->material_index[2]);
|
|
}
|
|
force[2] = c->freduction * maxfl;
|
|
c->wheel_slip |= 1u;
|
|
}
|
|
break;
|
|
case 3:
|
|
force[2] = c->freduction * maxfl;
|
|
force[3] = c->freduction * maxfr;
|
|
c->wheel_slip |= 1u;
|
|
pV = (v135 * 2.0 - maxfl - maxfr) / (maxfr + maxfl);
|
|
if (&gProgram_state.current_car == c) {
|
|
v76 = 20.0;
|
|
} else {
|
|
v76 = 60.0;
|
|
}
|
|
if (v76 <= pV) {
|
|
if (maxfl > 0.1) {
|
|
c->new_skidding |= 4u;
|
|
}
|
|
if (maxfr > 0.1) {
|
|
c->new_skidding |= 8u;
|
|
}
|
|
}
|
|
if (IRandomBetween(0, 1)) {
|
|
if (maxfl > 0.1) {
|
|
SkidNoise(c, 2, pV, c->material_index[2]);
|
|
}
|
|
} else if (maxfr > 0.1) {
|
|
SkidNoise(c, 3, pV, c->material_index[3]);
|
|
}
|
|
break;
|
|
}
|
|
BrVector3Scale(&v136, &rightplane, v99);
|
|
BrVector3Scale(&a, &v103, v109);
|
|
BrVector3Accumulate(&v136, &a);
|
|
BrVector3Scale(&v123, &rightplane, v98);
|
|
BrVector3Scale(&a, &v103, v108);
|
|
BrVector3Accumulate(&v123, &a);
|
|
|
|
rightplane = c->wpos[0];
|
|
rightplane.v[1] = rightplane.v[1] - c->oldd[0];
|
|
BrVector3Sub(&rightplane, &rightplane, &c->cmpos);
|
|
BrVector3Scale(&b, &v136, force[0]);
|
|
BrVector3Accumulate(&B, &b);
|
|
BrVector3Cross(&a, &rightplane, &b);
|
|
BrVector3Accumulate(&f, &a);
|
|
|
|
rightplane = c->wpos[1];
|
|
rightplane.v[1] = rightplane.v[1] - c->oldd[1];
|
|
BrVector3Sub(&rightplane, &rightplane, &c->cmpos);
|
|
BrVector3Scale(&b, &v136, force[1]);
|
|
BrVector3Accumulate(&B, &b);
|
|
BrVector3Cross(&a, &rightplane, &b);
|
|
BrVector3Accumulate(&f, &a);
|
|
|
|
rightplane = c->wpos[2];
|
|
rightplane.v[1] = rightplane.v[1] - c->oldd[2];
|
|
BrVector3Sub(&rightplane, &rightplane, &c->cmpos);
|
|
BrVector3Scale(&b, &v123, force[2]);
|
|
BrVector3Accumulate(&B, &b);
|
|
BrVector3Cross(&a, &rightplane, &b);
|
|
BrVector3Accumulate(&f, &a);
|
|
|
|
rightplane = c->wpos[3];
|
|
rightplane.v[1] = rightplane.v[1] - c->oldd[3];
|
|
BrVector3Sub(&rightplane, &rightplane, &c->cmpos);
|
|
BrVector3Scale(&b, &v123, force[3]);
|
|
BrVector3Accumulate(&B, &b);
|
|
BrVector3Cross(&a, &rightplane, &b);
|
|
BrVector3Accumulate(&f, &a);
|
|
|
|
} else {
|
|
c->max_force_front = 0.0;
|
|
c->max_force_rear = 0.0;
|
|
StopSkid(c);
|
|
}
|
|
c->number_of_wheels_on_ground = normnum;
|
|
BrMatrix34ApplyV(&b, &B, mat);
|
|
BrVector3Scale(&rightplane, &f, dt);
|
|
ApplyTorque(c, &rightplane);
|
|
BrVector3Scale(&rightplane, &b, dt / c->M);
|
|
BrVector3Accumulate(&c->v, &rightplane);
|
|
if (c->speed < 0.000099999997
|
|
&& ((!c->keys.acc && c->joystick.acc <= 0) || !c->gear)
|
|
&& !c->keys.dec
|
|
&& c->joystick.dec <= 0
|
|
&& c->bounce_rate == 0.0
|
|
&& BrVector3Length(&c->omega) < 0.05) {
|
|
if (vol) {
|
|
v73 = c->driver > eDriver_non_car && c->underwater_ability ? 1.0 - (1.0 - vol->gravity_multiplier) * 0.6 : vol->gravity_multiplier;
|
|
friction_number = BrVector3Length(&b) / v73 / gGravity_multiplier;
|
|
} else {
|
|
friction_number = BrVector3Length(&b);
|
|
}
|
|
if (c->M > friction_number || (c->keys.brake && normnum >= 3)) {
|
|
if (stop_timer == 100.0) {
|
|
stop_timer = 0.0;
|
|
}
|
|
if (stop_timer > 0.5) {
|
|
BrVector3SetFloat(&c->v, 0.0, 0.0, 0.0);
|
|
BrVector3SetFloat(&c->omega, 0.0, 0.0, 0.0);
|
|
stop_timer = 0.5;
|
|
}
|
|
}
|
|
}
|
|
stop_timer = dt + stop_timer;
|
|
if (stop_timer > 1.0) {
|
|
stop_timer = 100.0;
|
|
}
|
|
AddDrag(c, dt);
|
|
if (c->driver >= eDriver_net_human) {
|
|
c->acc_force = -(v136.v[2] * force[0]) - v136.v[2] * force[1];
|
|
// LOG_DEBUG("old %f new %f", old, c->acc_force);
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall DoRevs(tCar_spec *c@<EAX>, br_scalar dt)
|
|
void DoRevs(tCar_spec* c, br_scalar dt) {
|
|
br_scalar wheel_spin_force;
|
|
br_scalar ts;
|
|
int revs_increase;
|
|
LOG_TRACE("(%p, %f)", c, dt);
|
|
|
|
ts = -(c->car_master_actor->t.t.mat.m[2][2] * c->v.v[2]
|
|
+ c->car_master_actor->t.t.mat.m[2][1] * c->v.v[1]
|
|
+ c->car_master_actor->t.t.mat.m[2][0] * c->v.v[0]);
|
|
|
|
if (c->gear) {
|
|
c->target_revs = ts / c->speed_revs_ratio / (double)c->gear;
|
|
} else {
|
|
c->target_revs = 0.0;
|
|
}
|
|
if (c->target_revs < 0.0) {
|
|
c->target_revs = 0.0;
|
|
c->gear = 0;
|
|
}
|
|
if (!c->number_of_wheels_on_ground || ((c->wheel_slip & 2) + 1) != 0 || !c->gear) {
|
|
if (c->number_of_wheels_on_ground) {
|
|
wheel_spin_force = c->force_torque_ratio * c->torque - (double)c->gear * c->acc_force;
|
|
} else {
|
|
wheel_spin_force = c->force_torque_ratio * c->torque;
|
|
}
|
|
if (c->gear) {
|
|
if (c->gear < 2 && (c->keys.dec || c->joystick.dec > 0) && fabs(ts) < 1.0 && c->revs > 1000.0) {
|
|
c->gear = -c->gear;
|
|
}
|
|
} else {
|
|
if (c->revs > 1000.0 && !c->keys.brake && (c->keys.acc || c->joystick.acc > 0) && !gCountdown) {
|
|
if (c->keys.backwards) {
|
|
c->gear = -1;
|
|
} else {
|
|
c->gear = 1;
|
|
}
|
|
}
|
|
wheel_spin_force = c->force_torque_ratio * c->torque;
|
|
}
|
|
c->revs = wheel_spin_force / c->force_torque_ratio * dt / 0.0002 + c->revs;
|
|
|
|
if (c->traction_control && wheel_spin_force > 0.0 && c->revs > c->target_revs && c->gear && c->target_revs > 1000.0) {
|
|
c->revs = c->target_revs;
|
|
}
|
|
if (c->revs <= 0.0) {
|
|
c->revs = 0.0;
|
|
}
|
|
}
|
|
if ((c->wheel_slip & 2) == 0 && c->target_revs > 6000.0 && c->revs > 6000.0 && c->gear < c->max_gear && c->gear > 0 && !c->just_changed_gear) {
|
|
c->gear++;
|
|
}
|
|
if (c->gear > 1 && c->target_revs < 3000.0 && !c->just_changed_gear) {
|
|
c->gear--;
|
|
}
|
|
if (c->revs < 200.0 && c->target_revs < 200.0 && c->gear <= 1 && !c->keys.acc && c->joystick.acc <= 0 && !c->just_changed_gear) {
|
|
c->gear = 0;
|
|
}
|
|
if (c->just_changed_gear && c->revs < 6000.0 && c->revs > 200.0 && (c->gear < 2 || c->revs >= 3000.0)) {
|
|
c->just_changed_gear = 0;
|
|
}
|
|
if (c->revs >= 6000.0 && (c->keys.acc || c->joystick.acc > 0)) {
|
|
c->just_changed_gear = 0;
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall ApplyTorque(tCar_spec *c@<EAX>, br_vector3 *tdt@<EDX>)
|
|
void ApplyTorque(tCar_spec* c, br_vector3* tdt) {
|
|
LOG_TRACE("(%p, %p)", c, tdt);
|
|
|
|
c->omega.v[0] = tdt->v[0] / c->I.v[0] + c->omega.v[0];
|
|
c->omega.v[1] = tdt->v[1] / c->I.v[1] + c->omega.v[1];
|
|
c->omega.v[2] = tdt->v[2] / c->I.v[2] + c->omega.v[2];
|
|
}
|
|
|
|
// IDA: void __usercall TranslateCar(tCollision_info *c@<EAX>, br_scalar dt)
|
|
void TranslateCar(tCollision_info* c, br_scalar dt) {
|
|
br_vector3 t;
|
|
LOG_TRACE("(%p, %f)", c, dt);
|
|
|
|
t.v[0] = c->v.v[0] * dt;
|
|
t.v[1] = c->v.v[1] * dt;
|
|
t.v[2] = c->v.v[2] * dt;
|
|
c->car_master_actor->t.t.mat.m[3][0] = c->car_master_actor->t.t.mat.m[3][0] + t.v[0];
|
|
c->car_master_actor->t.t.mat.m[3][1] = c->car_master_actor->t.t.mat.m[3][1] + t.v[1];
|
|
c->car_master_actor->t.t.mat.m[3][2] = c->car_master_actor->t.t.mat.m[3][2] + t.v[2];
|
|
}
|
|
|
|
// IDA: int __usercall CollCheck@<EAX>(tCollision_info *c@<EAX>, br_scalar dt)
|
|
int CollCheck(tCollision_info* c, br_scalar dt) {
|
|
br_vector3 a;
|
|
br_vector3 a1;
|
|
br_vector3 aa;
|
|
br_vector3 bb;
|
|
br_vector3 cc;
|
|
br_vector3 pos;
|
|
br_vector3 r[8];
|
|
br_vector3 norm;
|
|
br_vector3 n[8];
|
|
br_vector3 dir;
|
|
br_vector3 tv;
|
|
br_vector3 tv2;
|
|
br_vector3 tau[4];
|
|
br_vector3 old_val;
|
|
br_vector3 ftau;
|
|
br_vector3 max_friction;
|
|
br_vector3 vel;
|
|
br_vector3 p_vel;
|
|
br_vector3 normal_force;
|
|
br_vector3 friction_force;
|
|
br_scalar d[4];
|
|
br_scalar f[4];
|
|
br_scalar total_force;
|
|
br_scalar point_vel;
|
|
br_scalar batwick_length;
|
|
br_matrix4 M;
|
|
br_scalar dist;
|
|
br_scalar min_d;
|
|
br_scalar ts;
|
|
br_scalar ts2;
|
|
br_scalar v_diff;
|
|
br_matrix34* mat;
|
|
br_matrix34* oldmat;
|
|
br_matrix34 mat_to_oldmat;
|
|
br_matrix34 oldmat_to_mat;
|
|
br_matrix34 tm;
|
|
int collision;
|
|
br_bounds bnds;
|
|
tFace_ref* f_ref;
|
|
int i;
|
|
int j;
|
|
int l;
|
|
int k;
|
|
int material;
|
|
int noise_defeat;
|
|
static int oldk;
|
|
br_scalar min;
|
|
br_scalar max;
|
|
br_vector3 edges[3];
|
|
br_vector3 corner;
|
|
br_vector3 test_dir;
|
|
br_scalar min_acc;
|
|
br_scalar max_acc;
|
|
br_matrix34 message_mat;
|
|
LOG_TRACE("(%p, %f)", c, dt);
|
|
|
|
tCar_spec* car_spec; // added for readability
|
|
|
|
// v34 = 0;
|
|
// v35 = 0;
|
|
// v36 = 0x3F800000;
|
|
// v48 = 0x3F800347;
|
|
car_spec = (tCar_spec*)c;
|
|
mat = &c->car_master_actor->t.t.mat;
|
|
oldmat = &c->oldmat;
|
|
k = 0;
|
|
gMaterial_index = 0;
|
|
if (c->dt >= 0.0 && gNet_mode == eNet_mode_host) {
|
|
oldmat = &message_mat;
|
|
GetExpandedMatrix(&message_mat, &c->message.mat);
|
|
}
|
|
if (dt < 0.0) {
|
|
mat = oldmat;
|
|
}
|
|
BrMatrix34LPInverse(&tm, mat);
|
|
BrMatrix34Mul(&oldmat_to_mat, oldmat, &tm);
|
|
|
|
oldmat_to_mat.m[3][0] = oldmat_to_mat.m[3][0] / WORLD_SCALE;
|
|
oldmat_to_mat.m[3][1] = oldmat_to_mat.m[3][1] / WORLD_SCALE;
|
|
oldmat_to_mat.m[3][2] = oldmat_to_mat.m[3][2] / WORLD_SCALE;
|
|
GetNewBoundingBox(&bnds, &c->bounds[2], &oldmat_to_mat);
|
|
for (i = 0; i < 3; ++i) {
|
|
if (c->bounds[2].min.v[i] < bnds.min.v[i]) {
|
|
bnds.min.v[i] = c->bounds[2].min.v[i];
|
|
}
|
|
if (c->bounds[2].max.v[i] > bnds.max.v[i]) {
|
|
bnds.max.v[i] = c->bounds[2].max.v[i];
|
|
}
|
|
}
|
|
a1.v[0] = mat->m[3][0] / WORLD_SCALE;
|
|
a1.v[1] = mat->m[3][1] / WORLD_SCALE;
|
|
a1.v[2] = mat->m[3][2] / WORLD_SCALE;
|
|
BrMatrix34ApplyV(&aa, &bnds.min, mat);
|
|
BrVector3Accumulate(&aa, &a1);
|
|
for (j = 0; j < 3; ++j) {
|
|
edges[j].v[0] = (bnds.max.v[j] - bnds.min.v[j]) * mat->m[j][0];
|
|
edges[j].v[1] = (bnds.max.v[j] - bnds.min.v[j]) * mat->m[j][1];
|
|
edges[j].v[2] = (bnds.max.v[j] - bnds.min.v[j]) * mat->m[j][2];
|
|
}
|
|
i = 0;
|
|
f_ref = &gFace_list__car[c->box_face_start];
|
|
while (c->box_face_end - c->box_face_start > i && i < 50) {
|
|
BrVector3Sub(&bb, &aa, &f_ref->v[0]);
|
|
max = BrVector3Dot(&bb, &f_ref->normal);
|
|
min = max;
|
|
for (j = 0; j < 3; ++j) {
|
|
ts = BrVector3Dot(&edges[j], &f_ref->normal);
|
|
if (ts >= 0) {
|
|
max = max + ts;
|
|
} else {
|
|
min = min + ts;
|
|
}
|
|
}
|
|
if ((max <= 0.001 || min <= 0.001) && (max >= -0.001 || min >= -0.001)) {
|
|
f_ref->flags &= ~0x80u;
|
|
k++;
|
|
} else {
|
|
f_ref->flags |= 0x80u;
|
|
}
|
|
i++;
|
|
f_ref++;
|
|
}
|
|
if (!k) {
|
|
return 0;
|
|
}
|
|
k = 0;
|
|
BrMatrix34LPInverse(&tm, oldmat);
|
|
BrMatrix34Mul(&mat_to_oldmat, mat, &tm);
|
|
gEliminate_faces = 1;
|
|
for (i = 0; i < 8 + c->extra_point_num; i++) {
|
|
if (i >= 8) {
|
|
tv = c->extra_points[i - 8];
|
|
} else {
|
|
tv.v[0] = ((i & 2) == 0) * c->bounds[1].min.v[0] + ((i & 2) >> 1) * c->bounds[1].max.v[0];
|
|
tv.v[1] = ((i & 1) == 0) * c->bounds[1].min.v[1] + (i & 1) * c->bounds[1].max.v[1];
|
|
tv.v[2] = ((i & 4) == 0) * c->bounds[1].max.v[2] + ((i & 4) >> 2) * c->bounds[1].min.v[2];
|
|
}
|
|
BrMatrix34ApplyP(&dir, &tv, mat);
|
|
if (dt >= 0.0) {
|
|
BrMatrix34ApplyP(&a, &tv, oldmat);
|
|
} else {
|
|
BrVector3Scale(&a, &c->pos, WORLD_SCALE);
|
|
}
|
|
BrVector3Sub(&dir, &dir, &a);
|
|
BrVector3Normalise(&normal_force, &dir);
|
|
BrVector3Scale(&normal_force, &normal_force, 0.0072463769);
|
|
BrVector3Accumulate(&dir, &normal_force);
|
|
material = FindFloorInBoxM2(&a, &dir, &norm, &dist, c);
|
|
if (dist >= 0.0 && dist < 1.0001) {
|
|
BrVector3Scale(&cc, &c->pos, WORLD_SCALE);
|
|
BrVector3Sub(&cc, &cc, &a);
|
|
FindFloorInBoxM(&a, &cc, &bb, &ts, c);
|
|
if (i < 8 || ts > 1.0) {
|
|
BrMatrix34TApplyV(&a, &norm, oldmat);
|
|
AddCollPoint(dist, &tv, &a, r, n, &dir, k, c);
|
|
k++;
|
|
if (!gMaterial_index) {
|
|
gMaterial_index = material;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
gEliminate_faces = 0;
|
|
if (k < 1) {
|
|
k += BoxFaceIntersect(&c->bounds[1], mat, &mat_to_oldmat, &r[k], &n[k], &d[k], 8 - k, c);
|
|
}
|
|
if (k > 4) {
|
|
k = 4;
|
|
}
|
|
for (i = 0; i < k; i++) {
|
|
if (fabs(r[i].v[1]) + fabs(r[i].v[2]) + fabs(r[i].v[0]) > 500.0) {
|
|
for (j = i + 1; j < k; j++) {
|
|
if (fabs(r[j].v[1]) + fabs(r[j].v[2]) + fabs(r[j].v[0]) < 500.0) {
|
|
r[i] = r[j];
|
|
n[i] = n[j];
|
|
i++;
|
|
}
|
|
}
|
|
k = i;
|
|
break;
|
|
}
|
|
}
|
|
if (dt >= 0.0) {
|
|
if (k > 0 && c->collision_flag && k < 4
|
|
&& (fabs(r[0].v[0] - c->old_point.v[0]) > 0.05
|
|
|| fabs(r[0].v[1] - c->old_point.v[1]) > 0.05
|
|
|| fabs(r[0].v[2] - c->old_point.v[2]) > 0.05)) {
|
|
r[k] = c->old_point;
|
|
n[k] = c->old_norm;
|
|
k++;
|
|
}
|
|
if (k > 0) {
|
|
c->old_point = r[0];
|
|
c->old_norm = n[0];
|
|
BrMatrix34Copy(mat, oldmat);
|
|
c->omega = c->oldomega;
|
|
BrMatrix34TApplyV(&c->velocity_car_space, &c->v, mat);
|
|
memset(&norm, 0, sizeof(norm));
|
|
collision = 0;
|
|
for (i = 0; i < k; i++) {
|
|
BrVector3Cross(&tau[i], &r[i], &n[i]);
|
|
tau[i].v[0] = tau[i].v[0] / c->I.v[0];
|
|
tau[i].v[1] = tau[i].v[1] / c->I.v[1];
|
|
tau[i].v[2] = tau[i].v[2] / c->I.v[2];
|
|
BrVector3Cross(&normal_force, &c->omega, &r[i]);
|
|
BrVector3Accumulate(&normal_force, &c->velocity_car_space);
|
|
d[i] = -(BrVector3Dot(&n[i], &normal_force));
|
|
BrVector3Add(&normal_force, &r[i], &c->cmpos);
|
|
BrMatrix34ApplyP(&dir, &normal_force, &mat_to_oldmat);
|
|
BrVector3Sub(&dir, &dir, &normal_force);
|
|
ts = -(BrVector3Dot(&n[i], &dir) / dt);
|
|
if (ts > d[i]) {
|
|
d[i] = ts;
|
|
}
|
|
if (d[i] > 0.0) {
|
|
collision = 1;
|
|
}
|
|
}
|
|
if (!collision) {
|
|
d[0] = 0.5;
|
|
}
|
|
for (i = 0; k > i; ++i) {
|
|
for (j = 0; k > j; ++j) {
|
|
BrVector3Cross(&normal_force, &tau[j], &r[i]);
|
|
BrVector3InvScale(&norm, &n[j], c->M);
|
|
BrVector3Accumulate(&normal_force, &norm);
|
|
M.m[i][j] = BrVector3Dot(&n[i], &normal_force);
|
|
}
|
|
}
|
|
switch (k) {
|
|
case 1:
|
|
ts = SinglePointColl(f, &M, d);
|
|
break;
|
|
case 2:
|
|
ts = TwoPointColl(f, &M, d, tau, n);
|
|
break;
|
|
case 3:
|
|
d[3] = 0.0;
|
|
ts = ThreePointCollRec(f, &M, d, tau, n, c);
|
|
break;
|
|
case 4:
|
|
ts = FourPointColl(f, &M, d, tau, n, c);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (k > 3) {
|
|
k = 3;
|
|
}
|
|
// if (f[0] > 10.0 || f[1] > 10.0 || f[2] > 10.0) {
|
|
// v31 = 0;
|
|
// }
|
|
if (fabs(ts) <= 0.000001) {
|
|
BrVector3Set(&c->v, 0, 0, 0);
|
|
BrVector3Set(&c->omega, 0, 0, 0);
|
|
BrVector3Set(&c->oldomega, 0, 0, 0);
|
|
return k;
|
|
}
|
|
BrVector3Set(&p_vel, 0, 0, 0);
|
|
BrVector3Set(&dir, 0, 0, 0);
|
|
BrVector3Set(&friction_force, 0, 0, 0);
|
|
total_force = 0.0;
|
|
for (i = 0; k > i; ++i) {
|
|
if (f[i] < 0.001) {
|
|
f[i] = 0.001;
|
|
}
|
|
f[i] = f[i] * 1.001;
|
|
BrVector3Scale(&tau[i], &tau[i], f[i]);
|
|
BrVector3Add(&c->omega, &tau[i], &c->omega);
|
|
f[i] = f[i] / c->M;
|
|
BrVector3Scale(&n[i], &n[i], f[i]);
|
|
BrVector3Accumulate(&p_vel, &n[i]);
|
|
BrVector3Add(&bb, &r[i], &c->cmpos);
|
|
BrVector3Scale(&bb, &bb, f[i]);
|
|
BrVector3Accumulate(&dir, &bb);
|
|
total_force = f[i] + total_force;
|
|
}
|
|
if (gPinball_factor != 0.0) {
|
|
BrVector3Scale(&p_vel, &p_vel, gPinball_factor);
|
|
point_vel = BrVector3LengthSquared(&p_vel);
|
|
if (point_vel > 10.0) {
|
|
noise_defeat = 1;
|
|
if (c->driver == eDriver_local_human) {
|
|
DRS3StartSound(gIndexed_outlets[1], 9011);
|
|
} else {
|
|
DRS3StartSound3D(gIndexed_outlets[1], 9011, &c->pos, &gZero_v__car, 1, 255, 0x10000, 0x10000);
|
|
}
|
|
if (point_vel > 10000.0) {
|
|
BrVector3Normalise(&p_vel, &p_vel);
|
|
BrVector3Scale(&p_vel, &p_vel, 100);
|
|
}
|
|
}
|
|
}
|
|
BrVector3Accumulate(&c->velocity_car_space, &p_vel);
|
|
BrVector3InvScale(&dir, &dir, total_force);
|
|
BrVector3Cross(&tv, &c->omega, &dir);
|
|
BrVector3Accumulate(&tv, &c->velocity_car_space);
|
|
batwick_length = BrVector3Length(&tv);
|
|
if (!c->collision_flag || (c->collision_flag == 1 && oldk < k)) {
|
|
for (i = 0; k > i; ++i) {
|
|
BrVector3Cross(&vel, &c->omega, &r[i]);
|
|
BrVector3Accumulate(&vel, &c->velocity_car_space);
|
|
AddFriction(c, &vel, &n[i], &r[i], f[i], &max_friction);
|
|
BrVector3Accumulate(&friction_force, &max_friction);
|
|
BrVector3Accumulate(&c->velocity_car_space, &max_friction);
|
|
}
|
|
}
|
|
oldk = k;
|
|
BrMatrix34ApplyP(&pos, &dir, &c->car_master_actor->t.t.mat);
|
|
BrVector3InvScale(&pos, &pos, WORLD_SCALE);
|
|
noise_defeat = 0;
|
|
BrVector3Add(&normal_force, &friction_force, &p_vel);
|
|
BrMatrix34ApplyV(&norm, &normal_force, mat);
|
|
min = dt * 90.0 / 10.0;
|
|
max = dt * 110.0 / 10.0;
|
|
if (c->last_special_volume) {
|
|
min = c->last_special_volume->gravity_multiplier * min;
|
|
max = c->last_special_volume->gravity_multiplier * max;
|
|
}
|
|
if (c->velocity_car_space.v[2] * c->velocity_car_space.v[2] + c->velocity_car_space.v[1] * c->velocity_car_space.v[1] + c->velocity_car_space.v[0] * c->velocity_car_space.v[0] < 0.050000001
|
|
&& total_force * 0.1 > c->omega.v[2] * tv.v[2] + c->omega.v[1] * tv.v[1] + c->omega.v[0] * tv.v[0]
|
|
&& k >= 3
|
|
&& norm.v[1] > min
|
|
&& norm.v[1] < max) {
|
|
if (c->driver <= eDriver_non_car || fabs(normal_force.v[2]) <= total_force * 0.89999998) {
|
|
BrVector3Set(&c->v, 0, 0, 0);
|
|
BrVector3Set(&norm, 0, 0, 0);
|
|
BrVector3Set(&normal_force, 0, 0, 0);
|
|
BrVector3Set(&c->omega, 0, 0, 0);
|
|
BrVector3Set(&c->oldomega, 0, 0, 0);
|
|
if (c->driver <= eDriver_non_car || car_spec->max_force_rear == 0.0) {
|
|
if (c->driver <= eDriver_non_car) {
|
|
PipeSingleNonCar(c);
|
|
}
|
|
c->doing_nothing_flag = 1;
|
|
}
|
|
} else {
|
|
BrVector3SetFloat(&tv2, 0.0, -1.0, 0.0);
|
|
bb.v[0] = mat->m[1][2] * tv2.v[1] - mat->m[1][1] * tv2.v[2];
|
|
bb.v[1] = mat->m[1][0] * tv2.v[2] - mat->m[1][2] * tv2.v[0];
|
|
bb.v[2] = mat->m[1][1] * tv2.v[0] - mat->m[1][0] * tv2.v[1];
|
|
if (BrVector3Dot(&bb, (br_vector3*)&mat->m[0][1]) <= 0.0) {
|
|
c->omega.v[0] = -0.5;
|
|
} else {
|
|
c->omega.v[0] = 0.5;
|
|
}
|
|
}
|
|
}
|
|
BrVector3Accumulate(&c->v, &norm);
|
|
if (c->driver >= eDriver_net_human) {
|
|
BrVector3Scale(&normal_force, &normal_force, gDefensive_powerup_factor[car_spec->power_up_levels[0]]);
|
|
}
|
|
if (c->driver < eDriver_net_human) {
|
|
BrVector3Scale(&normal_force, &normal_force, 0.0099999998);
|
|
} else {
|
|
BrVector3Scale(&normal_force, &normal_force, 0.75);
|
|
}
|
|
v_diff = (car_spec->pre_car_col_velocity.v[1] - c->v.v[1]) * gDefensive_powerup_factor[car_spec->power_up_levels[0]];
|
|
if (car_spec->invulnerable
|
|
|| (c->driver < eDriver_net_human && (c->driver != eDriver_oppo || PointOutOfSight(&c->pos, 150.0)))
|
|
|| (v_diff >= -20.0)
|
|
|| car_spec->number_of_wheels_on_ground >= 3) {
|
|
CrushAndDamageCar(car_spec, &dir, &normal_force, NULL);
|
|
} else {
|
|
if (c->driver == eDriver_oppo && c->index == 4 && v_diff < -40.0) {
|
|
KnackerThisCar(car_spec);
|
|
StealCar(car_spec);
|
|
v_diff = v_diff * 5.0;
|
|
}
|
|
for (i = 0; i < ((tCar_spec*)c)->car_actor_count; i++) {
|
|
ts2 = (v_diff + 20.0) * -0.01;
|
|
TotallySpamTheModel(car_spec, i, car_spec->car_model_actors[i].actor, &car_spec->car_model_actors[i].crush_data, ts2);
|
|
}
|
|
for (i = 0; i < 12; i++) {
|
|
DamageUnit(car_spec, i, IRandomPosNeg(5) + (v_diff + 20.0) * -1.5);
|
|
}
|
|
}
|
|
if (!noise_defeat) {
|
|
CrashNoise(&norm, &pos, gMaterial_index);
|
|
ScrapeNoise(batwick_length, &pos, gMaterial_index);
|
|
}
|
|
BrVector3InvScale(&tv, &tv, WORLD_SCALE);
|
|
BrMatrix34ApplyV(&bb, &tv, &c->car_master_actor->t.t.mat);
|
|
BrMatrix34ApplyV(&norm, &p_vel, &c->car_master_actor->t.t.mat);
|
|
CreateSparks(&pos, &bb, &norm, gCurrent_race.material_modifiers[gMaterial_index].sparkiness, car_spec);
|
|
}
|
|
return k;
|
|
} else {
|
|
if (k) {
|
|
c->old_point = r[0];
|
|
c->old_norm = n[0];
|
|
}
|
|
return k;
|
|
}
|
|
}
|
|
|
|
// IDA: br_scalar __usercall AddFriction@<ST0>(tCollision_info *c@<EAX>, br_vector3 *vel@<EDX>, br_vector3 *normal_force@<EBX>, br_vector3 *pos@<ECX>, br_scalar total_force, br_vector3 *max_friction)
|
|
br_scalar AddFriction(tCollision_info* c, br_vector3* vel, br_vector3* normal_force, br_vector3* pos, br_scalar total_force, br_vector3* max_friction) {
|
|
br_vector3 norm;
|
|
br_vector3 tv;
|
|
br_vector3 ftau;
|
|
br_scalar ts;
|
|
br_scalar point_vel;
|
|
LOG_TRACE("(%p, %p, %p, %p, %f, %p)", c, vel, normal_force, pos, total_force, max_friction);
|
|
|
|
ts = (normal_force->v[1] * vel->v[1] + normal_force->v[2] * vel->v[2] + normal_force->v[0] * vel->v[0])
|
|
/ (normal_force->v[1] * normal_force->v[1]
|
|
+ normal_force->v[2] * normal_force->v[2]
|
|
+ normal_force->v[0] * normal_force->v[0]);
|
|
tv.v[0] = normal_force->v[0] * ts;
|
|
tv.v[1] = normal_force->v[1] * ts;
|
|
tv.v[2] = normal_force->v[2] * ts;
|
|
vel->v[0] = vel->v[0] - tv.v[0];
|
|
vel->v[1] = vel->v[1] - tv.v[1];
|
|
vel->v[2] = vel->v[2] - tv.v[2];
|
|
point_vel = total_force * 0.34999999 * gCurrent_race.material_modifiers[gMaterial_index].car_wall_friction;
|
|
ts = sqrt(vel->v[1] * vel->v[1] + vel->v[2] * vel->v[2] + vel->v[0] * vel->v[0]);
|
|
if (ts < 0.000099999997) {
|
|
max_friction->v[0] = 0.0;
|
|
max_friction->v[1] = 0.0;
|
|
max_friction->v[2] = 0.0;
|
|
return 0.0;
|
|
}
|
|
ts = 1.0 / -ts;
|
|
max_friction->v[0] = vel->v[0] * ts;
|
|
max_friction->v[1] = vel->v[1] * ts;
|
|
max_friction->v[2] = vel->v[2] * ts;
|
|
ftau.v[0] = pos->v[1] * max_friction->v[2] - pos->v[2] * max_friction->v[1];
|
|
ftau.v[1] = pos->v[2] * max_friction->v[0] - pos->v[0] * max_friction->v[2];
|
|
ftau.v[2] = pos->v[0] * max_friction->v[1] - pos->v[1] * max_friction->v[0];
|
|
ftau.v[0] = c->M * ftau.v[0];
|
|
ftau.v[1] = c->M * ftau.v[1];
|
|
ftau.v[2] = c->M * ftau.v[2];
|
|
ftau.v[0] = ftau.v[0] / c->I.v[0];
|
|
ftau.v[1] = ftau.v[1] / c->I.v[1];
|
|
ftau.v[2] = ftau.v[2] / c->I.v[2];
|
|
ts = 1.0 / c->M;
|
|
norm.v[0] = pos->v[2] * ftau.v[1] - pos->v[1] * ftau.v[2];
|
|
norm.v[1] = pos->v[0] * ftau.v[2] - pos->v[2] * ftau.v[0];
|
|
norm.v[2] = pos->v[1] * ftau.v[0] - pos->v[0] * ftau.v[1];
|
|
ts = max_friction->v[0] * norm.v[0] + max_friction->v[1] * norm.v[1] + max_friction->v[2] * norm.v[2] + ts;
|
|
if (fabs(ts) <= 0.000099999997) {
|
|
ts = 0.0;
|
|
} else {
|
|
ts = -((max_friction->v[1] * vel->v[1] + max_friction->v[2] * vel->v[2] + max_friction->v[0] * vel->v[0]) / ts);
|
|
}
|
|
if (ts > point_vel) {
|
|
ts = point_vel;
|
|
}
|
|
max_friction->v[0] = max_friction->v[0] * ts;
|
|
max_friction->v[1] = max_friction->v[1] * ts;
|
|
max_friction->v[2] = max_friction->v[2] * ts;
|
|
tv.v[0] = pos->v[1] * max_friction->v[2] - pos->v[2] * max_friction->v[1];
|
|
tv.v[1] = pos->v[2] * max_friction->v[0] - pos->v[0] * max_friction->v[2];
|
|
tv.v[2] = pos->v[0] * max_friction->v[1] - pos->v[1] * max_friction->v[0];
|
|
tv.v[0] = c->M * tv.v[0];
|
|
tv.v[1] = c->M * tv.v[1];
|
|
tv.v[2] = c->M * tv.v[2];
|
|
ApplyTorque((tCar_spec*)c, &tv);
|
|
return point_vel;
|
|
}
|
|
|
|
// IDA: void __usercall AddFrictionCarToCar(tCollision_info *car1@<EAX>, tCollision_info *car2@<EDX>, br_vector3 *vel1@<EBX>, br_vector3 *vel2@<ECX>, br_vector3 *normal_force1, br_vector3 *pos1, br_vector3 *pos2, br_scalar total_force, br_vector3 *max_friction)
|
|
void AddFrictionCarToCar(tCollision_info* car1, tCollision_info* car2, br_vector3* vel1, br_vector3* vel2, br_vector3* normal_force1, br_vector3* pos1, br_vector3* pos2, br_scalar total_force, br_vector3* max_friction) {
|
|
br_vector3 v_diff1;
|
|
br_vector3 v_diff2;
|
|
br_vector3 tau1;
|
|
br_vector3 tau2;
|
|
br_vector3 tv;
|
|
br_vector3 tv2;
|
|
br_vector3 vel2_in_frame_1;
|
|
br_scalar ts;
|
|
br_scalar ts2;
|
|
br_scalar v_diff;
|
|
br_scalar stopping_impulse;
|
|
br_scalar total_friction;
|
|
int i;
|
|
LOG_TRACE("(%p, %p, %p, %p, %p, %p, %p, %f, %p)", car1, car2, vel1, vel2, normal_force1, pos1, pos2, total_force, max_friction);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __cdecl ScrapeNoise(br_scalar vel, br_vector3 *position, int material)
|
|
void ScrapeNoise(br_scalar vel, br_vector3* position, int material) {
|
|
tS3_volume vol;
|
|
static tS3_sound_tag scrape_tag;
|
|
static tS3_volume last_scrape_vol;
|
|
br_vector3 velocity;
|
|
br_vector3 position_in_br;
|
|
LOG_TRACE("(%f, %p, %d)", vel, position, material);
|
|
|
|
vol = vel * 7.f;
|
|
if (gCurrent_race.material_modifiers[material].scrape_noise_index != -1) {
|
|
if (scrape_tag == 0 || (!DRS3SoundStillPlaying(scrape_tag) && vol > 30)) {
|
|
BrVector3Set(&velocity, 0.f, 0.f, 0.f);
|
|
scrape_tag = DRS3StartSound3D(gIndexed_outlets[1],
|
|
gMetal_scrape_sound_id__car[IRandomBetween(0, COUNT_OF(gMetal_scrape_sound_id__car) - 1)],
|
|
position, &velocity, 1, vol, IRandomBetween(49152, 81920), 0x10000);
|
|
last_scrape_vol = vol;
|
|
} else if (last_scrape_vol < vol) {
|
|
DRS3ChangeVolume(scrape_tag, vol);
|
|
last_scrape_vol = vol;
|
|
}
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall SkidNoise(tCar_spec *pC@<EAX>, int pWheel_num@<EDX>, br_scalar pV, int material)
|
|
void SkidNoise(tCar_spec* pC, int pWheel_num, br_scalar pV, int material) {
|
|
br_vector3 pos;
|
|
br_vector3 world_pos;
|
|
br_vector3 wv;
|
|
br_vector3 wvw;
|
|
br_scalar ts;
|
|
static tS3_volume last_skid_vol[2];
|
|
int i;
|
|
LOG_TRACE("(%p, %d, %f, %d)", pC, pWheel_num, pV, material);
|
|
|
|
i = IRandomBetween(0, 1);
|
|
if (gCurrent_race.material_modifiers[material].tyre_noise_index == -1) {
|
|
return;
|
|
}
|
|
if (IRandomBetween(0, 4) != 0) {
|
|
return;
|
|
}
|
|
|
|
last_skid_vol[i] = pV * 10.0;
|
|
if ((pWheel_num & 1) != 0) {
|
|
pos.v[0] = pC->bounds[1].max.v[0];
|
|
} else {
|
|
pos.v[0] = pC->bounds[1].min.v[0];
|
|
}
|
|
pos.v[1] = pC->wpos[pWheel_num].v[1] - pC->oldd[pWheel_num];
|
|
pos.v[2] = pC->wpos[pWheel_num].v[2];
|
|
BrMatrix34ApplyP(&world_pos, &pos, &pC->car_master_actor->t.t.mat);
|
|
BrVector3InvScale(&world_pos, &world_pos, WORLD_SCALE);
|
|
if (!DRS3SoundStillPlaying(gSkid_tag[i]) || (pC->driver == eDriver_local_human && gLast_car_to_skid[i] != pC)) {
|
|
gSkid_tag[i] = DRS3StartSound3D(
|
|
gIndexed_outlets[1],
|
|
IRandomBetween(0, 4) + 9000,
|
|
&world_pos,
|
|
&pC->velocity_bu_per_sec,
|
|
1,
|
|
last_skid_vol[i],
|
|
IRandomBetween(49152, 81920),
|
|
0x10000);
|
|
gLast_car_to_skid[i] = pC;
|
|
}
|
|
if (gCurrent_race.material_modifiers[material].smoke_type == 1) {
|
|
BrVector3Cross(&wv, &pC->omega, &pos);
|
|
BrVector3Add(&wv, &wv, &pC->velocity_car_space);
|
|
ts = -(BrVector3Dot(&wv, &pC->road_normal));
|
|
BrVector3Scale(&wvw, &pC->road_normal, ts);
|
|
BrVector3Add(&wv, &wv, &wvw);
|
|
BrMatrix34ApplyV(&wvw, &wv, &pC->car_master_actor->t.t.mat);
|
|
CreatePuffOfSmoke(&world_pos, &wvw, pV / 25.0, 1.0, 4, pC);
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall StopSkid(tCar_spec *pC@<EAX>)
|
|
void StopSkid(tCar_spec* pC) {
|
|
LOG_TRACE("(%p)", pC);
|
|
|
|
if (gLast_car_to_skid[0] == pC) {
|
|
DRS3StopSound(gSkid_tag[0]);
|
|
}
|
|
if (gLast_car_to_skid[1] == pC) {
|
|
DRS3StopSound(gSkid_tag[1]);
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall CrashNoise(br_vector3 *pForce@<EAX>, br_vector3 *position@<EDX>, int material@<EBX>)
|
|
void CrashNoise(br_vector3* pForce, br_vector3* position, int material) {
|
|
static tS3_sound_tag crunch_tag;
|
|
static tS3_volume last_crunch_vol;
|
|
tS3_volume vol;
|
|
br_vector3 velocity;
|
|
LOG_TRACE("(%p, %p, %d)", pForce, position, material);
|
|
|
|
vol = 60.f * BrVector3Length(pForce);
|
|
if (gCurrent_race.material_modifiers[material].crash_noise_index != -1) {
|
|
if (vol >= 256) {
|
|
vol = 255;
|
|
}
|
|
if (crunch_tag == 0 || (!DRS3SoundStillPlaying(crunch_tag) && vol > 30)) {
|
|
last_crunch_vol = vol;
|
|
(void)last_crunch_vol;
|
|
BrVector3Set(&velocity, 0.f, 0.f, 0.f);
|
|
crunch_tag = DRS3StartSound3D(gIndexed_outlets[1],
|
|
gMetal_crunch_sound_id__car[IRandomBetween(0, COUNT_OF(gMetal_crunch_sound_id__car) - 1)],
|
|
position, &velocity, 1, vol, IRandomBetween(49152, 81920), 0x10000);
|
|
}
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall CrushAndDamageCar(tCar_spec *c@<EAX>, br_vector3 *pPosition@<EDX>, br_vector3 *pForce_car_space@<EBX>, tCar_spec *car2@<ECX>)
|
|
void CrushAndDamageCar(tCar_spec* c, br_vector3* pPosition, br_vector3* pForce_car_space, tCar_spec* car2) {
|
|
br_vector3 force;
|
|
br_vector3 force2;
|
|
br_vector3 position;
|
|
br_vector3 pos_w;
|
|
br_vector3 car_to_cam;
|
|
br_vector3 force_for_bodywork;
|
|
br_scalar ts;
|
|
int i;
|
|
br_matrix34 m;
|
|
br_scalar fudge_multiplier;
|
|
LOG_TRACE("(%p, %p, %p, %p)", c, pPosition, pForce_car_space, car2);
|
|
|
|
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>)
|
|
int ExpandBoundingBox(tCar_spec* c) {
|
|
br_scalar min_z;
|
|
br_scalar max_z;
|
|
br_scalar dist;
|
|
br_vector3 tv;
|
|
br_vector3 old_pos;
|
|
int l;
|
|
br_matrix34 mat;
|
|
LOG_TRACE("(%p)", c);
|
|
|
|
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>)
|
|
void CrushBoundingBox(tCar_spec* c, int crush_only) {
|
|
br_vector3 min;
|
|
br_vector3 max;
|
|
int i;
|
|
br_actor* actor;
|
|
LOG_TRACE("(%p, %d)", c, crush_only);
|
|
|
|
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)
|
|
void AddCollPoint(br_scalar dist, br_vector3* p, br_vector3* norm, br_vector3* r, br_vector3* n, br_vector3* dir, int num, tCollision_info* c) {
|
|
static br_scalar d[4];
|
|
int i;
|
|
int furthest;
|
|
LOG_TRACE("(%f, %p, %p, %p, %p, %p, %d, %p)", dist, p, norm, r, n, dir, num, c);
|
|
|
|
if (num < 4) {
|
|
d[num] = dist;
|
|
n[num] = *norm;
|
|
r[num].v[0] = p->v[0] - c->cmpos.v[0];
|
|
r[num].v[1] = p->v[1] - c->cmpos.v[1];
|
|
r[num].v[2] = p->v[2] - c->cmpos.v[2];
|
|
return;
|
|
}
|
|
furthest = 0;
|
|
for (i = 1; i < 4; i++) {
|
|
if (d[furthest] < d[i]) {
|
|
furthest = i;
|
|
}
|
|
}
|
|
if (d[furthest] >= dist) {
|
|
num = furthest;
|
|
d[num] = dist;
|
|
n[num] = *norm;
|
|
r[num].v[0] = p->v[0] - c->cmpos.v[0];
|
|
r[num].v[1] = p->v[1] - c->cmpos.v[1];
|
|
r[num].v[2] = p->v[2] - c->cmpos.v[2];
|
|
}
|
|
}
|
|
|
|
// IDA: br_scalar __usercall SinglePointColl@<ST0>(br_scalar *f@<EAX>, br_matrix4 *m@<EDX>, br_scalar *d@<EBX>)
|
|
br_scalar SinglePointColl(br_scalar* f, br_matrix4* m, br_scalar* d) {
|
|
LOG_TRACE("(%p, %p, %p)", f, m, d);
|
|
|
|
*f = *d / m->m[0][0];
|
|
if (*f < 0.0) {
|
|
*f = 0.0;
|
|
}
|
|
return fabs(m->m[0][0]);
|
|
}
|
|
|
|
// IDA: br_scalar __usercall TwoPointColl@<ST0>(br_scalar *f@<EAX>, br_matrix4 *m@<EDX>, br_scalar *d@<EBX>, br_vector3 *tau@<ECX>, br_vector3 *n)
|
|
br_scalar TwoPointColl(br_scalar* f, br_matrix4* m, br_scalar* d, br_vector3* tau, br_vector3* n) {
|
|
br_scalar ts;
|
|
LOG_TRACE("(%p, %p, %p, %p, %p)", f, m, d, tau, n);
|
|
|
|
ts = m->m[1][1] * m->m[0][0] - m->m[0][1] * m->m[1][0];
|
|
if (fabs(ts) >= 0.000001) {
|
|
*f = (m->m[1][1] * *d - m->m[0][1] * d[1]) / ts;
|
|
f[1] = (m->m[1][0] * *d - m->m[0][0] * d[1]) / -ts;
|
|
}
|
|
if (f[1] >= 0.0 && fabs(ts) >= 0.000001) {
|
|
if (*f < 0.0) {
|
|
m->m[0][0] = m->m[1][1];
|
|
*tau = tau[1];
|
|
*n = n[1];
|
|
*d = d[1];
|
|
ts = SinglePointColl(f, m, d);
|
|
f[1] = 0.0;
|
|
}
|
|
} else {
|
|
ts = SinglePointColl(f, m, d);
|
|
f[1] = 0.0;
|
|
}
|
|
return fabs(ts);
|
|
}
|
|
|
|
// IDA: br_scalar __usercall DrMatrix4Inverse@<ST0>(br_matrix4 *mi@<EAX>, br_matrix4 *mc@<EDX>)
|
|
br_scalar DrMatrix4Inverse(br_matrix4* mi, br_matrix4* mc) {
|
|
LOG_TRACE("(%p, %p)", mi, mc);
|
|
|
|
return BrMatrix4Inverse(mi, mc);
|
|
}
|
|
|
|
// IDA: br_scalar __usercall ThreePointColl@<ST0>(br_scalar *f@<EAX>, br_matrix4 *m@<EDX>, br_scalar *d@<EBX>)
|
|
br_scalar ThreePointColl(br_scalar* f, br_matrix4* m, br_scalar* d) {
|
|
br_matrix4 mc;
|
|
br_matrix4 mi;
|
|
br_scalar ts;
|
|
LOG_TRACE("(%p, %p, %p)", f, m, d);
|
|
|
|
BrMatrix4Copy(&mc, m);
|
|
memset(&mc.m[2][3], 0, 16);
|
|
mc.m[1][3] = 0.0;
|
|
mc.m[0][3] = 0.0;
|
|
mc.m[3][3] = 1.0;
|
|
ts = DrMatrix4Inverse(&mi, &mc);
|
|
BrMatrix4TApply((br_vector4*)f, (br_vector4*)d, &mi);
|
|
f[3] = 0.0;
|
|
return fabs(ts);
|
|
}
|
|
|
|
// IDA: br_scalar __usercall ThreePointCollRec@<ST0>(br_scalar *f@<EAX>, br_matrix4 *m@<EDX>, br_scalar *d@<EBX>, br_vector3 *tau@<ECX>, br_vector3 *n, tCollision_info *c)
|
|
br_scalar ThreePointCollRec(br_scalar* f, br_matrix4* m, br_scalar* d, br_vector3* tau, br_vector3* n, tCollision_info* c) {
|
|
int i;
|
|
int j;
|
|
br_scalar ts;
|
|
LOG_TRACE("(%p, %p, %p, %p, %p, %p)", f, m, d, tau, n, c);
|
|
|
|
ts = ThreePointColl(f, m, d);
|
|
if (*f >= 0.0 && f[1] >= 0.0 && f[2] >= 0.0 && ts >= 0.000001) {
|
|
c->infinite_mass = 256;
|
|
return ts;
|
|
}
|
|
if (ts >= 0.000001) {
|
|
if (*f >= 0.0) {
|
|
if (f[1] >= 0.0) {
|
|
if (f[2] >= 0.0) {
|
|
return 0.0;
|
|
}
|
|
i = 0;
|
|
j = 1;
|
|
} else {
|
|
i = 0;
|
|
j = 2;
|
|
}
|
|
} else {
|
|
i = 1;
|
|
j = 2;
|
|
}
|
|
} else {
|
|
i = 0;
|
|
j = 1;
|
|
}
|
|
m->m[0][0] = m->m[0][5 * i];
|
|
m->m[1][0] = m->m[j][i];
|
|
m->m[0][1] = m->m[i][j];
|
|
m->m[1][1] = m->m[0][5 * j];
|
|
*tau = tau[i];
|
|
tau[1] = tau[j];
|
|
*n = n[i];
|
|
n[1] = n[j];
|
|
*d = d[i];
|
|
d[1] = d[j];
|
|
ts = TwoPointColl(f, m, d, tau, n);
|
|
f[2] = 0.0;
|
|
return ts;
|
|
}
|
|
|
|
// IDA: br_scalar __usercall FourPointColl@<ST0>(br_scalar *f@<EAX>, br_matrix4 *m@<EDX>, br_scalar *d@<EBX>, br_vector3 *tau@<ECX>, br_vector3 *n, tCollision_info *c)
|
|
br_scalar FourPointColl(br_scalar* f, br_matrix4* m, br_scalar* d, br_vector3* tau, br_vector3* n, tCollision_info* c) {
|
|
int i;
|
|
int j;
|
|
int l;
|
|
br_scalar ts;
|
|
LOG_TRACE("(%p, %p, %p, %p, %p, %p)", f, m, d, tau, n, c);
|
|
|
|
ts = ThreePointColl(f, m, d);
|
|
if (*f < 0.0 || f[1] < 0.0 || f[2] < 0.0 || ts < 0.000001) {
|
|
if (ts >= 0.000001) {
|
|
if (*f >= 0.0) {
|
|
if (f[1] >= 0.0) {
|
|
j = 2;
|
|
} else {
|
|
j = 1;
|
|
}
|
|
} else {
|
|
j = 0;
|
|
}
|
|
} else {
|
|
j = 3;
|
|
}
|
|
for (i = j; i < 3; ++i) {
|
|
for (l = 0; l < 4; ++l) {
|
|
m->m[i][l] = m->m[i + 1][l];
|
|
}
|
|
d[i] = d[i + 1];
|
|
tau[i] = tau[i + 1];
|
|
n[i] = n[i + 1];
|
|
d[i] = d[i + 1];
|
|
}
|
|
for (i = j; i < 3; ++i) {
|
|
for (l = 0; l < 3; ++l) {
|
|
m->m[l][i] = m->m[l][i + 1];
|
|
}
|
|
}
|
|
return ThreePointCollRec(f, m, d, tau, n, c);
|
|
} else {
|
|
c->infinite_mass = 256;
|
|
return ts;
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall MultiFindFloorInBoxM(int pNum_rays@<EAX>, br_vector3 *a@<EDX>, br_vector3 *b@<EBX>, br_vector3 *nor@<ECX>, br_scalar *d, tCar_spec *c, int *mat_ref)
|
|
void MultiFindFloorInBoxM(int pNum_rays, br_vector3* a, br_vector3* b, br_vector3* nor, br_scalar* d, tCar_spec* c, int* mat_ref) {
|
|
br_vector3 aa[4];
|
|
br_vector3 bb;
|
|
int i;
|
|
LOG_TRACE("(%d, %p, %p, %p, %p, %p, %p)", pNum_rays, a, b, nor, d, c, mat_ref);
|
|
|
|
for (i = 0; i < pNum_rays; i++) {
|
|
aa[i].v[0] = a[i].v[0] / WORLD_SCALE;
|
|
aa[i].v[1] = a[i].v[1] / WORLD_SCALE;
|
|
aa[i].v[2] = a[i].v[2] / WORLD_SCALE;
|
|
d[i] = 2.0;
|
|
}
|
|
bb.v[0] = b->v[0] / WORLD_SCALE;
|
|
bb.v[1] = b->v[1] / WORLD_SCALE;
|
|
bb.v[2] = b->v[2] / WORLD_SCALE;
|
|
MultiFindFloorInBoxBU(pNum_rays, aa, &bb, nor, d, c, mat_ref);
|
|
}
|
|
|
|
// IDA: void __usercall MultiFindFloorInBoxBU(int pNum_rays@<EAX>, br_vector3 *a@<EDX>, br_vector3 *b@<EBX>, br_vector3 *nor@<ECX>, br_scalar *d, tCar_spec *c, int *mat_ref)
|
|
void MultiFindFloorInBoxBU(int pNum_rays, br_vector3* a, br_vector3* b, br_vector3* nor, br_scalar* d, tCar_spec* c, int* mat_ref) {
|
|
br_vector3 nor2;
|
|
int i;
|
|
int j;
|
|
int l;
|
|
br_scalar dist[4];
|
|
tFace_ref* face_ref;
|
|
LOG_TRACE("(%d, %p, %p, %p, %p, %p, %p)", pNum_rays, a, b, nor, d, c, mat_ref);
|
|
|
|
for (i = c->box_face_start; i < c->box_face_end; i++) {
|
|
face_ref = &gFace_list__car[i];
|
|
if (!gEliminate_faces || (face_ref->flags & 0x80) == 0x0) {
|
|
MultiRayCheckSingleFace(pNum_rays, face_ref, a, b, &nor2, dist);
|
|
for (j = 0; j < pNum_rays; ++j) {
|
|
if (d[j] > dist[j]) {
|
|
d[j] = dist[j];
|
|
nor[j] = nor2;
|
|
l = *gFace_list__car[i].material->identifier - 47;
|
|
if (l >= 0 && l < 11) {
|
|
mat_ref[j] = l;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall findfloor(br_vector3 *a@<EAX>, br_vector3 *b@<EDX>, br_vector3 *nor@<EBX>, br_scalar *d@<ECX>)
|
|
void findfloor(br_vector3* a, br_vector3* b, br_vector3* nor, br_scalar* d) {
|
|
br_material* material;
|
|
br_vector3 aa;
|
|
br_vector3 bb;
|
|
LOG_TRACE("(%p, %p, %p, %p)", a, b, nor, d);
|
|
|
|
aa.v[0] = a->v[0] / WORLD_SCALE;
|
|
aa.v[1] = a->v[1] / WORLD_SCALE;
|
|
aa.v[2] = a->v[2] / WORLD_SCALE;
|
|
bb.v[0] = b->v[0] / WORLD_SCALE;
|
|
bb.v[1] = b->v[1] / WORLD_SCALE;
|
|
bb.v[2] = b->v[2] / WORLD_SCALE;
|
|
FindFace(&aa, &bb, nor, d, &material);
|
|
}
|
|
|
|
// IDA: int __usercall FindFloorInBoxM@<EAX>(br_vector3 *a@<EAX>, br_vector3 *b@<EDX>, br_vector3 *nor@<EBX>, br_scalar *d@<ECX>, tCollision_info *c)
|
|
int FindFloorInBoxM(br_vector3* a, br_vector3* b, br_vector3* nor, br_scalar* d, tCollision_info* c) {
|
|
br_vector3 aa;
|
|
br_vector3 bb;
|
|
LOG_TRACE("(%p, %p, %p, %p, %p)", a, b, nor, d, c);
|
|
|
|
aa.v[0] = a->v[0] / WORLD_SCALE;
|
|
aa.v[1] = a->v[1] / WORLD_SCALE;
|
|
aa.v[2] = a->v[2] / WORLD_SCALE;
|
|
bb.v[0] = b->v[0] / WORLD_SCALE;
|
|
bb.v[1] = b->v[1] / WORLD_SCALE;
|
|
bb.v[2] = b->v[2] / WORLD_SCALE;
|
|
return FindFloorInBoxBU(&aa, &bb, nor, d, c);
|
|
}
|
|
|
|
// IDA: int __usercall FindFloorInBoxBU@<EAX>(br_vector3 *a@<EAX>, br_vector3 *b@<EDX>, br_vector3 *nor@<EBX>, br_scalar *d@<ECX>, tCollision_info *c)
|
|
int FindFloorInBoxBU(br_vector3* a, br_vector3* b, br_vector3* nor, br_scalar* d, tCollision_info* c) {
|
|
br_vector3 nor2;
|
|
int i;
|
|
int j;
|
|
br_scalar dist;
|
|
tFace_ref* face_ref;
|
|
LOG_TRACE("(%p, %p, %p, %p, %p)", a, b, nor, d, c);
|
|
|
|
j = 0; // added to keep compiler happy
|
|
*d = 2.0;
|
|
for (i = c->box_face_start; i < c->box_face_end; i++) {
|
|
face_ref = &gFace_list__car[i];
|
|
if (!gEliminate_faces || SLOBYTE(face_ref->flags) >= 0) {
|
|
CheckSingleFace(face_ref, a, b, &nor2, &dist);
|
|
if (*d > dist) {
|
|
*d = dist;
|
|
j = i;
|
|
*nor = nor2;
|
|
}
|
|
}
|
|
}
|
|
if (*d >= 2.0) {
|
|
return 0;
|
|
}
|
|
i = *gFace_list__car[j].material->identifier - '/';
|
|
if (i < 0 || i >= 11) {
|
|
return 0;
|
|
} else {
|
|
return *gFace_list__car[j].material->identifier - '/';
|
|
}
|
|
}
|
|
|
|
// IDA: int __usercall FindFloorInBoxBU2@<EAX>(br_vector3 *a@<EAX>, br_vector3 *b@<EDX>, br_vector3 *nor@<EBX>, br_scalar *d@<ECX>, tCollision_info *c)
|
|
int FindFloorInBoxBU2(br_vector3* a, br_vector3* b, br_vector3* nor, br_scalar* d, tCollision_info* c) {
|
|
br_vector3 nor2;
|
|
br_vector3 tv;
|
|
int i;
|
|
int j;
|
|
br_scalar dist;
|
|
tFace_ref* face_ref;
|
|
LOG_TRACE("(%p, %p, %p, %p, %p)", a, b, nor, d, c);
|
|
|
|
j = 0; // added to keep compiler happy
|
|
*d = 2.0;
|
|
for (i = c->box_face_start; i < c->box_face_end; i++) {
|
|
face_ref = &gFace_list__car[i];
|
|
if (!gEliminate_faces || SLOBYTE(face_ref->flags) >= 0) {
|
|
CheckSingleFace(face_ref, a, b, &nor2, &dist);
|
|
if (*d > dist) {
|
|
if (face_ref->material->colour_map_1 == DOUBLESIDED_FLAG_COLOR_MAP || (face_ref->material->flags & 0x1800) != 0) {
|
|
tv.v[0] = c->pos.v[0] - a->v[0];
|
|
tv.v[1] = c->pos.v[1] - a->v[1];
|
|
tv.v[2] = c->pos.v[2] - a->v[2];
|
|
if (tv.v[2] * nor2.v[2] + tv.v[1] * nor2.v[1] + tv.v[0] * nor2.v[0] >= 0.0) {
|
|
*d = dist;
|
|
j = i;
|
|
*nor = nor2;
|
|
}
|
|
} else {
|
|
*d = dist;
|
|
j = i;
|
|
*nor = nor2;
|
|
}
|
|
}
|
|
}
|
|
face_ref++;
|
|
}
|
|
if (*d >= 2.0) {
|
|
return 0;
|
|
}
|
|
i = *gFace_list__car[j].material->identifier - '/';
|
|
if (i < 0 || i >= 11) {
|
|
return 0;
|
|
} else {
|
|
return *gFace_list__car[j].material->identifier - '/';
|
|
}
|
|
}
|
|
|
|
// IDA: int __usercall FindFloorInBoxM2@<EAX>(br_vector3 *a@<EAX>, br_vector3 *b@<EDX>, br_vector3 *nor@<EBX>, br_scalar *d@<ECX>, tCollision_info *c)
|
|
int FindFloorInBoxM2(br_vector3* a, br_vector3* b, br_vector3* nor, br_scalar* d, tCollision_info* c) {
|
|
br_vector3 aa;
|
|
br_vector3 bb;
|
|
LOG_TRACE("(%p, %p, %p, %p, %p)", a, b, nor, d, c);
|
|
|
|
aa.v[0] = a->v[0] / WORLD_SCALE;
|
|
aa.v[1] = a->v[1] / WORLD_SCALE;
|
|
aa.v[2] = a->v[2] / WORLD_SCALE;
|
|
bb.v[0] = b->v[0] / WORLD_SCALE;
|
|
bb.v[1] = b->v[1] / WORLD_SCALE;
|
|
bb.v[2] = b->v[2] / WORLD_SCALE;
|
|
return FindFloorInBoxBU2(&aa, &bb, nor, d, c);
|
|
}
|
|
|
|
// IDA: int __usercall BoxFaceIntersect@<EAX>(br_bounds *pB@<EAX>, br_matrix34 *pM@<EDX>, br_matrix34 *pMold@<EBX>, br_vector3 *pPoint_list@<ECX>, br_vector3 *pNorm_list, br_scalar *pDist_list, int pMax_pnts, tCollision_info *c)
|
|
int BoxFaceIntersect(br_bounds* pB, br_matrix34* pM, br_matrix34* pMold, br_vector3* pPoint_list, br_vector3* pNorm_list, br_scalar* pDist_list, int pMax_pnts, tCollision_info* c) {
|
|
br_vector3 p[3];
|
|
br_vector3 tv;
|
|
br_vector3 pos;
|
|
br_bounds bnds;
|
|
int i;
|
|
int j;
|
|
int n;
|
|
int flag;
|
|
int m;
|
|
tFace_ref* f_ref;
|
|
br_face* face;
|
|
LOG_TRACE("(%p, %p, %p, %p, %p, %p, %d, %p)", pB, pM, pMold, pPoint_list, pNorm_list, pDist_list, pMax_pnts, c);
|
|
|
|
n = 0;
|
|
bnds.min.v[0] = pB->min.v[0] * 0.14492753;
|
|
bnds.min.v[1] = pB->min.v[1] * 0.14492753;
|
|
bnds.min.v[2] = pB->min.v[2] * 0.14492753;
|
|
bnds.max.v[0] = pB->max.v[0] * 0.14492753;
|
|
bnds.max.v[1] = pB->max.v[1] * 0.14492753;
|
|
bnds.max.v[2] = pB->max.v[2] * 0.14492753;
|
|
pos.v[0] = pM->m[3][0] * 0.14492753;
|
|
pos.v[1] = pM->m[3][1] * 0.14492753;
|
|
pos.v[2] = pM->m[3][2] * 0.14492753;
|
|
pMold->m[3][0] = pMold->m[3][0] * 0.14492753;
|
|
pMold->m[3][1] = pMold->m[3][1] * 0.14492753;
|
|
pMold->m[3][2] = pMold->m[3][2] * 0.14492753;
|
|
|
|
for (i = c->box_face_start; i < c->box_face_end && i < c->box_face_start + 50; i++) {
|
|
f_ref = &gFace_list__car[i];
|
|
if (SLOBYTE(f_ref->flags) >= 0 && *f_ref->material->identifier != '!') {
|
|
tv.v[0] = f_ref->v[0].v[0] - pos.v[0];
|
|
tv.v[1] = f_ref->v[0].v[1] - pos.v[1];
|
|
tv.v[2] = f_ref->v[0].v[2] - pos.v[2];
|
|
BrMatrix34TApplyV(p, &tv, pM);
|
|
tv.v[0] = f_ref->v[1].v[0] - pos.v[0];
|
|
tv.v[1] = f_ref->v[1].v[1] - pos.v[1];
|
|
tv.v[2] = f_ref->v[1].v[2] - pos.v[2];
|
|
BrMatrix34TApplyV(&p[1], &tv, pM);
|
|
tv.v[0] = f_ref->v[2].v[0] - pos.v[0];
|
|
tv.v[1] = f_ref->v[2].v[1] - pos.v[1];
|
|
tv.v[2] = f_ref->v[2].v[2] - pos.v[2];
|
|
BrMatrix34TApplyV(&p[2], &tv, pM);
|
|
j = n;
|
|
if ((f_ref->flags & 1) == 0) {
|
|
n += AddEdgeCollPoints(p, &p[1], &bnds, pMold, pPoint_list, pNorm_list, n, pMax_pnts, c);
|
|
}
|
|
if ((f_ref->flags & 2) == 0) {
|
|
n += AddEdgeCollPoints(&p[1], &p[2], &bnds, pMold, pPoint_list, pNorm_list, n, pMax_pnts, c);
|
|
}
|
|
if ((f_ref->flags & 4) == 0) {
|
|
n += AddEdgeCollPoints(&p[2], p, &bnds, pMold, pPoint_list, pNorm_list, n, pMax_pnts, c);
|
|
}
|
|
if (n > j) {
|
|
if (!gMaterial_index) {
|
|
m = *f_ref->material->identifier - '/';
|
|
if (m > 0 && m < 11) {
|
|
gMaterial_index = m;
|
|
}
|
|
}
|
|
while (n > j) {
|
|
pPoint_list[j].v[0] = pPoint_list[j].v[0] * WORLD_SCALE;
|
|
pPoint_list[j].v[1] = pPoint_list[j].v[1] * WORLD_SCALE;
|
|
pPoint_list[j].v[2] = pPoint_list[j].v[2] * WORLD_SCALE;
|
|
pPoint_list[j].v[0] = pPoint_list[j].v[0] - c->cmpos.v[0];
|
|
pPoint_list[j].v[1] = pPoint_list[j].v[1] - c->cmpos.v[1];
|
|
pPoint_list[j].v[2] = pPoint_list[j].v[2] - c->cmpos.v[2];
|
|
++j;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (n) {
|
|
m = 0;
|
|
for (i = 0; i < n - 1; i++) {
|
|
flag = 1;
|
|
for (j = i + 1; j < n; j++) {
|
|
if (fabs(pPoint_list[i].v[0] - pPoint_list[j].v[0]) <= 0.001
|
|
&& fabs(pPoint_list[i].v[1] - pPoint_list[j].v[1]) <= 0.001
|
|
&& fabs(pPoint_list[i].v[2] - pPoint_list[j].v[2]) <= 0.001) {
|
|
flag = 0;
|
|
break;
|
|
}
|
|
}
|
|
if (flag) {
|
|
pPoint_list[m].v[0] = pPoint_list[i].v[0];
|
|
pPoint_list[m].v[1] = pPoint_list[i].v[1];
|
|
pPoint_list[m].v[2] = pPoint_list[i].v[2];
|
|
m++;
|
|
}
|
|
}
|
|
pPoint_list[m].v[0] = pPoint_list[n - 1].v[0];
|
|
pPoint_list[m].v[1] = pPoint_list[n - 1].v[1];
|
|
pPoint_list[m].v[2] = pPoint_list[n - 1].v[2];
|
|
n = m + 1;
|
|
}
|
|
pMold->m[3][0] = pMold->m[3][0] * WORLD_SCALE;
|
|
pMold->m[3][1] = pMold->m[3][1] * WORLD_SCALE;
|
|
pMold->m[3][2] = pMold->m[3][2] * WORLD_SCALE;
|
|
return n;
|
|
}
|
|
|
|
// IDA: int __usercall AddEdgeCollPoints@<EAX>(br_vector3 *p1@<EAX>, br_vector3 *p2@<EDX>, br_bounds *pB@<EBX>, br_matrix34 *pMold@<ECX>, br_vector3 *pPoint_list, br_vector3 *pNorm_list, int n, int pMax_pnts, tCollision_info *c)
|
|
int AddEdgeCollPoints(br_vector3* p1, br_vector3* p2, br_bounds* pB, br_matrix34* pMold, br_vector3* pPoint_list, br_vector3* pNorm_list, int n, int pMax_pnts, tCollision_info* c) {
|
|
br_vector3 op1;
|
|
br_vector3 op2;
|
|
br_vector3 a;
|
|
br_vector3 b;
|
|
br_vector3 edge;
|
|
br_vector3 hp1;
|
|
br_vector3 hp2;
|
|
br_vector3 hp3;
|
|
int plane1;
|
|
int plane2;
|
|
int plane3;
|
|
int d;
|
|
LOG_TRACE("(%p, %p, %p, %p, %p, %p, %d, %d, %p)", p1, p2, pB, pMold, pPoint_list, pNorm_list, n, pMax_pnts, c);
|
|
|
|
float scale;
|
|
|
|
plane1 = LineBoxColl(p1, p2, pB, &hp1);
|
|
if (!plane1) {
|
|
return 0;
|
|
}
|
|
if (n + 2 > pMax_pnts) {
|
|
return 0;
|
|
}
|
|
plane2 = LineBoxColl(p2, p1, pB, &hp2);
|
|
if (!plane2) {
|
|
return 0;
|
|
}
|
|
if (plane1 == 8 || plane2 == 8 || (plane1 ^ plane2) != 4) {
|
|
if (plane1 != 8 || plane2 == 8) {
|
|
if (plane2 != 8 || plane1 == 8) {
|
|
if (plane1 == 8 || plane2 == 8) {
|
|
if (plane1 == 8 && plane2 == 8) {
|
|
BrMatrix34ApplyP(&op1, p1, pMold);
|
|
plane3 = LineBoxColl(&op1, p1, pB, &pPoint_list[n]);
|
|
GetPlaneNormal(&pNorm_list[n], plane3);
|
|
d = n + (plane3 != 8);
|
|
BrMatrix34ApplyP(&op1, p2, pMold);
|
|
plane3 = LineBoxColl(&op1, p2, pB, &pPoint_list[d]);
|
|
GetPlaneNormal(&pNorm_list[d], plane3);
|
|
return (n != d) + (plane3 != 8);
|
|
} else {
|
|
return 0;
|
|
}
|
|
} else {
|
|
op1.v[0] = hp2.v[0] + hp1.v[0];
|
|
op1.v[1] = hp2.v[1] + hp1.v[1];
|
|
op1.v[2] = hp2.v[2] + hp1.v[2];
|
|
op1.v[0] = op1.v[0] * 0.5;
|
|
op1.v[1] = op1.v[1] * 0.5;
|
|
op1.v[2] = op1.v[2] * 0.5;
|
|
BrMatrix34ApplyP(&op2, &op1, pMold);
|
|
plane3 = LineBoxColl(&op2, &op1, pB, &hp3);
|
|
if (plane3 != 8 && plane3) {
|
|
if (plane1 == plane3 || plane2 == plane3) {
|
|
GetBoundsEdge(
|
|
&pPoint_list[n],
|
|
&edge,
|
|
pB,
|
|
plane1,
|
|
plane2,
|
|
&op2,
|
|
&hp1,
|
|
&hp2,
|
|
c->collision_flag);
|
|
op1.v[0] = hp1.v[0] - hp2.v[0];
|
|
op1.v[1] = hp1.v[1] - hp2.v[1];
|
|
op1.v[2] = hp1.v[2] - hp2.v[2];
|
|
op2.v[0] = edge.v[1] * op1.v[2] - op1.v[1] * edge.v[2];
|
|
op2.v[1] = edge.v[2] * op1.v[0] - op1.v[2] * edge.v[0];
|
|
op2.v[2] = op1.v[1] * edge.v[0] - edge.v[1] * op1.v[0];
|
|
scale = sqrt(op2.v[1] * op2.v[1] + op2.v[2] * op2.v[2] + op2.v[0] * op2.v[0]);
|
|
if (scale <= 2.3841858e-7) {
|
|
pNorm_list[n].v[0] = 1.0;
|
|
pNorm_list[n].v[1] = 0.0;
|
|
pNorm_list[n].v[2] = 0.0;
|
|
} else {
|
|
scale = 1.0 / scale;
|
|
pNorm_list[n].v[0] = op2.v[0] * scale;
|
|
pNorm_list[n].v[1] = op2.v[1] * scale;
|
|
pNorm_list[n].v[2] = op2.v[2] * scale;
|
|
}
|
|
op1.v[0] = pB->max.v[0] + pB->min.v[0];
|
|
op1.v[1] = pB->min.v[1] + pB->max.v[1];
|
|
op1.v[2] = pB->max.v[2] + pB->min.v[2];
|
|
op1.v[0] = op1.v[0] * 0.5;
|
|
op1.v[1] = op1.v[1] * 0.5;
|
|
op1.v[2] = op1.v[2] * 0.5;
|
|
op1.v[0] = pPoint_list[n].v[0] - op1.v[0];
|
|
op1.v[1] = pPoint_list[n].v[1] - op1.v[1];
|
|
op1.v[2] = pPoint_list[n].v[2] - op1.v[2];
|
|
if (pNorm_list[n].v[1] * op1.v[1] + pNorm_list[n].v[2] * op1.v[2] + pNorm_list[n].v[0] * op1.v[0] > 0.0) {
|
|
pNorm_list[n].v[0] = -pNorm_list[n].v[0];
|
|
pNorm_list[n].v[1] = -pNorm_list[n].v[1];
|
|
pNorm_list[n].v[2] = -pNorm_list[n].v[2];
|
|
}
|
|
op1 = pNorm_list[n];
|
|
BrMatrix34ApplyV(&pNorm_list[n], &op1, pMold);
|
|
return 1;
|
|
} else {
|
|
GetBoundsEdge(
|
|
&pPoint_list[n],
|
|
&edge,
|
|
pB,
|
|
plane1,
|
|
plane3,
|
|
&hp3,
|
|
&hp1,
|
|
&hp2,
|
|
c->collision_flag);
|
|
GetBoundsEdge(
|
|
&pPoint_list[n + 1],
|
|
&edge,
|
|
pB,
|
|
plane2,
|
|
plane3,
|
|
&hp3,
|
|
&hp1,
|
|
&hp2,
|
|
c->collision_flag);
|
|
GetPlaneNormal(&pNorm_list[n], plane3);
|
|
pNorm_list[n + 1] = pNorm_list[n];
|
|
return 2;
|
|
}
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
} else {
|
|
BrMatrix34ApplyP(&b, p2, pMold);
|
|
plane3 = LineBoxColl(&b, p2, pB, &hp3);
|
|
if (plane3 == 8) {
|
|
return 0;
|
|
} else {
|
|
pPoint_list[n] = hp3;
|
|
GetPlaneNormal(&pNorm_list[n], plane1);
|
|
if (plane1 == plane3 || (plane3 ^ plane1) == 4) {
|
|
return 1;
|
|
} else {
|
|
GetBoundsEdge(&pPoint_list[n + 1], &edge, pB, plane1, plane3, p2, &hp1, &hp3, c->collision_flag);
|
|
op1.v[0] = p1->v[0] - p2->v[0];
|
|
op1.v[1] = p1->v[1] - p2->v[1];
|
|
op1.v[2] = p1->v[2] - p2->v[2];
|
|
pNorm_list[n + 1].v[0] = edge.v[1] * op1.v[2] - op1.v[1] * edge.v[2];
|
|
pNorm_list[n + 1].v[1] = edge.v[2] * op1.v[0] - op1.v[2] * edge.v[0];
|
|
pNorm_list[n + 1].v[2] = op1.v[1] * edge.v[0] - edge.v[1] * op1.v[0];
|
|
scale = sqrt(
|
|
pNorm_list[n + 1].v[0] * pNorm_list[n + 1].v[0]
|
|
+ pNorm_list[n + 1].v[1] * pNorm_list[n + 1].v[1]
|
|
+ pNorm_list[n + 1].v[2] * pNorm_list[n + 1].v[2]);
|
|
if (scale <= 2.3841858e-7) {
|
|
pNorm_list[n + 1].v[0] = 1.0;
|
|
pNorm_list[n + 1].v[1] = 0.0;
|
|
pNorm_list[n + 1].v[2] = 0.0;
|
|
} else {
|
|
scale = 1.0 / scale;
|
|
pNorm_list[n + 1].v[0] = pNorm_list[n + 1].v[0] * scale;
|
|
pNorm_list[n + 1].v[1] = pNorm_list[n + 1].v[1] * scale;
|
|
pNorm_list[n + 1].v[2] = pNorm_list[n + 1].v[2] * scale;
|
|
}
|
|
d = (plane1 - 1) & 3;
|
|
if ((pNorm_list[n + 1].v[d] < 0.0) == (plane1 & 4) >> 2) {
|
|
pNorm_list[n + 1].v[0] = -pNorm_list[n + 1].v[0];
|
|
pNorm_list[n + 1].v[1] = -pNorm_list[n + 1].v[1];
|
|
pNorm_list[n + 1].v[2] = -pNorm_list[n + 1].v[2];
|
|
}
|
|
op1 = pNorm_list[n + 1];
|
|
BrMatrix34ApplyV(&pNorm_list[n + 1], &op1, pMold);
|
|
return 2;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
BrMatrix34ApplyP(&a, p1, pMold);
|
|
plane3 = LineBoxColl(&a, p1, pB, &hp3);
|
|
if (plane3 == 8) {
|
|
return 0;
|
|
} else {
|
|
pPoint_list[n] = hp3;
|
|
GetPlaneNormal(&pNorm_list[n], plane2);
|
|
if (plane2 == plane3 || (plane3 ^ plane2) == 4) {
|
|
return 1;
|
|
} else {
|
|
GetBoundsEdge(&pPoint_list[n + 1], &edge, pB, plane2, plane3, p1, &hp2, &hp3, c->collision_flag);
|
|
op1.v[0] = p1->v[0] - p2->v[0];
|
|
op1.v[1] = p1->v[1] - p2->v[1];
|
|
op1.v[2] = p1->v[2] - p2->v[2];
|
|
pNorm_list[n + 1].v[0] = edge.v[1] * op1.v[2] - op1.v[1] * edge.v[2];
|
|
pNorm_list[n + 1].v[1] = edge.v[2] * op1.v[0] - op1.v[2] * edge.v[0];
|
|
pNorm_list[n + 1].v[2] = op1.v[1] * edge.v[0] - edge.v[1] * op1.v[0];
|
|
scale = sqrt(
|
|
pNorm_list[n + 1].v[0] * pNorm_list[n + 1].v[0]
|
|
+ pNorm_list[n + 1].v[1] * pNorm_list[n + 1].v[1]
|
|
+ pNorm_list[n + 1].v[2] * pNorm_list[n + 1].v[2]);
|
|
if (scale <= 2.3841858e-7) {
|
|
pNorm_list[n + 1].v[0] = 1.0;
|
|
pNorm_list[n + 1].v[1] = 0.0;
|
|
pNorm_list[n + 1].v[2] = 0.0;
|
|
} else {
|
|
scale = 1.0 / scale;
|
|
pNorm_list[n + 1].v[0] = pNorm_list[n + 1].v[0] * scale;
|
|
pNorm_list[n + 1].v[1] = pNorm_list[n + 1].v[1] * scale;
|
|
pNorm_list[n + 1].v[2] = pNorm_list[n + 1].v[2] * scale;
|
|
}
|
|
d = (plane2 - 1) & 3;
|
|
if ((pNorm_list[n + 1].v[d] < 0.0) == (plane2 & 4) >> 2) {
|
|
pNorm_list[n + 1].v[0] = -pNorm_list[n + 1].v[0];
|
|
pNorm_list[n + 1].v[1] = -pNorm_list[n + 1].v[1];
|
|
pNorm_list[n + 1].v[2] = -pNorm_list[n + 1].v[2];
|
|
}
|
|
op1 = pNorm_list[n + 1];
|
|
BrMatrix34ApplyV(&pNorm_list[n + 1], &op1, pMold);
|
|
return 2;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
op1.v[0] = hp2.v[0] + hp1.v[0];
|
|
op1.v[1] = hp2.v[1] + hp1.v[1];
|
|
op1.v[2] = hp2.v[2] + hp1.v[2];
|
|
op1.v[0] = op1.v[0] * 0.5;
|
|
op1.v[1] = op1.v[1] * 0.5;
|
|
op1.v[2] = op1.v[2] * 0.5;
|
|
BrMatrix34ApplyP(&op2, &op1, pMold);
|
|
plane3 = LineBoxColl(&op2, &op1, pB, &hp3);
|
|
if (plane3 == 8) {
|
|
return 0;
|
|
} else {
|
|
GetBoundsEdge(&pPoint_list[n], &edge, pB, plane1, plane3, &op2, &hp1, &hp2, c->collision_flag);
|
|
GetBoundsEdge(&pPoint_list[n + 1], &edge, pB, plane2, plane3, &op2, &hp1, &hp2, c->collision_flag);
|
|
GetPlaneNormal(&pNorm_list[n], plane3);
|
|
pNorm_list[n + 1] = pNorm_list[n];
|
|
return 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall GetPlaneNormal(br_vector3 *n@<EAX>, int p@<EDX>)
|
|
void GetPlaneNormal(br_vector3* n, int p) {
|
|
int d;
|
|
LOG_TRACE("(%p, %d)", n, p);
|
|
|
|
d = (p - 1) & 3;
|
|
n->v[0] = 0.0;
|
|
n->v[1] = 0.0;
|
|
n->v[2] = 0.0;
|
|
if ((p & 4) != 0) {
|
|
n->v[d] = 1.0;
|
|
} else {
|
|
n->v[d] = -1.0;
|
|
}
|
|
}
|
|
|
|
// IDA: int __usercall GetBoundsEdge@<EAX>(br_vector3 *pos@<EAX>, br_vector3 *edge@<EDX>, br_bounds *pB@<EBX>, int plane1@<ECX>, int plane2, br_vector3 *a, br_vector3 *b, br_vector3 *c, int flag)
|
|
int GetBoundsEdge(br_vector3* pos, br_vector3* edge, br_bounds* pB, int plane1, int plane2, br_vector3* a, br_vector3* b, br_vector3* c, int flag) {
|
|
int d1;
|
|
int d2;
|
|
int d3;
|
|
br_vector3 n;
|
|
br_vector3 p;
|
|
br_vector3 q;
|
|
LOG_TRACE("(%p, %p, %p, %d, %d, %p, %p, %p, %d)", pos, edge, pB, plane1, plane2, a, b, c, flag);
|
|
|
|
d1 = (plane1 - 1) & 3;
|
|
d2 = (plane2 - 1) & 3;
|
|
n.v[0] = b->v[0] - a->v[0];
|
|
n.v[1] = b->v[1] - a->v[1];
|
|
n.v[2] = b->v[2] - a->v[2];
|
|
p.v[0] = c->v[0] - a->v[0];
|
|
p.v[1] = c->v[1] - a->v[1];
|
|
p.v[2] = c->v[2] - a->v[2];
|
|
q.v[0] = p.v[2] * n.v[1] - p.v[1] * n.v[2];
|
|
q.v[1] = n.v[2] * p.v[0] - p.v[2] * n.v[0];
|
|
q.v[2] = p.v[1] * n.v[0] - n.v[1] * p.v[0];
|
|
if ((plane1 & 4) != 0) {
|
|
pos->v[d1] = pB->min.v[d1];
|
|
} else {
|
|
pos->v[d1] = pB->max.v[d1];
|
|
}
|
|
if ((plane2 & 4) != 0) {
|
|
pos->v[d2] = pB->min.v[d2];
|
|
} else {
|
|
pos->v[d2] = pB->max.v[d2];
|
|
}
|
|
d3 = 3 - d1 - d2;
|
|
edge->v[d1] = 0.0;
|
|
edge->v[d2] = 0.0;
|
|
edge->v[d3] = 1.0;
|
|
if ((flag & 1) != 0) {
|
|
pos->v[d3] = (c->v[d3] + b->v[d3]) / 2.0;
|
|
} else {
|
|
pos->v[d3] = a->v[d3] - ((pos->v[d2] - a->v[d2]) * q.v[d2] + (pos->v[d1] - a->v[d1]) * q.v[d1]) / q.v[d3];
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
// IDA: void __usercall oldMoveOurCar(tU32 pTime_difference@<EAX>)
|
|
void oldMoveOurCar(tU32 pTime_difference) {
|
|
br_vector3 thrust_vector;
|
|
br_matrix34 direction_matrix;
|
|
br_matrix34 old_mat;
|
|
double rotate_amount;
|
|
br_scalar nearest_y_above;
|
|
br_scalar nearest_y_below;
|
|
br_scalar speed;
|
|
int below_face_index;
|
|
int above_face_index;
|
|
br_model* below_model;
|
|
br_model* above_model;
|
|
LOG_TRACE("(%d)", pTime_difference);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __cdecl ToggleCollisionDetection()
|
|
void ToggleCollisionDetection() {
|
|
LOG_TRACE("()");
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __cdecl CancelPendingCunningStunt()
|
|
void CancelPendingCunningStunt() {
|
|
LOG_TRACE("()");
|
|
|
|
gQuite_wild_end = 0;
|
|
gQuite_wild_start = 0;
|
|
gOn_me_wheels_start = 0;
|
|
gWoz_upside_down_at_all = 0;
|
|
gWild_start = 0;
|
|
}
|
|
|
|
// IDA: float __cdecl frac(float pN)
|
|
float frac(float pN) {
|
|
LOG_TRACE("(%f)", pN);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall SetAmbientPratCam(tCar_spec *pCar@<EAX>)
|
|
void SetAmbientPratCam(tCar_spec* pCar) {
|
|
br_scalar vcs_x;
|
|
br_scalar vcs_y;
|
|
br_scalar vcs_z;
|
|
br_scalar abs_vcs_x;
|
|
br_scalar abs_vcs_y;
|
|
br_scalar abs_vcs_z;
|
|
br_scalar abs_omega_x;
|
|
br_scalar abs_omega_y;
|
|
br_scalar abs_omega_z;
|
|
tU32 the_time;
|
|
static tU32 last_time_on_ground;
|
|
LOG_TRACE("(%p)", pCar);
|
|
|
|
STUB_ONCE();
|
|
}
|
|
|
|
// IDA: void __usercall MungeCarGraphics(tU32 pFrame_period@<EAX>)
|
|
void MungeCarGraphics(tU32 pFrame_period) {
|
|
int i;
|
|
int j;
|
|
int update_mat;
|
|
int spinning_wildly;
|
|
int spinning_mildly;
|
|
int car_count;
|
|
int oily_count;
|
|
int car;
|
|
int cat;
|
|
int new_special_screen;
|
|
tCar_spec* the_car;
|
|
br_scalar distance_from_camera;
|
|
br_scalar car_x;
|
|
br_scalar car_z;
|
|
br_scalar oily_size;
|
|
br_scalar car_radius;
|
|
br_scalar abs_omega_x;
|
|
br_scalar abs_omega_y;
|
|
br_scalar abs_omega_z;
|
|
float wheel_speed;
|
|
float speed_mph;
|
|
float rev_angle;
|
|
float sine_angle;
|
|
float raw_revs;
|
|
float rev_reducer;
|
|
tSpecial_screen* the_special_screen;
|
|
br_material* the_material;
|
|
tU32 the_time;
|
|
br_actor* oily_actor;
|
|
LOG_TRACE("(%d)", pFrame_period);
|
|
|
|
if (gNet_mode
|
|
&& ((gCurrent_net_game->type == eNet_game_type_foxy && gThis_net_player_index == gIt_or_fox)
|
|
|| (gCurrent_net_game->type == eNet_game_type_tag && gThis_net_player_index != gIt_or_fox))) {
|
|
gProgram_state.current_car.power_up_levels[1] = 0;
|
|
}
|
|
SetAmbientPratCam(&gProgram_state.current_car);
|
|
if (gProgram_state.cockpit_on) {
|
|
SwitchCarActor(&gProgram_state.current_car, gProgram_state.current_car.car_actor_count - 1);
|
|
} else {
|
|
SwitchCarActor(&gProgram_state.current_car, gProgram_state.current_car.car_actor_count - 2);
|
|
}
|
|
|
|
the_time = PDGetTotalTime();
|
|
for (cat = eVehicle_self; cat <= eVehicle_rozzer; cat++) {
|
|
if (cat) {
|
|
car_count = GetCarCount(cat);
|
|
} else {
|
|
car_count = 1;
|
|
}
|
|
for (car = 0; car_count > car; car++) {
|
|
if (cat) {
|
|
the_car = GetCarSpec(cat, car);
|
|
} else {
|
|
the_car = &gProgram_state.current_car;
|
|
}
|
|
the_car->car_master_actor->render_style = (the_car->driver != eDriver_local_human) && PointOutOfSight(&the_car->pos, gYon_squared);
|
|
}
|
|
}
|
|
for (car = 0; car < gNum_active_cars; car++) {
|
|
the_car = gActive_car_list[car];
|
|
if (the_car->car_master_actor->render_style != BR_RSTYLE_NONE) {
|
|
car_x = the_car->car_master_actor->t.t.mat.m[3][0];
|
|
car_z = the_car->car_master_actor->t.t.mat.m[3][2];
|
|
the_car->shadow_intersection_flags = 0;
|
|
oily_count = GetOilSpillCount();
|
|
for (i = 0; i < oily_count; i++) {
|
|
GetOilSpillDetails(i, &oily_actor, &oily_size);
|
|
if (oily_actor) {
|
|
car_radius = the_car->bounds[1].max.v[2] / WORLD_SCALE * 1.5;
|
|
if (oily_actor->t.t.mat.m[3][0] - oily_size < car_x + car_radius
|
|
&& oily_actor->t.t.mat.m[3][0] + oily_size > car_x - car_radius
|
|
&& oily_actor->t.t.mat.m[3][2] - oily_size < car_z + car_radius
|
|
&& oily_actor->t.t.mat.m[3][2] + oily_size > car_z - car_radius) {
|
|
the_car->shadow_intersection_flags |= 1 << i;
|
|
}
|
|
}
|
|
}
|
|
if (the_car->driver < eDriver_net_human && (!gAction_replay_mode || !ReplayIsPaused())) {
|
|
if (gCountdown) {
|
|
sine_angle = FRandomBetween(0.40000001, 1.6) * ((double)GetTotalTime() / ((double)gCountdown * 100.0));
|
|
sine_angle = frac(sine_angle) * 360.0;
|
|
sine_angle = FastScalarSin(sine_angle);
|
|
raw_revs = (double)the_car->red_line * fabs(sine_angle);
|
|
rev_reducer = (11.0 - (double)gCountdown) / 10.0;
|
|
the_car->revs = rev_reducer * raw_revs;
|
|
} else {
|
|
the_car->revs = (the_car->speedo_speed / 0.003
|
|
- (double)(int)(the_car->speedo_speed / 0.003))
|
|
* (double)(the_car->red_line - 800)
|
|
+ 800.0;
|
|
}
|
|
}
|
|
for (i = 0; i < the_car->number_of_steerable_wheels; i++) {
|
|
ControlBoundFunkGroove(the_car->steering_ref[i], the_car->steering_angle);
|
|
}
|
|
for (i = 0; i < 4; i++) {
|
|
ControlBoundFunkGroove(the_car->rf_sus_ref[i], the_car->rf_sus_position);
|
|
if ((i & 1) != 0) {
|
|
ControlBoundFunkGroove(the_car->lf_sus_ref[i], -the_car->lf_sus_position);
|
|
} else {
|
|
ControlBoundFunkGroove(the_car->lf_sus_ref[i], the_car->lf_sus_position);
|
|
}
|
|
}
|
|
for (i = 0; i < 2; i++) {
|
|
ControlBoundFunkGroove(the_car->rr_sus_ref[i], the_car->rr_sus_position);
|
|
if ((i & 1) != 0) {
|
|
ControlBoundFunkGroove(the_car->lr_sus_ref[i], -the_car->lr_sus_position);
|
|
} else {
|
|
ControlBoundFunkGroove(the_car->lr_sus_ref[i], the_car->lr_sus_position);
|
|
}
|
|
}
|
|
if (!gAction_replay_mode || !ReplayIsPaused()) {
|
|
wheel_speed = -(the_car->speedo_speed / the_car->non_driven_wheels_circum * (double)gFrame_period);
|
|
ControlBoundFunkGroovePlus(the_car->non_driven_wheels_spin_ref_1, wheel_speed);
|
|
ControlBoundFunkGroovePlus(the_car->non_driven_wheels_spin_ref_2, wheel_speed);
|
|
ControlBoundFunkGroovePlus(the_car->non_driven_wheels_spin_ref_3, wheel_speed);
|
|
ControlBoundFunkGroovePlus(the_car->non_driven_wheels_spin_ref_4, wheel_speed);
|
|
if (the_car->driver >= eDriver_net_human) {
|
|
if (the_car->gear) {
|
|
wheel_speed = -(the_car->revs
|
|
* the_car->speed_revs_ratio
|
|
/ 6900.0
|
|
* (double)the_car->gear
|
|
/ the_car->driven_wheels_circum
|
|
* (double)gFrame_period);
|
|
} else if (the_car->keys.brake) {
|
|
wheel_speed = 0.0;
|
|
} else {
|
|
wheel_speed = -(the_car->speedo_speed / the_car->driven_wheels_circum * (double)gFrame_period);
|
|
}
|
|
}
|
|
ControlBoundFunkGroovePlus(the_car->driven_wheels_spin_ref_1, wheel_speed);
|
|
ControlBoundFunkGroovePlus(the_car->driven_wheels_spin_ref_2, wheel_speed);
|
|
ControlBoundFunkGroovePlus(the_car->driven_wheels_spin_ref_3, wheel_speed);
|
|
ControlBoundFunkGroovePlus(the_car->driven_wheels_spin_ref_4, wheel_speed);
|
|
}
|
|
if (gAction_replay_mode) {
|
|
MungeSpecialVolume((tCollision_info*)the_car);
|
|
} else if (the_car->driver == eDriver_local_human) {
|
|
abs_omega_x = (fabs(the_car->I.v[0]) + 3.3) / 2.0 * fabs(the_car->omega.v[0]);
|
|
abs_omega_y = (fabs(the_car->I.v[1]) + 3.57) / 2.0 * fabs(the_car->omega.v[1]);
|
|
abs_omega_z = (fabs(the_car->I.v[2]) + 0.44) / 2.0 * fabs(the_car->omega.v[2]);
|
|
spinning_wildly = abs_omega_x > 26.4 || abs_omega_y > 49.98 || abs_omega_z > 3.52;
|
|
if (spinning_wildly && the_time - gLast_cunning_stunt > 10000) {
|
|
if (gWild_start
|
|
&& (!the_car->last_special_volume || the_car->last_special_volume->gravity_multiplier == 1.0)) {
|
|
if (the_time - gWild_start >= 500) {
|
|
DoFancyHeadup(9);
|
|
EarnCredits(gCunning_stunt_bonus[gProgram_state.skill_level]);
|
|
gLast_cunning_stunt = the_time;
|
|
gOn_me_wheels_start = 0;
|
|
gQuite_wild_end = 0;
|
|
gQuite_wild_start = 0;
|
|
gWoz_upside_down_at_all = 0;
|
|
}
|
|
} else {
|
|
gWild_start = the_time;
|
|
}
|
|
} else {
|
|
gWild_start = 0;
|
|
spinning_mildly = abs_omega_x > 1.65 || abs_omega_z > 0.22;
|
|
if (the_car->number_of_wheels_on_ground <= 3) {
|
|
gOn_me_wheels_start = 0;
|
|
if (the_car->number_of_wheels_on_ground || !spinning_mildly) {
|
|
gQuite_wild_end = the_time;
|
|
} else {
|
|
if (!gQuite_wild_start) {
|
|
gQuite_wild_start = the_time;
|
|
}
|
|
if (the_car->car_master_actor->t.t.mat.m[1][1] < -0.80000001) {
|
|
gWoz_upside_down_at_all = the_time;
|
|
}
|
|
}
|
|
} else {
|
|
if (!gQuite_wild_end) {
|
|
gQuite_wild_end = the_time;
|
|
}
|
|
if (gQuite_wild_start
|
|
&& the_time - gLast_cunning_stunt > 10000
|
|
&& gQuite_wild_end - gQuite_wild_start >= 2000
|
|
&& gWoz_upside_down_at_all >= gQuite_wild_start
|
|
&& gWoz_upside_down_at_all <= gQuite_wild_end
|
|
&& (gOn_me_wheels_start || the_time - gQuite_wild_end < 300)) {
|
|
if (gOn_me_wheels_start) {
|
|
if (the_time - gOn_me_wheels_start > 500
|
|
&& (!the_car->last_special_volume
|
|
|| the_car->last_special_volume->gravity_multiplier == 1.0)) {
|
|
DoFancyHeadup(9);
|
|
EarnCredits(gCunning_stunt_bonus[gProgram_state.skill_level]);
|
|
gLast_cunning_stunt = PDGetTotalTime();
|
|
gQuite_wild_end = 0;
|
|
gQuite_wild_start = 0;
|
|
gOn_me_wheels_start = 0;
|
|
gWoz_upside_down_at_all = 0;
|
|
}
|
|
} else {
|
|
gOn_me_wheels_start = the_time;
|
|
}
|
|
} else {
|
|
gQuite_wild_end = 0;
|
|
gQuite_wild_start = 0;
|
|
gOn_me_wheels_start = 0;
|
|
gWoz_upside_down_at_all = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (the_car->driver != eDriver_local_human && the_car->car_model_variable) {
|
|
distance_from_camera = (car_x - gCamera_to_world.m[3][0])
|
|
* (car_x - gCamera_to_world.m[3][0])
|
|
+ (car_z - gCamera_to_world.m[3][2])
|
|
* (car_z - gCamera_to_world.m[3][2])
|
|
+ (the_car->car_master_actor->t.t.mat.m[3][1] - gCamera_to_world.m[3][1])
|
|
* (the_car->car_master_actor->t.t.mat.m[3][1] - gCamera_to_world.m[3][1]);
|
|
|
|
distance_from_camera = distance_from_camera / gCar_simplification_factor[gGraf_spec_index][gCar_simplification_level];
|
|
if (gNet_mode && gNet_players[gIt_or_fox].car == the_car) {
|
|
distance_from_camera = 0.0;
|
|
}
|
|
for (i = 0; the_car->car_actor_count > i; i++) {
|
|
if (the_car->car_model_actors[i].min_distance_squared <= distance_from_camera) {
|
|
SwitchCarActor(the_car, i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (the_car->screen_material) {
|
|
the_material = NULL;
|
|
if (the_car->last_special_volume && the_car->last_special_volume->screen_material) {
|
|
if (gAction_replay_mode && the_car->last_special_volume == gDefault_water_spec_vol) {
|
|
if (gProgram_state.current_depth_effect.type == eDepth_effect_fog) {
|
|
the_material = gProgram_state.standard_screen_fog;
|
|
} else if (gProgram_state.current_depth_effect.sky_texture) {
|
|
the_material = gProgram_state.standard_screen;
|
|
} else {
|
|
the_material = gProgram_state.standard_screen_dark;
|
|
}
|
|
} else {
|
|
the_material = the_car->last_special_volume->screen_material;
|
|
}
|
|
} else if (gProgram_state.current_depth_effect.type == eDepth_effect_fog) {
|
|
the_material = gProgram_state.standard_screen_fog;
|
|
} else if (gProgram_state.current_depth_effect.sky_texture) {
|
|
the_material = gProgram_state.standard_screen;
|
|
} else {
|
|
the_material = gProgram_state.standard_screen_dark;
|
|
}
|
|
update_mat = 0;
|
|
if (the_material && the_car->screen_material_source != the_material) {
|
|
the_car->screen_material->flags = the_material->flags;
|
|
the_car->screen_material->ka = the_material->ka;
|
|
the_car->screen_material->kd = the_material->kd;
|
|
the_car->screen_material->ks = the_material->ks;
|
|
the_car->screen_material->power = the_material->power;
|
|
the_car->screen_material->index_base = the_material->index_base;
|
|
the_car->screen_material->index_range = the_material->index_range;
|
|
the_car->screen_material->colour_map = the_material->colour_map;
|
|
|
|
the_car->screen_material->map_transform = the_material->map_transform;
|
|
the_car->screen_material->index_shade = gRender_shade_table;
|
|
the_car->screen_material_source = the_material;
|
|
update_mat = 1;
|
|
}
|
|
if (the_car->screen_material->colour_map) {
|
|
the_car->screen_material->map_transform.m[2][0] = fmod(car_x, 1.0);
|
|
the_car->screen_material->map_transform.m[2][1] = fmod(car_z, 1.0);
|
|
if (!update_mat) {
|
|
BrMaterialUpdate(the_car->screen_material, 1u);
|
|
}
|
|
}
|
|
if (update_mat) {
|
|
BrMaterialUpdate(the_car->screen_material, 0x7FFFu);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// IDA: void __cdecl ResetCarScreens()
|
|
void ResetCarScreens() {
|
|
int cat;
|
|
int car_count;
|
|
int i;
|
|
tCar_spec* the_car;
|
|
LOG_TRACE("()");
|
|
STUB();
|
|
}
|
|
|
|
// IDA: tCar_spec* __cdecl GetRaceLeader()
|
|
tCar_spec* GetRaceLeader() {
|
|
int i;
|
|
int score;
|
|
tCar_spec* car;
|
|
LOG_TRACE("()");
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __cdecl AmIGettingBoredWatchingCameraSpin()
|
|
void AmIGettingBoredWatchingCameraSpin() {
|
|
static tU32 time_of_death;
|
|
static tU32 headup_timer;
|
|
tCar_spec* car;
|
|
char s[256];
|
|
LOG_TRACE("()");
|
|
|
|
STUB_ONCE();
|
|
}
|
|
|
|
// IDA: void __cdecl ViewNetPlayer()
|
|
void ViewNetPlayer() {
|
|
LOG_TRACE("()");
|
|
|
|
if (gOpponent_viewing_mode) {
|
|
if (gProgram_state.cockpit_on) {
|
|
ToggleCockpit();
|
|
}
|
|
gNet_player_to_view_index++;
|
|
if (gNumber_of_net_players <= gNet_player_to_view_index) {
|
|
gNet_player_to_view_index = -1;
|
|
}
|
|
if (gNet_player_to_view_index < 0) {
|
|
gCar_to_view = GetRaceLeader();
|
|
} else {
|
|
gCar_to_view = gNet_players[gNet_player_to_view_index].car;
|
|
}
|
|
gCamera_yaw = 0;
|
|
InitialiseExternalCamera();
|
|
PositionExternalCamera(gCar_to_view, 200u);
|
|
}
|
|
}
|
|
|
|
// IDA: void __cdecl ViewOpponent()
|
|
void ViewOpponent() {
|
|
static int n;
|
|
LOG_TRACE("()");
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __cdecl ToggleCarToCarCollisions()
|
|
void ToggleCarToCarCollisions() {
|
|
LOG_TRACE("()");
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __cdecl SwapCar()
|
|
void SwapCar() {
|
|
LOG_TRACE("()");
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __cdecl AdjustDownForce()
|
|
void AdjustDownForce() {
|
|
char s[100];
|
|
tCar_spec* c;
|
|
LOG_TRACE("()");
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __cdecl FreezeMechanics()
|
|
void FreezeMechanics() {
|
|
LOG_TRACE("()");
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __cdecl PutOpponentsInNeutral()
|
|
void PutOpponentsInNeutral() {
|
|
LOG_TRACE("()");
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __cdecl SetPanningFieldOfView()
|
|
void SetPanningFieldOfView() {
|
|
br_camera* camera_ptr;
|
|
LOG_TRACE("()");
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall CheckDisablePlingMaterials(tCar_spec *pCar@<EAX>)
|
|
void CheckDisablePlingMaterials(tCar_spec* pCar) {
|
|
br_matrix34* mat;
|
|
br_scalar height;
|
|
int i;
|
|
LOG_TRACE("(%p)", pCar);
|
|
STUB_ONCE();
|
|
}
|
|
|
|
// IDA: void __usercall PositionExternalCamera(tCar_spec *c@<EAX>, tU32 pTime@<EDX>)
|
|
void PositionExternalCamera(tCar_spec* c, tU32 pTime) {
|
|
static int old_camera_mode;
|
|
br_camera* camera_ptr;
|
|
LOG_TRACE("(%p, %d)", c, pTime);
|
|
|
|
camera_ptr = (br_camera*)gCamera->type_data;
|
|
CheckCameraHither();
|
|
AmIGettingBoredWatchingCameraSpin();
|
|
if ((!gAction_replay_mode || gAction_replay_camera_mode == eAction_replay_standard) && old_camera_mode != -1) {
|
|
camera_ptr->field_of_view = BrDegreeToAngle(gCamera_angle);
|
|
old_camera_mode = -1;
|
|
}
|
|
if (!gProgram_state.cockpit_on) {
|
|
if (gOpponent_viewing_mode && gAction_replay_mode) {
|
|
c = &gProgram_state.current_car;
|
|
} else {
|
|
c = gCar_to_view;
|
|
}
|
|
if (c->car_master_actor->t.t.mat.m[3][0] <= 500.0) {
|
|
if (gAction_replay_mode && gAction_replay_camera_mode) {
|
|
LOG_PANIC("%d, %d", gAction_replay_mode, gAction_replay_camera_mode);
|
|
if (gAction_replay_camera_mode == eAction_replay_action && (CheckDisablePlingMaterials(c), IncidentCam(c, pTime))) {
|
|
SetPanningFieldOfView();
|
|
EnablePlingMaterials();
|
|
old_camera_mode = gAction_replay_camera_mode;
|
|
} else {
|
|
CheckDisablePlingMaterials(c);
|
|
SetPanningFieldOfView();
|
|
if (gAction_replay_camera_mode != old_camera_mode) {
|
|
SetUpPanningCamera(c);
|
|
old_camera_mode = gAction_replay_camera_mode;
|
|
}
|
|
PanningExternalCamera(c, pTime);
|
|
EnablePlingMaterials();
|
|
}
|
|
} else {
|
|
NormalPositionExternalCamera(c, pTime);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall CameraBugFix(tCar_spec *c@<EAX>, tU32 pTime@<EDX>)
|
|
void CameraBugFix(tCar_spec* c, tU32 pTime) {
|
|
br_matrix34 mat;
|
|
br_matrix34* m2;
|
|
br_vector3 tv;
|
|
LOG_TRACE("(%p, %d)", c, pTime);
|
|
STUB_ONCE();
|
|
}
|
|
|
|
// IDA: int __usercall PossibleRemoveNonCarFromWorld@<EAX>(br_actor *pActor@<EAX>)
|
|
int PossibleRemoveNonCarFromWorld(br_actor* pActor) {
|
|
tU8 cx;
|
|
tU8 cz;
|
|
tTrack_spec* track_spec;
|
|
LOG_TRACE("(%p)", pActor);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall PutNonCarBackInWorld(br_actor *pActor@<EAX>)
|
|
void PutNonCarBackInWorld(br_actor* pActor) {
|
|
tU8 cx;
|
|
tU8 cz;
|
|
tTrack_spec* track_spec;
|
|
LOG_TRACE("(%p)", pActor);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: int __usercall IncidentCam@<EAX>(tCar_spec *c@<EAX>, tU32 pTime@<EDX>)
|
|
int IncidentCam(tCar_spec* c, tU32 pTime) {
|
|
br_matrix34* m2;
|
|
br_matrix34 mat;
|
|
br_vector3 tv;
|
|
br_vector3 tv2;
|
|
br_vector3 perp;
|
|
br_vector3 vertical;
|
|
br_vector3 murderer_pos;
|
|
br_scalar ts;
|
|
tCar_spec* car2;
|
|
static tU32 next_incident_time;
|
|
static tIncident_type type;
|
|
static float severity;
|
|
static tIncident_info info;
|
|
static int random;
|
|
static int count;
|
|
br_scalar temp;
|
|
br_vector3 old_cam_pos;
|
|
int removed;
|
|
LOG_TRACE("(%p, %d)", c, pTime);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: int __usercall MoveCamToIncident@<EAX>(tCar_spec *c@<EAX>, tIncident_type *type@<EDX>, float *severity@<EBX>, tIncident_info *info@<ECX>, tU32 *next_incident_time)
|
|
int MoveCamToIncident(tCar_spec* c, tIncident_type* type, float* severity, tIncident_info* info, tU32* next_incident_time) {
|
|
tU32 next_incident_time2;
|
|
tU32 t;
|
|
tIncident_type type2;
|
|
float severity2;
|
|
tIncident_info info2;
|
|
br_vector3 pos;
|
|
br_vector3 left;
|
|
br_vector3 right;
|
|
br_vector3 vertical;
|
|
br_vector3 tv;
|
|
br_vector3 tv2;
|
|
br_vector3 perp;
|
|
int test;
|
|
LOG_TRACE("(%p, %p, %p, %p, %p)", c, type, severity, info, next_incident_time);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall PanningExternalCamera(tCar_spec *c@<EAX>, tU32 pTime@<EDX>)
|
|
void PanningExternalCamera(tCar_spec* c, tU32 pTime) {
|
|
br_matrix34* m2;
|
|
br_matrix34* m1;
|
|
br_vector3 tv;
|
|
br_scalar ts;
|
|
static int inside_camera_zone;
|
|
LOG_TRACE("(%p, %d)", c, pTime);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: int __usercall CheckForWall@<EAX>(br_vector3 *start@<EAX>, br_vector3 *end@<EDX>)
|
|
int CheckForWall(br_vector3* start, br_vector3* end) {
|
|
br_vector3 dir;
|
|
br_material* material;
|
|
br_vector3 normal;
|
|
br_scalar d;
|
|
LOG_TRACE("(%p, %p)", start, end);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall SetUpPanningCamera(tCar_spec *c@<EAX>)
|
|
void SetUpPanningCamera(tCar_spec* c) {
|
|
br_vector3 pos;
|
|
br_vector3 perp;
|
|
br_vector3 dir;
|
|
br_vector3 tv;
|
|
br_vector3 tv2;
|
|
br_scalar ts;
|
|
tU32 time;
|
|
tU32 t;
|
|
tU32 t2;
|
|
tU32 time_step;
|
|
br_matrix34* m2;
|
|
br_matrix34* m1;
|
|
br_vector3 left;
|
|
br_vector3 right;
|
|
br_vector3 car_centre;
|
|
int left_score;
|
|
int right_score;
|
|
LOG_TRACE("(%p)", c);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall SaveCameraPosition(int i@<EAX>)
|
|
void SaveCameraPosition(int i) {
|
|
LOG_TRACE("(%d)", i);
|
|
|
|
if (gSave_camera[i].saved != 1) {
|
|
gSave_camera[i].zoom = gCamera_zoom;
|
|
gSave_camera[i].yaw = gCamera_yaw;
|
|
gSave_camera[i].saved = 1;
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall RestoreCameraPosition(int i@<EAX>)
|
|
void RestoreCameraPosition(int i) {
|
|
LOG_TRACE("(%d)", i);
|
|
|
|
if (gSave_camera[i].saved != 0) {
|
|
gCamera_zoom = gSave_camera[i].zoom;
|
|
gCamera_yaw = gSave_camera[i].yaw;
|
|
gSave_camera[i].saved = 0;
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall NormalPositionExternalCamera(tCar_spec *c@<EAX>, tU32 pTime@<EDX>)
|
|
void NormalPositionExternalCamera(tCar_spec* c, tU32 pTime) {
|
|
br_matrix34* m2;
|
|
br_matrix34* m1;
|
|
br_scalar time;
|
|
br_scalar ts;
|
|
br_scalar ts2;
|
|
br_scalar dist;
|
|
br_scalar height_inc;
|
|
br_scalar l;
|
|
br_scalar frac;
|
|
br_vector3 vn;
|
|
br_vector3 a;
|
|
br_vector3 b;
|
|
br_vector3 tv;
|
|
br_angle yaw;
|
|
br_angle theta;
|
|
br_scalar d;
|
|
int face;
|
|
int i;
|
|
int swoop;
|
|
int manual_swing;
|
|
int manual_zoom;
|
|
br_vector3 old_camera_pos;
|
|
br_scalar scale;
|
|
LOG_TRACE("(%p, %d)", c, pTime);
|
|
|
|
m1 = &gCamera->t.t.mat;
|
|
m2 = &c->car_master_actor->t.t.mat;
|
|
swoop = gCountdown && c->pos.v[1] + 0.001 < gCamera_height;
|
|
manual_swing = gOld_yaw__car != gCamera_yaw || swoop;
|
|
manual_zoom = (double)gOld_zoom != gCamera_zoom;
|
|
old_camera_pos = *(br_vector3*)&m1->m[3][0];
|
|
if (!gProgram_state.cockpit_on) {
|
|
if (swoop) {
|
|
gCamera_yaw = 0;
|
|
manual_swing = 1;
|
|
}
|
|
if (fabs(c->speedo_speed) > 0.0006f && gCamera_mode > 0) {
|
|
gCamera_mode = -1;
|
|
gCamera_sign = m2->m[2][1] * c->direction.v[1]
|
|
+ m2->m[2][2] * c->direction.v[2]
|
|
+ m2->m[2][0] * c->direction.v[0]
|
|
> 0.0;
|
|
}
|
|
if (c->frame_collision_flag && gCamera_mode != -2) {
|
|
gCamera_mode = 1;
|
|
}
|
|
if (gCar_flying || gCamera_reset || gCamera_mode == -2) {
|
|
gCamera_mode = 0;
|
|
}
|
|
d = sqrt(gCamera_zoom) + 0.57971013;
|
|
if (!gCamera_mode || gCamera_mode == -1) {
|
|
vn = c->direction;
|
|
MoveWithWheels(c, &vn, manual_swing);
|
|
vn.v[1] = 0.0;
|
|
scale = sqrt(vn.v[2] * vn.v[2] + 0.0 * 0.0 + vn.v[0] * vn.v[0]);
|
|
if (scale <= 2.3841858e-7) {
|
|
vn.v[0] = 1.0;
|
|
vn.v[1] = 0.0;
|
|
vn.v[2] = 0.0;
|
|
} else {
|
|
scale = 1.0 / scale;
|
|
vn.v[0] = vn.v[0] * scale;
|
|
vn.v[1] = vn.v[1] * scale;
|
|
vn.v[2] = vn.v[2] * scale;
|
|
}
|
|
if (gCar_flying) {
|
|
gCamera_sign = 0;
|
|
}
|
|
SwingCamera(c, m2, m1, &vn, pTime);
|
|
a.v[0] = vn.v[0] * d;
|
|
a.v[1] = vn.v[1] * d;
|
|
a.v[2] = vn.v[2] * d;
|
|
m1->m[3][0] = c->pos.v[0] - a.v[0];
|
|
m1->m[3][1] = c->pos.v[1] - a.v[1];
|
|
m1->m[3][2] = c->pos.v[2] - a.v[2];
|
|
gView_direction = vn;
|
|
}
|
|
if (gCamera_mode == 1) {
|
|
if (manual_swing || manual_zoom) {
|
|
old_camera_pos = gCamera_pos_before_collide;
|
|
}
|
|
a.v[0] = c->pos.v[0] - old_camera_pos.v[0];
|
|
a.v[1] = c->pos.v[1] - old_camera_pos.v[1];
|
|
a.v[2] = c->pos.v[2] - old_camera_pos.v[2];
|
|
a.v[1] = 0.0;
|
|
if (manual_swing) {
|
|
DrVector3RotateY(&a, (gCamera_sign == 0 ? 1 : -1) * (gCamera_yaw - gOld_yaw__car));
|
|
gCamera_yaw = gOld_yaw__car;
|
|
}
|
|
scale = sqrt(a.v[1] * a.v[1] + a.v[2] * a.v[2] + a.v[0] * a.v[0]);
|
|
if (scale <= 2.3841858e-7) {
|
|
vn.v[0] = 1.0;
|
|
vn.v[1] = 0.0;
|
|
vn.v[2] = 0.0;
|
|
} else {
|
|
scale = 1.0 / scale;
|
|
vn.v[0] = a.v[0] * scale;
|
|
vn.v[1] = a.v[1] * scale;
|
|
vn.v[2] = a.v[2] * scale;
|
|
}
|
|
gView_direction = vn;
|
|
vn.v[0] = -d * vn.v[0];
|
|
vn.v[1] = vn.v[1] * -d;
|
|
vn.v[2] = vn.v[2] * -d;
|
|
a.v[0] = a.v[0] + vn.v[0];
|
|
a.v[1] = a.v[1] + vn.v[1];
|
|
a.v[2] = a.v[2] + vn.v[2];
|
|
dist = sqrt(a.v[1] * a.v[1] + a.v[2] * a.v[2] + a.v[0] * a.v[0]);
|
|
l = (double)pTime / 1000.0 * (dist + 1.0) / dist;
|
|
if (l < 1.0f && a.v[2] * vn.v[2] + a.v[1] * vn.v[1] + a.v[0] * vn.v[0] > 0.0) {
|
|
a.v[0] = (l - 1.0) * a.v[0];
|
|
a.v[1] = (l - 1.0) * a.v[1];
|
|
a.v[2] = (l - 1.0) * a.v[2];
|
|
vn.v[0] = a.v[0] + vn.v[0];
|
|
vn.v[1] = a.v[1] + vn.v[1];
|
|
vn.v[2] = a.v[2] + vn.v[2];
|
|
}
|
|
m1->m[3][0] = c->pos.v[0] + vn.v[0];
|
|
m1->m[3][1] = c->pos.v[1] + vn.v[1];
|
|
m1->m[3][2] = c->pos.v[2] + vn.v[2];
|
|
}
|
|
height_inc = gCamera_zoom * gCamera_zoom + 0.30000001;
|
|
time = (double)pTime * 0.001;
|
|
if (!gCamera_frozen || gAction_replay_mode) {
|
|
if (pTime < 5000) {
|
|
if (swoop) {
|
|
if (time > 0.2) {
|
|
time = 0.2;
|
|
}
|
|
gCamera_height -= time * 5.0;
|
|
if (gCamera_height < c->pos.v[1]) {
|
|
gCamera_height = c->pos.v[1];
|
|
}
|
|
} else {
|
|
gCamera_height = time * 5.0 * c->pos.v[1] + gCamera_height;
|
|
gCamera_height = gCamera_height / (time * 5.0 + 1.0);
|
|
}
|
|
} else {
|
|
gCamera_height = c->pos.v[1];
|
|
}
|
|
}
|
|
l = c->direction.v[1] * d;
|
|
if (l > 0) {
|
|
if (c->pos.v[1] - l - height_inc / 2.0 > gCamera_height) {
|
|
gCamera_height = c->pos.v[1] - l - height_inc / 2.0;
|
|
}
|
|
}
|
|
|
|
m1->m[3][1] = height_inc + gCamera_height;
|
|
gCamera_pos_before_collide = *(br_vector3*)&m1->m[3][0];
|
|
CollideCameraWithOtherCars(&c->pos, (br_vector3*)m1->m[3]);
|
|
if (manual_swing || manual_zoom) {
|
|
CollideCamera2(&c->pos, (br_vector3*)m1->m[3], &old_camera_pos, 1);
|
|
} else {
|
|
CollideCamera2(&c->pos, (br_vector3*)m1->m[3], &old_camera_pos, 0);
|
|
}
|
|
if (gCamera_has_collided && swoop) {
|
|
gCamera_height = c->pos.v[1];
|
|
}
|
|
PointCameraAtCar(c, m2, m1);
|
|
}
|
|
gOld_yaw__car = gCamera_yaw;
|
|
gOld_zoom = (br_angle)gCamera_zoom;
|
|
}
|
|
|
|
// IDA: void __usercall MoveWithWheels(tCar_spec *c@<EAX>, br_vector3 *vn@<EDX>, int manual_swing@<EBX>)
|
|
void MoveWithWheels(tCar_spec* c, br_vector3* vn, int manual_swing) {
|
|
br_angle yaw;
|
|
br_angle theta;
|
|
static int move_with_wheels;
|
|
LOG_TRACE("(%p, %p, %d)", c, vn, manual_swing);
|
|
|
|
if (c->speed <= 0.000099999997 && !gCamera_mode) {
|
|
if (manual_swing) {
|
|
if (gCamera_yaw <= 32760u) {
|
|
yaw = gCamera_yaw;
|
|
} else {
|
|
yaw = gCamera_yaw - 32760;
|
|
}
|
|
if (yaw <= 8190u || yaw >= 24570u) {
|
|
if (!move_with_wheels) {
|
|
theta = BrRadianToAngle(atan2(c->wpos[0].v[2] * c->curvature, 1.0));
|
|
gCamera_yaw -= (-2 * gCamera_sign + 1) * theta;
|
|
move_with_wheels = 1;
|
|
}
|
|
} else if (move_with_wheels) {
|
|
theta = BrRadianToAngle(atan2(c->wpos[0].v[2] * c->curvature, 1.0));
|
|
gCamera_yaw += (-2 * gCamera_sign + 1) * theta;
|
|
move_with_wheels = 0;
|
|
}
|
|
}
|
|
if (move_with_wheels) {
|
|
if (!gCar_flying) {
|
|
theta = BrRadianToAngle(atan2(c->wpos[0].v[2] * c->curvature, 1.0));
|
|
DrVector3RotateY(vn, theta);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall SwingCamera(tCar_spec *c@<EAX>, br_matrix34 *m1@<EDX>, br_matrix34 *m2@<EBX>, br_vector3 *vn@<ECX>, tU32 pTime)
|
|
void SwingCamera(tCar_spec* c, br_matrix34* m1, br_matrix34* m2, br_vector3* vn, tU32 pTime) {
|
|
int i;
|
|
br_scalar ts;
|
|
br_angle yaw;
|
|
br_angle theta;
|
|
br_angle alpha;
|
|
br_scalar sin_dtheta;
|
|
br_scalar cos_dtheta;
|
|
br_scalar sign;
|
|
int manual_swing;
|
|
static br_angle omega = 0;
|
|
static int elapsed_time = -1;
|
|
static br_vector3 old_vn;
|
|
LOG_TRACE("(%p, %p, %p, %p, %d)", c, m1, m2, vn, pTime);
|
|
|
|
manual_swing = gOld_yaw__car != gCamera_yaw;
|
|
if (elapsed_time > 500) {
|
|
elapsed_time = -1;
|
|
}
|
|
if (elapsed_time >= 0) {
|
|
elapsed_time += pTime;
|
|
}
|
|
sign = -(m1->m[2][0] * vn->v[0] + m1->m[2][1] * vn->v[1] + m1->m[2][2] * vn->v[2]);
|
|
ts = vn->v[1] * old_vn.v[1] + vn->v[2] * old_vn.v[2] + vn->v[0] * old_vn.v[0];
|
|
|
|
old_vn = *vn;
|
|
if ((sign < 0.0) == gCamera_sign) {
|
|
elapsed_time = -1;
|
|
} else if (ts <= 0.0 || elapsed_time >= 0) {
|
|
if (elapsed_time < 0) {
|
|
elapsed_time = 0;
|
|
}
|
|
if (elapsed_time < 500 && sign <= 0.0) {
|
|
vn->v[0] = -vn->v[0];
|
|
vn->v[1] = -vn->v[1];
|
|
vn->v[2] = -vn->v[2];
|
|
} else {
|
|
elapsed_time = 500;
|
|
if (sign <= 0.0) {
|
|
ts = 0.0005999999999999999;
|
|
} else {
|
|
ts = 0.0001;
|
|
}
|
|
if (fabs(c->speedo_speed) <= ts || gCar_flying) {
|
|
vn->v[0] = -vn->v[0];
|
|
vn->v[1] = -vn->v[1];
|
|
vn->v[2] = -vn->v[2];
|
|
} else {
|
|
gCamera_sign = gCamera_sign == 0;
|
|
omega = BrDegreeToAngle(pTime * 0.03);
|
|
if (gCamera_yaw <= 32760) {
|
|
yaw = gCamera_yaw;
|
|
} else {
|
|
yaw = gCamera_yaw - 32760;
|
|
}
|
|
if ((uint16_t)(gCamera_yaw + 16380) <= 32760) {
|
|
if (yaw > 8190 && yaw < 24570) {
|
|
gCamera_yaw = 32760 - gCamera_yaw;
|
|
}
|
|
} else {
|
|
gCamera_yaw = 32760 - gCamera_yaw;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
gCamera_sign = gCamera_sign == 0;
|
|
if (gCamera_yaw <= 32760) {
|
|
yaw = gCamera_yaw;
|
|
} else {
|
|
yaw = gCamera_yaw - 32760;
|
|
}
|
|
if (yaw > 8190 && yaw < 24570) {
|
|
gCamera_yaw = -gCamera_yaw;
|
|
}
|
|
}
|
|
if (gCamera_sign) {
|
|
yaw = -gCamera_yaw;
|
|
} else {
|
|
yaw = gCamera_yaw;
|
|
}
|
|
if (!gCar_flying) {
|
|
DrVector3RotateY(vn, yaw);
|
|
}
|
|
sin_dtheta = 0.0;
|
|
br_scalar v16 = vn->v[0] * gView_direction.v[2] - vn->v[2] * gView_direction.v[0];
|
|
br_scalar v17 = vn->v[0] * gView_direction.v[0] + vn->v[2] * gView_direction.v[2];
|
|
|
|
br_angle v8 = BrRadianToAngle(sqrt(c->omega.v[2] * c->omega.v[2] + c->omega.v[0] * c->omega.v[0] + c->omega.v[1] * c->omega.v[1]) * pTime / 1000.0);
|
|
sin_dtheta = sin(BrAngleToRadian(v8)) + 0.1;
|
|
|
|
if (omega || gCamera_reset || (c->speed < 0.000099999997 && !manual_swing) || gCamera_mode == -1 || (v17 > 0.0 && !manual_swing && fabs(v16) > sin_dtheta)) {
|
|
if (!gCar_flying) {
|
|
theta = BrRadianToAngle(asin(sin_dtheta));
|
|
if (omega < theta) {
|
|
omega = theta;
|
|
}
|
|
if (!omega) {
|
|
omega = BrDegreeToAngle(pTime * 0.03); // (__int64)((double)(int)pTime * 0.03 * 182.0444444444445);
|
|
}
|
|
cos_dtheta = cos(BrAngleToRadian(omega));
|
|
if (cos_dtheta <= v17) {
|
|
omega = 0;
|
|
gCamera_mode = 0;
|
|
} else {
|
|
ts = BrAngleToRadian(omega);
|
|
if (v16 <= 0.0) {
|
|
vn->v[0] = cos(ts) * gView_direction.v[0] - sin(ts) * gView_direction.v[2];
|
|
vn->v[2] = sin(ts) * gView_direction.v[0] + cos(ts) * gView_direction.v[2];
|
|
} else {
|
|
vn->v[0] = sin(ts) * gView_direction.v[2] + cos(ts) * gView_direction.v[0];
|
|
vn->v[2] = cos(ts) * gView_direction.v[2] - sin(ts) * gView_direction.v[0];
|
|
}
|
|
omega += BrDegreeToAngle(pTime * 0.03);
|
|
if (BrDegreeToAngle(pTime * 0.1) < omega) {
|
|
omega = BrDegreeToAngle(pTime * 0.1);
|
|
}
|
|
if (omega < theta) {
|
|
omega = theta;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall PointCameraAtCar(tCar_spec *c@<EAX>, br_matrix34 *m1@<EDX>, br_matrix34 *m2@<EBX>)
|
|
void PointCameraAtCar(tCar_spec* c, br_matrix34* m1, br_matrix34* m2) {
|
|
br_vector3 vn;
|
|
br_vector3 tv;
|
|
br_vector3 tv2;
|
|
br_scalar dist;
|
|
br_scalar frac;
|
|
br_angle theta;
|
|
br_vector3* pos;
|
|
br_camera* camera_ptr;
|
|
br_angle off_centre_angle;
|
|
int swoop;
|
|
br_scalar scale;
|
|
LOG_TRACE("(%p, %p, %p)", c, m1, m2);
|
|
|
|
camera_ptr = (br_camera*)gCamera->type_data;
|
|
theta = camera_ptr->field_of_view / 5;
|
|
swoop = gCountdown && c->pos.v[1] + 0.0099999998 < gCamera_height;
|
|
if (swoop) {
|
|
tv.v[0] = gAverage_grid_position.v[0] - c->pos.v[0];
|
|
tv.v[1] = gAverage_grid_position.v[1] - c->pos.v[1];
|
|
tv.v[2] = gAverage_grid_position.v[2] - c->pos.v[2];
|
|
frac = (gCamera_height - c->pos.v[1]) / 10.0;
|
|
tv.v[0] = tv.v[0] * frac;
|
|
tv.v[1] = tv.v[1] * frac;
|
|
tv.v[2] = tv.v[2] * frac;
|
|
tv.v[0] = c->pos.v[0] + tv.v[0];
|
|
tv.v[1] = c->pos.v[1] + tv.v[1];
|
|
tv.v[2] = c->pos.v[2] + tv.v[2];
|
|
pos = &tv;
|
|
theta = (1.0 - frac) * (double)theta;
|
|
} else {
|
|
pos = &c->pos;
|
|
}
|
|
vn.v[0] = c->pos.v[0] - m2->m[3][0];
|
|
vn.v[2] = c->pos.v[2] - m2->m[3][2];
|
|
scale = sqrt(vn.v[2] * vn.v[2] + 0.0 * 0.0 + vn.v[0] * vn.v[0]);
|
|
if (scale <= 2.3841858e-7) {
|
|
vn.v[0] = 1.0;
|
|
vn.v[1] = 0.0;
|
|
vn.v[2] = 0.0;
|
|
} else {
|
|
scale = 1.0 / scale;
|
|
vn.v[0] *= scale;
|
|
vn.v[1] = 0.0;
|
|
vn.v[2] *= scale;
|
|
}
|
|
m2->m[0][0] = -vn.v[2];
|
|
m2->m[0][1] = 0.0;
|
|
m2->m[0][2] = vn.v[0];
|
|
m2->m[1][0] = 0.0;
|
|
m2->m[1][1] = 1.0;
|
|
m2->m[1][2] = 0.0;
|
|
m2->m[2][0] = -vn.v[0];
|
|
m2->m[2][1] = 0.0;
|
|
m2->m[2][2] = -vn.v[2];
|
|
tv2.v[0] = pos->v[0] - m2->m[3][0];
|
|
tv2.v[1] = pos->v[1] - m2->m[3][1];
|
|
tv2.v[2] = pos->v[2] - m2->m[3][2];
|
|
dist = tv2.v[2] * vn.v[2] + tv2.v[1] * vn.v[1] + tv2.v[0] * vn.v[0];
|
|
BrMatrix34PreRotateX(m2, theta - BrRadianToAngle(atan2(m2->m[3][1] - pos->v[1], dist)));
|
|
}
|
|
|
|
// IDA: void __usercall PointCamera(br_vector3 *pos@<EAX>, br_matrix34 *m2@<EDX>)
|
|
void PointCamera(br_vector3* pos, br_matrix34* m2) {
|
|
br_vector3 vn;
|
|
br_scalar dist;
|
|
br_angle theta;
|
|
br_camera* camera_ptr;
|
|
LOG_TRACE("(%p, %p)", pos, m2);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: int __usercall CollideCamera2@<EAX>(br_vector3 *car_pos@<EAX>, br_vector3 *cam_pos@<EDX>, br_vector3 *old_camera_pos@<EBX>, int manual_move@<ECX>)
|
|
int CollideCamera2(br_vector3* car_pos, br_vector3* cam_pos, br_vector3* old_camera_pos, int manual_move) {
|
|
int i;
|
|
int k;
|
|
br_vector3 a;
|
|
br_vector3 b;
|
|
br_vector3 vn;
|
|
br_vector3 tv;
|
|
br_vector3 tv2;
|
|
br_scalar l;
|
|
br_scalar d;
|
|
br_scalar ts;
|
|
br_scalar ts2;
|
|
br_scalar dist;
|
|
br_scalar hither;
|
|
br_angle theta;
|
|
tBounds bnds;
|
|
br_matrix34 mat;
|
|
br_material* material;
|
|
br_scalar alpha;
|
|
br_scalar sa;
|
|
br_scalar sb;
|
|
br_scalar sc;
|
|
tFace_ref face_list[3];
|
|
LOG_TRACE("(%p, %p, %p, %d)", car_pos, cam_pos, old_camera_pos, manual_move);
|
|
|
|
#ifdef DETHRACE_FIX_BUGS
|
|
ts2 = 0.f;
|
|
#endif
|
|
hither = ((br_camera*)gCamera->type_data)->hither_z * 3.0;
|
|
gCamera_has_collided = 0;
|
|
for (i = 0; i < 1; i++) {
|
|
tv.v[0] = cam_pos->v[0] - car_pos->v[0];
|
|
tv.v[1] = cam_pos->v[1] - car_pos->v[1];
|
|
tv.v[2] = cam_pos->v[2] - car_pos->v[2];
|
|
dist = sqrt(tv.v[1] * tv.v[1] + tv.v[2] * tv.v[2] + tv.v[0] * tv.v[0]);
|
|
tv.v[0] = tv.v[0] * 1.2;
|
|
tv.v[1] = tv.v[1] * 1.2;
|
|
tv.v[2] = tv.v[2] * 1.2;
|
|
FindFace(car_pos, &tv, &a, &ts, &material);
|
|
if (ts <= 1.0) {
|
|
gCamera_has_collided = 1;
|
|
if (a.v[1] * tv.v[1] + a.v[2] * tv.v[2] + a.v[0] * tv.v[0] > 0.0) {
|
|
a.v[0] = -a.v[0];
|
|
a.v[1] = -a.v[1];
|
|
a.v[2] = -a.v[2];
|
|
}
|
|
if (gCamera_mode == 1 && !manual_move) {
|
|
tv2.v[0] = car_pos->v[0] - old_camera_pos->v[0];
|
|
tv2.v[1] = car_pos->v[1] - old_camera_pos->v[1];
|
|
tv2.v[2] = car_pos->v[2] - old_camera_pos->v[2];
|
|
FindFace(old_camera_pos, &tv2, &b, &ts2, &material);
|
|
if (ts2 > 1.0) {
|
|
*cam_pos = *old_camera_pos;
|
|
return i;
|
|
}
|
|
}
|
|
tv.v[0] = tv.v[0] * ts;
|
|
tv.v[1] = tv.v[1] * ts;
|
|
tv.v[2] = tv.v[2] * ts;
|
|
tv2.v[0] = a.v[0] * hither;
|
|
tv2.v[1] = a.v[1] * hither;
|
|
tv2.v[2] = a.v[2] * hither;
|
|
tv.v[0] = tv2.v[0] + tv.v[0];
|
|
tv.v[1] = tv2.v[1] + tv.v[1];
|
|
tv.v[2] = tv2.v[2] + tv.v[2];
|
|
dist = sqrt(tv.v[1] * tv.v[1] + tv.v[2] * tv.v[2] + tv.v[0] * tv.v[0]);
|
|
cam_pos->v[0] = car_pos->v[0] + tv.v[0];
|
|
cam_pos->v[1] = car_pos->v[1] + tv.v[1];
|
|
cam_pos->v[2] = car_pos->v[2] + tv.v[2];
|
|
if (gMin_camera_car_distance > dist && !i && a.v[1] > -0.7) {
|
|
tv2.v[0] = -a.v[1] * a.v[0];
|
|
tv2.v[1] = -a.v[1] * a.v[1];
|
|
tv2.v[2] = -a.v[1] * a.v[2];
|
|
tv2.v[1] = tv2.v[1] + 1.0;
|
|
if (gProgram_state.current_car.car_master_actor->t.t.mat.m[1][1] < 0.0) {
|
|
tv2.v[0] = -tv2.v[0];
|
|
tv2.v[1] = -tv2.v[1];
|
|
tv2.v[2] = -tv2.v[2];
|
|
}
|
|
d = tv2.v[1] * tv2.v[1] + tv2.v[2] * tv2.v[2] + tv2.v[0] * tv2.v[0];
|
|
l = tv2.v[1] * tv.v[1] + tv2.v[2] * tv.v[2] + tv2.v[0] * tv.v[0];
|
|
alpha = tv.v[1] * tv.v[1]
|
|
+ tv.v[2] * tv.v[2]
|
|
+ tv.v[0] * tv.v[0]
|
|
- gMin_camera_car_distance * gMin_camera_car_distance;
|
|
ts2 = l * l - alpha * d * 4.0;
|
|
if (alpha >= 0 && d != 0.0) {
|
|
sa = (sqrt(ts2) - l) / (d * 2.0);
|
|
tv2.v[0] = tv2.v[0] * sa;
|
|
tv2.v[1] = tv2.v[1] * sa;
|
|
tv2.v[2] = tv2.v[2] * sa;
|
|
FindFace(cam_pos, &tv2, &a, &ts, &material);
|
|
if (ts < 1.0) {
|
|
tv2.v[0] = tv2.v[0] * ts;
|
|
tv2.v[1] = tv2.v[1] * ts;
|
|
tv2.v[2] = tv2.v[2] * ts;
|
|
}
|
|
b.v[0] = tv.v[0];
|
|
b.v[1] = 0.0;
|
|
b.v[2] = tv.v[2];
|
|
dist = sqrt(0.0 * 0.0 + tv.v[2] * tv.v[2] + tv.v[0] * tv.v[0]);
|
|
if (alpha <= 2.3841858e-7) {
|
|
b.v[0] = 1.0;
|
|
b.v[1] = 0.0;
|
|
b.v[2] = 0.0;
|
|
} else {
|
|
alpha = 1.0 / dist;
|
|
b.v[0] = b.v[0] * alpha;
|
|
b.v[1] = b.v[1] * alpha;
|
|
b.v[2] = b.v[2] * alpha;
|
|
}
|
|
tv.v[0] = tv2.v[0] + tv.v[0];
|
|
tv.v[1] = tv2.v[1] + tv.v[1];
|
|
tv.v[2] = tv2.v[2] + tv.v[2];
|
|
ts2 = tv.v[1] * b.v[1] + tv.v[2] * b.v[2] + b.v[0] * tv.v[0];
|
|
if (ts2 < 0.029999999 && !gAction_replay_mode) {
|
|
dist = sqrt(tv2.v[1] * tv2.v[1] + tv2.v[2] * tv2.v[2] + tv2.v[0] * tv2.v[0]);
|
|
if (dist <= 2.3841858e-7) {
|
|
tv2.v[0] = 1.0;
|
|
tv2.v[1] = 0.0;
|
|
tv2.v[2] = 0.0;
|
|
} else {
|
|
alpha = 1.0 / dist;
|
|
tv2.v[0] = tv2.v[0] * alpha;
|
|
tv2.v[1] = tv2.v[1] * alpha;
|
|
tv2.v[2] = tv2.v[2] * alpha;
|
|
}
|
|
if (tv2.v[2] * b.v[2] + tv2.v[0] * b.v[0] + tv2.v[1] * b.v[1] < -0.029999999)
|
|
alpha = tv2.v[1] * b.v[1] + tv2.v[2] * b.v[2] + b.v[0] * tv2.v[0];
|
|
alpha = (0.029999999 - ts2) / alpha;
|
|
tv2.v[0] = tv2.v[0] * alpha;
|
|
tv2.v[1] = tv2.v[1] * alpha;
|
|
tv2.v[2] = tv2.v[2] * alpha;
|
|
tv.v[0] = tv2.v[0] + tv.v[0];
|
|
tv.v[1] = tv2.v[1] + tv.v[1];
|
|
tv.v[2] = tv2.v[2] + tv.v[2];
|
|
}
|
|
}
|
|
}
|
|
cam_pos->v[0] = car_pos->v[0] + tv.v[0];
|
|
cam_pos->v[1] = car_pos->v[1] + tv.v[1];
|
|
cam_pos->v[2] = car_pos->v[2] + tv.v[2];
|
|
}
|
|
|
|
bnds.mat = &mat;
|
|
BrMatrix34Identity(&mat);
|
|
tv2.v[0] = hither;
|
|
tv2.v[1] = hither;
|
|
tv2.v[2] = hither;
|
|
bnds.original_bounds.min.v[0] = cam_pos->v[0] - hither;
|
|
bnds.original_bounds.min.v[1] = cam_pos->v[1] - hither;
|
|
bnds.original_bounds.min.v[2] = cam_pos->v[2] - hither;
|
|
bnds.original_bounds.max.v[0] = cam_pos->v[0] + hither;
|
|
bnds.original_bounds.max.v[1] = cam_pos->v[1] + hither;
|
|
bnds.original_bounds.max.v[2] = cam_pos->v[2] + hither;
|
|
k = FindFacesInBox(&bnds, face_list, 3);
|
|
if (k > 0) {
|
|
tv2.v[0] = cam_pos->v[0] - face_list[0].v[0].v[0];
|
|
tv2.v[1] = cam_pos->v[1] - face_list[0].v[0].v[1];
|
|
tv2.v[2] = cam_pos->v[2] - face_list[0].v[0].v[2];
|
|
sa = face_list[0].normal.v[2] * tv2.v[2]
|
|
+ face_list[0].normal.v[1] * tv2.v[1]
|
|
+ face_list[0].normal.v[0] * tv2.v[0];
|
|
// ts2 = sa;
|
|
if (sa < hither && sa >= 0.0) {
|
|
tv2.v[0] = (hither - sa) * face_list[0].normal.v[0];
|
|
tv2.v[1] = (hither - sa) * face_list[0].normal.v[1];
|
|
tv2.v[2] = (hither - sa) * face_list[0].normal.v[2];
|
|
cam_pos->v[0] = cam_pos->v[0] + tv2.v[0];
|
|
cam_pos->v[1] = cam_pos->v[1] + tv2.v[1];
|
|
cam_pos->v[2] = cam_pos->v[2] + tv2.v[2];
|
|
}
|
|
if (k > 1) {
|
|
sb = face_list[1].normal.v[2] * face_list[0].normal.v[2]
|
|
+ face_list[1].normal.v[1] * face_list[0].normal.v[1]
|
|
+ face_list[1].normal.v[0] * face_list[0].normal.v[0];
|
|
if (sb > 0.94999999 && k > 2) {
|
|
face_list[1].normal.v[0] = face_list[2].normal.v[0];
|
|
face_list[1].normal.v[1] = face_list[2].normal.v[1];
|
|
face_list[1].normal.v[2] = face_list[2].normal.v[2];
|
|
face_list[1].v[0].v[0] = face_list[2].v[0].v[0];
|
|
face_list[1].v[0].v[1] = face_list[2].v[0].v[1];
|
|
face_list[1].v[0].v[2] = face_list[2].v[0].v[2];
|
|
sb = face_list[2].normal.v[2] * face_list[0].normal.v[2]
|
|
+ face_list[2].normal.v[1] * face_list[0].normal.v[1]
|
|
+ face_list[2].normal.v[0] * face_list[0].normal.v[0];
|
|
k = 2;
|
|
}
|
|
if (sb <= 0.94999999) {
|
|
tv2.v[0] = cam_pos->v[0] - face_list[1].v[0].v[0];
|
|
tv2.v[1] = cam_pos->v[1] - face_list[1].v[0].v[1];
|
|
tv2.v[2] = cam_pos->v[2] - face_list[1].v[0].v[2];
|
|
sc = face_list[1].normal.v[2] * tv2.v[2]
|
|
+ face_list[1].normal.v[1] * tv2.v[1]
|
|
+ face_list[1].normal.v[0] * tv2.v[0];
|
|
if (sc < hither && sc >= 0.0) {
|
|
sc = face_list[1].normal.v[2] * face_list[0].normal.v[2]
|
|
+ face_list[1].normal.v[1] * face_list[0].normal.v[1]
|
|
+ face_list[1].normal.v[0] * face_list[0].normal.v[0];
|
|
b.v[0] = face_list[0].normal.v[0] * sc;
|
|
b.v[1] = face_list[0].normal.v[1] * sc;
|
|
b.v[2] = face_list[0].normal.v[2] * sc;
|
|
face_list[1].normal.v[0] = face_list[1].normal.v[0] - b.v[0];
|
|
face_list[1].normal.v[1] = face_list[1].normal.v[1] - b.v[1];
|
|
face_list[1].normal.v[2] = face_list[1].normal.v[2] - b.v[2];
|
|
tv2.v[0] = (hither - ts2) * face_list[1].normal.v[0];
|
|
tv2.v[1] = (hither - ts2) * face_list[1].normal.v[1];
|
|
tv2.v[2] = (hither - ts2) * face_list[1].normal.v[2];
|
|
cam_pos->v[0] = cam_pos->v[0] + tv2.v[0];
|
|
cam_pos->v[1] = cam_pos->v[1] + tv2.v[1];
|
|
cam_pos->v[2] = cam_pos->v[2] + tv2.v[2];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
i += k;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
// IDA: int __usercall BoundsTest@<EAX>(br_bounds *bnds@<EAX>, br_vector3 *p@<EDX>)
|
|
int BoundsTest(br_bounds* bnds, br_vector3* p) {
|
|
int j;
|
|
LOG_TRACE("(%p, %p)", bnds, p);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: int __usercall CollideCameraWithOtherCars@<EAX>(br_vector3 *car_pos@<EAX>, br_vector3 *cam_pos@<EDX>)
|
|
int CollideCameraWithOtherCars(br_vector3* car_pos, br_vector3* cam_pos) {
|
|
int i;
|
|
int plane;
|
|
br_scalar ts;
|
|
tCar_spec* c;
|
|
br_vector3 tv;
|
|
br_vector3 pos_car_space;
|
|
br_vector3 dir;
|
|
br_vector3 p;
|
|
br_vector3 n;
|
|
br_bounds bnds;
|
|
LOG_TRACE("(%p, %p)", car_pos, cam_pos);
|
|
|
|
STUB_ONCE();
|
|
return 0;
|
|
}
|
|
|
|
// IDA: void __cdecl InitialiseExternalCamera()
|
|
void InitialiseExternalCamera() {
|
|
br_scalar ts;
|
|
tCar_spec* c;
|
|
br_vector3 r;
|
|
br_angle yaw;
|
|
LOG_TRACE("()");
|
|
|
|
c = gCar_to_view;
|
|
if (!gProgram_state.racing) {
|
|
c = &gProgram_state.current_car;
|
|
}
|
|
gCamera_height = c->pos.v[1];
|
|
BrVector3Set(&gView_direction, c->direction.v[0], 0.0f, c->direction.v[2]);
|
|
BrVector3Normalise(&gView_direction, &gView_direction);
|
|
ts = -BrVector3Dot(&gView_direction, (br_vector3*)c->car_master_actor->t.t.mat.m[2]);
|
|
gCamera_sign = ts < 0;
|
|
gCamera_mode = 0;
|
|
if (gCamera_sign) {
|
|
yaw = -gCamera_yaw;
|
|
} else {
|
|
yaw = gCamera_yaw;
|
|
}
|
|
DrVector3RotateY(&gView_direction, yaw);
|
|
gMin_camera_car_distance = 0.6f;
|
|
gCamera_frozen = 0;
|
|
gCamera_mode = -2;
|
|
if (gCountdown && (gNet_mode == eNet_mode_none || gCurrent_net_game->options.grid_start) && gCountdown > 4) {
|
|
gCamera_height = gCamera_height + 10.0f;
|
|
}
|
|
}
|
|
|
|
// IDA: void __cdecl FreezeCamera()
|
|
void FreezeCamera() {
|
|
LOG_TRACE("()");
|
|
|
|
gCamera_frozen = 1;
|
|
}
|
|
|
|
// IDA: void __usercall FlyCar(tCar_spec *c@<EAX>, br_scalar dt)
|
|
void FlyCar(tCar_spec* c, br_scalar dt) {
|
|
int accflag;
|
|
int turnflag;
|
|
br_vector3 step;
|
|
br_matrix34* mat;
|
|
br_angle theta;
|
|
static br_scalar vel;
|
|
tFace_ref faces[20];
|
|
tBounds bnds;
|
|
LOG_TRACE("(%p, %f)", c, dt);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall DrVector3RotateY(br_vector3 *v@<EAX>, br_angle t@<EDX>)
|
|
void DrVector3RotateY(br_vector3* v, br_angle t) {
|
|
br_scalar c;
|
|
br_scalar s;
|
|
br_scalar ts;
|
|
LOG_TRACE("(%p, %d)", v, t);
|
|
|
|
c = cos(BrAngleToRadian(t));
|
|
s = sin(BrAngleToRadian(t));
|
|
ts = v->v[0] * c + v->v[2] * s;
|
|
v->v[2] = v->v[2] * c - v->v[0] * s;
|
|
v->v[0] = ts;
|
|
}
|
|
|
|
// IDA: void __cdecl CrashCarsTogether(br_scalar dt)
|
|
void CrashCarsTogether(br_scalar dt) {
|
|
int pass;
|
|
int k;
|
|
int i;
|
|
tCollison_data collide_list[32];
|
|
LOG_TRACE("(%f)", dt);
|
|
|
|
STUB_ONCE();
|
|
}
|
|
|
|
// IDA: int __cdecl CrashCarsTogetherSinglePass(br_scalar dt, int pPass, tCollison_data *collide_list)
|
|
int CrashCarsTogetherSinglePass(br_scalar dt, int pPass, tCollison_data* collide_list) {
|
|
int i;
|
|
int j;
|
|
int l;
|
|
int m;
|
|
int n;
|
|
int collided;
|
|
int k;
|
|
int ref1;
|
|
int ref2;
|
|
int c1im;
|
|
int c2im;
|
|
tCollision_info* car_1;
|
|
tCollision_info* car_2;
|
|
tCollision_info* car_3;
|
|
tCollision_info* car_in_middle;
|
|
tCollision_info* car_on_wall;
|
|
LOG_TRACE("(%f, %d, %p)", dt, pPass, collide_list);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall BringCarToAGrindingHalt(tCollision_info *car@<EAX>)
|
|
void BringCarToAGrindingHalt(tCollision_info* car) {
|
|
LOG_TRACE("(%p)", car);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: int __usercall BoundsOverlapTest@<EAX>(br_bounds *b1@<EAX>, br_bounds *b2@<EDX>)
|
|
int BoundsOverlapTest_car(br_bounds* b1, br_bounds* b2) {
|
|
LOG_TRACE("(%p, %p)", b1, b2);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: int __usercall SimpleCarCarCollisionTest@<EAX>(tCollision_info *car1@<EAX>, tCollision_info *car2@<EDX>)
|
|
int SimpleCarCarCollisionTest(tCollision_info* car1, tCollision_info* car2) {
|
|
LOG_TRACE("(%p, %p)", car1, car2);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: int __usercall CollideTwoCarsWithWalls@<EAX>(tCollision_info *car1@<EAX>, tCollision_info *car2@<EDX>, br_scalar dt)
|
|
int CollideTwoCarsWithWalls(tCollision_info* car1, tCollision_info* car2, br_scalar dt) {
|
|
br_vector3 mom1;
|
|
br_vector3 mom2;
|
|
int l;
|
|
int m;
|
|
int n;
|
|
int p;
|
|
int im1;
|
|
int im2;
|
|
LOG_TRACE("(%p, %p, %f)", car1, car2, dt);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: int __usercall CollideTwoCarsRepeatedly@<EAX>(tCollision_info *car1@<EAX>, tCollision_info *car2@<EDX>, br_scalar dt)
|
|
int CollideTwoCarsRepeatedly(tCollision_info* car1, tCollision_info* car2, br_scalar dt) {
|
|
int l;
|
|
int collide;
|
|
br_scalar ts;
|
|
LOG_TRACE("(%p, %p, %f)", car1, car2, dt);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: int __usercall CollideTwoCars@<EAX>(tCollision_info *car1@<EAX>, tCollision_info *car2@<EDX>, int pPass@<EBX>)
|
|
int CollideTwoCars(tCollision_info* car1, tCollision_info* car2, int pPass) {
|
|
int k;
|
|
int old_k;
|
|
int i;
|
|
int j;
|
|
br_scalar dist;
|
|
br_scalar ts;
|
|
br_bounds new_car1_bnds;
|
|
br_bounds new_car2_bnds;
|
|
br_bounds bnds;
|
|
br_matrix34* mat1;
|
|
br_matrix34* mat2;
|
|
br_matrix34* oldmat1;
|
|
br_matrix34* oldmat2;
|
|
br_matrix34 inv_mat1;
|
|
br_matrix34 inv_mat2;
|
|
br_matrix34 inv_oldmat1;
|
|
br_matrix34 inv_oldmat2;
|
|
br_matrix34 car2_to_car1;
|
|
br_matrix34 car1_to_car2;
|
|
br_matrix34 old_car2_to_car1;
|
|
br_matrix34 old_car1_to_car2;
|
|
br_matrix34 car1_to_old_car1;
|
|
br_matrix34 car2_to_old_car2;
|
|
br_vector3 r[16];
|
|
br_vector3 n[16];
|
|
br_vector3 sep;
|
|
br_vector3 tv;
|
|
int add_point;
|
|
static br_vector3 oldr1;
|
|
static br_vector3 oldr2;
|
|
static br_vector3 oldn1;
|
|
static br_vector3 oldn2;
|
|
static int is_old_point_available;
|
|
LOG_TRACE("(%p, %p, %d)", car1, car2, pPass);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: int __usercall GetEdgeEdgeCollisions@<EAX>(br_bounds *pB1@<EAX>, br_bounds *pB2@<EDX>, br_matrix34 *pM21@<EBX>, br_matrix34 *pM12@<ECX>, br_matrix34 *pMo21, br_matrix34 *pMo12, br_matrix34 *pM1o1, br_vector3 *pPoint_list, br_vector3 *pNorm_list, int pMax)
|
|
int GetEdgeEdgeCollisions(br_bounds* pB1, br_bounds* pB2, br_matrix34* pM21, br_matrix34* pM12, br_matrix34* pMo21, br_matrix34* pMo12, br_matrix34* pM1o1, br_vector3* pPoint_list, br_vector3* pNorm_list, int pMax) {
|
|
br_vector3 p1;
|
|
br_vector3 p2;
|
|
br_vector3 tp1;
|
|
br_vector3 tp2;
|
|
br_vector3 tp3;
|
|
br_vector3 hp1;
|
|
br_vector3 hp2;
|
|
br_vector3 hp3;
|
|
br_vector3 shp1;
|
|
br_vector3 shp2;
|
|
br_vector3 edge;
|
|
int plane1;
|
|
int plane2;
|
|
int plane3;
|
|
br_scalar ts;
|
|
int i;
|
|
int j;
|
|
int n;
|
|
LOG_TRACE("(%p, %p, %p, %p, %p, %p, %p, %p, %p, %d)", pB1, pB2, pM21, pM12, pMo21, pMo12, pM1o1, pPoint_list, pNorm_list, pMax);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: int __usercall FacePointCarCarCollide@<EAX>(tCollision_info *car1@<EAX>, tCollision_info *car2@<EDX>, br_matrix34 *pMms@<EBX>, br_matrix34 *pMoms@<ECX>, br_matrix34 *pMsos, br_vector3 *pPoint_list, br_vector3 *pNorm_list, int pMax, int order)
|
|
int FacePointCarCarCollide(tCollision_info* car1, tCollision_info* car2, br_matrix34* pMms, br_matrix34* pMoms, br_matrix34* pMsos, br_vector3* pPoint_list, br_vector3* pNorm_list, int pMax, int order) {
|
|
int k;
|
|
int i;
|
|
int j;
|
|
int l;
|
|
int plane;
|
|
br_vector3 a;
|
|
br_vector3 a1;
|
|
br_vector3 aa;
|
|
br_vector3 bb;
|
|
br_vector3 norm;
|
|
br_vector3 hp;
|
|
br_vector3 centre;
|
|
br_scalar dist;
|
|
br_bounds* pStat_box;
|
|
br_bounds* pMove_box;
|
|
LOG_TRACE("(%p, %p, %p, %p, %p, %p, %p, %d, %d)", car1, car2, pMms, pMoms, pMsos, pPoint_list, pNorm_list, pMax, order);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall MungeCarsMass(tCollision_info *pCar@<EAX>, br_scalar pFactor)
|
|
void MungeCarsMass(tCollision_info* pCar, br_scalar pFactor) {
|
|
LOG_TRACE("(%p, %f)", pCar, pFactor);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall ModifyCarsMass(tCollision_info *pCar_1@<EAX>, tCollision_info *pCar_2@<EDX>)
|
|
void ModifyCarsMass(tCollision_info* pCar_1, tCollision_info* pCar_2) {
|
|
LOG_TRACE("(%p, %p)", pCar_1, pCar_2);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall ResetCarsMass(tCollision_info *pCar_1@<EAX>, tCollision_info *pCar_2@<EDX>)
|
|
void ResetCarsMass(tCollision_info* pCar_1, tCollision_info* pCar_2) {
|
|
LOG_TRACE("(%p, %p)", pCar_1, pCar_2);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: int __usercall DoCollide@<EAX>(tCollision_info *car1@<EAX>, tCollision_info *car2@<EDX>, br_vector3 *r@<EBX>, br_vector3 *n@<ECX>, int k, int pPass, br_matrix34 *mat1_to_mat2)
|
|
int DoCollide(tCollision_info* car1, tCollision_info* car2, br_vector3* r, br_vector3* n, int k, int pPass, br_matrix34* mat1_to_mat2) {
|
|
br_matrix34* mat1;
|
|
br_matrix34* mat2;
|
|
br_matrix34* oldmat1;
|
|
br_matrix34* oldmat2;
|
|
br_matrix4 M;
|
|
br_vector3 tau1[8];
|
|
br_vector3 a;
|
|
br_vector3 norm;
|
|
br_vector3 f1;
|
|
br_vector3 f2;
|
|
br_vector3 pos1;
|
|
br_vector3 pos2;
|
|
br_vector3 max_friction;
|
|
br_vector3 tv;
|
|
br_vector3 tv2;
|
|
br_vector3* tau2;
|
|
br_vector3 torque1;
|
|
br_vector3 torque2;
|
|
br_scalar f[4];
|
|
br_scalar d[4];
|
|
br_scalar ts;
|
|
br_scalar tforce;
|
|
int i;
|
|
int j;
|
|
int car1_point;
|
|
int car2_point;
|
|
int plane;
|
|
int move_car1;
|
|
int move_car2;
|
|
br_vector3 a2;
|
|
br_vector3 f12;
|
|
br_vector3 f22;
|
|
br_vector3 point_vel1;
|
|
br_vector3 point_vel2;
|
|
br_scalar fudge_multiplier;
|
|
br_scalar factor;
|
|
int need_to_fudge;
|
|
LOG_TRACE("(%p, %p, %p, %p, %d, %d, %p)", car1, car2, r, n, k, pPass, mat1_to_mat2);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: br_scalar __usercall TwoPointCollB@<ST0>(br_scalar *f@<EAX>, br_matrix4 *m@<EDX>, br_scalar *d@<EBX>, br_vector3 *tau@<ECX>, br_vector3 *n)
|
|
br_scalar TwoPointCollB(br_scalar* f, br_matrix4* m, br_scalar* d, br_vector3* tau, br_vector3* n) {
|
|
br_scalar ts;
|
|
LOG_TRACE("(%p, %p, %p, %p, %p)", f, m, d, tau, n);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: br_scalar __usercall ThreePointCollRecB@<ST0>(br_scalar *f@<EAX>, br_matrix4 *m@<EDX>, br_scalar *d@<EBX>, br_vector3 *tau@<ECX>, br_vector3 *n)
|
|
br_scalar ThreePointCollRecB(br_scalar* f, br_matrix4* m, br_scalar* d, br_vector3* tau, br_vector3* n) {
|
|
int i;
|
|
int j;
|
|
br_scalar ts;
|
|
LOG_TRACE("(%p, %p, %p, %p, %p)", f, m, d, tau, n);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: br_scalar __usercall FourPointCollB@<ST0>(br_scalar *f@<EAX>, br_matrix4 *m@<EDX>, br_scalar *d@<EBX>, br_vector3 *tau@<ECX>, br_vector3 *n)
|
|
br_scalar FourPointCollB(br_scalar* f, br_matrix4* m, br_scalar* d, br_vector3* tau, br_vector3* n) {
|
|
int i;
|
|
int j;
|
|
int l;
|
|
br_scalar ts;
|
|
LOG_TRACE("(%p, %p, %p, %p, %p)", f, m, d, tau, n);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: int __usercall TestForNan@<EAX>(float *f@<EAX>)
|
|
int TestForNan(float* f) {
|
|
tU32 i;
|
|
LOG_TRACE("(%p)", f);
|
|
i = *f;
|
|
return (~i & 0x7F800000) == 0;
|
|
}
|
|
|
|
// IDA: void __cdecl CheckCameraHither()
|
|
void CheckCameraHither() {
|
|
br_camera* cam;
|
|
static int old_hither;
|
|
LOG_TRACE("()");
|
|
|
|
cam = (br_camera*)gCamera->type_data;
|
|
if (TestForNan(&cam->hither_z)) {
|
|
cam->hither_z = (float)old_hither;
|
|
}
|
|
old_hither = (int)cam->hither_z;
|
|
}
|
|
|
|
// IDA: void __usercall SetCarSuspGiveAndHeight(tCar_spec *pCar@<EAX>, br_scalar pFront_give_factor, br_scalar pRear_give_factor, br_scalar pDamping_factor, br_scalar pExtra_front_height, br_scalar pExtra_rear_height)
|
|
void SetCarSuspGiveAndHeight(tCar_spec* pCar, br_scalar pFront_give_factor, br_scalar pRear_give_factor, br_scalar pDamping_factor, br_scalar pExtra_front_height, br_scalar pExtra_rear_height) {
|
|
br_scalar front_give;
|
|
br_scalar rear_give;
|
|
br_scalar damping;
|
|
br_scalar ratio;
|
|
int i;
|
|
LOG_TRACE("(%p, %f, %f, %f, %f, %f)", pCar, pFront_give_factor, pRear_give_factor, pDamping_factor, pExtra_front_height, pExtra_rear_height);
|
|
|
|
front_give = pCar->susp_give[1] * pFront_give_factor * WORLD_SCALE;
|
|
rear_give = pCar->susp_give[0] * pRear_give_factor * WORLD_SCALE;
|
|
damping = pCar->damping * pDamping_factor;
|
|
ratio = fabs((pCar->wpos[0].v[2] - pCar->cmpos.v[2]) / (pCar->wpos[2].v[2] - pCar->cmpos.v[2]));
|
|
pCar->sk[0] = pCar->M / (ratio + 1.0) * 5.0 / rear_give;
|
|
pCar->sb[0] = pCar->M / (ratio + 1.0) * sqrt(5.0) / sqrt(rear_give);
|
|
ratio = 1.0 / ratio;
|
|
pCar->sk[1] = pCar->M / (ratio + 1.0) * 5.0 / front_give;
|
|
pCar->sb[1] = pCar->M / (ratio + 1.0) * sqrt(5.0) / sqrt(front_give);
|
|
pCar->sb[0] = pCar->sb[0] * damping;
|
|
pCar->sb[1] = pCar->sb[1] * damping;
|
|
pCar->susp_height[0] = pCar->ride_height + rear_give + pExtra_rear_height;
|
|
pCar->susp_height[1] = pCar->ride_height + front_give + pExtra_front_height;
|
|
|
|
if (rear_give >= front_give) {
|
|
i = -rear_give;
|
|
} else {
|
|
i = -front_give;
|
|
}
|
|
if (pExtra_rear_height >= pExtra_front_height) {
|
|
i -= pExtra_rear_height;
|
|
} else {
|
|
i -= pExtra_front_height;
|
|
}
|
|
pCar->bounds[0].min.v[1] = i;
|
|
pCar->bounds[0].min.v[1] = pCar->bounds[0].min.v[1] / WORLD_SCALE;
|
|
}
|
|
|
|
// IDA: int __usercall TestForCarInSensiblePlace@<EAX>(tCar_spec *car@<EAX>)
|
|
int TestForCarInSensiblePlace(tCar_spec* car) {
|
|
br_bounds bnds;
|
|
br_matrix34 mat;
|
|
br_matrix34* mat1;
|
|
br_matrix34* mat2;
|
|
int i;
|
|
int j;
|
|
int k;
|
|
tCollision_info* c2;
|
|
tCollision_info* car_info;
|
|
br_vector3 sep;
|
|
br_vector3 tv;
|
|
br_vector3 tv2;
|
|
LOG_TRACE("(%p)", car);
|
|
|
|
car_info = (tCollision_info*)car;
|
|
if (!gProgram_state.racing) {
|
|
return 1;
|
|
}
|
|
mat1 = &car_info->car_master_actor->t.t.mat;
|
|
if (!gDoing_physics) {
|
|
mat1->m[3][0] = mat1->m[3][0] * WORLD_SCALE;
|
|
mat1->m[3][1] = mat1->m[3][1] * WORLD_SCALE;
|
|
mat1->m[3][2] = mat1->m[3][2] * WORLD_SCALE;
|
|
}
|
|
GetFacesInBox(car_info);
|
|
BrMatrix34ApplyP(&car_info->pos, &car_info->cmpos, &car_info->car_master_actor->t.t.mat);
|
|
car_info->pos.v[0] = car_info->pos.v[0] / WORLD_SCALE;
|
|
car_info->pos.v[1] = car_info->pos.v[1] / WORLD_SCALE;
|
|
car_info->pos.v[2] = car_info->pos.v[2] / WORLD_SCALE;
|
|
k = CollCheck(car_info, -2.0);
|
|
if (!k) {
|
|
if (gNum_active_non_cars + gNum_active_cars != gNum_cars_and_non_cars) {
|
|
GetNonCars();
|
|
}
|
|
for (i = 0; i < gNum_cars_and_non_cars; i++) {
|
|
c2 = (tCollision_info*)gActive_car_list[i];
|
|
if (car_info != c2) {
|
|
mat2 = &c2->car_master_actor->t.t.mat;
|
|
mat2->m[3][0] = mat2->m[3][0] * WORLD_SCALE;
|
|
mat2->m[3][1] = mat2->m[3][1] * WORLD_SCALE;
|
|
mat2->m[3][2] = mat2->m[3][2] * WORLD_SCALE;
|
|
sep.v[0] = mat1->m[3][0] - mat2->m[3][0];
|
|
sep.v[1] = mat1->m[3][1] - mat2->m[3][1];
|
|
sep.v[2] = mat1->m[3][2] - mat2->m[3][2];
|
|
if (BrVector3LengthSquared(&sep) <= 100.0) {
|
|
k += TestOldMats(car_info, c2, 0);
|
|
k += TestOldMats(c2, car_info, 0);
|
|
}
|
|
if (k) {
|
|
BrMatrix34ApplyP(&tv, &car_info->cmpos, mat1);
|
|
BrMatrix34ApplyP(&tv2, &c2->cmpos, mat2);
|
|
tv.v[0] = tv2.v[0] - tv.v[0];
|
|
tv.v[1] = tv2.v[1] - tv.v[1];
|
|
tv.v[2] = tv2.v[2] - tv.v[2];
|
|
BrMatrix34TApplyV(&car_info->old_point, &tv, &car_info->car_master_actor->t.t.mat);
|
|
BrVector3Normalise(&car_info->old_norm, &car_info->old_point);
|
|
BrVector3Negate(&car_info->old_norm, &car_info->old_norm);
|
|
}
|
|
mat2->m[3][0] = mat2->m[3][0] / WORLD_SCALE;
|
|
mat2->m[3][1] = mat2->m[3][1] / WORLD_SCALE;
|
|
mat2->m[3][2] = mat2->m[3][2] / WORLD_SCALE;
|
|
if (k) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!gDoing_physics) {
|
|
mat1->m[3][0] = mat1->m[3][0] / WORLD_SCALE;
|
|
mat1->m[3][1] = mat1->m[3][1] / WORLD_SCALE;
|
|
mat1->m[3][2] = mat1->m[3][2] / WORLD_SCALE;
|
|
}
|
|
if (k) {
|
|
return 0;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
// IDA: int __usercall TestOldMats@<EAX>(tCollision_info *c1@<EAX>, tCollision_info *c2@<EDX>, int newmats@<EBX>)
|
|
int TestOldMats(tCollision_info* c1, tCollision_info* c2, int newmats) {
|
|
br_vector3 p1;
|
|
br_vector3 p2;
|
|
br_vector3 tp1;
|
|
br_vector3 tp2;
|
|
br_vector3 tp3;
|
|
br_vector3 hp1;
|
|
br_vector3 hp2;
|
|
br_vector3 hp3;
|
|
br_vector3 shp1;
|
|
br_vector3 shp2;
|
|
br_vector3 edge;
|
|
int plane1;
|
|
int plane2;
|
|
int plane3;
|
|
br_scalar ts;
|
|
int i;
|
|
int j;
|
|
int n;
|
|
br_bounds* b1;
|
|
br_bounds* b2;
|
|
br_matrix34 invmat1;
|
|
br_matrix34 mat21;
|
|
LOG_TRACE("(%p, %p, %d)", c1, c2, newmats);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: int __usercall PullActorFromWorld@<EAX>(br_actor *pActor@<EAX>)
|
|
int PullActorFromWorld(br_actor* pActor) {
|
|
LOG_TRACE("(%p)", pActor);
|
|
|
|
if (gDoing_physics) {
|
|
return DoPullActorFromWorld(pActor);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// IDA: int __usercall DoPullActorFromWorld@<EAX>(br_actor *pActor@<EAX>)
|
|
int DoPullActorFromWorld(br_actor* pActor) {
|
|
int num;
|
|
int i;
|
|
tCollision_info* c;
|
|
tNon_car_spec* non_car;
|
|
LOG_TRACE("(%p)", pActor);
|
|
|
|
STUB();
|
|
return 0;
|
|
}
|
|
|
|
// IDA: void __usercall CheckForDeAttachmentOfNonCars(tU32 pTime@<EAX>)
|
|
void CheckForDeAttachmentOfNonCars(tU32 pTime) {
|
|
static tU32 total_time;
|
|
br_bounds bnds;
|
|
int i;
|
|
int j;
|
|
int last_free_slot;
|
|
int drop;
|
|
tCollision_info* c;
|
|
tCollision_info* c2;
|
|
br_actor* actor;
|
|
tU8 cx;
|
|
tU8 cz;
|
|
tTrack_spec* track_spec;
|
|
br_matrix34 mat;
|
|
LOG_TRACE("(%d)", pTime);
|
|
|
|
STUB_ONCE();
|
|
}
|
|
|
|
// IDA: void __usercall AdjustNonCar(br_actor *pActor@<EAX>, br_matrix34 *pMat@<EDX>)
|
|
void AdjustNonCar(br_actor* pActor, br_matrix34* pMat) {
|
|
tU8 cx;
|
|
tU8 cz;
|
|
tTrack_spec* track_spec;
|
|
LOG_TRACE("(%p, %p)", pActor, pMat);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: void __usercall PipeSingleNonCar(tCollision_info *c@<EAX>)
|
|
void PipeSingleNonCar(tCollision_info* c) {
|
|
LOG_TRACE("(%p)", c);
|
|
NOT_IMPLEMENTED();
|
|
}
|
|
|
|
// IDA: int __usercall GetPrecalculatedFacesUnderCar@<EAX>(tCar_spec *pCar@<EAX>, tFace_ref **pFace_refs@<EDX>)
|
|
int GetPrecalculatedFacesUnderCar(tCar_spec* pCar, tFace_ref** pFace_refs) {
|
|
LOG_TRACE("(%p, %p)", pCar, pFace_refs);
|
|
|
|
if (pCar->box_face_ref != gFace_num__car
|
|
&& (pCar->box_face_ref != gFace_num__car - 1 || pCar->box_face_start <= gFace_count)) {
|
|
return 0;
|
|
}
|
|
*pFace_refs = &gFace_list__car[pCar->box_face_start];
|
|
return pCar->box_face_end - pCar->box_face_start;
|
|
}
|
|
|
|
// IDA: br_material* __cdecl SomeNearbyMaterial()
|
|
br_material* SomeNearbyMaterial() {
|
|
LOG_TRACE("()");
|
|
NOT_IMPLEMENTED();
|
|
}
|