Compare commits

..
Author SHA1 Message Date
SirKnightly 504108603d Automated build commit 2023-10-14 02:16:58 +00:00
259 changed files with 2438 additions and 5438 deletions

No files matched your search

+1 -5
View File
@@ -92,7 +92,6 @@ jobs:
name: Checkout
with:
submodules: true # `true` to checkout submodules, `recursive` to recursively checkout submodules
ref: '${{ github.ref }}'
- name: Prepare Vulkan SDK
uses: humbletim/[email protected]
with:
@@ -146,7 +145,6 @@ jobs:
with:
submodules: true
fetch-depth: '0' # value 0 to fetch all history and tags for all branches
ref: '${{ github.ref }}'
- name: Download Release builds
# Grab the release builds
uses: actions/download-artifact@v2
@@ -193,7 +191,6 @@ jobs:
name: Checkout
with:
submodules: true
ref: '${{ github.ref }}'
# - name: Cache Qt
# # Cache Qt
# id: cache-qt-win
@@ -288,7 +285,7 @@ jobs:
with:
submodules: true
fetch-depth: '0'
ref: '${{ github.ref }}'
- name: Download Release builds
uses: actions/download-artifact@v2
with:
@@ -360,7 +357,6 @@ jobs:
with:
submodules: true
fetch-depth: 0
ref: '${{ github.ref }}'
- name: Prepare Vulkan SDK
uses: humbletim/[email protected]
with:
-81
View File
@@ -1,81 +0,0 @@
name: Weekly Coverity Scan for Freespace Open
# adapted from code by "albert-github" on the doxygen repository
# many thanks for figuring this out first so it could be less painful for us!
# This mode is for testing
on: [push, pull_request]
# In production, push on a specific schedule
#on:
# schedule:
# - cron: "1 0 * * 5" # Run once per a week on Friday morning (midnight UTC, 4 AM EST), to avoid Coverity's submission limits
env:
QT_VERSION: 5.12.9
coverity_email: [email protected]
coverity_token: ${{ secrets.COVERITY_TOKEN }}
jobs:
build:
name: Build FSO With Coverity Wrapper
runs-on: ${{ matrix.config.os }}
strategy:
fail-fast: false
matrix:
config:
- { name: "GCC on ubuntu", os: ubuntu-latest, build_type: "Release" }
steps:
- name: Install Dependencies
run: |
sudo apt-get install ninja-build
sudo apt install cmake libsdl2-dev g++
sudo apt-get install libopenal-dev
sudo apt-get install -y libudev-dev
sudo apt-get install doxygen
sudo apt install graphviz
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive # `true` to checkout submodules, `recursive` to recursively checkout submodules
# pipe results of wget to a log file because it's very verbose and rarely fails
- name: Install Coverity
run: |
wget -o wgetlog.txt -q https://scan.coverity.com/download/cxx/linux64 --post-data "token=${{ env.coverity_token }}&project=scp-fs2open/fs2open.github.com" -O coverity_tool.tgz
mkdir cov-scan
tar ax -f coverity_tool.tgz --strip-components=1 -C cov-scan
- name: Setup Environment
run: |
echo "$(pwd)/cov-scan/bin" >> $GITHUB_PATH
echo "NPROC=$(getconf _NPROCESSORS_ONLN)" >> $GITHUB_ENV
- name: Prepare Vulkan SDK
uses: humbletim/[email protected]
with:
vulkan-query-version: 1.3.204.0
vulkan-components: Vulkan-Headers, Vulkan-Loader
vulkan-use-cache: true
- name: Configure CMake for FSO
env:
CONFIGURATION: Release
compiler: gcc-5
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
- name: Build FSO with Coverity Wrapper
working-directory: ./build
env:
CONFIGURATION: Release
run: cov-build --dir cov-int ninja -k 20 all
- name: Compress Results
working-directory: ./build
run: tar zcf cov-scan.tgz cov-int
#Comment this out when testing to keep from running into upload limits
- name: Upload to Coverity
run: |
cd build
curl --form token=${{ env.coverity_token }} --form email=${{ env.coverity_email }} --form [email protected] --form version="$(git rev-parse HEAD)" --form description="Automatic GHA scan" 'https://scan.coverity.com/builds?project=scp-fs2open/fs2open.github.com'
-1
View File
@@ -250,7 +250,6 @@ documentation/doxygen/*
projects/*
/.vs
CMakeSettings.json
CMakePresets.json
# Weird files created by Linux
.fuse_hidden*
+1 -1
View File
@@ -19,7 +19,7 @@
# HLP_API:
# HLP_KEY:
# LINUX_RESULT: bool, if the linux builds were successfully uploaded
# LINUX_RESULT: bool, if the linux builds were sucessfully uploaded
# WINDOWS_RESULT: bool, if the windows builds were successfully uploaded
import sys
+1 -1
View File
@@ -7,7 +7,7 @@ if (EXISTS "${PROJECT_SOURCE_DIR}/version_override.cmake")
endif()
set_if_not_defined(FSO_VERSION_MAJOR 23)
set_if_not_defined(FSO_VERSION_MINOR 3)
set_if_not_defined(FSO_VERSION_MINOR 1)
set_if_not_defined(FSO_VERSION_BUILD 0)
# A numeric revision e.g. the CI build number
+18 -9
View File
@@ -56,6 +56,12 @@ extern const int Num_ai_flag_names;
#define AIDO_DOCK_NOW 2 // Immediately move into dock position. For ships that start mission docked.
#define AIDO_UNDOCK 3 // Set goal of undocking with object.
// Submodes for seeking safety.
#define AISS_1 41 // Pick a spot to fly to.
#define AISS_2 42 // Flying to spot.
#define AISS_3 43 // Gotten near spot, fly about there.
#define AISS_1a 44 // Pick a new nearby spot because we are endangered, then go to AISS_2
// Flags to ai_turn_towards_vector().
#define AITTV_FAST (1<<0) // Turn fast, not slowed down based on skill level.
#define AITTV_VIA_SEXP (1<<1) // Goober5000 - via sexp
@@ -87,7 +93,7 @@ extern const int Num_ai_flag_names;
#define AIM_BAY_DEPART 18 // Departing to a fighter bay, following path to do so
#define AIM_SENTRYGUN 19 // AI mode for sentry guns only (floating turrets)
#define AIM_WARP_OUT 20 // Commence warp out sequence. Point in legal direction. Then call John's code.
#define AIM_FLY_TO_SHIP 21 // Rendezvous with a ship. Like stay-near, but non-perpetual.
#define AIM_FLY_TO_SHIP 21 // [Kazan] Fly to a ship, doesn't matter if it's hostile or friendly -- for Autopilot usage
#define AIM_LUA 22 // Generic Lua-based AI mode
#define MAX_AI_BEHAVIORS 23 // Number of AIM_xxxx types
@@ -180,12 +186,6 @@ typedef struct ai_class {
#define AIS_UNDOCK_3 33
#define AIS_UNDOCK_4 34
// Submodes for seeking safety.
#define AISS_1 41 // Pick a spot to fly to.
#define AISS_2 42 // Flying to spot.
#define AISS_3 43 // Gotten near spot, fly about there.
#define AISS_1a 44 // Pick a new nearby spot because we are endangered, then go to AISS_2. (Not implemented.)
// Submodes for Guard behavior
#define AIS_GUARD_PATROL 101
#define AIS_GUARD_ATTACK 102
@@ -240,6 +240,7 @@ typedef struct ai_info {
flagset<AI::AI_Flags> ai_flags; // Special flags for AI behavior.
int shipnum; // Ship using this slot, -1 means none.
int behavior; // AI behavior; vestigial field from early development of FS1
int mode;
int previous_mode;
int mode_time; // timestamp at which current mode elapses.
@@ -307,7 +308,6 @@ typedef struct ai_info {
fix submode_start_time; // time at which we entered the current submode
int submode_parm0; // parameter specific to current submode
int submode_parm1; // SUSHI: Another optional parameter
float submode_float0; // Goober5000: a float parameter
fix next_predict_pos_time; // Next time to predict position.
int next_dynamic_path_check_time; //ETP: Time of next path check in ai_new_maybe_reposition_attack_subsys
@@ -373,6 +373,11 @@ typedef struct ai_info {
float ai_turret_max_aim_update_delay;
flagset<AI::Profile_Flags> ai_profile_flags; //Holds AI_Profiles flags (possibly overriden by AI class) that actually apply to AI
union {
float stay_near_distance; // Distance to stay within for AIM_STAY_NEAR mode.
};
ship_subsys* targeted_subsys; // Targeted subobject on current target. NULL if none;
ship_subsys* last_subsys_target; // last known subsystem target
int targeted_subsys_parent; // Parent objnum of subobject, not necessarily targeted
@@ -560,7 +565,7 @@ extern void ai_attack_wing(object *attacker, int wingnum);
extern void ai_deathroll_start(object *ship_obj);
extern int set_target_objnum(ai_info *aip, int objnum);
extern void ai_form_on_wing(object *objp, object *goal_objp);
extern void ai_do_stay_near(object *objp, object *other_obj, float dist, int additional_data);
extern void ai_do_stay_near(object *objp, object *other_obj, float dist);
extern ship_subsys *set_targeted_subsys(ai_info *aip, ship_subsys *new_subsys, int parent_objnum);
extern void ai_rearm_repair( object *objp, int docker_index, object *goal_objp, int dockee_index );
extern void ai_add_rearm_goal( object *requester_objp, object *support_objp );
@@ -620,6 +625,10 @@ int get_nearest_objnum(int objnum, int enemy_team_mask, int enemy_wing, float ra
// moved to header file by Goober5000
void ai_announce_ship_dying(object *dying_objp);
// added by kazan
void ai_start_fly_to_ship(object *objp, int shipnum);
void ai_fly_to_ship();
//Moved declaration here for player ship -WMC
void ai_process_subobjects(int objnum);
-1
View File
@@ -156,7 +156,6 @@ namespace AI {
Whackable_debris,
Whackable_asteroids,
Dynamic_goals_afterburn_hard,
Hudsquadmsg_tactical_disarm_disable,
NUM_VALUES
};
+1 -8
View File
@@ -552,9 +552,7 @@ void parse_ai_profiles_tbl(const char *filename)
profile->flags.set(AI::Profile_Flags::All_nonshielded_ships_can_manage_ets, temp);
}
// ----------
set_flag(profile, "$no directional bias for missile and ship turning:", AI::Profile_Flags::No_turning_directional_bias);
set_flag(profile, "$no directional bias for missile and ship turning:", AI::Profile_Flags::No_turning_directional_bias);
set_flag(profile, "$respect ship axial turnrate differences:", AI::Profile_Flags::Use_axial_turnrate_differences);
@@ -625,8 +623,6 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$dynamic goals afterburn hard:", AI::Profile_Flags::Dynamic_goals_afterburn_hard);
set_flag(profile, "$hud squad messages use tactical disarm/disable:", AI::Profile_Flags::Hudsquadmsg_tactical_disarm_disable);
// if we've been through once already and are at the same place, force a move
if (saved_Mp && (saved_Mp == Mp))
{
@@ -816,7 +812,4 @@ void ai_profile_t::reset()
if (mod_supports_version(23, 2, 0)) {
flags.set(AI::Profile_Flags::Ships_playing_dead_dont_manage_ets);
}
if (mod_supports_version(23, 4, 0)) {
flags.set(AI::Profile_Flags::Hudsquadmsg_tactical_disarm_disable);
}
}
+2 -2
View File
@@ -914,13 +914,13 @@ static void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy)
}
if (tswp->num_secondary_banks > 0) {
if (!(En_objp->flags[Object::Object_Flags::Protected]) || (aip->goals[0].ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISABLE_SHIP_TACTICAL | AI_GOAL_DISARM_SHIP | AI_GOAL_DISARM_SHIP_TACTICAL))) {
if (!(En_objp->flags[Object::Object_Flags::Protected]) || (aip->goals[0].ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP))) {
bool valid_secondary = ai_choose_secondary_weapon(Pl_objp, aip, En_objp);
int current_bank = tswp->current_secondary_bank;
if (current_bank > -1 && valid_secondary) {
weapon_info *swip = &Weapon_info[tswp->secondary_bank_weapons[current_bank]];
if(!(En_objp->flags[Object::Object_Flags::Protected]) || ((aip->goals[0].ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISABLE_SHIP_TACTICAL | AI_GOAL_DISARM_SHIP | AI_GOAL_DISARM_SHIP_TACTICAL)) && swip->wi_flags[Weapon::Info_Flags::Puncture] )) { //override lockdown on protected ships when using anti subsystem weapons - Valathil
if(!(En_objp->flags[Object::Object_Flags::Protected]) || ((aip->goals[0].ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP)) && swip->wi_flags[Weapon::Info_Flags::Puncture] )) { //override lockdown on protected ships when using anti subsystem weapons - Valathil
// If ship is protected and very low on hits, don't fire missiles.
if (!(En_objp->flags[Object::Object_Flags::Protected]) || (En_objp->hull_strength > 10*swip->damage)) {
if (aip->ai_flags[AI::AI_Flags::Unload_secondaries]) {
+153 -94
View File
@@ -1316,7 +1316,7 @@ void ai_turn_towards_vector(vec3d* dest, object* objp, vec3d* slide_vec, vec3d*
// Don't allow a ship to turn if it has no engine strength.
// AL 3-12-98: objp may not always be a ship!
if ( (objp->type == OBJ_SHIP) && !(flags & AITTV_VIA_SEXP) ) {
if (!Ships[objp->instance].flags[Ship::Ship_Flags::Maneuver_despite_engines] && ship_get_subsystem_strength(&Ships[objp->instance], SUBSYSTEM_ENGINE) <= 0.0f)
if (ship_get_subsystem_strength(&Ships[objp->instance], SUBSYSTEM_ENGINE) <= 0.0f)
return;
}
@@ -3462,6 +3462,36 @@ void ai_dock_with_object(object *docker, int docker_index, object *dockee, int d
}
/*
* Cause a ship to fly toward a ship.
*/
void ai_start_fly_to_ship(object *objp, int shipnum)
{
ai_info *aip;
aip = &Ai_info[Ships[objp->instance].ai_index];
if (The_mission.flags[Mission::Mission_Flags::Use_ap_cinematics] && AutoPilotEngaged)
{
aip->ai_flags.remove(AI::AI_Flags::Formation_wing);
}
else
{
aip->ai_flags.set(AI::AI_Flags::Formation_wing);
}
aip->ai_flags.remove(AI::AI_Flags::Formation_object);
aip->mode = AIM_FLY_TO_SHIP;
aip->submode_start_time = Missiontime;
aip->target_objnum = Ships[shipnum].objnum;
// clear targeted subsystem
set_targeted_subsys(aip, nullptr, -1);
Assert(aip->active_goal != AI_ACTIVE_GOAL_DYNAMIC);
}
// Cause a ship to fly its waypoints.
// flags tells:
// WPF_REPEAT Set -> repeat waypoints.
@@ -3503,7 +3533,7 @@ void ai_start_waypoints(object *objp, waypoint_list *wp_list, int wp_flags)
/**
* Make *objp stay within dist units of *other_objp
*/
void ai_do_stay_near(object *objp, object *other_objp, float dist, int additional_data)
void ai_do_stay_near(object *objp, object *other_objp, float dist)
{
ai_info *aip;
@@ -3516,8 +3546,7 @@ void ai_do_stay_near(object *objp, object *other_objp, float dist, int additiona
aip->mode = AIM_STAY_NEAR;
aip->submode = -1;
aip->submode_start_time = Missiontime;
aip->submode_float0 = dist;
aip->submode_parm0 = additional_data;
aip->stay_near_distance = dist;
aip->goal_objnum = OBJ_INDEX(other_objp);
aip->goal_signature = other_objp->signature;
}
@@ -4893,6 +4922,84 @@ void ai_waypoints()
}
}
// --------------------------------------------------------------------------
// make Pl_objp fly toward a ship
void ai_fly_to_ship()
{
ai_info *aip;
object* target_p = NULL;
aip = &Ai_info[Ships[Pl_objp->instance].ai_index];
if ( aip->mode != AIM_FLY_TO_SHIP ) {
Warning(LOCATION,
"ai_fly_to_ship called for '%s' when ai_info.mode not equal to AIM_FLY_TO_SHIP. Is actually '%d'",
Ships[Pl_objp->instance].ship_name,
aip->mode);
aip->mode = AIM_NONE;
return;
}
if ( aip->active_goal < 0 || aip->active_goal >= MAX_AI_GOALS ) {
Warning(LOCATION,
"'%s' is trying to fly-to a ship without an active AI_GOAL\n\n"
"Active ai mode is '%d'",
Ships[Pl_objp->instance].ship_name,
aip->active_goal);
aip->mode = AIM_NONE;
return;
}
Assert( aip->goals[aip->active_goal].target_name != NULL );
if ( aip->goals[aip->active_goal].target_name[0] == '\0' ) {
Warning(LOCATION, "'%s' is trying to fly-to-ship without a name for the ship", Ships[Pl_objp->instance].ship_name);
aip->mode = AIM_NONE;
ai_remove_ship_goal( aip, aip->active_goal ); // function sets aip->active_goal to NONE for me
return;
}
for (int j = 0; j < MAX_SHIPS; j++)
{
if (Ships[j].objnum != -1 && !stricmp(aip->goals[aip->active_goal].target_name, Ships[j].ship_name))
{
target_p = &Objects[Ships[j].objnum];
break;
}
}
if ( target_p == NULL ) {
#ifndef NDEBUG
for (int i = 0; i < MAX_AI_GOALS; i++)
{
if (aip->mode == AIM_FLY_TO_SHIP || aip->goals[i].ai_mode == AI_GOAL_FLY_TO_SHIP)
{
mprintf(("Ship '%s' told to fly to target ship '%s'\n",
Ships[Pl_objp->instance].ship_name,
aip->goals[i].target_name));
}
}
#endif
Warning(LOCATION, "Ship '%s' told to fly to a ship but none of the ships it was told to fly to exist.\n"
"See log before this message for list of ships set as fly-to tagets",
Ships[Pl_objp->instance].ship_name);
aip->mode = AIM_NONE;
ai_remove_ship_goal( aip, aip->active_goal ); // function sets aip->active_goal to NONE for me
return;
} else {
bool done, treat_as_ship;
ai_fly_to_target_position(&(target_p->pos), &done, &treat_as_ship);
if ( done ) {
// remove the goal from the AI goals of the ship pr wing, respectively.
// Wether or not we should treat this as a ship or a wing is determined by
// ai_fly_to_target when it marks the AI directive as complete
if ( treat_as_ship ) {
ai_mission_goal_complete( aip ); // this call should reset the AI mode
} else {
ai_mission_wing_goal_complete( Ships[Pl_objp->instance].wingnum, &(aip->goals[aip->active_goal]) );
}
}
}
}
// Make Pl_objp avoid En_objp
// Not like evading. This is for avoiding a collision!
// Note, use sliding if available.
@@ -5564,7 +5671,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, Weapon::Info_Flag
Assert( shipp->ship_info_index >= 0 && shipp->ship_info_index < ship_info_size());
//made it so it only selects puncture weapons if the active goal is to disable something -Bobboau
if ((flags == Weapon::Info_Flags::Puncture) && (Ai_info[shipp->ai_index].goals[0].ai_mode & (AI_GOAL_DISARM_SHIP | AI_GOAL_DISARM_SHIP_TACTICAL | AI_GOAL_DISABLE_SHIP | AI_GOAL_DISABLE_SHIP_TACTICAL)))
if ((flags == Weapon::Info_Flags::Puncture) && (Ai_info[shipp->ai_index].goals[0].ai_mode & (AI_GOAL_DISARM_SHIP | AI_GOAL_DISABLE_SHIP)))
{
if (swp->current_primary_bank >= 0)
{
@@ -5789,7 +5896,7 @@ void set_primary_weapon_linkage(object *objp)
// puncture weapons
if ( (aip->active_goal != AI_GOAL_NONE) && (aip->active_goal != AI_ACTIVE_GOAL_DYNAMIC) )
{
if ( aip->goals[aip->active_goal].ai_mode & (AI_GOAL_DISABLE_SHIP|AI_GOAL_DISABLE_SHIP_TACTICAL|AI_GOAL_DISARM_SHIP|AI_GOAL_DISARM_SHIP_TACTICAL) )
if ( aip->goals[aip->active_goal].ai_mode & (AI_GOAL_DISABLE_SHIP|AI_GOAL_DISARM_SHIP) )
{
// only continue if both primaries are puncture weapons
if ( swp->num_primary_banks == 2 ) {
@@ -9379,15 +9486,9 @@ void ai_chase()
firing_range = MIN((swip->max_speed * swip->lifetime * 0.75f), swip->weapon_range);
else
{
float secondary_range_mult;
// Cyborg: need to check for division by zero, coverity 1523419
if (aip->ai_secondary_range_mult == FLT_MIN && (ai_maybe_autoscale(Num_ai_classes) > 1))
secondary_range_mult = (float)(Game_skill_level + 1 + (3 * ai_maybe_autoscale(aip->ai_class)/(ai_maybe_autoscale(Num_ai_classes) - 1)))/NUM_SKILL_LEVELS;
else if (aip->ai_secondary_range_mult == FLT_MIN)
secondary_range_mult = (float)(Game_skill_level + 2)/NUM_SKILL_LEVELS; // default to using the default retail class Captain out of the seven there are total when we don't have enough autoscale classes or just one regular class. (This simplifies to 2 + Game_skill_level / Num of skill levels)
else
secondary_range_mult = aip->ai_secondary_range_mult;
float secondary_range_mult = (aip->ai_secondary_range_mult == FLT_MIN)
? (float)(Game_skill_level + 1 + (3 * ai_maybe_autoscale(aip->ai_class)/(ai_maybe_autoscale(Num_ai_classes) - 1)))/NUM_SKILL_LEVELS
: aip->ai_secondary_range_mult;
firing_range = MIN((swip->max_speed * swip->lifetime * secondary_range_mult), swip->weapon_range);
}
@@ -9690,7 +9791,7 @@ float dock_orient_and_approach(object *docker_objp, int docker_index, object *do
// Goober5000 - moved out here to save calculations
if (dock_mode != DOA_DOCK_STAY)
if (!Ships[docker_objp->instance].flags[Ship::Ship_Flags::Maneuver_despite_engines] && ship_get_subsystem_strength(&Ships[docker_objp->instance], SUBSYSTEM_ENGINE) <= 0.0f)
if (ship_get_subsystem_strength(&Ships[docker_objp->instance], SUBSYSTEM_ENGINE) <= 0.0f)
return 9999.9f;
// If dockee has moved much, then path will be recreated.
@@ -11256,52 +11357,24 @@ void ai_still()
// Make *Pl_objp stay near another ship.
void ai_stay_near()
{
auto aip = &Ai_info[Ships[Pl_objp->instance].ai_index];
int goal_objnum = aip->goal_objnum;
ai_info *aip;
int goal_objnum;
aip = &Ai_info[Ships[Pl_objp->instance].ai_index];
goal_objnum = aip->goal_objnum;
if ((goal_objnum < 0) || (Objects[goal_objnum].type != OBJ_SHIP) || (Objects[goal_objnum].signature != aip->goal_signature)) {
aip->mode = AIM_NONE;
}
// "escort" behavior
else if (aip->submode_parm0 != 0) {
vec3d rand_vec, center_to_goal, center_to_objp;
auto goal_objp = &Objects[goal_objnum];
float max_dist = aip->submode_float0;
// Figure out a goal point to fly to
// Make not all ships pursue same point.
// Calculate the seed from both shipnums so the same Pl_objp doesn't always choose the same spot
static_randvec((goal_objp->instance * MAX_SHIPS) + (Pl_objp->instance), &rand_vec);
aip->goal_point = goal_objp->pos + max_dist * rand_vec;
// Make sure point is on the near side of goal_objp (relative to Pl_objp's position).
center_to_goal = aip->goal_point - goal_objp->pos;
center_to_objp = Pl_objp->pos - goal_objp->pos;
if (vm_vec_dot(&center_to_goal, &center_to_objp) < 0.0f) {
vm_vec_negate(&rand_vec);
aip->goal_point = goal_objp->pos + max_dist * rand_vec;
}
// Fly to the point
auto dist = vm_vec_dist_quick(&goal_objp->pos, &Pl_objp->pos);
if (dist > max_dist) {
turn_towards_point(Pl_objp, &aip->goal_point, nullptr, 0.0f);
accelerate_ship(aip, dist / max_dist - 0.8f);
float dot = vm_vec_dot_to_point(&Pl_objp->orient.vec.fvec, &Pl_objp->pos, &aip->goal_point);
if (ai_willing_to_afterburn_hard(aip) && dot > 0.99f && dist - max_dist > 700.0f)
ai_afterburn_hard(Pl_objp, aip);
}
}
// standard behavior
else {
} else {
float dist, max_dist, scale;
vec3d rand_vec, goal_pos, vec_to_goal;
auto goal_objp = &Objects[goal_objnum];
float max_dist = aip->submode_float0;
object *goal_objp;
goal_objp = &Objects[goal_objnum];
// Make not all ships pursue same point.
// Calculate the seed from both shipnums so the same Pl_objp doesn't always choose the same spot
static_randvec((goal_objp->instance * MAX_SHIPS) + (Pl_objp->instance), &rand_vec);
static_randvec(OBJ_INDEX(Pl_objp), &rand_vec);
// Make sure point is in front hemisphere (relative to Pl_objp's position.
vm_vec_sub(&vec_to_goal, &goal_objp->pos, &Pl_objp->pos);
@@ -11310,22 +11383,28 @@ void ai_stay_near()
}
// Scale the random vector by an amount proportional to the distance from Pl_objp to the true goal.
float dist = vm_vec_dist_quick(&goal_objp->pos, &Pl_objp->pos);
float scale = dist - max_dist/2;
dist = vm_vec_dist_quick(&goal_objp->pos, &Pl_objp->pos);
max_dist = aip->stay_near_distance;
scale = dist - max_dist/2;
if (scale < 0.0f)
scale = 0.0f;
vm_vec_scale_add(&goal_pos, &goal_objp->pos, &rand_vec, scale);
// Fly to the point
if (max_dist < Pl_objp->radius + goal_objp->radius + 25.0f)
max_dist = Pl_objp->radius + goal_objp->radius + 25.0f;
if (dist > max_dist) {
turn_towards_point(Pl_objp, &goal_pos, nullptr, 0.0f);
turn_towards_point(Pl_objp, &goal_pos, NULL, 0.0f);
accelerate_ship(aip, dist / max_dist - 0.8f);
float dot = vm_vec_dot_to_point(&Pl_objp->orient.vec.fvec, &Pl_objp->pos, &goal_pos);
if (ai_willing_to_afterburn_hard(aip) && dot > 0.99f && dist - max_dist > 700.0f)
ai_afterburn_hard(Pl_objp, aip);
}
}
}
// Warn player if dock path is obstructed.
@@ -12077,7 +12156,7 @@ object *get_wing_leader(int wingnum)
// If this ship is disabled, try another ship in the wing.
int n = 0;
while (!Ships[ship_num].flags[Ship::Ship_Flags::Maneuver_despite_engines] && ship_get_subsystem_strength(&Ships[ship_num], SUBSYSTEM_ENGINE) == 0.0f) {
while (ship_get_subsystem_strength(&Ships[ship_num], SUBSYSTEM_ENGINE) == 0.0f) {
n++;
if (n >= wingp->current_count) {
@@ -12420,7 +12499,7 @@ int ai_formation()
} else { // Formation flying in waypoint mode.
Assert(aip->ai_flags[AI::AI_Flags::Formation_wing]);
if ( aip->mode != AIM_WAYPOINTS ) {
if ( (aip->mode != AIM_WAYPOINTS) && (aip->mode != AIM_FLY_TO_SHIP) ) {
aip->ai_flags.remove(AI::AI_Flags::Formation_wing);
return 1;
}
@@ -13050,25 +13129,10 @@ void ai_manage_shield(object *objp, ai_info *aip)
// Scale between 1x and 3x based on ai_class (SUSHI: only if autoscale is on)
if (aip->ai_class_autoscale)
{
int number_of_as_classes = ai_get_autoscale_index(Num_ai_classes);
// Cyborg: Make sure that autoscale index is greater than one before dividing, coverity 1523548
if (The_mission.ai_profile->flags[AI::Profile_Flags::Adjusted_AI_class_autoscale] && number_of_as_classes > 1)
delay = delay + delay * (float)(3 * (number_of_as_classes - ai_get_autoscale_index(aip->ai_class) - 1) / (number_of_as_classes - 1));
else {
static bool autoscale_checked = false;
// warn if there's only one autoscale ai class
if (number_of_as_classes == 1 && !autoscale_checked) {
mprintf(("Warning! Having only 1 autoscale ai class will disable autoscale features that rely on division."));
autoscale_checked = true;
}
// Only adjust if we have more than one ai class to avoid div by 0
if (Num_ai_classes > 1){
delay = delay + delay * (float)(3 * (Num_ai_classes - aip->ai_class - 1) / (Num_ai_classes - 1));
}
}
if (The_mission.ai_profile->flags[AI::Profile_Flags::Adjusted_AI_class_autoscale])
delay = delay + delay * (float)(3 * (ai_get_autoscale_index(Num_ai_classes) - ai_get_autoscale_index(aip->ai_class) - 1) / (ai_get_autoscale_index(Num_ai_classes) - 1));
else
delay = delay + delay * (float)(3 * (Num_ai_classes - aip->ai_class - 1) / (Num_ai_classes - 1));
}
// set timestamp
@@ -13438,14 +13502,8 @@ int ai_acquire_emerge_path(object *pl_objp, int parent_objnum, int allowed_path_
}
}
// Cyborg: to avoid divide by zero and avoid a logic path that should not exist check for 0 allowed paths -- Coverity 1523287
if (num_allowed_paths == 0) {
bay_path = Ai_last_arrive_path % bay->num_paths;
UNREACHABLE("Parent_shipp in ai_acquire_emerge_path somehow does not have any allowed bay paths!");
} else {
// cycle through the allowed paths
bay_path = allowed_bay_paths[Ai_last_arrive_path % num_allowed_paths];
}
// cycle through the allowed paths
bay_path = allowed_bay_paths[Ai_last_arrive_path % num_allowed_paths];
}
// choose from among all paths
else
@@ -13863,7 +13921,6 @@ void ai_execute_behavior(ai_info *aip)
case AIM_STILL:
ai_still();
break;
case AIM_FLY_TO_SHIP: // same code as stay-near
case AIM_STAY_NEAR:
ai_stay_near();
break;
@@ -13873,6 +13930,9 @@ void ai_execute_behavior(ai_info *aip)
case AIM_WAYPOINTS:
ai_waypoints();
break;
case AIM_FLY_TO_SHIP:
ai_fly_to_ship();
break;
case AIM_DOCK:
ai_dock();
break;
@@ -14839,7 +14899,7 @@ void ai_frame(int objnum)
aip->ai_flags.remove(AI::AI_Flags::Avoid_shockwave_started);
}
// moved call to ai_do_repair frame here from below because of the subsequent if statement returning
// moved call to ai_do_repair frame here from below because of the subsequent if statment returning
// if the ship is getting repaired
// If waiting to be repaired, just stop and sit.
ai_do_repair_frame(Pl_objp, aip, flFrametime);
@@ -14961,9 +15021,9 @@ void ai_frame(int objnum)
if ( aip->targeted_subsys->current_hits <= 0.0f ) {
int subsys_type;
if ( aip->goals[0].ai_mode == AI_GOAL_DISABLE_SHIP || aip->goals[0].ai_mode == AI_GOAL_DISABLE_SHIP_TACTICAL ) {
if ( aip->goals[0].ai_mode == AI_GOAL_DISABLE_SHIP ) {
subsys_type = SUBSYSTEM_ENGINE;
} else if ( aip->goals[0].ai_mode == AI_GOAL_DISARM_SHIP || aip->goals[0].ai_mode == AI_GOAL_DISARM_SHIP_TACTICAL ) {
} else if ( aip->goals[0].ai_mode == AI_GOAL_DISARM_SHIP ) {
subsys_type = SUBSYSTEM_TURRET;
} else {
subsys_type = -1;
@@ -15219,7 +15279,6 @@ void init_ai_object(int objnum)
aip->submode_start_time = 0;
aip->submode_parm0 = 0;
aip->submode_parm1 = 0;
aip->submode_float0 = 0.0f;
aip->active_goal = -1;
aip->goal_check_time = timestamp(0);
aip->last_predicted_enemy_pos = near_vec;
+124 -133
View File
@@ -51,8 +51,6 @@ struct ship_registry_entry;
// Goober5000 - okay, this seems really stupid. If any ship in the mission is assigned a goal
// in PURGE_GOALS_ALL_SHIPS, *every* other ship will have certain goals purged. So I added
// PURGE_GOALS_ONE_SHIP for goals which should only purge other goals in the one ship.
// Goober5000 - note that the new disable and disarm goals (AI_GOAL_DISABLE_SHIP_TACTICAL and
// AI_GOAL_DISARM_SHIP_TACTICAL) do not purge ANY goals, not even the ones in the one ship
#define PURGE_GOALS_ALL_SHIPS (AI_GOAL_IGNORE | AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP)
#define PURGE_GOALS_ONE_SHIP (AI_GOAL_IGNORE_NEW)
@@ -77,9 +75,7 @@ ai_goal_list Ai_goal_names[] =
{ "Attack wing", AI_GOAL_CHASE_WING, 0 },
{ "Guard ship", AI_GOAL_GUARD, 0 },
{ "Disable ship", AI_GOAL_DISABLE_SHIP, 0 },
{ "Disable ship (tactical)",AI_GOAL_DISABLE_SHIP_TACTICAL, 0 },
{ "Disarm ship", AI_GOAL_DISARM_SHIP, 0 },
{ "Disarm ship (tactical)", AI_GOAL_DISARM_SHIP_TACTICAL, 0 },
{ "Attack any", AI_GOAL_CHASE_ANY, 0 },
{ "Ignore ship", AI_GOAL_IGNORE, 0 },
{ "Ignore ship (new)", AI_GOAL_IGNORE_NEW, 0 },
@@ -124,10 +120,8 @@ const char *Ai_goal_text(int goal, int submode)
case AI_GOAL_GUARD_WING:
return XSTR( "guard ", 480);
case AI_GOAL_DISABLE_SHIP:
case AI_GOAL_DISABLE_SHIP_TACTICAL:
return XSTR( "disable ", 481);
case AI_GOAL_DISARM_SHIP:
case AI_GOAL_DISARM_SHIP_TACTICAL:
return XSTR( "disarm ", 482);
case AI_GOAL_EVADE_SHIP:
return XSTR( "evade ", 483);
@@ -534,12 +528,11 @@ void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list, ai_info *ai
// ignore goals should get rid of any kind of attack goal
case AI_GOAL_IGNORE:
case AI_GOAL_IGNORE_NEW:
if ( purge_ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISABLE_SHIP_TACTICAL | AI_GOAL_DISARM_SHIP | AI_GOAL_DISARM_SHIP_TACTICAL | AI_GOAL_CHASE | AI_GOAL_CHASE_WING | AI_GOAL_CHASE_SHIP_CLASS | AI_GOAL_DESTROY_SUBSYSTEM) )
if ( purge_ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP | AI_GOAL_CHASE | AI_GOAL_CHASE_WING | AI_GOAL_CHASE_SHIP_CLASS | AI_GOAL_DESTROY_SUBSYSTEM) )
purge_goal->flags.set(AI::Goal_Flags::Purge);
break;
// disarm/disable goals should remove attacks from certain ships types
// (but not tactical disarm/disable)
case AI_GOAL_DISARM_SHIP:
case AI_GOAL_DISABLE_SHIP:
if ( purge_ai_mode & (AI_GOAL_CHASE | AI_GOAL_CHASE_WING | AI_GOAL_CHASE_SHIP_CLASS) ) {
@@ -556,17 +549,12 @@ void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list, ai_info *ai
}
// grab the ship type of the ship that is being disarmed/disabled
int crippled_ship_type = Ship_info[Ships[ship_index].ship_info_index].class_type;
ship_type_info *crippled_ships_type = &Ship_types[Ship_info[Ships[ship_index].ship_info_index].class_type];
if (ai_ship_type < 0 || crippled_ship_type < 0)
break;
ship_type_info *crippled_ship_type_info = &Ship_types[crippled_ship_type];
// work through all the ship types to see if the class matching our ai ship must ignore the ship
// work through all the ship types which to see if the class matching our ai ship must ignore the ship
// being disarmed/disabled
for ( j=0 ; j < (int)crippled_ship_type_info->ai_cripple_ignores.size(); j++) {
if (crippled_ship_type_info->ai_cripple_ignores[j] == ai_ship_type) {
for ( j=0 ; j < (int)crippled_ships_type->ai_cripple_ignores.size(); j++) {
if (crippled_ships_type->ai_cripple_ignores[j] == ai_ship_type) {
purge_goal->flags.set(AI::Goal_Flags::Purge);
}
}
@@ -943,16 +931,14 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, char
break;
case OP_AI_DISABLE_SHIP:
case OP_AI_DISABLE_SHIP_TACTICAL:
aigp->ai_mode = (op == OP_AI_DISABLE_SHIP) ? AI_GOAL_DISABLE_SHIP : AI_GOAL_DISABLE_SHIP_TACTICAL;
aigp->ai_mode = AI_GOAL_DISABLE_SHIP;
aigp->target_name = ai_get_goal_target_name( CTEXT(CDR(node)), &aigp->target_name_index );
aigp->ai_submode = -SUBSYSTEM_ENGINE;
aigp->priority = atoi( CTEXT(CDR(CDR(node))) );
break;
case OP_AI_DISARM_SHIP:
case OP_AI_DISARM_SHIP_TACTICAL:
aigp->ai_mode = (op == OP_AI_DISARM_SHIP) ? AI_GOAL_DISARM_SHIP : AI_GOAL_DISARM_SHIP_TACTICAL;
aigp->ai_mode = AI_GOAL_DISARM_SHIP;
aigp->target_name = ai_get_goal_target_name( CTEXT(CDR(node)), &aigp->target_name_index );
aigp->ai_submode = -SUBSYSTEM_TURRET;
aigp->priority = atoi( CTEXT(CDR(CDR(node))) );
@@ -1036,30 +1022,17 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, char
aigp->ai_mode = AI_GOAL_KEEP_SAFE_DISTANCE;
break;
case OP_AI_FLY_TO_SHIP:
case OP_AI_STAY_NEAR_SHIP:
{
bool is_nan, is_nan_forever;
aigp->target_name = ai_get_goal_target_name( CTEXT(CDR(node)), &aigp->target_name_index );
aigp->priority = atoi( CTEXT(CDDR(node)) );
// distance from ship
if ( CDDDR(node) < 0 )
aigp->float_data = 300.0f;
else
aigp->float_data = i2fl(eval_num(CDDDR(node), is_nan, is_nan_forever));
// (the CDDDDR argument is whether to afterburn, and is handled at the end of the function, so don't handle it here)
// whether to "escort" the ship
if ( CDDDDDR(node) >= 0 )
aigp->int_data = is_sexp_true(CDDDDDR(node)) ? 1 : 0;
if (op == OP_AI_FLY_TO_SHIP)
aigp->ai_mode = AI_GOAL_FLY_TO_SHIP;
else
aigp->ai_mode = AI_GOAL_STAY_NEAR_SHIP;
aigp->ai_mode = AI_GOAL_STAY_NEAR_SHIP;
break;
}
@@ -1077,6 +1050,7 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, char
case OP_AI_EVADE_SHIP:
case OP_AI_IGNORE:
case OP_AI_IGNORE_NEW:
case OP_AI_FLY_TO_SHIP:
aigp->target_name = ai_get_goal_target_name( CTEXT(CDR(node)), &aigp->target_name_index );
aigp->priority = atoi( CTEXT(CDR(CDR(node))) );
@@ -1103,10 +1077,14 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, char
aigp->ai_mode = AI_GOAL_CHASE_WING;
} else if (op == OP_AI_CHASE_SHIP_CLASS) {
aigp->ai_mode = AI_GOAL_CHASE_SHIP_CLASS;
} else if ( op == OP_AI_STAY_NEAR_SHIP ) {
aigp->ai_mode = AI_GOAL_STAY_NEAR_SHIP;
} else if ( op == OP_AI_IGNORE ) {
aigp->ai_mode = AI_GOAL_IGNORE;
} else if ( op == OP_AI_IGNORE_NEW ) {
aigp->ai_mode = AI_GOAL_IGNORE_NEW;
} else if ( op == OP_AI_FLY_TO_SHIP ) {
aigp->ai_mode = AI_GOAL_FLY_TO_SHIP;
} else
UNREACHABLE("Coding error: unhandled AI goal in ai_add_goal_sub_sexp!");
@@ -1143,8 +1121,7 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, char
}
// Goober5000 - we now have an extra optional chase argument to allow chasing our own team
if ( op == OP_AI_CHASE || op == OP_AI_CHASE_WING || op == OP_AI_CHASE_SHIP_CLASS
|| op == OP_AI_DISABLE_SHIP || op == OP_AI_DISABLE_SHIP_TACTICAL || op == OP_AI_DISARM_SHIP || op == OP_AI_DISARM_SHIP_TACTICAL ) {
if ( op == OP_AI_CHASE || op == OP_AI_CHASE_WING || op == OP_AI_CHASE_SHIP_CLASS || op == OP_AI_DISABLE_SHIP || op == OP_AI_DISARM_SHIP ) {
if (is_sexp_true(CDDDR(node)))
aigp->flags.set(AI::Goal_Flags::Target_own_team);
}
@@ -1161,7 +1138,8 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, char
if (op == OP_AI_GUARD ||
op == OP_AI_GUARD_WING ||
op == OP_AI_WAYPOINTS ||
op == OP_AI_WAYPOINTS_ONCE) {
op == OP_AI_WAYPOINTS_ONCE ||
op == OP_AI_FLY_TO_SHIP) {
if (is_sexp_true(CDDDR(node)))
aigp->flags.set(AI::Goal_Flags::Afterburn_hard);
}
@@ -1169,11 +1147,8 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, char
op == OP_AI_CHASE_WING ||
op == OP_AI_CHASE_SHIP_CLASS ||
op == OP_AI_DISABLE_SHIP ||
op == OP_AI_DISABLE_SHIP_TACTICAL ||
op == OP_AI_DISARM_SHIP ||
op == OP_AI_DISARM_SHIP_TACTICAL ||
op == OP_AI_STAY_NEAR_SHIP ||
op == OP_AI_FLY_TO_SHIP) {
op == OP_AI_STAY_NEAR_SHIP) {
if (is_sexp_true(CDDDDR(node)))
aigp->flags.set(AI::Goal_Flags::Afterburn_hard);
}
@@ -1248,13 +1223,11 @@ int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp )
priority = ( CDR( CDR( CDR(node) ) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( CDR( node ) ) ) ) ) : -1;
break;
case OP_AI_DISABLE_SHIP:
case OP_AI_DISABLE_SHIP_TACTICAL:
goalmode = (op == OP_AI_DISABLE_SHIP) ? AI_GOAL_DISABLE_SHIP : AI_GOAL_DISABLE_SHIP_TACTICAL;
goalmode = AI_GOAL_DISABLE_SHIP;
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
break;
case OP_AI_DISARM_SHIP:
case OP_AI_DISARM_SHIP_TACTICAL:
goalmode = (op == OP_AI_DISARM_SHIP) ? AI_GOAL_DISARM_SHIP : AI_GOAL_DISARM_SHIP_TACTICAL;
goalmode = AI_GOAL_DISABLE_SHIP;
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
break;
case OP_AI_WARP_OUT:
@@ -1284,8 +1257,11 @@ int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp )
priority = ( CDR(node) >= 0 ) ? atoi( CTEXT( CDR( node ) ) ) : -1;
break;
case OP_AI_PLAY_DEAD:
goalmode = AI_GOAL_PLAY_DEAD;
priority = ( CDR(node) >= 0 ) ? atoi( CTEXT( CDR( node ) ) ) : -1;
break;
case OP_AI_PLAY_DEAD_PERSISTENT:
goalmode = (op == OP_AI_PLAY_DEAD) ? AI_GOAL_PLAY_DEAD : AI_GOAL_PLAY_DEAD_PERSISTENT;
goalmode = AI_GOAL_PLAY_DEAD_PERSISTENT;
priority = ( CDR(node) >= 0 ) ? atoi( CTEXT( CDR( node ) ) ) : -1;
break;
case OP_AI_KEEP_SAFE_DISTANCE:
@@ -1327,9 +1303,12 @@ int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp )
goalmode = AI_GOAL_STAY_NEAR_SHIP;
break;
case OP_AI_IGNORE:
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
goalmode = AI_GOAL_IGNORE;
break;
case OP_AI_IGNORE_NEW:
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
goalmode = (op == OP_AI_IGNORE) ? AI_GOAL_IGNORE : AI_GOAL_IGNORE_NEW;
goalmode = AI_GOAL_IGNORE_NEW;
break;
case OP_AI_FORM_ON_WING:
priority = 99;
@@ -1551,11 +1530,13 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
{
int status;
ai_achievability return_val;
ai_info *aip;
int index = -1, sindex = -1;
int modelnum = -1;
auto objp = &Objects[objnum];
Assert( objp->instance != -1 );
auto shipp = &Ships[objp->instance];
auto aip = &Ai_info[shipp->ai_index];
aip = &Ai_info[Ships[objp->instance].ai_index];
// these orders are always achievable.
if ( (aigp->ai_mode == AI_GOAL_KEEP_SAFE_DISTANCE)
@@ -1566,11 +1547,11 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
if (aigp->ai_mode == AI_GOAL_LUA)
return ai_lua_is_achievable(aigp, objnum);
auto target_ship_entry = aigp->target_name == nullptr ? nullptr : ship_registry_get(aigp->target_name);
// warp (depart) only achievable if there's somewhere to depart to
if (aigp->ai_mode == AI_GOAL_WARP)
{
ship *shipp = &Ships[objp->instance];
// always valid if has working subspace drive, not disabled, and not limited by subsystem strength
if ( ship_can_warp_full_check(shipp) )
return ai_achievability::ACHIEVABLE;
@@ -1589,7 +1570,9 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// if the wing target is valid then be sure to set the override bit so that it always
// gets executed next
if ( aigp->ai_mode == AI_GOAL_FORM_ON_WING ) {
if (!target_ship_entry || !target_ship_entry->shipp)
sindex = ship_name_lookup( aigp->target_name );
if (sindex < 0)
return ai_achievability::NOT_ACHIEVABLE;
aigp->flags.set(AI::Goal_Flags::Goal_override);
@@ -1646,10 +1629,11 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// shipnum could be -1 depending on if the ship hasn't arrived or died. only look for subsystem
// destroyed when shipnum is valid
sindex = ship_name_lookup( aigp->target_name );
// can't determine the status of this goal if ship not valid
// or we haven't found a valid subsystem index yet
if ( !target_ship_entry || !target_ship_entry->shipp || (aigp->flags[AI::Goal_Flags::Subsys_needs_fixup]) ) {
if ( (sindex == -1) || (aigp->flags[AI::Goal_Flags::Subsys_needs_fixup]) ) {
status = 0;
break;
}
@@ -1658,46 +1642,46 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// as 0 so we can continue. (The subsystem name must be turned into an index into the ship's subsystems
// for this goal to be valid).
Assert ( aigp->ai_submode >= 0 );
ssp = ship_get_indexed_subsys( target_ship_entry->shipp, aigp->ai_submode );
ssp = ship_get_indexed_subsys( &Ships[sindex], aigp->ai_submode );
if (ssp != NULL) {
// see MWA 3/20/97 comment above - instead of checking the mission log, check the current hits
status = (ssp->current_hits <= 0.0f) ? 1 : 0;
} else {
// not supposed to ever happen, but could if there is a mismatch between the table and model subsystems
nprintf(("AI", "Couldn't find subsystem %d for ship %s\n", aigp->ai_submode, target_ship_entry->shipp->ship_name));
nprintf(("AI", "Couldn't find subsystem %d for ship %s\n", aigp->ai_submode, Ships[sindex].ship_name));
status = 0;
}
break;
}
case AI_GOAL_DISABLE_SHIP:
case AI_GOAL_DISABLE_SHIP_TACTICAL:
{
// shipnum could be -1 depending on if the ship hasn't arrived or died. only look for subsystem
// destroyed when shipnum is valid
sindex = ship_name_lookup(aigp->target_name);
// can't determine the status of this goal if ship not valid
if (!target_ship_entry || !target_ship_entry->shipp) {
if (sindex < 0) {
status = 0;
} else {
// see MWA 3/20/97 comment above - instead of checking the mission log, check the current hits
status = (target_ship_entry->shipp->subsys_info[SUBSYSTEM_ENGINE].aggregate_current_hits <= 0.0f) ? 1 : 0;
status = (Ships[sindex].subsys_info[SUBSYSTEM_ENGINE].aggregate_current_hits <= 0.0f) ? 1 : 0;
}
break;
}
case AI_GOAL_DISARM_SHIP:
case AI_GOAL_DISARM_SHIP_TACTICAL:
{
// shipnum could be -1 depending on if the ship hasn't arrived or died. only look for subsystem
// destroyed when shipnum is valid
sindex = ship_name_lookup(aigp->target_name);
// can't determine the status of this goal if ship not valid
if (!target_ship_entry || !target_ship_entry->shipp) {
if (sindex < 0) {
status = 0;
} else {
// see MWA 3/20/97 comment above - instead of checking the mission log, check the current hits
status = (target_ship_entry->shipp->subsys_info[SUBSYSTEM_TURRET].aggregate_current_hits <= 0.0f) ? 1 : 0;
status = (Ships[sindex].subsys_info[SUBSYSTEM_TURRET].aggregate_current_hits <= 0.0f) ? 1 : 0;
}
break;
}
@@ -1716,23 +1700,22 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// MWA -- 4/22/98. Check for the ship actually being in the mission before
// checking departure and destroyed. In multiplayer, since ships can respawn,
// they get log entries for being destroyed even though they have respawned.
// Goober5000 - update this to use ship registry status with similar logic
if (target_ship_entry && target_ship_entry->status == ShipStatus::EXITED) {
status = 1;
return_val = ai_achievability::NOT_ACHIEVABLE;
sindex = ship_name_lookup( aigp->target_name );
if ( sindex < 0 ) {
status = mission_log_get_time( LOG_SHIP_DEPARTED, aigp->target_name, NULL, NULL);
if ( !status ) {
status = mission_log_get_time( LOG_SHIP_DESTROYED, aigp->target_name, NULL, NULL);
if ( !status ) {
status = mission_log_get_time( LOG_SELF_DESTRUCTED, aigp->target_name, NULL, NULL);
}
}
if ( status )
return_val = ai_achievability::NOT_ACHIEVABLE;
} else {
status = 0;
}
// fly-to-ship can potentially be determined
if (aigp->ai_mode == AI_GOAL_FLY_TO_SHIP && target_ship_entry && target_ship_entry->objp) {
auto dist = vm_vec_dist(&target_ship_entry->objp->pos, &objp->pos);
if (dist < aigp->float_data) {
return_val = ai_achievability::SATISFIED;
status = 1;
}
}
break;
}
@@ -1785,12 +1768,12 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// the if statement.
if ( (aigp->ai_mode == AI_GOAL_CHASE_WING) || (aigp->ai_mode == AI_GOAL_GUARD_WING) )
{
int wingnum = wing_name_lookup( aigp->target_name );
sindex = wing_name_lookup( aigp->target_name );
if (wingnum < 0)
if (sindex < 0)
return ai_achievability::NOT_KNOWN;
wing *wingp = &Wings[wingnum];
wing *wingp = &Wings[sindex];
if ( wingp->flags[Ship::Wing_Flags::Gone] )
return ai_achievability::NOT_ACHIEVABLE;
@@ -1807,22 +1790,24 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
}
else
{
if (!target_ship_entry)
auto ship_entry = ship_registry_get(aigp->target_name);
if (!ship_entry)
{
status = SHIP_STATUS_UNKNOWN;
}
// goal ship is currently in mission
else if (target_ship_entry->status == ShipStatus::PRESENT || target_ship_entry->status == ShipStatus::DEATH_ROLL)
else if (ship_entry->status == ShipStatus::PRESENT || ship_entry->status == ShipStatus::DEATH_ROLL)
{
status = SHIP_STATUS_ARRIVED;
}
// goal ship is still on the arrival list
else if (target_ship_entry->status == ShipStatus::NOT_YET_PRESENT)
else if (ship_entry->status == ShipStatus::NOT_YET_PRESENT)
{
status = SHIP_STATUS_NOT_ARRIVED;
}
// goal ship has left the area
else if (target_ship_entry->status == ShipStatus::EXITED)
else if (ship_entry->status == ShipStatus::EXITED)
{
status = SHIP_STATUS_GONE;
}
@@ -1833,16 +1818,18 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
if (status == SHIP_STATUS_UNKNOWN)
{
mprintf(("Potentially incorrect behaviour in AI goal for ship %s: Ship %s could not be found among currently active, departed, or yet-to-arrive ships.\nPlease check the mission file.\n", shipp->ship_name, aigp->target_name));
mprintf(("Potentially incorrect behaviour in AI goal for ship %s: Ship %s could not be found among currently active, departed, or yet-to-arrive ships.\nPlease check the mission file.\n", Ships[objp->instance].ship_name, aigp->target_name));
}
}
// Goober5000 - before doing anything else, check if this is a disarm goal for an arrived ship...
if ((status == SHIP_STATUS_ARRIVED) && (aigp->ai_mode == AI_GOAL_DISARM_SHIP || aigp->ai_mode == AI_GOAL_DISARM_SHIP_TACTICAL))
if ((status == SHIP_STATUS_ARRIVED) && (aigp->ai_mode == AI_GOAL_DISARM_SHIP))
{
if (target_ship_entry && target_ship_entry->shipp) {
sindex = ship_name_lookup(aigp->target_name);
if ( sindex >= 0 ) {
// if the ship has no turrets, we can't disarm it!
if (target_ship_entry->shipp->subsys_info[SUBSYSTEM_TURRET].type_count == 0)
if (Ships[sindex].subsys_info[SUBSYSTEM_TURRET].type_count == 0)
return ai_achievability::NOT_ACHIEVABLE;
} else {
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
@@ -1869,36 +1856,40 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// this goal will get removed.
if ( (aigp->ai_mode == AI_GOAL_DOCK) && (status == SHIP_STATUS_ARRIVED) ) {
if (!(aigp->flags[AI::Goal_Flags::Docker_index_valid])) {
int modelnum = Ship_info[shipp->ship_info_index].model_num;
modelnum = Ship_info[Ships[objp->instance].ship_info_index].model_num;
Assert( modelnum >= 0 );
aigp->docker.index = model_find_dock_name_index(modelnum, aigp->docker.name);
index = model_find_dock_name_index(modelnum, aigp->docker.name);
aigp->docker.index = index;
aigp->flags.set(AI::Goal_Flags::Docker_index_valid);
}
if (!(aigp->flags[AI::Goal_Flags::Dockee_index_valid])) {
if (target_ship_entry && target_ship_entry->shipp) {
int modelnum = Ship_info[target_ship_entry->shipp->ship_info_index].model_num;
aigp->dockee.index = model_find_dock_name_index(modelnum, aigp->dockee.name);
sindex = ship_name_lookup(aigp->target_name);
if ( sindex != -1 ) {
modelnum = Ship_info[Ships[sindex].ship_info_index].model_num;
index = model_find_dock_name_index(modelnum, aigp->dockee.name);
aigp->dockee.index = index;
aigp->flags.set(AI::Goal_Flags::Dockee_index_valid);
} else
aigp->dockee.index = -1; // this will force code into if statement below making goal not achievable.
}
if ( (aigp->dockee.index == -1) || (aigp->docker.index == -1) ) {
Warning(LOCATION, "Cannot determine docking information for %s!", shipp->ship_name); // for now, allender wants to know about these things!!!!
Warning(LOCATION, "Cannot determine docking information for %s!", Ships[objp->instance].ship_name); // for now, allender wants to know about these things!!!!
return ai_achievability::NOT_ACHIEVABLE;
}
// if ship is disabled, don't know if it can dock or not
if ( shipp->flags[Ship::Ship_Flags::Disabled] )
if ( Ships[objp->instance].flags[Ship::Ship_Flags::Disabled] )
return ai_achievability::NOT_KNOWN;
// we must also determine if we're prevented from docking for any reason
if (!target_ship_entry || !target_ship_entry->shipp) {
sindex = ship_name_lookup(aigp->target_name);
if (sindex < 0) {
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
return ai_achievability::NOT_ACHIEVABLE; // force this goal to be invalid
}
auto goal_objp = target_ship_entry->objp;
object *goal_objp = &Objects[Ships[sindex].objnum];
// if the ship that I am supposed to dock with is docked with something else, then I need to put my goal on hold
// [MK, 4/23/98: With Mark, we believe this fixes the problem of Comet refusing to warp out after docking with Omega.
@@ -1947,9 +1938,11 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// might happen too, so err on the safe side. (Yay for emergent paragraph justification!)
if ((aip->mode == AIM_DOCK) && (aip->submode >= AIS_UNDOCK_0))
{
if ( target_ship_entry && target_ship_entry->shipp ) {
sindex = ship_name_lookup(aigp->target_name);
if ( sindex >= 0 ) {
// only put it on hold if it's someone other than the guy we're undocking from right now!!
if (aip->goal_objnum != target_ship_entry->shipp->objnum)
if (aip->goal_objnum != Ships[sindex].objnum)
return ai_achievability::NOT_KNOWN;
} else {
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
@@ -1962,8 +1955,10 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// have fixed up the subsystem name (of the subsystem to destroy) into an index into
// the ship's subsystem list
if ( aigp->flags[AI::Goal_Flags::Subsys_needs_fixup] ) {
if ( target_ship_entry && target_ship_entry->shipp ) {
aigp->ai_submode = ship_find_subsys( target_ship_entry->shipp, aigp->docker.name );
sindex = ship_name_lookup( aigp->target_name );
if ( sindex != -1 ) {
aigp->ai_submode = ship_find_subsys( &Ships[sindex], aigp->docker.name );
aigp->flags.remove(AI::Goal_Flags::Subsys_needs_fixup);
} else {
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
@@ -1971,12 +1966,15 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
}
}
} else if ( ((aigp->ai_mode == AI_GOAL_IGNORE) || (aigp->ai_mode == AI_GOAL_IGNORE_NEW)) && (status == SHIP_STATUS_ARRIVED) ) {
object *ignored;
// for ignoring a ship, call the ai_ignore object function, then declare the goal satisfied
if (!target_ship_entry || !target_ship_entry->shipp) {
sindex = ship_name_lookup( aigp->target_name );
if (sindex < 0) {
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
return ai_achievability::NOT_ACHIEVABLE; // force this goal to be invalid
}
auto ignored = target_ship_entry->objp;
ignored = &Objects[Ships[sindex].objnum];
ai_ignore_object(objp, ignored, (aigp->ai_mode == AI_GOAL_IGNORE_NEW));
@@ -1992,9 +1990,7 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
case AI_GOAL_GUARD:
case AI_GOAL_GUARD_WING:
case AI_GOAL_DISABLE_SHIP:
case AI_GOAL_DISABLE_SHIP_TACTICAL:
case AI_GOAL_DISARM_SHIP:
case AI_GOAL_DISARM_SHIP_TACTICAL:
case AI_GOAL_DESTROY_SUBSYSTEM:
case AI_GOAL_IGNORE:
case AI_GOAL_IGNORE_NEW:
@@ -2011,7 +2007,7 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
else if ( status == SHIP_STATUS_UNKNOWN )
return ai_achievability::NOT_KNOWN;
UNREACHABLE("Invalid status variable %d for ship %s; get Allender or a SCP member", status, shipp->ship_name); // get allender -- bad logic
UNREACHABLE("Invalid status variable %d for ship %s; get Allender or a SCP member", status, Ships[objp->instance].ship_name); // get allender -- bad logic
break;
}
@@ -2023,29 +2019,30 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// short circuit a couple of cases. Ship not arrived shouldn't happen. Ship gone means
// we mark the goal as not achievable.
if ( status == SHIP_STATUS_NOT_ARRIVED ) {
UNREACHABLE("Ship %s cannot rearm a target %s that hasn't arrived; get Allender or a SCP member", shipp->ship_name, aigp->target_name); // get Allender. this shouldn't happen!!!
UNREACHABLE("Ship %s cannot rearm a target %s that hasn't arrived; get Allender or a SCP member", Ships[objp->instance].ship_name, aigp->target_name); // get Allender. this shouldn't happen!!!
return ai_achievability::NOT_ACHIEVABLE;
}
if ( status == SHIP_STATUS_GONE )
return ai_achievability::NOT_ACHIEVABLE;
if ( !target_ship_entry || !target_ship_entry->shipp ) {
sindex = ship_name_lookup( aigp->target_name );
if ( sindex < 0 ) {
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
return ai_achievability::NOT_ACHIEVABLE;
}
// if destination currently being repaired, then goal is still active
if ( Ai_info[target_ship_entry->shipp->ai_index].ai_flags[AI::AI_Flags::Being_repaired] )
// if desitnation currently being repaired, then goal is stil active
if ( Ai_info[Ships[sindex].ai_index].ai_flags[AI::AI_Flags::Being_repaired] )
return ai_achievability::ACHIEVABLE;
// if the destination ship is dying or departing (but not completed yet), the mark goal as
// not achievable.
if ( target_ship_entry->shipp->is_dying_or_departing())
if ( Ships[sindex].is_dying_or_departing())
return ai_achievability::NOT_ACHIEVABLE;
// if the destination object is no longer awaiting repair, then remove the item
if ( !(Ai_info[target_ship_entry->shipp->ai_index].ai_flags[AI::AI_Flags::Awaiting_repair]) )
if ( !(Ai_info[Ships[sindex].ai_index].ai_flags[AI::AI_Flags::Awaiting_repair]) )
return ai_achievability::NOT_ACHIEVABLE;
// not repairing anything means that he can do this goal!!!
@@ -2060,7 +2057,7 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// if he is repairing something, he can satisfy his repair goal (his goal_objnum)
// return GOAL_NOT_KNOWN which is kind of a hack which puts the goal on hold until it can be
// satisfied.
if ( aip->goal_objnum != target_ship_entry->shipp->objnum )
if ( aip->goal_objnum != Ships[sindex].objnum )
return ai_achievability::NOT_KNOWN;
return ai_achievability::ACHIEVABLE;
@@ -2341,6 +2338,12 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
break;
}
case AI_GOAL_FLY_TO_SHIP:
shipnum = ship_name_lookup( current_goal->target_name );
Assert (shipnum != -1 ); // shouldn't get here if this is false!!!!
ai_start_fly_to_ship(objp, shipnum);
break;
case AI_GOAL_DOCK: {
shipnum = ship_name_lookup( current_goal->target_name );
Assert (shipnum != -1 ); // shouldn't get here if this is false!!!!
@@ -2415,27 +2418,22 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
break;
// when destroying a subsystem, we can destroy a specific instance of a subsystem
// or all instances of a type of subsystem (i.e. a specific engine or all engines).
// the ai_submode value is > 0 for a specific instance of subsystem and < 0 for all
// instances of a specific type
// when destroying a subsystem, we can destroy a specific instance of a subsystem
// or all instances of a type of subsystem (i.e. a specific engine or all engines).
// the ai_submode value is > 0 for a specific instance of subsystem and < 0 for all
// instances of a specific type
case AI_GOAL_DESTROY_SUBSYSTEM:
case AI_GOAL_DISABLE_SHIP:
case AI_GOAL_DISABLE_SHIP_TACTICAL:
case AI_GOAL_DISARM_SHIP:
case AI_GOAL_DISARM_SHIP_TACTICAL: {
case AI_GOAL_DISARM_SHIP: {
shipnum = ship_name_lookup( current_goal->target_name );
Assert( shipnum >= 0 );
other_obj = &Objects[Ships[shipnum].objnum];
ai_attack_object( objp, other_obj);
ai_set_attack_subsystem( objp, current_goal->ai_submode ); // submode stored the subsystem type
// don't protect-ship for tactical goals
if (current_goal->ai_mode != AI_GOAL_DESTROY_SUBSYSTEM && current_goal->ai_mode != AI_GOAL_DISABLE_SHIP_TACTICAL && current_goal->ai_mode != AI_GOAL_DISARM_SHIP_TACTICAL) {
if (current_goal->ai_mode != AI_GOAL_DESTROY_SUBSYSTEM) {
if (aip->target_objnum != -1) {
int class_type = Ship_info[Ships[shipnum].ship_info_index].class_type;
// Only protect if _not_ a capital ship. We don't want the Lucifer accidentally getting protected.
if (class_type >= 0 && Ship_types[class_type].flags[Ship::Type_Info_Flags::AI_protected_on_cripple])
if (Ship_types[Ship_info[Ships[shipnum].ship_info_index].class_type].flags[Ship::Type_Info_Flags::AI_protected_on_cripple])
Objects[aip->target_objnum].flags.set(Object::Object_Flags::Protected);
}
} else // Just in case this ship had been protected, unprotect it.
@@ -2513,17 +2511,14 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
// labels for support ship commands
case AI_GOAL_STAY_NEAR_SHIP:
case AI_GOAL_FLY_TO_SHIP:
{
case AI_GOAL_STAY_NEAR_SHIP: {
shipnum = ship_name_lookup( current_goal->target_name );
Assert( shipnum >= 0 );
other_obj = &Objects[Ships[shipnum].objnum];
float dist = current_goal->float_data; // How far away to stay from ship. Should be set in SEXP?
int additional_data = current_goal->int_data; // Whether to target a particular point as if escorting
ai_do_stay_near(objp, other_obj, dist, additional_data);
ai_do_stay_near(objp, other_obj, dist);
break;
}
}
case AI_GOAL_KEEP_SAFE_DISTANCE:
// todo MK: hook to keep support ship at a safe distance
@@ -2571,9 +2566,7 @@ void ai_update_goal_references(ai_goal *goals, sexp_ref_type type, const char *o
case AI_GOAL_DESTROY_SUBSYSTEM:
case AI_GOAL_GUARD:
case AI_GOAL_DISABLE_SHIP:
case AI_GOAL_DISABLE_SHIP_TACTICAL:
case AI_GOAL_DISARM_SHIP:
case AI_GOAL_DISARM_SHIP_TACTICAL:
case AI_GOAL_IGNORE:
case AI_GOAL_IGNORE_NEW:
case AI_GOAL_EVADE_SHIP:
@@ -2647,9 +2640,7 @@ bool query_referenced_in_ai_goals(ai_goal *goals, sexp_ref_type type, const char
case AI_GOAL_DESTROY_SUBSYSTEM:
case AI_GOAL_GUARD:
case AI_GOAL_DISABLE_SHIP:
case AI_GOAL_DISABLE_SHIP_TACTICAL:
case AI_GOAL_DISARM_SHIP:
case AI_GOAL_DISARM_SHIP_TACTICAL:
case AI_GOAL_IGNORE:
case AI_GOAL_IGNORE_NEW:
case AI_GOAL_EVADE_SHIP:
+3 -5
View File
@@ -73,17 +73,15 @@ struct ai_info;
#define AI_GOAL_FLY_TO_SHIP (1<<23) // 0x00800000
#define AI_GOAL_IGNORE_NEW (1<<24) // 0x01000000
#define AI_GOAL_CHASE_SHIP_CLASS (1<<25) // 0x02000000
#define AI_GOAL_PLAY_DEAD_PERSISTENT (1<<26) // 0x04000000
#define AI_GOAL_LUA (1<<27) // 0x08000000
#define AI_GOAL_DISARM_SHIP_TACTICAL (1<<28) // 0x10000000
#define AI_GOAL_DISABLE_SHIP_TACTICAL (1<<29) // 0x20000000
#define AI_GOAL_PLAY_DEAD_PERSISTENT (1<<26) // 0x03000000
#define AI_GOAL_LUA (1<<27) // 0x04000000
// now the masks for ship types
// Goober5000: added AI_GOAL_STAY_NEAR_SHIP and AI_GOAL_KEEP_SAFE_DISTANCE as valid for fighters
//WMC - Don't need these anymore. Whee!
/*
#define AI_GOAL_ACCEPT_FIGHTER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_CHASE | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_WARP | AI_GOAL_DESTROY_SUBSYSTEM | AI_GOAL_CHASE_WING | AI_GOAL_GUARD | AI_GOAL_DISABLE_SHIP | AI_GOAL_DISABLE_SHIP_TACTICAL | AI_GOAL_DISARM_SHIP | AI_GOAL_DISARM_SHIP_TACTICAL | AI_GOAL_CHASE_ANY | AI_GOAL_IGNORE | AI_GOAL_IGNORE_NEW | AI_GOAL_GUARD_WING | AI_GOAL_EVADE_SHIP | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_PLAY_DEAD_PERSISTENT | AI_GOAL_STAY_NEAR_SHIP | AI_GOAL_KEEP_SAFE_DISTANCE )
#define AI_GOAL_ACCEPT_FIGHTER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_CHASE | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_WARP | AI_GOAL_DESTROY_SUBSYSTEM | AI_GOAL_CHASE_WING | AI_GOAL_GUARD | AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP | AI_GOAL_CHASE_ANY | AI_GOAL_IGNORE | AI_GOAL_IGNORE_NEW | AI_GOAL_GUARD_WING | AI_GOAL_EVADE_SHIP | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_PLAY_DEAD_PERSISTENT | AI_GOAL_STAY_NEAR_SHIP | AI_GOAL_KEEP_SAFE_DISTANCE )
#define AI_GOAL_ACCEPT_BOMBER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_FIGHTER | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_STEALTH ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_FIGHTER | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_TRANSPORT ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_CHASE | AI_GOAL_CHASE_WING | AI_GOAL_DOCK | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_WARP | AI_GOAL_UNDOCK | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_PLAY_DEAD_PERSISTENT | AI_GOAL_STAY_NEAR_SHIP )
+5 -162
View File
@@ -18,9 +18,9 @@ void ai_lua_add_mode(int sexp_op, const ai_mode_lua& mode) {
}
bool ai_lua_add_order(int sexp_op, player_order_lua order) {
Player_orders.emplace_back(order.parseText, order.displayText, -1, sexp_op);
Player_orders.emplace_back(vm_strdup(order.parseText.c_str()), vm_strdup(order.displayText.c_str()), -1, sexp_op);
Player_orders.back().localize();
Lua_player_orders.emplace(sexp_op, std::move(order));
return true;
@@ -48,134 +48,6 @@ const player_order_lua* ai_lua_find_player_order(int sexp_op) {
return &aiLuaOrder->second;
}
int ai_lua_get_num_general_orders() {
int count = 0;
for (const auto& order : Lua_player_orders) {
if (order.second.generalOrder) {
count++;
}
}
return count;
}
SCP_vector<SCP_string> ai_lua_get_general_order_categories(bool enabled_only)
{
SCP_vector<SCP_string> list;
for (const auto& order : Lua_player_orders) {
const SCP_string &cat = order.second.category;
// If it's not a general order then move on
if (!order.second.generalOrder) {
continue;
}
// If the order is not enabled then move on
if (enabled_only && !order.second.cur_enabled) {
continue;
}
Assertion((cat.length() > 0), "Lua general orders category name must be longer than 0 characters!");
for (size_t i = 0; i <= list.size(); i++) {
// reached the end of the list, so add it
if (i == list.size()) {
list.push_back(cat);
break;
}
// if it's already in the list then don't add it
if (cat == list[i]) {
break;
}
}
}
return list;
}
SCP_vector<SCP_string> ai_lua_get_general_orders(bool onlyEnabled, bool onlyValid, const SCP_string& category)
{
SCP_vector<SCP_string> list;
for (auto order : Lua_player_orders) {
if (order.second.generalOrder) {
bool add = false;
// Only enabled orders
if (onlyEnabled && order.second.cur_enabled) {
add = true;
// Only valid orders
} else if (onlyValid && order.second.cur_valid) {
add = true;
// Only orders that match the category requested
} else if ((!category.empty()) && (order.second.category == category)) {
add = true;
// All general orders
} else {
add = true;
}
if (add) {
list.push_back(order.second.parseText);
}
}
}
return list;
}
int ai_lua_find_general_order_id(const SCP_string& name) {
for (const auto& order : Lua_player_orders) {
if (order.second.parseText == name) {
return order.first;
}
}
return -1;
}
void ai_lua_enable_general_order(int sexp_op, bool enable) {
auto aiLuaOrder = Lua_player_orders.find(sexp_op);
if (aiLuaOrder == Lua_player_orders.end())
return;
else
aiLuaOrder->second.cur_enabled = enable;
}
void ai_lua_validate_general_order(int sexp_op, bool validity)
{
auto aiLuaOrder = Lua_player_orders.find(sexp_op);
if (aiLuaOrder == Lua_player_orders.end())
return;
else
aiLuaOrder->second.cur_valid = validity;
}
void ai_lua_reset_general_orders() {
for (auto order : Lua_player_orders) {
ai_lua_enable_general_order(order.first, false);
ai_lua_validate_general_order(order.first, false);
}
}
bool ai_lua_is_general_order(int sexp_op) {
auto aiLuaOrder = Lua_player_orders.find(sexp_op);
if (aiLuaOrder == Lua_player_orders.end())
return false;
return aiLuaOrder->second.generalOrder;
}
void run_ai_lua_action(const luacpp::LuaFunction& action, const ai_mode_lua& lua_ai, ai_info* aip) {
if (!action.isValid()) {
Error(LOCATION,
@@ -184,11 +56,7 @@ void run_ai_lua_action(const luacpp::LuaFunction& action, const ai_mode_lua& lua
}
luacpp::LuaValueList luaParameters;
if (aip->shipnum >= 0){
luaParameters.push_back(luacpp::LuaValue::createValue(action.getLuaState(), scripting::api::l_AI_Helper.Set(object_h(&Objects[Ships[aip->shipnum].objnum]))));
} else {
luaParameters.push_back(luacpp::LuaValue::createValue(action.getLuaState(), scripting::api::l_AI_Helper.Set(object_h())));
}
luaParameters.push_back(luacpp::LuaValue::createValue(action.getLuaState(), scripting::api::l_AI_Helper.Set(object_h(&Objects[Ships[aip->shipnum].objnum]))));
if (lua_ai.needsTarget) {
luaParameters.push_back(luacpp::LuaValue::createValue(action.getLuaState(), scripting::api::l_OSWPT.Set(aip->lua_ai_target.target)));
}
@@ -199,13 +67,8 @@ void run_ai_lua_action(const luacpp::LuaFunction& action, const ai_mode_lua& lua
auto retVals = action.call(Script_system.GetLuaSession(), luaParameters);
if (!retVals.empty() && retVals[0].getValueType() == luacpp::ValueType::BOOLEAN) {
if (retVals[0].getValue<bool>()) {
// If we don't have a ship then it's a general order and we have nothing else to do
if (aip->shipnum >= 0) {
ai_mission_goal_complete(aip);
}
}
if (retVals[0].getValue<bool>())
ai_mission_goal_complete(aip);
}
}
@@ -240,26 +103,6 @@ void ai_lua_start(ai_goal* aigp, object* objp){
run_ai_lua_action(action, lua_ai, aip);
}
// For sending general orders that don't run on a ship.
// Essentially just runs arbitrary lua script when the command is called
void ai_lua_start_general(int lua_sexp_id, int target_objnum)
{
//Create a dummy aip to pass the target data
ai_info aip;
aip.shipnum = -1;
if (target_objnum >= 0) {
aip.lua_ai_target = {object_ship_wing_point_team(&Ships[Objects[target_objnum].instance]), {}};
}
const auto& lua_ai = ai_lua_find_mode(lua_sexp_id);
const auto& lua_ai_sexp = lua_ai->sexp;
const auto& action = lua_ai_sexp.getActionEnter();
run_ai_lua_action(action, *lua_ai, &aip);
}
bool ai_lua_is_valid_target_intrinsic(int sexp_op, int target_objnum, ship* self) {
ship* target = &Ships[Objects[target_objnum].instance];
-13
View File
@@ -19,10 +19,6 @@ struct player_order_lua {
int ai_message = MESSAGE_YESSIR;
SCP_string parseText = "";
SCP_string displayText = "";
bool generalOrder = false;
SCP_string category = "";
bool cur_enabled = false;
bool cur_valid = false;
enum class target_restrictions : int { TARGET_ALLIES, TARGET_ALL, TARGET_OWN, TARGET_ENEMIES, TARGET_SAME_WING, TARGET_PLAYER_WING, TARGET_ALL_CAPS, TARGET_ALLIED_CAPS, TARGET_ENEMY_CAPS, TARGET_NOT_SELF } targetRestrictions = target_restrictions::TARGET_ALL;
enum class ship_restrictions : int { ANY, WING, IN_PLAYER_WING, PLAYER_WING } shipRestrictions = ship_restrictions::ANY;
};
@@ -33,17 +29,8 @@ bool ai_lua_add_order(int sexp_op, player_order_lua order);
bool ai_lua_has_mode(int sexp_op);
const ai_mode_lua* ai_lua_find_mode(int sexp_op);
const player_order_lua* ai_lua_find_player_order(int sexp_op);
SCP_vector<SCP_string> ai_lua_get_general_order_categories(bool enabled_only = true);
int ai_lua_get_num_general_orders();
SCP_vector<SCP_string> ai_lua_get_general_orders(bool onlyEnabled = false, bool onlyValid = false, const SCP_string& category = "");
int ai_lua_find_general_order_id(const SCP_string& name);
void ai_lua_enable_general_order(int sexp_op, bool enable);
void ai_lua_validate_general_order(int sexp_op, bool validity);
void ai_lua_reset_general_orders();
bool ai_lua_is_general_order(int sexp_op);
void ai_lua(ai_info* aip);
void ai_lua_start(ai_goal* aigp, object* objp);
void ai_lua_start_general(int lua_sexp_id, int target_objnum);
bool ai_lua_is_valid_target(int sexp_op, int target_objnum, ship* self, size_t order);
bool ai_lua_is_valid_ship(int sexp_op, bool isWing, ship* self);
ai_achievability ai_lua_is_achievable(const ai_goal* aigp, int objnum);
+1 -1
View File
@@ -1104,7 +1104,7 @@ int find_turret_enemy(ship_subsys *turret_subsys, int objnum, vec3d *tpos, vec3d
ai_info *aip = &Ai_info[Ships[Objects[objnum].instance].ai_index];
sip = &Ship_info[Ships[Objects[objnum].instance].ship_info_index];
if ((sip->class_type >= 0) && (Ship_types[sip->class_type].flags[Ship::Type_Info_Flags::Turret_tgt_ship_tgt]) && (aip->target_objnum != -1)) {
if ((Ship_types[sip->class_type].flags[Ship::Type_Info_Flags::Turret_tgt_ship_tgt]) && (aip->target_objnum != -1)) {
int target_objnum = aip->target_objnum;
if (Objects[target_objnum].signature == aip->target_signature) {
+1 -1
View File
@@ -670,7 +670,7 @@ void anim_read_header(anim *ptr, CFILE *fp)
* @param file_mapped Whether to use memory-mapped file or not.
*
* @details Memory-mapped files will page in the animation from disk as it is needed, but performance is not as good.
* @return Pointer to anim that is loaded if success, NULL if failure.
* @return Pointer to anim that is loaded if sucess, NULL if failure.
*/
anim *anim_load(const char *real_filename, int cf_dir_type, int file_mapped)
{
+1 -1
View File
@@ -1030,7 +1030,7 @@ bool asteroid_is_within_view(vec3d *pos, float range, bool range_override)
float dot = vm_vec_dot(&Eye_matrix.vec.fvec, &vec_to_asteroid);
// if asteroid is within view or far enough away then wrap
if (dot > cos(g3_get_hfov(Proj_fov))) {
if (dot > cos(Proj_fov)) {
if (range_override) {
return true;
} else {
+1 -1
View File
@@ -598,7 +598,7 @@ int bm_create_3d(int bpp, int w, int h, int d, void* data) {
// make sure that we have valid data
if (data == nullptr) {
UNREACHABLE("No valid data received for 3D Bitmap creation!");
UNREACHABLE("No valid data recieved for 3D Bitmap creation!");
return -1;
}
+21 -53
View File
@@ -14,8 +14,8 @@
#include "ship/ship.h" //compute_slew_matrix
//*************************IMPORTANT GLOBALS*************************
fov_t VIEWER_ZOOM_DEFAULT = 0.75f; // Default viewer zoom, 0.625 as per multi-lateral agreement on 3/24/97
fov_t COCKPIT_ZOOM_DEFAULT = 0.75f;
float VIEWER_ZOOM_DEFAULT = 0.75f; // Default viewer zoom, 0.625 as per multi-lateral agreement on 3/24/97
float COCKPIT_ZOOM_DEFAULT = 0.75f;
float Sexp_fov = 0.0f;
warp_camera Warp_camera;
@@ -27,33 +27,6 @@ SCP_vector<camera*> Cameras;
camid Current_camera;
camid Main_camera;
asymmetric_fov operator* (const asymmetric_fov& left, const float& right) {
return asymmetric_fov{ left.left * right, left.right * right, left.up * right, left.down * right };
}
asymmetric_fov operator+ (const asymmetric_fov& left, const float& right) {
float ar = (left.up - left.down) / (left.right - left.left);
return asymmetric_fov{ left.left - right * 0.5f, left.right + right * 0.5f, left.up + right * 0.5f * ar, left.down - right * 0.5f * ar };
}
asymmetric_fov operator- (const asymmetric_fov& left, const float& right) {
float ar = (left.up - left.down) / (left.right - left.left);
return asymmetric_fov{ left.left + right * 0.5f, left.right - right * 0.5f, left.up - right * 0.5f * ar, left.down + right * 0.5f * ar };
}
#define APPLY_TO_FOV_T(op, name) \
struct apply_##name##_to_fov { \
float r; \
template<typename T> \
fov_t operator()(const T& l) { \
return fov_t(l op r); \
} \
}; \
fov_t operator op (const fov_t& zoom, const float& scale) { \
return mpark::visit(apply_##name##_to_fov{scale}, zoom); \
}
APPLY_TO_FOV_T(*, mul)
APPLY_TO_FOV_T(+, add)
APPLY_TO_FOV_T(-, sub)
static SCP_string fov_display(float val)
{
auto degrees = fl_degrees(val);
@@ -61,20 +34,15 @@ static SCP_string fov_display(float val)
sprintf(out, u8"%.1f\u00B0", degrees);
return out;
}
auto FovOption = options::OptionBuilder<float>("Graphics.FOV",
std::pair<const char*, int>{"Field Of View", 1703},
std::pair<const char*, int>{"The vertical field of view", 1704})
.category("Graphics")
.range(0.436332f, 1.5708f)
.change_listener([](const float& val, bool) {
VIEWER_ZOOM_DEFAULT = val;
return true;
})
.display(fov_display)
.default_val(0.75f)
.level(options::ExpertLevel::Advanced)
.importance(60)
.finish();
auto FovOption = options::OptionBuilder<float>("Graphics.FOV", "Field Of View", "The vertical field of view.")
.category("Graphics")
.range(0.436332f, 1.5708f)
.bind_to(&VIEWER_ZOOM_DEFAULT)
.display(fov_display)
.default_val(0.75f)
.level(options::ExpertLevel::Advanced)
.importance(60)
.finish();
//*************************CLASS: camera*************************
//This is where the camera class begins! :D
@@ -117,7 +85,7 @@ void camera::reset()
func_custom_orientation = NULL;
fov.clear();
fov.set(g3_get_hfov(VIEWER_ZOOM_DEFAULT));
fov.set(VIEWER_ZOOM_DEFAULT);
pos_x.clear();
pos_y.clear();
@@ -136,7 +104,7 @@ void camera::set_name(const char *in_name)
strncpy(name, in_name, NAME_LENGTH-1);
}
void camera::set_fov(fov_t in_fov, float in_fov_time, float in_fov_acceleration_time, float in_fov_deceleration_time)
void camera::set_fov(float in_fov, float in_fov_time, float in_fov_acceleration_time, float in_fov_deceleration_time)
{
if(in_fov_time == 0.0f && in_fov_acceleration_time == 0.0f && in_fov_deceleration_time == 0.0f)
{
@@ -146,23 +114,26 @@ void camera::set_fov(fov_t in_fov, float in_fov_time, float in_fov_acceleration_
}
flags &= ~CAM_STATIONARY_FOV;
if(g3_get_hfov(in_fov) <= 0.0f)
if(in_fov <= 0.0f)
{
fov.setVD(in_fov_time, in_fov_acceleration_time, 0.0f);
}
fov.setAVD(g3_get_hfov(in_fov), in_fov_time, in_fov_acceleration_time, in_fov_deceleration_time, 0.0f);
fov.setAVD(in_fov, in_fov_time, in_fov_acceleration_time, in_fov_deceleration_time, 0.0f);
}
void camera::set_object_host(object *objp, int n_object_host_submodel)
{
if(objp == NULL)
object_host = object_h();
object_host = object_h(objp);
object_host_submodel = n_object_host_submodel;
set_custom_position_function(NULL);
set_custom_orientation_function(NULL);
if(n_object_host_submodel > 0)
{
if(objp != nullptr && objp->type == OBJ_SHIP)
if(objp->type == OBJ_SHIP)
{
ship_subsys* ssp = GET_FIRST(&Ships[objp->instance].subsys_list);
while ( ssp != END_OF_LIST( &Ships[objp->instance].subsys_list ) )
@@ -348,14 +319,11 @@ int camera::get_object_target_submodel()
return object_target_submodel;
}
fov_t camera::get_fov()
float camera::get_fov()
{
if(!(flags & CAM_STATIONARY_FOV))
{
float fov_now;
fov.get(&fov_now, nullptr);
return fov_now;
//TODO enable moving asymmetric fov
fov.get(&c_fov, NULL);
}
return c_fov;
+5 -18
View File
@@ -10,8 +10,6 @@
#include <string>
#include <mpark/variant.hpp>
#define CAM_STATIONARY_FOV (1<<0)
#define CAM_STATIONARY_ORI (1<<1)
#define CAM_STATIONARY_POS (1<<2)
@@ -20,17 +18,6 @@
#define EXTERN_CAM_BBOX_CONSTANT_PADDING 5.0f
#define EXTERN_CAM_BBOX_MULTIPLIER_PADDING 1.5f
struct asymmetric_fov {
float left, right, up, down;
friend asymmetric_fov operator* (const asymmetric_fov&, const float&);
friend asymmetric_fov operator+ (const asymmetric_fov&, const float&);
friend asymmetric_fov operator- (const asymmetric_fov&, const float&);
};
using fov_t = mpark::variant<float, asymmetric_fov>;
fov_t operator* (const fov_t&, const float&);
fov_t operator+ (const fov_t&, const float&);
fov_t operator- (const fov_t&, const float&);
class camera
{
protected:
@@ -54,7 +41,7 @@ protected:
avd_movement ori[9];
//Cache stuff
fov_t c_fov;
float c_fov;
vec3d c_pos;
matrix c_ori;
public:
@@ -72,7 +59,7 @@ public:
void set_custom_position_function(void (*n_func_custom_position)(camera *cam, vec3d *pos));
void set_custom_orientation_function(void (*n_func_custom_orientation)(camera *cam, matrix *ori));
void set_fov(fov_t in_fov, float in_fov_time = 0.0f, float in_fov_acceleration_time = 0.0f, float in_deceleration_time = 0.0f);
void set_fov(float in_fov, float in_fov_time = 0.0f, float in_fov_acceleration_time = 0.0f, float in_deceleration_time = 0.0f);
void set_position(vec3d *in_position = NULL, float in_translation_time = 0.0f, float in_translation_acceleration_time = 0.0f, float in_translation_deceleration_time = 0.0f, float in_end_velocity = 0.0f);
@@ -87,7 +74,7 @@ public:
int get_object_host_submodel();
object *get_object_target();
int get_object_target_submodel();
fov_t get_fov();
float get_fov();
void get_info(vec3d *position, matrix *orientation, bool apply_camera_orientation = true);
//Is
@@ -168,8 +155,8 @@ public:
//Some global stuff
extern SCP_vector<subtitle> Subtitles;
extern fov_t VIEWER_ZOOM_DEFAULT;
extern fov_t COCKPIT_ZOOM_DEFAULT;
extern float VIEWER_ZOOM_DEFAULT;
extern float COCKPIT_ZOOM_DEFAULT;
extern float Sexp_fov;
//Helpful functions
+1 -1
View File
@@ -438,7 +438,7 @@ int cfile_flush_dir(int dir_type)
// filename = name of filename or filepath to process
// ext = extension to add. Must start with the period
// Returns: new filename or filepath with extension.
const char *cf_add_ext(const char *filename, const char *ext)
char *cf_add_ext(const char *filename, const char *ext)
{
static char path[MAX_PATH_LEN];
+1 -1
View File
@@ -171,7 +171,7 @@ int cfile_init(const char *exe_dir, const char *cdrom_dir=NULL);
void cfile_close();
// add an extension to a filename if it doesn't already have it
const char *cf_add_ext(const char *filename, const char *ext);
char *cf_add_ext(const char *filename, const char *ext);
// return filename of a CFILE you called cfopen() successfully on.
const char *cf_get_filename(const CFILE *cfile);
+1 -8
View File
@@ -188,7 +188,6 @@ Flag exe_params[] =
//flag launcher text FSO on_flags off_flags category reference URL
{ "-window", "Run in window", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-window", },
{ "-fullscreen_window", "Run in fullscreen window", false, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fullscreen_window", },
{ "-capture_mouse", "Capture the mouse within the window", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-capture_mouse", },
{ "-stretch_menu", "Stretch interface to fill screen", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-stretch_menu", },
{ "-noscalevid", "Disable scale-to-window for movies", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noscalevid", },
{ "-nomotiondebris", "Disable motion debris", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nomotiondebris",},
@@ -407,7 +406,6 @@ cmdline_parm use_3dwarp("-3dwarp", nullptr, AT_NONE); // Is now Fireball_use_3
cmdline_parm use_warp_flash("-warp_flash", nullptr, AT_NONE); // Cmdline_warp_flash
cmdline_parm allow_autpilot_interrupt("-no_ap_interrupt", nullptr, AT_NONE);
cmdline_parm stretch_menu("-stretch_menu", nullptr, AT_NONE); // Cmdline_stretch_menu
cmdline_parm capture_mouse("-capture_mouse", nullptr, AT_NONE); // Cmdline_capture_mouse
cmdline_parm no_screenshake("-no_screenshake", nullptr, AT_NONE); // Cmdline_no_screenshake
cmdline_parm deadzone("-deadzone",
"Sets the joystick deadzone. Integer value from 0 to 100 as a percentage of the joystick's range (100% would make the stick do nothing). Disables deadzone slider in the in-game Options menu.", AT_INT); //Cmdline_deadzone
@@ -416,7 +414,6 @@ int Cmdline_ship_choice_3d = 0;
int Cmdline_weapon_choice_3d = 0;
int Cmdline_autopilot_interruptable = 1;
int Cmdline_stretch_menu = 0;
bool Cmdline_capture_mouse = false;
int Cmdline_no_screenshake = 0;
int Cmdline_deadzone = -1;
@@ -1649,7 +1646,7 @@ bool SetCmdlineParams()
// be sure that this string fits in our limits
if ( strlen(Cmdline_game_password) >= MAX_PASSWD_LEN ) {
ReleaseWarning(LOCATION, "Multi game password is longer than max of %d characters and will be trimmed to fit!", MAX_PASSWD_LEN-1);
ReleaseWarning(LOCATION, "Multi game password is longer than max of %d charaters and will be trimmed to fit!", MAX_PASSWD_LEN-1);
Cmdline_game_password[MAX_PASSWD_LEN-1] = '\0';
}
}
@@ -1874,10 +1871,6 @@ bool SetCmdlineParams()
if ( stretch_menu.found() ) {
Cmdline_stretch_menu = 1;
}
if ( capture_mouse.found() ) {
Cmdline_capture_mouse = true;
}
// new lighting lines
if ( ambient_power_arg.found() )
Cmdline_ambient_power = ambient_power_arg.get_float();
-1
View File
@@ -86,7 +86,6 @@ extern int Cmdline_ship_choice_3d;
extern int Cmdline_weapon_choice_3d;
extern int Cmdline_autopilot_interruptable;
extern int Cmdline_stretch_menu;
extern bool Cmdline_capture_mouse;
extern int Cmdline_no_screenshake;
extern int Cmdline_deadzone;
+4 -5
View File
@@ -1359,6 +1359,9 @@ bool control_config_accept(bool API_Access)
}
}
hud_squadmsg_save_keys(); // rebuild map for saving/restoring keys in squadmsg mode
if (!API_Access) {
gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
gamesnd_play_iface(InterfaceSounds::COMMIT_PRESSED);
@@ -1627,7 +1630,7 @@ void control_config_close(bool API_Access)
Ui_window.destroy();
common_free_interface_palette(); // restore game palette
}
hud_squadmsg_save_keys(); // rebuild map for saving/restoring keys in squadmsg mode
game_flush();
if (Game_mode & GM_MULTIPLAYER) {
@@ -2533,10 +2536,6 @@ void control_config_do_frame(float frametime)
if (List_buttons[i].pressed()) {
// Select the pressed line
Selected_line = i + Scroll_offset;
// Cyborg - Quick assertion for Coverity 1093701. Not likely to happen, but we check for a negative Selected Line later.
Assertion(Selected_line > -1, "control_config_do_frame() has somehow managed to get a negative Selected_line index of %d. Please get an SCP member.", Selected_line);
Selected_item = selItem::None;
List_buttons[i].get_mouse_pos(&x, &y);
+26 -28
View File
@@ -45,29 +45,27 @@ int Failed_key_index;
// Joystick configuration
int Joy_dead_zone_size = 10;
auto DeadZoneOption = options::OptionBuilder<int>("Input.JoystickDeadZone",
std::pair<const char*, int>{"Deadzone", 1377},
std::pair<const char*, int>{"The deadzone used for all joysticks", 1744})
.category("Input")
.range(0, 45)
.level(options::ExpertLevel::Beginner)
.default_val(10)
.bind_to(&Joy_dead_zone_size)
.importance(1)
.finish();
auto DeadZoneOption =
options::OptionBuilder<int>("Input.JoystickDeadZone", "Deadzone", "The deadzone of the selected joystick.")
.category("Input")
.range(0, 45)
.level(options::ExpertLevel::Beginner)
.default_val(10)
.bind_to(&Joy_dead_zone_size)
.importance(1)
.finish();
int Joy_sensitivity = 9;
auto SensitivityOption = options::OptionBuilder<int>("Input.JoystickSensitivity",
std::pair<const char*, int>{"Sensitivity", 1745},
std::pair<const char*, int>{"The sensitivity used for all joysticks", 1746})
.category("Input")
.range(0, 9)
.level(options::ExpertLevel::Beginner)
.default_val(9)
.bind_to(&Joy_sensitivity)
.importance(2)
.finish();
auto SensitivityOption =
options::OptionBuilder<int>("Input.JoystickSensitivity", "Sensitivity", "The sentitivity of the selected joystick.")
.category("Input")
.range(0, 9)
.level(options::ExpertLevel::Beginner)
.default_val(9)
.bind_to(&Joy_sensitivity)
.importance(2)
.finish();
//! arrays which hold the key mappings. The array index represents a key-independent action.
//! please use SPACES for aligning the fields of this array
@@ -160,8 +158,8 @@ void control_config_common_init_bindings() {
// flight controls (flight modes)
(BANK_WHEN_PRESSED, -1, -1, SHIP_TAB, 1, "Bank When Pressed", CC_TYPE_CONTINUOUS)
(AFTERBURNER, KEY_TAB, 5, SHIP_TAB, 1, "Afterburner", CC_TYPE_CONTINUOUS)
(GLIDE_WHEN_PRESSED, -1, -1, SHIP_TAB, 1774, "Glide When Pressed", CC_TYPE_CONTINUOUS)
(TOGGLE_GLIDING, KEY_ALTED | KEY_G, -1, SHIP_TAB, 1775, "Toggle Gliding", CC_TYPE_TRIGGER)
(GLIDE_WHEN_PRESSED, -1, -1, SHIP_TAB, 0, "Glide When Pressed", CC_TYPE_CONTINUOUS)
(TOGGLE_GLIDING, KEY_ALTED | KEY_G, -1, SHIP_TAB, 0, "Toggle Gliding", CC_TYPE_TRIGGER)
// flight controls (axes)
(JOY_HEADING_AXIS, JOY_X_AXIS, MOUSE_X_AXIS, SHIP_TAB, 1016, "Turn (Yaw) Axis", CC_TYPE_AXIS_REL)
@@ -175,7 +173,7 @@ void control_config_common_init_bindings() {
(FIRE_SECONDARY, KEY_SPACEBAR, 1, WEAPON_TAB, 1, "Fire Secondary Weapon", CC_TYPE_CONTINUOUS)
(CYCLE_NEXT_PRIMARY, KEY_PERIOD, -1, WEAPON_TAB, 1, "Cycle Primary Weapon Forward", CC_TYPE_TRIGGER)
(CYCLE_PREV_PRIMARY, KEY_COMMA, -1, WEAPON_TAB, 1, "Cycle Primary Weapon Backward", CC_TYPE_TRIGGER)
(CYCLE_PRIMARY_WEAPON_SEQUENCE, KEY_O, -1, WEAPON_TAB, 1776, "Cycle Primary Weapon Firing Rate", CC_TYPE_TRIGGER)
(CYCLE_PRIMARY_WEAPON_SEQUENCE, KEY_O, -1, WEAPON_TAB, 0, "Cycle Primary Weapon Firing Rate", CC_TYPE_TRIGGER)
(CYCLE_SECONDARY, KEY_DIVIDE, -1, WEAPON_TAB, 1, "Cycle Secondary Weapon Forward", CC_TYPE_TRIGGER)
(CYCLE_NUM_MISSLES, KEY_SHIFTED | KEY_DIVIDE, -1, WEAPON_TAB, 1, "Cycle Secondary Weapon Firing Rate", CC_TYPE_TRIGGER)
(LAUNCH_COUNTERMEASURE, KEY_X, 3, WEAPON_TAB, 1, "Launch Countermeasure", CC_TYPE_TRIGGER)
@@ -211,8 +209,8 @@ void control_config_common_init_bindings() {
(PADLOCK_DOWN, -1, 32, COMPUTER_TAB, 1, "View Rear", CC_TYPE_CONTINUOUS)
(PADLOCK_LEFT, -1, 34, COMPUTER_TAB, 1, "View Left", CC_TYPE_CONTINUOUS)
(PADLOCK_RIGHT, -1, 35, COMPUTER_TAB, 1, "View Right", CC_TYPE_CONTINUOUS)
(VIEW_TOPDOWN, -1, -1, COMPUTER_TAB, 1777, "Top-Down View", CC_TYPE_TRIGGER)
(VIEW_TRACK_TARGET, -1, -1, COMPUTER_TAB, 1778, "Target Padlock View", CC_TYPE_TRIGGER)
(VIEW_TOPDOWN, -1, -1, COMPUTER_TAB, 0, "Top-Down View", CC_TYPE_TRIGGER)
(VIEW_TRACK_TARGET, -1, -1, COMPUTER_TAB, 0, "Target Padlock View", CC_TYPE_TRIGGER)
(RADAR_RANGE_CYCLE, KEY_RAPOSTRO, -1, COMPUTER_TAB, 1, "Cycle Radar Range", CC_TYPE_TRIGGER)
(SQUADMSG_MENU, KEY_C, -1, COMPUTER_TAB, 1, "Communications Menu", CC_TYPE_TRIGGER)
@@ -237,8 +235,8 @@ void control_config_common_init_bindings() {
// Navigation and Autopilot
(SHOW_NAVMAP, -1, -1, NO_TAB, 1, "Show Nav Map", CC_TYPE_TRIGGER, true)
(AUTO_PILOT_TOGGLE, KEY_ALTED | KEY_A, -1, COMPUTER_TAB, 1779, "Toggle Auto Pilot", CC_TYPE_TRIGGER)
(NAV_CYCLE, KEY_ALTED | KEY_N, -1, COMPUTER_TAB, 1780, "Cycle Nav Points", CC_TYPE_TRIGGER)
(AUTO_PILOT_TOGGLE, KEY_ALTED | KEY_A, -1, COMPUTER_TAB, 0, "Toggle Auto Pilot", CC_TYPE_TRIGGER)
(NAV_CYCLE, KEY_ALTED | KEY_N, -1, COMPUTER_TAB, 0, "Cycle Nav Points", CC_TYPE_TRIGGER)
// Escort
(ADD_REMOVE_ESCORT, KEY_ALTED | KEY_E, -1, COMPUTER_TAB, 1, "Add or Remove Escort", CC_TYPE_TRIGGER)
@@ -260,7 +258,7 @@ void control_config_common_init_bindings() {
// HUD
(TOGGLE_HUD, KEY_SHIFTED | KEY_O, -1, COMPUTER_TAB, 1, "Toggle HUD", CC_TYPE_TRIGGER)
(TOGGLE_HUD_CONTRAST, KEY_L, -1, COMPUTER_TAB, 1, "Toggle High HUD Contrast", CC_TYPE_TRIGGER)
(TOGGLE_HUD_SHADOWS, KEY_ALTED | KEY_L, -1, COMPUTER_TAB, 1781, "Toggle HUD Drop Shadows", CC_TYPE_TRIGGER)
(TOGGLE_HUD_SHADOWS, KEY_ALTED | KEY_L, -1, COMPUTER_TAB, 0, "Toggle HUD Drop Shadows", CC_TYPE_TRIGGER)
(HUD_TARGETBOX_TOGGLE_WIREFRAME, KEY_ALTED | KEY_SHIFTED | KEY_Q, -1, COMPUTER_TAB, 1, "Toggle HUD Wireframe Target View", CC_TYPE_TRIGGER)
// Custom Controls
+1 -1
View File
@@ -108,7 +108,7 @@ class Decoder {
* @note A implementation should initialize the datastructures required for decoding here.
*
* @param fileName The name of the file that should be opened
* @return @c true if the initialization was successful, @c false otherwise
* @return @c true if the initialization was successfull, @c false otherwise
*/
virtual bool initialize(const SCP_string& fileName, const PlaybackProperties& properties) = 0;
+1 -1
View File
@@ -119,7 +119,7 @@
* half-rate linear filtering on GCN.
*
* If SMAA is applied to 64-bit color buffers, switching to point filtering
* when accessing them will increase the performance. Search for
* when accesing them will increase the performance. Search for
* 'SMAASamplePoint' to see which textures may benefit from point
* filtering, and where (which is basically the color input in the edge
* detection and resolve passes).
+3 -5
View File
@@ -24,8 +24,6 @@ layout (std140) uniform globalDeferredData {
float invScreenWidth;
float invScreenHeight;
float nearPlane;
};
layout (std140) uniform matrixData {
@@ -81,7 +79,7 @@ void GetLightInfo(vec3 position, in float alpha, in vec3 reflectDir, out vec3 li
lightDirOut = lightPosition - position.xyz;
float dist = length(lightDirOut);
// this chunk is unnecessary if sourceRadius= 0.0, but let's avoid a branch.
// this chunk is unneccessary if sourceRadius= 0.0, but let's avoid a branch.
// given a sphere of radius sourceRadius centered at lightDirOut,
// move lightDirOut towards the ray defined by reflectDir
lightDirOut = ExpandLightSize(lightDirOut, reflectDir);
@@ -124,7 +122,7 @@ void GetLightInfo(vec3 position, in float alpha, in vec3 reflectDir, out vec3 li
// should figure out how to optimise these calcs - qaz
// this chunk is unnecessary if sourceRadius = 0.0, but let's avoid a branch.
// this chunk is unneccessary if sourceRadius = 0.0, but let's avoid a branch.
// Same principle as in LT_POINT, treat chosen location as a spherelight.
lightDirOut = ExpandLightSize(lightDirOut, reflectDir);
float dist = length(lightDirOut);
@@ -170,7 +168,7 @@ void main()
vec2 screenPos = gl_FragCoord.xy * vec2(invScreenWidth, invScreenHeight);
vec3 position = texture(PositionBuffer, screenPos).xyz;
if(abs(dot(position, position)) < nearPlane * nearPlane)
if(abs(dot(position, position)) < 0.1)
discard;
vec3 diffColor = texture(ColorBuffer, screenPos).rgb;
+1 -1
View File
@@ -11,7 +11,7 @@ in vec4 fragTexCoord;
out vec4 fragOut0;
// Iteratively optimised points to give low discrepancy distribution on arbitrary hemisphere.
// Iteratively optimised points to give low discrepancy distribution on arbritrary hemisphere.
const vec3 points[128] = vec3[128](
vec3(-0.2268, 0.6185, 0.7523),
vec3( 0.9958, -0.0871, -0.0277),
+2 -2
View File
@@ -33,7 +33,7 @@ vec3 ComputeGGX(vec3 specColor, vec3 diffColor, vec3 light, vec3 normal, vec3 ha
// NOTE - we're intentionally using UE4's reflectance model as modellers are using tools designed for common engines.
// Cook-Torrance BRDF Model (Specular Reflection) = Distribution * Fresnel * Geometry / (4*dotNV*dotNL)
// Cook-Torrance BRDF Model (Specular Reflection) = Distibution * Fresnel * Geometry / (4*dotNV*dotNL)
// Distribution Term - Trowbridge-Reitz GGX
@@ -49,7 +49,7 @@ vec3 ComputeGGX(vec3 specColor, vec3 diffColor, vec3 light, vec3 normal, vec3 ha
// Smith's method:
// Microsurfaces block light rays coming in from the light
// AND block light rays reflecting to the camera.
// Hence, model both separately and multiply.
// Hence, model both seperately and multiply.
float g1vNL = GeometrySchlickGGX(dotNL, k);
float g1vNV = GeometrySchlickGGX(dotNV, k);
float geometry = g1vNL * g1vNV;
-714
View File
@@ -1,714 +0,0 @@
-- Module options:
local always_try_using_lpeg = true
local register_global_module_table = false
local global_module_name = 'json'
--[==[
David Kolf's JSON module for Lua 5.1/5.2
Version 2.5
For the documentation see the corresponding readme.txt or visit
<http://dkolf.de/src/dkjson-lua.fsl/>.
You can contact the author by sending an e-mail to 'david' at the
domain 'dkolf.de'.
Copyright (C) 2010-2014 David Heiko Kolf
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]==]
-- global dependencies:
local pairs, type, tostring, tonumber, getmetatable, setmetatable, rawset =
pairs, type, tostring, tonumber, getmetatable, setmetatable, rawset
local error, require, pcall, select = error, require, pcall, select
local floor, huge = math.floor, math.huge
local strrep, gsub, strsub, strbyte, strchar, strfind, strlen, strformat =
string.rep, string.gsub, string.sub, string.byte, string.char,
string.find, string.len, string.format
local strmatch = string.match
local concat = table.concat
local json = { version = "dkjson 2.5" }
if register_global_module_table then
_G[global_module_name] = json
end
local _ENV = nil -- blocking globals in Lua 5.2
pcall (function()
-- Enable access to blocked metatables.
-- Don't worry, this module doesn't change anything in them.
local debmeta = require "debug".getmetatable
if debmeta then getmetatable = debmeta end
end)
json.null = setmetatable ({}, {
__tojson = function () return "null" end
})
local function isarray (tbl)
local max, n, arraylen = 0, 0, 0
for k,v in pairs (tbl) do
if k == 'n' and type(v) == 'number' then
arraylen = v
if v > max then
max = v
end
else
if type(k) ~= 'number' or k < 1 or floor(k) ~= k then
return false
end
if k > max then
max = k
end
n = n + 1
end
end
if max > 10 and max > arraylen and max > n * 2 then
return false -- don't create an array with too many holes
end
return true, max
end
local escapecodes = {
["\""] = "\\\"", ["\\"] = "\\\\", ["\b"] = "\\b", ["\f"] = "\\f",
["\n"] = "\\n", ["\r"] = "\\r", ["\t"] = "\\t"
}
local function escapeutf8 (uchar)
local value = escapecodes[uchar]
if value then
return value
end
local a, b, c, d = strbyte (uchar, 1, 4)
a, b, c, d = a or 0, b or 0, c or 0, d or 0
if a <= 0x7f then
value = a
elseif 0xc0 <= a and a <= 0xdf and b >= 0x80 then
value = (a - 0xc0) * 0x40 + b - 0x80
elseif 0xe0 <= a and a <= 0xef and b >= 0x80 and c >= 0x80 then
value = ((a - 0xe0) * 0x40 + b - 0x80) * 0x40 + c - 0x80
elseif 0xf0 <= a and a <= 0xf7 and b >= 0x80 and c >= 0x80 and d >= 0x80 then
value = (((a - 0xf0) * 0x40 + b - 0x80) * 0x40 + c - 0x80) * 0x40 + d - 0x80
else
return ""
end
if value <= 0xffff then
return strformat ("\\u%.4x", value)
elseif value <= 0x10ffff then
-- encode as UTF-16 surrogate pair
value = value - 0x10000
local highsur, lowsur = 0xD800 + floor (value/0x400), 0xDC00 + (value % 0x400)
return strformat ("\\u%.4x\\u%.4x", highsur, lowsur)
else
return ""
end
end
local function fsub (str, pattern, repl)
-- gsub always builds a new string in a buffer, even when no match
-- exists. First using find should be more efficient when most strings
-- don't contain the pattern.
if strfind (str, pattern) then
return gsub (str, pattern, repl)
else
return str
end
end
local function quotestring (value)
-- based on the regexp "escapable" in https://github.com/douglascrockford/JSON-js
value = fsub (value, "[%z\1-\31\"\\\127]", escapeutf8)
if strfind (value, "[\194\216\220\225\226\239]") then
value = fsub (value, "\194[\128-\159\173]", escapeutf8)
value = fsub (value, "\216[\128-\132]", escapeutf8)
value = fsub (value, "\220\143", escapeutf8)
value = fsub (value, "\225\158[\180\181]", escapeutf8)
value = fsub (value, "\226\128[\140-\143\168-\175]", escapeutf8)
value = fsub (value, "\226\129[\160-\175]", escapeutf8)
value = fsub (value, "\239\187\191", escapeutf8)
value = fsub (value, "\239\191[\176-\191]", escapeutf8)
end
return "\"" .. value .. "\""
end
json.quotestring = quotestring
local function replace(str, o, n)
local i, j = strfind (str, o, 1, true)
if i then
return strsub(str, 1, i-1) .. n .. strsub(str, j+1, -1)
else
return str
end
end
-- locale independent num2str and str2num functions
local decpoint, numfilter
local function updatedecpoint ()
decpoint = strmatch(tostring(0.5), "([^05+])")
-- build a filter that can be used to remove group separators
numfilter = "[^0-9%-%+eE" .. gsub(decpoint, "[%^%$%(%)%%%.%[%]%*%+%-%?]", "%%%0") .. "]+"
end
updatedecpoint()
local function num2str (num)
return replace(fsub(tostring(num), numfilter, ""), decpoint, ".")
end
local function str2num (str)
local num = tonumber(replace(str, ".", decpoint))
if not num then
updatedecpoint()
num = tonumber(replace(str, ".", decpoint))
end
return num
end
local function addnewline2 (level, buffer, buflen)
buffer[buflen+1] = "\n"
buffer[buflen+2] = strrep (" ", level)
buflen = buflen + 2
return buflen
end
function json.addnewline (state)
if state.indent then
state.bufferlen = addnewline2 (state.level or 0,
state.buffer, state.bufferlen or #(state.buffer))
end
end
local encode2 -- forward declaration
local function addpair (key, value, prev, indent, level, buffer, buflen, tables, globalorder, state)
local kt = type (key)
if kt ~= 'string' and kt ~= 'number' then
return nil, "type '" .. kt .. "' is not supported as a key by JSON."
end
if prev then
buflen = buflen + 1
buffer[buflen] = ","
end
if indent then
buflen = addnewline2 (level, buffer, buflen)
end
buffer[buflen+1] = quotestring (key)
buffer[buflen+2] = ":"
return encode2 (value, indent, level, buffer, buflen + 2, tables, globalorder, state)
end
local function appendcustom(res, buffer, state)
local buflen = state.bufferlen
if type (res) == 'string' then
buflen = buflen + 1
buffer[buflen] = res
end
return buflen
end
local function exception(reason, value, state, buffer, buflen, defaultmessage)
defaultmessage = defaultmessage or reason
local handler = state.exception
if not handler then
return nil, defaultmessage
else
state.bufferlen = buflen
local ret, msg = handler (reason, value, state, defaultmessage)
if not ret then return nil, msg or defaultmessage end
return appendcustom(ret, buffer, state)
end
end
function json.encodeexception(reason, value, state, defaultmessage)
return quotestring("<" .. defaultmessage .. ">")
end
encode2 = function (value, indent, level, buffer, buflen, tables, globalorder, state)
local valtype = type (value)
local valmeta = getmetatable (value)
valmeta = type (valmeta) == 'table' and valmeta -- only tables
local valtojson = valmeta and valmeta.__tojson
if valtojson then
if tables[value] then
return exception('reference cycle', value, state, buffer, buflen)
end
tables[value] = true
state.bufferlen = buflen
local ret, msg = valtojson (value, state)
if not ret then return exception('custom encoder failed', value, state, buffer, buflen, msg) end
tables[value] = nil
buflen = appendcustom(ret, buffer, state)
elseif value == nil then
buflen = buflen + 1
buffer[buflen] = "null"
elseif valtype == 'number' then
local s
if value ~= value or value >= huge or -value >= huge then
-- This is the behaviour of the original JSON implementation.
s = "null"
else
s = num2str (value)
end
buflen = buflen + 1
buffer[buflen] = s
elseif valtype == 'boolean' then
buflen = buflen + 1
buffer[buflen] = value and "true" or "false"
elseif valtype == 'string' then
buflen = buflen + 1
buffer[buflen] = quotestring (value)
elseif valtype == 'table' then
if tables[value] then
return exception('reference cycle', value, state, buffer, buflen)
end
tables[value] = true
level = level + 1
local isa, n = isarray (value)
if n == 0 and valmeta and valmeta.__jsontype == 'object' then
isa = false
end
local msg
if isa then -- JSON array
buflen = buflen + 1
buffer[buflen] = "["
for i = 1, n do
buflen, msg = encode2 (value[i], indent, level, buffer, buflen, tables, globalorder, state)
if not buflen then return nil, msg end
if i < n then
buflen = buflen + 1
buffer[buflen] = ","
end
end
buflen = buflen + 1
buffer[buflen] = "]"
else -- JSON object
local prev = false
buflen = buflen + 1
buffer[buflen] = "{"
local order = valmeta and valmeta.__jsonorder or globalorder
if order then
local used = {}
n = #order
for i = 1, n do
local k = order[i]
local v = value[k]
if v then
used[k] = true
buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state)
prev = true -- add a seperator before the next element
end
end
for k,v in pairs (value) do
if not used[k] then
buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state)
if not buflen then return nil, msg end
prev = true -- add a seperator before the next element
end
end
else -- unordered
for k,v in pairs (value) do
buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state)
if not buflen then return nil, msg end
prev = true -- add a seperator before the next element
end
end
if indent then
buflen = addnewline2 (level - 1, buffer, buflen)
end
buflen = buflen + 1
buffer[buflen] = "}"
end
tables[value] = nil
else
return exception ('unsupported type', value, state, buffer, buflen,
"type '" .. valtype .. "' is not supported by JSON.")
end
return buflen
end
function json.encode (value, state)
state = state or {}
local oldbuffer = state.buffer
local buffer = oldbuffer or {}
state.buffer = buffer
updatedecpoint()
local ret, msg = encode2 (value, state.indent, state.level or 0,
buffer, state.bufferlen or 0, state.tables or {}, state.keyorder, state)
if not ret then
error (msg, 2)
elseif oldbuffer == buffer then
state.bufferlen = ret
return true
else
state.bufferlen = nil
state.buffer = nil
return concat (buffer)
end
end
local function loc (str, where)
local line, pos, linepos = 1, 1, 0
while true do
pos = strfind (str, "\n", pos, true)
if pos and pos < where then
line = line + 1
linepos = pos
pos = pos + 1
else
break
end
end
return "line " .. line .. ", column " .. (where - linepos)
end
local function unterminated (str, what, where)
return nil, strlen (str) + 1, "unterminated " .. what .. " at " .. loc (str, where)
end
local function scanwhite (str, pos)
while true do
pos = strfind (str, "%S", pos)
if not pos then return nil end
local sub2 = strsub (str, pos, pos + 1)
if sub2 == "\239\187" and strsub (str, pos + 2, pos + 2) == "\191" then
-- UTF-8 Byte Order Mark
pos = pos + 3
elseif sub2 == "//" then
pos = strfind (str, "[\n\r]", pos + 2)
if not pos then return nil end
elseif sub2 == "/*" then
pos = strfind (str, "*/", pos + 2)
if not pos then return nil end
pos = pos + 2
else
return pos
end
end
end
local escapechars = {
["\""] = "\"", ["\\"] = "\\", ["/"] = "/", ["b"] = "\b", ["f"] = "\f",
["n"] = "\n", ["r"] = "\r", ["t"] = "\t"
}
local function unichar (value)
if value < 0 then
return nil
elseif value <= 0x007f then
return strchar (value)
elseif value <= 0x07ff then
return strchar (0xc0 + floor(value/0x40),
0x80 + (floor(value) % 0x40))
elseif value <= 0xffff then
return strchar (0xe0 + floor(value/0x1000),
0x80 + (floor(value/0x40) % 0x40),
0x80 + (floor(value) % 0x40))
elseif value <= 0x10ffff then
return strchar (0xf0 + floor(value/0x40000),
0x80 + (floor(value/0x1000) % 0x40),
0x80 + (floor(value/0x40) % 0x40),
0x80 + (floor(value) % 0x40))
else
return nil
end
end
local function scanstring (str, pos)
local lastpos = pos + 1
local buffer, n = {}, 0
while true do
local nextpos = strfind (str, "[\"\\]", lastpos)
if not nextpos then
return unterminated (str, "string", pos)
end
if nextpos > lastpos then
n = n + 1
buffer[n] = strsub (str, lastpos, nextpos - 1)
end
if strsub (str, nextpos, nextpos) == "\"" then
lastpos = nextpos + 1
break
else
local escchar = strsub (str, nextpos + 1, nextpos + 1)
local value
if escchar == "u" then
value = tonumber (strsub (str, nextpos + 2, nextpos + 5), 16)
if value then
local value2
if 0xD800 <= value and value <= 0xDBff then
-- we have the high surrogate of UTF-16. Check if there is a
-- low surrogate escaped nearby to combine them.
if strsub (str, nextpos + 6, nextpos + 7) == "\\u" then
value2 = tonumber (strsub (str, nextpos + 8, nextpos + 11), 16)
if value2 and 0xDC00 <= value2 and value2 <= 0xDFFF then
value = (value - 0xD800) * 0x400 + (value2 - 0xDC00) + 0x10000
else
value2 = nil -- in case it was out of range for a low surrogate
end
end
end
value = value and unichar (value)
if value then
if value2 then
lastpos = nextpos + 12
else
lastpos = nextpos + 6
end
end
end
end
if not value then
value = escapechars[escchar] or escchar
lastpos = nextpos + 2
end
n = n + 1
buffer[n] = value
end
end
if n == 1 then
return buffer[1], lastpos
elseif n > 1 then
return concat (buffer), lastpos
else
return "", lastpos
end
end
local scanvalue -- forward declaration
local function scantable (what, closechar, str, startpos, nullval, objectmeta, arraymeta)
local len = strlen (str)
local tbl, n = {}, 0
local pos = startpos + 1
if what == 'object' then
setmetatable (tbl, objectmeta)
else
setmetatable (tbl, arraymeta)
end
while true do
pos = scanwhite (str, pos)
if not pos then return unterminated (str, what, startpos) end
local char = strsub (str, pos, pos)
if char == closechar then
return tbl, pos + 1
end
local val1, err
val1, pos, err = scanvalue (str, pos, nullval, objectmeta, arraymeta)
if err then return nil, pos, err end
pos = scanwhite (str, pos)
if not pos then return unterminated (str, what, startpos) end
char = strsub (str, pos, pos)
if char == ":" then
if val1 == nil then
return nil, pos, "cannot use nil as table index (at " .. loc (str, pos) .. ")"
end
pos = scanwhite (str, pos + 1)
if not pos then return unterminated (str, what, startpos) end
local val2
val2, pos, err = scanvalue (str, pos, nullval, objectmeta, arraymeta)
if err then return nil, pos, err end
tbl[val1] = val2
pos = scanwhite (str, pos)
if not pos then return unterminated (str, what, startpos) end
char = strsub (str, pos, pos)
else
n = n + 1
tbl[n] = val1
end
if char == "," then
pos = pos + 1
end
end
end
scanvalue = function (str, pos, nullval, objectmeta, arraymeta)
pos = pos or 1
pos = scanwhite (str, pos)
if not pos then
return nil, strlen (str) + 1, "no valid JSON value (reached the end)"
end
local char = strsub (str, pos, pos)
if char == "{" then
return scantable ('object', "}", str, pos, nullval, objectmeta, arraymeta)
elseif char == "[" then
return scantable ('array', "]", str, pos, nullval, objectmeta, arraymeta)
elseif char == "\"" then
return scanstring (str, pos)
else
local pstart, pend = strfind (str, "^%-?[%d%.]+[eE]?[%+%-]?%d*", pos)
if pstart then
local number = str2num (strsub (str, pstart, pend))
if number then
return number, pend + 1
end
end
pstart, pend = strfind (str, "^%a%w*", pos)
if pstart then
local name = strsub (str, pstart, pend)
if name == "true" then
return true, pend + 1
elseif name == "false" then
return false, pend + 1
elseif name == "null" then
return nullval, pend + 1
end
end
return nil, pos, "no valid JSON value at " .. loc (str, pos)
end
end
local function optionalmetatables(...)
if select("#", ...) > 0 then
return ...
else
return {__jsontype = 'object'}, {__jsontype = 'array'}
end
end
function json.decode (str, pos, nullval, ...)
local objectmeta, arraymeta = optionalmetatables(...)
return scanvalue (str, pos, nullval, objectmeta, arraymeta)
end
function json.use_lpeg ()
local g = require ("lpeg")
if g.version() == "0.11" then
error "due to a bug in LPeg 0.11, it cannot be used for JSON matching"
end
local pegmatch = g.match
local P, S, R = g.P, g.S, g.R
local function ErrorCall (str, pos, msg, state)
if not state.msg then
state.msg = msg .. " at " .. loc (str, pos)
state.pos = pos
end
return false
end
local function Err (msg)
return g.Cmt (g.Cc (msg) * g.Carg (2), ErrorCall)
end
local SingleLineComment = P"//" * (1 - S"\n\r")^0
local MultiLineComment = P"/*" * (1 - P"*/")^0 * P"*/"
local Space = (S" \n\r\t" + P"\239\187\191" + SingleLineComment + MultiLineComment)^0
local PlainChar = 1 - S"\"\\\n\r"
local EscapeSequence = (P"\\" * g.C (S"\"\\/bfnrt" + Err "unsupported escape sequence")) / escapechars
local HexDigit = R("09", "af", "AF")
local function UTF16Surrogate (match, pos, high, low)
high, low = tonumber (high, 16), tonumber (low, 16)
if 0xD800 <= high and high <= 0xDBff and 0xDC00 <= low and low <= 0xDFFF then
return true, unichar ((high - 0xD800) * 0x400 + (low - 0xDC00) + 0x10000)
else
return false
end
end
local function UTF16BMP (hex)
return unichar (tonumber (hex, 16))
end
local U16Sequence = (P"\\u" * g.C (HexDigit * HexDigit * HexDigit * HexDigit))
local UnicodeEscape = g.Cmt (U16Sequence * U16Sequence, UTF16Surrogate) + U16Sequence/UTF16BMP
local Char = UnicodeEscape + EscapeSequence + PlainChar
local String = P"\"" * g.Cs (Char ^ 0) * (P"\"" + Err "unterminated string")
local Integer = P"-"^(-1) * (P"0" + (R"19" * R"09"^0))
local Fractal = P"." * R"09"^0
local Exponent = (S"eE") * (S"+-")^(-1) * R"09"^1
local Number = (Integer * Fractal^(-1) * Exponent^(-1))/str2num
local Constant = P"true" * g.Cc (true) + P"false" * g.Cc (false) + P"null" * g.Carg (1)
local SimpleValue = Number + String + Constant
local ArrayContent, ObjectContent
-- The functions parsearray and parseobject parse only a single value/pair
-- at a time and store them directly to avoid hitting the LPeg limits.
local function parsearray (str, pos, nullval, state)
local obj, cont
local npos
local t, nt = {}, 0
repeat
obj, cont, npos = pegmatch (ArrayContent, str, pos, nullval, state)
if not npos then break end
pos = npos
nt = nt + 1
t[nt] = obj
until cont == 'last'
return pos, setmetatable (t, state.arraymeta)
end
local function parseobject (str, pos, nullval, state)
local obj, key, cont
local npos
local t = {}
repeat
key, obj, cont, npos = pegmatch (ObjectContent, str, pos, nullval, state)
if not npos then break end
pos = npos
t[key] = obj
until cont == 'last'
return pos, setmetatable (t, state.objectmeta)
end
local Array = P"[" * g.Cmt (g.Carg(1) * g.Carg(2), parsearray) * Space * (P"]" + Err "']' expected")
local Object = P"{" * g.Cmt (g.Carg(1) * g.Carg(2), parseobject) * Space * (P"}" + Err "'}' expected")
local Value = Space * (Array + Object + SimpleValue)
local ExpectedValue = Value + Space * Err "value expected"
ArrayContent = Value * Space * (P"," * g.Cc'cont' + g.Cc'last') * g.Cp()
local Pair = g.Cg (Space * String * Space * (P":" + Err "colon expected") * ExpectedValue)
ObjectContent = Pair * Space * (P"," * g.Cc'cont' + g.Cc'last') * g.Cp()
local DecodeValue = ExpectedValue * g.Cp ()
function json.decode (str, pos, nullval, ...)
local state = {}
state.objectmeta, state.arraymeta = optionalmetatables(...)
local obj, retpos = pegmatch (DecodeValue, str, pos, nullval, state)
if state.msg then
return nil, state.pos, state.msg
else
return obj, retpos
end
end
-- use this function only once:
json.use_lpeg = function () return json end
json.using_lpeg = true
return json -- so you can get the module using json = require "dkjson".use_lpeg()
end
if always_try_using_lpeg then
pcall (json.use_lpeg)
end
return json
+4 -29
View File
@@ -1,5 +1,5 @@
#Ship types
#Ship types
$Name: Navbuoy
$Max Debris Speed: 200
$FF Multiplier: 1.0
@@ -12,7 +12,6 @@ $AI:
+Turrets attack this: YES
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Vaporize Percent Chance: 0.0
$Name: Sentry Gun
$Counts for Alone: YES
$On Hotkey List: YES
@@ -33,7 +32,6 @@ $AI:
+Turrets attack this: YES
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Vaporize Percent Chance: 0.0
$Name: Escape Pod
$Praise Destruction: YES
$On Hotkey List: YES
@@ -52,7 +50,6 @@ $AI:
+Turrets attack this: YES
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Vaporize Percent Chance: 0.0
$Name: Cargo
$Scannable: YES
$Max Debris Speed: 200
@@ -66,7 +63,6 @@ $Fog:
$AI:
+Passive docks: ( "cargo" )
$Vaporize Percent Chance: 0.0
$Name: Support
$Counts for Alone: YES
$Praise Destruction: YES
@@ -93,7 +89,6 @@ $AI:
+Active docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Vaporize Percent Chance: 0.0
;;WMC - Stealth ships always have another type, so this isn't used
$Name: Stealth
$Counts for Alone: YES
@@ -119,7 +114,6 @@ $AI:
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Vaporize Percent Chance: 0.0
$Name: Fighter
$Counts for Alone: YES
$Praise Destruction: YES
@@ -147,7 +141,6 @@ $AI:
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Vaporize Percent Chance: 0.0
$Name: Bomber
$Counts for Alone: YES
$Praise Destruction: YES
@@ -175,8 +168,7 @@ $AI:
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Vaporize Percent Chance: 0.0
;;WMC - This fighter/bomber type doesn't seem to be used anywhere, because no ship is set as both fighter and bomber
;;WMC - This fighter/bomber type doesn't seem to be used anywhere, because no ship is set as both fighter and bomber
$Name: Fighter/bomber
$Counts for Alone: YES
$Praise Destruction: YES
@@ -203,7 +195,6 @@ $AI:
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Vaporize Percent Chance: 0.0
$Name: Transport
$Counts for Alone: YES
$Praise Destruction: YES
@@ -213,7 +204,6 @@ $Show Attack Direction: YES
$Max Debris Speed: 150
$FF Multiplier: 1.0
$EMP Multiplier: 2.0
$Warp Sound Range Multiplier: 6.0
$Beams Easily Hit: YES
$Protected on cripple: YES
$Fog:
@@ -233,7 +223,6 @@ $AI:
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Vaporize Percent Chance: 0.0
$Name: Freighter
$Counts for Alone: YES
$Praise Destruction: YES
@@ -244,7 +233,6 @@ $Scannable: YES
$Max Debris Speed: 150
$FF Multiplier: 1.0
$EMP Multiplier: 1.75
$Warp Sound Range Multiplier: 6.0
$Beams Easily Hit: YES
$Protected on cripple: YES
$Fog:
@@ -265,7 +253,6 @@ $AI:
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Vaporize Percent Chance: 0.0
$Name: AWACS
$Counts for Alone: YES
$Praise Destruction: YES
@@ -275,7 +262,6 @@ $Show Attack Direction: YES
$Max Debris Speed: 150
$FF Multiplier: 1.0
$EMP Multiplier: 0.8
$Warp Sound Range Multiplier: 6.0
$Beams Easily Hit: YES
$Protected on cripple: YES
$Fog:
@@ -295,7 +281,6 @@ $AI:
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Vaporize Percent Chance: 0.0
$Name: Gas Miner
$Counts for Alone: YES
$Praise Destruction: YES
@@ -305,7 +290,6 @@ $Show Attack Direction: YES
$Max Debris Speed: 150
$FF Multiplier: 1.0
$EMP Multiplier: 1.0
$Warp Sound Range Multiplier: 6.0
$Beams Easily Hit: YES
$Protected on cripple: YES
$Fog:
@@ -325,7 +309,6 @@ $AI:
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Vaporize Percent Chance: 0.0
$Name: Cruiser
$Counts for Alone: YES
$Praise Destruction: YES
@@ -335,7 +318,6 @@ $Show Attack Direction: YES
$Max Debris Speed: 150
$FF Multiplier: 1.0
$EMP Multiplier: 0.9
$Warp Sound Range Multiplier: 6.0
$Beams Easily Hit: YES
$Protected on cripple: YES
$Fog:
@@ -355,7 +337,6 @@ $AI:
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Vaporize Percent Chance: 0.0
$Name: Corvette
$Counts for Alone: YES
$Praise Destruction: YES
@@ -365,7 +346,6 @@ $Show Attack Direction: YES
$Max Debris Speed: 150
$FF Multiplier: 1.0
$EMP Multiplier: 0.3333
$Warp Sound Range Multiplier: 6.0
$Beams Easily Hit: YES
$Protected on cripple: YES
$Fog:
@@ -385,7 +365,6 @@ $AI:
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Vaporize Percent Chance: 0.0
$Name: Capital
$Counts for Alone: YES
$Praise Destruction: YES
@@ -415,7 +394,6 @@ $AI:
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Vaporize Percent Chance: 0.0
$Name: Super Cap
$Counts for Alone: YES
$Praise Destruction: YES
@@ -443,7 +421,6 @@ $AI:
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Vaporize Percent Chance: 0.0
$Name: Drydock
$Counts for Alone: YES
$Praise Destruction: YES
@@ -469,7 +446,6 @@ $AI:
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Vaporize Percent Chance: 0.0
$Name: Knossos Device
$Counts for Alone: YES
$Praise Destruction: YES
@@ -493,5 +469,4 @@ $AI:
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Vaporize Percent Chance: 0.0
#End
#End
+1 -1
View File
@@ -311,7 +311,7 @@ static char* GetFilePart(char *source)
SCP_string safe_string;
// Entry point into the main exception handling routine. This routine is put into an except()
// statement at the beginning of a thread and is called anytime that there is a program exception
// statment at the beginning of a thread and is called anytime that there is a program exception
// The data is stored in a file called ErrorLog.txt in the data directory.
//
// data: pointer to the exception data
+27 -34
View File
@@ -48,51 +48,44 @@ bool fireballs_parsed = false;
bool Fireball_use_3d_warp = false;
static auto WarpOption __UNUSED = options::OptionBuilder<bool>("Graphics.3dWarp",
std::pair<const char*, int>{"3D Warp", 1770},
std::pair<const char*, int>{"Use a 3D model for warp effects", 1771})
.category("Graphics")
.default_val(true)
.level(options::ExpertLevel::Advanced)
.bind_to(&Fireball_use_3d_warp)
.importance(65)
.finish();
static auto WarpOption __UNUSED = options::OptionBuilder<bool>("Graphics.3dWarp", "3D Warp", "Use a 3D model for warp effects")
.category("Graphics")
.default_val(true)
.level(options::ExpertLevel::Advanced)
.bind_to(&Fireball_use_3d_warp)
.importance(65)
.finish();
/**
* Play warp in sound for warp effect
*/
void fireball_play_warphole_open_sound(int ship_class, fireball *fb)
{
gamesnd_id sound_index;
float range_multiplier = 1.0f;
object *fireball_objp;
Assert((fb != NULL) && (fb->objnum >= 0));
if((fb == NULL) || (fb->objnum < 0)){
return;
}
auto fireball_objp = &Objects[fb->objnum];
auto sound_index = gamesnd_id(GameSounds::WARP_IN);
fireball_objp = &Objects[fb->objnum];
if (fb->warp_open_sound_index.isValid()) {
sound_index = gamesnd_id(GameSounds::WARP_IN);
if(fb->warp_open_sound_index.isValid()) {
sound_index = fb->warp_open_sound_index;
} else if ((ship_class >= 0) && (ship_class < ship_info_size())) {
if ( Ship_info[ship_class].is_huge_ship() ) {
sound_index = gamesnd_id(GameSounds::CAPITAL_WARP_IN);
}
}
if (ship_class >= 0 && ship_class < ship_info_size()) {
if (Ship_info[ship_class].is_huge_ship()) {
fb->flags |= FBF_WARP_CAPITAL_SIZE;
} else if (Ship_info[ship_class].is_big_ship()) {
} else if ( Ship_info[ship_class].is_big_ship() ) {
range_multiplier = 6.0f;
fb->flags |= FBF_WARP_CRUISER_SIZE;
}
// originally 6.0 for SIF_BIG_SHIP and 1.0 for everything else
if (Ship_info[ship_class].class_type >= 0)
fb->warp_sound_range_multiplier = Ship_types[Ship_info[ship_class].class_type].warp_sound_range_multiplier;
else
fb->warp_sound_range_multiplier = 1.0f;
}
snd_play_3d(gamesnd_get_game_sound(sound_index), &fireball_objp->pos, &Eye_position, fireball_objp->radius, NULL, 0, 1.0f, SND_PRIORITY_DOUBLE_INSTANCE, NULL, fb->warp_sound_range_multiplier); // play warp sound effect
snd_play_3d(gamesnd_get_game_sound(sound_index), &fireball_objp->pos, &Eye_position, fireball_objp->radius, NULL, 0, 1.0f, SND_PRIORITY_DOUBLE_INSTANCE, NULL, range_multiplier); // play warp sound effect
}
/**
@@ -100,14 +93,15 @@ void fireball_play_warphole_open_sound(int ship_class, fireball *fb)
*/
void fireball_play_warphole_close_sound(fireball *fb)
{
Assert((fb != NULL) && (fb->objnum >= 0));
if((fb == NULL) || (fb->objnum < 0)){
return;
}
auto fireball_objp = &Objects[fb->objnum];
auto sound_index = gamesnd_id(GameSounds::WARP_OUT);
gamesnd_id sound_index;
if (fb->warp_close_sound_index.isValid()) {
object *fireball_objp;
fireball_objp = &Objects[fb->objnum];
sound_index = gamesnd_id(GameSounds::WARP_OUT);
if ( fb->warp_close_sound_index.isValid() ) {
sound_index = fb->warp_close_sound_index;
} else if ( fb->flags & FBF_WARP_CAPITAL_SIZE ) {
sound_index = gamesnd_id(GameSounds::CAPITAL_WARP_OUT);
@@ -115,7 +109,7 @@ void fireball_play_warphole_close_sound(fireball *fb)
return;
}
snd_play_3d(gamesnd_get_game_sound(sound_index), &fireball_objp->pos, &Eye_position, fireball_objp->radius, NULL, 0, 1.0F, SND_PRIORITY_SINGLE_INSTANCE, NULL, fb->warp_sound_range_multiplier); // play warp sound effect
snd_play_3d(gamesnd_get_game_sound(sound_index), &fireball_objp->pos, &Eye_position, fireball_objp->radius); // play warp sound effect
}
static void fireball_generate_unique_id(char *unique_id, int buffer_len, int fireball_index)
@@ -851,7 +845,6 @@ int fireball_create(vec3d *pos, int fireball_type, int render_type, int parent_o
new_fireball->warp_close_sound_index = warp_close_sound;
new_fireball->warp_open_duration = (warp_open_duration < 0.0f) ? WARPHOLE_GROW_TIME : warp_open_duration;
new_fireball->warp_close_duration = (warp_close_duration < 0.0f) ? WARPHOLE_GROW_TIME : warp_close_duration;
new_fireball->warp_sound_range_multiplier = 1.0f;
matrix orient;
if(orient_override != NULL){
-3
View File
@@ -92,9 +92,6 @@ typedef struct fireball {
gamesnd_id warp_close_sound_index;
float warp_open_duration;
float warp_close_duration;
// the sound multiplier is based on the ship class, but we lose that while the warp is closing
float warp_sound_range_multiplier;
} fireball;
// end move
+7 -9
View File
@@ -24,15 +24,13 @@
bool Fireball_warp_flash = false;
static auto WarpFlashOption __UNUSED = options::OptionBuilder<bool>("Graphics.WarpFlash",
std::pair<const char*, int>{"Warp Flash", 1768},
std::pair<const char*, int>{"Show flash upon warp open or close", 1769})
.category("Graphics")
.default_val(true)
.level(options::ExpertLevel::Advanced)
.bind_to_once(&Fireball_warp_flash)
.importance(65)
.finish();
static auto WarpFlashOption __UNUSED = options::OptionBuilder<bool>("Graphics.WarpFlash", "Warp Flash", "Show flash upon warp open or close")
.category("Graphics")
.default_val(true)
.level(options::ExpertLevel::Advanced)
.bind_to_once(&Fireball_warp_flash)
.importance(65)
.finish();
void warpin_batch_draw_face( int texture, vertex *v1, vertex *v2, vertex *v3 )
{
-3
View File
@@ -16,7 +16,6 @@
#include "gamesnd/gamesnd.h"
#include "globalincs/alphacolors.h"
#include "io/key.h"
#include "mission/missionmessage.h"
#include "missionui/missionscreencommon.h"
#include "sound/audiostr.h"
#include "ui/ui.h"
@@ -517,7 +516,6 @@ void gameplay_help_leave()
// unpause all game sounds
weapon_unpause_sounds();
audiostream_unpause_all();
message_resume_all();
gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
game_flush();
@@ -633,7 +631,6 @@ void gameplay_help_do_frame(float /*frametime*/)
// make sure game sounds are paused
weapon_pause_sounds();
audiostream_pause_all();
message_pause_all();
k = Ui_window.process() & ~KEY_DEBUGGED;
gameplay_help_process_key(k);
+7 -12
View File
@@ -45,15 +45,13 @@ static bool music_volume_change_listener(float new_val, bool /*initial*/)
return true;
}
static auto MusicVolumeOption __UNUSED = options::OptionBuilder<float>("Audio.Music",
std::pair<const char*, int>{"Music", 1371},
std::pair<const char*, int>{"Volume used for playing music", 1760})
.category("Audio")
.default_val(Default_music_volume)
.range(0.0f, 1.0f)
.change_listener(music_volume_change_listener)
.importance(1)
.finish();
static auto MusicVolumeOption __UNUSED = options::OptionBuilder<float>("Audio.Music", "Music", "Volume used for playing music")
.category("Audio")
.default_val(Default_music_volume)
.range(0.0f, 1.0f)
.change_listener(music_volume_change_listener)
.importance(1)
.finish();
typedef struct tagSNDPATTERN {
int default_next_pattern; // Needed so the next_pattern member can be reset
@@ -606,10 +604,7 @@ void event_music_level_start(int force_soundtrack)
// Check that soundtrack index is in range, except that < 0 means no soundtrack
if (Current_soundtrack_num < 0)
{
Pattern_timer_id = TIMESTAMP::never(); // update the timestamp as if a soundtrack did start
return;
}
Assert(Current_soundtrack_num < (int)Soundtracks.size());
if (Current_soundtrack_num >= (int)Soundtracks.size())
return;
+42 -74
View File
@@ -245,89 +245,57 @@ detail_levels Detail_defaults[NUM_DEFAULT_DETAIL_LEVELS] = {
// Global used to access detail levels in game and libs
detail_levels Detail = Detail_defaults[NUM_DEFAULT_DETAIL_LEVELS - 1];
const SCP_vector<std::pair<int, std::pair<const char*, int>>> DetailLevelValues = {{ 0, {"Minimum", 1680}},
{ 1, {"Low", 1161}},
{ 2, {"Medium", 1162}},
{ 3, {"High", 1163}},
{ 4, {"Ultra", 1721}}};
const SCP_vector<std::pair<int, SCP_string>> DetailLevelValues = {{ 0, "Minimum" },
{ 1, "Low" },
{ 2, "Medium" },
{ 3, "High" },
{ 4, "Ultra" }, };
const auto ModelDetailOption __UNUSED = options::OptionBuilder<int>("Graphics.Detail",
std::pair<const char*, int>{"Model Detail", 1739},
std::pair<const char*, int>{"Detail level of models", 1740})
.importance(8)
.category("Graphics")
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.change_listener([](int val, bool) {
Detail.detail_distance = val;
return true;
})
.finish();
const auto ModelDetailOption __UNUSED =
options::OptionBuilder<int>("Graphics.Detail", "Model Detail", "Detail level of models").importance(8).category(
"Graphics").values(DetailLevelValues).default_val(MAX_DETAIL_LEVEL).change_listener([](int val, bool) {
Detail.detail_distance = val;
return true;
}).finish();
const auto TexturesOption __UNUSED = options::OptionBuilder<int>("Graphics.Texture",
std::pair<const char*, int>{"3D Hardware Textures", 1362},
std::pair<const char*, int>{"Level of detail of textures", 1720})
.importance(6)
.category("Graphics")
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.change_listener([](int val, bool) {
Detail.hardware_textures = val;
return true;
})
.finish();
"3D Hardware Textures",
"Level of detail of textures").importance(6).category("Graphics").values(
DetailLevelValues).default_val(MAX_DETAIL_LEVEL).change_listener([](int val, bool) {
Detail.hardware_textures = val;
return true;
}).finish();
const auto ParticlesOption __UNUSED = options::OptionBuilder<int>("Graphics.Particles",
std::pair<const char*, int>{"Particles", 1363},
std::pair<const char*, int>{"Level of detail for particles", 1717})
.importance(5)
.category("Graphics")
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.change_listener([](int val, bool) {
Detail.num_particles = val;
return true;
})
.finish();
"Particles",
"Level of detail for particles").importance(5).category(
"Graphics").values(DetailLevelValues).default_val(MAX_DETAIL_LEVEL).change_listener([](int val, bool) {
Detail.num_particles = val;
return true;
}).finish();
const auto SmallDebrisOption __UNUSED = options::OptionBuilder<int>("Graphics.SmallDebris",
std::pair<const char*, int>{"Impact Effects", 1364},
std::pair<const char*, int>{"Level of detail of impact effects", 1743})
.category("Graphics")
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.importance(4)
.change_listener([](int val,bool) {
Detail.num_small_debris = val;
return true;
})
.finish();
const auto SmallDebrisOption __UNUSED =
options::OptionBuilder<int>("Graphics.SmallDebris", "Impact Effects", "Level of detail of impact effects").category(
"Graphics").values(DetailLevelValues).default_val(MAX_DETAIL_LEVEL).importance(4).change_listener([](int val,
bool) {
Detail.num_small_debris = val;
return true;
}).finish();
const auto ShieldEffectsOption __UNUSED = options::OptionBuilder<int>("Graphics.ShieldEffects",
std::pair<const char*, int>{"Shield Hit Effects", 1718},
std::pair<const char*, int>{"Level of detail of shield impacts", 1719})
.importance(3)
.category("Graphics")
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.change_listener([](int val, bool) {
Detail.shield_effects = val;
return true;
})
.finish();
"Shield Hit Effects",
"Level of detail of shield impacts").importance(3).category(
"Graphics").values(DetailLevelValues).default_val(MAX_DETAIL_LEVEL).change_listener([](int val, bool) {
Detail.shield_effects = val;
return true;
}).finish();
const auto StarsOption __UNUSED = options::OptionBuilder<int>("Graphics.Stars",
std::pair<const char*, int>{"Stars", 1366},
std::pair<const char*, int>{"Number of stars in the mission", 1698})
.importance(2)
.category("Graphics")
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.change_listener([](int val, bool) {
Detail.num_stars = val;
return true;
})
.finish();
const auto StarsOption __UNUSED =
options::OptionBuilder<int>("Graphics.Stars", "Stars", "Number of stars in the mission").importance(2).category(
"Graphics").values(DetailLevelValues).default_val(MAX_DETAIL_LEVEL).change_listener([](int val, bool) {
Detail.num_stars = val;
return true;
}).finish();
// Call this with:
// 0 - lowest
+32 -48
View File
@@ -53,10 +53,41 @@ version parse_version() {
return v;
}
version parse_version_inline() {
version v;
SCP_string input;
stuff_string(input, F_RAW);
return version(std::move(input), 0);
size_t start_pos = 0;
size_t end_pos = input.find('.');
v.major = std::atoi(input.substr(start_pos, end_pos - start_pos).c_str());
if (end_pos == SCP_string::npos)
return v;
start_pos = end_pos + 1;
end_pos = input.find('.', start_pos);
v.minor = std::atoi(input.substr(start_pos, end_pos - start_pos).c_str());
if (end_pos == SCP_string::npos)
return v;
start_pos = end_pos + 1;
end_pos = input.find('.', start_pos);
v.build = std::atoi(input.substr(start_pos, end_pos - start_pos).c_str());
if (end_pos == SCP_string::npos)
return v;
start_pos = end_pos + 1;
end_pos = input.find('.', start_pos);
v.revision = std::atoi(input.substr(start_pos, end_pos - start_pos).c_str());
return v;
}
version get_executable_version() {
version v;
@@ -71,53 +102,6 @@ version get_executable_version() {
version::version(int major_in, int minor_in, int build_in, int revision_in) :
major(major_in), minor(minor_in), build(build_in), revision(revision_in) {
}
version::version(const SCP_string& semver, int missing) : major(missing), minor(missing), build(missing), revision(missing) {
int i = 0;
auto str = semver;
int has_fields = 0;
while (i <= 4) {
size_t pos = str.find_first_of('.');
SCP_string ver;
if (pos != SCP_string::npos) {
ver = str.substr(0, pos);
str.erase(0, pos + 1);
}
else {
ver = str;
str.clear();
}
if (!ver.empty() && std::find_if(ver.begin(), ver.end(), [](char c) { return !std::isdigit(c, SCP_default_locale); }) == ver.end()) {
switch (has_fields) {
case 0:
major = std::stoi(ver.c_str());
++has_fields;
break;
case 1:
minor = std::stoi(ver.c_str());
++has_fields;
break;
case 2:
build = std::stoi(ver.c_str());
++has_fields;
break;
case 3:
revision = std::stoi(ver.c_str());
++has_fields;
break;
default:
UNREACHABLE("Version parsing broken, get a coder!");
break;
}
}
else
break; //Break out of the loop if the first string is not a digit.
i++;
}
}
bool version::isValid() const { return major != 0 || minor != 0 || build != 0 || revision != 0; }
bool version::operator<(const version& v) const {
-2
View File
@@ -57,8 +57,6 @@ struct version {
version(int major, int minor = 0, int build = 0, int revision = 0);
version(const SCP_string& semver, int missing = -1);
bool isValid() const;
bool operator<(const version& other) const;
+128 -138
View File
@@ -112,38 +112,35 @@ static bool gamma_change_listener(float new_val, bool initial)
return true;
}
static auto GammaOption __UNUSED = options::OptionBuilder<float>("Graphics.Gamma",
std::pair<const char*, int>{"Brightness", 1375},
std::pair<const char*, int>{"The brightness value used for the game window", 1738})
.category("Graphics")
.default_val(1.0f)
.enumerator(gamma_value_enumerator)
.display(gamma_display)
.change_listener(gamma_change_listener)
.finish();
static auto GammaOption __UNUSED =
options::OptionBuilder<float>("Graphics.Gamma", "Brightness", "The brighness value used for the game window")
.category("Graphics")
.default_val(1.0f)
.enumerator(gamma_value_enumerator)
.display(gamma_display)
.change_listener(gamma_change_listener)
.finish();
const SCP_vector<std::pair<int, std::pair<const char*, int>>> DetailLevelValues = {{ 0, {"Minimum", 1680}},
{ 1, {"Low", 1161}},
{ 2, {"Medium", 1162}},
{ 3, {"High", 1163}},
{ 4, {"Ultra", 1721}}};
const SCP_vector<std::pair<int, SCP_string>> DetailLevelValues = {{ 0, "Minimum" },
{ 1, "Low" },
{ 2, "Medium" },
{ 3, "High" },
{ 4, "Ultra" }, };
const auto LightingOption __UNUSED = options::OptionBuilder<int>("Graphics.Lighting",
std::pair<const char*, int>{"Lighting", 1367},
std::pair<const char*, int>{"Level of detail of the lighting", 1715})
.importance(1)
.category("Graphics")
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.change_listener([](int val, bool initial) {
Detail.lighting = val;
if (!initial) {
gr_recompile_all_shaders(nullptr);
}
return true;
})
.finish();
const auto LightingOption __UNUSED = options::OptionBuilder<int>("Graphics.Lighting", "Lighting", "Level of detail of the lighting")
.importance(1)
.category("Graphics")
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.change_listener([](int val, bool initial) {
Detail.lighting = val;
if (!initial) {
gr_recompile_all_shaders(nullptr);
}
return true;
})
.finish();
os::ViewportState Gr_configured_window_state = os::ViewportState::Windowed;
@@ -165,18 +162,17 @@ static bool mode_change_func(os::ViewportState state, bool initial)
return true;
}
static auto WindowModeOption __UNUSED = options::OptionBuilder<os::ViewportState>("Graphics.WindowMode",
std::pair<const char*, int>{"Window Mode", 1772},
std::pair<const char*, int>{"Controls how the game window is created", 1773})
.category("Graphics")
.level(options::ExpertLevel::Beginner)
.values({{os::ViewportState::Fullscreen, {"Fullscreen", 1679}},
{os::ViewportState::Borderless, {"Borderless", 1675}},
{os::ViewportState::Windowed, {"Windowed", 1676}}})
.importance(98)
.default_val(os::ViewportState::Fullscreen)
.change_listener(mode_change_func)
.finish();
static auto WindowModeOption __UNUSED = options::OptionBuilder<os::ViewportState>("Graphics.WindowMode", "Window Mode",
"Controls how the game window is created.")
.category("Graphics")
.level(options::ExpertLevel::Beginner)
.values({{os::ViewportState::Fullscreen, "Fullscreen"},
{os::ViewportState::Borderless, "Borderless"},
{os::ViewportState::Windowed, "Windowed"}})
.importance(98)
.default_val(os::ViewportState::Fullscreen)
.change_listener(mode_change_func)
.finish();
const std::shared_ptr<scripting::OverridableHook<>> OnFrameHook = scripting::OverridableHook<>::Factory(
"On Frame", "Called every frame as the last action before showing the frame result to the user.", {}, tl::nullopt, CHA_ONFRAME);
@@ -192,7 +188,6 @@ int gr_stencil_mode = 0;
// Default clipping distances
const float Default_min_draw_distance = 1.0f;
const float Default_max_draw_distance = 1e10;
float Min_draw_distance_cockpit = 0.02f;
float Min_draw_distance = Default_min_draw_distance;
float Max_draw_distance = Default_max_draw_distance;
@@ -256,19 +251,18 @@ static bool videodisplay_change(int display, bool initial)
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED_DISPLAY(display), SDL_WINDOWPOS_CENTERED_DISPLAY(display));
return true;
}
static auto VideoDisplayOption = options::OptionBuilder<int>("Graphics.Display",
std::pair<const char*, int>{"Primary display", 1741},
std::pair<const char*, int>{"The display used for rendering", 1742})
.category("Graphics")
.level(options::ExpertLevel::Beginner)
.deserializer(videodisplay_deserializer)
.serializer(videodisplay_serializer)
.enumerator(videodisplay_enumerator)
.display(videodisplay_display)
.default_val(0)
.change_listener(videodisplay_change)
.importance(99)
.finish();
static auto VideoDisplayOption =
options::OptionBuilder<int>("Graphics.Display", "Primary display", "The display used for rendering.")
.category("Graphics")
.level(options::ExpertLevel::Beginner)
.deserializer(videodisplay_deserializer)
.serializer(videodisplay_serializer)
.enumerator(videodisplay_enumerator)
.display(videodisplay_display)
.default_val(0)
.change_listener(videodisplay_change)
.importance(99)
.finish();
struct ResolutionInfo {
uint32_t width = 0;
@@ -365,83 +359,80 @@ static bool resolution_change(const ResolutionInfo& /*info*/, bool initial)
}
*/
}
static auto ResolutionOption = options::OptionBuilder<ResolutionInfo>("Graphics.Resolution",
std::pair<const char*, int>{"Resolution", 1748},
std::pair<const char*, int>{"The rendering resolution", 1749})
.category("Graphics")
.level(options::ExpertLevel::Beginner)
.deserializer(resolution_deserializer)
.serializer(resolution_serializer)
.enumerator(resolution_enumerator)
.display(resolution_display)
.default_func(resolution_default)
.change_listener(resolution_change)
.importance(100)
.finish();
static auto ResolutionOption =
options::OptionBuilder<ResolutionInfo>("Graphics.Resolution", "Resolution", "The rendering resolution.")
.category("Graphics")
.level(options::ExpertLevel::Beginner)
.deserializer(resolution_deserializer)
.serializer(resolution_serializer)
.enumerator(resolution_enumerator)
.display(resolution_display)
.default_func(resolution_default)
.change_listener(resolution_change)
.importance(100)
.finish();
bool Gr_enable_soft_particles = false;
static auto SoftParticlesOption __UNUSED = options::OptionBuilder<bool>("Graphics.SoftParticles",
std::pair<const char*, int>{"Soft Particles", 1761},
std::pair<const char*, int>{"Enable or disable soft particle rendering", 1762})
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.default_val(true)
.bind_to_once(&Gr_enable_soft_particles)
.importance(68)
.finish();
static auto SoftParticlesOption __UNUSED = options::OptionBuilder<bool>("Graphics.SoftParticles", "Soft Particles",
"Enable or disable soft particle rendering.")
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.default_val(true)
.bind_to_once(&Gr_enable_soft_particles)
.importance(68)
.finish();
flagset<FramebufferEffects> Gr_framebuffer_effects;
static auto FramebufferEffectsOption __UNUSED = options::OptionBuilder<flagset<FramebufferEffects>>("Graphics.FramebufferEffects",
std::pair<const char*, int>{"Framebuffer effects", 1732},
std::pair<const char*, int>{"Controls which framebuffer effects will be applied to the scene", 1733})
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.values({{{}, {"None", 211}},
{{FramebufferEffects::Shockwaves}, {"Shockwaves", 1688}},
{{FramebufferEffects::Thrusters}, {"Thrusters", 1689}},
{{FramebufferEffects::Shockwaves, FramebufferEffects::Thrusters}, {"All", 1690}}})
.default_val({FramebufferEffects::Shockwaves, FramebufferEffects::Thrusters})
.bind_to_once(&Gr_framebuffer_effects)
.importance(77)
.finish();
static auto FramebufferEffectsOption __UNUSED =
options::OptionBuilder<flagset<FramebufferEffects>>(
"Graphics.FramebufferEffects", "Framebuffer effects",
"Controls which framebuffer effects will be applied to the scene.")
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.values({{{}, "None"},
{{FramebufferEffects::Shockwaves}, "Shockwaves"},
{{FramebufferEffects::Thrusters}, "Thrusters"},
{{FramebufferEffects::Shockwaves, FramebufferEffects::Thrusters}, "All"}})
.default_val({FramebufferEffects::Shockwaves, FramebufferEffects::Thrusters})
.bind_to_once(&Gr_framebuffer_effects)
.importance(77)
.finish();
AntiAliasMode Gr_aa_mode = AntiAliasMode::None;
AntiAliasMode Gr_aa_mode_last_frame = AntiAliasMode::None;
static auto AAOption __UNUSED = options::OptionBuilder<AntiAliasMode>("Graphics.AAMode",
std::pair<const char*, int>{"Anti Aliasing", 1752},
std::pair<const char*, int>{"Controls the anti aliasing mode of the engine.", 1753})
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.values({{AntiAliasMode::None, {"None", 211}},
{AntiAliasMode::FXAA_Low, {"FXAA Low", 1681}},
{AntiAliasMode::FXAA_Medium, {"FXAA Medium", 1682}},
{AntiAliasMode::FXAA_High, {"FXAA High", 1683}},
{AntiAliasMode::SMAA_Low, {"SMAA Low", 1684}},
{AntiAliasMode::SMAA_Medium, {"SMAA Medium", 1685}},
{AntiAliasMode::SMAA_High, {"SMAA High", 1686}},
{AntiAliasMode::SMAA_Ultra, {"SMAA Ultra", 1687}}})
.default_val(AntiAliasMode::None)
.bind_to(&Gr_aa_mode)
.importance(79)
.finish();
static auto AAOption __UNUSED = options::OptionBuilder<AntiAliasMode>("Graphics.AAMode", "Anti Aliasing",
"Controls the anti aliasing mode of the engine.")
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.values({{AntiAliasMode::None, "None"},
{AntiAliasMode::FXAA_Low, "FXAA Low"},
{AntiAliasMode::FXAA_Medium, "FXAA Medium"},
{AntiAliasMode::FXAA_High, "FXAA High"},
{AntiAliasMode::SMAA_Low, "SMAA Low"},
{AntiAliasMode::SMAA_Medium, "SMAA Medium"},
{AntiAliasMode::SMAA_High, "SMAA High"},
{AntiAliasMode::SMAA_Ultra, "SMAA Ultra"}})
.default_val(AntiAliasMode::None)
.bind_to(&Gr_aa_mode)
.importance(79)
.finish();
extern int Cmdline_msaa_enabled;
static auto MSAAOption __UNUSED = options::OptionBuilder<int>("Graphics.MSAASamples",
std::pair<const char*, int>{"Multisample Anti Aliasing", 1758},
std::pair<const char*, int>{"Controls whether multisample anti asliasing is enabled, and with how many samples", 1759})
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.values({{0, {"Off", 1693}},
{4, {"4 Samples", 1694}},
{8, {"8 Samples", 1695}},
{16, {"16 Samples", 1696}}})
.default_val(0)
.bind_to_once(&Cmdline_msaa_enabled)
.importance(78)
.finish();
static auto MSAAOption __UNUSED = options::OptionBuilder<int>("Graphics.MSAASamples", "Multisample Anti Aliasing",
"Controls whether multisample anti aliasing is enabled, and with how many samples.")
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.values({{0, "Off"},
{4, "4 Samples"},
{8, "8 Samples"},
{16, "16 Samples"}})
.default_val(0)
.bind_to(&Cmdline_msaa_enabled)
.importance(78)
.finish();
bool gr_is_fxaa_mode(AntiAliasMode mode)
{
@@ -453,27 +444,26 @@ bool gr_is_smaa_mode(AntiAliasMode mode) {
bool Gr_post_processing_enabled = true;
static auto PostProcessOption __UNUSED = options::OptionBuilder<bool>("Graphics.PostProcessing",
std::pair<const char*, int>{"Post processing", 1726},
std::pair<const char*, int>{"Controls whether post processing is enabled in the engine.", 1727})
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.default_val(false)
.bind_to_once(&Gr_post_processing_enabled)
.importance(69)
.finish();
static auto PostProcessOption __UNUSED =
options::OptionBuilder<bool>("Graphics.PostProcessing", "Post processing",
"Controls whether post processing is enabled in the engine")
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.default_val(false)
.bind_to_once(&Gr_post_processing_enabled)
.importance(69)
.finish();
bool Gr_enable_vsync = true;
static auto VSyncOption __UNUSED = options::OptionBuilder<bool>("Graphics.VSync",
std::pair<const char*, int>{"Vertical Sync", 1766},
std::pair<const char*, int>{"Controls how the engine does vertical synchronization", 1767})
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.default_val(true)
.bind_to_once(&Gr_enable_vsync)
.importance(70)
.finish();
static auto VSyncOption __UNUSED = options::OptionBuilder<bool>("Graphics.VSync", "Vertical Sync",
"Controls how the engine does vertical synchronization")
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.default_val(true)
.bind_to_once(&Gr_enable_vsync)
.importance(70)
.finish();
static std::unique_ptr<graphics::util::UniformBufferManager> UniformBufferManager;
+3 -4
View File
@@ -36,7 +36,6 @@ class OverridableHook;
extern const float Default_min_draw_distance;
extern const float Default_max_draw_distance;
extern float Min_draw_distance_cockpit;
extern float Min_draw_distance;
extern float Max_draw_distance;
extern int Gr_inited;
@@ -103,7 +102,7 @@ public:
Stack.push_back(Current_transform);
}
const matrix4 &get_transform() const
matrix4 &get_transform()
{
return Current_transform;
}
@@ -116,7 +115,7 @@ public:
Stack.push_back(Current_transform);
}
void push_and_replace(const matrix4 &new_transform)
void push_and_replace(matrix4 new_transform)
{
Current_transform = new_transform;
Stack.push_back(Current_transform);
@@ -301,7 +300,7 @@ public:
void add_vertex_component(vertex_format_data::vertex_format format_type, size_t stride, size_t offset);
size_t get_vertex_stride() const { return Vertex_stride; }
size_t get_vertex_stride() { return Vertex_stride; }
bool operator==(const vertex_layout& other) const;
-37
View File
@@ -734,43 +734,6 @@ void generic_anim_render(generic_anim *ga, float frametime, int x, int y, bool m
}
}
void generic_anim_render_ex(generic_anim* ga, float frametime, int x, int y, int w, int h, bool menu, const generic_extras* ge)
{
if ((ge != nullptr) && (ga->use_hud_color == true)) {
Warning(LOCATION, "Monochrome generic anims can't use extra info (yet)");
return;
}
float a = 1.0f;
if (ge != nullptr) {
a = ge->alpha;
}
if (ga->type == BM_TYPE_PNG) {
generic_anim_render_variable_frame_delay(ga, frametime, a);
}
else {
generic_anim_render_fixed_frame_delay(ga, frametime, a);
}
if (ga->num_frames > 0) {
ga->previous_frame = ga->current_frame;
if (ga->use_hud_color) {
gr_aabitmap_ex(x, y, w, h, 0, 0, (menu ? GR_RESIZE_MENU : GR_RESIZE_FULL));
}
else {
if (ge == nullptr) {
gr_bitmap_ex(x, y, w, h, 0, 0, (menu ? GR_RESIZE_MENU : GR_RESIZE_FULL));
}
else if (ge->draw == true) {
// currently only for lua streaminganim objects
// and don't draw them unless requested...
gr_bitmap_uv(x, y, w, h, ge->u0, ge->v0, ge->u1, ge->v1, ge->resize_mode);
}
}
}
}
/*
* @brief reset an animation back to the start
*
-1
View File
@@ -91,6 +91,5 @@ int generic_anim_stream(generic_anim *ga, const bool cache = true);
int generic_bitmap_load(generic_bitmap *gb);
void generic_anim_unload(generic_anim *ga);
void generic_anim_render(generic_anim *ga, float frametime, int x, int y, bool menu = false, const generic_extras *ge = nullptr);
void generic_anim_render_ex(generic_anim* ga, float frametime, int x, int y, int w, int h, bool menu = false, const generic_extras* ge = nullptr);
void generic_anim_reset(generic_anim *ga);
#endif
+1 -1
View File
@@ -441,7 +441,7 @@ void material::set_color(int r, int g, int b, int a)
Clr.xyzw.w = i2fl(a) / 255.0f;
}
void material::set_color(const color &clr_in)
void material::set_color(color &clr_in)
{
if ( clr_in.is_alphacolor ) {
Clr.xyzw.x = i2fl(clr_in.red) / 255.0f;
+1 -1
View File
@@ -133,7 +133,7 @@ public:
void set_color(float red, float green, float blue, float alpha);
void set_color(int r, int g, int b, int a);
void set_color(const color &clr_in);
void set_color(color &clr_in);
const vec4& get_color() const;
void set_color_scale(float scale);
+10 -27
View File
@@ -16,8 +16,6 @@ matrix4 gr_texture_matrix;
matrix4 gr_env_texture_matrix;
float gr_near_plane;
bool gr_htl_projection_matrix_set = false;
static int modelview_matrix_depth = 1;
@@ -118,43 +116,28 @@ void gr_end_instance_matrix()
}
// the projection matrix; fov, aspect ratio, near, far
void gr_set_proj_matrix(fov_t fov, float aspect, float z_near, float z_far) {
void gr_set_proj_matrix(float fov, float aspect, float z_near, float z_far) {
if (gr_screen.rendering_to_texture != -1) {
gr_set_viewport(gr_screen.offset_x, gr_screen.offset_y, gr_screen.clip_width, gr_screen.clip_height);
} else {
gr_set_viewport(gr_screen.offset_x, (gr_screen.max_h - gr_screen.offset_y - gr_screen.clip_height), gr_screen.clip_width, gr_screen.clip_height);
}
gr_last_projection_matrix = gr_projection_matrix;
float clip_width, clip_height;
if (mpark::holds_alternative<float>(fov)) {
float clip_width, clip_height;
clip_height = tan(mpark::get<float>(fov) * 0.5f) * z_near;
clip_width = clip_height * aspect;
if (gr_screen.rendering_to_texture != -1) {
create_perspective_projection_matrix(&gr_projection_matrix, -clip_width, clip_width, clip_height, -clip_height, z_near, z_far);
} else {
create_perspective_projection_matrix(&gr_projection_matrix, -clip_width, clip_width, -clip_height, clip_height, z_near, z_far);
}
}
else {
const auto& afov = mpark::get<asymmetric_fov>(fov);
float clip_l = tanf(afov.left) * z_near;
float clip_r = tanf(afov.right) * z_near;
float clip_u = tanf(afov.up) * z_near;
float clip_d = tanf(afov.down) * z_near;
if (gr_screen.rendering_to_texture != -1) {
create_perspective_projection_matrix(&gr_projection_matrix, clip_l, clip_r, clip_u, clip_d, z_near, z_far);
}
else {
create_perspective_projection_matrix(&gr_projection_matrix, clip_l, clip_r, clip_d, clip_u, z_near, z_far);
}
clip_height = tan( fov * 0.5f ) * z_near;
clip_width = clip_height * aspect;
gr_last_projection_matrix = gr_projection_matrix;
if (gr_screen.rendering_to_texture != -1) {
create_perspective_projection_matrix(&gr_projection_matrix, -clip_width, clip_width, clip_height, -clip_height, z_near, z_far);
} else {
create_perspective_projection_matrix(&gr_projection_matrix, -clip_width, clip_width, -clip_height, clip_height, z_near, z_far);
}
gr_htl_projection_matrix_set = true;
matrix_uniform_up_to_date = false;
gr_near_plane = z_near;
}
void gr_end_proj_matrix() {
+1 -3
View File
@@ -1,7 +1,6 @@
#pragma once
#include "graphics/2d.h"
#include "render/3d.h"
extern transform_stack gr_model_matrix_stack;
extern matrix4 gr_view_matrix;
@@ -9,7 +8,6 @@ extern matrix4 gr_model_view_matrix;
extern matrix4 gr_projection_matrix;
extern matrix4 gr_last_projection_matrix;
extern matrix4 gr_env_texture_matrix;
extern float gr_near_plane;
void gr_matrix_on_frame();
@@ -17,7 +15,7 @@ void gr_start_instance_matrix(const vec3d* offset, const matrix* rotation);
void gr_start_angles_instance_matrix(const vec3d* pos, const angles* rotation);
void gr_end_instance_matrix();
void gr_set_proj_matrix(fov_t fov, float aspect, float z_near, float z_far);
void gr_set_proj_matrix(float fov, float aspect, float z_near, float z_far);
void gr_end_proj_matrix();
void gr_set_view_matrix(const vec3d* pos, const matrix* orient);
+2 -6
View File
@@ -27,7 +27,6 @@
#include "graphics/2d.h"
#include "graphics/matrix.h"
#include "libs/renderdoc/renderdoc.h"
#include "lighting/lighting.h"
#include "math/floating.h"
#include "model/model.h"
#include "options/Option.h"
@@ -862,9 +861,6 @@ int opengl_init_display_device()
}
}
if (Cmdline_capture_mouse)
attrs.flags.set(os::ViewPortFlags::Capture_Mouse);
auto viewport = gr_opengl_create_viewport(attrs);
if (!viewport) {
return 1;
@@ -1181,7 +1177,7 @@ static void init_extensions() {
// we require a minimum GLSL version
if (GLSL_version < MIN_REQUIRED_GLSL_VERSION) {
Error(LOCATION, "Current GL Shading Language Version of %d is less than the required version of %d. Switch video modes or update your drivers.", GLSL_version, MIN_REQUIRED_GLSL_VERSION);
Error(LOCATION, "Current GL Shading Langauge Version of %d is less than the required version of %d. Switch video modes or update your drivers.", GLSL_version, MIN_REQUIRED_GLSL_VERSION);
}
GLint max_texture_units;
@@ -1403,7 +1399,7 @@ bool gr_opengl_is_capable(gr_capability capability)
case CAPABILITY_POST_PROCESSING:
return Gr_post_processing_enabled && !Cmdline_no_fbo;
case CAPABILITY_DEFERRED_LIGHTING:
return !Cmdline_no_fbo && light_deferred_enabled();
return !Cmdline_no_fbo && !Cmdline_no_deferred_lighting;
case CAPABILITY_SHADOWS:
case CAPABILITY_THICK_OUTLINE:
return !Cmdline_no_geo_sdr_effects;
+4 -5
View File
@@ -57,7 +57,7 @@ void opengl_clear_deferred_buffers()
void gr_opengl_deferred_lighting_begin(bool clearNonColorBufs)
{
if (!light_deferred_enabled())
if ( Cmdline_no_deferred_lighting)
return;
static const float black[] = {0, 0, 0, 1.0f};
@@ -149,7 +149,7 @@ void gr_opengl_deferred_lighting_msaa()
opengl_set_generic_uniform_data<graphics::generic_data::msaa_data>(
[&](graphics::generic_data::msaa_data* data) {
data->samples = Cmdline_msaa_enabled;
data->fov = g3_get_hfov(Proj_fov);
data->fov = Proj_fov;
});
GL_state.SetAlphaBlendMode(gr_alpha_blend::ALPHA_BLEND_NONE);
GL_state.SetZbufferType(ZBUFFER_TYPE_WRITE);
@@ -181,7 +181,7 @@ void gr_opengl_deferred_lighting_finish()
GR_DEBUG_SCOPE("Deferred lighting finish");
TRACE_SCOPE(tracing::ApplyLights);
if (!light_deferred_enabled()) {
if (Cmdline_no_deferred_lighting) {
return;
}
@@ -254,7 +254,6 @@ void gr_opengl_deferred_lighting_finish()
header->invScreenWidth = 1.0f / gr_screen.max_w;
header->invScreenHeight = 1.0f / gr_screen.max_h;
header->nearPlane = gr_near_plane;
// Only the first directional light uses shaders so we need to know when we already saw that light
bool first_directional = true;
@@ -481,7 +480,7 @@ void gr_opengl_deferred_lighting_finish()
data->noiseColorScale2 = std::get<1>(neb.getNoiseColorScale());
data->noiseColorIntensity = neb.getNoiseColorIntensity();
data->aspect = gr_screen.clip_aspect;
data->fov = g3_get_hfov(Proj_fov);
data->fov = Proj_fov;
});
{
+1 -2
View File
@@ -25,7 +25,6 @@
#include "graphics/matrix.h"
#include "graphics/paths/PathRenderer.h"
#include "graphics/util/uniform_structs.h"
#include "lighting/lighting.h"
#include "render/3d.h"
#include "tracing/tracing.h"
@@ -674,7 +673,7 @@ void gr_opengl_scene_texture_begin()
Scene_texture_v_scale = 1.0f;
}
if (!light_deferred_enabled()) {
if ( Cmdline_no_deferred_lighting ) {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
} else {
+1 -1
View File
@@ -398,7 +398,7 @@ static void handle_includes_impl(SCP_vector<SCP_string>& include_stack,
if (first_quote == SCP_string::npos || second_quote == SCP_string::npos) {
Error(LOCATION,
"Shader %s:%d: Malformed include line. Could not find both quote characters.",
"Shader %s:%d: Malformed include line. Could not find both quote charaters.",
filename.c_str(),
line_num);
}
+20 -22
View File
@@ -47,19 +47,17 @@ extern int GLOWMAP;
extern int SPECMAP;
extern int ENVMAP;
const SCP_vector<std::pair<int, std::pair<const char*, int>>> TextureFilteringValues = {{0, {"Bilinear", 1677}},
{ 1, {"Trilinear", 1678}}};
const SCP_vector<std::pair<int, SCP_string>> TextureFilteringValues = {{ 0, "Bilinear" },
{ 1, "Trilinear" }, };
static auto TextureFilteringOption __UNUSED = options::OptionBuilder<int>("Graphics.TextureFilter",
std::pair<const char*, int>{"Texture Filtering", 1763},
std::pair<const char*, int>{"Texture filtering option", 1764})
.importance(1)
.category("Graphics")
.values(TextureFilteringValues)
.default_val(0)
.bind_to_once(&GL_mipmap_filter)
.flags({options::OptionFlags::ForceMultiValueSelection})
.finish();
static auto TextureFilteringOption __UNUSED = options::OptionBuilder<int>("Graphics.TextureFilter", "Texture Filtering", "Texture filtering option")
.importance(1)
.category("Graphics")
.values(TextureFilteringValues)
.default_val(0)
.bind_to_once(&GL_mipmap_filter)
.flags({options::OptionFlags::ForceMultiValueSelection})
.finish();
static SCP_vector<float> anisotropic_value_enumerator()
{
@@ -102,16 +100,16 @@ static float anisotropic_default()
return max;
}
static auto AnisotropyOption = options::OptionBuilder<float>("Graphics.Anisotropy",
std::pair<const char*, int>{"Anistropic filtering", 1736},
std::pair<const char*, int>{"Controls the amount of anistropic filtering of the textures", 1737})
.enumerator(anisotropic_value_enumerator)
.category("Graphics")
.display(anisotropic_display)
.default_func(anisotropic_default)
.level(options::ExpertLevel::Advanced)
.importance(78)
.finish();
static auto AnisotropyOption =
options::OptionBuilder<float>("Graphics.Anisotropy", "Anisotropic filtering",
"Controls the amount of anisotropic filtering of the textures.")
.enumerator(anisotropic_value_enumerator)
.category("Graphics")
.display(anisotropic_display)
.default_func(anisotropic_default)
.level(options::ExpertLevel::Advanced)
.importance(78)
.finish();
// forward declarations
int opengl_free_texture(tcache_slot_opengl *t);
+2 -2
View File
@@ -974,7 +974,7 @@ void opengl_tnl_set_material_particle(particle_material * material_info)
data->srgb = High_dynamic_range ? 1 : 0;
data->blend_alpha = material_info->get_blend_mode() != ALPHA_BLEND_ADDITIVE;
if (!light_deferred_enabled()) {
if (Cmdline_no_deferred_lighting) {
data->linear_depth = 0;
} else {
data->linear_depth = 1;
@@ -984,7 +984,7 @@ void opengl_tnl_set_material_particle(particle_material * material_info)
Current_shader->program->Uniforms.setTextureUniform("baseMap", 0);
Current_shader->program->Uniforms.setTextureUniform("depthMap", 1);
if (light_deferred_enabled()) {
if (!Cmdline_no_deferred_lighting) {
Assert(Scene_position_texture != 0);
GL_state.Texture.Enable(1, GL_TEXTURE_2D, Scene_position_texture);
+20 -21
View File
@@ -40,28 +40,27 @@ PostEffectUniformType mapUniformNameToType(const SCP_string& uniform_name)
// used by In-Game Options menu
bool Post_processing_enable_lightshafts = true;
static auto LightshaftsOption __UNUSED = options::OptionBuilder<bool>("Graphics.Lightshafts",
std::pair<const char*, int>{"Lightshafts", 1724},
std::pair<const char*, int>{"Enables or disables lightshafts (requires post-processing)", 1725})
.category("Graphics")
.default_val(true)
.level(options::ExpertLevel::Advanced)
.bind_to(&Post_processing_enable_lightshafts)
.importance(60)
.finish();
auto LightshaftsOption __UNUSED =
options::OptionBuilder<bool>("Graphics.Lightshafts", "Lightshafts", "Enable lightshafts (requires post-processing)")
.category("Graphics")
.default_val(true)
.level(options::ExpertLevel::Advanced)
.bind_to(&Post_processing_enable_lightshafts)
.importance(60)
.finish();
int Post_processing_bloom_intensity = 25; // using default value of Cmdline_bloom_intensity
static auto BloomIntensityOption __UNUSED = options::OptionBuilder<int>("Graphics.BloomIntensity",
std::pair<const char*, int>{"Bloom intensity", 1701},
std::pair<const char*, int>{"Sets the bloom intensity (requires post-processing)", 1702})
.category("Graphics")
.range(0, 200)
.level(options::ExpertLevel::Advanced)
.default_val(25)
.bind_to(&Post_processing_bloom_intensity)
.importance(55)
.finish();
auto BloomIntensityOption __UNUSED = options::OptionBuilder<int>("Graphics.BloomIntensity",
"Bloom intensity",
"Set bloom intensity (requires post-processing)")
.category("Graphics")
.range(0, 200)
.level(options::ExpertLevel::Advanced)
.default_val(25)
.bind_to(&Post_processing_bloom_intensity)
.importance(55)
.finish();
} // namespace
bool PostProcessingManager::parse_table()
@@ -224,7 +223,7 @@ bool gr_lightshafts_enabled()
}
if (Using_in_game_options) {
return graphics::LightshaftsOption->getValue();
return graphics::Post_processing_enable_lightshafts;
} else {
return !Cmdline_force_lightshaft_off;
}
@@ -241,7 +240,7 @@ int gr_bloom_intensity()
}
if (Using_in_game_options) {
return graphics::BloomIntensityOption->getValue();
return graphics::Post_processing_bloom_intensity;
} else {
return Cmdline_bloom_intensity;
}
+41 -57
View File
@@ -34,20 +34,24 @@ ShadowQuality Shadow_quality = ShadowQuality::Disabled;
bool Shadow_quality_uses_mod_option = false;
auto ShadowQualityOption = options::OptionBuilder<ShadowQuality>("Graphics.Shadows",
std::pair<const char*, int>{"Shadow Quality", 1750},
std::pair<const char*, int>{"The quality of the shadows", 1751})
.values({{ShadowQuality::Disabled, {"Disabled", 1779}},
{ShadowQuality::Low, {"Low", 1160}},
{ShadowQuality::Medium, {"Medium", 1161}},
{ShadowQuality::High, {"High", 1162}},
{ShadowQuality::Ultra, {"Ultra", 1721}}})
.change_listener([](ShadowQuality val, bool initial) {if (initial) {Shadow_quality = val;}return initial;})
.level(options::ExpertLevel::Advanced)
.category("Graphics")
.default_val(ShadowQuality::Disabled)
.importance(80)
.finish();
auto ShadowQualityOption =
options::OptionBuilder<ShadowQuality>("Graphics.Shadows", "Shadow Quality", "The quality of the shadows")
.values({{ShadowQuality::Disabled, "Disabled"},
{ShadowQuality::Low, "Low"},
{ShadowQuality::Medium, "Medium"},
{ShadowQuality::High, "High"},
{ShadowQuality::Ultra, "Ultra"}})
.change_listener([](ShadowQuality val, bool initial) {
if (initial) {
Shadow_quality = val;
}
return initial; // No dynamic changes implemented
})
.level(options::ExpertLevel::Advanced)
.category("Graphics")
.default_val(ShadowQuality::Disabled)
.importance(80)
.finish();
bool shadows_obj_in_frustum(object *objp, matrix *light_orient, vec3d *min, vec3d *max)
{
@@ -218,34 +222,14 @@ void shadows_debug_show_frustum(matrix* orient, vec3d *pos, float fov, float asp
g3_render_line_3d(true, &far_bottom_left, &far_top_left);
}
void shadows_construct_light_frustum(light_frustum_info *shadow_data, matrix *light_matrix, matrix *orient, vec3d * /*pos*/, fov_t fov, float aspect, float z_near, float z_far)
void shadows_construct_light_frustum(light_frustum_info *shadow_data, matrix *light_matrix, matrix *orient, vec3d * /*pos*/, float fov, float aspect, float z_near, float z_far)
{
// find the widths and heights of the near plane and far plane to determine the points of this frustum
float near_l, near_r, near_u, near_d;
float far_l, far_r, far_u, far_d;
if (mpark::holds_alternative<float>(fov)) {
near_d = tanf(mpark::get<float>(fov) * 0.5f) * z_near;
near_u = -near_d;
near_r = near_d * aspect;
near_l = -near_r;
float near_height = tanf(fov * 0.5f) * z_near;
float near_width = near_height * aspect;
far_d = tanf(mpark::get<float>(fov) * 0.5f) * z_far;
far_u = -far_d;
far_r = far_d * aspect;
far_l = -far_r;
}
else {
const auto& afov = mpark::get<asymmetric_fov>(fov);
near_d = tanf(-afov.down) * z_near;
near_u = -tanf(afov.up) * z_near;
near_r = tanf(-afov.left) * z_near;
near_l = -tanf(afov.right) * z_near;
far_d = tanf(-afov.down) * z_far;
far_u = -tanf(afov.up) * z_far;
far_r = tanf(-afov.left) * z_far;
far_l = -tanf(afov.right) * z_far;
}
float far_height = tanf(fov * 0.5f) * z_far;
float far_width = far_height * aspect;
vec3d up_scale = ZERO_VECTOR;
vec3d right_scale = ZERO_VECTOR;
@@ -263,40 +247,40 @@ void shadows_construct_light_frustum(light_frustum_info *shadow_data, matrix *li
// near top left
up_scale = orient->vec.uvec;
vm_vec_scale(&up_scale, near_u);
vm_vec_scale(&up_scale, -near_height);
right_scale = orient->vec.rvec;
vm_vec_scale(&right_scale, near_l);
vm_vec_scale(&right_scale, -near_width);
vm_vec_add(&near_top_left, &up_scale, &right_scale);
vm_vec_add2(&near_top_left, &forward_scale_near);
// near top right
up_scale = orient->vec.uvec;
vm_vec_scale(&up_scale, near_u);
vm_vec_scale(&up_scale, -near_height);
right_scale = orient->vec.rvec;
vm_vec_scale(&right_scale, near_r);
vm_vec_scale(&right_scale, near_width);
vm_vec_add(&near_top_right, &up_scale, &right_scale);
vm_vec_add2(&near_top_right, &forward_scale_near);
// near bottom left
up_scale = orient->vec.uvec;
vm_vec_scale(&up_scale, near_d);
vm_vec_scale(&up_scale, near_height);
right_scale = orient->vec.rvec;
vm_vec_scale(&right_scale, near_l);
vm_vec_scale(&right_scale, -near_width);
vm_vec_add(&near_bottom_left, &up_scale, &right_scale);
vm_vec_add2(&near_bottom_left, &forward_scale_near);
// near bottom right
up_scale = orient->vec.uvec;
vm_vec_scale(&up_scale, near_d);
vm_vec_scale(&up_scale, near_height);
right_scale = orient->vec.rvec;
vm_vec_scale(&right_scale, near_r);
vm_vec_scale(&right_scale, near_width);
vm_vec_add(&near_bottom_right, &up_scale, &right_scale);
vm_vec_add2(&near_bottom_right, &forward_scale_near);
@@ -308,40 +292,40 @@ void shadows_construct_light_frustum(light_frustum_info *shadow_data, matrix *li
// far top left
up_scale = orient->vec.uvec;
vm_vec_scale(&up_scale, far_u);
vm_vec_scale(&up_scale, -far_height);
right_scale = orient->vec.rvec;
vm_vec_scale(&right_scale, far_l);
vm_vec_scale(&right_scale, -far_width);
vm_vec_add(&far_top_left, &up_scale, &right_scale);
vm_vec_add2(&far_top_left, &forward_scale_far);
// far top right
up_scale = orient->vec.uvec;
vm_vec_scale(&up_scale, far_u);
vm_vec_scale(&up_scale, -far_height);
right_scale = orient->vec.rvec;
vm_vec_scale(&right_scale, far_r);
vm_vec_scale(&right_scale, far_width);
vm_vec_add(&far_top_right, &up_scale, &right_scale);
vm_vec_add2(&far_top_right, &forward_scale_far);
// far bottom left
up_scale = orient->vec.uvec;
vm_vec_scale(&up_scale, far_d);
vm_vec_scale(&up_scale, far_height);
right_scale = orient->vec.rvec;
vm_vec_scale(&right_scale, far_l);
vm_vec_scale(&right_scale, -far_width);
vm_vec_add(&far_bottom_left, &up_scale, &right_scale);
vm_vec_add2(&far_bottom_left, &forward_scale_far);
// far bottom right
up_scale = orient->vec.uvec;
vm_vec_scale(&up_scale, far_d);
vm_vec_scale(&up_scale, far_height);
right_scale = orient->vec.rvec;
vm_vec_scale(&right_scale, far_r);
vm_vec_scale(&right_scale, far_width);
vm_vec_add(&far_bottom_right, &up_scale, &right_scale);
vm_vec_add2(&far_bottom_right, &forward_scale_far);
@@ -397,7 +381,7 @@ void shadows_construct_light_frustum(light_frustum_info *shadow_data, matrix *li
shadows_construct_light_proj(shadow_data);
}
matrix shadows_start_render(matrix *eye_orient, vec3d *eye_pos, fov_t fov, float aspect, float veryneardist, float neardist, float middist, float fardist)
matrix shadows_start_render(matrix *eye_orient, vec3d *eye_pos, float fov, float aspect, float veryneardist, float neardist, float middist, float fardist)
{
if(Static_light.empty())
return vmd_identity_matrix;
@@ -435,7 +419,7 @@ void shadows_end_render()
gr_shadow_map_end();
}
void shadows_render_all(fov_t fov, matrix *eye_orient, vec3d *eye_pos)
void shadows_render_all(float fov, matrix *eye_orient, vec3d *eye_pos)
{
if (gr_screen.mode == GR_STUB) {
return;
+3 -4
View File
@@ -12,7 +12,6 @@
#include "globalincs/pstypes.h"
#include "object/object.h"
#include "render/3d.h"
#define MAX_SHADOW_CASCADES 4
@@ -39,11 +38,11 @@ extern bool Shadow_quality_uses_mod_option;
extern matrix4 Shadow_proj_matrix[MAX_SHADOW_CASCADES];
extern float Shadow_cascade_distances[MAX_SHADOW_CASCADES];
void shadows_construct_light_frustum(vec3d *min_out, vec3d *max_out, vec3d light_vec, matrix *orient, vec3d *pos, fov_t fov, float aspect, float z_near, float z_far);
void shadows_construct_light_frustum(vec3d *min_out, vec3d *max_out, vec3d light_vec, matrix *orient, vec3d *pos, float fov, float aspect, float z_near, float z_far);
bool shadows_obj_in_frustum(object *objp, vec3d *min, vec3d *max, matrix *light_orient);
void shadows_render_all(fov_t fov, matrix *eye_orient, vec3d *eye_pos);
void shadows_render_all(float fov, matrix *eye_orient, vec3d *eye_pos);
matrix shadows_start_render(matrix *eye_orient, vec3d *eye_pos, fov_t fov, float aspect, float veryneardist, float neardist, float middist, float fardist);
matrix shadows_start_render(matrix *eye_orient, vec3d *eye_pos, float fov, float aspect, float veryneardist, float neardist, float middist, float fardist);
void shadows_end_render();
/**
+1 -1
View File
@@ -66,7 +66,7 @@ namespace font
{
if (string[i] >= Lcl_special_chars || string[i] < 0)
{
// Special character needs to be handled separately
// Special character needs to be handled seperately
return i;
}
}
+1 -2
View File
@@ -30,9 +30,8 @@ struct deferred_global_data {
float invScreenWidth;
float invScreenHeight;
float nearPlane;
float pad;
float pad[2];
};
/**
-3
View File
@@ -321,9 +321,6 @@ bool VulkanRenderer::initDisplayDevice() const
}
}
if (Cmdline_capture_mouse)
attrs.flags.set(os::ViewPortFlags::Capture_Mouse);
auto viewPort = m_graphicsOps->createViewport(attrs);
if (!viewPort) {
return false;
+66 -29
View File
@@ -71,7 +71,7 @@ SCP_vector<std::unique_ptr<HudGauge>> default_hud_gauges;
#define HUD_NEW_ALPHA_BRIGHT_HI 255
// Externals not related to the HUD code itself
extern fov_t View_zoom;
extern float View_zoom;
// globals that will control the color of the HUD gauges
int HUD_color_red = 0;
@@ -91,6 +91,10 @@ color HUD_color_debug; // grey debug text shown on HUD
static sound_handle Player_engine_snd_loop = sound_handle::invalid();
// HUD render frame offsets
float HUD_offset_x = 0.0f;
float HUD_offset_y = 0.0f;
// the offset of the player's view vector and the ship forward vector in pixels (Swifty)
int HUD_nose_x;
int HUD_nose_y;
@@ -1029,8 +1033,8 @@ void HudGauge::renderCircle(int x, int y, int diameter, bool filled)
void HudGauge::setClip(int x, int y, int w, int h)
{
int hx = 0;
int hy = 0;
int hx = fl2i(HUD_offset_x);
int hy = fl2i(HUD_offset_y);
if ( gr_screen.rendering_to_texture != -1 ) {
gr_set_screen_scale(canvas_w, canvas_h, -1, -1, target_w, target_h, target_w, target_h, true);
@@ -1047,22 +1051,17 @@ void HudGauge::setClip(int x, int y, int w, int h)
gr_set_clip(hx, hy, w, h);
} else {
if (reticle_follow) {
if ( reticle_follow ) {
hx += HUD_nose_x;
hy += HUD_nose_y;
gr_resize_screen_pos(&hx, &hy);
gr_set_screen_scale(base_w, base_h);
gr_unsize_screen_pos(&hx, &hy);
}
else {
gr_set_screen_scale(base_w, base_h);
}
x += hx;
y += hy;
gr_resize_screen_pos(&hx, &hy);
gr_set_screen_scale(base_w, base_h);
gr_resize_screen_pos(&x, &y, &w, &h);
gr_set_clip(x, y, w, h, GR_RESIZE_NONE);
gr_set_clip(hx+x, hy+y, w, h, GR_RESIZE_NONE);
}
gr_reset_screen_scale();
@@ -1086,6 +1085,9 @@ void HudGauge::resetClip()
gr_set_clip(hx, hy, w, h);
} else {
hx = fl2i(HUD_offset_x);
hy = fl2i(HUD_offset_y);
gr_resize_screen_pos(&hx, &hy);
gr_set_screen_scale(base_w, base_h);
@@ -1776,8 +1778,8 @@ void HudGaugeMissionTime::render(float /*frametime*/)
int minutes=0;
int seconds=0;
mission_time = f2fl(Missiontime) + (float)The_mission.HUD_timer_padding; // convert to seconds
mission_time = f2fl(Missiontime); // convert to seconds
minutes=(int)(mission_time/60);
seconds=(int)mission_time%60;
@@ -2019,7 +2021,7 @@ void hud_damage_popup_init()
Damage_flash_timer = 1;
for ( i = 0; i < SUBSYSTEM_MAX; i++ ) {
Pl_hud_subsys_info[i].last_str = 1.0f;
Pl_hud_subsys_info[i].last_str = 1000.0f;
Pl_hud_subsys_info[i].flash_duration_timestamp = 1;
Pl_hud_next_flash_timestamp = 1;
Pl_hud_is_bright = 0;
@@ -2074,11 +2076,6 @@ void HudGaugeDamage::initLineHeight(int h)
line_h = h;
}
void HudGaugeDamage::initDisplayValue(bool value)
{
always_display = value;
}
void HudGaugeDamage::initBitmaps(const char *fname_top, const char *fname_middle, const char *fname_bottom)
{
damage_top.first_frame = bm_load_animation(fname_top, &damage_top.num_frames);
@@ -2139,7 +2136,7 @@ void HudGaugeDamage::render(float /*frametime*/)
for ( pss = GET_FIRST(&Player_ship->subsys_list); pss !=END_OF_LIST(&Player_ship->subsys_list); pss = GET_NEXT(pss) ) {
psub = pss->system_info;
strength = ship_get_subsystem_strength(Player_ship, psub->type);
if ( always_display || strength < 1 ) {
if ( strength < 1 ) {
// display the actual health of this specific subsystem --wookieejedi
if (pss->max_hits > 0) {
// get percentage if this subsystem has hitpoints to begin with
@@ -2276,7 +2273,7 @@ void HudGaugeDamage::render(float /*frametime*/)
// Show hull integrity if it's below 100% or if a subsystem is damaged
// The second case is just to make the display look complete
// The third case is there to make the gauge appear only if needed if the right option is set
if ( always_display || screen_integrity < 100 || !info_lines.empty() ) {
if ( screen_integrity < 100 || !info_lines.empty() ) {
DamageInfo info;
info.name = XSTR( "Hull Integrity", 220);
@@ -3749,8 +3746,42 @@ int hud_objective_notify_active()
* @param wiggedy_wack
* @param eye_orient
*/
void HUD_set_offsets()
void HUD_set_offsets(object *viewer_obj, int wiggedy_wack, matrix *eye_orient)
{
if ( (viewer_obj == Player_obj) && wiggedy_wack ){
vec3d tmp;
vertex pt;
HUD_offset_x = 0.0f;
HUD_offset_y = 0.0f;
vm_vec_scale_add( &tmp, &Eye_position, &eye_orient->vec.fvec, 100.0f );
(void) g3_rotate_vertex(&pt,&tmp);
g3_project_vertex(&pt);
gr_unsize_screen_posf( &pt.screen.xyw.x, &pt.screen.xyw.y );
HUD_offset_x -= 0.45f * (i2fl(gr_screen.clip_width_unscaled)*0.5f - pt.screen.xyw.x);
HUD_offset_y -= 0.45f * (i2fl(gr_screen.clip_height_unscaled)*0.5f - pt.screen.xyw.y);
if ( HUD_offset_x > 100.0f ) {
HUD_offset_x = 100.0f;
} else if ( HUD_offset_x < -100.0f ) {
HUD_offset_x += 100.0f;
}
if ( HUD_offset_y > 100.0f ) {
HUD_offset_y = 100.0f;
} else if ( HUD_offset_y < -100.0f ) {
HUD_offset_y += 100.0f;
}
} else {
HUD_offset_x = 0.0f;
HUD_offset_y = 0.0f;
}
if ( Viewer_mode & ( VM_TOPDOWN | VM_CHASE ) ) {
HUD_nose_x = 0;
HUD_nose_y = 0;
@@ -3814,7 +3845,10 @@ void HUD_get_nose_coordinates(int *x, int *y)
*/
void HUD_reset_clip()
{
gr_set_clip(0, 0, gr_screen.max_w_unscaled, gr_screen.max_h_unscaled);
int hx = fl2i(HUD_offset_x);
int hy = fl2i(HUD_offset_y);
gr_set_clip(hx, hy, gr_screen.max_w_unscaled, gr_screen.max_h_unscaled);
}
/**
@@ -3822,7 +3856,10 @@ void HUD_reset_clip()
*/
void HUD_set_clip(int x, int y, int w, int h)
{
gr_set_clip(x, y, w, h);
int hx = fl2i(HUD_offset_x);
int hy = fl2i(HUD_offset_y);
gr_set_clip(hx+x, hy+y, w, h);
}
/**
@@ -3832,7 +3869,7 @@ void HUD_set_clip(int x, int y, int w, int h)
void hud_save_restore_camera_data(int save)
{
static vec3d save_view_position;
static fov_t save_view_zoom;
static float save_view_zoom;
static matrix save_view_matrix;
static matrix save_eye_matrix;
static vec3d save_eye_position;
@@ -4098,7 +4135,7 @@ void HudGaugeSupernova::render(float /*frametime*/)
}
HudGaugeFlightPath::HudGaugeFlightPath():
HudGauge3DAnchor(HUD_OBJECT_FLIGHT_PATH, HUD_CENTER_RETICLE, false, false, VM_EXTERNAL | VM_DEAD_VIEW | VM_WARP_CHASE | VM_PADLOCK_ANY, 255, 255, 255)
HudGauge(HUD_OBJECT_FLIGHT_PATH, HUD_CENTER_RETICLE, false, false, VM_EXTERNAL | VM_DEAD_VIEW | VM_WARP_CHASE | VM_PADLOCK_ANY, 255, 255, 255)
{
}
+4 -23
View File
@@ -129,7 +129,7 @@ void hud_render_gauges(int cockpit_display_num = -1);
void hud_stop_looped_engine_sounds();
// set the offset values for this render frame
void HUD_set_offsets();
void HUD_set_offsets(object *viewer_obj, int wiggedy_wack, matrix *eye_orient);
// returns the offset between the player's view vector and the forward vector of the ship in pixels (Swifty)
void HUD_get_nose_coordinates(int *x, int *y);
@@ -277,7 +277,7 @@ public:
void initOriginAndOffset(float originX, float originY, int offsetX, int offsetY);
void initCoords(bool use_coords, int coordsX, int coordsY);
virtual void initSlew(bool slew);
void initSlew(bool slew);
void initCockpitTarget(const char* display_name, int _target_x, int _target_y, int _target_w, int _target_h, int _canvas_w, int _canvas_h);
void initRenderStatus(bool render);
@@ -362,21 +362,6 @@ public:
void resetClip();
};
//Use this instead of HudGauge whenever you have a HudGauge that is anchored in 3D-space (i.e. takes its rendering coordinates from g3_rotate/project_vertex, as these MUST NEVER slew.
class HudGauge3DAnchor : public HudGauge {
public:
HudGauge3DAnchor()
: HudGauge() { }
HudGauge3DAnchor(int _gauge_object, int _gauge_config, bool /*_slew*/, bool _message, int _disabled_views, int r, int g, int b)
: HudGauge(_gauge_object, _gauge_config, false, _message, _disabled_views, r, g, b) { }
// constructor for custom gauges
HudGauge3DAnchor(int _gauge_config, bool /*_slew*/, int r, int g, int b, char* _custom_name, char* _custom_text, char* frame_fname, int txtoffset_x, int txtoffset_y)
: HudGauge(_gauge_config, false, r, g, b, _custom_name, _custom_text, frame_fname, txtoffset_x, txtoffset_y) { }
void initSlew(bool /*slew*/) override {};
};
class HudGaugeMissionTime: public HudGauge // HUD_MISSION_TIME
{
hud_frames time_gauge;
@@ -507,10 +492,7 @@ protected:
int next_flash;
bool flash_status;
bool always_display;
public:
public:
HudGaugeDamage();
void initBitmaps(const char *fname_top, const char *fname_middle, const char *fname_bottom);
void initHeaderOffsets(int x, int y);
@@ -521,7 +503,6 @@ protected:
void initSubsysIntegValueOffsetX(int x);
void initBottomBgOffset(int offset);
void initLineHeight(int h);
void initDisplayValue(bool value);
void render(float frametime) override;
void pageIn() override;
void initialize() override;
@@ -581,7 +562,7 @@ public:
void render(float frametime) override;
};
class HudGaugeFlightPath: public HudGauge3DAnchor
class HudGaugeFlightPath: public HudGauge
{
hud_frames Marker;
+1 -1
View File
@@ -331,7 +331,7 @@ int draw_subsys_brackets(graphics::line_draw_list* draw_list, ship_subsys* subsy
}
HudGaugeBrackets::HudGaugeBrackets():
HudGauge3DAnchor(HUD_OBJECT_BRACKETS, HUD_OFFSCREEN_INDICATOR, false, true, VM_DEAD_VIEW, 255, 255, 255)
HudGauge(HUD_OBJECT_BRACKETS, HUD_OFFSCREEN_INDICATOR, false, true, VM_DEAD_VIEW, 255, 255, 255)
{
}
+1 -1
View File
@@ -25,7 +25,7 @@ void draw_brackets_diamond_quick(graphics::line_draw_list* draw_list, int x1, in
int draw_subsys_brackets(graphics::line_draw_list* draw_list, ship_subsys* subsys, int min_width, int min_height, bool draw = true, bool set_color = true, int* draw_coords = NULL);
class HudGaugeBrackets: public HudGauge3DAnchor
class HudGaugeBrackets: public HudGauge
{
protected:
int attacking_dot;
+7 -2
View File
@@ -1266,7 +1266,7 @@ void hud_config_button_do(int n)
case HCB_SAVE_HCF:
int exists;
const char *out;
char *out;
// get the text in the input control
exists = 0;
@@ -1658,6 +1658,10 @@ void hud_config_as_observer(ship *shipp,ai_info *aif)
// store the current hud
hud_config_backup();
// bash these values so the HUD is not offset incorrectly
HUD_offset_x = 0.0f;
HUD_offset_y = 0.0f;
// initialize the observer HUD
hud_observer_init(shipp,aif);
}
@@ -1704,9 +1708,10 @@ void hud_config_color_load(const char *name)
{
int idx;
char str[1024];
char *fname;
ubyte r, g, b, a;
const char *fname = cf_add_ext(name, ".hcf");
fname = cf_add_ext(name, ".hcf");
try
{
+7 -13
View File
@@ -125,25 +125,19 @@ void update_ets(object* objp, float fl_frametime)
// This will translate to 71% max speed at 50% engines, and 31% max speed at 10% engines
//
float engine_aggregate_strength;
if (ship_p->flags[Ship::Ship_Flags::Maneuver_despite_engines]) {
// Pretend our strength is 100% when this flag is active
engine_aggregate_strength = 1.0f;
} else {
engine_aggregate_strength = ship_get_subsystem_strength(ship_p, SUBSYSTEM_ENGINE);
}
float eng_current_strength = ship_get_subsystem_strength(ship_p, SUBSYSTEM_ENGINE);
// only update max speed if engine_aggregate_strength has changed
// which helps minimize amount of overrides to max speed
if (engine_aggregate_strength != ship_p->prev_engine_aggregate_strength) {
// only update max speed if aggregate engine health has changed
// which helps minimze amount of overrides to max speed
if (eng_current_strength != ship_p->prev_engine_aggregate_strength) {
ets_update_max_speed(objp);
ship_p->prev_engine_aggregate_strength = engine_aggregate_strength;
ship_p->prev_engine_aggregate_strength = eng_current_strength;
// check if newly updated max speed should be reduced due to engine damage
// don't let engine strength affect max speed when playing on lowest skill level
if ((objp != Player_obj) || (Game_skill_level > 0)) {
if (engine_aggregate_strength < SHIP_MIN_ENGINES_FOR_FULL_SPEED) {
objp->phys_info.max_vel.xyz.z *= fl_sqrt(engine_aggregate_strength);
if (eng_current_strength < SHIP_MIN_ENGINES_FOR_FULL_SPEED) {
objp->phys_info.max_vel.xyz.z *= fl_sqrt(eng_current_strength);
}
}
}
+1 -1
View File
@@ -107,7 +107,7 @@ void hud_init_missile_lock()
}
HudGaugeLock::HudGaugeLock():
HudGauge3DAnchor(HUD_OBJECT_LOCK, HUD_LEAD_INDICATOR, false, false, VM_DEAD_VIEW, 255, 255, 255)
HudGauge(HUD_OBJECT_LOCK, HUD_LEAD_INDICATOR, false, false, VM_DEAD_VIEW, 255, 255, 255)
{
}
+1 -1
View File
@@ -24,7 +24,7 @@ void hud_do_lock_indicators(float frametime);
void hud_stop_looped_locking_sounds();
void hud_lock_reset(float lock_time_scale=1.0f);
class HudGaugeLock: public HudGauge3DAnchor
class HudGaugeLock: public HudGauge
{
protected:
hud_anim Lock_gauge;
+6 -36
View File
@@ -444,10 +444,6 @@ void HudGaugeMessages::render(float /*frametime*/)
// dependant on max_width, max_lines, and line_height
setClip(position[0], position[1], Window_width, Window_height+2);
//Since setClip already sets makes drawing local, further renderings mustn't additionally slew
bool doSlew = reticle_follow;
reticle_follow = false;
for ( SCP_vector<Hud_display_info>::iterator m = active_messages.begin(); m != active_messages.end(); ++m) {
if ( !timestamp_elapsed(m->total_life) ) {
if ( !(Player->flags & PLAYER_FLAGS_MSG_MODE) || !Hidden_by_comms_menu) {
@@ -463,8 +459,6 @@ void HudGaugeMessages::render(float /*frametime*/)
}
}
}
reticle_follow = doSlew;
}
// Similar to HUD printf, but shows only one message at a time, at a fixed location.
@@ -880,7 +874,6 @@ void hud_scrollback_init()
// pause all game sounds
weapon_pause_sounds();
audiostream_pause_all();
message_pause_all();
hud_initialize_scrollback_lines();
@@ -941,7 +934,6 @@ void hud_scrollback_close()
// unpause all game sounds
weapon_unpause_sounds();
audiostream_unpause_all();
message_resume_all();
}
@@ -1188,41 +1180,19 @@ void HudGaugeTalkingHead::render(float frametime)
// hud_set_default_color();
setGaugeColor();
int tablePosX = position[0];
int tablePosY = position[1];
if (reticle_follow && gr_screen.rendering_to_texture == -1) {
int nx = HUD_nose_x;
int ny = HUD_nose_y;
gr_resize_screen_pos(&nx, &ny);
gr_set_screen_scale(base_w, base_h);
gr_unsize_screen_pos(&nx, &ny);
gr_reset_screen_scale();
tablePosX += nx;
tablePosY += ny;
}
// clear
setClip(position[0] + Anim_offsets[0], position[1] + Anim_offsets[1], Anim_size[0], Anim_size[1]);
gr_clear();
resetClip();
//renderBitmap is slew corrected, so use uncorrected position
renderBitmap(Head_frame.first_frame, position[0], position[1]); // head ani border
int hx = tablePosX + Anim_offsets[0];
int hy = tablePosY + Anim_offsets[1];
if (gr_screen.rendering_to_texture != -1)
gr_set_screen_scale(canvas_w, canvas_h, -1, -1, target_w, target_h, target_w, target_h, true);
else
gr_set_screen_scale(base_w, base_h);
generic_anim_render_ex(head_anim,frametime, hx, hy, Anim_size[0], Anim_size[1]);
gr_reset_screen_scale();
float scale_x = i2fl(Anim_size[0]) / i2fl(head_anim->width);
float scale_y = i2fl(Anim_size[1]) / i2fl(head_anim->height);
gr_set_screen_scale(fl2ir(base_w / scale_x), fl2ir(base_h / scale_y));
setGaugeColor();
generic_anim_render(head_anim,frametime, fl2ir((position[0] + Anim_offsets[0] + HUD_offset_x) / scale_x), fl2ir((position[1] + Anim_offsets[1] + HUD_offset_y) / scale_y));
// draw title
gr_set_screen_scale(base_w, base_h);
renderString(position[0] + Header_offsets[0], position[1] + Header_offsets[1], XSTR("message", 217));
} else {
for (int j = 0; j < Num_messages_playing; ++j) {
-1
View File
@@ -18,7 +18,6 @@
#define MAX_HUD_LINE_LEN 256 // maximum number of characters for a HUD message
// If these are changed, the lua 'addMessageToScrollback' method in mission.cpp should be updated.
#define HUD_SOURCE_COMPUTER 0
#define HUD_SOURCE_TRAINING 1
#define HUD_SOURCE_HIDDEN 2
-5
View File
@@ -4143,7 +4143,6 @@ void load_gauge_damage(gauge_settings* settings)
char fname_top[MAX_FILENAME_LEN] = "damage1";
char fname_middle[MAX_FILENAME_LEN] = "damage2";
char fname_bottom[MAX_FILENAME_LEN] = "damage3";
bool always_display = false;
settings->origin[0] = 0.5f;
settings->origin[1] = 0.0f;
@@ -4201,9 +4200,6 @@ void load_gauge_damage(gauge_settings* settings)
if(optional_string("Bottom Background Offset:")) {
stuff_int(&bottom_bg_offset);
}
if(optional_string("Always Display:")) {
stuff_boolean(&always_display);
}
hud_gauge->initBitmaps(fname_top, fname_middle, fname_bottom);
hud_gauge->initHullIntegOffsets(hull_integ_offsets[0], hull_integ_offsets[1]);
@@ -4214,7 +4210,6 @@ void load_gauge_damage(gauge_settings* settings)
hud_gauge->initSubsysIntegValueOffsetX(subsys_integ_val_offset_x);
hud_gauge->initBottomBgOffset(bottom_bg_offset);
hud_gauge->initHeaderOffsets(header_offsets[0], header_offsets[1]);
hud_gauge->initDisplayValue(always_display);
gauge_assign_common(settings, std::move(hud_gauge));
}
+10 -7
View File
@@ -365,8 +365,8 @@ void hud_shield_show_mini(object *objp, int x_force, int y_force, int x_hull_off
if (!Shield_mini_loaded)
return;
sx = (x_force == -1) ? Shield_mini_coords[gr_screen.res][0] : x_force;
sy = (y_force == -1) ? Shield_mini_coords[gr_screen.res][1] : y_force;
sx = (x_force == -1) ? Shield_mini_coords[gr_screen.res][0]+fl2i(HUD_offset_x) : x_force;
sy = (y_force == -1) ? Shield_mini_coords[gr_screen.res][1]+fl2i(HUD_offset_y) : y_force;
// draw the ship first
hud_shield_maybe_flash(HUD_TARGET_MINI_ICON, SHIELD_HIT_TARGET, Shield_hit_data[SHIELD_HIT_TARGET].hull_hit_index);
@@ -596,6 +596,9 @@ void HudGaugeShield::showShields(object *objp, int mode)
sx = position[0];
sy = position[1];
sx += fl2i(HUD_offset_x);
sy += fl2i(HUD_offset_y);
// draw the ship first
maybeFlashShield(SHIELD_HIT_PLAYER, Shield_hit_data[SHIELD_HIT_PLAYER].hull_hit_index);
@@ -632,7 +635,7 @@ void HudGaugeShield::showShields(object *objp, int mode)
g3_set_view_matrix( &finger_vec, &vmd_identity_matrix, 1.0f);
}*/
gr_set_proj_matrix(Proj_fov * 0.5f, gr_screen.clip_aspect, Min_draw_distance, Max_draw_distance);
gr_set_proj_matrix(0.5f*Proj_fov, gr_screen.clip_aspect, Min_draw_distance, Max_draw_distance);
gr_set_view_matrix(&Eye_position, &Eye_matrix);
//We're ready to show stuff
@@ -968,8 +971,8 @@ void HudGaugeShieldMini::showMiniShields(object *objp)
setGaugeColor();
sx = position[0];
sy = position[1];
sx = position[0]+fl2i(HUD_offset_x);
sy = position[1]+fl2i(HUD_offset_y);
// draw the ship first
maybeFlashShield(SHIELD_HIT_TARGET, Shield_hit_data[SHIELD_HIT_TARGET].hull_hit_index);
@@ -1058,8 +1061,8 @@ void HudGaugeShieldMini::showIntegrity(float p_target_integrity)
}
}
final_pos[0] += position[0];
final_pos[1] += position[1];
final_pos[0] += fl2i( HUD_offset_x ) + position[0];
final_pos[1] += fl2i( HUD_offset_y ) + position[1];
sprintf(text_integrity, "%d", numeric_integrity);
if ( numeric_integrity < 100 ) {
+100 -91
View File
@@ -105,15 +105,32 @@ typedef struct mmode_item {
SCP_string text; // text to display on the menu
} mmode_item;
#define MAX_MENU_ITEMS 50 // max number of items in the menu
#define MAX_MENU_DISPLAY 10 // max number that can be displayed
char Squad_msg_title[256] = "";
mmode_item MsgItems[MAX_MENU_ITEMS];
int Num_menu_items = -1; // number of items for a message menu
int First_menu_item= -1; // index of first item in the menu
SCP_string Lua_sqd_msg_cat;
// -----------
// following set of vars/defines are used to store/restore key bindings for keys that
// are used in messaging mode
// array to temporarily store key bindings that will be in use for the messaging
// system
typedef struct key_store {
int option_num; // which element in the Control_config array is this
int id; // which id (1 or 2) is this key.
int key_value; // which key value to put there.
} key_store;
#define MAX_KEYS_NO_SCROLL 10
#define MAX_KEYS_USED 12 // maximum number of keys used for the messaging system
key_store key_save[MAX_KEYS_USED]; // array to save the key information during messaging mode
int num_keys_saved = 0; // number of keys that are saved.
// next array is the array of MAX_KEYS_USED size which are the keys to use for messaging mode
int keys_used[] = { KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0,
@@ -122,6 +139,17 @@ int keys_used[] = { KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_
#define ID1 1
#define ID2 2
// following are defines and character strings that are used as part of messaging mode
#define NUM_COMM_ORDER_TYPES 6
#define TYPE_SHIP_ITEM 0
#define TYPE_WING_ITEM 1
#define TYPE_ALL_FIGHTERS_ITEM 2
#define TYPE_REINFORCEMENT_ITEM 3
#define TYPE_REPAIR_REARM_ITEM 4
#define TYPE_REPAIR_REARM_ABORT_ITEM 5
SCP_string Comm_order_types[NUM_COMM_ORDER_TYPES];
@@ -214,8 +242,18 @@ void hud_squadmsg_start()
}
}
// int i;
//if ( num_keys_saved < 0 ) // save the keys if they haven't been saved yet
hud_squadmsg_save_keys();
Msg_key = -1;
/*
for (i=0; i<num_keys_saved; i++)
clear_key_binding ( (short) key_save[i].key_value ); // removes all mention of this key from Control_config
*/
Num_menu_items = -1; // reset the menu items
First_menu_item = 0;
Squad_msg_mode = SM_MODE_TYPE_SELECT; // start off at the base state
@@ -236,7 +274,7 @@ void hud_squadmsg_start()
}
}
// function which will clean things up when messaging mode is done
// functions which will restore all of the key binding stuff when messaging mode is done
void hud_squadmsg_end()
{
if (scripting::hooks::OnHudCommMenuClosed->isActive())
@@ -249,6 +287,17 @@ void hud_squadmsg_end()
}
}
/*
int i;
key_store *ksp;
// move through all keys saved and restore their orignal values.
for ( i=0; i<num_keys_saved; i++ ) {
ksp = &key_save[i];
Control_config[ksp->option_num].key_id = (short) ksp->key_value;
}
*/
if ( message_is_playing() == FALSE )
snd_play( gamesnd_get_game_sound(GameSounds::SQUADMSGING_OFF) );
@@ -377,6 +426,10 @@ int hud_squadmsg_count_ships(int add_to_menu)
}
}
// if adding to the menu and we have > 10 items, then don't allow page up and page down to be used.
if ( add_to_menu && (Num_menu_items > MAX_MENU_DISPLAY) )
hud_squadmsg_save_keys(1);
return count;
}
@@ -563,7 +616,7 @@ int hud_squadmsg_get_key()
// use a timestamp to prevent top level key code from possibly reprocessing this key
Msg_eat_key_timestamp = timestamp(MSG_KEY_EAT_TIME);
if ( k == KEY_PAGEDOWN ) { // pageup and pagedown scroll the menu -- deal with these separately!!
if ( k == KEY_PAGEDOWN ) { // pageup and pagedown scroll the menu -- deal with these seperately!!
hud_squadmsg_page_down();
return -1;
} else if ( k == KEY_PAGEUP ) {
@@ -1094,7 +1147,7 @@ int hud_squadmsg_send_ship_command( int shipnum, int command, int send_message,
Objects[ainfo->target_objnum].flags.remove(Object::Object_Flags::Protected);
}
ai_mode = (The_mission.ai_profile->flags[AI::Profile_Flags::Hudsquadmsg_tactical_disarm_disable]) ? AI_GOAL_DISABLE_SHIP_TACTICAL : AI_GOAL_DISABLE_SHIP;
ai_mode = AI_GOAL_DISABLE_SHIP;
ai_submode = -SUBSYSTEM_ENGINE;
message = MESSAGE_DISABLE_TARGET;
break;
@@ -1108,7 +1161,7 @@ int hud_squadmsg_send_ship_command( int shipnum, int command, int send_message,
Objects[ainfo->target_objnum].flags.remove(Object::Object_Flags::Protected);
}
ai_mode = (The_mission.ai_profile->flags[AI::Profile_Flags::Hudsquadmsg_tactical_disarm_disable]) ? AI_GOAL_DISARM_SHIP_TACTICAL : AI_GOAL_DISARM_SHIP;
ai_mode = AI_GOAL_DISARM_SHIP;
ai_submode = -SUBSYSTEM_TURRET;
message = MESSAGE_DISARM_TARGET;
break;
@@ -1380,7 +1433,7 @@ int hud_squadmsg_send_wing_command( int wingnum, int command, int send_message,
Assert(target_shipname);
Assert(wing_team != target_team);
ai_mode = (The_mission.ai_profile->flags[AI::Profile_Flags::Hudsquadmsg_tactical_disarm_disable]) ? AI_GOAL_DISABLE_SHIP_TACTICAL : AI_GOAL_DISABLE_SHIP;
ai_mode = AI_GOAL_DISABLE_SHIP;
ai_submode = -SUBSYSTEM_ENGINE;
message = MESSAGE_DISABLE_TARGET;
break;
@@ -1389,7 +1442,7 @@ int hud_squadmsg_send_wing_command( int wingnum, int command, int send_message,
Assert(target_shipname);
Assert(wing_team != target_team);
ai_mode = (The_mission.ai_profile->flags[AI::Profile_Flags::Hudsquadmsg_tactical_disarm_disable]) ? AI_GOAL_DISARM_SHIP_TACTICAL : AI_GOAL_DISARM_SHIP;
ai_mode = AI_GOAL_DISARM_SHIP;
ai_submode = -SUBSYSTEM_TURRET;
message = MESSAGE_DISARM_TARGET;
break;
@@ -1577,26 +1630,13 @@ void hud_squadmsg_type_select( )
{
int k, i;
int num_order_types = NUM_COMM_ORDER_TYPES;
int lua_order_count = 0;
// Now get a list of all lua categories to add. Meow.
SCP_vector<SCP_string> lua_cat_list = ai_lua_get_general_order_categories();
num_order_types += (int)lua_cat_list.size();
// Add the items
for (i = 0; i < num_order_types; i++)
for (i = 0; i < NUM_COMM_ORDER_TYPES; i++)
{
if (i < NUM_COMM_ORDER_TYPES) {
MsgItems[i].text = Comm_order_types[i];
} else {
MsgItems[i].text = lua_cat_list[i - NUM_COMM_ORDER_TYPES];
}
MsgItems[i].text = Comm_order_types[i];
MsgItems[i].active = 1; // assume active
}
Num_menu_items = num_order_types;
Num_menu_items = NUM_COMM_ORDER_TYPES;
// check to see if the player is a traitor. If so, then he will not
@@ -1627,13 +1667,6 @@ void hud_squadmsg_type_select( )
MsgItems[TYPE_REPAIR_REARM_ITEM].active = 1; // this item will always be available (I think)
MsgItems[TYPE_REPAIR_REARM_ABORT_ITEM].active = 0;
for(const auto& cat : lua_cat_list){
if (ai_lua_get_general_orders(false, false, cat).size() == 0) {
MsgItems[NUM_COMM_ORDER_TYPES + lua_order_count].active = 0;
}
lua_order_count++;
}
// AL: 10/13/97
// If the player ship communications are severely damaged, then the player
// will only be able to call for repair/rearm ships
@@ -1701,9 +1734,6 @@ do_main_menu:
hud_squadmsg_do_mode( SM_MODE_REPAIR_REARM );
} else if ( k == TYPE_REPAIR_REARM_ABORT_ITEM ) {
hud_squadmsg_do_mode( SM_MODE_REPAIR_REARM_ABORT );
} else if (k >= NUM_COMM_ORDER_TYPES) {
Lua_sqd_msg_cat = lua_cat_list[k - NUM_COMM_ORDER_TYPES];
hud_squadmsg_do_mode( SM_MODE_GENERAL );
}
}
}
@@ -2048,60 +2078,6 @@ void hud_squadmsg_ship_command()
}
}
void hud_squadmsg_msg_general()
{
int k;
Num_menu_items = 0;
for (size_t order_id = 0; order_id < Player_orders.size(); order_id++) {
Assert(Num_menu_items < MAX_MENU_ITEMS);
if (Player_orders[order_id].lua_id <= 0) {
continue;
}
auto lua_porder = ai_lua_find_player_order(Player_orders[order_id].lua_id);
//If it's not a general order then do not add it.
if (!lua_porder->generalOrder) {
continue;
}
//If it's not part of the selected category then do not add it.
if (lua_porder->category != Lua_sqd_msg_cat) {
continue;
}
//Only add it if it is enabled for the mission
if (lua_porder->cur_enabled) {
MsgItems[Num_menu_items].text = Player_orders[order_id].localized_name;
MsgItems[Num_menu_items].instance = Player_orders[order_id].lua_id;
MsgItems[Num_menu_items].active = (int)lua_porder->cur_valid;
// do some other checks to possibly gray out other items.
// if no target, remove any items which are associated with the players target
if (!hud_squadmsg_is_target_order_valid(order_id, nullptr))
MsgItems[Num_menu_items].active = 0;
Num_menu_items++;
}
}
strcpy_s(Squad_msg_title, XSTR("What Command", 321));
k = hud_squadmsg_get_key();
// when we get a valid goal, we must add the goal to the ai ship's goal list
if (k != -1) {
Assert(k < Num_menu_items);
ai_lua_start_general(MsgItems[k].instance, Player_ai->target_objnum);
hud_squadmsg_toggle();
}
}
// function to display list of command for a wing
void hud_squadmsg_wing_command()
{
@@ -2187,6 +2163,43 @@ void hud_squadmsg_wing_command()
//----------------------------------------------------------
// external entry points below!!!!
// when starting messaging mode, we must remove old bindings from the
// keys that are used for messaging mode (which will get restored when
// messaging mode is done).
// this code below will get called only the key config changes (from ControlsConfig.cpp)
// or if the bindings haven't been saved yet. This code doesn't remove the bindings
// but just sets up the array so that the bindings can be removed when messaging
// mode is entered.
//
// do_scroll indicates whether we should save the page up and page down keys
void hud_squadmsg_save_keys( int /*do_scroll*/ )
{
// int i, j;
num_keys_saved = 0;
/*
for ( j=0; j<MAX_KEYS_USED; j++ ) {
for ( i=0; Control_config[i].text[0]; i++ ) { // the text field in this structure is empty at the end of the config list
if ( Control_config[i].key_id == keys_used[j] ) { // this is true if we have a match
// if we are not saving scrolling keys and we are trying to match page up and page down
// then skip them.
if ( !do_scroll && ((keys_used[j] == KEY_PAGEDOWN) || (keys_used[j] == KEY_PAGEUP)) )
continue;
Assert( num_keys_saved < MAX_KEYS_USED );
key_save[num_keys_saved].option_num = i;
key_save[num_keys_saved].key_value = keys_used[j];
num_keys_saved++;
break; // done with this key -- move to next.
}
}
}
*/
}
// function is called once per mission start. Initializes those values
// which only need to be inited once per mission.
void hud_init_squadmsg( void )
@@ -2401,10 +2414,6 @@ int hud_squadmsg_do_frame( )
hud_squadmsg_msg_all_fighters();
break;
case SM_MODE_GENERAL:
hud_squadmsg_msg_general();
break;
default:
Int3(); // get allender -- invalid mode in messaging system
break;
+1 -15
View File
@@ -24,7 +24,6 @@
#define SM_MODE_REPAIR_REARM 7 //repair/rearm player ship
#define SM_MODE_REPAIR_REARM_ABORT 8 //abort repair/rearm of player ship
#define SM_MODE_ALL_FIGHTERS 9 //message all fighters/bombers
#define SM_MODE_GENERAL 10 //general orders, usually luaAI
// define for trapping messages send to "all fighters"
#define MESSAGE_ALL_FIGHTERS -999
@@ -61,20 +60,6 @@ class object;
// used for Message box gauge
#define NUM_MBOX_FRAMES 3
#define MAX_MENU_ITEMS 50 // max number of items in the menu
#define MAX_MENU_DISPLAY 10 // max number that can be displayed
// following are defines and character strings that are used as part of messaging mode
#define NUM_COMM_ORDER_TYPES 6
#define TYPE_SHIP_ITEM 0
#define TYPE_WING_ITEM 1
#define TYPE_ALL_FIGHTERS_ITEM 2
#define TYPE_REINFORCEMENT_ITEM 3
#define TYPE_REPAIR_REARM_ITEM 4
#define TYPE_REPAIR_REARM_ABORT_ITEM 5
typedef struct player_order {
private:
//Needed, because legacy order-id's were not assigned in order
@@ -155,6 +140,7 @@ extern void hud_init_comm_orders();
extern void hud_squadmsg_toggle(); // toggles the state of messaging mode
extern void hud_squadmsg_shortcut( int command ); // use of a shortcut key
extern int hud_squadmsg_hotkey_select( int k ); // a hotkey was hit -- maybe send a message to those ship(s)
extern void hud_squadmsg_save_keys( int do_scroll = 0 ); // saves into local area keys which need to be saved/restored when in messaging mode
extern int hud_squadmsg_do_frame();
extern int hud_query_order_issued(const char *to, const char *order_name, const char *target = nullptr, int timestamp = 0, const char *from = nullptr, const char *special_index = nullptr);
extern int hud_squadmsg_read_key( int k ); // called from high level keyboard code
+36 -61
View File
@@ -2073,7 +2073,7 @@ bool evaluate_ship_as_closest_target(esct *esct_p)
}
// bail if harmless
if ( Ship_info[esct_p->shipp->ship_info_index].class_type < 0 || !(Ship_types[Ship_info[esct_p->shipp->ship_info_index].class_type].flags[Ship::Type_Info_Flags::Target_as_threat])) {
if ( Ship_info[esct_p->shipp->ship_info_index].class_type > -1 && !(Ship_types[Ship_info[esct_p->shipp->ship_info_index].class_type].flags[Ship::Type_Info_Flags::Target_as_threat])) {
return false;
}
@@ -2758,12 +2758,18 @@ void HudGaugeOrientationTee::renderOrientation(object *from_objp, object *to_obj
y1 += position[1];
x1 += position[0];
x1 += HUD_offset_x;
y1 += HUD_offset_y;
y2 = sinf(dot_product) * (Radius - T_OFFSET_FROM_CIRCLE - T_LENGTH);
x2 = cosf(dot_product) * (Radius - T_OFFSET_FROM_CIRCLE - T_LENGTH);
y2 += position[1];
x2 += position[0];
x2 += HUD_offset_x;
y2 += HUD_offset_y;
x3 = x1 - T_BASE_LENGTH * sinf(dot_product);
y3 = y1 + T_BASE_LENGTH * cosf(dot_product);
x4 = x1 + T_BASE_LENGTH * sinf(dot_product);
@@ -2977,7 +2983,6 @@ void HudGaugeReticleTriangle::renderTriangle(vec3d *hostile_pos, int aspect_flag
float ang;
float xpos,ypos,cur_dist,sin_ang,cos_ang;
int draw_inside=0;
int tablePosX, tablePosY;
// determine if the given object is within the targeting reticle
// (which means the triangle is not drawn)
@@ -2987,24 +2992,6 @@ void HudGaugeReticleTriangle::renderTriangle(vec3d *hostile_pos, int aspect_flag
g3_rotate_vertex(&hostile_vertex, hostile_pos);
g3_project_vertex(&hostile_vertex);
if (reticle_follow) {
int nx = HUD_nose_x;
int ny = HUD_nose_y;
gr_resize_screen_pos(&nx, &ny);
gr_set_screen_scale(base_w, base_h);
gr_unsize_screen_pos(&nx, &ny);
gr_reset_screen_scale();
tablePosX = position[0] + nx;
tablePosY = position[1] + ny;
}
else {
//Technically not non-slewing, but keeps old behaviour
tablePosX = position[0] + fl2i(HUD_nose_x);
tablePosY = position[1] + fl2i(HUD_nose_y);
}
if (hostile_vertex.codes == 0) { // on screen
int projected_x, projected_y;
@@ -3016,8 +3003,8 @@ void HudGaugeReticleTriangle::renderTriangle(vec3d *hostile_pos, int aspect_flag
unsize(&projected_x, &projected_y);
mag_squared = (projected_x - tablePosX) * (projected_x - tablePosX) +
(projected_y - tablePosY) * (projected_y - tablePosY);
mag_squared = (projected_x - position[0]) * (projected_x - position[0]) +
(projected_y - position[1]) * (projected_y - position[1]);
if ( mag_squared < Radius*Radius ) {
if ( show_interior ) {
@@ -3029,21 +3016,28 @@ void HudGaugeReticleTriangle::renderTriangle(vec3d *hostile_pos, int aspect_flag
}
}
// even if the screen position overflowed, it will still be pointing in the correct direction
unsize( &hostile_vertex.screen.xyw.x, &hostile_vertex.screen.xyw.y );
int HUD_nose_scaled_x = HUD_nose_x;
int HUD_nose_scaled_y = HUD_nose_y;
ang = atan2_safe(-(hostile_vertex.screen.xyw.y - tablePosY), hostile_vertex.screen.xyw.x - tablePosX);
gr_resize_screen_pos(&HUD_nose_scaled_x, &HUD_nose_scaled_y);
unsize( &hostile_vertex.world.xyz.x, &hostile_vertex.world.xyz.y );
ang = atan2_safe(hostile_vertex.world.xyz.y,hostile_vertex.world.xyz.x);
sin_ang=sinf(ang);
cos_ang=cosf(ang);
if ( draw_inside ) {
xpos = tablePosX + cos_ang*(Radius-7);
ypos = tablePosY - sin_ang*(Radius-7);
xpos = position[0] + cos_ang*(Radius-7);
ypos = position[1] - sin_ang*(Radius-7);
} else {
xpos = tablePosX + cos_ang*(Radius+4);
ypos = tablePosY - sin_ang*(Radius+4);
xpos = position[0] + cos_ang*(Radius+4);
ypos = position[1] - sin_ang*(Radius+4);
}
xpos += HUD_offset_x + HUD_nose_x;
ypos += HUD_offset_y + HUD_nose_y;
if ( split_tri ) {
// renderTriangleMissileSplit(ang, xpos, ypos, cur_dist, aspect_flag, draw_inside);
renderTriangleMissileTail(ang, xpos, ypos, cur_dist, aspect_flag, draw_inside);
@@ -3583,8 +3577,8 @@ void hud_show_hostile_triangle()
continue;
}
// always ignore cargo containers, navbouys, etc, and non-ships
if ( Ship_info[sp->ship_info_index].class_type < 0 || !(Ship_types[Ship_info[sp->ship_info_index].class_type].flags[Ship::Type_Info_Flags::Show_attack_direction]) ) {
// always ignore cargo containers and navbuoys
if ( Ship_info[sp->ship_info_index].class_type > -1 && !(Ship_types[Ship_info[sp->ship_info_index].class_type].flags[Ship::Type_Info_Flags::Show_attack_direction]) ) {
continue;
}
@@ -3824,7 +3818,7 @@ void polish_predicted_target_pos(weapon_info *wip, object *targetp, vec3d *enemy
}
HudGaugeLeadIndicator::HudGaugeLeadIndicator():
HudGauge3DAnchor(HUD_OBJECT_LEAD, HUD_LEAD_INDICATOR, false, false, VM_EXTERNAL | VM_DEAD_VIEW | VM_WARP_CHASE | VM_PADLOCK_ANY | VM_OTHER_SHIP, 255, 255, 255)
HudGauge(HUD_OBJECT_LEAD, HUD_LEAD_INDICATOR, false, false, VM_EXTERNAL | VM_DEAD_VIEW | VM_WARP_CHASE | VM_PADLOCK_ANY | VM_OTHER_SHIP, 255, 255, 255)
{
}
@@ -4255,32 +4249,11 @@ void HudGaugeLeadSight::renderSight(int frame_offset, vec3d *target_pos, vec3d *
float reticle_target_sx = target_sx - Lead_sight_half[0] - target_lead_sx;
float reticle_target_sy = target_sy - Lead_sight_half[1] - target_lead_sy;
int tablePosX = position[0];
int tablePosY = position[1];
bool do_slew = reticle_follow;
if (do_slew) {
int nx = HUD_nose_x;
int ny = HUD_nose_y;
gr_resize_screen_pos(&nx, &ny);
gr_set_screen_scale(base_w, base_h);
gr_unsize_screen_pos(&nx, &ny);
gr_reset_screen_scale();
tablePosX += nx;
tablePosY += ny;
}
reticle_target_sx += tablePosX + 0.5f;
reticle_target_sy += tablePosY + 0.5f;
reticle_target_sx += position[0] + 0.5f;
reticle_target_sy += position[1] + 0.5f;
setGaugeColor();
//We need to do slewing manually only on the non-3D-dependant part of the hud, so make the rendering function believe that we don't slew
reticle_follow = false;
renderBitmap(Lead_sight.first_frame + frame_offset, fl2i(reticle_target_sx), fl2i(reticle_target_sy));
reticle_follow = do_slew;
renderBitmap(Lead_sight.first_frame + frame_offset, fl2i(reticle_target_sx) + fl2i(HUD_offset_x), fl2i(reticle_target_sy) + fl2i(HUD_offset_y));
}
}
@@ -6391,7 +6364,7 @@ void hud_target_clear_display_list()
}
HudGaugeOffscreen::HudGaugeOffscreen():
HudGauge3DAnchor(HUD_OBJECT_OFFSCREEN, HUD_OFFSCREEN_INDICATOR, false, true, VM_DEAD_VIEW | VM_OTHER_SHIP, 255, 255, 255)
HudGauge(HUD_OBJECT_OFFSCREEN, HUD_OFFSCREEN_INDICATOR, false, true, VM_DEAD_VIEW | VM_OTHER_SHIP, 255, 255, 255)
{
}
@@ -6522,9 +6495,11 @@ void HudGaugeOffscreen::calculatePosition(vertex* target_point, vec3d *tpos, vec
codes_or = (ubyte)(target_point->codes | eye_vertex->codes);
clip_line(&target_point,&eye_vertex,codes_or,0);
g3_project_vertex(target_point);
if (!(target_point->flags&PF_PROJECTED))
g3_project_vertex(target_point);
g3_project_vertex(eye_vertex);
if (!(eye_vertex->flags&PF_PROJECTED))
g3_project_vertex(eye_vertex);
if (eye_vertex->flags&PF_OVERFLOW) {
Int3(); // This is unlikely to happen, but can if a clip goes through the player's eye.
@@ -7441,8 +7416,8 @@ void HudGaugeHardpoints::render(float /*frametime*/)
//unsize(&xc, &yc);
//unsize(&draw_point.screen.xyw.x, &draw_point.screen.xyw.y);
if (!(draw_point.flags & PF_OVERFLOW))
renderCircle((int)draw_point.screen.xyw.x + position[0], (int)draw_point.screen.xyw.y + position[1], 10);
renderCircle((int)draw_point.screen.xyw.x + position[0], (int)draw_point.screen.xyw.y + position[1], 10);
//renderCircle(xc, yc, 25);
} else {
model_render_params weapon_render_info;
+2 -2
View File
@@ -543,7 +543,7 @@ public:
void render(float frametime) override;
};
class HudGaugeOffscreen: public HudGauge3DAnchor
class HudGaugeOffscreen: public HudGauge
{
protected:
float Max_offscreen_tri_seperation;
@@ -562,7 +562,7 @@ public:
void pageIn() override;
};
class HudGaugeLeadIndicator: public HudGauge3DAnchor
class HudGaugeLeadIndicator: public HudGauge
{
protected:
hud_frames Lead_indicator_gauge;
+16 -6
View File
@@ -39,7 +39,7 @@
#endif
extern fov_t View_zoom;
extern float View_zoom;
int Target_window_coords[GR_NUM_RESOLUTIONS][4] =
{
@@ -524,7 +524,7 @@ void HudGaugeTargetBox::renderTargetIntegrity(int disabled,int force_obj_num)
}
}
void HudGaugeTargetBox::renderTargetSetup(vec3d *camera_eye, matrix *camera_orient, fov_t zoom)
void HudGaugeTargetBox::renderTargetSetup(vec3d *camera_eye, matrix *camera_orient, float zoom)
{
// JAS: g3_start_frame uses clip_width and clip_height to determine the
// size to render to. Normally, you would set this by using gr_set_clip,
@@ -943,7 +943,7 @@ void HudGaugeTargetBox::renderTargetWeapon(object *target_objp)
vm_vec_sub(&obj_pos, &viewed_obj->pos, &viewer_obj->pos);
}
renderTargetSetup(&camera_eye, &camera_orient, View_zoom * (1.0f/3.0f));
renderTargetSetup(&camera_eye, &camera_orient, View_zoom/3);
model_clear_instance(viewed_model_num);
model_render_params render_info;
@@ -1269,7 +1269,7 @@ void HudGaugeTargetBox::renderTargetJumpNode(object *target_objp)
matrix camera_orient = IDENTITY_MATRIX;
vec3d orient_vec, up_vector;
float factor, dist;
int hx = 0, hy = 0, w, h;
int hx, hy, w, h;
SCP_list<CJumpNode>::iterator jnp;
for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) {
@@ -1329,6 +1329,10 @@ void HudGaugeTargetBox::renderTargetJumpNode(object *target_objp)
dist = dist * Hud_unit_multiplier;
}
// account for hud shaking
hx = fl2i(HUD_offset_x);
hy = fl2i(HUD_offset_y);
sprintf(outstr,XSTR( "d: %.0f", 340), dist);
hud_num_make_mono(outstr, font_num);
gr_get_string_size(&w,&h,outstr);
@@ -2107,13 +2111,19 @@ void HudGaugeTargetBox::showTargetData(float /*frametime*/)
break;
}
int hx, hy;
// Account for HUD shaking
hx = fl2i(HUD_offset_x);
hy = fl2i(HUD_offset_y);
// print out the target distance and speed
sprintf(outstr,XSTR( "d: %.0f%s", 350), displayed_target_distance, modifiers[Player_ai->current_target_dist_trend]);
hud_num_make_mono(outstr, font_num);
gr_get_string_size(&w,&h,outstr);
renderString(position[0] + Dist_offsets[0], position[1] + Dist_offsets[1], EG_TBOX_DIST, outstr);
renderString(position[0] + Dist_offsets[0]+hx, position[1] + Dist_offsets[1]+hy, EG_TBOX_DIST, outstr);
#if 0
current_target_speed = vm_vec_dist(&target_objp->pos, &target_objp->last_pos) / frametime;
@@ -2141,7 +2151,7 @@ void HudGaugeTargetBox::showTargetData(float /*frametime*/)
sprintf(outstr, XSTR( "s: %.0f%s", 351), displayed_target_speed, (displayed_target_speed>1)?modifiers[Player_ai->current_target_speed_trend]:"");
hud_num_make_mono(outstr, font_num);
renderString(position[0] + Speed_offsets[0], position[1] + Speed_offsets[1], EG_TBOX_SPEED, outstr);
renderString(position[0] + Speed_offsets[0]+hx, position[1] + Speed_offsets[1]+hy, EG_TBOX_SPEED, outstr);
//
// output target info for debug purposes only, this will be removed later
+1 -1
View File
@@ -128,7 +128,7 @@ public:
void renderTargetDebris(object *target_objp);
void renderTargetAsteroid(object *target_objp);
void renderTargetJumpNode(object *target_objp);
void renderTargetSetup(vec3d *camera_eye, matrix *camera_orient, fov_t zoom);
void renderTargetSetup(vec3d *camera_eye, matrix *camera_orient, float zoom);
void renderTargetClose();
void renderTargetForeground();
void renderTargetIntegrity(int disabled, int force_obj_num = -1);
+44 -52
View File
@@ -238,61 +238,53 @@ SCP_vector<Joystick*> joystick_enumerator()
* Joystick options for the new menu system
* These should be displayed as a dropdown box type widget
*/
auto JoystickOption = options::OptionBuilder<Joystick*>("Input.Joystick",
std::pair<const char*, int>{"Joystick 0", 1705},
std::pair<const char*, int>{"The current joystick 0", 1706})
.category("Input") // Category this option shows up in the scripting heirachy
.deserializer(joystick_deserialize) // callback for json to C++
.serializer(joystick_serializer) // callback for C++ to json
.display(joystick_display) // callback for constructing the display label
.enumerator(joystick_enumerator) // callback for enumerating/constructing the values this option may take
.level(options::ExpertLevel::Beginner)
.default_val(nullptr) // initial/default value for this option
.flags({options::OptionFlags::ForceMultiValueSelection})
.importance(3)
.finish();
auto JoystickOption = options::OptionBuilder<Joystick*>("Input.Joystick", "Joystick", "The current joystick 0.")
.category("Input") // Category this option shows up in the scripting heirachy
.deserializer(joystick_deserialize) // callback for json to C++
.serializer(joystick_serializer) // callback for C++ to json
.display(joystick_display) // callback for constructing the display label
.enumerator(joystick_enumerator) // callback for enumerating/constructing the values this option may take
.level(options::ExpertLevel::Beginner)
.default_val(nullptr) // initial/default value for this option
.flags({options::OptionFlags::ForceMultiValueSelection})
.importance(3)
.finish();
auto JoystickOption1 = options::OptionBuilder<Joystick*>("Input.Joystick1",
std::pair<const char*, int>{"Joystick 1", 1707},
std::pair<const char*, int>{"The current joystick 1", 1708})
.category("Input")
.deserializer(joystick_deserialize)
.serializer(joystick_serializer)
.display(joystick_display)
.enumerator(joystick_enumerator)
.level(options::ExpertLevel::Beginner)
.default_val(nullptr)
.flags({ options::OptionFlags::ForceMultiValueSelection })
.importance(3)
.finish();
auto JoystickOption1 = options::OptionBuilder<Joystick*>("Input.Joystick1", "Joystick1", "The current joystick 1.")
.category("Input")
.deserializer(joystick_deserialize)
.serializer(joystick_serializer)
.display(joystick_display)
.enumerator(joystick_enumerator)
.level(options::ExpertLevel::Beginner)
.default_val(nullptr)
.flags({ options::OptionFlags::ForceMultiValueSelection })
.importance(3)
.finish();
auto JoystickOption2 = options::OptionBuilder<Joystick*>("Input.Joystick2",
std::pair<const char*, int>{"Joystick 2", 1709},
std::pair<const char*, int>{"The current joystick 2", 1710})
.category("Input")
.deserializer(joystick_deserialize)
.serializer(joystick_serializer)
.display(joystick_display)
.enumerator(joystick_enumerator)
.level(options::ExpertLevel::Beginner)
.default_val(nullptr)
.flags({ options::OptionFlags::ForceMultiValueSelection })
.importance(3)
.finish();
auto JoystickOption2 = options::OptionBuilder<Joystick*>("Input.Joystick2", "Joystick2", "The current joystick 2.")
.category("Input")
.deserializer(joystick_deserialize)
.serializer(joystick_serializer)
.display(joystick_display)
.enumerator(joystick_enumerator)
.level(options::ExpertLevel::Beginner)
.default_val(nullptr)
.flags({ options::OptionFlags::ForceMultiValueSelection })
.importance(3)
.finish();
auto JoystickOption3 = options::OptionBuilder<Joystick*>("Input.Joystick3",
std::pair<const char*, int>{"Joystick 3", 1711},
std::pair<const char*, int>{"The current joystick 3", 1712})
.category("Input")
.deserializer(joystick_deserialize)
.serializer(joystick_serializer)
.display(joystick_display)
.enumerator(joystick_enumerator)
.level(options::ExpertLevel::Beginner)
.default_val(nullptr)
.flags({ options::OptionFlags::ForceMultiValueSelection })
.importance(3)
.finish();
auto JoystickOption3 = options::OptionBuilder<Joystick*>("Input.Joystick3", "Joystick3", "The current joystick 3.")
.category("Input")
.deserializer(joystick_deserialize)
.serializer(joystick_serializer)
.display(joystick_display)
.enumerator(joystick_enumerator)
.level(options::ExpertLevel::Beginner)
.default_val(nullptr)
.flags({ options::OptionFlags::ForceMultiValueSelection })
.importance(3)
.finish();
HatPosition convertSDLHat(int val)
{
+19 -22
View File
@@ -46,30 +46,27 @@ static haptic_effect_t pDeathroll1;
static haptic_effect_t pDeathroll2;
static haptic_effect_t pExplode;
static auto ForceFeedbackOption = options::OptionBuilder<bool>("Input.ForceFeedback",
std::pair<const char*, int>{"Force Feedback", 1728},
std::pair<const char*, int>{"Enable or disable force feedback", 1729})
.category("Input")
.level(options::ExpertLevel::Beginner)
.default_val(false)
.finish();
static auto ForceFeedbackOption =
options::OptionBuilder<bool>("Input.ForceFeedback", "Force Feedback", "Enable or disable force feedback.")
.category("Input")
.level(options::ExpertLevel::Beginner)
.default_val(false)
.finish();
static auto HitEffectOption = options::OptionBuilder<bool>("Input.HitEffect",
std::pair<const char*, int>{"Directional Hit", 1730},
std::pair<const char*, int>{"Enable or disable the directional hit effect", 1731})
.category("Input")
.level(options::ExpertLevel::Beginner)
.default_val(false)
.finish();
static auto HitEffectOption =
options::OptionBuilder<bool>("Input.HitEffect", "Directional Hit", "Enable or disable the directional hit effect.")
.category("Input")
.level(options::ExpertLevel::Beginner)
.default_val(false)
.finish();
static auto ForceFeedbackStrength = options::OptionBuilder<float>("Input.FFStrength",
std::pair<const char*, int>{"Force Feedback Strength", 1756},
std::pair<const char*, int>{"The realtive strength of Force Feedback effects", 1757})
.category("Input")
.level(options::ExpertLevel::Beginner)
.range(0, 100)
.default_val(100)
.finish();
static auto ForceFeedbackStrength = options::OptionBuilder<float>("Input.FFStrength", "Force Feedback Strength",
"The relative strength of Force Feedback effects.")
.category("Input")
.level(options::ExpertLevel::Beginner)
.range(0, 100)
.default_val(100)
.finish();
static int joy_ff_create_effects();
static int joy_ff_has_valid_effects();
+11 -20
View File
@@ -166,8 +166,6 @@ void factor_table::resize(size_t size)
}
}
// Cyborg -- You may see a linter or coverity complain about this function, since it basically discards a lot of the result of the float division.
// But using modulo division instead is actually about 60% slower based on some quick testing I did, and it gives the same results.
bool factor_table::isNaturalNumberFactor(size_t factor, size_t n)
{
return ((float)n / (float)factor) == n / factor;
@@ -643,7 +641,7 @@ extern int Framerate_delay;
extern vec3d Eye_position;
extern matrix Eye_matrix;
extern void g3_set_view_matrix(const vec3d *view_pos, const matrix *view_matrix, fov_t zoom);
extern void g3_set_view_matrix(const vec3d *view_pos, const matrix *view_matrix, float zoom);
extern int Show_cpu;
@@ -875,17 +873,13 @@ void process_debug_keys(int k)
do_subobj_hit_stuff(objp, Player_obj, &g_subobj_pos, Player_ai->targeted_subsys->system_info->subobj_num, (float) -Player_ai->targeted_subsys->system_info->type, NULL); //100.0f);
if ( Player_ai->targeted_subsys->system_info->type == SUBSYSTEM_ENGINE ) {
if ( sp->subsys_info[SUBSYSTEM_ENGINE].aggregate_current_hits <= 0.0f ) {
mission_log_add_entry(LOG_SHIP_DISABLED, sp->ship_name, NULL );
sp->flags.set(Ship::Ship_Flags::Disabled); // add the disabled flag
}
if ( sp->subsys_info[SUBSYSTEM_ENGINE].aggregate_current_hits <= 0.0f ) {
mission_log_add_entry(LOG_SHIP_DISABLED, sp->ship_name, NULL );
sp->flags.set(Ship::Ship_Flags::Disabled); // add the disabled flag
}
if ( Player_ai->targeted_subsys->system_info->type == SUBSYSTEM_TURRET ) {
if ( sp->subsys_info[SUBSYSTEM_TURRET].aggregate_current_hits <= 0.0f ) {
mission_log_add_entry(LOG_SHIP_DISARMED, sp->ship_name, NULL );
}
if ( sp->subsys_info[SUBSYSTEM_TURRET].aggregate_current_hits <= 0.0f ) {
mission_log_add_entry(LOG_SHIP_DISARMED, sp->ship_name, NULL );
}
}
}
@@ -1326,7 +1320,7 @@ void process_debug_keys(int k)
break;
}
cam->set_fov(cam->get_fov() + 0.1f);
HUD_sourced_printf(HUD_SOURCE_HIDDEN, "Camera fov raised to %0.2f" , g3_get_hfov(cam->get_fov()));
HUD_sourced_printf(HUD_SOURCE_HIDDEN, "Camera fov raised to %0.2f" , cam->get_fov());
}
break;
@@ -1340,7 +1334,7 @@ void process_debug_keys(int k)
break;
}
cam->set_fov(cam->get_fov() - 0.1f);
HUD_sourced_printf(HUD_SOURCE_HIDDEN, "Camera fov lowered to %0.2f" , g3_get_hfov(cam->get_fov()));
HUD_sourced_printf(HUD_SOURCE_HIDDEN, "Camera fov lowered to %0.2f" , cam->get_fov());
}
break;
case KEY_DEBUGGED + KEY_Z:
@@ -1517,8 +1511,7 @@ void game_do_end_mission_popup()
game_stop_time();
game_stop_looped_sounds();
audiostream_pause_all();
weapon_pause_sounds();
message_pause_all();
snd_stop_all();
pf_flags = PF_BODY_BIG | PF_USE_AFFIRMATIVE_ICON | PF_USE_NEGATIVE_ICON;
choice = popup(pf_flags, 3, POPUP_NO, XSTR( "&Yes, Quit", 28), XSTR( "Yes, &Restart", 29), XSTR( "Do you really want to end the mission?", 30));
@@ -1539,8 +1532,6 @@ void game_do_end_mission_popup()
game_start_subspace_ambient_sound();
}
audiostream_unpause_all();
weapon_unpause_sounds();
message_resume_all();
break;
}
@@ -1840,7 +1831,7 @@ int button_function_critical(int n, net_player *p = NULL)
}
hud_gauge_popup_start(HUD_WEAPONS_GAUGE);
if (ship_select_next_primary(objp, CycleDirection::NEXT)) {
if (ship_select_next_primary(objp, CYCLE_PRIMARY_NEXT)) {
ship* shipp = &Ships[objp->instance];
if ( timestamp_elapsed(shipp->weapons.next_primary_fire_stamp[shipp->weapons.current_primary_bank]) ) {
shipp->weapons.next_primary_fire_stamp[shipp->weapons.current_primary_bank] = timestamp(BANK_SWITCH_DELAY); // 1/4 second delay until can fire
@@ -1861,7 +1852,7 @@ int button_function_critical(int n, net_player *p = NULL)
}
hud_gauge_popup_start(HUD_WEAPONS_GAUGE);
if (ship_select_next_primary(objp, CycleDirection::PREV)) {
if (ship_select_next_primary(objp, CYCLE_PRIMARY_PREV)) {
ship* shipp = &Ships[objp->instance];
if ( timestamp_elapsed(shipp->weapons.next_primary_fire_stamp[shipp->weapons.current_primary_bank]) ) {
shipp->weapons.next_primary_fire_stamp[shipp->weapons.current_primary_bank] = timestamp(BANK_SWITCH_DELAY); // 1/4 second delay until can fire
+18 -21
View File
@@ -56,31 +56,28 @@ int Mouse_dz = 0;
int Mouse_sensitivity = 4;
static auto MouseSensitivityOption __UNUSED = options::OptionBuilder<int>("Input.MouseSensitivity",
std::pair<const char*, int>{"Sensitivity", 1374},
std::pair<const char*, int>{"The sensitivity of the mouse input", 1747})
.category("Input")
.range(0, 9)
.level(options::ExpertLevel::Beginner)
.default_val(4)
.bind_to(&Mouse_sensitivity)
.importance(0)
.finish();
static auto MouseSensitivityOption __UNUSED =
options::OptionBuilder<int>("Input.MouseSensitivity", "Sensitivity", "The sentitivity of the mouse input.")
.category("Input")
.range(0, 9)
.level(options::ExpertLevel::Beginner)
.default_val(4)
.bind_to(&Mouse_sensitivity)
.importance(0)
.finish();
bool Use_mouse_to_fly = false;
static SCP_string mouse_mode_display(bool mode) { return mode ? XSTR("Joy-0", 1699) : XSTR("Mouse", 1774); }
static SCP_string mouse_mode_display(bool mode) { return mode ? "Joy-0" : "Mouse"; }
static auto UseMouseOption __UNUSED = options::OptionBuilder<bool>("Input.UseMouse",
std::pair<const char*, int>{"Mouse", 1376},
std::pair<const char*, int>{"Whether or not to use the mouse for flying", 1765})
.category("Input")
.display(mouse_mode_display)
.level(options::ExpertLevel::Beginner)
.default_val(false)
.bind_to(&Use_mouse_to_fly)
.importance(1)
.finish();
static auto UseMouseOption __UNUSED = options::OptionBuilder<bool>("Input.UseMouse", "Mouse", "Use the mouse for flying")
.category("Input")
.display(mouse_mode_display)
.level(options::ExpertLevel::Beginner)
.default_val(false)
.bind_to(&Use_mouse_to_fly)
.importance(1)
.finish();
const std::shared_ptr<scripting::Hook<>> OnMouseWheelHook = scripting::Hook<>::Factory(
"On Mouse Wheel", "Called when the mouse wheel is moved in any direction.",
-24
View File
@@ -20,7 +20,6 @@
#include "math/vecmat.h"
#include "model/modelrender.h"
#include "render/3d.h"
#include "options/Option.h"
SCP_vector<light> Lights;
@@ -101,29 +100,6 @@ DCF(light,"Changes lighting parameters")
}
}
// used by In-Game Options menu
static bool DeferredLightingEnabled = true;
static auto DeferredLightingOption = options::OptionBuilder<bool>("Graphics.DeferredLighting",
std::pair<const char*, int>{"Deferred Lighting", 1782},
std::pair<const char*, int>{"Enables or disables deferred lighting", 1783})
.category("Graphics")
.default_val(true)
.level(options::ExpertLevel::Advanced)
.bind_to_once(&DeferredLightingEnabled)
.importance(60)
.finish();
bool light_deferred_enabled()
{
if (Using_in_game_options) {
return DeferredLightingOption->getValue();
} else {
return !Cmdline_no_deferred_lighting;
}
}
void light_reset()
{
Static_light.clear();
-2
View File
@@ -114,6 +114,4 @@ extern int light_get_global_count();
extern int light_get_global_dir(vec3d *pos, int n);
bool light_compare_by_type(const light &a, const light &b);
bool light_deferred_enabled();
#endif
+2 -35
View File
@@ -20,7 +20,6 @@
#include "playerman/player.h"
#include "mod_table/mod_table.h"
#include <tl/optional.hpp>
// ------------------------------------------------------------------------------------------------------------
// LOCALIZE DEFINES/VARS
@@ -63,7 +62,7 @@ bool *Lcl_unexpected_tstring_check = nullptr;
// NOTE: with map storage of XSTR strings, the indexes no longer need to be contiguous,
// but internal strings should still increment XSTR_SIZE to avoid collisions.
// retail XSTR_SIZE = 1570
// #define XSTR_SIZE 1784 // This is the next available ID
// #define XSTR_SIZE 1675
// struct to allow for strings.tbl-determined x offset
@@ -482,35 +481,6 @@ void parse_tstringstbl(const char *filename)
parse_stringstbl_common(filename, true);
}
struct xstr_delayed_order {
SCP_string& toFill;
const char* name;
int xstr;
};
static void lcl_delayed_xstr_internal(tl::optional<xstr_delayed_order> to_init) {
static SCP_vector<xstr_delayed_order> delayed_init;
if (to_init) {
if (Xstr_inited)
to_init->toFill = XSTR(to_init->name, to_init->xstr);
else
delayed_init.emplace_back(std::move(*to_init));
}
else {
Assertion(Xstr_inited, "Tried to resolve delayed XSTR before XSTR init!");
for (const auto& delayed : delayed_init)
delayed.toFill = XSTR(delayed.name, delayed.xstr);
delayed_init.clear();
}
}
void lcl_delayed_xstr(SCP_string& str, const char* name, int xstr) {
lcl_delayed_xstr_internal(xstr_delayed_order{ str, name, xstr });
}
// initialize the xstr table
void lcl_xstr_init()
{
@@ -579,8 +549,6 @@ void lcl_xstr_init()
Xstr_inited = true;
lcl_delayed_xstr_internal(tl::nullopt);
}
@@ -1215,7 +1183,6 @@ const char *XSTR(const char *str, int index, bool force_lookup)
{
if(!Xstr_inited)
{
//If you're here then you should use lcl_delayed_xstr instead!
Int3();
return str;
}
@@ -1768,4 +1735,4 @@ void lcl_translate_medal_name_pl(char *name)
} else if (!strcmp(name, "SOC Unit Crest")) {
strcpy(name, "Tarcza S\xB3u\xBF\x62 Specjalnych");
}
}
}
-2
View File
@@ -135,6 +135,4 @@ void lcl_translate_targetbox_name_pl(char *name);
void lcl_translate_medal_name_gr(char *name);
void lcl_translate_medal_name_pl(char *name);
void lcl_delayed_xstr(SCP_string& str, const char* name, int xstr);
#endif // defined __FREESPACE2_LOCALIZATION_UTILITIES_HEADER_FILE
+1 -1
View File
@@ -2811,7 +2811,7 @@ void vm_matrix4_get_orientation(matrix *out, const matrix4 *m)
out->a2d[2][2] = m->a2d[2][2];
}
void vm_matrix4_get_offset(vec3d *out, const matrix4 *m)
void vm_matrix4_get_offset(vec3d *out, matrix4 *m)
{
out->xyz.x = m->vec.pos.xyzw.x;
out->xyz.y = m->vec.pos.xyzw.y;
+1 -7
View File
@@ -565,7 +565,7 @@ void vm_matrix4_set_transform(matrix4 *out, matrix *m, vec3d *v);
void vm_matrix4_get_orientation(matrix *out, const matrix4 *m);
void vm_matrix4_get_offset(vec3d *out, const matrix4 *m);
void vm_matrix4_get_offset(vec3d *out, matrix4 *m);
void vm_vec_transform(vec4 *dest, const vec4 *src, const matrix4 *m);
void vm_vec_transform(vec3d *dest, const vec3d *src, const matrix4 *m, bool pos = true);
@@ -669,12 +669,6 @@ inline vec3d operator*(const vec3d& left, float right)
vm_vec_copy_scale(&out, &left, right);
return out;
}
inline vec3d operator*(float left, const vec3d& right)
{
vec3d out;
vm_vec_copy_scale(&out, &right, left);
return out;
}
inline vec3d& operator*=(vec3d& left, float right)
{
vm_vec_scale(&left, right);
-1
View File
@@ -114,7 +114,6 @@ const char *fs2_open_credit_text =
"libpcp - Copyright (c) 2013 by Cisco Systems, Inc.\n"
"This software uses libraries from the FFmpeg project under the LGPLv2.1\n"
"Dear ImGui by Omar Cornut and contributors\n"
"dkjson.lua - Copyright (C) 2010-2014 David Heiko Kolf"
"\n"
"\n"
"\n";
+1 -9
View File
@@ -2610,7 +2610,7 @@ void parse_one_main_hall(bool replace, int num_resolutions, int &hall_idx, int &
err_msg += Main_hall_region_map[i].name;
}
Error(LOCATION, "Unknown Door Region '%s'! Expected one of: %s", temp_scp_string.c_str(), err_msg.c_str());
Error(LOCATION, "Unkown Door Region '%s'! Expected one of: %s", temp_scp_string.c_str(), err_msg.c_str());
}
m->regions[idx].action = action;
@@ -2717,11 +2717,3 @@ void main_hall_unpause()
main_hall_start_ambient();
}
/**
* Toggle the help overlay
*/
void main_hall_toggle_help(bool enable)
{
help_overlay_set_state(Main_hall_overlay_id, main_hall_get_overlay_resolution_index(), (int)enable);
}
-2
View File
@@ -216,6 +216,4 @@ void main_hall_vasudan_funny();
void main_hall_pause();
void main_hall_unpause();
void main_hall_toggle_help(bool enable);
#endif
+6 -18
View File
@@ -1804,7 +1804,7 @@ void options_multi_vox_do()
}
// if the currently selected player is muted
if((Om_vox_player_select != NULL) && options_multi_vox_plist_get(Om_vox_player_select) > -1 && !Om_vox_player_flags[options_multi_vox_plist_get(Om_vox_player_select)]){
if((Om_vox_player_select != NULL) && !Om_vox_player_flags[options_multi_vox_plist_get(Om_vox_player_select)]){
Om_vox_buttons[gr_screen.res][OM_VOX_VOICE_MUTE].button.draw_forced(2);
}
@@ -1910,15 +1910,7 @@ void options_multi_vox_button_pressed(int n)
// mute/unmute button
case OM_VOX_VOICE_MUTE:
if(Om_vox_player_select != NULL){
int index = options_multi_vox_plist_get(Om_vox_player_select);
// there's already an assertion for this in options_multi_vox_plist_get, just ignore in release
if (index < 0){
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
break;
}
Om_vox_player_flags[index] = !Om_vox_player_flags[index];
Om_vox_player_flags[options_multi_vox_plist_get(Om_vox_player_select)] = !Om_vox_player_flags[options_multi_vox_plist_get(Om_vox_player_select)];
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
} else {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
@@ -2113,17 +2105,13 @@ int options_multi_vox_plist_get(net_player *pl)
for(idx=0;idx<Om_vox_num_players;idx++){
if(pl == Om_vox_players[idx]){
break;
return idx;
}
}
// Should never get a bad value here, but the places where this is called can now handle the negative return value, as it's not catastrophic.
// Still Assert to assist with bug tracking in debug.
Assertion(idx < Om_vox_num_players, "options_multi_vox_plist_get() could not find the correct net player. Please report to an SCP member!");
if (idx >= Om_vox_num_players)
return -1;
else
return idx;
// should neve get here. hmmm.
Int3();
return -1;
}
// scroll the player list down
+1 -1
View File
@@ -402,7 +402,7 @@ void player_select_do()
// Goober5000 - display a popup warning about problems in the mod
if ((Global_warning_count > 10 || Global_error_count > 0) && !Startup_warning_dialog_displayed) {
char text[512];
sprintf(text, XSTR ("Warning!\n\nThe currently active mod has generated %d warnings and/or errors during program startup. These could have been caused by anything from incorrectly formatted table files to corrupt models.\n\nWhile FreeSpace Open will attempt to compensate for these issues, it cannot guarantee a trouble-free gameplay experience.\n\nPlease contact the authors of the mod for assistance.", 1640), Global_warning_count + Global_error_count);
sprintf(text, XSTR ("Warning!\n\nThe currently active mod has generated %d warnings and/or errors during program startup. These could have been caused by anything from incorrectly formated table files to corrupt models.\n\nWhile FreeSpace Open will attempt to compensate for these issues, it cannot guarantee a trouble-free gameplay experience.\n\nPlease contact the authors of the mod for assistance.", 1640), Global_warning_count + Global_error_count);
popup(PF_TITLE_BIG | PF_TITLE_RED | PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, text);
Startup_warning_dialog_displayed = true;
}
+104 -26
View File
@@ -191,8 +191,8 @@ int Sim_room_slider_coords[GR_NUM_RESOLUTIONS][4] = {
#define READYROOM_FLAG_FROM_VOLITION (1<<0) // volition made
static struct {
int type; // see READYROOM_LINE_* defines above
const char *name;
const char *filename;
char *name;
char *filename;
int x; // X coordinate of line
int y; // Y coordinate of line
int flags; // special flags, see READYROOM_FLAG_* defines above
@@ -238,7 +238,7 @@ static UI_SLIDER2 Sim_room_slider;
typedef struct hash_node {
hash_node *next;
const char *filename;
char *filename;
} hash_node;
static hash_node *Campaign_mission_hash_table[CAMPAIGN_MISSION_HASH_SIZE];
@@ -294,7 +294,7 @@ int hash_filename(const char *filename) {
// insert filename into Campaign_mission_hash_table
//
// returns 1 if successful, 0 if could not allocate memory
int hash_insert(const char *filename) {
int hash_insert(char *filename) {
int hash_val = hash_filename(filename);
hash_node *cur_node;
@@ -403,7 +403,7 @@ void campaign_mission_hash_table_delete()
// add a line of sim_room smuck to end of list
int sim_room_line_add(int type, const char *name, const char *filename, int x, int y, int flags)
int sim_room_line_add(int type, char *name, char *filename, int x, int y, int flags)
{
if (Num_lines >= MAX_LINES)
return 0;
@@ -458,7 +458,8 @@ int sim_room_standalone_mission_filter(const char *filename)
int build_standalone_mission_list_do_frame(bool API_Access)
{
int font_height = gr_get_font_height();
SCP_string popup_str;
char filename[MAX_FILENAME_LEN];
char str[256];
bool lcl_weirdness = false;
// When no standalone missions in data directory
@@ -473,12 +474,15 @@ int build_standalone_mission_list_do_frame(bool API_Access)
if (Num_standalone_missions > 0) { // sanity check
if (strlen(Mission_filenames[Num_standalone_missions_with_info]) < MAX_FILENAME_LEN - 4) { // sanity check?
// tack on an extension
auto filename = cf_add_ext(Mission_filenames[Num_standalone_missions_with_info], FS_MISSION_FILE_EXT);
strcpy_s(filename, Mission_filenames[Num_standalone_missions_with_info]);
// update popup
sprintf(popup_str, XSTR("Single Mission\n\n%s", 989), filename);
popup_change_text(popup_str.c_str());
// update popup
memset(str, 0, 256);
sprintf(str, XSTR("Single Mission\n\n%s",989), filename);
popup_change_text(str);
// tack on an extension
strcat_s(filename, FS_MISSION_FILE_EXT);
// activate tstrings check
Lcl_unexpected_tstring_check = &lcl_weirdness;
@@ -512,7 +516,7 @@ int build_standalone_mission_list_do_frame(bool API_Access)
// determine some extra information
int flags = 0;
auto fb = game_find_builtin_mission(filename);
fs_builtin_mission *fb = game_find_builtin_mission(filename);
if((fb != NULL) && (fb->flags & FSB_FROM_VOLITION)){
flags |= READYROOM_FLAG_FROM_VOLITION;
}
@@ -541,7 +545,8 @@ int build_standalone_mission_list_do_frame(bool API_Access)
int build_campaign_mission_list_do_frame(bool API_Access)
{
int font_height = gr_get_font_height();
SCP_string popup_str;
char str[256];
char filename[MAX_FILENAME_LEN];
static int valid_missions_with_info = 0; // we use this to avoid blank entries in the mission list
// When no campaign files in data directory
@@ -551,8 +556,9 @@ int build_campaign_mission_list_do_frame(bool API_Access)
}
// change popup
sprintf(popup_str, XSTR("Campaign Mission\n\n%s", 990), Campaign.missions[Num_campaign_missions_with_info].name);
popup_change_text(popup_str.c_str());
memset(str, 0, 256);
sprintf(str, XSTR("Campaign Mission\n\n%s",990), Campaign.missions[Num_campaign_missions_with_info].name);
popup_change_text(str);
// Set global variable so we we'll have list available next time
Campaign_mission_names[Num_campaign_missions_with_info] = NULL;
@@ -563,7 +569,7 @@ int build_campaign_mission_list_do_frame(bool API_Access)
{
if (!get_mission_info(Campaign.missions[Num_campaign_missions_with_info].name))
{
auto filename = Campaign.missions[Num_campaign_missions_with_info].name;
strcpy_s(filename, Campaign.missions[Num_campaign_missions_with_info].name);
// add to list
Campaign_mission_names[Num_campaign_missions_with_info] = vm_strdup(The_mission.name);
@@ -584,7 +590,7 @@ int build_campaign_mission_list_do_frame(bool API_Access)
// determine some extra information
int flags = 0;
auto fb = game_find_builtin_mission(Campaign.missions[Num_campaign_missions_with_info].name);
fs_builtin_mission *fb = game_find_builtin_mission(Campaign.missions[Num_campaign_missions_with_info].name);
if((fb != NULL) && (fb->flags & FSB_FROM_VOLITION))
{
flags |= READYROOM_FLAG_FROM_VOLITION;
@@ -612,6 +618,7 @@ void sim_room_build_listing()
{
int i, y, max_num_entries_viewable;
int font_height = gr_get_font_height();
char full_filename[256];
Num_lines = y = 0;
list_y = Mission_list_coords[gr_screen.res][1];
@@ -630,8 +637,9 @@ void sim_room_build_listing()
if (Standalone_mission_names[i]) {
// determine some extra information
int flags = 0;
auto full_filename = cf_add_ext(Mission_filenames[i], FS_MISSION_FILE_EXT);
auto fb = game_find_builtin_mission(full_filename);
memset(full_filename, 0, 256);
strcpy_s(full_filename, cf_add_ext(Mission_filenames[i], FS_MISSION_FILE_EXT));
fs_builtin_mission *fb = game_find_builtin_mission(full_filename);
if((fb != NULL) && (fb->flags & FSB_FROM_VOLITION)){
flags |= READYROOM_FLAG_FROM_VOLITION;
}
@@ -657,8 +665,9 @@ void sim_room_build_listing()
if (Campaign_mission_names[i]) {
// determine some extra information
int flags = 0;
auto full_filename = cf_add_ext(Campaign.missions[i].name, FS_MISSION_FILE_EXT);
auto fb = game_find_builtin_mission(full_filename);
memset(full_filename, 0, 256);
strcpy_s(full_filename, cf_add_ext(Campaign.missions[i].name, FS_MISSION_FILE_EXT));
fs_builtin_mission *fb = game_find_builtin_mission(full_filename);
if((fb != NULL) && (fb->flags & FSB_FROM_VOLITION)){
flags |= READYROOM_FLAG_FROM_VOLITION;
}
@@ -828,6 +837,70 @@ int sim_room_can_resume_savegame(char * /*savegame_filename*/)
#endif
}
// Decide wether to resume a save game or not
// exit: 1 => savegame has been restored
// 0 => no restore, proceed to briefing
// -1 => don't start mission at all
int sim_room_maybe_resume_savegame()
{
// MWA -- 3/26/98 -- removed all savegame references in game
return 0;
/*
char savegame_filename[_MAX_FNAME];
int popup_rval = -1, resume_savegame = 0;
// Generate the save-game filename for this campaign
memset(savegame_filename, 0, _MAX_FNAME);
mission_campaign_savefile_generate_root(savegame_filename);
strcat_s(savegame_filename, NOX("svg"));
// Decide if we should offer choice to resume this savegame
if ( sim_room_can_resume_savegame(savegame_filename) ) {
popup_rval = popup(0, 3, XSTR("&Cancel",-1), XSTR("&Overwrite",-1), XSTR("&Resume",-1), XSTR("A save game for this mission exists.", -1));
switch ( popup_rval ) {
case 0:
case -1:
resume_savegame = -1;
break;
case 1:
resume_savegame = 0;
break;
case 2:
resume_savegame = 1;
break;
default:
Int3();
resume_savegame = -1;
break;
}
} else {
resume_savegame = 0;
}
if (resume_savegame == 1) {
if ( state_restore_all(savegame_filename) == -1 ) {
popup_rval = popup(PF_TITLE_BIG | PF_TITLE_RED, 2, POPUP_NO, POPUP_YES, XSTR("Error\nSaved misison could not be loaded.\nDo you wish to start this mission from the beginning?", -1));
if (popup_rval == 1) {
resume_savegame = 0;
} else {
resume_savegame = -1;
}
} else {
resume_savegame = 1;
}
}
// If we are resuming this savegame, then delete the file
if (resume_savegame == 1) {
cf_delete(savegame_filename);
}
return resume_savegame;
*/
}
int readyroom_continue_campaign()
{
// check for possible mission loop, need to do this before calling mission_campaign_next_mission()!
@@ -979,7 +1052,7 @@ void sim_room_init()
{
int i;
sim_room_buttons *b;
char wild_card[8];
char wild_card[256];
list_x1 = Mission_list_coords[gr_screen.res][0];
list_x2 = Campaign_list_coords[gr_screen.res][0];
@@ -1077,6 +1150,7 @@ void sim_room_init()
gr_flip();
Get_file_list_filter = sim_room_standalone_mission_filter;
memset(wild_card, 0, 256);
strcpy_s(wild_card, NOX("*"));
strcat_s(wild_card, FS_MISSION_FILE_EXT);
@@ -1165,7 +1239,7 @@ void sim_room_close()
//functionality without a complete refactor.
void api_sim_room_build_mission_list(bool API_Access)
{
char wild_card[8];
char wild_card[256];
Num_campaign_missions = 0;
Get_file_list_filter = sim_room_campaign_mission_filter;
@@ -1178,6 +1252,7 @@ void api_sim_room_build_mission_list(bool API_Access)
}
Get_file_list_filter = sim_room_standalone_mission_filter;
memset(wild_card, 0, 256);
strcpy_s(wild_card, NOX("*"));
strcat_s(wild_card, FS_MISSION_FILE_EXT);
@@ -1365,8 +1440,10 @@ void sim_room_do_frame(float /*frametime*/)
gr_printf_menu(list_x2, Mission_list_coords[gr_screen.res][1], "%s", buf);
// blit the proper icons if necessary
auto full_name = cf_add_ext(Campaign.filename,FS_CAMPAIGN_FILE_EXT);
auto fb = game_find_builtin_mission(full_name);
char full_name[CF_MAX_PATHNAME_LENGTH + 4];
memset(full_name, 0, CF_MAX_PATHNAME_LENGTH + 4);
strcpy_s(full_name, cf_add_ext(Campaign.filename,FS_CAMPAIGN_FILE_EXT));
fs_builtin_mission *fb = game_find_builtin_mission(full_name);
if(fb != NULL){
// sim_room_blit_icons(0, Mission_list_coords[gr_screen.res][1], fb, 0);
}
@@ -1528,7 +1605,8 @@ void campaign_room_build_listing()
if (Campaign_names[i] != NULL) {
// determine some extra information
int flags = 0;
auto fb = game_find_builtin_mission(Campaign_file_names[i]);
fs_builtin_mission *fb = game_find_builtin_mission(Campaign_file_names[i]);
if (fb != NULL) {
if (fb->flags & FSB_FROM_VOLITION) {
flags |= READYROOM_FLAG_FROM_VOLITION;
-5
View File
@@ -1082,7 +1082,6 @@ static void intel_info_init(intel_data* inteli)
inteli->desc = "";
inteli->anim_filename[0] = '\0';
inteli->flags = IIF_DEFAULT_VALUE;
inteli->custom_data = {};
}
void parse_intel_table(const char* filename)
@@ -1157,10 +1156,6 @@ void parse_intel_table(const char* filename)
stuff_string(intel_p->desc, F_MULTITEXT);
}
if (optional_string("$Custom data:")) {
parse_string_map(intel_p->custom_data, "$end_custom_data", "+Val:");
}
//retail table doesn't have #end so we have to check for the start of the next entry
//or for the end of the file instead. I have also Added #end compatibility here to
//bring the table in line with other tables for absent minded modders - Mjn
+1 -2
View File
@@ -15,12 +15,11 @@
#include "globalincs/globals.h"
#include "globalincs/pstypes.h"
typedef struct intel_data {
typedef struct {
char name[NAME_LENGTH];
SCP_string desc;
char anim_filename[NAME_LENGTH];
int flags;
SCP_map<SCP_string, SCP_string> custom_data;
} intel_data;
// flags by Goober5000
-1
View File
@@ -35,7 +35,6 @@ namespace Mission {
Toggle_start_chase_view, // Toggles (versus the default) whether the player starts the mission in chase view - Goober5000
Neb2_fog_color_override, // Whether to use explicit fog colors instead of checking the palette - Goober5000
Fullneb_background_bitmaps, // Show background bitmaps despite fullneb
Preload_subspace, // Preload the subspace tunnel for both the sexp and specs checkbox (for scripts) - MjnMixael
NUM_VALUES
};
+8 -9
View File
@@ -127,15 +127,14 @@ debriefing *Debriefing; // pointer to correct debriefing
bool Briefing_voice_enabled = true; // flag which turn on/off voice playback of briefings/debriefings
static auto BriefingVoiceOption __UNUSED = options::OptionBuilder<bool>("Audio.BriefingVoice",
std::pair<const char*, int>{"Briefing voice", 1368},
std::pair<const char*, int>{"Enable or disable voice playback in the briefing", 1716})
.category("Audio")
.level(options::ExpertLevel::Beginner)
.default_val(true)
.bind_to(&Briefing_voice_enabled)
.importance(4)
.finish();
static auto BriefingVoiceOption __UNUSED = options::OptionBuilder<bool>("Audio.BriefingVoice", "Briefing voice",
"Enable or disable voice playback in the briefing.")
.category("Audio")
.level(options::ExpertLevel::Beginner)
.default_val(true)
.bind_to(&Briefing_voice_enabled)
.importance(4)
.finish();
// --------------------------------------------------------------------------------------
// Module global data
Loaded 100 of 259 files, more files were not shown because too many files have changed in this diff. Show more