diff --git a/code/ai/ai.h b/code/ai/ai.h index f5fc94b8a75..090204cc50f 100644 --- a/code/ai/ai.h +++ b/code/ai/ai.h @@ -276,8 +276,8 @@ typedef struct ai_info { int ai_class; // Class. Might be override of default. // Probably become obsolete, to be replaced by path_start, path_cur, etc. - waypoint_list *wp_list; // waypoint list being followed - int wp_index; // waypoint index in list + int wp_list_index; // index of waypoint list being followed + int wp_index; // index of waypoint in list int wp_flags; // waypoint flags, see WPF_xxxx int waypoint_speed_cap; // -1 no cap, otherwise cap - changed to int by Goober5000 @@ -533,7 +533,7 @@ extern void ai_ignore_wing(object *ignorer, int wingnum); extern void ai_dock_with_object(object *docker, int docker_index, object *dockee, int dockee_index, int dock_type); extern void ai_stay_still(object *still_objp, vec3d *view_pos); extern void ai_do_default_behavior(object *obj); -extern void ai_start_waypoints(object *objp, waypoint_list *wp_list, int wp_flags, int start_index); +extern void ai_start_waypoints(object *objp, int wl_index, int wp_flags, int start_index); extern void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hit_normal); extern void ai_ship_destroy(int shipnum); extern vec3d ai_get_acc_limit(vec3d* vel_limit, const object* objp); diff --git a/code/ai/aicode.cpp b/code/ai/aicode.cpp index 70161e5d503..a99c9ffc920 100644 --- a/code/ai/aicode.cpp +++ b/code/ai/aicode.cpp @@ -3515,20 +3515,33 @@ void ai_dock_with_object(object *docker, int docker_index, object *dockee, int d // flags tells: // WPF_REPEAT Set -> repeat waypoints. // WPF_BACKTRACK Go in reverse. -void ai_start_waypoints(object *objp, waypoint_list *wp_list, int wp_flags, int start_index) +void ai_start_waypoints(object *objp, int wp_list_index, int wp_flags, int start_index) { - ai_info *aip; - Assert(wp_list != NULL); + auto aip = &Ai_info[Ships[objp->instance].ai_index]; - if (start_index < 0 || start_index >= (int)wp_list->get_waypoints().size()) + if (Waypoint_lists.empty()) + { + Warning(LOCATION, "No waypoint lists in mission!"); + aip->mode = AIM_NONE; + return; + } + + auto wp_list = find_waypoint_list_at_index(wp_list_index); + if (!wp_list) + { + Warning(LOCATION, "wp_list_index %d must be a valid waypoint list index!", wp_list_index); + wp_list_index = 0; + wp_list = find_waypoint_list_at_index(wp_list_index); + } + + auto wp = find_waypoint_at_index(wp_list, start_index); + if (!wp) { Warning(LOCATION, "Starting index for %s on '%s' is out of range!", Ships[objp->instance].ship_name, wp_list->get_name()); start_index = (wp_flags & WPF_BACKTRACK) ? (int)wp_list->get_waypoints().size() - 1 : 0; } - aip = &Ai_info[Ships[objp->instance].ai_index]; - - if ( (aip->mode == AIM_WAYPOINTS) && (aip->wp_list == wp_list) ) + if ( (aip->mode == AIM_WAYPOINTS) && (aip->wp_list_index == wp_list_index) ) { if (aip->wp_index == INVALID_WAYPOINT_POSITION) { @@ -3548,7 +3561,7 @@ void ai_start_waypoints(object *objp, waypoint_list *wp_list, int wp_flags, int } aip->ai_flags.remove(AI::AI_Flags::Formation_object); - aip->wp_list = wp_list; + aip->wp_list_index = wp_list_index; aip->wp_index = start_index; aip->wp_flags = wp_flags; aip->mode = AIM_WAYPOINTS; @@ -4896,19 +4909,15 @@ void ai_waypoints() // sanity checking for stuff that should never happen if (aip->wp_index == INVALID_WAYPOINT_POSITION) { - if (aip->wp_list == NULL) { - UNREACHABLE("Waypoints should have been assigned already!"); - ai_start_waypoints(Pl_objp, &Waypoint_lists.front(), WPF_REPEAT, 0); - } else { - UNREACHABLE("Waypoints should have been started already!"); - ai_start_waypoints(Pl_objp, aip->wp_list, WPF_REPEAT, 0); - } + UNREACHABLE("Waypoints should have been started already!"); + ai_start_waypoints(Pl_objp, (aip->wp_list_index < 0) ? 0 : aip->wp_list_index, WPF_REPEAT, 0); } - Assert(!aip->wp_list->get_waypoints().empty()); // What? Is this zero? Probably never got initialized! + auto wp_list = find_waypoint_list_at_index(aip->wp_list_index); + Assert(wp_list && !wp_list->get_waypoints().empty()); // What? Is this zero? Probably never got initialized! bool done, treat_as_ship; - ai_fly_to_target_position(aip->wp_list->get_waypoints()[aip->wp_index].get_pos(), &done, &treat_as_ship); + ai_fly_to_target_position(wp_list->get_waypoints()[aip->wp_index].get_pos(), &done, &treat_as_ship); if ( done ) { bool reached_end; @@ -4918,7 +4927,7 @@ void ai_waypoints() reached_end = (aip->wp_index == -1); } else { ++aip->wp_index; - reached_end = (aip->wp_index == (int)aip->wp_list->get_waypoints().size()); + reached_end = (aip->wp_index == static_cast(wp_list->get_waypoints().size())); } if (reached_end) { @@ -4926,7 +4935,7 @@ void ai_waypoints() if ( aip->wp_flags & WPF_REPEAT ) { // go back to the start. if (aip->wp_flags & WPF_BACKTRACK) { - aip->wp_index = (int)aip->wp_list->get_waypoints().size() - 1; + aip->wp_index = static_cast(wp_list->get_waypoints().size()) - 1; } else { aip->wp_index = 0; } @@ -4944,10 +4953,10 @@ void ai_waypoints() // ai_fly_to_target_position when it marks the AI directive as complete if ( treat_as_ship ) { ai_mission_goal_complete( aip ); // this call should reset the AI mode - mission_log_add_entry( LOG_WAYPOINTS_DONE, Ships[Pl_objp->instance].ship_name, aip->wp_list->get_name(), -1 ); + mission_log_add_entry( LOG_WAYPOINTS_DONE, Ships[Pl_objp->instance].ship_name, wp_list->get_name(), -1 ); } else { ai_mission_wing_goal_complete( Ships[Pl_objp->instance].wingnum, &(aip->goals[aip->active_goal]) ); - mission_log_add_entry( LOG_WAYPOINTS_DONE, Wings[Ships[Pl_objp->instance].wingnum].name, aip->wp_list->get_name(), -1 ); + mission_log_add_entry( LOG_WAYPOINTS_DONE, Wings[Ships[Pl_objp->instance].wingnum].name, wp_list->get_name(), -1 ); } // adds scripting hook for 'On Waypoints Done' --wookieejedi if (scripting::hooks::OnWaypointsDone->isActive()) { @@ -4955,7 +4964,7 @@ void ai_waypoints() scripting::hook_param_list( scripting::hook_param("Ship", 'o', Pl_objp), scripting::hook_param("Wing", 'o', scripting::api::l_Wing.Set(Ships[Pl_objp->instance].wingnum)), - scripting::hook_param("Waypointlist", 'o', scripting::api::l_WaypointList.Set(scripting::api::waypointlist_h(aip->wp_list))) + scripting::hook_param("Waypointlist", 'o', scripting::api::l_WaypointList.Set(scripting::api::waypointlist_h(wp_list))) )); } } @@ -12665,7 +12674,7 @@ int ai_formation() // skip if wing leader has no waypoint order or a different waypoint list // ...or if it's a different start index or direction if ( (laip->mode != AIM_WAYPOINTS) - || (laip->wp_list != aip->wp_list) + || (laip->wp_list_index != aip->wp_list_index) || (laip->submode_parm0 != aip->submode_parm0) || ((laip->wp_flags & WPF_BACKTRACK) != (aip->wp_flags & WPF_BACKTRACK)) ) { @@ -12673,16 +12682,17 @@ int ai_formation() } } - aip->wp_list = laip->wp_list; + aip->wp_list_index = laip->wp_list_index; aip->wp_index = laip->wp_index; aip->wp_flags = laip->wp_flags; - if (aip->wp_list != nullptr) { + auto wp_list = find_waypoint_list_at_index(aip->wp_list_index); + if (wp_list) { if (aip->wp_flags & WPF_BACKTRACK) { if (aip->wp_index == -1) ++aip->wp_index; } else { - if (aip->wp_index == (int)aip->wp_list->get_waypoints().size()) + if (aip->wp_index == static_cast(wp_list->get_waypoints().size())) --aip->wp_index; } } @@ -15455,7 +15465,7 @@ void init_ai_object(int objnum) //Init stuff from AI class and AI profiles init_aip_from_class_and_profile(aip, &Ai_classes[Ship_info[ship_type].ai_class], The_mission.ai_profile); - aip->wp_list = NULL; + aip->wp_list_index = -1; aip->wp_index = INVALID_WAYPOINT_POSITION; aip->attacker_objnum = -1; diff --git a/code/ai/aigoals.cpp b/code/ai/aigoals.cpp index d81076df70d..4953b42fc82 100644 --- a/code/ai/aigoals.cpp +++ b/code/ai/aigoals.cpp @@ -166,7 +166,7 @@ void ai_goal_reset(ai_goal *aigp, bool adding_goal, int ai_mode, int ai_submode, aigp->target_name = nullptr; aigp->target_name_index = -1; - aigp->wp_list = nullptr; + aigp->wp_list_index = -1; aigp->target_instance = -1; aigp->target_signature = -1; @@ -738,8 +738,8 @@ void ai_add_goal_sub_player(int type, int mode, int submode, const char *target_ if ( mode == AI_GOAL_WARP ) { if (submode >= 0) { - aigp->wp_list = find_waypoint_list_at_index(submode); - Assert(aigp->wp_list != NULL); + aigp->wp_list_index = submode; + Assert(find_waypoint_list_at_index(aigp->wp_list_index) != nullptr); } } @@ -1605,10 +1605,10 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp ) // check to see if we have a valid list. If not, then try to set one up. If that // fails, then we must pitch this order if ( (aigp->ai_mode == AI_GOAL_WAYPOINTS_ONCE) || (aigp->ai_mode == AI_GOAL_WAYPOINTS) ) { - if ( aigp->wp_list == NULL ) { - aigp->wp_list = find_matching_waypoint_list(aigp->target_name); + if ( aigp->wp_list_index < 0 ) { + aigp->wp_list_index = find_matching_waypoint_list_index(aigp->target_name); - if ( aigp->wp_list == NULL ) { + if ( aigp->wp_list_index < 0 ) { Warning(LOCATION, "Unknown waypoint list %s - not found in mission file. Killing ai goal", aigp->target_name ); return ai_achievability::NOT_ACHIEVABLE; } @@ -2344,7 +2344,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip ) flags |= WPF_REPEAT; if (current_goal->flags[AI::Goal_Flags::Waypoints_in_reverse]) flags |= WPF_BACKTRACK; - ai_start_waypoints(objp, current_goal->wp_list, flags, current_goal->int_data); + ai_start_waypoints(objp, current_goal->wp_list_index, flags, current_goal->int_data); break; } diff --git a/code/ai/aigoals.h b/code/ai/aigoals.h index 79868e0135c..9d8cd5475f3 100644 --- a/code/ai/aigoals.h +++ b/code/ai/aigoals.h @@ -119,7 +119,7 @@ typedef struct ai_goal { const char *target_name; // name of the thing that this goal acts upon int target_name_index; // index of goal_target_name in Goal_target_names[][] - waypoint_list *wp_list; // waypoints that this ship might fly. + int wp_list_index; // waypoints that this ship might fly. int target_instance; // instance of thing this ship might be chasing (currently only used for weapons; note, not the same as objnum!) int target_signature; // signature of object this ship might be chasing (currently only used for weapons; paired with above value to confirm target) diff --git a/code/autopilot/autopilot.cpp b/code/autopilot/autopilot.cpp index 42399eaaac8..4cd14ac6b53 100644 --- a/code/autopilot/autopilot.cpp +++ b/code/autopilot/autopilot.cpp @@ -66,7 +66,7 @@ int start_dist; void autopilot_ai_waypoint_goal_fixup(ai_goal* aigp) { // this function sets wp_index properly; - aigp->wp_list = find_matching_waypoint_list(aigp->target_name); + aigp->wp_list_index = find_matching_waypoint_list_index(aigp->target_name); } @@ -111,13 +111,15 @@ const vec3d *NavPoint::GetPosition() { if (flags & NP_WAYPOINT) { - waypoint *wpt = find_waypoint_at_index((waypoint_list*) target_obj, waypoint_num-1); - Assert(wpt != NULL); + auto wpt = find_waypoint_at_indexes(target_index, waypoint_num-1); + Assert(wpt != nullptr); + if (wpt == nullptr) + return &vmd_zero_vector; return wpt->get_pos(); } else { - return &Objects[((ship*) target_obj)->objnum].pos; + return &Objects[target_index].pos; } } @@ -462,12 +464,12 @@ bool StartAutopilot() { if (Navs[CurrentNav].flags & NP_WAYPOINT) { - ai_add_ship_goal_player( AIG_TYPE_PLAYER_SHIP, AI_GOAL_WAYPOINTS_ONCE, 0, ((waypoint_list*)Navs[CurrentNav].target_obj)->get_name(), &Ai_info[Ships[i].ai_index] ); + ai_add_ship_goal_player( AIG_TYPE_PLAYER_SHIP, AI_GOAL_WAYPOINTS_ONCE, 0, Waypoint_lists[Navs[CurrentNav].target_index].get_name(), &Ai_info[Ships[i].ai_index] ); //fixup has to wait until after wing goals } else { - ai_add_ship_goal_player( AIG_TYPE_PLAYER_SHIP, AI_GOAL_FLY_TO_SHIP, 0, ((ship*)Navs[CurrentNav].target_obj)->ship_name, &Ai_info[Ships[i].ai_index] ); + ai_add_ship_goal_player( AIG_TYPE_PLAYER_SHIP, AI_GOAL_FLY_TO_SHIP, 0, Ships[Objects[Navs[CurrentNav].target_index].instance].ship_name, &Ai_info[Ships[i].ai_index] ); } } @@ -491,7 +493,7 @@ bool StartAutopilot() if (Navs[CurrentNav].flags & NP_WAYPOINT) { - ai_add_wing_goal_player( AIG_TYPE_PLAYER_WING, AI_GOAL_WAYPOINTS_ONCE, 0, ((waypoint_list*)Navs[CurrentNav].target_obj)->get_name(), i ); + ai_add_wing_goal_player( AIG_TYPE_PLAYER_WING, AI_GOAL_WAYPOINTS_ONCE, 0, Waypoint_lists[Navs[CurrentNav].target_index].get_name(), i ); // "fix up" the goal for (j = 0; j < MAX_AI_GOALS; j++) @@ -505,7 +507,7 @@ bool StartAutopilot() } else { - ai_add_wing_goal_player( AIG_TYPE_PLAYER_WING, AI_GOAL_FLY_TO_SHIP, 0, ((ship*)Navs[CurrentNav].target_obj)->ship_name, i ); + ai_add_wing_goal_player( AIG_TYPE_PLAYER_WING, AI_GOAL_FLY_TO_SHIP, 0, Ships[Objects[Navs[CurrentNav].target_index].instance].ship_name, i ); } } @@ -874,12 +876,12 @@ void EndAutoPilot() if (Navs[CurrentNav].flags & NP_WAYPOINT) { goal = AI_GOAL_WAYPOINTS_ONCE; - goal_name = ((waypoint_list*)Navs[CurrentNav].target_obj)->get_name(); + goal_name = Waypoint_lists[Navs[CurrentNav].target_index].get_name(); } else { goal = AI_GOAL_FLY_TO_SHIP; - goal_name = ((ship*)Navs[CurrentNav].target_obj)->ship_name; + goal_name = Ships[Objects[Navs[CurrentNav].target_index].instance].ship_name; } // assign ship goals @@ -1094,9 +1096,9 @@ void NavSystem_Do() for (i = 0; i < MAX_NAVPOINTS; i++) { - if ((Navs[i].flags & NP_SHIP) && (Navs[i].target_obj != NULL)) + if ((Navs[i].flags & NP_SHIP) && (Navs[i].target_index >= 0)) { - if (((ship*)Navs[i].target_obj)->objnum == -1) + if (Objects[Navs[i].target_index].flags[Object::Object_Flags::Should_be_dead]) { if (CurrentNav == i) CurrentNav = -1; @@ -1108,7 +1110,7 @@ void NavSystem_Do() // check if we're reached a Node for (i = 0; i < MAX_NAVPOINTS; i++) { - if (Navs[i].target_obj != NULL) + if (Navs[i].target_index >= 0) { if (Navs[i].flags & NP_VALIDTYPE && DistanceTo(i) < 1000) Navs[i].flags |= NP_VISITED; @@ -1392,7 +1394,7 @@ bool AddNav_Ship(const char *Nav, const char *TargetName, int flags) { if (Ships[i].objnum != -1 && !stricmp(TargetName, Ships[i].ship_name)) { - tnav.target_obj = (void *)&Ships[i]; + tnav.target_index = Ships[i].objnum; } } @@ -1433,7 +1435,7 @@ bool AddNav_Waypoint(const char *Nav, const char *WP_Path, int node, int flags) Assert(!(tnav.flags & NP_SHIP)); - tnav.target_obj = find_matching_waypoint_list(WP_Path); + tnav.target_index = find_matching_waypoint_list_index(WP_Path); tnav.waypoint_num = node; // copy it into it's location diff --git a/code/autopilot/autopilot.h b/code/autopilot/autopilot.h index 9695ade8b1b..86646b88b41 100644 --- a/code/autopilot/autopilot.h +++ b/code/autopilot/autopilot.h @@ -34,7 +34,7 @@ class NavPoint ubyte normal_color[3] = { 0x80, 0x80, 0xFF }; ubyte visited_color[3] = { 0xFF, 0xFF, 0x00 }; - const void *target_obj = nullptr; + int target_index = -1; //waypoint list index if NP_WAYPOINT, otherwise object index int waypoint_num = -1; //only used when flags & NP_WAYPOINT const vec3d *GetPosition(); @@ -53,7 +53,7 @@ class NavPoint visited_color[1] = 0xFF; visited_color[2] = 0x00; - target_obj = nullptr; + target_index = -1; waypoint_num = -1; } }; diff --git a/code/mission/missiontraining.cpp b/code/mission/missiontraining.cpp index 036f219ccb4..8b68c91d44f 100644 --- a/code/mission/missiontraining.cpp +++ b/code/mission/missiontraining.cpp @@ -92,7 +92,7 @@ int Training_context_speed_set; int Training_context_speed_min; int Training_context_speed_max; TIMESTAMP Training_context_speed_timestamp; -waypoint_list *Training_context_path; +int Training_context_waypoint_path; int Training_context_goal_waypoint; int Training_context_at_waypoint; float Training_context_distance; @@ -398,7 +398,7 @@ void training_mission_init() Training_context = 0; Training_context_speed_set = 0; Training_context_speed_timestamp = TIMESTAMP::invalid(); - Training_context_path = nullptr; + Training_context_waypoint_path = -1; Players_target = UNINITIALIZED; Players_mlocked = UNINITIALIZED; diff --git a/code/mission/missiontraining.h b/code/mission/missiontraining.h index f039b6b959f..4e3a298043f 100644 --- a/code/mission/missiontraining.h +++ b/code/mission/missiontraining.h @@ -25,7 +25,7 @@ extern int Training_context_speed_min; extern int Training_context_speed_max; extern int Training_context_speed_set; extern TIMESTAMP Training_context_speed_timestamp; -extern waypoint_list *Training_context_path; +extern int Training_context_waypoint_path; extern int Training_context_goal_waypoint; extern int Training_context_at_waypoint; extern float Training_context_distance; diff --git a/code/network/multi_obj.cpp b/code/network/multi_obj.cpp index b842e2e8105..139bea759e8 100644 --- a/code/network/multi_obj.cpp +++ b/code/network/multi_obj.cpp @@ -1493,8 +1493,9 @@ int multi_oo_pack_data(net_player *pl, object *objp, ushort oo_flags, ubyte *dat // either send out the waypoint they are trying to get to *or* their current target if (umode == AIM_WAYPOINTS) { // if it's already started pointing to a waypoint, grab its net_signature and send that instead - if ((aip->wp_list != nullptr) && (aip->wp_index >= 0 && aip->wp_index < static_cast(aip->wp_list->get_waypoints().size()))) { - target_signature = Objects[aip->wp_list->get_waypoints().at(aip->wp_index).get_objnum()].net_signature; + waypoint* wp; + if ((wp = find_waypoint_at_indexes(aip->wp_list_index, aip->wp_index)) != nullptr) { + target_signature = Objects[wp->get_objnum()].net_signature; } } // send the target signature. 2021 Version! else if ((aip->goals[0].target_name != nullptr) && strlen(aip->goals[0].target_name) != 0) { @@ -2124,12 +2125,14 @@ int multi_oo_unpack_data(net_player* pl, ubyte* data, int seq_num, int time_delt Ai_info[shipp->ai_index].goals[0].target_name = nullptr; // set their waypoints if in waypoint mode. } else if (umode == AIM_WAYPOINTS) { - waypoint* destination = find_waypoint_with_instance(target_objp->instance); - if (destination != nullptr) { - Ai_info[shipp->ai_index].wp_list = destination->get_parent_list(); - Ai_info[shipp->ai_index].wp_index = find_index_of_waypoint(Ai_info[shipp->ai_index].wp_list, destination); + int wp_list_index = calc_waypoint_list_index(target_objp->instance); + int wp_index = calc_waypoint_index(target_objp->instance); + if (find_waypoint_at_indexes(wp_list_index, wp_index) != nullptr) { + Ai_info[shipp->ai_index].wp_list_index = wp_list_index; + Ai_info[shipp->ai_index].wp_index = wp_index; } else { - Ai_info[shipp->ai_index].wp_list = nullptr; + Ai_info[shipp->ai_index].wp_list_index = -1; + Ai_info[shipp->ai_index].wp_index = INVALID_WAYPOINT_POSITION; } } else { Ai_info[shipp->ai_index].target_objnum = OBJ_INDEX(target_objp); diff --git a/code/object/waypoint.cpp b/code/object/waypoint.cpp index f02f1fcc370..e4f8bfe2bb4 100644 --- a/code/object/waypoint.cpp +++ b/code/object/waypoint.cpp @@ -153,13 +153,17 @@ void calc_waypoint_indexes(int waypoint_instance, int &waypoint_list_index, int int calc_waypoint_list_index(int waypoint_instance) { - Assert(waypoint_instance >= 0); + if (waypoint_instance < 0) + return -1; + return waypoint_instance / 0x10000; } int calc_waypoint_index(int waypoint_instance) { - Assert(waypoint_instance >= 0); + if (waypoint_instance < 0) + return -1; + return waypoint_instance & 0xffff; } @@ -198,7 +202,7 @@ void waypoint_create_game_objects() waypoint_list *find_matching_waypoint_list(const char *name) { - Assert(name != NULL); + Assert(name != nullptr); for (auto &ii: Waypoint_lists) { @@ -206,7 +210,22 @@ waypoint_list *find_matching_waypoint_list(const char *name) return ⅈ } - return NULL; + return nullptr; +} + +int find_matching_waypoint_list_index(const char *name) +{ + Assert(name != nullptr); + + int i = 0; + for (auto &ii: Waypoint_lists) + { + if (!stricmp(ii.get_name(), name)) + return i; + i++; + } + + return -1; } // NOTE: waypoint names are always in the format Name:index @@ -309,34 +328,30 @@ waypoint_list *find_waypoint_list_with_instance(int waypoint_instance, int *wayp waypoint *find_waypoint_with_instance(int waypoint_instance) { if (waypoint_instance < 0) - return NULL; - - waypoint_list *wp_list = find_waypoint_list_at_index(calc_waypoint_list_index(waypoint_instance)); - if (wp_list == NULL) - return NULL; + return nullptr; - return find_waypoint_at_index(wp_list, calc_waypoint_index(waypoint_instance)); + return find_waypoint_at_indexes(calc_waypoint_list_index(waypoint_instance), calc_waypoint_index(waypoint_instance)); } waypoint_list *find_waypoint_list_at_index(int index) { - Assert(index >= 0); - - if (index >= 0 && index < (int)Waypoint_lists.size()) + if (SCP_vector_inbounds(Waypoint_lists, index)) return &Waypoint_lists[index]; - return NULL; + return nullptr; } waypoint *find_waypoint_at_index(waypoint_list *list, int index) { - Assert(list != NULL); - Assert(index >= 0); - - if (index >= 0 && index < (int)list->get_waypoints().size()) + if (list && SCP_vector_inbounds(list->get_waypoints(), index)) return &list->get_waypoints()[index]; - return NULL; + return nullptr; +} + +waypoint *find_waypoint_at_indexes(int list_index, int index) +{ + return find_waypoint_at_index(find_waypoint_list_at_index(list_index), index); } int find_index_of_waypoint_list(const waypoint_list *wp_list) @@ -417,7 +432,7 @@ int waypoint_add(const vec3d *pos, int waypoint_instance) { // get a name for it char buf[NAME_LENGTH]; - waypoint_find_unique_name(buf, (int)(Waypoint_lists.size() + 1)); + waypoint_find_unique_name(buf, static_cast(Waypoint_lists.size()) + 1); // add new list with that name waypoint_list new_list(buf); @@ -425,8 +440,8 @@ int waypoint_add(const vec3d *pos, int waypoint_instance) wp_list = &Waypoint_lists.back(); // set up references - wp_list_index = (int)(Waypoint_lists.size() - 1); - wp_index = (int) wp_list->get_waypoints().size(); + wp_list_index = static_cast(Waypoint_lists.size()) - 1; + wp_index = static_cast(wp_list->get_waypoints().size()); } // create the waypoint on the same list as, and immediately after, waypoint_instance else @@ -439,7 +454,7 @@ int waypoint_add(const vec3d *pos, int waypoint_instance) // it has to be on, or at the end of, an existing list Assert(wp_list != NULL); - Assert((uint) wp_index <= wp_list->get_waypoints().size()); + Assert(wp_index <= static_cast(wp_list->get_waypoints().size())); // iterate through all waypoints that are at this index or later, // and edit their instances so that they point to a waypoint one place higher diff --git a/code/object/waypoint.h b/code/object/waypoint.h index f59332b6bfa..5d225e71cef 100644 --- a/code/object/waypoint.h +++ b/code/object/waypoint.h @@ -72,6 +72,7 @@ void waypoint_create_game_objects(); // Find a waypoint list with the specified name waypoint_list *find_matching_waypoint_list(const char *name); +int find_matching_waypoint_list_index(const char *name); // Find a waypoint with the specified name (e.g. Path:1) waypoint *find_matching_waypoint(const char *name); @@ -84,6 +85,7 @@ waypoint *find_waypoint_with_instance(int waypoint_instance); // Find something at the specified index waypoint_list *find_waypoint_list_at_index(int index); waypoint *find_waypoint_at_index(waypoint_list *list, int index); +waypoint *find_waypoint_at_indexes(int list_index, int index); int find_index_of_waypoint_list(const waypoint_list *wp_list); int find_index_of_waypoint(const waypoint_list *wp_list, const waypoint *wpt); diff --git a/code/parse/sexp.cpp b/code/parse/sexp.cpp index 5644a779f8c..084adf976ab 100644 --- a/code/parse/sexp.cpp +++ b/code/parse/sexp.cpp @@ -20215,7 +20215,8 @@ int sexp_waypoint_twice() int sexp_path_flown() { if (Training_context & TRAINING_CONTEXT_FLY_PATH) { - if ((uint) Training_context_goal_waypoint == Training_context_path->get_waypoints().size()){ + auto wp_list = find_waypoint_list_at_index(Training_context_waypoint_path); + if (wp_list && (Training_context_goal_waypoint == static_cast(wp_list->get_waypoints().size()))) { return SEXP_TRUE; } } @@ -24990,8 +24991,8 @@ void sexp_set_training_context_fly_path(int node) return; Training_context |= TRAINING_CONTEXT_FLY_PATH; - Training_context_path = wp_list; - Training_context_distance = (float)distance; + Training_context_waypoint_path = find_index_of_waypoint_list(wp_list); + Training_context_distance = static_cast(distance); Training_context_goal_waypoint = 0; Training_context_at_waypoint = -1; } diff --git a/code/scripting/api/libs/mission.cpp b/code/scripting/api/libs/mission.cpp index 7273f1626c6..0b00d52fbb4 100644 --- a/code/scripting/api/libs/mission.cpp +++ b/code/scripting/api/libs/mission.cpp @@ -1269,8 +1269,8 @@ ADE_FUNC(createWaypoint, l_Mission, "[vector Position, waypointlist List]", int waypoint_instance = -1; if (wlh && wlh->isValid()) { - int wp_list_index = find_index_of_waypoint_list(wlh->wlp); - int wp_index = (int) wlh->wlp->get_waypoints().size() - 1; + int wp_list_index = find_index_of_waypoint_list(wlh->getList()); + int wp_index = static_cast(wlh->getList()->get_waypoints().size()) - 1; waypoint_instance = calc_waypoint_instance(wp_list_index, wp_index); } int obj_idx = waypoint_add(v3 != NULL ? v3 : &vmd_zero_vector, waypoint_instance); diff --git a/code/scripting/api/objs/order.cpp b/code/scripting/api/objs/order.cpp index 3c2017aeebc..df78c346850 100644 --- a/code/scripting/api/objs/order.cpp +++ b/code/scripting/api/objs/order.cpp @@ -243,7 +243,7 @@ ADE_VIRTVAR(Target, l_Order, "object", "Target of the order. Value may also be a flags |= WPF_REPEAT; if (ohp->aigp->flags[AI::Goal_Flags::Waypoints_in_reverse]) flags |= WPF_BACKTRACK; - ai_start_waypoints(ohp->objh.objp(), wpl, flags, ohp->aigp->int_data); + ai_start_waypoints(ohp->objh.objp(), find_index_of_waypoint_list(wpl), flags, ohp->aigp->int_data); } } } @@ -303,9 +303,9 @@ ADE_VIRTVAR(Target, l_Order, "object", "Target of the order. Value may also be a case AI_GOAL_WAYPOINTS: case AI_GOAL_WAYPOINTS_ONCE: // check if waypoint order is the current goal (ohp->odx == 0) and if it is valid - if ( (ohp->odx == 0) && (aip->wp_index != INVALID_WAYPOINT_POSITION) && - (aip->wp_index >= 0 && aip->wp_index < static_cast(aip->wp_list->get_waypoints().size())) ) { - objnum = aip->wp_list->get_waypoints()[aip->wp_index].get_objnum(); + waypoint* wp; + if ( (ohp->odx == 0) && (aip->wp_index != INVALID_WAYPOINT_POSITION) && ((wpl = find_waypoint_list_at_index(aip->wp_list_index)) != nullptr) && ((wp = find_waypoint_at_index(wpl, aip->wp_index)) != nullptr) ) { + objnum = wp->get_objnum(); } else { wpl = find_matching_waypoint_list(ohp->aigp->target_name); if (wpl != nullptr) { diff --git a/code/scripting/api/objs/waypoint.cpp b/code/scripting/api/objs/waypoint.cpp index 49bd22cca31..ed7a4a214c6 100644 --- a/code/scripting/api/objs/waypoint.cpp +++ b/code/scripting/api/objs/waypoint.cpp @@ -13,43 +13,41 @@ ADE_OBJ_DERIV(l_Waypoint, object_h, "waypoint", "waypoint handle", l_Object); ADE_FUNC(getList, l_Waypoint, NULL, "Returns the waypoint list", "waypointlist", "waypointlist handle or invalid handle if waypoint was invalid") { object_h *oh = NULL; - waypointlist_h wpl; waypoint_list *wp_list = NULL; if(!ade_get_args(L, "o", l_Waypoint.GetPtr(&oh))) return ade_set_error(L, "o", l_WaypointList.Set(waypointlist_h())); if(oh->isValid() && oh->objp()->type == OBJ_WAYPOINT) { wp_list = find_waypoint_list_with_instance(oh->objp()->instance); - if(wp_list != NULL) - wpl = waypointlist_h(wp_list); - } - - if (wpl.isValid()) { - return ade_set_args(L, "o", l_WaypointList.Set(wpl)); + return ade_set_args(L, "o", l_WaypointList.Set(waypointlist_h(wp_list))); } return ade_set_error(L, "o", l_WaypointList.Set(waypointlist_h())); } -waypointlist_h::waypointlist_h() {wlp=NULL;name[0]='\0';} -waypointlist_h::waypointlist_h(waypoint_list* n_wlp) { - wlp = n_wlp; - if(n_wlp != NULL) { - strcpy_s(name, wlp->get_name()); - } else { - memset(name, 0, sizeof(name)); - } +waypointlist_h::waypointlist_h() + : wl_index(-1) +{} +waypointlist_h::waypointlist_h(int _wl_index) +{ + if (SCP_vector_inbounds(Waypoint_lists, _wl_index)) + wl_index = _wl_index; + else + wl_index = -1; } +waypointlist_h::waypointlist_h(waypoint_list* _wlp) + : waypointlist_h((_wlp == nullptr) ? -1 : find_index_of_waypoint_list(_wlp)) +{} waypointlist_h::waypointlist_h(const char* wlname) + : waypointlist_h((wlname == nullptr) ? nullptr : find_matching_waypoint_list(wlname)) +{} +bool waypointlist_h::isValid() const { - wlp = NULL; - if ( wlname != NULL ) { - strcpy_s(name, wlname); - wlp = find_matching_waypoint_list(wlname); - } + return SCP_vector_inbounds(Waypoint_lists, wl_index); } -bool waypointlist_h::isValid() const { - return (wlp != NULL && !strcmp(wlp->get_name(), name)); +waypoint_list* waypointlist_h::getList() const +{ + return isValid() ? &Waypoint_lists[wl_index] : nullptr; } //**********HANDLE: WaypointList @@ -58,23 +56,20 @@ ADE_OBJ(l_WaypointList, waypointlist_h, "waypointlist", "waypointlist handle"); ADE_INDEXER(l_WaypointList, "number Index", "Array of waypoints that are part of the waypoint list", "waypoint", "Waypoint, or invalid handle if the index or waypointlist handle is invalid") { int idx = -1; - waypointlist_h* wlh = NULL; - char wpname[128]; + waypointlist_h* wlh = nullptr; if( !ade_get_args(L, "oi", l_WaypointList.GetPtr( &wlh ), &idx)) return ade_set_error( L, "o", l_Waypoint.Set( object_h() ) ); - if(!wlh->isValid()) + if(!wlh || !wlh->isValid()) return ade_set_error( L, "o", l_Waypoint.Set( object_h() ) ); //Lua-->FS2 idx--; - //Get waypoint name - sprintf(wpname, "%s:%d", wlh->wlp->get_name(), calc_waypoint_index(idx) + 1); - waypoint *wpt = find_matching_waypoint( wpname ); - if( (idx >= 0) && ((uint) idx < wlh->wlp->get_waypoints().size()) && (wpt != NULL) && (wpt->get_objnum() >= 0) ) { - return ade_set_args(L, "o", l_Waypoint.Set(object_h(&Objects[wpt->get_objnum()]))); - } + //Get waypoint + auto wp = find_waypoint_at_index(wlh->getList(), idx); + if (wp) + return ade_set_args(L, "o", l_Waypoint.Set(object_h(wp->get_objnum()))); return ade_set_error(L, "o", l_Waypoint.Set( object_h() ) ); } @@ -86,11 +81,15 @@ ADE_FUNC(__len, l_WaypointList, "number", "Number of waypoints in the list, or 0 if handle is invalid") { - waypointlist_h* wlh = NULL; + waypointlist_h* wlh = nullptr; if ( !ade_get_args(L, "o", l_WaypointList.GetPtr(&wlh)) ) { - return ade_set_error( L, "o", l_Waypoint.Set( object_h() ) ); + return ade_set_error(L, "i", 0); + } + if (!wlh || !wlh->isValid()) { + return ade_set_error(L, "i", 0); } - return ade_set_args(L, "i", wlh->wlp->get_waypoints().size()); + + return ade_set_args(L, "i", wlh->getList()->get_waypoints().size()); } ADE_VIRTVAR(Name, l_WaypointList, "string", "Name of WaypointList", "string", "Waypointlist name, or empty string if handle is invalid") @@ -100,13 +99,15 @@ ADE_VIRTVAR(Name, l_WaypointList, "string", "Name of WaypointList", "string", "W if ( !ade_get_args(L, "o|s", l_WaypointList.GetPtr(&wlh), &s) ) { return ade_set_error(L, "s", ""); } + if (!wlh || !wlh->isValid()) { + return ade_set_error(L, "s", ""); + } if(ADE_SETTING_VAR && s != NULL) { - wlh->wlp->set_name(s); - strcpy_s(wlh->name,s); + wlh->getList()->set_name(s); } - return ade_set_args( L, "s", wlh->name); + return ade_set_args( L, "s", wlh->getList()->get_name()); } ADE_FUNC(isValid, l_WaypointList, NULL, "Return if this waypointlist handle is valid", "boolean", "true if valid false otherwise") diff --git a/code/scripting/api/objs/waypoint.h b/code/scripting/api/objs/waypoint.h index b05cdae4b1b..19ece7f28ea 100644 --- a/code/scripting/api/objs/waypoint.h +++ b/code/scripting/api/objs/waypoint.h @@ -12,12 +12,13 @@ DECLARE_ADE_OBJ(l_Waypoint, object_h); struct waypointlist_h { - waypoint_list *wlp; - char name[NAME_LENGTH]; + int wl_index; waypointlist_h(); - explicit waypointlist_h(waypoint_list *n_wlp); + explicit waypointlist_h(int _wl_index); + explicit waypointlist_h(waypoint_list* _wlp); explicit waypointlist_h(const char* wlname); bool isValid() const; + waypoint_list* getList() const; }; DECLARE_ADE_OBJ(l_WaypointList, waypointlist_h); diff --git a/code/ship/ship.cpp b/code/ship/ship.cpp index 1bda9545226..fe89d92a40e 100644 --- a/code/ship/ship.cpp +++ b/code/ship/ship.cpp @@ -17140,9 +17140,10 @@ int ship_return_seconds_to_goal(ship *sp) if ( aip->mode == AIM_WAYPOINTS ) { // Is traveling a waypoint path min_speed = 0.9f * max_speed; - if (aip->wp_list != NULL) { + auto wp_list = find_waypoint_list_at_index(aip->wp_list_index); + if (wp_list != nullptr) { Assert(aip->wp_index != INVALID_WAYPOINT_POSITION); - auto& waypoints = aip->wp_list->get_waypoints(); + auto& waypoints = wp_list->get_waypoints(); // distance to current waypoint dist += vm_vec_dist_quick(&objp->pos, waypoints[aip->wp_index].get_pos()); diff --git a/freespace2/freespace.cpp b/freespace2/freespace.cpp index 3ed6035a101..cd35a6bd2de 100644 --- a/freespace2/freespace.cpp +++ b/freespace2/freespace.cpp @@ -7042,7 +7042,7 @@ void game_do_training_checks() } if (Training_context & TRAINING_CONTEXT_FLY_PATH) { - wplp = Training_context_path; + wplp = find_waypoint_list_at_index(Training_context_waypoint_path); if (wplp->get_waypoints().size() > (uint) Training_context_goal_waypoint) { i = Training_context_goal_waypoint; do {