diff --git a/src/DETHRACE/CMakeLists.txt b/src/DETHRACE/CMakeLists.txt index cc85d166..4961e5e0 100644 --- a/src/DETHRACE/CMakeLists.txt +++ b/src/DETHRACE/CMakeLists.txt @@ -61,8 +61,6 @@ endif() target_sources(dethrace_obj PRIVATE common/skidmark.c - common/opponent.c - common/brucetrk.c common/brucetrk.h common/car.c @@ -129,7 +127,7 @@ target_sources(dethrace_obj PRIVATE common/oil.h common/oppocar.c common/oppocar.h - + common/opponent.c common/opponent.h common/oppoproc.c common/oppoproc.h @@ -192,15 +190,14 @@ endif() if(MSVC_42_FOR_RECCMP) add_executable(dethrace WIN32) set(CMAKE_C_FLAGS_DEBUG "/Od /Oi /Zi /MLd /G5") - - add_compile_definitions(_DEBUG) set_target_properties(dethrace PROPERTIES OUTPUT_NAME "CARM95") target_link_options(dethrace PRIVATE /INCREMENTAL:NO /subsystem:windows /ENTRY:mainCRTStartup) set_source_files_properties(common/skidmark.c PROPERTIES COMPILE_FLAGS "/FAs") # set_source_files_properties(common/brucetrk.c PROPERTIES COMPILE_FLAGS "/G5") - set_source_files_properties(common/opponent.c PROPERTIES COMPILE_FLAGS "/FAs /G5") + + # set_source_files_properties(common/car.c PROPERTIES COMPILE_FLAGS "/GB") reccmp_add_target(dethrace ID CARM95) reccmp_configure() else() diff --git a/src/DETHRACE/common/loading.c b/src/DETHRACE/common/loading.c index 84a08781..cfbef261 100644 --- a/src/DETHRACE/common/loading.c +++ b/src/DETHRACE/common/loading.c @@ -1375,17 +1375,17 @@ void ReadNonCarMechanicsData(FILE* pF, tNon_car_spec* non_car) { c = &non_car->collision_info; c->driver = 0; c->index = GetAnInt(pF); - ReadThreeFloats(pF, non_car->free_cmpos.v[0], non_car->free_cmpos.v[1], non_car->free_cmpos.v[2]); - ReadThreeFloats(pF, non_car->attached_cmpos.v[0], non_car->attached_cmpos.v[1], non_car->attached_cmpos.v[2]); - ReadThreeFloats(pF, c->bounds[1].min.v[0], c->bounds[1].min.v[1], c->bounds[1].min.v[2]); - ReadThreeFloats(pF, c->bounds[1].max.v[0], c->bounds[1].max.v[1], c->bounds[1].max.v[2]); + ReadVector3(pF, non_car->free_cmpos.v[0], non_car->free_cmpos.v[1], non_car->free_cmpos.v[2]); + ReadVector3(pF, non_car->attached_cmpos.v[0], non_car->attached_cmpos.v[1], non_car->attached_cmpos.v[2]); + ReadVector3(pF, c->bounds[1].min.v[0], c->bounds[1].min.v[1], c->bounds[1].min.v[2]); + ReadVector3(pF, c->bounds[1].max.v[0], c->bounds[1].max.v[1], c->bounds[1].max.v[2]); c->extra_point_num = GetAnInt(pF); if (c->extra_point_num > 6) { sprintf(s, "%d", c->index); FatalError(kFatalError_TooManyExtraPointsForCar_S, s); } for (i = 0; c->extra_point_num > i; ++i) { - ReadThreeFloats(pF, c->extra_points[i].v[0], c->extra_points[i].v[1], c->extra_points[i].v[2]); + ReadVector3(pF, c->extra_points[i].v[0], c->extra_points[i].v[1], c->extra_points[i].v[2]); } ReadPairOfFloats(pF, non_car->free_mass, non_car->attached_mass); @@ -1423,14 +1423,14 @@ void ReadNonCarMechanicsData(FILE* pF, tNon_car_spec* non_car) { non_car->I_over_M.v[1] = ts1 / 12.0f; ts1 = BR_SQR2(het, len); non_car->I_over_M.v[0] = ts1 / 12.0f; - BrVector3Scale(&non_car->free_cmpos, &non_car->free_cmpos, WORLD_SCALE); - BrVector3Scale(&non_car->attached_cmpos, &non_car->attached_cmpos, WORLD_SCALE); - BrVector3Scale(&non_car->I_over_M, &non_car->I_over_M, 47.61000061035156f); - BrVector3Scale(&c->bounds[1].min, &c->bounds[1].min, WORLD_SCALE); - BrVector3Scale(&c->bounds[1].max, &c->bounds[1].max, WORLD_SCALE); + DRVector3Scale(&non_car->free_cmpos, &non_car->free_cmpos, WORLD_SCALE); + DRVector3Scale(&non_car->attached_cmpos, &non_car->attached_cmpos, WORLD_SCALE); + DRVector3Scale(&non_car->I_over_M, &non_car->I_over_M, 47.61000061035156f); + DRVector3Scale(&c->bounds[1].min, &c->bounds[1].min, WORLD_SCALE); + DRVector3Scale(&c->bounds[1].max, &c->bounds[1].max, WORLD_SCALE); for (i = 0; c->extra_point_num > i; ++i) { - BrVector3Scale(&c->extra_points[i], &c->extra_points[i], WORLD_SCALE); + DRVector3Scale(&c->extra_points[i], &c->extra_points[i], WORLD_SCALE); } memcpy(&c->max_bounds[0], &c->bounds[0], sizeof(c->max_bounds[0])); memcpy(&c->max_bounds[1], &c->bounds[1], sizeof(c->max_bounds[0])); diff --git a/src/DETHRACE/common/opponent.c b/src/DETHRACE/common/opponent.c index 78397a14..13069eeb 100644 --- a/src/DETHRACE/common/opponent.c +++ b/src/DETHRACE/common/opponent.c @@ -110,11 +110,7 @@ tU32 gNext_elastication; // GLOBAL: CARM95 0x00507150 tU32 gNext_write_during_elastication; - -// GLOBAL: CARM95 0x00507154 char* gCop_name = "Faceless Cop"; - -// GLOBAL: CARM95 0x00507158 char* gDrone_name = "Innocent Civilian"; // GLOBAL: CARM95 0x0050715c @@ -219,10 +215,9 @@ void PointActorAlongThisBloodyVector(br_actor* pThe_actor, br_vector3* pThe_vect br_transform trans; trans.type = BR_TRANSFORM_LOOK_UP; - BrVector3Copy(&trans.t.look_up.t, &pThe_actor->t.t.translate.t); BrVector3Copy(&trans.t.look_up.look, pThe_vector); BrVector3Set(&trans.t.look_up.up, 0.f, 1.f, 0.f); - + BrVector3Copy(&trans.t.look_up.t, &pThe_actor->t.t.translate.t); BrTransformToTransform(&pThe_actor->t, &trans); } @@ -247,6 +242,7 @@ void ProcessCurrentObjective(tOpponent_spec* pOpponent_spec, tProcess_objective_ ProcessLevitate(pOpponent_spec, pCommand); break; case eOOT_knackered_and_freewheeling: + // FIXME: is keys correct? memset(&pOpponent_spec->car_spec->keys, 0, sizeof(pOpponent_spec->car_spec->keys)); pOpponent_spec->car_spec->acc_force = 0.f; pOpponent_spec->car_spec->brake_force = 0.f; @@ -258,6 +254,8 @@ void ProcessCurrentObjective(tOpponent_spec* pOpponent_spec, tProcess_objective_ case eOOT_wait_for_some_hapless_sod: ProcessWaitForSomeHaplessSod(pOpponent_spec, pCommand); break; + case eOOT_rematerialise: + break; case eOOT_return_to_start: ProcessReturnToStart(pOpponent_spec, pCommand); break; @@ -344,11 +342,9 @@ tS16 FindNearestPathNode(br_vector3* pActor_coords, br_scalar* pDistance) { 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) { - if (!gAlready_elasticating || gProgram_state.AI_vehicles.path_sections[gMobile_section].node_indices[1] != i) { - *pDistance = distance; - nearest_node = i; - } + 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; @@ -384,10 +380,10 @@ tS16 FindNearestGeneralSection(tCar_spec* pPursuee, br_vector3* pActor_coords, b br_vector3 zero_vector; #endif - nearest_node_section_no = -1; nearest_section = -1; - nearest_node_distance_squared = BR_SCALAR_MAX; + nearest_node_section_no = -1; closest_distance_squared = BR_SCALAR_MAX; + nearest_node_distance_squared = BR_SCALAR_MAX; #if defined(DETHRACE_FIX_BUGS) BrVector3Set(&zero_vector, 0.f, 0.f, 0.f); nearest_node_v = &zero_vector; @@ -410,57 +406,57 @@ tS16 FindNearestGeneralSection(tCar_spec* pPursuee, br_vector3* pActor_coords, b if (!gAlready_elasticating || gMobile_section != section_no) { BrVector3Sub(&a, finish, start); BrVector3Sub(&p, pActor_coords, start); - BrVector3Sub(&wank, &p, &a); - the_distance_squared = BrVector3LengthSquared(&wank); - if (the_distance_squared < nearest_node_distance_squared) { - nearest_node_distance_squared = the_distance_squared; - nearest_node_section_no = section_no; + the_distance_squared = Vector3DistanceSquared(&p, &a); + if (the_distance_squared < closest_distance_squared) { + closest_distance_squared = the_distance_squared; + nearest_section = section_no; nearest_node_v = finish; } the_distance_squared = BrVector3LengthSquared(&p); - if (the_distance_squared < nearest_node_distance_squared) { - nearest_node_distance_squared = the_distance_squared; - nearest_node_section_no = section_no; + if (the_distance_squared < closest_distance_squared) { + closest_distance_squared = the_distance_squared; + nearest_section = section_no; nearest_node_v = start; } length_squared_a = BrVector3LengthSquared(&a); - if (length_squared_a < 0.0001f) { - continue; - } - t = BrVector3Dot(&p, &a) / length_squared_a; - if (t >= 0 && t <= 1.f) { - BrVector3Scale(&intersect, &a, t); - BrVector3Sub(&wank, &p, &intersect); - the_distance_squared = BrVector3LengthSquared(&wank); - if (the_distance_squared < closest_distance_squared) { - closest_distance_squared = the_distance_squared; - nearest_section = section_no; - BrVector3Add(pIntersect, start, &intersect); - BrVector3NormaliseQuick(pPath_direction, &a); + if (length_squared_a >= 0.0001f) { + t = BrVector3Dot(&p, &a) / length_squared_a; + if (t >= 0 && t <= 1.f) { + p.v[0] -= t * a.v[0]; + p.v[1] -= t * a.v[1]; + p.v[2] -= t * a.v[2]; + the_distance_squared = BrVector3LengthSquared(&p); + if (the_distance_squared < nearest_node_distance_squared) { + BrVector3Scale(&intersect, &a, t); + BrVector3Add(pIntersect, start, &intersect); + BrVector3NormaliseQuick(pPath_direction, &a); + nearest_node_distance_squared = the_distance_squared; + nearest_node_section_no = section_no; + } } } } } - if (closest_distance_squared > nearest_node_distance_squared) { - nearest_section = nearest_node_section_no; + if (nearest_node_distance_squared > closest_distance_squared) { + nearest_node_section_no = nearest_section; if (pPursuee != NULL) { - start = &pPursuee->my_trail.trail_nodes[nearest_node_section_no]; - finish = &pPursuee->my_trail.trail_nodes[nearest_node_section_no + 1]; + start = &pPursuee->my_trail.trail_nodes[nearest_section]; + finish = &pPursuee->my_trail.trail_nodes[nearest_section + 1]; } else { - start = &gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[nearest_node_section_no].node_indices[0]].p; - finish = &gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[nearest_node_section_no].node_indices[1]].p; + start = &gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[nearest_section].node_indices[0]].p; + finish = &gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[nearest_section].node_indices[1]].p; } - BrVector3Sub(&a, finish, start); - BrVector3NormaliseQuick(pPath_direction, &a); + BrVector3Sub(&p, finish, start); + BrVector3NormaliseQuick(pPath_direction, &p); BrVector3Copy(pIntersect, nearest_node_v); - *pDistance = sqrt(nearest_node_distance_squared); - } else { *pDistance = sqrt(closest_distance_squared); + } else { + *pDistance = sqrt(nearest_node_distance_squared); } if (pPursuee != NULL) { - nearest_section += 15000; + nearest_node_section_no += 15000; } - return nearest_section; + return nearest_node_section_no; } // IDA: void __usercall DeadStopCar(tCar_spec *pCar_spec@) @@ -511,25 +507,23 @@ void NewObjective(tOpponent_spec* pOpponent_spec, tOpponent_objective_type pObje if (pObjective_type == eOOT_pursue_and_twat) { pOpponent_spec->time_for_this_objective_to_finish += 90000; } - va_start(marker, pObjective_type); switch (pObjective_type) { case eOOT_complete_race: gNum_of_opponents_completing_race++; break; + case eOOT_pursue_and_twat: + va_start(marker, pObjective_type); + pOpponent_spec->pursue_car_data.pursuee = va_arg(marker, tCar_spec*); + va_end(marker); + break; case eOOT_get_near_player: gNum_of_opponents_getting_near++; break; - case eOOT_pursue_and_twat: - pOpponent_spec->pursue_car_data.pursuee = va_arg(marker, tCar_spec*); - gNum_of_opponents_pursuing++; - break; - default: break; } dr_dprintf("%s: NewObjective() - type %d", pOpponent_spec->car_spec->driver_name, pObjective_type); ProcessCurrentObjective(pOpponent_spec, ePOC_start); - va_end(marker); } // IDA: void __usercall CalcRaceRoute(tOpponent_spec *pOpponent_spec@) @@ -571,8 +565,8 @@ void CalcRaceRoute(tOpponent_spec* pOpponent_spec) { race_section_count = 0; normal_section_ok_direction_count = 0; normal_section_wrong_direction_count = 0; - for (section_no_index = 0; section_no_index < gProgram_state.AI_vehicles.path_nodes[node_no].number_of_sections; section_no_index++) { - section_no = gProgram_state.AI_vehicles.path_nodes[node_no].sections[section_no_index]; + for (i = 0; i < gProgram_state.AI_vehicles.path_nodes[node_no].number_of_sections; i++) { + section_no = gProgram_state.AI_vehicles.path_nodes[node_no].sections[i]; if (pOpponent_spec->next_sections[pOpponent_spec->nnext_sections - 1].section_no != section_no) { if (gProgram_state.AI_vehicles.path_sections[section_no].type == 1 && gProgram_state.AI_vehicles.path_sections[section_no].node_indices[0] == node_no) { pOpponent_spec->complete_race_data.found_race_section = 1; @@ -592,7 +586,7 @@ void CalcRaceRoute(tOpponent_spec* pOpponent_spec) { } else if (normal_section_ok_direction_count != 0) { AddToOpponentsProjectedRoute(pOpponent_spec, temp_section_array[IRandomBetween(0, normal_section_ok_direction_count - 1)], 1); } else if (normal_section_wrong_direction_count != 0) { - AddToOpponentsProjectedRoute(pOpponent_spec, temp_section_array[IRandomBetween(0, normal_section_wrong_direction_count - 1)], 0); + AddToOpponentsProjectedRoute(pOpponent_spec, temp_section_array[IRandomBetween(0, normal_section_wrong_direction_count - 1)], 1); } else if (pOpponent_spec->complete_race_data.found_race_section) { pOpponent_spec->complete_race_data.finished_calcing_race_route = 1; } else { @@ -615,14 +609,17 @@ void TopUpRandomRoute(tOpponent_spec* pOpponent_spec, int pSections_to_add) { if (!pSections_to_add) { PDEnterDebugger("TopUpRandomRoute() called with no seed (woof, bark, etc.)"); } - if (pSections_to_add < 0) { - target = 10; - } else { + if (pSections_to_add >= 0) { target = MIN(pSections_to_add + pOpponent_spec->nnext_sections, 10); + } else { + target = 10; } while (pOpponent_spec->nnext_sections < target) { node_no = gProgram_state.AI_vehicles.path_sections[pOpponent_spec->next_sections[pOpponent_spec->nnext_sections - 1].section_no].node_indices[pOpponent_spec->next_sections[pOpponent_spec->nnext_sections - 1].direction]; - if (gProgram_state.AI_vehicles.path_nodes[node_no].number_of_sections > 1) { + if (gProgram_state.AI_vehicles.path_nodes[node_no].number_of_sections <= 1) { + section_no = pOpponent_spec->next_sections[pOpponent_spec->nnext_sections - 1].section_no; + direction = pOpponent_spec->next_sections[pOpponent_spec->nnext_sections - 1].direction == 0; + } else { num_of_temp_sections = 0; for (i = 0; i < gProgram_state.AI_vehicles.path_nodes[node_no].number_of_sections; i++) { section_no = gProgram_state.AI_vehicles.path_nodes[node_no].sections[i]; @@ -634,19 +631,16 @@ void TopUpRandomRoute(tOpponent_spec* pOpponent_spec, int pSections_to_add) { } } - if (num_of_temp_sections > 1) { - section_no = temp_section_array[IRandomBetween(0, num_of_temp_sections - 1)]; - direction = gProgram_state.AI_vehicles.path_sections[section_no].node_indices[1] != node_no; - } else if (num_of_temp_sections == 1) { - section_no = temp_section_array[0]; - direction = gProgram_state.AI_vehicles.path_sections[section_no].node_indices[1] != node_no; - } else { + if (num_of_temp_sections == 0) { section_no = pOpponent_spec->next_sections[pOpponent_spec->nnext_sections - 1].section_no; direction = pOpponent_spec->next_sections[pOpponent_spec->nnext_sections - 1].direction == 0; + } else if (num_of_temp_sections == 1) { + section_no = temp_section_array[0]; + direction = gProgram_state.AI_vehicles.path_sections[temp_section_array[0]].node_indices[1] != node_no; + } else { + section_no = temp_section_array[IRandomBetween(0, num_of_temp_sections - 1)]; + direction = gProgram_state.AI_vehicles.path_sections[section_no].node_indices[1] != node_no; } - } else { - section_no = pOpponent_spec->next_sections[pOpponent_spec->nnext_sections - 1].section_no; - direction = pOpponent_spec->next_sections[pOpponent_spec->nnext_sections - 1].direction == 0; } AddToOpponentsProjectedRoute(pOpponent_spec, section_no, direction); } @@ -667,6 +661,9 @@ int SearchForSection(tRoute_section* pTemp_store, tRoute_section* pPerm_store, i tS16 section_no_index; br_scalar distance_so_far; + // added by dethrace for readability (?) + tS16 section_no_dir_index; + gSFS_cycles_this_time++; if (pDepth == 1) { memset(gBit_per_node, 0, (gProgram_state.AI_vehicles.number_of_path_nodes + 7) / 8); @@ -684,36 +681,41 @@ int SearchForSection(tRoute_section* pTemp_store, tRoute_section* pPerm_store, i section_no = node_ptr->sections[section_no_index]; direction = gProgram_state.AI_vehicles.path_sections[section_no].node_indices[1] != node_no; + section_no_dir_index = gProgram_state.AI_vehicles.path_sections[section_no].node_indices[direction]; - if ((gBit_per_node[gProgram_state.AI_vehicles.path_sections[section_no].node_indices[direction] / 8] & (1 << (gProgram_state.AI_vehicles.path_sections[section_no].node_indices[direction] % 8))) != 0) { - continue; - } - if ((gProgram_state.AI_vehicles.path_sections[section_no].one_way && gProgram_state.AI_vehicles.path_sections[section_no].node_indices[1] == node_no)) { - continue; - } - if (!pOpponent_spec->cheating && gProgram_state.AI_vehicles.path_sections[section_no].type == ePST_cheat_only) { - continue; - } + // int b = BYTE4(v8); + // int y = (int)(((BYTE4(v8) ^ (((BYTE4(v8) ^ v8) - BYTE4(v8)) & 7)) - BYTE4(v8))); + // int val = valx(v8); + // LOG_DEBUG("val %d, b %d, y %d", val, b, y); + // int x = ((BYTE4(v8) ^ (((BYTE4(v8) ^ v8) - BYTE4(v8)) & 7)) - BYTE4(v8)); + // int x2 = v8 & 7; + // if (x != x2 || val != x) { + // TELL_ME_IF_WE_PASS_THIS_WAY(); + // } + if ((gBit_per_node[section_no_dir_index / 8] & (1 << (section_no_dir_index & 7))) == 0 + && (!gProgram_state.AI_vehicles.path_sections[section_no].one_way || direction) + && (pOpponent_spec->cheating || gProgram_state.AI_vehicles.path_sections[section_no].type != ePST_cheat_only)) { - pTemp_store[pDepth].section_no = section_no; - pTemp_store[pDepth].direction = direction; - distance_so_far = gProgram_state.AI_vehicles.path_sections[section_no].length + pDistance_so_far; - if (pTarget_section == section_no && distance_so_far <= shortest_dist) { - shortest_dist = distance_so_far; - *pNum_of_perm_store_sections = pDepth + 1; - memcpy(pPerm_store, pTemp_store, sizeof(tRoute_section) * *pNum_of_perm_store_sections); + pTemp_store[pDepth].section_no = section_no; + pTemp_store[pDepth].direction = direction; + distance_so_far = gProgram_state.AI_vehicles.path_sections[section_no].length + pDistance_so_far; - gWanky_arse_tit_fuck = routes_found + 1; - routes_found++; - if (routes_found >= 2) { - return 1; - } else { - gBit_per_node[node_no / 8] &= ~(1 << (node_no % 8)); - return 0; + if (pTarget_section == section_no && distance_so_far < shortest_dist) { + shortest_dist = distance_so_far; + *pNum_of_perm_store_sections = pDepth + 1; + memcpy(pPerm_store, pTemp_store, sizeof(tRoute_section) * *pNum_of_perm_store_sections); + // dword_530DD4 = ++routes_found + routes_found++; + if (routes_found >= 2) { + return 1; + } + break; + } + + if (pDepth < 9 + && SearchForSection(pTemp_store, pPerm_store, pNum_of_perm_store_sections, pTarget_section, pDepth + 1, distance_so_far, pOpponent_spec)) { + return 1; } - } - if (pDepth < 9 && SearchForSection(pTemp_store, pPerm_store, pNum_of_perm_store_sections, pTarget_section, pDepth + 1, distance_so_far, pOpponent_spec)) { - return 1; } } gBit_per_node[node_no / 8] &= ~(1 << (node_no % 8)); @@ -767,28 +769,27 @@ void CalcGetNearPlayerRoute(tOpponent_spec* pOpponent_spec, tCar_spec* pPlayer) TopUpRandomRoute(pOpponent_spec, 1); } while (pOpponent_spec->nnext_sections < 6 && !fuck_it) { - temp_store[0].section_no = pOpponent_spec->next_sections[pOpponent_spec->nnext_sections - 1].section_no; - temp_store[0].direction = pOpponent_spec->next_sections[pOpponent_spec->nnext_sections - 1].direction; + temp_store[0] = pOpponent_spec->next_sections[pOpponent_spec->nnext_sections - 1]; dr_dprintf("%s: CalcGetNearPlayerRoute() - In loop; our section #%d, player's section #%d", pOpponent_spec->car_spec->driver_name, temp_store[0].section_no, players_section); gSFS_count++; gSFS_cycles_this_time = 0; SearchForSection(temp_store, perm_store, &num_of_perm_store_sections, players_section, 1, 0.f, pOpponent_spec); gSFS_total_cycles += gSFS_cycles_this_time; - if (gSFS_cycles_this_time > gSFS_max_cycles) { + if (gSFS_max_cycles < gSFS_cycles_this_time) { gSFS_max_cycles = gSFS_cycles_this_time; } - dr_dprintf(">>>SearchForSection() - max %d, avg %.1f", gSFS_max_cycles, (float)gSFS_total_cycles / gSFS_count); - if (num_of_perm_store_sections > 1) { - sections_to_copy = MIN(COUNT_OF(pOpponent_spec->next_sections) - pOpponent_spec->nnext_sections, num_of_perm_store_sections - 1); - memcpy(&pOpponent_spec->next_sections[pOpponent_spec->nnext_sections], &perm_store[1], sizeof(tRoute_section) * sections_to_copy); - pOpponent_spec->nnext_sections += sections_to_copy; - TopUpRandomRoute(pOpponent_spec, 1); - } else { + dr_dprintf(">>>SearchForSection() - max %d, avg %.1f", gSFS_max_cycles, gSFS_total_cycles / (float)gSFS_count); + if (num_of_perm_store_sections <= 1) { dr_dprintf("%s: CalcGetNearPlayerRoute() - SearchForSection() produced bugger all", pOpponent_spec->car_spec->driver_name); fuck_it = 1; if (pOpponent_spec->nnext_sections <= 4) { TopUpRandomRoute(pOpponent_spec, 4 - pOpponent_spec->nnext_sections + 4); } + } else { + sections_to_copy = MIN(COUNT_OF(pOpponent_spec->next_sections) - pOpponent_spec->nnext_sections, num_of_perm_store_sections - 1); + memcpy(&pOpponent_spec->next_sections[pOpponent_spec->nnext_sections], &perm_store[1], sizeof(tRoute_section) * sections_to_copy); + pOpponent_spec->nnext_sections += sections_to_copy; + TopUpRandomRoute(pOpponent_spec, 1); } } } @@ -810,31 +811,34 @@ void CalcReturnToStartPointRoute(tOpponent_spec* pOpponent_spec) { ClearOpponentsProjectedRoute(pOpponent_spec); section_no = FindNearestPathSection(&pOpponent_spec->car_spec->car_master_actor->t.t.translate.t, §ion_v, &intersect, &distance); + distance = BrVector3Length(§ion_v); BrVector3Normalise(§ion_v, §ion_v); - if (BrVector3Dot(&pOpponent_spec->car_spec->direction, §ion_v) > 0.0f) { - AddToOpponentsProjectedRoute(pOpponent_spec, section_no, 1); - } else { + if (BrVector3Dot(&pOpponent_spec->car_spec->direction, §ion_v) <= 0.0f) { AddToOpponentsProjectedRoute(pOpponent_spec, section_no, 0); + } else { + AddToOpponentsProjectedRoute(pOpponent_spec, section_no, 1); } - temp_store[0].section_no = pOpponent_spec->next_sections[pOpponent_spec->nnext_sections - 1].section_no; - temp_store[0].direction = pOpponent_spec->next_sections[pOpponent_spec->nnext_sections - 1].direction; + temp_store[0] = pOpponent_spec->next_sections[pOpponent_spec->nnext_sections - 1]; gSFS_count++; gSFS_cycles_this_time = 0; SearchForSection(temp_store, perm_store, &num_of_perm_store_sections, pOpponent_spec->return_to_start_data.section_no, 1, 0.0f, pOpponent_spec); gSFS_total_cycles += gSFS_cycles_this_time; - if (gSFS_cycles_this_time > gSFS_max_cycles) { + if (gSFS_max_cycles < gSFS_cycles_this_time) { gSFS_max_cycles = gSFS_cycles_this_time; } - if (num_of_perm_store_sections > 1) { - sections_to_copy = MIN(num_of_perm_store_sections - 1, 10 - pOpponent_spec->nnext_sections); - memcpy(&pOpponent_spec->next_sections[pOpponent_spec->nnext_sections], &perm_store[1], sizeof(tRoute_section) * sections_to_copy); - pOpponent_spec->nnext_sections += sections_to_copy; - TopUpRandomRoute(pOpponent_spec, 1); - } else { + if (num_of_perm_store_sections <= 1) { if (pOpponent_spec->nnext_sections <= 6) { TopUpRandomRoute(pOpponent_spec, 4 - pOpponent_spec->nnext_sections + 4); } + } else { + sections_to_copy = 10 - pOpponent_spec->nnext_sections; + if (sections_to_copy >= num_of_perm_store_sections - 1) { + sections_to_copy = num_of_perm_store_sections - 1; + } + memcpy(&pOpponent_spec->next_sections[pOpponent_spec->nnext_sections], &perm_store[1], sizeof(tRoute_section) * sections_to_copy); + pOpponent_spec->nnext_sections += sections_to_copy; + TopUpRandomRoute(pOpponent_spec, 1); } } @@ -849,14 +853,13 @@ void ClearOpponentsProjectedRoute(tOpponent_spec* pOpponent_spec) { // FUNCTION: CARM95 0x004030ef int AddToOpponentsProjectedRoute(tOpponent_spec* pOpponent_spec, tS16 pSection_no, int pDirection) { - if (pOpponent_spec->nnext_sections < COUNT_OF(pOpponent_spec->next_sections)) { - pOpponent_spec->next_sections[pOpponent_spec->nnext_sections].section_no = pSection_no; - pOpponent_spec->next_sections[pOpponent_spec->nnext_sections].direction = pDirection; - pOpponent_spec->nnext_sections++; - return 1; - } else { + if (pOpponent_spec->nnext_sections >= COUNT_OF(pOpponent_spec->next_sections)) { return 0; } + pOpponent_spec->next_sections[pOpponent_spec->nnext_sections].section_no = pSection_no; + pOpponent_spec->next_sections[pOpponent_spec->nnext_sections].direction = pDirection; + pOpponent_spec->nnext_sections++; + return 1; } // IDA: int __usercall ShiftOpponentsProjectedRoute@(tOpponent_spec *pOpponent_spec@, int pPlaces@) @@ -864,16 +867,15 @@ int AddToOpponentsProjectedRoute(tOpponent_spec* pOpponent_spec, tS16 pSection_n int ShiftOpponentsProjectedRoute(tOpponent_spec* pOpponent_spec, int pPlaces) { int i; - if (pOpponent_spec->nnext_sections > pPlaces) { - for (i = 0; i < COUNT_OF(pOpponent_spec->next_sections) - pPlaces; i++) { - pOpponent_spec->next_sections[i].section_no = pOpponent_spec->next_sections[pPlaces + i].section_no; - pOpponent_spec->next_sections[i].direction = pOpponent_spec->next_sections[pPlaces + i].direction; - } - pOpponent_spec->nnext_sections -= pPlaces; - return 1; - } else { + if (pOpponent_spec->nnext_sections <= pPlaces) { return 0; } + for (i = 0; i < COUNT_OF(pOpponent_spec->next_sections) - pPlaces; i++) { + pOpponent_spec->next_sections[i].section_no = pOpponent_spec->next_sections[pPlaces + i].section_no; + pOpponent_spec->next_sections[i].direction = pOpponent_spec->next_sections[pPlaces + i].direction; + } + pOpponent_spec->nnext_sections -= pPlaces; + return 1; } // IDA: void __usercall StunTheBugger(tOpponent_spec *pOpponent_spec@, int pMilliseconds@) @@ -902,15 +904,6 @@ void ProcessCompleteRace(tOpponent_spec* pOpponent_spec, tProcess_objective_comm int res; char str[256]; - initial_pos = &gProgram_state.initial_position; - car_actor = pOpponent_spec->car_spec->car_master_actor; - data = &pOpponent_spec->complete_race_data; - -#ifdef DETHRACE_FIX_BUGS - // fix use uninitialized error - res = eFPR_OK; -#endif - switch (pCommand) { case ePOC_start: dr_dprintf("%s: ProcessCompleteRace() - new objective started", pOpponent_spec->car_spec->driver_name); @@ -923,13 +916,11 @@ void ProcessCompleteRace(tOpponent_spec* pOpponent_spec, tProcess_objective_comm ShiftOpponentsProjectedRoute(pOpponent_spec, pOpponent_spec->follow_path_data.section_no - 20000); pOpponent_spec->follow_path_data.section_no = 20000; } - - if (pOpponent_spec->nnext_sections == 0 - || (res = ProcessFollowPath(pOpponent_spec, ePOC_run, 0, 0, 0)) == eFPR_end_of_path) { + res = ProcessFollowPath(pOpponent_spec, ePOC_run, 0, 0, 0); + if (pOpponent_spec->nnext_sections == 0 || res == eFPR_end_of_path) { dr_dprintf("%s: Giving up following race path because ran out of race path", pOpponent_spec->car_spec->driver_name); NewObjective(pOpponent_spec, eOOT_get_near_player); } - if (res != eFPR_OK) { if (res == eFPR_given_up) { dr_dprintf("%s: Giving up complete_race because ProcessFollowPath() gave up", pOpponent_spec->car_spec->driver_name); @@ -942,15 +933,12 @@ void ProcessCompleteRace(tOpponent_spec* pOpponent_spec, tProcess_objective_comm dr_dprintf("%s: Time to give up complete_race. Might be back in a sec, though!", pOpponent_spec->car_spec->driver_name); ObjectiveComplete(pOpponent_spec); } - if (pOpponent_spec->nnext_sections <= 4 && !data->finished_calcing_race_route) { + if (pOpponent_spec->nnext_sections < 5 && !pOpponent_spec->complete_race_data.finished_calcing_race_route) { CalcRaceRoute(pOpponent_spec); } break; - -#ifdef DETHRACE_FIX_BUGS default: break; -#endif } } @@ -990,42 +978,41 @@ void RecordNextTrailNode(tCar_spec* pPursuee) { int visible; trail = &pPursuee->my_trail; - visible = 1; - trail->nodes_shifted_this_frame = 0; - if (trail->time_of_next_recording < gTime_stamp_for_this_munging) { - - trail->time_of_next_recording = gTime_stamp_for_this_munging + 500; - if (BrVector3Dot(&pPursuee->direction, &trail->base_heading) < FastScalarCos(30)) { - trail->has_deviated_recently = 1; - } - BrVector3Sub(&car_to_last_point_v, &trail->trail_nodes[trail->number_of_nodes - 2], &pPursuee->car_master_actor->t.t.translate.t); - length = BrVector3Length(&car_to_last_point_v); - if (length < 0.3f) { - return; - } - CalcNegativeXVector(&offset_v, &trail->trail_nodes[trail->number_of_nodes - 2], &pPursuee->car_master_actor->t.t.translate.t, 0.5f); - - BrVector3Add(&start1, &trail->trail_nodes[trail->number_of_nodes - 2], &offset_v); - BrVector3Add(&finish1, &pPursuee->car_master_actor->t.t.translate.t, &offset_v); - BrVector3Sub(&start2, &trail->trail_nodes[trail->number_of_nodes - 2], &offset_v); - BrVector3Sub(&finish2, &pPursuee->car_master_actor->t.t.translate.t, &offset_v); - - if ((trail->has_deviated_recently - || !(visible = PointVisibleFromHere(&start1, &finish1)) - || !(visible = PointVisibleFromHere(&start2, &finish2)) - || !(visible = PointVisibleFromHere(&trail->trail_nodes[trail->number_of_nodes - 2], &pPursuee->car_master_actor->t.t.translate.t))) - && ((visible && length > 2.0f) || (!visible && length > 1.5f))) { - if (trail->number_of_nodes < COUNT_OF(trail->trail_nodes)) { - trail->number_of_nodes++; - } else { - memmove(trail->trail_nodes, &trail->trail_nodes[1], (COUNT_OF(trail->trail_nodes) - 1) * sizeof(trail->trail_nodes[0])); - trail->nodes_shifted_this_frame = 1; - } - trail->has_deviated_recently = 0; - BrVector3Copy(&trail->base_heading, &pPursuee->direction); - } - BrVector3Copy(&trail->trail_nodes[trail->number_of_nodes - 1], &pPursuee->car_master_actor->t.t.translate.t); + if (trail->time_of_next_recording >= gTime_stamp_for_this_munging) { + return; } + trail->time_of_next_recording = gTime_stamp_for_this_munging + 500; + trail->nodes_shifted_this_frame = 0; + if (BrVector3Dot(&trail->base_heading, &pPursuee->direction) < FastScalarCos(30)) { + trail->has_deviated_recently = 1; + } + BrVector3Sub(&car_to_last_point_v, &trail->trail_nodes[trail->number_of_nodes - 2], &pPursuee->car_master_actor->t.t.translate.t); + length = BrVector3Length(&car_to_last_point_v); + if (length < 0.3f) { + return; + } + CalcNegativeXVector(&offset_v, &trail->trail_nodes[trail->number_of_nodes - 2], &pPursuee->car_master_actor->t.t.translate.t, 0.5f); + + BrVector3Add(&start1, &trail->trail_nodes[trail->number_of_nodes - 2], &offset_v); + BrVector3Add(&finish1, &pPursuee->car_master_actor->t.t.translate.t, &offset_v); + BrVector3Sub(&start2, &trail->trail_nodes[trail->number_of_nodes - 2], &offset_v); + BrVector3Sub(&finish2, &pPursuee->car_master_actor->t.t.translate.t, &offset_v); + visible = 1; + if ((trail->has_deviated_recently + || !(visible = PointVisibleFromHere(&start1, &finish1)) + || !(visible = PointVisibleFromHere(&start2, &finish2)) + || !(visible = PointVisibleFromHere(&trail->trail_nodes[trail->number_of_nodes - 2], &pPursuee->car_master_actor->t.t.translate.t))) + && ((visible && length > 2.0f) || (!visible && length > 1.5f))) { + if (trail->number_of_nodes >= COUNT_OF(trail->trail_nodes)) { + memmove(trail->trail_nodes, &trail->trail_nodes[1], (COUNT_OF(trail->trail_nodes) - 1) * sizeof(trail->trail_nodes[0])); + trail->nodes_shifted_this_frame = 1; + } else { + trail->number_of_nodes++; + } + trail->has_deviated_recently = 0; + BrVector3Copy(&trail->base_heading, &pPursuee->direction); + } + BrVector3Copy(&trail->trail_nodes[trail->number_of_nodes - 1], &pPursuee->car_master_actor->t.t.translate.t); } // IDA: tS16 __usercall FindNearestTrailSection@(tOpponent_spec *pOpponent_spec@, tCar_spec *pPursuee@, br_vector3 *pSection_v@, br_vector3 *pIntersect@, br_scalar *pDistance) @@ -1041,13 +1028,13 @@ tS16 CalcNextTrailSection(tOpponent_spec* pOpponent_spec, int pSection) { int section_no; tPursuee_trail* trail; - section_no = pSection - 15000; trail = &pOpponent_spec->pursue_car_data.pursuee->my_trail; + section_no = pSection - 15000; - if (trail->number_of_nodes - 2 <= section_no) { - return -1; + if (trail->number_of_nodes - 2 > section_no) { + return pSection + 1; } - return section_no + 15001; + return -1; } // IDA: void __usercall ProcessPursueAndTwat(tOpponent_spec *pOpponent_spec@, tProcess_objective_command pCommand@) @@ -1066,8 +1053,7 @@ void ProcessPursueAndTwat(tOpponent_spec* pOpponent_spec, tProcess_objective_com tS16 section_no; data = &pOpponent_spec->pursue_car_data; - switch (pCommand) { - case ePOC_start: + if (pCommand == ePOC_start) { dr_dprintf("%s: ProcessPursueAndTwat() - new objective started", pOpponent_spec->car_spec->driver_name); data->direct_line_nodes[0].number_of_sections = 1; data->direct_line_nodes[0].sections[0] = 10000; @@ -1088,153 +1074,139 @@ void ProcessPursueAndTwat(tOpponent_spec* pOpponent_spec, tProcess_objective_com data->time_last_away_from_pursuee = gTime_stamp_for_this_munging; data->state = ePCS_what_now; return; + } - case ePOC_run: + if (pCommand != ePOC_run) { + return; + } - if (CAR_SPEC_IS_ROZZER(pOpponent_spec->car_spec) && pOpponent_spec->distance_from_home > 75.0f) { - dr_dprintf("%s: Completing pursuit objective because I'm out of my precinct", pOpponent_spec->car_spec->driver_name); - NewObjective(pOpponent_spec, eOOT_return_to_start); - return; - } + if (CAR_SPEC_IS_ROZZER(pOpponent_spec->car_spec) && pOpponent_spec->distance_from_home > 75.0f) { + dr_dprintf("%s: Completing pursuit objective because I'm out of my precinct", pOpponent_spec->car_spec->driver_name); + NewObjective(pOpponent_spec, eOOT_return_to_start); + return; + } - data->direct_line_section.length = MAX(pOpponent_spec->player_to_oppo_d, 3.0f); - if (pOpponent_spec->player_to_oppo_d > 3.0f) { - data->time_last_away_from_pursuee = gTime_stamp_for_this_munging; - } - if (gOpponents[pOpponent_spec->index].psyche.grudge_against_player < 15) { - dr_dprintf("%s: Completing pursuit objective because I'm happy now", pOpponent_spec->car_spec->driver_name); - ObjectiveComplete(pOpponent_spec); - return; - } - if (data->state != ePCS_backing_up) { - if (data->time_last_twatted_em + 1000 < gTime_stamp_for_this_munging && data->time_last_twatted_em + 3000 > gTime_stamp_for_this_munging && BrVector3Length(&data->pursuee->v) < 0.3f) { - dr_dprintf("%s: Backing up because we're 'stationary' after colliding with pursuee", pOpponent_spec->car_spec->driver_name); - data->start_backup_time = gTime_stamp_for_this_munging; - data->state = ePCS_backing_up; - } else { - - if (data->time_last_away_from_pursuee + 7000 < gTime_stamp_for_this_munging && data->time_last_twatted_em + 7000 < gTime_stamp_for_this_munging && data->start_backup_time + 10000 < gTime_stamp_for_this_munging) { - dr_dprintf("%s: Backing up because we're too close to pursuee without having twatted him", pOpponent_spec->car_spec->driver_name); - data->start_backup_time = gTime_stamp_for_this_munging; - data->state = ePCS_backing_up; - } else { - if (pOpponent_spec->cheating) { - if (pOpponent_spec->player_to_oppo_d < 50.0f - && PointVisibleFromHere(&data->pursuee->car_master_actor->t.t.translate.t, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t)) { - data->time_pursuee_last_visible = gTime_stamp_for_this_munging; - } else { - data->time_pursuee_last_visible = 0; - } - } else if (pOpponent_spec->player_in_view_now || (data->time_of_next_visibility_check < gTime_stamp_for_this_munging && pOpponent_spec->player_to_oppo_d < 35.0f && PointVisibleFromHere(&data->pursuee->car_master_actor->t.t.translate.t, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t))) { + data->direct_line_section.length = MAX(pOpponent_spec->player_to_oppo_d, 3.0f); + if (pOpponent_spec->player_to_oppo_d > 3.0f) { + data->time_last_away_from_pursuee = gTime_stamp_for_this_munging; + } + if (gOpponents[pOpponent_spec->index].psyche.grudge_against_player < 15u) { + dr_dprintf("%s: Completing pursuit objective because I'm happy now", pOpponent_spec->car_spec->driver_name); + ObjectiveComplete(pOpponent_spec); + return; + } + if (data->state != ePCS_backing_up) { + if (data->time_last_twatted_em + 1000 >= gTime_stamp_for_this_munging || data->time_last_twatted_em + 3000 <= gTime_stamp_for_this_munging || BrVector3Length(&data->pursuee->v) >= 0.3f) { + if (data->time_last_away_from_pursuee + 7000 >= gTime_stamp_for_this_munging || data->time_last_twatted_em + 7000 >= gTime_stamp_for_this_munging || data->start_backup_time + 10000 >= gTime_stamp_for_this_munging) { + if (pOpponent_spec->cheating) { + if (pOpponent_spec->player_to_oppo_d < 50.0f + && PointVisibleFromHere(&data->pursuee->car_master_actor->t.t.translate.t, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t)) { data->time_pursuee_last_visible = gTime_stamp_for_this_munging; - data->time_of_next_visibility_check = gTime_stamp_for_this_munging + 600; - } - if (data->time_pursuee_last_visible + 3000 > gTime_stamp_for_this_munging) { - if (data->state != ePCS_following_line_of_sight) { - dr_dprintf("%s: Commencing ePCS_following_line_of_sight state", pOpponent_spec->car_spec->driver_name); - data->state = ePCS_following_line_of_sight; - sprintf(str, "%s: I've spotted you!", pOpponent_spec->car_spec->driver_name); - ProcessFollowPath(pOpponent_spec, ePOC_start, 1, 1, 0); - } } else { - if (data->pursuee->my_trail.number_of_nodes < 2) { - dr_dprintf("%s: Giving up pursuit - not visible & no trail yet", pOpponent_spec->car_spec->driver_name); + data->time_pursuee_last_visible = 0; + } + } else if (pOpponent_spec->player_in_view_now || (data->time_of_next_visibility_check < gTime_stamp_for_this_munging && pOpponent_spec->player_to_oppo_d < 35.0f && PointVisibleFromHere(&data->pursuee->car_master_actor->t.t.translate.t, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t))) { + data->time_pursuee_last_visible = gTime_stamp_for_this_munging; + data->time_of_next_visibility_check = gTime_stamp_for_this_munging + 600; + } + if (data->time_pursuee_last_visible + 3000 <= gTime_stamp_for_this_munging) { + if (data->pursuee->my_trail.number_of_nodes < 2) { + dr_dprintf("%s: Giving up pursuit - not visible & no trail yet", pOpponent_spec->car_spec->driver_name); + NewObjective(pOpponent_spec, eOOT_get_near_player); + return; + } + if (data->state != ePCS_following_trail) { + section_no = FindNearestTrailSection(pOpponent_spec, data->pursuee, §ion_v, &intersect, &distance); + data->state = ePCS_following_trail; + if (distance > 20.0f || section_no == -1) { + dr_dprintf("%s: Giving up pursuit - not visible & trail ain't close enough (%f)", pOpponent_spec->car_spec->driver_name, distance); NewObjective(pOpponent_spec, eOOT_get_near_player); return; } - if (data->state != ePCS_following_trail) { - section_no = FindNearestTrailSection(pOpponent_spec, data->pursuee, §ion_v, &intersect, &distance); - data->state = ePCS_following_trail; - if (distance > 20.0f || section_no == -1) { - dr_dprintf("%s: Giving up pursuit - not visible & trail ain't close enough (%f)", pOpponent_spec->car_spec->driver_name, distance); - NewObjective(pOpponent_spec, eOOT_get_near_player); - return; - } - dr_dprintf("%s: Commencing ePCS_following_trail state", pOpponent_spec->car_spec->driver_name); - pOpponent_spec->follow_path_data.section_no = section_no; - ProcessFollowPath(pOpponent_spec, ePOC_start, 1, 0, 0); - } + dr_dprintf("%s: Commencing ePCS_following_trail state", pOpponent_spec->car_spec->driver_name); + pOpponent_spec->follow_path_data.section_no = section_no; + ProcessFollowPath(pOpponent_spec, ePOC_start, 1, 0, 0); } + } else if (data->state != ePCS_following_line_of_sight) { + dr_dprintf("%s: Commencing ePCS_following_line_of_sight state", pOpponent_spec->car_spec->driver_name); + data->state = ePCS_following_line_of_sight; + sprintf(str, "%s: I've spotted you!", pOpponent_spec->car_spec->driver_name); + ProcessFollowPath(pOpponent_spec, ePOC_start, 1, 1, 0); } + } else { + dr_dprintf("%s: Backing up because we're too close to pursuee without having twatted him", pOpponent_spec->car_spec->driver_name); + data->start_backup_time = gTime_stamp_for_this_munging; + data->state = ePCS_backing_up; } + } else { + dr_dprintf("%s: Backing up because we're 'stationary' after colliding with pursuee", pOpponent_spec->car_spec->driver_name); + data->start_backup_time = gTime_stamp_for_this_munging; + data->state = ePCS_backing_up; } - switch (data->state) { - - case ePCS_backing_up: - if (data->start_backup_time + 2200 < gTime_stamp_for_this_munging) { - pOpponent_spec->car_spec->acc_force = 0.0; - pOpponent_spec->car_spec->brake_force = pOpponent_spec->car_spec->M * 15.0f; - if (data->start_backup_time + 3000 < gTime_stamp_for_this_munging) { - pOpponent_spec->car_spec->brake_force = 0.0f; - data->state = ePCS_what_now; - dr_dprintf("%s: Finished backing up.", pOpponent_spec->car_spec->driver_name); - } - } else { - pOpponent_spec->car_spec->curvature = 0.0f; - pOpponent_spec->car_spec->brake_force = 0.0f; - pOpponent_spec->car_spec->acc_force = pOpponent_spec->car_spec->M * -8.0f; - } - break; - - case ePCS_following_line_of_sight: - BrVector3Copy(&data->direct_line_nodes[0].p, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t); - BrVector3Sub(&wank, &data->pursuee->car_master_actor->t.t.translate.t, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t); - d = BrVector3Length(&wank); - BrVector3Sub(&wank, &data->pursuee->v, &pOpponent_spec->car_spec->v); - s = BrVector3Length(&wank); - if (s < 1.0f) { - t = 0.0; - } else { - t = d / s / 2.0f; - } - BrVector3Scale(&data->direct_line_nodes[1].p, &data->pursuee->v, t); - BrVector3Accumulate(&data->direct_line_nodes[1].p, &data->pursuee->car_master_actor->t.t.translate.t); - if (d < 2.0f) { - ProcessFollowPath(pOpponent_spec, ePOC_run, 1, 1, 1); - } else { - ProcessFollowPath(pOpponent_spec, ePOC_run, 1, 1, 0); - } - break; - - case ePCS_following_trail: - if (data->pursuee->my_trail.nodes_shifted_this_frame) { - if (pOpponent_spec->follow_path_data.section_no > 15000) { - pOpponent_spec->follow_path_data.section_no--; - } else { - data->state = ePCS_following_trail; - section_no = FindNearestTrailSection(pOpponent_spec, data->pursuee, §ion_v, &intersect, &distance); - dr_dprintf("%s: Trail got away; found new trail section %d", pOpponent_spec->car_spec->driver_name, section_no); - if (section_no == -1 || distance > 20.0f || !PointVisibleFromHere(&intersect, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t)) { - dr_dprintf("%s: ...which unfortunately is too far away (%fBRU) or not visible - end of pursuit", pOpponent_spec->car_spec->driver_name, distance); - NewObjective(pOpponent_spec, eOOT_get_near_player); - break; - } - pOpponent_spec->follow_path_data.section_no = section_no; - ProcessFollowPath(pOpponent_spec, ePOC_start, 1, 0, 0); - } - dr_dprintf("%s: Following re-jobbied section %d/%d", pOpponent_spec->car_spec->driver_name, pOpponent_spec->follow_path_data.section_no, data->pursuee->my_trail.number_of_nodes - 1); - } - sprintf(str, "%s: Trail section %d/%d", pOpponent_spec->car_spec->driver_name, pOpponent_spec->follow_path_data.section_no, data->pursuee->my_trail.number_of_nodes - 1); - res = ProcessFollowPath(pOpponent_spec, ePOC_run, 1, 0, 0); - if (res == eFPR_given_up) { - NewObjective(pOpponent_spec, eOOT_get_near_player); - return; - } - if (res == eFPR_end_of_path) { - NewObjective(pOpponent_spec, eOOT_get_near_player); - return; - } - break; - - case ePCS_what_now: - PDEnterDebugger("ERROR: what_now state called in ProcessPursueAndTwat()"); - - default: - break; - } - + } + switch (data->state) { + case ePCS_what_now: + PDEnterDebugger("ERROR: what_now state called in ProcessPursueAndTwat()"); break; + case ePCS_following_trail: + if (data->pursuee->my_trail.nodes_shifted_this_frame) { + if (pOpponent_spec->follow_path_data.section_no <= 15000) { + data->state = ePCS_following_trail; + section_no = FindNearestTrailSection(pOpponent_spec, data->pursuee, §ion_v, &intersect, &distance); + dr_dprintf("%s: Trail got away; found new trail section %d", pOpponent_spec->car_spec->driver_name, section_no); + if (section_no == -1 || distance > 20.0f || !PointVisibleFromHere(&intersect, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t)) { + dr_dprintf("%s: ...which unfortunately is too far away (%fBRU) or not visible - end of pursuit", pOpponent_spec->car_spec->driver_name, distance); + NewObjective(pOpponent_spec, eOOT_get_near_player); + return; + } + pOpponent_spec->follow_path_data.section_no = section_no; + ProcessFollowPath(pOpponent_spec, ePOC_start, 1, 0, 0); + } else { + pOpponent_spec->follow_path_data.section_no--; + } + dr_dprintf("%s: Following re-jobbied section %d/%d", pOpponent_spec->car_spec->driver_name, pOpponent_spec->follow_path_data.section_no, data->pursuee->my_trail.number_of_nodes - 1); + } + sprintf(str, "%s: Trail section %d/%d", pOpponent_spec->car_spec->driver_name, pOpponent_spec->follow_path_data.section_no, data->pursuee->my_trail.number_of_nodes - 1); + res = ProcessFollowPath(pOpponent_spec, ePOC_run, 1, 0, 0); + if (res == eFPR_given_up || res == eFPR_end_of_path) { + NewObjective(pOpponent_spec, eOOT_get_near_player); + } + break; + case ePCS_following_line_of_sight: + BrVector3Copy(&data->direct_line_nodes[0].p, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t); + BrVector3Sub(&wank, &data->pursuee->car_master_actor->t.t.translate.t, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t); + s = BrVector3Length(&wank); + BrVector3Sub(&wank, &data->pursuee->v, &pOpponent_spec->car_spec->v); + t = BrVector3Length(&wank); + if (t >= 1.0f) { + d = s / t / 2.0; + } else { + d = 0.0; + } + BrVector3Scale(&data->direct_line_nodes[1].p, &data->pursuee->v, d); + BrVector3Accumulate(&data->direct_line_nodes[1].p, &data->pursuee->car_master_actor->t.t.translate.t); + if (s >= 2.0f) { + ProcessFollowPath(pOpponent_spec, ePOC_run, 1, 1, 0); + } else { + ProcessFollowPath(pOpponent_spec, ePOC_run, 1, 1, 1); + } + break; + case ePCS_backing_up: + if (data->start_backup_time + 2200 >= gTime_stamp_for_this_munging) { + pOpponent_spec->car_spec->curvature = 0.0f; + pOpponent_spec->car_spec->brake_force = 0.0f; + pOpponent_spec->car_spec->acc_force = pOpponent_spec->car_spec->M * -8.0f; + } else { + pOpponent_spec->car_spec->acc_force = 0.0; + pOpponent_spec->car_spec->brake_force = pOpponent_spec->car_spec->M * 15.0f; + if (data->start_backup_time + 3000 < gTime_stamp_for_this_munging) { + pOpponent_spec->car_spec->brake_force = 0.0f; + data->state = ePCS_what_now; + dr_dprintf("%s: Finished backing up.", pOpponent_spec->car_spec->driver_name); + } + } + break; default: return; } @@ -1252,50 +1224,48 @@ void ProcessRunAway(tOpponent_spec* pOpponent_spec, tProcess_objective_command p switch (pCommand) { + case ePOC_run: + if (pOpponent_spec->run_away_data.time_to_stop >= gTime_stamp_for_this_munging) { + if (pOpponent_spec->follow_path_data.section_no > 20000) { + ShiftOpponentsProjectedRoute(pOpponent_spec, pOpponent_spec->follow_path_data.section_no - 20000); + pOpponent_spec->follow_path_data.section_no = 20000; + } + if (pOpponent_spec->nnext_sections < 10) { + TopUpRandomRoute(pOpponent_spec, 10 - pOpponent_spec->nnext_sections); + } + if (ProcessFollowPath(pOpponent_spec, ePOC_run, 0, 0, 0) == eFPR_given_up) { + ClearOpponentsProjectedRoute(pOpponent_spec); + section_no = FindNearestPathSection(&pOpponent_spec->car_spec->car_master_actor->t.t.translate.t, &direction_v, &intersect, &distance); + if (BrVector3Dot(&pOpponent_spec->car_spec->direction, &direction_v) < 0.0f) { + AddToOpponentsProjectedRoute(pOpponent_spec, section_no, 0); + } else { + AddToOpponentsProjectedRoute(pOpponent_spec, section_no, 1); + } + TopUpRandomRoute(pOpponent_spec, -1); + ProcessFollowPath(pOpponent_spec, ePOC_start, 0, 0, 0); + } + } else { + ObjectiveComplete(pOpponent_spec); + } + break; + case ePOC_start: dr_dprintf("%s: ProcessRunAway() - new objective started", pOpponent_spec->car_spec->driver_name); pOpponent_spec->run_away_data.time_to_stop = gTime_stamp_for_this_munging + 1000 * IRandomBetween(30, 90); ClearOpponentsProjectedRoute(pOpponent_spec); section_no = FindNearestPathSection(&pOpponent_spec->car_spec->car_master_actor->t.t.translate.t, &direction_v, &intersect, &distance); - if (BrVector3Dot(&pOpponent_spec->car_spec->direction, &direction_v) >= 0.0f) { - AddToOpponentsProjectedRoute(pOpponent_spec, section_no, 1); - } else { + if (BrVector3Dot(&pOpponent_spec->car_spec->direction, &direction_v) < 0.0f) { AddToOpponentsProjectedRoute(pOpponent_spec, section_no, 0); + } else { + AddToOpponentsProjectedRoute(pOpponent_spec, section_no, 1); } TopUpRandomRoute(pOpponent_spec, -1); ProcessFollowPath(pOpponent_spec, ePOC_start, 0, 0, 0); sprintf(str, "%s: Shit! I'm out of here...", pOpponent_spec->car_spec->driver_name); break; - case ePOC_run: - if (pOpponent_spec->run_away_data.time_to_stop < gTime_stamp_for_this_munging) { - ObjectiveComplete(pOpponent_spec); - return; - } - if (pOpponent_spec->follow_path_data.section_no > 20000) { - ShiftOpponentsProjectedRoute(pOpponent_spec, pOpponent_spec->follow_path_data.section_no - 20000); - pOpponent_spec->follow_path_data.section_no = 20000; - } - if (pOpponent_spec->nnext_sections < 10) { - TopUpRandomRoute(pOpponent_spec, 10 - pOpponent_spec->nnext_sections); - } - res = ProcessFollowPath(pOpponent_spec, ePOC_run, 0, 0, 0); - if (res == eFPR_given_up) { - ClearOpponentsProjectedRoute(pOpponent_spec); - section_no = FindNearestPathSection(&pOpponent_spec->car_spec->car_master_actor->t.t.translate.t, &direction_v, &intersect, &distance); - if (BrVector3Dot(&pOpponent_spec->car_spec->direction, &direction_v) >= 0.0f) { - AddToOpponentsProjectedRoute(pOpponent_spec, section_no, 1); - } else { - AddToOpponentsProjectedRoute(pOpponent_spec, section_no, 0); - } - TopUpRandomRoute(pOpponent_spec, -1); - ProcessFollowPath(pOpponent_spec, ePOC_start, 0, 0, 0); - } - - break; - case ePOC_die: - return; + break; } } @@ -1305,14 +1275,11 @@ void ProcessWaitForSomeHaplessSod(tOpponent_spec* pOpponent_spec, tProcess_objec switch (pCommand) { case ePOC_start: - pOpponent_spec->car_spec->brake_force = 15.f * pOpponent_spec->car_spec->M; - return; case ePOC_run: pOpponent_spec->car_spec->brake_force = 15.f * pOpponent_spec->car_spec->M; - return; - - case ePOC_die: - return; + break; + default: + break; } } @@ -1326,26 +1293,17 @@ void ProcessReturnToStart(tOpponent_spec* pOpponent_spec, tProcess_objective_com int res; switch (pCommand) { - case ePOC_start: - dr_dprintf("%s: ProcessReturnToStart() - new objective started", pOpponent_spec->car_spec->driver_name); - pOpponent_spec->return_to_start_data.waiting_near_start = 0; - pOpponent_spec->return_to_start_data.section_no = FindNearestPathSection(&pOpponent_spec->start_pos, §ion_v, &pOpponent_spec->return_to_start_data.nearest_path_point, &distance); - pOpponent_spec->return_to_start_data.nearest_path_point.v[1] = 0.0; - CalcReturnToStartPointRoute(pOpponent_spec); - ProcessFollowPath(pOpponent_spec, ePOC_start, 0, 0, 0); - break; case ePOC_run: if (TeleportCopToStart(pOpponent_spec)) { break; } - if (!pOpponent_spec->return_to_start_data.waiting_near_start) { - BrVector3Copy(&our_pos_xz, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t); + if (pOpponent_spec->return_to_start_data.waiting_near_start) { + pOpponent_spec->car_spec->brake_force = pOpponent_spec->car_spec->M * 15.0f; + } else { + our_pos_xz = pOpponent_spec->car_spec->car_master_actor->t.t.translate.t; our_pos_xz.v[1] = 0.0f; BrVector3Sub(&cop_to_start, &pOpponent_spec->start_pos, &our_pos_xz); - if (BrVector3Length(&cop_to_start) < 10.f) { - pOpponent_spec->return_to_start_data.waiting_near_start = 1; - pOpponent_spec->car_spec->brake_force = pOpponent_spec->car_spec->M * 15.0f; - } else { + if (BrVector3Length(&cop_to_start) >= 10.0) { if (pOpponent_spec->follow_path_data.section_no > 20000) { ShiftOpponentsProjectedRoute(pOpponent_spec, pOpponent_spec->follow_path_data.section_no - 20000); pOpponent_spec->follow_path_data.section_no = 20000; @@ -1364,14 +1322,22 @@ void ProcessReturnToStart(tOpponent_spec* pOpponent_spec, tProcess_objective_com CalcReturnToStartPointRoute(pOpponent_spec); ProcessFollowPath(pOpponent_spec, ePOC_start, 0, 0, 0); } + } else { + pOpponent_spec->return_to_start_data.waiting_near_start = 1; + pOpponent_spec->car_spec->brake_force = pOpponent_spec->car_spec->M * 15.0f; } - } else { - pOpponent_spec->car_spec->brake_force = pOpponent_spec->car_spec->M * 15.0f; } break; - - case ePOC_die: - return; + case ePOC_start: + dr_dprintf("%s: ProcessReturnToStart() - new objective started", pOpponent_spec->car_spec->driver_name); + pOpponent_spec->return_to_start_data.waiting_near_start = 0; + pOpponent_spec->return_to_start_data.section_no = FindNearestPathSection(&pOpponent_spec->start_pos, §ion_v, &pOpponent_spec->return_to_start_data.nearest_path_point, &distance); + pOpponent_spec->return_to_start_data.nearest_path_point.v[1] = 0.0; + CalcReturnToStartPointRoute(pOpponent_spec); + ProcessFollowPath(pOpponent_spec, ePOC_start, 0, 0, 0); + break; + default: + break; } } @@ -1382,50 +1348,41 @@ void ProcessLevitate(tOpponent_spec* pOpponent_spec, tProcess_objective_command float terminal_time; float y; - switch (pCommand) { - case ePOC_start: + if (pCommand == ePOC_start) { dr_dprintf("%s: ProcessLevitate() - new objective started", pOpponent_spec->car_spec->driver_name); pOpponent_spec->levitate_data.waiting_to_levitate = 1; pOpponent_spec->car_spec->brake_force = 15.f * pOpponent_spec->car_spec->M; pOpponent_spec->car_spec->acc_force = 0.f; pOpponent_spec->levitate_data.time_started = gTime_stamp_for_this_munging; - break; - - case ePOC_run: + } else if (pCommand == ePOC_run) { if (pOpponent_spec->levitate_data.waiting_to_levitate) { if ((BrVector3Length(&pOpponent_spec->car_spec->v) < .01f && BrVector3Length(&pOpponent_spec->car_spec->omega) < 1.f) || gTime_stamp_for_this_munging - pOpponent_spec->levitate_data.time_started > 4000) { pOpponent_spec->levitate_data.waiting_to_levitate = 0; pOpponent_spec->levitate_data.time_started = gTime_stamp_for_this_munging; pOpponent_spec->levitate_data.initial_y = pOpponent_spec->car_spec->car_master_actor->t.t.translate.t.v[1]; if (pOpponent_spec->car_spec->has_been_stolen) { - NewTextHeadupSlot(eHeadupSlot_misc, 250, 5000, -4, GetMiscString(kMiscString_CarAddedToChangeCarList)); + NewTextHeadupSlot(eHeadupSlot_misc, 250, 2500, -4, GetMiscString(kMiscString_CarAddedToChangeCarList)); } } else { pOpponent_spec->car_spec->brake_force = 15.f * pOpponent_spec->car_spec->M; pOpponent_spec->car_spec->acc_force = 0.f; BrVector3InvScale(&pOpponent_spec->car_spec->omega, &pOpponent_spec->car_spec->omega, - pow(2.f, gFrame_period_for_this_munging / 1000.0)); + pow(gFrame_period_for_this_munging / 1000.f, 2.f)); } } if (!pOpponent_spec->levitate_data.waiting_to_levitate) { TurnOpponentPhysicsOff(pOpponent_spec); - t = (gTime_stamp_for_this_munging - pOpponent_spec->levitate_data.time_started) / 1000.0; - terminal_time = 20.f; - if (t < terminal_time) { - y = t * t * .5f / 2.f; + t = (gTime_stamp_for_this_munging - pOpponent_spec->levitate_data.time_started) / 1000.f; + if (t < 20.f) { + y = .5f * t * t / 2.f; } else { - y = terminal_time * terminal_time * 0.5 / 2.0 + (t - terminal_time) * 10.0; + y = 10.f * (t - 20.f) + 100.f; } pOpponent_spec->car_spec->car_master_actor->t.t.translate.t.v[1] = pOpponent_spec->levitate_data.initial_y + y; if (y > 200.f) { pOpponent_spec->finished_for_this_race = 1; } } - break; - case ePOC_die: - return; - default: - break; } } @@ -1437,25 +1394,21 @@ void ProcessGetNearPlayer(tOpponent_spec* pOpponent_spec, tProcess_objective_com int res; char str[256]; - initial_pos = &gProgram_state.initial_position; - car_actor = pOpponent_spec->car_spec->car_master_actor; - - switch (pCommand) { - case ePOC_start: + if (pCommand == ePOC_start) { dr_dprintf("%s: ProcessGetNearPlayer() - new objective started", pOpponent_spec->car_spec->driver_name); ClearOpponentsProjectedRoute(pOpponent_spec); CalcGetNearPlayerRoute(pOpponent_spec, &gProgram_state.current_car); ProcessFollowPath(pOpponent_spec, ePOC_start, 0, 0, 0); - break; - - case ePOC_run: - if (CAR_SPEC_IS_ROZZER(pOpponent_spec->car_spec) && pOpponent_spec->distance_from_home > 75.0f) { + return; + } + if (pCommand == ePOC_run) { + if ((pOpponent_spec->car_spec->car_ID & 0xff00) == 768 && pOpponent_spec->distance_from_home > 75.0) { dr_dprintf("%s: Completing get_near objective because I'm out of my precinct", pOpponent_spec->car_spec->driver_name); NewObjective(pOpponent_spec, eOOT_return_to_start); return; } if (pOpponent_spec->follow_path_data.section_no > 20000) { - if (pOpponent_spec->player_to_oppo_d < 10.0f || pOpponent_spec->follow_path_data.section_no == pOpponent_spec->players_section_when_last_calced_full_path) { + if (pOpponent_spec->player_to_oppo_d < 10.0 || pOpponent_spec->follow_path_data.section_no == pOpponent_spec->players_section_when_last_calced_full_path) { dr_dprintf("%s: ProcessGetNearPlayer() - giving up 'cos got to player's section", pOpponent_spec->car_spec->driver_name); ObjectiveComplete(pOpponent_spec); return; @@ -1469,20 +1422,14 @@ void ProcessGetNearPlayer(tOpponent_spec* pOpponent_spec, tProcess_objective_com res = ProcessFollowPath(pOpponent_spec, ePOC_run, 0, 0, 0); sprintf(str, "Get near: %d", GetOpponentsRealSection(pOpponent_spec, pOpponent_spec->follow_path_data.section_no)); - if (res == eFPR_given_up || res == eFPR_end_of_path) { - if (res == eFPR_given_up) { - NewObjective(pOpponent_spec, eOOT_pursue_and_twat, &gProgram_state.current_car); - return; - } else { - dr_dprintf("%s: Restarting get_near_player route because ran out of path!", pOpponent_spec->car_spec->driver_name); - } + if (res == eFPR_given_up) { + NewObjective(pOpponent_spec, eOOT_pursue_and_twat, &gProgram_state.current_car); + } else if (res == eFPR_end_of_path) { + dr_dprintf("%s: Restarting get_near_player route because ran out of path!", pOpponent_spec->car_spec->driver_name); ClearOpponentsProjectedRoute(pOpponent_spec); CalcGetNearPlayerRoute(pOpponent_spec, &gProgram_state.current_car); ProcessFollowPath(pOpponent_spec, ePOC_start, 0, 0, 0); } - - default: - break; } } @@ -1520,13 +1467,12 @@ int HeadOnWithPlayerPossible(tOpponent_spec* pOpponent_spec) { - pOpponent_spec->car_spec->car_master_actor->t.t.mat.m[3][2]; BrVector3Normalise(&oppo_to_player_norm, &oppo_to_player_norm); - if (gHead_on_cos_value < BrVector3Dot(&pOpponent_spec->car_spec->direction, &oppo_to_player_norm) - && -gHead_on_cos_value > BrVector3Dot(&gProgram_state.current_car.direction, &oppo_to_player_norm)) { - - dr_dprintf("HOORAY! Head-on imminent"); - return 1; + if (gHead_on_cos_value >= BrVector3Dot(&pOpponent_spec->car_spec->direction, &pOpponent_spec->car_spec->direction) + || -gHead_on_cos_value <= BrVector3Dot(&pOpponent_spec->car_spec->direction, &pOpponent_spec->car_spec->direction)) { + return 0; } - return 0; + dr_dprintf("HOORAY! Head-on imminent"); + return 1; } // IDA: int __usercall AlreadyPursuingCar@(tOpponent_spec *pOpponent_spec@, tCar_spec *pPursuee@) @@ -1560,12 +1506,12 @@ void ObjectiveComplete(tOpponent_spec* pOpponent_spec) { case eOOT_complete_race: gNum_of_opponents_completing_race--; break; - case eOOT_get_near_player: - gNum_of_opponents_getting_near--; - break; case eOOT_pursue_and_twat: gNum_of_opponents_pursuing--; break; + case eOOT_get_near_player: + gNum_of_opponents_getting_near--; + break; default: break; } @@ -1634,17 +1580,16 @@ void ChooseNewObjective(tOpponent_spec* pOpponent_spec, int pMust_choose_one) { if (gTime_stamp_for_this_munging > pOpponent_spec->next_out_of_world_check) { pOpponent_spec->next_out_of_world_check = gTime_stamp_for_this_munging + 500; if (HasCarFallenOffWorld(pOpponent_spec->car_spec)) { - if (pOpponent_spec->car_spec->last_time_we_touched_a_player > gTime_stamp_for_this_munging - 7000) { + if (pOpponent_spec->car_spec->last_time_we_touched_a_player <= gTime_stamp_for_this_munging - 7000) { + TeleportOpponentToNearestSafeLocation(pOpponent_spec); + NewObjective(pOpponent_spec, eOOT_complete_race); + } else { TurnOpponentPhysicsOff(pOpponent_spec); pOpponent_spec->finished_for_this_race = 1; KnackerThisCar(pOpponent_spec->car_spec); pOpponent_spec->car_spec->car_master_actor->t.t.mat.m[3][1] -= 1000.0f; - return; - } else { - TeleportOpponentToNearestSafeLocation(pOpponent_spec); - NewObjective(pOpponent_spec, eOOT_complete_race); - return; } + return; } } if (pOpponent_spec->car_spec->knackered && !pOpponent_spec->knackeredness_detected) { @@ -1666,6 +1611,7 @@ void ChooseNewObjective(tOpponent_spec* pOpponent_spec, int pMust_choose_one) { NewObjective(pOpponent_spec, eOOT_get_near_player); } } + return; } else { if (CAR_SPEC_GET_SPEED_FACTOR(pOpponent_spec->car_spec) == 0.0f) { dr_dprintf("%s: Decided to freeze", pOpponent_spec->car_spec->driver_name); @@ -1681,15 +1627,17 @@ void ChooseNewObjective(tOpponent_spec* pOpponent_spec, int pMust_choose_one) { general_grudge_increase = (pOpponent_spec->nastiness * 40.0f + 10.0f); if (pOpponent_spec->car_spec->scary_bang && pOpponent_spec->player_to_oppo_d < 10.0f) { if (pOpponent_spec->current_objective == eOOT_pursue_and_twat) { - pursuit_percentage = 40; + percentage = 40; } else { - pursuit_percentage = 0; + percentage = 0; } - if (CAR_SPEC_IS_ROZZER(pOpponent_spec->car_spec) && PercentageChance(20)) { - dr_dprintf("%s: Decided to run away", pOpponent_spec->car_spec->driver_name); - NewObjective(pOpponent_spec, eOOT_run_away); - return; - } else if (PercentageChance((pursuit_percentage + 60) - pOpponent_spec->nastiness * 50.0f)) { + if (CAR_SPEC_IS_ROZZER(pOpponent_spec->car_spec)) { + if (PercentageChance(20)) { + dr_dprintf("%s: Decided to run away", pOpponent_spec->car_spec->driver_name); + NewObjective(pOpponent_spec, eOOT_run_away); + return; + } + } else if (PercentageChance((percentage + 60) - pOpponent_spec->nastiness * 50.0)) { dr_dprintf("%s: Decided to run away", pOpponent_spec->car_spec->driver_name); NewObjective(pOpponent_spec, eOOT_run_away); return; @@ -1704,6 +1652,14 @@ void ChooseNewObjective(tOpponent_spec* pOpponent_spec, int pMust_choose_one) { return; } if (pOpponent_spec->car_spec->big_bang && LastTwatterAPlayer(pOpponent_spec) && !AlreadyPursuingCar(pOpponent_spec, pOpponent_spec->car_spec->last_person_to_hit_us)) { + // v4 = gOpponents[pOpponent_spec->index].psyche.grudge_against_player; + // if (v4 <= 20) { + // v4 = 20; + // } + // v5 = general_grudge_increase + v4; + // if (v5 >= 100) { + // LOBYTE(v5) = 100; + // } gOpponents[pOpponent_spec->index].psyche.grudge_against_player = MIN(100, MAX(20, gOpponents[pOpponent_spec->index].psyche.grudge_against_player) + general_grudge_increase); sprintf(str, "%s: Christ! What was that?", pOpponent_spec->car_spec->driver_name); dr_dprintf("%s: Decided to pursue after big bang; last person to twat us was %s", pOpponent_spec->car_spec->driver_name, pOpponent_spec->car_spec->last_person_to_hit_us->driver_name); @@ -1711,6 +1667,14 @@ void ChooseNewObjective(tOpponent_spec* pOpponent_spec, int pMust_choose_one) { return; } if (LastTwatteeAPlayer(pOpponent_spec) && !AlreadyPursuingCar(pOpponent_spec, pOpponent_spec->car_spec->last_person_we_hit)) { + // v6 = gOpponents[pOpponent_spec->index].psyche.grudge_against_player; + // if (v6 <= 20) { + // v6 = 20; + // } + // v7 = general_grudge_increase + v6; + // if (v7 >= 100) { + // LOBYTE(v7) = 100; + // } gOpponents[pOpponent_spec->index].psyche.grudge_against_player = MIN(100, MAX(20, gOpponents[pOpponent_spec->index].psyche.grudge_against_player) + general_grudge_increase); sprintf(str, "%s: Ha! Bet you weren't expecting that!", pOpponent_spec->car_spec->driver_name); dr_dprintf("%s: Decided to pursue %s after accidentally hitting them", pOpponent_spec->car_spec->driver_name, pOpponent_spec->car_spec->last_person_we_hit->driver_name); @@ -1718,7 +1682,15 @@ void ChooseNewObjective(tOpponent_spec* pOpponent_spec, int pMust_choose_one) { return; } if (!AlreadyPursuingCar(pOpponent_spec, &gProgram_state.current_car)) { - if (pOpponent_spec->car_spec->grudge_raised_recently && (!CAR_SPEC_IS_ROZZER(pOpponent_spec->car_spec) || pOpponent_spec->player_to_oppo_d <= 20.f) && LastTwatterAPlayer(pOpponent_spec) && gOpponents[pOpponent_spec->index].psyche.grudge_against_player > 20) { + if (pOpponent_spec->car_spec->grudge_raised_recently && (!CAR_SPEC_IS_ROZZER(pOpponent_spec->car_spec) || pOpponent_spec->player_to_oppo_d <= 20.0) && LastTwatterAPlayer(pOpponent_spec) && gOpponents[pOpponent_spec->index].psyche.grudge_against_player > 20) { + // v8 = gOpponents[pOpponent_spec->index].psyche.grudge_against_player; + // if (v8 <= 20) { + // v8 = 20; + // } + // v9 = general_grudge_increase + v8; + // if (v9 >= 100) { + // LOBYTE(v9) = 100; + // } gOpponents[pOpponent_spec->index].psyche.grudge_against_player = MIN(100, MAX(20, gOpponents[pOpponent_spec->index].psyche.grudge_against_player) + general_grudge_increase); sprintf(str, "%s: Right! That's enough, %s!", pOpponent_spec->car_spec->driver_name, gProgram_state.current_car.driver_name); dr_dprintf("%s: Decided to pursue after grudginess raised; last person to twat us was %s", pOpponent_spec->car_spec->driver_name, pOpponent_spec->car_spec->last_person_to_hit_us->driver_name); @@ -1726,76 +1698,69 @@ void ChooseNewObjective(tOpponent_spec* pOpponent_spec, int pMust_choose_one) { return; } - if (pOpponent_spec->player_in_view_now) { - do_it = 0; - if (pOpponent_spec->acknowledged_piv == 0) { + if ((pOpponent_spec->player_in_view_now) != 0 && (pOpponent_spec->acknowledged_piv) == 0) { + pOpponent_spec->acknowledged_piv = 1; + if (CAR_SPEC_IS_ROZZER(pOpponent_spec->car_spec)) { + pursuit_percentage = (BrVector3Length(&gProgram_state.current_car.v) - gDefinite_no_cop_pursuit_speed) * gCop_pursuit_speed_percentage_multiplier; + } else if (gProgram_state.skill_level + 3 > gNum_of_opponents_pursuing) { + pursuit_percentage = gOpponents[pOpponent_spec->index].psyche.grudge_against_player - 20 + pOpponent_spec->nastiness * 30.f; + } else { + pursuit_percentage = 0; + } - pOpponent_spec->acknowledged_piv = 1; - if (CAR_SPEC_IS_ROZZER(pOpponent_spec->car_spec)) { - percentage = (BrVector3Length(&gProgram_state.current_car.v) - gDefinite_no_cop_pursuit_speed) * gCop_pursuit_speed_percentage_multiplier; - } else if (gProgram_state.skill_level + 3 > gNum_of_opponents_pursuing) { - percentage = gOpponents[pOpponent_spec->index].psyche.grudge_against_player - 20 + pOpponent_spec->nastiness * 30.f; - } else { - percentage = 0; - } - - percentage += 50 * HeadOnWithPlayerPossible(pOpponent_spec); - do_it = PercentageChance(percentage); - dr_dprintf("%s: Spotted player; chance of pursuing %d%%: %s", pOpponent_spec->car_spec->driver_name, percentage, do_it ? "YES, Decided to pursue" : "NO, Decided NOT to pursue"); - if (do_it) { - gOpponents[pOpponent_spec->index].psyche.grudge_against_player = MIN(100, MAX(20, gOpponents[pOpponent_spec->index].psyche.grudge_against_player) + general_grudge_increase); - sprintf(str, "%s: I've decided to kill you for the fun of it", pOpponent_spec->car_spec->driver_name); - NewObjective(pOpponent_spec, eOOT_pursue_and_twat, &gProgram_state.current_car); - return; - } + pursuit_percentage += 50 * HeadOnWithPlayerPossible(pOpponent_spec); + do_it = PercentageChance(pursuit_percentage); + dr_dprintf("%s: Spotted player; chance of pursuing %d%%: %s", pOpponent_spec->car_spec->driver_name, pursuit_percentage, do_it ? "YES, Decided to pursue" : "NO, Decided NOT to pursue"); + if (do_it) { + gOpponents[pOpponent_spec->index].psyche.grudge_against_player = MIN(100, MAX(20, gOpponents[pOpponent_spec->index].psyche.grudge_against_player) + general_grudge_increase); + sprintf(str, "%s: I've decided to kill you for the fun of it", pOpponent_spec->car_spec->driver_name); + NewObjective(pOpponent_spec, eOOT_pursue_and_twat, &gProgram_state.current_car); + return; } } } } } - if (pMust_choose_one) { - dr_dprintf("%s: Choosing new objective because we have to...", pOpponent_spec->car_spec->driver_name, pOpponent_spec->car_spec->last_person_to_hit_us); - if (pOpponent_spec->has_moved_at_some_point) { - if (CAR_SPEC_IS_ROZZER(pOpponent_spec->car_spec)) { - NewObjective(pOpponent_spec, eOOT_return_to_start); - return; - } else { - if (gNum_of_opponents_getting_near + gNum_of_opponents_pursuing < 3 && pOpponent_spec->player_to_oppo_d > 10.0f) { - dr_dprintf("%s: Choosing to get_near because not enough oppos are yet (%d/%d)", pOpponent_spec->car_spec->driver_name, gNum_of_opponents_getting_near + gNum_of_opponents_pursuing, 3); - NewObjective(pOpponent_spec, eOOT_get_near_player); - return; - } - if (gNum_of_opponents_completing_race < 2) { - dr_dprintf("%s: Choosing to complete_race because not enough oppos are yet (%d/%d)", pOpponent_spec->car_spec->driver_name, gNum_of_opponents_completing_race, 2); - NewObjective(pOpponent_spec, eOOT_complete_race); - return; - } - - percentage = (int)pOpponent_spec->player_to_oppo_d - 15; - if (PercentageChance(percentage)) { - dr_dprintf("%s: Choosing to get_near because chance dictated it (%d%%)", pOpponent_spec->car_spec->driver_name, percentage); + if (!pMust_choose_one) { + return; + } + dr_dprintf("%s: Choosing new objective because we have to...", pOpponent_spec->car_spec->driver_name); + if (pOpponent_spec->has_moved_at_some_point) { + if (CAR_SPEC_IS_ROZZER(pOpponent_spec->car_spec)) { + NewObjective(pOpponent_spec, eOOT_return_to_start); + return; + } + if (gNum_of_opponents_pursuing + gNum_of_opponents_getting_near >= 3 || pOpponent_spec->player_to_oppo_d <= 10.0) { + if (gNum_of_opponents_completing_race >= 2) { + pursuit_percentage = pOpponent_spec->player_to_oppo_d - 15.0f; + if (PercentageChance(pursuit_percentage)) { + dr_dprintf("%s: Choosing to get_near because chance dictated it (%d%%)", pOpponent_spec->car_spec->driver_name, pursuit_percentage); NewObjective(pOpponent_spec, eOOT_get_near_player); return; } else { - dr_dprintf("%s: Choosing to complete_race because chance dictated it (%d%%)", pOpponent_spec->car_spec->driver_name, percentage); - NewObjective(pOpponent_spec, eOOT_complete_race); - return; + dr_dprintf("%s: Choosing to complete_race because chance dictated it (%d%%)", pOpponent_spec->car_spec->driver_name, pursuit_percentage); } + } else { + dr_dprintf("%s: Choosing to complete_race because not enough oppos are yet (%d/%d)", pOpponent_spec->car_spec->driver_name, gNum_of_opponents_completing_race, 2); } - - } else if (CAR_SPEC_IS_ROZZER(pOpponent_spec->car_spec)) { - NewObjective(pOpponent_spec, eOOT_wait_for_some_hapless_sod); - return; - } else if (pOpponent_spec->pursue_from_start && !gMellow_opponents) { - gOpponents[pOpponent_spec->index].psyche.grudge_against_player = MIN(100.f, pOpponent_spec->nastiness * 40.f + (MAX(20, gOpponents[pOpponent_spec->index].psyche.grudge_against_player) + 20)); - NewObjective(pOpponent_spec, eOOT_pursue_and_twat, &gProgram_state.current_car); - return; - - } else { NewObjective(pOpponent_spec, eOOT_complete_race); return; } + dr_dprintf("%s: Choosing to get_near because not enough oppos are yet (%d/%d)", pOpponent_spec->car_spec->driver_name, gNum_of_opponents_pursuing + gNum_of_opponents_getting_near, 3); + NewObjective(pOpponent_spec, eOOT_get_near_player); + return; } + if (CAR_SPEC_IS_ROZZER(pOpponent_spec->car_spec)) { + NewObjective(pOpponent_spec, eOOT_wait_for_some_hapless_sod); + return; + } + if (!pOpponent_spec->pursue_from_start || gMellow_opponents) { + NewObjective(pOpponent_spec, eOOT_complete_race); + return; + } + + gOpponents[pOpponent_spec->index].psyche.grudge_against_player = MIN(100, pOpponent_spec->nastiness * 40.0 + (MAX(20, gOpponents[pOpponent_spec->index].psyche.grudge_against_player) + 20)); + NewObjective(pOpponent_spec, eOOT_pursue_and_twat, &gProgram_state.current_car); } } @@ -1804,16 +1769,13 @@ void ChooseNewObjective(tOpponent_spec* pOpponent_spec, int pMust_choose_one) { void ProcessThisOpponent(tOpponent_spec* pOpponent_spec) { int i; - if ((!gMap_mode || !gShow_opponents) && (pOpponent_spec->last_in_view + 3000 < gTime_stamp_for_this_munging)) { - if (pOpponent_spec->cheating == 0) { - StartToCheat(pOpponent_spec); - } - } else { + if ((gMap_mode && gShow_opponents) || pOpponent_spec->last_in_view + 3000 >= gTime_stamp_for_this_munging) { if (pOpponent_spec->cheating) { OiStopCheating(pOpponent_spec); } + } else if (pOpponent_spec->cheating == 0) { + StartToCheat(pOpponent_spec); } - ChooseNewObjective(pOpponent_spec, pOpponent_spec->new_objective_required); pOpponent_spec->new_objective_required = 0; if (gCountdown || gRace_finished) { @@ -1855,39 +1817,32 @@ void RebuildActiveCarList(void) { gActive_car_list_rebuild_required = 0; gNum_active_cars = 0; - for (i = 0; i < 1; i++) { - if (i > 0) { - PDFatalError("mGet_car_count( eVehicle_self ) > 1 - I didn't know this could happen!"); - } - - car_spec = &gProgram_state.current_car; - if (!car_spec->disabled || gAction_replay_mode) { - gActive_car_list[gNum_active_cars] = car_spec; - gNum_active_cars++; - car_spec->active = 1; - } + if (!gProgram_state.current_car.disabled || gAction_replay_mode) { + gActive_car_list[gNum_active_cars] = &gProgram_state.current_car; + gNum_active_cars++; + gProgram_state.current_car.active = 1; } if (gNet_mode == eNet_mode_host) { for (i = 0; i < GetCarCount(eVehicle_net_player); i++) { car_spec = GetCarSpec(eVehicle_net_player, i); - if (!car_spec->disabled) { + if (car_spec->disabled) { + car_spec->active = 0; + } else { gActive_car_list[gNum_active_cars] = car_spec; gNum_active_cars++; car_spec->active = 1; - } else { - car_spec->active = 0; } } } else if (gNet_mode == eNet_mode_client) { for (i = 0; i < GetCarCount(eVehicle_net_player); i++) { car_spec = GetCarSpec(eVehicle_net_player, i); - if (!car_spec->disabled && IsNetCarActive(&car_spec->car_master_actor->t.t.translate.t)) { + if (car_spec->disabled || !IsNetCarActive(&car_spec->car_master_actor->t.t.translate.t)) { + car_spec->active = 0; + } else { gActive_car_list[gNum_active_cars] = car_spec; gNum_active_cars++; car_spec->active = 1; - } else { - car_spec->active = 0; } } } @@ -1901,13 +1856,12 @@ void RebuildActiveCarList(void) { car_spec->active = 0; } } - for (i = 0; i < gNumber_of_cops_before_faffage; i++) { + for (i = 0; gNumber_of_cops_before_faffage > i; ++i) { car_spec = GetCarSpec(eVehicle_rozzer, i); if (gProgram_state.AI_vehicles.cops[i].physics_me || gAction_replay_mode) { gActive_car_list[gNum_active_cars] = car_spec; gNum_active_cars++; car_spec->active = 1; - } else { } } } @@ -1929,7 +1883,7 @@ void StartToCheat(tOpponent_spec* pOpponent_spec) { dr_dprintf("%s: StartToCheat() - Starting to cheat", pOpponent_spec->car_spec->driver_name); pOpponent_spec->cheating = 1; - if (CAR_SPEC_IS_ROZZER(pOpponent_spec->car_spec)) { + if ((pOpponent_spec->car_spec->car_ID & 0xff00) == 0x300) { dr_dprintf("%s: StartToCheat() - Turning physics OFF", pOpponent_spec->car_spec->driver_name); TurnOpponentPhysicsOff(pOpponent_spec); RebuildActiveCarList(); @@ -1942,7 +1896,7 @@ void OiStopCheating(tOpponent_spec* pOpponent_spec) { dr_dprintf("%s: OiStopCheating() - End of cheating sesh", pOpponent_spec->car_spec->driver_name); pOpponent_spec->cheating = 0; - if (CAR_SPEC_IS_ROZZER(pOpponent_spec->car_spec)) { + if ((pOpponent_spec->car_spec->car_ID & 0xff00) == 0x300) { dr_dprintf("%s: OiStopCheating() - Turning physics ON", pOpponent_spec->car_spec->driver_name); TurnOpponentPhysicsOn(pOpponent_spec); RebuildActiveCarList(); @@ -1958,18 +1912,17 @@ int TeleportCopToStart(tOpponent_spec* pOpponent_spec) { return 0; } BrVector3Sub(&wank, &gProgram_state.current_car.car_master_actor->t.t.translate.t, &pOpponent_spec->start_pos); - if (BrVector3Length(&wank) > gIn_view_distance) { - BrVector3Copy(&pOpponent_spec->car_spec->car_master_actor->t.t.translate.t, &pOpponent_spec->start_pos); - PointActorAlongThisBloodyVector(pOpponent_spec->car_spec->car_master_actor, &pOpponent_spec->start_direction); - pOpponent_spec->physics_me = 0; - RematerialiseOpponent(pOpponent_spec, 0.0); - TurnOpponentPhysicsOff(pOpponent_spec); - RebuildActiveCarList(); - NewObjective(pOpponent_spec, eOOT_wait_for_some_hapless_sod); - return 1; + if (BrVector3Length(&wank) <= gIn_view_distance) { + return 0; } - - return 0; + pOpponent_spec->car_spec->car_master_actor->t.t.euler.t = pOpponent_spec->start_pos; + PointActorAlongThisBloodyVector(pOpponent_spec->car_spec->car_master_actor, &pOpponent_spec->start_direction); + pOpponent_spec->physics_me = 0; + RematerialiseOpponent(pOpponent_spec, 0.0); + TurnOpponentPhysicsOff(pOpponent_spec); + RebuildActiveCarList(); + NewObjective(pOpponent_spec, eOOT_wait_for_some_hapless_sod); + return 1; } // IDA: void __usercall CalcDistanceFromHome(tOpponent_spec *pOpponent_spec@) @@ -1990,34 +1943,32 @@ int MassageOpponentPosition(tOpponent_spec* pOpponent_spec, int pMassage_count) br_vector3 positive_y_vector; br_vector3 direction_v; + BrVector3Set(&positive_y_vector, 0.f, 1.f, 0.f); mat = &pOpponent_spec->car_spec->car_master_actor->t.t.mat; car_trans = &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t; if (pMassage_count > 22) { return 0; - } - - if (pMassage_count > 20) { + } else if (pMassage_count > 20) { car_trans->v[1] += (pMassage_count - 20) * 2.0f; + return 1; } else { - direction_v.v[0] = -mat->m[2][0]; - direction_v.v[1] = -mat->m[2][1]; - direction_v.v[2] = -mat->m[2][2]; - if (pMassage_count % 4 < 2) { - BrVector3Normalise(&displacement, &direction_v); - BrVector3Scale(&displacement, &displacement, (pMassage_count / 4) * 0.5f); - } else { - BrVector3Set(&positive_y_vector, 0.f, 1.f, 0.f); + direction_v.v[0] = -pOpponent_spec->car_spec->car_master_actor->t.t.mat.m[2][0]; + direction_v.v[1] = -pOpponent_spec->car_spec->car_master_actor->t.t.mat.m[2][1]; + direction_v.v[2] = -pOpponent_spec->car_spec->car_master_actor->t.t.mat.m[2][2]; + if (pMassage_count % 4 >= 2) { BrVector3Cross(&displacement, &positive_y_vector, &direction_v); BrVector3Normalise(&displacement, &displacement); BrVector3Scale(&displacement, &displacement, (pMassage_count / 4) * 0.1f); + } else { + BrVector3Normalise(&displacement, &direction_v); + BrVector3Scale(&displacement, &displacement, (pMassage_count / 4) * 0.5f); } if (pMassage_count % 2) { BrVector3Negate(&displacement, &displacement); } BrVector3Accumulate(car_trans, &displacement); + return 1; } - - return 1; } // IDA: int __usercall RematerialiseOpponentOnThisSection@(tOpponent_spec *pOpponent_spec@, br_scalar pSpeed, tS16 pSection_no) @@ -2040,38 +1991,36 @@ int RematerialiseOpponentOnThisSection(tOpponent_spec* pOpponent_spec, br_scalar } start = GetOpponentsSectionStartNodePoint(pOpponent_spec, pSection_no); finish = GetOpponentsSectionFinishNodePoint(pOpponent_spec, pSection_no); - BrVector3Sub(&a, finish, start); - length = BrVector3Length(&a); - if (length != 0.f) { - BrVector3Sub(&p, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t, start); - t = BrVector3Dot(&a, &p) / BrVector3LengthSquared(&a); + 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(&intersect, start); + BrVector3Copy(&p, start); } else if (t > 1.f) { - BrVector3Copy(&intersect, finish); + BrVector3Copy(&p, finish); } else { - BrVector3Scale(&intersect, &a, t); - BrVector3Add(&intersect, &intersect, start); + p.v[0] = start->v[0] + t * section_v.v[0]; + p.v[1] = start->v[1] + t * section_v.v[1]; + p.v[2] = start->v[2] + t * section_v.v[2]; } - BrVector3Copy(&pOpponent_spec->car_spec->car_master_actor->t.t.translate.t, &intersect); - BrVector3Sub(§ion_v, finish, start); - PointActorAlongThisBloodyVector(pOpponent_spec->car_spec->car_master_actor, §ion_v); + 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)) { - BrVector3Sub(&car_to_end, finish, &pOpponent_spec->car_spec->car_master_actor->t.t.translate.t); - distance_to_end = BrVector3Length(&car_to_end); - pOpponent_spec->car_spec->brake_force = 0.f; - pOpponent_spec->car_spec->acc_force = 0.f; - if (distance_to_end < 5.f) { - pOpponent_spec->car_spec->brake_force = 15.f * pOpponent_spec->car_spec->M; - } else { - pOpponent_spec->car_spec->acc_force = pOpponent_spec->car_spec->M / 2.f; - } - pOpponent_spec->last_in_view = gTime_stamp_for_this_munging; - return 1; - } else { + 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) @@ -2091,7 +2040,6 @@ int RematerialiseOpponentOnNearestSection(tOpponent_spec* pOpponent_spec, br_sca return 1; } section_no = FindNearestPathSection(&pOpponent_spec->car_spec->car_master_actor->t.t.translate.t, &direction_v, &intersect, &distance); - start = &gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[section_no].node_indices[0]].p; finish = &gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[section_no].node_indices[1]].p; BrVector3Copy(&pOpponent_spec->car_spec->car_master_actor->t.t.translate.t, &intersect); PointActorAlongThisBloodyVector(pOpponent_spec->car_spec->car_master_actor, &direction_v); @@ -2099,12 +2047,12 @@ int RematerialiseOpponentOnNearestSection(tOpponent_spec* pOpponent_spec, br_sca 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->brake_force = pOpponent_spec->car_spec->M * 15.0f; - } else { + 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.0f; + } else { + pOpponent_spec->car_spec->brake_force = pOpponent_spec->car_spec->M * 15.0f; } } return 0; @@ -2139,106 +2087,104 @@ int RematerialiseOpponent(tOpponent_spec* pOpponent_spec, br_scalar pSpeed) { this_total = 0; mat = &pOpponent_spec->car_spec->car_master_actor->t.t.mat; massage_count = 0; - theta = -BrRadianToAngle(atan2(mat->m[2][2], mat->m[2][0])) + BR_ANGLE_DEG(90); + phi = BrDegreeToAngle(90) - BrRadianToAngle(atan2(mat->m[2][2], mat->m[2][0])); if (pOpponent_spec->physics_me) { dr_dprintf("%s: Actually, we're already materialised", pOpponent_spec->car_spec->driver_name); - return 1; - } - total++; - BrMatrix34Copy(&original_mat, mat); - TurnOpponentPhysicsOn(pOpponent_spec); - RebuildActiveCarList(); - do { - count++; - this_total++; - BrVector3Scale((br_vector3*)mat->m[3], (br_vector3*)mat->m[3], WORLD_SCALE_D); - BrVector3Copy(&b, (br_vector3*)mat->m[3]); - BrMatrix34RotateY(mat, theta); - BrVector3Copy((br_vector3*)mat->m[3], &b); - BrVector3SetFloat(&b, 0.f, -100.f, 0.f); - BrVector3Copy(&a, (br_vector3*)mat->m[3]); - a.v[1] += 1.f; - findfloor(&a, &b, &norm, &dist); - a.v[1] += 100.f; - findfloor(&a, &b, &norm2, &dist2); - if (dist2 <= 1.f) { - BrVector3SetFloat(&b, 0.f, -5.01f, 0.f); - a.v[1] -= 100.f; - for (i = 0; i < 20; i++) { - a.v[1] += 5.f; - findfloor(&a, &b, &norm2, &dist2); - if (dist2 <= 1.f) { - break; - } - } - dist2 = (i + 1) * 0.05f + -dist2 / 20.f; - } - if (dist2 < dist) { - dist = -dist2; - BrVector3Copy(&norm, &norm2); - } - if (BR_ABS(dist) <= 1.f) { - mat->m[3][1] -= dist * 100.f - 2.f; - ts = BrVector3Dot((br_vector3*)mat->m[2], &norm); - phi = BrRadianToAngle(asin(ts)); - BrMatrix34PreRotateX(mat, phi); - ts = BrVector3Dot((br_vector3*)mat->m[0], &norm); - phi = -BrRadianToAngle(asin(ts)); - BrMatrix34PreRotateZ(mat, phi); - } - BrVector3Negate(&pOpponent_spec->car_spec->direction, (br_vector3*)mat->m[2]); - 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); - BrVector3InvScale((br_vector3*)mat->m[3], (br_vector3*)mat->m[3], WORLD_SCALE_D); - BrVector3Copy(&pOpponent_spec->car_spec->v, (br_vector3*)pOpponent_spec->car_spec->car_master_actor->t.t.mat.m[2]); - BrVector3Negate(&pOpponent_spec->car_spec->v, &pOpponent_spec->car_spec->v); - BrVector3Normalise(&pOpponent_spec->car_spec->v, &pOpponent_spec->car_spec->v); - BrVector3Scale(&pOpponent_spec->car_spec->v, &pOpponent_spec->car_spec->v, pSpeed * WORLD_SCALE_D); - BrVector3Set(&pOpponent_spec->car_spec->omega, 0.f, 0.f, 0.f); - pOpponent_spec->car_spec->curvature = 0.0; - BrMatrix34Copy(&pOpponent_spec->car_spec->oldmat, mat); - BrMatrix34Copy(&pOpponent_spec->car_spec->old_frame_mat, mat); - BrVector3Scale((br_vector3*)pOpponent_spec->car_spec->oldmat.m[3], (br_vector3*)pOpponent_spec->car_spec->oldmat.m[3], WORLD_SCALE); - for (j = 0; j < COUNT_OF(pOpponent_spec->car_spec->oldd); j++) { - pOpponent_spec->car_spec->oldd[j] = pOpponent_spec->car_spec->ride_height; - } - pOpponent_spec->car_spec->gear = 0; - pOpponent_spec->car_spec->revs = 0.f; - pOpponent_spec->car_spec->traction_control = 1; - 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) { - BrMatrix34Copy(mat, &original_mat); - } - } while (!sensible_place && MassageOpponentPosition(pOpponent_spec, massage_count++)); - - count--; - this_total--; - if (sensible_place) { - dr_dprintf("%s: Rematerialised (took %d attempts, orig. pos. (%7.3f,%7.3f,%7.3f), actual pos. (%7.3f,%7.3f,%7.3f))", - pOpponent_spec->car_spec->driver_name, - this_total + 1, - original_mat.m[3][0], original_mat.m[3][1], original_mat.m[3][2], - mat->m[3][0], mat->m[3][1], mat->m[3][2]); - } - if (this_total > highest) { - highest = this_total; - } - if (count != 0) { - dr_dprintf("MassageOpponentPosition() called an avg of %.1f times (max %d) per ReMaterialisation", - count / (float)total, highest); - } - if (!sensible_place) { - TurnOpponentPhysicsOff(pOpponent_spec); + } else { + total++; + BrMatrix34Copy(&original_mat, mat); + TurnOpponentPhysicsOn(pOpponent_spec); RebuildActiveCarList(); - TeleportOpponentToNearestSafeLocation(pOpponent_spec); - return 1; + while (1) { + count++; + BrVector3Scale((br_vector3*)mat->m[3], (br_vector3*)mat->m[3], WORLD_SCALE); + BrVector3Copy(&b, (br_vector3*)mat->m[3]); + BrMatrix34RotateY(mat, phi); + BrVector3Copy((br_vector3*)mat->m[3], &b); + BrVector3SetFloat(&b, 0.f, -100.f, 0.f); + BrVector3Copy(&a, (br_vector3*)mat->m[3]); + a.v[1] += 1.f; + findfloor(&a, &b, &norm, &dist); + a.v[1] += 100.f; + findfloor(&a, &b, &norm2, &dist2); + if (dist2 <= 1.f) { + BrVector3SetFloat(&b, 0.f, -5.01f, 0.f); + a.v[1] -= 100.f; + for (i = 0; i < 20; i++) { + a.v[1] += 5.f; + findfloor(&a, &b, &norm2, &dist2); + if (dist2 <= 1.f) { + break; + } + } + dist2 = (i + 1) * 0.05f - dist2 / 20.f; + } + if (dist2 < dist) { + dist = -dist2; + BrVector3Copy(&norm, &norm2); + } + if (fabs(dist) <= 1.f) { + mat->m[3][1] -= dist * 100.f - 2.f; + BrMatrix34PreRotateX(mat, BrRadianToAngle(asin(BrVector3Dot((br_vector3*)mat->m[2], &norm)))); + BrMatrix34PreRotateZ(mat, BrRadianToAngle(asin(BrVector3Dot((br_vector3*)mat->m[2], &norm)))); + } + BrVector3Negate(&pOpponent_spec->car_spec->direction, (br_vector3*)mat->m[2]); + 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); + BrVector3InvScale((br_vector3*)mat->m[3], (br_vector3*)mat->m[3], WORLD_SCALE); + BrVector3Copy(&pOpponent_spec->car_spec->v, (br_vector3*)pOpponent_spec->car_spec->car_master_actor->t.t.mat.m[2]); + BrVector3Negate(&pOpponent_spec->car_spec->v, &pOpponent_spec->car_spec->v); + BrVector3Normalise(&pOpponent_spec->car_spec->v, &pOpponent_spec->car_spec->v); + BrVector3Scale(&pOpponent_spec->car_spec->v, &pOpponent_spec->car_spec->v, pSpeed * WORLD_SCALE); + BrVector3Set(&pOpponent_spec->car_spec->omega, 0.f, 0.f, 0.f); + BrMatrix34Copy(&pOpponent_spec->car_spec->oldmat, mat); + BrMatrix34Copy(&pOpponent_spec->car_spec->old_frame_mat, mat); + BrVector3Scale((br_vector3*)pOpponent_spec->car_spec->oldmat.m[3], (br_vector3*)pOpponent_spec->car_spec->oldmat.m[3], WORLD_SCALE); + for (i = 0; i < COUNT_OF(pOpponent_spec->car_spec->oldd); i++) { + pOpponent_spec->car_spec->oldd[i] = pOpponent_spec->car_spec->ride_height; + } + pOpponent_spec->car_spec->gear = 0; + pOpponent_spec->car_spec->revs = 0.f; + pOpponent_spec->car_spec->traction_control = 1; + 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; + } else { + BrMatrix34Copy(mat, &original_mat); + } + if (!MassageOpponentPosition(pOpponent_spec, massage_count++)) { + break; + } + this_total++; + } + count--; + if (sensible_place) { + dr_dprintf("%s: Rematerialised (took %d attempts, orig. pos. (%7.3f,%7.3f,%7.3f), actual pos. (%7.3f,%7.3f,%7.3f))", + pOpponent_spec->car_spec->driver_name, + this_total + 1, + original_mat.m[3][0], original_mat.m[3][1], original_mat.m[3][2], + mat->m[3][0], mat->m[3][1], mat->m[3][2]); + } + if (this_total > highest) { + highest = this_total; + } + if (count != 0) { + dr_dprintf("MassageOpponentPosition() called an avg of %.1f times (max %d) per ReMaterialisation", + count / total, highest); + } + if (sensible_place) { + ResetCarSpecialVolume((tCollision_info*)pOpponent_spec->car_spec); + } else { + TurnOpponentPhysicsOff(pOpponent_spec); + RebuildActiveCarList(); + TeleportOpponentToNearestSafeLocation(pOpponent_spec); + } } - ResetCarSpecialVolume((tCollision_info*)pOpponent_spec->car_spec); return 1; } @@ -2296,18 +2242,16 @@ void ChallengeOccurred(int pChallenger_index, int pAccepted) { void LoadCopCars(void) { int i; - if (gProgram_state.AI_vehicles.number_of_cops != 0) { - for (i = 0; i < gProgram_state.AI_vehicles.number_of_cops; i++) { - PossibleService(); - gProgram_state.AI_vehicles.cops[i].car_spec = BrMemAllocate(sizeof(tCar_spec), kMem_cop_car_spec); - LoadCar( - gBIG_APC_index == i ? "BIGAPC.TXT" : "APC.TXT", - eDriver_oppo, - gProgram_state.AI_vehicles.cops[i].car_spec, - (gBIG_APC_index == i) ? 4 : 3, - "The Cops", - &gTheir_cars_storage_space); - } + for (i = 0; i < gProgram_state.AI_vehicles.number_of_cops; i++) { + PossibleService(); + gProgram_state.AI_vehicles.cops[i].car_spec = BrMemAllocate(sizeof(tCar_spec), kMem_cop_car_spec); + LoadCar( + gBIG_APC_index == i ? "BIGAPC.TXT" : "APC.TXT", + eDriver_oppo, + gProgram_state.AI_vehicles.cops[i].car_spec, + (gBIG_APC_index == i) ? 4 : 3, + "The Cops", + &gTheir_cars_storage_space); } } @@ -2334,6 +2278,10 @@ void LoadInOppoPaths(FILE* pF) { int sections_to_delete; int delete_these[1024]; + float x_0; + float x_1; + float x_2; + data_errors = 0; sections_to_delete = 0; dr_dprintf("Start of LoadInOppoPaths()..."); @@ -2346,86 +2294,79 @@ void LoadInOppoPaths(FILE* pF) { do { res = GetALineAndDontArgue(pF, s); } while (res && strcmp("START OF OPPONENT PATHS", s) != 0); - if (res == 0) { - // return; - - } else { - if (gNet_mode != eNet_mode_none) { - } + if (res) { ReallocExtraPathNodes(GetAnInt(pF)); - if (gProgram_state.AI_vehicles.number_of_path_nodes != 0) { - for (node_no = 0; node_no < gProgram_state.AI_vehicles.number_of_path_nodes; node_no++) { - ReadThreeFloats(pF, x, y, z); - gProgram_state.AI_vehicles.path_nodes[node_no].p.v[0] = x; - gProgram_state.AI_vehicles.path_nodes[node_no].p.v[1] = y; - gProgram_state.AI_vehicles.path_nodes[node_no].p.v[2] = z; - gProgram_state.AI_vehicles.path_nodes[node_no].number_of_sections = 0; - } + for (i = 0; i < gProgram_state.AI_vehicles.number_of_path_nodes; i++) { + GetThreeFloats(pF, &gProgram_state.AI_vehicles.path_nodes[i].p.v[0], &gProgram_state.AI_vehicles.path_nodes[i].p.v[1], &gProgram_state.AI_vehicles.path_nodes[i].p.v[2]); + gProgram_state.AI_vehicles.path_nodes[i].number_of_sections = 0; } ReallocExtraPathSections(GetAnInt(pF)); - if (gProgram_state.AI_vehicles.number_of_path_sections != 0) { - for (section_no = 0; section_no < gProgram_state.AI_vehicles.number_of_path_sections; section_no++) { - PossibleService(); - GetNScalars(pF, 8, scalars); - gProgram_state.AI_vehicles.path_sections[section_no].node_indices[0] = scalars[0]; - gProgram_state.AI_vehicles.path_sections[section_no].node_indices[1] = scalars[1]; - gProgram_state.AI_vehicles.path_sections[section_no].min_speed[0] = scalars[2]; - gProgram_state.AI_vehicles.path_sections[section_no].max_speed[0] = scalars[3]; - gProgram_state.AI_vehicles.path_sections[section_no].min_speed[1] = scalars[4]; - gProgram_state.AI_vehicles.path_sections[section_no].max_speed[1] = scalars[5]; - gProgram_state.AI_vehicles.path_sections[section_no].width = scalars[6]; + for (i = 0; i < gProgram_state.AI_vehicles.number_of_path_sections; i++) { + PossibleService(); + GetNScalars(pF, 8, scalars); + gProgram_state.AI_vehicles.path_sections[i].node_indices[0] = scalars[0]; + gProgram_state.AI_vehicles.path_sections[i].node_indices[1] = scalars[1]; + gProgram_state.AI_vehicles.path_sections[i].min_speed[0] = scalars[2]; + gProgram_state.AI_vehicles.path_sections[i].max_speed[0] = scalars[3]; + gProgram_state.AI_vehicles.path_sections[i].min_speed[1] = scalars[4]; + gProgram_state.AI_vehicles.path_sections[i].max_speed[1] = scalars[5]; + gProgram_state.AI_vehicles.path_sections[i].width = scalars[6]; + x = gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[i].node_indices[1]].p.v[0] + - gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[i].node_indices[0]].p.v[0]; + y = gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[i].node_indices[1]].p.v[1] + - gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[i].node_indices[0]].p.v[1]; + z = gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[i].node_indices[1]].p.v[2] + - gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[i].node_indices[0]].p.v[2]; - BrVector3Sub(§ion_v, - &gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[section_no].node_indices[1]].p, - &gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[section_no].node_indices[0]].p); - - gProgram_state.AI_vehicles.path_sections[section_no].length = BrVector3Length(§ion_v); - if (scalars[7] >= 1000.0f) { - gProgram_state.AI_vehicles.path_sections[section_no].type = (tU8)(scalars[7] - 1000.0f); - gProgram_state.AI_vehicles.path_sections[section_no].one_way = 1; - } else { - gProgram_state.AI_vehicles.path_sections[section_no].type = (tU8)scalars[7]; - gProgram_state.AI_vehicles.path_sections[section_no].one_way = 0; - } - for (node_no = 0; node_no < 2; node_no++) { - node_ptr = &gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[section_no].node_indices[node_no]]; - if (node_ptr->number_of_sections < 8) { - node_ptr->sections[node_ptr->number_of_sections] = (tS16)section_no; - node_ptr->number_of_sections++; - } else { - dr_dprintf("ERROR: Too many sections (including section #%d) attached to node #%d", - section_no, - gProgram_state.AI_vehicles.path_sections[section_no].node_indices[node_no]); - data_errors = 1; - } - } - BrVector3Sub(§ion_v, - &gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[section_no].node_indices[1]].p, - &gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[section_no].node_indices[0]].p); - - if (BrVector3LengthSquared(§ion_v) == 0.0f) { + gProgram_state.AI_vehicles.path_sections[i].length = sqrt(x * x + y * y + z * z); + if (scalars[7] < 1000.0f) { + gProgram_state.AI_vehicles.path_sections[i].type = (tU8)scalars[7]; + gProgram_state.AI_vehicles.path_sections[i].one_way = 0; + } else { + gProgram_state.AI_vehicles.path_sections[i].type = (tU8)(scalars[7] - 1000.0f); + gProgram_state.AI_vehicles.path_sections[i].one_way = 1; + } + for (j = 0; j < 2; j++) { + node_ptr = &gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[i].node_indices[j]]; + if (node_ptr->number_of_sections >= 8u) { dr_dprintf( - "ERROR: Opponent path section #%d has zero length (nodes #%d and #%d are in same position). Secti" - "on and one node will be deleted.", - section_no, - gProgram_state.AI_vehicles.path_sections[section_no].node_indices[0], - gProgram_state.AI_vehicles.path_sections[section_no].node_indices[1]); - delete_these[sections_to_delete] = section_no; - sections_to_delete++; + "ERROR: Too many sections (including section #%d) attached to node #%d", + i, + gProgram_state.AI_vehicles.path_sections[i].node_indices[j]); + data_errors = 1; + } else { + node_ptr->sections[node_ptr->number_of_sections] = (tS16)i; + node_ptr->number_of_sections++; } } + x = gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[i].node_indices[1]].p.v[0] + - gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[i].node_indices[0]].p.v[0]; + y = gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[i].node_indices[1]].p.v[1] + - gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[i].node_indices[0]].p.v[1]; + z = gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[i].node_indices[1]].p.v[2] + - gProgram_state.AI_vehicles.path_nodes[gProgram_state.AI_vehicles.path_sections[i].node_indices[0]].p.v[2]; + if (z * z + x * x + y * y == 0.0f) { + dr_dprintf( + "ERROR: Opponent path section #%d has zero length (nodes #%d and #%d are in same position). Secti" + "on and one node will be deleted.", + j, + gProgram_state.AI_vehicles.path_sections[i].node_indices[0], + gProgram_state.AI_vehicles.path_sections[i].node_indices[1]); + delete_these[sections_to_delete] = j; + sections_to_delete++; + } } if (data_errors) { PDFatalError("Opponent path data inconsistencies. Unable to rectumify them."); } if (sections_to_delete != 0) { - for (i = 0; i < sections_to_delete; i++) { - dr_dprintf("Deleting section #%d (was #%d)", delete_these[i], i + delete_these[i]); - DeleteSection(delete_these[i]); + for (j = 0; j < sections_to_delete; j++) { + dr_dprintf("Deleting section #%d (was #%d)", delete_these[j], j + delete_these[j]); + DeleteSection(delete_these[j]); DeleteOrphanNodes(); - for (j = i; j < sections_to_delete; j++) { - delete_these[i]--; + for (section_no = j; section_no < sections_to_delete; section_no++) { + delete_these[j]--; } } WriteOutOppoPaths(); @@ -2438,29 +2379,29 @@ void LoadInOppoPaths(FILE* pF) { } if (gAusterity_mode || gNet_mode != eNet_mode_none) { gProgram_state.AI_vehicles.number_of_cops = GetAnInt(pF); - for (i = 0; i < gProgram_state.AI_vehicles.number_of_cops; i++) { + for (j = 0; j < gProgram_state.AI_vehicles.number_of_cops; j++) { GetALineAndDontArgue(pF, s); } gProgram_state.AI_vehicles.number_of_cops = 0; } else { gProgram_state.AI_vehicles.number_of_cops = GetAnInt(pF); - if (gProgram_state.AI_vehicles.number_of_cops != 0) { - for (i = 0; i < gProgram_state.AI_vehicles.number_of_cops; i++) { - PossibleService(); - GetNScalars(pF, 6, scalars); - BrVector3Set(&gProgram_state.AI_vehicles.cop_start_points[i], scalars[0], scalars[1], scalars[2]); + for (j = 0; j < gProgram_state.AI_vehicles.number_of_cops; j++) { + PossibleService(); + GetNScalars(pF, 6, scalars); + BrVector3Set(&gProgram_state.AI_vehicles.cop_start_points[j], scalars[0], scalars[1], scalars[2]); - if (scalars[3] == 9.0f && scalars[4] == 9.0f && scalars[5] == 9.0f) { - gBIG_APC_index = i; - } + if (scalars[3] == 9.0f && scalars[4] == 9.0f && scalars[5] == 9.0f) { + gBIG_APC_index = j; + } - section_no = FindNearestPathSection(&gProgram_state.AI_vehicles.cop_start_points[i], §ion_v, &intersect, &distance); - BrVector3Set(&positive_y_vector, 0.0, 1.0, 0.0); - BrVector3Cross(&gProgram_state.AI_vehicles.cop_start_vectors[i], &positive_y_vector, §ion_v); - BrVector3Sub(&cop_to_section, &intersect, &gProgram_state.AI_vehicles.cop_start_points[i]); - if (BrVector3Dot(&gProgram_state.AI_vehicles.cop_start_vectors[i], &cop_to_section) < 0.0f) { - BrVector3Negate(&gProgram_state.AI_vehicles.cop_start_vectors[i], &gProgram_state.AI_vehicles.cop_start_vectors[i]); - } + FindNearestPathSection(&gProgram_state.AI_vehicles.cop_start_points[j], &cop_to_section, &intersect, &distance); + BrVector3Set(&gProgram_state.AI_vehicles.cop_start_vectors[j], + cop_to_section.v[2] * 1.0f - cop_to_section.v[1] * 0.0f, + cop_to_section.v[0] * 0.0f - cop_to_section.v[2] * 0.0f, + cop_to_section.v[1] * 0.0f - cop_to_section.v[0] * 1.0f); + BrVector3Sub(§ion_v, &intersect, &gProgram_state.AI_vehicles.cop_start_points[j]); + if (BrVector3Dot(&gProgram_state.AI_vehicles.cop_start_vectors[j], §ion_v) < 0.0f) { + BrVector3Negate(&gProgram_state.AI_vehicles.cop_start_vectors[j], &gProgram_state.AI_vehicles.cop_start_vectors[j]); } } } @@ -2492,12 +2433,11 @@ void DisposeOpponentPaths(void) { if (gBit_per_node != NULL) { BrMemFree(gBit_per_node); } - + gBit_per_node = NULL; gProgram_state.AI_vehicles.number_of_path_nodes = 0; gProgram_state.AI_vehicles.number_of_path_sections = 0; gProgram_state.AI_vehicles.path_nodes = NULL; gProgram_state.AI_vehicles.path_sections = NULL; - gBit_per_node = NULL; } // IDA: void __usercall MungeOpponents(tU32 pFrame_period@) @@ -2514,72 +2454,79 @@ void MungeOpponents(tU32 pFrame_period) { gAcme_frame_count++; gTime_stamp_for_this_munging = GetTotalTime(); gFrame_period_for_this_munging = pFrame_period; - gFrame_period_for_this_munging_in_secs = gFrame_period_for_this_munging / 1000.f; + gFrame_period_for_this_munging_in_secs = pFrame_period / 1000.f; if (!gAcknowledged_start && !gCountdown) { gAcknowledged_start = 1; if (!gStart_jumped) { un_stun_flag = 1; } } - if (gProgram_state.current_car.no_of_processes_recording_my_trail != 0) { - RecordNextTrailNode(&gProgram_state.current_car); - } else { + if (gProgram_state.current_car.no_of_processes_recording_my_trail == 0) { StartRecordingTrail(&gProgram_state.current_car); + } else { + RecordNextTrailNode(&gProgram_state.current_car); } TrackElasticateyPath(); - if (!gProcessing_opponents) { - return; - } - gNum_of_opponents_pursuing = 0; - gNum_of_opponents_getting_near = 0; - gNum_of_opponents_completing_race = 0; - for (i = 0; i < gProgram_state.AI_vehicles.number_of_opponents; i++) { - if (!gProgram_state.AI_vehicles.opponents[i].finished_for_this_race) { - if (gProgram_state.AI_vehicles.opponents[i].current_objective == eOOT_pursue_and_twat) { - gNum_of_opponents_pursuing++; - } else if (gProgram_state.AI_vehicles.opponents[i].current_objective == eOOT_get_near_player) { - - gNum_of_opponents_getting_near++; - - } else if (gProgram_state.AI_vehicles.opponents[i].current_objective == eOOT_complete_race) { - gNum_of_opponents_completing_race++; - } - } - } - for (i = 0; i < gProgram_state.AI_vehicles.number_of_opponents; i++) { - if (!gProgram_state.AI_vehicles.opponents[i].finished_for_this_race) { - if (un_stun_flag) { - UnStunTheBugger(&gProgram_state.AI_vehicles.opponents[i]); - } - CalcOpponentConspicuousnessWithAViewToCheatingLikeFuck(&gProgram_state.AI_vehicles.opponents[i]); - CalcPlayerConspicuousness(&gProgram_state.AI_vehicles.opponents[i]); - ProcessThisOpponent(&gProgram_state.AI_vehicles.opponents[i]); - ClearTwattageOccurrenceVariables(&gProgram_state.AI_vehicles.opponents[i]); - } - } - for (i = 0; i < gNumber_of_cops_before_faffage; i++) { - if (!gProgram_state.AI_vehicles.cops[i].finished_for_this_race) { - if (un_stun_flag) { - UnStunTheBugger(&gProgram_state.AI_vehicles.cops[i]); - } - CalcDistanceFromHome(&gProgram_state.AI_vehicles.cops[i]); - CalcOpponentConspicuousnessWithAViewToCheatingLikeFuck(&gProgram_state.AI_vehicles.cops[i]); - CalcPlayerConspicuousness(&gProgram_state.AI_vehicles.cops[i]); - ProcessThisOpponent(&gProgram_state.AI_vehicles.cops[i]); - ClearTwattageOccurrenceVariables(&gProgram_state.AI_vehicles.cops[i]); - gProgram_state.AI_vehicles.cops[i].murder_reported = 0; - } - } - if (gNext_grudge_reduction < gTime_stamp_for_this_munging) { - gNext_grudge_reduction = gTime_stamp_for_this_munging + 3000; + if (gProcessing_opponents) { + gNum_of_opponents_pursuing = 0; + gNum_of_opponents_getting_near = 0; + gNum_of_opponents_completing_race = 0; for (i = 0; i < gProgram_state.AI_vehicles.number_of_opponents; i++) { if (!gProgram_state.AI_vehicles.opponents[i].finished_for_this_race) { - gOpponents[gProgram_state.AI_vehicles.opponents[i].index].psyche.grudge_against_player -= MIN(gOpponents[gProgram_state.AI_vehicles.opponents[i].index].psyche.grudge_against_player, gGrudge_reduction_per_period); + switch (gProgram_state.AI_vehicles.opponents[i].current_objective) { + case eOOT_pursue_and_twat: + gNum_of_opponents_pursuing++; + break; + case eOOT_get_near_player: + gNum_of_opponents_getting_near++; + break; + case eOOT_complete_race: + gNum_of_opponents_completing_race++; + break; + default: + break; + } } } + for (i = 0; i < gProgram_state.AI_vehicles.number_of_opponents; i++) { + if (!gProgram_state.AI_vehicles.opponents[i].finished_for_this_race) { + if (un_stun_flag) { + UnStunTheBugger(&gProgram_state.AI_vehicles.opponents[i]); + } + CalcOpponentConspicuousnessWithAViewToCheatingLikeFuck(&gProgram_state.AI_vehicles.opponents[i]); + CalcPlayerConspicuousness(&gProgram_state.AI_vehicles.opponents[i]); + ProcessThisOpponent(&gProgram_state.AI_vehicles.opponents[i]); + ClearTwattageOccurrenceVariables(&gProgram_state.AI_vehicles.opponents[i]); + } + } + for (i = 0; i < gNumber_of_cops_before_faffage; i++) { + if (!gProgram_state.AI_vehicles.cops[i].finished_for_this_race) { + if (un_stun_flag) { + UnStunTheBugger(&gProgram_state.AI_vehicles.cops[i]); + } + CalcDistanceFromHome(&gProgram_state.AI_vehicles.cops[i]); + CalcOpponentConspicuousnessWithAViewToCheatingLikeFuck(&gProgram_state.AI_vehicles.cops[i]); + CalcPlayerConspicuousness(&gProgram_state.AI_vehicles.cops[i]); + ProcessThisOpponent(&gProgram_state.AI_vehicles.cops[i]); + ClearTwattageOccurrenceVariables(&gProgram_state.AI_vehicles.cops[i]); + gProgram_state.AI_vehicles.cops[i].murder_reported = 0; + } + } + if (gNext_grudge_reduction < gTime_stamp_for_this_munging) { + gNext_grudge_reduction = gTime_stamp_for_this_munging + 3000; + for (i = 0; i < gProgram_state.AI_vehicles.number_of_opponents; i++) { + if (!gProgram_state.AI_vehicles.opponents[i].finished_for_this_race) { + if (gOpponents[gProgram_state.AI_vehicles.opponents[i].index].psyche.grudge_against_player >= gGrudge_reduction_per_period) { + gOpponents[gProgram_state.AI_vehicles.opponents[i].index].psyche.grudge_against_player -= gGrudge_reduction_per_period; + } else { + gOpponents[gProgram_state.AI_vehicles.opponents[i].index].psyche.grudge_against_player = 0; + } + } + } + } + RebuildActiveCarList(); + gFirst_frame = 0; } - RebuildActiveCarList(); - gFirst_frame = 0; } // IDA: void __cdecl SetInitialCopPositions() @@ -2605,6 +2552,8 @@ void InitOpponents(tRace_info* pRace_info) { int rank_dependent_difficulty; int skill_dependent_difficulty; br_bounds bounds; + tCar_spec* car_spec; + tOpponent_spec* opponent_spec; gNext_grudge_reduction = gTime_stamp_for_this_munging + 8000; gGrudge_reduction_per_period = 3 - gProgram_state.skill_level; @@ -2612,28 +2561,29 @@ void InitOpponents(tRace_info* pRace_info) { gFirst_frame = 1; gAcknowledged_start = 0; gStart_jumped = 0; - gNum_viewable_cars = 0; - gViewable_car_list[gNum_viewable_cars] = &gProgram_state.current_car; - gNum_viewable_cars++; + gViewable_car_list[0] = &gProgram_state.current_car; + gNum_viewable_cars = 1; BrActorToBounds(&bounds, gProgram_state.track_spec.the_actor); gMinimum_yness_before_knackerisation = bounds.min.v[1] - 2.f; gDefinite_no_cop_pursuit_speed = 17.8788f; gDefinite_cop_pursuit_speed = 44.697f; gCop_pursuit_speed_percentage_multiplier = 100.f / (gDefinite_cop_pursuit_speed - gDefinite_no_cop_pursuit_speed); - gHead_on_cos_value = cos(0.5235668420791626f); + gHead_on_cos_value = cos(.5235668f); gAcme_frame_count = 0; gProgram_state.current_car.no_of_processes_recording_my_trail = 0; - rank_dependent_difficulty = (101.0 - (gCurrent_race.suggested_rank < 10 ? 0.5 : gCurrent_race.suggested_rank)) / 10.0; - skill_dependent_difficulty = gProgram_state.skill_level * 5; - gBig_bang = 70.f - (2 * skill_dependent_difficulty + 3 * rank_dependent_difficulty) * gOpponent_nastyness_frigger; - gIn_view_distance = MAX(gCamera_yon + 10.f, 45.f); + rank_dependent_difficulty = (101.f - (gCurrent_race.suggested_rank < 10 ? .5f : gCurrent_race.suggested_rank)) / 10.0f; + gBig_bang = 70.f - (3 * rank_dependent_difficulty + 10 * gProgram_state.skill_level) * gOpponent_nastyness_frigger; + gIn_view_distance = gCamera_yon + 10.f; + if (gCamera_yon + 10.f <= 45.f) { + gIn_view_distance = 45.f; + } gTime_stamp_for_this_munging = GetTotalTime(); gFrame_period_for_this_munging = 1; gFrame_period_for_this_munging_in_secs = gFrame_period_for_this_munging / 1000.f; - if (gNet_mode != eNet_mode_none) { - gProgram_state.AI_vehicles.number_of_opponents = 0; - } else { + if (gNet_mode == eNet_mode_none) { gProgram_state.AI_vehicles.number_of_opponents = pRace_info->number_of_racers - 1; + } else { + gProgram_state.AI_vehicles.number_of_opponents = 0; } gNumber_of_cops_before_faffage = gProgram_state.AI_vehicles.number_of_cops; for (i = 0, opponent_number = 0; i < gProgram_state.AI_vehicles.number_of_opponents; i++, opponent_number++) { @@ -2642,7 +2592,7 @@ void InitOpponents(tRace_info* pRace_info) { opponent_number++; } gProgram_state.AI_vehicles.opponents[i].car_spec = pRace_info->opponent_list[opponent_number].car_spec; - gProgram_state.AI_vehicles.opponents[i].car_spec->car_ID = i + 0x200; + gProgram_state.AI_vehicles.opponents[i].car_spec->car_ID = i | 0x200; dr_dprintf("Car '%s', car_ID %x", gProgram_state.AI_vehicles.opponents[i].car_spec->driver_name, gProgram_state.AI_vehicles.opponents[i].car_spec->car_ID); @@ -2673,11 +2623,10 @@ void InitOpponents(tRace_info* pRace_info) { gProgram_state.AI_vehicles.opponents[i].has_moved_at_some_point = 0; gProgram_state.AI_vehicles.opponents[i].player_in_view_now = 0; gProgram_state.AI_vehicles.opponents[i].acknowledged_piv = 0; - - gProgram_state.AI_vehicles.opponents[i].nastiness = ((99.0 - (gCurrent_race.suggested_rank < 10 ? 0.5 : gCurrent_race.suggested_rank)) / 98.0 - + (gOpponents[gProgram_state.AI_vehicles.opponents[i].index].strength_rating - 1) / 4.0 - + gProgram_state.skill_level / 2.0) - / 3.0 * gOpponent_nastyness_frigger; + gProgram_state.AI_vehicles.opponents[i].nastiness = (gProgram_state.skill_level / 2.f + + ((float)(gOpponents[gProgram_state.AI_vehicles.opponents[i].index].strength_rating - 1)) / 4.f + + (99.f - (gCurrent_race.suggested_rank < 10 ? .5f : (float)gCurrent_race.suggested_rank)) / 98.f) + / 3.f * gOpponent_nastyness_frigger; BrVector3Set(&gProgram_state.AI_vehicles.opponents[i].pos_last_frame, 0.f, 0.f, 0.f); gOpponents[gProgram_state.AI_vehicles.opponents[i].index].psyche.grudge_against_player = 10; gViewable_car_list[gNum_viewable_cars] = gProgram_state.AI_vehicles.opponents[i].car_spec; @@ -2685,20 +2634,18 @@ void InitOpponents(tRace_info* pRace_info) { StunTheBugger(&gProgram_state.AI_vehicles.opponents[i], 10000); } if (gChallenger_index__opponent >= 0) { - tCar_spec* car_spec; - tOpponent_spec* opponent_spec; car_spec = GetCarSpecFromGlobalOppoIndex(gChallenger_index__opponent); opponent_spec = GetOpponentSpecFromCarSpec(car_spec); - if (opponent_spec != NULL) { - opponent_spec->pursue_from_start = 1; - } else { + if (opponent_spec == NULL) { dr_dprintf("ERROR - can't record dare - no opponent_spec for car_spec"); + } else { + opponent_spec->pursue_from_start = 1; } gChallenger_index__opponent = -1; } for (i = 0; i < gProgram_state.AI_vehicles.number_of_cops; i++) { PossibleService(); - gProgram_state.AI_vehicles.cops[i].car_spec->car_ID = i + 0x300; + gProgram_state.AI_vehicles.cops[i].car_spec->car_ID = i | 0x300; gProgram_state.AI_vehicles.cops[i].index = 3; gProgram_state.AI_vehicles.cops[i].time_last_processed = gTime_stamp_for_this_munging; gProgram_state.AI_vehicles.cops[i].time_this_objective_started = gTime_stamp_for_this_munging; @@ -2721,15 +2668,10 @@ void InitOpponents(tRace_info* pRace_info) { gProgram_state.AI_vehicles.cops[i].has_moved_at_some_point = 0; gProgram_state.AI_vehicles.cops[i].player_in_view_now = 0; gProgram_state.AI_vehicles.cops[i].acknowledged_piv = 0; -#ifdef DETHRACE_FIX_BUGS - gProgram_state.AI_vehicles.cops[i].nastiness = -#else - gProgram_state.AI_vehicles.opponents[i].nastiness = -#endif - ((99.0 - (gCurrent_race.suggested_rank < 10 ? 0.5 : gCurrent_race.suggested_rank)) / 98.0 - + gProgram_state.skill_level / 2.0 + 2.25) + gProgram_state.AI_vehicles.cops[i].nastiness = (gProgram_state.skill_level / 2.f + + (99.f - (gCurrent_race.suggested_rank < 10 ? .5f : (float)gCurrent_race.suggested_rank)) / 98.f + + 2.25f) / 3.f * gOpponent_nastyness_frigger; - BrVector3Copy(&gProgram_state.AI_vehicles.cops[i].start_pos, &gProgram_state.AI_vehicles.cop_start_points[i]); BrVector3Copy(&gProgram_state.AI_vehicles.cops[i].start_direction, &gProgram_state.AI_vehicles.cop_start_vectors[i]); BrVector3Set(&gProgram_state.AI_vehicles.cops[i].pos_last_frame, 0.f, 0.f, 0.f); @@ -2739,7 +2681,6 @@ void InitOpponents(tRace_info* pRace_info) { gProgram_state.AI_vehicles.cops[i].car_spec->last_person_we_hit = NULL; gProgram_state.AI_vehicles.cops[i].car_spec->last_collision_time = 0; gProgram_state.AI_vehicles.cops[i].car_spec->last_time_we_touched_a_player = 0; - gProgram_state.AI_vehicles.cops[i].car_spec->no_of_processes_recording_my_trail = 0; gProgram_state.AI_vehicles.cops[i].car_spec->grudge_raised_recently = 1; gOpponents[gProgram_state.AI_vehicles.cops[i].index].psyche.grudge_against_player = 10; StunTheBugger(&gProgram_state.AI_vehicles.cops[i], 10000); @@ -2752,11 +2693,10 @@ void InitOpponents(tRace_info* pRace_info) { // FUNCTION: CARM95 0x0040b186 void DisposeOpponents(void) { int i; - if (gProgram_state.AI_vehicles.number_of_cops != 0) { - for (i = 0; i < gProgram_state.AI_vehicles.number_of_cops; i++) { - DisposeCar(gProgram_state.AI_vehicles.cops[i].car_spec, (i == gBIG_APC_index) ? 4 : 3); - BrMemFree(gProgram_state.AI_vehicles.cops[i].car_spec); - } + + for (i = 0; i < gProgram_state.AI_vehicles.number_of_cops; i++) { + DisposeCar(gProgram_state.AI_vehicles.cops[i].car_spec, (i == gBIG_APC_index) ? 4 : 3); + BrMemFree(gProgram_state.AI_vehicles.cops[i].car_spec); } } @@ -2767,14 +2707,22 @@ void WakeUpOpponentsToTheFactThatTheStartHasBeenJumped(int pWhat_the_countdown_w for (i = 0; i < gProgram_state.AI_vehicles.number_of_opponents; i++) { UnStunTheBugger(&gProgram_state.AI_vehicles.opponents[i]); - StunTheBugger(&gProgram_state.AI_vehicles.opponents[i], MIN(IRandomBetween(1000, 2500), 1000 * pWhat_the_countdown_was)); + if (IRandomBetween(1000, 2500) < 1000 * pWhat_the_countdown_was) { + StunTheBugger(&gProgram_state.AI_vehicles.opponents[i], IRandomBetween(1000, 2500)); + } else { + StunTheBugger(&gProgram_state.AI_vehicles.opponents[i], 1000 * pWhat_the_countdown_was); + } } for (i = 0; i < gProgram_state.AI_vehicles.number_of_cops; i++) { UnStunTheBugger(&gProgram_state.AI_vehicles.cops[i]); - StunTheBugger(&gProgram_state.AI_vehicles.cops[i], MIN(IRandomBetween(1000, 2500), 1000 * pWhat_the_countdown_was)); + if (IRandomBetween(1000, 2500) < 1000 * pWhat_the_countdown_was) { + StunTheBugger(&gProgram_state.AI_vehicles.cops[i], IRandomBetween(1000, 2500)); + } else { + StunTheBugger(&gProgram_state.AI_vehicles.cops[i], 1000 * pWhat_the_countdown_was); + } } - gAcknowledged_start = 1; gStart_jumped = 1; + gAcknowledged_start = 1; } // IDA: void __usercall ReportMurderToPoliceDepartment(tCar_spec *pCar_spec@) @@ -2797,12 +2745,16 @@ int GetCarCount(tVehicle_type pCategory) { case eVehicle_self: return 1; + case eVehicle_net_player: + if (gNet_mode) { + return gNumber_of_net_players - 1; + } else { + return 0; + } + break; case eVehicle_opponent: return gProgram_state.AI_vehicles.number_of_opponents; - case eVehicle_net_player: - return gNet_mode ? gNumber_of_net_players - 1 : 0; - case eVehicle_rozzer: return gNumber_of_cops_before_faffage; @@ -2811,9 +2763,10 @@ int GetCarCount(tVehicle_type pCategory) { case eVehicle_not_really: return gNum_active_non_cars; - } - return 0; + default: + return 0; + } } // IDA: tCar_spec* __usercall GetCarSpec@(tVehicle_type pCategory@, int pIndex@) @@ -2826,7 +2779,11 @@ tCar_spec* GetCarSpec(tVehicle_type pCategory, int pIndex) { return &gProgram_state.current_car; case eVehicle_net_player: - return pIndex >= gThis_net_player_index ? gNet_players[pIndex + 1].car : gNet_players[pIndex].car; + if (gThis_net_player_index > pIndex) { + return gNet_players[pIndex].car; + } else { + return gNet_players[pIndex + 1].car; + } case eVehicle_opponent: return gProgram_state.AI_vehicles.opponents[pIndex].car_spec; @@ -2840,8 +2797,10 @@ tCar_spec* GetCarSpec(tVehicle_type pCategory, int pIndex) { case eVehicle_not_really: return (tCar_spec*)gActive_non_car_list[pIndex]; + + default: + return 0; } - return 0; } // IDA: char* __usercall GetDriverName@(tVehicle_type pCategory@, int pIndex@) @@ -2854,18 +2813,13 @@ char* GetDriverName(tVehicle_type pCategory, int pIndex) { case eVehicle_opponent: return gOpponents[gProgram_state.AI_vehicles.opponents[pIndex].index].name; case eVehicle_rozzer: - return gCop_name; + return "Faceless Cop"; case eVehicle_drone: - return gDrone_name; + return "Innocent Civilian"; case eVehicle_not_really: - return NULL; - -#ifdef DETHRACE_FIX_BUGS default: - break; -#endif + return NULL; } - return NULL; } // IDA: tOpponent_spec* __usercall GetOpponentSpecFromCarSpec@(tCar_spec *pCar_spec@) @@ -2873,13 +2827,13 @@ char* GetDriverName(tVehicle_type pCategory, int pIndex) { tOpponent_spec* GetOpponentSpecFromCarSpec(tCar_spec* pCar_spec) { int i; - if (CAR_SPEC_IS_OPPONENT(pCar_spec)) { + if ((pCar_spec->car_ID & 0xff00) == 0x200) { for (i = 0; i < GetCarCount(eVehicle_opponent); i++) { if (gProgram_state.AI_vehicles.opponents[i].car_spec == pCar_spec) { return &gProgram_state.AI_vehicles.opponents[i]; } } - } else if (CAR_SPEC_IS_ROZZER(pCar_spec)) { + } else if ((pCar_spec->car_ID & 0xff00) == 0x300) { for (i = 0; i < GetCarCount(eVehicle_rozzer); i++) { if (gProgram_state.AI_vehicles.cops[i].car_spec == pCar_spec) { return &gProgram_state.AI_vehicles.cops[i]; @@ -2908,22 +2862,25 @@ int GetOpponentsRealSection(tOpponent_spec* pOpponent_spec, int pSection_no) { if (pSection_no >= 20000) { return pOpponent_spec->next_sections[pSection_no - 20000].section_no; - } else if (pSection_no < 10000) { + } else if (pSection_no >= 10000) { + return -1; + } else { return pSection_no; } - return -1; } // IDA: int __usercall GetOpponentsFirstSection@(tOpponent_spec *pOpponent_spec@) // FUNCTION: CARM95 0x0040b806 int GetOpponentsFirstSection(tOpponent_spec* pOpponent_spec) { - if (pOpponent_spec->current_objective == eOOT_pursue_and_twat) { - if (pOpponent_spec->pursue_car_data.state == ePCS_following_trail) { - return pOpponent_spec->follow_path_data.section_no; - } else if (pOpponent_spec->pursue_car_data.state == ePCS_following_line_of_sight) { - return 10000; - } + if (pOpponent_spec->current_objective != eOOT_pursue_and_twat) { + return 20000; + } + if (pOpponent_spec->pursue_car_data.state == ePCS_following_trail) { + return pOpponent_spec->follow_path_data.section_no; + } + if (pOpponent_spec->pursue_car_data.state == ePCS_following_line_of_sight) { + return 10000; } return 20000; } @@ -2931,15 +2888,18 @@ int GetOpponentsFirstSection(tOpponent_spec* pOpponent_spec) { // IDA: int __usercall GetOpponentsNextSection@(tOpponent_spec *pOpponent_spec@, tS16 pCurrent_section@) // FUNCTION: CARM95 0x0040b86e int GetOpponentsNextSection(tOpponent_spec* pOpponent_spec, tS16 pCurrent_section) { - if (pCurrent_section >= 20000) { - if (pCurrent_section - 19999 < pOpponent_spec->nnext_sections && (pOpponent_spec->cheating || gProgram_state.AI_vehicles.path_sections[pCurrent_section - 19999].type != ePST_cheat_only)) { - return pCurrent_section + 1; + + if (pCurrent_section < 20000) { + if (pCurrent_section < 15000) { + return -1; + } else { + return CalcNextTrailSection(pOpponent_spec, pCurrent_section); } + } else if (pCurrent_section - 19999 >= pOpponent_spec->nnext_sections || (!pOpponent_spec->cheating && gProgram_state.AI_vehicles.path_sections[pCurrent_section - 19999].type == ePST_cheat_only)) { return -1; - } else if (pCurrent_section >= 15000) { - return CalcNextTrailSection(pOpponent_spec, pCurrent_section); + } else { + return pCurrent_section + 1; } - return -1; } // IDA: tS16 __usercall GetOpponentsSectionStartNode@(tOpponent_spec *pOpponent_spec@, tS16 pSection@) @@ -2949,11 +2909,16 @@ tS16 GetOpponentsSectionStartNode(tOpponent_spec* pOpponent_spec, tS16 pSection) int node_index_index; if (pSection >= 20000 && pSection - 20000 < pOpponent_spec->nnext_sections) { - section_no = pOpponent_spec->next_sections[pSection - 20000].section_no; node_index_index = pOpponent_spec->next_sections[pSection - 20000].direction == 0; - return pOpponent_spec->nnext_sections >= pSection - 20000 ? gProgram_state.AI_vehicles.path_sections[section_no].node_indices[node_index_index] : -1; + 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); + 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; } @@ -2965,13 +2930,12 @@ tS16 GetOpponentsSectionFinishNode(tOpponent_spec* pOpponent_spec, tS16 pSection int node_index_index; if (pSection >= 20000 && pSection - 20000 < pOpponent_spec->nnext_sections) { - section_no = pOpponent_spec->next_sections[pSection - 20000].section_no; - node_index_index = pOpponent_spec->next_sections[pSection - 20000].direction; - return gProgram_state.AI_vehicles.path_sections[section_no].node_indices[node_index_index]; + 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); + 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 -1; + return 0; } // IDA: br_vector3* __usercall GetOpponentsSectionStartNodePoint@(tOpponent_spec *pOpponent_spec@, tS16 pSection@) @@ -2983,17 +2947,20 @@ br_vector3* GetOpponentsSectionStartNodePoint(tOpponent_spec* pOpponent_spec, tS if (pSection >= 20000 && pOpponent_spec->nnext_sections > pSection - 20000) { section_no = pOpponent_spec->next_sections[pSection - 20000].section_no; - node_index_index = pOpponent_spec->next_sections[pSection - 20000].direction == 0; - node_no = gProgram_state.AI_vehicles.path_sections[section_no].node_indices[node_index_index]; + node_index_index = pOpponent_spec->next_sections[pSection - 20000].direction; + node_no = gProgram_state.AI_vehicles.path_sections[section_no].node_indices[node_index_index == 0]; return &gProgram_state.AI_vehicles.path_nodes[node_no].p; - } else if (pSection >= 15000) { + } + + if (pSection >= 15000) { return &pOpponent_spec->pursue_car_data.pursuee->my_trail.trail_nodes[pSection - 15000]; - } else if (pSection == 10000) { + } + if (pSection == 10000) { return &pOpponent_spec->pursue_car_data.direct_line_nodes[0].p; } dr_dprintf("BIG ERROR - GetOpponentsSectionStartNodePoint() - section not found in next_section array for opponent %s", pOpponent_spec->car_spec->driver_name); PDEnterDebugger("BIG ERROR - GetOpponentsSectionStartNodePoint()"); - return NULL; + return 0; } // IDA: br_vector3* __usercall GetOpponentsSectionFinishNodePoint@(tOpponent_spec *pOpponent_spec@, tS16 pSection@) @@ -3012,11 +2979,12 @@ br_vector3* GetOpponentsSectionFinishNodePoint(tOpponent_spec* pOpponent_spec, t return &pOpponent_spec->pursue_car_data.pursuee->my_trail.trail_nodes[(pSection + 1) - 15000]; } else if (pSection == 10000) { return &pOpponent_spec->pursue_car_data.direct_line_nodes[1].p; + } else { + dr_dprintf("BIG ERROR - GetOpponentsSectionFinishNodePoint() - section not found in next_section array for opponent %s", + pOpponent_spec->car_spec->driver_name); + PDEnterDebugger("BIG ERROR - GetOpponentsSectionFinishNodePoint()"); + return NULL; } - dr_dprintf("BIG ERROR - GetOpponentsSectionFinishNodePoint() - section not found in next_section array for opponent %s", - pOpponent_spec->car_spec->driver_name); - PDEnterDebugger("BIG ERROR - GetOpponentsSectionFinishNodePoint()"); - return NULL; } // IDA: br_scalar __usercall GetOpponentsSectionWidth@(tOpponent_spec *pOpponent_spec@, tS16 pSection@) @@ -3025,9 +2993,11 @@ br_scalar GetOpponentsSectionWidth(tOpponent_spec* pOpponent_spec, tS16 pSection if (pSection >= 20000 && pSection - 20000 < pOpponent_spec->nnext_sections) { return gProgram_state.AI_vehicles.path_sections[pOpponent_spec->next_sections[pSection - 20000].section_no].width; - } else if (pSection >= 15000) { + } + if (pSection >= 15000) { return 0.5f; - } else if (pSection == 10000) { + } + if (pSection == 10000) { return pOpponent_spec->pursue_car_data.direct_line_section.width; } return gProgram_state.AI_vehicles.path_sections[pSection].width; @@ -3042,10 +3012,12 @@ int GetOpponentsSectionMinSpeed(tOpponent_spec* pOpponent_spec, tS16 pSection, i if (pSection >= 20000 && pSection - 20000 < pOpponent_spec->nnext_sections) { section_no = pOpponent_spec->next_sections[pSection - 20000].section_no; direction = pOpponent_spec->next_sections[pSection - 20000].direction; - return gProgram_state.AI_vehicles.path_sections[section_no].min_speed[(direction ^ pTowards_finish) == 0]; - } else if (pSection >= 15000) { + return gProgram_state.AI_vehicles.path_sections[section_no].min_speed[pTowards_finish == direction]; + } + if (pSection >= 15000) { return 0; - } else if (pSection == 10000) { + } + if (pSection == 10000) { return pOpponent_spec->pursue_car_data.direct_line_section.min_speed[pTowards_finish]; } dr_dprintf("WARNING - GetOpponentsSectionMinSpeed() - section not found in next_section array for opponent %s", pOpponent_spec->car_spec->driver_name); @@ -3062,10 +3034,12 @@ int GetOpponentsSectionMaxSpeed(tOpponent_spec* pOpponent_spec, tS16 pSection, i if (pSection >= 20000 && pSection - 20000 < pOpponent_spec->nnext_sections) { section_no = pOpponent_spec->next_sections[pSection - 20000].section_no; direction = pOpponent_spec->next_sections[pSection - 20000].direction; - return gProgram_state.AI_vehicles.path_sections[section_no].max_speed[(direction ^ pTowards_finish) == 0]; - } else if (pSection >= 15000) { + return gProgram_state.AI_vehicles.path_sections[section_no].max_speed[pTowards_finish == direction]; + } + if (pSection >= 15000) { return 255; - } else if (pSection == 10000) { + } + if (pSection == 10000) { return pOpponent_spec->pursue_car_data.direct_line_section.max_speed[pTowards_finish]; } dr_dprintf("WARNING - GetOpponentsSectionMaxSpeed() - section not found in next_section array for opponent %s", pOpponent_spec->car_spec->driver_name); @@ -3076,8 +3050,6 @@ int GetOpponentsSectionMaxSpeed(tOpponent_spec* pOpponent_spec, tS16 pSection, i // IDA: void __usercall InitOpponentPsyche(int pOpponent_index@) // FUNCTION: CARM95 0x0040bf68 void InitOpponentPsyche(int pOpponent_index) { - int i; - gOpponents[pOpponent_index].psyche.grudge_against_player = 0; } @@ -3121,7 +3093,7 @@ void RecordOpponentTwattageOccurrence(tCar_spec* pTwatter, tCar_spec* pTwattee) return; } damage = pTwattee->damage_magnitude_accumulator; - bangness = MIN(sqrt(damage * 300000.0), 100); + bangness = MIN(sqrt(damage * 300000.0f), 100); grudginess_caused_by_damage = bangness / 10 + 50 * CAR_SPEC_IS_ROZZER(pTwattee); dr_dprintf("Frame %0.6d: %s hit %s, damage %f, bangness %d, gBig_bang %d, grudginess %d", gAcme_frame_count, @@ -3131,68 +3103,65 @@ void RecordOpponentTwattageOccurrence(tCar_spec* pTwatter, tCar_spec* pTwattee) bangness, gBig_bang, grudginess_caused_by_damage); - if (gMin_bangness > bangness) { - gMin_bangness = bangness; - dr_dprintf("(New gMin_bangness - %d)", gMin_bangness); - } else { + if (gMin_bangness <= bangness) { if (gMax_bangness < bangness) { gMax_bangness = bangness; - dr_dprintf("(New gMax_bangness - %d)", gMax_bangness); + dr_dprintf("(New gMax_bangness - %d)", bangness); } - } - if (bangness < 5) { - return; - } - pTwatter->last_collision_time = gTime_stamp_for_this_munging; - pTwatter->last_person_we_hit = pTwattee; - pTwattee->last_collision_time = gTime_stamp_for_this_munging; - pTwattee->last_person_to_hit_us = pTwatter; - pTwattee->grudge_raised_recently = 1; - if (bangness >= gBig_bang || CAR_SPEC_IS_ROZZER(pTwattee)) { - pTwattee->big_bang = 1; - } - if (bangness >= 80) { - pTwattee->scary_bang = 1; - } - if (pTwatter->driver == eDriver_local_human) { - twattee_opponent_spec = GetOpponentSpecFromCarSpec(pTwattee); - if (pTwattee->scary_bang) { - StunTheBugger(twattee_opponent_spec, 30 * MIN(bangness, 100) + 1000); - } - twattee_index = twattee_opponent_spec->index; - new_grudge_value = grudginess_caused_by_damage + gOpponents[twattee_index].psyche.grudge_against_player; - if (new_grudge_value > 100) { - new_grudge_value = 100; - } - gOpponents[twattee_index].psyche.grudge_against_player = new_grudge_value; - } else if (pTwattee->driver == eDriver_local_human) { - twatter_opponent_spec = GetOpponentSpecFromCarSpec(pTwatter); - if (twatter_opponent_spec->current_objective == eOOT_pursue_and_twat && twatter_opponent_spec->pursue_car_data.pursuee == pTwattee) { - twatter_opponent_spec->pursue_car_data.time_last_twatted_em = gTime_stamp_for_this_munging; - } - twatter_index = twatter_opponent_spec->index; - new_grudge_value = gOpponents[twatter_index].psyche.grudge_against_player - (twatter_opponent_spec->current_objective == eOOT_pursue_and_twat ? 0 : 2 * grudginess_caused_by_damage); - if (new_grudge_value < 0) { - new_grudge_value = 0; - } - gOpponents[twatter_index].psyche.grudge_against_player = new_grudge_value; } else { - twatter_opponent_spec = GetOpponentSpecFromCarSpec(pTwatter); - twattee_opponent_spec = GetOpponentSpecFromCarSpec(pTwattee); - if (pTwattee->scary_bang) { - StunTheBugger(twattee_opponent_spec, 30 * bangness + 1000); + gMin_bangness = bangness; + dr_dprintf("(New gMin_bangness - %d)", bangness); + } + if (bangness >= 5) { + pTwatter->last_collision_time = gTime_stamp_for_this_munging; + pTwatter->last_person_we_hit = pTwattee; + pTwattee->last_collision_time = gTime_stamp_for_this_munging; + pTwattee->last_person_to_hit_us = pTwatter; + pTwattee->grudge_raised_recently = 1; + if (bangness >= gBig_bang || CAR_SPEC_IS_ROZZER(pTwattee)) { + pTwattee->big_bang = 1; } - twatter_index = twatter_opponent_spec->index; - twattee_index = twattee_opponent_spec->index; - if (twatter_opponent_spec->current_objective == eOOT_pursue_and_twat && twatter_opponent_spec->pursue_car_data.pursuee == pTwattee) { - twatter_opponent_spec->pursue_car_data.time_last_twatted_em = gTime_stamp_for_this_munging; + if (bangness >= 80) { + pTwattee->scary_bang = 1; } - if (CAR_SPEC_IS_OPPONENT(pTwatter) && CAR_SPEC_IS_ROZZER(pTwattee)) { - new_grudge_value = grudginess_caused_by_damage + gOpponents[twattee_index].psyche.grudge_against_player; + if (pTwatter->driver == eDriver_local_human) { + twattee_opponent_spec = GetOpponentSpecFromCarSpec(pTwattee); + if (pTwattee->scary_bang) { + StunTheBugger(twattee_opponent_spec, 30 * bangness + 1000); + } + new_grudge_value = grudginess_caused_by_damage + gOpponents[twattee_opponent_spec->index].psyche.grudge_against_player; if (new_grudge_value > 100) { new_grudge_value = 100; } - gOpponents[twattee_index].psyche.grudge_against_player = new_grudge_value; + gOpponents[twattee_opponent_spec->index].psyche.grudge_against_player = new_grudge_value; + } else if (pTwattee->driver == eDriver_local_human) { + twatter_opponent_spec = GetOpponentSpecFromCarSpec(pTwatter); + if (twatter_opponent_spec->current_objective == eOOT_pursue_and_twat && twatter_opponent_spec->pursue_car_data.pursuee == pTwattee) { + twatter_opponent_spec->pursue_car_data.time_last_twatted_em = gTime_stamp_for_this_munging; + } + twatter_index = twatter_opponent_spec->index; + new_grudge_value = gOpponents[twatter_index].psyche.grudge_against_player - (twatter_opponent_spec->current_objective == eOOT_pursue_and_twat ? 0 : 2 * grudginess_caused_by_damage); + if (new_grudge_value < 0) { + new_grudge_value = 0; + } + gOpponents[twatter_index].psyche.grudge_against_player = new_grudge_value; + } else { + twatter_opponent_spec = GetOpponentSpecFromCarSpec(pTwatter); + twattee_opponent_spec = GetOpponentSpecFromCarSpec(pTwattee); + if (pTwattee->scary_bang) { + StunTheBugger(twattee_opponent_spec, 30 * bangness + 1000); + } + twattee_index = twattee_opponent_spec->index; + if (twatter_opponent_spec->current_objective == eOOT_pursue_and_twat && twatter_opponent_spec->pursue_car_data.pursuee == pTwattee) { + twatter_opponent_spec->pursue_car_data.time_last_twatted_em = gTime_stamp_for_this_munging; + } + if (CAR_SPEC_IS_OPPONENT(pTwatter) && CAR_SPEC_IS_ROZZER(pTwattee)) { + new_grudge_value = grudginess_caused_by_damage + gOpponents[twattee_index].psyche.grudge_against_player; + if (new_grudge_value > 100) { + new_grudge_value = 100; + } + gOpponents[twattee_index].psyche.grudge_against_player = new_grudge_value; + } } } } @@ -3200,6 +3169,7 @@ void RecordOpponentTwattageOccurrence(tCar_spec* pTwatter, tCar_spec* pTwattee) // IDA: void __cdecl ToggleOpponentTest() // FUNCTION: CARM95 0x0040c537 void ToggleOpponentTest(void) { + gTest_toggle = !gTest_toggle; } @@ -3252,10 +3222,9 @@ void RepairOpponentsSystems(void) { int i; for (i = 0; i < gProgram_state.AI_vehicles.number_of_opponents; i++) { - if (!gProgram_state.AI_vehicles.opponents[i].finished_for_this_race) { + if (!gProgram_state.AI_vehicles.opponents[i].pursue_from_start) { TotallyRepairACar(gProgram_state.AI_vehicles.opponents[i].car_spec); - TurnOpponentPhysicsOn(&gProgram_state.AI_vehicles.opponents[i]); - NewObjective(&gProgram_state.AI_vehicles.opponents[i], eOOT_complete_race); + TurnOpponentPhysicsOff(&gProgram_state.AI_vehicles.opponents[i]); gProgram_state.AI_vehicles.opponents[i].knackeredness_detected = 0; } } @@ -3298,20 +3267,20 @@ void DeleteSection(tS16 pSection_to_delete) { tS16 node_no_index; tS16 found_it; - for (node_no_index = 0; node_no_index < 2; node_no_index++) { - node_no = gProgram_state.AI_vehicles.path_sections[pSection_to_delete].node_indices[node_no_index]; - if (node_no >= 0) { + for (node_no = 0; node_no < 2; node_no++) { + node_no_index = gProgram_state.AI_vehicles.path_sections[pSection_to_delete].node_indices[node_no]; + if (node_no_index >= 0) { found_it = 0; - for (section_no_index = 0; section_no_index < (gProgram_state.AI_vehicles.path_nodes[node_no].number_of_sections - 1); section_no_index++) { - if (gProgram_state.AI_vehicles.path_nodes[node_no].sections[section_no_index] == pSection_to_delete) { + for (section_no = 0; section_no < (gProgram_state.AI_vehicles.path_nodes[node_no_index].number_of_sections - 1); section_no++) { + if (gProgram_state.AI_vehicles.path_nodes[node_no_index].sections[section_no] == pSection_to_delete) { found_it = 1; } if (found_it) { - gProgram_state.AI_vehicles.path_nodes[node_no].sections[section_no_index] = gProgram_state.AI_vehicles.path_nodes[node_no].sections[section_no_index + 1]; + gProgram_state.AI_vehicles.path_nodes[node_no_index].sections[section_no] = gProgram_state.AI_vehicles.path_nodes[node_no_index].sections[section_no + 1]; } } - if (gProgram_state.AI_vehicles.path_nodes[node_no].number_of_sections != 0) { - gProgram_state.AI_vehicles.path_nodes[node_no].number_of_sections--; + if (gProgram_state.AI_vehicles.path_nodes[node_no_index].number_of_sections != 0) { + gProgram_state.AI_vehicles.path_nodes[node_no_index].number_of_sections--; } } } @@ -3405,12 +3374,10 @@ void InsertThisNodeInThisSectionHere(tS16 pInserted_node, tS16 pSection_no, br_v tS16 node2; tS16 node3; - node1 = gProgram_state.AI_vehicles.path_sections[pSection_no].node_indices[0]; - node2 = pInserted_node; - node3 = gProgram_state.AI_vehicles.path_sections[pSection_no].node_indices[1]; + 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] = node2; - gProgram_state.AI_vehicles.path_sections[new_section].node_indices[1] = node3; + 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]; @@ -3418,21 +3385,21 @@ void InsertThisNodeInThisSectionHere(tS16 pInserted_node, tS16 pSection_no, br_v 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] = node2; + 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[node2].p, pWhere); - gProgram_state.AI_vehicles.path_nodes[node2].sections - [gProgram_state.AI_vehicles.path_nodes[node2].number_of_sections] + 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[node2].number_of_sections++; // = gProgram_state.AI_vehicles.path_nodes[node2].number_of_sections + 1; - gProgram_state.AI_vehicles.path_nodes[node2].sections - [gProgram_state.AI_vehicles.path_nodes[node2].number_of_sections] + 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[node2].number_of_sections++; - for (section_no_index = 0; section_no_index < gProgram_state.AI_vehicles.path_nodes[node3].number_of_sections; section_no_index++) { - if (gProgram_state.AI_vehicles.path_nodes[node3].sections[section_no_index] == pSection_no) { - gProgram_state.AI_vehicles.path_nodes[node3].sections[section_no_index] = 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; } } } @@ -3466,64 +3433,50 @@ void RecalcNearestPathSectionSpeed(int pMax_not_min, int pAdjustment) { int new_speed; int nearest_end; - if (!gOppo_paths_shown) { - return; - } - if (gAlready_elasticating) { -#ifdef DETHRACE_FIX_BUGS - // section_no is used uninitialized otherwise. Perhaps this should `return` here instead? - section_no = 0; -#endif - } else { + if (gOppo_paths_shown) { section_no = FindNearestPathSection(&gSelf->t.t.translate.t, &direction_v, &intersect, &distance); - if (distance > 10.f) { + if (!gAlready_elasticating && distance > 10.f) { NewTextHeadupSlot(eHeadupSlot_misc, 0, 2000, -1, "Can't find any paths close enough"); - return; + } 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(eHeadupSlot_misc, 0, 2000, -1, str); } } - 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); - if (dist_to_finish < dist_to_start) { - nearest_end = 1; - } else { - nearest_end = 0; - } - pAdjustment *= 5; - - if (pMax_not_min) { - new_speed = gProgram_state.AI_vehicles.path_sections[section_no].max_speed[nearest_end] + pAdjustment; - } else { - new_speed = gProgram_state.AI_vehicles.path_sections[section_no].min_speed[nearest_end] + pAdjustment; - } - - if (pAdjustment < 0 && new_speed > 100) { - new_speed = 100; - } else if (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.2 * gProgram_state.AI_vehicles.path_sections[section_no].min_speed[nearest_end]), - (int)(2.2 * 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.2 * gProgram_state.AI_vehicles.path_sections[section_no].min_speed[nearest_end]), - (int)(2.2 * gProgram_state.AI_vehicles.path_sections[section_no].max_speed[nearest_end])); - } - ShowOppoPaths(); - NewTextHeadupSlot(eHeadupSlot_misc, 0, 2000, -1, str); } // IDA: void __cdecl RecalcNearestPathSectionWidth(br_scalar pAdjustment) @@ -3535,26 +3488,24 @@ void RecalcNearestPathSectionWidth(br_scalar pAdjustment) { br_scalar distance; char str[128]; - if (!gOppo_paths_shown) { - return; - } - if (gAlready_elasticating) { - section_no = gMobile_section; - } else { - section_no = FindNearestPathSection(&gSelf->t.t.translate.t, &direction_v, &intersect, &distance); - if (distance > 10.f) { - NewTextHeadupSlot(eHeadupSlot_misc, 0, 2000, -1, "Can't find any paths close enough"); - return; + if (gOppo_paths_shown) { + if (!gAlready_elasticating) { + section_no = FindNearestPathSection(&gSelf->t.t.translate.t, &direction_v, &intersect, &distance); + if (distance > 10.f) { + NewTextHeadupSlot(eHeadupSlot_misc, 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(eHeadupSlot_misc, 0, 2000, -1, str); } - pAdjustment = (int)pAdjustment * pAdjustment + pAdjustment; - gProgram_state.AI_vehicles.path_sections[section_no].width += 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.0 * gProgram_state.AI_vehicles.path_sections[section_no].width); - NewTextHeadupSlot(eHeadupSlot_misc, 0, 2000, -1, str); } // IDA: void __usercall CalcNegativeXVector(br_vector3 *pNegative_x_vector@, br_vector3 *pStart@, br_vector3 *pFinish@, br_scalar pLength) @@ -3563,9 +3514,13 @@ void CalcNegativeXVector(br_vector3* pNegative_x_vector, br_vector3* pStart, br_ br_vector3 positive_y_vector; br_vector3 path_vector; - BrVector3Set(&positive_y_vector, 0, 1.0, 0.0); - BrVector3Sub(&path_vector, pFinish, pStart); - BrVector3Cross(pNegative_x_vector, &positive_y_vector, &path_vector); + positive_y_vector.v[0] = pFinish->v[0] - pStart->v[0]; + positive_y_vector.v[1] = pFinish->v[1] - pStart->v[1]; + positive_y_vector.v[2] = pFinish->v[2] - pStart->v[2]; + pNegative_x_vector->v[0] = 1.0 * positive_y_vector.v[2] - positive_y_vector.v[1] * 0.0; + pNegative_x_vector->v[1] = 0.0 * positive_y_vector.v[0] - positive_y_vector.v[2] * 0.0; + pNegative_x_vector->v[2] = positive_y_vector.v[1] * 0.0 - 1.0 * positive_y_vector.v[0]; + BrVector3Normalise(pNegative_x_vector, pNegative_x_vector); BrVector3Scale(pNegative_x_vector, pNegative_x_vector, pLength); } @@ -3614,13 +3569,13 @@ void MakeSection(br_uint_16 pFirst_vertex, br_uint_16 pFirst_face, br_vector3* p height = .3f; BrVector3Set(&offset_v, 0.f, 0.f, 0.f); the_material_finish_lt = pMaterial_centre_lt; - the_material_start_lt = the_material_finish_lt; + the_material_start_lt = pMaterial_centre_lt; the_material_finish_dk = pMaterial_centre_dk; - the_material_start_dk = the_material_finish_dk; + the_material_start_dk = pMaterial_centre_dk; } - BrVector3Sub(¢re_length_v, pFinish, pStart); - BrVector3InvScale(¢re_length_v, ¢re_length_v, 2); - BrVector3Accumulate(¢re_length_v, pStart); + 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); @@ -3642,8 +3597,10 @@ void MakeCube(br_uint_16 pFirst_vertex, br_uint_16 pFirst_face, br_vector3* pPoi br_vector3 offset_v; br_vector3 point; - BrVector3Copy(&point, pPoint); + point.v[0] = pPoint->v[0]; + point.v[1] = pPoint->v[1]; point.v[1] += .15f; + point.v[2] = pPoint->v[2]; BrVector3Set(&offset_v, .1f, .1f, .1f); MakeVertexAndOffsetIt(gOppo_path_model, pFirst_vertex + 0, point.v[0], point.v[1], point.v[2], &offset_v); @@ -3692,7 +3649,6 @@ void ReallocModelFacesAndVertices(br_model* pModel, int pNum_faces, int pNum_ver int i; new_vertices = BrResAllocate(pModel, pNum_vertices * sizeof(br_vertex), BR_MEMORY_VERTICES); - // this is something like BrMemSet32 in the dissassembly, although no such function exists in open-source BRender memset(new_vertices, 0, pNum_vertices * sizeof(br_vertex)); if (pModel->nvertices != 0) { for (i = 0; i < ((pNum_vertices <= pModel->nvertices) ? pNum_vertices : pModel->nvertices); i++) { @@ -3705,7 +3661,6 @@ void ReallocModelFacesAndVertices(br_model* pModel, int pNum_faces, int pNum_ver pModel->nvertices = pNum_vertices; new_faces = BrResAllocate(pModel, pNum_faces * sizeof(br_face), BR_MEMORY_FACES); - // this is something like BrMemSet32 in the dissassembly, although no such function exists in open-source BRender memset(new_faces, 0, pNum_faces * sizeof(br_face)); if (pModel->nfaces != 0) { for (i = 0; i < ((pNum_faces <= pModel->nfaces) ? pNum_faces : pModel->nfaces); i++) { @@ -3776,7 +3731,6 @@ void RebuildOppoPathModel(void) { br_material* edge_mat_finish_lt; br_material* edge_mat_finish_dk; - at_least_one = 0; if (gProgram_state.AI_vehicles.number_of_path_nodes < 2) { if (gOppo_path_model != NULL) { BrModelRemove(gOppo_path_model); @@ -3849,20 +3803,14 @@ void RebuildOppoPathModel(void) { centre_mat_lt, centre_mat_dk, edge_mat_start_lt, edge_mat_start_dk, edge_mat_finish_lt, edge_mat_finish_dk); - at_least_one = 1; } - - first_face = 12 * gProgram_state.AI_vehicles.number_of_path_sections; - first_vertex = 18 * gProgram_state.AI_vehicles.number_of_path_sections; - for (i = 0; i < gProgram_state.AI_vehicles.number_of_cops; i++) { - MakeCube(first_vertex + 8 * i, - first_face + 12 * 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); - at_least_one = 1; } BrModelUpdate(gOppo_path_model, BR_MODU_ALL); } @@ -3879,8 +3827,8 @@ int ConsistencyCheck(void) { tS16 section_no_index1; int found_how_many; int failed; - tU8* nodes_referenced_by_sections_array; - tU8* sections_referenced_by_nodes_array; + tU8* nodes_referenced_by_sections_array = NULL; + tU8* sections_referenced_by_nodes_array = NULL; failed = 0; if (gProgram_state.AI_vehicles.number_of_path_nodes != 0) { @@ -3891,70 +3839,64 @@ int ConsistencyCheck(void) { sections_referenced_by_nodes_array = BrMemAllocate(gProgram_state.AI_vehicles.number_of_path_sections, kMem_sections_array); memset(sections_referenced_by_nodes_array, 0, gProgram_state.AI_vehicles.number_of_path_sections); } - for (section_no = 0; section_no < gProgram_state.AI_vehicles.number_of_path_sections; section_no++) { - start_node = gProgram_state.AI_vehicles.path_sections[section_no].node_indices[0]; - finish_node = gProgram_state.AI_vehicles.path_sections[section_no].node_indices[1]; + for (section_no_index = 0; section_no_index < gProgram_state.AI_vehicles.number_of_path_sections; section_no_index++) { + start_node = gProgram_state.AI_vehicles.path_sections[section_no_index].node_indices[0]; + finish_node = gProgram_state.AI_vehicles.path_sections[section_no_index].node_indices[1]; if (finish_node == start_node) { - dr_dprintf("CONSISTENCY FAILURE: Section #%d has both ends attached to same node!", section_no); + dr_dprintf("CONSISTENCY FAILURE: Section #%d has both ends attached to same node!", section_no_index); failed = 1; } - if (start_node < 0 || gProgram_state.AI_vehicles.number_of_path_nodes - 1 < start_node) { - dr_dprintf( - "CONSISTENCY FAILURE: Section #%d references invalid node (#%d) - should be in range 0..%d", - section_no, start_node, gProgram_state.AI_vehicles.number_of_path_nodes - 1); - failed = 1; - } else { + if (start_node >= 0 && gProgram_state.AI_vehicles.number_of_path_nodes - 1 >= start_node) { nodes_referenced_by_sections_array[start_node] = 1; nodes_referenced_by_sections_array[finish_node] = 1; found_how_many = 0; - for (section_no_index = 0; section_no_index < gProgram_state.AI_vehicles.path_nodes[start_node].number_of_sections; section_no_index++) { - if (gProgram_state.AI_vehicles.path_nodes[start_node].sections[section_no_index] == section_no) { + for (section_no_index1 = 0; section_no_index1 < gProgram_state.AI_vehicles.path_nodes[start_node].number_of_sections; section_no_index1++) { + if (gProgram_state.AI_vehicles.path_nodes[start_node].sections[section_no_index1] == section_no_index) { found_how_many++; } } if (found_how_many == 0) { dr_dprintf( "CONSISTENCY FAILURE: Section #%d references node #%d but not vice-versa", - section_no, + section_no_index, start_node); failed = 1; } - } - if (finish_node < 0 || gProgram_state.AI_vehicles.number_of_path_nodes - 1 < finish_node) { + } else { dr_dprintf( "CONSISTENCY FAILURE: Section #%d references invalid node (#%d) - should be in range 0..%d", - section_no, - finish_node, + section_no_index, + start_node, gProgram_state.AI_vehicles.number_of_path_nodes - 1); failed = 1; - - } else { + } + if (finish_node >= 0 && gProgram_state.AI_vehicles.number_of_path_nodes - 1 >= finish_node) { found_how_many = 0; - for (section_no_index = 0; section_no_index < gProgram_state.AI_vehicles.path_nodes[finish_node].number_of_sections; section_no_index++) { - if (gProgram_state.AI_vehicles.path_nodes[finish_node].sections[section_no_index] == section_no) { + for (section_no_index1 = 0; section_no_index1 < gProgram_state.AI_vehicles.path_nodes[finish_node].number_of_sections; section_no_index1++) { + if (gProgram_state.AI_vehicles.path_nodes[finish_node].sections[section_no_index1] == section_no_index) { found_how_many++; } } if (found_how_many == 0) { dr_dprintf( "CONSISTENCY FAILURE: Section #%d references node #%d but not vice-versa", - section_no, + section_no_index, finish_node); failed = 1; } + } else { + dr_dprintf( + "CONSISTENCY FAILURE: Section #%d references invalid node (#%d) - should be in range 0..%d", + section_no_index, + finish_node, + gProgram_state.AI_vehicles.number_of_path_nodes - 1); + failed = 1; } } for (node_no = 0; node_no < gProgram_state.AI_vehicles.number_of_path_nodes; node_no++) { for (section_no_index = 0; section_no_index < gProgram_state.AI_vehicles.path_nodes[node_no].number_of_sections; section_no_index++) { section_no = gProgram_state.AI_vehicles.path_nodes[node_no].sections[section_no_index]; - if (section_no < 0 || gProgram_state.AI_vehicles.number_of_path_sections - 1 < section_no) { - dr_dprintf( - "CONSISTENCY FAILURE: Node #%d references invalid section (#%d) - should be in range 0..%d", - node_no, - section_no, - gProgram_state.AI_vehicles.number_of_path_sections - 1); - failed = 1; - } else { + if (section_no >= 0 && gProgram_state.AI_vehicles.number_of_path_sections - 1 >= section_no) { sections_referenced_by_nodes_array[section_no] = 1; if (gProgram_state.AI_vehicles.path_sections[section_no].node_indices[0] != node_no && gProgram_state.AI_vehicles.path_sections[section_no].node_indices[1] != node_no) { @@ -3964,12 +3906,18 @@ int ConsistencyCheck(void) { section_no); failed = 1; } + } else { + dr_dprintf( + "CONSISTENCY FAILURE: Node #%d references invalid section (#%d) - should be in range 0..%d", + node_no, + section_no, + gProgram_state.AI_vehicles.number_of_path_sections - 1); + failed = 1; } found_how_many = 0; - for (section_no_index1 = section_no_index; section_no_index1 < gProgram_state.AI_vehicles.path_nodes[node_no].number_of_sections; section_no_index1++) { + for (section_no_index1 = section_no; section_no_index1 < gProgram_state.AI_vehicles.path_nodes[node_no].number_of_sections; section_no_index1++) { if (gProgram_state.AI_vehicles.path_nodes[node_no].sections[section_no_index1] == section_no) { found_how_many++; - } else { } } if (found_how_many > 1) { @@ -4006,9 +3954,8 @@ int ConsistencyCheck(void) { gProgram_state.AI_vehicles.number_of_path_nodes); dr_dprintf("^^^ CONSISTENCY FAILURE ^^^"); PDEnterDebugger("OPPONENT PATH CONSISTENCY FAILURE - refer to DIAGNOST.TXT"); - return 0; } - return 1; + return !failed; } // IDA: void __cdecl ShowOppoPaths() @@ -4016,17 +3963,17 @@ int ConsistencyCheck(void) { void ShowOppoPaths(void) { char str[256]; - if (gOppo_paths_shown) { + if (!gOppo_paths_shown) { + if (gOppo_path_actor != NULL) { + gOppo_path_actor->render_style = BR_RSTYLE_NONE; + } + NewTextHeadupSlot(eHeadupSlot_misc, 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(eHeadupSlot_misc, 0, 3000, -1, str); - } else { - if (gOppo_path_actor != NULL) { - gOppo_path_actor->render_style = BR_RSTYLE_NONE; - } - NewTextHeadupSlot(eHeadupSlot_misc, 0, 3000, -1, "Not displaying any paths"); + NewTextHeadupSlot(eHeadupSlot_misc, 0, 1000, -1, str); } if (ConsistencyCheck()) { WriteOutOppoPaths(); @@ -4047,31 +3994,32 @@ void WriteOutOppoPaths(void) { for (i = 0; 1; i++) { #ifdef DETHRACE_FIX_BUGS sprintf(str, "OPATH%03d.TXT", i); +#else + 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 - sprintf(str, "OPATH%0.3d.TXT", i); - PathCat(the_path, gApplication_path, str); f = DRfopen(the_path, "r+"); #endif - if (!f) { - strcpy(gOppo_path_filename, the_path); - gMade_path_filename = 1; + if (f == NULL) { break; } fclose(f); } + strcpy(gOppo_path_filename, the_path); + gMade_path_filename = 1; } #ifdef DETHRACE_FIX_BUGS f = fopen(gOppo_path_filename, "w"); - if (f == NULL) { - printf("f is NULL, errno=%d, msg=\"%s\"\n", errno, strerror(errno)); - } #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); @@ -4105,7 +4053,7 @@ void WriteOutOppoPaths(void) { gProgram_state.AI_vehicles.cop_start_points[i].v[2], 0.f, 0.f, 0.f, i); } - fprintf(f, "\n%s\n", "END OF OPPONENT PATHS"); + fprintf(f, "END OF OPPONENT PATHS"); fclose(f); } @@ -4118,10 +4066,7 @@ int NewNodeOKHere(void) { 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); - - if (BrVector3Length(&last_node_to_this) == 0.f) { - return 0; - } + return BrVector3Length(&last_node_to_this) != 0.f; } return 1; } @@ -4150,8 +4095,6 @@ void DropElasticateyNode(void) { tPath_section_type_enum original_type; all_the_same_type = 1; - section_type = ePST_normal; - if (!NewNodeOKHere()) { return; } @@ -4159,7 +4102,7 @@ void DropElasticateyNode(void) { 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); - section_type = gProgram_state.AI_vehicles.path_sections[gMobile_section].type; + 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); @@ -4171,29 +4114,27 @@ void DropElasticateyNode(void) { if (gProgram_state.AI_vehicles.number_of_path_nodes == 0) { NewTextHeadupSlot(eHeadupSlot_misc, 0, 2000, -1, "Not implemented yet. Go away."); return; - } else { - old_node = FindNearestPathNode(&gSelf->t.t.translate.t, &distance); - if (distance > 10.f) { - NewTextHeadupSlot(eHeadupSlot_misc, 0, 2000, -1, "Can't find any nodes close enough"); - return; - } - - if (gProgram_state.AI_vehicles.path_nodes[old_node].number_of_sections >= 1) { - original_type = gProgram_state.AI_vehicles.path_sections[gProgram_state.AI_vehicles.path_nodes[old_node].sections[0]].type; - 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 != original_type) { - all_the_same_type = 0; - } - } - if (all_the_same_type) { - section_type = original_type; - } - } - gAlready_elasticating = 1; - new_node = ReallocExtraPathNodes(1); - gMobile_section = ReallocExtraPathSections(1); - one_wayness = 0; } + old_node = FindNearestPathNode(&gSelf->t.t.translate.t, &distance); + if (distance > 10.f) { + NewTextHeadupSlot(eHeadupSlot_misc, 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; @@ -4201,18 +4142,18 @@ void DropElasticateyNode(void) { 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].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 = gProgram_state.AI_vehicles.path_sections[gProgram_state.AI_vehicles.path_nodes[old_node].sections[0]].width; - } else { + 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++; + 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++; + 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(eHeadupSlot_misc, 0, 2000, -1, str); @@ -4235,63 +4176,60 @@ void InsertAndElasticate(void) { tPath_section_type_enum section_type; not_perp = 0; - section_type = ePST_normal; - - if (!NewNodeOKHere()) { - return; - } - 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(eHeadupSlot_misc, 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; + 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(eHeadupSlot_misc, 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(eHeadupSlot_misc, 0, 2000, -1, str); } - InsertThisNodeInThisSectionHere(inserted_node, section_no, &gSelf->t.t.translate.t); - gMobile_section = new_section; - gProgram_state.AI_vehicles.path_sections[gMobile_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++; - 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++; - gAlready_elasticating = 1; - ShowOppoPaths(); - sprintf(str, "New section %d, new node #%d inserted into section #%d", - gMobile_section, inserted_node, section_no); - NewTextHeadupSlot(eHeadupSlot_misc, 0, 2000, -1, str); } } @@ -4308,32 +4246,31 @@ void InsertAndDontElasticate(void) { char str[256]; not_perp = 0; - if (!NewNodeOKHere()) { - return; - } - 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(eHeadupSlot_misc, 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; + 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(eHeadupSlot_misc, 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(eHeadupSlot_misc, 0, 2000, -1, str); } - 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(eHeadupSlot_misc, 0, 2000, -1, str); } } @@ -4342,21 +4279,17 @@ void InsertAndDontElasticate(void) { void DropDeadEndNode(void) { char str[256]; - if (!NewNodeOKHere()) { - return; + 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(eHeadupSlot_misc, 0, 4000, -1, str); } - if (!gAlready_elasticating) { - return; - } - 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(eHeadupSlot_misc, 0, 4000, -1, str); } // IDA: void __cdecl DropNodeOnNodeAndStopElasticating() @@ -4366,26 +4299,25 @@ void DropNodeOnNodeAndStopElasticating(void) { char str[256]; br_scalar distance; - if (!gAlready_elasticating) { - return; - } - 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(eHeadupSlot_misc, 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(eHeadupSlot_misc, 0, 2000, -1, str); - } else { - gAlready_elasticating = 0; - gProgram_state.AI_vehicles.number_of_path_nodes--; - 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++; - 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(eHeadupSlot_misc, 0, 4000, -1, str); + 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(eHeadupSlot_misc, 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(eHeadupSlot_misc, 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(eHeadupSlot_misc, 0, 4000, -1, str); + } } } @@ -4393,60 +4325,54 @@ void DropNodeOnNodeAndStopElasticating(void) { // FUNCTION: CARM95 0x004103c5 void WidenOppoPathSection(void) { - if (!gOppo_paths_shown) { - return; + if (gOppo_paths_shown) { + RecalcNearestPathSectionWidth(.05f); } - RecalcNearestPathSectionWidth(.05f); } // IDA: void __cdecl NarrowOppoPathSection() // FUNCTION: CARM95 0x00410573 void NarrowOppoPathSection(void) { - if (!gOppo_paths_shown) { - return; + if (gOppo_paths_shown) { + RecalcNearestPathSectionWidth(-.05f); } - RecalcNearestPathSectionWidth(-.05f); } // IDA: void __cdecl IncreaseSectionMinSpeed() // FUNCTION: CARM95 0x0041059d void IncreaseSectionMinSpeed(void) { - if (!gOppo_paths_shown) { - return; + if (gOppo_paths_shown) { + RecalcNearestPathSectionSpeed(0, 1); } - RecalcNearestPathSectionSpeed(0, 1); } // IDA: void __cdecl DecreaseSectionMinSpeed() // FUNCTION: CARM95 0x00410a7f void DecreaseSectionMinSpeed(void) { - if (!gOppo_paths_shown) { - return; + if (gOppo_paths_shown) { + RecalcNearestPathSectionSpeed(0, -1); } - RecalcNearestPathSectionSpeed(0, -1); } // IDA: void __cdecl IncreaseSectionMaxSpeed() // FUNCTION: CARM95 0x00410aa8 void IncreaseSectionMaxSpeed(void) { - if (!gOppo_paths_shown) { - return; + if (gOppo_paths_shown) { + RecalcNearestPathSectionSpeed(1, 1); } - RecalcNearestPathSectionSpeed(1, 1); } // IDA: void __cdecl DecreaseSectionMaxSpeed() // FUNCTION: CARM95 0x00410ad1 void DecreaseSectionMaxSpeed(void) { - if (!gOppo_paths_shown) { - return; + if (gOppo_paths_shown) { + RecalcNearestPathSectionSpeed(1, -1); } - RecalcNearestPathSectionSpeed(1, -1); } // IDA: void __cdecl PullOppoPoint() @@ -4455,22 +4381,20 @@ void PullOppoPoint(void) { tS16 node_no; br_scalar distance; - if (!gOppo_paths_shown) { - return; - } - if (gAlready_elasticating) { - NewTextHeadupSlot(eHeadupSlot_misc, 0, 2000, -1, "Not while you're elasticating"); - return; - } else { - node_no = FindNearestPathNode(&gSelf->t.t.translate.t, &distance); - if (distance > 10.f) { - NewTextHeadupSlot(eHeadupSlot_misc, 0, 2000, -1, "Can't find any paths close enough"); - return; + if (gOppo_paths_shown) { + if (gAlready_elasticating) { + NewTextHeadupSlot(eHeadupSlot_misc, 0, 2000, -1, "Not while you're elasticating"); + } else { + node_no = FindNearestPathNode(&gSelf->t.t.translate.t, &distance); + if (distance > 10.f) { + NewTextHeadupSlot(eHeadupSlot_misc, 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(eHeadupSlot_misc, 0, 2000, -1, "Bing!"); + } } - BrVector3Copy(&gProgram_state.AI_vehicles.path_nodes[node_no].p, &gSelf->t.t.translate.t); } - ShowOppoPaths(); - NewTextHeadupSlot(eHeadupSlot_misc, 0, 2000, -1, "Bing!"); } // IDA: void __cdecl ShowNodeInfo() @@ -4543,10 +4467,10 @@ void ShowSectionInfo2(void) { NewTextHeadupSlot(eHeadupSlot_misc, 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.2 * gProgram_state.AI_vehicles.path_sections[gMobile_section].min_speed[0]), - (int)(2.2 * gProgram_state.AI_vehicles.path_sections[gMobile_section].max_speed[0]), - (int)(2.2 * gProgram_state.AI_vehicles.path_sections[gMobile_section].min_speed[1]), - (int)(2.2 * gProgram_state.AI_vehicles.path_sections[gMobile_section].max_speed[1])); + (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(eHeadupSlot_misc, 0, 2000, -1, str); } else { section_no = FindNearestPathSection(&gSelf->t.t.translate.t, &direction_v, &intersect, &distance); @@ -4554,10 +4478,10 @@ void ShowSectionInfo2(void) { NewTextHeadupSlot(eHeadupSlot_misc, 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.2 * gProgram_state.AI_vehicles.path_sections[section_no].min_speed[0]), - (int)(2.2 * gProgram_state.AI_vehicles.path_sections[section_no].max_speed[0]), - (int)(2.2 * gProgram_state.AI_vehicles.path_sections[section_no].min_speed[1]), - (int)(2.2 * gProgram_state.AI_vehicles.path_sections[section_no].max_speed[1])); + (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(eHeadupSlot_misc, 0, 2000, -1, str); } } @@ -4627,13 +4551,10 @@ void DeleteOppoPathNodeAndJoin(void) { NewTextHeadupSlot(eHeadupSlot_misc, 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(eHeadupSlot_misc, 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)) { - - NewTextHeadupSlot(eHeadupSlot_misc, 0, 2000, -1, "Sections must point in same direction"); - } else { + } 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(); @@ -4641,6 +4562,8 @@ void DeleteOppoPathNodeAndJoin(void) { ConsistencyCheck(); ShowOppoPaths(); NewTextHeadupSlot(eHeadupSlot_misc, 0, 2000, -1, "Blam!"); + } else { + NewTextHeadupSlot(eHeadupSlot_misc, 0, 2000, -1, "Sections must point in same direction"); } } } @@ -4724,10 +4647,10 @@ void ToggleOneWayNess(void) { if (distance > 10.f) { NewTextHeadupSlot(eHeadupSlot_misc, 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 = 1; - } 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) { @@ -4756,10 +4679,10 @@ void CopStartPointInfo(void) { } 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); + distance = BrVector3LengthSquared(&car_to_point); if (distance < closest_distance) { - closest_distance = distance; closest = i; + closest_distance = distance; } } if (closest < 0 || closest_distance > 10.f) { diff --git a/src/DETHRACE/common/skidmark.c b/src/DETHRACE/common/skidmark.c index 0fd2d6bc..30196c0a 100644 --- a/src/DETHRACE/common/skidmark.c +++ b/src/DETHRACE/common/skidmark.c @@ -33,10 +33,10 @@ void AdjustSkid(int pSkid_num, br_matrix34* pMatrix, int pMaterial_index) { // IDA: br_material* __usercall MaterialFromIndex@(int pIndex@) // FUNCTION: CARM95 0x00401088 br_material* MaterialFromIndex(int pIndex) { - if (pIndex <= -2) { - return gMaterial[-2 - pIndex]; - } else { + if (pIndex > -2) { return gCurrent_race.material_modifiers[pIndex].skid_mark_material; + } else { + return gMaterial[-2 - pIndex]; } } @@ -306,7 +306,7 @@ int FarFromLine2D(br_vector3* pPt, br_vector3* pL1, br_vector3* pL2) { to_pt.v[0] = BR_SUB(pPt->v[0], pL2->v[0]); to_pt.v[1] = BR_SUB(pPt->v[2], pL2->v[2]); - cross = (-line.v[0]) * to_pt.v[1] + to_pt.v[0] * line.v[1]; + cross = -(line.v[0]) * to_pt.v[1] + to_pt.v[0] * line.v[1]; line_len = BrVector2Length(&line); if (fabs(cross) > line_len * 0.05f) { return 1; diff --git a/src/DETHRACE/dr_types.h b/src/DETHRACE/dr_types.h index 9a7ad3fb..fe70ed24 100644 --- a/src/DETHRACE/dr_types.h +++ b/src/DETHRACE/dr_types.h @@ -589,14 +589,14 @@ typedef struct tJoystick { tS32 dec; } tJoystick; -typedef struct tPursuee_trail { // size: 0x144 - br_vector3 trail_nodes[25]; // @0x0 - br_vector3 base_heading; // @0x12c - tU32 time_of_next_recording; // @0x138 - tU32 end_of_deviation; // @0x13c - tU8 number_of_nodes; // @0x140 - tU8 has_deviated_recently; // @0x141 - tU8 nodes_shifted_this_frame; // @0x142 +typedef struct tPursuee_trail { + br_vector3 trail_nodes[25]; + br_vector3 base_heading; + tU32 time_of_next_recording; + tU32 end_of_deviation; + tU8 number_of_nodes; + tU8 has_deviated_recently; + tU8 nodes_shifted_this_frame; } tPursuee_trail; typedef struct tCar_spec_struct { // size: 0x1a9c @@ -1659,71 +1659,71 @@ typedef struct tOpponent { tText_chunk* text_chunks; } tOpponent; -typedef struct tProgram_state { // size: 0x356c - tS32 credits; // @0x0 - tS32 credits_earned; // @0x4 - tS32 credits_lost; // @0x8 - tU32 view_change_start; // @0xc - tU32 pratcam_move_start; // @0x10 - int peds_killed; // @0x14 - int sausage_eater_mode; // @0x18 - int rank; // @0x1c - int loaded; // @0x20 - int last_slot; // @0x24 - int skill_level; // @0x28 - int parts_shop_visited; // @0x2c - int racing; // @0x30 - int cut_scene; // @0x34 - int saving; // @0x38 - int loading; // @0x3c - int dont_save_or_load; // @0x40 - int dont_load; // @0x44 - int mirror_on; // @0x48 - int prat_cam_on; // @0x4c - int cockpit_on; // @0x50 - int cockpit_image_index; // @0x54 - int current_render_left; // @0x58 - int current_render_top; // @0x5c - int current_render_right; // @0x60 - int current_render_bottom; // @0x64 - int frame_rate_headup; // @0x68 - int revs; // @0x6c - int music_volume; // @0x70 - int effects_volume; // @0x74 - int current_race_index; // @0x78 - int redo_race_index; // @0x7c - int credits_per_rank; // @0x80 - int game_completed; // @0x84 - int number_of_cars; // @0x88 - int current_car_index; // @0x8c - tWhich_view which_view; // @0x90 - tWhich_view new_view; // @0x94 - tWhich_view pending_view; // @0x98 - tWhich_view old_view; // @0x9c - tRace_sel_view_type view_type; // @0xa0 - tProg_status prog_status; // @0xa4 - tFrank_anne frank_or_anniness; // @0xa8 - tAuto_parts_reply auto_parts_reply; // @0xac - tCar_spec current_car; // @0xb0 - char player_name[2][14]; // @0x1b4c - char track_file_name[14]; // @0x1b68 - char car_name[14]; // @0x1b76 - int cars_available[60]; // @0x1b84 - br_vector3 initial_position; // @0x1c74 - br_scalar initial_yaw; // @0x1c80 - tTrack_spec track_spec; // @0x1c84 - tDepth_effect default_depth_effect; // @0x1cb0 - tDepth_effect current_depth_effect; // @0x1cc0 - int special_volume_count; // @0x1cd0 - tSpecial_volume* special_volumes; // @0x1cd4 - br_material* standard_screen; // @0x1cd8 - br_material* standard_screen_dark; // @0x1cdc - br_material* standard_screen_fog; // @0x1ce0 - int special_screens_count; // @0x1ce4 - tSpecial_screen* special_screens; // @0x1ce8 - tIntelligent_vehicles AI_vehicles; // @0x1cec - tNon_car_spec* non_cars; // @0x3564 - int num_non_car_spaces; // @0x3568 +typedef struct tProgram_state { + tS32 credits; + tS32 credits_earned; + tS32 credits_lost; + tU32 view_change_start; + tU32 pratcam_move_start; + int peds_killed; + int sausage_eater_mode; + int rank; + int loaded; + int last_slot; + int skill_level; + int parts_shop_visited; + int racing; + int cut_scene; + int saving; + int loading; + int dont_save_or_load; + int dont_load; + int mirror_on; + int prat_cam_on; + int cockpit_on; + int cockpit_image_index; + int current_render_left; + int current_render_top; + int current_render_right; + int current_render_bottom; + int frame_rate_headup; + int revs; + int music_volume; + int effects_volume; + int current_race_index; + int redo_race_index; + int credits_per_rank; + int game_completed; + int number_of_cars; + int current_car_index; + tWhich_view which_view; + tWhich_view new_view; + tWhich_view pending_view; + tWhich_view old_view; + tRace_sel_view_type view_type; + tProg_status prog_status; + tFrank_anne frank_or_anniness; + tAuto_parts_reply auto_parts_reply; + tCar_spec current_car; + char player_name[2][14]; + char track_file_name[14]; + char car_name[14]; + int cars_available[60]; + br_vector3 initial_position; + br_scalar initial_yaw; + tTrack_spec track_spec; + tDepth_effect default_depth_effect; + tDepth_effect current_depth_effect; + int special_volume_count; + tSpecial_volume* special_volumes; + br_material* standard_screen; + br_material* standard_screen_dark; + br_material* standard_screen_fog; + int special_screens_count; + tSpecial_screen* special_screens; + tIntelligent_vehicles AI_vehicles; + tNon_car_spec* non_cars; + int num_non_car_spaces; } tProgram_state; typedef struct tDR_font { diff --git a/src/DETHRACE/macros.h b/src/DETHRACE/macros.h index 03726d01..2ff70345 100644 --- a/src/DETHRACE/macros.h +++ b/src/DETHRACE/macros.h @@ -55,14 +55,23 @@ (V2) = (T); \ } while (0) -#define ReadThreeFloats(pF, a, b, c) \ - do { \ - float x_0, x_1, x_2; \ - GetThreeFloats(pF, &x_0, &x_1, &x_2); \ - a = x_0; \ - b = x_1; \ - c = x_2; \ - \ +#define ReadVector3(pF, a, b, c) \ + do { \ + float x[3]; \ + GetThreeFloats(pF, &x[2], &x[1], &x[0]); \ + a = x[2]; \ + b = x[1]; \ + c = x[0]; \ + \ + } while (0) + +#define ReadVector32(pF, a, b, c) \ + do { \ + float x[3]; \ + GetThreeFloats(pF, &x[2], &x[1], &x[0]); \ + b = x[2]; \ + c = x[1]; \ + a = x[0]; \ } while (0) #define ReadPairOfFloats(pF, a, b) \ @@ -73,4 +82,11 @@ b = x[0]; \ } while (0) +#define DRVector3Scale(v1, v2, s) \ + do { \ + (v1)->v[0] = BR_MUL((v2)->v[0], s); \ + (v1)->v[1] = BR_MUL((v2)->v[1], s); \ + (v1)->v[2] = BR_MUL((v2)->v[2], s); \ + } while (0) + #endif diff --git a/src/library_msvc.h b/src/library_msvc.h index 590d1ec0..da42fecd 100644 --- a/src/library_msvc.h +++ b/src/library_msvc.h @@ -214,7 +214,7 @@ // __loctotime_t // LIBRARY: CARM95 0x004EA9E0 -// $$$00001(1) +// __chkstk // GLOBAL: CARM95 0x0052D39C // __mb_cur_max @@ -224,12 +224,3 @@ // GLOBAL: CARM95 0x0052D190 // _pctype - -// GLOBAL: CARM95 0x004EAB82 -// __CIpow - -// GLOBAL: CARM95 0x004EA8DA -// __CIatan2 - -// GLOBAL: CARM95 0x004EA8C2 -// __CIasin