Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions code/ai/aicode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11123,6 +11123,12 @@ void ai_do_objects_repairing_stuff( object *repaired_objp, object *repair_objp,
aip->ai_flags.remove(AI::AI_Flags::Awaiting_repair);
stamp = timestamp(-1);

if (repair_objp != nullptr && scripting::hooks::OnSupportRearmStarted->isActive()) {
scripting::hooks::OnSupportRearmStarted->run(
scripting::hook_param_list(scripting::hook_param("Support Ship", 'o', repair_objp),
scripting::hook_param("Target Ship", 'o', repaired_objp)));
}

// if this is a player ship, then subtract the repair penalty from this player's score
if ( repaired_objp->flags[Object::Object_Flags::Player_ship] ) {
if ( !(Game_mode & GM_MULTIPLAYER) ) {
Expand Down Expand Up @@ -11195,6 +11201,12 @@ void ai_do_objects_repairing_stuff( object *repaired_objp, object *repair_objp,
mission_log_add_entry(LOG_PLAYER_ABORTED_REARM, Ships[repaired_objp->instance].ship_name, NULL);
}

if (repair_objp != nullptr && scripting::hooks::OnSupportRearmFinished->isActive()) {
scripting::hooks::OnSupportRearmFinished->run(
scripting::hook_param_list(scripting::hook_param("Support Ship", 'o', repair_objp),
scripting::hook_param("Target Ship", 'o', repaired_objp)));
}

stamp = timestamp((int) ((30 + 10*frand()) * 1000));
break;

Expand Down
1 change: 1 addition & 0 deletions code/mission/mission_flags.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ namespace Mission {
Neb2_fog_color_override, // Whether to use explicit fog colors instead of checking the palette - Goober5000
Fullneb_background_bitmaps, // Show background bitmaps despite fullneb
Preload_subspace, // Preload the subspace tunnel for both the sexp and specs checkbox (for scripts) - MjnMixael
Limited_support_rearm_pool, // Support ships can only rearm weapons while mission-level pool is available - MjnMixael

NUM_VALUES
};
Expand Down
91 changes: 87 additions & 4 deletions code/mission/missionparse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,8 @@ flag_def_list_new<Mission::Mission_Flags> Parse_mission_flags[] = {
{"Toggle Starting in Chase View", Mission::Mission_Flags::Toggle_start_chase_view, true, false},
{"Nebula Fog Color Override", Mission::Mission_Flags::Neb2_fog_color_override, true, true},
{"Full Nebula Background Bitmaps", Mission::Mission_Flags::Fullneb_background_bitmaps, true, true},
{"Preload Subspace Tunnel", Mission::Mission_Flags::Preload_subspace, true, false}
{"Preload Subspace Tunnel", Mission::Mission_Flags::Preload_subspace, true, false},
{"Limit Support Rearm to Mission Pool", Mission::Mission_Flags::Limited_support_rearm_pool, true, true}
};

parse_object_flag_description<Mission::Mission_Flags> Parse_mission_flag_descriptions[] = {
Expand Down Expand Up @@ -418,7 +419,8 @@ parse_object_flag_description<Mission::Mission_Flags> Parse_mission_flag_descrip
{Mission::Mission_Flags::Toggle_start_chase_view, "Toggles whether the player starts the mission in chase view"},
{Mission::Mission_Flags::Neb2_fog_color_override, "Whether to use explicit fog colors instead of checking the palette"},
{Mission::Mission_Flags::Fullneb_background_bitmaps, "Show background bitmaps despite full nebula"},
{Mission::Mission_Flags::Preload_subspace, "Preload the subspace tunnel for both the sexp and specs checkbox"},
{Mission::Mission_Flags::Preload_subspace, "Preload the subspace tunnel for both the sexp and specs checkbox"},
{Mission::Mission_Flags::Limited_support_rearm_pool, "Support ships can only rearm from the mission weapon pool"},
};

const size_t Num_parse_mission_flags = sizeof(Parse_mission_flags) / sizeof(flag_def_list_new<Mission::Mission_Flags>);
Expand Down Expand Up @@ -882,6 +884,18 @@ void parse_mission_info(mission *pm, bool basic = false)
pm->support_ships.max_support_ships = (temp > 0) ? 0 : -1;
}

if (optional_string("+Disallow Support Rearm:")) {
int temp;
stuff_int(&temp);
pm->support_ships.disallow_rearm = (temp != 0);
}

if (optional_string("+Allow Support Rearm Weapon Precedence:")) {
int temp;
stuff_int(&temp);
pm->support_ships.allow_rearm_weapon_precedence = (temp != 0);
}

if ( optional_string("+Hull Repair Ceiling:"))
{
float temp;
Expand All @@ -904,6 +918,12 @@ void parse_mission_info(mission *pm, bool basic = false)
}
}

if (optional_string("+Support Rearm Pool From Loadout:")) {
int temp;
stuff_int(&temp);
pm->support_ships.rearm_pool_from_loadout = (temp != 0);
}

if (optional_string("+All Teams Attack")){
Mission_all_attack = 1;
}
Expand Down Expand Up @@ -1106,13 +1126,16 @@ void parse_player_info(mission *pm)
void parse_player_info2(mission *pm)
{
int nt, i;
SCP_vector<loadout_row> list, list2;
SCP_vector<loadout_row> list, list2, support_rearm_list;
team_data *ptr;

if (OnLoadoutAboutToParseHook->isActive()) {
OnLoadoutAboutToParseHook->run();
}

// initialize support rearm pool from mission loadout data (weapon index -> count)
memset(pm->support_ships.rearm_weapon_pool, 0, sizeof(pm->support_ships.rearm_weapon_pool));

// read in a ship/weapon pool for each team.
for ( nt = 0; nt < Num_teams; nt++ ) {
int num_choices;
Expand Down Expand Up @@ -1223,6 +1246,13 @@ void parse_player_info2(mission *pm)

ptr->weaponry_pool[num_choices] = wc.index;
ptr->weaponry_count[num_choices] = wc.count;
if (pm->support_ships.rearm_pool_from_loadout) {
if (Weapon_info[wc.index].disallow_rearm) {
pm->support_ships.rearm_weapon_pool[nt][wc.index] = 0;
} else if (wc.count > 0 && pm->support_ships.rearm_weapon_pool[nt][wc.index] >= 0) {
pm->support_ships.rearm_weapon_pool[nt][wc.index] += wc.count;
}
}

// if the list isn't set by a variable leave the variable name empty
if (wc.index_sexp_var == NOT_SET_BY_SEXP_VARIABLE) {
Expand All @@ -1244,6 +1274,34 @@ void parse_player_info2(mission *pm)
}
ptr->num_weapon_choices = num_choices;

if (optional_string("+Support Rearm Pool:")) {
support_rearm_list.clear();
stuff_loadout_list(support_rearm_list, ParseLookupType::MISSION_LOADOUT_WEAPON_LIST);

if (!pm->support_ships.rearm_pool_from_loadout) {
for (auto& wc : support_rearm_list) {
if (wc.index < 0 || wc.index >= weapon_info_size()) {
continue;
}

if (!(Weapon_info[wc.index].wi_flags[Weapon::Info_Flags::Player_allowed]) && !Fred_running) {
WarningEx(LOCATION,
"Weapon '%s' in support rearm pool isn't allowed on player loadout! Ignoring it ...\n",
Weapon_info[wc.index].name);
continue;
}

if (Weapon_info[wc.index].disallow_rearm) {
pm->support_ships.rearm_weapon_pool[nt][wc.index] = 0;
} else if (wc.count < 0) {
pm->support_ships.rearm_weapon_pool[nt][wc.index] = -1;
} else if (wc.count > 0 && pm->support_ships.rearm_weapon_pool[nt][wc.index] >= 0) {
pm->support_ships.rearm_weapon_pool[nt][wc.index] += wc.count;
}
}
}
}

memset(ptr->weapon_required, 0, MAX_WEAPON_TYPES * sizeof(bool));
if (optional_string("+Required for mission:"))
{
Expand Down Expand Up @@ -7072,6 +7130,10 @@ void mission::Reset()
support_ships.max_support_ships = -1; // infinite
support_ships.max_concurrent_ships = 1;
support_ships.ship_class = -1;
memset(&support_ships.rearm_weapon_pool, -1, sizeof(support_ships.rearm_weapon_pool));
support_ships.disallow_rearm = false;
support_ships.allow_rearm_weapon_precedence = false;
support_ships.rearm_pool_from_loadout = false;

// for each species, store whether support is available
for (int species = 0; species < (int)Species_info.size(); species++) {
Expand Down Expand Up @@ -9443,5 +9505,26 @@ bool check_for_24_3_data()

bool check_for_25_1_data()
{
return (count_items_with_value(Props) > 0);
if ((count_items_with_value(Props) > 0)) {
return true;
}

if (The_mission.flags[Mission::Mission_Flags::Limited_support_rearm_pool]) {
return true;
}

if (The_mission.support_ships.disallow_rearm || The_mission.support_ships.allow_rearm_weapon_precedence ||
The_mission.support_ships.rearm_pool_from_loadout) {
return true;
}

for (int team = 0; team < Num_teams; ++team) {
for (int pool_wep = 0; pool_wep < MAX_WEAPON_TYPES; ++pool_wep) {
if (The_mission.support_ships.rearm_weapon_pool[team][pool_wep] != -1) {
return true;
}
}
}

return false;
}
26 changes: 15 additions & 11 deletions code/mission/missionparse.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,17 +103,21 @@ inline const std::vector<std::pair<SCP_string, int>> Mission_event_teams_tvt = [

// Goober5000
typedef struct support_ship_info {
ArrivalLocation arrival_location; // arrival location
int arrival_anchor; // arrival anchor
DepartureLocation departure_location; // departure location
int departure_anchor; // departure anchor
float max_hull_repair_val; // % of a ship's hull that can be repaired -C
float max_subsys_repair_val; // same thing, except for subsystems -C
int max_support_ships; // max number of consecutive support ships
int max_concurrent_ships; // max number of concurrent support ships in mission per team
int ship_class; // ship class of support ship
int tally; // number of support ships so far
int support_available_for_species; // whether support is available for a given species (this is a bitfield)
ArrivalLocation arrival_location; // arrival location
int arrival_anchor; // arrival anchor
DepartureLocation departure_location; // departure location
int departure_anchor; // departure anchor
float max_hull_repair_val; // % of a ship's hull that can be repaired -C
float max_subsys_repair_val; // same thing, except for subsystems -C
int max_support_ships; // max number of consecutive support ships
int max_concurrent_ships; // max number of concurrent support ships in mission per team
int ship_class; // ship class of support ship
int tally; // number of support ships so far
int support_available_for_species; // whether support is available for a given species (this is a bitfield)
bool disallow_rearm; // if true, support ships can only repair and will not rearm weapons
bool allow_rearm_weapon_precedence; // if true, support ships may swap to precedence weapons when rearm pool is empty
bool rearm_pool_from_loadout; // initialize rearm pool from mission loadout after filling starting loadout ships
int rearm_weapon_pool[MAX_TVT_TEAMS][MAX_WEAPON_TYPES]; // mission stockpile used to limit support ship rearming
} support_ship_info;

// movie type defines
Expand Down
44 changes: 44 additions & 0 deletions code/missioneditor/missionsave.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2757,6 +2757,24 @@ int Fred_mission_save::save_mission_info()
// this is compatible with non-SCP variants - Goober5000
fout(" %d", (The_mission.support_ships.max_support_ships == 0) ? 1 : 0);

if (save_config.save_format != MissionFormat::RETAIL) {
if (optional_string_fred("+Disallow Support Rearm:")) {
parse_comments(2);
} else {
fout("\n+Disallow Support Rearm:");
}

fout(" %d", The_mission.support_ships.disallow_rearm ? 1 : 0);

if (optional_string_fred("+Allow Support Rearm Weapon Precedence:")) {
parse_comments(2);
} else {
fout("\n+Allow Support Rearm Weapon Precedence:");
}

fout(" %d", The_mission.support_ships.allow_rearm_weapon_precedence ? 1 : 0);
}

// here be WMCoolmon's hull and subsys repair stuff
if (save_config.save_format != MissionFormat::RETAIL) {
if (optional_string_fred("+Hull Repair Ceiling:")) {
Expand All @@ -2772,6 +2790,13 @@ int Fred_mission_save::save_mission_info()
fout("\n+Subsystem Repair Ceiling:");
}
fout(" %f", The_mission.support_ships.max_subsys_repair_val);

if (optional_string_fred("+Support Rearm Pool From Loadout:")) {
parse_comments(1);
} else {
fout("\n+Support Rearm Pool From Loadout:");
}
fout(" %d", The_mission.support_ships.rearm_pool_from_loadout ? 1 : 0);
}

if (Mission_all_attack) {
Expand Down Expand Up @@ -4369,6 +4394,25 @@ int Fred_mission_save::save_players()

fout(")");

if (save_config.save_format != MissionFormat::RETAIL && !The_mission.support_ships.rearm_pool_from_loadout) {
if (optional_string_fred("+Support Rearm Pool:", "$Starting Shipname:")) {
parse_comments(2);
} else {
fout("\n\n+Support Rearm Pool:");
}

fout(" (\n");
for (j = 0; j < weapon_info_size(); j++) {
if (!Weapon_info[j].wi_flags[Weapon::Info_Flags::Player_allowed]) {
continue;
}
if (The_mission.support_ships.rearm_weapon_pool[i][j] != 0) {
fout("\t\"%s\"\t%d\n", Weapon_info[j].name, The_mission.support_ships.rearm_weapon_pool[i][j]);
}
}
fout(")");
}

// sanity check
if (save_config.save_format == MissionFormat::RETAIL && wrote_fso_data) {
// this is such an unlikely (and hard-to-fix) case that a warning should be sufficient
Expand Down
37 changes: 37 additions & 0 deletions code/scripting/api/libs/mission.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
#include "scripting/api/objs/ship.h"
#include "scripting/api/objs/shipclass.h"
#include "scripting/api/objs/sound.h"
#include "scripting/api/objs/support_rearm_pool.h"
#include "scripting/api/objs/team.h"
#include "scripting/api/objs/vecmath.h"
#include "scripting/api/objs/waypoint.h"
Expand Down Expand Up @@ -261,6 +262,42 @@ ADE_FUNC(runSEXP, l_Mission, "string", "Runs the defined SEXP script within a `w
return ADE_RETURN_FALSE;
}

//****SUBLIBRARY: Mission/SupportRearmPools
ADE_LIB_DERIV(l_Mission_SupportRearmPools,
"SupportRearmPools",
nullptr,
"Per-team mission support rearm pools (team indexed).",
l_Mission);

ADE_INDEXER(l_Mission_SupportRearmPools,
"number TeamIndex",
"Gets support rearm pool handle for a specific team.",
"support_rearm_pool_team",
"Support rearm pool team handle, or invalid handle if index is out of range.")
{
int idx = -1;
if (!ade_get_args(L, "*i", &idx)) {
return ade_set_error(L, "o", l_SupportRearmPoolTeam.Set(-1));
}

idx--; // Lua to C++ index
if (idx < 0 || idx >= Num_teams || idx >= MAX_TVT_TEAMS) {
return ade_set_error(L, "o", l_SupportRearmPoolTeam.Set(-1));
}

return ade_set_args(L, "o", l_SupportRearmPoolTeam.Set(idx));
}

ADE_FUNC(__len,
l_Mission_SupportRearmPools,
nullptr,
"The number of support rearm pool teams.",
"number",
"The number of TVT/loadout teams with support rearm pools.")
{
return ade_set_args(L, "i", MIN(Num_teams, MAX_TVT_TEAMS));
}

//****SUBLIBRARY: Mission/Asteroids
ADE_LIB_DERIV(l_Mission_Asteroids, "Asteroids", NULL, "Asteroids in the mission", l_Mission);

Expand Down
Loading