Skip to content
Draft
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
2 changes: 1 addition & 1 deletion code/ai/ai_profiles.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ extern int Num_ai_profiles;
extern int Default_ai_profile;
extern ai_profile_t Ai_profiles[MAX_AI_PROFILES];

#define AI_PROFILES_INDEX(ai_p) ((int)((ai_p) - Ai_profiles))
#define AI_PROFILES_INDEX(ai_p) (static_cast<int>((ai_p)-Ai_profiles))

void ai_profiles_init();

Expand Down
2 changes: 1 addition & 1 deletion code/ai/aiturret.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1755,7 +1755,7 @@ bool turret_fire_weapon(int weapon_num,

parent_aip = &Ai_info[Ships[Objects[parent_objnum].instance].ai_index];
parent_ship = &Ships[Objects[parent_objnum].instance];
int turret_weapon_class = weapon_info_get_index(wip);
int turret_weapon_class = WEAPON_INFO_INDEX(wip);

#ifndef NDEBUG
// moved here from check_ok_to_fire
Expand Down
2 changes: 1 addition & 1 deletion code/debris/debris.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ int Debris_num_submodels = 0;

particle::ParticleEffectHandle Debris_hit_particle;

#define DEBRIS_INDEX(dp) (int)(dp-Debris.data())
#define DEBRIS_INDEX(dp) (static_cast<int>((dp)-Debris.data()))

// Find the first available arc slot. If none is available, and no_create is false, add one.
debris_electrical_arc *debris_find_or_create_electrical_arc_slot(debris *db, bool no_create);
Expand Down
54 changes: 45 additions & 9 deletions code/mission/missionparse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ SCP_vector<SCP_string> Parse_names;

SCP_vector<SCP_string> Mission_parse_warnings;

// true while a mission is being parsed and post-processed
bool Parsing_mission = false;

// Routes a parse-time auto-correction notice to the right surface for the app:
// outside QtFRED, the existing Warning(LOCATION, ...) popup; inside QtFRED, the
// Mission_parse_warnings queue so the ErrorChecker can present it without a popup.
Expand Down Expand Up @@ -4801,8 +4804,26 @@ int parse_wing_create_ships( wing *wingp, int num_to_create, bool force_create,
wingp->total_arrived_count++;
if (wingp->num_waves > 1)
{
char pre_bash_name[NAME_LENGTH];
strcpy_s(pre_bash_name, p_objp->name);

wing_bash_ship_name(p_objp, wingp, wingp->total_arrived_count + wingp->red_alert_skipped_ships);

// if the bash renamed this parse object (which can happen if the ship was saved using the legacy
// hash format), re-key its not-yet-present registry entry so that the old name doesn't shadow
// lookups of the new name. (For subsequent waves, the pre-bash name belongs to a previous wave's
// ship, whose entry must keep its key; the status and parse object checks exclude that case.)
if (stricmp(pre_bash_name, p_objp->name) != 0)
{
auto ship_it = Ship_registry_map.find(pre_bash_name);
if (ship_it != Ship_registry_map.end()
&& Ship_registry[ship_it->second].status == ShipStatus::NOT_YET_PRESENT
&& Ship_registry[ship_it->second].pobj_num == POBJ_INDEX(p_objp))
{
ship_registry_rename(ship_it->second, p_objp->name, true);
}
}

// subsequent waves of ships will not be in the ship registry, so add them
if (!ship_registry_exists(p_objp->name))
{
Expand Down Expand Up @@ -7534,6 +7555,8 @@ bool parse_main(const char *mission_name, int flags)

Assert(Ship_info.size() <= MAX_SHIP_CLASSES);

Parsing_mission = true;

do {
// don't do this for imports
if (!(flags & MPF_IMPORT_FSM)) {
Expand Down Expand Up @@ -7585,6 +7608,8 @@ bool parse_main(const char *mission_name, int flags)
}
} while (0);

Parsing_mission = false;

if (!Fred_running)
strcpy_s(Mission_filename, mission_name);

Expand Down Expand Up @@ -8026,6 +8051,17 @@ int mission_parse_get_multi_mission_info( const char *filename )
return The_mission.num_players;
}

static p_object *mission_parse_get_arrival_ship_sub(const char *name)
{
for (auto p_objp : list_range(&Ship_arrival_list))
{
if (!stricmp(p_objp->name, name))
return p_objp; // still on the arrival list
}

return nullptr;
}

/**
* @brief Returns the parse object on the ship arrival list associated with the given name.
* @param[in] name The name of the object
Expand All @@ -8036,18 +8072,18 @@ int mission_parse_get_multi_mission_info( const char *filename )
*/
p_object *mission_parse_get_arrival_ship(const char *name)
{
p_object *p_objp;

if (name == nullptr)
return nullptr;

for (p_objp = GET_FIRST(&Ship_arrival_list); p_objp != END_OF_LIST(&Ship_arrival_list); p_objp = GET_NEXT(p_objp))
{
if (!stricmp(p_objp->name, name))
{
return p_objp; // still on the arrival list
}
}
// try the normal lookup
auto p_objp = mission_parse_get_arrival_ship_sub(name);
if (p_objp)
return p_objp;

// also search for ship names hashed using the legacy format
SCP_string legacy_hashed;
if (wing_bash_legacy_hashed_ship_name(legacy_hashed, name))
return mission_parse_get_arrival_ship_sub(legacy_hashed.c_str());

return nullptr;
}
Expand Down
5 changes: 4 additions & 1 deletion code/mission/missionparse.h
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@ class p_object

// Goober5000 - this is now dynamic
extern SCP_vector<p_object> Parse_objects;
#define POBJ_INDEX(pobjp) (int)(pobjp - &Parse_objects[0]) // yes, this arithmetic is valid :D
#define POBJ_INDEX(pobjp) (static_cast<int>((pobjp)-Parse_objects.data()))

extern p_object Support_ship_pobj, *Arriving_support_ship;
extern p_object Ship_arrival_list;
Expand Down Expand Up @@ -588,6 +588,9 @@ extern SCP_vector<SCP_string> Parse_names;
// silently buried. Outside of QtFRED these sites still call Warning(LOCATION, ...).
extern SCP_vector<SCP_string> Mission_parse_warnings;

// true while a mission is being parsed and post-processed
extern bool Parsing_mission;

extern char Player_start_shipname[NAME_LENGTH];
extern int Player_start_shipnum;
extern p_object *Player_start_pobject;
Expand Down
5 changes: 2 additions & 3 deletions code/missionui/redalert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -969,9 +969,8 @@ void red_alert_bash_ship_status()
// give the ship its name from the latest wave
// (this will make the ship match to the correct red-alert data)
wing_bash_ship_name(shipp, wingp, ((rws->latest_wave - 1) * wingp->wave_count) + 1 + pos_in_wing);
// need to update the ship registry too
strcpy_s(Ship_registry[ship_entry_index].name, shipp->ship_name);
Ship_registry_map[shipp->ship_name] = ship_entry_index;
// need to update the ship registry too; keep the old key because the previous name was a real ship name that may still be referenced
ship_registry_rename(ship_entry_index, shipp->ship_name, false);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion code/network/multi.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ class player;
//

// netplayer management
#define NET_PLAYER_INDEX(np) (static_cast<int>(np-Net_players))
#define NET_PLAYER_INDEX(np) (static_cast<int>((np)-Net_players))
#define NET_PLAYER_NUM(np) (NET_PLAYER_INDEX(np))
#define MY_NET_PLAYER_NUM (NET_PLAYER_INDEX(Net_player))

Expand Down
5 changes: 5 additions & 0 deletions code/network/multi_ingame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1332,7 +1332,12 @@ void process_ingame_wings_packet( ubyte *data, header *hinfo )
// kind of stupid, but bash the name since it won't get recreated properly from
// the parse_wing_create_ships call.
shipp = &Ships[shipnum];
int ship_entry_index = ship_registry_get_index(shipp->ship_name);
Assertion(ship_entry_index >= 0, "Ship %s must be in the ship registry!", shipp->ship_name);
wing_bash_ship_name(shipp, wingp, which_one + 1);
// need to update the ship registry too
if (ship_entry_index >= 0)
ship_registry_rename(ship_entry_index, shipp->ship_name, true);
nprintf(("Network", "Created %s\n", shipp->ship_name));

objp = &Objects[shipp->objnum];
Expand Down
2 changes: 1 addition & 1 deletion code/object/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ extern object *Player_obj; // Which object is the player. Has to be valid.
// given it's pointer. This way, we can replace it with a macro
// to check that the pointer is valid for debugging.
// This code will break in 64 bit builds when we have more than 2^31 objects but that will probably never happen
#define OBJ_INDEX(objp) static_cast<int>(objp-Objects)
#define OBJ_INDEX(objp) (static_cast<int>((objp)-Objects))

/*
* FUNCTIONS
Expand Down
10 changes: 9 additions & 1 deletion code/parse/sexp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5846,7 +5846,15 @@ const ship_registry_entry *eval_ship(int node)
return eval_ship(arg_node);
}

auto ship_it = Ship_registry_map.find(CTEXT(node));
// look up the ship in the ship registry
auto ship_name = CTEXT(node);
auto ship_it = Ship_registry_map.find(ship_name);
if (ship_it == Ship_registry_map.end())
{
SCP_string legacy_hashed;
if (wing_bash_legacy_hashed_ship_name(legacy_hashed, ship_name))
ship_it = Ship_registry_map.find(legacy_hashed);
}
if (ship_it != Ship_registry_map.end())
{
// cache the value if it can't change later
Expand Down
12 changes: 10 additions & 2 deletions code/scripting/api/objs/ship.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ ADE_VIRTVAR(ArmorClass, l_Ship, "string", "Current Armor class", "string", "Armo
return ade_set_args(L, "s", name);
}

ADE_VIRTVAR(Name, l_Ship, "string", "Ship name. This is the actual name of the ship. Use <i>getDisplayString</i> to get the string which should be displayed to the player.", "string", "Ship name, or empty string if handle is invalid")
ADE_VIRTVAR(Name, l_Ship, "string", "Ship name. This is the actual name of the ship. Use <i>getDisplayString</i> to get the string which should be displayed to the player. Beware of setting the name to the name of an existing ship!", "string", "Ship name, or empty string if handle is invalid")
{
object_h *objh;
const char* s = nullptr;
Expand All @@ -355,10 +355,18 @@ ADE_VIRTVAR(Name, l_Ship, "string", "Ship name. This is the actual name of the s

ship *shipp = &Ships[objh->objp()->instance];

if(ADE_SETTING_VAR && s != nullptr) {
if(ADE_SETTING_VAR && s != nullptr)
{
int ship_entry_index = ship_registry_get_index(shipp->ship_name);
Assertion(ship_entry_index >= 0, "Ship %s must be in the ship registry!", shipp->ship_name);

auto len = sizeof(shipp->ship_name);
strncpy(shipp->ship_name, s, len);
shipp->ship_name[len - 1] = 0;

// need to update the ship registry too
if (ship_entry_index >= 0)
ship_registry_rename(ship_entry_index, shipp->ship_name, true);
}

return ade_set_args(L, "s", shipp->ship_name);
Expand Down
Loading
Loading