diff --git a/CMakeLists.txt b/CMakeLists.txt index f39dd1fa95..0439bc7049 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -108,7 +108,13 @@ SET(FSO_RUN_ARGUMENTS "" CACHE STRING "Additional arguments passed to a generate option(FSO_INSTALL_DEBUG_FILES "Install some debug files (currently only PDB files on windows)" OFF) -OPTION(COTIRE_ENABLE "Enable cotire, this speeds up builds but may cause issues while developing (default = OFF)" OFF) +set(DEFAULT_VAL OFF) +if(MSVC) + # MSVC has been tested + set(DEFAULT_VAL ON) +endif() + +OPTION(COTIRE_ENABLE "Enable cotire, this speeds up builds but may cause issues while developing (default = OFF)" ${DEFAULT_VAL}) MARK_AS_ADVANCED(FORCE FSO_CMAKE_DEBUG) MARK_AS_ADVANCED(FORCE FSO_BUILD_INCLUDED_LIBS) @@ -189,4 +195,4 @@ elseif(UNIX) ENDIF() message(STATUS "Building FSO tools: ${FSO_BUILD_TOOLS}") message(STATUS "Building wxFRED: ${FSO_BUILD_WXFRED2}") -message(STATUS "Fatal warnings: ${FSO_FATAL_WARNINGS}") \ No newline at end of file +message(STATUS "Fatal warnings: ${FSO_FATAL_WARNINGS}") diff --git a/cmake/toolchain-msvc.cmake b/cmake/toolchain-msvc.cmake index 2c3276dcac..492df012c7 100644 --- a/cmake/toolchain-msvc.cmake +++ b/cmake/toolchain-msvc.cmake @@ -12,25 +12,25 @@ MARK_AS_ADVANCED(FORCE MSVC_USE_RUNTIME_DLL) # These are the warnings we disable set(WARNING_FLAGS - /wd"4100" # unreferenced formal parameters - /wd"4127" # constant conditional (assert) - /wd"4201" # nonstandard extension used: nameless struct/union (happens a lot in Windows include headers) - /wd"4290" # C++ exception specification ignored except to indicate a function is not __declspec(nothrow) - /wd"4390" # empty control statement (triggered by nprintf and mprintf's inside of one-line if's, etc) - /wd"4410" # illegal size for operand... ie... fxch st(1) - /wd"4511" # copy constructor could not be generated (happens a lot in Windows include headers) - /wd"4512" # assignment operator could not be generated (happens a lot in Windows include headers) - /wd"4514" # unreferenced inline function removed - /wd"4611" # _setjmp warning. Since we use setjmp alot, and we don't really use constructors or destructors, this warning doesn't really apply to us. - /wd"4663" # C++ language change (template specification) - /wd"4710" # is inline function not expanded (who cares?) - /wd"4711" # tells us an inline function was expanded (who cares?) - /wd"4786" # is identifier truncated to 255 characters (happens all the time in Microsoft #includes) -- Goober5000" - /wd"4996" # deprecated strcpy, strcat, sprintf, etc. (from MSVC 2005) - taylor - /wd"4311" # Disables warnings about casting pointer types to ints. The funny thing is these warnings can't be resolved, just disabled... - m!m - /wd"4302" # Same as above - m!m - /wd"4366" # The result of the unary '&' operator may be unaligned - m!m - $<$:/wd"4101"> # In release mode there are unreferenced variables because debug needs them + /wd4100 # unreferenced formal parameters + /wd4127 # constant conditional (assert) + /wd4201 # nonstandard extension used: nameless struct/union (happens a lot in Windows include headers) + /wd4290 # C++ exception specification ignored except to indicate a function is not __declspec(nothrow) + /wd4390 # empty control statement (triggered by nprintf and mprintf's inside of one-line if's, etc) + /wd4410 # illegal size for operand... ie... fxch st(1) + /wd4511 # copy constructor could not be generated (happens a lot in Windows include headers) + /wd4512 # assignment operator could not be generated (happens a lot in Windows include headers) + /wd4514 # unreferenced inline function removed + /wd4611 # _setjmp warning. Since we use setjmp alot, and we don't really use constructors or destructors, this warning doesn't really apply to us. + /wd4663 # C++ language change (template specification) + /wd4710 # is inline function not expanded (who cares?) + /wd4711 # tells us an inline function was expanded (who cares?) + /wd4786 # is identifier truncated to 255 characters (happens all the time in Microsoft #includes) -- Goober5000" + /wd4996 # deprecated strcpy, strcat, sprintf, etc. (from MSVC 2005) - taylor + /wd4311 # Disables warnings about casting pointer types to ints. The funny thing is these warnings can't be resolved, just disabled... - m!m + /wd4302 # Same as above - m!m + /wd4366 # The result of the unary '&' operator may be unaligned - m!m + $<$:/wd4101> # In release mode there are unreferenced variables because debug needs them ) target_compile_options(compiler INTERFACE ${WARNING_FLAGS}) diff --git a/cmake/util.cmake b/cmake/util.cmake index 010627a15d..cd9b47979e 100644 --- a/cmake/util.cmake +++ b/cmake/util.cmake @@ -128,12 +128,7 @@ macro(configure_cotire target) # add ignored paths for the precompiled header here set_target_properties(code PROPERTIES COTIRE_PREFIX_HEADER_IGNORE_PATH "${CMAKE_SOURCE_DIR};${CMAKE_BINARY_DIR}") - - IF(DEFINED CMAKE_CONFIGURATION_TYPES) - cotire(${target} CONFIGURATIONS ${CMAKE_CONFIGURATION_TYPES}) - ELSE(DEFINED CMAKE_CONFIGURATION_TYPES) - cotire(${target}) - ENDIF(DEFINED CMAKE_CONFIGURATION_TYPES) + cotire(${target}) ENDIF(COTIRE_ENABLE) endmacro(configure_cotire) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 507d5331e0..d79fff897d 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -38,9 +38,10 @@ IF (FSO_USE_SPEECH) target_link_libraries(code PUBLIC speech) ENDIF(FSO_USE_SPEECH) +TARGET_LINK_LIBRARIES(code PUBLIC jansson) + # Headers for standalone "gui" on UNIX IF(UNIX) - TARGET_LINK_LIBRARIES(code PUBLIC jansson) TARGET_LINK_LIBRARIES(code PUBLIC ${MONGOOSE_LIBS}) ENDIF(UNIX) diff --git a/code/ai/ai.h b/code/ai/ai.h index 0b4e62f5a8..e94c922571 100644 --- a/code/ai/ai.h +++ b/code/ai/ai.h @@ -228,10 +228,8 @@ typedef struct ai_class { int ai_chance_to_use_missiles_on_plr[NUM_SKILL_LEVELS]; float ai_max_aim_update_delay[NUM_SKILL_LEVELS]; float ai_turret_max_aim_update_delay[NUM_SKILL_LEVELS]; - int ai_profile_flags; //Holds the state of flags that are set - int ai_profile_flags_set; //Holds which flags are set and which are just left alone - int ai_profile_flags2; - int ai_profile_flags2_set; + flagset ai_profile_flags; //Holds the state of flags that are set + flagset ai_profile_flags_set; //Holds which flags are set and which are just left alone //SUSHI: These are optional overrides to an AI class to prevent the automatic scaling based on AI class index int ai_aburn_use_factor[NUM_SKILL_LEVELS]; @@ -461,8 +459,7 @@ typedef struct ai_info { int ai_chance_to_use_missiles_on_plr; float ai_max_aim_update_delay; float ai_turret_max_aim_update_delay; - int ai_profile_flags; //Holds AI_Profiles flags (possibly overriden by AI class) that actually apply to AI - int ai_profile_flags2; + flagset ai_profile_flags; //Holds AI_Profiles flags (possibly overriden by AI class) that actually apply to AI union { diff --git a/code/ai/ai_flags.h b/code/ai/ai_flags.h new file mode 100644 index 0000000000..389c3fdeda --- /dev/null +++ b/code/ai/ai_flags.h @@ -0,0 +1,121 @@ +#ifndef AI_FLAGS_H +#define AI_FLAGS_H + +#include "globalincs/flagset.h" + +namespace AI { + FLAG_LIST(AI_Flags) { + Formation_wing, // Fly in formation as part of wing. + Awaiting_repair, // Awaiting a repair ship. + Being_repaired, // Currently docked with repair ship. + Repairing, // Repairing a ship (or going to repair a ship) + Seek_lock, // set if should focus on gaining aspect lock, not hitting with lasers + Formation_object, // Fly in formation off a specific object. + Temporary_ignore, // Means current ignore_objnum is only temporary, not an order from the player. + Use_exit_path, // Used by path code, to flag path as an exit path + Use_static_path, // Used by path code, use fixed path, don't try to recreate + Target_collision, // Collided with aip->target_objnum last frame. Avoid that ship for half a second or so. + Unload_secondaries, // Fire secondaries as fast as possible! + On_subsys_path, // Current path leads to a subsystem + Avoid_shockwave_ship, // Avoid an existing shockwave from a ship. + Avoid_shockwave_weapon, // Avoid an expected shockwave from a weapon. shockwave_object field contains object index. + Avoid_shockwave_started, // Already started avoiding shockwave, don't keep deciding whether to avoid. + Attack_slowly, // Move slowly while attacking. + Repair_obstructed, // Ship wants to be repaired, but path is obstructed. + Kamikaze, // Crash into target + No_dynamic, // Not allowed to get dynamic goals + Avoiding_small_ship, // Avoiding a player ship. + Avoiding_big_ship, // Avoiding a large ship. + Big_ship_collide_recover_1, // Collided into a big ship. Recovering by flying away. + Big_ship_collide_recover_2, // Collided into a big ship. Fly towards big ship sphere perimeter. + Stealth_pursuit, // AI is trying to fight stealth ship + Unload_primaries, // Fire primaries as fast as possible! + Trying_unsuccessfully_to_warp, // Trying to warp, but can't warp at the moment + Free_afterburner_use, // Use afterburners while following waypoints or flying towards objects + + NUM_VALUES + }; + + FLAG_LIST(Goal_Flags) { + Docker_index_valid, // when set, index field for docker is valid + Dockee_index_valid, // when set, index field for dockee is valid + Goal_on_hold, // when set, this goal cannot currently be satisfied, although it could be in the future + Subsys_needs_fixup, // when set, the subsystem index (for a destroy subsystem goal) is invalid and must be gotten from the subsys name stored in docker.name field!! + Goal_override, // paired with AIG_TYPE_DYNAMIC to mean this goal overrides any other goal + Purge, // purge this goal next time we process + Goals_purged, // this goal has already caused other goals to get purged + Depart_sound_played,// Goober5000 - replacement for AL's hack ;) + Target_own_team, + + NUM_VALUES + }; + + FLAG_LIST(Override_Flags) { + Full, // Full sexp control + Roll, // Sexp forced roll maneuver + Pitch, // Sexp forced pitch change + Heading, // Sexp forced heading change + Full_lat, // full control over up/side/forward movement + Up, // vertical movement + Sideways, // horizontal movement + Forward, // forward movement + + NUM_VALUES + }; + + FLAG_LIST(Profile_Flags) { + Advanced_turret_fov_edge_checks, + Ai_aims_from_ship_center, + Ai_can_slow_down_attacking_big_ships, + Ai_guards_specific_ship_in_wing, + All_ships_manage_shields, + Allow_multi_event_scoring, + Allow_primary_link_at_start, + Allow_rapid_secondary_dumbfire, + Allow_turrets_target_weapons_freely, + Allow_vertical_dodge, + Aspect_invulnerability_fix, + Aspect_lock_countermeasure, + Assist_scoring_scales_with_damage, + Beams_damage_weapons, + Big_ships_can_attack_beam_turrets_on_untargeted_ships, + Disable_linked_fire_penalty, + Disable_weapon_damage_scaling, + Dont_insert_random_turret_fire_delay, + Fix_ai_class_bug, + Fix_ai_path_order_bug, + Fix_heat_seeker_stealth_bug, + Fix_linked_primary_bug, + Force_beam_turret_fov, + Glide_decay_requires_thrust, + Hack_improve_non_homing_swarm_turret_fire_accuracy, + Huge_turret_weapons_ignore_bombs, + Include_beams_in_stat_calcs, + Kill_scoring_scales_with_damage, + Multi_allow_empty_primaries, + Multi_allow_empty_secondaries, + Navigation_subsys_governs_warp, + No_min_dock_speed_cap, + No_special_player_avoid, + No_warp_camera, + Perform_fewer_scream_checks, + Player_weapon_scale_fix, + Prevent_targeting_bombs_beyond_range, + Require_turret_to_have_target_in_fov, + Shockwaves_damage_small_ship_subsystems, + Smart_afterburner_management, + Smart_primary_weapon_selection, + Smart_secondary_weapon_selection, + Smart_shield_management, + Smart_subsystem_targeting_for_turrets, + Strict_turred_tagged_only_targeting, + Turrets_ignore_target_radius, + Use_additive_weapon_velocity, + Use_newtonian_dampening, + Use_only_single_fov_for_turrets, + + NUM_VALUES + }; +} + +#endif \ No newline at end of file diff --git a/code/ai/ai_profiles.cpp b/code/ai/ai_profiles.cpp index 46e2ada57b..4e32ab602c 100644 --- a/code/ai/ai_profiles.cpp +++ b/code/ai/ai_profiles.cpp @@ -28,24 +28,13 @@ static char Default_profile_name[NAME_LENGTH]; // utility -void set_flag(ai_profile_t *profile, char *name, int flag, int type) +void set_flag(ai_profile_t *profile, const char *name, AI::Profile_Flags flag) { if (optional_string(name)) { bool val; stuff_boolean(&val); - - if (type == AIP_FLAG) { - if (val) - profile->flags |= flag; - else - profile->flags &= ~flag; - } else { - if (val) - profile->flags2 |= flag; - else - profile->flags2 &= ~flag; - } + profile->flags.set(flag, val); } } @@ -152,12 +141,12 @@ void parse_ai_profiles_tbl(const char *filename) // base profile, so zero it out if (profile == &Ai_profiles[0]) { - memset(profile, 0, sizeof(ai_profile_t)); + profile->reset(); } // brand new profile, so set it to the base defaults else { - memcpy(profile, &Ai_profiles[0], sizeof(ai_profile_t)); + *profile = Ai_profiles[0]; } } @@ -358,91 +347,91 @@ void parse_ai_profiles_tbl(const char *filename) if (optional_string("$Detail Distance Multiplier:")) parse_float_list(profile->detail_distance_mult, NUM_SKILL_LEVELS); - set_flag(profile, "$big ships can attack beam turrets on untargeted ships:", AIPF_BIG_SHIPS_CAN_ATTACK_BEAM_TURRETS_ON_UNTARGETED_SHIPS, AIP_FLAG); + set_flag(profile, "$big ships can attack beam turrets on untargeted ships:", AI::Profile_Flags::Big_ships_can_attack_beam_turrets_on_untargeted_ships); - set_flag(profile, "$smart primary weapon selection:", AIPF_SMART_PRIMARY_WEAPON_SELECTION, AIP_FLAG); + set_flag(profile, "$smart primary weapon selection:", AI::Profile_Flags::Smart_primary_weapon_selection); - set_flag(profile, "$smart secondary weapon selection:", AIPF_SMART_SECONDARY_WEAPON_SELECTION, AIP_FLAG); + set_flag(profile, "$smart secondary weapon selection:", AI::Profile_Flags::Smart_secondary_weapon_selection); - set_flag(profile, "$smart shield management:", AIPF_SMART_SHIELD_MANAGEMENT, AIP_FLAG); + set_flag(profile, "$smart shield management:", AI::Profile_Flags::Smart_shield_management); - set_flag(profile, "$smart afterburner management:", AIPF_SMART_AFTERBURNER_MANAGEMENT, AIP_FLAG); + set_flag(profile, "$smart afterburner management:", AI::Profile_Flags::Smart_afterburner_management); - set_flag(profile, "$allow rapid secondary dumbfire:", AIPF_ALLOW_RAPID_SECONDARY_DUMBFIRE, AIP_FLAG); + set_flag(profile, "$allow rapid secondary dumbfire:", AI::Profile_Flags::Allow_rapid_secondary_dumbfire); - set_flag(profile, "$huge turret weapons ignore bombs:", AIPF_HUGE_TURRET_WEAPONS_IGNORE_BOMBS, AIP_FLAG); + set_flag(profile, "$huge turret weapons ignore bombs:", AI::Profile_Flags::Huge_turret_weapons_ignore_bombs); - set_flag(profile, "$don't insert random turret fire delay:", AIPF_DONT_INSERT_RANDOM_TURRET_FIRE_DELAY, AIP_FLAG); + set_flag(profile, "$don't insert random turret fire delay:", AI::Profile_Flags::Dont_insert_random_turret_fire_delay); - set_flag(profile, "$hack improve non-homing swarm turret fire accuracy:", AIPF_HACK_IMPROVE_NON_HOMING_SWARM_TURRET_FIRE_ACCURACY, AIP_FLAG); + set_flag(profile, "$hack improve non-homing swarm turret fire accuracy:", AI::Profile_Flags::Hack_improve_non_homing_swarm_turret_fire_accuracy); - set_flag(profile, "$shockwaves damage small ship subsystems:", AIPF_SHOCKWAVES_DAMAGE_SMALL_SHIP_SUBSYSTEMS, AIP_FLAG); + set_flag(profile, "$shockwaves damage small ship subsystems:", AI::Profile_Flags::Shockwaves_damage_small_ship_subsystems); - set_flag(profile, "$navigation subsystem governs warpout capability:", AIPF_NAVIGATION_SUBSYS_GOVERNS_WARP, AIP_FLAG); + set_flag(profile, "$navigation subsystem governs warpout capability:", AI::Profile_Flags::Navigation_subsys_governs_warp); - set_flag(profile, "$ignore lower bound for minimum speed of docked ship:", AIPF_NO_MIN_DOCK_SPEED_CAP, AIP_FLAG); + 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:", AIPF_DISABLE_LINKED_FIRE_PENALTY, AIP_FLAG); + set_flag(profile, "$disable linked fire penalty:", AI::Profile_Flags::Disable_linked_fire_penalty); - set_flag(profile, "$disable weapon damage scaling:", AIPF_DISABLE_WEAPON_DAMAGE_SCALING, AIP_FLAG); + set_flag(profile, "$disable weapon damage scaling:", AI::Profile_Flags::Disable_weapon_damage_scaling); - set_flag(profile, "$use additive weapon velocity:", AIPF_USE_ADDITIVE_WEAPON_VELOCITY, AIP_FLAG); + set_flag(profile, "$use additive weapon velocity:", AI::Profile_Flags::Use_additive_weapon_velocity); - set_flag(profile, "$use newtonian dampening:", AIPF_USE_NEWTONIAN_DAMPENING, AIP_FLAG); + set_flag(profile, "$use newtonian dampening:", AI::Profile_Flags::Use_newtonian_dampening); - set_flag(profile, "$include beams for kills and assists:", AIPF_INCLUDE_BEAMS_IN_STAT_CALCS, AIP_FLAG); + set_flag(profile, "$include beams for kills and assists:", AI::Profile_Flags::Include_beams_in_stat_calcs); - set_flag(profile, "$score kills based on damage caused:", AIPF_KILL_SCORING_SCALES_WITH_DAMAGE, AIP_FLAG); + set_flag(profile, "$score kills based on damage caused:", AI::Profile_Flags::Kill_scoring_scales_with_damage); - set_flag(profile, "$score assists based on damage caused:", AIPF_ASSIST_SCORING_SCALES_WITH_DAMAGE, AIP_FLAG); + set_flag(profile, "$score assists based on damage caused:", AI::Profile_Flags::Assist_scoring_scales_with_damage); - set_flag(profile, "$allow event and goal scoring in multiplayer:", AIPF_ALLOW_MULTI_EVENT_SCORING, AIP_FLAG); + set_flag(profile, "$allow event and goal scoring in multiplayer:", AI::Profile_Flags::Allow_multi_event_scoring); - set_flag(profile, "$fix linked primary weapon decision bug:", AIPF_FIX_LINKED_PRIMARY_BUG, AIP_FLAG); + set_flag(profile, "$fix linked primary weapon decision bug:", AI::Profile_Flags::Fix_linked_primary_bug); - set_flag(profile, "$prevent turrets targeting too distant bombs:", AIPF_PREVENT_TARGETING_BOMBS_BEYOND_RANGE, AIP_FLAG); + 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:", AIPF_SMART_SUBSYSTEM_TARGETING_FOR_TURRETS, AIP_FLAG); + set_flag(profile, "$smart subsystem targeting for turrets:", AI::Profile_Flags::Smart_subsystem_targeting_for_turrets); - set_flag(profile, "$fix heat seekers homing on stealth ships bug:", AIPF_FIX_HEAT_SEEKER_STEALTH_BUG, AIP_FLAG); + set_flag(profile, "$fix heat seekers homing on stealth ships bug:", AI::Profile_Flags::Fix_heat_seeker_stealth_bug); - set_flag(profile, "$multi allow empty primaries:", AIPF_MULTI_ALLOW_EMPTY_PRIMARIES, AIP_FLAG); + set_flag(profile, "$multi allow empty primaries:", AI::Profile_Flags::Multi_allow_empty_primaries); - set_flag(profile, "$multi allow empty secondaries:", AIPF_MULTI_ALLOW_EMPTY_SECONDARIES, AIP_FLAG); + set_flag(profile, "$multi allow empty secondaries:", AI::Profile_Flags::Multi_allow_empty_secondaries); - set_flag(profile, "$allow turrets target weapons freely:", AIPF_ALLOW_TURRETS_TARGET_WEAPONS_FREELY, AIP_FLAG); + set_flag(profile, "$allow turrets target weapons freely:", AI::Profile_Flags::Allow_turrets_target_weapons_freely); - set_flag(profile, "$use only single fov for turrets:", AIPF_USE_ONLY_SINGLE_FOV_FOR_TURRETS, AIP_FLAG); + set_flag(profile, "$use only single fov for turrets:", AI::Profile_Flags::Use_only_single_fov_for_turrets); - set_flag(profile, "$allow vertical dodge:", AIPF_ALLOW_VERTICAL_DODGE, AIP_FLAG); + set_flag(profile, "$allow vertical dodge:", AI::Profile_Flags::Allow_vertical_dodge); - set_flag(profile, "$force beam turrets to use normal fov:", AIPF_FORCE_BEAM_TURRET_FOV, AIP_FLAG); + set_flag(profile, "$force beam turrets to use normal fov:", AI::Profile_Flags::Force_beam_turret_fov); - set_flag(profile, "$fix ai class bug:", AIPF_FIX_AI_CLASS_BUG, AIP_FLAG); + set_flag(profile, "$fix ai class bug:", AI::Profile_Flags::Fix_ai_class_bug); - set_flag(profile, "$turrets ignore targets radius in range checks:", AIPF2_TURRETS_IGNORE_TARGET_RADIUS, AIP_FLAG2); + set_flag(profile, "$turrets ignore targets radius in range checks:", AI::Profile_Flags::Turrets_ignore_target_radius); - set_flag(profile, "$no extra collision avoidance vs player:", AIPF2_NO_SPECIAL_PLAYER_AVOID, AIP_FLAG2); + set_flag(profile, "$no extra collision avoidance vs player:", AI::Profile_Flags::No_special_player_avoid); - set_flag(profile, "$perform fewer checks for death screams:", AIPF2_PERFORM_FEWER_SCREAM_CHECKS, AIP_FLAG2); + set_flag(profile, "$perform fewer checks for death screams:", AI::Profile_Flags::Perform_fewer_scream_checks); - set_flag(profile, "$advanced turret fov edge checks:", AIPF2_ADVANCED_TURRET_FOV_EDGE_CHECKS, AIP_FLAG2); + set_flag(profile, "$advanced turret fov edge checks:", AI::Profile_Flags::Advanced_turret_fov_edge_checks); - set_flag(profile, "$require turrets to have target in fov:", AIPF2_REQUIRE_TURRET_TO_HAVE_TARGET_IN_FOV, AIP_FLAG2); + set_flag(profile, "$require turrets to have target in fov:", AI::Profile_Flags::Require_turret_to_have_target_in_fov); - set_flag(profile, "$all ships manage shields:", AIPF2_ALL_SHIPS_MANAGE_SHIELDS, AIP_FLAG2); + set_flag(profile, "$all ships manage shields:", AI::Profile_Flags::All_ships_manage_shields); - set_flag(profile, "$ai aims from ship center:", AIPF2_AI_AIMS_FROM_SHIP_CENTER, AIP_FLAG2); + set_flag(profile, "$ai aims from ship center:", AI::Profile_Flags::Ai_aims_from_ship_center); - set_flag(profile, "$allow primary link at mission start:", AIPF2_ALLOW_PRIMARY_LINK_AT_START, AIP_FLAG2); + set_flag(profile, "$allow primary link at mission start:", AI::Profile_Flags::Allow_primary_link_at_start); - set_flag(profile, "$allow beams to damage bombs:", AIPF2_BEAMS_DAMAGE_WEAPONS, AIP_FLAG2); + set_flag(profile, "$allow beams to damage bombs:", AI::Profile_Flags::Beams_damage_weapons); - set_flag(profile, "$disable weapon damage scaling for player:", AIPF2_PLAYER_WEAPON_SCALE_FIX, AIP_FLAG2); + set_flag(profile, "$disable weapon damage scaling for player:", AI::Profile_Flags::Player_weapon_scale_fix); - set_flag(profile, "$countermeasures affect aspect seekers:", AIPF2_ASPECT_LOCK_COUNTERMEASURE, AIP_FLAG2); + set_flag(profile, "$countermeasures affect aspect seekers:", AI::Profile_Flags::Aspect_lock_countermeasure); - set_flag(profile, "$ai guards specific ship in wing:", AIPF2_AI_GUARDS_SPECIFIC_SHIP_IN_WING, AIP_FLAG2); + set_flag(profile, "$ai guards specific ship in wing:", AI::Profile_Flags::Ai_guards_specific_ship_in_wing); profile->ai_path_mode = AI_PATH_MODE_NORMAL; if (optional_string("$ai path mode:")) @@ -457,17 +446,17 @@ void parse_ai_profiles_tbl(const char *filename) } } - set_flag(profile, "$no warp camera:", AIPF2_NO_WARP_CAMERA, AIP_FLAG2); + set_flag(profile, "$no warp camera:", AI::Profile_Flags::No_warp_camera); - set_flag(profile, "$fix ai path order bug:", AIPF2_FIX_AI_PATH_ORDER_BUG, AIP_FLAG2); + set_flag(profile, "$fix ai path order bug:", AI::Profile_Flags::Fix_ai_path_order_bug); - set_flag(profile, "$strict turret-tagged-only targeting:", AIPF2_STRICT_TURRET_TAGGED_ONLY_TARGETING, AIP_FLAG2); + set_flag(profile, "$strict turret-tagged-only targeting:", AI::Profile_Flags::Strict_turred_tagged_only_targeting); - set_flag(profile, "$aspect bomb invulnerability fix:", AIPF2_ASPECT_INVULNERABILITY_FIX, AIP_FLAG2); + set_flag(profile, "$aspect bomb invulnerability fix:", AI::Profile_Flags::Aspect_invulnerability_fix); - set_flag(profile, "$glide decay requires thrust:", AIPF2_GLIDE_DECAY_REQUIRES_THRUST, AIP_FLAG2); + set_flag(profile, "$glide decay requires thrust:", AI::Profile_Flags::Glide_decay_requires_thrust); - set_flag(profile, "$ai can slow down when attacking big ships:", AIPF2_AI_CAN_SLOW_DOWN_ATTACKING_BIG_SHIPS, AIP_FLAG2); + set_flag(profile, "$ai can slow down when attacking big ships:", AI::Profile_Flags::Ai_can_slow_down_attacking_big_ships); profile->bay_arrive_speed_mult = 1.0f; profile->bay_depart_speed_mult = 1.0f; @@ -486,20 +475,14 @@ void parse_ai_profiles_tbl(const char *filename) mprintf(("Warning: \"$perform less checks for death screams\" flag is deprecated in favor of \"$perform fewer checks for death screams\"\n")); bool temp; stuff_boolean(&temp); - if (temp) - profile->flags2 |= AIPF2_PERFORM_FEWER_SCREAM_CHECKS; - else - profile->flags2 &= ~AIPF2_PERFORM_FEWER_SCREAM_CHECKS; + profile->flags.set(AI::Profile_Flags::Perform_fewer_scream_checks, temp); } if (optional_string("$allow primary link delay:")) { mprintf(("Warning: \"$allow primary link delay\" flag is deprecated in favor of \"$allow primary link at mission start\"\n")); bool temp; stuff_boolean(&temp); - if (temp) - profile->flags2 &= ~AIPF2_ALLOW_PRIMARY_LINK_AT_START; - else - profile->flags2 |= AIPF2_ALLOW_PRIMARY_LINK_AT_START; + profile->flags.set(AI::Profile_Flags::Allow_primary_link_at_start, !temp); } @@ -570,3 +553,69 @@ int ai_profile_lookup(char *name) return -1; } + +void ai_profile_t::reset() +{ + memset(profile_name, 0, sizeof(profile_name)); + + flags.reset(); + + ai_path_mode = 0; + bay_arrive_speed_mult = 0; + bay_depart_speed_mult = 0; + + for (int i = 0; i < NUM_SKILL_LEVELS; ++i) { + max_incoming_asteroids[i] = 0; + max_allowed_player_homers[i] = 0; + max_attackers[i] = 0; + predict_position_delay[i] = 0; + in_range_time[i] = 0; + shield_manage_delay[i] = 0; + + link_energy_levels_always[i] = 0; + link_energy_levels_maybe[i] = 0; + + link_ammo_levels_always[i] = 0; + link_ammo_levels_maybe[i] = 0; + primary_ammo_burst_mult[i] = 0; + + cmeasure_life_scale[i] = 0; + cmeasure_fire_chance[i] = 0; + weapon_energy_scale[i] = 0; + shield_energy_scale[i] = 0; + afterburner_recharge_scale[i] = 0; + player_damage_scale[i] = 0; + + subsys_damage_scale[i] = 0; + beam_friendly_damage_cap[i] = 0; + turn_time_scale[i] = 0; + glide_attack_percent[i] = 0; + circle_strafe_percent[i] = 0; + glide_strafe_percent[i] = 0; + random_sidethrust_percent[i] = 0; + stalemate_time_thresh[i] = 0; + stalemate_dist_thresh[i] = 0; + max_aim_update_delay[i] = 0; + turret_max_aim_update_delay[i] = 0; + + ship_fire_delay_scale_hostile[i] = 0; + ship_fire_delay_scale_friendly[i] = 0; + + ship_fire_secondary_delay_scale_hostile[i] = 0; + ship_fire_secondary_delay_scale_friendly[i] = 0; + + max_turret_ownage_target[i] = 0; + max_turret_ownage_player[i] = 0; + + kill_percentage_scale[i] = 0; + assist_percentage_scale[i] = 0; + + assist_award_percentage_scale[i] = 0; + + repair_penalty[i] = 0; + delay_bomb_arm_timer[i] = 0; + chance_to_use_missiles_on_plr[i] = 0; + player_autoaim_fov[i] = 0; + detail_distance_mult[i] = 0; + } +} diff --git a/code/ai/ai_profiles.h b/code/ai/ai_profiles.h index ba712399fa..27f14fd465 100644 --- a/code/ai/ai_profiles.h +++ b/code/ai/ai_profiles.h @@ -12,6 +12,7 @@ #include "globalincs/globals.h" #include "globalincs/pstypes.h" #include "globalincs/systemvars.h" +#include "ai/ai_flags.h" // flag int defines #define AIP_FLAG 1 @@ -76,12 +77,11 @@ #define MAX_AI_PROFILES 5 -typedef struct ai_profile_t { - +class ai_profile_t { +public: char profile_name[NAME_LENGTH]; - int flags; - int flags2; + flagset flags; // difficulty-related values int max_incoming_asteroids[NUM_SKILL_LEVELS]; // max number of asteroids thrown at friendlies @@ -159,7 +159,8 @@ typedef struct ai_profile_t { float bay_arrive_speed_mult; float bay_depart_speed_mult; -} ai_profile_t; + void reset(); +}; extern int Num_ai_profiles; diff --git a/code/ai/aibig.cpp b/code/ai/aibig.cpp index bb1959725d..16f99d7a61 100644 --- a/code/ai/aibig.cpp +++ b/code/ai/aibig.cpp @@ -786,13 +786,13 @@ void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy, vec3d *f int current_bank_adjusted = MAX_SHIP_PRIMARY_BANKS + current_bank; - if ((aip->ai_flags & AIF_UNLOAD_SECONDARIES) || (swip->burst_flags & WBF_FAST_FIRING)) { + if ((aip->ai_flags & AIF_UNLOAD_SECONDARIES) || (swip->burst_flags[Weapon::Burst_Flags::Fast_firing])) { if (swip->burst_shots > swp->burst_counter[current_bank_adjusted]) { t = swip->burst_delay; swp->burst_counter[current_bank_adjusted]++; } else { t = swip->fire_wait; - if ((swip->burst_shots > 0) && (swip->burst_flags & WBF_RANDOM_LENGTH)) { + if ((swip->burst_shots > 0) && (swip->burst_flags[Weapon::Burst_Flags::Random_length])) { swp->burst_counter[current_bank_adjusted] = myrand() % swip->burst_shots; } else { swp->burst_counter[current_bank_adjusted] = 0; @@ -804,7 +804,7 @@ void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy, vec3d *f swp->burst_counter[current_bank_adjusted]++; } else { t = set_secondary_fire_delay(aip, temp_shipp, swip, false); - if ((swip->burst_shots > 0) && (swip->burst_flags & WBF_RANDOM_LENGTH)) { + if ((swip->burst_shots > 0) && (swip->burst_flags[Weapon::Burst_Flags::Random_length])) { swp->burst_counter[current_bank_adjusted] = myrand() % swip->burst_shots; } else { swp->burst_counter[current_bank_adjusted] = 0; @@ -1206,7 +1206,7 @@ void ai_big_attack_get_data(vec3d *enemy_pos, float *dist_to_enemy, float *dot_t float weapon_speed; // Compute position of gun in absolute space and use that as fire position. - if (po->n_guns > 0 && !(The_mission.ai_profile->flags2 & AIPF2_AI_AIMS_FROM_SHIP_CENTER)) { + if (po->n_guns > 0 && !(The_mission.ai_profile->flags[AI::Profile_Flags::Ai_aims_from_ship_center])) { pnt = po->gun_banks[0].pnt[0]; vm_vec_unrotate(&gun_pos, &pnt, &Pl_objp->orient); vm_vec_add2(&gun_pos, &Pl_objp->pos); @@ -1351,7 +1351,7 @@ void ai_big_strafe_attack() turn_towards_point(Pl_objp, &target_pos, NULL, 0.0f); fix last_hit = Missiontime - aip->last_hit_time; - if ( aip->ai_profile_flags2 & AIPF2_AI_CAN_SLOW_DOWN_ATTACKING_BIG_SHIPS ) { + if ( aip->ai_profile_flags[AI::Profile_Flags::Ai_can_slow_down_attacking_big_ships] ) { // Slow down if we've not been hit for a while if ( target_dist > 1200 || last_hit < F1_0*6) { accel = 1.0f; @@ -1809,7 +1809,7 @@ void ai_big_strafe_maybe_attack_turret(object *ship_objp, object *weapon_objp) // the ai will not always go after different ships firing beams at them. // Approx 1/4 chance we'll go after the other ship's beam. - bool attack_turret_on_different_ship = (aip->ai_profile_flags & AIPF_BIG_SHIPS_CAN_ATTACK_BEAM_TURRETS_ON_UNTARGETED_SHIPS) + bool attack_turret_on_different_ship = (aip->ai_profile_flags[AI::Profile_Flags::Big_ships_can_attack_beam_turrets_on_untargeted_ships]) && (Weapon_info[Weapons[weapon_objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Beam]) && (frand()*100 < 25.0f); // unless we're making an exception, we should only attack a turret if it sits on the current target diff --git a/code/ai/aicode.cpp b/code/ai/aicode.cpp index f4b7df380c..bf5ce1b4ce 100644 --- a/code/ai/aicode.cpp +++ b/code/ai/aicode.cpp @@ -555,10 +555,8 @@ void init_ai_class(ai_class *aicp) aicp->ai_max_aim_update_delay[i] = FLT_MIN; aicp->ai_turret_max_aim_update_delay[i] = FLT_MIN; } - aicp->ai_profile_flags = 0; - aicp->ai_profile_flags_set = 0; - aicp->ai_profile_flags2 = 0; - aicp->ai_profile_flags2_set = 0; + aicp->ai_profile_flags.reset(); + aicp->ai_profile_flags_set.reset(); //AI Class autoscale overrides //INT_MIN and FLT_MIN represent the "not set" state @@ -572,25 +570,22 @@ void init_ai_class(ai_class *aicp) aicp->ai_class_autoscale = true; //Retail behavior is to do the stupid autoscaling } -void set_aic_flag(ai_class *aicp, char *name, int flag, int type) +void set_aic_flag(ai_class *aicp, char *name, AI::Profile_Flags flag) { - int* flags = (type == AIP_FLAG) ? &(aicp->ai_profile_flags) : &(aicp->ai_profile_flags2); - int* set = (type == AIP_FLAG) ? &(aicp->ai_profile_flags_set) : &(aicp->ai_profile_flags2_set); + auto flags = &(aicp->ai_profile_flags); + auto set = &(aicp->ai_profile_flags_set); if (optional_string(name)) { bool val; stuff_boolean(&val); - if (val) - *flags |= flag; - else - *flags &= ~flag; + flags->set(flag, val); - *set |= flag; - } + set->set(flag); + } else - *set &= ~flag; + set->remove(flag); } void parse_ai_class() @@ -740,35 +735,35 @@ void parse_ai_class() if (optional_string("$Turret Max Aim Update Delay:")) parse_float_list(aicp->ai_turret_max_aim_update_delay, NUM_SKILL_LEVELS); - set_aic_flag(aicp, "$big ships can attack beam turrets on untargeted ships:", AIPF_BIG_SHIPS_CAN_ATTACK_BEAM_TURRETS_ON_UNTARGETED_SHIPS, AIP_FLAG); + set_aic_flag(aicp, "$big ships can attack beam turrets on untargeted ships:", AI::Profile_Flags::Big_ships_can_attack_beam_turrets_on_untargeted_ships); - set_aic_flag(aicp, "$smart primary weapon selection:", AIPF_SMART_PRIMARY_WEAPON_SELECTION, AIP_FLAG); + set_aic_flag(aicp, "$smart primary weapon selection:", AI::Profile_Flags::Smart_primary_weapon_selection); - set_aic_flag(aicp, "$smart secondary weapon selection:", AIPF_SMART_SECONDARY_WEAPON_SELECTION, AIP_FLAG); + set_aic_flag(aicp, "$smart secondary weapon selection:", AI::Profile_Flags::Smart_secondary_weapon_selection); - set_aic_flag(aicp, "$smart shield management:", AIPF_SMART_SHIELD_MANAGEMENT, AIP_FLAG); + set_aic_flag(aicp, "$smart shield management:", AI::Profile_Flags::Smart_shield_management); - set_aic_flag(aicp, "$smart afterburner management:", AIPF_SMART_AFTERBURNER_MANAGEMENT, AIP_FLAG); + set_aic_flag(aicp, "$smart afterburner management:", AI::Profile_Flags::Smart_afterburner_management); - set_aic_flag(aicp, "$allow rapid secondary dumbfire:", AIPF_ALLOW_RAPID_SECONDARY_DUMBFIRE, AIP_FLAG); + set_aic_flag(aicp, "$allow rapid secondary dumbfire:", AI::Profile_Flags::Allow_rapid_secondary_dumbfire); - set_aic_flag(aicp, "$huge turret weapons ignore bombs:", AIPF_HUGE_TURRET_WEAPONS_IGNORE_BOMBS, AIP_FLAG); + set_aic_flag(aicp, "$huge turret weapons ignore bombs:", AI::Profile_Flags::Huge_turret_weapons_ignore_bombs); - set_aic_flag(aicp, "$don't insert random turret fire delay:", AIPF_DONT_INSERT_RANDOM_TURRET_FIRE_DELAY, AIP_FLAG); + set_aic_flag(aicp, "$don't insert random turret fire delay:", AI::Profile_Flags::Dont_insert_random_turret_fire_delay); - set_aic_flag(aicp, "$prevent turrets targeting too distant bombs:", AIPF_PREVENT_TARGETING_BOMBS_BEYOND_RANGE, AIP_FLAG); + set_aic_flag(aicp, "$prevent turrets targeting too distant bombs:", AI::Profile_Flags::Prevent_targeting_bombs_beyond_range); - set_aic_flag(aicp, "$smart subsystem targeting for turrets:", AIPF_SMART_SUBSYSTEM_TARGETING_FOR_TURRETS, AIP_FLAG); + set_aic_flag(aicp, "$smart subsystem targeting for turrets:", AI::Profile_Flags::Smart_subsystem_targeting_for_turrets); - set_aic_flag(aicp, "$allow turrets target weapons freely:", AIPF_ALLOW_TURRETS_TARGET_WEAPONS_FREELY, AIP_FLAG); + set_aic_flag(aicp, "$allow turrets target weapons freely:", AI::Profile_Flags::Allow_turrets_target_weapons_freely); - set_aic_flag(aicp, "$allow vertical dodge:", AIPF_ALLOW_VERTICAL_DODGE, AIP_FLAG); + set_aic_flag(aicp, "$allow vertical dodge:", AI::Profile_Flags::Allow_vertical_dodge); - set_aic_flag(aicp, "$no extra collision avoidance vs player:", AIPF2_NO_SPECIAL_PLAYER_AVOID, AIP_FLAG2); + set_aic_flag(aicp, "$no extra collision avoidance vs player:", AI::Profile_Flags::No_special_player_avoid); - set_aic_flag(aicp, "$all ships manage shields:", AIPF2_ALL_SHIPS_MANAGE_SHIELDS, AIP_FLAG2); + set_aic_flag(aicp, "$all ships manage shields:", AI::Profile_Flags::All_ships_manage_shields); - set_aic_flag(aicp, "$ai can slow down when attacking big ships:", AIPF2_AI_CAN_SLOW_DOWN_ATTACKING_BIG_SHIPS, AIP_FLAG2); + set_aic_flag(aicp, "$ai can slow down when attacking big ships:", AI::Profile_Flags::Ai_can_slow_down_attacking_big_ships); } void reset_ai_class_names() @@ -1354,7 +1349,7 @@ void adjust_accel_for_docking(ai_info *aip) float ratio = objp->phys_info.mass / dock_calc_total_docked_mass(objp); // put cap on how much ship can slow down - if ( (ratio < 0.8f) && !(The_mission.ai_profile->flags & AIPF_NO_MIN_DOCK_SPEED_CAP) ) { + if ( (ratio < 0.8f) && !(The_mission.ai_profile->flags[AI::Profile_Flags::No_min_dock_speed_cap]) ) { ratio = 0.8f; } @@ -4995,7 +4990,7 @@ void evade_weapon() rdot = vm_vec_dot(&Pl_objp->orient.vec.rvec, &vec_from_enemy); udot = vm_vec_dot(&Pl_objp->orient.vec.uvec, &vec_from_enemy); - if (aip->ai_profile_flags & AIPF_ALLOW_VERTICAL_DODGE && fl_abs(udot) > fl_abs(rdot)) + if (aip->ai_profile_flags[AI::Profile_Flags::Allow_vertical_dodge] && fl_abs(udot) > fl_abs(rdot)) { if ((udot < -0.5f) || (udot > 0.5f)) vm_vec_scale_add(&goal_point, &Pl_objp->pos, &Pl_objp->orient.vec.uvec, -200.0f); @@ -5119,7 +5114,7 @@ void evade_ship() if (percent_left > 30.0f + ((OBJ_INDEX(Pl_objp)) & 0x0f)) { afterburners_start(Pl_objp); - if (aip->ai_profile_flags & AIPF_SMART_AFTERBURNER_MANAGEMENT) { + if (aip->ai_profile_flags[AI::Profile_Flags::Smart_afterburner_management]) { aip->afterburner_stop_time = (fix) (Missiontime + F1_0 + static_randf(OBJ_INDEX(Pl_objp)) * F1_0 / 4); } else { aip->afterburner_stop_time = Missiontime + F1_0 + static_rand(OBJ_INDEX(Pl_objp))/4; @@ -5315,7 +5310,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, Weapon::Info_Flag } //not using the new AI, use the old version of this function instead. - if (!(Ai_info[shipp->ai_index].ai_profile_flags & AIPF_SMART_PRIMARY_WEAPON_SELECTION)) + if (!(Ai_info[shipp->ai_index].ai_profile_flags[AI::Profile_Flags::Smart_primary_weapon_selection])) { return ai_select_primary_weapon_OLD(objp, other_objp, flags); } @@ -5506,11 +5501,6 @@ void set_primary_weapon_linkage(object *objp) ai_info *aip; ship_weapon *swp; weapon_info *wip; - - int total_ammo; - int current_ammo; - float ammo_pct; - int i; shipp = &Ships[objp->instance]; sip = &Ship_info[shipp->ship_info_index]; @@ -5555,7 +5545,7 @@ void set_primary_weapon_linkage(object *objp) } // Don't want all ships always linking weapons at start, so asynchronize. - if (!(The_mission.ai_profile->flags2 & AIPF2_ALLOW_PRIMARY_LINK_AT_START)) + if (!(The_mission.ai_profile->flags[AI::Profile_Flags::Allow_primary_link_at_start])) { if (Missiontime < i2f(30)) return; @@ -5569,7 +5559,7 @@ void set_primary_weapon_linkage(object *objp) // get energy level float energy; - if (The_mission.ai_profile->flags & AIPF_FIX_LINKED_PRIMARY_BUG) { + if (The_mission.ai_profile->flags[AI::Profile_Flags::Fix_linked_primary_bug]) { energy = shipp->weapon_energy / sip->max_weapon_reserve * 100.0f; } else { energy = shipp->weapon_energy; @@ -5585,29 +5575,31 @@ void set_primary_weapon_linkage(object *objp) } // also check ballistics - Goober5000 - if (sip->flags[Ship::Info_Flags::Ballistic_primaries]) + int total_ammo = 0; + int current_ammo = 0; + bool all_ballistic = true; + + // count ammo, and do not continue unless all weapons are ballistic + for (int i = 0; i < swp->num_primary_banks; i++) { - total_ammo = 0; - current_ammo = 0; + wip = &Weapon_info[swp->primary_bank_weapons[i]]; - // count ammo, and do not continue unless all weapons are ballistic - for (i = 0; i < swp->num_primary_banks; i++) + if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) { - wip = &Weapon_info[swp->primary_bank_weapons[i]]; - - if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) - { - total_ammo += swp->primary_bank_start_ammo[i]; - current_ammo += swp->primary_bank_ammo[i]; - } - else - { - return; - } + total_ammo += swp->primary_bank_start_ammo[i]; + current_ammo += swp->primary_bank_ammo[i]; } + else + { + all_ballistic = false; + break; + } + } + if (all_ballistic) + { Assert(total_ammo); // Goober5000: div-0 check - ammo_pct = float (current_ammo) / float (total_ammo) * 100.0f; + float ammo_pct = float (current_ammo) / float (total_ammo) * 100.0f; // link according to defined levels if (ammo_pct > aip->ai_link_ammo_levels_always) @@ -5616,7 +5608,7 @@ void set_primary_weapon_linkage(object *objp) } else if (ammo_pct > aip->ai_link_ammo_levels_maybe) { - if (objp->hull_strength < shipp->ship_max_hull_strength/3.0f) + if (objp->hull_strength < shipp->ship_max_hull_strength / 3.0f) { shipp->flags.set(Ship::Ship_Flags::Primary_linked); } @@ -5850,7 +5842,7 @@ void ai_select_secondary_weapon(object *objp, ship_weapon *swp, flagsetai_profile_flags & AIPF_SMART_SECONDARY_WEAPON_SELECTION) && (prio1.none_set())) { + if ((aip->ai_profile_flags[AI::Profile_Flags::Smart_secondary_weapon_selection]) && (prio1.none_set())) { ignore_mask.set(Weapon::Info_Flags::Homing_aspect).set(Weapon::Info_Flags::Homing_heat).set(Weapon::Info_Flags::Homing_javelin); } @@ -5858,7 +5850,7 @@ void ai_select_secondary_weapon(object *objp, ship_weapon *swp, flagsetsecondary_bank_weapons[weapon_bank_list[i]]].wi_flags; - auto ignore_mask_to_use = ((aip->ai_profile_flags & AIPF_SMART_SECONDARY_WEAPON_SELECTION) && (wi_flags[Weapon::Info_Flags::Bomber_plus])) ? (ignore_mask - Weapon::Info_Flags::Huge) : ignore_mask; + auto ignore_mask_to_use = ((aip->ai_profile_flags[AI::Profile_Flags::Smart_secondary_weapon_selection]) && (wi_flags[Weapon::Info_Flags::Bomber_plus])) ? (ignore_mask - Weapon::Info_Flags::Huge) : ignore_mask; if (!(wi_flags & ignore_mask_to_use).any_set()) { // Maybe bombs are illegal. if ((wi_flags & prio1).any_set()) { @@ -5870,7 +5862,7 @@ void ai_select_secondary_weapon(object *objp, ship_weapon *swp, flagsetai_profile_flags & AIPF_SMART_SECONDARY_WEAPON_SELECTION) && (prio2.none_set())) { + if ((aip->ai_profile_flags[AI::Profile_Flags::Smart_secondary_weapon_selection]) && (prio2.none_set())) { ignore_mask.set(Weapon::Info_Flags::Homing_aspect).set(Weapon::Info_Flags::Homing_heat).set(Weapon::Info_Flags::Homing_javelin); } @@ -5880,7 +5872,7 @@ void ai_select_secondary_weapon(object *objp, ship_weapon *swp, flagsetsecondary_bank_weapons[weapon_bank_list[i]]].wi_flags; - auto ignore_mask_to_use = ((aip->ai_profile_flags & AIPF_SMART_SECONDARY_WEAPON_SELECTION) && (wi_flags[Weapon::Info_Flags::Bomber_plus])) ? (ignore_mask - Weapon::Info_Flags::Huge) : ignore_mask; + auto ignore_mask_to_use = ((aip->ai_profile_flags[AI::Profile_Flags::Smart_secondary_weapon_selection]) && (wi_flags[Weapon::Info_Flags::Bomber_plus])) ? (ignore_mask - Weapon::Info_Flags::Huge) : ignore_mask; if (!(wi_flags & ignore_mask_to_use).any_set()) { // Maybe bombs are illegal. if (swp->secondary_bank_ammo[weapon_bank_list[i]] > 0) { @@ -5904,7 +5896,7 @@ void ai_select_secondary_weapon(object *objp, ship_weapon *swp, flagsetsecondary_bank_weapons[swp->current_secondary_bank]]; // phreak -- rapid dumbfire? let it rip! - if ((aip->ai_profile_flags & AIPF_ALLOW_RAPID_SECONDARY_DUMBFIRE) && !(wip->is_homing()) && (wip->fire_wait < .5f)) + if ((aip->ai_profile_flags[AI::Profile_Flags::Allow_rapid_secondary_dumbfire]) && !(wip->is_homing()) && (wip->fire_wait < .5f)) { aip->ai_flags |= AIF_UNLOAD_SECONDARIES; } @@ -6407,7 +6399,7 @@ void set_predicted_enemy_pos(vec3d *predicted_enemy_pos, object *pobjp, vec3d *e wip = ai_get_weapon(&shipp->weapons); target_moving_direction = *enemy_vel; - if (wip != NULL && The_mission.ai_profile->flags & AIPF_USE_ADDITIVE_WEAPON_VELOCITY) + if (wip != NULL && The_mission.ai_profile->flags[AI::Profile_Flags::Use_additive_weapon_velocity]) vm_vec_scale_sub2(&target_moving_direction, &pobjp->phys_info.vel, wip->vel_inherit_amount); if (wip != NULL) @@ -6439,7 +6431,7 @@ void set_predicted_enemy_pos(vec3d *predicted_enemy_pos, object *pobjp, vec3d *e // Compute position of gun in absolute space and use that as fire position // ...unless we want to just use the ship center - if(pm->gun_banks != NULL && !(The_mission.ai_profile->flags2 & AIPF2_AI_AIMS_FROM_SHIP_CENTER)){ + if(pm->gun_banks != NULL && !(The_mission.ai_profile->flags[AI::Profile_Flags::Ai_aims_from_ship_center])){ pnt = pm->gun_banks[0].pnt[0]; } else { //Use the convergence offset, if there is one @@ -6697,7 +6689,7 @@ void attack_set_accel(ai_info *aip, ship_info *sip, float dist_to_enemy, float d percent_left = 100.0f * shipp->afterburner_fuel / sip_local->afterburner_fuel_capacity; if (percent_left > 30.0f + ((OBJ_INDEX(Pl_objp)) & 0x0f)) { afterburners_start(Pl_objp); - if (aip->ai_profile_flags & AIPF_SMART_AFTERBURNER_MANAGEMENT) { + if (aip->ai_profile_flags[AI::Profile_Flags::Smart_afterburner_management]) { float max_ab_vel; float time_to_exhaust_25pct_fuel; float time_to_fly_75pct_of_distance; @@ -7230,7 +7222,7 @@ void ai_chase_attack(ai_info *aip, ship_info *sip, vec3d *predicted_enemy_pos, f float dot_to_enemy, dot_from_enemy; float bank_override = 0.0f; - if (!(aip->ai_profile_flags2 & AIPF2_NO_SPECIAL_PLAYER_AVOID) && avoid_player(Pl_objp, predicted_enemy_pos)) + if (!(aip->ai_profile_flags[AI::Profile_Flags::No_special_player_avoid]) && avoid_player(Pl_objp, predicted_enemy_pos)) return; compute_dots(Pl_objp, En_objp, &dot_to_enemy, &dot_from_enemy); @@ -7548,7 +7540,7 @@ void ai_set_guard_object(object *objp, object *other_objp) // If ship to guard is in a wing, guard that whole wing, unless the appropriate flag has been set ai_info *other_aip = &Ai_info[Ships[other_objp->instance].ai_index]; - if ((other_aip->wing != -1) && (other_aip->wing != aip->wing) && !(The_mission.ai_profile->flags2 & AIPF2_AI_GUARDS_SPECIFIC_SHIP_IN_WING)) { + if ((other_aip->wing != -1) && (other_aip->wing != aip->wing) && !(The_mission.ai_profile->flags[AI::Profile_Flags::Ai_guards_specific_ship_in_wing])) { ai_set_guard_wing(objp, Ai_info[Ships[other_objp->instance].ai_index].wing); } else { @@ -7743,7 +7735,7 @@ void ai_choose_secondary_weapon(object *objp, ai_info *aip, object *en_objp) if (is_big_ship) { wif_priority1.set(Weapon::Info_Flags::Huge); - if (aip->ai_profile_flags & AIPF_SMART_SECONDARY_WEAPON_SELECTION) { + if (aip->ai_profile_flags[AI::Profile_Flags::Smart_secondary_weapon_selection]) { wif_priority2.set(Weapon::Info_Flags::Bomber_plus); } else { @@ -7760,7 +7752,7 @@ void ai_choose_secondary_weapon(object *objp, ai_info *aip, object *en_objp) wif_priority1.set(Weapon::Info_Flags::Puncture); wif_priority2.set(Weapon::Info_Flags::Homing_aspect).set(Weapon::Info_Flags::Homing_heat).set(Weapon::Info_Flags::Homing_javelin); } - else if ((aip->ai_profile_flags & AIPF_SMART_SECONDARY_WEAPON_SELECTION) && (en_objp->type == OBJ_ASTEROID)) //prefer dumbfires if its an asteroid + else if ((aip->ai_profile_flags[AI::Profile_Flags::Smart_secondary_weapon_selection]) && (en_objp->type == OBJ_ASTEROID)) //prefer dumbfires if its an asteroid { wif_priority1.reset(); wif_priority2.reset(); @@ -8842,13 +8834,13 @@ void ai_chase() float t; int current_bank_adjusted = MAX_SHIP_PRIMARY_BANKS + current_bank; - if ((aip->ai_flags & AIF_UNLOAD_SECONDARIES) || (swip->burst_flags & WBF_FAST_FIRING)) { + if ((aip->ai_flags & AIF_UNLOAD_SECONDARIES) || (swip->burst_flags[Weapon::Burst_Flags::Fast_firing])) { if (swip->burst_shots > swp->burst_counter[current_bank_adjusted]) { t = swip->burst_delay; swp->burst_counter[current_bank_adjusted]++; } else { t = swip->fire_wait; - if ((swip->burst_shots > 0) && (swip->burst_flags & WBF_RANDOM_LENGTH)) { + if ((swip->burst_shots > 0) && (swip->burst_flags[Weapon::Burst_Flags::Random_length])) { swp->burst_counter[current_bank_adjusted] = myrand() % swip->burst_shots; } else { swp->burst_counter[current_bank_adjusted] = 0; @@ -8860,7 +8852,7 @@ void ai_chase() swp->burst_counter[current_bank_adjusted]++; } else { t = set_secondary_fire_delay(aip, temp_shipp, swip, false); - if ((swip->burst_shots > 0) && (swip->burst_flags & WBF_RANDOM_LENGTH)) { + if ((swip->burst_shots > 0) && (swip->burst_flags[Weapon::Burst_Flags::Random_length])) { swp->burst_counter[current_bank_adjusted] = myrand() % swip->burst_shots; } else { swp->burst_counter[current_bank_adjusted] = 0; @@ -11727,7 +11719,7 @@ int ai_formation() if (aip->mode == AIM_WAYPOINTS) { - if (The_mission.ai_profile->flags2 & AIPF2_FIX_AI_PATH_ORDER_BUG){ + if (The_mission.ai_profile->flags[AI::Profile_Flags::Fix_ai_path_order_bug]){ // skip if wing leader has no waypoint order or a different waypoint list if ((laip->mode != AIM_WAYPOINTS) || !(aip->wp_list == laip->wp_list)){ return 1; @@ -12285,7 +12277,7 @@ void ai_balance_shield(object *objp) for (i=0; in_quadrants; i++) { if (objp->shield_quadrant[i] < shield_strength_avg) { // only do it the retail way if using smart shields (since that's a bigger thing) - taylor - if (Ai_info[Ships[objp->instance].ai_index].ai_profile_flags & AIPF_SMART_SHIELD_MANAGEMENT) + if (Ai_info[Ships[objp->instance].ai_index].ai_profile_flags[AI::Profile_Flags::Smart_shield_management]) shield_add_strength(objp, delta); else objp->shield_quadrant[i] += delta/objp->n_quadrants; @@ -12295,7 +12287,7 @@ void ai_balance_shield(object *objp) } else { // only do it the retail way if using smart shields (since that's a bigger thing) - taylor - if (Ai_info[Ships[objp->instance].ai_index].ai_profile_flags & AIPF_SMART_SHIELD_MANAGEMENT) + if (Ai_info[Ships[objp->instance].ai_index].ai_profile_flags[AI::Profile_Flags::Smart_shield_management]) shield_add_strength(objp, -delta); else objp->shield_quadrant[i] -= delta/objp->n_quadrants; @@ -12335,7 +12327,7 @@ void ai_manage_shield(object *objp, ai_info *aip) // set timestamp aip->shield_manage_timestamp = timestamp((int) (delay * 1000.0f)); - if (sip->is_small_ship() || (aip->ai_profile_flags2 & AIPF2_ALL_SHIPS_MANAGE_SHIELDS)) { + if (sip->is_small_ship() || (aip->ai_profile_flags[AI::Profile_Flags::All_ships_manage_shields])) { if (Missiontime - aip->last_hit_time < F1_0*10) ai_transfer_shield(objp, aip->last_hit_quadrant); else @@ -13234,30 +13226,29 @@ int maybe_request_support(object *objp) desire += mrs_subsystem(shipp, SUBSYSTEM_SENSORS); - // Set desire based on percentage of secondary weapons. ship_weapon *swp = &shipp->weapons; - for ( i = 0; i < swp->num_secondary_banks; i++ ) { - if (swp->secondary_bank_start_ammo[i] > 0) { - r = (float) swp->secondary_bank_ammo[i]/swp->secondary_bank_start_ammo[i]; - desire += (int) ((1.0f - r) * 3.0f); + // Set desire based on percentage of secondary weapons. + for (i = 0; i < swp->num_secondary_banks; ++i) + { + if (swp->secondary_bank_start_ammo[i] > 0) + { + r = (float)swp->secondary_bank_ammo[i] / swp->secondary_bank_start_ammo[i]; + desire += (int)((1.0f - r) * 3.0f); } } // Set desire based on ballistic weapons - Goober5000 - if (sip->flags[Ship::Info_Flags::Ballistic_primaries]) + for (i = 0; i < swp->num_primary_banks; ++i) { - for (i = 0; i < swp->num_primary_banks; i++) + wip = &Weapon_info[swp->primary_bank_weapons[i]]; + + if (wip->wi_flags[Weapon::Info_Flags::Ballistic] && swp->primary_bank_start_ammo[i] > 0) { - wip = &Weapon_info[swp->primary_bank_weapons[i]]; + r = (float) swp->primary_bank_ammo[i] / swp->primary_bank_start_ammo[i]; - if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) - { - r = (float) swp->primary_bank_ammo[i] / swp->primary_bank_start_ammo[i]; - - // cube ammo level for better behavior, and adjust for number of banks - desire += (int) ((1.0f - r)*(1.0f - r)*(1.0f - r) * (5.0f / swp->num_primary_banks)); - } + // cube ammo level for better behavior, and adjust for number of banks + desire += (int) ((1.0f - r)*(1.0f - r)*(1.0f - r) * (5.0f / swp->num_primary_banks)); } } @@ -14459,28 +14450,6 @@ void init_ai_system() Ppfp = Path_points; } -int combine_flags(int base_flags, int override_flags, int override_set) -{ - int result = 0; - //Scan through every bit in the flag int - for (int i = 0; i < 31; i++) - { - int flag = (1 << i); - //If this flag is marked in the override as set, copy it from the override - if (override_set & flag) - { - if (override_flags & flag) - result |= flag; - } - else //Otherwise, copy it from the base flag - { - if (base_flags & flag) - result |= flag; - } - } - return result; -} - //Sets the ai_info stuff based on what is in the ai class and the current ai profile //Stuff in the ai class will override what is in the ai profile, but only if it is set. //Unset per-difficulty-level values are marked with FLT_MIN or INT_MIN @@ -14556,8 +14525,7 @@ void init_aip_from_class_and_profile(ai_info *aip, ai_class *aicp, ai_profile_t profile->turret_max_aim_update_delay[Game_skill_level] : aicp->ai_turret_max_aim_update_delay[Game_skill_level]; //Combine AI profile and AI class flags - aip->ai_profile_flags = combine_flags(profile->flags, aicp->ai_profile_flags, aicp->ai_profile_flags_set); - aip->ai_profile_flags2 = combine_flags(profile->flags2, aicp->ai_profile_flags2, aicp->ai_profile_flags2_set); + aip->ai_profile_flags = profile->flags | (aicp->ai_profile_flags & aicp->ai_profile_flags_set); } void ai_do_default_behavior(object *obj) diff --git a/code/ai/aiturret.cpp b/code/ai/aiturret.cpp index 25e450fbba..ee3c440169 100644 --- a/code/ai/aiturret.cpp +++ b/code/ai/aiturret.cpp @@ -494,7 +494,7 @@ int valid_turret_enemy(object *objp, object *turret_parent) return 0; } - if ( (!((wip->wi_flags[Weapon::Info_Flags::Bomb]) || (wip->wi_flags[Weapon::Info_Flags::Turret_Interceptable])) && !(Ai_info[Ships[turret_parent->instance].ai_index].ai_profile_flags & AIPF_ALLOW_TURRETS_TARGET_WEAPONS_FREELY) ) ) { + if ( (!((wip->wi_flags[Weapon::Info_Flags::Bomb]) || (wip->wi_flags[Weapon::Info_Flags::Turret_Interceptable])) && !(Ai_info[Ships[turret_parent->instance].ai_index].ai_profile_flags[AI::Profile_Flags::Allow_turrets_target_weapons_freely]) ) ) { return 0; } @@ -598,7 +598,7 @@ void evaluate_obj_as_target(object *objp, eval_enemy_obj_struct *eeo) // however if this is removed turrets still track targets but don't fire at them (which looks silly) if (eeo->eeo_flags & EEOF_TAGGED_ONLY) { if (!ship_is_tagged(objp) && - ( (The_mission.ai_profile->flags2 & AIPF2_STRICT_TURRET_TAGGED_ONLY_TARGETING) || + ( (The_mission.ai_profile->flags[AI::Profile_Flags::Strict_turred_tagged_only_targeting]) || ( !(objp->type == OBJ_WEAPON) && !(turret_weapon_has_flags(&eeo->turret_subsys->weapons, Weapon::Info_Flags::Spawn))) )) { return; } @@ -656,7 +656,7 @@ void evaluate_obj_as_target(object *objp, eval_enemy_obj_struct *eeo) // check if bomb is homing on the turret parent ship bool check_weapon = true; - if ((Ai_info[Ships[turret_parent_obj->instance].ai_index].ai_profile_flags & AIPF_PREVENT_TARGETING_BOMBS_BEYOND_RANGE) && (dist > eeo->weapon_travel_dist)) { + if ((Ai_info[Ships[turret_parent_obj->instance].ai_index].ai_profile_flags[AI::Profile_Flags::Prevent_targeting_bombs_beyond_range]) && (dist > eeo->weapon_travel_dist)) { check_weapon = false; } @@ -1044,7 +1044,7 @@ int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subs case 0: //Return if a bomb is found //don't fire anti capital ship turrets at bombs. - if ( !((aip->ai_profile_flags & AIPF_HUGE_TURRET_WEAPONS_IGNORE_BOMBS) && big_only_flag) ) + if ( !((aip->ai_profile_flags[AI::Profile_Flags::Huge_turret_weapons_ignore_bombs]) && big_only_flag) ) { // Missile_obj_list for( mo = GET_FIRST(&Missile_obj_list); mo != END_OF_LIST(&Missile_obj_list); mo = GET_NEXT(mo) ) { @@ -1321,7 +1321,7 @@ void ship_get_global_turret_gun_info(object *objp, ship_subsys *ssp, vec3d *gpos vec3d target_moving_direction = ssp->last_aim_enemy_vel; //Try to guess where the enemy will be, and store that spot in predicted_enemy_pos - if (The_mission.ai_profile->flags & AIPF_USE_ADDITIVE_WEAPON_VELOCITY) { + if (The_mission.ai_profile->flags[AI::Profile_Flags::Use_additive_weapon_velocity]) { vm_vec_scale_sub2(&target_moving_direction, &objp->phys_info.vel, wip->vel_inherit_amount); } @@ -1417,7 +1417,7 @@ int aifft_rotate_turret(ship *shipp, int parent_objnum, ship_subsys *ss, object target_moving_direction = ss->last_aim_enemy_vel; //Try to guess where the enemy will be, and store that spot in predicted_enemy_pos - if (The_mission.ai_profile->flags & AIPF_USE_ADDITIVE_WEAPON_VELOCITY) { + if (The_mission.ai_profile->flags[AI::Profile_Flags::Use_additive_weapon_velocity]) { vm_vec_scale_sub2(&target_moving_direction, &objp->phys_info.vel, wip->vel_inherit_amount); } @@ -1490,7 +1490,7 @@ float aifft_compute_turret_dot(object *objp, object *enemy_objp, vec3d *abs_gunp vm_vec_unrotate(&turret_norm, &turret_subsysp->system_info->turret_norm, &objp->orient); float dot_return = vm_vec_dot(&turret_norm, &vector_out); - if (Ai_info[Ships[objp->instance].ai_index].ai_profile_flags & AIPF_SMART_SUBSYSTEM_TARGETING_FOR_TURRETS) { + if (Ai_info[Ships[objp->instance].ai_index].ai_profile_flags[AI::Profile_Flags::Smart_subsystem_targeting_for_turrets]) { if (dot_return > turret_subsysp->system_info->turret_fov) { // target is in sight and in fov return dot_return; @@ -1619,7 +1619,7 @@ ship_subsys *aifft_find_turret_subsys(object *objp, ship_subsys *ssp, object *en int idx; float dot_fov_modifier = 0.0f; - if (Ai_info[shipp->ai_index].ai_profile_flags & AIPF_SMART_SUBSYSTEM_TARGETING_FOR_TURRETS) { + if (Ai_info[shipp->ai_index].ai_profile_flags[AI::Profile_Flags::Smart_subsystem_targeting_for_turrets]) { if (ssp->system_info->turret_fov < 0) dot_fov_modifier = ssp->system_info->turret_fov; } @@ -1677,7 +1677,7 @@ void turret_set_next_fire_timestamp(int weapon_num, weapon_info *wip, ship_subsy turret->weapons.burst_counter[weapon_num]++; } else { wait *= wip->fire_wait; - if ((wip->burst_shots > 0) && (wip->burst_flags & WBF_RANDOM_LENGTH)) { + if ((wip->burst_shots > 0) && (wip->burst_flags[Weapon::Burst_Flags::Random_length])) { turret->weapons.burst_counter[weapon_num] = (myrand() % wip->burst_shots); } else { turret->weapons.burst_counter[weapon_num] = 0; @@ -1691,7 +1691,7 @@ void turret_set_next_fire_timestamp(int weapon_num, weapon_info *wip, ship_subsy fs_dest = &turret->weapons.next_secondary_fire_stamp[weapon_num - MAX_SHIP_PRIMARY_BANKS]; //Check for the new cooldown flag - if(!((wip->wi_flags[Weapon::Info_Flags::Same_turret_cooldown]) || ((wip->burst_shots > 0) && (wip->burst_flags & WBF_FAST_FIRING)))) + if(!((wip->wi_flags[Weapon::Info_Flags::Same_turret_cooldown]) || ((wip->burst_shots > 0) && (wip->burst_flags[Weapon::Burst_Flags::Fast_firing])))) { // make side even for team vs. team @@ -2065,7 +2065,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum, } } //Not useful -WMC - else if (!(parent_aip->ai_profile_flags & AIPF_DONT_INSERT_RANDOM_TURRET_FIRE_DELAY) && last_shot_in_salvo) + else if (!(parent_aip->ai_profile_flags[AI::Profile_Flags::Dont_insert_random_turret_fire_delay]) && last_shot_in_salvo) { float wait = 1000.0f * frand_range(0.9f, 1.1f); turret->turret_next_fire_stamp = timestamp((int) wait); @@ -2104,7 +2104,7 @@ void turret_swarm_fire_from_turret(turret_swarm_info *tsi) // *If it's a non-homer, then use the last fire direction instead of turret orientation to fix inaccuracy // problems with non-homing swarm weapons -Et1 - if ( (Weapon_info[tsi->weapon_class].subtype == WP_LASER) || ((The_mission.ai_profile->flags & AIPF_HACK_IMPROVE_NON_HOMING_SWARM_TURRET_FIRE_ACCURACY) + if ( (Weapon_info[tsi->weapon_class].subtype == WP_LASER) || ((The_mission.ai_profile->flags[AI::Profile_Flags::Hack_improve_non_homing_swarm_turret_fire_accuracy]) && !(Weapon_info[tsi->weapon_class].is_homing())) ) { turret_fvec = tsi->turret->turret_last_fire_direction; @@ -2292,7 +2292,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum) //WMC - build a list of valid weapons. Fire spawns if there are any. float dist_to_enemy = 0.0f; if(lep != NULL) { - if (The_mission.ai_profile->flags2 & AIPF2_TURRETS_IGNORE_TARGET_RADIUS) + if (The_mission.ai_profile->flags[AI::Profile_Flags::Turrets_ignore_target_radius]) dist_to_enemy = MAX(0,vm_vec_normalized_dir(&v2e, &predicted_enemy_pos, &gpos)); else dist_to_enemy = MAX(0,vm_vec_normalized_dir(&v2e, &predicted_enemy_pos, &gpos) - lep->radius); @@ -2441,7 +2441,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum) else { // check tagged-only for non-ship targets - if (tagged_only && (!(lep->type == OBJ_WEAPON) || (The_mission.ai_profile->flags2 & AIPF2_STRICT_TURRET_TAGGED_ONLY_TARGETING))) { + if (tagged_only && (!(lep->type == OBJ_WEAPON) || (The_mission.ai_profile->flags[AI::Profile_Flags::Strict_turred_tagged_only_targeting]))) { continue; } } @@ -2608,7 +2608,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum) //turret_weapon_class = tp->turret_weapon_type; bool in_sight = false; - if (The_mission.ai_profile->flags & AIPF_USE_ONLY_SINGLE_FOV_FOR_TURRETS) { + if (The_mission.ai_profile->flags[AI::Profile_Flags::Use_only_single_fov_for_turrets]) { // we have already passed the FOV test of the turret so... in_sight = true; } else { diff --git a/code/cmdline/cmdline.cpp b/code/cmdline/cmdline.cpp index 942e2e7190..b8fc2ae911 100644 --- a/code/cmdline/cmdline.cpp +++ b/code/cmdline/cmdline.cpp @@ -231,7 +231,6 @@ Flag exe_params[] = { "-output_sexps", "Output SEXPs to sexps.html", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-output_sexps", }, { "-output_scripting", "Output scripting to scripting.html", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-output_scripting", }, { "-save_render_target", "Save render targets to file", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-save_render_target", }, - { "-debug_window", "Display debug window", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-debug_window", }, { "-verify_vps", "Spew VP CRCs to vp_crcs.txt", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-verify_vps", }, { "-reparse_mainhall", "Reparse mainhall.tbl when loading halls", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-reparse_mainhall", }, { "-profile_frame_time","Profile engine subsystems", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-profile_frame_timings", }, @@ -239,6 +238,7 @@ Flag exe_params[] = { "-no_unfocused_pause","Don't pause if the window isn't focused", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_unfocused_pause", }, { "-benchmark_mode", "Puts the game into benchmark mode", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-benchmark_mode", }, { "-noninteractive", "Disables interactive dialogs", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noninteractive", }, + { "-json_pilot", "Dump pilot files in JSON format", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-json_pilot", }, }; // forward declaration @@ -485,6 +485,7 @@ cmdline_parm frame_profile_write_file("-profile_write_file", NULL, AT_NONE); // cmdline_parm no_unfocused_pause_arg("-no_unfocused_pause", NULL, AT_NONE); //Cmdline_no_unfocus_pause cmdline_parm benchmark_mode_arg("-benchmark_mode", NULL, AT_NONE); //Cmdline_benchmark_mode cmdline_parm noninteractive_arg("-noninteractive", NULL, AT_NONE); //Cmdline_noninteractive +cmdline_parm json_pilot("-json_pilot", NULL, AT_NONE); //Cmdline_json_pilot char *Cmdline_start_mission = NULL; @@ -511,6 +512,7 @@ bool Cmdline_profile_write_file = false; bool Cmdline_no_unfocus_pause = false; bool Cmdline_benchmark_mode = false; bool Cmdline_noninteractive = false; +bool Cmdline_json_pilot = false; // Other cmdline_parm get_flags_arg("-get_flags", "Output the launcher flags file", AT_NONE); @@ -1853,6 +1855,11 @@ bool SetCmdlineParams() Cmdline_noninteractive = true; } + if (json_pilot.found()) + { + Cmdline_json_pilot = true; + } + //Deprecated flags - CommanderDJ if( deprecated_spec_arg.found() ) { diff --git a/code/cmdline/cmdline.h b/code/cmdline/cmdline.h index c49230a20b..e650a4eab9 100644 --- a/code/cmdline/cmdline.h +++ b/code/cmdline/cmdline.h @@ -158,5 +158,6 @@ extern bool Cmdline_profile_write_file; extern bool Cmdline_no_unfocus_pause; extern bool Cmdline_benchmark_mode; extern bool Cmdline_noninteractive; +extern bool Cmdline_json_pilot; #endif diff --git a/code/cutscene/cutscenes.h b/code/cutscene/cutscenes.h index 0d59e01f79..17627bf9fe 100644 --- a/code/cutscene/cutscenes.h +++ b/code/cutscene/cutscenes.h @@ -21,7 +21,15 @@ typedef struct cutscene_info { bool viewable; } cutscene_info; +#if SCP_COMPILER_IS_GNU +#pragma GCC diagnostic push +// This suppresses a GCC bug where it thinks that the Cutscenes from the enum class below shadows a global variable +#pragma GCC diagnostic ignored "-Wshadow" +#endif extern SCP_vector Cutscenes; +#if SCP_COMPILER_IS_GNU +#pragma GCC diagnostic pop +#endif // initializa table data void cutscene_init(); diff --git a/code/def_files/deferred-f.sdr b/code/def_files/deferred-f.sdr index ddb45a5c49..6789bd4ac7 100644 --- a/code/def_files/deferred-f.sdr +++ b/code/def_files/deferred-f.sdr @@ -30,7 +30,7 @@ vec3 FresnelSchlick(vec3 specColor, vec3 light, vec3 halfVec) } vec3 SpecularBlinnPhong(vec3 specColor, vec3 light, vec3 normal, vec3 halfVec, float specPower, float dotNL) { - return FresnelSchlick(max(specColor, vec3(0.04)), light, halfVec) * ((specPower + 2) / 8 ) * pow(clamp(dot(normal, halfVec), 0.0, 1.0), specPower) * dotNL; + return FresnelSchlick(max(specColor, vec3(0.04)), light, halfVec) * ((specPower + 2.0) / 8.0 ) * pow(clamp(dot(normal, halfVec), 0.0, 1.0), specPower) * dotNL; } vec4 SpecularLegacy(vec4 specColor, vec3 normal, vec3 halfVec, float specPower) { diff --git a/code/globalincs/vmallocator.h b/code/globalincs/vmallocator.h index 5ea828a772..9b54ff3728 100644 --- a/code/globalincs/vmallocator.h +++ b/code/globalincs/vmallocator.h @@ -14,28 +14,28 @@ #include template< typename T > -class SCP_vector : public std::vector< T, std::allocator< T > > { }; +using SCP_vector = std::vector< T, std::allocator< T > >; template< typename T > -class SCP_list : public std::list< T, std::allocator< T > > { }; +using SCP_list = std::list< T, std::allocator< T > >; typedef std::basic_string, std::allocator > SCP_string; typedef std::basic_stringstream, std::allocator > SCP_stringstream; template< typename T, typename U > -class SCP_map : public std::map, std::allocator > > { }; +using SCP_map = std::map, std::allocator > >; template< typename T, typename U > -class SCP_multimap : public std::multimap, std::allocator > > { }; +using SCP_multimap = std::multimap, std::allocator > >; template< typename T > -class SCP_queue : public std::queue< T, std::deque< T, std::allocator< T > > > { }; +using SCP_queue = std::queue< T, std::deque< T, std::allocator< T > > >; template< typename T > -class SCP_deque : public std::deque< T, std::allocator< T > > { }; +using SCP_deque = std::deque< T, std::allocator< T > >; template< typename Key, typename T, typename Hash = std::hash, typename KeyEqual = std::equal_to > -class SCP_unordered_map : public std::unordered_map< Key, T, Hash, KeyEqual, std::allocator< std::pair > > { }; +using SCP_unordered_map = std::unordered_map< Key, T, Hash, KeyEqual, std::allocator< std::pair > >; #endif // _VMALLOCATOR_H_INCLUDED_ diff --git a/code/hud/hudobserver.cpp b/code/hud/hudobserver.cpp index e80e131402..05e49e16ce 100644 --- a/code/hud/hudobserver.cpp +++ b/code/hud/hudobserver.cpp @@ -26,7 +26,7 @@ ai_info Hud_obs_ai; void hud_observer_init(ship *shipp, ai_info *aip) { // setup the pseduo ship and ai - memcpy(&Hud_obs_ai, aip, sizeof(ai_info)); + Hud_obs_ai = *aip; // (we used to do a memcpy here, but that doesn't work any longer, so let's just assign the values we need) Hud_obs_ship.clear(); strcpy_s(Hud_obs_ship.ship_name, shipp->ship_name); diff --git a/code/hud/hudtarget.cpp b/code/hud/hudtarget.cpp index ae9de01642..92b341696f 100644 --- a/code/hud/hudtarget.cpp +++ b/code/hud/hudtarget.cpp @@ -3704,7 +3704,7 @@ void hud_calculate_lead_pos(vec3d *lead_target_pos, vec3d *target_pos, object *t target_moving_direction = targetp->phys_info.vel; - if(The_mission.ai_profile->flags & AIPF_USE_ADDITIVE_WEAPON_VELOCITY) + if(The_mission.ai_profile->flags[AI::Profile_Flags::Use_additive_weapon_velocity]) vm_vec_scale_sub2(&target_moving_direction, &Player_obj->phys_info.vel, wip->vel_inherit_amount); // test if the target is moving at all @@ -3797,7 +3797,7 @@ void polish_predicted_target_pos(weapon_info *wip, object *targetp, vec3d *enemy // additive velocity stuff // not just the player's main target vec3d enemy_vel = targetp->phys_info.vel; - if (The_mission.ai_profile->flags & AIPF_USE_ADDITIVE_WEAPON_VELOCITY) { + if (The_mission.ai_profile->flags[AI::Profile_Flags::Use_additive_weapon_velocity]) { vm_vec_scale_sub2( &enemy_vel, &Player_obj->phys_info.vel, wip->vel_inherit_amount); } @@ -5541,11 +5541,11 @@ void HudGaugeWeaponEnergy::render(float frametime) bool use_new_gauge = false; // Goober5000 - only check for the new gauge in case of command line + a ballistic-capable ship - if (Cmdline_ballistic_gauge && Ship_info[Player_ship->ship_info_index].flags[Ship::Info_Flags::Ballistic_primaries]) + if (Cmdline_ballistic_gauge) { - for(x = 0; x < Player_ship->weapons.num_primary_banks; x++) + for (x = 0; x < Player_ship->weapons.num_primary_banks; ++x) { - if(Weapon_info[Player_ship->weapons.primary_bank_weapons[x]].wi_flags[Weapon::Info_Flags::Ballistic]) + if (Weapon_info[Player_ship->weapons.primary_bank_weapons[x]].wi_flags[Weapon::Info_Flags::Ballistic]) { use_new_gauge = true; break; @@ -5651,7 +5651,7 @@ void HudGaugeWeaponEnergy::render(float frametime) sw = &Player_ship->weapons; // show ballistic ammunition in energy gauge if need be - if ( Show_ballistic && Ship_info[Player_ship->ship_info_index].flags[Ship::Info_Flags::Ballistic_primaries] ) { + if ( Show_ballistic ) { if ( Player_ship->flags[Ship::Ship_Flags::Primary_linked] ) { // go through all ballistic primaries and add up their ammunition totals and max capacities @@ -5670,7 +5670,11 @@ void HudGaugeWeaponEnergy::render(float frametime) max_ballistic_ammo = sw->primary_bank_start_ammo[sw->current_primary_bank]; } - percent_left = i2fl(ballistic_ammo) / i2fl(max_ballistic_ammo); + if (max_ballistic_ammo > 0) { + percent_left = i2fl(ballistic_ammo) / i2fl(max_ballistic_ammo); + } else { + percent_left = 1.0f; + } } else { // also leave if no energy can be stored for weapons - Goober5000 if (!ship_has_energy_weapons(Player_ship)) diff --git a/code/io/keycontrol.cpp b/code/io/keycontrol.cpp index 0a4d3d8fb3..4f651e2ce7 100644 --- a/code/io/keycontrol.cpp +++ b/code/io/keycontrol.cpp @@ -588,18 +588,15 @@ void debug_max_primary_weapons(object *objp) // Goober5000 ship_weapon *swp = &shipp->weapons; weapon_info *wip; - if (sip->flags[Ship::Info_Flags::Ballistic_primaries]) + for ( index = 0; index < MAX_SHIP_PRIMARY_BANKS; index++ ) { - for ( index = 0; index < MAX_SHIP_PRIMARY_BANKS; index++ ) + wip = &Weapon_info[swp->primary_bank_weapons[index]]; + if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) { - wip = &Weapon_info[swp->primary_bank_weapons[index]]; - if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) - { - float capacity, size; - capacity = (float) sip->primary_bank_ammo_capacity[index]; - size = (float) wip->cargo_size; - swp->primary_bank_ammo[index] = fl2i((capacity / size)+0.5f); - } + float capacity, size; + capacity = (float) sip->primary_bank_ammo_capacity[index]; + size = (float) wip->cargo_size; + swp->primary_bank_ammo[index] = fl2i((capacity / size)+0.5f); } } } diff --git a/code/mission/missiongoals.cpp b/code/mission/missiongoals.cpp index 88e882326b..293b3c95d6 100644 --- a/code/mission/missiongoals.cpp +++ b/code/mission/missiongoals.cpp @@ -734,7 +734,7 @@ void multi_player_maybe_add_score (int score, int team) return; } - if (!(The_mission.ai_profile->flags & AIPF_ALLOW_MULTI_EVENT_SCORING)) { + if (!(The_mission.ai_profile->flags[AI::Profile_Flags::Allow_multi_event_scoring])) { return; } diff --git a/code/mission/missionmessage.cpp b/code/mission/missionmessage.cpp index f7da574594..686a600bbb 100644 --- a/code/mission/missionmessage.cpp +++ b/code/mission/missionmessage.cpp @@ -1976,7 +1976,7 @@ void message_send_builtin_to_player( int type, ship *shipp, int priority, int ti nprintf(("messaging", "Couldn't find persona for %s\n", shipp->ship_name )); // be sure that this ship can actually send a message!!! (i.e. not-not-flyable -- get it!) - Assert( !Ship_info[shipp->ship_info_index].is_flyable() ); // get allender or alan + Assert( Ship_info[shipp->ship_info_index].is_flyable() ); // get allender or alan } else { persona_index = The_mission.command_persona; // use the terran command persona } diff --git a/code/mission/missionparse.cpp b/code/mission/missionparse.cpp index 4435bb142a..ec9cd94e75 100644 --- a/code/mission/missionparse.cpp +++ b/code/mission/missionparse.cpp @@ -1929,7 +1929,7 @@ int parse_create_object_sub(p_object *p_objp) aip->ai_class = p_objp->ai_class; shipp->weapons.ai_class = p_objp->ai_class; // Fred uses this instead of above. //Fixes a bug where the AI class attributes were not copied if the AI class was set in the mission. - if (The_mission.ai_profile->flags & AIPF_FIX_AI_CLASS_BUG) + if (The_mission.ai_profile->flags[AI::Profile_Flags::Fix_ai_class_bug]) ship_set_new_ai_class(shipnum, p_objp->ai_class); // must reset the number of ai goals when the object is created diff --git a/code/missionui/missionweaponchoice.cpp b/code/missionui/missionweaponchoice.cpp index 7b4bf9dc77..885df92774 100644 --- a/code/missionui/missionweaponchoice.cpp +++ b/code/missionui/missionweaponchoice.cpp @@ -1119,16 +1119,6 @@ void wl_set_disabled_weapons(int ship_class) // Determine whether weapon #i is allowed on this ship class in the current type of mission. // As of 9/6/99, the only difference is dogfight missions have a different list of legal weapons. Wl_icons[i].can_use = eval_weapon_flag_for_game_type(sip->allowed_weapons[i]); - - // Goober5000: ballistic primaries - if (Weapon_info[i].wi_flags[Weapon::Info_Flags::Ballistic]) - { - // not allowed if this ship is not ballistic - if (!(sip->flags[Ship::Info_Flags::Ballistic_primaries])) - { - Wl_icons[i].can_use = 0; - } - } } } @@ -4043,8 +4033,7 @@ void wl_apply_current_loadout_to_all_ships_in_current_wing() } // make sure this ship can accept this weapon - if (!eval_weapon_flag_for_game_type(sip->allowed_weapons[weapon_type_to_add]) - || ((wip->wi_flags[Weapon::Info_Flags::Ballistic]) && !(sip->flags[Ship::Info_Flags::Ballistic_primaries]))) + if (!eval_weapon_flag_for_game_type(sip->allowed_weapons[weapon_type_to_add])) { SCP_string temp; sprintf(temp, XSTR("%s is unable to carry %s weaponry", 1629), ship_name, wep_display_name); diff --git a/code/network/multi_ingame.cpp b/code/network/multi_ingame.cpp index 709ddf0f97..53508bf80e 100644 --- a/code/network/multi_ingame.cpp +++ b/code/network/multi_ingame.cpp @@ -1439,11 +1439,8 @@ void send_ingame_ship_request_packet(int code,int rdata,net_player *pl) val = (ubyte)shipp->engine_recharge_index; ADD_DATA(val); - // add the ballistic primary flag - Goober5000 + // dummy field to replace ballistic primary flag val = 0; - if(sip->flags[Ship::Info_Flags::Ballistic_primaries]){ - val |= (1<<0); - } ADD_DATA(val); // add current primary and secondary banks, and add link status @@ -1685,11 +1682,8 @@ void process_ingame_ship_request_packet(ubyte *data, header *hinfo) GET_DATA(val); Player_ship->engine_recharge_index = val; - // handle the ballistic primary flag - Goober5000 + // handle the dummy value that used to be the ballistic primary flag GET_DATA(val); - if(val & (1<<0)){ - Ship_info[Player_ship->ship_info_index].flags.set(Ship::Info_Flags::Ballistic_primaries); - } // get current primary and secondary banks, and add link status GET_DATA(val); diff --git a/code/network/multiteamselect.cpp b/code/network/multiteamselect.cpp index 8f5f7ca093..d20428536d 100644 --- a/code/network/multiteamselect.cpp +++ b/code/network/multiteamselect.cpp @@ -2754,12 +2754,12 @@ int multi_ts_ok_to_commit() } // if the ship doesn't have primary weapons - if (!primary_ok && !(The_mission.ai_profile->flags & AIPF_MULTI_ALLOW_EMPTY_PRIMARIES)) { + if (!primary_ok && !(The_mission.ai_profile->flags[AI::Profile_Flags::Multi_allow_empty_secondaries])) { return 2; } // if the ship doesn't have secondary weapons - if (!secondary_ok && !(The_mission.ai_profile->flags & AIPF_MULTI_ALLOW_EMPTY_SECONDARIES)) { + if (!secondary_ok && !(The_mission.ai_profile->flags[AI::Profile_Flags::Multi_allow_empty_secondaries])) { return 3; } } diff --git a/code/object/collideweaponweapon.cpp b/code/object/collideweaponweapon.cpp index 5b770f0041..8a67857d51 100644 --- a/code/object/collideweaponweapon.cpp +++ b/code/object/collideweaponweapon.cpp @@ -59,7 +59,7 @@ int collide_weapon_weapon( obj_pair * pair ) A_radius *= 2; // Makes bombs easier to hit } - if ((The_mission.ai_profile->flags2 & AIPF2_ASPECT_INVULNERABILITY_FIX) && (wipA->is_locked_homing()) && (wpA->homing_object != &obj_used_list)) { + if ((The_mission.ai_profile->flags[AI::Profile_Flags::Aspect_invulnerability_fix]) && (wipA->is_locked_homing()) && (wpA->homing_object != &obj_used_list)) { if ( (wipA->max_lifetime - wpA->lifeleft) < The_mission.ai_profile->delay_bomb_arm_timer[Game_skill_level] ) return 0; } @@ -71,7 +71,7 @@ int collide_weapon_weapon( obj_pair * pair ) if (!(wipB->wi_flags[Weapon::Info_Flags::Hard_target_bomb])) { B_radius *= 2; // Makes bombs easier to hit } - if ((The_mission.ai_profile->flags2 & AIPF2_ASPECT_INVULNERABILITY_FIX) && (wipB->is_locked_homing()) && (wpB->homing_object != &obj_used_list)) { + if ((The_mission.ai_profile->flags[AI::Profile_Flags::Aspect_invulnerability_fix]) && (wipB->is_locked_homing()) && (wpB->homing_object != &obj_used_list)) { if ( (wipB->max_lifetime - wpB->lifeleft) < The_mission.ai_profile->delay_bomb_arm_timer[Game_skill_level] ) return 0; } @@ -104,8 +104,8 @@ int collide_weapon_weapon( obj_pair * pair ) if ((wipA->wi_flags[Weapon::Info_Flags::Bomb]) && (wipB->wi_flags[Weapon::Info_Flags::Bomb])) { wpA->lifeleft = 0.01f; wpB->lifeleft = 0.01f; - wpA->weapon_flags |= WF_DESTROYED_BY_WEAPON; - wpB->weapon_flags |= WF_DESTROYED_BY_WEAPON; + wpA->weapon_flags.set(Weapon::Weapon_Flags::Destroyed_by_weapon); + wpB->weapon_flags.set(Weapon::Weapon_Flags::Destroyed_by_weapon); } else { A->hull_strength -= bDamage; B->hull_strength -= aDamage; @@ -121,29 +121,29 @@ int collide_weapon_weapon( obj_pair * pair ) if (A->hull_strength < 0.0f) { wpA->lifeleft = 0.01f; - wpA->weapon_flags |= WF_DESTROYED_BY_WEAPON; + wpA->weapon_flags.set(Weapon::Weapon_Flags::Destroyed_by_weapon); } if (B->hull_strength < 0.0f) { wpB->lifeleft = 0.01f; - wpB->weapon_flags |= WF_DESTROYED_BY_WEAPON; + wpB->weapon_flags.set(Weapon::Weapon_Flags::Destroyed_by_weapon); } } } else { A->hull_strength -= bDamage; wpB->lifeleft = 0.01f; - wpB->weapon_flags |= WF_DESTROYED_BY_WEAPON; + wpB->weapon_flags.set(Weapon::Weapon_Flags::Destroyed_by_weapon); if (A->hull_strength < 0.0f) { wpA->lifeleft = 0.01f; - wpA->weapon_flags |= WF_DESTROYED_BY_WEAPON; + wpA->weapon_flags.set(Weapon::Weapon_Flags::Destroyed_by_weapon); } } } else if (wipB->weapon_hitpoints > 0) { B->hull_strength -= aDamage; wpA->lifeleft = 0.01f; - wpA->weapon_flags |= WF_DESTROYED_BY_WEAPON; + wpA->weapon_flags.set(Weapon::Weapon_Flags::Destroyed_by_weapon); if (B->hull_strength < 0.0f) { wpB->lifeleft = 0.01f; - wpB->weapon_flags |= WF_DESTROYED_BY_WEAPON; + wpB->weapon_flags.set(Weapon::Weapon_Flags::Destroyed_by_weapon); } } @@ -154,14 +154,14 @@ int collide_weapon_weapon( obj_pair * pair ) if (wipA->wi_flags[Weapon::Info_Flags::Bomb]) { //Update stats. -Halleck scoring_eval_hit(A, B, 0); - if (wpA->weapon_flags & WF_DESTROYED_BY_WEAPON) { + if (wpA->weapon_flags[Weapon::Weapon_Flags::Destroyed_by_weapon]) { scoring_eval_kill_on_weapon(A, B); } } if (wipB->wi_flags[Weapon::Info_Flags::Bomb]) { //Update stats. -Halleck scoring_eval_hit(B, A, 0); - if (wpB->weapon_flags & WF_DESTROYED_BY_WEAPON) { + if (wpB->weapon_flags[Weapon::Weapon_Flags::Destroyed_by_weapon]) { scoring_eval_kill_on_weapon(B, A); } } diff --git a/code/object/object.cpp b/code/object/object.cpp index a170d4baba..8f1c3e42b5 100644 --- a/code/object/object.cpp +++ b/code/object/object.cpp @@ -853,7 +853,7 @@ void obj_move_call_physics(object *objp, float frametime) } // if a weapon is flagged as dead, kill its engines just like a ship - if((objp->type == OBJ_WEAPON) && (Weapons[objp->instance].weapon_flags & WF_DEAD_IN_WATER)){ + if((objp->type == OBJ_WEAPON) && (Weapons[objp->instance].weapon_flags[Weapon::Weapon_Flags::Dead_in_water])){ vm_vec_zero(&objp->phys_info.desired_vel); vm_vec_zero(&objp->phys_info.desired_rotvel); objp->phys_info.flags |= (PF_REDUCED_DAMP | PF_DEAD_DAMP); diff --git a/code/object/objectshield.cpp b/code/object/objectshield.cpp index c5d31e9566..23d303755f 100644 --- a/code/object/objectshield.cpp +++ b/code/object/objectshield.cpp @@ -55,7 +55,7 @@ void shield_add_strength(object *objp, float delta) if (shield_str >= shield_recharge_limit) return; - if (!(Ai_info[Ships[objp->instance].ai_index].ai_profile_flags & AIPF_SMART_SHIELD_MANAGEMENT) + if (!(Ai_info[Ships[objp->instance].ai_index].ai_profile_flags[AI::Profile_Flags::Smart_shield_management]) || delta <= 0.0f) //SUSHI: We don't want smart shield management for negative delta { // set the limit for the shield recharge diff --git a/code/parse/lua.cpp b/code/parse/lua.cpp index 8971f71091..40c8297637 100644 --- a/code/parse/lua.cpp +++ b/code/parse/lua.cpp @@ -10738,13 +10738,10 @@ ADE_VIRTVAR(DestroyedByWeapon, l_Weapon, "boolean", "Whether weapon was destroye weapon *wp = &Weapons[oh->objp->instance]; if(ADE_SETTING_VAR && numargs > 1) { - if(b) - wp->weapon_flags |= WF_DESTROYED_BY_WEAPON; - else - wp->weapon_flags &= ~WF_DESTROYED_BY_WEAPON; + wp->weapon_flags.set(Weapon::Weapon_Flags::Destroyed_by_weapon, b); } - return ade_set_args(L, "b", (wp->weapon_flags & WF_DESTROYED_BY_WEAPON) > 0); + return ade_set_args(L, "b", (wp->weapon_flags[Weapon::Weapon_Flags::Destroyed_by_weapon]) > 0); } ADE_VIRTVAR(LifeLeft, l_Weapon, "number", "Weapon life left (in seconds)", "number", "Life left (seconds) or 0 if weapon handle is invalid") diff --git a/code/parse/sexp.cpp b/code/parse/sexp.cpp index 6edd69ab8a..e7b7a654ba 100755 --- a/code/parse/sexp.cpp +++ b/code/parse/sexp.cpp @@ -15142,30 +15142,25 @@ int sexp_primaries_depleted(int node) return SEXP_FALSE; } - // see if ship has ballistic primary weapons - if (!(Ship_info[shipp->ship_info_index].flags[Ship::Info_Flags::Ballistic_primaries])) - return SEXP_FALSE; - // get num primary banks num_banks = shipp->weapons.num_primary_banks; num_depleted_banks = 0; // get number of depleted banks - for (int idx=0; idxweapons.primary_bank_weapons[idx]].wi_flags[Weapon::Info_Flags::Ballistic]) - { - // is this bank out of ammo? - if (shipp->weapons.primary_bank_ammo[idx] == 0) - { - num_depleted_banks++; - } + if (!(Weapon_info[shipp->weapons.primary_bank_weapons[idx]].wi_flags[Weapon::Info_Flags::Ballistic])) { + continue; + } + + // is this bank out of ammo? + if (shipp->weapons.primary_bank_ammo[idx] == 0) { + num_depleted_banks++; } } // are they all depleted? - return (num_depleted_banks == num_banks); + return (num_depleted_banks == num_banks) ? SEXP_TRUE : SEXP_FALSE; } int sexp_secondaries_depleted(int node) @@ -15190,13 +15185,14 @@ int sexp_secondaries_depleted(int node) // get number of depleted banks for (int idx=0; idxweapons.secondary_bank_ammo[idx] == 0) { num_depleted_banks++; } } // are they all depleted? - return (num_depleted_banks == num_banks); + return (num_depleted_banks == num_banks) ? SEXP_TRUE : SEXP_FALSE; } int sexp_facing(int node) diff --git a/code/physics/physics.cpp b/code/physics/physics.cpp index e813823bf2..93940bda45 100644 --- a/code/physics/physics.cpp +++ b/code/physics/physics.cpp @@ -716,7 +716,7 @@ void physics_read_flying_controls( matrix * orient, physics_info * pi, control_i // Only do the glide cap if we have one and are actively thrusting in some direction. // Unless AIPF2_GLIDE_DECAY_REQUIRES_THRUST isn't set. -MageKing17 - if ( curGlideCap >= 0.0f && (!(The_mission.ai_profile->flags2 & AIPF2_GLIDE_DECAY_REQUIRES_THRUST) || ci->forward != 0.0f || ci->sideways != 0.0f || ci->vertical != 0.0f) ) { + if ( curGlideCap >= 0.0f && (!(The_mission.ai_profile->flags[AI::Profile_Flags::Glide_decay_requires_thrust]) || ci->forward != 0.0f || ci->sideways != 0.0f || ci->vertical != 0.0f) ) { float currentmag = vm_vec_mag(&pi->desired_vel); if ( currentmag > curGlideCap ) { vm_vec_scale( &pi->desired_vel, curGlideCap / currentmag ); diff --git a/code/pilotfile/BinaryFileHandler.cpp b/code/pilotfile/BinaryFileHandler.cpp new file mode 100644 index 0000000000..8165308705 --- /dev/null +++ b/code/pilotfile/BinaryFileHandler.cpp @@ -0,0 +1,89 @@ + +#include "pilotfile/BinaryFileHandler.h" + +pilot::BinaryFileHandler::BinaryFileHandler(CFILE* cfp) : _cfp(cfp) { + Assertion(cfp != nullptr, "File pointer must be valid!"); +} + +pilot::BinaryFileHandler::~BinaryFileHandler() { + cfclose(_cfp); + _cfp = nullptr; +} + +void pilot::BinaryFileHandler::writeUByte(const char*, std::uint8_t value) { + cfwrite_ubyte(value, _cfp); +} +void pilot::BinaryFileHandler::writeShort(const char*, std::int16_t value) { + cfwrite_short(value, _cfp); +} + +void pilot::BinaryFileHandler::writeInt(const char*, std::int32_t value) { + cfwrite_int(value, _cfp); +} + +void pilot::BinaryFileHandler::writeUInt(const char*, std::uint32_t value) { + cfwrite_uint(value, _cfp); +} + +void pilot::BinaryFileHandler::writeFloat(const char*, float value) { + cfwrite_float(value, _cfp); +} + +void pilot::BinaryFileHandler::writeString(const char*, const char* str) { + cfwrite_string_len(str, _cfp); +} + +void pilot::BinaryFileHandler::startSectionWrite(Section id) { + if (id == Section::Unnamed) { + _sectionOffsets.push_back({id, 0}); + return; + } + + cfwrite_ushort((ushort) id, _cfp); + + // to be updated when endSection() is called + cfwrite_int(0, _cfp); + + // starting offset, for size of section + _sectionOffsets.push_back({id, (size_t)cftell(_cfp)}); +} + +void pilot::BinaryFileHandler::endSectionWrite() { + Assertion(!_sectionOffsets.empty(), "No active section!"); + auto previous_off = _sectionOffsets.back(); + + if (previous_off.id == Section::Unnamed) { + // ignore unnamed sections, these are only needed for JSON + return; + } + + + size_t cur = (size_t) cftell(_cfp); + _sectionOffsets.pop_back(); + + Assert(cur >= previous_off.offset); + + size_t section_size = cur - previous_off.offset; + + if (section_size) { + // go back to section size in file and write proper value + cfseek(_cfp, (int) (cur - section_size - sizeof(int)), CF_SEEK_SET); + cfwrite_int((int) section_size, _cfp); + + // go back to previous location for next section + cfseek(_cfp, (int) cur, CF_SEEK_SET); + } +} +void pilot::BinaryFileHandler::startArrayWrite(const char*, size_t size, bool short_index) { + if (short_index) { + cfwrite_ushort((short)size, _cfp); + } else { + cfwrite_int((int)size, _cfp); + } +} +void pilot::BinaryFileHandler::endArrayWrite() { + // Nothing to do here for the binary version +} +void pilot::BinaryFileHandler::flush() { + cflush(_cfp); +} diff --git a/code/pilotfile/BinaryFileHandler.h b/code/pilotfile/BinaryFileHandler.h new file mode 100644 index 0000000000..e83da02ba8 --- /dev/null +++ b/code/pilotfile/BinaryFileHandler.h @@ -0,0 +1,53 @@ + +#ifndef BINARY_FILE_HANDLER_H +#define BINARY_FILE_HANDLER_H +#pragma once + +#include "pilotfile/FileHandler.h" + +#include "globalincs/pstypes.h" +#include "cfile/cfile.h" + +namespace pilot { +class BinaryFileHandler: public FileHandler { + CFILE* _cfp; + + struct SectionOffset { + Section id; + size_t offset; + }; + + SCP_vector _sectionOffsets; + public: + explicit BinaryFileHandler(CFILE* cfp); + + ~BinaryFileHandler() override; + + void writeUByte(const char* name, std::uint8_t value) override; + + void writeShort(const char* name, std::int16_t value) override; + + void writeInt(const char* name, std::int32_t value) override; + + void writeUInt(const char* name, std::uint32_t value) override; + + void writeFloat(const char* name, float value) override; + + void writeString(const char* name, const char* str) override; + + + void startSectionWrite(Section id) override; + + void endSectionWrite() override; + + + void startArrayWrite(const char* name, size_t size, bool short_length = false) override; + + void endArrayWrite() override; + + + virtual void flush() override; +}; +} + +#endif // BINARY_FILE_HANDLER_H diff --git a/code/pilotfile/FileHandler.h b/code/pilotfile/FileHandler.h new file mode 100644 index 0000000000..966874f827 --- /dev/null +++ b/code/pilotfile/FileHandler.h @@ -0,0 +1,68 @@ + +#ifndef FILEHANDLER_H +#define FILEHANDLER_H +#pragma once + +#include +#include + +#include "globalincs/pstypes.h" + +#if SCP_COMPILER_IS_GNU +#pragma GCC diagnostic push +// This suppresses a GCC bug where it thinks that the Cutscenes from the enum class below shadows a global variable +#pragma GCC diagnostic ignored "-Wshadow" +#endif +// sections of a pilot file. includes both plr and csg sections +enum class Section { + Unnamed = 0, //!< Special unnamed section + Flags = 0x0001, + Info = 0x0002, + Loadout = 0x0003, + Controls = 0x0004, + Multiplayer = 0x0005, + Scoring = 0x0006, + ScoringMulti = 0x0007, + Techroom = 0x0008, + HUD = 0x0009, + Settings = 0x0010, + RedAlert = 0x0011, + Variables = 0x0012, + Missions = 0x0013, + Cutscenes = 0x0014, + LastMissions = 0x0015 +}; +#if SCP_COMPILER_IS_GNU +#pragma GCC diagnostic pop +#endif + +namespace pilot { +class FileHandler { + public: + virtual ~FileHandler() {} + + virtual void writeUByte(const char* name, std::uint8_t value) = 0; + + virtual void writeShort(const char* name, std::int16_t value) = 0; + + virtual void writeInt(const char* name, std::int32_t value) = 0; + + virtual void writeUInt(const char* name, std::uint32_t value) = 0; + + virtual void writeFloat(const char* name, float value) = 0; + + virtual void writeString(const char* name, const char* str) = 0; + + virtual void startSectionWrite(Section id) = 0; + + virtual void endSectionWrite() = 0; + + virtual void startArrayWrite(const char* name, size_t size, bool short_length = false) = 0; + + virtual void endArrayWrite() = 0; + + virtual void flush() = 0; +}; +} + +#endif // FILEHANDLER_H diff --git a/code/pilotfile/JSONFileHandler.cpp b/code/pilotfile/JSONFileHandler.cpp new file mode 100644 index 0000000000..50c7c276e4 --- /dev/null +++ b/code/pilotfile/JSONFileHandler.cpp @@ -0,0 +1,146 @@ + +#include "pilotfile/JSONFileHandler.h" + +namespace { +int json_write_callback(const char *buffer, size_t size, void *data) { + CFILE* cfp = (CFILE*)data; + + if (cfwrite(buffer, 1, (int)size, cfp) != size) { + return -1; // Error + } else { + return 0; // Success + } +} + +const SCP_vector> SectionMapping { + std::pair(Section::Unnamed, nullptr), + std::pair(Section::Flags, "flags"), + std::pair(Section::Info, "info"), + std::pair(Section::Loadout, "loadout"), + std::pair(Section::Controls, "controls"), + std::pair(Section::Multiplayer, "multiplayer"), + std::pair(Section::Scoring, "scoring"), + std::pair(Section::ScoringMulti, "scoring_multi"), + std::pair(Section::Techroom, "techroom"), + std::pair(Section::HUD, "hud"), + std::pair(Section::Settings, "settings"), + std::pair(Section::RedAlert, "red_alert"), + std::pair(Section::Variables, "variables"), + std::pair(Section::Missions, "missions"), + std::pair(Section::Cutscenes, "cutscenes"), + std::pair(Section::LastMissions, "last_mission") +}; + +const char* lookupSectionName(Section s) { + for (auto& pair : SectionMapping) { + if (pair.first == s) { + return pair.second; + } + } + Assertion(false, "Unknown section!"); + return nullptr; +} + +Section lookupSectionValue(const char* name) { + for (auto& pair : SectionMapping) { + if (!strcmp(pair.second, name)) { + return pair.first; + } + } + Assertion(false, "Unknown section name!"); + return Section::Unnamed; +} +} + +pilot::JSONFileHandler::JSONFileHandler(CFILE* cfp) : _cfp(cfp) { + Assertion(cfp != nullptr, "File pointer must be valid!"); + + _rootObj = json_object(); + _currentEl = _rootObj; + _elementStack.push_back(_currentEl); +} + +pilot::JSONFileHandler::~JSONFileHandler() { + json_decref(_rootObj); + + cfclose(_cfp); + _cfp = nullptr; +} +void pilot::JSONFileHandler::writeUByte(const char* name, std::uint8_t value) { + writeInteger(name, value); +} +void pilot::JSONFileHandler::writeShort(const char* name, std::int16_t value) { + writeInteger(name, value); +} +void pilot::JSONFileHandler::writeInt(const char* name, std::int32_t value) { + writeInteger(name, value); +} +void pilot::JSONFileHandler::writeUInt(const char* name, std::uint32_t value) { + writeInteger(name, value); +} +void pilot::JSONFileHandler::writeFloat(const char* name, float value) { + ensureNotExists(name); + json_object_set_new(_currentEl, name, json_real(value)); +} +void pilot::JSONFileHandler::writeString(const char* name, const char* str) { + ensureNotExists(name); + json_object_set_new(_currentEl, name, json_string(str)); +} +void pilot::JSONFileHandler::startSectionWrite(Section id) { + auto key_name = lookupSectionName(id); + + json_t* obj = json_object(); + + if (json_is_array(_currentEl)) { + // We are in an array, section must be unnamed + Assertion(key_name == nullptr, "Inside an array there can be no named section!"); + json_array_append_new(_currentEl, obj); + } else { + Assertion(key_name != nullptr, "Section outside of arrays must be named!"); + json_object_set_new(_currentEl, key_name, obj); + } + _currentEl = obj; + _elementStack.push_back(_currentEl); +} +void pilot::JSONFileHandler::endSectionWrite() { + Assertion(json_is_object(_currentEl), "Section ended while not in a section!"); + + _elementStack.pop_back(); + _currentEl = _elementStack.back(); +} +void pilot::JSONFileHandler::startArrayWrite(const char* name, size_t, bool) { + auto array = json_array(); + + if (json_is_array(_currentEl)) { + // We are in an array, section must be unnamed + Assertion(name == nullptr, "Inside an array there can be no named section!"); + json_array_append_new(_currentEl, array); + } else { + Assertion(name != nullptr, "Section outside of arrays must be named!"); + json_object_set_new(_currentEl, name, array); + } + _currentEl = array; + _elementStack.push_back(_currentEl); +} +void pilot::JSONFileHandler::endArrayWrite() { + Assertion(json_is_array(_currentEl), "Array ended while not in an array!"); + + _elementStack.pop_back(); + _currentEl = _elementStack.back(); +} +void pilot::JSONFileHandler::flush() { + Assertion(_elementStack.size() == 1, "Not all sections or arrays have been ended!"); + + json_dump_callback(_rootObj, json_write_callback, _cfp, JSON_INDENT(4)); +} +void pilot::JSONFileHandler::writeInteger(const char* name, json_int_t val) { + ensureNotExists(name); + + json_object_set_new(_currentEl, name, json_integer(val)); +} +void pilot::JSONFileHandler::ensureNotExists(const char* name) { + Assertion(json_is_object(_currentEl), "Currently not in an element that supports keys!"); + // Make sure we don't overwrite previous values + Assertion(json_object_get(_currentEl, name) == nullptr, "Entry with name %s already exists!", name); +} + diff --git a/code/pilotfile/JSONFileHandler.h b/code/pilotfile/JSONFileHandler.h new file mode 100644 index 0000000000..25818d9d7c --- /dev/null +++ b/code/pilotfile/JSONFileHandler.h @@ -0,0 +1,56 @@ + +#ifndef JSON_FILE_HANDLER_H +#define JSON_FILE_HANDLER_H +#pragma once + +#include "pilotfile/FileHandler.h" + +#include "globalincs/pstypes.h" +#include "cfile/cfile.h" + +#include + +namespace pilot { +class JSONFileHandler: public FileHandler { + CFILE* _cfp; + + json_t* _rootObj; + + json_t* _currentEl; + + SCP_vector _elementStack; + + void ensureNotExists(const char* name); + void writeInteger(const char* name, json_int_t value); + public: + explicit JSONFileHandler(CFILE* cfp); + + ~JSONFileHandler() override; + + void writeUByte(const char* name, std::uint8_t value) override; + + void writeShort(const char* name, std::int16_t value) override; + + void writeInt(const char* name, std::int32_t value) override; + + void writeUInt(const char* name, std::uint32_t value) override; + + void writeFloat(const char* name, float value) override; + + void writeString(const char* name, const char* str) override; + + + void startSectionWrite(Section id) override; + + void endSectionWrite() override; + + + void startArrayWrite(const char* name, size_t size, bool short_length = false) override; + + void endArrayWrite() override; + + void flush() override; +}; +} + +#endif // JSON_FILE_HANDLER_H diff --git a/code/pilotfile/csg.cpp b/code/pilotfile/csg.cpp index 51bd1e409d..947ad43b5d 100644 --- a/code/pilotfile/csg.cpp +++ b/code/pilotfile/csg.cpp @@ -1408,7 +1408,7 @@ bool pilotfile::load_savefile(const char *campaign) // the point of all this: read in the CSG contents while ( !cfeof(cfp) ) { - ushort section_id = cfread_ushort(cfp); + Section section_id = static_cast
(cfread_ushort(cfp)); uint section_size = cfread_uint(cfp); size_t start_pos = cftell(cfp); @@ -1647,7 +1647,7 @@ bool pilotfile::get_csg_rank(int *rank) // the point of all this: read in the CSG contents while ( !m_have_flags && !cfeof(cfp) ) { - ushort section_id = cfread_ushort(cfp); + Section section_id = static_cast
(cfread_ushort(cfp)); uint section_size = cfread_uint(cfp); size_t start_pos = cftell(cfp); diff --git a/code/pilotfile/pilotfile.cpp b/code/pilotfile/pilotfile.cpp index 5291d8d0a2..72faa18c3b 100644 --- a/code/pilotfile/pilotfile.cpp +++ b/code/pilotfile/pilotfile.cpp @@ -27,7 +27,7 @@ pilotfile::~pilotfile() } } -void pilotfile::startSection(Section::id section_id) +void pilotfile::startSection(Section section_id) { Assert( cfp ); diff --git a/code/pilotfile/pilotfile.h b/code/pilotfile/pilotfile.h index 25f1906d5a..9505ef5038 100644 --- a/code/pilotfile/pilotfile.h +++ b/code/pilotfile/pilotfile.h @@ -5,7 +5,9 @@ #include "cfile/cfile.h" #include "globalincs/pstypes.h" #include "stats/scoring.h" +#include "pilotfile/FileHandler.h" +#include class player; @@ -60,6 +62,7 @@ class pilotfile { // info shared between PLR and CSG ... // -------------------------------------------------------------------- CFILE *cfp; + std::unique_ptr handler; SCP_string filename; player *p; @@ -129,29 +132,8 @@ class pilotfile { scoring_special_t all_time_stats; scoring_special_t multi_stats; - // sections of a pilot file. includes both plr and csg sections - struct Section { - enum id { - Flags = 0x0001, - Info = 0x0002, - Loadout = 0x0003, - Controls = 0x0004, - Multiplayer = 0x0005, - Scoring = 0x0006, - ScoringMulti = 0x0007, - Techroom = 0x0008, - HUD = 0x0009, - Settings = 0x0010, - RedAlert = 0x0011, - Variables = 0x0012, - Missions = 0x0013, - Cutscenes = 0x0014, - LastMissions = 0x0015 - }; - }; - // for writing files, sets/updates section info - void startSection(Section::id section_id); + void startSection(Section section_id); void endSection(); // file offset of the size value for the current section (set with startSection()) size_t m_size_offset; diff --git a/code/pilotfile/plr.cpp b/code/pilotfile/plr.cpp index 13a1d31030..c233e0c240 100644 --- a/code/pilotfile/plr.cpp +++ b/code/pilotfile/plr.cpp @@ -10,6 +10,8 @@ #include "network/multi.h" #include "osapi/osregistry.h" #include "pilotfile/pilotfile.h" +#include "pilotfile/BinaryFileHandler.h" +#include "pilotfile/JSONFileHandler.h" #include "playerman/managepilot.h" #include "playerman/player.h" #include "ship/ship.h" @@ -56,31 +58,31 @@ void pilotfile::plr_read_flags() void pilotfile::plr_write_flags() { - startSection(Section::Flags); + handler->startSectionWrite(Section::Flags); // tips - cfwrite_ubyte((unsigned char)p->tips, cfp); + handler->writeUByte("tips", (unsigned char)p->tips); // saved flags - cfwrite_int(p->save_flags, cfp); + handler->writeInt("save_flags", p->save_flags); // listing mode (single or campaign missions) - cfwrite_int(p->readyroom_listing_mode, cfp); + handler->writeInt("readyroom_listing_mode", p->readyroom_listing_mode); // briefing auto-play - cfwrite_int(p->auto_advance, cfp); + handler->writeInt("auto_advance", p->auto_advance); // special rank setting (to avoid having to read all stats on verify) // should be multi only from now on - cfwrite_int(multi_stats.rank, cfp); + handler->writeInt("multi_rank", multi_stats.rank); // What game mode we were in last on this pilot - cfwrite_int(p->player_was_multi, cfp); + handler->writeInt("was_multi", p->player_was_multi); // which language was this pilot created with - cfwrite_string_len(p->language, cfp); + handler->writeString("language", p->language); - endSection(); + handler->endSectionWrite(); } void pilotfile::plr_read_info() @@ -104,21 +106,21 @@ void pilotfile::plr_read_info() void pilotfile::plr_write_info() { - startSection(Section::Info); + handler->startSectionWrite(Section::Info); // pilot image - cfwrite_string_len(p->image_filename, cfp); + handler->writeString("image_filename", p->image_filename); // multi squad name - cfwrite_string_len(p->m_squad_name, cfp); + handler->writeString("squad_name", p->m_squad_name); // squad image - cfwrite_string_len(p->m_squad_filename, cfp); + handler->writeString("squad_filename", p->m_squad_filename); // active campaign - cfwrite_string_len(p->current_campaign, cfp); + handler->writeString("current_campaign", p->current_campaign); - endSection(); + handler->endSectionWrite(); } void pilotfile::plr_read_hud() @@ -172,36 +174,40 @@ void pilotfile::plr_write_hud() { int idx; - startSection(Section::HUD); + handler->startSectionWrite(Section::HUD); // flags - cfwrite_int(HUD_config.show_flags, cfp); - cfwrite_int(HUD_config.show_flags2, cfp); + handler->writeInt("show_flags", HUD_config.show_flags); + handler->writeInt("show_flags2", HUD_config.show_flags2); - cfwrite_int(HUD_config.popup_flags, cfp); - cfwrite_int(HUD_config.popup_flags2, cfp); + handler->writeInt("popup_flags", HUD_config.popup_flags); + handler->writeInt("popup_flags2", HUD_config.popup_flags2); // settings - cfwrite_ubyte(HUD_config.num_msg_window_lines, cfp); + handler->writeUByte("num_msg_window_lines", HUD_config.num_msg_window_lines); - cfwrite_int(HUD_config.rp_flags, cfp); - cfwrite_int(HUD_config.rp_dist, cfp); + handler->writeInt("rp_flags", HUD_config.rp_flags); + handler->writeInt("rp_dist", HUD_config.rp_dist); // basic colors - cfwrite_int(HUD_config.main_color, cfp); - cfwrite_int(HUD_color_alpha, cfp); + handler->writeInt("main_color", HUD_config.main_color); + handler->writeInt("color_alpha", HUD_color_alpha); // gauge-specific colors - cfwrite_int(NUM_HUD_GAUGES, cfp); - + handler->startArrayWrite("hud_gauges", NUM_HUD_GAUGES); for (idx = 0; idx < NUM_HUD_GAUGES; idx++) { - cfwrite_ubyte(HUD_config.clr[idx].red, cfp); - cfwrite_ubyte(HUD_config.clr[idx].green, cfp); - cfwrite_ubyte(HUD_config.clr[idx].blue, cfp); - cfwrite_ubyte(HUD_config.clr[idx].alpha, cfp); - } + handler->startSectionWrite(Section::Unnamed); - endSection(); + handler->writeUByte("red", HUD_config.clr[idx].red); + handler->writeUByte("green", HUD_config.clr[idx].green); + handler->writeUByte("blue", HUD_config.clr[idx].blue); + handler->writeUByte("alpha", HUD_config.clr[idx].alpha); + + handler->endSectionWrite(); + } + handler->endArrayWrite(); + + handler->endSectionWrite(); } void pilotfile::plr_read_variables() @@ -229,22 +235,21 @@ void pilotfile::plr_read_variables() void pilotfile::plr_write_variables() { - int list_size = 0; - int idx; + handler->startSectionWrite(Section::Variables); - startSection(Section::Variables); + handler->startArrayWrite("variables", p->variables.size()); + for (auto& var : p->variables) { + handler->startSectionWrite(Section::Unnamed); - list_size = (int)p->variables.size(); + handler->writeInt("type", var.type); + handler->writeString("text", var.text); + handler->writeString("variable_name", var.variable_name); - cfwrite_int(list_size, cfp); - - for (idx = 0; idx < list_size; idx++) { - cfwrite_int(p->variables[idx].type, cfp); - cfwrite_string_len(p->variables[idx].text, cfp); - cfwrite_string_len(p->variables[idx].variable_name, cfp); + handler->endSectionWrite(); } + handler->endArrayWrite(); - endSection(); + handler->endSectionWrite(); } void pilotfile::plr_read_multiplayer() @@ -276,29 +281,29 @@ void pilotfile::plr_read_multiplayer() void pilotfile::plr_write_multiplayer() { - startSection(Section::Multiplayer); + handler->startSectionWrite(Section::Multiplayer); // netgame options - cfwrite_ubyte(p->m_server_options.squad_set, cfp); - cfwrite_ubyte(p->m_server_options.endgame_set, cfp); - cfwrite_int(p->m_server_options.flags, cfp); - cfwrite_uint(p->m_server_options.respawn, cfp); - cfwrite_ubyte(p->m_server_options.max_observers, cfp); - cfwrite_ubyte(p->m_server_options.skill_level, cfp); - cfwrite_ubyte(p->m_server_options.voice_qos, cfp); - cfwrite_int(p->m_server_options.voice_token_wait, cfp); - cfwrite_int(p->m_server_options.voice_record_time, cfp); - cfwrite_int((int)p->m_server_options.mission_time_limit, cfp); - cfwrite_int(p->m_server_options.kill_limit, cfp); + handler->writeUByte("squad_set", p->m_server_options.squad_set); + handler->writeUByte("endgame_set", p->m_server_options.endgame_set); + handler->writeInt("server_flags", p->m_server_options.flags); + handler->writeUInt("respawn", p->m_server_options.respawn); + handler->writeUByte("max_observers", p->m_server_options.max_observers); + handler->writeUByte("skill_level", p->m_server_options.skill_level); + handler->writeUByte("voice_qos", p->m_server_options.voice_qos); + handler->writeInt("voice_token_wait", p->m_server_options.voice_token_wait); + handler->writeInt("voice_record_time", p->m_server_options.voice_record_time); + handler->writeInt("mission_time_limit", (int)p->m_server_options.mission_time_limit); + handler->writeInt("kill_limit", p->m_server_options.kill_limit); // local options - cfwrite_int(p->m_local_options.flags, cfp); - cfwrite_int(p->m_local_options.obj_update_level, cfp); + handler->writeInt("local_flags", p->m_local_options.flags); + handler->writeInt("obj_update_level", p->m_local_options.obj_update_level); // netgame protocol - cfwrite_int(Multi_options_g.protocol, cfp); + handler->writeInt("protocol", Multi_options_g.protocol); - endSection(); + handler->endSectionWrite(); } void pilotfile::plr_read_stats() @@ -402,50 +407,50 @@ void pilotfile::plr_read_stats() void pilotfile::plr_write_stats() { - int idx, list_size = 0; - - startSection(Section::Scoring); + handler->startSectionWrite(Section::Scoring); // global, all-time stats - cfwrite_int(all_time_stats.score, cfp); - cfwrite_int(all_time_stats.rank, cfp); - cfwrite_int(all_time_stats.assists, cfp); - cfwrite_int(all_time_stats.kill_count, cfp); - cfwrite_int(all_time_stats.kill_count_ok, cfp); - cfwrite_int(all_time_stats.bonehead_kills, cfp); + handler->writeInt("score", all_time_stats.score); + handler->writeInt("rank", all_time_stats.rank); + handler->writeInt("assists", all_time_stats.assists); + handler->writeInt("kill_count", all_time_stats.kill_count); + handler->writeInt("kill_count_ok", all_time_stats.kill_count_ok); + handler->writeInt("bonehead_kills", all_time_stats.bonehead_kills); - cfwrite_uint(all_time_stats.p_shots_fired, cfp); - cfwrite_uint(all_time_stats.p_shots_hit, cfp); - cfwrite_uint(all_time_stats.p_bonehead_hits, cfp); + handler->writeUInt("p_shots_fired", all_time_stats.p_shots_fired); + handler->writeUInt("p_shots_hit", all_time_stats.p_shots_hit); + handler->writeUInt("p_bonehead_hits", all_time_stats.p_bonehead_hits); - cfwrite_uint(all_time_stats.s_shots_fired, cfp); - cfwrite_uint(all_time_stats.s_shots_hit, cfp); - cfwrite_uint(all_time_stats.s_bonehead_hits, cfp); + handler->writeUInt("s_shots_fired", all_time_stats.s_shots_fired); + handler->writeUInt("s_shots_hit", all_time_stats.s_shots_hit); + handler->writeUInt("s_bonehead_hits", all_time_stats.s_bonehead_hits); - cfwrite_uint(all_time_stats.flight_time, cfp); - cfwrite_uint(all_time_stats.missions_flown, cfp); - cfwrite_int((int)all_time_stats.last_flown, cfp); - cfwrite_int((int)all_time_stats.last_backup, cfp); + handler->writeUInt("flight_time", all_time_stats.flight_time); + handler->writeUInt("missions_flown", all_time_stats.missions_flown); + handler->writeInt("last_flown", (int)all_time_stats.last_flown); + handler->writeInt("last_backup", (int)all_time_stats.last_backup); // ship kills (contains ships across all mods, not just current) - list_size = (int)all_time_stats.ship_kills.size(); - cfwrite_int(list_size, cfp); - - for (idx = 0; idx < list_size; idx++) { - cfwrite_string_len(all_time_stats.ship_kills[idx].name.c_str(), cfp); - cfwrite_int(all_time_stats.ship_kills[idx].val, cfp); + handler->startArrayWrite("kills", all_time_stats.ship_kills.size()); + for (auto& kill : all_time_stats.ship_kills) { + handler->startSectionWrite(Section::Unnamed); + handler->writeString("name", kill.name.c_str()); + handler->writeInt("val", kill.val); + handler->endSectionWrite(); } + handler->endArrayWrite(); // medals earned (contains medals across all mods, not just current) - list_size = (int)all_time_stats.medals_earned.size(); - cfwrite_int(list_size, cfp); - - for (idx = 0; idx < list_size; idx++) { - cfwrite_string_len(all_time_stats.medals_earned[idx].name.c_str(), cfp); - cfwrite_int(all_time_stats.medals_earned[idx].val, cfp); + handler->startArrayWrite("medals", all_time_stats.medals_earned.size()); + for (auto& medal : all_time_stats.medals_earned) { + handler->startSectionWrite(Section::Unnamed); + handler->writeString("name", medal.name.c_str()); + handler->writeInt("val", medal.val); + handler->endSectionWrite(); } + handler->endArrayWrite(); - endSection(); + handler->endSectionWrite(); } void pilotfile::plr_read_stats_multi() @@ -549,50 +554,48 @@ void pilotfile::plr_read_stats_multi() void pilotfile::plr_write_stats_multi() { - int idx, list_size = 0; - - startSection(Section::ScoringMulti); + handler->startSectionWrite(Section::ScoringMulti); // global, all-time stats - cfwrite_int(multi_stats.score, cfp); - cfwrite_int(multi_stats.rank, cfp); - cfwrite_int(multi_stats.assists, cfp); - cfwrite_int(multi_stats.kill_count, cfp); - cfwrite_int(multi_stats.kill_count_ok, cfp); - cfwrite_int(multi_stats.bonehead_kills, cfp); + handler->writeInt("score", multi_stats.score); + handler->writeInt("rank", multi_stats.rank); + handler->writeInt("assists", multi_stats.assists); + handler->writeInt("kill_count", multi_stats.kill_count); + handler->writeInt("kill_count_ok", multi_stats.kill_count_ok); + handler->writeInt("bonehead_kills", multi_stats.bonehead_kills); - cfwrite_uint(multi_stats.p_shots_fired, cfp); - cfwrite_uint(multi_stats.p_shots_hit, cfp); - cfwrite_uint(multi_stats.p_bonehead_hits, cfp); + handler->writeUInt("p_shots_fired", multi_stats.p_shots_fired); + handler->writeUInt("p_shots_hit", multi_stats.p_shots_hit); + handler->writeUInt("p_bonehead_hits", multi_stats.p_bonehead_hits); - cfwrite_uint(multi_stats.s_shots_fired, cfp); - cfwrite_uint(multi_stats.s_shots_hit, cfp); - cfwrite_uint(multi_stats.s_bonehead_hits, cfp); + handler->writeUInt("s_shots_fired", multi_stats.s_shots_fired); + handler->writeUInt("s_shots_hit", multi_stats.s_shots_hit); + handler->writeUInt("s_bonehead_hits", multi_stats.s_bonehead_hits); - cfwrite_uint(multi_stats.flight_time, cfp); - cfwrite_uint(multi_stats.missions_flown, cfp); - cfwrite_int((int)multi_stats.last_flown, cfp); - cfwrite_int((int)multi_stats.last_backup, cfp); + handler->writeUInt("flight_time", multi_stats.flight_time); + handler->writeUInt("missions_flown", multi_stats.missions_flown); + handler->writeInt("last_flown", (int)multi_stats.last_flown); + handler->writeInt("last_backup", (int)multi_stats.last_backup); // ship kills (contains medals across all mods, not just current) - list_size = (int)multi_stats.ship_kills.size(); - cfwrite_int(list_size, cfp); - - for (idx = 0; idx < list_size; idx++) { - cfwrite_string_len(multi_stats.ship_kills[idx].name.c_str(), cfp); - cfwrite_int(multi_stats.ship_kills[idx].val, cfp); + handler->startArrayWrite("kills", multi_stats.ship_kills.size()); + for (auto& kill : multi_stats.ship_kills) { + handler->startSectionWrite(Section::Unnamed); + handler->writeString("name", kill.name.c_str()); + handler->writeInt("val", kill.val); + handler->endSectionWrite(); } + handler->endArrayWrite(); // medals earned (contains medals across all mods, not just current) - list_size = (int)multi_stats.medals_earned.size(); - cfwrite_int(list_size, cfp); - - for (idx = 0; idx < list_size; idx++) { - cfwrite_string_len(multi_stats.medals_earned[idx].name.c_str(), cfp); - cfwrite_int(multi_stats.medals_earned[idx].val, cfp); + handler->startArrayWrite("medals", multi_stats.medals_earned.size()); + for (auto& medal : multi_stats.medals_earned) { + handler->writeString("name", medal.name.c_str()); + handler->writeInt("val", medal.val); } + handler->endArrayWrite(); - endSection(); + handler->endSectionWrite(); } void pilotfile::plr_read_controls() @@ -627,27 +630,34 @@ void pilotfile::plr_read_controls() void pilotfile::plr_write_controls() { - int idx; + handler->startSectionWrite(Section::Controls); - startSection(Section::Controls); + // For some unknown reason, the old code used a short for the array length here... + handler->startArrayWrite("controls", CCFG_MAX, true); + for (size_t idx = 0; idx < CCFG_MAX; idx++) { + handler->startSectionWrite(Section::Unnamed); - cfwrite_ushort(CCFG_MAX, cfp); - - for (idx = 0; idx < CCFG_MAX; idx++) { - cfwrite_short(Control_config[idx].key_id, cfp); - cfwrite_short(Control_config[idx].joy_id, cfp); + handler->writeShort("key", Control_config[idx].key_id); + handler->writeShort("joystick", Control_config[idx].joy_id); // placeholder? for future mouse_id? - cfwrite_short(-1, cfp); + handler->writeShort("mouse", -1); + + handler->endSectionWrite(); } + handler->endArrayWrite(); - cfwrite_int(NUM_JOY_AXIS_ACTIONS, cfp); + handler->startArrayWrite("axes", NUM_JOY_AXIS_ACTIONS); + for (size_t idx = 0; idx < NUM_JOY_AXIS_ACTIONS; idx++) { + handler->startSectionWrite(Section::Unnamed); - for (idx = 0; idx < NUM_JOY_AXIS_ACTIONS; idx++) { - cfwrite_int(Axis_map_to[idx], cfp); - cfwrite_int(Invert_axis[idx], cfp); + handler->writeInt("axis_map", Axis_map_to[idx]); + handler->writeInt("invert_axis", Invert_axis[idx]); + + handler->endSectionWrite(); } + handler->endArrayWrite(); - endSection(); + handler->endSectionWrite(); } void pilotfile::plr_read_settings() @@ -694,39 +704,39 @@ void pilotfile::plr_read_settings() void pilotfile::plr_write_settings() { - startSection(Section::Settings); + handler->startSectionWrite(Section::Settings); // sound/voice/music - cfwrite_float(Master_sound_volume, cfp); - cfwrite_float(Master_event_music_volume, cfp); - cfwrite_float(Master_voice_volume, cfp); + handler->writeFloat("master_sound_volume", Master_sound_volume); + handler->writeFloat("master_event_music_volume", Master_event_music_volume); + handler->writeFloat("aster_voice_volume", Master_voice_volume); - cfwrite_int(Briefing_voice_enabled, cfp); + handler->writeInt("briefing_voice_enabled", Briefing_voice_enabled); // skill level - cfwrite_int(Game_skill_level, cfp); + handler->writeInt("game_skill_level", Game_skill_level); // input options - cfwrite_int(Use_mouse_to_fly, cfp); - cfwrite_int(Mouse_sensitivity, cfp); - cfwrite_int(Joy_sensitivity, cfp); - cfwrite_int(Joy_dead_zone_size, cfp); + handler->writeInt("use_mouse_to_fly", Use_mouse_to_fly); + handler->writeInt("mouse_sensitivity", Mouse_sensitivity); + handler->writeInt("joy_sensitivity", Joy_sensitivity); + handler->writeInt("joy_dead_zone_size", Joy_dead_zone_size); // detail - cfwrite_int(Detail.setting, cfp); - cfwrite_int(Detail.nebula_detail, cfp); - cfwrite_int(Detail.detail_distance, cfp); - cfwrite_int(Detail.hardware_textures, cfp); - cfwrite_int(Detail.num_small_debris, cfp); - cfwrite_int(Detail.num_particles, cfp); - cfwrite_int(Detail.num_stars, cfp); - cfwrite_int(Detail.shield_effects, cfp); - cfwrite_int(Detail.lighting, cfp); - cfwrite_int(Detail.targetview_model, cfp); - cfwrite_int(Detail.planets_suns, cfp); - cfwrite_int(Detail.weapon_extras, cfp); + handler->writeInt("setting", Detail.setting); + handler->writeInt("nebula_detail", Detail.nebula_detail); + handler->writeInt("detail_distance", Detail.detail_distance); + handler->writeInt("hardware_textures", Detail.hardware_textures); + handler->writeInt("num_small_debris", Detail.num_small_debris); + handler->writeInt("num_particles", Detail.num_particles); + handler->writeInt("num_stars", Detail.num_stars); + handler->writeInt("shield_effects", Detail.shield_effects); + handler->writeInt("lighting", Detail.lighting); + handler->writeInt("targetview_model", Detail.targetview_model); + handler->writeInt("planets_suns", Detail.planets_suns); + handler->writeInt("weapon_extras", Detail.weapon_extras); - endSection(); + handler->endSectionWrite(); } void pilotfile::plr_reset_data() @@ -763,6 +773,9 @@ void pilotfile::plr_close() cfclose(cfp); cfp = NULL; } + if (handler) { + handler.reset(); + } p = NULL; filename = ""; @@ -828,7 +841,7 @@ bool pilotfile::load_player(const char *callsign, player *_p) // the point of all this: read in the PLR contents while ( !cfeof(cfp) ) { - ushort section_id = cfread_ushort(cfp); + Section section_id = static_cast
(cfread_ushort(cfp)); uint section_size = cfread_uint(cfp); size_t start_pos = cftell(cfp); @@ -952,24 +965,34 @@ bool pilotfile::save_player(player *_p) } filename = p->callsign; - filename += ".plr"; - - if ( filename.size() == 4 ) { + if ( filename.empty() ) { mprintf(("PLR => Invalid filename '%s'!\n", filename.c_str())); return false; } - // open it, hopefully... - cfp = cfopen((char*)filename.c_str(), "wb", CFILE_NORMAL, CF_TYPE_PLAYERS); + if (Cmdline_json_pilot) { + filename += ".json"; + } else { + filename += ".plr"; + } - if ( !cfp ) { + // open it, hopefully... + auto fp = cfopen((char*)filename.c_str(), "wb", CFILE_NORMAL, CF_TYPE_PLAYERS); + + if ( !fp ) { mprintf(("PLR => Unable to open '%s' for saving!\n", filename.c_str())); return false; } + if (Cmdline_json_pilot) { + handler.reset(new pilot::JSONFileHandler(fp)); + } else { + handler.reset(new pilot::BinaryFileHandler(fp)); + } + // header and version - cfwrite_int(PLR_FILE_ID, cfp); - cfwrite_ubyte(PLR_VERSION, cfp); + handler->writeInt("signature", PLR_FILE_ID); + handler->writeUByte("version", PLR_VERSION); mprintf(("PLR => Saving '%s' with version %d...\n", filename.c_str(), (int)PLR_VERSION)); @@ -995,6 +1018,8 @@ bool pilotfile::save_player(player *_p) mprintf(("PLR => Saving: Settings...\n")); plr_write_settings(); + handler->flush(); + // Done! mprintf(("PLR => Saving complete!\n")); @@ -1039,7 +1064,7 @@ bool pilotfile::verify(const char *fname, int *rank, char *valid_language) // the point of all this: read in the PLR contents while ( !(m_have_flags && m_have_info) && !cfeof(cfp) ) { - ushort section_id = cfread_ushort(cfp); + Section section_id = static_cast
(cfread_ushort(cfp)); uint section_size = cfread_uint(cfp); size_t start_pos = cftell(cfp); diff --git a/code/ship/ship.cpp b/code/ship/ship.cpp index 7e300c8e59..cbd4718dc0 100644 --- a/code/ship/ship.cpp +++ b/code/ship/ship.cpp @@ -3440,21 +3440,6 @@ int parse_ship_values(ship_info* sip, const bool is_template, const bool first_t } } - sip->flags.remove(Ship::Info_Flags::Ballistic_primaries); - - //Set ship ballistic flag if necessary - for (i = 0; i < MAX_SHIP_PRIMARY_BANKS; i++) - { - for (j = 0; j < Num_weapon_types; j++) - { - if(sip->allowed_bank_restricted_weapons[i][j] && (Weapon_info[j].wi_flags[Weapon::Info_Flags::Ballistic])) - { - sip->flags.set(Ship::Info_Flags::Ballistic_primaries); - break; - } - } - } - find_and_stuff_optional("$AI Class:", &sip->ai_class, F_NAME, Ai_class_names, Num_ai_classes, "AI class names"); // Get Afterburner information @@ -5081,6 +5066,20 @@ int ship_show_velocity_dot = 0; DCF_BOOL( show_velocity_dot, ship_show_velocity_dot ) +bool ballistic_possible_for_this_ship(const ship_info *sip) +{ + for (int i = 0; i < MAX_SHIP_PRIMARY_BANKS; i++) + { + for (int j = 0; j < Num_weapon_types; ++j) + { + if (sip->allowed_bank_restricted_weapons[i][j] && (Weapon_info[j].wi_flags[Weapon::Info_Flags::Ballistic])) + return true; + } + } + + return false; +} + /** * Clean up ship entries, making sure various flags and settings are correct */ @@ -5105,7 +5104,7 @@ void ship_parse_post_cleanup() // be friendly; ensure ballistic flags check out if (pbank_capacity_specified) { - if ( !(sip->flags[Ship::Info_Flags::Ballistic_primaries]) ) { + if ( !ballistic_possible_for_this_ship(&(*sip)) ) { Warning(LOCATION, "Pbank capacity specified for non-ballistic-primary-enabled ship %s.\nResetting capacities to 0.\nTo fix this, add a ballistic primary to the list of allowed primaries.\n", sip->name); for (j = 0; j < MAX_SHIP_PRIMARY_BANKS; j++) { @@ -5113,7 +5112,7 @@ void ship_parse_post_cleanup() } } } else { - if (sip->flags[Ship::Info_Flags::Ballistic_primaries]) { + if ( ballistic_possible_for_this_ship(&(*sip)) ) { Warning(LOCATION, "Pbank capacity not specified for ballistic-primary-enabled ship %s.\nDefaulting to capacity of 1 per bank.\n", sip->name); for (j = 0; j < MAX_SHIP_PRIMARY_BANKS; j++) { @@ -5553,7 +5552,7 @@ void physics_ship_init(object *objp) pi->glide_accel_mult = sinfo->glide_accel_mult; //SUSHI: This defaults to the AI_Profile value, and is only optionally overridden - pi->use_newtonian_damp = ((The_mission.ai_profile->flags & AIPF_USE_NEWTONIAN_DAMPENING) != 0); + pi->use_newtonian_damp = The_mission.ai_profile->flags[AI::Profile_Flags::Use_newtonian_dampening]; if (sinfo->newtonian_damp_override) pi->use_newtonian_damp = sinfo->use_newtonian_damp; @@ -6480,9 +6479,9 @@ int subsys_set(int objnum, int ignore_subsys_info) // Wanderer if (model_system->flags[Model::Subsystem_Flags::No_ss_targeting]) ship_system->flags.set(Ship::Subsystem_Flags::No_SS_targeting); - if ((The_mission.ai_profile->flags2 & AIPF2_ADVANCED_TURRET_FOV_EDGE_CHECKS) || (model_system->flags[Model::Subsystem_Flags::Fov_edge_check])) + if ((The_mission.ai_profile->flags[AI::Profile_Flags::Advanced_turret_fov_edge_checks]) || (model_system->flags[Model::Subsystem_Flags::Fov_edge_check])) ship_system->flags.set(Ship::Subsystem_Flags::FOV_edge_check); - if ((The_mission.ai_profile->flags2 & AIPF2_REQUIRE_TURRET_TO_HAVE_TARGET_IN_FOV) || (model_system->flags[Model::Subsystem_Flags::Fov_required])) + if ((The_mission.ai_profile->flags[AI::Profile_Flags::Require_turret_to_have_target_in_fov]) || (model_system->flags[Model::Subsystem_Flags::Fov_required])) ship_system->flags.set(Ship::Subsystem_Flags::FOV_Required); if (model_system->flags[Model::Subsystem_Flags::No_replace]) @@ -8809,19 +8808,16 @@ void ship_process_post(object * obj, float frametime) } } - if ( sip->flags[Ship::Info_Flags::Ballistic_primaries] ) + for ( int i=0; iship_info_index, i, shipp->weapons.primary_bank_weapons[i]); - shipp->weapons.primary_bank_start_ammo[i] = max_missiles; - } - else - { - shipp->weapons.primary_bank_start_ammo[i] = shipp->weapons.primary_bank_ammo[i]; - } + max_missiles = get_max_ammo_count_for_primary_bank(shipp->ship_info_index, i, shipp->weapons.primary_bank_weapons[i]); + shipp->weapons.primary_bank_start_ammo[i] = max_missiles; + } + else + { + shipp->weapons.primary_bank_start_ammo[i] = shipp->weapons.primary_bank_ammo[i]; } } @@ -10703,7 +10699,7 @@ int ship_fire_primary(object * obj, int stream_weapons, int force) if (needs_target_pos) { target_velocity_vec = Objects[aip->target_objnum].phys_info.vel; - if (The_mission.ai_profile->flags & AIPF_USE_ADDITIVE_WEAPON_VELOCITY) + if (The_mission.ai_profile->flags[AI::Profile_Flags::Use_additive_weapon_velocity]) vm_vec_scale_sub2(&target_velocity_vec, &obj->phys_info.vel, winfo_p->vel_inherit_amount); } @@ -10753,7 +10749,7 @@ int ship_fire_primary(object * obj, int stream_weapons, int force) if (winfo_p->burst_shots > swp->burst_counter[bank_to_fire]) { next_fire_delay = winfo_p->burst_delay * 1000.0f; swp->burst_counter[bank_to_fire]++; - if (winfo_p->burst_flags & WBF_FAST_FIRING) + if (winfo_p->burst_flags[Weapon::Burst_Flags::Fast_firing]) fast_firing = true; } else if (winfo_p->max_delay != 0.0f && winfo_p->min_delay != 0.0f) { // Random fire delay (DahBlount) next_fire_delay = (((float)rand()) / (((float)RAND_MAX + 1.0f) * (winfo_p->max_delay - winfo_p->min_delay + 1.0f) + winfo_p->min_delay)) * 1000.0f; @@ -10772,7 +10768,7 @@ int ship_fire_primary(object * obj, int stream_weapons, int force) polymodel *pm = model_get( sip->model_num ); // Goober5000 (thanks to _argv[-1] for the original idea) - if ( (num_primary_banks > 1) && !(winfo_p->wi_flags[Weapon::Info_Flags::No_linked_penalty]) && !(The_mission.ai_profile->flags & AIPF_DISABLE_LINKED_FIRE_PENALTY) ) + if ( (num_primary_banks > 1) && !(winfo_p->wi_flags[Weapon::Info_Flags::No_linked_penalty]) && !(The_mission.ai_profile->flags[AI::Profile_Flags::Disable_linked_fire_penalty]) ) { int effective_primary_banks = 0; for (int it = 0; it < num_primary_banks; it++) @@ -11004,10 +11000,6 @@ int ship_fire_primary(object * obj, int stream_weapons, int force) // ballistics support for primaries - Goober5000 if ( winfo_p->wi_flags[Weapon::Info_Flags::Ballistic] ) { - // Make sure this ship is set up for ballistics. - // If you get this error, add the ballistic primaries tags to ships.tbl. - Assert ( sip->flags[Ship::Info_Flags::Ballistic_primaries] ); - // If ship is being repaired/rearmed, it cannot fire ballistics if ( aip->ai_flags & AIF_BEING_REPAIRED ) { @@ -12100,6 +12092,19 @@ int primary_out_of_ammo(ship_weapon *swp, int bank) return 0; } +bool ship_has_a_ballistic_primary(const ship *shipp) +{ + const ship_weapon *swp = &shipp->weapons; + + for (int i = 0; i < swp->num_primary_banks; i++) + { + if (Weapon_info[swp->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Ballistic]) + return true; + } + + return false; +} + /** * Return true if a new index gets selected. * @@ -12214,7 +12219,7 @@ int ship_select_next_primary(object *objp, int direction) } // test for ballistics - Goober5000 - if ( sip->flags[Ship::Info_Flags::Ballistic_primaries] ) + if (ship_has_a_ballistic_primary(shipp)) { // if we can't link, disengage primary linking and change to next available bank if (shipp->flags[Ship_Flags::Primary_linked]) @@ -13381,35 +13386,32 @@ float ship_calculate_rearm_duration( object *objp ) //now do the primary rearm time found_first_empty = false; - if (sip->flags[Ship::Info_Flags::Ballistic_primaries]) + for (i = 0; i < swp->num_primary_banks; i++) { - for (i = 0; i < swp->num_primary_banks; i++) + wip = &Weapon_info[swp->primary_bank_weapons[i]]; + if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) { - wip = &Weapon_info[swp->primary_bank_weapons[i]]; - if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) + //check how many full reloads we need + num_reloads = (swp->primary_bank_start_ammo[i] - swp->primary_bank_ammo[i])/REARM_NUM_BALLISTIC_PRIMARIES_PER_BATCH; + + //take into account a fractional reload + if ((swp->primary_bank_start_ammo[i] - swp->primary_bank_ammo[i]) % REARM_NUM_BALLISTIC_PRIMARIES_PER_BATCH != 0) { - //check how many full reloads we need - num_reloads = (swp->primary_bank_start_ammo[i] - swp->primary_bank_ammo[i])/REARM_NUM_BALLISTIC_PRIMARIES_PER_BATCH; - - //take into account a fractional reload - if ((swp->primary_bank_start_ammo[i] - swp->primary_bank_ammo[i]) % REARM_NUM_BALLISTIC_PRIMARIES_PER_BATCH != 0) - { - num_reloads++; - } - - //don't factor in the time it takes for the first reload, since that is loaded instantly - num_reloads--; - - if (num_reloads < 0) continue; - - if (!found_first_empty && (swp->primary_bank_start_ammo[i] - swp->primary_bank_ammo[i])) - { - found_first_empty = true; - prim_rearm_time += (float)snd_get_duration(Snds[SND_MISSILE_START_LOAD].id) / 1000.0f; - } - - prim_rearm_time += num_reloads * wip->rearm_rate; + num_reloads++; } + + //don't factor in the time it takes for the first reload, since that is loaded instantly + num_reloads--; + + if (num_reloads < 0) continue; + + if (!found_first_empty && (swp->primary_bank_start_ammo[i] - swp->primary_bank_ammo[i])) + { + found_first_empty = true; + prim_rearm_time += (float)snd_get_duration(Snds[SND_MISSILE_START_LOAD].id) / 1000.0f; + } + + prim_rearm_time += num_reloads * wip->rearm_rate; } } @@ -13457,7 +13459,7 @@ float ship_calculate_rearm_duration( object *objp ) // int ship_do_rearm_frame( object *objp, float frametime ) { - int i, banks_full, primary_banks_full, subsys_type, subsys_all_ok, last_ballistic_idx = 0; + int i, banks_full, primary_banks_full, subsys_type, subsys_all_ok, last_ballistic_idx = -1; float shield_str, repair_delta, repair_allocated, max_hull_repair, max_subsys_repair; ship *shipp; ship_weapon *swp; @@ -13647,80 +13649,22 @@ int ship_do_rearm_frame( object *objp, float frametime ) } // end for // rearm ballistic primaries - Goober5000 - if (sip->flags[Ship::Info_Flags::Ballistic_primaries]) + if ( aip->rearm_first_ballistic_primary == TRUE) { - if ( aip->rearm_first_ballistic_primary == TRUE) - { - for (i = 1; i < swp->num_primary_banks; i++ ) - { - if ( Weapon_info[swp->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Ballistic] ) - last_ballistic_idx = i; - } - } - for (i = 0; i < swp->num_primary_banks; i++ ) { if ( Weapon_info[swp->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Ballistic] ) - { - // Actual loading of bullets is preceded by a sound effect which is the bullet - // loading equipment moving into place - if ( aip->rearm_first_ballistic_primary == TRUE ) - { - // Goober5000 - int sound_index; - if (Snds[SND_BALLISTIC_START_LOAD].id >= 0) - sound_index = SND_BALLISTIC_START_LOAD; - else - sound_index = SND_MISSILE_START_LOAD; + last_ballistic_idx = i; + } + } - swp->primary_bank_rearm_time[i] = timestamp(snd_get_duration(Snds[sound_index].id)); - - if (i == last_ballistic_idx) - aip->rearm_first_ballistic_primary = FALSE; - } - - if ( swp->primary_bank_ammo[i] < swp->primary_bank_start_ammo[i] ) - { - float rearm_time; - - if ( objp == Player_obj ) - { - hud_gauge_popup_start(HUD_WEAPONS_GAUGE); - } - - if ( timestamp_elapsed(swp->primary_bank_rearm_time[i]) ) - { - rearm_time = Weapon_info[swp->primary_bank_weapons[i]].rearm_rate; - swp->primary_bank_rearm_time[i] = timestamp( (int)(rearm_time * 1000.f) ); - - // Goober5000 - int sound_index; - if (Snds[SND_BALLISTIC_LOAD].id >= 0) - sound_index = SND_BALLISTIC_LOAD; - else - sound_index = SND_MISSILE_LOAD; - - snd_play_3d( &Snds[sound_index], &objp->pos, &View_position ); - - swp->primary_bank_ammo[i] += REARM_NUM_BALLISTIC_PRIMARIES_PER_BATCH; - if ( swp->primary_bank_ammo[i] > swp->primary_bank_start_ammo[i] ) - { - swp->primary_bank_ammo[i] = swp->primary_bank_start_ammo[i]; - } - } - } - else - { - primary_banks_full++; - } - } - // if the bank is not a ballistic - else - { - primary_banks_full++; - } - - if ((aip->rearm_first_ballistic_primary == TRUE) && (i == swp->num_primary_banks - 1) && (primary_banks_full != swp->num_primary_banks)) + for (i = 0; i < swp->num_primary_banks; i++ ) + { + if (Weapon_info[swp->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Ballistic]) + { + // Actual loading of bullets is preceded by a sound effect which is the bullet + // loading equipment moving into place + if ( aip->rearm_first_ballistic_primary == TRUE ) { // Goober5000 int sound_index; @@ -13729,10 +13673,65 @@ int ship_do_rearm_frame( object *objp, float frametime ) else sound_index = SND_MISSILE_START_LOAD; - snd_play_3d( &Snds[sound_index], &objp->pos, &View_position ); + swp->primary_bank_rearm_time[i] = timestamp(snd_get_duration(Snds[sound_index].id)); + + if (i == last_ballistic_idx) + aip->rearm_first_ballistic_primary = FALSE; } - } // end for - } // end if - rearm ballistic primaries + + if ( swp->primary_bank_ammo[i] < swp->primary_bank_start_ammo[i] ) + { + float rearm_time; + + if ( objp == Player_obj ) + { + hud_gauge_popup_start(HUD_WEAPONS_GAUGE); + } + + if ( timestamp_elapsed(swp->primary_bank_rearm_time[i]) ) + { + rearm_time = Weapon_info[swp->primary_bank_weapons[i]].rearm_rate; + swp->primary_bank_rearm_time[i] = timestamp( (int)(rearm_time * 1000.f) ); + + // Goober5000 + int sound_index; + if (Snds[SND_BALLISTIC_LOAD].id >= 0) + sound_index = SND_BALLISTIC_LOAD; + else + sound_index = SND_MISSILE_LOAD; + + snd_play_3d( &Snds[sound_index], &objp->pos, &View_position ); + + swp->primary_bank_ammo[i] += REARM_NUM_BALLISTIC_PRIMARIES_PER_BATCH; + if ( swp->primary_bank_ammo[i] > swp->primary_bank_start_ammo[i] ) + { + swp->primary_bank_ammo[i] = swp->primary_bank_start_ammo[i]; + } + } + } + else + { + primary_banks_full++; + } + } + // if the bank is not a ballistic + else + { + primary_banks_full++; + } + + if ((aip->rearm_first_ballistic_primary == TRUE) && (i == last_ballistic_idx) && (primary_banks_full != swp->num_primary_banks)) + { + // Goober5000 + int sound_index; + if (Snds[SND_BALLISTIC_START_LOAD].id >= 0) + sound_index = SND_BALLISTIC_START_LOAD; + else + sound_index = SND_MISSILE_START_LOAD; + + snd_play_3d( &Snds[sound_index], &objp->pos, &View_position ); + } + } // end for } // end if (subsys_all_ok) if ( banks_full == swp->num_secondary_banks ) @@ -13775,8 +13774,7 @@ int ship_do_rearm_frame( object *objp, float frametime ) aip->rearm_release_delay = timestamp(1200); // check both primary and secondary banks are full - if ( (banks_full == swp->num_secondary_banks) && - ( !(sip->flags[Ship::Info_Flags::Ballistic_primaries]) || ((sip->flags[Ship::Info_Flags::Ballistic_primaries]) && (primary_banks_full == swp->num_primary_banks)) ) ) + if ( (banks_full == swp->num_secondary_banks) && (primary_banks_full == swp->num_primary_banks) ) { if ( timestamp_elapsed(aip->rearm_release_delay) ) return 1; @@ -14603,7 +14601,7 @@ int ship_engine_ok_to_warp(ship *sp) int ship_navigation_ok_to_warp(ship *sp) { // if not using the special flag, warp is always allowed - if (!(The_mission.ai_profile->flags & AIPF_NAVIGATION_SUBSYS_GOVERNS_WARP)) + if (!(The_mission.ai_profile->flags[AI::Profile_Flags::Navigation_subsys_governs_warp])) return 1; float navigation_strength = ship_get_subsystem_strength(sp, SUBSYSTEM_NAVIGATION); @@ -15599,7 +15597,7 @@ void ship_maybe_scream(ship *sp) return; // for WCSaga, only do a subset of the checks - if (!(The_mission.ai_profile->flags2 & AIPF2_PERFORM_FEWER_SCREAM_CHECKS)) + if (!(The_mission.ai_profile->flags[AI::Profile_Flags::Perform_fewer_scream_checks])) { // bail if this ship isn't from the player wing if (!(sp->flags[Ship_Flags::From_player_wing])) @@ -15666,34 +15664,31 @@ void ship_maybe_tell_about_low_ammo(ship *sp) swp = &sp->weapons; // stole the code for this from ship_maybe_tell_about_rearm() - if (Ship_info[sp->ship_info_index].flags[Ship::Info_Flags::Ballistic_primaries]) + for (i = 0; i < swp->num_primary_banks; i++) { - for (i = 0; i < swp->num_primary_banks; i++) + wip = &Weapon_info[swp->primary_bank_weapons[i]]; + + if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) { - wip = &Weapon_info[swp->primary_bank_weapons[i]]; - - if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) + if (swp->primary_bank_start_ammo[i] > 0) { - if (swp->primary_bank_start_ammo[i] > 0) + if ((float)swp->primary_bank_ammo[i] / (float)swp->primary_bank_start_ammo[i] < 0.3f) { - if ((float)swp->primary_bank_ammo[i] / (float)swp->primary_bank_start_ammo[i] < 0.3f) - { - // multiplayer tvt - if(MULTI_TEAM) { - multi_team_filter = sp->team; - } - - message_send_builtin_to_player(MESSAGE_PRIMARIES_LOW, sp, MESSAGE_PRIORITY_NORMAL, MESSAGE_TIME_SOON, 0, 0, -1, multi_team_filter); - - Player->allow_ammo_timestamp = timestamp(PLAYER_LOW_AMMO_MSG_INTERVAL); - - // better reset this one too - Player->request_repair_timestamp = timestamp(PLAYER_REQUEST_REPAIR_MSG_INTERVAL); - - Player->low_ammo_complaint_count++; - sp->ammo_low_complaint_count++; - break; + // multiplayer tvt + if(MULTI_TEAM) { + multi_team_filter = sp->team; } + + message_send_builtin_to_player(MESSAGE_PRIMARIES_LOW, sp, MESSAGE_PRIORITY_NORMAL, MESSAGE_TIME_SOON, 0, 0, -1, multi_team_filter); + + Player->allow_ammo_timestamp = timestamp(PLAYER_LOW_AMMO_MSG_INTERVAL); + + // better reset this one too + Player->request_repair_timestamp = timestamp(PLAYER_REQUEST_REPAIR_MSG_INTERVAL); + + Player->low_ammo_complaint_count++; + sp->ammo_low_complaint_count++; + break; } } } @@ -15747,21 +15742,18 @@ void ship_maybe_tell_about_rearm(ship *sp) } // also check ballistic primaries - Goober5000 - if (Ship_info[sp->ship_info_index].flags[Ship::Info_Flags::Ballistic_primaries]) + for (i = 0; i < swp->num_primary_banks; i++) { - for (i = 0; i < swp->num_primary_banks; i++) - { - wip = &Weapon_info[swp->primary_bank_weapons[i]]; + wip = &Weapon_info[swp->primary_bank_weapons[i]]; - if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) + if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) + { + if (swp->primary_bank_start_ammo[i] > 0) { - if (swp->primary_bank_start_ammo[i] > 0) + if ((float)swp->primary_bank_ammo[i] / (float)swp->primary_bank_start_ammo[i] < 0.3f) { - if ((float)swp->primary_bank_ammo[i] / (float)swp->primary_bank_start_ammo[i] < 0.3f) - { - message_type = MESSAGE_REARM_PRIMARIES; - break; - } + message_type = MESSAGE_REARM_PRIMARIES; + break; } } } @@ -16049,7 +16041,6 @@ float ship_get_secondary_weapon_range(ship *shipp) return srange; } -// Goober5000 - added for ballistic primaries /** * Determine the number of primary ammo units allowed max for a ship */ @@ -16057,13 +16048,12 @@ int get_max_ammo_count_for_primary_bank(int ship_class, int bank, int ammo_type) { float capacity, size; - if (!(Ship_info[ship_class].flags[Ship::Info_Flags::Ballistic_primaries])) - { + if (!(Weapon_info[ammo_type].wi_flags[Weapon::Info_Flags::Ballistic])) return 0; - } capacity = (float) Ship_info[ship_class].primary_bank_ammo_capacity[bank]; size = (float) Weapon_info[ammo_type].cargo_size; + Assertion(size > 0.0f, "Weapon cargo size for %s must be greater than 0!", Weapon_info[ammo_type].name); return fl2i((capacity / size)+0.5f); } @@ -16083,6 +16073,7 @@ int get_max_ammo_count_for_bank(int ship_class, int bank, int ammo_type) } else { capacity = (float) Ship_info[ship_class].secondary_bank_ammo_capacity[bank]; size = (float) Weapon_info[ammo_type].cargo_size; + Assertion(size > 0.0f, "Weapon cargo size for %s must be greater than 0!", Weapon_info[ammo_type].name); return (int) (capacity / size); } } diff --git a/code/ship/shiphit.cpp b/code/ship/shiphit.cpp index 1affd69675..7e127bc07a 100755 --- a/code/ship/shiphit.cpp +++ b/code/ship/shiphit.cpp @@ -478,7 +478,7 @@ float do_subobj_hit_stuff(object *ship_objp, object *other_obj, vec3d *hitpos, i { // MK, 9/2/99. Shockwaves do zero subsystem damage on small ships. // Goober5000 - added back in via flag - if ((Ship_info[ship_p->ship_info_index].is_small_ship()) && !(The_mission.ai_profile->flags & AIPF_SHOCKWAVES_DAMAGE_SMALL_SHIP_SUBSYSTEMS)) + if ((Ship_info[ship_p->ship_info_index].is_small_ship()) && !(The_mission.ai_profile->flags[AI::Profile_Flags::Shockwaves_damage_small_ship_subsystems])) return damage; else { damage_left = shockwave_get_damage(other_obj->instance) / 4.0f; @@ -2230,7 +2230,7 @@ static void ship_do_damage(object *ship_objp, object *other_obj, vec3d *hitpos, // Goober5000 - only count beams fired by fighters or bombers unless the ai profile says different if (bobjn >= 0) { - if ( !(The_mission.ai_profile->flags & AIPF_INCLUDE_BEAMS_IN_STAT_CALCS) && + if ( !(The_mission.ai_profile->flags[AI::Profile_Flags::Include_beams_in_stat_calcs]) && !(Ship_info[Ships[Objects[bobjn].instance].ship_info_index].is_fighter_bomber()) && !(Objects[bobjn].flags[Object::Object_Flags::Player_ship]) ) { bobjn = -1; diff --git a/code/sound/acm.cpp b/code/sound/acm.cpp index dcb8bbb1bb..0695884d72 100644 --- a/code/sound/acm.cpp +++ b/code/sound/acm.cpp @@ -13,34 +13,33 @@ #include -// we aren't including all of mmreg.h on Windows so this picks up the slack #ifndef WAVE_FORMAT_ADPCM #define WAVE_FORMAT_ADPCM 2 #endif -typedef struct adpcmcoef_tag { +typedef struct fs_adpcmcoef_tag { short iCoef1; short iCoef2; -} ADPCMCOEFSET; +} FS_ADPCMCOEFSET; -typedef struct adpcmblockheader_tag { +typedef struct fs_adpcmblockheader_tag { ubyte bPredictor; ushort iDelta; short iSamp1; short iSamp2; -} ADPCMBLOCKHEADER; +} FS_ADPCMBLOCKHEADER; -typedef struct adpcmwaveformat_tag { +typedef struct fs_adpcmwaveformat_tag { WAVEFORMATEX wav; WORD wSamplesPerBlock; WORD wNumCoef; - ADPCMCOEFSET *aCoef; -} ADPCMWAVEFORMAT; + FS_ADPCMCOEFSET *aCoef; +} FS_ADPCMWAVEFORMAT; -typedef struct ADPCM_FMT_T { - ADPCMWAVEFORMAT adpcm; - ADPCMBLOCKHEADER *header; +typedef struct FS_ADPCM_FMT_T { + FS_ADPCMWAVEFORMAT adpcm; + FS_ADPCMBLOCKHEADER *header; int bytes_remaining; uint bytes_processed; @@ -51,14 +50,13 @@ typedef struct ADPCM_FMT_T { ubyte nibble; ushort dest_bps; -} adpcm_fmt_t; +} fs_adpcm_fmt_t; -typedef struct acm_stream_t { - adpcm_fmt_t *fmt; +typedef struct fs_acm_stream_t { + fs_adpcm_fmt_t *fmt; ushort dest_bps; ushort src_bps; -} acm_stream_t; - +} fs_acm_stream_t; // similar to BIAL_IF_MACRO in SDL_sound #define IF_ERR(a, b) if (a) { mprintf(("ACM ERROR, line %d...\n", __LINE__)); return b; } @@ -126,7 +124,7 @@ static int read_ubyte(SDL_RWops* rw, ubyte *i) } // decoding functions -static int read_adpcm_block_headers(SDL_RWops* rw, adpcm_fmt_t *fmt) +static int read_adpcm_block_headers(SDL_RWops* rw, fs_adpcm_fmt_t *fmt) { int i; int max = fmt->adpcm.wav.nChannels; @@ -160,7 +158,7 @@ static int read_adpcm_block_headers(SDL_RWops* rw, adpcm_fmt_t *fmt) return 1; } -static void do_adpcm_nibble(ubyte nib, ADPCMBLOCKHEADER *header, int lPredSamp) +static void do_adpcm_nibble(ubyte nib, FS_ADPCMBLOCKHEADER *header, int lPredSamp) { static const short max_audioval = ((1<<(16-1))-1); static const short min_audioval = -(1<<(16-1)); @@ -196,7 +194,7 @@ static void do_adpcm_nibble(ubyte nib, ADPCMBLOCKHEADER *header, int lPredSamp) header->iSamp1 = (short)lNewSamp; } -static int decode_adpcm_sample_frame(SDL_RWops* rw, adpcm_fmt_t *fmt) +static int decode_adpcm_sample_frame(SDL_RWops* rw, fs_adpcm_fmt_t *fmt) { int i; int max = fmt->adpcm.wav.nChannels; @@ -224,7 +222,7 @@ static int decode_adpcm_sample_frame(SDL_RWops* rw, adpcm_fmt_t *fmt) return 1; } -static void put_adpcm_sample_frame1(ubyte *_buf, adpcm_fmt_t *fmt) +static void put_adpcm_sample_frame1(ubyte *_buf, fs_adpcm_fmt_t *fmt) { int i; @@ -246,7 +244,7 @@ static void put_adpcm_sample_frame1(ubyte *_buf, adpcm_fmt_t *fmt) } } -static void put_adpcm_sample_frame2(ubyte *_buf, adpcm_fmt_t *fmt) +static void put_adpcm_sample_frame2(ubyte *_buf, fs_adpcm_fmt_t *fmt) { int i; @@ -268,7 +266,7 @@ static void put_adpcm_sample_frame2(ubyte *_buf, adpcm_fmt_t *fmt) } } -static uint read_sample_fmt_adpcm(ubyte *data, SDL_RWops* rw, adpcm_fmt_t *fmt) +static uint read_sample_fmt_adpcm(ubyte *data, SDL_RWops* rw, fs_adpcm_fmt_t *fmt) { uint bw = 0; @@ -310,7 +308,7 @@ static uint read_sample_fmt_adpcm(ubyte *data, SDL_RWops* rw, adpcm_fmt_t *fmt) /* End ADPCM Compression Handler * *****************************************************************************/ -static void adpcm_memory_free(adpcm_fmt_t *fmt) +static void adpcm_memory_free(fs_adpcm_fmt_t *fmt) { if (fmt->adpcm.aCoef != NULL) { vm_free(fmt->adpcm.aCoef); @@ -371,9 +369,9 @@ int ACM_convert_ADPCM_to_PCM(WAVEFORMATEX *pwfxSrc, ubyte *src, int src_len, uby int left_over = 0; int i; - adpcm_fmt_t *fmt = (adpcm_fmt_t *)vm_malloc(sizeof(adpcm_fmt_t)); + fs_adpcm_fmt_t *fmt = (fs_adpcm_fmt_t *)vm_malloc(sizeof(fs_adpcm_fmt_t)); IF_ERR(fmt == NULL, -1); - memset(fmt, '\0', sizeof(adpcm_fmt_t)); + memset(fmt, '\0', sizeof(fs_adpcm_fmt_t)); // wav header info (WAVEFORMATEX) IF_ERR2(!read_word(hdr, &fmt->adpcm.wav.wFormatTag), goto Error); @@ -388,7 +386,7 @@ int ACM_convert_ADPCM_to_PCM(WAVEFORMATEX *pwfxSrc, ubyte *src, int src_len, uby IF_ERR2(!read_word_s(hdr, &fmt->adpcm.wNumCoef), goto Error); // allocate memory for COEF struct and fill it - fmt->adpcm.aCoef = (ADPCMCOEFSET *)vm_malloc(sizeof(ADPCMCOEFSET) * fmt->adpcm.wNumCoef); + fmt->adpcm.aCoef = (FS_ADPCMCOEFSET *)vm_malloc(sizeof(FS_ADPCMCOEFSET) * fmt->adpcm.wNumCoef); IF_ERR2(fmt->adpcm.aCoef == NULL, goto Error); for (i = 0; i < fmt->adpcm.wNumCoef; i++) { @@ -397,7 +395,7 @@ int ACM_convert_ADPCM_to_PCM(WAVEFORMATEX *pwfxSrc, ubyte *src, int src_len, uby } // allocate memory for the ADPCM block header that's to be filled later - fmt->header = (ADPCMBLOCKHEADER *)vm_malloc(sizeof(ADPCMBLOCKHEADER) * fmt->adpcm.wav.nChannels); + fmt->header = (FS_ADPCMBLOCKHEADER *)vm_malloc(sizeof(FS_ADPCMBLOCKHEADER) * fmt->adpcm.wav.nChannels); IF_ERR2(fmt->header == NULL, goto Error); // estimate size of uncompressed data @@ -498,13 +496,13 @@ int ACM_stream_open(WAVEFORMATEX *pwfxSrc, WAVEFORMATEX *pwfxDest, void **stream Assert( pwfxSrc->wFormatTag == WAVE_FORMAT_ADPCM ); int i; - acm_stream_t *str = NULL; + fs_acm_stream_t *str = NULL; auto hdr = SDL_RWFromConstMem((void*)pwfxSrc, sizeof(WAVEFORMATEX) + pwfxSrc->cbSize); - adpcm_fmt_t *fmt = (adpcm_fmt_t *)vm_malloc(sizeof(adpcm_fmt_t)); + fs_adpcm_fmt_t *fmt = (fs_adpcm_fmt_t *)vm_malloc(sizeof(fs_adpcm_fmt_t)); IF_ERR2(fmt == NULL, goto Error); - memset(fmt, '\0', sizeof(adpcm_fmt_t)); + memset(fmt, '\0', sizeof(fs_adpcm_fmt_t)); // wav header info (WAVEFORMATEX) IF_ERR2(!read_word(hdr, &fmt->adpcm.wav.wFormatTag), goto Error); @@ -519,7 +517,7 @@ int ACM_stream_open(WAVEFORMATEX *pwfxSrc, WAVEFORMATEX *pwfxDest, void **stream IF_ERR2(!read_word_s(hdr, &fmt->adpcm.wNumCoef), goto Error); // allocate memory for COEF struct and fill it - fmt->adpcm.aCoef = (ADPCMCOEFSET *)vm_malloc(sizeof(ADPCMCOEFSET) * fmt->adpcm.wNumCoef); + fmt->adpcm.aCoef = (FS_ADPCMCOEFSET *)vm_malloc(sizeof(FS_ADPCMCOEFSET) * fmt->adpcm.wNumCoef); IF_ERR2(fmt->adpcm.aCoef == NULL, goto Error); for (i = 0; i < fmt->adpcm.wNumCoef; i++) { @@ -528,7 +526,7 @@ int ACM_stream_open(WAVEFORMATEX *pwfxSrc, WAVEFORMATEX *pwfxDest, void **stream } // allocate memory for the ADPCM block header that's to be filled later - fmt->header = (ADPCMBLOCKHEADER *)vm_malloc(sizeof(ADPCMBLOCKHEADER) * fmt->adpcm.wav.nChannels); + fmt->header = (FS_ADPCMBLOCKHEADER *)vm_malloc(sizeof(FS_ADPCMBLOCKHEADER) * fmt->adpcm.wav.nChannels); IF_ERR2(fmt->header == NULL, goto Error); // sanity check, should always be 4 @@ -542,7 +540,7 @@ int ACM_stream_open(WAVEFORMATEX *pwfxSrc, WAVEFORMATEX *pwfxDest, void **stream fmt->sample_frame_size = dest_bps/8*pwfxSrc->nChannels; fmt->dest_bps = (ushort)dest_bps; - str = (acm_stream_t *)vm_malloc(sizeof(acm_stream_t)); + str = (fs_acm_stream_t *)vm_malloc(sizeof(fs_acm_stream_t)); IF_ERR2(str == NULL, goto Error); str->fmt = fmt; str->dest_bps = (ushort)dest_bps; @@ -578,7 +576,7 @@ int ACM_stream_close(void *stream) return 0; } - acm_stream_t *str = (acm_stream_t *)stream; + fs_acm_stream_t *str = (fs_acm_stream_t *)stream; adpcm_memory_free(str->fmt); vm_free(str); @@ -592,7 +590,7 @@ int ACM_query_source_size(void *stream, int dest_len) return 0; } - acm_stream_t *str = (acm_stream_t *)stream; + fs_acm_stream_t *str = (fs_acm_stream_t *)stream; // estimate size of compressed data // uncompressed data has: channels=pfwxScr->nChannels, bitPerSample=destbits @@ -607,7 +605,7 @@ int ACM_query_dest_size(void *stream, int src_len) return 0; } - acm_stream_t *str = (acm_stream_t *)stream; + fs_acm_stream_t *str = (fs_acm_stream_t *)stream; // estimate size of uncompressed data // uncompressed data has: channels=pfwxScr->nChannels, bitPerSample=destbits @@ -626,7 +624,7 @@ int ACM_convert(void *stream, ubyte *src, int src_len, ubyte *dest, int max_dest return 0; } - acm_stream_t *str = (acm_stream_t *)stream; + fs_acm_stream_t *str = (fs_acm_stream_t *)stream; uint rc; auto rw = SDL_RWFromConstMem((void*) src, src_len); diff --git a/code/source_groups.cmake b/code/source_groups.cmake index 8037a84407..6f90f9dd88 100644 --- a/code/source_groups.cmake +++ b/code/source_groups.cmake @@ -6,6 +6,7 @@ set (file_root set (file_root_ai ai/ai.cpp ai/ai.h + ai/ai_flags.h ai/ai_profiles.cpp ai/ai_profiles.h ai/aibig.cpp @@ -831,7 +832,12 @@ set (file_root_physics # PilotFile files set (file_root_pilotfile + pilotfile/BinaryFileHandler.cpp + pilotfile/BinaryFileHandler.h pilotfile/csg.cpp + pilotfile/FileHandler.h + pilotfile/JSONFileHandler.cpp + pilotfile/JSONFileHandler.h pilotfile/csg_convert.cpp pilotfile/pilotfile.cpp pilotfile/pilotfile.h diff --git a/code/stats/scoring.cpp b/code/stats/scoring.cpp index 67252b29ab..9886c46b5c 100644 --- a/code/stats/scoring.cpp +++ b/code/stats/scoring.cpp @@ -673,7 +673,7 @@ int scoring_eval_kill(object *ship_objp) killer_sig = dead_ship->damage_ship_id[max_damage_index]; // set the scale value if we only award 100% score for 100% damage - if (The_mission.ai_profile->flags & AIPF_KILL_SCORING_SCALES_WITH_DAMAGE) { + if (The_mission.ai_profile->flags[AI::Profile_Flags::Kill_scoring_scales_with_damage]) { scoring_scale_by_damage = max_damage_pct; } @@ -998,7 +998,7 @@ void scoring_eval_assists(ship *sp,int killer_sig, bool is_enemy_player) // evaluate each damage slot to see if it did enough to give the assis for(idx=0;idxdamage_ship[idx]/sp->total_damage_received) >= Assist_percentage) || (The_mission.ai_profile->flags & AIPF_ASSIST_SCORING_SCALES_WITH_DAMAGE)){ + if(((sp->damage_ship[idx]/sp->total_damage_received) >= Assist_percentage) || (The_mission.ai_profile->flags[AI::Profile_Flags::Assist_scoring_scales_with_damage])){ // get the player which did this damage (if any) plr = NULL; @@ -1036,7 +1036,7 @@ void scoring_eval_assists(ship *sp,int killer_sig, bool is_enemy_player) // maybe award assist points based on damage - if (The_mission.ai_profile->flags & AIPF_ASSIST_SCORING_SCALES_WITH_DAMAGE) { + if (The_mission.ai_profile->flags[AI::Profile_Flags::Assist_scoring_scales_with_damage]) { scoring_scale_by_damage = (sp->damage_ship[idx]/sp->total_damage_received); assist_score = (int)(sp->score * scoring_scale_factor * scoring_scale_by_damage); plr->stats.m_score += assist_score; @@ -1086,7 +1086,7 @@ void scoring_eval_hit(object *hit_obj, object *other_obj,int from_blast) return; } - if((other_obj->type == OBJ_WEAPON) && !(Weapons[other_obj->instance].weapon_flags & WF_ALREADY_APPLIED_STATS)){ + if((other_obj->type == OBJ_WEAPON) && !(Weapons[other_obj->instance].weapon_flags[Weapon::Weapon_Flags::Already_applied_stats])){ // bogus weapon if(other_obj->instance >= MAX_WEAPONS){ return; diff --git a/code/weapon/beam.cpp b/code/weapon/beam.cpp index 4932800818..3e6cfd1f5d 100644 --- a/code/weapon/beam.cpp +++ b/code/weapon/beam.cpp @@ -2913,7 +2913,7 @@ int beam_collide_early_out(object *a, object *b) /* if(bwi->b_info.beam_type == BEAM_TYPE_C){ return 1; }*/ - if(The_mission.ai_profile->flags2 & AIPF2_BEAMS_DAMAGE_WEAPONS) { + if(The_mission.ai_profile->flags[AI::Profile_Flags::Beams_damage_weapons]) { if((Weapon_info[Weapons[b->instance].weapon_info_index].weapon_hitpoints <= 0) && (Weapon_info[Weapons[b->instance].weapon_info_index].subtype == WP_LASER)) { return 1; } @@ -3199,7 +3199,7 @@ void beam_handle_collisions(beam *b) break; case OBJ_WEAPON: - if (The_mission.ai_profile->flags2 & AIPF2_BEAMS_DAMAGE_WEAPONS) { + if (The_mission.ai_profile->flags[AI::Profile_Flags::Beams_damage_weapons]) { if (!(Game_mode & GM_MULTIPLAYER) || MULTIPLAYER_MASTER) { object *trgt = &Objects[target]; @@ -3401,7 +3401,7 @@ int beam_ok_to_fire(beam *b) vm_vec_sub(&aim_dir, &b->last_shot, &b->last_start); vm_vec_normalize(&aim_dir); - if (The_mission.ai_profile->flags & AIPF_FORCE_BEAM_TURRET_FOV) { + if (The_mission.ai_profile->flags[AI::Profile_Flags::Force_beam_turret_fov]) { vec3d turret_normal; if (b->flags & BF_IS_FIGHTER_BEAM) { diff --git a/code/weapon/emp.cpp b/code/weapon/emp.cpp index 39b665694a..5f401828c1 100644 --- a/code/weapon/emp.cpp +++ b/code/weapon/emp.cpp @@ -138,7 +138,7 @@ void emp_apply(vec3d *pos, float inner_radius, float outer_radius, float emp_int // if the bomb was within 1/4 of the outer radius, castrate it if(dist_mag <= (outer_radius * 0.25f)){ // memset(&target->phys_info, 0, sizeof(physics_info)); - Weapons[target->instance].weapon_flags |= WF_DEAD_IN_WATER; + Weapons[target->instance].weapon_flags.set(Weapon::Weapon_Flags::Dead_in_water); mprintf(("EMP killing weapon\n")); } } diff --git a/code/weapon/shockwave.cpp b/code/weapon/shockwave.cpp index c1023c7081..e10f39c55d 100644 --- a/code/weapon/shockwave.cpp +++ b/code/weapon/shockwave.cpp @@ -328,7 +328,7 @@ void shockwave_move(object *shockwave_objp, float frametime) objp->hull_strength -= damage; if (objp->hull_strength < 0.0f) { Weapons[objp->instance].lifeleft = 0.01f; - Weapons[objp->instance].weapon_flags |= WF_DESTROYED_BY_WEAPON; + Weapons[objp->instance].weapon_flags.set(Weapon::Weapon_Flags::Destroyed_by_weapon); } break; default: diff --git a/code/weapon/weapon.h b/code/weapon/weapon.h index 90f3f43eec..f051d9075a 100644 --- a/code/weapon/weapon.h +++ b/code/weapon/weapon.h @@ -41,23 +41,6 @@ extern int Num_weapon_subtypes; #define WEAPON_EXHAUST_DELTA_TIME 75 // Delay in milliseconds between exhaust blobs -#define WF_LOCK_WARNING_PLAYED (1<<0) // set when a lock warning sound is played for the player - // (needed since we don't want to play multiple lock sounds) -#define WF_ALREADY_APPLIED_STATS (1<<1) // for use in ship_apply_local and ship_apply_global damage functions - // so that we don't record multiple hits (stats) for one impact -#define WF_PLAYED_FLYBY_SOUND (1<<2) // flyby sound has been played for this weapon -#define WF_CONSIDER_FOR_FLYBY_SOUND (1<<3) // consider for flyby -#define WF_DEAD_IN_WATER (1<<4) // a missiles engines have died -#define WF_LOCKED_WHEN_FIRED (1<<5) // fired with a lock -#define WF_DESTROYED_BY_WEAPON (1<<6) // destroyed by damage from other weapon -#define WF_SPAWNED (1<<7) //Spawned from a spawning type weapon -#define WF_HOMING_UPDATE_NEEDED (1<<8) // this is a newly spawned homing weapon which needs to update client machines -#define WF_NO_HOMING (1<<9) // this weapon should ignore any homing behavior it'd usually have - -// flags for setting burst fire -#define WBF_FAST_FIRING (1<<0) // burst is to use only the firewait to determine firing delays -#define WBF_RANDOM_LENGTH (1<<1) // burst is to fire random length bursts - //particle names go here -nuke #define PSPEW_NONE -1 //used to disable a spew, useful for xmts #define PSPEW_DEFAULT 0 //std fs2 pspew @@ -101,7 +84,7 @@ typedef struct weapon { int target_sig; // So we know if the target is the same one we've been tracking float nearest_dist; // nearest distance yet attained to target fix creation_time; // time at which created, stuffed Missiontime - int weapon_flags; // bit flags defining behavior, see WF_xxxx + flagset weapon_flags; // bit flags defining behavior, see WF_xxxx object* homing_object; // object this weapon is homing on. ship_subsys* homing_subsys; // subsystem this weapon is homing on vec3d homing_pos; // world position missile is homing on @@ -450,7 +433,7 @@ typedef struct weapon_info { int burst_shots; float burst_delay; - int burst_flags; + flagset burst_flags; // Thruster effects generic_anim thruster_flame; diff --git a/code/weapon/weapons.cpp b/code/weapon/weapons.cpp index 4be5c81863..6710348151 100644 --- a/code/weapon/weapons.cpp +++ b/code/weapon/weapons.cpp @@ -94,12 +94,12 @@ char *Weapon_subtype_names[] = { }; int Num_weapon_subtypes = sizeof(Weapon_subtype_names)/sizeof(char *); -flag_def_list Burst_fire_flags[] = { - { "fast firing", WBF_FAST_FIRING, 0 }, - { "random length", WBF_RANDOM_LENGTH, 0 } +flag_def_list_new Burst_fire_flags[] = { + { "fast firing", Weapon::Burst_Flags::Fast_firing, true, false }, + { "random length", Weapon::Burst_Flags::Random_length, true, false } }; -int Num_burst_fire_flags = sizeof(Burst_fire_flags)/sizeof(flag_def_list); +const size_t Num_burst_fire_flags = sizeof(Burst_fire_flags)/sizeof(flag_def_list_new); weapon_explosions Weapon_explosions; @@ -2636,7 +2636,7 @@ int parse_weapon(int subtype, bool replace, const char *filename) } if (optional_string("$Burst Flags:")) { - parse_string_flag_list((int*)&wip->burst_flags, Burst_fire_flags, Num_burst_fire_flags); + parse_string_flag_list(wip->burst_flags, Burst_fire_flags, Num_burst_fire_flags, NULL); } if (optional_string("$Thruster Flame Effect:")) { @@ -3586,8 +3586,8 @@ void weapon_delete(object *obj) void weapon_maybe_play_warning(weapon *wp) { if ( wp->homing_object == Player_obj ) { - if ( !(wp->weapon_flags & WF_LOCK_WARNING_PLAYED) ) { - wp->weapon_flags |= WF_LOCK_WARNING_PLAYED; + if ( !(wp->weapon_flags[Weapon::Weapon_Flags::Lock_warning_played]) ) { + wp->weapon_flags.set(Weapon::Weapon_Flags::Lock_warning_played); // Use heatlock-warning sound for Heat and Javelin for now // Possibly add an additional third sound later if ( (Weapon_info[wp->weapon_info_index].wi_flags[Weapon::Info_Flags::Homing_heat]) || @@ -3684,11 +3684,11 @@ void find_homing_object(object *weapon_objp, int num) //WMC - Spawn weapons shouldn't go for protected ships // ditto for untargeted heat seekers - niffiwan if ( (objp->flags[Object::Object_Flags::Protected]) && - ((wp->weapon_flags & WF_SPAWNED) || (wip->wi_flags[Weapon::Info_Flags::Untargeted_heat_seeker])) ) + ((wp->weapon_flags[Weapon::Weapon_Flags::Spawned]) || (wip->wi_flags[Weapon::Info_Flags::Untargeted_heat_seeker])) ) continue; // Spawned weapons should never home in on their parent - even in multiplayer dogfights where they would pass the iff test below - if ((wp->weapon_flags & WF_SPAWNED) && (objp == &Objects[weapon_objp->parent])) + if ((wp->weapon_flags[Weapon::Weapon_Flags::Spawned]) && (objp == &Objects[weapon_objp->parent])) continue; homing_object_team = obj_team(objp); @@ -3714,7 +3714,7 @@ void find_homing_object(object *weapon_objp, int num) // Goober5000: if missiles can't home on sensor-ghosted ships, // they definitely shouldn't home on stealth ships - if ( sp->flags[Ship::Ship_Flags::Stealth] && (The_mission.ai_profile->flags & AIPF_FIX_HEAT_SEEKER_STEALTH_BUG) ) { + if ( sp->flags[Ship::Ship_Flags::Stealth] && (The_mission.ai_profile->flags[AI::Profile_Flags::Fix_heat_seeker_stealth_bug]) ) { continue; } @@ -3945,7 +3945,7 @@ bool aspect_should_lose_target(weapon* wp) if (target_info->wi_flags[Weapon::Info_Flags::Cmeasure]) { // Check if we can home on this countermeasure - bool home_on_cmeasure = The_mission.ai_profile->flags2 & AIPF2_ASPECT_LOCK_COUNTERMEASURE + bool home_on_cmeasure = The_mission.ai_profile->flags[AI::Profile_Flags::Aspect_lock_countermeasure] || target_info->wi_flags[Weapon::Info_Flags::Cmeasure_aspect_home_on]; if (!home_on_cmeasure) @@ -4003,8 +4003,8 @@ void weapon_home(object *obj, int num, float frame_time) return; } } - else if (MULTIPLAYER_MASTER && (wip->is_locked_homing()) && (wp->weapon_flags & WF_HOMING_UPDATE_NEEDED)) { - wp->weapon_flags &= ~WF_HOMING_UPDATE_NEEDED; + else if (MULTIPLAYER_MASTER && (wip->is_locked_homing()) && (wp->weapon_flags[Weapon::Weapon_Flags::Homing_update_needed])) { + wp->weapon_flags.remove(Weapon::Weapon_Flags::Homing_update_needed); send_homing_weapon_info(num); } @@ -4128,7 +4128,7 @@ void weapon_home(object *obj, int num, float frame_time) break; case OBJ_WEAPON: { - bool home_on_cmeasure = The_mission.ai_profile->flags2 & AIPF2_ASPECT_LOCK_COUNTERMEASURE + bool home_on_cmeasure = The_mission.ai_profile->flags[AI::Profile_Flags::Aspect_lock_countermeasure] || hobj_infop->wi_flags[Weapon::Info_Flags::Cmeasure_aspect_home_on]; // don't home on countermeasures or non-bombs, that's handled elsewhere @@ -4430,7 +4430,7 @@ void weapon_maybe_play_flyby_sound(object *weapon_objp, weapon *wp) return; } - if ( !(wp->weapon_flags & WF_PLAYED_FLYBY_SOUND) && (wp->weapon_flags & WF_CONSIDER_FOR_FLYBY_SOUND) ) { + if ( !(wp->weapon_flags[Weapon::Weapon_Flags::Played_flyby_sound]) && (wp->weapon_flags[Weapon::Weapon_Flags::Consider_for_flyby_sound]) ) { float dist, dot, radius; if ( (Weapon_info[wp->weapon_info_index].wi_flags[Weapon::Info_Flags::Corkscrew]) ) { @@ -4469,7 +4469,7 @@ void weapon_maybe_play_flyby_sound(object *weapon_objp, weapon *wp) } } Weapon_flyby_sound_timer = timestamp(200); - wp->weapon_flags |= WF_PLAYED_FLYBY_SOUND; + wp->weapon_flags.set(Weapon::Weapon_Flags::Played_flyby_sound); } } } @@ -4711,7 +4711,7 @@ void weapon_process_post(object * obj, float frame_time) } // a single player or multiplayer server function -- it affects actual weapon movement. - if (wip->is_homing() && !(wp->weapon_flags & WF_NO_HOMING)) { + if (wip->is_homing() && !(wp->weapon_flags[Weapon::Weapon_Flags::No_homing])) { weapon_home(obj, num, frame_time); // If this is a swarm type missile, @@ -4900,7 +4900,7 @@ void weapon_set_tracking_info(int weapon_objnum, int parent_objnum, int target_o wp = &Weapons[Objects[weapon_objnum].instance]; wip = &Weapon_info[wp->weapon_info_index]; - if (wp->weapon_flags & WF_NO_HOMING) { + if (wp->weapon_flags[Weapon::Weapon_Flags::No_homing]) { return; } @@ -4912,7 +4912,7 @@ void weapon_set_tracking_info(int weapon_objnum, int parent_objnum, int target_o } if (parent_objp != NULL && (Ships[parent_objp->instance].flags[Ship::Ship_Flags::No_secondary_lockon])) { - wp->weapon_flags |= WF_NO_HOMING; + wp->weapon_flags.set(Weapon::Weapon_Flags::No_homing); wp->homing_object = &obj_used_list; wp->homing_subsys = NULL; wp->target_num = -1; @@ -4997,7 +4997,7 @@ void weapon_set_tracking_info(int weapon_objnum, int parent_objnum, int target_o if (target_is_locked && (wp->target_num != -1) && (wip->is_locked_homing()) ) { wp->lifeleft *= LOCKED_HOMING_EXTENDED_LIFE_FACTOR; if (MULTIPLAYER_MASTER) { - wp->weapon_flags |= WF_HOMING_UPDATE_NEEDED; + wp->weapon_flags.set(Weapon::Weapon_Flags::Homing_update_needed); } } @@ -5197,7 +5197,7 @@ int weapon_create( vec3d * pos, matrix * porient, int weapon_type, int parent_ob } wp->turret_subsys = NULL; vm_vec_zero(&wp->homing_pos); - wp->weapon_flags = 0; + wp->weapon_flags.reset(); wp->target_sig = -1; wp->cmeasure_ignore_list = nullptr; wp->det_range = wip->det_range; @@ -5350,7 +5350,7 @@ int weapon_create( vec3d * pos, matrix * porient, int weapon_type, int parent_ob // Turey - maybe make the initial speed of the weapon take into account the velocity of the parent. // Improves aiming during gliding. - if ((parent_objp != NULL) && (The_mission.ai_profile->flags & AIPF_USE_ADDITIVE_WEAPON_VELOCITY)) { + if ((parent_objp != NULL) && (The_mission.ai_profile->flags[AI::Profile_Flags::Use_additive_weapon_velocity])) { float pspeed = vm_vec_mag( &parent_objp->phys_info.vel ); vm_vec_scale_add2( &objp->phys_info.vel, &parent_objp->phys_info.vel, wip->vel_inherit_amount ); wp->weapon_max_vel += pspeed * wip->vel_inherit_amount; @@ -5410,7 +5410,7 @@ int weapon_create( vec3d * pos, matrix * porient, int weapon_type, int parent_ob // Ensure weapon flyby sound doesn't get played for player lasers if ( parent_objp != NULL && parent_objp == Player_obj ) { - wp->weapon_flags |= WF_PLAYED_FLYBY_SOUND; + wp->weapon_flags.set(Weapon::Weapon_Flags::Played_flyby_sound); } wp->pick_big_attack_point_timestamp = timestamp(1); @@ -5441,12 +5441,12 @@ int weapon_create( vec3d * pos, matrix * porient, int weapon_type, int parent_ob // if the weapon was fired locked if(is_locked){ - wp->weapon_flags |= WF_LOCKED_WHEN_FIRED; + wp->weapon_flags.set(Weapon::Weapon_Flags::Locked_when_fired); } //if the weapon was spawned from a spawning type weapon if(is_spawned){ - wp->weapon_flags |= WF_SPAWNED; + wp->weapon_flags.set(Weapon::Weapon_Flags::Spawned); } wp->alpha_current = -1.0f; @@ -5559,7 +5559,7 @@ void spawn_child_weapons(object *objp) beam_fire(&fire_info); } else { vm_vector_2_matrix(&orient, &tvec, NULL, NULL); - weapon_objnum = weapon_create(&pos, &orient, child_id, parent_num, -1, wp->weapon_flags & WF_LOCKED_WHEN_FIRED, 1); + weapon_objnum = weapon_create(&pos, &orient, child_id, parent_num, -1, wp->weapon_flags[Weapon::Weapon_Flags::Locked_when_fired], 1); //if the child inherits parent target, do it only if the parent weapon was locked to begin with if ((child_wip->wi_flags[Weapon::Info_Flags::Inherit_parent_target]) && (wp->homing_object != &obj_used_list)) @@ -5972,7 +5972,7 @@ void weapon_do_area_effect(object *wobjp, shockwave_create_info *sci, vec3d *pos objp->hull_strength -= damage; if (objp->hull_strength < 0.0f) { Weapons[objp->instance].lifeleft = 0.01f; - Weapons[objp->instance].weapon_flags |= WF_DESTROYED_BY_WEAPON; + Weapons[objp->instance].weapon_flags.set(Weapon::Weapon_Flags::Destroyed_by_weapon); } break; default: @@ -6007,7 +6007,7 @@ bool weapon_armed(weapon *wp, bool hit_target) weapon_info *wip = &Weapon_info[wp->weapon_info_index]; - if((wp->weapon_flags & WF_DESTROYED_BY_WEAPON) + if((wp->weapon_flags[Weapon::Weapon_Flags::Destroyed_by_weapon]) && !wip->arm_time && wip->arm_dist == 0.0f && wip->arm_radius == 0.0f) @@ -6212,7 +6212,7 @@ void weapon_hit( object * weapon_obj, object * other_obj, vec3d * hitpos, int qu //Set shockwaves flag int sw_flag = SW_WEAPON; - if ( ((other_obj) && (other_obj->type == OBJ_WEAPON)) || (Weapons[num].weapon_flags & WF_DESTROYED_BY_WEAPON)) { + if ( ((other_obj) && (other_obj->type == OBJ_WEAPON)) || (Weapons[num].weapon_flags[Weapon::Weapon_Flags::Destroyed_by_weapon])) { sw_flag |= SW_WEAPON_KILL; } @@ -6957,13 +6957,13 @@ float weapon_get_damage_scale(weapon_info *wip, object *wep, object *target) } // if this is a lockarm weapon, and it was fired unlocked - if((wip->wi_flags[Weapon::Info_Flags::Lockarm]) && !(wp->weapon_flags & WF_LOCKED_WHEN_FIRED)){ + if((wip->wi_flags[Weapon::Info_Flags::Lockarm]) && !(wp->weapon_flags[Weapon::Weapon_Flags::Locked_when_fired])){ total_scale *= 0.1f; } // if the hit object was a ship and we're doing damage scaling if ( (target->type == OBJ_SHIP) && - !(The_mission.ai_profile->flags & AIPF_DISABLE_WEAPON_DAMAGE_SCALING) && + !(The_mission.ai_profile->flags[AI::Profile_Flags::Disable_weapon_damage_scaling]) && !(Ship_info[Ships[target->instance].ship_info_index].flags[Ship::Info_Flags::Disable_weapon_damage_scaling]) ) { ship_info *sip; @@ -7000,7 +7000,7 @@ float weapon_get_damage_scale(weapon_info *wip, object *wep, object *target) if( is_big_damage_ship && !(wip->hurts_big_ships()) ){ // if the player is firing it - if ( from_player && !(The_mission.ai_profile->flags2 & AIPF2_PLAYER_WEAPON_SCALE_FIX)) { + if ( from_player && !(The_mission.ai_profile->flags[AI::Profile_Flags::Player_weapon_scale_fix])) { // if it's a laser weapon if(wip->subtype == WP_LASER){ total_scale *= 0.01f; @@ -7120,10 +7120,10 @@ void weapon_render(object* obj, draw_list *scene) vec3d headp; vm_vec_scale_add(&headp, &obj->pos, &obj->orient.vec.fvec, wip->laser_length); - wp->weapon_flags &= ~WF_CONSIDER_FOR_FLYBY_SOUND; + wp->weapon_flags.remove(Weapon::Weapon_Flags::Consider_for_flyby_sound); if ( batch_add_laser(wip->laser_bitmap.first_frame + framenum, &headp, wip->laser_head_radius, &obj->pos, wip->laser_tail_radius, alpha, alpha, alpha) ) { - wp->weapon_flags |= WF_CONSIDER_FOR_FLYBY_SOUND; + wp->weapon_flags.set(Weapon::Weapon_Flags::Consider_for_flyby_sound); } } @@ -7229,7 +7229,7 @@ void weapon_render(object* obj, draw_list *scene) render_info.set_flags(render_flags); model_render_queue(&render_info, scene, wip->model_num, &obj->orient, &obj->pos); - wp->weapon_flags |= WF_CONSIDER_FOR_FLYBY_SOUND; + wp->weapon_flags.set(Weapon::Weapon_Flags::Consider_for_flyby_sound); break; } @@ -7549,7 +7549,7 @@ void weapon_info::reset() this->burst_delay = 1.0f; // 1 second, just incase its not defined this->burst_shots = 0; - this->burst_flags = 0; + this->burst_flags.reset(); generic_anim_init(&this->thruster_flame); generic_anim_init(&this->thruster_glow); diff --git a/code/windows_stub/stubs.cpp b/code/windows_stub/stubs.cpp index 3eb75f12b0..58230135dc 100644 --- a/code/windows_stub/stubs.cpp +++ b/code/windows_stub/stubs.cpp @@ -201,34 +201,9 @@ int _chdir(const char *path) // make specified directory int _mkdir(const char *path) { - int status = 1; // if we don't ever call mkdir() to update this then assume we are in error - char *c, tmp_path[MAX_PATH]; - - memset(tmp_path, 0, MAX_PATH); - strncpy(tmp_path, path, MAX_PATH-1); - - c = &tmp_path[1]; - - while (c++) { - c = strchr(c, '/'); - - if (c) { - *c = '\0'; - - status = mkdir(tmp_path, 0755); - -#ifndef NDEBUG - int m_error = errno; - - if (status && (m_error != EEXIST) ) { - Warning(__FILE__, __LINE__, "Cannot mkdir %s: %s", tmp_path, strerror(m_error)); - } -#endif - *c = '/'; - } - } - - return status; + // Windows _mkdir does not take file permissions as a parameter. + // umask already deals with that, so 0777 should be fine. + return mkdir(path, 0777); } void _splitpath (char *path, char *drive, char *dir, char *fname, char *ext) diff --git a/freespace2/freespace.cpp b/freespace2/freespace.cpp index 353a51a160..c7f2b8d629 100644 --- a/freespace2/freespace.cpp +++ b/freespace2/freespace.cpp @@ -5360,7 +5360,7 @@ void game_process_event( int current_state, int event ) shipfx_warpout_start( Player_obj ); Player->control_mode = PCM_WARPOUT_STAGE2; - if (!(The_mission.ai_profile->flags2 & AIPF2_NO_WARP_CAMERA)) { + if (!(The_mission.ai_profile->flags[AI::Profile_Flags::No_warp_camera])) { Player->saved_viewer_mode = Viewer_mode; Viewer_mode |= VM_WARP_CHASE; Warp_camera = warp_camera(Player_obj); diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index ddb77bbf93..cc9ea712ad 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -19,9 +19,8 @@ add_subdirectory(opengl) ADD_SUBDIRECTORY(libsdl) +ADD_SUBDIRECTORY(jansson) # These are only required for the web-ui which is non-Windows IF(UNIX) - ADD_SUBDIRECTORY(jansson) - ADD_SUBDIRECTORY(mongoose) ENDIF(UNIX) diff --git a/lib/jansson/CMakeLists.txt b/lib/jansson/CMakeLists.txt index 5bee9f8ec0..4905268675 100644 --- a/lib/jansson/CMakeLists.txt +++ b/lib/jansson/CMakeLists.txt @@ -49,7 +49,7 @@ # the source directory. # The rest is down to the usual make process. -IF(NOT ${FSO_BUILD_INCLUDED_LIBS} AND ${UNIX}) +IF(NOT FSO_BUILD_INCLUDED_LIBS AND UNIX) find_package(PkgConfig) if (PKG_CONFIG_FOUND) @@ -66,7 +66,7 @@ IF(NOT ${FSO_BUILD_INCLUDED_LIBS} AND ${UNIX}) endif() ENDIF() -IF(${FSO_BUILD_INCLUDED_LIBS} OR NOT ${JANSSON_FOUND}) +IF(FSO_BUILD_INCLUDED_LIBS OR NOT JANSSON_FOUND) MESSAGE(STATUS "Building jansson from source...") # Options set(USE_URANDOM ON)