Compare commits

..
Author SHA1 Message Date
Tyler Blount b662a5a716 Increase Weapon Info Limit 2020-05-09 16:56:20 -06:00
55 changed files with 516 additions and 2428 deletions

No files matched your search

-13
View File
@@ -14,17 +14,6 @@ misc-*,\
-misc-static-assert,\
-misc-unused-parameters,\
-misc-non-private-member-variables-in-classes,\
readability-*,\
-readability-function-size,\
-readability-identifier-naming,\
-readability-implicit-bool-conversion,\
-readability-inconsistent-declaration-parameter-name,\
-readability-isolate-declaration,\
-readability-magic-numbers,\
-readability-named-parameter,\
-readability-qualified-auto,\
-readability-uppercase-literal-suffix,\
-readability-else-after-return,\
"
WarningsAsErrors: ''
HeaderFilterRegex: 'code/.*$|freespace2/.*$|qtfred/.*$|test/src/.*$|build/.*$'
@@ -34,7 +23,5 @@ CheckOptions:
value: 'assert,Assert,Assertion'
- key: 'modernize-use-emplace.ContainersWithPushBack'
value: 'std::vector;std::deque;std::list;SCP_vector;SCP_deque;SCP_list'
- key: 'readability-braces-around-statements.ShortStatementLines'
value: '4' # Avoid flagging simple if (...) return false; statements
...
+13 -15
View File
@@ -18,7 +18,8 @@
#include "ship/ship.h"
SCP_vector<char *> Goal_target_names;
int Total_goal_target_names = 0;
char Goal_target_names[MAX_GOAL_TARGET_NAMES][NAME_LENGTH];
ai_info Ai_info[MAX_AI_INFO];
ai_info *Player_ai;
@@ -81,25 +82,22 @@ void set_wingnum(int objnum, int wingnum)
Ai_info[ai_index].wing = wingnum;
}
const char *ai_get_goal_target_name(const char *name, int *index)
char *ai_get_goal_target_name(const char *name, int *index)
{
Assertion(name != nullptr && index != nullptr, "Arguments cannot be null!");
Assert(name != NULL);
Assert(index != NULL);
int i;
for (int i = 0; i < static_cast<int>(Goal_target_names.size()); ++i) {
for (i=0; i < Total_goal_target_names; i++)
if (!stricmp(name, Goal_target_names[i])) {
*index = i;
return Goal_target_names[i];
}
}
*index = static_cast<int>(Goal_target_names.size());
Goal_target_names.push_back(vm_strdup(name));
return Goal_target_names[*index];
}
void ai_clear_goal_target_names()
{
for (auto ptr : Goal_target_names)
vm_free(ptr);
Goal_target_names.clear();
Assert(Total_goal_target_names < MAX_GOAL_TARGET_NAMES);
Assertion(strlen(name) <= NAME_LENGTH - 1, "Goal target name %s is too long. Needs to be 31 characters or less.", name);
i = Total_goal_target_names++;
strcpy_s(Goal_target_names[i], name);
*index = i;
return Goal_target_names[i];
}
+8 -5
View File
@@ -83,7 +83,7 @@ typedef struct ai_goal {
fix time; // time at which this goal was issued.
int priority; // how important is this goal -- number 0 - 100
const char *target_name; // name of the thing that this goal acts upon
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 target_instance; // instance of thing this ship might be chasing (currently only used for weapons; note, not the same as objnum!)
@@ -93,17 +93,19 @@ typedef struct ai_goal {
// (AIGF_DOCKER_INDEX_VALID and AIGF_DOCKEE_INDEX_VALID tell us to use indexes; otherwise we use names)
// these are the dockpoints used on the docker and dockee ships, not the ships themselves
union {
const char *name;
char *name;
int index;
} docker;
union {
const char *name;
char *name;
int index;
} dockee;
} ai_goal;
#define MAX_GOAL_TARGET_NAMES 100
#define AIM_CHASE 0
#define AIM_EVADE 1
#define AIM_GET_BEHIND 2
@@ -511,6 +513,8 @@ typedef struct {
#define BURST_DURATION 500 // decay time over which Player->damage_this_burst falls from MAX_BURST_DAMAGE to 0
extern int Mission_all_attack; // !0 means all teams attack all teams.
extern int Total_goal_target_names;
extern char Goal_target_names[MAX_GOAL_TARGET_NAMES][NAME_LENGTH];
extern void update_ai_info_for_hit(int hitter_obj, int hit_obj);
extern void ai_frame_all(void);
@@ -552,8 +556,7 @@ void ai_process( object * obj, int ai_index, float frametime );
int get_wingnum(int objnum);
void set_wingnum(int objnum, int wingnum);
const char *ai_get_goal_target_name(const char *name, int *index);
void ai_clear_goal_target_names();
char *ai_get_goal_target_name(const char *name, int *index);
extern void init_ai_system(void);
extern void ai_attack_object(object *attacker, object *attacked, ship_subsys *ssp, int ship_info_index = -1);
-2
View File
@@ -84,7 +84,6 @@ namespace AI {
Assist_scoring_scales_with_damage,
Beams_damage_weapons,
Big_ships_can_attack_beam_turrets_on_untargeted_ships,
Check_comms_for_non_player_ships,
Disable_linked_fire_penalty,
Disable_player_secondary_doublefire,
Disable_ai_secondary_doublefire,
@@ -94,7 +93,6 @@ namespace AI {
Fix_ai_path_order_bug,
Fix_heat_seeker_stealth_bug,
Fix_linked_primary_bug,
Fix_ramming_stationary_targets_bug,
Force_beam_turret_fov,
Free_afterburner_use,
Glide_decay_requires_thrust,
+2 -24
View File
@@ -7,11 +7,11 @@
#include "ai/ai_profiles.h"
#include "globalincs/pstypes.h"
#include "def_files/def_files.h"
#include "ai/ai_profiles.h"
#include "globalincs/pstypes.h"
#include "localization/localize.h"
#include "mod_table/mod_table.h"
#include "parse/parselo.h"
#include "ship/ship.h"
#include "weapon/weapon.h"
@@ -371,8 +371,6 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$navigation subsystem governs warpout capability:", AI::Profile_Flags::Navigation_subsys_governs_warp);
set_flag(profile, "$check communications for non-player ships:", AI::Profile_Flags::Check_comms_for_non_player_ships);
set_flag(profile, "$ignore lower bound for minimum speed of docked ship:", AI::Profile_Flags::No_min_dock_speed_cap);
set_flag(profile, "$disable linked fire penalty:", AI::Profile_Flags::Disable_linked_fire_penalty);
@@ -397,8 +395,6 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$fix linked primary weapon decision bug:", AI::Profile_Flags::Fix_linked_primary_bug);
set_flag(profile, "$fix ramming stationary targets bug:", AI::Profile_Flags::Fix_ramming_stationary_targets_bug);
set_flag(profile, "$prevent turrets targeting too distant bombs:", AI::Profile_Flags::Prevent_targeting_bombs_beyond_range);
set_flag(profile, "$smart subsystem targeting for turrets:", AI::Profile_Flags::Smart_subsystem_targeting_for_turrets);
@@ -632,22 +628,4 @@ void ai_profile_t::reset()
for (int i = 0; i <= MAX_DETAIL_LEVEL; ++i) {
detail_distance_mult[i] = 0;
}
// via Github #2332, enable bugfixes if we are targeting version 20 and up
if (mod_supports_version(20, 0, 0)) {
flags.set(AI::Profile_Flags::Huge_turret_weapons_ignore_bombs);
flags.set(AI::Profile_Flags::Fix_linked_primary_bug);
flags.set(AI::Profile_Flags::Prevent_targeting_bombs_beyond_range);
flags.set(AI::Profile_Flags::Fix_heat_seeker_stealth_bug);
flags.set(AI::Profile_Flags::Allow_vertical_dodge);
flags.set(AI::Profile_Flags::Fix_ai_class_bug);
flags.set(AI::Profile_Flags::Ai_guards_specific_ship_in_wing);
flags.set(AI::Profile_Flags::Fix_ai_path_order_bug);
flags.set(AI::Profile_Flags::Aspect_invulnerability_fix);
flags.set(AI::Profile_Flags::Use_actual_primary_range);
}
// this flag has been enabled ever since 3.7.2
if (mod_supports_version(3, 7, 2)) {
flags.set(AI::Profile_Flags::Fix_ramming_stationary_targets_bug);
}
}
+5 -24
View File
@@ -66,7 +66,6 @@
#include "ship/ship.h"
#include "ship/shipfx.h"
#include "ship/shiphit.h"
#include "ship/subsysdamage.h"
#include "weapon/beam.h"
#include "weapon/flak.h"
#include "weapon/swarm.h"
@@ -275,7 +274,7 @@ typedef struct {
int team;
int weapon_index;
int max_fire_count;
const char *shipname;
char *shipname;
} huge_fire_info;
SCP_vector<huge_fire_info> Ai_huge_fire_info;
@@ -5675,16 +5674,7 @@ int ai_fire_primary_weapon(object *objp)
float dot;
vec3d v2t;
bool condition;
if (The_mission.ai_profile->flags[AI::Profile_Flags::Fix_ramming_stationary_targets_bug]) {
// fixed by Mantis 3147 - Avoid bashing orientation if trying to avoid a collision.
condition = !(vm_vec_mag_quick(&G_predicted_pos) < AICODE_SMALL_MAGNITUDE) && (aip->submode != SM_AVOID);
} else {
// retail behavior
condition = !(vm_vec_mag_quick(&G_predicted_pos) < AICODE_SMALL_MAGNITUDE);
}
if ( condition ) {
if ( !(vm_vec_mag_quick(&G_predicted_pos) < AICODE_SMALL_MAGNITUDE ) && !(aip->submode == SM_AVOID) ) {
if ( vm_vec_cmp(&G_predicted_pos, &G_fire_pos) ) {
vm_vec_normalized_dir(&v2t, &G_predicted_pos, &G_fire_pos);
dot = vm_vec_dot(&v2t, &objp->orient.vec.fvec);
@@ -8234,15 +8224,9 @@ void ai_chase()
if ((real_dot_to_enemy < 0.25f) || (aip->target_time < 1.0f)) {
predicted_enemy_pos = enemy_pos;
} else if (aip->ai_flags[AI::AI_Flags::Seek_lock]) {
if (The_mission.ai_profile->flags[AI::Profile_Flags::Fix_ramming_stationary_targets_bug]) {
// fixed by Mantis 3147 - Bash orientation if aspect seekers are equipped.
set_predicted_enemy_pos(&predicted_enemy_pos, Pl_objp, &aip->last_aim_enemy_pos, &aip->last_aim_enemy_vel, aip); // Set G_fire_pos
predicted_enemy_pos = enemy_pos;
G_predicted_pos = predicted_enemy_pos;
} else {
// retail behavior
predicted_enemy_pos = enemy_pos;
}
set_predicted_enemy_pos(&predicted_enemy_pos, Pl_objp, &aip->last_aim_enemy_pos, &aip->last_aim_enemy_vel, aip); // Set G_fire_pos
predicted_enemy_pos = enemy_pos;
G_predicted_pos = predicted_enemy_pos;
} else {
// Set predicted_enemy_pos.
// See if attacking a subsystem.
@@ -14546,9 +14530,6 @@ void process_friendly_hit_message( int message, object *objp )
if (Ships[objp->instance].flags[Ship::Ship_Flags::No_builtin_messages]) {
index = -1;
}
if (The_mission.ai_profile->flags[AI::Profile_Flags::Check_comms_for_non_player_ships] && hud_communications_state(&Ships[objp->instance]) <= COMM_DAMAGED) {
index = -1;
}
// Karajorma - pick a random ship to send Command messages if command is silenced.
if (index < 0 && (The_mission.flags[Mission::Mission_Flags::No_builtin_command]) ) {
+14 -10
View File
@@ -310,7 +310,7 @@ void ai_clear_wing_goals( int wingnum )
void ai_mission_wing_goal_complete( int wingnum, ai_goal *remove_goalp )
{
int mode, submode, priority, i;
const char *name;
char *name;
ai_goal *aigp;
wing *wingp;
@@ -388,7 +388,7 @@ void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list, ai_info *ai
{
int i, j;
ai_goal *purge_goal;
const char *name;
char *name;
int mode, ship_index, wingnum;
// get locals for easer access
@@ -1413,17 +1413,21 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
{
ship *shipp = &Ships[objp->instance];
// always valid if has working subspace drive, not disabled, and not limited by subsystem strength
if ( ship_can_warp_full_check(shipp) )
// always valid if has subspace drive
if (!(shipp->flags[Ship::Ship_Flags::No_subspace_drive]))
return AI_GOAL_ACHIEVABLE;
// if we can't warp, we can only depart if the ship (or its wing) departs to a fighter bay and the mothership is present
if (ship_can_bay_depart(shipp)) {
return AI_GOAL_ACHIEVABLE;
}
else {
return AI_GOAL_NOT_KNOWN;
// if no subspace drive, only valid if our mothership is present
// check that we have a mothership and that we can depart to it
if (shipp->departure_location == DEPART_AT_DOCK_BAY)
{
int anchor_shipnum = ship_name_lookup(Parse_names[shipp->departure_anchor]);
if (anchor_shipnum >= 0 && ship_useful_for_departure(anchor_shipnum, shipp->departure_path_mask))
return AI_GOAL_ACHIEVABLE;
}
return AI_GOAL_NOT_KNOWN;
}
+1 -1
View File
@@ -57,7 +57,7 @@ cf_pathtype Pathtypes[CF_MAX_PATH_TYPES] = {
{ CF_TYPE_MAPS, "data" DIR_SEPARATOR_STR "maps", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
{ CF_TYPE_TEXT, "data" DIR_SEPARATOR_STR "text", ".txt .net", CF_TYPE_DATA },
{ CF_TYPE_MODELS, "data" DIR_SEPARATOR_STR "models", ".pof", CF_TYPE_DATA },
{ CF_TYPE_TABLES, "data" DIR_SEPARATOR_STR "tables", ".tbl .tbm .lua", CF_TYPE_DATA },
{ CF_TYPE_TABLES, "data" DIR_SEPARATOR_STR "tables", ".tbl .tbm", CF_TYPE_DATA },
{ CF_TYPE_SOUNDS, "data" DIR_SEPARATOR_STR "sounds", ".wav .ogg", CF_TYPE_DATA },
{ CF_TYPE_SOUNDS_8B22K, "data" DIR_SEPARATOR_STR "sounds" DIR_SEPARATOR_STR "8b22k", ".wav .ogg", CF_TYPE_SOUNDS },
{ CF_TYPE_SOUNDS_16B11K, "data" DIR_SEPARATOR_STR "sounds" DIR_SEPARATOR_STR "16b11k", ".wav .ogg", CF_TYPE_SOUNDS },
+1 -9
View File
@@ -230,8 +230,7 @@ Flag exe_params[] =
{ "-pos", "Show position of camera", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-pos", },
{ "-stats", "Show statistics", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-stats", },
{ "-coords", "Show coordinates", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-coords", },
{ "-pofspew", "Dump model information to pofspew.txt", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-pofspew", },
{ "-weaponspew", "Dump weapon stats and spreadsheets", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-weaponspew", },
{ "-pofspew", "Generate all ibx files immediately", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-pofspew", },
{ "-tablecrcs", "Dump table CRCs for multi validation", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-tablecrcs", },
{ "-missioncrcs", "Dump mission CRCs for multi validation", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-missioncrcs", },
{ "-dis_collisions", "Disable collisions", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-dis_collisions", },
@@ -275,7 +274,6 @@ cmdline_parm port_arg("-port", "Multiplayer network port", AT_INT);
cmdline_parm multilog_arg("-multilog", NULL, AT_NONE); // Cmdline_multi_log
cmdline_parm client_dodamage("-clientdamage", NULL, AT_NONE); // Cmdline_client_dodamage
cmdline_parm pof_spew("-pofspew", NULL, AT_NONE); // Cmdline_spew_pof_info
cmdline_parm weapon_spew("-weaponspew", nullptr, AT_NONE); // Cmdline_spew_weapon_stats
cmdline_parm mouse_coords("-coords", NULL, AT_NONE); // Cmdline_mouse_coords
cmdline_parm timeout("-timeout", "Multiplayer network timeout (secs)", AT_INT); // Cmdline_timeout
cmdline_parm bit32_arg("-32bit", "Deprecated", AT_NONE); // (only here for retail compatibility reasons, doesn't actually do anything)
@@ -297,7 +295,6 @@ int Cmdline_multi_stream_chat_to_file = 0;
int Cmdline_network_port = -1;
int Cmdline_restricted_game = 0;
int Cmdline_spew_pof_info = 0;
bool Cmdline_spew_weapon_stats = false;
int Cmdline_start_netgame = 0;
int Cmdline_timeout = -1;
int Cmdline_use_last_pilot = 0;
@@ -1671,11 +1668,6 @@ bool SetCmdlineParams()
Cmdline_spew_pof_info = 1;
}
// spew weapon stats
if (weapon_spew.found()) {
Cmdline_spew_weapon_stats = true;
}
// mouse coords
if(mouse_coords.found()){
Cmdline_mouse_coords = 1;
-2
View File
@@ -149,7 +149,5 @@ extern bool Cmdline_show_video_info;
extern bool Cmdline_debug_window;
extern bool Cmdline_graphics_debug_output;
extern bool Cmdline_log_to_stdout;
extern bool Cmdline_spew_weapon_stats;
#endif
+2 -2
View File
@@ -286,7 +286,7 @@ std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream>& st
if (status->subtitleStream == nullptr) {
// We don't have an external subtitle stream or loading from that file has failed
auto& current_language = Lcl_languages[Lcl_current_lang == LCL_UNTRANSLATED ? LCL_DEFAULT : Lcl_current_lang];
auto& current_language = Lcl_languages[Lcl_current_lang];
for (uint32_t i = 0; i < ctx->nb_streams; ++i) {
auto test_stream = ctx->streams[i];
@@ -428,7 +428,7 @@ std::unique_ptr<InputStream> openInputStream(const SCP_string& name) {
std::unique_ptr<InputStream> openSubtitleStream(const SCP_string& name)
{
auto& current_language = Lcl_languages[Lcl_current_lang == LCL_UNTRANSLATED ? LCL_DEFAULT : Lcl_current_lang];
auto& current_language = Lcl_languages[Lcl_current_lang];
for (auto ext : CHECKED_SUBT_EXTENSIONS) {
SCP_string fileName;
+4 -5
View File
@@ -240,12 +240,11 @@ void debris_process_post(object * obj, float frame_time)
MONITOR_INC(NumSmallDebris,1);
}
if (db->lifeleft >= 0.0f) {
if ( db->lifeleft >= 0.0f) {
db->lifeleft -= frame_time;
}
if ( db->lifeleft < 0.0f ) {
debris_start_death_roll(obj, db);
if ( db->lifeleft < 0.0f ) {
debris_start_death_roll(obj, db);
}
}
maybe_delete_debris(db); // Make this debris go away if it's very far away.
+1 -1
View File
@@ -45,7 +45,7 @@ void main()
fragDepthLinear = ( 2.0 * farZ * nearZ ) / ( farZ + nearZ - gl_FragCoord.z * (farZ-nearZ) );
}
// assume UV of 0.5, 0.5 is the centroid of this sphere volume
float depthOffset = sqrt((fragRadius*fragRadius) - (offset_len*offset_len));
float depthOffset = sqrt(pow(fragRadius, 2.0) - pow(offset_len, 2.0));
float frontDepth = fragDepthLinear - depthOffset;
float backDepth = fragDepthLinear + depthOffset;
float intensity = smoothstep(max(nearZ, frontDepth), backDepth, sceneDepthLinear);
+1 -1
View File
@@ -70,7 +70,7 @@
// from weapon.h
#define MAX_WEAPONS 2000
#define MAX_WEAPON_TYPES 300
#define MAX_WEAPON_TYPES 500
// from model.h
+1 -1
View File
@@ -55,7 +55,7 @@ struct version {
version() = default;
version(int major, int minor = 0, int build = 0, int revision = 0);
version(int major, int minor, int build, int revision);
bool isValid() const;
+21 -1050
View File
File diff suppressed because it is too large. Load diff
-3
View File
@@ -18,7 +18,6 @@ void hud_init_missile_lock();
void hud_calculate_lock_position(float frametime);
void hud_calculate_lock_start_pos();
void hud_do_lock_indicator(float frametime);
void hud_do_lock_indicators(float frametime);
void hud_stop_looped_locking_sounds();
void hud_lock_reset(float lock_time_scale=1.0f);
@@ -55,9 +54,7 @@ public:
void initLoopLockedAnim(bool loop);
void render(float frametime) override;
void renderOld(float frametime);
void renderLockTriangles(int center_x, int center_y, float frametime);
void renderLockTrianglesNew(int center_x, int center_y, int start_timestamp);
void renderLockTrianglesOld(int center_x, int center_y, int radius);
void pageIn() override;
void initialize() override;
+83 -44
View File
@@ -238,9 +238,8 @@ SCP_vector<squadmsg_history> Squadmsg_history;
// forward declarations
void hud_add_issued_order(const char *name, int order);
void hud_update_last_order(char *target, int order_source, int special_index);
bool hud_squadmsg_is_target_order_valid(int order, int find_order, ai_info *aip = nullptr);
bool hud_squadmsg_ship_valid(ship *shipp, object *objp = nullptr);
bool hud_squadmsg_ship_order_valid( int shipnum, int order );
int hud_squadmsg_is_target_order_valid(int order, int find_order, ai_info *aip = NULL );
int hud_squadmsg_ship_order_valid( int shipnum, int order );
// function to set up variables needed when messaging mode is started
void hud_squadmsg_start()
@@ -301,15 +300,31 @@ bool hud_squadmsg_exist_fighters( )
{
objp = &Objects[so->objnum];
shipp = &Ships[objp->instance];
Assertion(shipp->objnum != -1, "hud_squadmsg_exist_fighters() discovered that ship #%d ('%s') has an objnum of -1. Since the ship was retrieved from its object number (%d), this should be impossible; get a coder!\n", objp->instance, shipp->ship_name, so->objnum);
Assert ( shipp->objnum != -1 );
// check fighter is accepting orders
if (shipp->orders_accepted == 0)
continue;
// be sure ship is on correct team
#ifdef NDEBUG
if (shipp->team != Player_ship->team)
continue;
#else
if (!Msg_enemies && (shipp->team != Player_ship->team))
continue;
#endif
// cannot be my ship or an instructor
if ((objp == Player_obj) || is_instructor(objp))
continue;
// ship must be a fighter/bomber
if (!(Ship_info[shipp->ship_info_index].is_fighter_bomber()))
if ( !(Ship_info[shipp->ship_info_index].is_fighter_bomber()) )
continue;
// this ship satisfies everything
if (hud_squadmsg_ship_valid(shipp, objp))
return true;
return true;
}
return false;
@@ -322,7 +337,7 @@ bool hud_squadmsg_ship_valid(ship *shipp, object *objp)
if (!objp) // For simplicity's sake, allow it to be called with just the ship pointer
objp = &Objects[shipp->objnum];
// ships must be able to receive orders
// ships must be able to receive a message
if ( Ship_info[shipp->ship_info_index].class_type < 0 || !(Ship_types[Ship_info[shipp->ship_info_index].class_type].flags[Ship::Type_Info_Flags::AI_accept_player_orders]) )
return false;
@@ -359,10 +374,6 @@ bool hud_squadmsg_ship_valid(ship *shipp, object *objp)
return false;
}
// maybe check comm system
if (The_mission.ai_profile->flags[AI::Profile_Flags::Check_comms_for_non_player_ships] && hud_communications_state(shipp) != COMM_OK)
return false;
// If we got to this point, the ship must be valid.
return true;
}
@@ -409,14 +420,14 @@ int hud_squadmsg_count_ships(int add_to_menu)
}
// routine to return true if a wing should be put onto the messaging menu
bool hud_squadmsg_wing_valid(wing *wingp)
int hud_squadmsg_wing_valid(wing *wingp)
{
int idx, ship_num;
// a couple of special cases to account for before adding to count (or to menu). Don't count
// wings that are leaving or left.
if ( wingp->flags[Ship::Wing_Flags::Gone, Ship::Wing_Flags::Departing] )
return false;
return 0;
// Goober5000 - instead of checking wing leader, let's check all ships in wing;
// there are several significant cases when e.g. wings contain ships of different IFFs
@@ -425,13 +436,34 @@ bool hud_squadmsg_wing_valid(wing *wingp)
ship_num = wingp->ship_index[idx];
Assert(ship_num >= 0);
// if at least one ship in this wing is valid, that's all we need
if (hud_squadmsg_ship_valid(&Ships[ship_num]))
return true;
// don't check player
if (ship_num == SHIP_INDEX(Player_ship))
continue;
// be sure ship is on same team
#ifdef NDEBUG
if (Ships[ship_num].team != Player_ship->team)
continue;
#else
if (!Msg_enemies && (Ships[ship_num].team != Player_ship->team))
continue;
#endif
// check if ship is accepting orders
if (Ships[ship_num].orders_accepted == 0)
continue;
// if doing a message shortcut is being used, be sure the ship can "accept" the command.
if ( Msg_shortcut_command >= 0 && !(Ships[ship_num].orders_accepted & Msg_shortcut_command) )
return 0;
// at least one ship in this wing is valid, and that's all we need
return 1;
}
// no ships in the wing were valid
return false;
return 0;
}
// function like above, except for wings
@@ -734,8 +766,8 @@ void hud_squadmsg_repair_rearm_abort( int toggle_state, object *obj)
}
// Goober5000 - redone and added a bit
// returns true if an order is valid for a ship. Applies to things like departure when engines are blown, etc.
bool hud_squadmsg_ship_order_valid( int shipnum, int order )
// returns 1 if an order is valid for a ship. Applies to things like departure when engines are blown, etc.
int hud_squadmsg_ship_order_valid( int shipnum, int order )
{
// Goober5000
Assert( shipnum >= 0 && shipnum < MAX_SHIPS );
@@ -746,24 +778,31 @@ bool hud_squadmsg_ship_order_valid( int shipnum, int order )
case DEPART_ITEM:
// disabled ships can't depart.
if (shipp->flags[Ship::Ship_Flags::Disabled])
return false;
return 0;
// Goober5000: also can't depart if no subspace drives and no valid mothership
if ( !(ship_can_warp_full_check(shipp)) )
if (shipp->flags[Ship::Ship_Flags::No_subspace_drive])
{
// function accounts for ship's wing and returns true if ship has bay departure and mothership present, false otherwise
return ship_can_bay_depart(shipp);
// check that we have a mothership and that we can depart to it
if (shipp->departure_location == DEPART_AT_DOCK_BAY)
{
int anchor_shipnum = ship_name_lookup(Parse_names[shipp->departure_anchor]);
if (anchor_shipnum >= 0 && ship_useful_for_departure(anchor_shipnum, shipp->departure_path_mask))
return 1;
}
return 0;
}
break;
}
return true;
return 1;
}
// returns true or false if the Players target is valid for the given order
// find_order is true when we need to search the comm_orders array for the order entry. We have
// to do this action in some cases since all we know is the actual "value" of the order
bool hud_squadmsg_is_target_order_valid(int order, int find_order, ai_info *aip )
int hud_squadmsg_is_target_order_valid(int order, int find_order, ai_info *aip )
{
int target_objnum, i;
ship *shipp, *ordering_shipp;
@@ -784,22 +823,22 @@ bool hud_squadmsg_is_target_order_valid(int order, int find_order, ai_info *aip
// orders which don't operate on targets are always valid
if ( !(Comm_orders[order].item & TARGET_MESSAGES) )
return true;
return 1;
target_objnum = aip->target_objnum;
// order isn't valid if there is no player target
if ( target_objnum == -1 ) {
return false;
return 0;
}
objp = &Objects[target_objnum];
ordering_shipp = &Ships[aip->shipnum];
// target isn't a ship, then return false
// target isn't a ship, then return 0
if ( (objp->type != OBJ_SHIP) && (objp->type != OBJ_WEAPON) )
return false;
return 0;
// if it's a weapon, then it needs to be a WIF_BOMB weapon. Only attack order valid, and only
// valid on bombs not on the player's team
@@ -807,54 +846,54 @@ bool hud_squadmsg_is_target_order_valid(int order, int find_order, ai_info *aip
if ( objp->type == OBJ_WEAPON ) {
if (Weapons[objp->instance].lssm_stage==3){
return false;
return 0;
}
if ( (Comm_orders[order].item == ATTACK_TARGET_ITEM )
&& ((Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Bomb]) || (Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Fighter_Interceptable]))
&& (Weapons[objp->instance].team != ordering_shipp->team) ) {
return true;
}
&& (Weapons[objp->instance].team != ordering_shipp->team) )
return false;
return 1;
return 0;
}
Assert( objp->type == OBJ_SHIP );
shipp = &Ships[objp->instance];
// if target is a navbouy, return false
// if target is a navbouy, return 0
if ( Ship_info[shipp->ship_info_index].flags[Ship::Info_Flags::Navbuoy] ){
return false;
return 0;
}
// if we are messaging a ship, and that ship is our target, no target type orders are ever active
if ( (Squad_msg_mode == SM_MODE_SHIP_COMMAND) && (Objects[target_objnum].instance == Msg_instance) ){
return false;
return 0;
}
// if the order is a disable order or depart, and the ship is disabled, order isn't active
if ( (Comm_orders[order].item == DISABLE_TARGET_ITEM) && (shipp->flags[Ship::Ship_Flags::Disabled]) ){
return false;
return 0;
}
// same as above except for disarmed.
if ( (Comm_orders[order].item == DISARM_TARGET_ITEM) && ((shipp->subsys_info[SUBSYSTEM_TURRET].type_count == 0) || (shipp->subsys_info[SUBSYSTEM_TURRET].aggregate_current_hits <= 0.0f)) ){
return false;
return 0;
}
// if order is disable subsystem, and no subsystem targeted or no hits, then order not valid
if ( (Comm_orders[order].item == DISABLE_SUBSYSTEM_ITEM) && ((aip->targeted_subsys == NULL) || (aip->targeted_subsys->current_hits <= 0.0f)) ){
return false;
return 0;
}
// check based on target's and player's team
if ( (shipp->team == ordering_shipp->team) && (FRIENDLY_TARGET_MESSAGES & Comm_orders[order].item) ){
return true;
return 1;
} else if ( (shipp->team != ordering_shipp->team) && (ENEMY_TARGET_MESSAGES & Comm_orders[order].item) ){
return true;
return 1;
} else {
return false;
return 0;
}
}
+8 -7
View File
@@ -3431,7 +3431,6 @@ void hud_show_targeting_gauges(float frametime)
vec3d target_pos;
hud_show_hostile_triangle();
hud_do_lock_indicators(frametime);
if (Player_ai->target_objnum == -1)
return;
@@ -3481,6 +3480,8 @@ void hud_show_targeting_gauges(float frametime)
// display the lock indicator
if (!Player->target_is_dying) {
hud_do_lock_indicator(frametime);
// update and render artillery
hud_artillery_update();
hud_artillery_render();
@@ -4557,7 +4558,7 @@ int hud_sensors_ok(ship *sp, int show_msg)
}
}
int hud_communications_state(ship *sp, bool for_death_scream)
int hud_communications_state(ship *sp)
{
float str;
@@ -4571,7 +4572,11 @@ int hud_communications_state(ship *sp, bool for_death_scream)
if ((sp == Player_ship) && (sp->flags[Ship::Ship_Flags::Dying]))
return COMM_OK;
str = ship_get_subsystem_strength( sp, SUBSYSTEM_COMMUNICATION, for_death_scream );
// Goober5000 - check for scrambled communications
if ( emp_active_local() || sp->flags[Ship::Ship_Flags::Scramble_messages] )
return COMM_SCRAMBLED;
str = ship_get_subsystem_strength( sp, SUBSYSTEM_COMMUNICATION );
if ( (str <= 0.01) || ship_subsys_disrupted(sp, SUBSYSTEM_COMMUNICATION) ) {
return COMM_DESTROYED;
@@ -4579,10 +4584,6 @@ int hud_communications_state(ship *sp, bool for_death_scream)
return COMM_DAMAGED;
}
// Goober5000 - check for scrambled communications
if (emp_active_local() || sp->flags[Ship::Ship_Flags::Scramble_messages])
return COMM_SCRAMBLED;
return COMM_OK;
}
+1 -1
View File
@@ -125,7 +125,7 @@ void hud_update_weapon_flash();
void hud_process_homing_missiles(void);
int hud_sensors_ok(ship *sp, int show_msg = 1);
int hud_communications_state(ship *sp, bool for_death_scream = false);
int hud_communications_state(ship *sp);
int hud_get_best_primary_bank(float *range);
void hud_target_toggle_hidden_from_sensors();
+3 -60
View File
@@ -25,12 +25,9 @@
#include "nebula/neb.h"
#include "object/objectsnd.h"
#include "playerman/managepilot.h"
#include "particle/particle.h"
#include "render/3d.h"
#include "render/batching.h"
#include "ship/ship.h"
#include "ship/shiphit.h"
#include "debris/debris.h"
#include "species_defs/species_defs.h"
#include "starfield/nebula.h"
#include "starfield/starfield.h"
@@ -50,7 +47,6 @@
#define LAB_FLAG_SHOW_WEAPONS (1 << 6) // determines if external weapons models are displayed
#define LAB_FLAG_INITIAL_ROTATION (1 << 7) // initial rotation setting
#define LAB_FLAG_DESTROYED_SUBSYSTEMS (1 << 8) // render model as if all subsystems are destroyed
#define LAB_FLAG_SHIP_EXPLODING (1 << 9) // execute the ship kill stuff
// modes
#define LAB_MODE_NONE 0 // not showing anything
@@ -68,7 +64,6 @@ static Window* Lab_material_override_window = nullptr;
static Window* Lab_variables_window = nullptr;
static Window* Lab_description_window = nullptr;
static Window* Lab_background_window = nullptr;
static Window* Lab_actions_window = nullptr;
static Text* Lab_description_text = nullptr;
static TreeItem** Lab_species_nodes = nullptr;
@@ -354,7 +349,7 @@ void labviewer_render_model(float frametime)
if (dx || dy) {
// Rotate the ship
if (Trackball_mode == 1 && !(Lab_viewer_flags & LAB_FLAG_SHIP_EXPLODING)) {
if (Trackball_mode == 1) {
angles rot_angle;
vm_extract_angles_matrix_alternate(&rot_angle, &Lab_model_orient);
@@ -441,6 +436,7 @@ void labviewer_render_model(float frametime)
Ships[obj->instance].flags.set(Ship::Ship_Flags::Render_without_heightmap, Lab_Heightmap_override);
Ships[obj->instance].flags.set(Ship::Ship_Flags::Render_without_miscmap, Lab_Miscmap_override);
ship_process_post(obj, frametime);
ship_model_update_instance(obj);
Ships[obj->instance].team_name = Lab_team_color;
@@ -471,11 +467,6 @@ void labviewer_render_model(float frametime)
Ships[obj->instance].flags.set(Ship::Ship_Flags::No_thrusters);
}
obj_move_all(frametime);
particle::move_all(frametime);
particle::ParticleManager::get()->doFrame(frametime);
shockwave_move_all(frametime);
Trail_render_override = true;
game_render_frame(Lab_cam);
Trail_render_override = false;
@@ -1590,12 +1581,10 @@ void labviewer_change_ship_lod(Tree* caller)
}
Lab_selected_object = ship_create(&vmd_identity_matrix, &Lab_model_pos, ship_index);
Objects[Lab_selected_object].flags.set(Object::Object_Flags::Player_ship);
auto ship_objp = &Ships[Objects[Lab_selected_object].instance];
auto ship_infop = &Ship_info[ship_objp->ship_info_index];
// This is normally set during mission parse
ship_objp->special_exp_damage = -1;
// If the ship class defines replacement textures, load them and apply them to the ship
// load the texture
auto replacements = SCP_vector<texture_replace>();
@@ -1638,8 +1627,6 @@ void labviewer_change_ship_lod(Tree* caller)
labviewer_update_flags_window();
labviewer_update_variables_window();
labviewer_recalc_camera();
Lab_viewer_flags &= ~LAB_FLAG_SHIP_EXPLODING;
}
void labviewer_change_ship(Tree* caller)
@@ -2087,34 +2074,6 @@ void labviewer_make_background_window(Button* /*caller*/)
}
}
// ----------------------------- Actions window --------------------------------
void lab_actions_window_close(GUIObject* /*caller*/) {
Lab_actions_window = nullptr;
}
void labviewer_actions_destroy_ship(Button* /*caller*/) {
auto obj = &Objects[Lab_selected_object];
if (obj->type == OBJ_SHIP) {
obj->flags.remove(Object::Object_Flags::Player_ship);
ship_self_destruct(obj);
Lab_viewer_flags |= LAB_FLAG_SHIP_EXPLODING;
}
}
void labviewer_make_actions_window(Button* /*caller*/)
{
if (Lab_actions_window != nullptr)
return;
Lab_actions_window = (Window*)Lab_screen->Add(
new Window("Actions", gr_screen.center_offset_x + 250, gr_screen.center_offset_y + 50)
);
Lab_actions_window->SetCloseFunction(lab_actions_window_close);
Lab_actions_window->AddChild(new Button("Destroy Ship", 0, 0, labviewer_actions_destroy_ship));
}
// ----------------------------- Lab functions ---------------------------------
bool is_same_obj_type(int curr, int next)
{
@@ -2247,9 +2206,6 @@ void lab_init()
x += cbp->GetWidth() + 10;
cbp = Lab_toolbar->AddChild(new Button("Backgrounds", x, 0, labviewer_make_background_window));
x += cbp->GetWidth() + 10;
cbp = Lab_toolbar->AddChild(new Button("Actions", x, 0, labviewer_make_actions_window));
x += cbp->GetWidth() + 20;
cbp = Lab_toolbar->AddChild(new Button("Exit", x, 0, labviewer_exit));
@@ -2319,15 +2275,6 @@ void lab_init()
Lab_selected_mission = "None";
Lab_skybox_orientation = vmd_identity_matrix;
fireball_init();
debris_init();
extern void debris_page_in();
debris_page_in();
shockwave_level_init();
particle::init();
ai_paused = 1;
}
#include "lab.h"
@@ -2581,8 +2528,4 @@ void lab_close()
cam_delete(Lab_cam);
obj_init();
shockwave_level_close();
ai_paused = 0;
}
+48 -71
View File
@@ -27,13 +27,13 @@
// general language/localization data ---------------------
// current language
int Lcl_current_lang = LCL_UNTRANSLATED;
int Lcl_current_lang = FS2_OPEN_DEFAULT_LANGUAGE;
SCP_vector<lang_info> Lcl_languages;
// These are the original languages supported by FS2. The code expects these languages to be supported even if the tables don't
lang_info Lcl_builtin_languages[NUM_BUILTIN_LANGUAGES] = {
{ "English", "", {127,0,176,0,0}, 589986744}, // English ("" is correct; the game data files do not use a language extension for English)
{ "English", "", {127,0,176,0,0}, 589986744}, // English
{ "German", "gr", {164,0,176,0,0}, -1132430286 }, // German
{ "French", "fr", {164,0,176,0,0}, 0 }, // French
{ "Polish", "pl", {127,0,176,0,0}, -1131728960}, // Polish
@@ -46,7 +46,7 @@ int Lcl_special_chars;
int Lcl_fr = 0;
int Lcl_gr = 0;
int Lcl_pl = 0;
int Lcl_en = 1;
int Lcl_english = 1;
bool *Lcl_unexpected_tstring_check = nullptr;
@@ -111,8 +111,8 @@ void lcl_init(int lang_init)
// initialize encryption
encrypt_init();
// set up the first language (which should be English)
Lcl_languages.push_back(Lcl_builtin_languages[0]);
// setup English
Lcl_languages.push_back(Lcl_builtin_languages[FS2_OPEN_DEFAULT_LANGUAGE]);
// check string.tbl to see which languages we support
try
@@ -126,8 +126,8 @@ void lcl_init(int lang_init)
parse_modular_table(NOX("*-lcl.tbm"), parse_stringstbl_quick);
// if we only have one language at this point, we need to setup the builtin languages as we might be dealing with an old style strings.tbl
// which doesn't support anything beyond the builtin languages. Note, we start at i = 1 because we added the first language above.
// if the only language we have at this point is English, we need to setup the builtin languages as we might be dealing with an old style strings.tbl
// which doesn't support anything beyond the builtin languages. Note, we start at i = 1 because we added English above.
if ((int)Lcl_languages.size() == 1) {
for (i=1; i<NUM_BUILTIN_LANGUAGES; i++) {
Lcl_languages.push_back(Lcl_builtin_languages[i]);
@@ -135,12 +135,18 @@ void lcl_init(int lang_init)
}
// read the language from the registry
if (lang_init < 0) {
if(lang_init < 0){
memset(lang_string, 0, 128);
// default to DEFAULT_LANGUAGE (which should be English so we don't have to put German text
// default to DEFAULT_LANGUAGE (which should be English so we don't have to put German text
// in tstrings in the #default section)
ret = os_config_read_string(nullptr, "Language", Lcl_languages[LCL_DEFAULT].lang_name);
strcpy_s(lang_string, ret);
ret = os_config_read_string(NULL, "Language", Lcl_languages[FS2_OPEN_DEFAULT_LANGUAGE].lang_name);
if(ret == NULL){
Error(LOCATION, "Default language not found.");
}
strcpy_s(lang_string, ret);
// look it up
lang = -1;
@@ -151,18 +157,13 @@ void lcl_init(int lang_init)
}
}
if(lang < 0){
lang = LCL_DEFAULT;
}
lang = 0;
}
} else {
Assert(lang_init == LCL_UNTRANSLATED || (lang_init >= 0 && lang_init < (int)Lcl_languages.size()));
Assert((lang_init >= 0) && (lang_init < (int)Lcl_languages.size()));
lang = lang_init;
}
// and after all that... the default language reverts to untranslated unless we are specifically translating it
if (lang == LCL_DEFAULT && !Use_tabled_strings_for_default_language) {
lang = LCL_UNTRANSLATED;
}
// set the language (this function takes care of setting up file pointers)
lcl_set_language(lang);
}
@@ -251,14 +252,14 @@ void parse_stringstbl_common(const char *filename, const bool external)
// move down to the proper section
memset(language_tag, 0, sizeof(language_tag));
strcpy_s(language_tag, "#");
if (external && (Lcl_current_lang == LCL_UNTRANSLATED || Lcl_current_lang == LCL_DEFAULT)) {
if (external && Lcl_current_lang == FS2_OPEN_DEFAULT_LANGUAGE){
strcat_s(language_tag, "default");
} else {
strcat_s(language_tag, Lcl_languages[Lcl_current_lang == LCL_UNTRANSLATED ? LCL_DEFAULT : Lcl_current_lang].lang_name);
strcat_s(language_tag, Lcl_languages[Lcl_current_lang].lang_name);
}
if ( skip_to_string(language_tag) != 1 ) {
mprintf(("Language tag %s not found in %s\n", language_tag, filename));
mprintf(("Current language not found in %s\n", filename));
return;
}
@@ -483,62 +484,46 @@ void lcl_set_language(int lang)
{
Lcl_current_lang = lang;
if (lang == LCL_UNTRANSLATED) {
nprintf(("General", "Setting language to UNTRANSLATED\n"));
// but for the purposes of array access, we use the default
lang = LCL_DEFAULT;
} else {
nprintf(("General", "Setting language to %s\n", Lcl_languages[lang].lang_name));
}
nprintf(("General", "Setting language to %s\n", Lcl_languages[lang].lang_name));
Assertion((lang >= 0) && (lang < (int)Lcl_languages.size()), "Attempt to set language to an invalid language");
Assertion((Lcl_current_lang >= 0) && (Lcl_current_lang < (int)Lcl_languages.size()), "Attempt to set language to an invalid language");
// flag the proper language as being active
Lcl_special_chars = Lcl_languages[lang].special_char_indexes[0];
Lcl_special_chars = Lcl_languages[Lcl_current_lang].special_char_indexes[0];
Lcl_fr = 0;
Lcl_gr = 0;
Lcl_pl = 0;
Lcl_en = 0;
if (!strcmp(Lcl_languages[lang].lang_name, Lcl_builtin_languages[LCL_ENGLISH].lang_name)) {
Lcl_en = 1;
} else if (!strcmp(Lcl_languages[lang].lang_name, Lcl_builtin_languages[LCL_FRENCH].lang_name)) {
Lcl_english = 0;
if (!strcmp(Lcl_languages[Lcl_current_lang].lang_name, Lcl_builtin_languages[LCL_ENGLISH].lang_name)) {
Lcl_english = 1;
} else if (!strcmp(Lcl_languages[Lcl_current_lang].lang_name, Lcl_builtin_languages[LCL_FRENCH].lang_name)) {
Lcl_fr = 1;
} else if (!strcmp(Lcl_languages[lang].lang_name, Lcl_builtin_languages[LCL_GERMAN].lang_name)) {
} else if (!strcmp(Lcl_languages[Lcl_current_lang].lang_name, Lcl_builtin_languages[LCL_GERMAN].lang_name)) {
Lcl_gr = 1;
} else if (!strcmp(Lcl_languages[lang].lang_name, Lcl_builtin_languages[LCL_POLISH].lang_name)) {
} else if (!strcmp(Lcl_languages[Lcl_current_lang].lang_name, Lcl_builtin_languages[LCL_POLISH].lang_name)) {
Lcl_pl = 1;
}
}
ubyte lcl_get_font_index(int font_num)
{
int lang = Lcl_current_lang;
if (Lcl_current_lang == LCL_UNTRANSLATED) {
lang = LCL_DEFAULT;
}
if (Unicode_text_mode) {
// In Unicode mode there are no special characters. Some of the code still uses this function in that mode so
// we just return 0 to signify that there are no special characters in this font
return 0;
} else {
Assertion((font_num >= 0) && (font_num < LCL_MAX_FONTS), "Passed an invalid font index");
Assertion((lang >= 0) && (lang < (int)Lcl_languages.size()), "Current language is not valid, can't get font indexes");
Assertion((Lcl_current_lang >= 0) && (Lcl_current_lang < (int)Lcl_languages.size()), "Current language is not valid, can't get font indexes");
return Lcl_languages[lang].special_char_indexes[font_num];
return Lcl_languages[Lcl_current_lang].special_char_indexes[font_num];
}
}
// maybe add localized directory to full path with file name when opening a localized file
int lcl_add_dir_to_path_with_filename(char *current_path, size_t path_max)
{
int lang = Lcl_current_lang;
if (Lcl_current_lang == LCL_UNTRANSLATED) {
lang = LCL_DEFAULT;
}
// if the disk extension is 0 length, don't add anything
if (strlen(Lcl_languages[lang].lang_ext) <= 0) {
if (strlen(Lcl_languages[Lcl_current_lang].lang_ext) <= 0) {
return 1;
}
@@ -559,7 +544,7 @@ int lcl_add_dir_to_path_with_filename(char *current_path, size_t path_max)
}
// add extension
strcat_s(current_path, path_max, Lcl_languages[lang].lang_ext);
strcat_s(current_path, path_max, Lcl_languages[Lcl_current_lang].lang_ext);
strcat_s(current_path, path_max, DIR_SEPARATOR_STR );
// copy rest of filename from temp
@@ -799,8 +784,8 @@ bool lcl_ext_localize_sub(const SCP_string &in, SCP_string &text_str, SCP_string
return false;
}
// if the localization file is not open, or there's no entry, or we're not translating, return the original string
if ( !Xstr_inited || (str_id < 0) || (Lcl_current_lang == LCL_UNTRANSLATED) ) {
// if the localization file is not open, or there's no entry, return the original string
if ( !Xstr_inited || (str_id < 0) ) {
out = text_str;
if (id != NULL)
@@ -840,7 +825,7 @@ void lcl_ext_localize(const char *in, char *out, size_t max_len, int *id)
if (Lcl_unexpected_tstring_check)
{
int saved_language = Lcl_current_lang;
Lcl_current_lang = LCL_DEFAULT;
Lcl_current_lang = FS2_OPEN_DEFAULT_LANGUAGE;
bool extracted = lcl_ext_localize_sub(in, text_str, out, max_len, id);
// the untranslated and default-translated strings should always be identical, so if they're different, it might mean we have some data from a different mod
@@ -875,7 +860,7 @@ void lcl_ext_localize(const SCP_string &in, SCP_string &out, int *id)
if (Lcl_unexpected_tstring_check)
{
int saved_language = Lcl_current_lang;
Lcl_current_lang = LCL_DEFAULT;
Lcl_current_lang = FS2_OPEN_DEFAULT_LANGUAGE;
bool extracted = lcl_ext_localize_sub(in, text_str, out, id);
// the untranslated and default-translated strings should always be identical, so if they're different, it might mean we have some data from a different mod
@@ -909,20 +894,15 @@ const char *XSTR(const char *str, int index)
return str;
}
if (Lcl_current_lang != LCL_UNTRANSLATED)
// perform a lookup
if (index >= 0 && index < XSTR_SIZE)
{
// perform a lookup
if (index >= 0 && index < XSTR_SIZE)
{
// return translation of string
if (Xstr_table[index].str)
return Xstr_table[index].str;
else
mprintf(("No XSTR entry in strings.tbl for index %d\n", index));
}
// return translation of string
if (Xstr_table[index].str)
return Xstr_table[index].str;
}
// can't translate; return original English string
// can't translate; return original english string
return str;
}
@@ -1171,12 +1151,9 @@ int lcl_ext_get_id(const SCP_string &xstr, int *out)
void lcl_get_language_name(char *lang_name)
{
int lang = Lcl_current_lang;
if (Lcl_current_lang == LCL_UNTRANSLATED)
lang = LCL_DEFAULT;
Assert(Lcl_current_lang < (int)Lcl_languages.size());
Assert(lang >= 0 && lang < (int)Lcl_languages.size());
strcpy(lang_name, Lcl_languages[lang].lang_name);
strcpy(lang_name, Lcl_languages[Lcl_current_lang].lang_name);
}
// ------------------------------------------------------------------
+3 -4
View File
@@ -19,14 +19,13 @@
// LOCALIZE DEFINES/VARS
//
// language defines (English should always be index 0)
// language defines
#define LCL_ENGLISH 0
#define LCL_GERMAN 1
#define LCL_FRENCH 2
#define LCL_POLISH 3
#define LCL_UNTRANSLATED 10 // this should be higher than the highest builtin language
#define LCL_DEFAULT 0
#define FS2_OPEN_DEFAULT_LANGUAGE 0
// for language name strings
#define LCL_LANG_NAME_LEN 32
@@ -57,7 +56,7 @@ extern int Lcl_special_chars;
extern int Lcl_fr;
extern int Lcl_gr;
extern int Lcl_pl;
extern int Lcl_en;
extern int Lcl_english;
// The currently active language. Index into Lcl_languages.
extern int Lcl_current_lang;
+51 -63
View File
@@ -233,8 +233,8 @@ const auto OnMessageReceivedHook = scripting::Hook::Factory(
});
// forward declarations
void message_maybe_distort_text(char *text, int shipnum, bool for_death_scream);
int comm_between_player_and_ship(int other_shipnum, bool for_death_scream);
void message_maybe_distort_text(char *text, int shipnum);
int comm_between_player_and_ship(int other_shipnum);
// following functions to parse messages.tbl -- code pretty much ripped from weapon/ship table parsing code
@@ -865,8 +865,9 @@ void message_kill_all( int kill_all )
if ( kill_all ) {
Num_messages_playing = 0;
fsspeech_stop();
}
fsspeech_stop();
}
// function to kill nth playing message
@@ -1450,47 +1451,6 @@ void message_queue_process()
Assert ( q->priority != -1 );
Assert ( q->time_added != -1 );
int provisional_message_shipnum = -1;
// Do some checks to see if we are actually going to play this message at all. These checks have been moved above the
// "if ( Num_messages_playing )" block because we don't want to cancel an existing message if we have nothing to replace it with.
// Goober5000 - argh, don't conflate special sources with ships!
// NOTA BENE: don't check for != HUD_SOURCE_TERRAN_CMD, because with the new command persona code, Command could be a ship
if ( q->source != HUD_SOURCE_IMPORTANT ) {
provisional_message_shipnum = ship_name_lookup( q->who_from );
// see if we need to check if sending ship is alive
if ( (provisional_message_shipnum < 0) && (q->flags & MQF_CHECK_ALIVE) ) {
goto all_done;
}
}
// AL: added 07/14/97.. only play avi/sound if in gameplay
if ( gameseq_get_state() != GS_STATE_GAME_PLAY )
goto all_done;
// AL 4-7-98: Can't receive messages if comm is destroyed
if ( hud_communications_state(Player_ship) == COMM_DESTROYED ) {
goto all_done;
}
// G5K 4-26-20: Can't send messages if comm is destroyed
if ( The_mission.ai_profile->flags[AI::Profile_Flags::Check_comms_for_non_player_ships] && hud_communications_state(&Ships[provisional_message_shipnum], (q->builtin_type == MESSAGE_WINGMAN_SCREAM)) == COMM_DESTROYED ) {
goto all_done;
}
// Don't play death scream unless a small ship.
if ( q->builtin_type == MESSAGE_WINGMAN_SCREAM ) {
if (provisional_message_shipnum < 0) {
goto all_done;
}
if (!(Ship_info[Ships[provisional_message_shipnum].ship_info_index].is_small_ship() || (Ships[provisional_message_shipnum].flags[Ship::Ship_Flags::Always_death_scream])) ) {
goto all_done;
}
}
// At this point we think we're going to play the queued message.
if ( Num_messages_playing ) {
// peek at the first message on the queue to see if it should interrupt, or overlap a currently
// playing message. Mission specific messages will always interrupt builtin messages. They
@@ -1550,23 +1510,30 @@ void message_queue_process()
if ( Num_messages_playing == MAX_PLAYING_MESSAGES )
return;
// Goober5000 - argh, don't conflate special sources with ships!
// NOTA BENE: don't check for != HUD_SOURCE_TERRAN_CMD, because with the new command persona code, Command could be a ship
if ( q->source != HUD_SOURCE_IMPORTANT ) {
Message_shipnum = ship_name_lookup( q->who_from );
// see if we need to check if sending ship is alive
if ( (Message_shipnum < 0) && (q->flags & MQF_CHECK_ALIVE) ) {
goto all_done;
}
}
// if this is a ship, then don't play anything if this ship is already talking
if ( provisional_message_shipnum != -1 ) {
if ( Message_shipnum != -1 ) {
for ( i = 0; i < Num_messages_playing; i++ ) {
if ( (Playing_messages[i].shipnum != -1) && (Playing_messages[i].shipnum == provisional_message_shipnum) ){
if ( (Playing_messages[i].shipnum != -1) && (Playing_messages[i].shipnum == Message_shipnum) ){
return;
}
}
}
// At this point we are definitely going to play the queued message.
Message_shipnum = provisional_message_shipnum;
// set up module globals for this message
m = &Messages[q->message_num];
Playing_messages[Num_messages_playing].anim_data = NULL;
Playing_messages[Num_messages_playing].wave = sound_handle::invalid();
Playing_messages[Num_messages_playing].wave = sound_handle::invalid();
Playing_messages[Num_messages_playing].id = q->message_num;
Playing_messages[Num_messages_playing].priority = q->priority;
Playing_messages[Num_messages_playing].shipnum = Message_shipnum;
@@ -1581,6 +1548,24 @@ void message_queue_process()
message_translate_tokens(buf, q->special_message);
Message_expire = timestamp(static_cast<int>(42 * strlen(buf)));
// AL: added 07/14/97.. only play avi/sound if in gameplay
if ( gameseq_get_state() != GS_STATE_GAME_PLAY )
goto all_done;
// AL 4-7-98: Can't receive messages if comm is destroyed
if ( hud_communications_state(Player_ship) == COMM_DESTROYED ) {
goto all_done;
}
// Don't play death scream unless a small ship.
if ( q->builtin_type == MESSAGE_WINGMAN_SCREAM ) {
if (Message_shipnum < 0) {
goto all_done;
}
if (!(Ship_info[Ships[Message_shipnum].ship_info_index].is_small_ship() || (Ships[Message_shipnum].flags[Ship::Ship_Flags::Always_death_scream])) ) {
goto all_done;
}
}
// play wave first, since need to know duration for picking anim start frame
if(message_play_wave(q) == false) {
@@ -1591,7 +1576,7 @@ void message_queue_process()
message_play_anim(q);
// distort the message if comms system is damaged
message_maybe_distort_text(buf, Message_shipnum, (q->builtin_type == MESSAGE_WINGMAN_SCREAM));
message_maybe_distort_text(buf, Message_shipnum);
#ifndef NDEBUG
// debug only -- if the message is a builtin message, put in parens whether or not the voice played
@@ -1636,8 +1621,8 @@ void message_queue_process()
scripting::hook_param("Builtin", 'b', builtinMessage),
scripting::hook_param("Sender", 'o', sender)));
Num_messages_playing++; // this has to be done at the end because some sound functions use it to index into the array
all_done:
Num_messages_playing++;
message_remove_from_queue(q);
}
@@ -2211,7 +2196,7 @@ void message_maybe_distort()
was_muted = 0;
if ( comm_between_player_and_ship(Playing_messages[i].shipnum, Playing_messages[i].builtin_type == MESSAGE_WINGMAN_SCREAM) != COMM_OK ) {
if ( comm_between_player_and_ship(Playing_messages[i].shipnum) != COMM_OK) {
was_muted = Message_wave_muted;
if ( timestamp_elapsed(Next_mute_time) ) {
Next_mute_time = fl2i(Distort_patterns[Distort_num][Distort_next++] * Message_wave_duration);
@@ -2242,11 +2227,11 @@ void message_maybe_distort()
// Blank out portions of the sound based on Distort_num, this this is that same
// data that will be used to blank out portions of the audio playback
//
void message_maybe_distort_text(char *text, int shipnum, bool for_death_scream)
void message_maybe_distort_text(char *text, int shipnum)
{
int voice_duration;
if (comm_between_player_and_ship(shipnum, for_death_scream) == COMM_OK) {
if (comm_between_player_and_ship(shipnum) == COMM_OK) {
return;
}
@@ -2387,28 +2372,31 @@ bool change_message(const char* name, const char* message, int persona_index, in
}
/**
* This returns the minimum of the comm state between the player and the other ship. In practice, retail has no checks whatsoever on a ship's ability
* to send messages unless that ship is the player, so such a change requires an AI profiles option and we must default to the player's state. However, we
* have a bit of wiggle room with COMM_SCRAMBLED, because EMP effects are either transient or set by the scramble-messages SEXP.
* Ideally, this would return the minimum of the comm state between the player and the other ship. In practice, retail has no checks whatsoever on a ship's ability
* to send messages unless that ship is the player, so such a change would require an AI profiles option and we must default to the player's state. However, we
* have a bit of wiggle room with COMM_SCRAMBLED, because EMP effects are either transient or set by the newly enhanced scramble-messages SEXP. Thus any comm
* dropout does not cause an unanticipated deviation in the mission design.
*/
int comm_between_player_and_ship(int other_shipnum, bool for_death_scream)
int comm_between_player_and_ship(int other_shipnum)
{
int player_comm_state = hud_communications_state(Player_ship);
if (other_shipnum < 0)
return player_comm_state;
int other_comm_state = hud_communications_state(&Ships[other_shipnum], for_death_scream);
int other_comm_state = hud_communications_state(&Ships[other_shipnum]);
if (The_mission.ai_profile->flags[AI::Profile_Flags::Check_comms_for_non_player_ships])
/* here is where you would check the flag
if (hypothetical_ai_profiles_flag)
{
return MIN(player_comm_state, other_comm_state);
}
else
*/
{
if (player_comm_state == COMM_OK && other_comm_state == COMM_OK)
return COMM_OK;
else if (player_comm_state == COMM_OK && other_comm_state == COMM_SCRAMBLED)
else if (player_comm_state == COMM_SCRAMBLED || other_comm_state == COMM_SCRAMBLED)
return COMM_SCRAMBLED;
else
return player_comm_state;
+19 -5
View File
@@ -6001,7 +6001,7 @@ void parse_init(bool basic)
for (int i = 0; i < MAX_CARGO; i++)
Cargo_names[i] = Cargo_names_buf[i]; // make a pointer array for compatibility
ai_clear_goal_target_names();
Total_goal_target_names = 0;
// if we are just wanting basic info then we shouldn't need sexps
// (prevents memory fragmentation with the now dynamic Sexp_nodes[])
@@ -7103,6 +7103,21 @@ void mission_eval_arrivals()
Mission_arrival_timestamp = timestamp(ARRIVAL_TIMESTAMP);
}
/**
* Checks the warp drive; we might be able to depart some other way (e.g. by entering a docking bay)
*/
int ship_can_use_warp_drive(ship *shipp)
{
// must *have* a subspace drive
if (shipp->flags[Ship::Ship_Flags::No_subspace_drive])
return 0;
// navigation must work
if (!ship_navigation_ok_to_warp(shipp))
return 0;
return 1;
}
/**
* Called to make object objp depart. Rewritten and expanded by Goober5000.
@@ -7135,7 +7150,7 @@ int mission_do_departure(object *objp, bool goal_is_to_warp)
mprintf(("Looks like we were ordered to depart; initiating the standard departure logic\n"));
}
// since our goal is to warp, then if we can warp, jump directly to the warping part
else if (ship_can_warp_full_check(shipp))
else if (ship_can_use_warp_drive(shipp))
{
mprintf(("Our current goal is to warp! Trying to warp...\n"));
goto try_to_warp;
@@ -7205,7 +7220,7 @@ int mission_do_departure(object *objp, bool goal_is_to_warp)
try_to_warp:
// make sure we can actually warp
if (ship_can_warp_full_check(shipp))
if (ship_can_use_warp_drive(shipp))
{
mprintf(("Setting mode to warpout\n"));
@@ -7258,8 +7273,7 @@ void mission_eval_departures()
// don't process a ship that is already departing or dying or disabled
// AL 12-30-97: Added SF_CANNOT_WARP to check
// Goober5000 - fixed so that it WILL eval when SF_CANNOT_WARP if departing to dockbay
// wookieejedi - fixed so it accounts for break and never warp too
if ( shipp->is_dying_or_departing() || ( !(ship_can_warp_full_check(shipp)) && (shipp->departure_location != DEPART_AT_DOCK_BAY)) || ship_subsys_disrupted(shipp, SUBSYSTEM_ENGINE) ) {
if ( shipp->is_dying_or_departing() || (shipp->cannot_warp() && (shipp->departure_location != DEPART_AT_DOCK_BAY)) || ship_subsys_disrupted(shipp, SUBSYSTEM_ENGINE) ) {
continue;
}
+4 -22
View File
@@ -1853,7 +1853,7 @@ bool is_weapon_carried(int weapon_index)
return false;
}
bool check_for_gaps_in_weapon_slots()
bool is_a_weapon_slot_empty()
{
for (int slot = 0; slot < MAX_WING_BLOCKS*MAX_WING_SLOTS; ++slot)
{
@@ -1866,38 +1866,21 @@ bool check_for_gaps_in_weapon_slots()
continue;
ship_info *sip = &Ship_info[Wss_slots[slot].ship_class];
bool empty_slot = false;
// check primary banks
for (int bank = 0; bank < sip->num_primary_banks; ++bank) // NOLINT(modernize-loop-convert)
{
// is the slot empty?
if (Wss_slots[slot].wep_count[bank] <= 0)
{
empty_slot = true;
}
// is there a full slot following a gap?
else if (empty_slot)
{
return true;
}
}
empty_slot = false;
// check secondary banks
for (int bank = 0; bank < sip->num_secondary_banks; ++bank)
{
// is the slot empty?
if (Wss_slots[slot].wep_count[MAX_SHIP_PRIMARY_BANKS + bank] <= 0)
{
empty_slot = true;
}
// is there a full slot following a gap?
else if (empty_slot)
{
return true;
}
}
}
}
@@ -1972,13 +1955,12 @@ void commit_pressed()
}
}
// Goober5000 - check that there are no gaps in weapon slots (Mantis 2715)
// Any incomplete loadouts that make it through the loadout screen will be condensed so that gaps are moved to the bottom. This check adds that responsibility to the player.
// Goober5000 - check that all weapon slots are filled (Mantis 2715)
// Note: don't check for training, scramble, or red-alert missions
// Note2: don't check missions without briefings either
if (check_for_gaps_in_weapon_slots() && !(The_mission.game_type & MISSION_TYPE_TRAINING) && !The_mission.flags[Mission::Mission_Flags::Scramble, Mission::Mission_Flags::Red_alert, Mission::Mission_Flags::No_briefing])
if (is_a_weapon_slot_empty() && !(The_mission.game_type & MISSION_TYPE_TRAINING) && !The_mission.flags[Mission::Mission_Flags::Scramble, Mission::Mission_Flags::Red_alert, Mission::Mission_Flags::No_briefing])
{
popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, XSTR("At least one ship has an empty weapon bank before a full weapon bank.\n\nAll weapon banks must have weapons assigned, or if there are any gaps, they must be at the bottom of the set of banks.", 1642), weapon_list.c_str());
popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, XSTR("At least one ship has an empty weapon bank. All weapon banks must have weapons assigned.", 1642), weapon_list.c_str());
return;
}
+2 -13
View File
@@ -42,7 +42,6 @@ float Shield_pain_flash_factor;
gameversion::version Targetted_version; // Defaults to retail
SCP_string Window_title;
bool Unicode_text_mode;
bool Use_tabled_strings_for_default_language;
SCP_string Movie_subtitle_font;
bool Enable_scripts_in_fred; // By default FRED does not initialize the scripting system
SCP_string Window_icon_path;
@@ -100,12 +99,6 @@ void parse_mod_table(const char *filename)
mprintf(("Game settings table: Unicode mode: %s\n", Unicode_text_mode ? "yes" : "no"));
}
if (optional_string("$Use tabled strings for the default language:")) {
stuff_boolean(&Use_tabled_strings_for_default_language);
mprintf(("Game settings table: Use tabled strings (translations) for the default language: %s\n", Use_tabled_strings_for_default_language ? "yes" : "no"));
}
optional_string("#CAMPAIGN SETTINGS");
if (optional_string("$Default Campaign File Name:")) {
@@ -542,14 +535,11 @@ void mod_table_init()
// parse any modular tables
parse_modular_table("*-mod.tbm", parse_mod_table);
}
bool mod_supports_version(int major, int minor, int build)
{
bool mod_supports_version(int major, int minor, int build) {
return Targetted_version >= gameversion::version(major, minor, build, 0);
}
void mod_table_reset() {
void mod_table_reset()
{
Directive_wait_time = 3000;
True_loop_argument_sexps = false;
Fixed_turret_collisions = false;
@@ -575,7 +565,6 @@ void mod_table_reset()
Targetted_version = gameversion::version(2, 0, 0, 0); // Defaults to retail
Window_title = "";
Unicode_text_mode = false;
Use_tabled_strings_for_default_language = false;
Movie_subtitle_font = "font01.vf";
Enable_scripts_in_fred = false;
Window_icon_path = "app_icon_sse";
-1
View File
@@ -33,7 +33,6 @@ extern float Generic_pain_flash_factor;
extern float Shield_pain_flash_factor;
extern SCP_string Window_title;
extern bool Unicode_text_mode;
extern bool Use_tabled_strings_for_default_language;
extern SCP_string Movie_subtitle_font;
extern bool Enable_scripts_in_fred;
extern SCP_string Window_icon_path;
+1 -1
View File
@@ -4011,7 +4011,7 @@ int model_rotate_gun(int model_num, model_subsystem *turret, matrix *orient, ang
{
base_delta = vm_delta_from_interp_angle( base_angles->h, desired_angles.h );
gun_delta = vm_delta_from_interp_angle( gun_angles->p, desired_angles.p );
ss->points_to_target = sqrt((base_delta*base_delta) + (gun_delta*gun_delta));
ss->points_to_target = sqrt( pow(base_delta,2) + pow(gun_delta,2));
}
return 1;
+1 -1
View File
@@ -2157,7 +2157,7 @@ void multi_warpout_all_players()
// if we're an observer, or we're respawning, or we can't warp out. so just jump into the debrief state
if((Net_player->flags & NETINFO_FLAG_OBSERVER) || (Net_player->flags & NETINFO_FLAG_RESPAWNING) ||
((Player_obj->type == OBJ_SHIP) && !(ship_can_warp_full_check(Player_ship)))){
((Player_obj->type == OBJ_SHIP) && ( Player_ship->cannot_warp())) ){
multi_handle_sudden_mission_end();
+1 -7
View File
@@ -781,16 +781,10 @@ void obj_player_fire_stuff( object *objp, control_info ci )
// single player and multiplayer masters do all of the following
if ( !MULTIPLAYER_CLIENT ) {
if ( ci.fire_secondary_count ) {
if ( !ship_start_secondary_fire(objp) ) {
ship_fire_secondary( objp );
}
ship_fire_secondary( objp );
// kill the secondary count
ci.fire_secondary_count = 0;
} else {
if ( ship_stop_secondary_fire(objp) ) {
ship_fire_secondary( objp );
}
}
}
+13
View File
@@ -89,6 +89,8 @@ namespace
int Global_warning_count = 0;
int Global_error_count = 0;
extern lua_Debug Ade_debug_info;
namespace os
{
namespace dialogs
@@ -164,6 +166,17 @@ namespace os
msgStream << "\n";
msgStream << "\n";
msgStream << Separator;
msgStream << "ADE Debug:";
msgStream << "\n";
msgStream << Separator;
LuaDebugPrint(msgStream, Ade_debug_info);
msgStream << Separator;
msgStream << "\n";
msgStream << "\n";
msgStream << Separator;
// Get the stack via the debug.traceback() function
+1 -5
View File
@@ -4309,12 +4309,8 @@ int parse_modular_table(const char *name_check, void (*parse_callback)(const cha
Parsing_modular_table = true;
const auto ext = strrchr(name_check, '.');
for (i = 0; i < num_files; i++){
if (ext != nullptr) {
tbl_file_names[i] += ext;
}
tbl_file_names[i] += ".tbm";
mprintf(("TBM => Starting parse of '%s' ...\n", tbl_file_names[i].c_str()));
(*parse_callback)(tbl_file_names[i].c_str());
}
-3
View File
@@ -26480,7 +26480,6 @@ int eval_sexp(int cur_node, int referenced_node)
return sexp_val;
}
#ifndef NDEBUG
// now, reconcile positive and negative - Goober5000
if (sexp_val < 0 && sexp_val > SEXP_UNLIKELY_RETURN_VALUE_BOUND)
{
@@ -26495,12 +26494,10 @@ int eval_sexp(int cur_node, int referenced_node)
// if we need a positive value, make it positive
if (query_operator_argument_type(get_operator_index(parent_node), arg_num) == OPF_POSITIVE)
{
Warning(LOCATION, "Parent node %s, argument %d (value %d) is negative, but is required to be positive!", Sexp_nodes[parent_node].text, arg_num + 1, sexp_val);
sexp_val *= -1;
}
}
}
#endif
if ( sexp_val ){
Sexp_nodes[cur_node].value = SEXP_TRUE;
+1 -1
View File
@@ -1038,7 +1038,7 @@ void read_player_controls(object *objp, float frametime)
target_warpout_speed = ship_get_warpout_speed(objp);
// check if warp ability has been disabled
if (!(Warpout_forced) && !(ship_can_warp_full_check(&Ships[objp->instance]))) {
if (!(Warpout_forced) && (Ships[objp->instance].flags[Ship::Ship_Flags::Warp_broken] || Ships[objp->instance].flags[Ship::Ship_Flags::Warp_never]) ) {
HUD_sourced_printf(HUD_SOURCE_HIDDEN, "%s", XSTR( "Cannot warp out at this time.", 81));
snd_play(gamesnd_get_game_sound(GameSounds::PLAYER_WARP_FAIL));
gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_STOP );
+2 -4
View File
@@ -323,8 +323,7 @@ ADE_FUNC(getCurrentLanguage,
"Determines the language that is being used by the engine. This returns the full name of the language (e.g. \"English\").",
"string",
"The current game language") {
auto lang_name = (Lcl_current_lang == LCL_UNTRANSLATED) ? "UNTRANSLATED" : Lcl_languages[Lcl_current_lang].lang_name;
return ade_set_args(L, "s", lang_name);
return ade_set_args(L, "s", Lcl_languages[Lcl_current_lang].lang_name);
}
ADE_FUNC(getCurrentLanguageExtension,
@@ -335,8 +334,7 @@ ADE_FUNC(getCurrentLanguageExtension,
"This will return an empty string for the default language.",
"string",
"The current game language") {
int lang = (Lcl_current_lang == LCL_UNTRANSLATED) ? LCL_DEFAULT : Lcl_current_lang;
return ade_set_args(L, "s", Lcl_languages[lang].lang_ext);
return ade_set_args(L, "s", Lcl_languages[Lcl_current_lang].lang_ext);
}
ADE_FUNC(getVersionString, l_Base, nullptr,
-83
View File
@@ -1,83 +0,0 @@
//
//
#include "engine.h"
#include "scripting/scripting.h"
namespace scripting {
namespace api {
//**********LIBRARY: Engine
ADE_LIB(l_Engine, "Engine", "engine", "Basic engine access functions");
ADE_FUNC(addHook, l_Engine,
"string name, function hookFunction, [table conditionals = {}], [function override_func = return false]",
"Adds a function to be called from the specified game hook", "boolean",
"true if hook was installed properly, false otherwise")
{
using namespace luacpp;
const char* hook_name;
LuaFunction hook;
LuaTable conditionals;
LuaFunction override_func;
if (!ade_get_args(L, "su|tu", &hook_name, &hook, &conditionals, &override_func)) {
return ADE_RETURN_FALSE;
}
if (!hook.isValid()) {
LuaError(L, "Hook function is invalid!");
return ADE_RETURN_FALSE;
}
ConditionedHook cond_hook;
script_action action;
action.action_type = scripting_string_to_action(hook_name);
if (action.action_type == CHA_NONE) {
LuaError(L, "Invalid hook name '%s'!", hook_name);
return ADE_RETURN_FALSE;
}
action.hook.hook_function.language = SC_LUA;
action.hook.hook_function.function = hook;
if (override_func.isValid()) {
action.hook.override_function.language = SC_LUA;
action.hook.override_function.function = override_func;
}
cond_hook.AddAction(&action);
if (conditionals.isValid()) {
for (const auto& tableEntry : conditionals) {
const auto& key = tableEntry.first;
const auto& value = tableEntry.second;
if (!key.is(ValueType::STRING)) {
LuaError(L, "Conditional key '%s' is not a string", key.getValue<SCP_string>().c_str());
return ADE_RETURN_FALSE;
}
if (!value.is(ValueType::STRING)) {
LuaError(L, "Conditional value '%s' for key '%s' is not a string", value.getValue<SCP_string>().c_str(),
key.getValue<SCP_string>().c_str());
return ADE_RETURN_FALSE;
}
script_condition cond;
cond.condition_type = scripting_string_to_condition(key.getValue<SCP_string>().c_str());
cond.condition_string = value.getValue<SCP_string>();
cond_hook.AddCondition(&cond);
}
}
Script_system.AddConditionedHook(std::move(cond_hook));
return ADE_RETURN_TRUE;
}
} // namespace api
} // namespace scripting
-13
View File
@@ -1,13 +0,0 @@
#pragma once
#include "scripting/ade_api.h"
namespace scripting {
namespace api {
DECLARE_ADE_LIB(l_Engine);
}
}
+4 -21
View File
@@ -1470,7 +1470,7 @@ ADE_FUNC(warpOut, l_Ship, NULL, "Warps ship out", "boolean", "True if successful
return ADE_RETURN_TRUE;
}
ADE_FUNC(canWarp, l_Ship, nullptr, "Checks whether ship has a working subspace drive, is allowed to use it, and is not disabled or limited by subsystem strength.", "boolean", "True if successful, or nil if ship handle is invalid")
ADE_FUNC(canWarp, l_Ship, NULL, "Checks whether ship has a working subspace drive and is allowed to use it", "boolean", "True if successful, or nil if ship handle is invalid")
{
object_h *objh;
if(!ade_get_args(L, "o", l_Ship.GetPtr(&objh)))
@@ -1480,28 +1480,11 @@ ADE_FUNC(canWarp, l_Ship, nullptr, "Checks whether ship has a working subspace d
return ADE_RETURN_NIL;
ship *shipp = &Ships[objh->objp->instance];
if( ship_can_warp_full_check(shipp) ){
return ADE_RETURN_TRUE;
if(shipp->flags[Ship::Ship_Flags::No_subspace_drive]){
return ADE_RETURN_FALSE;
}
return ADE_RETURN_FALSE;
}
ADE_FUNC(canBayDepart, l_Ship, nullptr, "Checks whether ship has a bay departure location and if its mother ship is present.", "boolean", "True if successful, or nil if ship handle is invalid")
{
object_h *objh;
if(!ade_get_args(L, "o", l_Ship.GetPtr(&objh)))
return ADE_RETURN_NIL;
if(!objh->IsValid())
return ADE_RETURN_NIL;
ship *shipp = &Ships[objh->objp->instance];
if( ship_can_bay_depart(shipp) ){
return ADE_RETURN_TRUE;
}
return ADE_RETURN_FALSE;
return ADE_RETURN_TRUE;
}
// Aardwolf's function for finding if a ship should be drawn as blue on the radar/minimap
+51 -1
View File
@@ -58,7 +58,6 @@
#include "scripting/api/libs/base.h"
#include "scripting/api/libs/bitops.h"
#include "scripting/api/libs/cfile.h"
#include "scripting/api/libs/engine.h"
#include "scripting/api/libs/graphics.h"
#include "scripting/api/libs/hookvars.h"
#include "scripting/api/libs/hud.h"
@@ -77,6 +76,46 @@ using namespace scripting;
using namespace scripting::api;
// *************************Housekeeping*************************
//WMC - The miraculous lines of code that make Lua debugging worth something.
lua_Debug Ade_debug_info;
char debug_stack[4][32];
void ade_debug_ret(lua_State *L, lua_Debug *ar)
{
Assert(L != NULL);
Assert(ar != NULL);
lua_getstack(L, 1, ar);
lua_getinfo(L, "nSlu", ar);
memcpy(&Ade_debug_info, ar, sizeof(lua_Debug));
int n;
for (n = 0; n < 4; n++) {
debug_stack[n][0] = '\0';
}
for (n = 0; n < 4; n++) {
if (lua_getstack(L,n+1, ar) == 0)
break;
lua_getinfo(L,"n", ar);
if (ar->name == NULL)
break;
strcpy_s(debug_stack[n],ar->name);
}
}
//WMC - because the behavior of the return keyword
//was changed, I now have to use this in hooks.
static int ade_return_hack(lua_State *L)
{
int i = 0;
int num = lua_gettop(L);
for(i = 0; i < num; i++)
{
lua_pushvalue(L, i+1);
}
return num;
}
static void *vm_lua_alloc(void*, void *ptr, size_t, size_t nsize) {
if (nsize == 0)
@@ -126,6 +165,11 @@ int script_state::CreateLuaState()
}
lua_pop(L, 1); //os table
//*****SET DEBUG HOOKS
#ifndef NDEBUG
lua_sethook(L, ade_debug_ret, LUA_MASKRET, 0);
#endif
//*****INITIALIZE ADE
uint i;
mprintf(("LUA: Beginning ADE initialization\n"));
@@ -136,6 +180,12 @@ int script_state::CreateLuaState()
ade_manager::getInstance()->getEntry(i).SetTable(L, LUA_GLOBALSINDEX, LUA_GLOBALSINDEX); //Oh the miracles of OOP.
}
//*****INITIALIZE RETURN HACK FUNCTION
lua_pushstring(L, "ade_return_hack");
lua_pushboolean(L, 0);
lua_pushcclosure(L, ade_return_hack, 2);
lua_setglobal(L, "ade_return_hack");
//*****INITIALIZE ENUMERATION CONSTANTS
mprintf(("ADE: Initializing enumeration constants...\n"));
enum_h eh;
+4 -4
View File
@@ -66,7 +66,7 @@ bool LuaFunction::setEnvironment(const LuaTable& table) {
return ret;
}
LuaValueList LuaFunction::operator()(const LuaValueList& args) const {
LuaValueList LuaFunction::operator()(const LuaValueList& args) {
return this->call(args);
}
@@ -91,7 +91,7 @@ void LuaFunction::setReference(const LuaReference& ref) {
}
}
LuaValueList LuaFunction::call(const LuaValueList& args) const {
LuaValueList LuaFunction::call(const LuaValueList& args) {
int err_idx = 0;
int stackTop;
@@ -108,8 +108,8 @@ LuaValueList LuaFunction::call(const LuaValueList& args) const {
this->pushValue();
// Push the arguments onto the stack
for (const auto& arg : args) {
arg.pushValue();
for (LuaValueList::const_iterator iter = args.begin(); iter != args.end(); ++iter) {
iter->pushValue();
}
// actually call the function now!
+2 -2
View File
@@ -110,13 +110,13 @@ class LuaFunction: public LuaValue {
* @exception LuaException If an error occurs while executing the function an exception is thrown
* with the message of the error.
*/
LuaValueList call(const LuaValueList& arguments = LuaValueList()) const;
LuaValueList call(const LuaValueList& arguments = LuaValueList());
/**
* @brief Calls the function. See call().
* @return Same as call().
*/
LuaValueList operator()(const LuaValueList& arguments = LuaValueList()) const;
LuaValueList operator()(const LuaValueList& arguments = LuaValueList());
private:
LuaReference _errorFunction;
};
+55 -127
View File
@@ -174,36 +174,6 @@ void script_parse_table(const char* filename)
return;
}
}
void script_parse_lua_script(const char *filename) {
using namespace luacpp;
CFILE *cfp = cfopen(filename, "rb", CFILE_NORMAL, CF_TYPE_TABLES);
if(cfp == nullptr)
{
Warning(LOCATION, "Could not open lua script file '%s'", filename);
return;
}
int len = cfilelength(cfp);
SCP_string source;
source.resize((size_t) len);
cfread(&source[0], len, 1, cfp);
cfclose(cfp);
try {
auto function = LuaFunction::createFromCode(Script_system.GetLuaSession(), source, filename);
function.setErrorFunction(LuaFunction::createFromCFunction(Script_system.GetLuaSession(), ade_friendly_error));
script_function func;
func.language = SC_LUA;
func.function = function;
Script_system.AddGameInitFunction(func);
} catch (const LuaException& e) {
LuaError(Script_system.GetLuaSession(), "Failed to parse %s: %s", filename, e.what());
}
}
static void json_doc_generate_class(json_t* elObj, const DocumentationElementClass* lib)
{
@@ -405,8 +375,6 @@ void script_init()
mprintf(("SCRIPTING: Beginning main hook parse sequence....\n"));
script_parse_table("scripting.tbl");
parse_modular_table(NOX("*-sct.tbm"), script_parse_table);
mprintf(("SCRIPTING: Parsing pure Lua scripts\n"));
parse_modular_table(NOX("*-sct.lua"), script_parse_lua_script);
mprintf(("SCRIPTING: Inititialization complete.\n"));
}
/*
@@ -468,7 +436,7 @@ bool ConditionedHook::ConditionsValid(int action, object *objp, int more_data)
case CHC_STATE:
if(gameseq_get_depth() < 0)
return false;
if(stricmp(GS_state_text[gameseq_get_state(0)], scp->condition_string.c_str()) != 0)
if(stricmp(GS_state_text[gameseq_get_state(0)], scp->data.name) != 0)
return false;
break;
case CHC_SHIPTYPE:
@@ -477,19 +445,19 @@ bool ConditionedHook::ConditionsValid(int action, object *objp, int more_data)
sip = &Ship_info[Ships[objp->instance].ship_info_index];
if(sip->class_type < 0)
return false;
if(stricmp(Ship_types[sip->class_type].name, scp->condition_string.c_str()) != 0)
if(stricmp(Ship_types[sip->class_type].name, scp->data.name) != 0)
return false;
break;
case CHC_SHIPCLASS:
if(objp == NULL || objp->type != OBJ_SHIP)
return false;
if(stricmp(Ship_info[Ships[objp->instance].ship_info_index].name, scp->condition_string.c_str()) != 0)
if(stricmp(Ship_info[Ships[objp->instance].ship_info_index].name, scp->data.name) != 0)
return false;
break;
case CHC_SHIP:
if(objp == NULL || objp->type != OBJ_SHIP)
return false;
if(stricmp(Ships[objp->instance].ship_name, scp->condition_string.c_str()) != 0)
if(stricmp(Ships[objp->instance].ship_name, scp->data.name) != 0)
return false;
break;
case CHC_MISSION:
@@ -502,7 +470,7 @@ bool ConditionedHook::ConditionsValid(int action, object *objp, int more_data)
return false;
if(len > 4 && !stricmp(&Mission_filename[len-4], ".fs2"))
len -= 4;
if(strnicmp(scp->condition_string.c_str(), Mission_filename, len) != 0)
if(strnicmp(scp->data.name, Mission_filename, len) != 0)
return false;
break;
}
@@ -513,21 +481,21 @@ bool ConditionedHook::ConditionsValid(int action, object *objp, int more_data)
return false;
if(len > 4 && !stricmp(&Mission_filename[len-4], ".fc2"))
len -= 4;
if(strnicmp(scp->condition_string.c_str(), Mission_filename, len) != 0)
if(strnicmp(scp->data.name, Mission_filename, len) != 0)
return false;
break;
}
case CHC_WEAPONCLASS:
{
if (action == CHA_COLLIDEWEAPON) {
if (stricmp(Weapon_info[more_data].name, scp->condition_string.c_str()) != 0)
if (stricmp(Weapon_info[more_data].name, scp->data.name) != 0)
return false;
} else if (!(action == CHA_ONWPSELECTED || action == CHA_ONWPDESELECTED || action == CHA_ONWPEQUIPPED || action == CHA_ONWPFIRED || action == CHA_ONTURRETFIRED )) {
if(objp == NULL || (objp->type != OBJ_WEAPON && objp->type != OBJ_BEAM))
return false;
else if (( objp->type == OBJ_WEAPON) && (stricmp(Weapon_info[Weapons[objp->instance].weapon_info_index].name, scp->condition_string.c_str()) != 0 ))
else if (( objp->type == OBJ_WEAPON) && (stricmp(Weapon_info[Weapons[objp->instance].weapon_info_index].name, scp->data.name) != 0 ))
return false;
else if (( objp->type == OBJ_BEAM) && (stricmp(Weapon_info[Beams[objp->instance].weapon_info_index].name, scp->condition_string.c_str()) != 0 ))
else if (( objp->type == OBJ_BEAM) && (stricmp(Weapon_info[Beams[objp->instance].weapon_info_index].name, scp->data.name) != 0 ))
return false;
} else if(objp == NULL || objp->type != OBJ_SHIP) {
return false;
@@ -541,35 +509,27 @@ bool ConditionedHook::ConditionsValid(int action, object *objp, int more_data)
bool primary = false, secondary = false, prev_primary = false, prev_secondary = false;
switch (action) {
case CHA_ONWPSELECTED:
if (shipp->weapons.current_primary_bank >= 0) {
primary = stricmp(Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].name, scp->condition_string.c_str()) == 0;
}
if (shipp->weapons.current_secondary_bank >= 0) {
secondary = stricmp(Weapon_info[shipp->weapons.secondary_bank_weapons[shipp->weapons.current_secondary_bank]].name, scp->condition_string.c_str()) == 0;
}
if (!(primary || secondary)) {
if (shipp->weapons.current_primary_bank >= 0)
primary = stricmp(Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].name, scp->data.name) == 0;
if (shipp->weapons.current_secondary_bank >= 0)
secondary = stricmp(Weapon_info[shipp->weapons.secondary_bank_weapons[shipp->weapons.current_secondary_bank]].name, scp->data.name) == 0;
if (!(primary || secondary))
return false;
}
if ((shipp->flags[Ship::Ship_Flags::Primary_linked]) && primary && (Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].wi_flags[Weapon::Info_Flags::Nolink])) {
if ((shipp->flags[Ship::Ship_Flags::Primary_linked]) && primary && (Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].wi_flags[Weapon::Info_Flags::Nolink]))
return false;
}
break;
case CHA_ONWPDESELECTED:
if (shipp->weapons.current_primary_bank >= 0) {
primary = stricmp(Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].name, scp->condition_string.c_str()) == 0;
}
if (shipp->weapons.previous_primary_bank >= 0) {
prev_primary = stricmp(Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.previous_primary_bank]].name, scp->condition_string.c_str()) == 0;
}
if (shipp->weapons.current_secondary_bank >= 0) {
secondary = stricmp(Weapon_info[shipp->weapons.secondary_bank_weapons[shipp->weapons.current_secondary_bank]].name, scp->condition_string.c_str()) == 0;
}
if (shipp->weapons.previous_secondary_bank >= 0) {
prev_secondary = stricmp(Weapon_info[shipp->weapons.secondary_bank_weapons[shipp->weapons.previous_secondary_bank]].name, scp->condition_string.c_str()) == 0;
}
if (shipp->weapons.current_primary_bank >= 0)
primary = stricmp(Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].name, scp->data.name) == 0;
if (shipp->weapons.previous_primary_bank >= 0)
prev_primary = stricmp(Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.previous_primary_bank]].name, scp->data.name) == 0;
if (shipp->weapons.current_secondary_bank >= 0)
secondary = stricmp(Weapon_info[shipp->weapons.secondary_bank_weapons[shipp->weapons.current_secondary_bank]].name, scp->data.name) == 0;
if (shipp->weapons.previous_secondary_bank >= 0)
prev_secondary = stricmp(Weapon_info[shipp->weapons.secondary_bank_weapons[shipp->weapons.previous_secondary_bank]].name, scp->data.name) == 0;
if ((shipp->flags[Ship::Ship_Flags::Primary_linked]) && prev_primary && (Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.previous_primary_bank]].wi_flags[Weapon::Info_Flags::Nolink]))
return true;
@@ -577,10 +537,10 @@ bool ConditionedHook::ConditionsValid(int action, object *objp, int more_data)
if ( !prev_secondary && ! secondary && !prev_primary && !primary )
return false;
if ( (!prev_secondary && !secondary) && (prev_primary && primary) )
if ( (!prev_secondary && !secondary) && (prev_primary && primary) )
return false;
if ( (!prev_secondary && !secondary) && (!prev_primary && primary) )
if ( (!prev_secondary && !secondary) && (!prev_primary && primary) )
return false;
if ( (!prev_primary && !primary) && (prev_secondary && secondary) )
@@ -594,8 +554,7 @@ bool ConditionedHook::ConditionsValid(int action, object *objp, int more_data)
bool equipped = false;
for(int j = 0; j < MAX_SHIP_PRIMARY_BANKS; j++) {
if (!equipped && (shipp->weapons.primary_bank_weapons[j] >= 0) && (shipp->weapons.primary_bank_weapons[j] < weapon_info_size()) ) {
if (!stricmp(Weapon_info[shipp->weapons.primary_bank_weapons[j]].name,
scp->condition_string.c_str())) {
if ( !stricmp(Weapon_info[shipp->weapons.primary_bank_weapons[j]].name, scp->data.name) ) {
equipped = true;
break;
}
@@ -605,8 +564,7 @@ bool ConditionedHook::ConditionsValid(int action, object *objp, int more_data)
if (!equipped) {
for(int j = 0; j < MAX_SHIP_SECONDARY_BANKS; j++) {
if (!equipped && (shipp->weapons.secondary_bank_weapons[j] >= 0) && (shipp->weapons.secondary_bank_weapons[j] < weapon_info_size()) ) {
if (!stricmp(Weapon_info[shipp->weapons.secondary_bank_weapons[j]].name,
scp->condition_string.c_str())) {
if ( !stricmp(Weapon_info[shipp->weapons.secondary_bank_weapons[j]].name, scp->data.name) ) {
equipped = true;
break;
}
@@ -621,11 +579,11 @@ bool ConditionedHook::ConditionsValid(int action, object *objp, int more_data)
}
case CHA_ONWPFIRED: {
if (more_data == 1) {
primary = stricmp(Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].name, scp->condition_string.c_str()) == 0;
primary = stricmp(Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].name, scp->data.name) == 0;
secondary = false;
} else {
primary = false;
secondary = stricmp(Weapon_info[shipp->weapons.secondary_bank_weapons[shipp->weapons.current_secondary_bank]].name, scp->condition_string.c_str()) == 0;
secondary = stricmp(Weapon_info[shipp->weapons.secondary_bank_weapons[shipp->weapons.current_secondary_bank]].name, scp->data.name) == 0;
}
if ((shipp->flags[Ship::Ship_Flags::Primary_linked]) && primary && (Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].wi_flags[Weapon::Info_Flags::Nolink]))
@@ -636,22 +594,22 @@ bool ConditionedHook::ConditionsValid(int action, object *objp, int more_data)
break;
}
case CHA_ONTURRETFIRED: {
if (! (stricmp(Weapon_info[shipp->last_fired_turret->last_fired_weapon_info_index].name, scp->condition_string.c_str()) == 0))
if (! (stricmp(Weapon_info[shipp->last_fired_turret->last_fired_weapon_info_index].name, scp->data.name) == 0))
return false;
break;
}
case CHA_PRIMARYFIRE: {
if (stricmp(Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].name, scp->condition_string.c_str()) != 0)
if (stricmp(Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].name, scp->data.name) != 0)
return false;
break;
}
case CHA_SECONDARYFIRE: {
if (stricmp(Weapon_info[shipp->weapons.secondary_bank_weapons[shipp->weapons.current_secondary_bank]].name, scp->condition_string.c_str()) != 0)
if (stricmp(Weapon_info[shipp->weapons.secondary_bank_weapons[shipp->weapons.current_secondary_bank]].name, scp->data.name) != 0)
return false;
break;
}
case CHA_BEAMFIRE: {
if (!(stricmp(Weapon_info[more_data].name, scp->condition_string.c_str()) == 0))
if (!(stricmp(Weapon_info[more_data].name, scp->data.name) == 0))
return false;
break;
}
@@ -664,7 +622,7 @@ bool ConditionedHook::ConditionsValid(int action, object *objp, int more_data)
case CHC_OBJECTTYPE:
if(objp == NULL)
return false;
if(stricmp(Object_type_names[objp->type], scp->condition_string.c_str()) != 0)
if(stricmp(Object_type_names[objp->type], scp->data.name) != 0)
return false;
break;
case CHC_KEYPRESS:
@@ -675,7 +633,7 @@ bool ConditionedHook::ConditionsValid(int action, object *objp, int more_data)
if(Current_key_down == 0)
return false;
//WMC - could be more efficient, but whatever.
if(stricmp(textify_scancode(Current_key_down), scp->condition_string.c_str()) != 0)
if(stricmp(textify_scancode(Current_key_down), scp->data.name) != 0)
return false;
break;
}
@@ -686,7 +644,7 @@ bool ConditionedHook::ConditionsValid(int action, object *objp, int more_data)
int action_index = more_data;
if (action_index <= 0 || stricmp(scp->condition_string.c_str(), Control_config[action_index].text) != 0)
if (action_index <= 0 || stricmp(scp->data.name, Control_config[action_index].text) != 0)
return false;
break;
}
@@ -695,13 +653,13 @@ bool ConditionedHook::ConditionsValid(int action, object *objp, int more_data)
// Goober5000: I'm going to assume scripting doesn't care about SVN revision
char buf[32];
sprintf(buf, "%i.%i.%i", FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD);
if(stricmp(buf, scp->condition_string.c_str()) != 0)
if(stricmp(buf, scp->data.name) != 0)
{
//In case some people are lazy and say "3.7" instead of "3.7.0" or something
if(FS_VERSION_BUILD == 0)
{
sprintf(buf, "%i.%i", FS_VERSION_MAJOR, FS_VERSION_MINOR);
if(stricmp(buf, scp->condition_string.c_str()) != 0)
if(stricmp(buf, scp->data.name) != 0)
return false;
}
else
@@ -715,12 +673,12 @@ bool ConditionedHook::ConditionsValid(int action, object *objp, int more_data)
{
if(Fred_running)
{
if(stricmp("FRED2_Open", scp->condition_string.c_str()) != 0 && stricmp("FRED2Open", scp->condition_string.c_str()) != 0 && stricmp("FRED 2", scp->condition_string.c_str()) != 0 && stricmp("FRED", scp->condition_string.c_str()) != 0)
if(stricmp("FRED2_Open", scp->data.name) != 0 && stricmp("FRED2Open", scp->data.name) != 0 && stricmp("FRED 2", scp->data.name) != 0 && stricmp("FRED", scp->data.name) != 0)
return false;
}
else
{
if(stricmp("FS2_Open", scp->condition_string.c_str()) != 0 && stricmp("FS2Open", scp->condition_string.c_str()) != 0 && stricmp("Freespace 2", scp->condition_string.c_str()) != 0 && stricmp("Freespace", scp->condition_string.c_str()) != 0)
if(stricmp("FS2_Open", scp->data.name) != 0 && stricmp("FS2Open", scp->data.name) != 0 && stricmp("Freespace 2", scp->data.name) != 0 && stricmp("Freespace", scp->data.name) != 0)
return false;
}
}
@@ -1324,13 +1282,13 @@ int script_state::RunBytecode(script_function& hd)
return 1;
}
ConditionalType script_parse_condition()
int script_parse_condition()
{
char buf[NAME_LENGTH];
for (int i = 0; i < Num_script_conditions; i++) {
sprintf(buf, "$%s:", Script_conditions[i].name);
if(optional_string(buf))
return static_cast<ConditionalType>(Script_conditions[i].def);
if (optional_string(buf))
return Script_conditions[i].def;
}
return CHC_NONE;
@@ -1347,29 +1305,7 @@ const scripting::HookBase* script_parse_action()
return nullptr;
}
int32_t scripting_string_to_action(const char* action)
{
for (const auto& hook : scripting::getHooks()) {
if (hook->getHookName() == action)
return hook->getHookId();
}
return CHA_NONE;
}
ConditionalType scripting_string_to_condition(const char* condition)
{
for (int i = 0; i < Num_script_conditions; i++) {
if (!stricmp(Script_conditions[i].name, condition)) {
return static_cast<ConditionalType>(Script_conditions[i].def);
}
}
return CHC_NONE;
}
void script_state::ParseGlobalChunk(ConditionalActions hookType, const char* debug_str) {
void script_state::ParseGlobalChunk(int hookType, const char* debug_str) {
ConditionedHook hook;
script_action sat;
@@ -1384,9 +1320,10 @@ void script_state::ParseGlobalChunk(ConditionalActions hookType, const char* deb
}
bool script_state::ParseCondition(const char *filename)
{
ConditionedHook *chp = nullptr;
ConditionedHook *chp = NULL;
int condition;
for(auto condition = script_parse_condition(); condition != CHC_NONE; condition = script_parse_condition())
for(condition = script_parse_condition(); condition != CHC_NONE; condition = script_parse_condition())
{
script_condition sct;
sct.condition_type = condition;
@@ -1404,7 +1341,7 @@ bool script_state::ParseCondition(const char *filename)
case CHC_VERSION:
case CHC_APPLICATION:
default:
stuff_string(sct.condition_string, F_NAME);
stuff_string(sct.data.name, F_NAME, CONDITION_LENGTH);
break;
}
@@ -1431,10 +1368,13 @@ bool script_state::ParseCondition(const char *filename)
sat.action_type = action->getHookId();
// WMC - build error string
SCP_string buf;
char* buf = (char*)vm_malloc(strlen(filename) + action->getHookName().size() + 4);
sprintf(buf, "%s - %s", filename, action->getHookName().c_str());
ParseChunk(&sat.hook, buf.c_str());
ParseChunk(&sat.hook, buf);
// Free error string
vm_free(buf);
// Add the action
if (chp->AddAction(&sat))
@@ -1451,10 +1391,6 @@ bool script_state::ParseCondition(const char *filename)
return true;
}
void script_state::AddConditionedHook(ConditionedHook hook) { ConditionalHooks.push_back(std::move(hook)); }
void script_state::AddGameInitFunction(script_function func) { GameInitFunctions.push_back(std::move(func)); }
//*************************CLASS: script_state*************************
bool script_state::IsOverride(script_hook &hd)
{
@@ -1467,14 +1403,6 @@ bool script_state::IsOverride(script_hook &hd)
return b;
}
void script_state::RunInitFunctions() {
for (const auto& initFunc : GameInitFunctions) {
initFunc.function();
}
// We don't need this anymore so no need to keep references to those functions around anymore
GameInitFunctions.clear();
}
void scripting_state_init()
{
// nothing to do here
+30 -32
View File
@@ -43,22 +43,20 @@ extern bool script_hook_valid(script_hook *hook);
#define MAX_HOOK_CONDITIONS 8
// Conditionals
enum ConditionalType {
CHC_NONE = -1,
CHC_MISSION = 0,
CHC_SHIP = 1,
CHC_SHIPCLASS = 2,
CHC_SHIPTYPE = 3,
CHC_STATE = 4,
CHC_CAMPAIGN = 5,
CHC_WEAPONCLASS = 6,
CHC_OBJECTTYPE = 7,
CHC_KEYPRESS = 8,
CHC_ACTION = 9,
CHC_VERSION = 10,
CHC_APPLICATION = 11,
};
//Conditionals
#define CHC_NONE -1
#define CHC_MISSION 0
#define CHC_SHIP 1
#define CHC_SHIPCLASS 2
#define CHC_SHIPTYPE 3
#define CHC_STATE 4
#define CHC_CAMPAIGN 5
#define CHC_WEAPONCLASS 6
#define CHC_OBJECTTYPE 7
#define CHC_KEYPRESS 8
#define CHC_ACTION 9
#define CHC_VERSION 10
#define CHC_APPLICATION 11
//Actions
enum ConditionalActions : int32_t {
@@ -118,18 +116,25 @@ void scripting_state_init();
void scripting_state_close();
void scripting_state_do_frame(float frametime);
int32_t scripting_string_to_action(const char* action);
ConditionalType scripting_string_to_condition(const char* condition);
struct script_condition
class script_condition
{
ConditionalType condition_type = CHC_NONE;
SCP_string condition_string;
public:
int condition_type{CHC_NONE};
union
{
char name[CONDITION_LENGTH];
} data;
script_condition()
{
memset(data.name, 0, sizeof(data.name));
}
};
struct script_action
class script_action
{
int32_t action_type {CHA_NONE};
public:
int action_type{CHA_NONE};
script_hook hook;
};
@@ -230,8 +235,6 @@ private:
SCP_vector<image_desc> ScriptImages;
SCP_vector<ConditionedHook> ConditionalHooks;
SCP_vector<script_function> GameInitFunctions;
private:
void ParseChunkSub(script_function& out_func, const char* debug_str=NULL);
@@ -291,11 +294,8 @@ public:
const char* debug_str = nullptr);
bool EvalString(const char* string, const char* debug_str = nullptr);
void ParseChunk(script_hook *dest, const char* debug_str=NULL);
void ParseGlobalChunk(ConditionalActions hookType, const char* debug_str=nullptr);
void ParseGlobalChunk(int hookType, const char* debug_str=NULL);
bool ParseCondition(const char *filename="<Unknown>");
void AddConditionedHook(ConditionedHook hook);
void AddGameInitFunction(script_function func);
//***Hook running functions
template <typename T>
@@ -305,8 +305,6 @@ public:
int RunCondition(int condition, object* objp = nullptr, int more_data = 0);
bool IsConditionOverride(int action, object *objp=NULL);
void RunInitFunctions();
//*****Other functions
void EndFrame();
+33 -264
View File
@@ -6966,7 +6966,6 @@ void ship_render_show_ship_cockpit(object *objp)
model_render_params render_info;
render_info.set_object_number(OBJ_INDEX(objp));
render_info.set_replacement_textures(Ships[objp->instance].ship_replacement_textures);
render_info.set_detail_level_lock(0);
model_render_immediate(&render_info, Ship_info[Ships[objp->instance].ship_info_index].model_num, &objp->orient,
@@ -10646,6 +10645,8 @@ int ship_stop_fire_primary(object * obj)
int tracers[MAX_SHIPS][4][4];
float ship_get_subsystem_strength( ship *shipp, int type );
/**
* Checks whether a ship would use autoaim if it were to fire its primaries at
* the given object, taking lead into account.
@@ -11844,34 +11845,33 @@ int ship_fire_secondary( object *obj, int allow_swarm )
// Ensure if this is a "require-lock" missile, that a lock actually exists
if ( wip->wi_flags[Weapon::Info_Flags::No_dumbfire] ) {
if (!aip->current_target_is_locked && !ship_lock_present(shipp) && !(shipp->missile_locks_firing.size() > 0)) {
if (obj == Player_obj) {
if (!Weapon_energy_cheat) {
if ( aip->current_target_is_locked <= 0 ) {
if ( obj == Player_obj ) {
if ( !Weapon_energy_cheat ) {
float max_dist;
max_dist = wip->lifetime * wip->max_speed;
if (wip->wi_flags[Weapon::Info_Flags::Local_ssm]) {
max_dist = wip->lssm_lock_range;
if (wip->wi_flags[Weapon::Info_Flags::Local_ssm]){
max_dist= wip->lssm_lock_range;
}
if ((aip->target_objnum != -1) &&
(vm_vec_dist_quick(&obj->pos, &Objects[aip->target_objnum].pos) > max_dist)) {
HUD_sourced_printf(HUD_SOURCE_HIDDEN, "%s", XSTR("Too far from target to acquire lock", 487));
if ((aip->target_objnum != -1) && (vm_vec_dist_quick(&obj->pos, &Objects[aip->target_objnum].pos) > max_dist)) {
HUD_sourced_printf(HUD_SOURCE_HIDDEN, "%s", XSTR( "Too far from target to acquire lock", 487));
} else {
char missile_name[NAME_LENGTH];
strcpy_s(missile_name, wip->get_display_string());
end_string_at_first_hash_symbol(missile_name);
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR("Cannot fire %s without a lock", 488), missile_name);
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Cannot fire %s without a lock", 488), missile_name);
}
snd_play(gamesnd_get_game_sound(ship_get_sound(Player_obj, GameSounds::OUT_OF_MISSLES)));
swp->next_secondary_fire_stamp[bank] = timestamp(800); // to avoid repeating messages
snd_play( gamesnd_get_game_sound(ship_get_sound(Player_obj, GameSounds::OUT_OF_MISSLES)) );
swp->next_secondary_fire_stamp[bank] = timestamp(800); // to avoid repeating messages
return 0;
}
} else {
// multiplayer clients should always fire the weapon here, so return only if not
// a multiplayer client.
if (!MULTIPLAYER_CLIENT) {
if ( !MULTIPLAYER_CLIENT ) {
return 0;
}
}
@@ -11902,21 +11902,16 @@ int ship_fire_secondary( object *obj, int allow_swarm )
}
}
if ( !allow_swarm && obj == Player_obj ) {
ship_queue_missile_locks(shipp);
}
// if trying to fire a swarm missile, make sure being called from right place
if ( (wip->wi_flags[Weapon::Info_Flags::Swarm]) && !allow_swarm ) {
Assert(wip->swarm_count > 0);
if (wip->multi_lock && obj == Player_obj) {
shipp->num_swarm_missiles_to_fire = (int)shipp->missile_locks_firing.size();
} else if(wip->swarm_count <= 0){
if(wip->swarm_count <= 0){
shipp->num_swarm_missiles_to_fire = SWARM_DEFAULT_NUM_MISSILES_FIRED;
} else {
shipp->num_swarm_missiles_to_fire = wip->swarm_count;
}
shipp->swarm_missile_bank = bank;
return 1; // Note: Missiles didn't get fired, but the frame interval code will fire them.
}
@@ -11925,11 +11920,7 @@ int ship_fire_secondary( object *obj, int allow_swarm )
if ( (wip->wi_flags[Weapon::Info_Flags::Corkscrew]) && !allow_swarm ) {
//phreak 11-9-02
//changed this from 4 to custom number defined in tables
if (wip->multi_lock && obj == Player_obj) {
shipp->num_corkscrew_to_fire = (ubyte)shipp->missile_locks_firing.size();
} else {
shipp->num_corkscrew_to_fire = (ubyte)(shipp->num_corkscrew_to_fire + (ubyte)wip->cs_num_fired);
}
shipp->num_corkscrew_to_fire = (ubyte)(shipp->num_corkscrew_to_fire + (ubyte)wip->cs_num_fired);
shipp->corkscrew_missile_bank = bank;
return 1; // Note: Missiles didn't get fired, but the frame interval code will fire them.
}
@@ -11943,7 +11934,7 @@ int ship_fire_secondary( object *obj, int allow_swarm )
t = Weapon_info[weapon_idx].fire_wait; // They can fire 5 times a second
swp->burst_counter[bank_adjusted] = 0;
}
swp->next_secondary_fire_stamp[bank] = timestamp((int)(t * 1000.0f));
swp->next_secondary_fire_stamp[bank] = timestamp((int) (t * 1000.0f));
swp->last_secondary_fire_stamp[bank] = timestamp();
// Here is where we check if weapons subsystem is capable of firing the weapon.
@@ -11971,33 +11962,6 @@ int ship_fire_secondary( object *obj, int allow_swarm )
return 0; // we can make a quick out here!!!
}
int target_objnum;
ship_subsys *target_subsys;
int locked;
if ( obj == Player_obj ) {
// use missile lock slots
if ( shipp->missile_locks_firing.size() > 0 ) {
lock_info lock_data = shipp->missile_locks_firing.back();
if ( wip->multi_lock ) {
shipp->missile_locks_firing.pop_back();
}
target_objnum = OBJ_INDEX(lock_data.obj);
target_subsys = lock_data.subsys;
locked = 1;
} else {
target_objnum = -1;
target_subsys = nullptr;
locked = 0;
}
} else {
target_objnum = aip->target_objnum;
target_subsys = aip->targeted_subsys;
locked = aip->current_target_is_locked;
}
num_slots = pm->missile_banks[bank].num_slots;
// determine if there is enough ammo left to fire weapons on this bank. As with primary
@@ -12108,7 +12072,7 @@ int ship_fire_secondary( object *obj, int allow_swarm )
// create the weapon -- for multiplayer, the net_signature is assigned inside
// of weapon_create
weapon_num = weapon_create( &firing_pos, &firing_orient, weapon_idx, OBJ_INDEX(obj), -1, locked);
weapon_num = weapon_create( &firing_pos, &firing_orient, weapon_idx, OBJ_INDEX(obj), -1, aip->current_target_is_locked);
if (weapon_num == -1) {
// Weapon most likely failed to fire
@@ -12120,7 +12084,7 @@ int ship_fire_secondary( object *obj, int allow_swarm )
if (weapon_num >= 0) {
weapon_idx = Weapons[Objects[weapon_num].instance].weapon_info_index;
weapon_set_tracking_info(weapon_num, OBJ_INDEX(obj), target_objnum, locked, target_subsys);
weapon_set_tracking_info(weapon_num, OBJ_INDEX(obj), aip->target_objnum, aip->current_target_is_locked, aip->targeted_subsys);
has_fired = true;
// create the muzzle flash effect
@@ -13389,7 +13353,7 @@ int ship_get_subsys_index(ship *shipp, ship_subsys *subsys)
// 0.0 and 1.0 which is the relative combined strength of the given subsystem type. The number
// calculated for the engines is slightly different. Once an engine reaches < 15% of its hits, its
// output drops to that %. A dead engine has no output.
float ship_get_subsystem_strength( ship *shipp, int type, bool skip_dying_check )
float ship_get_subsystem_strength( ship *shipp, int type )
{
float strength;
ship_subsys *ssp;
@@ -13397,7 +13361,7 @@ float ship_get_subsystem_strength( ship *shipp, int type, bool skip_dying_check
Assert ( (type >= 0) && (type < SUBSYSTEM_MAX) );
// For a dying ship, all subsystem strengths are zero.
if (Objects[shipp->objnum].hull_strength <= 0.0f && !skip_dying_check)
if (Objects[shipp->objnum].hull_strength <= 0.0f)
return 0.0f;
// short circuit 1
@@ -14390,9 +14354,8 @@ static void ship_add_ship_type_kill_count( int ship_info_index )
return;
}
//Add it if we are actually in gameplay
if (Ship_type_counts.size() > static_cast<size_t>(type))
Ship_type_counts[type].killed++;
//Add it
Ship_type_counts[type].killed++;
}
int ship_query_general_type(int ship)
@@ -14485,16 +14448,14 @@ int ship_get_random_player_wing_ship( int flags, float max_dist, int persona_ind
if ( Ships[ship_index].flags[Ship_Flags::Dying] ) {
continue;
}
// see if ship meets our criteria
// see if ship meets our criterea
if ( (flags == SHIP_GET_NO_PLAYERS || flags == SHIP_GET_UNSILENCED) && (Objects[Ships[ship_index].objnum].flags[Object::Object_Flags::Player_ship]) ){
continue;
}
if (flags == SHIP_GET_UNSILENCED) {
if (Ships[ship_index].flags[Ship_Flags::No_builtin_messages])
continue;
if (The_mission.ai_profile->flags[AI::Profile_Flags::Check_comms_for_non_player_ships] && hud_communications_state(&Ships[ship_index]) <= COMM_DAMAGED)
continue;
if ( (flags == SHIP_GET_UNSILENCED) && (Ships[ship_index].flags[Ship_Flags::No_builtin_messages]) )
{
continue;
}
// don't process ships on a different team
@@ -14728,57 +14689,6 @@ int ship_navigation_ok_to_warp(ship *sp)
return 1;
}
// wookieejedi
// checks both the warp flags and ship_engine_ok_to_warp() and ship_navigation_ok_to_warp() --wookieejedi
// returns true if ship is able to warp, otherwise return false
bool ship_can_warp_full_check(ship* sp)
{
if (!(sp->cannot_warp_flags()) && ship_navigation_ok_to_warp(sp) && ship_engine_ok_to_warp(sp)) {
// there are no warp flags that are preventing us from warping and the nav and engines are good
// thus warp is allowed
return true;
} else {
// warp is not allowed since one of those conditions was not met
return false;
}
}
// wookieejedi
// check to see if a ship can depart via bay
// takes into account if the ship is in a wing
// returns true if the ship has a bay departure and the mothership is present, false otherwise
bool ship_can_bay_depart(ship* sp)
{
// if this ship belongs to a wing, then use the wing departure information
int departure_location;
int departure_anchor;
int departure_path_mask;
if (sp->wingnum >= 0)
{
wing *wingp = &Wings[sp->wingnum];
departure_location = wingp->departure_location;
departure_anchor = wingp->departure_anchor;
departure_path_mask = wingp->departure_path_mask;
} else {
departure_location = sp->departure_location;
departure_anchor = sp->departure_anchor;
departure_path_mask = sp->departure_path_mask;
}
if ( departure_location == DEPART_AT_DOCK_BAY )
{
Assertion( departure_anchor >= 0, "Ship %s must have a valid departure anchor", sp->ship_name );
int anchor_shipnum = ship_name_lookup(Parse_names[departure_anchor]);
if (anchor_shipnum >= 0 && ship_useful_for_departure(anchor_shipnum, departure_path_mask)) {
// can bay depart at this time
return true;
}
}
// cannot bay depart at this time
return false;
}
// Calculate the normal vector from a subsystem position and its first path point
// input: sp => pointer to ship that is parent of subsystem
// ss => pointer to subsystem of interest
@@ -15591,9 +15501,6 @@ void ship_maybe_praise_self(ship *deader_sp, ship *killer_sp)
if ( killer_sp->flags[Ship_Flags::No_builtin_messages] ) {
return;
}
if (The_mission.ai_profile->flags[AI::Profile_Flags::Check_comms_for_non_player_ships] && hud_communications_state(killer_sp) != COMM_OK) {
return;
}
message_send_builtin_to_player(MESSAGE_PRAISE_SELF, killer_sp, MESSAGE_PRIORITY_HIGH, MESSAGE_TIME_SOON, 0, 0, -1, -1);
Player->praise_self_timestamp = timestamp(Builtin_messages[MESSAGE_PRAISE_SELF].min_delay);
@@ -15689,12 +15596,8 @@ play_ask_help:
if (!(Ship_info[sp->ship_info_index].is_fighter_bomber())) //If we're still here, only continue if we're a fighter or bomber.
return;
// only unsilenced ships should ask for help
if (sp->flags[Ship_Flags::No_builtin_messages])
return;
if (The_mission.ai_profile->flags[AI::Profile_Flags::Check_comms_for_non_player_ships] && hud_communications_state(&Ships[objp->instance]) <= COMM_DAMAGED)
return;
if (!(sp->flags[Ship_Flags::No_builtin_messages])) // Karajorma - Only unsilenced ships should ask for help
{
message_send_builtin_to_player(MESSAGE_HELP, sp, MESSAGE_PRIORITY_HIGH, MESSAGE_TIME_IMMEDIATE, 0, 0, -1, multi_team_filter);
Player->allow_ask_help_timestamp = timestamp(Builtin_messages[MESSAGE_HELP].min_delay);
@@ -15703,6 +15606,7 @@ play_ask_help:
Player->allow_scream_timestamp = timestamp(15000);
Player->ask_help_count++;
}
}
/**
@@ -15741,9 +15645,9 @@ void ship_scream(ship *sp)
// Bail if the ship is silenced
if (sp->flags[Ship_Flags::No_builtin_messages])
{
return;
if (The_mission.ai_profile->flags[AI::Profile_Flags::Check_comms_for_non_player_ships] && hud_communications_state(sp, true) <= COMM_DAMAGED)
return;
}
message_send_builtin_to_player(MESSAGE_WINGMAN_SCREAM, sp, MESSAGE_PRIORITY_HIGH, MESSAGE_TIME_IMMEDIATE, 0, 0, -1, multi_team_filter);
Player->allow_scream_timestamp = timestamp(Builtin_messages[MESSAGE_WINGMAN_SCREAM].min_delay);
@@ -15828,8 +15732,6 @@ void ship_maybe_tell_about_low_ammo(ship *sp)
if (sp->flags[Ship_Flags::No_builtin_messages]) {
return;
}
if (The_mission.ai_profile->flags[AI::Profile_Flags::Check_comms_for_non_player_ships] && hud_communications_state(sp) <= COMM_DAMAGED)
return;
// don't mention low ammo if we're docked, for the same reason as in maybe_request_support
if (object_is_docked(&Objects[sp->objnum]))
@@ -15895,8 +15797,6 @@ void ship_maybe_tell_about_rearm(ship *sp)
// Silent ships should remain just that
if (sp->flags[Ship_Flags::No_builtin_messages])
return;
if (The_mission.ai_profile->flags[AI::Profile_Flags::Check_comms_for_non_player_ships] && hud_communications_state(sp) <= COMM_DAMAGED)
return;
// AL 1-4-98: If ship integrity is low, tell player you want to get repaired. Otherwise, tell
// the player you want to get re-armed.
@@ -19265,134 +19165,3 @@ bool ship::is_arriving(ship::warpstage stage, bool dock_leader_or_single)
Assertion(false, "ship::is_arriving didn't handle all possible states; get a coder!");
return false;
}
void ship_clear_lock(lock_info *slot) {
vec3d zero_vec = ZERO_VECTOR;
slot->accumulated_x_pixels = 0;
slot->accumulated_y_pixels = 0;
slot->catch_up_distance = 0.0f;
slot->catching_up = 0;
slot->current_target_sx = -1;
slot->current_target_sy = -1;
slot->dist_to_lock = 0.0f;
slot->indicator_start_x = -1;
slot->indicator_start_y = -1;
slot->indicator_visible = false;
slot->indicator_x = -1;
slot->indicator_y = -1;
slot->last_dist_to_target = 0.0f;
slot->locked_timestamp = 0;
slot->maintain_lock_count = 0;
slot->need_new_start_pos = false;
slot->target_in_lock_cone = false;
slot->world_pos = zero_vec;
slot->locked = false;
slot->obj = nullptr;
slot->subsys = nullptr;
slot->time_to_lock = -1.0f;
}
void ship_queue_missile_locks(ship *shipp)
{
shipp->missile_locks_firing.clear();
// queue up valid missile locks
std::copy_if(shipp->missile_locks.begin(), shipp->missile_locks.end(), std::back_inserter(shipp->missile_locks_firing), [](lock_info lock) { return lock.locked; });
}
bool ship_lock_present(ship *shipp)
{
return std::any_of(shipp->missile_locks.begin(), shipp->missile_locks.end(), [](lock_info lock) { return lock.locked; });
}
bool ship_start_secondary_fire(object* objp)
{
Assert( objp != nullptr);
if ( objp->type != OBJ_SHIP ) {
return false;
}
int n = objp->instance;
Assert( n >= 0 && n < MAX_SHIPS );
Assert( Ships[n].objnum == OBJ_INDEX(objp) );
ship *shipp = &Ships[n];
ship_info *sip = &Ship_info[shipp->ship_info_index];
ship_weapon* swp = &shipp->weapons;
int bank = swp->current_secondary_bank;
if ( bank < 0 || bank >= sip->num_secondary_banks ) {
return false;
}
Assert( (swp->secondary_bank_weapons[bank] >= 0) && (swp->secondary_bank_weapons[bank] < weapon_info_size()) );
weapon_info *wip = &Weapon_info[swp->secondary_bank_weapons[bank]];
if ( wip->trigger_lock ) {
swp->flags.set(Ship::Weapon_Flags::Trigger_Lock);
return true;
}
return false;
}
bool ship_stop_secondary_fire(object* objp)
{
Assert( objp != nullptr);
if ( objp->type != OBJ_SHIP ) {
return false;
}
int n = objp->instance;
if ( n < 0 || n >= MAX_SHIPS ) {
return false;
}
Assert( Ships[n].objnum == OBJ_INDEX(objp) );
ship *shipp = &Ships[n];
ship_info *sip = &Ship_info[shipp->ship_info_index];
ship_weapon *swp = &shipp->weapons;
int bank = swp->current_secondary_bank;
if ( bank < 0 || bank >= sip->num_secondary_banks ) {
return false;
}
Assert( (swp->secondary_bank_weapons[bank] >= 0) && (swp->secondary_bank_weapons[bank] < weapon_info_size()) );
weapon_info *wip = &Weapon_info[swp->secondary_bank_weapons[bank]];
if ( wip->trigger_lock && swp->flags[Ship::Weapon_Flags::Trigger_Lock]) {
swp->flags.remove(Ship::Weapon_Flags::Trigger_Lock);
return true;
}
return false;
}
+2 -50
View File
@@ -31,7 +31,6 @@
#include "weapon/trails.h"
#include "ship/ship_flags.h"
#include "weapon/weapon_flags.h"
#include "ai/ai.h"
#include <string>
#include <particle/ParticleManager.h>
@@ -284,36 +283,6 @@ typedef struct cockpit_display_info {
int size[2];
} cockpit_display_info;
// structure to keep track of ship locks
typedef struct lock_info {
object *obj;
ship_subsys *subsys;
vec3d world_pos;
int current_target_sx;
int current_target_sy;
bool locked;
int maintain_lock_count;
int indicator_x;
int indicator_y;
int indicator_start_x;
int indicator_start_y;
bool indicator_visible;
float time_to_lock;
float dist_to_lock;
int catching_up;
float catch_up_distance;
float last_dist_to_target;
double accumulated_x_pixels;
double accumulated_y_pixels;
bool need_new_start_pos;
bool target_in_lock_cone;
int locked_timestamp;
} lock_info;
// structure definition for a linked list of subsystems for a ship. Each subsystem has a pointer
// to the static data for the subsystem. The obj_subsystem data is defined and read in the model
// code. Other dynamic data (such as current_hits) should remain in this structure.
@@ -591,9 +560,6 @@ public:
vec3d wash_rot_axis;
int wash_timestamp;
SCP_vector<lock_info> missile_locks;
SCP_vector<lock_info> missile_locks_firing;
int num_swarm_missiles_to_fire; // number of swarm missiles that need to be launched
int next_swarm_fire; // timestamp of next swarm missile to fire
int next_swarm_path; // next path number for swarm missile to take
@@ -756,7 +722,7 @@ public:
//Helper functions
bool is_arriving(ship::warpstage stage = ship::warpstage::BOTH, bool dock_leader_or_single = false);
inline bool is_departing() { return flags[Ship::Ship_Flags::Depart_warp, Ship::Ship_Flags::Depart_dockbay]; }
inline bool cannot_warp_flags() { return flags[Ship::Ship_Flags::Warp_broken, Ship::Ship_Flags::Warp_never, Ship::Ship_Flags::Disabled, Ship::Ship_Flags::No_subspace_drive]; }
inline bool cannot_warp() { return flags[Ship::Ship_Flags::Warp_broken, Ship::Ship_Flags::Warp_never, Ship::Ship_Flags::Disabled]; }
inline bool is_dying_or_departing() { return is_departing() || flags[Ship::Ship_Flags::Dying]; }
bool has_display_name();
@@ -1443,9 +1409,6 @@ extern bool in_autoaim_fov(ship *shipp, int bank_to_fire, object *obj);
extern int ship_stop_fire_primary(object * obj);
extern int ship_fire_primary(object * objp, int stream_weapons, int force = 0);
extern int ship_fire_secondary(object * objp, int allow_swarm = 0 );
bool ship_start_secondary_fire(object* objp);
bool ship_stop_secondary_fire(object* objp);
extern int ship_launch_countermeasure(object *objp, int rand_val = -1);
// for special targeting lasers
@@ -1534,7 +1497,7 @@ extern ship_subsys *ship_get_indexed_subsys( ship *sp, int index, vec3d *attacke
extern int ship_get_index_from_subsys(ship_subsys *ssp, int objnum);
extern int ship_get_subsys_index(ship *sp, const char* ss_name); // returns numerical index in linked list of subsystems
extern int ship_get_subsys_index(ship *shipp, ship_subsys *subsys);
extern float ship_get_subsystem_strength( ship *shipp, int type, bool skip_dying_check = false );
extern float ship_get_subsystem_strength( ship *shipp, int type );
extern ship_subsys *ship_get_subsys(ship *shipp, const char *subsys_name);
extern int ship_get_num_subsys(ship *shipp);
extern ship_subsys *ship_get_closest_subsys_in_sight(ship *sp, int subsys_type, vec3d *attacker_pos);
@@ -1575,8 +1538,6 @@ int ship_secondary_bank_has_ammo(int shipnum); // check if current secondary ban
int ship_engine_ok_to_warp(ship *sp); // check if ship has engine power to warp
int ship_navigation_ok_to_warp(ship *sp); // check if ship has navigation power to warp
bool ship_can_warp_full_check(ship *sp); // checks both the warp flags and ship_engine_ok_to_warp() and ship_navigation_ok_to_warp() --wookieejedi
bool ship_can_bay_depart(ship *sp); // checks to see if a ship has a departure location as a bay and if the mothership is present
int ship_return_subsys_path_normal(ship *sp, ship_subsys *ss, vec3d *gsubpos, vec3d *norm);
int ship_subsystem_in_sight(object* objp, ship_subsys* subsys, vec3d *eye_pos, vec3d* subsys_pos, int do_facing_check=1, float *dot_out=NULL, vec3d *vec_out=NULL);
@@ -1837,13 +1798,4 @@ extern void toggle_ignore_list_flag(Ship::Ship_Flags flag);
ship_subsys* ship_get_subsys_for_submodel(ship* shipp, int submodel);
// Clears a lock_info struct with defaults
void ship_clear_lock(lock_info *slot);
// queues up locks
void ship_queue_missile_locks(ship *shipp);
// snoops missile locks to see if any are ready to fire.
bool ship_lock_present(ship *shipp);
#endif
-1
View File
@@ -9,7 +9,6 @@ namespace Ship {
Beam_Free = 0, // if this is a beam weapon, its free to fire
Turret_Lock, // is this turret is free to fire or locked
Tagged_Only, // only fire if target is tagged
Trigger_Lock, // // indicates that the trigger is held down
NUM_VALUES
};
+1 -1
View File
@@ -56,7 +56,7 @@ extern int button_function(int n);
extern void hud_squadmsg_msg_all_fighters();
extern void hud_squadmsg_shortcut( int command );
extern bool hud_squadmsg_ship_valid(ship *shipp, object *objp = nullptr);
extern bool hud_squadmsg_wing_valid(wing *wingp);
extern int hud_squadmsg_wing_valid(wing *wingp);
extern int Msg_instance;;
extern int Msg_shortcut_command;
-2
View File
@@ -1073,8 +1073,6 @@ add_file_folder("Scripting\\\\Api\\\\Libs"
scripting/api/libs/bitops.h
scripting/api/libs/cfile.cpp
scripting/api/libs/cfile.h
scripting/api/libs/engine.cpp
scripting/api/libs/engine.h
scripting/api/libs/graphics.cpp
scripting/api/libs/graphics.h
scripting/api/libs/hookvars.cpp
+1 -30
View File
@@ -38,15 +38,6 @@ extern int Num_weapon_subtypes;
#define WRT_LASER 1
#define WRT_POF 2
// constants for weapon lock acquire methods
#define WLOCK_PIXEL 0
#define WLOCK_TIMER 1
// constants for weapon lock restrictions
#define LR_CURRENT_TARGET 0 // Only lock current target and subsystem
#define LR_CURRENT_TARGET_SUBSYS 1 //
#define LR_ANY_TARGETS 2
//particle names go here -nuke
#define PSPEW_NONE -1 //used to disable a spew, useful for xmts
#define PSPEW_DEFAULT 0 //std fs2 pspew
@@ -324,24 +315,11 @@ struct weapon_info
short swarm_count; // how many swarm missiles are fired for this weapon
int SwarmWait; // *Swarm firewait, default is 150 -Et1
int target_restrict;
bool multi_lock;
int max_seeking; // how many seekers can be active at a time if multilock is enabled. A value of one will lock stuff up one by one.
int max_seekers_per_target; // how many seekers can be attached to a target.
SCP_vector<int> ship_type_restrict;
SCP_vector<SCP_string> ship_type_restrict_temp;
bool trigger_lock; // Trigger must be held down and released to lock and fire.
bool launch_reset_locks; // Lock indicators reset after firing
// Specific to ASPECT homing missiles.
int acquire_method;
float min_lock_time; // minimum time (in seconds) to achieve lock
int lock_pixels_per_sec; // pixels/sec moved while locking
int catchup_pixels_per_sec; // pixels/sec moved while catching-up for a lock
int catchup_pixel_penalty; // number of extra pixels to move while locking as a penalty for catching up for a lock
float lock_fov;
int catchup_pixel_penalty; // number of extra pixels to move while locking as a penalty for catching up for a lock
// Specific to HEAT homing missiles.
float fov;
@@ -651,11 +629,4 @@ void validate_SSM_entries();
void shield_impact_explosion(vec3d *hitpos, object *objp, float radius, int idx);
// Swifty - return number of max simultaneous locks
int weapon_get_max_missile_seekers(weapon_info *wip);
// return if this weapon can lock on this ship type
bool weapon_can_lock_on_ship_type(weapon_info *wip, int ship_type);
#endif
+4 -302
View File
@@ -222,7 +222,6 @@ int Weapon_impact_timer; // timer, initialized at start of each mission
#define REARM_NUM_BALLISTIC_PRIMARIES_PER_BATCH 100
extern int compute_num_homing_objects(object *target_objp);
void weapon_spew_stats();
weapon_explosions::weapon_explosions()
@@ -986,10 +985,8 @@ int parse_weapon(int subtype, bool replace, const char *filename)
if ( optional_string("$Model file:") ) {
stuff_string(wip->pofbitmap_name, F_NAME, MAX_FILENAME_LEN);
if (VALID_FNAME(wip->pofbitmap_name))
if ( VALID_FNAME(wip->pofbitmap_name) )
wip->render_type = WRT_POF;
else
wip->render_type = WRT_NONE;
diag_printf("Model pof file -- %s\n", wip->pofbitmap_name );
}
@@ -1020,7 +1017,7 @@ int parse_weapon(int subtype, bool replace, const char *filename)
if (wip->render_type == WRT_POF) {
mprintf(("WARNING: Weapon '%s' has both LASER and POF render types! Will only use POF type!\n", wip->name));
generic_anim_init(&wip->laser_bitmap, nullptr);
generic_anim_init(&wip->laser_bitmap, NULL);
} else {
generic_anim_init(&wip->laser_bitmap, fname);
wip->render_type = WRT_LASER;
@@ -1398,56 +1395,6 @@ int parse_weapon(int subtype, bool replace, const char *filename)
}
}
if (optional_string("+Target Lock Restriction:")) {
if (optional_string("current target, any subsystem")) {
wip->target_restrict = LR_CURRENT_TARGET_SUBSYS;
}
else if (optional_string("any target")) {
wip->target_restrict = LR_ANY_TARGETS;
}
else if (optional_string("current target only")) {
wip->target_restrict = LR_CURRENT_TARGET;
}
else {
wip->target_restrict = LR_CURRENT_TARGET;
}
}
if (optional_string("+Independent Seekers:")) {
stuff_boolean(&wip->multi_lock);
}
if (optional_string("+Trigger Hold:")) {
stuff_boolean(&wip->trigger_lock);
}
if (optional_string("+Reset On Launch:")) {
stuff_boolean(&wip->launch_reset_locks);
}
if (optional_string("+Max Seekers Per Target:")) {
stuff_int(&wip->max_seekers_per_target);
}
if (optional_string("+Max Active Seekers:")) {
stuff_int(&wip->max_seeking);
}
if (optional_string("+Ship Types:")) {
stuff_string_list(wip->ship_type_restrict_temp);
}
if (wip->is_locked_homing()) {
// locked homing missiles have a much longer lifespan than the AI think they do
wip->max_lifetime = wip->lifetime * LOCKED_HOMING_EXTENDED_LIFE_FACTOR;
@@ -3600,9 +3547,6 @@ void weapon_init()
}
weapon_level_init();
if (Cmdline_spew_weapon_stats)
weapon_spew_stats();
}
@@ -3649,7 +3593,6 @@ void weapon_close()
void weapon_level_init()
{
int i;
extern int ships_inited;
// Reset everything between levels
Num_weapons = 0;
@@ -3661,19 +3604,6 @@ void weapon_level_init()
for (i = 0; i < weapon_info_size(); i++) {
Weapon_info[i].damage_type_idx = Weapon_info[i].damage_type_idx_sav;
Weapon_info[i].shockwave.damage_type_idx = Weapon_info[i].shockwave.damage_type_idx_sav;
if ( ships_inited ) {
// populate ship type lock restrictions
for ( int j = 0; j < (int)Weapon_info[i].ship_type_restrict_temp.size(); ++j ) {
int idx = ship_type_name_lookup((char*)Weapon_info[i].ship_type_restrict_temp[j].c_str());
if ( idx >= 0 ) {
Weapon_info[i].ship_type_restrict.push_back(idx);
}
}
Weapon_info[i].ship_type_restrict_temp.clear();
}
}
trail_level_init(); // reset all missile trails
@@ -7764,25 +7694,12 @@ void weapon_info::reset()
// *Default is 150 -Et1
this->SwarmWait = SWARM_MISSILE_DELAY;
this->target_restrict = LR_CURRENT_TARGET;
this->multi_lock = false;
this->trigger_lock = false;
this->launch_reset_locks = false;
this->max_seeking = 1;
this->max_seekers_per_target = 1;
this->ship_type_restrict.clear();
this->ship_type_restrict_temp.clear();
this->acquire_method = WLOCK_PIXEL;
this->min_lock_time = 0.0f;
this->lock_pixels_per_sec = 50;
this->catchup_pixels_per_sec = 50;
this->catchup_pixel_penalty = 50;
this->fov = 0; //should be cos(pi), not pi
this->seeker_strength = 1.0f;
this->lock_fov = 0.85f;
this->pre_launch_snd = gamesnd_id();
this->pre_launch_snd_min_interval = 0;
@@ -7973,228 +7890,13 @@ void weapon_info::reset()
// Reset using default constructor
this->impact_decal = decals::creation_info();
}
const char* weapon_info::get_display_string()
{
const char* weapon_info::get_display_string() {
if (has_alternate_name()) {
return alt_name;
} else {
return name;
}
}
bool weapon_info::has_alternate_name()
{
bool weapon_info::has_alternate_name() {
return alt_name[0] != '\0';
}
void weapon_spew_stats()
{
#ifndef NDEBUG
// csv weapon stats for comparisons
mprintf(("Name,Type,Velocity,Range,Damage Hull,DPS Hull,Damage Shield,DPS Shield,Damage Subsystem,DPS Subsystem,Power Use,Fire Wait,ROF,Reload,1/Reload,Area Effect,Shockwave\n"));
for (auto &wi : Weapon_info)
{
if (wi.subtype != WP_LASER)
continue;
weapon_info *wip_base = nullptr;
if (strchr(wi.name, '#'))
{
char temp[NAME_LENGTH];
strcpy_s(temp, wi.name);
end_string_at_first_hash_symbol(temp);
int idx = weapon_info_lookup(temp);
if (idx >= 0)
wip_base = &Weapon_info[idx];
}
if (wi.wi_flags[Weapon::Info_Flags::Player_allowed] || (wip_base != nullptr && wip_base->wi_flags[Weapon::Info_Flags::Player_allowed]))
{
mprintf(("%s,%s,", wi.name, "Primary"));
mprintf(("%.2f,%.2f,", wi.max_speed, wi.max_speed * wi.lifetime));
float multiplier = (wi.shockwave.speed > 0.0f) ? 2.0f : 1.0f;
mprintf(("%.2f,%.2f,", multiplier * wi.damage * wi.armor_factor, multiplier * wi.damage * wi.armor_factor / wi.fire_wait));
mprintf(("%.2f,%.2f,", multiplier * wi.damage * wi.shield_factor, multiplier * wi.damage * wi.shield_factor / wi.fire_wait));
mprintf(("%.2f,%.2f,", multiplier * wi.damage * wi.subsystem_factor, multiplier * wi.damage * wi.subsystem_factor / wi.fire_wait));
mprintf(("%.2f,", wi.energy_consumed / wi.fire_wait));
mprintf(("%.2f,%.2f,", wi.fire_wait, 1.0f / wi.fire_wait));
mprintf((",,")); // no reload for primaries
if (wi.shockwave.inner_rad > 0.0f || wi.shockwave.outer_rad > 0.0f)
mprintf(("Yes,"));
else
mprintf((","));
if (wi.shockwave.speed > 0.0f)
mprintf(("Yes\n"));
else
mprintf(("\n"));
}
}
for (auto &wi : Weapon_info)
{
if (wi.subtype != WP_MISSILE)
continue;
weapon_info *wip_base = nullptr;
if (strchr(wi.name, '#'))
{
char temp[NAME_LENGTH];
strcpy_s(temp, wi.name);
end_string_at_first_hash_symbol(temp);
int idx = weapon_info_lookup(temp);
if (idx >= 0)
wip_base = &Weapon_info[idx];
}
if (wi.wi_flags[Weapon::Info_Flags::Player_allowed] || (wip_base != nullptr && wip_base->wi_flags[Weapon::Info_Flags::Player_allowed]) || wi.wi_flags[Weapon::Info_Flags::Child])
{
mprintf(("%s,%s,", wi.name, "Secondary"));
mprintf(("%.2f,%.2f,", wi.max_speed, wi.max_speed * wi.lifetime));
float multiplier = (wi.shockwave.speed > 0.0f) ? 2.0f : 1.0f;
mprintf(("%.2f,%.2f,", multiplier * wi.damage * wi.armor_factor, multiplier * wi.damage * wi.armor_factor / wi.fire_wait));
mprintf(("%.2f,%.2f,", multiplier * wi.damage * wi.shield_factor, multiplier * wi.damage * wi.shield_factor / wi.fire_wait));
mprintf(("%.2f,%.2f,", multiplier * wi.damage * wi.subsystem_factor, multiplier * wi.damage * wi.subsystem_factor / wi.fire_wait));
mprintf((",")); // no power use for secondaries
mprintf(("%.2f,%.2f,", wi.fire_wait, 1.0f / wi.fire_wait));
mprintf(("%.2f,%.2f,", wi.reloaded_per_batch / wi.rearm_rate, wi.rearm_rate / wi.reloaded_per_batch)); // rearm_rate is actually the reciprocal of what is in weapons.tbl
if (wi.shockwave.inner_rad > 0.0f || wi.shockwave.outer_rad > 0.0f)
mprintf(("Yes,"));
else
mprintf((","));
if (wi.shockwave.speed > 0.0f)
mprintf(("Yes\n"));
else
mprintf(("\n"));
}
}
// mvp-style stats
mprintf(("\n"));
for (auto &wi : Weapon_info)
{
if (wi.subtype != WP_LASER)
continue;
weapon_info *wip_base = nullptr;
if (strchr(wi.name, '#'))
{
char temp[NAME_LENGTH];
strcpy_s(temp, wi.name);
end_string_at_first_hash_symbol(temp);
int idx = weapon_info_lookup(temp);
if (idx >= 0)
wip_base = &Weapon_info[idx];
}
if (wi.wi_flags[Weapon::Info_Flags::Player_allowed] || (wip_base != nullptr && wip_base->wi_flags[Weapon::Info_Flags::Player_allowed]))
{
mprintf(("%s\n", wi.name));
mprintf(("\tVelocity: %-11.0fRange: %.0f\n", wi.max_speed, wi.max_speed * wi.lifetime));
float multiplier = (wi.shockwave.inner_rad > 0.0f || wi.shockwave.outer_rad > 0.0f) ? 2.0f : 1.0f;
mprintf(("\tDPS: "));
mprintf(("%.0f Hull, ", multiplier * wi.damage * wi.armor_factor / wi.fire_wait));
mprintf(("%.0f Shield, ", multiplier * wi.damage * wi.shield_factor / wi.fire_wait));
mprintf(("%.0f Subsystem\n", multiplier * wi.damage * wi.subsystem_factor / wi.fire_wait));
char watts[NAME_LENGTH];
sprintf(watts, "%.1f", wi.energy_consumed / wi.fire_wait);
char *p = strstr(watts, ".0");
if (p)
*p = 0;
strcat(watts, "W");
char rof[NAME_LENGTH];
sprintf(rof, "%.1f", 1.0f / wi.fire_wait);
p = strstr(rof, ".0");
if (p)
*p = 0;
strcat(rof, "/s");
mprintf(("\tPower Use: %-10sROF: %s\n\n", watts, rof));
}
}
for (auto &wi : Weapon_info)
{
if (wi.subtype != WP_MISSILE)
continue;
weapon_info *wip_base = nullptr;
if (strchr(wi.name, '#'))
{
char temp[NAME_LENGTH];
strcpy_s(temp, wi.name);
end_string_at_first_hash_symbol(temp);
int idx = weapon_info_lookup(temp);
if (idx >= 0)
wip_base = &Weapon_info[idx];
}
if (wi.wi_flags[Weapon::Info_Flags::Player_allowed] || (wip_base != nullptr && wip_base->wi_flags[Weapon::Info_Flags::Player_allowed]) || wi.wi_flags[Weapon::Info_Flags::Child])
{
mprintf(("%s\n", wi.name));
mprintf(("\tVelocity: %-11.0fRange: %.0f\n", wi.max_speed, wi.max_speed * wi.lifetime));
float multiplier = (wi.shockwave.inner_rad > 0.0f || wi.shockwave.outer_rad > 0.0f) ? 2.0f : 1.0f;
mprintf(("\tDamage: "));
mprintf(("%.0f Hull, ", multiplier * wi.damage * wi.armor_factor));
mprintf(("%.0f Shield, ", multiplier * wi.damage * wi.shield_factor));
mprintf(("%.0f Subsystem\n", multiplier * wi.damage * wi.subsystem_factor));
char wait[NAME_LENGTH];
sprintf(wait, "%.1f", wi.fire_wait);
char *p = strstr(wait, ".0");
if (p)
*p = 0;
strcat(wait, "s");
bool flip = wi.rearm_rate <= 1.0f;
char flip_str[NAME_LENGTH];
sprintf(flip_str, "%d/", wi.reloaded_per_batch);
char reload[NAME_LENGTH];
sprintf(reload, "%.1f", flip ? wi.reloaded_per_batch / wi.rearm_rate : wi.rearm_rate);
p = strstr(reload, ".0");
if (p)
*p = 0;
mprintf(("\tFire Wait: %-10sReload: %s%s%ss\n\n", wait, !flip ? flip_str : "", reload, flip ? "/" : ""));
}
}
#endif
}
// Given a weapon, figure out how many independent locks we can have with it.
int weapon_get_max_missile_seekers(weapon_info *wip)
{
int max_target_locks;
if ( wip->multi_lock ) {
if ( wip->wi_flags[Weapon::Info_Flags::Swarm] ) {
max_target_locks = wip->swarm_count;
} else if ( wip->wi_flags[Weapon::Info_Flags::Corkscrew] ) {
max_target_locks = wip->cs_num_fired;
} else {
max_target_locks = 1;
}
} else {
max_target_locks = 1;
}
return max_target_locks;
}
bool weapon_can_lock_on_ship_type(weapon_info *wip, int ship_type)
{
// Determine if there are any restrictions, treating an empty list as true
return (wip->ship_type_restrict.size() == 0) ||
std::any_of(wip->ship_type_restrict.begin(), wip->ship_type_restrict.end(), [ship_type](int type) { return type == ship_type; });
}
+4 -5
View File
@@ -333,13 +333,13 @@ bool fred_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps)
// Load game_settings.tbl
mod_table_init();
// initialize localization module. Make sure this is done AFTER initializing OS.
// NOTE: Fred should ALWAYS run without localization. Otherwise it might swap in another language
// initialize localization module. Make sure this is done AFTER initialzing OS.
// NOTE : Fred should ALWAYS run in English. Otherwise it might swap in another language
// when saving - which would cause inconsistencies when externalizing to tstrings.tbl via Exstr
// trust me on this :)
lcl_init(LCL_UNTRANSLATED);
lcl_init(FS2_OPEN_DEFAULT_LANGUAGE);
// Goober5000 - force init XSTRs (so they work, but only work untranslated, based on above comment)
// Goober5000 - force init XSTRs (so they work, but only work in English, based on above comment)
extern int Xstr_inited;
Xstr_inited = 1;
@@ -466,7 +466,6 @@ bool fred_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps)
Id_select_type_waypoint = (int)(Ship_info.size());
Fred_main_wnd -> init_tools();
Script_system.RunInitFunctions();
Script_system.RunCondition(CHA_GAMEINIT);
return true;
+4 -2
View File
@@ -1195,7 +1195,8 @@ void ShipGoalsDlg::OnSelchangeObject10()
void ShipGoalsDlg::set_object(int item)
{
int i = 0, z, num;
char *str;
int i = 0, z, num, not_used;
ship_subsys *subsys;
if (m_behavior[item] > 0) {
@@ -1212,7 +1213,8 @@ void ShipGoalsDlg::set_object(int item)
for (i=0; i<num; i++) {
Assert(Docking_bay_list[i]);
z = m_dock2_box[item] -> AddString(Docking_bay_list[i]);
m_dock2_box[item] -> SetItemDataPtr(z, Docking_bay_list[i]);
str = ai_get_goal_target_name(Docking_bay_list[i], &not_used);
m_dock2_box[item] -> SetItemDataPtr(z, str);
}
} else if ((mode == AI_GOAL_DESTROY_SUBSYSTEM) && (m_data[item] >= 0)) {
-1
View File
@@ -1902,7 +1902,6 @@ void game_init()
// Do this before the initial scripting hook runs in case that hook does something with the UI
scpui::initialize();
Script_system.RunInitFunctions();
Script_system.RunCondition(CHA_GAMEINIT);
game_title_screen_close();
+5 -6
View File
@@ -95,13 +95,13 @@ initialize(const std::string& cfilepath, int argc, char* argv[], Editor* editor,
mod_table_init();
listener(SubSystem::Locale);
// initialize localization module. Make sure this is done AFTER initializing OS.
// NOTE: Fred should ALWAYS run without localization. Otherwise it might swap in another language
// initialize localization module. Make sure this is done AFTER initialzing OS.
// NOTE : Fred should ALWAYS run in English. Otherwise it might swap in another language
// when saving - which would cause inconsistencies when externalizing to tstrings.tbl via Exstr
// trust me on this :)
lcl_init(LCL_UNTRANSLATED);
lcl_init(FS2_OPEN_DEFAULT_LANGUAGE);
// Goober5000 - force init XSTRs (so they work, but only work untranslated, based on above comment)
// Goober5000 - force init XSTRs (so they work, but only work in English, based on above comment)
Xstr_inited = 1;
#ifndef NDEBUG
@@ -254,9 +254,8 @@ initialize(const std::string& cfilepath, int argc, char* argv[], Editor* editor,
control_config_common_init();
listener(SubSystem::ScriptingInitHook);
Script_system.RunInitFunctions();
Script_system.RunCondition(CHA_GAMEINIT);
return true;
}