diff --git a/code/ai/ai_flags.h b/code/ai/ai_flags.h index acb0fd479ef..e99707caf25 100644 --- a/code/ai/ai_flags.h +++ b/code/ai/ai_flags.h @@ -165,6 +165,7 @@ namespace AI { Dynamic_goals_afterburn_hard, Player_orders_afterburn_hard, Hudsquadmsg_tactical_disarm_disable, + Hudsquadmsg_new_form_on_wing, Align_to_target_when_guarding_still, Debris_respects_big_damage, Dont_limit_change_in_speed_due_to_physics_whack, diff --git a/code/ai/ai_profiles.cpp b/code/ai/ai_profiles.cpp index db08fffbe9e..cf987264475 100644 --- a/code/ai/ai_profiles.cpp +++ b/code/ai/ai_profiles.cpp @@ -647,6 +647,8 @@ void parse_ai_profiles_tbl(const char *filename) set_flag(profile, "$hud squad messages use tactical disarm/disable:", AI::Profile_Flags::Hudsquadmsg_tactical_disarm_disable); + set_flag(profile, "$hud squad messages use ai-form-on-wing-new:", AI::Profile_Flags::Hudsquadmsg_new_form_on_wing); + set_flag(profile, "$align to target when guarding stationary ship:", AI::Profile_Flags::Align_to_target_when_guarding_still); if (optional_string("$rotation factor multiplier for player collisions:")) { diff --git a/code/ai/aigoals.cpp b/code/ai/aigoals.cpp index d7b914152e9..e2df840d218 100644 --- a/code/ai/aigoals.cpp +++ b/code/ai/aigoals.cpp @@ -53,11 +53,11 @@ struct ship_registry_entry; // PURGE_GOALS_ONE_SHIP for goals which should only purge other goals in the one ship. // Goober5000 - note that the new disable and disarm goals (AI_GOAL_DISABLE_SHIP_TACTICAL and // AI_GOAL_DISARM_SHIP_TACTICAL) do not purge ANY goals, not even the ones in the one ship -inline bool purge_goals_all_ships(ai_goal_mode ai_mode) +[[nodiscard]] bool purge_goals_all_ships(ai_goal_mode ai_mode) { return ai_mode == AI_GOAL_IGNORE || ai_mode == AI_GOAL_DISABLE_SHIP || ai_mode == AI_GOAL_DISARM_SHIP; } -inline bool purge_goals_one_ship(ai_goal_mode ai_mode) +[[nodiscard]] bool purge_goals_one_ship(ai_goal_mode ai_mode) { return ai_mode == AI_GOAL_IGNORE_NEW; } @@ -79,6 +79,7 @@ ai_goal_list Ai_goal_names[] = { "Depart", AI_GOAL_WARP, 0 }, { "Attack subsys", AI_GOAL_DESTROY_SUBSYSTEM, 0 }, { "Form on wing", AI_GOAL_FORM_ON_WING, 0 }, + { "Form on wing (new)", AI_GOAL_FORM_ON_WING_NEW, 0 }, { "Undock", AI_GOAL_UNDOCK, 0 }, { "Attack wing", AI_GOAL_CHASE_WING, 0 }, { "Guard ship", AI_GOAL_GUARD, 0 }, @@ -95,6 +96,7 @@ ai_goal_list Ai_goal_names[] = { "Keep safe dist", AI_GOAL_KEEP_SAFE_DISTANCE, 0 }, { "Rearm ship", AI_GOAL_REARM_REPAIR, 0 }, { "Stay still", AI_GOAL_STAY_STILL, 0 }, + { "Stay still (new)", AI_GOAL_STAY_STILL_NEW, 0 }, { "Play dead", AI_GOAL_PLAY_DEAD, 0 }, { "Play dead (persistent)", AI_GOAL_PLAY_DEAD_PERSISTENT, 0 }, { "Attack weapon", AI_GOAL_CHASE_WEAPON, 0 }, @@ -123,6 +125,7 @@ const char *Ai_goal_text(ai_goal_mode goal, int submode) case AI_GOAL_DESTROY_SUBSYSTEM: return XSTR( "destroy ", 477); case AI_GOAL_FORM_ON_WING: + case AI_GOAL_FORM_ON_WING_NEW: return XSTR( "form on ", 478); case AI_GOAL_UNDOCK: return XSTR( "undock ", 479); @@ -195,12 +198,12 @@ void ai_maybe_add_form_goal(wing* wingp) return; } - int j; + auto form_goal = The_mission.ai_profile->flags[AI::Profile_Flags::Hudsquadmsg_new_form_on_wing] ? AI_GOAL_FORM_ON_WING_NEW : AI_GOAL_FORM_ON_WING; // iterate through the ship_index list of this wing and check for orders. We will do // this for all ships in the wing instead of on a wing only basis in case some ships // in the wing actually have different orders than others - for (j = 0; j < wingp->current_count; j++) { + for (int j = 0; j < wingp->current_count; j++) { ai_info* aip; Assert(wingp->ship_index[j] != -1); // get Allender @@ -221,13 +224,13 @@ void ai_maybe_add_form_goal(wing* wingp) if (Netgame.type_flags & NG_TYPE_TEAM) { const ship_registry_entry* ship_regp = ship_registry_get(Ships[wingp->ship_index[j]].ship_name); wingnum = TVT_wings[ship_regp->p_objp()->team]; - ai_add_ship_goal_player(ai_goal_type::PLAYER_SHIP, AI_GOAL_FORM_ON_WING, -1, Ships[Wings[wingnum].ship_index[Wings[wingnum].special_ship]].ship_name, aip); + ai_add_ship_goal_player(ai_goal_type::PLAYER_SHIP, form_goal, -1, Ships[Wings[wingnum].ship_index[Wings[wingnum].special_ship]].ship_name, aip); } else { wingnum = Starting_wings[0]; - ai_add_ship_goal_player(ai_goal_type::PLAYER_SHIP, AI_GOAL_FORM_ON_WING, -1, Ships[Wings[wingnum].ship_index[Wings[wingnum].special_ship]].ship_name, aip); + ai_add_ship_goal_player(ai_goal_type::PLAYER_SHIP, form_goal, -1, Ships[Wings[wingnum].ship_index[Wings[wingnum].special_ship]].ship_name, aip); } } else if (!(Game_mode & GM_MULTIPLAYER)) { - ai_add_ship_goal_player(ai_goal_type::PLAYER_SHIP, AI_GOAL_FORM_ON_WING, -1, Player_ship->ship_name, aip); + ai_add_ship_goal_player(ai_goal_type::PLAYER_SHIP, form_goal, -1, Player_ship->ship_name, aip); } } } @@ -767,7 +770,7 @@ void ai_add_goal_sub_player(ai_goal_type type, ai_goal_mode mode, int submode, c aigp->priority = PLAYER_PRIORITY_SUPPORT_LOW; // Goober5000 - same with form-on-wing, since it's a type of staying near - else if ( mode == AI_GOAL_FORM_ON_WING ) + else if ( mode == AI_GOAL_FORM_ON_WING || mode == AI_GOAL_FORM_ON_WING_NEW ) // NOLINT(readability-braces-around-statements) aigp->priority = PLAYER_PRIORITY_SUPPORT_LOW; else if ( aigp->type == ai_goal_type::PLAYER_WING ) // NOLINT(readability-braces-around-statements) @@ -936,11 +939,9 @@ void ai_add_goal_sub_sexp( int sexp, ai_goal_type type, ai_info *aip, ai_goal *a // for achievability. aigp->target_name = ai_get_goal_target_name(CTEXT(CDR(node)), &aigp->target_name_index); // waypoint path name; - aigp->priority = eval_num(CDDR(node), priority_is_nan, priority_is_nan_forever); - aigp->ai_mode = AI_GOAL_WAYPOINTS; - if ( op == OP_AI_WAYPOINTS_ONCE ) - aigp->ai_mode = AI_GOAL_WAYPOINTS_ONCE; + aigp->ai_mode = (op == OP_AI_WAYPOINTS_ONCE) ? AI_GOAL_WAYPOINTS_ONCE : AI_GOAL_WAYPOINTS; + if (CDDDDR(node) < 0) aigp->int_data = 0; // handle optional node separately because we don't subtract 1 here else @@ -1019,7 +1020,8 @@ void ai_add_goal_sub_sexp( int sexp, ai_goal_type type, ai_info *aip, ai_goal *a } case OP_AI_STAY_STILL: - aigp->ai_mode = AI_GOAL_STAY_STILL; + case OP_AI_STAY_STILL_NEW: + aigp->ai_mode = (op == OP_AI_STAY_STILL) ? AI_GOAL_STAY_STILL : AI_GOAL_STAY_STILL_NEW; aigp->target_name = ai_get_goal_target_name(CTEXT(CDR(node)), &aigp->target_name_index); // waypoint path name; aigp->priority = eval_num(CDDR(node), priority_is_nan, priority_is_nan_forever); break; @@ -1040,13 +1042,9 @@ void ai_add_goal_sub_sexp( int sexp, ai_goal_type type, ai_info *aip, ai_goal *a break; case OP_AI_PLAY_DEAD: - aigp->priority = eval_num(CDR(node), priority_is_nan, priority_is_nan_forever); - aigp->ai_mode = AI_GOAL_PLAY_DEAD; - break; - case OP_AI_PLAY_DEAD_PERSISTENT: aigp->priority = eval_num(CDR(node), priority_is_nan, priority_is_nan_forever); - aigp->ai_mode = AI_GOAL_PLAY_DEAD_PERSISTENT; + aigp->ai_mode = (op == OP_AI_PLAY_DEAD) ? AI_GOAL_PLAY_DEAD : AI_GOAL_PLAY_DEAD_PERSISTENT; break; case OP_AI_KEEP_SAFE_DISTANCE: @@ -1082,9 +1080,10 @@ void ai_add_goal_sub_sexp( int sexp, ai_goal_type type, ai_info *aip, ai_goal *a } case OP_AI_FORM_ON_WING: + case OP_AI_FORM_ON_WING_NEW: aigp->priority = 99; aigp->target_name = ai_get_goal_target_name(CTEXT(CDR(node)), &aigp->target_name_index); - aigp->ai_mode = AI_GOAL_FORM_ON_WING; + aigp->ai_mode = (op == OP_AI_FORM_ON_WING) ? AI_GOAL_FORM_ON_WING : AI_GOAL_FORM_ON_WING_NEW; break; case OP_AI_CHASE: @@ -1293,12 +1292,9 @@ int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp, bool &remove_more ) /* We now need to determine what the mode and submode values are*/ switch( op ) { - case OP_AI_WAYPOINTS_ONCE: - goalmode = AI_GOAL_WAYPOINTS_ONCE; - priority = eval_priority_et_seq(CDDR(node)); - break; case OP_AI_WAYPOINTS: - goalmode = AI_GOAL_WAYPOINTS; + case OP_AI_WAYPOINTS_ONCE: + goalmode = (op == OP_AI_WAYPOINTS_ONCE) ? AI_GOAL_WAYPOINTS_ONCE : AI_GOAL_WAYPOINTS; priority = eval_priority_et_seq(CDDR(node)); break; case OP_AI_DESTROY_SUBSYS: @@ -1329,7 +1325,8 @@ int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp, bool &remove_more ) priority = eval_priority_et_seq(CDR(node)); break; case OP_AI_STAY_STILL: - goalmode = AI_GOAL_STAY_STILL; + case OP_AI_STAY_STILL_NEW: + goalmode = (op == OP_AI_STAY_STILL) ? AI_GOAL_STAY_STILL : AI_GOAL_STAY_STILL_NEW; priority = eval_priority_et_seq(CDDR(node)); break; case OP_AI_DOCK: @@ -1390,8 +1387,9 @@ int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp, bool &remove_more ) goalmode = (op == OP_AI_IGNORE) ? AI_GOAL_IGNORE : AI_GOAL_IGNORE_NEW; break; case OP_AI_FORM_ON_WING: + case OP_AI_FORM_ON_WING_NEW: priority = eval_priority_et_seq(-1, 99); - goalmode = AI_GOAL_FORM_ON_WING; + goalmode = (op == OP_AI_FORM_ON_WING) ? AI_GOAL_FORM_ON_WING : AI_GOAL_FORM_ON_WING_NEW; break; case OP_AI_FLY_TO_SHIP: priority = eval_priority_et_seq(CDDR(node)); @@ -1620,7 +1618,7 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp ) // these orders are always achievable. if ( (aigp->ai_mode == AI_GOAL_KEEP_SAFE_DISTANCE) - || (aigp->ai_mode == AI_GOAL_CHASE_ANY) || (aigp->ai_mode == AI_GOAL_STAY_STILL) + || (aigp->ai_mode == AI_GOAL_CHASE_ANY) || (aigp->ai_mode == AI_GOAL_STAY_STILL) || (aigp->ai_mode == AI_GOAL_STAY_STILL_NEW) || (aigp->ai_mode == AI_GOAL_PLAY_DEAD) || (aigp->ai_mode == AI_GOAL_PLAY_DEAD_PERSISTENT)) return ai_achievability::ACHIEVABLE; @@ -1649,7 +1647,7 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp ) // form on wing is always achievable if we are forming on Player, but it's up for grabs otherwise // if the wing target is valid then be sure to set the override bit so that it always // gets executed next - if ( aigp->ai_mode == AI_GOAL_FORM_ON_WING ) { + if ( aigp->ai_mode == AI_GOAL_FORM_ON_WING || aigp->ai_mode == AI_GOAL_FORM_ON_WING_NEW ) { if (!target_ship_entry || !target_ship_entry->has_shipp()) return ai_achievability::NOT_ACHIEVABLE; @@ -2341,7 +2339,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip ) // Goober5000 - we may want to use AI for the player // AL 3-7-98: If this is a player ship, and the goal is not a formation goal, then do a quick out - if ( !(Player_use_ai) && (objp->flags[Object::Object_Flags::Player_ship]) && (current_goal->ai_mode != AI_GOAL_FORM_ON_WING) ) + if ( !(Player_use_ai) && (objp->flags[Object::Object_Flags::Player_ship]) && (current_goal->ai_mode != AI_GOAL_FORM_ON_WING) && (current_goal->ai_mode != AI_GOAL_FORM_ON_WING_NEW) ) { return; } @@ -2537,39 +2535,46 @@ void ai_process_mission_orders( int objnum, ai_info *aip ) break; case AI_GOAL_STAY_STILL: + case AI_GOAL_STAY_STILL_NEW: + // we don't clear out ship goals for the "new" goal variant + if (current_goal->ai_mode == AI_GOAL_STAY_STILL) + { + // clear out the object's goals. Seems to me that if a ship is staying still for a purpose + // then we need to clear everything out since there is not a real way to get rid of this goal + // clearing out goals is okay here since we are now what mode to set this AI object to. + ai_clear_ship_goals(aip); + } // for now, ignore any other parameters!!!! - // clear out the object's goals. Seems to me that if a ship is staying still for a purpose - // then we need to clear everything out since there is not a real way to get rid of this goal - // clearing out goals is okay here since we are now what mode to set this AI object to. - ai_clear_ship_goals( aip ); ai_stay_still( objp, NULL ); break; case AI_GOAL_PLAY_DEAD: - // if a ship is playing dead, MWA says that it shouldn't try to do anything else. - // clearing out goals is okay here since we are now what mode to set this AI object to. - ai_clear_ship_goals( aip ); - aip->mode = AIM_PLAY_DEAD; - aip->submode = -1; - aip->submode_start_time = Missiontime; - break; - case AI_GOAL_PLAY_DEAD_PERSISTENT: - // same as above, but we don't clear out ship goals + // we don't clear out ship goals for the "persistent" goal variant + if (current_goal->ai_mode == AI_GOAL_PLAY_DEAD) + { + // if a ship is playing dead, MWA says that it shouldn't try to do anything else. + // clearing out goals is okay here since we are now what mode to set this AI object to. + ai_clear_ship_goals(aip); + } aip->mode = AIM_PLAY_DEAD; aip->submode = -1; aip->submode_start_time = Missiontime; break; case AI_GOAL_FORM_ON_WING: - // get the ship first, since we're going to wipe it out next + case AI_GOAL_FORM_ON_WING_NEW: + // get the ship first, since we might wipe it out next shipnum = ship_name_lookup( current_goal->target_name ); Assert( shipnum >= 0 ); other_obj = &Objects[Ships[shipnum].objnum]; - // for form on wing, we need to clear out all goals for this ship, and then call the form - // on wing AI code - // clearing out goals is okay here since we are now what mode to set this AI object to. - ai_clear_ship_goals( aip ); + // we don't clear out ship goals for the "new" goal variant + if (current_goal->ai_mode == AI_GOAL_FORM_ON_WING) + { + // for form on wing, we need to clear out all goals for this ship, and then call the form on wing AI code + // clearing out goals is okay here since we are now what mode to set this AI object to. + ai_clear_ship_goals(aip); + } ai_form_on_wing( objp, other_obj ); break; diff --git a/code/ai/aigoals.h b/code/ai/aigoals.h index 68547349528..9b36c42517b 100644 --- a/code/ai/aigoals.h +++ b/code/ai/aigoals.h @@ -47,9 +47,8 @@ enum class ai_goal_type enum ai_goal_mode : uint8_t { AI_GOAL_NONE = 0, - AI_GOAL_PLACEHOLDER_1, - AI_GOAL_CHASE, // per the original #define list, AI_GOAL_CHASE started at 2 (1<<1) + AI_GOAL_CHASE, AI_GOAL_DOCK, // used for undocking as well AI_GOAL_WAYPOINTS, AI_GOAL_WAYPOINTS_ONCE, @@ -84,6 +83,8 @@ enum ai_goal_mode : uint8_t AI_GOAL_LUA, AI_GOAL_DISARM_SHIP_TACTICAL, AI_GOAL_DISABLE_SHIP_TACTICAL, + AI_GOAL_STAY_STILL_NEW, + AI_GOAL_FORM_ON_WING_NEW, AI_GOAL_NUM_VALUES }; diff --git a/code/def_files/data/tables/objecttypes.tbl b/code/def_files/data/tables/objecttypes.tbl index ef73d9355b0..c6a10ee288a 100644 --- a/code/def_files/data/tables/objecttypes.tbl +++ b/code/def_files/data/tables/objecttypes.tbl @@ -47,7 +47,7 @@ $Fog: +Start dist: 10.0 +Compl dist: 600.0 $AI: - +Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "play dead (persistent)" "stay near ship" ) + +Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "stay still (new)" "play dead" "play dead (persistent)" "stay near ship" ) +Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" ) +Turrets attack this: YES +Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" ) @@ -83,7 +83,7 @@ $Fog: +Start dist: 10.0 +Compl dist: 500.0 $AI: - +Valid goals: ( "fly to ship" "dock" "undock" "waypoints" "waypoints once" "stay near ship" "keep safe dist" "stay still" "play dead" "play dead (persistent)" "rearm ship" ) + +Valid goals: ( "fly to ship" "dock" "undock" "waypoints" "waypoints once" "stay near ship" "keep safe dist" "stay still" "stay still (new)" "play dead" "play dead (persistent)" "rearm ship" ) +Accept Player Orders: YES +Player orders: ( "rearm me" "abort rearm" "depart" ) +Auto attacks: YES @@ -110,9 +110,9 @@ $Fog: +Start dist: 10.0 +Compl dist: 500.0 $AI: - +Valid goals: ( "fly to ship" "attack ship" "waypoints" "waypoints once" "depart" "attack subsys" "attack wing" "guard ship" "disable ship" "disable ship (tactical)" "disarm ship" "disarm ship (tactical)" "attack any" "attack ship class" "ignore ship" "ignore ship (new)" "guard wing" "evade ship" "stay still" "play dead" "play dead (persistent)" "stay near ship" "keep safe dist" "form on wing") + +Valid goals: ( "fly to ship" "attack ship" "waypoints" "waypoints once" "depart" "attack subsys" "attack wing" "guard ship" "disable ship" "disable ship (tactical)" "disarm ship" "disarm ship (tactical)" "attack any" "attack ship class" "ignore ship" "ignore ship (new)" "guard wing" "evade ship" "stay still" "stay still (new)" "play dead" "play dead (persistent)" "stay near ship" "keep safe dist" "form on wing" "form on wing (new)" ) +Accept Player Orders: YES - +Player Orders: ( "attack ship" "disable ship" "disable ship (tactical)" "disarm ship" "disarm ship (tactical)" "guard ship" "ignore ship" "ignore ship (new)" "form on wing" "cover me" "attack any" "attack ship class" "depart" "disable subsys" ) + +Player Orders: ( "attack ship" "disable ship" "disable ship (tactical)" "disarm ship" "disarm ship (tactical)" "guard ship" "ignore ship" "ignore ship (new)" "form on wing" "form on wing (new)" "cover me" "attack any" "attack ship class" "depart" "disable subsys" ) +Auto attacks: YES +Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" ) +Guards attack this: YES @@ -138,9 +138,9 @@ $Fog: +Start dist: 10.0 +Compl dist: 500.0 $AI: - +Valid goals: ( "fly to ship" "attack ship" "waypoints" "waypoints once" "depart" "attack subsys" "attack wing" "guard ship" "disable ship" "disable ship (tactical)" "disarm ship" "disarm ship (tactical)" "attack any" "attack ship class" "ignore ship" "ignore ship (new)" "guard wing" "evade ship" "stay still" "play dead" "play dead (persistent)" "stay near ship" "keep safe dist" "form on wing" ) + +Valid goals: ( "fly to ship" "attack ship" "waypoints" "waypoints once" "depart" "attack subsys" "attack wing" "guard ship" "disable ship" "disable ship (tactical)" "disarm ship" "disarm ship (tactical)" "attack any" "attack ship class" "ignore ship" "ignore ship (new)" "guard wing" "evade ship" "stay still" "stay still (new)" "play dead" "play dead (persistent)" "stay near ship" "keep safe dist" "form on wing" "form on wing (new)" ) +Accept Player Orders: YES - +Player Orders: ( "attack ship" "disable ship" "disable ship (tactical)" "disarm ship" "disarm ship (tactical)" "guard ship" "ignore ship" "ignore ship (new)" "form on wing" "cover me" "attack any" "attack ship class" "depart" "disable subsys" ) + +Player Orders: ( "attack ship" "disable ship" "disable ship (tactical)" "disarm ship" "disarm ship (tactical)" "guard ship" "ignore ship" "ignore ship (new)" "form on wing" "form on wing (new)" "cover me" "attack any" "attack ship class" "depart" "disable subsys" ) +Auto attacks: YES +Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" ) +Guards attack this: YES @@ -166,7 +166,7 @@ $Fog: +Start dist: 10.0 +Compl dist: 500.0 $AI: - +Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "play dead (persistent)" "stay near ship" ) + +Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "stay still (new)" "play dead" "play dead (persistent)" "stay near ship" ) +Accept Player Orders: YES +Player Orders: ( "attack ship" "dock" "depart" ) +Auto attacks: YES @@ -197,7 +197,7 @@ $Fog: +Start dist: 10.0 +Compl dist: 600.0 $AI: - +Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "play dead (persistent)" "stay near ship" ) + +Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "stay still (new)" "play dead" "play dead (persistent)" "stay near ship" ) +Accept Player Orders: YES +Player Orders: ( "attack ship" "dock" "depart" ) +Auto attacks: YES @@ -228,7 +228,7 @@ $Fog: +Start dist: 10.0 +Compl dist: 600.0 $AI: - +Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "play dead (persistent)" "stay near ship" ) + +Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "stay still (new)" "play dead" "play dead (persistent)" "stay near ship" ) +Accept Player Orders: YES +Player Orders: ( "attack ship" "depart" ) +Auto attacks: YES @@ -258,7 +258,7 @@ $Fog: +Start dist: 10.0 +Compl dist: 600.0 $AI: - +Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "play dead (persistent)" "stay near ship" ) + +Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "stay still (new)" "play dead" "play dead (persistent)" "stay near ship" ) +Accept Player Orders: YES +Player Orders: ( "attack ship" "depart" ) +Auto attacks: YES @@ -288,7 +288,7 @@ $Fog: +Start dist: 10.0 +Compl dist: 600.0 $AI: - +Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "play dead (persistent)" "stay near ship" ) + +Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "stay still (new)" "play dead" "play dead (persistent)" "stay near ship" ) +Accept Player Orders: YES +Player Orders: ( "attack ship" "depart" ) +Auto attacks: YES @@ -318,7 +318,7 @@ $Fog: +Start dist: 10.0 +Compl dist: 600.0 $AI: - +Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "play dead (persistent)" "stay near ship" ) + +Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "stay still (new)" "play dead" "play dead (persistent)" "stay near ship" ) +Accept Player Orders: YES +Player Orders: ( "attack ship" "depart" ) +Auto attacks: YES @@ -348,7 +348,7 @@ $Fog: +Start dist: 10.0 +Compl dist: 750.0 $AI: - +Valid goals: ( "fly to ship" "attack ship" "attack wing" "waypoints" "waypoints once" "depart" "stay still" "play dead" "play dead (persistent)" "stay near ship" ) + +Valid goals: ( "fly to ship" "attack ship" "attack wing" "waypoints" "waypoints once" "depart" "stay still" "stay still (new)" "play dead" "play dead (persistent)" "stay near ship" ) +Accept Player Orders: YES +Player Orders: ( "depart" ) +Auto attacks: YES @@ -378,7 +378,7 @@ $Fog: +Start dist: 10.0 +Compl dist: 1000.0 $AI: - +Valid goals: ( "fly to ship" "attack ship" "attack wing" "waypoints" "waypoints once" "depart" "stay still" "play dead" "play dead (persistent)" "stay near ship" ) + +Valid goals: ( "fly to ship" "attack ship" "attack wing" "waypoints" "waypoints once" "depart" "stay still" "stay still (new)" "play dead" "play dead (persistent)" "stay near ship" ) +Auto attacks: YES +Attempt Broadside: YES +Actively Pursues: ( "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" ) diff --git a/code/hud/hudsquadmsg.cpp b/code/hud/hudsquadmsg.cpp index b6a9a981c08..82d1b2715e0 100644 --- a/code/hud/hudsquadmsg.cpp +++ b/code/hud/hudsquadmsg.cpp @@ -1172,7 +1172,7 @@ int hud_squadmsg_send_ship_command( int shipnum, int command, int send_message, case FORMATION_ITEM: message = MESSAGE_FORM_ON_MY_WING; target_shipname = ordering_shipp->ship_name; - ai_mode = AI_GOAL_FORM_ON_WING; + ai_mode = (The_mission.ai_profile->flags[AI::Profile_Flags::Hudsquadmsg_new_form_on_wing]) ? AI_GOAL_FORM_ON_WING_NEW : AI_GOAL_FORM_ON_WING; ai_submode = 0; break; @@ -1430,7 +1430,7 @@ int hud_squadmsg_send_wing_command( int wingnum, int command, int send_message, case FORMATION_ITEM: message = MESSAGE_FORM_ON_MY_WING; target_shipname = ordering_shipp->ship_name; - ai_mode = AI_GOAL_FORM_ON_WING; + ai_mode = (The_mission.ai_profile->flags[AI::Profile_Flags::Hudsquadmsg_new_form_on_wing]) ? AI_GOAL_FORM_ON_WING_NEW : AI_GOAL_FORM_ON_WING; ai_submode = 0; break; diff --git a/code/parse/sexp.cpp b/code/parse/sexp.cpp index f5a32e16a23..094e459116d 100644 --- a/code/parse/sexp.cpp +++ b/code/parse/sexp.cpp @@ -865,11 +865,13 @@ SCP_vector Operators = { { "ai-ignore", OP_AI_IGNORE, 2, 2, SEXP_GOAL_OPERATOR, }, { "ai-ignore-new", OP_AI_IGNORE_NEW, 2, 2, SEXP_GOAL_OPERATOR, }, { "ai-form-on-wing", OP_AI_FORM_ON_WING, 1, 1, SEXP_GOAL_OPERATOR, }, + { "ai-form-on-wing-new", OP_AI_FORM_ON_WING_NEW, 1, 1, SEXP_GOAL_OPERATOR, }, { "ai-fly-to-ship", OP_AI_FLY_TO_SHIP, 2, 5, SEXP_GOAL_OPERATOR, }, { "ai-stay-near-ship", OP_AI_STAY_NEAR_SHIP, 2, 5, SEXP_GOAL_OPERATOR, }, { "ai-evade-ship", OP_AI_EVADE_SHIP, 2, 2, SEXP_GOAL_OPERATOR, }, { "ai-keep-safe-distance", OP_AI_KEEP_SAFE_DISTANCE, 1, 1, SEXP_GOAL_OPERATOR, }, { "ai-stay-still", OP_AI_STAY_STILL, 2, 2, SEXP_GOAL_OPERATOR, }, + { "ai-stay-still-new", OP_AI_STAY_STILL_NEW, 2, 2, SEXP_GOAL_OPERATOR, }, { "ai-play-dead", OP_AI_PLAY_DEAD, 1, 1, SEXP_GOAL_OPERATOR, }, { "ai-play-dead-persistent", OP_AI_PLAY_DEAD_PERSISTENT, 1, 1, SEXP_GOAL_OPERATOR, }, @@ -927,9 +929,11 @@ sexp_ai_goal_link Sexp_ai_goal_links[] = { { AI_GOAL_IGNORE, OP_AI_IGNORE }, { AI_GOAL_IGNORE_NEW, OP_AI_IGNORE_NEW }, { AI_GOAL_STAY_STILL, OP_AI_STAY_STILL }, + { AI_GOAL_STAY_STILL_NEW, OP_AI_STAY_STILL_NEW }, { AI_GOAL_PLAY_DEAD, OP_AI_PLAY_DEAD }, { AI_GOAL_PLAY_DEAD_PERSISTENT, OP_AI_PLAY_DEAD_PERSISTENT }, { AI_GOAL_FORM_ON_WING, OP_AI_FORM_ON_WING }, + { AI_GOAL_FORM_ON_WING_NEW, OP_AI_FORM_ON_WING_NEW }, { AI_GOAL_FLY_TO_SHIP, OP_AI_FLY_TO_SHIP }, { AI_GOAL_REARM_REPAIR, OP_AI_REARM_REPAIR }, }; @@ -31438,9 +31442,11 @@ int query_operator_return_type(int op) case OP_AI_IGNORE: case OP_AI_IGNORE_NEW: case OP_AI_STAY_STILL: + case OP_AI_STAY_STILL_NEW: case OP_AI_PLAY_DEAD: case OP_AI_PLAY_DEAD_PERSISTENT: case OP_AI_FORM_ON_WING: + case OP_AI_FORM_ON_WING_NEW: case OP_AI_FLY_TO_SHIP: case OP_AI_REARM_REPAIR: return OPR_AI_GOAL; @@ -32908,12 +32914,14 @@ int query_operator_argument_type(int op, int argnum) return OPF_POSITIVE; case OP_AI_STAY_STILL: + case OP_AI_STAY_STILL_NEW: if (!argnum) return OPF_SHIP_POINT; else return OPF_POSITIVE; case OP_AI_FORM_ON_WING: + case OP_AI_FORM_ON_WING_NEW: return OPF_SHIP; case OP_GOOD_REARM_TIME: @@ -36586,9 +36594,11 @@ int get_category(int op_id) case OP_AI_KEEP_SAFE_DISTANCE: case OP_AI_IGNORE: case OP_AI_STAY_STILL: + case OP_AI_STAY_STILL_NEW: case OP_AI_PLAY_DEAD: case OP_AI_IGNORE_NEW: case OP_AI_FORM_ON_WING: + case OP_AI_FORM_ON_WING_NEW: case OP_AI_CHASE_SHIP_CLASS: case OP_AI_PLAY_DEAD_PERSISTENT: case OP_AI_FLY_TO_SHIP: @@ -39729,9 +39739,17 @@ SCP_vector Sexp_help = { "\t1:\tName of target to ignore.\r\n" "\t2:\tGoal priority (number between 0 and 89) - note, this does not imply any ranking of ignored targets." }, - { OP_AI_STAY_STILL, "Ai-stay still (Ship goal)\r\n" + { OP_AI_STAY_STILL, "Ai-stay-still (Ship goal)\r\n" "\tCauses the specified ship to stay still. The ship will do nothing until attacked at " - "which time the ship will come to life and defend itself.\r\n\r\n" + "which time the ship will come to life and defend itself. All other goals specified for the ship will be purged.\r\n\r\n" + "Takes 2 arguments...\r\n" + "\t1:\tShip or waypoint the ship staying still will directly face (currently not implemented)\r\n" + "\t2:\tGoal priority (number between 0 and 89)." }, + + { OP_AI_STAY_STILL_NEW, "Ai-stay-still-new (Ship goal)\r\n" + "\tCauses the specified ship to stay still. The ship will do nothing until attacked at " + "which time the ship will come to life and defend itself. Unlike the legacy ai-stay-still, " + "no other goals specified for the ship will be purged.\r\n\r\n" "Takes 2 arguments...\r\n" "\t1:\tShip or waypoint the ship staying still will directly face (currently not implemented)\r\n" "\t2:\tGoal priority (number between 0 and 89)." }, @@ -39740,17 +39758,20 @@ SCP_vector Sexp_help = { "\tCauses the specified ship to pretend that it is dead and not do anything. This " "expression should be used to indicate that a ship has no pilot and cannot respond " "to any enemy threats. A ship playing dead will not respond to any attack.\r\n\r\n" - "Do note that the ship's goal list is cleared, which means that if it receives any other goal in any way, " - "it will immediately come back to life. Use ai-play-dead-persistent to prevent this from happening.\r\n\r\n" + "Do note that the ship's goal list is cleared, which means both that it forgets " + "this goal and all previous goals, and that if it receives any other goal in any way, " + "it will immediately come back to life. Use ai-play-dead-persistent to prevent this " + "from happening.\r\n\r\n" "Takes 1 argument...\r\n" "\t1:\tGoal priority (number between 0 and 89)." }, { OP_AI_PLAY_DEAD_PERSISTENT, "Ai-play-dead-persistent (Ship goal)\r\n" "\tCauses the specified ship to pretend that it is dead and not do anything. This " - "goal behaves exactly like ai-play-dead, with the important difference that the ship " - "will not immediately come back to life whenever it is given an order or a new goal " - "of any priority. The only ways this goal can be removed are via remove-goal, " - "clear-goals, or a new goal of a *higher* priority.\r\n\r\n" + "goal behaves like ai-play-dead, with the important differences that the goal 'persists' " + "until it is removed, and the existing goal list is not cleared. The ship will not " + "come back to life whenever it is given an order or a new goal, so the only ways the " + "ship will stop playing dead are if this goal is removed, or a new goal of a higher " + "priority is assigned.\r\n\r\n" "Takes 1 argument...\r\n" "\t1:\tGoal priority (number between 0 and 89)." }, @@ -39760,6 +39781,12 @@ SCP_vector Sexp_help = { "Takes 1 argument...\r\n" "\t1:\tShip to form on." }, + { OP_AI_FORM_ON_WING_NEW, "Ai-form-on-wing-new (Ship Goal)\r\n" + "\tCauses the ship to form on the specified ship's wing. This works analogous to the " + "player order. Unlike the legacy ai-form-on-wing, no other goals specified for the ship will be purged.\r\n\r\n" + "Takes 1 argument...\r\n" + "\t1:\tShip to form on." }, + { OP_FLASH_HUD_GAUGE, "Ai-flash hud gauge (Training goal)\r\n" "\tCauses the specified hud gauge to flash to draw the player's attention to it.\r\n\r\n" "Takes 1 argument...\r\n" diff --git a/code/parse/sexp.h b/code/parse/sexp.h index cad826b4e96..f00e8ff1538 100644 --- a/code/parse/sexp.h +++ b/code/parse/sexp.h @@ -953,6 +953,8 @@ enum : int { OP_AI_REARM_REPAIR, // Goober5000 OP_AI_DISABLE_SHIP_TACTICAL, // Goober5000 OP_AI_DISARM_SHIP_TACTICAL, // Goober5000 + OP_AI_STAY_STILL_NEW, // Goober5000 + OP_AI_FORM_ON_WING_NEW, // Goober5000 // OP_CATEGORY_UNLISTED diff --git a/code/scripting/api/objs/enums.cpp b/code/scripting/api/objs/enums.cpp index 58550c4ed2a..f5e19d59d5e 100644 --- a/code/scripting/api/objs/enums.cpp +++ b/code/scripting/api/objs/enums.cpp @@ -38,6 +38,7 @@ const lua_enum_def_list Enumerations[] = { {"ORDER_EVADE", LE_ORDER_EVADE, true}, {"ORDER_FLY_TO", LE_ORDER_FLY_TO, true}, {"ORDER_FORM_ON_WING", LE_ORDER_FORM_ON_WING, true}, + {"ORDER_FORM_ON_WING_NEW", LE_ORDER_FORM_ON_WING_NEW, true}, {"ORDER_GUARD", LE_ORDER_GUARD, true}, {"ORDER_GUARD_WING", LE_ORDER_GUARD_WING, true}, {"ORDER_IGNORE_SHIP", LE_ORDER_IGNORE, true}, @@ -48,6 +49,7 @@ const lua_enum_def_list Enumerations[] = { {"ORDER_REARM", LE_ORDER_REARM, true}, {"ORDER_STAY_NEAR", LE_ORDER_STAY_NEAR, true}, {"ORDER_STAY_STILL", LE_ORDER_STAY_STILL, true}, + {"ORDER_STAY_STILL_NEW", LE_ORDER_STAY_STILL_NEW, true}, {"ORDER_UNDOCK", LE_ORDER_UNDOCK, true}, {"ORDER_WAYPOINTS", LE_ORDER_WAYPOINTS, true}, {"ORDER_WAYPOINTS_ONCE", LE_ORDER_WAYPOINTS_ONCE, true}, diff --git a/code/scripting/api/objs/enums.h b/code/scripting/api/objs/enums.h index a2db7fe9d60..53f51c62fc2 100644 --- a/code/scripting/api/objs/enums.h +++ b/code/scripting/api/objs/enums.h @@ -37,6 +37,7 @@ enum lua_enum : int32_t { LE_ORDER_EVADE, LE_ORDER_FLY_TO, LE_ORDER_FORM_ON_WING, + LE_ORDER_FORM_ON_WING_NEW, LE_ORDER_GUARD, LE_ORDER_GUARD_WING, LE_ORDER_IGNORE, @@ -47,6 +48,7 @@ enum lua_enum : int32_t { LE_ORDER_REARM, LE_ORDER_STAY_NEAR, LE_ORDER_STAY_STILL, + LE_ORDER_STAY_STILL_NEW, LE_ORDER_UNDOCK, LE_ORDER_WAYPOINTS, LE_ORDER_WAYPOINTS_ONCE, diff --git a/code/scripting/api/objs/order.cpp b/code/scripting/api/objs/order.cpp index 96e2b0b9b5f..f9d309b4da7 100644 --- a/code/scripting/api/objs/order.cpp +++ b/code/scripting/api/objs/order.cpp @@ -90,7 +90,6 @@ ADE_FUNC(getType, l_Order, NULL, "Gets the type of the order.", "enumeration", " switch(ohp->aigp->ai_mode){ case AI_GOAL_NONE: - case AI_GOAL_PLACEHOLDER_1: case AI_GOAL_NUM_VALUES: break; case AI_GOAL_DESTROY_SUBSYSTEM: @@ -113,6 +112,9 @@ ADE_FUNC(getType, l_Order, NULL, "Gets the type of the order.", "enumeration", " case AI_GOAL_FORM_ON_WING: eh_idx = LE_ORDER_FORM_ON_WING; break; + case AI_GOAL_FORM_ON_WING_NEW: + eh_idx = LE_ORDER_FORM_ON_WING_NEW; + break; case AI_GOAL_UNDOCK: eh_idx = LE_ORDER_UNDOCK; break; @@ -155,6 +157,9 @@ ADE_FUNC(getType, l_Order, NULL, "Gets the type of the order.", "enumeration", " case AI_GOAL_STAY_STILL: eh_idx = LE_ORDER_STAY_STILL; break; + case AI_GOAL_STAY_STILL_NEW: + eh_idx = LE_ORDER_STAY_STILL_NEW; + break; case AI_GOAL_PLAY_DEAD: eh_idx = LE_ORDER_PLAY_DEAD; break; @@ -202,18 +207,20 @@ ADE_VIRTVAR(Target, l_Order, "object", "Target of the order. Value may also be a case AI_GOAL_DESTROY_SUBSYSTEM: case AI_GOAL_CHASE: case AI_GOAL_FORM_ON_WING: + case AI_GOAL_FORM_ON_WING_NEW: case AI_GOAL_GUARD: case AI_GOAL_DISABLE_SHIP: case AI_GOAL_DISABLE_SHIP_TACTICAL: case AI_GOAL_DISARM_SHIP: case AI_GOAL_DISARM_SHIP_TACTICAL: - case AI_GOAL_IGNORE_NEW: case AI_GOAL_IGNORE: + case AI_GOAL_IGNORE_NEW: case AI_GOAL_EVADE_SHIP: case AI_GOAL_STAY_NEAR_SHIP: case AI_GOAL_KEEP_SAFE_DISTANCE: case AI_GOAL_FLY_TO_SHIP: case AI_GOAL_STAY_STILL: + case AI_GOAL_STAY_STILL_NEW: if ((newh->objp()->type == OBJ_SHIP) && !stricmp(Ships[newh->objp()->instance].ship_name, ohp->aigp->target_name)){ ohp->aigp->target_name = Ships[newh->objp()->instance].ship_name; ohp->aigp->time = Missiontime; @@ -290,13 +297,14 @@ ADE_VIRTVAR(Target, l_Order, "object", "Target of the order. Value may also be a case AI_GOAL_CHASE: case AI_GOAL_DOCK: case AI_GOAL_FORM_ON_WING: + case AI_GOAL_FORM_ON_WING_NEW: case AI_GOAL_GUARD: case AI_GOAL_DISABLE_SHIP: case AI_GOAL_DISABLE_SHIP_TACTICAL: case AI_GOAL_DISARM_SHIP: case AI_GOAL_DISARM_SHIP_TACTICAL: - case AI_GOAL_IGNORE_NEW: case AI_GOAL_IGNORE: + case AI_GOAL_IGNORE_NEW: case AI_GOAL_EVADE_SHIP: case AI_GOAL_STAY_NEAR_SHIP: case AI_GOAL_KEEP_SAFE_DISTANCE: @@ -323,6 +331,7 @@ ADE_VIRTVAR(Target, l_Order, "object", "Target of the order. Value may also be a } break; case AI_GOAL_STAY_STILL: + case AI_GOAL_STAY_STILL_NEW: shipnum = ship_name_lookup(ohp->aigp->target_name); if (shipnum != -1){ objnum = Ships[shipnum].objnum; diff --git a/code/scripting/api/objs/ship.cpp b/code/scripting/api/objs/ship.cpp index 1e3ba45c31f..142fe46a138 100644 --- a/code/scripting/api/objs/ship.cpp +++ b/code/scripting/api/objs/ship.cpp @@ -1587,21 +1587,11 @@ ADE_FUNC(giveOrder, l_Ship, "enumeration Order, [object Target=nil, subsystem Ta break; } case LE_ORDER_WAYPOINTS: - { - if(tgh_valid && tgh->objp()->type == OBJ_WAYPOINT) - { - ai_mode = AI_GOAL_WAYPOINTS; - waypoint_list *wp_list = find_waypoint_list_with_instance(tgh->objp()->instance); - if(wp_list != NULL) - ai_shipname = wp_list->get_name(); - } - break; - } case LE_ORDER_WAYPOINTS_ONCE: { if(tgh_valid && tgh->objp()->type == OBJ_WAYPOINT) { - ai_mode = AI_GOAL_WAYPOINTS_ONCE; + ai_mode = (eh->index == LE_ORDER_WAYPOINTS_ONCE) ? AI_GOAL_WAYPOINTS_ONCE : AI_GOAL_WAYPOINTS; waypoint_list *wp_list = find_waypoint_list_with_instance(tgh->objp()->instance); if(wp_list != NULL) ai_shipname = wp_list->get_name(); @@ -1615,10 +1605,11 @@ ADE_FUNC(giveOrder, l_Ship, "enumeration Order, [object Target=nil, subsystem Ta break; } case LE_ORDER_FORM_ON_WING: + case LE_ORDER_FORM_ON_WING_NEW: { if(tgh_valid && tgh->objp()->type == OBJ_SHIP) { - ai_mode = AI_GOAL_FORM_ON_WING; + ai_mode = (eh->index == LE_ORDER_FORM_ON_WING) ? AI_GOAL_FORM_ON_WING : AI_GOAL_FORM_ON_WING_NEW; ai_shipname = Ships[tgh->objp()->instance].ship_name; ai_submode = 0; } @@ -1724,8 +1715,9 @@ ADE_FUNC(giveOrder, l_Ship, "enumeration Order, [object Target=nil, subsystem Ta break; } case LE_ORDER_STAY_STILL: + case LE_ORDER_STAY_STILL_NEW: { - ai_mode = AI_GOAL_STAY_STILL; + ai_mode = (eh->index == LE_ORDER_STAY_STILL) ? AI_GOAL_STAY_STILL : AI_GOAL_STAY_STILL_NEW; if(tgh_valid && tgh->objp()->type == OBJ_SHIP) { ai_shipname = Ships[tgh->objp()->instance].ship_name; diff --git a/code/ship/ship.cpp b/code/ship/ship.cpp index b676b93567a..30113057d73 100644 --- a/code/ship/ship.cpp +++ b/code/ship/ship.cpp @@ -17245,6 +17245,7 @@ static const char* ship_get_ai_target_display_name(int goal, const char* name) switch (goal) { // These goals refer to ships so we need to retrieve their display name case AI_GOAL_FORM_ON_WING: + case AI_GOAL_FORM_ON_WING_NEW: case AI_GOAL_CHASE: case AI_GOAL_DOCK: case AI_GOAL_UNDOCK: @@ -17313,6 +17314,7 @@ SCP_string ship_return_orders(ship* sp) switch (aigp->ai_mode) { case AI_GOAL_FORM_ON_WING: + case AI_GOAL_FORM_ON_WING_NEW: case AI_GOAL_GUARD_WING: case AI_GOAL_CHASE_WING: if (aigp->target_name) { diff --git a/fred2/fredview.cpp b/fred2/fredview.cpp index e5ce41f34ef..6bca750ebc7 100644 --- a/fred2/fredview.cpp +++ b/fred2/fredview.cpp @@ -3522,6 +3522,7 @@ char *error_check_initial_orders(ai_goal *goals, int ship, int wing) break; case AI_GOAL_STAY_STILL: + case AI_GOAL_STAY_STILL_NEW: flag = 4; break; diff --git a/fred2/management.cpp b/fred2/management.cpp index 49024a82da7..fa28dc2aa20 100644 --- a/fred2/management.cpp +++ b/fred2/management.cpp @@ -142,6 +142,7 @@ ai_goal_list Ai_goal_list[] = { { "Stay near ship", AI_GOAL_STAY_NEAR_SHIP, 0 }, { "Keep safe distance", AI_GOAL_KEEP_SAFE_DISTANCE, 0 }, { "Stay still", AI_GOAL_STAY_STILL, 0 }, + { "Stay still (new)", AI_GOAL_STAY_STILL_NEW, 0 }, { "Play dead", AI_GOAL_PLAY_DEAD, 0 }, { "Play dead (persistent)", AI_GOAL_PLAY_DEAD_PERSISTENT, 0 } }; diff --git a/fred2/missionsave.cpp b/fred2/missionsave.cpp index a04c1b7da6c..dd36252cb93 100644 --- a/fred2/missionsave.cpp +++ b/fred2/missionsave.cpp @@ -703,6 +703,10 @@ void CFred_mission_save::save_ai_goals(ai_goal *goalp, int ship) str = "ai-stay-still"; break; + case AI_GOAL_STAY_STILL_NEW: + str = "ai-stay-still-new"; + break; + case AI_GOAL_REARM_REPAIR: str = "ai-rearm-repair"; break; diff --git a/fred2/shipgoalsdlg.cpp b/fred2/shipgoalsdlg.cpp index 1906ec335f0..7a57d1d6e94 100644 --- a/fred2/shipgoalsdlg.cpp +++ b/fred2/shipgoalsdlg.cpp @@ -505,6 +505,7 @@ void ShipGoalsDlg::initialize(ai_goal *goals, int ship) break; case AI_GOAL_STAY_STILL: + case AI_GOAL_STAY_STILL_NEW: flag = 9; // target is a ship or a waypoint break; @@ -688,6 +689,7 @@ void ShipGoalsDlg::set_item(int item, int init) break; case AI_GOAL_STAY_STILL: + case AI_GOAL_STAY_STILL_NEW: ptr = GET_FIRST(&obj_used_list); while (ptr != END_OF_LIST(&obj_used_list)) { if (ptr->type == OBJ_WAYPOINT) { @@ -731,6 +733,7 @@ void ShipGoalsDlg::set_item(int item, int init) case AI_GOAL_IGNORE_NEW: case AI_GOAL_STAY_NEAR_SHIP: case AI_GOAL_STAY_STILL: + case AI_GOAL_STAY_STILL_NEW: ptr = GET_FIRST(&obj_used_list); while (ptr != END_OF_LIST(&obj_used_list)) { if ((ptr->type == OBJ_SHIP) || (ptr->type == OBJ_START)) { @@ -1007,6 +1010,7 @@ void ShipGoalsDlg::update_item(int item, int multi) case AI_GOAL_EVADE_SHIP: case AI_GOAL_STAY_NEAR_SHIP: case AI_GOAL_STAY_STILL: + case AI_GOAL_STAY_STILL_NEW: case AI_GOAL_CHASE_SHIP_CLASS: break; diff --git a/qtfred/src/mission/Editor.cpp b/qtfred/src/mission/Editor.cpp index 08f2ff0807b..2086f85ab65 100644 --- a/qtfred/src/mission/Editor.cpp +++ b/qtfred/src/mission/Editor.cpp @@ -87,6 +87,7 @@ ai_goal_list Ai_goal_list[] = { { "Stay near ship", AI_GOAL_STAY_NEAR_SHIP, 0 }, { "Keep safe distance", AI_GOAL_KEEP_SAFE_DISTANCE, 0 }, { "Stay still", AI_GOAL_STAY_STILL, 0 }, + { "Stay still (new)", AI_GOAL_STAY_STILL_NEW, 0 }, { "Play dead", AI_GOAL_PLAY_DEAD, 0 }, { "Play dead (persistent)", AI_GOAL_PLAY_DEAD_PERSISTENT, 0 } }; @@ -2765,6 +2766,7 @@ const char* Editor::error_check_initial_orders(ai_goal* goals, int ship, int win break; case AI_GOAL_STAY_STILL: + case AI_GOAL_STAY_STILL_NEW: flag = 4; break; diff --git a/qtfred/src/mission/dialogs/ShipEditor/ShipGoalsDialogModel.cpp b/qtfred/src/mission/dialogs/ShipEditor/ShipGoalsDialogModel.cpp index 3e6ce39fe6c..27f5955be16 100644 --- a/qtfred/src/mission/dialogs/ShipEditor/ShipGoalsDialogModel.cpp +++ b/qtfred/src/mission/dialogs/ShipEditor/ShipGoalsDialogModel.cpp @@ -167,6 +167,7 @@ namespace fso { case AI_GOAL_EVADE_SHIP: case AI_GOAL_STAY_NEAR_SHIP: case AI_GOAL_STAY_STILL: + case AI_GOAL_STAY_STILL_NEW: case AI_GOAL_CHASE_SHIP_CLASS: break; @@ -491,6 +492,7 @@ namespace fso { break; case AI_GOAL_STAY_STILL: + case AI_GOAL_STAY_STILL_NEW: flag = 9; // target is a ship or a waypoint break; diff --git a/qtfred/src/mission/missionsave.cpp b/qtfred/src/mission/missionsave.cpp index 4ebf0393ac1..a4b374ba744 100644 --- a/qtfred/src/mission/missionsave.cpp +++ b/qtfred/src/mission/missionsave.cpp @@ -715,6 +715,10 @@ void CFred_mission_save::save_ai_goals(ai_goal* goalp, int ship) str = "ai-stay-still"; break; + case AI_GOAL_STAY_STILL_NEW: + str = "ai-stay-still-new"; + break; + case AI_GOAL_REARM_REPAIR: str = "ai-rearm-repair"; break; diff --git a/qtfred/src/ui/dialogs/ShipEditor/ShipGoalsDialog.cpp b/qtfred/src/ui/dialogs/ShipEditor/ShipGoalsDialog.cpp index e3063d05425..e4ce36c1440 100644 --- a/qtfred/src/ui/dialogs/ShipEditor/ShipGoalsDialog.cpp +++ b/qtfred/src/ui/dialogs/ShipEditor/ShipGoalsDialog.cpp @@ -177,6 +177,7 @@ void ShipGoalsDialog::updateUI() break; case AI_GOAL_STAY_STILL: + case AI_GOAL_STAY_STILL_NEW: object* ptr; ptr = GET_FIRST(&obj_used_list); while (ptr != END_OF_LIST(&obj_used_list)) { @@ -228,6 +229,7 @@ void ShipGoalsDialog::updateUI() case AI_GOAL_IGNORE_NEW: case AI_GOAL_STAY_NEAR_SHIP: case AI_GOAL_STAY_STILL: + case AI_GOAL_STAY_STILL_NEW: object* ptr; int inst, t; ptr = GET_FIRST(&obj_used_list);