Implement network (#366)
* SendCarData, ReceivedStartRace * fixes heap overflow during join * fixes access on possibly-null pDetails * DoNetScores * Fix cast warning of comparefn of qsort * DisplayUserMessage * Pack tNet_contents on 4 byte boundary so 32-bit and 64-bit Intel cpu get same struct lay-out * Add a few static assertions to verify net message offsets * Add dethrace Wireshark dissector (WIP) * add dissector installation instructions * Set wireshark info column * Fix various typo's * 4-byte align tNet_message_join as well + more dethrace.lua * Add more assertions * Fix network car choose loop * player scores * tidy * mechanics * Implement SortNetHeadAscending for 'Terminal Tag' * Update WireShark dissector * start of tNet_message_pedestrian dissector * network player cars can see each other move * netmsgid tidy ups * dissector: print HOST/CLIENT in info column * Don't allow hosting a game when starting dethrace with --no-bind * fix oldd copy * time_step is integer, fixes client car out of sync * wasted, recover, kick player out * NetSendPointCrush * crushpoint, declarewinner * network race summary wip * Start and finish a game of tag/fox * network fixes * Players can now send love letters to each other * Rewrite if's a bit * Use enum values for GetMiscString and DoFancyHeadup * Fix fox effect * Fix fox/it effect at start of race * Use KEYMAP_ enum values * Disable address sanitizer and dr_dprintf logging --------- Co-authored-by: Dethrace Labs <78985374+dethrace-labs@users.noreply.github.com>
This commit is contained in:
parent
1d5f6f1634
commit
673244bb8c
|
@ -29,6 +29,7 @@
|
|||
#include "skidmark.h"
|
||||
#include "sound.h"
|
||||
#include "spark.h"
|
||||
#include "structur.h"
|
||||
#include "trig.h"
|
||||
#include "utility.h"
|
||||
#include "world.h"
|
||||
|
@ -886,8 +887,7 @@ void CalcEngineForce(tCar_spec* c, br_scalar dt) {
|
|||
} else if (c->joystick.acc < 0) {
|
||||
ts = 1.2;
|
||||
} else {
|
||||
ts = c->joystick.acc / 54613.0;
|
||||
LOG_PANIC("ooo");
|
||||
ts = c->joystick.acc / 54613.0f;
|
||||
}
|
||||
|
||||
torque = c->engine_power_multiplier * ts * gEngine_powerup_factor[c->power_up_levels[1]];
|
||||
|
@ -1085,7 +1085,69 @@ void GetNetPos(tCar_spec* pCar) {
|
|||
float amount;
|
||||
br_scalar total_deflection;
|
||||
LOG_TRACE("(%p)", pCar);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (gNet_mode == eNet_mode_host && pCar->last_car_car_collision > pCar->message.cc_coll_time) {
|
||||
pCar->message.type = 0;
|
||||
pCar->dt = -1.0f;
|
||||
return;
|
||||
}
|
||||
if (fabsf(pCar->message.omega.v[0]) > 10000.0
|
||||
|| fabsf(pCar->message.omega.v[1]) > 10000.0
|
||||
|| fabsf(pCar->message.omega.v[2]) > 10000.0
|
||||
|| fabsf(pCar->message.omega.v[0]) > 10000.0
|
||||
|| fabsf(pCar->message.omega.v[1]) > 10000.0
|
||||
|| fabsf(pCar->message.omega.v[2]) > 10000.0) {
|
||||
BrVector3SetFloat(&pCar->message.omega, 0.0, 0.0, 0.0);
|
||||
BrVector3SetFloat(&pCar->message.v, 0.0, 0.0, 0.0);
|
||||
}
|
||||
GetExpandedMatrix(&pCar->car_master_actor->t.t.mat, &pCar->message.mat);
|
||||
if (gNet_mode == eNet_mode_client) {
|
||||
BrMatrix34Copy(&pCar->oldmat, &pCar->car_master_actor->t.t.mat);
|
||||
}
|
||||
BrVector3Copy(&pCar->v, &pCar->message.v);
|
||||
BrVector3Copy(&pCar->omega, &pCar->message.omega);
|
||||
|
||||
if (pCar->driver > eDriver_non_car) {
|
||||
pCar->curvature = pCar->message.curvature * pCar->maxcurve / 32767.0f;
|
||||
|
||||
for (j = 0; j < COUNT_OF(pCar->oldd); j++) {
|
||||
pCar->oldd[j] = (pCar->message.d[j] * pCar->susp_height[j >> 1]) / 255.0f;
|
||||
}
|
||||
if (pCar->driver == eDriver_oppo || pCar->repair_time >= pCar->message.repair_time) {
|
||||
for (j = 0; j < COUNT_OF(pCar->damage_units); j++) {
|
||||
pCar->damage_units[j].damage_level = pCar->message.damage[j];
|
||||
}
|
||||
SortOutSmoke(pCar);
|
||||
} else {
|
||||
if (pCar->message.repair_time - pCar->repair_time < 100000) {
|
||||
amount = RepairCar2(pCar, pCar->message.repair_time - pCar->repair_time, &total_deflection);
|
||||
} else {
|
||||
TotallyRepairACar(pCar);
|
||||
pCar->repair_time = pCar->message.repair_time;
|
||||
}
|
||||
for (j = 0; j < COUNT_OF(pCar->damage_units); j++) {
|
||||
pCar->damage_units[j].damage_level = pCar->message.damage[j];
|
||||
}
|
||||
SetSmokeLastDamageLevel(pCar);
|
||||
StopCarSmoking(pCar);
|
||||
}
|
||||
if (pCar->driver == eDriver_net_human) {
|
||||
pCar->revs = pCar->message.revs;
|
||||
}
|
||||
if (pCar->driver >= eDriver_net_human) {
|
||||
pCar->bounds[1].min.v[2] = pCar->message.front;
|
||||
pCar->bounds[1].max.v[2] = pCar->message.back;
|
||||
}
|
||||
if (pCar->driver != eDriver_local_human) {
|
||||
for (j = 0; j < COUNT_OF(pCar->wheel_dam_offset); j++) {
|
||||
pCar->wheel_dam_offset[j] = pCar->message.wheel_dam_offset[j];
|
||||
}
|
||||
}
|
||||
GetFacesInBox((tCollision_info*)pCar);
|
||||
}
|
||||
|
||||
pCar->message.type = 0;
|
||||
pCar->last_car_car_collision = pCar->message.cc_coll_time;
|
||||
}
|
||||
|
||||
// IDA: void __usercall ApplyPhysicsToCars(tU32 last_frame_time@<EAX>, tU32 pTime_difference@<EDX>)
|
||||
|
@ -1136,9 +1198,11 @@ void ApplyPhysicsToCars(tU32 last_frame_time, tU32 pTime_difference) {
|
|||
for (i = 0; i < gNum_active_cars; i++) {
|
||||
car = gActive_car_list[i];
|
||||
car->dt = -1.f;
|
||||
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.0001f <= car->dt) {
|
||||
if (car->message.type == NETMSGID_MECHANICS && car->message.time >= gLast_mechanics_time && car->message.time <= gLast_mechanics_time + harness_game_config.physics_step_time) {
|
||||
// time between car message and next mechanics
|
||||
car->dt = (gLast_mechanics_time + harness_game_config.physics_step_time - car->message.time) / 1000.0f;
|
||||
// if the time between car message and next mechanics is about equal to timestep
|
||||
if (car->dt >= gDt - 0.0001f) {
|
||||
GetNetPos(car);
|
||||
} else if (gNet_mode == eNet_mode_host) {
|
||||
car->dt = -1.f;
|
||||
|
@ -1170,7 +1234,7 @@ void ApplyPhysicsToCars(tU32 last_frame_time, tU32 pTime_difference) {
|
|||
non_car = gActive_non_car_list[i];
|
||||
if (!non_car->collision_info.doing_nothing_flag) {
|
||||
non_car->collision_info.dt = -1.f;
|
||||
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) {
|
||||
if (non_car->collision_info.message.type == NETMSGID_NONCAR_INFO && 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 = (gLast_mechanics_time + harness_game_config.physics_step_time - non_car->collision_info.message.time) / 1000.0f;
|
||||
GetNetPos((tCar_spec*)non_car);
|
||||
}
|
||||
|
@ -1422,7 +1486,7 @@ void ToggleControls(void) {
|
|||
LOG_TRACE("()");
|
||||
|
||||
gControl__car++;
|
||||
if (ControlCar[gControl__car] == 0) {
|
||||
if (ControlCar[gControl__car] == NULL) {
|
||||
gControl__car = 0;
|
||||
}
|
||||
switch (gControl__car) {
|
||||
|
@ -1447,13 +1511,81 @@ void ToggleControls(void) {
|
|||
// 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();
|
||||
|
||||
c->acc_force = 0.f;
|
||||
if (c->keys.acc) {
|
||||
c->acc_force = 7.f * c->M;
|
||||
}
|
||||
if (c->keys.dec) {
|
||||
c->acc_force = -7.f * c->M;
|
||||
}
|
||||
if (c->keys.left) {
|
||||
if (c->turn_speed < 0.f) {
|
||||
c->turn_speed = 0.f;
|
||||
}
|
||||
if (c->curvature >= 0.f) {
|
||||
c->turn_speed += dt / 0.04f * (0.05f / (5.f + BrVector3Length(&c->v)) / 2.f);
|
||||
} else {
|
||||
c->turn_speed += 0.01f * dt / 0.04f / 2.f;
|
||||
}
|
||||
}
|
||||
if (c->keys.right) {
|
||||
if (c->turn_speed > 0.f) {
|
||||
c->turn_speed = 0.f;
|
||||
}
|
||||
if (c->curvature <= 0.f) {
|
||||
c->turn_speed -= dt / 0.04f * (0.05f / (5.f + BrVector3Length(&c->v)) / 2.f);
|
||||
} else {
|
||||
c->turn_speed -= 0.01f * dt / 0.04f / 2.f;
|
||||
}
|
||||
}
|
||||
if (!c->keys.left && !c->keys.right) {
|
||||
c->turn_speed = 0.f;
|
||||
}
|
||||
c->curvature += c->turn_speed;
|
||||
if (c->curvature > c->maxcurve) {
|
||||
c->curvature = c->maxcurve;
|
||||
}
|
||||
if (c->curvature < -c->maxcurve) {
|
||||
c->curvature = -c->maxcurve;
|
||||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
||||
if (c->keys.left) {
|
||||
if (c->turn_speed < 0.f) {
|
||||
c->turn_speed = 0.f;
|
||||
}
|
||||
if (c->curvature >= 0.f && c->omega.v[1] >= 0.f) {
|
||||
c->turn_speed += dt / 0.04f * (0.05f / (5.f + BrVector3Length(&c->v)) / 2.f) * 0.75f;
|
||||
} else {
|
||||
c->turn_speed += 0.01f * dt / 0.04f / 2.f * 3.f;
|
||||
}
|
||||
}
|
||||
|
||||
if (c->keys.right) {
|
||||
if (c->turn_speed > 0.f) {
|
||||
c->turn_speed = 0.f;
|
||||
}
|
||||
if (c->curvature <= 0.f && c->omega.v[1] <= 0.f) {
|
||||
c->turn_speed -= dt / 0.04f * (0.05f / (5.f + BrVector3Length(&c->v)) / 2.f) * 0.75f;
|
||||
} else {
|
||||
c->turn_speed -= 0.01f * dt / 0.04f / 2.f * 3.f;
|
||||
}
|
||||
}
|
||||
if (!c->keys.left && !c->keys.right) {
|
||||
c->turn_speed = 0.f;
|
||||
}
|
||||
c->curvature += c->turn_speed;
|
||||
if (c->curvature > c->maxcurve) {
|
||||
c->curvature = c->maxcurve;
|
||||
}
|
||||
if (c->curvature < -c->maxcurve) {
|
||||
c->curvature = -c->maxcurve;
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall ControlCar4(tCar_spec *c@<EAX>, br_scalar dt)
|
||||
|
@ -1513,20 +1645,101 @@ void ControlCar4(tCar_spec* c, br_scalar dt) {
|
|||
// 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();
|
||||
|
||||
c->acc_force = 0.f;
|
||||
if (c->keys.acc) {
|
||||
c->acc_force = 7.f * c->M;
|
||||
}
|
||||
if (c->keys.dec) {
|
||||
c->acc_force = -7.f * c->M;
|
||||
}
|
||||
if (c->keys.left) {
|
||||
if (c->turn_speed < 0.f) {
|
||||
c->turn_speed = 0.f;
|
||||
}
|
||||
if (c->curvature >= 0) {
|
||||
c->turn_speed += dt / 0.04f * (0.05f / (5.f + BrVector3Length(&c->v)) / 2.f) * 0.5f;
|
||||
} else {
|
||||
c->turn_speed += 0.01f * dt / 0.04f / 2.f * .5f;
|
||||
}
|
||||
}
|
||||
if (c->keys.right) {
|
||||
if (c->turn_speed > 0.f) {
|
||||
c->turn_speed = 0.f;
|
||||
}
|
||||
if (c->curvature <= 0) {
|
||||
c->turn_speed -= dt / 0.04f * (0.05f / (5.f + BrVector3Length(&c->v)) / 2.f) * 0.5f;
|
||||
} else {
|
||||
c->turn_speed -= 0.01f * dt / 0.04f / 2.f * .5f;
|
||||
}
|
||||
}
|
||||
if (!c->keys.left && !c->keys.right) {
|
||||
c->turn_speed = 0.f;
|
||||
if (c->curvature < 0.f && !c->keys.holdw) {
|
||||
c->curvature += dt / 0.04f * 0.05f / (5.f + BrVector3Length(&c->v)) / 2.f * 4.f;
|
||||
if (c->curvature > 0.f) {
|
||||
c->curvature = 0.f;
|
||||
}
|
||||
} else if (c->curvature > 0.f && !c->keys.holdw) {
|
||||
c->curvature -= dt / 0.04f * 0.05f / (5.f + BrVector3Length(&c->v)) / 2.f * 4.f;
|
||||
if (c->curvature < 0.f) {
|
||||
c->curvature = 0.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
c->curvature += c->turn_speed;
|
||||
if (c->curvature > c->maxcurve) {
|
||||
c->curvature = c->maxcurve;
|
||||
}
|
||||
if (c->curvature < -c->maxcurve) {
|
||||
c->curvature = -c->maxcurve;
|
||||
}
|
||||
c->keys.left = 1;
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
||||
c->acc_force = 0.f;
|
||||
if (c->keys.acc) {
|
||||
c->acc_force = 7.f * c->M;
|
||||
}
|
||||
if (c->keys.dec) {
|
||||
c->acc_force = -7.f * c->M;
|
||||
}
|
||||
if (c->keys.left) {
|
||||
if (c->curvature >= 0.f) {
|
||||
c->curvature += dt / 0.04f * 0.05f / (5.f + BrVector3Length(&c->v));
|
||||
} else {
|
||||
c->curvature += 0.01f * dt / 0.04f;
|
||||
}
|
||||
}
|
||||
if (c->keys.right) {
|
||||
if (c->curvature <= 0.f) {
|
||||
c->curvature -= dt / 0.04f * 0.05f / (5.f + BrVector3Length(&c->v));
|
||||
} else {
|
||||
c->curvature -= 0.01f * dt / 0.04f;
|
||||
}
|
||||
}
|
||||
if (c->curvature > c->maxcurve) {
|
||||
c->curvature = c->maxcurve;
|
||||
}
|
||||
if (c->curvature < -c->maxcurve) {
|
||||
c->curvature = -c->maxcurve;
|
||||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
||||
e.a = BR_ANGLE_RAD(wdt->v[0]);
|
||||
e.b = BR_ANGLE_RAD(wdt->v[1]);
|
||||
e.c = BR_ANGLE_RAD(wdt->v[2]);
|
||||
e.order = 0;
|
||||
BrEulerToMatrix34(m, &e);
|
||||
}
|
||||
|
||||
// IDA: void __usercall RotateCar2(tCollision_info *c@<EAX>, br_scalar dt)
|
||||
|
@ -1537,7 +1750,18 @@ void RotateCar2(tCollision_info* c, br_scalar dt) {
|
|||
br_vector3 L2;
|
||||
br_matrix34 m;
|
||||
LOG_TRACE("(%p, %f)", c, dt);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
BrVector3Scale(&wdt, &c->omega, dt);
|
||||
BrVector3Negate(&wdt2, &wdt);
|
||||
BrVector3Mul(&L, &c->I, &c->omega);
|
||||
setrotate(&wdt2, &m);
|
||||
BrMatrix34ApplyV(&L2, &L, &m);
|
||||
setrotate(&wdt, &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);
|
||||
BrVector3Copy(&c->oldomega, &c->omega);
|
||||
Vector3Div(&c->omega, &L2, &c->I);
|
||||
}
|
||||
|
||||
// IDA: void __usercall RotateCarSecondOrder(tCollision_info *c@<EAX>, br_scalar dt)
|
||||
|
@ -4332,7 +4556,20 @@ tCar_spec* GetRaceLeader(void) {
|
|||
int score;
|
||||
tCar_spec* car;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if ((gCurrent_net_game->type == eNet_game_type_foxy || gCurrent_net_game->type == eNet_game_type_tag) && gIt_or_fox >= 0 && gIt_or_fox < gNumber_of_net_players) {
|
||||
car = gNet_players[gIt_or_fox].car;
|
||||
} else {
|
||||
car = gNet_players[0].car;
|
||||
score = gNet_players[0].last_score_index;
|
||||
for (i = 1; i < gNumber_of_net_players; i++) {
|
||||
if (score > gNet_players[i].last_score_index) {
|
||||
score = gNet_players[i].last_score_index;
|
||||
car = gNet_players[i].car;
|
||||
}
|
||||
}
|
||||
}
|
||||
return car;
|
||||
}
|
||||
|
||||
// IDA: void __cdecl AmIGettingBoredWatchingCameraSpin()
|
||||
|
@ -4343,7 +4580,46 @@ void AmIGettingBoredWatchingCameraSpin(void) {
|
|||
char s[256];
|
||||
LOG_TRACE("()");
|
||||
|
||||
STUB_ONCE();
|
||||
if (gNet_mode == eNet_mode_none
|
||||
|| (gCurrent_net_game->type != eNet_game_type_sudden_death
|
||||
&& gCurrent_net_game->type != eNet_game_type_tag
|
||||
&& gCurrent_net_game->type != eNet_game_type_fight_to_death)) {
|
||||
gOpponent_viewing_mode = 0;
|
||||
} else if (!gRace_finished) {
|
||||
time_of_death = 0;
|
||||
gOpponent_viewing_mode = 0;
|
||||
} else if (time_of_death == 0) {
|
||||
time_of_death = GetRaceTime();
|
||||
} else {
|
||||
if (GetRaceTime() >= time_of_death + 10000) {
|
||||
if (gOpponent_viewing_mode == 0) {
|
||||
gOpponent_viewing_mode = 1;
|
||||
gNet_player_to_view_index = -2;
|
||||
ViewNetPlayer();
|
||||
}
|
||||
if (gNet_player_to_view_index >= gNumber_of_net_players) {
|
||||
gNet_player_to_view_index = -2;
|
||||
ViewNetPlayer();
|
||||
}
|
||||
if (gNet_player_to_view_index < 0 && gCar_to_view != GetRaceLeader()) {
|
||||
gNet_player_to_view_index = -2;
|
||||
ViewNetPlayer();
|
||||
}
|
||||
if ((GetRaceTime() > headup_timer + 1000 || headup_timer > GetRaceTime()) && gRace_over_reason == eRace_not_over_yet) {
|
||||
strcpy(s, GetMiscString(kMiscString_WATCHING));
|
||||
strcat(s, " ");
|
||||
if (gNet_player_to_view_index >= 0) {
|
||||
strcat(s, gNet_players[gNet_player_to_view_index].player_name);
|
||||
} else if (gCurrent_net_game->type == eNet_game_type_tag) {
|
||||
strcat(s, GetMiscString(kMiscString_QUOTE_IT_QUOTE));
|
||||
} else {
|
||||
strcat(s, GetMiscString(kMiscString_RACE_LEADER));
|
||||
}
|
||||
headup_timer = GetRaceTime();
|
||||
NewTextHeadupSlot(6, 0, 500, -4, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __cdecl ViewNetPlayer()
|
||||
|
@ -5409,7 +5685,13 @@ int CollideCamera2(br_vector3* car_pos, br_vector3* cam_pos, br_vector3* old_cam
|
|||
int BoundsTest(br_bounds* bnds, br_vector3* p) {
|
||||
int j;
|
||||
LOG_TRACE("(%p, %p)", bnds, p);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
for (j = 0; j < 3; j++) {
|
||||
if (p->v[j] > bnds->max.v[j] || p->v[j] < bnds->min.v[j]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// IDA: int __usercall CollideCameraWithOtherCars@<EAX>(br_vector3 *car_pos@<EAX>, br_vector3 *cam_pos@<EDX>)
|
||||
|
@ -5426,7 +5708,24 @@ int CollideCameraWithOtherCars(br_vector3* car_pos, br_vector3* cam_pos) {
|
|||
br_bounds bnds;
|
||||
LOG_TRACE("(%p, %p)", car_pos, cam_pos);
|
||||
|
||||
STUB_ONCE();
|
||||
for (i = 0; i < gNum_cars_and_non_cars; i++) {
|
||||
if (BoundsTest(&gActive_car_list[i]->bounds_world_space, cam_pos)) {
|
||||
c = gActive_car_list[i];
|
||||
BrVector3Sub(&tv, cam_pos, &c->car_master_actor->t.t.translate.t);
|
||||
BrMatrix34TApplyV(&p, &tv, &c->car_master_actor->t.t.mat);
|
||||
if (BoundsTest(&c->bounds[0], &p)) {
|
||||
BrVector3Sub(&tv, cam_pos, car_pos);
|
||||
BrMatrix34TApplyV(&dir, &tv, &c->car_master_actor->t.t.mat);
|
||||
BrVector3Add(&pos_car_space, &p, &dir);
|
||||
BrVector3SetFloat(&tv, 0.03f, 0.03f, 0.03f);
|
||||
BrVector3Sub(&bnds.min, &c->bounds[0].min, &tv);
|
||||
BrVector3Add(&bnds.max, &c->bounds[0].max, &tv);
|
||||
plane = LineBoxColl(&pos_car_space, &p, &bnds, &tv);
|
||||
BrMatrix34ApplyP(cam_pos, &tv, &c->car_master_actor->t.t.mat);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1105,7 +1105,6 @@ void ConcussMe(void) {
|
|||
// IDA: void __cdecl CheckHelp()
|
||||
void CheckHelp(void) {
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
}
|
||||
|
||||
// IDA: void __cdecl CheckLoadSave()
|
||||
|
@ -1283,7 +1282,27 @@ void CheckHornLocal(tCar_spec* pCar) {
|
|||
// IDA: void __usercall CheckHorn3D(tCar_spec *pCar@<EAX>)
|
||||
void CheckHorn3D(tCar_spec* pCar) {
|
||||
LOG_TRACE("(%p)", pCar);
|
||||
STUB_ONCE();
|
||||
|
||||
if (pCar->keys.horn && pCar->horn_sound_tag == 0) {
|
||||
pCar->horn_sound_tag = DRS3StartSound3D(gEffects_outlet,
|
||||
5209,
|
||||
&pCar->car_master_actor->t.t.translate.t,
|
||||
&pCar->velocity_bu_per_sec,
|
||||
0,
|
||||
255,
|
||||
((pCar->car_ID & 7) << 12) + 0xc000,
|
||||
0x10000);
|
||||
} else {
|
||||
if (!pCar->keys.horn && pCar->horn_sound_tag != 0) {
|
||||
while (S3SoundStillPlaying(pCar->horn_sound_tag)) {
|
||||
DRS3StopSound(pCar->horn_sound_tag);
|
||||
DRS3StopOutletSound(gEffects_outlet);
|
||||
}
|
||||
if (!S3SoundStillPlaying(pCar->horn_sound_tag)) {
|
||||
pCar->horn_sound_tag = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __cdecl CheckHorns()
|
||||
|
@ -1378,14 +1397,14 @@ void CheckMapRenderMove(void) {
|
|||
old_x = gMap_render_x;
|
||||
if (gMap_mode) {
|
||||
amount = gFrame_period * .1f;
|
||||
if (KeyIsDown(30)) {
|
||||
if (KeyIsDown(KEYMAP_MOVE_UP)) {
|
||||
gMap_render_y -= amount;
|
||||
} else if (KeyIsDown(31)) {
|
||||
} else if (KeyIsDown(KEYMAP_MOVE_DOWN)) {
|
||||
gMap_render_y += amount;
|
||||
}
|
||||
if (KeyIsDown(32)) {
|
||||
if (KeyIsDown(KEYMAP_MOVE_LEFT)) {
|
||||
gMap_render_x -= amount;
|
||||
} else if (KeyIsDown(33)) {
|
||||
} else if (KeyIsDown(KEYMAP_MOVE_RIGHT)) {
|
||||
gMap_render_x += amount;
|
||||
}
|
||||
if (gMap_render_x != old_x || gMap_render_y != old_y) {
|
||||
|
@ -1731,7 +1750,7 @@ void FlipUpCar(tCar_spec* car) {
|
|||
count = 0;
|
||||
if (car->driver == eDriver_local_human && gNet_mode == eNet_mode_none) {
|
||||
FadePaletteDown();
|
||||
while (KeyIsDown(44)) {
|
||||
while (KeyIsDown(KEYMAP_REPAIR)) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
@ -2480,7 +2499,99 @@ void EnterUserMessage(void) {
|
|||
int the_key;
|
||||
int abuse_num;
|
||||
LOG_TRACE("()");
|
||||
STUB_ONCE();
|
||||
|
||||
if (!gEntering_message) {
|
||||
return;
|
||||
}
|
||||
if (gNet_mode == eNet_mode_none) {
|
||||
return;
|
||||
}
|
||||
if (!gCurrent_net_game->options.enable_text_messages) {
|
||||
return;
|
||||
}
|
||||
the_key = PDAnyKeyDown();
|
||||
if (gEntering_message == 1) {
|
||||
if (the_key != -1) {
|
||||
return;
|
||||
}
|
||||
gEntering_message = 2;
|
||||
}
|
||||
if (about_to_die) {
|
||||
if (the_key != -1) {
|
||||
return;
|
||||
}
|
||||
gEntering_message = 0;
|
||||
about_to_die = 0;
|
||||
return;
|
||||
}
|
||||
if (the_key == last_key) {
|
||||
if (next_time < PDGetTotalTime()) {
|
||||
next_time += 100;
|
||||
} else {
|
||||
the_key = -1;
|
||||
}
|
||||
} else {
|
||||
last_key = the_key;
|
||||
next_time = PDGetTotalTime() + 500;
|
||||
}
|
||||
switch (the_key) {
|
||||
case -1:
|
||||
case KEY_SHIFT_ANY:
|
||||
break;
|
||||
case KEY_CTRL_ANY:
|
||||
case KEY_CTRL_ANY_2:
|
||||
case KEY_TAB:
|
||||
case KEY_ESCAPE:
|
||||
about_to_die = 1;
|
||||
break;
|
||||
case KEY_BACKSPACE:
|
||||
case KEY_DELETE:
|
||||
case KEY_LEFT:
|
||||
len = strlen(&gString[20]);
|
||||
if (len > 0) {
|
||||
gString[20 + len - 1] = '\0';
|
||||
}
|
||||
break;
|
||||
case KEY_RETURN:
|
||||
case KEY_KP_ENTER:
|
||||
len = strlen(gNet_players[gThis_net_player_index].player_name);
|
||||
if (len <= 18) {
|
||||
the_message = gString + 18 - len;
|
||||
strcpy(the_message, gNet_players[gThis_net_player_index].player_name);
|
||||
the_message[len + 0] = ':';
|
||||
the_message[len + 1] = ' ';
|
||||
gString[COUNT_OF(gString) - 1] = '\0';
|
||||
NetSendHeadupToAllPlayers(the_message);
|
||||
gString[20] = '\0';
|
||||
NewTextHeadupSlot(4, 0, 1000, -4, GetMiscString(kMiscString_MESSAGE_SENT));
|
||||
about_to_die = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (gKey_mapping[KEYMAP_SEND_MESSAGE] == the_key) {
|
||||
about_to_die = 1;
|
||||
} else if (the_key <= KEY_KP_NUMLOCK || the_key >= KEY_SPACE) {
|
||||
len = strlen(&gString[20]);
|
||||
if (len < 64 - 1) {
|
||||
gString[20 + len] = PDGetASCIIFromKey(the_key);
|
||||
if (gString[20 + len] < gFonts[4].offset || gString[20 + len] >= gFonts[4].offset + gFonts[4].num_entries) {
|
||||
gString[20 + len] = '\0';
|
||||
}
|
||||
gString[20 + len + 1] = '\0';
|
||||
}
|
||||
} else if (the_key < KEY_KP_0 || the_key > KEY_KP_9) {
|
||||
gEntering_message = 0;
|
||||
} else {
|
||||
if (the_key == KEY_KP_0) {
|
||||
abuse_num = 9;
|
||||
} else {
|
||||
abuse_num = the_key - KEY_KP_1;
|
||||
}
|
||||
if (gAbuse_text[abuse_num] != NULL) {
|
||||
strcpy(&gString[20], gAbuse_text[abuse_num]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __cdecl DisplayUserMessage()
|
||||
|
@ -2489,7 +2600,36 @@ void DisplayUserMessage(void) {
|
|||
int len;
|
||||
tDR_font* font;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
font = &gFonts[FONT_NEWHITE];
|
||||
the_message = &gString[20];
|
||||
if (!gEntering_message || gNet_mode == eNet_mode_none) {
|
||||
return;
|
||||
}
|
||||
|
||||
len = strlen(the_message);
|
||||
if (len < 63 && (PDGetTotalTime() & 512) != 0) {
|
||||
the_message[len] = '_';
|
||||
the_message[len + 1] = '\0';
|
||||
}
|
||||
DimRectangle(gBack_screen,
|
||||
15 * gBack_screen->width / 100,
|
||||
gCurrent_graf_data->net_message_enter_y - font->height,
|
||||
85 * gBack_screen->width / 100,
|
||||
gCurrent_graf_data->net_message_enter_y + 6 * font->height,
|
||||
1);
|
||||
|
||||
TransDRPixelmapText(gBack_screen, 20 * gBack_screen->width / 100, gCurrent_graf_data->net_message_enter_y, font, GetMiscString(kMiscString_ENTER_MESSAGE), 100);
|
||||
OoerrIveGotTextInMeBoxMissus(
|
||||
FONT_NEWHITE,
|
||||
the_message,
|
||||
gBack_screen,
|
||||
20 * gBack_screen->width / 100,
|
||||
gCurrent_graf_data->net_message_enter_y + 2 * font->height,
|
||||
80 * gBack_screen->width / 100,
|
||||
gCurrent_graf_data->net_message_enter_y + 6 * font->height,
|
||||
0);
|
||||
the_message[len] = 0;
|
||||
}
|
||||
|
||||
// IDA: void __cdecl InitAbuseomatic()
|
||||
|
|
|
@ -665,7 +665,29 @@ void DoPratcamHit(br_vector3* pHit_vector) {
|
|||
br_scalar strength;
|
||||
LOG_TRACE("(%p)", pHit_vector);
|
||||
|
||||
STUB_ONCE();
|
||||
strength = BrVector3LengthSquared(pHit_vector);
|
||||
if (strength > 0.2f) {
|
||||
strength_modifier = 8;
|
||||
} else if (strength > 0.015f) {
|
||||
strength_modifier = 4;
|
||||
} else if (strength >= 0.001f) {
|
||||
strength_modifier = 0;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
if (fabsf(pHit_vector->v[2]) >= fabsf(pHit_vector->v[0])) {
|
||||
if (pHit_vector->v[2] >= 0.f) {
|
||||
PratcamEvent(14 + strength_modifier);
|
||||
} else {
|
||||
PratcamEvent(13 + strength_modifier);
|
||||
}
|
||||
} else {
|
||||
if (pHit_vector->v[0] >= 0.f) {
|
||||
PratcamEvent(15 + strength_modifier);
|
||||
} else {
|
||||
PratcamEvent(16 + strength_modifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall DamageSystems(tCar_spec *pCar@<EAX>, br_vector3 *pImpact_point@<EDX>, br_vector3 *pEnergy_vector@<EBX>, int pWas_hitting_a_car@<ECX>)
|
||||
|
@ -1153,7 +1175,7 @@ int DoCrashEarnings(tCar_spec* pCar1, tCar_spec* pCar2) {
|
|||
NetEarnCredits(NetPlayerFromCar(culprit), credits);
|
||||
} else {
|
||||
PratcamEvent(32);
|
||||
DoFancyHeadup(11);
|
||||
DoFancyHeadup(kFancyHeadupYouWastedEm);
|
||||
credits_squared = sqr(0.7f / victim->car_model_actors[victim->principal_car_actor].crush_data.softness_factor) * gWasted_creds[gProgram_state.skill_level] + 50.0f;
|
||||
credits = 100 * (int)(credits_squared / 100.0);
|
||||
AwardTime(gWasted_time[gProgram_state.skill_level]);
|
||||
|
@ -1218,13 +1240,13 @@ int DoCrashEarnings(tCar_spec* pCar1, tCar_spec* pCar2) {
|
|||
AwardTime(MIN(time, 90));
|
||||
if (pCar2) {
|
||||
if (head_on) {
|
||||
DoFancyHeadup(10);
|
||||
DoFancyHeadup(kFancyHeadupHeadOnBonus);
|
||||
} else if (bonus_level <= 2) {
|
||||
if (bonus_level > 1) {
|
||||
DoFancyHeadup(2);
|
||||
DoFancyHeadup(kFancyHeadupExtraStyleBonus);
|
||||
}
|
||||
} else {
|
||||
DoFancyHeadup(3);
|
||||
DoFancyHeadup(kFancyHeadupBonusForArtisticImpression);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -918,7 +918,15 @@ void ToggleSkyQuietly(void) {
|
|||
// IDA: void __cdecl ToggleSky()
|
||||
void ToggleSky(void) {
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
SetSkyTextureOn(!GetSkyTextureOn());
|
||||
if (gProgram_state.current_depth_effect.sky_texture != NULL) {
|
||||
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(kMiscString_SkyTextureOn));
|
||||
} else if (gSwap_sky_texture != NULL) {
|
||||
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(kMiscString_SkyTextureOff));
|
||||
} else {
|
||||
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(kMiscString_ThereIsNoSkyTextureForThisRace));
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: int __cdecl GetDepthCueingOn()
|
||||
|
@ -962,7 +970,15 @@ void ToggleDepthCueingQuietly(void) {
|
|||
// IDA: void __cdecl ToggleDepthCueing()
|
||||
void ToggleDepthCueing(void) {
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
SetDepthCueingOn(!GetDepthCueingOn());
|
||||
if (gProgram_state.current_depth_effect.type != eDepth_effect_none) {
|
||||
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(kMiscString_DepthCueingOn));
|
||||
} else if (gSwap_depth_effect_type != eDepth_effect_none) {
|
||||
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(kMiscString_DepthCueingOff));
|
||||
} else {
|
||||
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(kMiscString_ThereIsNoDepthCueingForThisRace));
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __cdecl ChangeDepthEffect()
|
||||
|
@ -976,7 +992,11 @@ void ChangeDepthEffect(void) {
|
|||
br_scalar distance;
|
||||
tSpecial_volume* special_volume;
|
||||
LOG_TRACE("()");
|
||||
STUB_ONCE();
|
||||
|
||||
gProgram_state.current_depth_effect.type = gProgram_state.default_depth_effect.type;
|
||||
gProgram_state.current_depth_effect.sky_texture = gProgram_state.default_depth_effect.sky_texture;
|
||||
gProgram_state.current_depth_effect.start = gProgram_state.default_depth_effect.start;
|
||||
gProgram_state.current_depth_effect.end = gProgram_state.default_depth_effect.end;
|
||||
}
|
||||
|
||||
// IDA: void __cdecl MungeForwardSky()
|
||||
|
|
|
@ -926,7 +926,13 @@ void MoveHeadupTo(int pHeadup_index, int pNew_x, int pNew_y) {
|
|||
int delta_x;
|
||||
tHeadup* the_headup;
|
||||
LOG_TRACE("(%d, %d, %d)", pHeadup_index, pNew_x, pNew_y);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (pHeadup_index >= 0) {
|
||||
delta_x = gHeadups[pHeadup_index].x - gHeadups[pHeadup_index].original_x;
|
||||
gHeadups[pHeadup_index].original_x = pNew_x;
|
||||
gHeadups[pHeadup_index].x = pNew_x + delta_x;
|
||||
gHeadups[pHeadup_index].y = pNew_y;
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall ChangeHeadupText(int pHeadup_index@<EAX>, char *pNew_text@<EDX>)
|
||||
|
|
|
@ -721,7 +721,23 @@ int FindFacesInBox2(tBounds* bnds, tFace_ref* face_list, int max_face) {
|
|||
int i;
|
||||
int j;
|
||||
LOG_TRACE("(%p, %p, %d)", bnds, face_list, max_face);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
a.v[0] = (bnds->original_bounds.min.v[0] + bnds->original_bounds.max.v[0]) * .5f;
|
||||
a.v[1] = (bnds->original_bounds.min.v[1] + bnds->original_bounds.max.v[1]) * .5f;
|
||||
a.v[2] = (bnds->original_bounds.min.v[2] + bnds->original_bounds.max.v[2]) * .5f;
|
||||
BrMatrix34ApplyP(&bnds->box_centre, &a, bnds->mat);
|
||||
BrVector3Sub(&b, &bnds->original_bounds.max, &bnds->original_bounds.min);
|
||||
bnds->radius = BrVector3Length(&b) / 2.f;
|
||||
BrMatrix34ApplyP(&bnds->real_bounds.min, &bnds->original_bounds.min, bnds->mat);
|
||||
BrVector3Copy(&bnds->real_bounds.max, &bnds->real_bounds.min);
|
||||
for (i = 0; i < 3; i++) {
|
||||
BrVector3Scale(&c[i], (br_vector3*)bnds->mat->m[i], b.v[i]);
|
||||
}
|
||||
for (i = 0; i < 3; i++) {
|
||||
bnds->real_bounds.min.v[i] += MIN(0.f, c[0].v[i]) + MIN(0.f, c[1].v[i]) + MIN(0.f, c[2].v[i]);
|
||||
bnds->real_bounds.max.v[i] += MAX(0.f, c[0].v[i]) + MAX(0.f, c[1].v[i]) + MAX(0.f, c[2].v[i]);
|
||||
}
|
||||
return max_face - ActorBoxPick(bnds, gTrack_actor, model_unk1, material_unk1, face_list, max_face, NULL);
|
||||
}
|
||||
|
||||
// IDA: int __usercall ActorBoxPick@<EAX>(tBounds *bnds@<EAX>, br_actor *ap@<EDX>, br_model *model@<EBX>, br_material *material@<ECX>, tFace_ref *face_list, int max_face, br_matrix34 *pMat)
|
||||
|
@ -1216,7 +1232,20 @@ int CompVert(int v1, int v2) {
|
|||
br_vector3 tv;
|
||||
br_vector2 tv2;
|
||||
LOG_TRACE("(%d, %d)", v1, v2);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (v1 == v2) {
|
||||
return 1;
|
||||
}
|
||||
vl = gSelected_model->vertices;
|
||||
BrVector3Sub(&tv, &vl[v1].p, &vl[v2].p);
|
||||
if (BrVector3LengthSquared(&tv) > 1e-5f) {
|
||||
return 0;
|
||||
}
|
||||
BrVector2Sub(&tv2, &vl[v1].map, &vl[v2].map);
|
||||
if (BrVector2LengthSquared(&tv2) > 1e-5f) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// IDA: void __usercall SetFacesGroup(int pFace@<EAX>)
|
||||
|
@ -1248,7 +1277,25 @@ void GetTilingLimits(br_vector2* min, br_vector2* max) {
|
|||
br_vertex* verts;
|
||||
br_face* faces;
|
||||
LOG_TRACE("(%p, %p)", min, max);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
verts = gSelected_model->vertices;
|
||||
faces = gSelected_model->faces;
|
||||
BrVector2Set(min, 32000.f, 32000.f);
|
||||
BrVector2Set(max, -32000.f, -32000.f);
|
||||
for (f = 0; f < gSelected_model->nfaces; f++) {
|
||||
if (faces[f].material == gSub_material) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
for (j = 0; j < 3; j++) {
|
||||
if (verts[faces[f].vertices[i]].map.v[j] < min->v[j]) {
|
||||
min->v[j] = verts[faces[f].vertices[i]].map.v[j];
|
||||
}
|
||||
if (verts[faces[f].vertices[i]].map.v[j] > max->v[j]) {
|
||||
max->v[j] = verts[faces[f].vertices[i]].map.v[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall Scale(int pD@<EAX>, int factor@<EDX>)
|
||||
|
@ -1261,43 +1308,74 @@ void Scale(int pD, int factor) {
|
|||
br_vertex* verts;
|
||||
br_face* faces;
|
||||
LOG_TRACE("(%d, %d)", pD, factor);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (gSelected_model == NULL) {
|
||||
return;
|
||||
}
|
||||
if (gSelected_model->nfaces != gNfaces) {
|
||||
return;
|
||||
}
|
||||
verts = gSelected_model->vertices;
|
||||
faces = gSelected_model->faces;
|
||||
GetTilingLimits(&min, &max);
|
||||
d = max.v[pD] - min.v[pD];
|
||||
if (d <= 0.f || factor + d <= 0.f) {
|
||||
return;
|
||||
}
|
||||
for (v = 0; v < gSelected_model->nvertices; v++) {
|
||||
for (f = 0; f < gSelected_model->nfaces; f++) {
|
||||
if (faces[f].material == gSub_material
|
||||
&& (faces[f].vertices[0] == v || faces[f].vertices[1] == v || faces[f].vertices[2] == v)) {
|
||||
verts[v].map.v[pD] = (factor + d) / d * verts[v].map.v[pD];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
BrModelUpdate(gSelected_model, BR_MODU_ALL);
|
||||
}
|
||||
|
||||
// IDA: void __cdecl ScaleUpX()
|
||||
void ScaleUpX(void) {
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
Scale(0, 1);
|
||||
}
|
||||
|
||||
// IDA: void __cdecl ScaleDnX()
|
||||
void ScaleDnX(void) {
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
Scale(0, -1);
|
||||
}
|
||||
|
||||
// IDA: void __cdecl ScaleUpY()
|
||||
void ScaleUpY(void) {
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
Scale(1, 1);
|
||||
}
|
||||
|
||||
// IDA: void __cdecl ScaleDnY()
|
||||
void ScaleDnY(void) {
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
Scale(1, -1);
|
||||
}
|
||||
|
||||
// IDA: void __cdecl SelectFaceForward()
|
||||
void SelectFaceForward(void) {
|
||||
br_vector3 dir;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
BrVector3Scale(&dir, (br_vector3*)&gProgram_state.current_car.car_master_actor->t.t.mat.m[2], -2.f);
|
||||
SelectFace(&dir);
|
||||
}
|
||||
|
||||
// IDA: void __cdecl SelectFaceDown()
|
||||
void SelectFaceDown(void) {
|
||||
br_vector3 dir;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
BrVector3Scale(&dir, (br_vector3*)&gProgram_state.current_car.car_master_actor->t.t.look_up.up, -2.f);
|
||||
SelectFace(&dir);
|
||||
}
|
||||
|
|
|
@ -736,23 +736,19 @@ int StartFlic(char* pFile_name, int pIndex, tFlic_descriptor_ptr pFlic_info, tU3
|
|||
MemSkipBytes(&pFlic_info->data, 0x6e);
|
||||
pFlic_info->the_pixelmap = pDest_pixelmap;
|
||||
|
||||
if (pX_offset == -1) {
|
||||
if (pDest_pixelmap != NULL) {
|
||||
pFlic_info->x_offset = (pDest_pixelmap->width - pFlic_info->width) / 2;
|
||||
} else {
|
||||
pFlic_info->x_offset = 0;
|
||||
}
|
||||
} else {
|
||||
if (pX_offset != -1) {
|
||||
pFlic_info->x_offset = pX_offset;
|
||||
}
|
||||
if (pY_offset == -1) {
|
||||
if (pDest_pixelmap != NULL) {
|
||||
pFlic_info->y_offset = (pDest_pixelmap->height - pFlic_info->height) / 2;
|
||||
} else {
|
||||
pFlic_info->y_offset = 0;
|
||||
}
|
||||
} else if (pDest_pixelmap != NULL) {
|
||||
pFlic_info->x_offset = (pDest_pixelmap->width - pFlic_info->width) / 2;
|
||||
} else {
|
||||
pFlic_info->x_offset = 0;
|
||||
}
|
||||
if (pY_offset != -1) {
|
||||
pFlic_info->y_offset = pY_offset;
|
||||
} else if (pDest_pixelmap != NULL) {
|
||||
pFlic_info->y_offset = (pDest_pixelmap->height - pFlic_info->height) / 2;
|
||||
} else {
|
||||
pFlic_info->y_offset = 0;
|
||||
}
|
||||
|
||||
if (pFrame_rate != 0) {
|
||||
|
|
|
@ -709,7 +709,11 @@ void InitializePalettes(void) {
|
|||
void SwitchToPalette(char* pPal_name) {
|
||||
br_pixelmap* the_palette;
|
||||
LOG_TRACE("(\"%s\")", pPal_name);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
the_palette = BrTableFind(pPal_name);
|
||||
if (the_palette != NULL) {
|
||||
DRSetPalette(the_palette);
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __cdecl ClearEntireScreen()
|
||||
|
|
|
@ -1608,7 +1608,14 @@ void ReadShrapnelMaterials(FILE* pF, tCollision_info* pCar_spec) {
|
|||
void CloneCar(tCar_spec** pOutput_car, tCar_spec* pInput_car) {
|
||||
int i;
|
||||
LOG_TRACE("(%p, %p)", pOutput_car, pInput_car);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
*pOutput_car = BrMemAllocate(sizeof(tCar_spec), kMem_cop_car_spec);
|
||||
**pOutput_car = *pInput_car;
|
||||
(*pOutput_car)->car_master_actor = CloneActor(pInput_car->car_master_actor);
|
||||
BrActorAdd(gNon_track_actor, (*pOutput_car)->car_master_actor);
|
||||
for (i = 0; i < pInput_car->car_actor_count; i++) {
|
||||
(*pOutput_car)->car_model_actors[i].actor = DRActorFindRecurse((*pOutput_car)->car_master_actor, pInput_car->car_model_actors[i].actor->identifier);
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall DisposeClonedCar(tCar_spec *pCar@<EAX>)
|
||||
|
@ -2900,7 +2907,11 @@ float GetAFloatPercent(FILE* pF) {
|
|||
char* str;
|
||||
float result;
|
||||
LOG_TRACE("(%p)", pF);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
GetALineAndDontArgue(pF, s);
|
||||
str = strtok(s, "\t ,/");
|
||||
sscanf(str, "%f", &result);
|
||||
return result / 100.f;
|
||||
}
|
||||
|
||||
// IDA: void __usercall GetPairOfFloats(FILE *pF@<EAX>, float *pF1@<EDX>, float *pF2@<EBX>)
|
||||
|
@ -2960,7 +2971,16 @@ void GetThreeIntsAndAString(FILE* pF, int* pF1, int* pF2, int* pF3, char* pS) {
|
|||
char s[256];
|
||||
char* str;
|
||||
LOG_TRACE("(%p, %p, %p, %p, \"%s\")", pF, pF1, pF2, pF3, pS);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
GetALineAndDontArgue(pF, s);
|
||||
str = strtok(s, "\t ,/");
|
||||
sscanf(str, "%d", pF1);
|
||||
str = strtok(NULL, "\t ,/");
|
||||
sscanf(str, "%d", pF2);
|
||||
str = strtok(NULL, "\t ,/");
|
||||
sscanf(str, "%d", pF3);
|
||||
str = strtok(NULL, "\t ,/");
|
||||
strcpy(pS, str);
|
||||
}
|
||||
|
||||
// IDA: void __usercall GetFourInts(FILE *pF@<EAX>, int *pF1@<EDX>, int *pF2@<EBX>, int *pF3@<ECX>, int *pF4)
|
||||
|
@ -2989,7 +3009,8 @@ br_scalar GetAScalar(FILE* pF) {
|
|||
// IDA: void __usercall GetPairOfScalars(FILE *pF@<EAX>, br_scalar *pS1@<EDX>, br_scalar *pS2@<EBX>)
|
||||
void GetPairOfScalars(FILE* pF, br_scalar* pS1, br_scalar* pS2) {
|
||||
LOG_TRACE("(%p, %p, %p)", pF, pS1, pS2);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
GetPairOfFloats(pF, pS1, pS2);
|
||||
}
|
||||
|
||||
// IDA: void __usercall GetThreeScalars(FILE *pF@<EAX>, br_scalar *pS1@<EDX>, br_scalar *pS2@<EBX>, br_scalar *pS3@<ECX>)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -19,6 +19,7 @@
|
|||
#include "pedestrn.h"
|
||||
#include "piping.h"
|
||||
#include "powerup.h"
|
||||
#include "pratcam.h"
|
||||
#include "replay.h"
|
||||
#include "spark.h"
|
||||
#include "structur.h"
|
||||
|
@ -160,7 +161,8 @@ int PermitNetServiceReentrancy(void) {
|
|||
// IDA: void __cdecl HaltNetServiceReentrancy()
|
||||
void HaltNetServiceReentrancy(void) {
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
gIn_net_service = 1;
|
||||
}
|
||||
|
||||
// IDA: void __usercall NetSendHeadupToAllPlayers(char *pMessage@<EAX>)
|
||||
|
@ -178,14 +180,34 @@ void NetSendHeadupToAllPlayers(char* pMessage) {
|
|||
void NetSendHeadupToEverybody(char* pMessage) {
|
||||
tNet_contents* the_contents;
|
||||
LOG_TRACE("(\"%s\")", pMessage);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (gNet_mode == eNet_mode_none) {
|
||||
return;
|
||||
}
|
||||
if (gProgram_state.racing) {
|
||||
NewTextHeadupSlot(4, 0, 3000, -4, pMessage);
|
||||
}
|
||||
the_contents = NetGetBroadcastContents(NETMSGID_HEADUP, 0);
|
||||
strcpy(the_contents->data.headup.text, pMessage);
|
||||
}
|
||||
|
||||
// IDA: void __usercall NetSendHeadupToPlayer(char *pMessage@<EAX>, tPlayer_ID pPlayer@<EDX>)
|
||||
void NetSendHeadupToPlayer(char* pMessage, tPlayer_ID pPlayer) {
|
||||
tNet_message* message;
|
||||
LOG_TRACE("(\"%s\", %d)", pMessage, pPlayer);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (gNet_mode == eNet_mode_none) {
|
||||
return;
|
||||
}
|
||||
if (gLocal_net_ID == pPlayer) {
|
||||
if (gProgram_state.racing) {
|
||||
NewTextHeadupSlot(4, 0, 3000, -4, pMessage);
|
||||
}
|
||||
} else {
|
||||
message = NetBuildMessage(NETMSGID_HEADUP, 0);
|
||||
strcpy(message->contents.data.headup.text, pMessage);
|
||||
NetGuaranteedSendMessageToPlayer(gCurrent_net_game, message, pPlayer, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __cdecl InitialisePlayerStati()
|
||||
|
@ -378,7 +400,8 @@ void NetSetPlayerSystemInfo(tNet_game_player_info* pPlayer, void* pSender_addres
|
|||
// IDA: void __usercall NetDisposePlayer(tNet_game_player_info *pPlayer@<EAX>)
|
||||
void NetDisposePlayer(tNet_game_player_info* pPlayer) {
|
||||
LOG_TRACE("(%p)", pPlayer);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
PDNetDisposePlayer(pPlayer);
|
||||
}
|
||||
|
||||
// IDA: void __usercall FillInThisPlayer(tNet_game_details *pGame@<EAX>, tNet_game_player_info *pPlayer@<EDX>, int pCar_index@<EBX>, int pHost@<ECX>)
|
||||
|
@ -460,7 +483,15 @@ void DisposeCarN(int pIndex) {
|
|||
// IDA: void __usercall PlayerHasLeft(int pIndex@<EAX>)
|
||||
void PlayerHasLeft(int pIndex) {
|
||||
LOG_TRACE("(%d)", pIndex);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (gCurrent_net_game->options.random_car_choice && (gCurrent_net_game->options.car_choice == eNet_car_all || gCurrent_net_game->options.car_choice == eNet_car_both)) {
|
||||
if (gNet_players[pIndex].car_index >= 0) {
|
||||
gCar_details[gNet_players[pIndex].car_index].ownership = eCar_owner_none;
|
||||
}
|
||||
if (gNet_players[pIndex].next_car_index >= 0) {
|
||||
gCar_details[gNet_players[pIndex].next_car_index].ownership = eCar_owner_none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall NetPlayersChanged(int pNew_count@<EAX>, tNet_game_player_info *pNew_players@<EDX>)
|
||||
|
@ -475,7 +506,14 @@ void NetPlayersChanged(int pNew_count, tNet_game_player_info* pNew_players) {
|
|||
LOG_TRACE("(%d, %p)", pNew_count, pNew_players);
|
||||
|
||||
if (gCurrent_net_game->type == eNet_game_type_tag || gCurrent_net_game->type == eNet_game_type_foxy) {
|
||||
old_fox_it = gNet_players[gIt_or_fox].ID;
|
||||
#ifdef DETHRACE_FIX_BUGS
|
||||
old_fox_it = -1;
|
||||
if (gIt_or_fox >= 0) {
|
||||
#endif
|
||||
old_fox_it = gNet_players[gIt_or_fox].ID;
|
||||
#ifdef DETHRACE_FIX_BUGS
|
||||
}
|
||||
#endif
|
||||
}
|
||||
for (i = 0; i < pNew_count; i++) {
|
||||
new_player = 1;
|
||||
|
@ -612,7 +650,8 @@ tNet_game_details* NetHostGame(tNet_game_type pGame_type, tNet_game_options* pOp
|
|||
// IDA: int __usercall NetInitClient@<EAX>(tNet_game_details *pDetails@<EAX>)
|
||||
int NetInitClient(tNet_game_details* pDetails) {
|
||||
LOG_TRACE("(%p)", pDetails);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
return PDNetInitClient(pDetails);
|
||||
}
|
||||
|
||||
// IDA: int __usercall NetJoinGameLowLevel@<EAX>(tNet_game_details *pDetails@<EAX>, char *pPlayer_name@<EDX>)
|
||||
|
@ -622,6 +661,12 @@ int NetJoinGameLowLevel(tNet_game_details* pDetails, char* pPlayer_name) {
|
|||
return PDNetJoinGame(pDetails, pPlayer_name);
|
||||
}
|
||||
|
||||
DR_STATIC_ASSERT(offsetof(tNet_message_join, player_info) == 4);
|
||||
DR_STATIC_ASSERT(offsetof(tNet_game_player_info, this_players_time_stamp) == 0x10);
|
||||
DR_STATIC_ASSERT(offsetof(tNet_game_player_info, wasted) == 0x68);
|
||||
DR_STATIC_ASSERT(offsetof(tNet_game_player_info, initial_position) == 0x8c);
|
||||
DR_STATIC_ASSERT(offsetof(tNet_game_player_info, car) == 0xbc);
|
||||
|
||||
// IDA: int __usercall NetJoinGame@<EAX>(tNet_game_details *pDetails@<EAX>, char *pPlayer_name@<EDX>, int pCar_index@<EBX>)
|
||||
int NetJoinGame(tNet_game_details* pDetails, char* pPlayer_name, int pCar_index) {
|
||||
int result;
|
||||
|
@ -718,19 +763,39 @@ int NetSendMessageToAddress(tNet_game_details* pDetails, tNet_message* pMessage,
|
|||
int NetSendMessageToPlayer(tNet_game_details* pDetails, tNet_message* pMessage, tPlayer_ID pPlayer) {
|
||||
int i;
|
||||
LOG_TRACE("(%p, %p, %d)", pDetails, pMessage, pPlayer);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (gNet_mode == eNet_mode_none) {
|
||||
return -3;
|
||||
}
|
||||
pMessage->sender = gLocal_net_ID;
|
||||
pMessage->senders_time_stamp = PDGetTotalTime();
|
||||
for (i = 0; i < gNumber_of_net_players; i++) {
|
||||
if (gNet_players[i].ID == pPlayer) {
|
||||
GetCheckSum(pMessage);
|
||||
return PDNetSendMessageToAddress(pDetails, pMessage, &gNet_players[i]);
|
||||
}
|
||||
}
|
||||
return -3;
|
||||
}
|
||||
|
||||
// IDA: int __usercall NetSendMessageToHost@<EAX>(tNet_game_details *pDetails@<EAX>, tNet_message *pMessage@<EDX>)
|
||||
int NetSendMessageToHost(tNet_game_details* pDetails, tNet_message* pMessage) {
|
||||
LOG_TRACE("(%p, %p)", pDetails, pMessage);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (gNet_mode == eNet_mode_none) {
|
||||
return -3;
|
||||
}
|
||||
pMessage->sender = gLocal_net_ID;
|
||||
pMessage->senders_time_stamp = PDGetTotalTime();
|
||||
DoCheckSum(pMessage);
|
||||
return PDNetSendMessageToAddress(pDetails, pMessage, &pDetails->pd_net_info);
|
||||
}
|
||||
|
||||
// IDA: int __usercall NetReplyToMessage@<EAX>(tNet_game_details *pDetails@<EAX>, tNet_message *pIncoming_message@<EDX>, tNet_message *pReply_message@<EBX>)
|
||||
int NetReplyToMessage(tNet_game_details* pDetails, tNet_message* pIncoming_message, tNet_message* pReply_message) {
|
||||
LOG_TRACE("(%p, %p, %p)", pDetails, pIncoming_message, pReply_message);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
return NetSendMessageToPlayer(pDetails, pReply_message, pIncoming_message->sender);
|
||||
}
|
||||
|
||||
// IDA: int __usercall NetSendMessageToAllPlayers@<EAX>(tNet_game_details *pDetails@<EAX>, tNet_message *pMessage@<EDX>)
|
||||
|
@ -843,7 +908,8 @@ tU32 NetGetMessageSize(tNet_message_type pType, tS32 pSize_decider) {
|
|||
tS32 NetCalcSizeDecider(tNet_contents* pContents) {
|
||||
tS32 the_decider;
|
||||
LOG_TRACE("(%p)", pContents);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// IDA: tNet_message* __usercall NetBuildMessage@<EAX>(tNet_message_type pType@<EAX>, tS32 pSize_decider@<EDX>)
|
||||
|
@ -867,7 +933,23 @@ tNet_contents* NetGetToHostContents(tNet_message_type pType, tS32 pSize_decider)
|
|||
tU32 the_size;
|
||||
tNet_contents* contents;
|
||||
LOG_TRACE("(%d, %d)", pType, pSize_decider);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
the_size = NetGetContentsSize(pType, pSize_decider);
|
||||
if (gTo_host_stack && the_size + gTo_host_stack->overall_size > MAX_MESAGE_STACK_SIZE) {
|
||||
NetSendMessageToHost(gCurrent_net_game, gTo_host_stack);
|
||||
gTo_host_stack = 0;
|
||||
}
|
||||
if (!gTo_host_stack) {
|
||||
gTo_host_stack = NetAllocateMessage(MAX_MESAGE_STACK_SIZE);
|
||||
gTo_host_stack->overall_size = offsetof(tNet_message, contents);
|
||||
gTo_host_stack->num_contents = 0;
|
||||
}
|
||||
contents = (tNet_contents*)((char*)gTo_host_stack + gTo_host_stack->overall_size);
|
||||
gTo_host_stack->overall_size += the_size;
|
||||
contents->header.type = pType;
|
||||
contents->header.contents_size = the_size;
|
||||
gTo_host_stack->num_contents++;
|
||||
return contents;
|
||||
}
|
||||
|
||||
// IDA: tNet_contents* __usercall NetGetBroadcastContents@<EAX>(tNet_message_type pType@<EAX>, tS32 pSize_decider@<EDX>)
|
||||
|
@ -969,7 +1051,7 @@ tNet_message* NetAllocateMessage(int pSize) {
|
|||
} else {
|
||||
gMessage_to_free = pointer;
|
||||
}
|
||||
pointer = ((void**)pointer)[1];
|
||||
pointer = (char*)pointer + sizeof(void*);
|
||||
}
|
||||
}
|
||||
if (pointer == NULL) {
|
||||
|
@ -1075,7 +1157,7 @@ void ReceivedJoin(tNet_contents* pContents, void* pSender_address) {
|
|||
LOG_TRACE("(%p, %p)", pContents, pSender_address);
|
||||
|
||||
new_player_count = gNumber_of_net_players;
|
||||
new_players = BrMemAllocate(new_player_count + 1 * sizeof(tNet_game_player_info), kMem_player_list_join);
|
||||
new_players = BrMemAllocate((new_player_count + 1) * sizeof(tNet_game_player_info), kMem_player_list_join);
|
||||
memcpy(new_players, gNet_players, gNumber_of_net_players * sizeof(tNet_game_player_info));
|
||||
|
||||
if ((!gCurrent_net_game->options.open_game && gProgram_state.racing) || gCurrent_net_game->num_players > 5 || gDont_allow_joiners) {
|
||||
|
@ -1128,13 +1210,39 @@ void KickPlayerOut(tPlayer_ID pID) {
|
|||
int new_player_count;
|
||||
tNet_game_player_info* new_players;
|
||||
LOG_TRACE("(%d)", pID);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
new_player_count = gNumber_of_net_players;
|
||||
new_players = (tNet_game_player_info*)BrMemAllocate(sizeof(tNet_game_player_info) * gNumber_of_net_players, kMem_player_list_leave);
|
||||
memcpy(new_players, gNet_players, sizeof(tNet_game_player_info) * new_player_count);
|
||||
for (i = 0; i < new_player_count; i++) {
|
||||
if (new_players[i].ID == pID) {
|
||||
if (new_players[i].car_index >= 0) {
|
||||
gCar_details[new_players[i].car_index].ownership = eCar_owner_none;
|
||||
}
|
||||
if (new_players[i].next_car_index >= 0 && gCurrent_net_game->options.random_car_choice && (gCurrent_net_game->options.car_choice == eNet_car_all || gCurrent_net_game->options.car_choice == eNet_car_both)) {
|
||||
gCar_details[new_players[i].next_car_index].ownership = eCar_owner_none;
|
||||
}
|
||||
#ifdef DETHRACE_FIX_BUGS
|
||||
for (j = i; j < new_player_count - 1; j++) {
|
||||
#else
|
||||
for (j = i; j < new_player_count; j++) {
|
||||
#endif
|
||||
memcpy(&new_players[j], &new_players[j + 1], sizeof(tNet_game_player_info));
|
||||
}
|
||||
new_player_count--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
NetPlayersChanged(new_player_count, new_players);
|
||||
BrMemFree(new_players);
|
||||
SendOutPlayerList();
|
||||
}
|
||||
|
||||
// IDA: void __usercall ReceivedLeave(tNet_contents *pContents@<EAX>, tNet_message *pMessage@<EDX>)
|
||||
void ReceivedLeave(tNet_contents* pContents, tNet_message* pMessage) {
|
||||
LOG_TRACE("(%p, %p)", pContents, pMessage);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
KickPlayerOut(pMessage->sender);
|
||||
}
|
||||
|
||||
// IDA: void __usercall NetFullScreenMessage(int pStr_index@<EAX>, int pLeave_it_up_there@<EDX>)
|
||||
|
@ -1213,7 +1321,7 @@ void HostHasBittenTheDust(int pMessage_index) {
|
|||
void ReceivedHosticide(tNet_contents* pContents) {
|
||||
LOG_TRACE("(%p)", pContents);
|
||||
|
||||
HostHasBittenTheDust(73);
|
||||
HostHasBittenTheDust(kMiscString_GAME_TERMINATED_BY_HOST);
|
||||
}
|
||||
|
||||
// IDA: void __cdecl ConfirmReceipt()
|
||||
|
@ -1316,7 +1424,50 @@ void ReceivedStartRace(tNet_contents* pContents) {
|
|||
int i;
|
||||
int index;
|
||||
LOG_TRACE("(%p)", pContents);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (pContents->data.player_list.number_of_players == -1) {
|
||||
if (gProgram_state.racing) {
|
||||
index = pContents->data.start_race.car_list[0].index;
|
||||
BrMatrix34Copy(&gNet_players[index].car->car_master_actor->t.t.mat, &pContents->data.start_race.car_list[0].mat);
|
||||
ReinitialiseCar(gNet_players[index].car);
|
||||
if (gThis_net_player_index == index) {
|
||||
if (!gInterface_within_race_mode) {
|
||||
FadePaletteDown();
|
||||
}
|
||||
CancelPendingCunningStunt();
|
||||
gProgram_state.credits_earned = gInitial_net_credits[gCurrent_net_game->options.starting_money_index];
|
||||
gProgram_state.credits_lost = 0;
|
||||
InitialiseExternalCamera();
|
||||
}
|
||||
gNet_players[index].last_waste_message = 0;
|
||||
gNet_players[index].wasteage_attributed = 0;
|
||||
}
|
||||
} else if (gSynch_race_start) {
|
||||
for (i = 0; i < pContents->data.start_race.car_count; i++) {
|
||||
gNet_players[pContents->data.start_race.car_list[i].index].next_car_index = pContents->data.start_race.car_list[i].next_car_index;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < pContents->data.player_list.number_of_players; i++) {
|
||||
gCurrent_race.number_of_racers = i + 1;
|
||||
gCurrent_race.opponent_list[i].index = -1;
|
||||
gCurrent_race.opponent_list[i].ranking = -1;
|
||||
gCurrent_race.opponent_list[i].car_spec = gNet_players[pContents->data.start_race.car_list[i].index].car;
|
||||
gCurrent_race.opponent_list[i].net_player_index = pContents->data.start_race.car_list[i].index;
|
||||
gNet_players[gCurrent_race.opponent_list[i].net_player_index].last_waste_message = 0;
|
||||
gNet_players[gCurrent_race.opponent_list[i].net_player_index].wasteage_attributed = 0;
|
||||
if (!gProgram_state.racing || gCurrent_race.opponent_list[i].car_spec->driver != eDriver_local_human) {
|
||||
BrMatrix34Copy(&gCurrent_race.opponent_list[i].car_spec->car_master_actor->t.t.mat, &pContents->data.start_race.car_list[i].mat);
|
||||
InitialiseCar(gCurrent_race.opponent_list[i].car_spec);
|
||||
}
|
||||
gNet_players[pContents->data.start_race.car_list[i].index].next_car_index = pContents->data.start_race.car_list[i].next_car_index;
|
||||
}
|
||||
gPending_race = pContents->data.player_list.batch_number;
|
||||
gCurrent_race.number_of_racers = pContents->data.player_list.number_of_players;
|
||||
gSynch_race_start = 1;
|
||||
if (!pContents->data.player_list.this_index || gProgram_state.racing) {
|
||||
gWait_for_it = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall ReceivedGuaranteeReply(tNet_contents *pContents@<EAX>)
|
||||
|
@ -1363,14 +1514,14 @@ void ReceivedHostReply(tNet_contents* pContents) {
|
|||
|
||||
if (pContents->data.heres_where_we_at.race_index != gProgram_state.current_race_index) {
|
||||
NetLeaveGame(gCurrent_net_game);
|
||||
NetFullScreenMessage(128, 0);
|
||||
NetFullScreenMessage(kMiscString_RACE_CHANGED_DURING_LOADING, 0);
|
||||
gProgram_state.prog_status = eProg_idling;
|
||||
}
|
||||
if (pContents->data.heres_where_we_at.race_has_started) {
|
||||
if (gCurrent_net_game->options.open_game) {
|
||||
gPending_race = pContents->data.heres_where_we_at.pending_race;
|
||||
} else {
|
||||
NetFullScreenMessage(89, 0);
|
||||
NetFullScreenMessage(kMiscString_SORRY_YOU_RE_TOO_LATE, 0);
|
||||
gProgram_state.prog_status = eProg_idling;
|
||||
}
|
||||
}
|
||||
|
@ -1404,33 +1555,46 @@ int PlayerIsInList(tPlayer_ID pID) {
|
|||
// IDA: void __usercall ReceivedTimeSync(tNet_contents *pContents@<EAX>, tNet_message *pMessage@<EDX>, tU32 pReceive_time@<EBX>)
|
||||
void ReceivedTimeSync(tNet_contents* pContents, tNet_message* pMessage, tU32 pReceive_time) {
|
||||
LOG_TRACE("(%p, %p, %d)", pContents, pMessage, pReceive_time);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (pMessage->senders_time_stamp - pContents->data.time_sync.race_start_time > pReceive_time + 10) {
|
||||
gRace_start -= pMessage->senders_time_stamp - pContents->data.time_sync.race_start_time - pReceive_time;
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall ReceivedConfirm(tNet_contents *pContents@<EAX>)
|
||||
void ReceivedConfirm(tNet_contents* pContents) {
|
||||
int i;
|
||||
LOG_TRACE("(%p)", pContents);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
for (i = 0; i < gNumber_of_net_players; i++) {
|
||||
if (gNet_players[i].ID == pContents->data.confirm.player) {
|
||||
gNet_players[i].awaiting_confirmation = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall ReceivedDisableCar(tNet_contents *pContents@<EAX>)
|
||||
void ReceivedDisableCar(tNet_contents* pContents) {
|
||||
LOG_TRACE("(%p)", pContents);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
}
|
||||
|
||||
// IDA: void __usercall ReceivedEnableCar(tNet_contents *pContents@<EAX>)
|
||||
void ReceivedEnableCar(tNet_contents* pContents) {
|
||||
LOG_TRACE("(%p)", pContents);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
}
|
||||
|
||||
// IDA: void __usercall ReceivedScores(tNet_contents *pContents@<EAX>)
|
||||
void ReceivedScores(tNet_contents* pContents) {
|
||||
int i;
|
||||
LOG_TRACE("(%p)", pContents);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
UseGeneralScore(pContents->data.scores.general_score);
|
||||
for (i = 0; i < gNumber_of_net_players; i++) {
|
||||
gNet_players[i].score = pContents->data.scores.scores[i];
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall ReceivedWasted(tNet_contents *pContents@<EAX>)
|
||||
|
@ -1445,7 +1609,62 @@ void ReceivedWasted(tNet_contents* pContents) {
|
|||
static tNet_game_player_info* last_culprit;
|
||||
static tNet_game_player_info* last_victim;
|
||||
LOG_TRACE("(%p)", pContents);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
victim = NetPlayerFromID(pContents->data.wasted.victim);
|
||||
if (victim == NULL) {
|
||||
return;
|
||||
}
|
||||
victim->car->knackered = 1;
|
||||
if (pContents->data.wasted.victim == gLocal_net_ID) {
|
||||
if (gCurrent_net_game->type == eNet_game_type_fight_to_death) {
|
||||
DoFancyHeadup(kFancyHeadupYouLost);
|
||||
gRace_finished = 1;
|
||||
} else {
|
||||
last_got_wasted_time = PDGetTotalTime();
|
||||
if (last_got_wasted_time - last_wasted_em_time > 1000) {
|
||||
DoFancyHeadup(kFancyHeadupYouAreWasted);
|
||||
} else {
|
||||
DoFancyHeadup(kFancyHeadupYouAreBothWasted);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pContents->data.wasted.culprit == -1) {
|
||||
if (victim->last_waste_message == 0) {
|
||||
victim->last_waste_message = GetTotalTime();
|
||||
}
|
||||
} else if (!victim->wasteage_attributed) {
|
||||
if (pContents->data.wasted.culprit == -2) {
|
||||
culprit = NULL;
|
||||
} else {
|
||||
culprit = NetPlayerFromID(pContents->data.wasted.culprit);
|
||||
}
|
||||
if (culprit != NULL && gNet_mode == eNet_mode_host && gCurrent_net_game->type == eNet_game_type_car_crusher) {
|
||||
culprit->score++;
|
||||
if (culprit->score >= gCurrent_net_game->options.race_end_target) {
|
||||
DeclareWinner(culprit - gNet_players);
|
||||
}
|
||||
}
|
||||
victim->last_waste_message = GetTotalTime();
|
||||
victim->wasteage_attributed = 1;
|
||||
if (victim == last_culprit && culprit == last_victim && victim != NULL && culprit != NULL && PDGetTotalTime() - last_wasty_message_time < 1000) {
|
||||
sprintf(s, "%s %s %s %s", victim->player_name, GetMiscString(kMiscString_AND), culprit->player_name, GetMiscString(kMiscString_WASTED_EACH_OTHER));
|
||||
} else {
|
||||
sprintf(s, "%s %s %s", victim->player_name, GetMiscString(kMiscString_WastedBy), culprit ? culprit->player_name : GetMiscString(kMiscString_COP));
|
||||
}
|
||||
NewTextHeadupSlot2(4, 0, 3000, -4, s, 0);
|
||||
last_wasty_message_time = PDGetTotalTime();
|
||||
last_culprit = culprit;
|
||||
last_victim = victim;
|
||||
if (pContents->data.wasted.culprit == gLocal_net_ID) {
|
||||
PratcamEvent(32);
|
||||
last_wasted_em_time = PDGetTotalTime();
|
||||
if (last_wasted_em_time - last_got_wasted_time > 1000) {
|
||||
DoFancyHeadup(kFancyHeadupYouWastedEm);
|
||||
} else {
|
||||
DoFancyHeadup(kFancyHeadupYouAreBothWasted);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall ReceivedCarDetailsReq(tNet_contents *pContents@<EAX>, void *pSender_address@<EDX>)
|
||||
|
@ -1487,7 +1706,13 @@ void ReceivedCarDetails(tNet_contents* pContents) {
|
|||
void ReceivedGameScores(tNet_contents* pContents) {
|
||||
int i;
|
||||
LOG_TRACE("(%p)", pContents);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
gReceived_game_scores = 1;
|
||||
for (i = 0; i < gNumber_of_net_players; i++) {
|
||||
gNet_players[i].played = pContents->data.game_scores.scores[i].played;
|
||||
gNet_players[i].won = pContents->data.game_scores.scores[i].won;
|
||||
gNet_players[i].games_score = pContents->data.game_scores.scores[i].score;
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall ReceivedMessage(tNet_message *pMessage@<EAX>, void *pSender_address@<EDX>, tU32 pReceive_time@<EBX>)
|
||||
|
@ -1671,7 +1896,7 @@ void CheckForDisappearees(void) {
|
|||
}
|
||||
}
|
||||
} else if (!gHost_died && gNumber_of_net_players != 0 && gNet_players[0].last_heard_from_him != 0 && the_time - gNet_players[0].last_heard_from_him >= 20000) {
|
||||
HostHasBittenTheDust(91);
|
||||
HostHasBittenTheDust(kMiscString_PANIC_HOST_HAS_DISAPPEARED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1784,7 +2009,13 @@ int NetGuaranteedSendMessageToAllPlayers(tNet_game_details* pDetails, tNet_messa
|
|||
// IDA: int __usercall NetGuaranteedSendMessageToEverybody@<EAX>(tNet_game_details *pDetails@<EAX>, tNet_message *pMessage@<EDX>, int (*pNotifyFail)(tU32, tNet_message*)@<EBX>)
|
||||
int NetGuaranteedSendMessageToEverybody(tNet_game_details* pDetails, tNet_message* pMessage, int (*pNotifyFail)(tU32, tNet_message*)) {
|
||||
LOG_TRACE("(%p, %p, %p)", pDetails, pMessage, pNotifyFail);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
pMessage->sender = gLocal_net_ID;
|
||||
pMessage->senders_time_stamp = PDGetTotalTime();
|
||||
pMessage->num_contents = 1;
|
||||
pMessage->guarantee_number = 0;
|
||||
ReceivedMessage(pMessage, &gNet_players[gThis_net_player_index], GetRaceTime());
|
||||
return NetGuaranteedSendMessageToAllPlayers(pDetails, pMessage, pNotifyFail);
|
||||
}
|
||||
|
||||
// IDA: int __usercall NetGuaranteedSendMessageToHost@<EAX>(tNet_game_details *pDetails@<EAX>, tNet_message *pMessage@<EDX>, int (*pNotifyFail)(tU32, tNet_message*)@<EBX>)
|
||||
|
@ -1893,7 +2124,8 @@ void ResendGuaranteedMessages(void) {
|
|||
// IDA: int __usercall SampleFailNotifier@<EAX>(tU32 pAge@<EAX>, tNet_message *pMessage@<EDX>)
|
||||
int SampleFailNotifier(tU32 pAge, tNet_message* pMessage) {
|
||||
LOG_TRACE("(%d, %p)", pAge, pMessage);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
return pAge > 9999;
|
||||
}
|
||||
|
||||
// IDA: void __cdecl NetWaitForGuaranteeReplies()
|
||||
|
@ -1914,7 +2146,13 @@ void NetWaitForGuaranteeReplies(void) {
|
|||
tNet_game_player_info* NetPlayerFromID(tPlayer_ID pPlayer) {
|
||||
int i;
|
||||
LOG_TRACE("(%d)", pPlayer);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
for (i = 0; i < gNumber_of_net_players; i++) {
|
||||
if (gNet_players[i].ID == pPlayer) {
|
||||
return &gNet_players[i];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// IDA: tCar_spec* __usercall NetCarFromPlayerID@<EAX>(tPlayer_ID pPlayer@<EAX>)
|
||||
|
@ -1922,14 +2160,25 @@ tCar_spec* NetCarFromPlayerID(tPlayer_ID pPlayer) {
|
|||
int i;
|
||||
tNet_game_player_info* player;
|
||||
LOG_TRACE("(%d)", pPlayer);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
player = NetPlayerFromID(pPlayer);
|
||||
if (player) {
|
||||
return player->car;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// IDA: tNet_game_player_info* __usercall NetPlayerFromCar@<EAX>(tCar_spec *pCar@<EAX>)
|
||||
tNet_game_player_info* NetPlayerFromCar(tCar_spec* pCar) {
|
||||
int i;
|
||||
LOG_TRACE("(%p)", pCar);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
for (i = 0; i < gNumber_of_net_players; i++) {
|
||||
if (gNet_players[i].car == pCar) {
|
||||
return &gNet_players[i];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// IDA: tU32 __usercall DoCheckSum@<EAX>(tNet_message *pMessage@<EAX>)
|
||||
|
|
|
@ -1574,7 +1574,9 @@ void ReadNetGameChoices(tNet_game_type* pGame_type, tNet_game_options* pGame_opt
|
|||
// IDA: int __usercall ChooseStartRace@<EAX>(int *pRank@<EAX>)
|
||||
int ChooseStartRace(int* pRank) {
|
||||
LOG_TRACE("(%p)", pRank);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
*pRank = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// IDA: void __usercall SetUpOtherNetThings(tNet_game_details *pNet_game@<EAX>)
|
||||
|
@ -1699,7 +1701,7 @@ int ChooseNetCar(tNet_game_details* pNet_game, tNet_game_options* pOptions, int*
|
|||
*pCar_index = PickARandomCar();
|
||||
car_index = 0;
|
||||
for (i = 0; i < gNumber_of_racers; i++) {
|
||||
if (gCar_details[i].ownership != eCar_owner_not_allowed) {
|
||||
if (gCar_details[i].ownership < eCar_owner_not_allowed) {
|
||||
gProgram_state.cars_available[car_index] = i;
|
||||
car_index++;
|
||||
}
|
||||
|
@ -1760,7 +1762,7 @@ int DoMultiPlayerStart(void) {
|
|||
}
|
||||
|
||||
if (gAusterity_mode) {
|
||||
NetFullScreenMessage(192, 0);
|
||||
NetFullScreenMessage(kMiscString_NOT_ENOUGH_MEMORY, 0);
|
||||
return 0;
|
||||
}
|
||||
if (NetInitialise()) {
|
||||
|
@ -1814,6 +1816,13 @@ int DoMultiPlayerStart(void) {
|
|||
return 1;
|
||||
}
|
||||
case eJoin_or_host_host:
|
||||
#if defined(DETHRACE_FIX_BUGS)
|
||||
/* Don't allow hosting a game when the game is launched with --no-bind */
|
||||
if (harness_game_config.no_bind) {
|
||||
DoErrorInterface(76);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
gProgram_state.frank_or_anniness = eFrankie;
|
||||
if (!OriginalCarmaCDinDrive()) {
|
||||
DoErrorInterface(kMiscString_PLEASE_INSERT_THE_CARMAGEDDON_CD);
|
||||
|
|
|
@ -840,7 +840,7 @@ void CalibrateJoysticks(void) {
|
|||
#ifdef __DOS__
|
||||
NOT_IMPLEMENTED();
|
||||
#else
|
||||
NetFullScreenMessage(229, 0);
|
||||
NetFullScreenMessage(kMiscString_USE_SYSTEM_CONTROL_PANEL_FOR_JOYSTICKS, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -1926,7 +1926,7 @@ void CheckPedestrianDeathScenario(tPedestrian_data* pPedestrian) {
|
|||
if (billiards_shot) {
|
||||
credits_value *= 4;
|
||||
PratcamEvent(30);
|
||||
DoFancyHeadup(8);
|
||||
DoFancyHeadup(kFancyHeadupNiceShotSir);
|
||||
} else if (fabsf(the_car->omega.v[X]) <= 5.0f
|
||||
&& fabsf(the_car->omega.v[Z]) <= 5.0f
|
||||
&& BrVector3Dot(&the_car->car_master_actor->t.t.look_up.up, &up) >= 0.1f
|
||||
|
|
|
@ -142,7 +142,7 @@ int gFizzle_height;
|
|||
int gNumber_of_icons;
|
||||
tPowerup* gPowerup_array;
|
||||
|
||||
#define GET_POWERUP_INDEX(POWERUP) (((POWERUP)-gPowerup_array) / sizeof(tPowerup))
|
||||
#define GET_POWERUP_INDEX(POWERUP) ((POWERUP)-gPowerup_array)
|
||||
|
||||
// IDA: void __usercall LosePowerupX(tPowerup *pThe_powerup@<EAX>, int pTell_net_players@<EDX>)
|
||||
void LosePowerupX(tPowerup* pThe_powerup, int pTell_net_players) {
|
||||
|
|
|
@ -615,7 +615,7 @@ int ChangeCar(int pNet_mode, int* pCar_index, tNet_game_details* pNet_game) {
|
|||
}
|
||||
if (result == 0) {
|
||||
if (pNet_mode) {
|
||||
*pCar_index = gProgram_state.cars_available[gCurrent_race_index];
|
||||
*pCar_index = gProgram_state.cars_available[gCurrent_car_index];
|
||||
} else {
|
||||
AboutToLoadFirstCar();
|
||||
SwitchToRealResolution();
|
||||
|
|
|
@ -1157,25 +1157,39 @@ tSO_result DoEndRaceSummary2(void) {
|
|||
// Suffix added to avoid duplicate symbol
|
||||
void DrawAnItem__racesumm(int pX, int pY_index, int pFont_index, char* pText) {
|
||||
LOG_TRACE("(%d, %d, %d, \"%s\")", pX, pY_index, pFont_index, pText);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
TransBrPixelmapText(gBack_screen,
|
||||
pX,
|
||||
gCurrent_graf_data->net_sum_headings_y + gCurrent_graf_data->net_sum_y_pitch * pY_index,
|
||||
pFont_index,
|
||||
gFont_7,
|
||||
pText);
|
||||
}
|
||||
|
||||
// IDA: void __usercall DrawColumnHeading(int pStr_index@<EAX>, int pX@<EDX>)
|
||||
// Suffix added to avoid duplicate symbol
|
||||
void DrawColumnHeading__racesumm(int pStr_index, int pX) {
|
||||
LOG_TRACE("(%d, %d)", pStr_index, pX);
|
||||
|
||||
TransBrPixelmapText(gBack_screen,
|
||||
pX,
|
||||
gCurrent_graf_data->net_sum_headings_y - gCurrent_graf_data->net_sum_y_pitch,
|
||||
250,
|
||||
gFont_7,
|
||||
GetMiscString(pStr_index));
|
||||
}
|
||||
|
||||
// IDA: int __usercall SortScores@<EAX>(void *pFirst_one@<EAX>, void *pSecond_one@<EDX>)
|
||||
int SortScores(void* pFirst_one, void* pSecond_one) {
|
||||
int SortScores(const void* pFirst_one, const void* pSecond_one) {
|
||||
LOG_TRACE("(%p, %p)", pFirst_one, pSecond_one);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
return gNet_players[*(int*)pSecond_one].games_score - gNet_players[*(int*)pFirst_one].games_score;
|
||||
}
|
||||
|
||||
// IDA: void __cdecl SortGameScores()
|
||||
void SortGameScores(void) {
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
qsort(gPlayer_lookup, gNumber_of_net_players, sizeof(gPlayer_lookup[0]), SortScores);
|
||||
}
|
||||
|
||||
// IDA: void __usercall NetSumDraw(int pCurrent_choice@<EAX>, int pCurrent_mode@<EDX>)
|
||||
|
@ -1184,21 +1198,125 @@ void NetSumDraw(int pCurrent_choice, int pCurrent_mode) {
|
|||
char s[256];
|
||||
tNet_game_player_info* player;
|
||||
LOG_TRACE("(%d, %d)", pCurrent_choice, pCurrent_mode);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
DrawColumnHeading__racesumm(kMiscString_PLAYED, gCurrent_graf_data->net_sum_x_3);
|
||||
DrawColumnHeading__racesumm(kMiscString_WON, gCurrent_graf_data->net_sum_x_4);
|
||||
DrawColumnHeading__racesumm(kMiscString_SCORE, gCurrent_graf_data->net_sum_x_5);
|
||||
BrPixelmapLine(gBack_screen,
|
||||
gCurrent_graf_data->net_sum_x_1,
|
||||
gCurrent_graf_data->net_sum_headings_y + 1 + gFont_7->glyph_y - gCurrent_graf_data->net_sum_y_pitch,
|
||||
gBack_screen->width - gCurrent_graf_data->net_sum_x_1,
|
||||
gCurrent_graf_data->net_sum_headings_y + 1 + gFont_7->glyph_y - gCurrent_graf_data->net_sum_y_pitch,
|
||||
252);
|
||||
|
||||
for (i = 0; i < gNumber_of_net_players; i++) {
|
||||
player = &gNet_players[gPlayer_lookup[i]];
|
||||
|
||||
strcpy(s, player->player_name);
|
||||
if (player->host) {
|
||||
strcat(s, " -");
|
||||
strcat(s, GetMiscString(kMiscString_HOST));
|
||||
strcat(s, "-");
|
||||
}
|
||||
TurnOffPaletteConversion();
|
||||
DRPixelmapRectangleMaskedCopy(gBack_screen,
|
||||
gCurrent_graf_data->net_sum_x_1,
|
||||
gCurrent_graf_data->net_sum_headings_y + 1 + i * gCurrent_graf_data->net_sum_y_pitch,
|
||||
gIcons_pix_low_res, /* DOS version uses low res, Windows version uses normal res */
|
||||
0,
|
||||
gCurrent_graf_data->net_head_icon_height * player->car_index,
|
||||
gIcons_pix_low_res->width, /* DOS version uses low res, Windows version uses normal res */
|
||||
gCurrent_graf_data->net_head_icon_height);
|
||||
TurnOnPaletteConversion();
|
||||
DrawAnItem__racesumm(gCurrent_graf_data->net_sum_x_2, i, 83, s);
|
||||
sprintf(s, "%d", player->played);
|
||||
DrawAnItem__racesumm(gCurrent_graf_data->net_sum_x_3, i, 83, s);
|
||||
sprintf(s, "%d", player->won);
|
||||
DrawAnItem__racesumm(gCurrent_graf_data->net_sum_x_4, i, 83, s);
|
||||
sprintf(s, "%d", player->games_score);
|
||||
DrawAnItem__racesumm(gCurrent_graf_data->net_sum_x_5, i, 83, s);
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __cdecl DoNetRaceSummary()
|
||||
void DoNetRaceSummary(void) {
|
||||
static tFlicette flicker_on[1];
|
||||
static tFlicette flicker_off[1];
|
||||
static tFlicette push[1];
|
||||
static tMouse_area mouse_areas[1];
|
||||
static tInterface_spec interface_spec;
|
||||
static tFlicette flicker_on[1] = { { 321, { 219, 112 }, { 172, 362 } } };
|
||||
static tFlicette flicker_off[1] = { { 322, { 219, 112 }, { 172, 362 } } };
|
||||
static tFlicette push[1] = { { 323, { 219, 112 }, { 172, 362 } } };
|
||||
static tMouse_area mouse_areas[1] = { { { 219, 112 }, { 172, 362 }, { 282, 182 }, { 192, 379 }, 0, 0, 0, NULL } };
|
||||
static tInterface_spec interface_spec = {
|
||||
0, // initial_imode
|
||||
63, // first_opening_flic
|
||||
0, // second_opening_flic
|
||||
-1, // end_flic_go_ahead
|
||||
-1, // end_flic_escaped
|
||||
-1, // end_flic_otherwise
|
||||
8, // flic_bunch_to_load
|
||||
{ -1, 0 }, // move_left_new_mode
|
||||
{ 0, 0 }, // move_left_delta
|
||||
{ 0, 0 }, // move_left_min
|
||||
{ 0, 0 }, // move_left_max
|
||||
{ NULL, NULL }, // move_left_proc
|
||||
{ -1, 0 }, // move_right_new_mode
|
||||
{ 0, 0 }, // move_right_delta
|
||||
{ 0, 0 }, // move_right_min
|
||||
{ 0, 0 }, // move_right_max
|
||||
{ NULL, NULL }, // move_right_proc
|
||||
{ -1, 0 }, // move_up_new_mode
|
||||
{ 0, 0 }, // move_up_delta
|
||||
{ 0, 0 }, // move_up_min
|
||||
{ 0, 0 }, // move_up_max
|
||||
{ NULL, NULL }, // move_up_proc
|
||||
{ -1, 0 }, // move_down_new_mode
|
||||
{ 0, 0 }, // move_down_delta
|
||||
{ 0, 0 }, // move_down_min
|
||||
{ 0, 0 }, // move_down_max
|
||||
{ NULL, NULL }, // move_down_proc
|
||||
{ 1, 1 }, // go_ahead_allowed
|
||||
{ NULL, NULL }, // go_ahead_proc
|
||||
{ 1, 1 }, // escape_allowed
|
||||
{ NULL, NULL }, // escape_proc
|
||||
NULL, // exit_proc
|
||||
&NetSumDraw, // draw_proc
|
||||
10000, // time_out
|
||||
NULL, // start_proc1
|
||||
NULL, // start_proc2
|
||||
NULL, // done_proc
|
||||
0, // font_needed
|
||||
{ 0, 0 }, // typeable
|
||||
NULL, // get_original_string
|
||||
0, // escape_code
|
||||
1, // dont_save_or_load
|
||||
1, // number_of_button_flics
|
||||
flicker_on, // flicker_on_flics
|
||||
flicker_off, // flicker_off_flics
|
||||
push, // pushed_flics
|
||||
1, // number_of_mouse_areas
|
||||
mouse_areas, // mouse_areas
|
||||
0, // number_of_recopy_areas
|
||||
NULL // recopy_areas
|
||||
};
|
||||
int i;
|
||||
int result;
|
||||
tS32 start_time;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
NetPlayerStatusChanged(ePlayer_status_summary);
|
||||
start_time = PDGetTotalTime();
|
||||
while (!gReceived_game_scores && PDGetTotalTime() - start_time < 20000) {
|
||||
NetService(0);
|
||||
}
|
||||
if (gReceived_game_scores) {
|
||||
for (i = 0; i < gNumber_of_net_players; i++) {
|
||||
gPlayer_lookup[i] = i;
|
||||
}
|
||||
SortGameScores();
|
||||
TurnOnPaletteConversion();
|
||||
DoInterfaceScreen(&interface_spec, 0, 0);
|
||||
NetPlayerStatusChanged(ePlayer_status_loading);
|
||||
TurnOffPaletteConversion();
|
||||
FadePaletteDown();
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: tSO_result __usercall DoEndRaceSummary@<EAX>(int *pFirst_summary_done@<EAX>, tRace_result pRace_result@<EDX>)
|
||||
|
|
|
@ -105,7 +105,7 @@ void DrawAnItem__racesumm(int pX, int pY_index, int pFont_index, char* pText);
|
|||
// Suffix added to avoid duplicate symbol
|
||||
void DrawColumnHeading__racesumm(int pStr_index, int pX);
|
||||
|
||||
int SortScores(void* pFirst_one, void* pSecond_one);
|
||||
int SortScores(const void* pFirst_one, const void* pSecond_one);
|
||||
|
||||
void SortGameScores(void);
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ void InitSound(void) {
|
|||
gSound_enabled = S3Init(the_path, gAusterity_mode) == 0;
|
||||
gSound_available = gSound_enabled;
|
||||
}
|
||||
S3Set3DSoundEnvironment(0.14492753, -1.0, -1.0);
|
||||
S3Set3DSoundEnvironment(1.0f / WORLD_SCALE, -1.0, -1.0);
|
||||
gVirgin_pass = 0;
|
||||
gCD_is_disabled = 0;
|
||||
UsePathFileToDetermineIfFullInstallation();
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#include "spark.h"
|
||||
#include "brender.h"
|
||||
#include "car.h"
|
||||
#include "crush.h"
|
||||
#include "depth.h"
|
||||
#include "displays.h"
|
||||
#include "errors.h"
|
||||
#include "formats.h"
|
||||
#include "globvars.h"
|
||||
|
@ -1207,7 +1209,12 @@ void GenerateContinuousSmoke(tCar_spec* pCar, int wheel, tU32 pTime) {
|
|||
// IDA: void __cdecl DustRotate()
|
||||
void DustRotate(void) {
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
gDust_rotate += 1;
|
||||
if (gDust_rotate >= gNum_dust_tables) {
|
||||
gDust_rotate = 0;
|
||||
}
|
||||
NewTextHeadupSlot(4, 0, 1000, -4, "Dust colour rotated");
|
||||
}
|
||||
|
||||
// IDA: void __usercall RenderSmoke(br_pixelmap *pRender_screen@<EAX>, br_pixelmap *pDepth_buffer@<EDX>, br_actor *pCamera@<EBX>, br_matrix34 *pCamera_to_world@<ECX>, tU32 pTime)
|
||||
|
@ -2149,7 +2156,13 @@ void SmudgeCar(tCar_spec* pCar, int fire_point) {
|
|||
void ResetSmokeColumns(void) {
|
||||
int i;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
for (i = 0; i < MAX_SMOKE_COLUMNS; i++) {
|
||||
if (gColumn_flags & (1 << i)) {
|
||||
BrActorRemove(gSmoke_column[i].flame_actor);
|
||||
}
|
||||
}
|
||||
gColumn_flags = 0;
|
||||
}
|
||||
|
||||
// IDA: void __usercall SetSmokeOn(int pSmoke_on@<EAX>)
|
||||
|
@ -2162,7 +2175,9 @@ void SetSmokeOn(int pSmoke_on) {
|
|||
// IDA: void __usercall ReallySetSmokeOn(int pSmoke_on@<EAX>)
|
||||
void ReallySetSmokeOn(int pSmoke_on) {
|
||||
LOG_TRACE("(%d)", pSmoke_on);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
ResetSmoke();
|
||||
ResetSmokeColumns();
|
||||
}
|
||||
|
||||
// IDA: void __usercall SetSmoke(int pSmoke_on@<EAX>)
|
||||
|
@ -2649,7 +2664,42 @@ void DoModelThing(br_actor* actor, br_model* pModel, br_material* material, void
|
|||
tU32 t;
|
||||
int val;
|
||||
LOG_TRACE("(%p, %p, %p, %p, %d, %d)", actor, pModel, material, render_data, style, on_screen);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
GetRaceTime();
|
||||
for (group = 0; group < V11MODEL(pModel)->ngroups; group++) {
|
||||
for (j = 0; j < V11MODEL(pModel)->groups[group].nvertices; j++) {
|
||||
if (!(((V11MODEL(pModel)->groups[group].vertex_colours[j]) >> 24) & 1)) {
|
||||
if (((V11MODEL(pModel)->groups[group].vertex_colours[j]) >> 24) < 0xc9) {
|
||||
val = ((V11MODEL(pModel)->groups[group].vertex_colours[j]) >> 24) + 2 * IRandomBetween(5, 10);
|
||||
V11MODEL(pModel)->groups[group].vertex_colours[j] = BR_COLOUR_RGBA(0, 0, 0, val);
|
||||
if (pModel->flags & BR_MODF_UPDATEABLE) {
|
||||
pModel->vertices[V11MODEL(pModel)->groups[group].vertex_user[j]].index = val;
|
||||
}
|
||||
} else {
|
||||
V11MODEL(pModel)->groups[group].vertex_colours[j] = BR_COLOUR_RGBA(0, 0, 0, 0xc9);
|
||||
if (pModel->flags & BR_MODF_UPDATEABLE) {
|
||||
pModel->vertices[V11MODEL(pModel)->groups[group].vertex_user[j]].index = 0xc9;
|
||||
}
|
||||
}
|
||||
} else if ((V11MODEL(pModel)->groups[group].vertex_colours[j] >> 24) < 20) {
|
||||
V11MODEL(pModel)->groups[group].vertex_colours[j] = 0;
|
||||
if (pModel->flags & BR_MODF_UPDATEABLE) {
|
||||
pModel->vertices[V11MODEL(pModel)->groups[group].vertex_user[j]].index = 0;
|
||||
}
|
||||
} else {
|
||||
val = ((V11MODEL(pModel)->groups[group].vertex_colours[j] >> 24) - 2 * IRandomBetween(5, 10)) << 24;
|
||||
V11MODEL(pModel)->groups[group].vertex_colours[j] = BR_COLOUR_RGBA(0, 0, 0, val);
|
||||
if (pModel->flags & BR_MODF_UPDATEABLE) {
|
||||
pModel->vertices[V11MODEL(pModel)->groups[group].vertex_user[j]].index = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((pModel->flags & BR_MODF_UPDATEABLE) && pModel->user != NULL) {
|
||||
BrModelUpdate(pModel, BR_MODU_VERTEX_POSITIONS);
|
||||
}
|
||||
pModel->user = NULL;
|
||||
BrZbModelRender(actor, pModel, material, style, BrOnScreenCheck(&pModel->bounds), 0);
|
||||
}
|
||||
|
||||
// IDA: void __usercall SetModelShade(br_actor *pActor@<EAX>, br_pixelmap *pShade@<EDX>)
|
||||
|
@ -2682,9 +2732,6 @@ void MakeCarIt(tCar_spec* pCar) {
|
|||
int i;
|
||||
LOG_TRACE("(%p)", pCar);
|
||||
|
||||
STUB();
|
||||
return;
|
||||
|
||||
shade[0] = gIt_shade_table;
|
||||
shade[1] = gFog_shade_table;
|
||||
shade[2] = gShade_list[0];
|
||||
|
@ -2694,14 +2741,14 @@ void MakeCarIt(tCar_spec* pCar) {
|
|||
|
||||
actor = pCar->car_model_actors[pCar->principal_car_actor].actor;
|
||||
bonny = pCar->car_model_actors[pCar->car_actor_count - 1].actor;
|
||||
if (((actor->model->flags & BR_MODF_CUSTOM) == 0) || actor->model->custom != DoTrueColModelThing) {
|
||||
if (!(actor->model->flags & BR_MODF_CUSTOM) || actor->model->custom != DoModelThing) {
|
||||
SetModelShade(actor, shade[shade_num]);
|
||||
actor->model->user = DoTrueColModelThing;
|
||||
actor->model->custom = DoTrueColModelThing;
|
||||
actor->model->user = DoModelThing;
|
||||
actor->model->custom = DoModelThing;
|
||||
actor->model->flags |= BR_MODF_CUSTOM;
|
||||
if (bonny != actor) {
|
||||
bonny->model->user = DoTrueColModelThing;
|
||||
bonny->model->custom = DoTrueColModelThing;
|
||||
bonny->model->user = DoModelThing;
|
||||
bonny->model->custom = DoModelThing;
|
||||
bonny->model->flags |= BR_MODF_CUSTOM;
|
||||
SetModelShade(bonny, shade[shade_num]);
|
||||
}
|
||||
|
@ -2715,5 +2762,33 @@ void StopCarBeingIt(tCar_spec* pCar) {
|
|||
br_actor* actor;
|
||||
br_actor* bonny;
|
||||
LOG_TRACE("(%p)", pCar);
|
||||
STUB();
|
||||
|
||||
actor = pCar->car_model_actors[pCar->principal_car_actor].actor;
|
||||
bonny = pCar->car_model_actors[pCar->car_actor_count - 1].actor;
|
||||
if (actor->model->custom == DoModelThing) {
|
||||
actor->model->flags &= ~BR_MODF_CUSTOM;
|
||||
SetModelShade(actor, gShade_list[0]);
|
||||
for (group = 0; group < V11MODEL(actor->model)->ngroups; group++) {
|
||||
for (i = 0; i < V11MODEL(actor->model)->groups[group].nvertices; i++) {
|
||||
V11MODEL(actor->model)->groups[group].vertex_colours[i] = 0;
|
||||
if (actor->model->flags & BR_MODF_UPDATEABLE) {
|
||||
actor->model->vertices[V11MODEL(actor->model)->groups[group].vertex_user[i]].index = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
SetModelForUpdate(actor->model, pCar, 0);
|
||||
if (bonny != actor) {
|
||||
bonny->model->flags &= ~BR_MODF_CUSTOM;
|
||||
SetModelShade(bonny, gShade_list[0]);
|
||||
for (group = 0; group < V11MODEL(bonny->model)->ngroups; group++) {
|
||||
for (i = 0; i < V11MODEL(bonny->model)->groups[group].nvertices; i++) {
|
||||
V11MODEL(bonny->model)->groups[group].vertex_colours[i] = 0;
|
||||
if (bonny->model->flags & BR_MODF_UPDATEABLE) {
|
||||
bonny->model->vertices[V11MODEL(bonny->model)->groups[group].vertex_user[i]].index = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
SetModelForUpdate(bonny->model, pCar, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "racesumm.h"
|
||||
#include "sound.h"
|
||||
#include "utility.h"
|
||||
#include "world.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
int gLast_wrong_checkpoint;
|
||||
|
@ -95,7 +96,7 @@ void RaceCompleted(tRace_over_reason pReason) {
|
|||
case eRace_over_abandoned:
|
||||
if (gNet_mode == eNet_mode_client) {
|
||||
gHost_abandon_game = 1;
|
||||
NetFullScreenMessage(87, 0);
|
||||
NetFullScreenMessage(kMiscString_HOST_ABANDONED_RACE, 0);
|
||||
}
|
||||
break;
|
||||
case eRace_over_out_of_time:
|
||||
|
@ -451,7 +452,17 @@ void SwapNetCarsLoad(void) {
|
|||
void SwapNetCarsDispose(void) {
|
||||
int i;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
DisableNetService();
|
||||
for (i = 0; i < gNumber_of_net_players; i++) {
|
||||
DisposeCar(gNet_players[i].car, gNet_players[i].car_index);
|
||||
if (gNet_players[i].car_index >= 0) {
|
||||
gCar_details[gNet_players[i].car_index].ownership = eCar_owner_none;
|
||||
}
|
||||
}
|
||||
ClearOutStorageSpace(&gOur_car_storage_space);
|
||||
ClearOutStorageSpace(&gNet_cars_storage_space);
|
||||
ReenableNetService();
|
||||
}
|
||||
|
||||
// IDA: void __cdecl DoGame()
|
||||
|
|
|
@ -1143,7 +1143,20 @@ void SubsStringJob(char* pStr, ...) {
|
|||
char* sub_pt;
|
||||
va_list ap;
|
||||
LOG_TRACE("(\"%s\")", pStr);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
va_start(ap, pStr);
|
||||
for (;;) {
|
||||
sub_pt = strchr(pStr, '%');
|
||||
if (sub_pt == NULL) {
|
||||
va_end(ap);
|
||||
return;
|
||||
}
|
||||
sub_str = va_arg(ap, char *);
|
||||
StripCR(sub_str);
|
||||
strcpy(temp_str, &sub_pt[1]);
|
||||
strcpy(sub_pt, sub_str);
|
||||
strcat(pStr, temp_str);
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall DecodeLine2(char *pS@<EAX>)
|
||||
|
|
|
@ -324,11 +324,11 @@ enum {
|
|||
kFancyHeadupCheckpoint = 12,
|
||||
kFancyHeadupOutOfTime = 13,
|
||||
kFancyHeadupRaceCompleted = 14,
|
||||
|
||||
// FIXME: missing network fancy head-ups
|
||||
|
||||
kFancyHeadupYouAreWasted = 15,
|
||||
kFancyHeadupYouAreBothWasted = 16,
|
||||
kFancyHeadupNetworkRaceOverNetworkLoss = 17,
|
||||
kFancyHeadupNetworkRaceNoMoreMoney = 18,
|
||||
kFancyHeadupYouLost = 19,
|
||||
kFancyHeadupNetworkVictory = 20,
|
||||
kFancyHeadupDemoTimeout = 21,
|
||||
};
|
||||
|
|
|
@ -473,7 +473,7 @@ typedef struct tReduced_matrix {
|
|||
br_vector3 translation;
|
||||
} tReduced_matrix;
|
||||
|
||||
typedef struct tCar_controls {
|
||||
typedef struct tCar_controls { // size: 0x4
|
||||
int joystick_acc : 8;
|
||||
int joystick_dec : 8;
|
||||
unsigned int left : 1; // 0x10000 bit 17
|
||||
|
@ -490,25 +490,25 @@ typedef struct tCar_controls {
|
|||
unsigned int horn : 1; // 0x8000000 bit 28
|
||||
} tCar_controls;
|
||||
|
||||
typedef struct tNet_message_mechanics_info {
|
||||
tU8 contents_size;
|
||||
tNet_message_type type;
|
||||
tU32 ID;
|
||||
tU32 time;
|
||||
tReduced_matrix mat;
|
||||
br_vector3 v;
|
||||
br_vector3 omega;
|
||||
tU8 d[4];
|
||||
tCar_controls keys;
|
||||
tU32 cc_coll_time;
|
||||
tS16 curvature;
|
||||
tU16 revs;
|
||||
br_scalar front;
|
||||
br_scalar back;
|
||||
tU32 repair_time;
|
||||
tU8 damage[12];
|
||||
tU16 powerups;
|
||||
br_scalar wheel_dam_offset[4];
|
||||
typedef struct tNet_message_mechanics_info { // size: 0x84
|
||||
tU8 contents_size; // @0x0
|
||||
tNet_message_type type; // @0x1
|
||||
tU32 ID; // @0x4
|
||||
tU32 time; // @0x8
|
||||
tReduced_matrix mat; // @0xc
|
||||
br_vector3 v; // @0x30
|
||||
br_vector3 omega; // @0x3c
|
||||
tU8 d[4]; // @0x48
|
||||
tCar_controls keys; // @0x4c
|
||||
tU32 cc_coll_time; // @0x50
|
||||
tS16 curvature; // @0x54
|
||||
tU16 revs; // @0x56
|
||||
br_scalar front; // @0x58
|
||||
br_scalar back; // @0x5c
|
||||
tU32 repair_time; // @0x60
|
||||
tU8 damage[12]; // @0x64
|
||||
tU16 powerups; // @0x70
|
||||
br_scalar wheel_dam_offset[4]; // @0x74
|
||||
} tNet_message_mechanics_info;
|
||||
|
||||
typedef struct tDamage_unit {
|
||||
|
@ -1033,6 +1033,7 @@ typedef struct tFace_ref {
|
|||
br_scalar d;
|
||||
} tFace_ref;
|
||||
|
||||
#pragma pack(push, 4)
|
||||
typedef struct tNet_game_player_info { // size: 0xc0
|
||||
tPD_net_player_info pd_net_info; // @0x0
|
||||
tU32 this_players_time_stamp; // @0x10
|
||||
|
@ -1062,6 +1063,7 @@ typedef struct tNet_game_player_info { // size: 0xc0
|
|||
br_matrix34 initial_position; // @0x8c
|
||||
tCar_spec* car; // @0xbc
|
||||
} tNet_game_player_info;
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef struct tNet_game_options { // size: 0x30
|
||||
int show_players_on_map; // @0x0
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
#ifndef MACROS_H
|
||||
#define MACROS_H
|
||||
|
||||
#define DR_JOIN2(A,B) A##B
|
||||
#define DR_JOIN(A,B) DR_JOIN2(A, B)
|
||||
#define DR_STATIC_ASSERT(V) typedef int DR_JOIN(dr_static_assert_, __COUNTER__)[(V)?1:-1]
|
||||
|
||||
#define VEHICLE_TYPE_FROM_ID(id) ((tVehicle_type)(id >> 8))
|
||||
#define VEHICLE_INDEX_FROM_ID(id) ((id)&0x00ff)
|
||||
|
||||
|
|
|
@ -56,6 +56,16 @@ int gSocket;
|
|||
#define MESSAGE_HEADER_STR "CW95MSG"
|
||||
#define JOINABLE_GAMES_CAPACITY 16
|
||||
|
||||
DR_STATIC_ASSERT(offsetof(tNet_message, pd_stuff_so_DO_NOT_USE) == 0);
|
||||
DR_STATIC_ASSERT(offsetof(tNet_message, magic_number) == 4);
|
||||
DR_STATIC_ASSERT(offsetof(tNet_message, guarantee_number) == 8);
|
||||
DR_STATIC_ASSERT(offsetof(tNet_message, sender) == 12);
|
||||
DR_STATIC_ASSERT(offsetof(tNet_message, version) == 16);
|
||||
DR_STATIC_ASSERT(offsetof(tNet_message, senders_time_stamp) == 20);
|
||||
DR_STATIC_ASSERT(offsetof(tNet_message, num_contents) == 24);
|
||||
DR_STATIC_ASSERT(offsetof(tNet_message, overall_size) == 26);
|
||||
DR_STATIC_ASSERT(offsetof(tNet_message, contents) == 28);
|
||||
|
||||
// IDA: void __cdecl ClearupPDNetworkStuff()
|
||||
void ClearupPDNetworkStuff(void) {
|
||||
LOG_TRACE("()");
|
||||
|
@ -640,9 +650,6 @@ int PDNetSendMessageToAddress(tNet_game_details* pDetails, tNet_message* pMessag
|
|||
LOG_TRACE("(%p, %p, %p)", pDetails, pMessage, pAddress);
|
||||
|
||||
NetNowIPXLocalTarget2String(str, (struct sockaddr_in*)pAddress);
|
||||
if (pDetails->pd_net_info.addr_in.sin_port == 0) {
|
||||
int i = 0;
|
||||
}
|
||||
|
||||
if (sendto(gSocket, (const char*)pMessage, pMessage->overall_size, 0, (const struct sockaddr*)pAddress, sizeof(struct sockaddr)) == -1) {
|
||||
dr_dprintf("PDNetSendMessageToAddress(): Error on sendto() - WSAGetLastError=%d", WSAGetLastError());
|
||||
|
|
|
@ -24,11 +24,11 @@ float dword_531D9C;
|
|||
float flt_531D7C;
|
||||
float flt_531D98;
|
||||
|
||||
void S3Set3DSoundEnvironment(float a1, float a2, float a3) {
|
||||
void S3Set3DSoundEnvironment(float pInverse_world_scale, float a2, float a3) {
|
||||
float tmp;
|
||||
|
||||
if (a1 == -1.0f) {
|
||||
a1 = 0.25f;
|
||||
if (pInverse_world_scale == -1.0f) {
|
||||
pInverse_world_scale = 0.25f;
|
||||
}
|
||||
if (a2 == -1.0f) {
|
||||
a2 = 1.2f;
|
||||
|
@ -36,7 +36,7 @@ void S3Set3DSoundEnvironment(float a1, float a2, float a3) {
|
|||
if (a3 == -1.0f) {
|
||||
a3 = 130000.0f;
|
||||
}
|
||||
dword_531D9C = a1;
|
||||
dword_531D9C = pInverse_world_scale;
|
||||
tmp = sqrtf(a3 / a2);
|
||||
flt_531D7C = tmp;
|
||||
flt_531D98 = tmp * dword_531D9C;
|
||||
|
|
|
@ -216,8 +216,8 @@ int Harness_ProcessCommandLine(int* argc, char* argv[]) {
|
|||
handled = 1;
|
||||
} else if (strstr(argv[i], "--physics-step-time=") != NULL) {
|
||||
char* s = strstr(argv[i], "=");
|
||||
harness_game_config.physics_step_time = atof(s + 1);
|
||||
LOG_INFO("Physics step time set to %f", harness_game_config.physics_step_time);
|
||||
harness_game_config.physics_step_time = atoi(s + 1);
|
||||
LOG_INFO("Physics step time set to %d", harness_game_config.physics_step_time);
|
||||
handled = 1;
|
||||
} else if (strstr(argv[i], "--fps=") != NULL) {
|
||||
char* s = strstr(argv[i], "=");
|
||||
|
|
|
@ -34,7 +34,7 @@ typedef struct tHarness_game_info {
|
|||
|
||||
typedef struct tHarness_game_config {
|
||||
int enable_cd_check;
|
||||
float physics_step_time;
|
||||
int physics_step_time;
|
||||
float fps;
|
||||
int freeze_timer;
|
||||
unsigned demo_timeout;
|
||||
|
|
|
@ -0,0 +1,937 @@
|
|||
-- Basic Dethrace Wireshark dissector
|
||||
--
|
||||
-- Installation instructions:
|
||||
-- 1. Open Wireshark GUI
|
||||
-- 2. Navigate to "Help -> About Wireshark" menu
|
||||
-- 3. Click on "Folder" tab and click in the list of paths on "Personal Lua Plugins".
|
||||
-- If the folder does not yet exist, a dialog will ask you to create it.
|
||||
-- 4. Paste this lua script in the "Personal Lua Plugins" directory, or create a symlink.
|
||||
-- 5. When modifying this script, reload all plug-ins with CTRL+SHIFT+L
|
||||
|
||||
dethrace_protocol = Proto("dethrace", "Dethrace Protocol")
|
||||
DETHRACE_PORT = 12286
|
||||
|
||||
broadcast_types = {
|
||||
[0x31] = "PING Request",
|
||||
[0x32] = "PONG Response",
|
||||
}
|
||||
|
||||
content_types = {
|
||||
[0x00] = "SendMeDetails",
|
||||
[0x01] = "Details",
|
||||
[0x02] = "Join",
|
||||
[0x03] = "NewPlayerList",
|
||||
[0x04] = "GuaranteeReply",
|
||||
[0x05] = "CarDetailsReq",
|
||||
[0x06] = "CarDetails",
|
||||
[0x07] = "Leave",
|
||||
[0x08] = "Hosticide",
|
||||
[0x09] = "RaceOver",
|
||||
[0x0a] = "StatusReport",
|
||||
[0x0b] = "StartRace",
|
||||
[0x0c] = "HeadUp",
|
||||
[0x0d] = "HostQuery",
|
||||
[0x0e] = "HostReply",
|
||||
[0x0f] = "Mechanics",
|
||||
[0x10] = "NonCar_Info",
|
||||
[0x11] = "TimeSync",
|
||||
[0x12] = "Confirm",
|
||||
[0x13] = "DisableCar",
|
||||
[0x14] = "EnableCar",
|
||||
[0x15] = "PowerUp",
|
||||
[0x16] = "Recover",
|
||||
[0x17] = "Scores",
|
||||
[0x18] = "Wasted",
|
||||
[0x19] = "Pedestrian",
|
||||
[0x1a] = "Gameplay",
|
||||
[0x1b] = "NonCarPosition",
|
||||
[0x1c] = "CopInfo",
|
||||
[0x1d] = "GameScores",
|
||||
[0x1e] = "OilSpill",
|
||||
[0x1f] = "CrushPoint",
|
||||
[0x20] = "None",
|
||||
}
|
||||
|
||||
-- FIXME: missing table: index -> car name
|
||||
|
||||
f_checksum = ProtoField.uint32("dethrace.checksum", "Checksum")
|
||||
f_broadcast_magic = ProtoField.string("dethrace.broadcast_magic", "Broadcast Magic", base.ASCII)
|
||||
f_broadcast_type = ProtoField.char("dethrace.broadcast_type", "Broadcast Type", base.NONE, broadcast_types)
|
||||
|
||||
f_terminator = ProtoField.char("dethrace.terminator", "Terminator")
|
||||
|
||||
f_message_magic = ProtoField.uint32("dethrace.magic", "Magic", base.HEX)
|
||||
f_message_guarantee = ProtoField.uint32("dethrace.guarantee", "Guarantee Number")
|
||||
f_message_sender = ProtoField.uint32("dethrace.sender", "Sender Player ID")
|
||||
f_message_version = ProtoField.int32("dethrace.version", "Version")
|
||||
f_message_timestamp = ProtoField.uint32("dethrace.time", "Sender Time Stamp")
|
||||
f_message_count = ProtoField.uint16("dethrace.count", "Count Contents")
|
||||
f_message_size = ProtoField.uint16("dethrace.size", "Overall Size")
|
||||
|
||||
f_contents_size = ProtoField.uint8("dethrace.content_size", "Content Size")
|
||||
f_contents_type = ProtoField.uint8("dethrace.content_type", "Content Type", base.DEC, content_types)
|
||||
|
||||
player_statuses = {
|
||||
[0] = "Unknown",
|
||||
[1] = "Ready",
|
||||
[2] = "Loading",
|
||||
[3] = "Wrecks Gallery",
|
||||
[4] = "Summary",
|
||||
[5] = "Not Responding",
|
||||
[6] = "Racing",
|
||||
[7] = "Main Menu",
|
||||
[8] = "Recovering",
|
||||
[9] = "Action Replay",
|
||||
}
|
||||
|
||||
f_player_status = ProtoField.uint32("dethrace.player_status", "Player Status", base.DEC, player_statuses)
|
||||
|
||||
function create_message_size_type(parent, message, name)
|
||||
local message_type = message(1, 1):uint()
|
||||
local tree = parent:add(dethrace_protocol, message(), string.format("%s (%d)", name, message_type))
|
||||
tree:add_le(f_contents_size, message(0, 1))
|
||||
tree:add_le(f_contents_type, message(1, 1))
|
||||
result = {}
|
||||
result["tree"] = tree
|
||||
result["size"] = message(0, 1):le_uint()
|
||||
result["type"] = message(1, 1):le_uint()
|
||||
return result
|
||||
end
|
||||
|
||||
f_pd_player_info = ProtoField.bytes("dethrace.pd_info", "PD Net Info")
|
||||
|
||||
function dissect_pd_player_info(tree, data)
|
||||
tree:add_le(f_pd_player_info, data(0, 16))
|
||||
return 16
|
||||
end
|
||||
|
||||
f_float = ProtoField.float("dethrace.float", "Floating value")
|
||||
|
||||
function dissect_br_matrix34(parent, data, name)
|
||||
local matrix_tree = parent:add(name, data(0, 48))
|
||||
local offset = 0
|
||||
for row_i = 0, 3 do
|
||||
local row_tree = matrix_tree:add(string.format("m[%d]", row_i), data(offset, 12))
|
||||
|
||||
for col_i = 0, 2 do
|
||||
local f = data(offset, 4):le_float()
|
||||
row_tree:add_le(f_float, data(offset, 4)):set_text(string.format("m[%d][%d] = %f", row_i, col_i, f))
|
||||
offset = offset + 4
|
||||
end
|
||||
end
|
||||
return offset
|
||||
end
|
||||
|
||||
function dissect_reduced_matrix(parent, data, name)
|
||||
local matrix_tree = parent:add(name, data(0, 36))
|
||||
local offset = 0
|
||||
for row_i = 0, 2 do
|
||||
local row_tree = matrix_tree:add(string.format("m[%d]", row_i), data(offset, 12))
|
||||
|
||||
for col_i = 0, 2 do
|
||||
local f = data(offset, 4):le_float()
|
||||
row_tree:add_le(f_float, data(offset, 4)):set_text(string.format("m[%d][%d] = %f", row_i, col_i, f))
|
||||
offset = offset + 4
|
||||
end
|
||||
end
|
||||
return offset
|
||||
end
|
||||
|
||||
function dissect_br_vector3(parent, data, name)
|
||||
local tree = parent:add(name, data(0, 12))
|
||||
local offset = 0
|
||||
|
||||
for i = 0, 2 do
|
||||
local f = data(offset, 4):le_float()
|
||||
tree:add_le(f_float, data(offset, 4)):set_text(string.format("v[%d] = %f", i, f))
|
||||
offset = offset + 4
|
||||
end
|
||||
return offset
|
||||
end
|
||||
|
||||
function dissect_message_sendmedetails(tree, message)
|
||||
-- tNet_message_send_me_details (0)
|
||||
local t = create_message_size_type(tree, message, "Send Me Details")["tree"]
|
||||
-- finished
|
||||
end
|
||||
|
||||
race_tracks = {
|
||||
[0] = "Sumo",
|
||||
[1] = "Coliseum",
|
||||
[2] = "Maim Street",
|
||||
[3] = "Coastal Carnage",
|
||||
[4] = "Fridge Racer",
|
||||
[5] = "Death Valley",
|
||||
[6] = "Off Quay",
|
||||
[7] = "Industrial Injury",
|
||||
[8] = "Avenue of Atrocities",
|
||||
[9] = "Terror on the Trails",
|
||||
[10] = "MagnaChem Mayhem",
|
||||
[11] = "Downtown Devastation",
|
||||
}
|
||||
|
||||
game_stages = {
|
||||
[0] = "Starting",
|
||||
[1] = "Ready",
|
||||
[2] = "Playing",
|
||||
}
|
||||
|
||||
game_types = {
|
||||
[0] = "Driven To Destruction",
|
||||
[1] = "Car Crusher",
|
||||
[2] = "Carnage",
|
||||
[3] = "Checkpoint Stampede",
|
||||
[4] = "Sudden Death",
|
||||
[5] = "Terminal Tag",
|
||||
[6] = "Fox 'n' Hounds",
|
||||
}
|
||||
|
||||
details_options_start_types = {
|
||||
[0] = "Random Start",
|
||||
[1] = "Grid Start",
|
||||
}
|
||||
|
||||
details_options_starting_money = {
|
||||
[0] = "$0",
|
||||
[1] = "$2,000",
|
||||
[2] = "$5,000",
|
||||
[3] = "$10,000",
|
||||
[4] = "$20,000",
|
||||
}
|
||||
|
||||
details_options_car_choices = {
|
||||
[0] = "Eagle",
|
||||
[1] = "Hawk",
|
||||
[2] = "Both",
|
||||
[3] = "All",
|
||||
}
|
||||
|
||||
f_details_host_name = ProtoField.stringz("dethrace.details.host_name", "Host Name")
|
||||
f_details_host_id = ProtoField.uint32("dethrace.details.host_id", "Host ID")
|
||||
f_details_num_players = ProtoField.uint32("dethrace.details.num_players", "Number Players")
|
||||
f_details_start_race = ProtoField.uint32("dethrace.details.start_race", "Start Race", base.DEC, race_tracks)
|
||||
f_details_no_races_yet = ProtoField.bool("dethrace.details.no_races_yet", "No Races Yet")
|
||||
f_details_status = ProtoField.uint32("dethrace.details.game_status", "Status", base.DEC, game_stages)
|
||||
f_details_type = ProtoField.uint32("dethrace.details.type", "Type", base.DEC, game_types)
|
||||
|
||||
f_details_option_show_players_on_map = ProtoField.bool("dethrace.details.options.players_on_map", "Show Players On Map")
|
||||
f_details_option_show_peds_on_map = ProtoField.bool("dethrace.details.options.peds_on_map", "Show Peds On Map")
|
||||
f_details_option_enable_text_messages = ProtoField.bool("dethrace.details.options.text_messages", "Enable Text Messages")
|
||||
f_details_option_show_powerups_on_map = ProtoField.bool("dethrace.details.options.powerups_on_map", "Show Powerups On Map")
|
||||
f_details_option_powerup_respawn = ProtoField.bool("dethrace.details.options.powerup_respawn", "Powerup Respawn")
|
||||
f_details_option_open_game = ProtoField.bool("dethrace.details.options.open_game", "Open Game")
|
||||
f_details_option_starting_money_index = ProtoField.uint32("dethrace.details.options.starting_money", "Starting Money", base.DEC, details_options_starting_money)
|
||||
f_details_option_start_type = ProtoField.uint32("dethrace.details.options.start_Type", "Start Type", base.DEC, details_options_start_types)
|
||||
f_details_option_race_end_target = ProtoField.uint32("dethrace.details.options.end_target", "Race End Target")
|
||||
f_details_option_random_car_choice = ProtoField.bool("dethrace.details.options.random_car", "Random Cars")
|
||||
f_details_option_race_sequence_type = ProtoField.uint32("dethrace.details.options.race_sequence_type", "Race Sequence Type")
|
||||
f_details_option_car_choice = ProtoField.uint32("dethrace.details.options.car_choice", "Car Choice", base.DEC, details_options_car_choices)
|
||||
|
||||
function dissect_game_details(parent, data)
|
||||
-- tNet_game_options
|
||||
local tree = parent:add("Options", data(48))
|
||||
tree:add_le(f_details_option_show_players_on_map, data(0, 4))
|
||||
tree:add_le(f_details_option_show_peds_on_map, data(4, 4))
|
||||
tree:add_le(f_details_option_enable_text_messages, data(8, 4))
|
||||
tree:add_le(f_details_option_show_powerups_on_map, data(12, 4))
|
||||
tree:add_le(f_details_option_powerup_respawn, data(16, 4))
|
||||
tree:add_le(f_details_option_open_game, data(20, 4))
|
||||
tree:add_le(f_details_option_starting_money_index, data(24, 4))
|
||||
tree:add_le(f_details_option_start_type, data(28, 4))
|
||||
tree:add_le(f_details_option_race_end_target, data(32, 4))
|
||||
tree:add_le(f_details_option_random_car_choice, data(36, 4))
|
||||
tree:add_le(f_details_option_race_sequence_type, data(40, 4))
|
||||
tree:add_le(f_details_option_car_choice, data(44, 4))
|
||||
return 48
|
||||
end
|
||||
|
||||
function dissect_message_details(tree, message)
|
||||
-- tNet_message_my_details (1)
|
||||
local t = create_message_size_type(tree, message, "Details")["tree"]
|
||||
local offset = 2
|
||||
|
||||
offset = offset + dissect_pd_player_info(t, message(offset))
|
||||
|
||||
t:add(f_details_host_name, message(offset, 32))
|
||||
offset = offset + 4
|
||||
|
||||
t:add_le(f_details_host_id, message(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
t:add_le(f_details_num_players, message(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
t:add_le(f_details_start_race, message(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
t:add_le(f_details_no_races_yet, message(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
t:add_le(f_details_status, message(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
offset = offset + dissect_game_details(t, message(offset))
|
||||
|
||||
t:add_le(f_details_type, message(offset, 4))
|
||||
offset = offset + 4
|
||||
end
|
||||
|
||||
f_join_timestamp = ProtoField.uint32("dethrace.join.timestamp", "Timestamp")
|
||||
f_join_last_heard = ProtoField.uint32("dethrace.join.time_last_heard", "Last heard timestamp")
|
||||
f_join_reposition_time = ProtoField.uint32("dethrace.join.time_reposition", "Reposition timestamp")
|
||||
f_join_last_waste_time = ProtoField.uint32("dethrace.join.time_waste", "Last waste message timestamp")
|
||||
f_join_host = ProtoField.bool("dethrace.join.host", "Host")
|
||||
f_join_playerid = ProtoField.uint32("dethrace.join.playerid", "Player ID")
|
||||
f_join_player_name = ProtoField.stringz("dethrace.join.player_name", "Player Name")
|
||||
f_join_car = ProtoField.uint32("dethrace.join.car", "Car") -- FIXME: use table index -> car name
|
||||
f_join_grid = ProtoField.uint32("dethrace.join.grid", "Grid Index")
|
||||
f_join_grid_set = ProtoField.bool("dethrace.join.grid_set", "Grid Position Set")
|
||||
f_join_opponent_index = ProtoField.uint32("dethrace.join.opponent_index", "Opponent List Index")
|
||||
f_join_wait_confirm = ProtoField.uint32("dethrace.join.wait_confirm", "Awaiting Confirmation") -- FIXME: find out values
|
||||
f_join_score = ProtoField.uint32("dethrace.join.score", "Score")
|
||||
f_join_credits = ProtoField.uint32("dethrace.join.credits", "Credits")
|
||||
f_join_wasted = ProtoField.bool("dethrace.join.wasted", "Wasted")
|
||||
f_join_wasteage_attributed = ProtoField.bool("dethrace.join.wasteage_attributed", "Wasteage Attributed") -- FIXME: find out what this is
|
||||
f_join_name_not_clipped = ProtoField.bool("dethrace.join.name_not_clipped", "Name Not Clipped") -- FIXME: find out what this is
|
||||
f_join_race_stuff_initialized = ProtoField.bool("dethrace.join.race_stuff_initialized", "Race Stuff Initialized")
|
||||
f_join_played = ProtoField.bool("dethrace.join.played", "Played")
|
||||
f_join_won = ProtoField.bool("dethrace.join.won", "Won")
|
||||
f_join_next_car_index = ProtoField.uint32("dethrace.join.next_car_index", "Next Car Index") -- FIXME: find out what this is
|
||||
f_join_games_score = ProtoField.uint32("dethrace.join.games_score", "Games Score")
|
||||
f_join_last_score_index = ProtoField.uint32("dethrace.join.last_score_index", "Last Score Index")
|
||||
f_join_last_score_index = ProtoField.uint32("dethrace.join.last_score_index", "Last Score Index")
|
||||
f_join_car_ptr = ProtoField.uint64("dethrace.join.car_ptr", "Car Spec (pointer)")
|
||||
|
||||
function dissect_game_player_info(tree, data)
|
||||
-- tNet_game_player_info
|
||||
local offset = dissect_pd_player_info(tree, data)
|
||||
|
||||
tree:add_le(f_join_timestamp, data(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
tree:add_le(f_join_last_heard, data(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
tree:add_le(f_join_reposition_time, data(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
tree:add_le(f_join_last_waste_time, data(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
tree:add_le(f_join_host, data(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
tree:add_le(f_join_playerid, data(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
tree:add(f_join_player_name, data(offset, 32))
|
||||
offset = offset + 32
|
||||
|
||||
tree:add_le(f_player_status, data(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
tree:add_le(f_join_car, data(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
tree:add_le(f_join_grid, data(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
tree:add_le(f_join_grid_set, data(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
tree:add_le(f_join_opponent_index, data(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
tree:add_le(f_join_wait_confirm, data(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
tree:add_le(f_join_score, data(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
tree:add_le(f_join_credits, data(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
tree:add_le(f_join_wasted, data(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
tree:add_le(f_join_wasteage_attributed, data(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
tree:add_le(f_join_name_not_clipped, data(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
tree:add_le(f_join_race_stuff_initialized, data(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
tree:add_le(f_join_played, data(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
tree:add_le(f_join_won, data(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
tree:add_le(f_join_next_car_index, data(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
tree:add_le(f_join_games_score, data(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
tree:add_le(f_join_last_score_index, data(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
offset = offset + dissect_br_matrix34(tree, data(offset), "Initial Position")
|
||||
|
||||
assert(offset == 0xbc, "offset of car spec ptr")
|
||||
|
||||
tree:add_le(f_join_car_ptr, data(offset, 4))
|
||||
|
||||
tree:set_len(offset)
|
||||
end
|
||||
|
||||
function dissect_message_join(tree, message)
|
||||
-- tNet_message_join (2)
|
||||
local t = create_message_size_type(tree, message, "Join")["tree"]
|
||||
local offset = 4
|
||||
|
||||
dissect_game_player_info(t:add("Player Info", message(offset)), message(offset))
|
||||
end
|
||||
|
||||
newerplayerlist_count_magics = {
|
||||
[-1] = "-1 (Selected Car Unavailable)",
|
||||
[0] = "0 (Game Already Started)",
|
||||
}
|
||||
|
||||
f_newplayerlist_count = ProtoField.int32("dethrace.newplayerlist.count", "Number Of Players")--, base.DEC, newerplayerlist_count_magics)
|
||||
f_newplayerlist_index = ProtoField.int32("dethrace.newplayerlist.index", "This Index")
|
||||
f_newplayerlist_batch_number = ProtoField.int32("dethrace.newplayerlist.batch_number", "Batch Number")
|
||||
|
||||
function dissect_message_newplayerlist(tree, message)
|
||||
-- tNet_message_new_player_list (3)
|
||||
local t = create_message_size_type(tree, message, "New Player List")["tree"]
|
||||
local offset = 4
|
||||
|
||||
local t_count = t:add_le(f_newplayerlist_count, message(offset, 4))
|
||||
if message(offset, 4):int() == 0 then
|
||||
t_count:set_text("Number Of Players: Game Already Started (0)")
|
||||
elseif message(offset, 4):int() == -1 then
|
||||
t_count:set_text("Number Of Players: Car Unavailable (-1)")
|
||||
end
|
||||
offset = offset + 4
|
||||
|
||||
t:add_le(f_newplayerlist_index, message(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
t:add_le(f_newplayerlist_batch_number, message(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
dissect_game_player_info(t:add("Player", message(offset)), message(offset))
|
||||
-- finished
|
||||
end
|
||||
|
||||
f_guaranteereply_number = ProtoField.uint32("dethrace.guaranteereply.number", "Guarantee Number")
|
||||
|
||||
function dissect_message_guaranteereply(tree, message)
|
||||
-- tNet_message_guarantee_reply (4)
|
||||
local t = create_message_size_type(tree, message, "Guarantee Reply")["tree"]
|
||||
t:add_le(f_guaranteereply_number, message(4, 4))
|
||||
-- FIXME: add reference to packet with this reply number
|
||||
-- finished
|
||||
end
|
||||
|
||||
function dissect_message_cardetailsreq(tree, message)
|
||||
-- tNet_message_car_details_req (5)
|
||||
local t = create_message_size_type(tree, message, "Car Details Req")["tree"]
|
||||
-- finished
|
||||
end
|
||||
|
||||
f_cardetails_count = ProtoField.uint32("dethrace.cardetails.count", "Car Count")
|
||||
f_cardetails_car = ProtoField.uint32("dethrace.cardetails.car_index", "Car") -- FIXME: use table index -> car name
|
||||
f_cardetails_owner = ProtoField.stringz("dethrace.cardetails.owner", "Owner")
|
||||
|
||||
function dissect_message_cardetails(tree, message)
|
||||
-- tNet_message_car_details (6)
|
||||
local t = create_message_size_type(tree, message, "Car Details")["tree"]
|
||||
local offset = 4
|
||||
|
||||
t:add_le(f_cardetails_count, message(4, 4))
|
||||
offset = offset + 4
|
||||
|
||||
for i = 0, 5 do
|
||||
local car_detail = message(offset, 20)
|
||||
local subtree = t:add(car_detail, string.format("Car[%d]", i))
|
||||
subtree:add_le(f_cardetails_car, car_detail(0, 4))
|
||||
subtree:add(f_cardetails_owner, car_detail(4, 16))
|
||||
|
||||
offset = offset + 20
|
||||
end
|
||||
-- finished
|
||||
end
|
||||
|
||||
function dissect_message_leave(tree, message)
|
||||
-- tNet_message_leave (7)
|
||||
local t = create_message_size_type(tree, message, "Leave")["tree"]
|
||||
-- finished
|
||||
end
|
||||
|
||||
function dissect_message_hosticide(tree, message)
|
||||
-- tNet_message_host_pissing_off (8)
|
||||
local t = create_message_size_type(tree, message, "Hosticide")["tree"]
|
||||
-- finished
|
||||
end
|
||||
|
||||
raceover_reasons = {
|
||||
[-1] = eRace_not_over_yet,
|
||||
[ 0] = eRace_over_laps,
|
||||
[ 1] = eRace_over_peds,
|
||||
[ 2] = eRace_over_opponents,
|
||||
[ 3] = eRace_over_abandoned,
|
||||
[ 4] = eRace_over_out_of_time,
|
||||
[ 5] = eRace_over_demo,
|
||||
[ 6] = eRace_over_network_victory,
|
||||
[ 7] = eRace_over_network_loss,
|
||||
}
|
||||
|
||||
f_raceover_reason = ProtoField.uint32("dethrace.raceover.reason", "Reason", base.DEC, raceover_reasons)
|
||||
|
||||
function dissect_message_raceover(tree, message)
|
||||
-- tNet_message_race_over (9)
|
||||
local t = create_message_size_type(tree, message, "Race Over (UNTESTED)")["tree"]
|
||||
t:add_le(f_raceover_reason, message(4, 4))
|
||||
-- finished
|
||||
end
|
||||
|
||||
function dissect_message_statusreport(tree, message)
|
||||
-- tNet_message_status_report (10)
|
||||
local t = create_message_size_type(tree, message, "Status Report")["tree"]
|
||||
t:add_le(f_player_status, message(4, 4))
|
||||
-- finished
|
||||
end
|
||||
|
||||
f_startrace_count = ProtoField.uint32("dethrace.startrace.count", "Car Count", base.DEC)
|
||||
f_startrace_racing = ProtoField.bool("dethrace.startrace.racing", "Racing")
|
||||
f_startrace_next = ProtoField.uint32("dethrace.startrace.next", "Next Race", base.DEC, race_tracks)
|
||||
f_startrace_grid_index = ProtoField.uint32("dethrace.startrace.grid.index", "Index", base.DEC)
|
||||
f_startrace_grid_next_car_index = ProtoField.uint32("dethrace.startrace.grid.next_car_index", "Next Car Index", base.DEC)
|
||||
|
||||
function dissect_message_startrace(tree, message)
|
||||
-- tNet_message_start_race (11)
|
||||
local t = create_message_size_type(tree, message, "Start Race")["tree"]
|
||||
local offset = 4
|
||||
|
||||
t:add_le(f_startrace_count, message(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
t:add_le(f_startrace_racing, message(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
t:add_le(f_startrace_next, message(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
for i = 0, 5 do
|
||||
local start = offset
|
||||
local subtree = t:add(message(offset), string.format("Grid Car[%d]", i))
|
||||
subtree:add_le(f_startrace_grid_index, message(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
subtree:add_le(f_startrace_grid_next_car_index, message(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
offset = offset + dissect_br_matrix34(subtree, message(offset), "Matrix")
|
||||
subtree:set_len(offset - start)
|
||||
end
|
||||
-- FIXME
|
||||
end
|
||||
|
||||
f_headup_text = ProtoField.stringz("dethrace.headup.message", "Message")
|
||||
|
||||
function dissect_message_headup(tree, message)
|
||||
-- tNet_message_headup (12)
|
||||
local t = create_message_size_type(tree, message, "Head-Up (UNTESTED)")["tree"]
|
||||
t:add(f_headup_text, message(4, 128))
|
||||
-- finished
|
||||
end
|
||||
|
||||
function dissect_message_hostquery(tree, message)
|
||||
-- tNet_message_host_query (13)
|
||||
local t = create_message_size_type(tree, message, "Host Query")["tree"]
|
||||
-- finished
|
||||
end
|
||||
|
||||
f_hostreply_started = ProtoField.bool("dethrace.hostreply.started", "Race Started")
|
||||
f_hostreply_race = ProtoField.uint32("dethrace.hostreply.race", "Race", base.DEC, race_tracks)
|
||||
f_hostreply_pending = ProtoField.uint32("dethrace.hostreply.pending", "Pending Race", base.DEC, race_tracks)
|
||||
|
||||
function dissect_message_hostreply(tree, message)
|
||||
-- tNet_message_host_reply (14)
|
||||
local t = create_message_size_type(tree, message, "Host Reply (UNTESTED)")["tree"]
|
||||
t:add(f_hostreply_started, message(4, 4))
|
||||
t:add(f_hostreply_race, message(8, 4))
|
||||
t:add(f_hostreply_pending, message(12, 4))
|
||||
-- finished
|
||||
end
|
||||
|
||||
f_mechanics_id = ProtoField.uint32("dethrace.mechanics.id", "ID")
|
||||
f_mechanics_time = ProtoField.uint32("dethrace.mechanics.time", "Time")
|
||||
f_mechanics_d = ProtoField.uint8("dethrace.mechanics.d", "D")
|
||||
f_mechanics_carcontrols = ProtoField.uint32("dethrace.mechanics.carcontrols", "Car Controls") -- FIXME: bitmask
|
||||
f_mechanics_coll_time = ProtoField.uint32("dethrace.mechanics.coll_time", "Car Control Collision Time")
|
||||
f_mechanics_curvature = ProtoField.int16("dethrace.mechanics.curvature", "Curvature")
|
||||
f_mechanics_revs = ProtoField.uint16("dethrace.mechanics.revs", "Revs")
|
||||
f_mechanics_front = ProtoField.float("dethrace.mechanics.front", "Front")
|
||||
f_mechanics_back = ProtoField.float("dethrace.mechanics.back", "Back")
|
||||
f_mechanics_repair_time = ProtoField.uint32("dethrace.mechanics.repair_time", "Repair Time")
|
||||
f_mechanics_powerups = ProtoField.int16("dethrace.mechanics.powerups", "Powerups")
|
||||
f_mechanics_damage = ProtoField.uint8("dethrace.mechanics.damage", "Damage")
|
||||
|
||||
function dissect_message_mechanics(tree, message)
|
||||
-- tNet_message_mechanics_info (15)
|
||||
local t = create_message_size_type(tree, message, "Mechanics")["tree"]
|
||||
local offset = 4
|
||||
|
||||
t:add_le(f_mechanics_id, message(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
t:add_le(f_mechanics_time, message(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
offset = offset + dissect_reduced_matrix(t, message(offset), "Matrix")
|
||||
|
||||
offset = offset + dissect_br_vector3(t, message(offset), "Velocity")
|
||||
|
||||
offset = offset + dissect_br_vector3(t, message(offset), "Omega")
|
||||
|
||||
do
|
||||
local sub = t:add("d", message(offset, 4))
|
||||
for i = 0, 3 do
|
||||
local item = sub:add_le(f_mechanics_d, message(offset, 1))
|
||||
item:set_text(string.format("d[%d] = %d", i, message(offset, 1):le_uint()))
|
||||
offset = offset + 1
|
||||
end
|
||||
end
|
||||
|
||||
t:add_le(f_mechanics_carcontrols, message(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
t:add_le(f_mechanics_coll_time, message(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
t:add_le(f_mechanics_curvature, message(offset, 2))
|
||||
offset = offset + 2
|
||||
|
||||
t:add_le(f_mechanics_revs, message(offset, 2))
|
||||
offset = offset + 2
|
||||
|
||||
t:add_le(f_mechanics_front, message(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
t:add_le(f_mechanics_back, message(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
t:add_le(f_mechanics_repair_time, message(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
t:add_le(f_mechanics_powerups, message(offset, 2))
|
||||
offset = offset + 2
|
||||
|
||||
do
|
||||
local sub = t:add("Damage", message(offset, 4))
|
||||
-- FIXME: use names of damage system (in addition to index)
|
||||
for i = 0, 11 do
|
||||
local item = sub:add_le(f_mechanics_damage, message(offset, 1))
|
||||
item:set_text(string.format("damage[%d] = %d", i, message(offset, 1):le_uint()))
|
||||
offset = offset + 1
|
||||
end
|
||||
end
|
||||
|
||||
t:add_le(f_mechanics_powerups, message(offset, 2))
|
||||
offset = offset + 2
|
||||
|
||||
-- omit 2 bytes of padding
|
||||
offset = offset + 2
|
||||
|
||||
if offset < message:len() then
|
||||
do
|
||||
local sub = t:add("Wheel Damage Offset", message(offset, 4))
|
||||
for i = 0, 3 do
|
||||
local item = sub:add_le(f_float, message(offset, 4))
|
||||
item:set_text(string.format("offset[%d] = %d", i, message(offset, 4):le_float()))
|
||||
offset = offset + 4
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function dissect_message_noncar_info(tree, message)
|
||||
-- tNet_message_non_car_info (16)
|
||||
local t = create_message_size_type(tree, message, "Non-Car Info (INCOMPLETE)")["tree"]
|
||||
-- FIXME
|
||||
end
|
||||
|
||||
f_timesync_time = ProtoField.uint32("dethrace.timesync.start_time", "Race Start Time")
|
||||
|
||||
function dissect_message_timesync(tree, message)
|
||||
-- tNet_message_time_sync (17)
|
||||
local t = create_message_size_type(tree, message, "Time Sync")["tree"]
|
||||
local offset = 4
|
||||
|
||||
t:add_le(f_timesync_time, message(offset, 4))
|
||||
offset = offset + 4
|
||||
end
|
||||
|
||||
function dissect_message_confirm(tree, message)
|
||||
-- tNet_message_players_confirm (18)
|
||||
local t = create_message_size_type(tree, message, "Confirm (INCOMPLETE)")["tree"]
|
||||
-- FIXME
|
||||
end
|
||||
|
||||
function dissect_message_disablecar(tree, message)
|
||||
-- tNet_message_disable_car (19)
|
||||
local t = create_message_size_type(tree, message, "Disable Car (INCOMPLETE)")["tree"]
|
||||
-- FIXME
|
||||
end
|
||||
|
||||
function dissect_message_enablecar(tree, message)
|
||||
-- tNet_message_enable_car (20)
|
||||
local t = create_message_size_type(tree, message, "Enable Car (INCOMPLETE)")["tree"]
|
||||
-- FIXME
|
||||
end
|
||||
|
||||
function dissect_message_powerup(tree, message)
|
||||
-- tNet_message_powerup (21)
|
||||
local t = create_message_size_type(tree, message, "Power-Up (INCOMPLETE)")["tree"]
|
||||
-- FIXME
|
||||
end
|
||||
|
||||
function dissect_message_recover(tree, message)
|
||||
-- tNet_message_recover (22)
|
||||
local t = create_message_size_type(tree, message, "Recover (INCOMPLETE)")["tree"]
|
||||
-- FIXME
|
||||
end
|
||||
|
||||
f_scores_played = ProtoField.bool("dethrace.score.played", "Played")
|
||||
f_scores_won = ProtoField.bool("dethrace.scored.won", "Won")
|
||||
f_scores_score = ProtoField.int32("dethrace.scored.score", "Score")
|
||||
|
||||
function dissect_message_scores(tree, message)
|
||||
-- tNet_message_game_scores (23)
|
||||
local header = create_message_size_type(tree, message, "Scores")
|
||||
local t = header["tree"]
|
||||
local offset = 4
|
||||
|
||||
for i = 0, 5 do
|
||||
local subtree = t:add(string.format("Scores[%d]", i), message(offset, 12))
|
||||
|
||||
subtree:add_le(f_scores_played, message(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
subtree:add_le(f_scores_won, message(offset, 4))
|
||||
offset = offset + 4
|
||||
|
||||
subtree:add_le(f_scores_score, message(offset, 4))
|
||||
offset = offset + 4
|
||||
end
|
||||
end
|
||||
|
||||
function dissect_message_wasted(tree, message)
|
||||
-- tNet_message_wasted (24)
|
||||
local t = create_message_size_type(tree, message, "Wasted (INCOMPLETE)")["tree"]
|
||||
-- FIXME
|
||||
end
|
||||
|
||||
f_ped_instruction = ProtoField.int8("dethrace.ped.instruction", "Action Instruction")
|
||||
f_ped_flags = ProtoField.int8("dethrace.ped.flags", "Flags")
|
||||
f_ped_index = ProtoField.int16("dethrace.ped.index", "Index")
|
||||
|
||||
function dissect_message_pedestrian(tree, message)
|
||||
-- tNet_message_pedestrian (25)
|
||||
local t = create_message_size_type(tree, message, "Pedestrian (INCOMPLETE)")["tree"]
|
||||
local offset = 2
|
||||
|
||||
t:add_le(f_ped_instruction, message(offset, 1))
|
||||
offset = offset + 1
|
||||
|
||||
t:add_le(f_ped_flags, message(offset, 1))
|
||||
offset = offset + 1
|
||||
|
||||
t:add_le(f_ped_index, message(offset, 2))
|
||||
offset = offset + 2
|
||||
|
||||
-- padding
|
||||
offset = offset + 2
|
||||
|
||||
offset = offset + dissect_br_vector3(t, message(offset, 12), "Position")
|
||||
|
||||
t:add_le(f_float, message(offset, 4)):set_text(string.format("Speed: %f", message(offset, 4):le_float()))
|
||||
offset = offset + 4
|
||||
|
||||
--offset = offset + dissect_br_vector3(t, message(offset, 12), "to_pos")
|
||||
-- FIXME
|
||||
end
|
||||
|
||||
function dissect_message_gameplay(tree, message)
|
||||
-- tNet_message_gameplay (26)
|
||||
local t = create_message_size_type(tree, message, "Gameplay (INCOMPLETE)")["tree"]
|
||||
-- FIXME
|
||||
end
|
||||
|
||||
function dissect_message_noncarposition(tree, message)
|
||||
-- tNet_message_non_car_position (27)
|
||||
local t = create_message_size_type(tree, message, "Non-Car Position (INCOMPLETE)")["tree"]
|
||||
-- FIXME
|
||||
end
|
||||
|
||||
function dissect_message_copinfo(tree, message)
|
||||
-- tNet_message_cop_info (28)
|
||||
local t = create_message_size_type(tree, message, "Cop Info (INCOMPLETE)")["tree"]
|
||||
-- FIXME
|
||||
end
|
||||
|
||||
function dissect_message_gamescores(tree, message)
|
||||
-- tNet_message_oil_spill (29)
|
||||
local t = create_message_size_type(tree, message, "Game Scores (INCOMPLETE)")["tree"]
|
||||
-- FIXME
|
||||
end
|
||||
|
||||
function dissect_message_oilspill(tree, message)
|
||||
-- tNet_message_oil_spill (30)
|
||||
local t = create_message_size_type(tree, message, "Oil Spill (INCOMPLETE)")["tree"]
|
||||
-- FIXME
|
||||
end
|
||||
|
||||
function dissect_message_crushpoint(tree, message)
|
||||
-- tNet_message_crush_point (31)
|
||||
local t = create_message_size_type(tree, message, "Crush Point (INCOMPLETE)")["tree"]
|
||||
-- FIXME
|
||||
end
|
||||
|
||||
function dissect_message_none(tree, message)
|
||||
-- none (32)
|
||||
local t = create_message_size_type(tree, message, "None")["tree"]
|
||||
-- finished
|
||||
end
|
||||
|
||||
dethrace_protocol.fields = {
|
||||
f_checksum, f_broadcast_magic, f_broadcast_type, f_terminator,
|
||||
f_float,
|
||||
|
||||
f_pd_player_info,
|
||||
|
||||
f_message_magic, f_message_guarantee, f_message_sender, f_message_version, f_message_timestamp, f_message_count, f_message_size,
|
||||
f_contents_size, f_contents_type,
|
||||
|
||||
-- 2 (join)
|
||||
f_join_timestamp, f_join_last_heard, f_join_reposition_time, f_join_last_waste_time,
|
||||
f_join_host, f_join_playerid, f_join_player_name, f_join_car, f_join_grid, f_join_grid_set,
|
||||
f_join_opponent_index, f_join_wait_confirm, f_join_score, f_join_credits, f_join_wasted,
|
||||
f_join_wasteage_attributed, f_join_name_not_clipped, f_join_race_stuff_initialized, f_join_played,
|
||||
f_join_won, f_join_next_car_index, f_join_games_score, f_join_last_score_index, f_join_car_ptr,
|
||||
|
||||
-- 3 (newplayerlist)
|
||||
f_newplayerlist_count, f_newplayerlist_index, f_newplayerlist_batch_number,
|
||||
|
||||
f_details_host_name, f_details_host_id, f_details_num_players, f_details_start_race, f_details_no_races_yet, f_details_status,
|
||||
f_details_option_show_players_on_map, f_details_option_show_peds_on_map, f_details_option_enable_text_messages, f_details_option_show_powerups_on_map, f_details_option_powerup_respawn, f_details_option_open_game, f_details_option_starting_money_index, f_details_option_start_type, f_details_option_race_end_target, f_details_option_random_car_choice, f_details_option_race_sequence_type, f_details_option_car_choice,
|
||||
f_details_type,
|
||||
|
||||
f_guaranteereply_number,
|
||||
|
||||
f_cardetails_count, f_cardetails_car, f_cardetails_owner,
|
||||
|
||||
f_raceover_reason,
|
||||
|
||||
f_statusreport_status,
|
||||
|
||||
f_startrace_count, f_startrace_racing, f_startrace_next, f_startrace_grid_index, f_startrace_grid_next_car_index,
|
||||
|
||||
f_headup_text,
|
||||
|
||||
f_hostreply_started, f_hostreply_race, f_hostreply_pending,
|
||||
f_player_status,
|
||||
|
||||
f_mechanics_id, f_mechanics_time, f_mechanics_d, f_mechanics_carcontrols, f_mechanics_coll_time,
|
||||
f_mechanics_curvature, f_mechanics_revs, f_mechanics_front, f_mechanics_back, f_mechanics_repair_time,
|
||||
f_mechanics_powerups, f_mechanics_damage,
|
||||
|
||||
f_timesync_time,
|
||||
|
||||
f_scores_played, f_scores_won, f_scores_score,
|
||||
|
||||
f_ped_instruction, f_ped_flags, f_ped_index,
|
||||
}
|
||||
|
||||
dethrace_message_dissectors = {
|
||||
[ 0] = dissect_message_sendmedetails,
|
||||
[ 1] = dissect_message_details,
|
||||
[ 2] = dissect_message_join,
|
||||
[ 3] = dissect_message_newplayerlist,
|
||||
[ 4] = dissect_message_guaranteereply,
|
||||
[ 5] = dissect_message_cardetailsreq,
|
||||
[ 6] = dissect_message_cardetails,
|
||||
[ 7] = dissect_message_leave,
|
||||
[ 8] = dissect_message_hosticide,
|
||||
[ 9] = dissect_message_raceover,
|
||||
[10] = dissect_message_statusreport,
|
||||
[11] = dissect_message_startrace,
|
||||
[12] = dissect_message_headup,
|
||||
[13] = dissect_message_hostquery,
|
||||
[14] = dissect_message_hostreply,
|
||||
[15] = dissect_message_mechanics,
|
||||
[16] = dissect_message_noncar_info,
|
||||
[17] = dissect_message_timesync,
|
||||
[18] = dissect_message_confirm,
|
||||
[19] = dissect_message_disablecar,
|
||||
[20] = dissect_message_enablecar,
|
||||
[21] = dissect_message_powerup,
|
||||
[22] = dissect_message_recover,
|
||||
[23] = dissect_message_scores,
|
||||
[24] = dissect_message_wasted,
|
||||
[25] = dissect_message_pedestrian,
|
||||
[26] = dissect_message_gameplay,
|
||||
[27] = dissect_message_noncarposition,
|
||||
[28] = dissect_message_copinfo,
|
||||
[29] = dissect_message_gamescores,
|
||||
[30] = dissect_message_oilspill,
|
||||
[31] = dissect_message_crushpoint,
|
||||
[32] = dissect_message_none,
|
||||
}
|
||||
|
||||
function dethrace_protocol.dissector(buffer, pinfo, tree)
|
||||
if buffer:bytes(4, 7) == ByteArray.new("43 57 39 35 4d 53 47") then -- "CW95MSG"
|
||||
local t = tree:add(dethrace_protocol, buffer(), "DethRace Broadcast Protocol")
|
||||
pinfo.cols.protocol = "DRBC"
|
||||
pinfo.cols.info = string.format("Broadcast: %s", broadcast_types[buffer(11, 1):uint()])
|
||||
t:add(f_checksum, buffer(0, 4))
|
||||
t:add(f_broadcast_magic, buffer(4, 7))
|
||||
t:add(f_broadcast_type, buffer(11, 1))
|
||||
t:add(f_terminator, buffer(12, 1))
|
||||
elseif buffer(4, 4):le_uint() == 0x763a5058 then -- "XP:v"
|
||||
pinfo.cols.protocol = "DR";
|
||||
do
|
||||
local t = tree:add(dethrace_protocol, buffer(0, 28), "DethRace Message Protocol")
|
||||
|
||||
t:add(f_checksum, buffer(0, 4))
|
||||
t:add_le(f_message_magic, buffer(4, 4))
|
||||
t:add_le(f_message_guarantee, buffer(8, 4))
|
||||
t:add_le(f_message_sender, buffer(12, 4))
|
||||
t:add_le(f_message_version, buffer(16, 4))
|
||||
t:add_le(f_message_timestamp, buffer(20, 4))
|
||||
t:add_le(f_message_count, buffer(24, 2))
|
||||
t:add_le(f_message_size, buffer(26, 2))
|
||||
end
|
||||
local sender_type_str
|
||||
if (pinfo.src_port == DETHRACE_PORT) then
|
||||
sender_type_str = "HOST"
|
||||
else
|
||||
sender_type_str = "CLIENT"
|
||||
end
|
||||
local message = buffer(28)
|
||||
local message_type = message(1, 1):uint()
|
||||
pinfo.cols.info = string.format("[%s] %s (%d)", sender_type_str, content_types[message_type], message_type)
|
||||
dethrace_message_dissectors[message_type](tree, message)
|
||||
end
|
||||
end
|
||||
|
||||
-- load the udp.port table
|
||||
udp_table = DissectorTable.get("udp.port")
|
||||
-- register our protocol to handle udp port 39456
|
||||
udp_table:add(DETHRACE_PORT, dethrace_protocol)
|
||||
|
Loading…
Reference in New Issue