diff --git a/src/DETHRACE/common/car.c b/src/DETHRACE/common/car.c index be5306bf..b4c4942d 100644 --- a/src/DETHRACE/common/car.c +++ b/src/DETHRACE/common/car.c @@ -4527,13 +4527,18 @@ void ViewOpponent() { // IDA: void __cdecl ToggleCarToCarCollisions() void ToggleCarToCarCollisions() { LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + gCar_car_collisions = !gCar_car_collisions; + if (gCar_car_collisions) { + NewTextHeadupSlot(4, 0, 3000, -4, "Car Car Collisions"); + } else { + NewTextHeadupSlot(4, 0, 3000, -4, "Ghost Cars"); + } } // IDA: void __cdecl SwapCar() void SwapCar() { LOG_TRACE("()"); - NOT_IMPLEMENTED(); } // IDA: void __cdecl AdjustDownForce() @@ -4541,19 +4546,41 @@ void AdjustDownForce() { char s[100]; tCar_spec* c; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + c = gCar_to_view; + c->down_force_speed += 50.f; + if (c->down_force_speed > 2000.f) { + c->down_force_speed = 50.f; + } + if (c->down_force_speed > 300.f) { + c->down_force_speed = 2000.0; + } + sprintf(s, "DownForceSpeed %f", c->down_force_speed); + NewTextHeadupSlot(4, 0, 1500, -4, s); } // IDA: void __cdecl FreezeMechanics() void FreezeMechanics() { LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + gFreeze_mechanics = !gFreeze_mechanics; + if (gFreeze_mechanics) { + NewTextHeadupSlot(4, 0, 3000, -4, "Mechanics Frozen"); + } else { + NewTextHeadupSlot(4, 0, 3000, -4, "Thawed Mechanics"); + } } // IDA: void __cdecl PutOpponentsInNeutral() void PutOpponentsInNeutral() { LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + gStop_opponents_moving = !gStop_opponents_moving; + if (gStop_opponents_moving == 0) { + NewTextHeadupSlot(4, 0, 3000, -4, "Opponents in neutral"); + } else { + NewTextHeadupSlot(4, 0, 3000, -4, "Back in gear"); + } } // IDA: void __cdecl SetPanningFieldOfView() diff --git a/src/DETHRACE/common/controls.c b/src/DETHRACE/common/controls.c index 84a7f55f..ca16adef 100644 --- a/src/DETHRACE/common/controls.c +++ b/src/DETHRACE/common/controls.c @@ -274,7 +274,7 @@ tEdit_func* gEdit_funcs[10][18][8] = { // 1 { ToggleOpponentProcessing, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, // 2 - { CopStartPointInfo, DeleteCopStartPoint, DropCopStartPoint, NULL /* sub_411E7F (empty func) */, NULL, NULL, NULL }, + { CopStartPointInfo, DeleteCopStartPoint, DropCopStartPoint, NULL, CycleCopStartPointType, NULL, NULL, NULL }, // 3 { ToggleMellowOpponents, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, // 4 diff --git a/src/DETHRACE/common/displays.c b/src/DETHRACE/common/displays.c index 213185ef..2c04699f 100644 --- a/src/DETHRACE/common/displays.c +++ b/src/DETHRACE/common/displays.c @@ -746,7 +746,7 @@ int NewTextHeadupSlot2(int pSlot_index, int pFlash_rate, int pLifetime, int pFon LOG_TRACE("(%d, %d, %d, %d, \"%s\", %d)", pSlot_index, pFlash_rate, pLifetime, pFont_index, pText, pQueue_it); time = PDGetTotalTime(); - if (pQueue_it && pSlot_index == 4 && (unsigned int)(time - gLast_centre_headup) < 1000) { + if (pQueue_it && pSlot_index == 4 && time - gLast_centre_headup < 1000) { if (gQueued_headup_count == 4) { KillOldestQueuedHeadup(); } diff --git a/src/DETHRACE/common/opponent.c b/src/DETHRACE/common/opponent.c index fed5456d..90814078 100644 --- a/src/DETHRACE/common/opponent.c +++ b/src/DETHRACE/common/opponent.c @@ -17,6 +17,8 @@ #include "skidmark.h" #include "trig.h" #include "utility.h" + +#include #include br_actor* gOppo_path_actor; @@ -211,7 +213,18 @@ tS16 FindNearestPathNode(br_vector3* pActor_coords, br_scalar* pDistance) { br_scalar distance; br_vector3 actor_to_node; LOG_TRACE("(%p, %p)", pActor_coords, pDistance); - NOT_IMPLEMENTED(); + + nearest_node = -1; + *pDistance = FLT_MAX; + for (i = 0; i < gProgram_state.AI_vehicles.number_of_path_nodes; i++) { + BrVector3Sub(&actor_to_node, &gProgram_state.AI_vehicles.path_nodes[i].p, pActor_coords); + distance = BrVector3Length(&actor_to_node); + if (distance < *pDistance && (!gAlready_elasticating || gProgram_state.AI_vehicles.path_sections[gMobile_section].node_indices[1] != i)) { + *pDistance = distance; + nearest_node = i; + } + } + return nearest_node; } // IDA: tS16 __usercall FindNearestPathSection@(br_vector3 *pActor_coords@, br_vector3 *pPath_direction@, br_vector3 *pIntersect@, br_scalar *pDistance@) @@ -1845,9 +1858,6 @@ int RematerialiseOpponentOnThisSection(tOpponent_spec* pOpponent_spec, br_scalar br_scalar length; LOG_TRACE("(%p, %f, %d)", pOpponent_spec, pSpeed, pSection_no); - NOT_IMPLEMENTED(); - - // UNFINISHED if (pOpponent_spec->physics_me) { dr_dprintf("%s: Actually, we're already materialised", pOpponent_spec->car_spec->driver_name); return 1; @@ -1856,7 +1866,34 @@ int RematerialiseOpponentOnThisSection(tOpponent_spec* pOpponent_spec, br_scalar finish = GetOpponentsSectionFinishNodePoint(pOpponent_spec, pSection_no); BrVector3Sub(§ion_v, finish, start); if (BrVector3Length(§ion_v) != 0.f) { + BrVector3Sub(&a, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t, start); + t = BrVector3Dot(§ion_v, &a) / BrVector3Dot(§ion_v, §ion_v); + if (t < 0.f) { + BrVector3Copy(&p, start); + } else if (t > 1.f) { + BrVector3Copy(&p, finish); + } else { + p.v[0] = start->v[0] + t * car_to_end.v[0]; + p.v[1] = start->v[1] + t * car_to_end.v[1]; + p.v[2] = start->v[2] + t * car_to_end.v[2]; + } + BrVector3Copy(&pOpponent_spec->car_spec->car_master_actor->t.t.translate.t, &p); + BrVector3Sub(&a, finish, start); + PointActorAlongThisBloodyVector(pOpponent_spec->car_spec->car_master_actor, &a); + } + if (!RematerialiseOpponent(pOpponent_spec, pSpeed)) { + return 0; + } + BrVector3Sub(&car_to_end, finish, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t); + pOpponent_spec->car_spec->brake_force = 0.f; + pOpponent_spec->car_spec->acc_force = 0.f; + if (BrVector3Length(&car_to_end) >= 5.f) { + pOpponent_spec->car_spec->acc_force = pOpponent_spec->car_spec->M / 2.f; + } else { + pOpponent_spec->car_spec->acc_force = 15.f * pOpponent_spec->car_spec->M; } + pOpponent_spec->last_in_view = gTime_stamp_for_this_munging; + return 1; } // IDA: int __usercall RematerialiseOpponentOnNearestSection@(tOpponent_spec *pOpponent_spec@, br_scalar pSpeed) @@ -1877,21 +1914,18 @@ int RematerialiseOpponentOnNearestSection(tOpponent_spec* pOpponent_spec, br_sca } section_no = FindNearestPathSection(&pOpponent_spec->car_spec->car_master_actor->t.t.translate.t, &direction_v, &intersect, &distance); finish = &gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[section_no].node_indices[1]].p; - pOpponent_spec->car_spec->car_master_actor->t.t.translate.t = intersect; + BrVector3Copy(&pOpponent_spec->car_spec->car_master_actor->t.t.translate.t, &intersect); PointActorAlongThisBloodyVector(pOpponent_spec->car_spec->car_master_actor, &direction_v); - car_to_end.v[0] = finish->v[0] - pOpponent_spec->car_spec->car_master_actor->t.t.mat.m[3][0]; - car_to_end.v[1] = finish->v[1] - pOpponent_spec->car_spec->car_master_actor->t.t.mat.m[3][1]; - car_to_end.v[2] = finish->v[2] - pOpponent_spec->car_spec->car_master_actor->t.t.mat.m[3][2]; + BrVector3Sub(&car_to_end, finish, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t); if (RematerialiseOpponent(pOpponent_spec, pSpeed)) { pOpponent_spec->car_spec->brake_force = 0.0f; pOpponent_spec->car_spec->acc_force = 0.0f; distance_to_end = BrVector3Length(&car_to_end); if (distance_to_end >= 5.0f) { - pOpponent_spec->car_spec->acc_force = pOpponent_spec->car_spec->M / 2.0; - + pOpponent_spec->car_spec->acc_force = pOpponent_spec->car_spec->M / 2.0f; } else { - pOpponent_spec->car_spec->brake_force = pOpponent_spec->car_spec->M * 15.0; + pOpponent_spec->car_spec->brake_force = pOpponent_spec->car_spec->M * 15.0f; } } return 0; @@ -1985,6 +2019,8 @@ int RematerialiseOpponent(tOpponent_spec* pOpponent_spec, br_scalar pSpeed) { BrMatrix34ApplyP(&pOpponent_spec->car_spec->pos, &pOpponent_spec->car_spec->cmpos, mat); BrVector3InvScale(&pOpponent_spec->car_spec->pos, &pOpponent_spec->car_spec->pos, WORLD_SCALE); BrVector3Negate(&pOpponent_spec->car_spec->direction, (br_vector3*)pOpponent_spec->car_spec->oldmat.m[3]); + pOpponent_spec->car_spec->box_face_ref = gFace_num__car - 2; + pOpponent_spec->car_spec->doing_nothing_flag = 0; sensible_place = TestForCarInSensiblePlace(pOpponent_spec->car_spec); if (sensible_place) { break; @@ -2743,7 +2779,20 @@ tS16 GetOpponentsSectionStartNode(tOpponent_spec* pOpponent_spec, tS16 pSection) tS16 section_no; int node_index_index; LOG_TRACE("(%p, %d)", pOpponent_spec, pSection); - NOT_IMPLEMENTED(); + + if (pSection >= 20000 && pSection - 20000 < pOpponent_spec->nnext_sections) { + node_index_index = pOpponent_spec->next_sections[pSection - 20000].direction == 0; + if (pSection - 20000 > pOpponent_spec->nnext_sections) { + section_no = -1; + } else { + section_no = gProgram_state.AI_vehicles.path_sections[pOpponent_spec->next_sections[pSection - 20000].section_no].node_indices[node_index_index]; + return section_no; + } + } + dr_dprintf("BIG ERROR - GetOpponentsSectionStartNode() - section not found in next_section array for opponent %s", + pOpponent_spec->car_spec->driver_name); + PDEnterDebugger("BIG ERROR - GetOpponentsSectionStartNode()"); + return -1; } // IDA: tS16 __usercall GetOpponentsSectionFinishNode@(tOpponent_spec *pOpponent_spec@, tS16 pSection@) @@ -2751,7 +2800,14 @@ tS16 GetOpponentsSectionFinishNode(tOpponent_spec* pOpponent_spec, tS16 pSection tS16 section_no; int node_index_index; LOG_TRACE("(%p, %d)", pOpponent_spec, pSection); - NOT_IMPLEMENTED(); + + if (pSection >= 20000 && pSection - 20000 < pOpponent_spec->nnext_sections) { + return gProgram_state.AI_vehicles.path_sections[pOpponent_spec->next_sections[pSection - 20000].section_no].node_indices[pOpponent_spec->next_sections[pSection - 20000].direction]; + } + dr_dprintf("BIG ERROR - GetOpponentsSectionFinishNode() - section not found in next_section array for opponent %s", + pOpponent_spec->car_spec->driver_name); + PDEnterDebugger("BIG ERROR - GetOpponentsSectionFinishNode()"); + return 0; } // IDA: br_vector3* __usercall GetOpponentsSectionStartNodePoint@(tOpponent_spec *pOpponent_spec@, tS16 pSection@) @@ -3188,7 +3244,40 @@ void InsertThisNodeInThisSectionHere(tS16 pInserted_node, tS16 pSection_no, br_v tS16 node2; tS16 node3; LOG_TRACE("(%d, %d, %p)", pInserted_node, pSection_no, pWhere); - NOT_IMPLEMENTED(); + + section_no_index = gProgram_state.AI_vehicles.path_sections[pSection_no].node_indices[1]; + new_section = ReallocExtraPathSections(1); + gProgram_state.AI_vehicles.path_sections[new_section].node_indices[0] = pInserted_node; + gProgram_state.AI_vehicles.path_sections[new_section].node_indices[1] = section_no_index; + gProgram_state.AI_vehicles.path_sections[new_section].min_speed[0] = 0; + gProgram_state.AI_vehicles.path_sections[new_section].max_speed[0] = 255; + gProgram_state.AI_vehicles.path_sections[new_section].min_speed[1] = + gProgram_state.AI_vehicles.path_sections[pSection_no].min_speed[1]; + gProgram_state.AI_vehicles.path_sections[new_section].max_speed[1] = + gProgram_state.AI_vehicles.path_sections[pSection_no].max_speed[1]; + gProgram_state.AI_vehicles.path_sections[new_section].width = + gProgram_state.AI_vehicles.path_sections[pSection_no].width; + gProgram_state.AI_vehicles.path_sections[new_section].type = + gProgram_state.AI_vehicles.path_sections[pSection_no].type; + gProgram_state.AI_vehicles.path_sections[new_section].one_way = + gProgram_state.AI_vehicles.path_sections[pSection_no].one_way; + gProgram_state.AI_vehicles.path_sections[pSection_no].node_indices[1] = pInserted_node; + gProgram_state.AI_vehicles.path_sections[pSection_no].min_speed[1] = 0; + gProgram_state.AI_vehicles.path_sections[pSection_no].max_speed[1] = 255; + BrVector3Copy(&gProgram_state.AI_vehicles.path_nodes[pInserted_node].p, pWhere); + gProgram_state.AI_vehicles.path_nodes[pInserted_node].sections + [gProgram_state.AI_vehicles.path_nodes[pInserted_node].number_of_sections] = pSection_no; + gProgram_state.AI_vehicles.path_nodes[pInserted_node].number_of_sections = + gProgram_state.AI_vehicles.path_nodes[pInserted_node].number_of_sections + 1; + gProgram_state.AI_vehicles.path_nodes[pInserted_node].sections + [gProgram_state.AI_vehicles.path_nodes[pInserted_node].number_of_sections] = new_section; + gProgram_state.AI_vehicles.path_nodes[pInserted_node].number_of_sections = + gProgram_state.AI_vehicles.path_nodes[pInserted_node].number_of_sections + 1; + for (node1 = 0; node1 < gProgram_state.AI_vehicles.path_nodes[section_no_index].number_of_sections; node1++) { + if (gProgram_state.AI_vehicles.path_nodes[section_no_index].sections[node1] == pSection_no) { + gProgram_state.AI_vehicles.path_nodes[section_no_index].sections[node1] = new_section; + } + } } // IDA: void __cdecl TrackElasticateyPath() @@ -3219,7 +3308,51 @@ void RecalcNearestPathSectionSpeed(int pMax_not_min, int pAdjustment) { int new_speed; int nearest_end; LOG_TRACE("(%d, %d)", pMax_not_min, pAdjustment); - NOT_IMPLEMENTED(); + + if (gOppo_paths_shown) { + section_no = FindNearestPathSection(&gSelf->t.t.translate.t, &direction_v, &intersect, &distance); + if (!gAlready_elasticating && distance > 10.f) { + NewTextHeadupSlot(4, 0, 2000, -1, "Can't find any paths close enough"); + } else { + BrVector3Sub(&wank, &gSelf->t.t.translate.t, &gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[section_no].node_indices[0]].p); + dist_to_start = BrVector3Length(&wank); + BrVector3Sub(&wank, &gSelf->t.t.translate.t, &gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[section_no].node_indices[1]].p); + dist_to_finish = BrVector3Length(&wank); + nearest_end = dist_to_finish < dist_to_start ? 1 : 0; + if (pMax_not_min) { + new_speed = gProgram_state.AI_vehicles.path_sections[section_no].max_speed[nearest_end]; + } else { + new_speed = gProgram_state.AI_vehicles.path_sections[section_no].min_speed[nearest_end]; + } + new_speed += 5 * pAdjustment; + if (5 * pAdjustment < 0 && new_speed > 100) { + new_speed = 100; + } else if (5 * pAdjustment > 0 && new_speed > 100) { + new_speed = 255; + } + if (new_speed < 0) { + new_speed = 0; + } else if (new_speed > 255) { + new_speed = 255; + } + if (pMax_not_min) { + gProgram_state.AI_vehicles.path_sections[section_no].max_speed[nearest_end] = new_speed; + } else { + gProgram_state.AI_vehicles.path_sections[section_no].min_speed[nearest_end] = new_speed; + } + if (nearest_end != 0) { + sprintf(str, "Towards section finish - Min Speed %d mph - Max speed %d mph", + (int)(2.2f * gProgram_state.AI_vehicles.path_sections[section_no].min_speed[nearest_end]), + (int)(2.2f * gProgram_state.AI_vehicles.path_sections[section_no].max_speed[nearest_end])); + } else { + sprintf(str, "Towards section start - Min Speed %d mph - Max speed %d mph", + (int)(2.2f * gProgram_state.AI_vehicles.path_sections[section_no].min_speed[0]), + (int)(2.2f * gProgram_state.AI_vehicles.path_sections[section_no].max_speed[0])); + } + ShowOppoPaths(); + NewTextHeadupSlot(4, 0, 2000, -1, str); + } + } } // IDA: void __cdecl RecalcNearestPathSectionWidth(br_scalar pAdjustment) @@ -3230,7 +3363,25 @@ void RecalcNearestPathSectionWidth(br_scalar pAdjustment) { br_scalar distance; char str[128]; LOG_TRACE("(%f)", pAdjustment); - NOT_IMPLEMENTED(); + + if (gOppo_paths_shown) { + if (!gAlready_elasticating) { + section_no = FindNearestPathSection(&gSelf->t.t.translate.t, &direction_v, &intersect, &distance); + if (distance > 10.f) { + NewTextHeadupSlot(4, 0, 2000, -1, "Can't find any paths close enough"); + return; + } + } else { + section_no = gMobile_section; + } + gProgram_state.AI_vehicles.path_sections[section_no].width += (int)pAdjustment * pAdjustment + pAdjustment; + if (gProgram_state.AI_vehicles.path_sections[section_no].width < .05f) { + gProgram_state.AI_vehicles.path_sections[section_no].width = .05f; + } + ShowOppoPaths(); + sprintf(str, "Width %2.1f BRU", 2.f * gProgram_state.AI_vehicles.path_sections[section_no].width); + NewTextHeadupSlot(4, 0, 2000, -1, str); + } } // IDA: void __usercall CalcNegativeXVector(br_vector3 *pNegative_x_vector@, br_vector3 *pStart@, br_vector3 *pFinish@, br_scalar pLength) @@ -3280,7 +3431,40 @@ void MakeSection(br_uint_16 pFirst_vertex, br_uint_16 pFirst_face, br_vector3* p br_material* the_material_finish_dk; br_scalar height; LOG_TRACE("(%d, %d, %p, %p, %f, %p, %p, %p, %p, %p, %p)", pFirst_vertex, pFirst_face, pStart, pFinish, pWidth, pMaterial_centre_lt, pMaterial_centre_dk, pMaterial_edges_start_lt, pMaterial_edges_start_dk, pMaterial_edges_finish_lt, pMaterial_edges_finish_dk); - NOT_IMPLEMENTED(); + + CalcNegativeXVector(&offset_v, pStart, pFinish, pWidth); + for (i = 0; i < 3; i++) { + the_material_start_lt = pMaterial_edges_start_lt; + the_material_start_dk = pMaterial_edges_start_dk; + the_material_finish_lt = pMaterial_edges_finish_lt; + the_material_finish_dk = pMaterial_edges_finish_dk; + height = .15f; + if (i == 1) { + BrVector3Negate(&offset_v, &offset_v); + } else if (i == 2) { + height = .3f; + BrVector3Set(&offset_v, 0.f, 0.f, 0.f); + the_material_finish_lt = pMaterial_centre_lt; + the_material_start_lt = pMaterial_centre_lt; + the_material_finish_dk = pMaterial_centre_dk; + the_material_start_dk = pMaterial_centre_dk; + } + centre_length_v.v[0] = pStart->v[0] + (pFinish->v[0] - pStart->v[0]) / 2.f; + centre_length_v.v[1] = pStart->v[1] + (pFinish->v[1] - pStart->v[1]) / 2.f; + centre_length_v.v[2] = pStart->v[2] + (pFinish->v[2] - pStart->v[2]) / 2.f; + + MakeVertexAndOffsetIt(gOppo_path_model, pFirst_vertex + 6 * i + 0, pStart->v[0], pStart->v[1], pStart->v[2], &offset_v); + MakeVertexAndOffsetIt(gOppo_path_model, pFirst_vertex + 6 * i + 1, pStart->v[0], pStart->v[1] + height, pStart->v[2], &offset_v); + MakeVertexAndOffsetIt(gOppo_path_model, pFirst_vertex + 6 * i + 2, centre_length_v.v[0], centre_length_v.v[1] + height, centre_length_v.v[2], &offset_v); + MakeVertexAndOffsetIt(gOppo_path_model, pFirst_vertex + 6 * i + 3, centre_length_v.v[0], centre_length_v.v[1], centre_length_v.v[2], &offset_v); + MakeVertexAndOffsetIt(gOppo_path_model, pFirst_vertex + 6 * i + 4, pFinish->v[0], pFinish->v[1] + height, pFinish->v[2], &offset_v); + MakeVertexAndOffsetIt(gOppo_path_model, pFirst_vertex + 6 * i + 5, pFinish->v[0], pFinish->v[1], pFinish->v[2], &offset_v); + + MakeFaceAndTextureIt(gOppo_path_model, pFirst_face + 4 * i + 0, pFirst_vertex + 6 * i + 0, pFirst_vertex + 6 * i + 1, pFirst_vertex + 6 * i + 2, the_material_start_lt); + MakeFaceAndTextureIt(gOppo_path_model, pFirst_face + 4 * i + 1, pFirst_vertex + 6 * i + 0, pFirst_vertex + 6 * i + 2, pFirst_vertex + 6 * i + 3, the_material_start_dk); + MakeFaceAndTextureIt(gOppo_path_model, pFirst_face + 4 * i + 2, pFirst_vertex + 6 * i + 3, pFirst_vertex + 6 * i + 2, pFirst_vertex + 6 * i + 4, the_material_finish_lt); + MakeFaceAndTextureIt(gOppo_path_model, pFirst_face + 4 * i + 3, pFirst_vertex + 6 * i + 3, pFirst_vertex + 6 * i + 4, pFirst_vertex + 6 * i + 5, the_material_finish_dk); + } } // IDA: void __usercall MakeCube(br_uint_16 pFirst_vertex@, br_uint_16 pFirst_face@, br_vector3 *pPoint@, br_material *pMaterial_1@, br_material *pMaterial_2, br_material *pMaterial_3) @@ -3402,8 +3586,8 @@ void AllocateMatsForOppoPathModel() { // IDA: void __cdecl RebuildOppoPathModel() void RebuildOppoPathModel() { - static int nvertices_last_time; - static int nfaces_last_time; + static int nvertices_last_time = 0; + static int nfaces_last_time = 0; int i; int at_least_one; br_uint_16 nfaces; @@ -3417,7 +3601,92 @@ void RebuildOppoPathModel() { br_material* edge_mat_finish_lt; br_material* edge_mat_finish_dk; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + if (gProgram_state.AI_vehicles.number_of_path_nodes < 2) { + if (gOppo_path_model != NULL) { + BrModelRemove(gOppo_path_model); + BrModelFree(gOppo_path_model); + gOppo_path_model = NULL; + } + if (gOppo_path_actor != NULL) { + gOppo_path_actor->type = BR_ACTOR_NONE; + gOppo_path_actor->render_style = BR_RSTYLE_NONE; + } + } else { + if (!gMats_allocated) { + AllocateMatsForOppoPathModel(); + } + if (gOppo_path_actor == NULL) { + gOppo_path_actor = BrActorAllocate(BR_ACTOR_MODEL, NULL); + BrActorAdd(gNon_track_actor, gOppo_path_actor); + } + if (gOppo_path_model == NULL) { + gOppo_path_actor->model = BrModelAllocate("OppoPathModel", 3, 1); + gOppo_path_model = gOppo_path_actor->model; + gOppo_path_model->flags |= BR_MODF_DONT_WELD | BR_MODF_KEEP_ORIGINAL | BR_MODF_GENERATE_TAGS; + BrModelAdd(gOppo_path_model); + } + gOppo_path_actor->model = gOppo_path_model; + gOppo_path_actor->type = BR_ACTOR_MODEL; + gOppo_path_actor->render_style = BR_RSTYLE_FACES; + CalcNumberOfFacesAndVerticesForOppoPathModel(&nfaces, &nvertices); + if (nvertices_last_time < nvertices || nfaces_last_time < nfaces) { + ReallocModelFacesAndVertices(gOppo_path_model, nfaces, nvertices); + nvertices_last_time = nvertices; + nfaces_last_time = nfaces; + } else { + gOppo_path_model->nvertices = nvertices; + gOppo_path_model->nfaces = nfaces; + } + for (i = 0; i < gProgram_state.AI_vehicles.number_of_path_sections; i++) { + centre_mat_lt = gMat_lt_grn; + centre_mat_dk = gMat_dk_grn; + edge_mat_start_lt = gMat_lt_grn; + edge_mat_start_dk = gMat_dk_grn; + edge_mat_finish_lt = gMat_lt_grn; + edge_mat_finish_dk = gMat_dk_grn; + if (gProgram_state.AI_vehicles.path_sections[i].type == 1) { + centre_mat_lt = gMat_lt_red; + centre_mat_dk = gMat_dk_red; + } else if (gProgram_state.AI_vehicles.path_sections[i].type == 2) { + centre_mat_lt = gMat_lt_blu; + centre_mat_dk = gMat_dk_blu; + } + if (gProgram_state.AI_vehicles.path_sections[i].one_way) { + centre_mat_lt = gMat_lt_yel; + } + if ((gProgram_state.AI_vehicles.path_sections[i].min_speed[0] != 0) || + (gProgram_state.AI_vehicles.path_sections[i].max_speed[0] != 255)) { + edge_mat_start_lt = gMat_lt_turq; + edge_mat_start_dk = gMat_dk_turq; + } + if ((gProgram_state.AI_vehicles.path_sections[i].min_speed[1] != 0) || + (gProgram_state.AI_vehicles.path_sections[i].max_speed[1] != 255)) { + edge_mat_finish_lt = gMat_lt_turq; + edge_mat_finish_dk = gMat_dk_turq; + } + if (gAlready_elasticating != 0 && gMobile_section == i) { + BrVector3Copy(&gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[i].node_indices[1]].p, + &gSelf->t.t.translate.t); + } + MakeSection(18 * i, 12 * i, + &gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[i].node_indices[0]].p, + &gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[i].node_indices[1]].p, + gProgram_state.AI_vehicles.path_sections[i].width, + centre_mat_lt,centre_mat_dk, + edge_mat_start_lt,edge_mat_start_dk, + edge_mat_finish_lt,edge_mat_finish_dk); + } + for (i = 0; i < gProgram_state.AI_vehicles.number_of_cops; i++) { + MakeCube(18 * gProgram_state.AI_vehicles.number_of_path_sections + 8 * i, + 12 * gProgram_state.AI_vehicles.number_of_path_sections + 12 * i, + gProgram_state.AI_vehicles.cop_start_points + i, + gMat_lt_turq, + gMat_lt_turq, + gMat_dk_turq); + } + BrModelUpdate(gOppo_path_model, BR_MODU_ALL); + } } // IDA: int __cdecl ConsistencyCheck() @@ -3566,9 +3835,27 @@ int ConsistencyCheck() { void ShowOppoPaths() { char str[256]; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + if (!gOppo_paths_shown) { + if (gOppo_path_actor != NULL) { + gOppo_path_actor->render_style = BR_RSTYLE_NONE; + } + NewTextHeadupSlot(4, 0, 1000, -1, "Not displaying any paths"); + } else { + RebuildOppoPathModel(); + sprintf(str, "Total %d nodes, %d sections", + gProgram_state.AI_vehicles.number_of_path_nodes, + gProgram_state.AI_vehicles.number_of_path_sections); + NewTextHeadupSlot(4, 0, 1000, -1, str); + } + if (ConsistencyCheck()) { + WriteOutOppoPaths(); + } } +#include +#include + // IDA: void __cdecl WriteOutOppoPaths() void WriteOutOppoPaths() { char the_path[256]; @@ -3585,7 +3872,12 @@ void WriteOutOppoPaths() { sprintf(str, "OPATH%0.3d.TXT", i); #endif PathCat(the_path, gApplication_path, str); +#ifdef DETHRACE_FIX_BUGS + // OldDRfopen refuses to open unknown .TXT files + f = fopen(the_path, "r"); +#else f = DRfopen(the_path, "r+"); +#endif if (f == NULL) { break; } @@ -3594,7 +3886,12 @@ void WriteOutOppoPaths() { strcpy(gOppo_path_filename, the_path); gMade_path_filename = 1; } +#ifdef DETHRACE_FIX_BUGS + f = fopen(gOppo_path_filename, "w"); +#else f = DRfopen(gOppo_path_filename, "wt"); +#endif + if (f == NULL) { printf("f is NULL, errno=%d, msg=\"%s\"\n", errno, strerror(errno));} fprintf(f, "%s\n", "START OF OPPONENT PATHS"); fprintf(f, "\n%-3d // Number of path nodes\n", gProgram_state.AI_vehicles.number_of_path_nodes); @@ -3636,13 +3933,24 @@ void WriteOutOppoPaths() { int NewNodeOKHere() { br_vector3 last_node_to_this; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + if (gAlready_elasticating) { + BrVector3Sub(&last_node_to_this, + &gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[gMobile_section].node_indices[1]].p, + &gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[gMobile_section].node_indices[0]].p); + return BrVector3Length(&last_node_to_this) != 0.f; + } + return 1; } // IDA: void __cdecl ShowHideOppoPaths() void ShowHideOppoPaths() { LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + if (!gAlready_elasticating) { + gOppo_paths_shown = !gOppo_paths_shown; + ShowOppoPaths(); + } } // IDA: void __cdecl DropElasticateyNode() @@ -3657,7 +3965,72 @@ void DropElasticateyNode() { tPath_section_type_enum section_type; tPath_section_type_enum original_type; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + all_the_same_type = 1; + if (!NewNodeOKHere()) { + return; + } + if (gAlready_elasticating) { + old_node = gProgram_state.AI_vehicles.path_sections[gMobile_section].node_indices[1]; + BrVector3Copy(&gProgram_state.AI_vehicles.path_nodes[old_node].p, + &gProgram_state.current_car.car_master_actor->t.t.translate.t); + original_type = gProgram_state.AI_vehicles.path_sections[gMobile_section].type; + one_wayness = gProgram_state.AI_vehicles.path_sections[gMobile_section].one_way; + new_node = ReallocExtraPathNodes(1); + gMobile_section = ReallocExtraPathSections(1); + } else { + if (!gOppo_paths_shown) { + NewTextHeadupSlot(4, 0, 2000, -1, "You must show paths before adding to them (F5)"); + return; + } + if (gProgram_state.AI_vehicles.number_of_path_nodes == 0) { + NewTextHeadupSlot(4, 0, 2000, -1, "Not implemented yet. Go away."); + return; + } + old_node = FindNearestPathNode(&gSelf->t.t.translate.t, &distance); + if (distance > 10.f) { + NewTextHeadupSlot(4, 0, 2000, -1, "Can't find any nodes close enough"); + return; + } + original_type = 0; + if (gProgram_state.AI_vehicles.path_nodes[old_node].number_of_sections != 0) { + for (section_no_index = 1; section_no_index < gProgram_state.AI_vehicles.path_nodes[old_node].number_of_sections; section_no_index++) { + if (gProgram_state.AI_vehicles.path_sections[gProgram_state.AI_vehicles.path_nodes[old_node].sections[section_no_index]].type != + gProgram_state.AI_vehicles.path_sections[gProgram_state.AI_vehicles.path_nodes[old_node].sections[0]].type) { + all_the_same_type = 0; + } + } + if (all_the_same_type) { + original_type = gProgram_state.AI_vehicles.path_sections [gProgram_state.AI_vehicles.path_nodes[old_node].sections[0]].type; + } + } + gAlready_elasticating = 1; + new_node = ReallocExtraPathNodes(1); + gMobile_section = ReallocExtraPathSections(1); + one_wayness = 0; + } + gProgram_state.AI_vehicles.path_sections[gMobile_section].node_indices[0] = old_node; + gProgram_state.AI_vehicles.path_sections[gMobile_section].node_indices[1] = new_node; + gProgram_state.AI_vehicles.path_sections[gMobile_section].min_speed[0] = 0; + gProgram_state.AI_vehicles.path_sections[gMobile_section].min_speed[1] = 0; + gProgram_state.AI_vehicles.path_sections[gMobile_section].max_speed[0] = 255; + gProgram_state.AI_vehicles.path_sections[gMobile_section].max_speed[1] = 255; + gProgram_state.AI_vehicles.path_sections[gMobile_section].type = original_type; + gProgram_state.AI_vehicles.path_sections[gMobile_section].one_way = one_wayness; + if (gProgram_state.AI_vehicles.path_nodes[old_node].number_of_sections == 0) { + gProgram_state.AI_vehicles.path_sections[gMobile_section].width = 1.f; + } else { + gProgram_state.AI_vehicles.path_sections[gMobile_section].width = + gProgram_state.AI_vehicles.path_sections[gProgram_state.AI_vehicles.path_nodes[old_node].sections[0]].width; + } + gProgram_state.AI_vehicles.path_nodes[new_node].number_of_sections = 0; + gProgram_state.AI_vehicles.path_nodes[new_node].sections[gProgram_state.AI_vehicles.path_nodes[new_node].number_of_sections] = gMobile_section; + gProgram_state.AI_vehicles.path_nodes[new_node].number_of_sections += 1; + gProgram_state.AI_vehicles.path_nodes[old_node].sections[gProgram_state.AI_vehicles.path_nodes[old_node].number_of_sections] = gMobile_section; + gProgram_state.AI_vehicles.path_nodes[old_node].number_of_sections += 1; + ShowOppoPaths(); + sprintf(str, "New section #%d, new node #%d", gMobile_section, new_node); + NewTextHeadupSlot(4, 0, 2000, -1, str); } // IDA: void __cdecl InsertAndElasticate() @@ -3675,7 +4048,63 @@ void InsertAndElasticate() { char str[256]; tPath_section_type_enum section_type; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + not_perp = 0; + if (NewNodeOKHere()) { + section_no = FindNearestPathSection(&gSelf->t.t.translate.t, &direction_v, &intersect, &distance); + BrVector3Sub(&wank, + &gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[section_no].node_indices[0]].p, + &intersect); + if (BrVector3Length(&wank) == 0.f) { + not_perp = 1; + } + BrVector3Sub(&wank, + &gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[section_no].node_indices[1]].p, + &intersect); + if (BrVector3Length(&wank) == 0.f) { + not_perp = 1; + } + if (not_perp || distance > 10.f) { + NewTextHeadupSlot(4, 0, 2000, -1, "Get nearer to the section"); + } else { + new_section = ReallocExtraPathSections(1); + if (gAlready_elasticating) { + inserted_node = gProgram_state.AI_vehicles.path_sections[gMobile_section].node_indices[1]; + section_type = gProgram_state.AI_vehicles.path_sections[gMobile_section].type; + one_wayness = gProgram_state.AI_vehicles.path_sections[gMobile_section].one_way; + elasticatey_node = ReallocExtraPathNodes(1); + gProgram_state.AI_vehicles.path_nodes[elasticatey_node].number_of_sections = 0; + gProgram_state.AI_vehicles.path_sections[new_section].width = gProgram_state.AI_vehicles.path_sections[gMobile_section].width; + } else { + inserted_node = ReallocExtraPathNodes(2); + gProgram_state.AI_vehicles.path_nodes[inserted_node].number_of_sections = 0; + elasticatey_node = inserted_node + 1; + gProgram_state.AI_vehicles.path_nodes[elasticatey_node].number_of_sections = 0; + gProgram_state.AI_vehicles.path_sections[new_section].width = gProgram_state.AI_vehicles.path_sections[section_no].width; + section_type = gProgram_state.AI_vehicles.path_sections[section_no].type; + one_wayness = gProgram_state.AI_vehicles.path_sections[section_no].one_way; + } + InsertThisNodeInThisSectionHere(inserted_node, section_no, &gSelf->t.t.translate.t); + gMobile_section = new_section; + gProgram_state.AI_vehicles.path_sections[new_section].node_indices[0] = inserted_node; + gProgram_state.AI_vehicles.path_sections[gMobile_section].node_indices[1] = elasticatey_node; + gProgram_state.AI_vehicles.path_sections[gMobile_section].min_speed[0] = 0; + gProgram_state.AI_vehicles.path_sections[gMobile_section].min_speed[1] = 0; + gProgram_state.AI_vehicles.path_sections[gMobile_section].max_speed[0] = 255; + gProgram_state.AI_vehicles.path_sections[gMobile_section].max_speed[1] = 255; + gProgram_state.AI_vehicles.path_sections[gMobile_section].type = section_type; + gProgram_state.AI_vehicles.path_sections[gMobile_section].one_way = one_wayness; + gProgram_state.AI_vehicles.path_nodes[inserted_node].sections[gProgram_state.AI_vehicles.path_nodes[inserted_node].number_of_sections] = gMobile_section; + gProgram_state.AI_vehicles.path_nodes[inserted_node].number_of_sections += 1; + gProgram_state.AI_vehicles.path_nodes[elasticatey_node].sections[gProgram_state.AI_vehicles.path_nodes[elasticatey_node].number_of_sections] = gMobile_section; + gProgram_state.AI_vehicles.path_nodes[elasticatey_node].number_of_sections += 1; + gAlready_elasticating = 1; + ShowOppoPaths(); + sprintf(str, "New section %d, new node #%d inserted into section #%d", + gMobile_section, inserted_node, section_no); + NewTextHeadupSlot(4, 0, 2000, -1, str); + } + } } // IDA: void __cdecl InsertAndDontElasticate() @@ -3689,14 +4118,52 @@ void InsertAndDontElasticate() { int not_perp; char str[256]; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + not_perp = 0; + if (NewNodeOKHere()) { + section_no = FindNearestPathSection(&gSelf->t.t.translate.t, &direction_v, &intersect, &distance); + BrVector3Sub(&wank, &gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[section_no].node_indices[0]].p, &intersect); + if (BrVector3Length(&wank) == 0.f) { + not_perp = 1; + } + BrVector3Sub(&wank, &gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[section_no].node_indices[1]].p, &intersect); + if (BrVector3Length(&wank) == 0.f) { + not_perp = 1; + } + if (not_perp || distance > 10.f) { + NewTextHeadupSlot(4, 0, 2000, -1, "Get nearer to the section"); + } else { + if (gAlready_elasticating) { + gAlready_elasticating = 0; + inserted_node = gProgram_state.AI_vehicles.path_sections[gMobile_section].node_indices[1]; + } else { + inserted_node = ReallocExtraPathNodes(1); + gProgram_state.AI_vehicles.path_nodes[inserted_node].number_of_sections = 0; + } + InsertThisNodeInThisSectionHere(inserted_node, section_no, &gSelf->t.t.translate.t); + ShowOppoPaths(); + sprintf(str, "New node #%d inserted into section #%d", inserted_node, section_no); + NewTextHeadupSlot(4, 0, 2000, -1, str); + } + } } // IDA: void __cdecl DropDeadEndNode() void DropDeadEndNode() { char str[256]; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + if (NewNodeOKHere() && gAlready_elasticating) { + gAlready_elasticating = 0; + BrVector3Copy( + &gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[gMobile_section].node_indices[1]].p, + &gSelf->t.t.translate.t); + ShowOppoPaths(); + sprintf(str, "New section #%d, finish node #%d", + gMobile_section, + gProgram_state.AI_vehicles.path_sections[gMobile_section].node_indices[1]); + NewTextHeadupSlot(4, 0, 4000, -1, str); + } } // IDA: void __cdecl DropNodeOnNodeAndStopElasticating() @@ -3705,43 +4172,82 @@ void DropNodeOnNodeAndStopElasticating() { char str[256]; br_scalar distance; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + if (gAlready_elasticating) { + node_no = FindNearestPathNode(&gSelf->t.t.translate.t, &distance); + if (gProgram_state.AI_vehicles.path_sections[gMobile_section].node_indices[0] == node_no || distance > 10.f) { + NewTextHeadupSlot(4, 0, 2000, -1, "Can't find any nodes close enough"); + } else if (gProgram_state.AI_vehicles.path_nodes[node_no].number_of_sections >= COUNT_OF(gProgram_state.AI_vehicles.path_nodes[node_no].sections)) { + sprintf(str, "Sorry, node #%d already has %d sections attached", node_no, (int)COUNT_OF(gProgram_state.AI_vehicles.path_nodes[node_no].sections)); + NewTextHeadupSlot(4, 0, 2000, -1, str); + } else { + gAlready_elasticating = 0; + gProgram_state.AI_vehicles.number_of_path_nodes -= 1; + gProgram_state.AI_vehicles.path_sections[gMobile_section].node_indices[1] = node_no; + gProgram_state.AI_vehicles.path_nodes[node_no].sections[gProgram_state.AI_vehicles.path_nodes[node_no].number_of_sections] = gMobile_section; + gProgram_state.AI_vehicles.path_nodes[node_no].number_of_sections += 1; + ShowOppoPaths(); + sprintf(str, "New section #%d, attached to existing node #%d", + gMobile_section, + gProgram_state.AI_vehicles.path_sections[gMobile_section].node_indices[1]); + NewTextHeadupSlot(4, 0, 4000, -1, str); + } + } } // IDA: void __cdecl WidenOppoPathSection() void WidenOppoPathSection() { LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + + if (gOppo_paths_shown) { + RecalcNearestPathSectionWidth(.05f); + } } // IDA: void __cdecl NarrowOppoPathSection() void NarrowOppoPathSection() { LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + if (gOppo_paths_shown) { + RecalcNearestPathSectionWidth(-.05f); + } } // IDA: void __cdecl IncreaseSectionMinSpeed() void IncreaseSectionMinSpeed() { LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + if (gOppo_paths_shown) { + RecalcNearestPathSectionSpeed(0, 1); + } } // IDA: void __cdecl DecreaseSectionMinSpeed() void DecreaseSectionMinSpeed() { LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + if (gOppo_paths_shown) { + RecalcNearestPathSectionSpeed(0, -1); + } } // IDA: void __cdecl IncreaseSectionMaxSpeed() void IncreaseSectionMaxSpeed() { LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + if (gOppo_paths_shown) { + RecalcNearestPathSectionSpeed(1, 1); + } } // IDA: void __cdecl DecreaseSectionMaxSpeed() void DecreaseSectionMaxSpeed() { LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + if (gOppo_paths_shown) { + RecalcNearestPathSectionSpeed(1, -1); + } } // IDA: void __cdecl PullOppoPoint() @@ -3749,7 +4255,21 @@ void PullOppoPoint() { tS16 node_no; br_scalar distance; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + if (gOppo_paths_shown) { + if (gAlready_elasticating) { + NewTextHeadupSlot(4, 0, 2000, -1, "Not while you're elasticating"); + } else { + node_no = FindNearestPathNode(&gSelf->t.t.translate.t, &distance); + if (distance > 10.f) { + NewTextHeadupSlot(4, 0, 2000, -1, "Can't find any paths close enough"); + } else { + BrVector3Copy(&gProgram_state.AI_vehicles.path_nodes[node_no].p, &gSelf->t.t.translate.t); + ShowOppoPaths(); + NewTextHeadupSlot(4, 0, 2000, -1, "Bing!"); + } + } + } } // IDA: void __cdecl ShowNodeInfo() @@ -3758,7 +4278,24 @@ void ShowNodeInfo() { char str[256]; br_scalar distance; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + if (!gOppo_paths_shown) { + NewTextHeadupSlot(4, 0, 2000, -1, "Show paths first (F5)"); + } else if (gAlready_elasticating) { + sprintf(str, "Next point will be #%d", + gProgram_state.AI_vehicles.path_sections[gMobile_section].node_indices[1]); + NewTextHeadupSlot(4, 0, 2000, -1, str); + } else { + node_no = FindNearestPathNode(&gSelf->t.t.translate.t, &distance); + if (distance > 10.f) { + NewTextHeadupSlot(4, 0, 2000, -1, "Can't find any nodes close enough"); + } else { + sprintf(str, "Nearest node #%d has %d attached sections", + node_no, + gProgram_state.AI_vehicles.path_nodes[node_no].number_of_sections); + NewTextHeadupSlot(4, 0, 2000, -1, str); + } + } } // IDA: void __cdecl ShowSectionInfo1() @@ -3769,7 +4306,27 @@ void ShowSectionInfo1() { br_vector3 direction_v; br_vector3 intersect; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + if (!gOppo_paths_shown) { + NewTextHeadupSlot(4, 0, 2000, -1, "Show paths first (F5)"); + } else if (gAlready_elasticating) { + sprintf(str, "This section will be #%d attached to nodes #%d and #%d", + gMobile_section, + gProgram_state.AI_vehicles.path_sections[gMobile_section].node_indices[0], + gProgram_state.AI_vehicles.path_sections[gMobile_section].node_indices[1]); + NewTextHeadupSlot(4, 0, 2000, -1, str); + } else { + section_no = FindNearestPathSection(&gSelf->t.t.translate.t, &direction_v, &intersect, &distance); + if (distance > 10.f) { + NewTextHeadupSlot(4, 0, 2000, -1, "Can't find any sections close enough"); + } else { + sprintf(str, "Nearest section #%d, start node #%d, finish node #%d", + section_no, + gProgram_state.AI_vehicles.path_sections[gMobile_section].node_indices[0], + gProgram_state.AI_vehicles.path_sections[gMobile_section].node_indices[1]); + NewTextHeadupSlot(4, 0, 2000, -1, str); + } + } } // IDA: void __cdecl ShowSectionInfo2() @@ -3780,7 +4337,29 @@ void ShowSectionInfo2() { br_vector3 direction_v; br_vector3 intersect; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + if (!gOppo_paths_shown) { + NewTextHeadupSlot(4, 0, 2000, -1, "Show paths first (F5)"); + } else if (gAlready_elasticating) { + sprintf(str, "Towards start - min %d max %d, finish - min %d, max %d mph", + (int)(2.2f * gProgram_state.AI_vehicles.path_sections[gMobile_section].min_speed[0]), + (int)(2.2f * gProgram_state.AI_vehicles.path_sections[gMobile_section].max_speed[0]), + (int)(2.2f * gProgram_state.AI_vehicles.path_sections[gMobile_section].min_speed[1]), + (int)(2.2f * gProgram_state.AI_vehicles.path_sections[gMobile_section].max_speed[1])); + NewTextHeadupSlot(4, 0, 2000, -1, str); + } else { + section_no = FindNearestPathSection(&gSelf->t.t.translate.t, &direction_v, &intersect, &distance); + if (distance > 10.f) { + NewTextHeadupSlot(4, 0, 2000, -1, "Can't find any sections close enough"); + } else { + sprintf(str, "Towards start - min %d max %d, finish - min %d, max %d mph", + (int)(2.2f * gProgram_state.AI_vehicles.path_sections[section_no].min_speed[0]), + (int)(2.2f * gProgram_state.AI_vehicles.path_sections[section_no].max_speed[0]), + (int)(2.2f * gProgram_state.AI_vehicles.path_sections[section_no].min_speed[1]), + (int)(2.2f * gProgram_state.AI_vehicles.path_sections[section_no].max_speed[1])); + NewTextHeadupSlot(4, 0, 2000, -1, str); + } + } } // IDA: void __cdecl DeleteOppoPathSection() @@ -3790,7 +4369,22 @@ void DeleteOppoPathSection() { br_vector3 direction_v; tS16 section_no; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + if (gOppo_paths_shown == 0) { + NewTextHeadupSlot(4, 0, 2000, -1, "Show paths first (F5)"); + } else if (gAlready_elasticating) { + NewTextHeadupSlot(4, 0, 2000, -1, "Not while you're creating a new section"); + } else { + section_no = FindNearestPathSection(&gSelf->t.t.translate.t, &direction_v, &intersect, &distance); + if (distance > 10.f) { + NewTextHeadupSlot(4, 0, 2000, -1, "Can't find any sections close enough"); + } else { + DeleteSection(section_no); + DeleteOrphanNodes(); + ShowOppoPaths(); + NewTextHeadupSlot(4, 0, 2000, -1, "Pop!"); + } + } } // IDA: void __cdecl DeleteOppoPathNodeAndSections() @@ -3798,7 +4392,23 @@ void DeleteOppoPathNodeAndSections() { br_scalar distance; tS16 node_no; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + if (!gOppo_paths_shown == 0) { + NewTextHeadupSlot(4, 0, 2000, -1, "Show paths first (F5)"); + } + else if (gAlready_elasticating) { + NewTextHeadupSlot(4, 0, 2000, -1, "Not while you're creating a new section"); + } else { + node_no = FindNearestPathNode(&gSelf->t.t.translate.t, &distance); + if (distance > 10.f) { + NewTextHeadupSlot(4, 0, 2000, -1, "Can't find any nodes close enough"); + } else { + DeleteNode(node_no, 1); + DeleteOrphanNodes(); + ShowOppoPaths(); + NewTextHeadupSlot(4, 0, 2000, -1, "Blam!"); + } + } } // IDA: void __cdecl DeleteOppoPathNodeAndJoin() @@ -3806,7 +4416,33 @@ void DeleteOppoPathNodeAndJoin() { br_scalar distance; tS16 node_no; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + if (!gOppo_paths_shown) { + NewTextHeadupSlot(4, 0, 2000, -1, "Show paths first (F5)"); + } else if (gAlready_elasticating) { + NewTextHeadupSlot(4, 0, 2000, -1, "Not while you're creating a new section"); + } else { + node_no = FindNearestPathNode(&gSelf->t.t.translate.t, &distance); + if (distance > 10.f) { + NewTextHeadupSlot(4, 0, 2000, -1, "Can't find any nodes close enough"); + } else if (gProgram_state.AI_vehicles.path_nodes[node_no].number_of_sections != 2) { + NewTextHeadupSlot(4, 0, 2000, -1, "Node must have exactly 2 sections attached"); + } else if ((gProgram_state.AI_vehicles.path_sections[gProgram_state.AI_vehicles.path_nodes[node_no].sections[0]].node_indices[0] == node_no + && gProgram_state.AI_vehicles.path_sections[gProgram_state.AI_vehicles.path_nodes[node_no].sections[1]].node_indices[1] == node_no) || + (gProgram_state.AI_vehicles.path_sections[gProgram_state.AI_vehicles.path_nodes[node_no].sections[1]].node_indices[0] == node_no + && gProgram_state.AI_vehicles.path_sections[gProgram_state.AI_vehicles.path_nodes[node_no].sections[0]].node_indices[1] == node_no)) { + ConsistencyCheck(); + DeleteNode(node_no,0); + ConsistencyCheck(); + DeleteOrphanNodes(); + ConsistencyCheck(); + ShowOppoPaths(); + NewTextHeadupSlot(4, 0, 2000, -1, "Blam!"); + } + else { + NewTextHeadupSlot(4, 0, 2000, -1, "Sections must point in same direction"); + } + } } // IDA: void __cdecl ReverseSectionDirection() @@ -3818,7 +4454,34 @@ void ReverseSectionDirection() { br_vector3 direction_v; tS16 section_no; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + if (!gOppo_paths_shown) { + NewTextHeadupSlot(4, 0, 2000, -1, "Show paths first (F5)"); + } else if (gAlready_elasticating) { + NewTextHeadupSlot(4, 0, 2000, -1, "Not while you're creating a new section"); + } else { + section_no = FindNearestPathSection(&gSelf->t.t.translate.t, &direction_v, &intersect, &distance); + if (distance > 10.f) { + NewTextHeadupSlot(4, 0, 2000, -1, "Can't find any sections close enough"); + } else { + temp = gProgram_state.AI_vehicles.path_sections[section_no].node_indices[0]; + gProgram_state.AI_vehicles.path_sections[section_no].node_indices[0] = + gProgram_state.AI_vehicles.path_sections[section_no].node_indices[1]; + gProgram_state.AI_vehicles.path_sections[section_no].node_indices[1] = temp; + + speed_temp = gProgram_state.AI_vehicles.path_sections[section_no].min_speed[0]; + gProgram_state.AI_vehicles.path_sections[section_no].min_speed[0] = + gProgram_state.AI_vehicles.path_sections[section_no].min_speed[1]; + gProgram_state.AI_vehicles.path_sections[section_no].min_speed[1] = speed_temp; + + speed_temp = gProgram_state.AI_vehicles.path_sections[section_no].max_speed[0]; + gProgram_state.AI_vehicles.path_sections[section_no].max_speed[0] = + gProgram_state.AI_vehicles.path_sections[section_no].max_speed[1]; + gProgram_state.AI_vehicles.path_sections[section_no].max_speed[1] = speed_temp; + + ShowOppoPaths(); + } + } } // IDA: void __cdecl CycleSectionType() @@ -3829,7 +4492,23 @@ void CycleSectionType() { tS16 section_no; char str[256]; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + if (!gOppo_paths_shown) { + NewTextHeadupSlot(4, 0, 2000, -1, "Show paths first (F5)"); + } else if (gAlready_elasticating) { + NewTextHeadupSlot(4, 0, 2000, -1, "Not while you're creating a new section"); + } else { + section_no = FindNearestPathSection(&gSelf->t.t.translate.t, &direction_v, &intersect, &distance); + if (distance > 10.f) { + NewTextHeadupSlot(4, 0, 2000, -1, "Can't find any sections close enough"); + } else { + gProgram_state.AI_vehicles.path_sections[section_no].type = + (gProgram_state.AI_vehicles.path_sections[section_no].type + 1) % 3; + sprintf(str, "%s section", gPath_section_type_names[gProgram_state.AI_vehicles.path_sections[section_no].type]); + ShowOppoPaths(); + NewTextHeadupSlot(4, 0, 2000, -1, str); + } + } } // IDA: void __cdecl ToggleOneWayNess() @@ -3839,7 +4518,30 @@ void ToggleOneWayNess() { br_vector3 direction_v; tS16 section_no; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + if (!gOppo_paths_shown) { + NewTextHeadupSlot(4, 0, 2000, -1, "Show paths first (F5)"); + } else if (gAlready_elasticating) { + NewTextHeadupSlot(4, 0, 2000, -1, "Not while you're creating a new section"); + } else { + section_no = FindNearestPathSection(&gSelf->t.t.translate.t, &direction_v, &intersect, &distance); + if (distance > 10.f) { + NewTextHeadupSlot(4, 0, 2000, -1, "Can't find any sections close enough"); + } else { + if (gProgram_state.AI_vehicles.path_sections[section_no].one_way) { + gProgram_state.AI_vehicles.path_sections[section_no].one_way = 0; + } + else { + gProgram_state.AI_vehicles.path_sections[section_no].one_way = 1; + } + ShowOppoPaths(); + if (gProgram_state.AI_vehicles.path_sections[section_no].one_way) { + NewTextHeadupSlot(4, 0, 2000, -1, "ONE-WAY"); + } else { + NewTextHeadupSlot(4, 0, 2000, -1, "TWO-WAY"); + } + } + } } // IDA: void __cdecl CopStartPointInfo() @@ -3851,14 +4553,50 @@ void CopStartPointInfo() { br_scalar distance; br_vector3 car_to_point; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + closest = -1; + closest_distance = FLT_MAX; + if (!gOppo_paths_shown) { + NewTextHeadupSlot(4, 0, 2000, -1, "Show paths first (F5)"); + } else { + for (i = 0; i < gProgram_state.AI_vehicles.number_of_cops; i++) { + BrVector3Sub(&car_to_point, &gSelf->t.t.translate.t, &gProgram_state.AI_vehicles.cop_start_points[i]); + distance = BrVector3LengthSquared(&car_to_point); + if (distance < closest_distance) { + closest = i; + closest_distance = distance; + } + } + if (closest < 0 || closest_distance > 10.f) { + NewTextHeadupSlot(4, 0, 2000, -1, "No cop start points close enough"); + } else { + sprintf(str, "Nearest cop start point #%d", closest); + NewTextHeadupSlot(4, 0, 2000, -1, str); + } + } } // IDA: void __cdecl DropCopStartPoint() void DropCopStartPoint() { char str[256]; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + if (!gOppo_paths_shown) { + NewTextHeadupSlot(4, 0, 2000, -1, "Show paths first (F5)"); + } else if (gAlready_elasticating) { + NewTextHeadupSlot(4, 0, 2000, -1, "Not while you're creating a new section"); + } else { + if (gProgram_state.AI_vehicles.number_of_cops < COUNT_OF(gProgram_state.AI_vehicles.cop_start_points)) { + BrVector3Copy(&gProgram_state.AI_vehicles.cop_start_points[gProgram_state.AI_vehicles.number_of_cops], &gSelf->t.t.translate.t); + gProgram_state.AI_vehicles.number_of_cops += 1; + ShowOppoPaths(); + sprintf(str, "New cop start point dropped (%d of %d)", gProgram_state.AI_vehicles.number_of_cops, (int)COUNT_OF(gProgram_state.AI_vehicles.cop_start_points)); + NewTextHeadupSlot(4, 0, 2000, -1, str); + } else { + sprintf(str, "Sorry, no more than %d cop start points", (int)COUNT_OF(gProgram_state.AI_vehicles.cop_start_points)); + NewTextHeadupSlot(4, 0, 2000, -1, str); + } + } } // IDA: void __cdecl DeleteCopStartPoint() @@ -3870,11 +4608,39 @@ void DeleteCopStartPoint() { br_scalar distance; br_vector3 car_to_point; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + closest = -1; + closest_distance = FLT_MAX; + if (!gOppo_paths_shown) { + NewTextHeadupSlot(4, 0, 2000, -1, "Show paths first (F5)"); + } else if (gAlready_elasticating) { + NewTextHeadupSlot(4, 0, 2000, -1, "Not while you're creating a new section"); + } else { + for (i = 0; i < gProgram_state.AI_vehicles.number_of_cops; i++) { + BrVector3Sub(&car_to_point, &gSelf->t.t.translate.t, &gProgram_state.AI_vehicles.cop_start_points[i]); + distance = BrVector3Length(&car_to_point); + if (distance < closest_distance) { + closest = i; + closest_distance = distance; + } + } + if (closest < 0 || closest_distance > 10.f) { + NewTextHeadupSlot(4, 0, 2000, -1, "No cop start points close enough"); + } else { + for (i = closest; i < gProgram_state.AI_vehicles.number_of_cops - 1; i++) { + BrVector3Copy(&gProgram_state.AI_vehicles.cop_start_points[i], + &gProgram_state.AI_vehicles.cop_start_points[i + 1]); + } + gProgram_state.AI_vehicles.number_of_cops -= 1; + ShowOppoPaths(); + sprintf(str, "Deleted cop start point #%d", closest); + NewTextHeadupSlot(4, 0, 2000, -1, str); + } + } } // IDA: void __cdecl CycleCopStartPointType() void CycleCopStartPointType() { LOG_TRACE("()"); - NOT_IMPLEMENTED(); + } diff --git a/src/DETHRACE/common/oppoproc.c b/src/DETHRACE/common/oppoproc.c index 9962f5c2..6be4715d 100644 --- a/src/DETHRACE/common/oppoproc.c +++ b/src/DETHRACE/common/oppoproc.c @@ -37,7 +37,9 @@ static void StraightestArcForCorner(float* p1, float* p2, float* p3, br_vector3* LOG_TRACE("(%p, %p, %p, %p, %p, %p, %p, %p, %f, %f)", p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); BrVector3Sub(&rel1, p6, p5); + rel1.v[1] = 0.f; BrVector3Sub(&rel3, p4, p5); + rel3.v[1] = 0.f; *p3 = BrVector3Length(&rel3); if (*p3 <= BR_SCALAR_EPSILON) { *p2 = 0.001f; @@ -202,8 +204,27 @@ tFollow_path_result ProcessFollowPath(tOpponent_spec* pOpponent_spec, tProcess_o trans_damage = car_spec->damage_units[1].damage_level; data = &pOpponent_spec->follow_path_data; car_master_actor = car_spec->car_master_actor; - if (pCommand == ePOC_run) { + if (pCommand == ePOC_start) { + data->first_section_no = GetOpponentsFirstSection(pOpponent_spec); + data->section_no = data->first_section_no; + dr_dprintf("%s: ProcessFollowPath() - new task started, first real section #%d", pOpponent_spec->car_spec->driver_name, GetOpponentsRealSection(pOpponent_spec, data->first_section_no)); + data->has_moved_during_this_task = 0; + data->struggle_time = 0; + data->last_finished_struggle_time = gTime_stamp_for_this_munging; + data->prev_acc = 0.f; + data->prev_acc_error = 0.f; + data->borrowed_time_start = gTime_stamp_for_this_munging; + data->last_struggle_section = -1; + data->made_it = 1; + data->cheating = 0; + data->cornering = 0; + if (!pOpponent_spec->cheating && !pOpponent_spec->physics_me) { + dr_dprintf("%s: Rematerialising from ePOC_start in ProcessFollowPath()...", pOpponent_spec->car_spec->driver_name); + RematerialiseOpponentOnNearestSection(pOpponent_spec, BrVector3Length(&car_spec->v)); + } + return eFPR_OK; + } else if (pCommand == ePOC_run) { if (pOpponent_spec->follow_path_data.cheating || pOpponent_spec->cheating) { return FollowCheatyPath(pOpponent_spec); } @@ -231,14 +252,14 @@ tFollow_path_result ProcessFollowPath(tOpponent_spec* pOpponent_spec, tProcess_o if (data->struggle_time) { if (data->struggle_time + 150 * (5 * data->number_of_struggles - 5) + 2750 >= gTime_stamp_for_this_munging) { if (data->struggle_time + 150 * (5 * data->number_of_struggles - 5) + 2000 >= gTime_stamp_for_this_munging) { - car_spec->brake_force = 0.0; - car_spec->acc_force = car_spec->M * -6.0; + car_spec->brake_force = 0.0f; + car_spec->acc_force = car_spec->M * -6.0f; } else { - car_spec->acc_force = 0.0; - car_spec->brake_force = car_spec->M * 15.0; + car_spec->acc_force = 0.0f; + car_spec->brake_force = car_spec->M * 15.0f; } - car_spec->curvature = 0.0; - return 0; + car_spec->curvature = 0.0f; + return eFPR_OK; } dr_dprintf("%s: done struggling. speed = %.2f m/s", pOpponent_spec->car_spec->driver_name, speed); data->made_it = 0; @@ -249,7 +270,7 @@ tFollow_path_result ProcessFollowPath(tOpponent_spec* pOpponent_spec, tProcess_o car_spec->acc_force = 0.0f; } else { if (pIgnore_end) { - stopped_speed = 0.07f; + stopped_speed = 0.06666667f; } else { stopped_speed = 0.2f; } @@ -261,8 +282,8 @@ tFollow_path_result ProcessFollowPath(tOpponent_spec* pOpponent_spec, tProcess_o data->number_of_struggles = 0; } else { if (data->number_of_struggles >= 3) { - car_spec->acc_force = 0.0; - car_spec->brake_force = 0.0; + car_spec->acc_force = 0.0f; + car_spec->brake_force = 0.0f; dr_dprintf("%s: Giving up trying to follow path 'cos we've struggled too much", pOpponent_spec->car_spec->driver_name); return eFPR_given_up; } @@ -271,7 +292,7 @@ tFollow_path_result ProcessFollowPath(tOpponent_spec* pOpponent_spec, tProcess_o } } BrVector3Sub(&car_to_end, GetOpponentsSectionFinishNodePoint(pOpponent_spec, data->section_no), &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t); - car_to_end.v[1] = 0.0; + car_to_end.v[1] = 0.0f; dist_to_end = BrVector3Length(&car_to_end) * WORLD_SCALE; dist_to_goal = dist_to_end; if (dist_to_end > 15.0f) { @@ -291,7 +312,7 @@ tFollow_path_result ProcessFollowPath(tOpponent_spec* pOpponent_spec, tProcess_o if (t + dot_a >= 0.0) { wank.v[0] = a.v[0] * t; wank.v[2] = a.v[2] * t; - wank.v[1] = 0.0; + wank.v[1] = 0.0f; BrVector3Accumulate(&car_to_end, &wank); } else { BrVector3Sub(&car_to_end, GetOpponentsSectionStartNodePoint(pOpponent_spec, data->section_no), &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t); @@ -326,46 +347,36 @@ tFollow_path_result ProcessFollowPath(tOpponent_spec* pOpponent_spec, tProcess_o } not_our_dir = (br_vector3*)&car_master_actor->t.t.mat.m[2]; - // FIXME: should be BrVector3Cross - wank.v[0] = car_master_actor->t.t.mat.m[2][2] * car_to_end.v[1] - car_master_actor->t.t.mat.m[2][1] * car_to_end.v[2]; - wank.v[1] = car_master_actor->t.t.mat.m[2][0] * car_to_end.v[2] - car_master_actor->t.t.mat.m[2][2] * car_to_end.v[0]; - wank.v[2] = car_master_actor->t.t.mat.m[2][1] * car_to_end.v[0] - car_master_actor->t.t.mat.m[2][0] * car_to_end.v[1]; - BrVector3Cross(&wank, &car_to_end, not_our_dir); radius = GetOpponentsSectionWidth(pOpponent_spec, data->section_no) * 0.5f; just_fucking_brake = 0; dot_d = BrVector3Dot(&car_to_end, not_our_dir); - if (dot_d <= 0.0f || speed <= 10.0f) { - if ((wank.v[1] <= 0.0f || dot_d <= 0.0f) && GetOpponentsSectionWidth(pOpponent_spec, data->section_no) >= wank.v[1]) { - if ((wank.v[1] >= 0.0 || dot_d <= 0.0) && -GetOpponentsSectionWidth(pOpponent_spec, data->section_no) <= wank.v[1]) { - if (wank.v[1] <= radius) { - if (-radius <= wank.v[1]) { - car_spec->curvature = 0.0f; - } else { - car_spec->curvature = -(MaxCurvatureForCarSpeed(car_spec, speed) * 0.05f); - } - data->desired_speed = 80.0f; - } else { - car_spec->curvature = MaxCurvatureForCarSpeed(car_spec, speed) * 0.05f; - data->desired_speed = 80.0f; - } - } else { - car_spec->curvature = -MaxCurvatureForCarSpeed(car_spec, speed); - data->desired_speed = 6.0f; - } - } else { - car_spec->curvature = MaxCurvatureForCarSpeed(car_spec, speed); - data->desired_speed = 6.0f; - } - } else { + if (dot_d > 0.0f && speed > 10.0f) { data->desired_speed = 6.0f; car_spec->curvature = 0.0f; just_fucking_brake = 1; + } else { + if ((wank.v[1] > 0.0f && dot_d > 0.0f) || GetOpponentsSectionWidth(pOpponent_spec, data->section_no) < wank.v[1]) { + car_spec->curvature = MaxCurvatureForCarSpeed(car_spec, speed); + data->desired_speed = 6.0f; + } else if ((wank.v[1] < 0.0f && dot_d > 0.0) || -GetOpponentsSectionWidth(pOpponent_spec, data->section_no) > wank.v[1]) { + car_spec->curvature = -MaxCurvatureForCarSpeed(car_spec, speed); + data->desired_speed = 6.0f; + } else if (wank.v[1] > radius) { + car_spec->curvature = MaxCurvatureForCarSpeed(car_spec, speed) * 0.05f; + data->desired_speed = 80.0f; + } else if (-radius > wank.v[1]) { + car_spec->curvature = -(MaxCurvatureForCarSpeed(car_spec, speed) * 0.05f); + data->desired_speed = 80.0f; + } else { + car_spec->curvature = 0.0f; + data->desired_speed = 80.0f; + } } if (just_fucking_brake) { car_spec->brake_force = car_spec->M * 15.0f; - car_spec->acc_force = 0.0; + car_spec->acc_force = 0.0f; } else { if (GetOpponentsNextSection(pOpponent_spec, data->section_no) != -1) { next_turning_radius = pOpponent_spec->car_spec->car_master_actor->t.t.translate.t.v[0] * -wank.v[2] + pOpponent_spec->car_spec->car_master_actor->t.t.translate.t.v[2] * wank.v[0]; @@ -376,20 +387,17 @@ tFollow_path_result ProcessFollowPath(tOpponent_spec* pOpponent_spec, tProcess_o if (v104 * next_turning_radius > 0.0f) { goal_width = 0.0f; speed2d = speed * speed / 24.0f + speed * 1.5f; - p = pOpponent_spec->car_spec->car_master_actor->t.t.translate.t; + BrVector3Copy(&p, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t); BrVector3Scale(&start, not_our_dir, -(next_turning_radius / v104)); BrVector3Accumulate(&start, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t); section_no = data->section_no; - for (sx = 0; GetOpponentsNextSection(pOpponent_spec, section_no) != -1; sx++) { - if (sx >= 4) { - break; - } + for (sx = 0; GetOpponentsNextSection(pOpponent_spec, section_no) != -1 && sx < 4; sx++) { BrVector3Copy(&next, GetOpponentsSectionFinishNodePoint(pOpponent_spec, GetOpponentsNextSection(pOpponent_spec, section_no))); next_width = GetOpponentsSectionWidth(pOpponent_spec, GetOpponentsNextSection(pOpponent_spec, section_no)); width = GetOpponentsSectionWidth(pOpponent_spec, data->section_no); StraightestArcForCorner(&corner_speed, &corner_speed2, &dot_a, &p, &start, &next, &p, &start, width, next_width); dot_a *= WORLD_SCALE; - goal_width = dot_a + goal_width; + goal_width += dot_a; if (goal_width > speed2d) { break; } @@ -404,27 +412,23 @@ tFollow_path_result ProcessFollowPath(tOpponent_spec* pOpponent_spec, tProcess_o if (goal_width - corner_speed2 < (speed * speed - stopping_distance) / 24.0f + desired_speed * 1.5f && data->desired_speed > desired_speed) { data->desired_speed = desired_speed; } - p = start; - start = next; + BrVector3Copy(&p, &start); + BrVector3Copy(&start, &next); section_no = GetOpponentsNextSection(pOpponent_spec, section_no); } } } effective_speed_factor = CAR_SPEC_GET_SPEED_FACTOR(car_spec); acc_factor = MAX(1.0f, effective_speed_factor); - if (engine_damage <= 50 || engine_damage >= 98) { - if (engine_damage >= 98) { - acc_factor -= 0.6f; - } - } else { + if (engine_damage > 50 && engine_damage < 98) { acc_factor -= (engine_damage - 50) * 0.0125f; + } else if (engine_damage >= 98) { + acc_factor -= 0.6f; } - if (trans_damage <= 50 || trans_damage >= 98) { - if (trans_damage >= 98) { - acc_factor -= 0.3f; - } - } else { + if (trans_damage > 50 && trans_damage < 98) { acc_factor -= (trans_damage - 50) * 0.00625f; + } else if (trans_damage >= 98) { + acc_factor -= 0.3f; } if (engine_damage >= 99 || trans_damage >= 99) { acc_factor = 0.0f; @@ -451,29 +455,10 @@ tFollow_path_result ProcessFollowPath(tOpponent_spec* pOpponent_spec, tProcess_o } } return eFPR_OK; - } else if (pCommand == ePOC_start) { - data->first_section_no = GetOpponentsFirstSection(pOpponent_spec); - data->section_no = data->first_section_no; - dr_dprintf("%s: ProcessFollowPath() - new task started, first real section #%d", pOpponent_spec->car_spec->driver_name, GetOpponentsRealSection(pOpponent_spec, data->first_section_no)); - data->has_moved_during_this_task = 0; - data->struggle_time = 0; - data->last_finished_struggle_time = gTime_stamp_for_this_munging; - data->prev_acc = 0.f; - data->prev_acc_error = 0.f; - data->borrowed_time_start = gTime_stamp_for_this_munging; - data->last_struggle_section = -1; - data->made_it = 1; - data->cheating = 0; - data->cornering = 0; - if (!pOpponent_spec->cheating && !pOpponent_spec->physics_me) { - dr_dprintf("%s: Rematerialising from ePOC_start in ProcessFollowPath()...", pOpponent_spec->car_spec->driver_name); - RematerialiseOpponentOnNearestSection(pOpponent_spec, BrVector3Length(&car_spec->v)); - } - return eFPR_OK; } BrFatal("C:\\Msdev\\Projects\\DethRace\\OPPOPROC.C", 1420, "C:\\Msdev\\Projects\\DethRace\\OPPOPROC.C line %d", 140); - return 0; + return eFPR_OK; } // IDA: tFollow_path_result __usercall FollowCheatyPath@(tOpponent_spec *pOpponent_spec@) @@ -505,14 +490,14 @@ tFollow_path_result FollowCheatyPath(tOpponent_spec* pOpponent_spec) { dr_dprintf("%s: Dematerialising", pOpponent_spec->car_spec->driver_name); BrVector3Sub(§ion_v, finish, start); BrVector3Sub(&car_to_end, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t, start); - distance_left = BrVector3Dot(§ion_v, &car_to_end) / BrVector3LengthSquared(§ion_v); - if (distance_left < 0.0f) { + t = BrVector3Dot(§ion_v, &car_to_end) / BrVector3LengthSquared(§ion_v); + if (t < 0.0f) { BrVector3Copy(&data->cheaty_intersect, start); - } else if (distance_left <= 1.0) { - BrVector3Scale(&data->cheaty_intersect, §ion_v, distance_left); - BrVector3Accumulate(&data->cheaty_intersect, start); - } else { + } else if (t > 1.f) { BrVector3Copy(&data->cheaty_intersect, finish); + } else { + BrVector3Scale(&data->cheaty_intersect, §ion_v, t); + BrVector3Accumulate(&data->cheaty_intersect, start); } BrVector3Sub(&car_to_intersect, &data->cheaty_intersect, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t); distance_to_intersect = BrVector3Length(&car_to_intersect); @@ -547,7 +532,7 @@ tFollow_path_result FollowCheatyPath(tOpponent_spec* pOpponent_spec) { } else if (section_min > 0) { desired_speed_BRU = section_min / WORLD_SCALE; } else { - desired_speed_BRU = MIN(7.0f, MAX(1.0f, distance_to_end * 2.0)); + desired_speed_BRU = MIN(7.0f, MAX(1.0f, distance_to_end * 2.0f)); } if (RematerialiseOpponentOnNearestSection(pOpponent_spec, desired_speed_BRU)) { pOpponent_spec->car_spec->brake_force = 0.0f; @@ -578,12 +563,12 @@ tFollow_path_result FollowCheatyPath(tOpponent_spec* pOpponent_spec) { BrVector3Sub(&p, finish, start); BrVector3Normalise(&p, &p); - while (frame_period_in_secs > 0.0) { + while (frame_period_in_secs > 0.0f) { BrVector3Sub(&a, finish, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t); distance_to_end = BrVector3Length(&a); if (distance_to_end < frame_period_in_secs) { BrVector3Accumulate(&pOpponent_spec->car_spec->car_master_actor->t.t.translate.t, &a); - frame_period_in_secs = frame_period_in_secs - distance_to_end; + frame_period_in_secs -= distance_to_end; dr_dprintf("%s: ProcessFollowPath() - current section %d(#%d) (cheating)", pOpponent_spec->car_spec->driver_name, data->section_no, GetOpponentsRealSection(pOpponent_spec, data->section_no)); data->section_no = GetOpponentsNextSection(pOpponent_spec, data->section_no); if (data->section_no == -1) { diff --git a/src/DETHRACE/pd/sys.h b/src/DETHRACE/pd/sys.h index 72dae641..4a06bdc4 100644 --- a/src/DETHRACE/pd/sys.h +++ b/src/DETHRACE/pd/sys.h @@ -146,7 +146,7 @@ int PDGetGorePassword(void); void PDDisplayGoreworthiness(int pGory); -void PDEnterDebugger(char* pStr); +HARNESS_NORETURN void PDEnterDebugger(char* pStr); // Added function br_material* PDMissingMaterial(char* name); diff --git a/src/harness/io_platforms/sdl_gl.c b/src/harness/io_platforms/sdl_gl.c index 6df03925..39410ae1 100644 --- a/src/harness/io_platforms/sdl_gl.c +++ b/src/harness/io_platforms/sdl_gl.c @@ -169,7 +169,7 @@ tRenderer* Window_Create(char* title, int width, int height, int pRender_width, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); if (window == NULL) { - LOG_PANIC("Failed to create window"); + LOG_PANIC("Failed to create window. %s", SDL_GetError()); } sdl_window_scale.x = ((float)pRender_width) / width;