Compare commits

..
Author SHA1 Message Date
Fabian Woltermann 5b01036723 vm_vec_random_cone needs to be called with the smaller angle first.
This also adds a check to that function to swap the values around should that not be the case
2018-08-10 17:26:42 +02:00
Fabian Woltermann 8a2641181f Merge pull request #1816 from asarium/fix/1815
Don't reset mission file name on mission end
2018-07-28 18:47:17 +02:00
m!m 36e8c3b623 Merge pull request #1814 from TRBlount/fix/random_cone
Fix vm_vec_random_cone/sphere functions
2018-07-28 18:44:58 +02:00
TRBlount 1c2a136ef7 Fix vm_vec_random_cone/sphere functions 2018-07-28 09:11:59 -06:00
asarium 72272cb8cf Don't reset mission file name on mission end
This was needed by the restart dialog action and got removed since the
Discord changes needed to know if a mission was active or not.

I removed the code which changed the mission file name and replaced it
with some internal handling in the discord code which should now handle
mission restarts better.

This fixes #1815.
2018-07-28 16:12:26 +02:00
m!m 4062f59128 Merge pull request #1813 from asarium/fix/stupidIfTypos
Fix crash when launching FSO without a mod option
2018-07-28 09:38:29 +02:00
asarium 24ab091671 Fix crash when launching FSO without a mod option 2018-07-27 18:17:18 +02:00
Fabian Woltermann 7cd17205b5 Merge pull request #1785 from asarium/feature/soundHandleIds
Use strongly typed handles for sound handles
2018-07-27 15:04:02 +02:00
Fabian Woltermann d58bd7db69 Merge pull request #1811 from asarium/fix/1754
Properly handle invalid UTF-8 sequences in NanoVG
2018-07-26 08:22:37 +02:00
m!m ce11936e56 Merge pull request #1810 from asarium/fix/discordLinkingIssue
Fix MSVC linking issue in new Discord Code
2018-07-25 23:18:00 +02:00
asarium feda97c148 Properly handle invalid UTF-8 sequences in NanoVG
The original issue was reported by Novachen in #1754 where a significant
slowdown was encountered in the controls menu (Ship and Misc tabs). I
traced the cause of the slowdown to repeated uploads of the NanoVG font
atlas texture even though no changes were necessary.

The root cause of the issue was that NanoVG did not handle invalid UTF-8
sequences at the end of a string properly. The UTF-8 decoder returned a
success code even though no code point was decoded which lead the rest
of the code to believe that the font atlas needed to be recreated.

This fixes #1754 by properly handling that case.

This also fixed an assertion failure if NanoVG was asked to render
2D elements without any vertices.
2018-07-25 14:17:06 +02:00
asarium a0e85e7ef5 Fix MSVC linking issue in new Discord Code
The CMake file did not contain the required target_link_libraries which
made the build fail when compiling it for the FastDebug configuration.
2018-07-25 13:31:33 +02:00
m!m 6939403262 Merge pull request #1808 from plieblang/MissionInfoParsing
Improve parsing of mission info text fields
2018-07-25 09:02:24 +02:00
Fabian Woltermann 33e8703555 Merge pull request #1788 from asarium/feature/discord
Add discord Rich Presence support
2018-07-25 08:21:23 +02:00
Fabian Woltermann 8a87d20415 Merge pull request #1801 from asarium/feature/shaderCacheLocation
Add CFile API for specifying the file location
2018-07-25 08:20:16 +02:00
Fabian Woltermann b324d2892c Merge pull request #1809 from EatThePath/master
Corrected faulty lifetime randomization for weapons in weapons.cpp
2018-07-25 08:16:46 +02:00
David Gibson 54bd7e3963 Corrected faulty lifetime randomization for weapons in weapons.cpp 2018-07-24 19:38:44 -05:00
plieblang b2230f723b Undo reformatting 2018-07-24 11:59:13 -07:00
m!m f75dafde4a Merge pull request #1746 from asarium/feature/objectDisplayString
Add ship display name feature
2018-07-24 15:49:11 +02:00
m!m d70f92e782 Merge pull request #1807 from asarium/fix/luaCallbackCrash
Fix crash on game shutdown if Lua object callbacks are used
2018-07-24 09:02:59 +02:00
plieblang d7e042b38a Dumb copy/paste mistake 2018-07-23 17:52:37 -07:00
plieblang 941a0c3c8a PR feedback and make methods static 2018-07-23 17:47:42 -07:00
plieblang edc6b94f7f Namespace resolution and size_type vs int mismatch 2018-07-23 13:38:34 -07:00
plieblang 1182a485ac Strip quotes from text and improve mission notes handling 2018-07-23 12:18:07 -07:00
asarium 3cd2c40331 Clear objects on game close 2018-07-23 19:21:16 +02:00
asarium c13cb44df4 Add ship display name feature
This adds a mission file option for ships which allows specifying a
different string which should be used for displaying the name of the
ship to the user. This name will not be used in SEXPs or other ship
lookup functions so it can be freely translated and two ships can also
have the same display name.

The new feature can be used by adding $Display name: <string> after $Name
for a ship in a mission file. I think I added proper support for FRED
(and qtFRED) so that this new value is properly saved but it would be
great if someone could test that.

This implements one of the features requested in #1730.
2018-07-22 23:16:00 +02:00
m!m aede65107b Merge pull request #1805 from asarium/feature/scriptingParsingApi
Add scripting API for accessing parsing system
2018-07-22 22:15:48 +02:00
asarium 197767ce94 Fix clang-tidy warnings 2018-07-22 11:47:33 +02:00
asarium 7924c66d37 Add function for listing files from CFile
This is basically a wrapper around cf_get_file_list which returns the
results in a table.
2018-07-22 11:47:33 +02:00
asarium 3106191cea Rename Mission_text to something better
The variable is now used by a lot of other things so it makes sense to
rename it to something that better describes what it is used for.
2018-07-22 11:47:33 +02:00
asarium 8c4ec9b91c Add scripting API for accessing parsing system
This allows scripts to use the same parsing functions which are also
used by the engine for parsing tables.
2018-07-22 11:47:33 +02:00
m!m 5bfcd1d063 Merge pull request #1804 from PeterMitsis/aicode-api-updates
Unused parameter removal from aicode.cpp module
2018-07-20 14:11:40 +02:00
Peter Mitsis 923265988c Fix warnings found by clang_tidy.sh
Signed-off-by: Peter Mitsis <[email protected]>
2018-07-19 19:24:23 -04:00
Peter Mitsis c485ed8199 aicode: Update maybe_cheat_fire_synaptic() API
Removes an unused parameter from the routine's API.

Signed-off-by: Peter Mitsis <[email protected]>
2018-07-19 13:09:35 -04:00
m!m 4353d4d47f Merge pull request #1803 from plieblang/MissionNoteSemicolonCrash
Write newline after mission notes
2018-07-19 17:06:11 +02:00
plieblang da65a66932 Semicolon fix for qtFRED as well 2018-07-18 13:57:29 -07:00
plieblang 7df8313b8b Force newline after mission notes 2018-07-18 13:33:27 -07:00
Peter Mitsis 187affe004 aicode: Update cheat_fire_synaptic() API
1. Removes unused parameter
2. Applies 'static' keyword to the routine.

Together, these two changes should help the compiler generate
more efficient code.

Signed-off-by: Peter Mitsis <[email protected]>
2018-07-17 16:24:17 -04:00
Peter Mitsis f29cc2ef86 aicode: Update ai_ship_destroy() API
Removes unused parameters from the routine.

Signed-off-by: Peter Mitsis <[email protected]>
2018-07-17 16:24:17 -04:00
Peter Mitsis 97e15ca135 aicode: Update ai_ship_hit() API
Removes two unused parameters from ai_ship_hit(). Instances where this
routine are called are also updated.

This should result in slightly more efficient code.

Signed-off-by: Peter Mitsis <[email protected]>
2018-07-17 16:24:17 -04:00
Peter Mitsis 868418c100 aicode: Update big_ship_collide_recover_start() API
Removes the unused parameter from the routine. This has a small
ripple effect such that it results in an unused parameter in one
of the routines from which it is called.

Signed-off-by: Peter Mitsis <[email protected]>
2018-07-17 16:24:17 -04:00
Peter Mitsis e413b10ce1 aicode: Update ai_control_info_check() API
1. Removes unused parameter
2. Applies the 'static' keyword to the routine.

Together, these two changes should help the compiler generate slightly
more efficient code.

Signed-off-by: Peter Mitsis <[email protected]>
2018-07-17 16:24:17 -04:00
Peter Mitsis bdd740eabd aicode: Update ai_find_shockwave_ship() API
1. Removes unused parameter
2. Applies 'static' keyword to the routine

Together, these two changes should help the compiler generate slightly
more efficient code.

Signed-off-by: Peter Mitsis <[email protected]>
2018-07-17 16:24:17 -04:00
Peter Mitsis d24e3c9295 aicode: Update ai_find_shockwave_weapon() API
1. Removes an unused parameter.
2. Applies the 'static' keyword to the routine.
3. Applies the 'const' keyword to the remaining parameter.

Together these changes should help the compiler generate slightly more
efficient code.

Signed-off-by: Peter Mitsis <[email protected]>
2018-07-17 16:24:13 -04:00
Peter Mitsis 13be144495 aicode: Update ai_preprocess_ignore_objnum() API
Applies the 'static' keyword to the routine as it is only used in the
module in which it is defined.

Removes an unused parameter.

Together, these two changes should help the compiler generate slightly
more efficient code.

Signed-off-by: Peter Mitsis <[email protected]>
2018-07-17 15:27:35 -04:00
Peter Mitsis 8857c4561a aicode: Update gwlr_object_1() API
Adds the 'static' keyword and removes unused parameters.

Signed-off-by: Peter Mitsis <[email protected]>
2018-07-17 15:25:22 -04:00
Peter Mitsis af4a2555db aicode: Update get_behind_ship() API
Adds the 'static' keyword to the routine as it is only used in the
module in which it is defined.

Removes its  unused parameter (and updates location where it is called).

Signed-off-by: Peter Mitsis <[email protected]>
2018-07-17 15:25:22 -04:00
Peter Mitsis ae2c4ef098 aicode: Update ai_chase_eb() API
Removes the unused parameter from the routine and adds the 'static'
keyword to the routine as it is only used in the module in which it
is defined.

Signed-off-by: Peter Mitsis <[email protected]>
2018-07-17 15:25:22 -04:00
Peter Mitsis 6e509868d2 aicode: Update ai_fire_secondary_weapon() API
Removes unused parameters from the routine.

Signed-off-by: Peter Mitsis <[email protected]>
2018-07-17 15:25:22 -04:00
Peter Mitsis d0bc3cf91d aicode: Update ai_select_primary_weapon_OLD() API
This routine is only used in the module in which it is defined, so the
'static' keyword has been applied to it.

One of its three parameters was unused, so it has been removed.

Finally, the 'const' keyword has been applied to appropriate arguments.

These changes should help the compiler generate slightly more efficient
code.

Signed-off-by: Peter Mitsis <[email protected]>
2018-07-17 15:25:22 -04:00
Peter Mitsis 10079c88cd aicode: Remove fds_aux()
The routine fds_aux() is not used anywhere.

Signed-off-by: Peter Mitsis <[email protected]>
2018-07-17 15:25:22 -04:00
Peter Mitsis 3aacb6cb42 aicode: Update ai_turn_towards_vector() API
The routine ai_turn_towards_vector() had an unused parameter (frametime)
and it has been removed.

Each of the instances where this routine is called have also been updated
to reflect the parameter removal. As this resulted in the routine
swarm_update_direction() suddenly having an unused parameter, that routine
and the places where it is called have also been updated (remove
unused parameter).

Signed-off-by: Peter Mitsis <[email protected]>
2018-07-17 15:25:22 -04:00
asarium b434776d53 Fix clang-tidy issues 2018-07-17 17:20:55 +02:00
asarium 20925f23cc Use new cfile location feature for pilot files
This was previously hard-coded but it is now possible to solve this
using the new location API.
2018-07-17 17:20:55 +02:00
asarium 64a9e3d03a Use location API for specifying shader cache location
The files are now exclusively stored in the top level user directory to
make the shader cache not dependent on the current mod. This also adds
some code which removes all old shader cache files which may be stored
in the old (per-mod) location.
2018-07-17 17:20:55 +02:00
asarium fe01372f46 Add CFile API for specifying location
This adds the capability for specifying a bit field for certain API
functions which will limit where they search for files.
2018-07-17 17:20:55 +02:00
asarium 7134e22322 Convert cfile find_location functions to return structs
The amount of output parameters is becoming quite large which makes it
harder to add new input parameters. For that reason I converted the
existing output parameters to a struct which cleans up the function
signature a lot.
2018-07-17 17:20:55 +02:00
m!m fac618c7f0 Merge pull request #1800 from PeterMitsis/remove-unused-parameters
Remove unused parameters
2018-07-16 22:33:22 +02:00
Fabian Woltermann b333104f45 Merge pull request #1799 from NovachenFS2/strings-translation-fix
Strings.tbl translation adjustments AddOn
2018-07-16 22:28:25 +02:00
Jenna Trassa c0401c24e5 Ballistic Weapon Energy Gauge 2018-07-16 10:46:02 +02:00
asarium 2ded9aa35d Format changes with clang-format 2018-07-16 10:21:52 +02:00
asarium ad54f588bb Use strongly typed handles for sound handles
This is similar to the other changes I already posted. Here the sound
instance handles are converted to their own handle type which will make
it easier to use the sound API.
2018-07-16 10:21:52 +02:00
Peter Mitsis a64ebca805 aibig: Update ai_big_maybe_enter_strafe_mode() API
Removes the unused parameter from ai_big_maybe_enter_strafe_mode().
Each place where this routine is called has been corrected to reflect
the updated API.

The 'const' keyword has been applied to remaining parameters as
necessary.

Signed-off-by: Peter Mitsis <[email protected]>
2018-07-15 22:27:43 -04:00
Peter Mitsis 69781cec25 aibig: Update ai_big_strafe_maybe_attack_turret() API
Adds the 'const' keyword to the parameters in the routine
ai_big_strafe_maybe_attack_turret() as they are unchanged
by the routine.

Signed-off-by: Peter Mitsis <[email protected]>
2018-07-15 22:19:56 -04:00
Peter Mitsis 137457e570 aibig: Update ai_big_strafe_maybe_retreat() API
The routine ai_big_strafe_maybe_retreat() is only used in the module in
which it is defined. Consequently it now sports the 'static' keyword, and
no longer uses the 'extern' keyword in its forward declaration (which has
been moved to be colocated with other forward declarations).

Secondly, since it was only using one of its two parameters, the unused
parameter has been removed.

Thirdly, since its only remaining parameter is not modified by the routine,
the 'const' keyword has been applied to it.

Signed-off-by: Peter Mitsis <[email protected]>
2018-07-15 22:02:35 -04:00
Peter Mitsis b7f3ba3660 aibig: Remove routine ai_big_ship()
The routine ai_big_ship() is empty, and appears to have been since it
was initially added many years ago. Removing it helps eliminate some
unused code.

Signed-off-by: Peter Mitsis <[email protected]>
2018-07-15 21:44:49 -04:00
Peter Mitsis bf6cfe61d7 aibig: Update ai_big_maybe_fire_weapons() API
The routine ai_big_maybe_fire_weapons() is only used in the file in
which it is defined and is thus a good candidate for being declared
'static'.

Furthermore, as it was only using two of the five parameters, the
three unused parameters have been removed and all instances where the
routine is called have been updated.

Signed-off-by: Peter Mitsis <[email protected]>
2018-07-15 21:44:08 -04:00
m!m 990838051a Merge pull request #1137 from asarium/lua/defaultScripts2
Add a lua loader that uses the CFile system
2018-07-15 22:57:40 +02:00
m!m 597104c479 Merge pull request #1798 from asarium/fix/debrisObjectsAssert
Convert debris object count Assert to Error
2018-07-15 22:57:25 +02:00
asarium 2ee5d21a10 Add discord Rich Presence support
This uses the Discord Rich Presence API for improving the integration of
FSO into Discord. At the moment this includes state notifications for
being in the main hall, the command and mission briefing and in-mission.
When in-mission it also includes the elapsed time of the mission with
support for time compression.

The details part of the notification includes the campaign name and
mission name if possible.
2018-07-15 19:37:24 +02:00
asarium 8c1d3492eb Convert debris object count Assert to Error
This will make the error message clearer instead of just showing a
cryptic Assert message. This cannot be handled by a simple warning since
capping num_debris_objects to MAX_DEBRIS_OBJECTS would then cause issues
when reading the rest of the header.
2018-07-15 18:34:44 +02:00
asarium ba5fcb971a Format changes with clang-format 2018-07-15 18:10:40 +02:00
asarium 5359b12b4f Only run valgrind on debug builds
In release builds there are a lot of false-positives probably due to the
optimizations of the compiler.
2018-07-15 18:10:40 +02:00
asarium 0fb7345617 Fix clang-tidy issues in gtest
Some of those are fixed in the newest version from their git repository
but I don't want to do a full update just for that.

modernize-make-unique was disabled since clang-tidy apparently doesn't
respect the language setting and make_unique is only present in C++14.
2018-07-15 18:10:40 +02:00
asarium a34ca578ba Add a lua loader that uses the CFile system
This allows to use the built-in lua "require" function with our file
system. This will help organize complicated scripts and it will also
allow to use libraries which were designed for this system.

To enable this change, this includes a new mechanism which allows to
load scripts from the default file system so that the files don't need
to be included in every mod. The default files can be overridden by a
mod if a special mod-table option has been set, similar to how external
shaders are handled right now.
2018-07-15 18:10:40 +02:00
m!m 7f03ac31ae Merge pull request #1797 from asarium/fix/particleEffectHandles
Use type-safe handles for particle effects
2018-07-15 16:37:31 +02:00
Fabian Woltermann 25b396f6a0 Merge pull request #1795 from NovachenFS2/strings-translation
Strings.tbl translation adjustments
2018-07-15 15:35:21 +02:00
asarium c6e2f94d0b Use type-safe handles for particle effects
Nightmare discovered an off-by-one error when checking the validity of a
particle effect handle. Since the new ID system makes that much easier
and less error-prone I decided to go ahead and convert all handles to
an ID typedef which also fixes the reported bug.
2018-07-15 14:50:32 +02:00
Jenna Trassa 9de8d45f19 Review changes for barracks.cpp 2018-07-15 09:25:17 +02:00
m!m 7f5168e9d6 Merge pull request #1796 from asarium/fix/movieBufferOffset
Use byte offset into immediate buffer for movie rendering
2018-07-14 23:47:34 +02:00
Jenna Trassa 490c5d8357 Review Changes in the hud.cpp 2018-07-14 22:28:18 +02:00
Fabian Woltermann 011ca4bb85 Merge pull request #1772 from asarium/build/betterSourceGroupFunction
CMake: Unify how source files are added to CMake
2018-07-14 21:50:00 +02:00
Fabian Woltermann a4f499ce8c Merge pull request #1789 from asarium/fix/shipCleanupMode
Fix assert in ship_cleanup
2018-07-14 21:48:47 +02:00
asarium 5578588894 Use byte offset into immediate buffer for movie rendering
This was causing issues when using the new scripting API in JAD where
there were a lot of 2D operations which filled up the immediate mode
buffer. The reason was that GL_ARB_vertex_attrib_binding the relative
offset is limited and the movie code adds the immediate buffer offset to
the vertex layout which then hit the offset limit set by OpenGL.

This fixes that by using the normal byte offset method which is already
used by the render_primitives functions.
2018-07-14 20:57:29 +02:00
Jenna Trassa dbee42bdec strings.tbl translation adjustments
Previously untranslateable strings can now translated, because they got an unique ID in the strings.tbl.
2018-07-14 14:43:05 +02:00
Jenna Trassa 783e4b5ab2 strings.tbl translation adjustments
Another duplicate that now uses a unique ID.
2018-07-14 14:39:24 +02:00
Jenna Trassa cea27244dc strings.tbl translation adjustments
A duplicate string that had an unique ID even there was an ID for this string. This one uses the initial ID for this string.
2018-07-14 14:36:03 +02:00
Jenna Trassa 09084395a5 strings.tbl translation adjustments
This string, that is used for the Docking precedure of the Support ship was untranslateable before. Now there is a given ID for the strings.tbl
2018-07-14 14:34:26 +02:00
Jenna Trassa 886b14e595 strings.tbl translation adjustments
A previously untranslateable string got an unique ID, that is translateable through the strings.tbl
2018-07-14 14:32:10 +02:00
Jenna Trassa 2fca5fd965 strings.tbl translation adjustments
The strings that got no ID got one. Aswell the duplicate string uses the id that is already predefined.
2018-07-14 14:30:24 +02:00
Jenna Trassa 69cb4f0136 strings.tbl translation adjustments
The string is getting an ID from the strings.tbl that is translateable.
2018-07-14 14:27:56 +02:00
Jenna Trassa 76d36b1c5f strings.tbl translation adjustments
A fix so that the duplicate string is using the id for the first string.
2018-07-14 14:26:48 +02:00
Jenna Trassa bf37a36e89 strings.tbl translation adjustments 2018-07-14 14:18:52 +02:00
Fabian Woltermann 6750f0a4cc Merge pull request #1794 from asarium/feature/scriptingMovies
Add scripting API for displaying movie files
2018-07-14 09:14:15 +02:00
asarium 06a21a0f9b Add scripting API for displaying movie files
This adds an API for the scripting system which allows it to load and
display movie files using the standard movie player code which includes
multi-threaded frame decoding.
2018-07-13 21:54:41 +02:00
m!m 3d653bd770 Merge pull request #1793 from asarium/feature/rgbMovies
Add support for movies with RGB(A) pixel format
2018-07-13 21:50:12 +02:00
asarium db3d92732f Add support for movies with RGB(A) pixel format
This allows to directly display RGB(A) movies without transcoding them
to YUV first. This allows the movie player to support APNG files (which
are supported natively by FFmpeg) with an alpha channel and without
converting them to YUV first.
2018-07-13 19:28:53 +02:00
MageKing17 4fbc0d02fa Merge pull request #1792 from fjelliott/shockwaves-check-huge-supercap-flags
Shockwaves caused by weapons respect big ship flags while calculating damage
2018-07-12 20:25:40 -07:00
Frans Elliott c6f75e7d14 Moved SUPERCAP_DAMAGE_SCALE macro from weapons.cpp to weapon.h so it can be used in shiphit.cpp. 2018-07-12 19:56:44 -05:00
Frans Elliott 8f4d2a27db Added a mod_table option that can enable/disable whether weapon shockwaves will respect the huge and supercap ship flags. The option is disabled by default to mirror retail behavior. 2018-07-12 19:17:31 -05:00
Frans Elliott c4bb136d80 Shockwaves caused by weapons will no longer deal lethal damage to big ships if the weapon that caused the shockwave isn't flagged as being able to deal lethal damage to that ship. For example, helios warheads now cannot kill a Sathanas, and small missiles that cause shockwaves (such as the EMP Adv.) cannot be used to kill corvettes. 2018-07-12 18:17:28 -05:00
m!m ea2656e75f Merge pull request #1790 from MageKing17/bugfix/inverted-sound-validity-check
Fix inverted validity check in snd_time_remaining().
2018-07-11 17:27:38 +02:00
MageKing17 d70672d7bc Fix inverted validity check in snd_time_remaining().
Overlooked mistake from PR #1777.
2018-07-10 17:17:38 -07:00
m!m ccc727a148 Merge pull request #1631 from Karajorma/Feature/EternalVariables
Feature/eternal variables
2018-07-10 15:15:29 +02:00
asarium 87ac2ca6a3 CMake: Unify how source files are added to CMake
This unifies how our CMake system handles adding source files to the
project so that all subprojects use the same mechanism. This also makes
it easier to add a new source folder to the code project since you don't
need to editor three places at the same time anymore.
2018-07-10 15:13:18 +02:00
Karajorma e8bd6b3929 Looks like I missed one. 2018-07-10 18:07:42 +08:00
Karajorma 4e7756d29f Fix errors in clang-tidy 2018-07-10 17:02:47 +08:00
asarium fd96dd287d Fix assert in ship_cleanup
The Assert did no cover all possible input values which caused some
isues for me. This fixes that.
2018-07-10 10:58:31 +02:00
m!m dea5fd9f30 Merge pull request #1784 from MageKing17/bugfix/target-priority-parsing
Make parse_weapon_targeting_priorities() work when weapon missing.
2018-07-10 10:46:18 +02:00
MageKing17 5ebf48b9b0 Adjustment in response to feedback/CI warning.
Warning() replaced with error_display(0), and a line changed to get rid of a clang-tidy warning about repeated types.
2018-07-09 12:07:42 -07:00
MageKing17 2dc2c0643f Merge pull request #1786 from asarium/fix/luaShipClassesIndex
Fix bounds check and string->int conversion in lua ship classes API
2018-07-09 03:14:47 -07:00
asarium e761d8a8e9 Fix bounds check and string->int conversion in lua ship classes API
The bounds check was not correct for 1-based indices. I moved the
Lua->C++ index conversion before the bounds check so that it makes
more sense.
Also, atoi isn't a reliable way for converting a string to an integer.
2018-07-09 10:32:08 +02:00
MageKing17 36b97487c6 Merge pull request #1787 from asarium/fix/invalidCampaignFile
Don't make invalid data in campaign file fatal
2018-07-08 19:20:22 -07:00
asarium 367825b1e0 Don't make invalid data in campaign file fatal
The previous code simply set a boolean flag to indicate that the data is
"invalid" which failed the campaign loading operation. With these
changes, those entries will simply be skipped. That can happen if a mod
added or removed a ship or weapon class or if two campaigns share the
same campaign name.
2018-07-08 10:29:59 +02:00
MageKing17 8f5a364345 Make parse_weapon_targeting_priorities() work when weapon missing.
Previously, if parse_weapon_targeting_priorities() couldn't find a weapon matching the name, it wouldn't parse the "+Target Priority:" line, so it would cause a parsing error when the parser failed to find "$Name:" or "#End" there. Now, the "match not found" codepath still parses it so that no mismatch occurs. Also, I reordered the function so that the parsing wasn't happening in the middle of a loop through the list of weapon types, because it made me cringe.
2018-07-07 10:48:23 -07:00
Fabian Woltermann 07a15286b4 Merge pull request #1777 from asarium/feature/soundIds
Use strongly-typed handles for sound entries
2018-07-07 14:21:44 +02:00
m!m 8e4deb0454 Merge pull request #1783 from MageKing17/bugfix/scripting-createship-safety
Lua's createShip() function now checks for a valid ship class.
2018-07-07 10:50:35 +02:00
MageKing17 aed44067df Lua's createShip() function now checks for a valid ship class.
Ideally it wouldn't be an optional argument at all, but that would break backwards-compatibility, so instead it'll just return an invalid ship handle instead of calling ship_create() with a class of -1. In addition, the Assert from ship_create() meant to guard against invalid ship_type values is now an Assertion that actually says what the invalid value of ship_type was, to make future debugging easier.
2018-07-06 19:25:31 -07:00
MageKing17 83844222c4 Merge pull request #1780 from asarium/build/prebuiltRetry
Retry prebuilt library download if it fails
2018-07-06 10:14:14 -07:00
MageKing17 ba5233e33b Merge pull request #1782 from asarium/fix/removeQuitMissionPopupHack
Remove hack for On Frame scripting hook and quit mission popup
2018-07-06 10:13:58 -07:00
MageKing17 b0bb660eb2 Merge pull request #1781 from asarium/fix/luaBackgroundDoc
Fix inconsistency in Lua background API documenation
2018-07-06 10:13:15 -07:00
MageKing17 74f258a9b3 Merge pull request #1776 from The-E/cleanup/downgrade_null_vec3d
Downgrade null vec3d warning to a log print
2018-07-06 09:58:02 -07:00
asarium d7d3b8c8e2 Remove hack for On Frame scripting hook and quit mission popup
I added this hack a long time ago and it always bothered me why I didn't
come up with a better solution. This is the better solution which uses
the popup_active function for determining if gr_flip is called within a
popup.
2018-07-06 17:03:29 +02:00
asarium 90aeb3651c Fix inconsistency in Lua background API documenation
The Lua type for matrices is called orientation instead of matrix.
2018-07-06 16:06:25 +02:00
asarium 6ee7679dd6 Retry prebuilt library download if it fails
This has been a problem for nighty and release builds which should be
fixed by this.
2018-07-06 14:48:32 +02:00
Karajorma 5baae08bdf Fix the qtFRED output to match that from regular FRED 2018-07-06 11:10:08 +08:00
MageKing17 646fb64c2f Merge pull request #1778 from asarium/feature/scriptingCallbacks
Add more generic scripting callback system
2018-07-05 15:13:02 -07:00
MageKing17 7544f321d6 Merge pull request #1771 from asarium/feature/scriptingBackgroundSupport
Add scripting API for manipulating mission backgrounds
2018-07-05 15:12:50 -07:00
Karajorma b2ff79fb38 That variable was meant to have a better name. 2018-07-05 14:06:04 +08:00
Karajorma 94c1cf65b3 Let's try this again. 2018-07-05 12:34:39 +08:00
Karajorma 0ce2908ce6 Fix the issues from the review and also fix an issue with qtFred 2018-07-05 12:20:30 +08:00
Karajorma 32fbe572e4 Merge branch 'master' of https://github.com/scp-fs2open/fs2open.github.com into Feature/EternalVariables 2018-07-05 10:31:54 +08:00
Goober5000 fb0ff8f1d0 Merge pull request #1779 from MageKing17/bugfix/lua-ship-targetsubsystem
Stop accessing Ships[] array with an objnum.
2018-07-03 21:53:09 -04:00
MageKing17 2cef1d4aa1 Stop accessing Ships[] array with an objnum.
Lua's Ship.TargetSubsystem VIRTVAR, when set, would write to an attribute of the Ships[] array based on an objnum instead of a ship instance index. Since MAX_OBJECTS is drastically higher than MAX_SHIPS, then depending on how many objects happen to be in the mission, an out-of-bounds array access can be easily generated. This commit makes sure to use the objnum instead as an index to the Objects[] array, and then retrieve the ship instance from it.
2018-07-03 16:50:36 -07:00
asarium 9dfb8faea3 Use strongly-typed handles for sound entries
This converts the previous int handles to a strongly-typed wrapper
handle which will make the API more self-documenting and will ensure
that wrongly used handles are detected at compile time.

I already found a few mistakes with these changes which I also fixed
here.
2018-07-03 10:43:10 +02:00
asarium 9651e7dca6 Add more generic scripting callback system
The current scripting hook is pretty simple and straight forward but it
makes a couple of scripting applications harder to implement than
needed.

For example, a lot of scripts need to do some work every frame
for all or some objects. The script needs to manage an internal list of
all the objects that are affected by that list which includes removing
invalid objects to conserve resources. This effectively mirrors what the
engine already does and adds unnecessary overhead.

In these changes I added a generic event system which can be used by any
part of the code for providing callbacks when a specific event occurs.
As an example, I added hooks for the pre- and post-move events to the
object class which are called before and after physics are applied to an
object.

I integrated that feature into the scripting system so now a script can
simply register a function as a callback which will be called whenever
the target event is executed.
2018-07-02 22:56:45 +02:00
Fabian Woltermann 51557d3aa3 remove extra braces 2018-07-01 09:00:36 +02:00
Fabian Woltermann 521a9b9461 Downgrade the null vec3d in vec3d normalize warning to a log print 2018-07-01 08:59:27 +02:00
m!m 130057c64a Merge pull request #1773 from asarium/fix/variableDlgInvalidName
Validate variable name when adding new variable
2018-07-01 00:45:31 +02:00
asarium f63e18957b Add scripting API for manipulating mission background
This adds a scripting API which can be used for adding and removing
background from a mission similarly to the existing SEXPs but with full
support for floating point numbers.

This was requested by Axem on Discord.
2018-06-30 23:22:07 +02:00
m!m df0be20d22 Merge pull request #1774 from The-E/cleanup/remove_path_warning
Remove "not enough points in path" warning
2018-06-30 23:20:22 +02:00
Fabian Woltermann cee37e7a2f Change this warning to a log print. This is only an issue when it's an issue, and most of the time it's not 2018-06-30 21:35:04 +02:00
asarium 90e16ffed2 Validate variable name when adding new variable
This is present in the variable modification dialog but not in the
editor which is used for adding a variable. This also adds the
validation to the editor for adding a new variable.
2018-06-30 17:42:20 +02:00
Fabian Woltermann c2a52174ba Merge pull request #1760 from asarium/build/gcc8Fixes
Fix GCC8 and FFmpeg warnings
2018-06-30 07:22:22 +02:00
Fabian Woltermann e389f7669d Merge pull request #1768 from asarium/feature/alwaysCacheBitmaps
Enable cache bitmaps by default and remove option
2018-06-30 07:20:56 +02:00
Fabian Woltermann 20681f1550 Merge pull request #1769 from TRBlount/feature/RNGSub
Add $Failure Rate:
2018-06-30 07:20:20 +02:00
TRBlount be8ea029da Resolve feedback 2018-06-29 11:19:56 -06:00
asarium 3dbcebb56e Enable cache bitmaps by default and remove option
Caching bitmaps between missions is no longer a problem for modern
system and this will improve the default load times when playing more
than one mission.
2018-06-29 12:15:21 +02:00
TRBlount 37453ae229 Add Failure Rate 2018-06-28 10:38:37 -06:00
m!m 9d907c99fe Merge pull request #1767 from MageKing17/feature/actual-weapon-range
Add AI profile flag to allow primary weapons to consider range.
2018-06-28 11:08:27 +02:00
MageKing17 490ef52b85 Add AI profile flag to allow primary weapons to consider range.
By enabling the "$Use Actual Primary Range:" profile flag (which can also be set on a per-AI-class basis), the code to determine if the AI should fire its primary weapons will not only perform its current "range based on speed of weapon and target" calculation, but it will also compute the weapon's actual range and not fire if the target is outside of it.
2018-06-27 23:11:40 -07:00
MageKing17 cf1cc5e862 Merge pull request #1765 from MageKing17/bugfix/primary-nolink-out-of-ammo
Nolink ballistic primaries no longer disallow linking when depleted.
2018-06-27 19:56:31 -07:00
m!m fc0105141b Merge pull request #1766 from asarium/fix/deferredSpecStatic
Apply spec_* values to lights in deferred pass
2018-06-27 23:27:57 +02:00
asarium 9878b48dd3 Apply spec_* values to lights in deferred pass
This was not present previously which meant that the command line values
were simply ignored by the engine. This adds the scaling back in which
should restore the lighting behavior to the previous status.
2018-06-27 19:39:14 +02:00
Fabian Woltermann af99fee8fc Merge pull request #1762 from asarium/feature/shaderCachePurge
Purge old shader cache files from file system
2018-06-27 19:13:25 +02:00
MageKing17 1cc09d5b8b Merge pull request #1764 from asarium/fix/emptyGameSoundPitch
Make sure that sound pitch range is initialized properly
2018-06-27 09:39:55 -07:00
MageKing17 d5c5cc6eb3 Nolink ballistic primaries no longer disallow linking when depleted.
When a ship with three primary banks has a Nolink weapon in one bank, the other two banks are still allowed to link; if that Nolink weapon has a limited ammo supply, however, depleting that ammo supply would disallow primary linking even though the weapon never contributed to primary linking in the first place. This commit changes the logic to only care if the depleted weapon doesn't have the Nolink flag. The ideal solution is probably to change how primary linking works so that even if the weapon doesn't have the Nolink flag the remaining primaries can still link, but that would be much more involved.
2018-06-27 09:04:14 -07:00
asarium b5bb5097b9 Make sure that sound pitch range is initialized properly
If a sound did not receive a valid sound name then the parsing function
would exit early and not set the pitch range properly. This would cause
a divide by zero if the duration of the sound was queried.

This moves the initialization of the pitch range to the start of the
parsing functions which makes sure that the range is initialized even if
the function exits early.
2018-06-27 17:23:13 +02:00
asarium f87e5bf318 Fix new warnings reported by GCC8
This also enabled GCC8 in Travis CI so that no new warnings are
introduced in other commits.
2018-06-26 11:51:08 +02:00
asarium 48667f0cbd Fix FFmpeg deprecation warnings 2018-06-24 23:07:00 +02:00
asarium 66637ef5cb Purge old shader cache files from file system
This automatically removes old shader cache files from the mod directory
when FSO is started. Those old files are likely to not be used anymore
so this will reduce the amount of disk space FSO uses for the shader
cache.
2018-06-24 22:21:33 +02:00
MageKing17 3b2b58e2cc Merge pull request #1757 from asarium/opengl/betterShaderCache
Improve handling of the shader cache
2018-06-23 21:51:07 -07:00
asarium d5282ca697 Improve handling of the shader cache
This adds an identification of the OpenGL implementation to the shader
content hash to avoid issues when using the same FSO install with
multiple graphics drivers.

Also adds support for querying the supported binary formats and
gracefully handling missing support for the format of a stored shader.
This can be useful when downgrading the version of a graphics driver
since the older version may not support the binary format yet.
2018-06-23 23:19:13 +02:00
m!m 6a099d2adc Merge pull request #1761 from asarium/fix/tgaLocking
Fix loading of TGA files with unexpected bit depths
2018-06-23 17:42:14 +02:00
Fabian Woltermann 6aa1f4899f Merge pull request #1756 from asarium/fix/modelClippingFlicker
Discard submodels by generating clipped vertices
2018-06-23 11:19:53 +02:00
asarium 4ec7d21965 Fix loading of TGA files with unexpected bit depths
The TGA loading code pretends that it does pixel conversion but doesn't
actually do that. This changes ensures that this circumstance is
communicated to the caller of bm_lock which will allow that code to
handle the case properly.

This was reported by Bomb3rman on discord.
2018-06-23 10:24:17 +02:00
MageKing17 bd5a4c4348 Merge pull request #1759 from Goober5000/cap_waypoint_speed_documentation
clarify documentation in cap-waypoint-speed
2018-06-21 18:13:00 -07:00
Goober5000 9135a01b1d clarify documentation in cap-waypoint-speed
The cap-waypoint-speed sexp only works for speeds above 0; this PR changes the documentation to clarify that.  I also tweaked an if() block in ship_return_time_to_goal because it used a >=0 comparison whereas every other comparison used >0.  (This is only for consistency, because the >0 check is used before this point would be reached.)
2018-06-21 17:04:02 -04:00
Fabian Woltermann 032579923e Merge pull request #1755 from asarium/fix/fullLogPathInLog
Write full log path and add legacy mode reason to log file
2018-06-18 08:08:36 +02:00
asarium 8c1e753991 Add log output for legacy mode reason
This will make debugging config location issues easier since the log
will state which path os_is_legacy_mode took while determining the
legacy mode status.
2018-06-17 20:51:11 +02:00
asarium 6a4c74084e Discard submodels by generating clipped vertices
This removes the clipping plane submodel removal code and replaces it
with shader code that generates vertices outside the clipping volume if
a model should not be rendered. This even improved performance since
clipping no longer needs to be active for all model rendering
operations.

This should finally fix #1579.
2018-06-17 14:27:19 +02:00
asarium 3799ce7d2f Write full log path to log file
This should make it a bit easier to determine if FSO is using the new
config file or the old one from only a log file.
2018-06-17 12:56:42 +02:00
m!m 2e213d5c97 Merge pull request #1659 from The-E/fix/1653
Delete all objects on mission end (Fix for #1653)
2018-06-17 12:14:22 +02:00
m!m 0c17177a1e Merge pull request #1713 from asarium/qtfred2_/goalsDialog
Port goal editor dialog code to qtFRED
2018-06-17 12:14:04 +02:00
m!m 93ced64c6f Merge pull request #1725 from asarium/opengl/thickModelOutlines
Render hardpoint model outlines using geometry shaders
2018-06-17 12:13:44 +02:00
m!m 4020b7c594 Merge pull request #1723 from asarium/feature/intelligentLegacyMode
Enable legacy config mode if legacy config is newer
2018-06-17 12:03:40 +02:00
m!m 13b26fd59f Merge pull request #1735 from asarium/cleanup/2dCallDereferences
Remove unnecessary function pointer dereferences in gr API
2018-06-15 12:03:14 +02:00
Goober5000 15bda8c4ac Merge pull request #1748 from asarium/build/unreachable
Add macro for marking unreachable code
2018-06-11 00:31:15 -04:00
asarium 39ab45dc7c Add macro for marking unreachable code
This can be used for mark parts of the code which should be unreachable
in normal execution. In debug mode, if such a statement is reached an
Error dialog is shown which aborts the execution. In release mode the
macro is replaced with a compiler specific expression that lets the
compiler know that this part is unreachable which allows it to optimize
the code better.
2018-06-09 17:38:17 +02:00
Fabian Woltermann 16a19783ae Merge pull request #1744 from asarium/fix/openAlGetErrorError
Fix OpenAL errors when sound is disabled
2018-06-09 08:41:15 +02:00
Goober5000 b1bc4ef44f Merge pull request #1743 from asarium/fix/1739
Respect trailing white space in tstrings.tbl strings
2018-06-08 21:14:33 -04:00
Goober5000 08e664a93a Merge pull request #1749 from asarium/feature/movieSrtSubtitles
Add support for external subtitle files
2018-06-08 20:55:42 -04:00
asarium aeee05c8dd Add support for external subtitle files
This allows to use external subtile files (currently only SRT is
configured) for providing subtitles for movie files. This should be more
universal since it also supports container formats with no support for
subtitle streams.

To use this code the srt file needs to be named
"<movie name>-<language code>.srt" where the language code is the file
extension name specified in the localization table. For english the
"-..." part can be omitted.
2018-06-08 23:29:15 +02:00
asarium 1fb3a65a90 Fix function brace wrapping in clang-format config 2018-06-08 23:28:54 +02:00
Goober5000 d53dc195ee Merge pull request #1742 from asarium/fix/1741
Enable log output for qtFRED
2018-06-08 15:21:14 -04:00
m!m 5b8880daa7 Merge pull request #1737 from Goober5000/fix_issue_1601
Change Warning about missing 640x480 interface art to a log statement
2018-06-08 19:42:41 +02:00
Goober5000 b0fc9cb31a address code review 2018-06-07 22:18:10 -04:00
m!m 323354295f Merge pull request #1751 from plieblang/PsnetTypoFix
Fix rsequence being reset twice and ssequence not being reset at all
2018-06-07 23:24:38 +02:00
plieblang b1881a700d Fix copy/paste error when closing socket 2018-06-07 12:12:54 -07:00
asarium 357cd76252 Render hardpoint model outlines using geometry shaders
This adds support for rendering models using thick lines (that means
lines wider than 1 pixel) which is required by the hardpoint HUD gauge.
This feature was present before the switch to OpenGL code and had to be
removed since the core profile does not support rendering lines wider
than 1 pixel.

This uses a geometry shader for converting all the triangles from a
model to 3 quads along the triangle lines which are as thick as set by
the model renderer. Geometry shaders are quite slow if they generate a
lot of geometry (and this generates 4 times the usual amount of geometry
in the shader) so it's probably not a very fast rendering operation but
it is only needed once per frame so it shouldn't be too bad.

I also added support for the RenderDoc API since I needed that for
debugging and it might be useful in the future. It will only become
active if RenderDoc is actually attached to the process so in most cases
the new code will do nothing.
2018-06-07 16:44:41 +02:00
Fabian Woltermann 30e70db561 Merge pull request #1750 from asarium/build/clang-format-config
Add initial clang-format config file
2018-06-07 13:40:14 +02:00
Goober5000 2c106f8c4b Merge pull request #1747 from ngld/pr/convertSexpInt3
Converted all Int3() calls in sexp.cpp into Warnings, Errors and Asserts
2018-06-06 22:59:50 -04:00
asarium 73bfb7a97e Add initial clang-format config file
This is largely based on how the existing code is formatted and is in no
way enforced by CI or anything else. This is only so that we actually
have a clang format file in the VCS since it's very useful.
2018-06-06 23:04:08 +02:00
ngld 4bead819f9 Implemented requested changes from code review 2018-06-06 03:35:13 +02:00
Goober5000 268828f092 Merge pull request #1736 from asarium/fix/translationBugs
Implement various translation features requested by Novachen
2018-06-05 21:28:14 -04:00
ngld 1614384a6a Converted all Int3() calls in sexp.cpp into Warnings, Errors and Asserts. 2018-06-06 02:20:52 +02:00
asarium 29b6af84cc Fix OpenAL errors when sound is disabled
Since there is no OpenAL context if sound is disabled there were errors
when calling alGetError on a non-existant context. This fixes that by
aborting the sound API call when the sound system wasn't initialized.
2018-06-05 12:31:37 +02:00
asarium cafee143c4 Respect trailing white space in tstrings.tbl strings
The current code drops trailing white space which can cause issues if
the translated string is used in concatenations. The retail tstrings.tbl
has some entries with white space at the end but since those strings are
not used for concatenations (or else this issue would have been found
earlier) this change should not cause issues there.

This fixes #1739.
2018-06-05 11:17:00 +02:00
asarium 6e21c8a736 Enable log output for qtFRED
This fixes #1741.
2018-06-05 11:09:31 +02:00
asarium bb56958dfc Fix various issues in the medal_stuff class
The assignment operator and copy constructors could be replaced with
their default implementations. The destrutor was also not needed since
it only executed the same action the default constructor would have
done.
2018-06-04 11:56:45 +02:00
asarium 120750ebd2 Adress code review feedback 2018-06-04 11:56:45 +02:00
asarium 3430a1c438 Disable hard-coded "cluster bomb" hack
This disables the old hack code if the weapon class has an alternate
name which may have been translated. See #1730 for more information.
2018-06-04 11:56:45 +02:00
asarium 1dc2e848cd Add option for disabling built-in translations 2018-06-04 11:56:45 +02:00
asarium 305429bf8b Add alternative display name for medals
This will only be used in the GUI which will allow translating the name
without having to change missions which use the name of the medal in
SEXPs.
2018-06-04 11:56:44 +02:00
asarium ae149b6061 Add convencience function for retrieving weapon alt name
I also fixed a few issues where the internal char array was used as a
mutable string which changed the string after it was parsed which is not
good(TM).

This also replaces all user-facing occurences of usages of name to use
the new function so that the correct, possibly translated, name is displayed
to the user.
2018-06-04 11:56:44 +02:00
Goober5000 429858d02e fix GitHub issue #1601
This turns the Warning about missing 640 interface art into a log print.  This applies to all instances of 640/1024: loading screens, cbrief and briefing backgrounds, and ship/weapon selection backgrounds.
2018-06-02 17:39:38 -04:00
asarium 1448277c29 Enable legacy config mode if legacy config is newer
There were some reports that using a newer launcher together with an
outdated launcher was causing some issues since the new launcher would
write the new config file which would cause FSO to ignore the changes of
the old launcher since the new config file already exists.

This fixes that by adding a check for when the config locations were
last modified. On Linux and Mac it checks when the old config locations
were modified last while on Windows it checks the registry to determine
if there was a change after the new config file was created.
2018-06-02 12:09:21 +02:00
Fabian Woltermann 61c533559b Removes an assert in object.cpp that was commented out and sets the number of retail stars to 0 when resetting the background in the lab 2018-06-02 11:58:01 +02:00
asarium e92121bed4 Remove unnecessary function pointer dereferences in gr API
Multiple function pointer dereferences are valid in C but do not change
the result of the operation. The graphics API had some function
definitions which used multiple pointer dereferences while the rest of
the functions did not.

This changes all occurences of the double dereferences to normal GR_CALL
declarations to keep the style in the API definitions consistent.
2018-05-31 15:07:20 +02:00
asarium f7b0f93c00 Port goal editor dialog code to qtFRED
The sexp_tree widget makes the model based dialog a bit ugly here since
it is required for some model operations even though it is a UI
component. In the future it could be split into a model component and an
UI component to allow better separation between model and UI.
2018-04-22 21:43:01 +02:00
Fabian Woltermann 758ca86f6f And fix the other one too 2018-03-16 20:10:21 +01:00
Fabian Woltermann 6406e2fbd4 fix variable conversion warning 2018-03-16 15:53:19 +01:00
Fabian Woltermann 18c2dbbde9 WIP fix for #1653.
This adds a step to the post-mission cleanup where we explicitly go through Objects and call obj_delete on everything not already deleted; this obviously needs testing.

Also a few cleanup steps in lab_init to make sure the lab isn't contaminated by leftover data from previously played missions.
2018-03-16 12:59:43 +01:00
Karajorma ef6c5d4da7 Still have some old variable names 2018-03-01 20:09:34 +08:00
Karajorma cb960a3416 Fix the saving for non-eternal variables. 2018-03-01 19:26:41 +08:00
Karajorma 194d944108 Merge branch 'master' of https://github.com/scp-fs2open/fs2open.github.com into Feature/EternalVariables 2018-03-01 18:53:03 +08:00
Karajorma 9ac97f2422 Eternal Variables initial commit - Saving non-eternals on restart or mission quit not working properly. 2018-02-24 17:52:08 +08:00
339 changed files with 25372 additions and 4508 deletions

No files matched your search

+99
View File
@@ -0,0 +1,99 @@
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: false
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: true
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 120
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IncludeCategories:
- Regex: '^(<.*\.(h|hh|hpp)>)$' # Includes of external libraries
Priority: 4
- Regex: '^(<.*>)$' # standard library includes (won't match deprecated C headers)
Priority: 5
- Regex: '^"[^/]*\.(h)"$' # Local includes
Priority: 1
- Regex: '^".*\.(h)"$' # standard engine includes
Priority: 2
- Regex: '.*' # Catch all in case something is unhandled above
Priority: 3
IncludeIsMainRegex: '$'
IndentCaseLabels: false
IndentWidth: 4
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left
ReflowComments: true
SortIncludes: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 4
UseTab: ForIndentation
...
+1
View File
@@ -3,6 +3,7 @@ Checks: "-*,\
modernize-*,\
-modernize-raw-string-literal,\
-modernize-use-using,\
-modernize-make-unique,\
performance-*,\
-performance-type-promotion-in-math-fn,\
misc-*,\
+4 -4
View File
@@ -76,14 +76,14 @@ matrix:
- *global_deps
- g++-5
- os: linux
env: CONFIGURATION="Debug" CC=gcc-7 CXX=g++-7
env: CONFIGURATION="Debug" CC=gcc-8 CXX=g++-8
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:beineri/opt-qt571-trusty'
packages:
- g++-7
- g++-8
- *global_deps
- os: linux
env: CONFIGURATION="Debug" CC=clang-4.0 CXX=clang++-4.0 CMAKE_OPTIONS="-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
@@ -115,14 +115,14 @@ matrix:
- *global_deps
- g++-5
- os: linux
env: CONFIGURATION="Release" CC=gcc-7 CXX=g++-7
env: CONFIGURATION="Release" CC=gcc-8 CXX=g++-8
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:beineri/opt-qt571-trusty'
packages:
- g++-7
- g++-8
- *global_deps
- os: linux
env: CONFIGURATION="Release" CC=clang-4.0 CXX=clang++-4.0
+7 -2
View File
@@ -7,8 +7,13 @@ cd build
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
ninja -k 20 all
valgrind --leak-check=full --error-exitcode=1 --gen-suppressions=all \
--suppressions="$TRAVIS_BUILD_DIR/ci/travis/valgrind.supp" ./bin/unittests --gtest_shuffle
if [ "$CONFIGURATION" = "Debug" ]; then
valgrind --leak-check=full --error-exitcode=1 --gen-suppressions=all \
--suppressions="$TRAVIS_BUILD_DIR/ci/travis/valgrind.supp" ./bin/unittests --gtest_shuffle
else
./bin/unittests --gtest_shuffle
fi
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
cmake --build . --config "$CONFIGURATION" | tee build.log | xcpretty
XCODE_RET=${PIPESTATUS[0]}
+9 -1
View File
@@ -25,4 +25,12 @@
fun:_dl_init
fun:dl_open_worker
fun:_dl_catch_error
}
}
{
CLang Lua unitialized value error
Memcheck:Cond
...
fun:luaH_get
fun:lua_rawget
fun:_ZN12_GLOBAL__N_117ade_index_handlerEP9lua_State
}
+11
View File
@@ -85,6 +85,17 @@ set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wreturn-type")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-deprecated -Wno-char-subscripts")
# These two warnings cause a lot of false-positives in the FSO code base
check_cxx_compiler_flag(-Wstringop-truncation SUPPORTS_STRINGOP_TRUNCATION)
if(SUPPORTS_STRINGOP_TRUNCATION)
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-stringop-truncation")
endif()
check_cxx_compiler_flag(-Wstringop-overflow SUPPORTS_STRINGOP_OVERFLOW)
if(SUPPORTS_STRINGOP_TRUNCATION)
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-stringop-overflow")
endif()
set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable -Wno-unused-but-set-variable -Wno-array-bounds -Wno-empty-body -Wno-clobbered -Wno-unused-parameter")
set(COMPILER_FLAGS_DEBUG "-O0 -g -Wshadow")
+10
View File
@@ -225,3 +225,13 @@ function(list_target_dependencies _target _out_var)
list(REMOVE_DUPLICATES out_list)
set(${_out_var} ${out_list} PARENT_SCOPE)
endfunction(list_target_dependencies)
macro(add_file_folder FOLDER_NAME)
string(MAKE_C_IDENTIFIER "${FOLDER_NAME}" VARIABLE_NAME)
set(files_${VARIABLE_NAME} ${files_${VARIABLE_NAME}} ${ARGN})
string(REPLACE "/" "\\" FIXED_FOLDER_FILE "${FOLDER_NAME}")
source_group("${FIXED_FOLDER_FILE}" FILES ${ARGN})
set(source_files ${source_files} ${ARGN})
endmacro(add_file_folder)
+3 -1
View File
@@ -3,7 +3,7 @@ INCLUDE(source_groups.cmake)
INCLUDE(voice_rec.cmake)
ADD_LIBRARY(code STATIC ${file_root} ${VOICE_REC_FILES})
ADD_LIBRARY(code STATIC ${source_files} ${VOICE_REC_FILES})
target_compile_features(code PUBLIC ${REQUIRED_CXX_FEATURES})
@@ -37,6 +37,8 @@ TARGET_LINK_LIBRARIES(code PUBLIC compiler)
target_link_libraries(code PUBLIC md5)
target_link_libraries(code PUBLIC discord-rpc)
enable_clang_tidy(code)
IF (FSO_USE_SPEECH)
+4 -4
View File
@@ -567,9 +567,9 @@ extern void ai_dock_with_object(object *docker, int docker_index, object *dockee
extern void ai_stay_still(object *still_objp, vec3d *view_pos);
extern void ai_do_default_behavior(object *obj);
extern void ai_start_waypoints(object *objp, waypoint_list *wp_list, int wp_flags);
extern void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hitpos, int shield_quadrant, vec3d *hit_normal);
extern void ai_ship_destroy(int shipnum, Ship::Exit_Flags method);
extern void ai_turn_towards_vector(vec3d *dest, object *objp, float frametime, float turn_time, vec3d *slide_vec, vec3d *rel_pos, float bank_override, int flags, vec3d *rvec = NULL, int sexp_flags = 0);
extern void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hit_normal);
extern void ai_ship_destroy(int shipnum);
extern void ai_turn_towards_vector(vec3d *dest, object *objp, float turn_time, vec3d *slide_vec, vec3d *rel_pos, float bank_override, int flags, vec3d *rvec = nullptr, int sexp_flags = 0);
extern void init_ai_object(int objnum);
extern void ai_init(void); // Call this one to parse ai.tbl.
extern void ai_level_init(void); // Call before each level to reset AI
@@ -622,7 +622,7 @@ extern float ai_path();
extern void evade_weapon();
extern int might_collide_with_ship(object *obj1, object *obj2, float dot_to_enemy, float dist_to_enemy, float duration);
extern int ai_fire_primary_weapon(object *objp); //changed to return weather it fired-Bobboau
extern int ai_fire_secondary_weapon(object *objp, int priority1 = -1, int priority2 = -1);
extern int ai_fire_secondary_weapon(object *objp);
extern float ai_get_weapon_dist(ship_weapon *swp);
extern void turn_towards_point(object *objp, vec3d *point, vec3d *slide_vec, float bank_override);
extern int ai_maybe_fire_afterburner(object *objp, ai_info *aip);
+1
View File
@@ -110,6 +110,7 @@ namespace AI {
Smart_subsystem_targeting_for_turrets,
Strict_turred_tagged_only_targeting,
Turrets_ignore_target_radius,
Use_actual_primary_range,
Use_additive_weapon_velocity,
Use_newtonian_dampening,
Use_only_single_fov_for_turrets,
+2
View File
@@ -458,6 +458,8 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$ai can slow down when attacking big ships:", AI::Profile_Flags::Ai_can_slow_down_attacking_big_ships);
set_flag(profile, "$use actual primary range:", AI::Profile_Flags::Use_actual_primary_range);
profile->bay_arrive_speed_mult = 1.0f;
profile->bay_depart_speed_mult = 1.0f;
if (optional_string("$bay arrive speed multiplier:")) {
+18 -24
View File
@@ -64,10 +64,11 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
void ai_big_avoid_ship();
int ai_big_maybe_follow_subsys_path(int do_dot_check=1);
void ai_big_strafe_position();
static int ai_big_strafe_maybe_retreat(const vec3d *target_pos);
extern int model_which_octant_distant_many( vec3d *pnt, int model_num,matrix *model_orient, vec3d * model_pos, polymodel **pm, int *octs);
extern void compute_desired_rvec(vec3d *rvec, vec3d *goal_pos, vec3d *cur_pos);
extern void big_ship_collide_recover_start(object *objp, object *big_objp, vec3d *collide_pos, vec3d *collision_normal);
extern void big_ship_collide_recover_start(object *objp, object *big_objp, vec3d *collision_normal);
// Called by ai_big_pick_attack_point.
@@ -631,7 +632,7 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
else
rvec = NULL;
ai_turn_towards_vector(enemy_pos, Pl_objp, flFrametime, sip->srotation_time, NULL, rel_pos, 0.0f, 0, rvec);
ai_turn_towards_vector(enemy_pos, Pl_objp, sip->srotation_time, nullptr, rel_pos, 0.0f, 0, rvec);
// calc range of primary weapon
weapon_travel_dist = ai_get_weapon_dist(&Ships[Pl_objp->instance].weapons);
@@ -707,14 +708,14 @@ extern float set_secondary_fire_delay(ai_info *aip, ship *shipp, weapon_info *sw
extern void ai_choose_secondary_weapon(object *objp, ai_info *aip, object *en_objp);
extern int maybe_avoid_big_ship(object *objp, object *ignore_objp, ai_info *aip, vec3d *goal_point, float delta_time);
extern void maybe_cheat_fire_synaptic(object *objp, ai_info *aip);
extern void maybe_cheat_fire_synaptic(object *objp);
// Determine if Pl_objp should fire weapons at current target, based on input parameters
//
// dist_to_enemy => distance (in m) to attack point on current target
// dot_to_enemy => dot product between fvec of Pl_objp and vector from Pl_objp to attack point
//
void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy, vec3d * /*firing_pos*/, vec3d * /*enemy_pos*/, vec3d * /*enemy_vel*/)
static void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy)
{
ai_info *aip;
ship_weapon *swp;
@@ -845,8 +846,6 @@ void ai_big_switch_to_chase_mode(ai_info *aip)
aip->submode_start_time = Missiontime;
}
extern int ai_big_strafe_maybe_retreat(float dist, vec3d *target_pos);
// Make object Pl_objp chase object En_objp, which is a big ship, not a small ship.
void ai_big_chase()
{
@@ -859,7 +858,7 @@ void ai_big_chase()
Assert(aip->mode == AIM_CHASE);
maybe_cheat_fire_synaptic(Pl_objp, aip);
maybe_cheat_fire_synaptic(Pl_objp);
ai_set_positions(Pl_objp, En_objp, aip, &player_pos, &enemy_pos);
@@ -882,7 +881,7 @@ void ai_big_chase()
dot_to_enemy = vm_vec_dot(&vec_to_enemy, &Pl_objp->orient.vec.fvec);
if (aip->ai_flags[AI::AI_Flags::Target_collision]) {
if ( ai_big_strafe_maybe_retreat(dist_to_enemy, &enemy_pos) ) {
if ( ai_big_strafe_maybe_retreat(&enemy_pos) ) {
aip->mode = AIM_STRAFE;
aip->submode_parm0 = Missiontime; // use parm0 as time strafe mode entered (i.e. MODE start time)
aip->submode = AIS_STRAFE_AVOID;
@@ -1045,7 +1044,7 @@ void ai_big_chase()
if ((dist_normal_to_enemy < ATTACK_COLLIDE_AVOID_DIST + speed_dist) || (time_to_enemy < ATTACK_COLLIDE_AVOID_TIME) ) {
// get away, simulate crsh recovery (don't use avoid)
// accelerate_ship(aip, -1.0f);
big_ship_collide_recover_start(Pl_objp, En_objp, &Pl_objp->pos, NULL);
big_ship_collide_recover_start(Pl_objp, En_objp, nullptr);
// aip->submode = SM_AVOID;
// aip->submode_start_time = Missiontime;
} else if ((dist_normal_to_enemy < ATTACK_COLLIDE_SLOW_DIST) || (time_to_enemy < ATTACK_COLLIDE_SLOW_TIME) ) {
@@ -1144,7 +1143,7 @@ void ai_big_chase()
// TODO: investigate why ships fire (and aren't close to hitting ship) when following a path near
// a big ship
if (aip->mode != AIM_EVADE && aip->path_start == -1 ) {
ai_big_maybe_fire_weapons(dist_to_enemy, dot_to_enemy, &player_pos, &predicted_enemy_pos, &En_objp->phys_info.vel);
ai_big_maybe_fire_weapons(dist_to_enemy, dot_to_enemy);
} else {
if (flFrametime < 1.0f)
aip->time_enemy_in_range *= (1.0f - flFrametime);
@@ -1153,11 +1152,6 @@ void ai_big_chase()
}
}
void ai_big_ship(object * /*objp*/)
{
// do nothing
}
// all three parms are output parameters
// Enemy object is En_objp
// pos => world pos of attack point
@@ -1228,7 +1222,7 @@ void ai_big_attack_get_data(vec3d *enemy_pos, float *dist_to_enemy, float *dot_t
// check to see if Pl_objp has gotten too close to attacking point.. if so, break off by entering
// AIS_STRAFE_RETREAT
int ai_big_strafe_maybe_retreat(float /*dist*/, vec3d *target_pos)
static int ai_big_strafe_maybe_retreat(const vec3d *target_pos)
{
ai_info *aip;
aip = &Ai_info[Ships[Pl_objp->instance].ai_index];
@@ -1258,7 +1252,7 @@ int ai_big_strafe_maybe_retreat(float /*dist*/, vec3d *target_pos)
if (aip->ai_flags[AI::AI_Flags::Target_collision]) {
// use standard collision resolution
aip->ai_flags.remove(AI::AI_Flags::Target_collision);
big_ship_collide_recover_start(Pl_objp, En_objp, &Pl_objp->pos, NULL);
big_ship_collide_recover_start(Pl_objp, En_objp, nullptr);
} else {
// too close for comfort so fly to box point + 300
aip->submode = AIS_STRAFE_RETREAT1;
@@ -1298,12 +1292,12 @@ void ai_big_strafe_attack()
}
ai_big_attack_get_data(&target_pos, &target_dist, &target_dot);
if ( ai_big_strafe_maybe_retreat(target_dist, &target_pos) )
if ( ai_big_strafe_maybe_retreat(&target_pos) )
return;
if (aip->ai_flags[AI::AI_Flags::Kamikaze]) {
if (target_dist < 1200.0f) {
ai_turn_towards_vector(&target_pos, Pl_objp, flFrametime, Ship_info[Ships[Pl_objp->instance].ship_info_index].srotation_time, NULL, NULL, 0.0f, 0);
ai_turn_towards_vector(&target_pos, Pl_objp, Ship_info[Ships[Pl_objp->instance].ship_info_index].srotation_time, nullptr, nullptr, 0.0f, 0);
accelerate_ship(aip, 1.0f);
if ((target_dist < 400.0f) && ai_maybe_fire_afterburner(Pl_objp, aip)) {
afterburners_start(Pl_objp);
@@ -1347,7 +1341,7 @@ void ai_big_strafe_attack()
}
// maybe fire weapons at target
ai_big_maybe_fire_weapons(target_dist, target_dot, &Pl_objp->pos, &En_objp->pos, &En_objp->phys_info.vel);
ai_big_maybe_fire_weapons(target_dist, target_dot);
turn_towards_point(Pl_objp, &target_pos, NULL, 0.0f);
fix last_hit = Missiontime - aip->last_hit_time;
@@ -1493,7 +1487,7 @@ void ai_big_strafe_glide_attack()
vm_vec_sub2(&target_pos, &En_objp->pos);
turn_towards_point(Pl_objp, &target_pos, NULL, 0.0f);
ai_big_maybe_fire_weapons(target_dist, target_dot, &Pl_objp->pos, &En_objp->pos, &En_objp->phys_info.vel);
ai_big_maybe_fire_weapons(target_dist, target_dot);
}
// if haven't been hit in quite a while, leave strafe mode
@@ -1517,7 +1511,7 @@ void ai_big_strafe_avoid()
mode_time = Missiontime - aip->submode_start_time;
ai_big_attack_get_data(&target_pos, &target_dist, &target_dot);
if ( ai_big_strafe_maybe_retreat(target_dist, &target_pos) )
if ( ai_big_strafe_maybe_retreat(&target_pos) )
return;
if ( mode_time > fl2f(0.5)) {
@@ -1704,7 +1698,7 @@ void ai_big_strafe()
//
// Check if weapon_objnum was fired by Pl_objp's target, and whether Pl_objp's target is a big ship, if
// so, enter AIM_STRAFE
int ai_big_maybe_enter_strafe_mode(object *pl_objp, int weapon_objnum, int /*consider_target_only*/)
int ai_big_maybe_enter_strafe_mode(const object *pl_objp, int weapon_objnum)
{
ai_info *aip;
ship_info *sip;
@@ -1778,7 +1772,7 @@ int ai_big_maybe_enter_strafe_mode(object *pl_objp, int weapon_objnum, int /*co
// Consider attacking a turret, if a turret actually fired the weapon
// input: ship_objp => ship that will attack the turret
// weapon_objp =>
void ai_big_strafe_maybe_attack_turret(object *ship_objp, object *weapon_objp)
void ai_big_strafe_maybe_attack_turret(const object *ship_objp, const object *weapon_objp)
{
ai_info *aip;
object *parent_objp;
+2 -3
View File
@@ -17,14 +17,13 @@ struct ai_info;
struct vec3d;
class ship_subsys;
void ai_big_ship(object *objp);
void ai_big_chase();
void ai_big_subsys_path_cleanup(ai_info *aip);
// strafe functions
void ai_big_strafe();
int ai_big_maybe_enter_strafe_mode(object *objp, int weapon_objnum, int consider_target_only=0);
void ai_big_strafe_maybe_attack_turret(object *ship_objp, object *weapon_objp);
int ai_big_maybe_enter_strafe_mode(const object *objp, int weapon_objnum);
void ai_big_strafe_maybe_attack_turret(const object *ship_objp, const object *weapon_objp);
void ai_big_pick_attack_point(object *objp, object *attacker_objp, vec3d *attack_point, float fov=1.0f);
void ai_big_pick_attack_point_turret(object *objp, ship_subsys *ssp, vec3d *gpos, vec3d *gvec, vec3d *attack_point, float weapon_travel_dist, float fov=1.0f);
+69 -97
View File
@@ -764,6 +764,8 @@ void parse_ai_class()
set_aic_flag(aicp, "$all ships manage shields:", AI::Profile_Flags::All_ships_manage_shields);
set_aic_flag(aicp, "$ai can slow down when attacking big ships:", AI::Profile_Flags::Ai_can_slow_down_attacking_big_ships);
set_aic_flag(aicp, "$use actual primary range:", AI::Profile_Flags::Use_actual_primary_range);
}
void reset_ai_class_names()
@@ -1132,7 +1134,7 @@ void ai_update_danger_weapon(int attacked_objnum, int weapon_objnum)
// If rvec != NULL, use it to match bank by calling vm_matrix_interpolate.
// (rvec defaults to NULL)
void ai_turn_towards_vector(vec3d *dest, object *objp, float /*frametime*/, float turn_time, vec3d *slide_vec, vec3d *rel_pos, float bank_override, int flags, vec3d *rvec, int sexp_flags)
void ai_turn_towards_vector(vec3d *dest, object *objp, float turn_time, vec3d *slide_vec, vec3d *rel_pos, float bank_override, int flags, vec3d *rvec, int sexp_flags)
{
matrix curr_orient;
vec3d vel_in, vel_out, desired_fvec, src;
@@ -1500,12 +1502,12 @@ void turn_towards_point(object *objp, vec3d *point, vec3d *slide_vec, float bank
if (aip->ai_flags[AI::AI_Flags::Formation_object, AI::AI_Flags::Formation_wing]) {
if (&Objects[aip->goal_objnum] != objp) {
float rotvel_z = objp->phys_info.rotvel.xyz.z;
ai_turn_towards_vector(point, objp, flFrametime, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, slide_vec, NULL, bank_override, 0);
ai_turn_towards_vector(point, objp, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, slide_vec, nullptr, bank_override, 0);
objp->phys_info.rotvel.xyz.z = rotvel_z;
}
} else {
// normal turn
ai_turn_towards_vector(point, objp, flFrametime, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, slide_vec, NULL, bank_override, 0);
ai_turn_towards_vector(point, objp, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, slide_vec, nullptr, bank_override, 0);
}
}
@@ -1520,7 +1522,7 @@ void turn_away_from_point(object *objp, vec3d *point, float bank_override)
vm_vec_sub(&opposite_point, &objp->pos, point);
vm_vec_add2(&opposite_point, &objp->pos);
ai_turn_towards_vector(&opposite_point, objp, flFrametime, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, NULL, NULL, bank_override, AITTV_FAST);
ai_turn_towards_vector(&opposite_point, objp, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, nullptr, nullptr, bank_override, AITTV_FAST);
}
@@ -3448,35 +3450,6 @@ float compute_time_to_enemy(float dist_to_enemy, object *pobjp)
return time_to_enemy + flFrametime;
}
// Stuff *dot and *tts.
// *dot is always computed. If dot is less than zero, the magnitude is
// incorrect, not having been divided by distance.
// If *dot is > 0.0f, then tts is computed. This is the time it will take object
// *objp to get to *pos, assuming it moves right at it.
void fds_aux(float *dot, float *tts, vec3d *pos, float /*dtime*/, object *objp)
{
vec3d v2s;
vm_vec_sub(&v2s, pos, &objp->pos);
*dot = vm_vec_dot(&v2s, &objp->orient.vec.fvec);
if (*dot > 0.0f) {
float dist;
dist = vm_vec_dist(&objp->pos, pos);
if (dist > 0.1f)
*dot /= dist;
else
*dot = 1.0f;
if (objp->phys_info.speed > 0.1f)
*tts = dist / objp->phys_info.speed;
else
*tts = dist * 100.0f;
}
}
// --------------------------------------------------------------------------
void ai_set_positions(object *pl_objp, object *en_objp, ai_info *aip, vec3d *player_pos, vec3d *enemy_pos)
{
@@ -3892,7 +3865,7 @@ float ai_path_0()
}
if (dist_to_goal > 0.1f)
ai_turn_towards_vector(&gcvp, Pl_objp, flFrametime, sip->srotation_time, slop_vec, NULL, 0.0f, 0);
ai_turn_towards_vector(&gcvp, Pl_objp, sip->srotation_time, slop_vec, nullptr, 0.0f, 0);
// Code to control speed is MUCH less forgiving in path following than in waypoint
// following. Must be very close to path or might hit objects.
@@ -4034,10 +4007,10 @@ float ai_path_1()
if (r <= 1.0f) {
vec3d midpoint;
vm_vec_avg3(&midpoint, &gcvp, &closest_point, &closest_point);
ai_turn_towards_vector(&midpoint, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0, prvec);
ai_turn_towards_vector(&midpoint, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0, prvec);
}
else {
ai_turn_towards_vector(&gcvp, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0, prvec);
ai_turn_towards_vector(&gcvp, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0, prvec);
}
}
@@ -4382,11 +4355,11 @@ void ai_fly_to_target_position(vec3d* target_pos, bool* pl_done_p=NULL, bool* pl
vm_vector_2_matrix(&Pl_objp->orient, &perp, NULL, NULL);
} else {
vm_vec_scale_add(&perp, &Pl_objp->pos, &Autopilot_flight_leader->phys_info.vel, 1000.0f);
ai_turn_towards_vector(&perp, Pl_objp, flFrametime, sip->srotation_time*3.0f*scale, slop_vec, NULL, 0.0f, 0);
ai_turn_towards_vector(&perp, Pl_objp, sip->srotation_time*3.0f*scale, slop_vec, nullptr, 0.0f, 0);
}
} else {
if (dist_to_goal > 0.1f) {
ai_turn_towards_vector(target_pos, Pl_objp, flFrametime, sip->srotation_time*3.0f*scale, slop_vec, NULL, 0.0f, 0);
ai_turn_towards_vector(target_pos, Pl_objp, sip->srotation_time*3.0f*scale, slop_vec, nullptr, 0.0f, 0);
}
}
@@ -5051,7 +5024,7 @@ void slide_face_ship()
dist = vm_vec_normalized_dir(&vec_from_enemy, &Pl_objp->pos, &En_objp->pos);
ai_turn_towards_vector(&En_objp->pos, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
ai_turn_towards_vector(&En_objp->pos, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
dot_from_enemy = vm_vec_dot(&vec_from_enemy, &En_objp->orient.vec.fvec);
@@ -5234,7 +5207,7 @@ vec3d G_predicted_pos, G_fire_pos;
// Else
// Select Any ol' weapon.
// Returns primary_bank index.
int ai_select_primary_weapon_OLD(object *objp, object * /*other_objp*/, Weapon::Info_Flags flags)
static int ai_select_primary_weapon_OLD(const object *objp, Weapon::Info_Flags flags)
{
ship *shipp = &Ships[objp->instance];
ship_weapon *swp = &shipp->weapons;
@@ -5325,7 +5298,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, Weapon::Info_Flag
//not using the new AI, use the old version of this function instead.
if (!(Ai_info[shipp->ai_index].ai_profile_flags[AI::Profile_Flags::Smart_primary_weapon_selection]))
{
return ai_select_primary_weapon_OLD(objp, other_objp, flags);
return ai_select_primary_weapon_OLD(objp, flags);
}
Assert( shipp->ship_info_index >= 0 && shipp->ship_info_index < static_cast<int>(Ship_info.size()));
@@ -6051,8 +6024,7 @@ int check_ok_to_fire(int objnum, int target_objnum, weapon_info *wip)
// --------------------------------------------------------------------------
// Fire a secondary weapon.
// Maybe choose to fire a different one.
// priority1 and priority2 are optional parameters with defaults = -1
int ai_fire_secondary_weapon(object *objp, int /*priority1*/, int /*priority2*/)
int ai_fire_secondary_weapon(object *objp)
{
ship_weapon *swp;
ship *shipp;
@@ -6072,7 +6044,7 @@ int ai_fire_secondary_weapon(object *objp, int /*priority1*/, int /*priority2*
Assert( shipp->ship_info_index >= 0 && shipp->ship_info_index < static_cast<int>(Ship_info.size()));
// Select secondary weapon.
current_bank = swp->current_secondary_bank; //ai_select_secondary_weapon(objp, swp, priority1, priority2);
current_bank = swp->current_secondary_bank;
if (current_bank == -1) {
return rval;
@@ -6539,14 +6511,14 @@ void ai_chase_ct()
vm_vec_add2(&tvec, &Pl_objp->orient.vec.rvec);
}
ai_turn_towards_vector(&tvec, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
ai_turn_towards_vector(&tvec, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
accelerate_ship(aip, 1.0f);
}
/**
* ATTACK submode handler for chase mode.
*/
void ai_chase_eb(ai_info *aip, ship_info *sip, vec3d *predicted_enemy_pos, float /*dist_to_enemy*/)
static void ai_chase_eb(ai_info *aip, ship_info *sip, vec3d *predicted_enemy_pos)
{
vec3d _pep;
float dot_to_enemy, dot_from_enemy;
@@ -6558,7 +6530,7 @@ void ai_chase_eb(ai_info *aip, ship_info *sip, vec3d *predicted_enemy_pos, float
if ((dot_to_enemy > dot_from_enemy + 0.1f) || (dot_to_enemy > 0.9f))
vm_vec_scale_add(&_pep, &Pl_objp->pos, &En_objp->orient.vec.fvec, 100.0f);
ai_turn_towards_vector(&_pep, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
ai_turn_towards_vector(&_pep, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
accelerate_ship(aip, 0.0f);
}
@@ -6755,7 +6727,7 @@ void attack_set_accel(ai_info *aip, ship_info *sip, float dist_to_enemy, float d
// Pl_objp (aip) tries to get behind En_objp.
// New on 2/21/98: If this ship can move backwards and slide, maybe do that to get behind.
void get_behind_ship(ai_info *aip, ship_info *sip, float /*dist_to_enemy*/)
static void get_behind_ship(ai_info *aip, ship_info *sip)
{
vec3d new_pos;
float dot;
@@ -6764,7 +6736,7 @@ void get_behind_ship(ai_info *aip, ship_info *sip, float /*dist_to_enemy*/)
vm_vec_normalized_dir(&vec_from_enemy, &Pl_objp->pos, &En_objp->pos);
vm_vec_scale_add(&new_pos, &En_objp->pos, &En_objp->orient.vec.fvec, -100.0f); // Pick point 100 units behind.
ai_turn_towards_vector(&new_pos, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
ai_turn_towards_vector(&new_pos, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
dot = vm_vec_dot(&vec_from_enemy, &En_objp->orient.vec.fvec);
@@ -6783,7 +6755,7 @@ int avoid_player(object *objp, vec3d *goal_pos)
if (aip->ai_flags[AI::AI_Flags::Avoiding_small_ship]) {
ship_info *sip = &Ship_info[Ships[objp->instance].ship_info_index];
ai_turn_towards_vector(&aip->avoid_goal_point, objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
ai_turn_towards_vector(&aip->avoid_goal_point, objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
accelerate_ship(aip, 0.5f);
return 1;
}
@@ -6981,7 +6953,7 @@ int maybe_avoid_big_ship(object *objp, object *ignore_objp, ai_info *aip, vec3d
vec3d v2g;
ai_turn_towards_vector(&aip->avoid_goal_point, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
ai_turn_towards_vector(&aip->avoid_goal_point, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
vm_vec_normalized_dir(&v2g, &aip->avoid_goal_point, &Pl_objp->pos);
float dot = vm_vec_dot(&objp->orient.vec.fvec, &v2g);
float d2 = (1.0f + dot) * (1.0f + dot);
@@ -7073,7 +7045,7 @@ void ai_stealth_find()
}
}
ai_turn_towards_vector(&new_pos, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
ai_turn_towards_vector(&new_pos, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
return;
}
@@ -7083,9 +7055,9 @@ void ai_stealth_find()
if (dist_to_enemy > 500.0f) {
vec3d rvec;
compute_desired_rvec(&rvec, &new_pos, &Pl_objp->pos);
ai_turn_towards_vector(&new_pos, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0, &rvec);
ai_turn_towards_vector(&new_pos, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0, &rvec);
} else {
ai_turn_towards_vector(&new_pos, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
ai_turn_towards_vector(&new_pos, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
}
dot_from_enemy = -vm_vec_dot(&vec_to_enemy, &En_objp->orient.vec.fvec);
@@ -7213,7 +7185,7 @@ void ai_stealth_sweep()
return;
}
ai_turn_towards_vector(&goal_pt, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
ai_turn_towards_vector(&goal_pt, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
float dot = 1.0f;
if (dist_to_goal < 100) {
@@ -7273,9 +7245,9 @@ void ai_chase_attack(ai_info *aip, ship_info *sip, vec3d *predicted_enemy_pos, f
if (dist_to_enemy > 500.0f) {
vec3d rvec;
compute_desired_rvec(&rvec, predicted_enemy_pos, &Pl_objp->pos);
ai_turn_towards_vector(&new_pos, Pl_objp, flFrametime, sip->srotation_time, NULL, rel_pos, bank_override, 0, &rvec);
ai_turn_towards_vector(&new_pos, Pl_objp, sip->srotation_time, nullptr, rel_pos, bank_override, 0, &rvec);
} else {
ai_turn_towards_vector(&new_pos, Pl_objp, flFrametime, sip->srotation_time, NULL, rel_pos, bank_override, 0);
ai_turn_towards_vector(&new_pos, Pl_objp, sip->srotation_time, nullptr, rel_pos, bank_override, 0);
}
attack_set_accel(aip, sip, dist_to_enemy, dot_to_enemy, dot_from_enemy);
@@ -7313,7 +7285,7 @@ void ai_chase_es(ai_info *aip, ship_info *sip)
float bank_override = Pl_objp->phys_info.speed;
ai_turn_towards_vector(&tvec, Pl_objp, flFrametime/2, sip->srotation_time, NULL, NULL, bank_override, 0);
ai_turn_towards_vector(&tvec, Pl_objp, sip->srotation_time, nullptr, nullptr, bank_override, 0);
accelerate_ship(aip, 1.0f);
}
@@ -7339,7 +7311,7 @@ void ai_chase_ga(ai_info *aip, ship_info *sip)
bank_override = Pl_objp->phys_info.speed;
ai_turn_towards_vector(&tvec, Pl_objp, flFrametime/2, sip->srotation_time, NULL, NULL, bank_override, 0);
ai_turn_towards_vector(&tvec, Pl_objp, sip->srotation_time, nullptr, nullptr, bank_override, 0);
accelerate_ship(aip, 2.0f);
@@ -8001,7 +7973,7 @@ void ai_cruiser_chase()
// kamikaze - ram and explode
if (aip->ai_flags[AI::AI_Flags::Kamikaze]) {
ai_turn_towards_vector(&En_objp->pos, Pl_objp, flFrametime, turn_time, NULL, NULL, 0.0f, 0);
ai_turn_towards_vector(&En_objp->pos, Pl_objp, turn_time, nullptr, nullptr, 0.0f, 0);
accelerate_ship(aip, 1.0f);
}
@@ -8041,7 +8013,7 @@ void ai_cruiser_chase()
}
// now move as desired
ai_turn_towards_vector(&goal_pos, Pl_objp, flFrametime, turn_time, NULL, NULL, 0.0f, 0, rvecp);
ai_turn_towards_vector(&goal_pos, Pl_objp, turn_time, nullptr, nullptr, 0.0f, 0, rvecp);
accelerate_ship(aip, accel);
// maybe switch to new mode
@@ -8322,7 +8294,7 @@ void ai_chase()
break;
case SM_EVADE_BRAKE:
ai_chase_eb(aip, sip, &predicted_enemy_pos, dist_to_enemy);
ai_chase_eb(aip, sip, &predicted_enemy_pos);
break;
case SM_EVADE:
@@ -8334,7 +8306,7 @@ void ai_chase()
break;
case SM_GET_BEHIND:
get_behind_ship(aip, sip, dist_to_enemy);
get_behind_ship(aip, sip);
break;
case SM_GET_AWAY: // Used to get away from opponent to prevent endless circling.
@@ -8768,7 +8740,11 @@ void ai_chase()
scale = (scale - 0.6f) * 1.5f;
else
scale = 0.0f;
if (dist_to_enemy < pwip->max_speed * (1.0f + scale)) {
float range = pwip->max_speed * (1.0f + scale);
if (aip->ai_profile_flags[AI::Profile_Flags::Use_actual_primary_range]) {
range = std::min( {range, pwip->max_speed * pwip->lifetime, pwip->weapon_range} );
}
if (dist_to_enemy < range) {
if(ai_fire_primary_weapon(Pl_objp) == 1){
has_fired = 1;
}else{
@@ -9329,7 +9305,7 @@ float dock_orient_and_approach(object *docker_objp, int docker_index, object *do
{
float dot, accel;
float turn_time = Ship_info[Ships[docker_objp->instance].ship_info_index].srotation_time;
ai_turn_towards_vector(&goal_point, docker_objp, flFrametime, turn_time, NULL, NULL, 0.0f, 0);
ai_turn_towards_vector(&goal_point, docker_objp, turn_time, nullptr, nullptr, 0.0f, 0);
dot = vm_vec_dot(&docker_objp->orient.vec.fvec, &away_vec);
accel = 0.1f;
@@ -9964,7 +9940,7 @@ void ai_big_guard()
}
// got the point, now let's go there
ai_turn_towards_vector(&goal_pt, Pl_objp, flFrametime, Ship_info[Ships[Pl_objp->instance].ship_info_index].srotation_time, NULL, NULL, 0.0f, 0);
ai_turn_towards_vector(&goal_pt, Pl_objp, Ship_info[Ships[Pl_objp->instance].ship_info_index].srotation_time, nullptr, nullptr, 0.0f, 0);
accelerate_ship(aip, 1.0f);
if ((aip->ai_flags[AI::AI_Flags::Free_afterburner_use]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (cur_guard_rad > 1.1f * max_guard_dist)) {
@@ -10088,7 +10064,7 @@ void ai_guard()
// quite far away, so try to go straight to
compute_desired_rvec(&rvec, &goal_point, &Pl_objp->pos);
ai_turn_towards_vector(&goal_point, Pl_objp, flFrametime, Ship_info[shipp->ship_info_index].srotation_time, NULL, NULL, 0.0f, 0, &rvec);
ai_turn_towards_vector(&goal_point, Pl_objp, Ship_info[shipp->ship_info_index].srotation_time, nullptr, nullptr, 0.0f, 0, &rvec);
if ((aip->ai_flags[AI::AI_Flags::Free_afterburner_use]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (accel_scale * (0.25f + dist_to_goal_point/700.0f) > 0.8f)) {
if (ai_maybe_fire_afterburner(Pl_objp, aip)) {
@@ -10713,8 +10689,8 @@ void ai_dock()
char *goal_ship_class_name = goal_sip->name;
char *goal_dock_path_name = model_get(goal_sip->model_num)->paths[aip->mp_index].name;
Warning(LOCATION, "Ship class %s has only %i points on dock path \"%s\". Recommended minimum number of points is 4. "\
"Docking along that path will look strange. You may wish to edit the model.", goal_ship_class_name, aip->path_length, goal_dock_path_name);
mprintf(("Ship class %s has only %i points on dock path \"%s\". Recommended minimum number of points is 4. "\
"Docking along that path will look strange. You may wish to edit the model.", goal_ship_class_name, aip->path_length, goal_dock_path_name));
}
aip->submode = AIS_DOCK_1;
@@ -11385,7 +11361,7 @@ float gwlr_1(object *objp, ai_info *aip)
/**
* Compute the largest radius of a ship forming on *objp's wing.
*/
float gwlr_object_1(object *objp, ai_info * /*aip*/)
static float gwlr_object_1(object *objp)
{
float max_radius;
object *o;
@@ -11418,7 +11394,7 @@ float get_wing_largest_radius(object *objp, int formation_object_flag)
aip = &Ai_info[shipp->ai_index];
if (formation_object_flag) {
return gwlr_object_1(objp, aip);
return gwlr_object_1(objp);
} else {
return gwlr_1(objp, aip);
}
@@ -12191,7 +12167,7 @@ void ai_maybe_launch_cmeasure(object *objp, ai_info *aip)
}
// --------------------------------------------------------------------------
void ai_preprocess_ignore_objnum(object * /*objp*/, ai_info *aip)
static void ai_preprocess_ignore_objnum(ai_info *aip)
{
if (aip->ai_flags[AI::AI_Flags::Temporary_ignore])
{
@@ -13064,7 +13040,6 @@ void ai_execute_behavior(ai_info *aip)
case AIM_NONE:
break;
case AIM_BIGSHIP:
ai_big_ship(Pl_objp);
break;
case AIM_PATH: {
int path_num;
@@ -13441,7 +13416,7 @@ void ai_warp_out(object *objp)
// Return object index of weapon that could produce a shockwave that should be known about to *objp.
// Return nearest one.
int ai_find_shockwave_weapon(object *objp, ai_info * /*aip*/)
static int ai_find_shockwave_weapon(const object *objp)
{
missile_obj *mo;
float nearest_dist = 999999.9f;
@@ -13507,7 +13482,7 @@ void ai_announce_ship_dying(object *dying_objp)
// Return object index of weapon that could produce a shockwave that should be known about to *objp.
// Return nearest one.
int ai_find_shockwave_ship(object *objp, ai_info * /*aip*/)
static int ai_find_shockwave_ship(object *objp)
{
ship_obj *so;
float nearest_dist = 999999.9f;
@@ -13550,7 +13525,7 @@ int aas_1(object *objp, ai_info *aip, vec3d *safe_pos)
// If we don't currently know of a weapon to avoid, try to find one.
// If we can't find one, then clear the bit so we don't keep coming here.
if (aip->shockwave_object == -1) {
int shockwave_weapon = ai_find_shockwave_weapon(objp, aip);
int shockwave_weapon = ai_find_shockwave_weapon(objp);
if (shockwave_weapon == -1) {
aip->ai_flags.remove(AI::AI_Flags::Avoid_shockwave_weapon);
return 0;
@@ -13639,7 +13614,7 @@ int aas_1(object *objp, ai_info *aip, vec3d *safe_pos)
}
} else if (aip->ai_flags[AI::AI_Flags::Avoid_shockwave_ship]) {
if (aip->shockwave_object == -1) {
int shockwave_ship = ai_find_shockwave_ship(objp, aip);
int shockwave_ship = ai_find_shockwave_ship(objp);
if (shockwave_ship == -1) {
aip->ai_flags.remove(AI::AI_Flags::Avoid_shockwave_ship);
return 0;
@@ -13869,7 +13844,7 @@ int maybe_big_ship_collide_recover_frame(object *objp, ai_info *aip)
vec3d v2g;
if (aip->ai_flags[AI::AI_Flags::Big_ship_collide_recover_1]) {
ai_turn_towards_vector(&aip->big_recover_pos_1, objp, flFrametime, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, NULL, NULL, 0.0f, 0, NULL);
ai_turn_towards_vector(&aip->big_recover_pos_1, objp, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, nullptr, nullptr, 0.0f, 0, nullptr);
dist = vm_vec_normalized_dir(&v2g, &aip->big_recover_pos_1, &objp->pos);
dot = vm_vec_dot(&objp->orient.vec.fvec, &v2g);
accelerate_ship(aip, dot);
@@ -13883,7 +13858,7 @@ int maybe_big_ship_collide_recover_frame(object *objp, ai_info *aip)
return 1;
} else if (aip->ai_flags[AI::AI_Flags::Big_ship_collide_recover_2]) {
ai_turn_towards_vector(&aip->big_recover_pos_2, objp, flFrametime, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, NULL, NULL, 0.0f, 0, NULL);
ai_turn_towards_vector(&aip->big_recover_pos_2, objp, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, nullptr, nullptr, 0.0f, 0, nullptr);
dist = vm_vec_normalized_dir(&v2g, &aip->big_recover_pos_2, &objp->pos);
dot = vm_vec_dot(&objp->orient.vec.fvec, &v2g);
accelerate_ship(aip, dot);
@@ -14003,7 +13978,7 @@ void ai_frame(int objnum)
if (maybe_big_ship_collide_recover_frame(Pl_objp, aip))
return;
ai_preprocess_ignore_objnum(Pl_objp, aip);
ai_preprocess_ignore_objnum(aip);
target_objnum = set_target_objnum(aip, aip->target_objnum);
Assert(objnum != target_objnum);
@@ -14158,7 +14133,7 @@ void ai_frame(int objnum)
}
}
void ai_control_info_check( object * /*obj*/, ai_info *aip )
static void ai_control_info_check(ai_info *aip)
{
if(aip->ai_override_flags.none_set())
return;
@@ -14259,7 +14234,7 @@ void ai_process( object * obj, int ai_index, float frametime )
if (rfc == 1) {
// Wanderer - sexp based override goes here - only if rfc is valid though
ai_control_info_check(obj, aip);
ai_control_info_check(aip);
vec3d copy_desired_rotvel = obj->phys_info.rotvel;
physics_read_flying_controls( &obj->orient, &obj->phys_info, &AI_ci, frametime);
// if obj is in formation and not flight leader, don't update rotvel
@@ -14794,10 +14769,10 @@ int firing_aspect_seeking_bomb(object *objp)
return 0;
}
// *objp collided with big ship *big_objp at global point *collide_pos
// Make it fly away from the collision point.
// *objp collided with big ship *big_objp at some global point.
// Make it fly away from the collision point.
// collision_normal is NULL, when a collision is imminent and we just want to bug out.
void big_ship_collide_recover_start(object *objp, object *big_objp, vec3d * /*collide_pos*/, vec3d *collision_normal)
void big_ship_collide_recover_start(object *objp, object *big_objp, vec3d *collision_normal)
{
ai_info *aip;
@@ -14886,9 +14861,9 @@ void ai_update_lethality(object *pship_obj, object *other_obj, float damage)
/**
* Object *objp_ship was hit by either weapon *objp_weapon or collided into by ship hit_objp at point *hitpos.
* Object *objp_ship was hit by either weapon *objp_weapon or collided into by ship hit_objp
*/
void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hitpos, int /*shield_quadrant*/, vec3d *hit_normal)
void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hit_normal)
{
int hitter_objnum = -2;
object *objp_hitter = NULL;
@@ -14930,7 +14905,7 @@ void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hitpos, int /*shie
// And the current object is _not_ a big ship
if (!Ship_info[Ships[objp_ship->instance].ship_info_index].is_big_or_huge()) {
// Recover from hitting a big ship. Note, if two big ships collide, they just pound away at each other. Oh well. Recovery looks dumb and it's very late.
big_ship_collide_recover_start(objp_ship, hit_objp, hitpos, hit_normal);
big_ship_collide_recover_start(objp_ship, hit_objp, hit_normal);
}
}
}
@@ -15067,7 +15042,7 @@ void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hitpos, int /*shie
return;
if ( (hit_objp->type == OBJ_WEAPON) && !(aip->ai_flags[AI::AI_Flags::No_dynamic]) ) {
if ( ai_big_maybe_enter_strafe_mode(objp_ship, OBJ_INDEX(hit_objp), 1) )
if ( ai_big_maybe_enter_strafe_mode(objp_ship, OBJ_INDEX(hit_objp)) )
return;
}
break;
@@ -15187,10 +15162,7 @@ void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hitpos, int /*shie
// Ship shipnum has been destroyed.
// Cleanup.
// the parameter 'method' is used to tell is this ship was destroyed or it departed normally.
// This function will get called in either case, and there are things that should be done if
// the ship actually gets destroyed which shouldn't get done if it departed.
void ai_ship_destroy(int shipnum, Ship::Exit_Flags /*method*/)
void ai_ship_destroy(int shipnum)
{
int objnum;
object *other_objp;
@@ -15441,7 +15413,7 @@ int ai_issue_rearm_request(object *requester_objp)
// we aren't able to do anything!
else {
Assert(result == 4);
Assertion(false, "This case should have already been caught by the is_support_allowed precheck!");
UNREACHABLE("This case should have already been caught by the is_support_allowed precheck!");
return -1;
}
}
@@ -15510,7 +15482,7 @@ int ai_return_path_num_from_dockbay(object *dockee_objp, int dockbay_index)
/**
* Actually go ahead and fire the synaptics.
*/
void cheat_fire_synaptic(object *objp, ship *shipp, ai_info * /*aip*/)
static void cheat_fire_synaptic(object *objp, ship *shipp)
{
ship_weapon *swp;
swp = &shipp->weapons;
@@ -15532,7 +15504,7 @@ void cheat_fire_synaptic(object *objp, ship *shipp, ai_info * /*aip*/)
// if they're near one or more enemies
// every so often
// fire a synaptic if they have one.
void maybe_cheat_fire_synaptic(object *objp, ai_info *aip)
void maybe_cheat_fire_synaptic(object *objp)
{
// Only do in subspace missions.
if (!(The_mission.flags[Mission::Mission_Flags::Subspace]))
@@ -15564,7 +15536,7 @@ void maybe_cheat_fire_synaptic(object *objp, ai_info *aip)
int count = num_nearby_fighters(iff_get_attackee_mask(obj_team(objp)), &objp->pos, 1500.0f);
if (count > 0)
cheat_fire_synaptic(objp, shipp, aip);
cheat_fire_synaptic(objp, shipp);
}
}
}
+1 -1
View File
@@ -125,7 +125,7 @@ const char *Ai_goal_text(int goal)
case AI_GOAL_REARM_REPAIR:
return XSTR( "rearm ", 484);
case AI_GOAL_FLY_TO_SHIP:
return XSTR( "rendezvous with ", -1);
return XSTR( "rendezvous with ", 1597);
}
// Avoid compiler warning
+1 -1
View File
@@ -1387,7 +1387,7 @@ void asteroid_hit( object * pasteroid_obj, object * other_obj, vec3d * hitpos, f
weapon_info *wip;
wip = &Weapon_info[Weapons[other_obj->instance].weapon_info_index];
// If the weapon didn't play any impact animation, play custom asteroid impact animation
if ( wip->impact_weapon_expl_effect < 0 ) {
if (!wip->impact_weapon_expl_effect.isValid()) {
particle::create( hitpos, &vmd_zero_vector, 0.0f, Asteroid_impact_explosion_radius, particle::PARTICLE_BITMAP, Asteroid_impact_explosion_ani );
}
}
+16 -23
View File
@@ -591,7 +591,7 @@ int bm_create(int bpp, int w, int h, void *data, int flags) {
memset(entry, 0, sizeof(bitmap_entry));
sprintf(entry->filename, "TMP%dx%d+%d", w, h, bpp);
sprintf_safe(entry->filename, "TMP%dx%d+%d", w, h, bpp);
entry->type = BM_TYPE_USER;
entry->comp_type = BM_TYPE_NONE;
entry->palette_checksum = 0;
@@ -1155,7 +1155,7 @@ static int bm_load_info(BM_TYPE type, const char *filename, CFILE *img_cfp, int
}
}
else {
Assertion(false, "Unknown file type specified! This is probably a coding error.");
UNREACHABLE("Unknown file type specified! This is probably a coding error.");
return -1;
}
@@ -1253,7 +1253,7 @@ int bm_load(const char *real_filename) {
// Mark the slot as filled, because cf_read might load a new bitmap
// into this slot.
strncpy(entry->filename, filename, MAX_FILENAME_LEN - 1);
strcpy_s(entry->filename, filename);
entry->type = type;
entry->comp_type = c_type;
entry->signature = Bm_next_signature++;
@@ -1681,7 +1681,7 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke
if (type == BM_TYPE_EFF) {
entry->info.ani.eff.type = eff_type;
sprintf(entry->info.ani.eff.filename, "%s_%.4d", clean_name, i);
sprintf_safe(entry->info.ani.eff.filename, "%s_%.4d", clean_name, i);
// bm_load_info() returns non-0 on failure
if (bm_load_info(eff_type, entry->info.ani.eff.filename,
@@ -1744,13 +1744,13 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke
entry->load_count++;
if (i == 0) {
sprintf(entry->filename, "%s", filename);
sprintf_safe(entry->filename, "%s", filename);
} else {
if (type == BM_TYPE_PNG) {
sprintf(entry->filename, "%s_%04d", filename, i);
sprintf_safe(entry->filename, "%s_%04d", filename, i);
}
else {
sprintf(entry->filename, "%s[%d]", filename, i);
sprintf_safe(entry->filename, "%s[%d]", filename, i);
}
}
@@ -1876,24 +1876,19 @@ int bm_load_sub_fast(const char *real_filename, int *handle, int dir_type, bool
}
int bm_load_sub_slow(const char *real_filename, const int num_ext, const char **ext_list, CFILE **img_cfp, int dir_type) {
char full_path[MAX_PATH];
size_t size = 0, offset = 0;
int rval = -1;
const void* file_data = nullptr;
rval = cf_find_file_location_ext(real_filename, num_ext, ext_list, dir_type, sizeof(full_path) - 1, full_path, &size, &offset, 0, &file_data);
auto res = cf_find_file_location_ext(real_filename, num_ext, ext_list, dir_type, false);
// could not be found, or is invalid for some reason
if ((rval < 0) || (rval >= num_ext))
if (!res.found)
return -1;
CFILE *test = cfopen_special(full_path, "rb", size, offset, file_data, dir_type);
CFILE *test = cfopen_special(res.full_name.c_str(), "rb", res.size, res.offset, res.data_ptr, dir_type);
if (test != NULL) {
if (img_cfp != NULL)
*img_cfp = test;
return rval;
return res.extension_index;
}
// umm, that's not good...
@@ -2385,7 +2380,7 @@ void bm_lock_png(int handle, bitmap_slot *bs, bitmap *bmp, int /*bpp*/, ubyte /*
void bm_lock_tga(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags) {
ubyte *data = NULL;
int d_size, byte_size;
int byte_size;
char filename[MAX_FILENAME_LEN];
auto be = &bs->entry;
@@ -2393,6 +2388,8 @@ void bm_lock_tga(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags)
// Unload any existing data
bm_free_data(bs);
bpp = be->bm.true_bpp;
if (Is_standalone) {
Assert(bpp == 8);
} else {
@@ -2409,7 +2406,6 @@ void bm_lock_tga(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags)
if (data) {
memset(data, 0, be->mem_taken);
d_size = byte_size;
} else {
return;
}
@@ -2429,7 +2425,7 @@ void bm_lock_tga(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags)
// this will populate filename[] whether it's EFF or not
EFF_FILENAME_CHECK;
tga_error = targa_read_bitmap(filename, data, NULL, d_size, be->dir_type);
tga_error = targa_read_bitmap(filename, data, nullptr, byte_size, be->dir_type);
if (tga_error != TARGA_ERROR_NONE) {
bm_free_data(bs);
@@ -2526,7 +2522,7 @@ int bm_make_render_target(int width, int height, int flags) {
entry->type = (flags & BMP_FLAG_RENDER_TARGET_STATIC) ? BM_TYPE_RENDER_TARGET_STATIC : BM_TYPE_RENDER_TARGET_DYNAMIC;
entry->signature = Bm_next_signature++;
sprintf(entry->filename, "RT_%dx%d+%d", w, h, bpp);
sprintf_safe(entry->filename, "RT_%dx%d+%d", w, h, bpp);
entry->bm.w = (short)w;
entry->bm.h = (short)h;
entry->bm.rowsize = (short)w;
@@ -2589,9 +2585,6 @@ void bm_page_in_start() {
for (auto& slot : block) {
auto& entry = slot.entry;
if (!Cmdline_cache_bitmaps && (entry.type != BM_TYPE_NONE)) {
bm_unload_fast(entry.handle);
}
entry.preloaded = 0;
entry.preload_count = 0;
#ifdef BMPMAN_NDEBUG
+75 -87
View File
@@ -33,70 +33,64 @@
#include "cfile/cfilesystem.h"
#include "osapi/osapi.h"
#include "parse/encrypt.h"
#include "cfilesystem.h"
#include <limits>
char Cfile_root_dir[CFILE_ROOT_DIRECTORY_LEN] = "";
char Cfile_user_dir[CFILE_ROOT_DIRECTORY_LEN] = "";
#ifdef SCP_UNIX
char Cfile_user_dir_legacy[CFILE_ROOT_DIRECTORY_LEN] = "";
#endif
// During cfile_init, verify that Pathtypes[n].index == n for each item
// Each path must have a valid parent that can be tracable all the way back to the root
// Each path must have a valid parent that can be tracable all the way back to the root
// so that we can create directories when we need to.
//
// Please make sure extensions are all lower-case, or we'll break unix compatibility
//
cf_pathtype Pathtypes[CF_MAX_PATH_TYPES] = {
// What type this is Path Extensions Parent
// type
{CF_TYPE_INVALID, NULL, NULL, CF_TYPE_INVALID},
// Root must be index 1!!
{CF_TYPE_ROOT, "", ".mve .ogg", CF_TYPE_ROOT},
{CF_TYPE_DATA, "data", ".cfg .txt", CF_TYPE_ROOT},
{CF_TYPE_MAPS, "data" DIR_SEPARATOR_STR "maps", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA},
{CF_TYPE_TEXT, "data" DIR_SEPARATOR_STR "text", ".txt .net", CF_TYPE_DATA},
{CF_TYPE_MODELS, "data" DIR_SEPARATOR_STR "models", ".pof", CF_TYPE_DATA},
{CF_TYPE_TABLES, "data" DIR_SEPARATOR_STR "tables", ".tbl .tbm", CF_TYPE_DATA},
{CF_TYPE_SOUNDS, "data" DIR_SEPARATOR_STR "sounds", ".wav .ogg", CF_TYPE_DATA},
{CF_TYPE_SOUNDS_8B22K, "data" DIR_SEPARATOR_STR "sounds" DIR_SEPARATOR_STR "8b22k", ".wav .ogg", CF_TYPE_SOUNDS},
{CF_TYPE_SOUNDS_16B11K, "data" DIR_SEPARATOR_STR "sounds" DIR_SEPARATOR_STR "16b11k", ".wav .ogg", CF_TYPE_SOUNDS},
{CF_TYPE_VOICE, "data" DIR_SEPARATOR_STR "voice", "", CF_TYPE_DATA},
{CF_TYPE_VOICE_BRIEFINGS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "briefing", ".wav .ogg",
CF_TYPE_VOICE},
{CF_TYPE_VOICE_CMD_BRIEF, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "command_briefings", ".wav .ogg",
CF_TYPE_VOICE},
{CF_TYPE_VOICE_DEBRIEFINGS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "debriefing", ".wav .ogg",
CF_TYPE_VOICE},
{CF_TYPE_VOICE_PERSONAS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "personas", ".wav .ogg", CF_TYPE_VOICE},
{CF_TYPE_VOICE_SPECIAL, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "special", ".wav .ogg", CF_TYPE_VOICE},
{CF_TYPE_VOICE_TRAINING, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "training", ".wav .ogg", CF_TYPE_VOICE},
{CF_TYPE_MUSIC, "data" DIR_SEPARATOR_STR "music", ".wav .ogg", CF_TYPE_DATA},
{CF_TYPE_MOVIES, "data" DIR_SEPARATOR_STR "movies", ".mve .msb .ogg .mp4 .srt", CF_TYPE_DATA},
{CF_TYPE_INTERFACE, "data" DIR_SEPARATOR_STR "interface", ".pcx .ani .dds .tga .eff .png .jpg", CF_TYPE_DATA},
{CF_TYPE_FONT, "data" DIR_SEPARATOR_STR "fonts", ".vf .ttf", CF_TYPE_DATA},
{CF_TYPE_EFFECTS, "data" DIR_SEPARATOR_STR "effects", ".ani .eff .pcx .neb .tga .jpg .png .dds .sdr", CF_TYPE_DATA},
{CF_TYPE_HUD, "data" DIR_SEPARATOR_STR "hud", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA},
{CF_TYPE_PLAYERS, "data" DIR_SEPARATOR_STR "players", ".hcf", CF_TYPE_DATA},
{CF_TYPE_PLAYER_IMAGES, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "images", ".pcx .png .dds",
CF_TYPE_PLAYERS},
{CF_TYPE_SQUAD_IMAGES, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "squads", ".pcx .png .dds",
CF_TYPE_PLAYERS},
{CF_TYPE_SINGLE_PLAYERS, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "single", ".pl2 .cs2 .plr .csg .css",
CF_TYPE_PLAYERS},
{CF_TYPE_MULTI_PLAYERS, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "multi", ".plr", CF_TYPE_PLAYERS},
{CF_TYPE_CACHE, "data" DIR_SEPARATOR_STR "cache", ".clr .tmp .bx", CF_TYPE_DATA}, // clr=cached color
{CF_TYPE_MULTI_CACHE, "data" DIR_SEPARATOR_STR "multidata", ".pcx .png .dds .fs2 .txt", CF_TYPE_DATA},
{CF_TYPE_MISSIONS, "data" DIR_SEPARATOR_STR "missions", ".fs2 .fc2 .ntl .ssv", CF_TYPE_DATA},
{CF_TYPE_CONFIG, "data" DIR_SEPARATOR_STR "config", ".cfg .tbl .tbm .xml .csv", CF_TYPE_DATA},
{CF_TYPE_DEMOS, "data" DIR_SEPARATOR_STR "demos", ".fsd", CF_TYPE_DATA},
{CF_TYPE_CBANIMS, "data" DIR_SEPARATOR_STR "cbanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA},
{CF_TYPE_INTEL_ANIMS, "data" DIR_SEPARATOR_STR "intelanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA},
{CF_TYPE_SCRIPTS, "data" DIR_SEPARATOR_STR "scripts", ".lua .lc", CF_TYPE_DATA},
{CF_TYPE_FICTION, "data" DIR_SEPARATOR_STR "fiction", ".txt", CF_TYPE_DATA},
{CF_TYPE_FREDDOCS, "data" DIR_SEPARATOR_STR "freddocs", ".html", CF_TYPE_DATA},
// clang-format off
cf_pathtype Pathtypes[CF_MAX_PATH_TYPES] = {
// What type this is Path Extensions Parent type
{ CF_TYPE_INVALID, NULL, NULL, CF_TYPE_INVALID },
// Root must be index 1!!
{ CF_TYPE_ROOT, "", ".mve .ogg", CF_TYPE_ROOT },
{ CF_TYPE_DATA, "data", ".cfg .txt", CF_TYPE_ROOT },
{ CF_TYPE_MAPS, "data" DIR_SEPARATOR_STR "maps", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
{ CF_TYPE_TEXT, "data" DIR_SEPARATOR_STR "text", ".txt .net", CF_TYPE_DATA },
{ CF_TYPE_MODELS, "data" DIR_SEPARATOR_STR "models", ".pof", CF_TYPE_DATA },
{ CF_TYPE_TABLES, "data" DIR_SEPARATOR_STR "tables", ".tbl .tbm", CF_TYPE_DATA },
{ CF_TYPE_SOUNDS, "data" DIR_SEPARATOR_STR "sounds", ".wav .ogg", CF_TYPE_DATA },
{ CF_TYPE_SOUNDS_8B22K, "data" DIR_SEPARATOR_STR "sounds" DIR_SEPARATOR_STR "8b22k", ".wav .ogg", CF_TYPE_SOUNDS },
{ CF_TYPE_SOUNDS_16B11K, "data" DIR_SEPARATOR_STR "sounds" DIR_SEPARATOR_STR "16b11k", ".wav .ogg", CF_TYPE_SOUNDS },
{ CF_TYPE_VOICE, "data" DIR_SEPARATOR_STR "voice", "", CF_TYPE_DATA },
{ CF_TYPE_VOICE_BRIEFINGS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "briefing", ".wav .ogg", CF_TYPE_VOICE },
{ CF_TYPE_VOICE_CMD_BRIEF, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "command_briefings", ".wav .ogg", CF_TYPE_VOICE },
{ CF_TYPE_VOICE_DEBRIEFINGS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "debriefing", ".wav .ogg", CF_TYPE_VOICE },
{ CF_TYPE_VOICE_PERSONAS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "personas", ".wav .ogg", CF_TYPE_VOICE },
{ CF_TYPE_VOICE_SPECIAL, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "special", ".wav .ogg", CF_TYPE_VOICE },
{ CF_TYPE_VOICE_TRAINING, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "training", ".wav .ogg", CF_TYPE_VOICE },
{ CF_TYPE_MUSIC, "data" DIR_SEPARATOR_STR "music", ".wav .ogg", CF_TYPE_DATA },
{ CF_TYPE_MOVIES, "data" DIR_SEPARATOR_STR "movies", ".mve .msb .ogg .mp4 .srt .webm .png",CF_TYPE_DATA },
{ CF_TYPE_INTERFACE, "data" DIR_SEPARATOR_STR "interface", ".pcx .ani .dds .tga .eff .png .jpg", CF_TYPE_DATA },
{ CF_TYPE_FONT, "data" DIR_SEPARATOR_STR "fonts", ".vf .ttf", CF_TYPE_DATA },
{ CF_TYPE_EFFECTS, "data" DIR_SEPARATOR_STR "effects", ".ani .eff .pcx .neb .tga .jpg .png .dds .sdr", CF_TYPE_DATA },
{ CF_TYPE_HUD, "data" DIR_SEPARATOR_STR "hud", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
{ CF_TYPE_PLAYERS, "data" DIR_SEPARATOR_STR "players", ".hcf", CF_TYPE_DATA },
{ CF_TYPE_PLAYER_IMAGES, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "images", ".pcx .png .dds", CF_TYPE_PLAYERS },
{ CF_TYPE_SQUAD_IMAGES, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "squads", ".pcx .png .dds", CF_TYPE_PLAYERS },
{ CF_TYPE_SINGLE_PLAYERS, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "single", ".pl2 .cs2 .plr .csg .css", CF_TYPE_PLAYERS },
{ CF_TYPE_MULTI_PLAYERS, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "multi", ".plr", CF_TYPE_PLAYERS },
{ CF_TYPE_CACHE, "data" DIR_SEPARATOR_STR "cache", ".clr .tmp .bx", CF_TYPE_DATA }, //clr=cached color
{ CF_TYPE_MULTI_CACHE, "data" DIR_SEPARATOR_STR "multidata", ".pcx .png .dds .fs2 .txt", CF_TYPE_DATA },
{ CF_TYPE_MISSIONS, "data" DIR_SEPARATOR_STR "missions", ".fs2 .fc2 .ntl .ssv", CF_TYPE_DATA },
{ CF_TYPE_CONFIG, "data" DIR_SEPARATOR_STR "config", ".cfg .tbl .tbm .xml .csv", CF_TYPE_DATA },
{ CF_TYPE_DEMOS, "data" DIR_SEPARATOR_STR "demos", ".fsd", CF_TYPE_DATA },
{ CF_TYPE_CBANIMS, "data" DIR_SEPARATOR_STR "cbanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
{ CF_TYPE_INTEL_ANIMS, "data" DIR_SEPARATOR_STR "intelanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
{ CF_TYPE_SCRIPTS, "data" DIR_SEPARATOR_STR "scripts", ".lua .lc", CF_TYPE_DATA },
{ CF_TYPE_FICTION, "data" DIR_SEPARATOR_STR "fiction", ".txt", CF_TYPE_DATA },
{ CF_TYPE_FREDDOCS, "data" DIR_SEPARATOR_STR "freddocs", ".html", CF_TYPE_DATA },
};
// clang-format on
#define CFILE_STACK_MAX 8
@@ -230,14 +224,8 @@ int cfile_init(const char *exe_dir, const char *cdrom_dir)
cfile_chdir(buf);
// set root directory
strncpy(Cfile_root_dir, buf, CFILE_ROOT_DIRECTORY_LEN-1);
strncpy(Cfile_user_dir, os_get_config_path().c_str(), CFILE_ROOT_DIRECTORY_LEN-1);
#ifdef SCP_UNIX
// Initialize path of old pilot files
extern const char* Osreg_user_dir_legacy;
snprintf(Cfile_user_dir_legacy, CFILE_ROOT_DIRECTORY_LEN-1, "%s/%s/", getenv("HOME"), Osreg_user_dir_legacy);
#endif
strcpy_s(Cfile_root_dir, buf);
strcpy_s(Cfile_user_dir, os_get_config_path().c_str());
for (i = 0; i < MAX_CFILE_BLOCKS; i++) {
Cfile_block_list[i].type = CFILE_BLOCK_UNUSED;
@@ -362,8 +350,7 @@ int cfile_push_chdir(int type)
return -1;
}
strncpy(Cfile_stack[Cfile_stack_pos++], OriginalDirectory,
CFILE_ROOT_DIRECTORY_LEN - 1);
strcpy_s(Cfile_stack[Cfile_stack_pos++], OriginalDirectory);
cf_create_default_path_string(dir, sizeof(dir) - 1, type, NULL);
@@ -486,17 +473,17 @@ char *cf_add_ext(const char *filename, const char *ext)
*
* @param filename Name of file to delete
* @param path_type Path type (CF_TYPE_xxx)
* @param location_flags Where to search for the location of the file to delete
*
* @return 0 on failure, 1 on success
*/
int cf_delete(const char *filename, int path_type)
int cf_delete(const char *filename, int path_type, uint32_t location_flags)
{
char longname[MAX_PATH_LEN];
Assert(CF_TYPE_SPECIFIED(path_type));
cf_create_default_path_string(longname, sizeof(longname) - 1,
path_type, filename);
cf_create_default_path_string(longname, sizeof(longname) - 1, path_type, filename, false, location_flags);
return (_unlink(longname) != -1);
}
@@ -522,12 +509,12 @@ int cf_access(const char *filename, int dir_type, int mode)
// If offset equates to boolean true, it was found in a VP and the logic will negate the function return
int cf_exists(const char *filename, int dir_type)
{
size_t offset = 1;
if ( (filename == NULL) || !strlen(filename) )
return 0;
return (cf_find_file_location(filename, dir_type, 0, NULL, NULL, &offset) && !offset);
auto find_res = cf_find_file_location(filename, dir_type);
return find_res.found && !find_res.offset;
}
// Goober5000
@@ -538,7 +525,7 @@ int cf_exists_full(const char *filename, int dir_type)
if ( (filename == NULL) || !strlen(filename) )
return 0;
return cf_find_file_location(filename, dir_type, 0, NULL, NULL, NULL);
return cf_find_file_location(filename, dir_type).found;
}
// same as the above, but with extension check
@@ -550,7 +537,7 @@ int cf_exists_full_ext(const char *filename, int dir_type, const int num_ext, co
if ( (num_ext <= 0) || (ext_list == NULL) )
return 0;
return (cf_find_file_location_ext(filename, num_ext, ext_list, dir_type, 0, NULL, NULL, NULL) != -1);
return cf_find_file_location_ext(filename, num_ext, ext_list, dir_type).found;
}
#ifdef _WIN32
@@ -624,7 +611,7 @@ static void mkdir_recursive(const char *path) {
// Creates the directory path if it doesn't exist. Even creates all its
// parent paths.
void cf_create_directory( int dir_type )
void cf_create_directory(int dir_type, uint32_t location_flags)
{
int num_dirs = 0;
int dir_tree[CF_MAX_PATH_TYPES];
@@ -646,7 +633,7 @@ void cf_create_directory( int dir_type )
int i;
for (i=num_dirs-1; i>=0; i-- ) {
cf_create_default_path_string( longname, sizeof(longname)-1, dir_tree[i], NULL );
cf_create_default_path_string(longname, sizeof(longname) - 1, dir_tree[i], nullptr, false, location_flags);
if (stat(longname, &statbuf) != 0) {
mprintf(( "CFILE: Creating new directory '%s'\n", longname ));
mkdir_recursive(longname);
@@ -673,14 +660,13 @@ extern int game_cd_changed();
// error ==> NULL
//
CFILE *_cfopen(const char* source, int line, const char *file_path, const char *mode, int type, int dir_type, bool localize)
CFILE* _cfopen(const char* source, int line, const char* file_path, const char* mode, int type, int dir_type,
bool localize, uint32_t location_flags)
{
/* Bobboau, what is this doing here? 31 is way too short... - Goober5000
if( strlen(file_path) > 31 )
Error(LOCATION, "file name %s too long, \nmust be less than 31 charicters", file_path);*/
char longname[_MAX_PATH];
if ( !cfile_inited ) {
Int3();
return NULL;
@@ -702,6 +688,8 @@ CFILE *_cfopen(const char* source, int line, const char *file_path, const char *
// the harddisk. No fancy packfile stuff here!
if ( strchr(mode,'w') || strchr(mode,'+') || strchr(mode,'a') ) {
char longname[_MAX_PATH];
// For write-only files, require a full path or a path type
#ifdef SCP_UNIX
if ( strpbrk(file_path, "/") ) {
@@ -715,9 +703,9 @@ CFILE *_cfopen(const char* source, int line, const char *file_path, const char *
Assert( dir_type != CF_TYPE_ANY );
// Create the directory if necessary
cf_create_directory( dir_type );
cf_create_directory(dir_type, location_flags);
cf_create_default_path_string( longname, sizeof(longname)-1, dir_type, file_path );
cf_create_default_path_string(longname, sizeof(longname) - 1, dir_type, file_path, false, location_flags);
}
Assert( !(type & CFILE_MEMORY_MAPPED) );
@@ -767,30 +755,29 @@ CFILE *_cfopen(const char* source, int line, const char *file_path, const char *
//================================================
// Search for file on disk, on cdrom, or in a packfile
size_t offset, size;
char copy_file_path[MAX_PATH_LEN]; // FIX change in memory from cf_find_file_location
strcpy_s(copy_file_path, file_path);
const void* file_data = nullptr;
if ( cf_find_file_location( copy_file_path, dir_type, sizeof(longname) - 1, longname, &size, &offset, localize, &file_data ) ) {
auto find_res = cf_find_file_location( copy_file_path, dir_type, localize, location_flags );
if ( find_res.found ) {
// Fount it, now create a cfile out of it
nprintf(("CFileDebug", "Requested file %s found at: %s\n", file_path, longname));
nprintf(("CFileDebug", "Requested file %s found at: %s\n", file_path, find_res.full_name.c_str()));
if ( type & CFILE_MEMORY_MAPPED ) {
// Can't open memory mapped files out of pack or memory files
if ( offset == 0 && file_data != nullptr ) {
if ( find_res.offset == 0 && find_res.data_ptr != nullptr ) {
#if defined _WIN32
HANDLE hFile;
hFile = CreateFile(longname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
hFile = CreateFile(find_res.full_name.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
return cf_open_mapped_fill_cfblock(source, line, hFile, dir_type);
}
#elif defined SCP_UNIX
FILE *fp = fopen( longname, "rb" );
FILE* fp = fopen(find_res.full_name.c_str(), "rb");
if (fp) {
return cf_open_mapped_fill_cfblock(source, line, fp, dir_type);
}
@@ -799,7 +786,8 @@ CFILE *_cfopen(const char* source, int line, const char *file_path, const char *
} else {
// since cfopen_special already has all the code to handle the opening we can just use that here
return _cfopen_special(source, line, longname, mode, size, offset, file_data, dir_type);
return _cfopen_special(source, line, find_res.full_name.c_str(), mode, find_res.size, find_res.offset,
find_res.data_ptr, dir_type);
}
}
@@ -907,7 +895,7 @@ static int cfget_cfile_block()
mprintf(("Out of cfile blocks! Currently opened files:\n"));
dump_opened_files();
Assertion(false, "There are no more free cfile blocks. This means that there are too many files opened by FSO.\n"
UNREACHABLE("There are no more free cfile blocks. This means that there are too many files opened by FSO.\n"
"This is probably caused by a programming or scripting error where a file does not get closed."); // out of free cfile blocks
return -1;
}
+92 -13
View File
@@ -95,6 +95,64 @@ typedef struct {
#define CF_SORT_TIME 2
#define CF_SORT_REVERSE 3
/**
* @brief Contains a collection of flags for specifying from where a CFILE should be opened
*
* There are two types of flags. CF_LOCATION_GAME_ROOT and CF_LOCATION_USER_ROOT specify in which basic root directory
* CFile should search for files.
*
* The remaining flags control what type of location may be used for the operation. It's possible to restrict the
* location to the primary mod, the remaining mods or the top-level root directory.
*/
enum CFileLocationFlags {
CF_LOCATION_ROOT_GAME = 1 << 0, //!< The game root location. This is the location of the game data (e.g. FS2 retail)
/**
* @brief The user directories.
*
* If the engine is in portable mode then using this flag exclusively will result in a failure to open files!
*/
CF_LOCATION_ROOT_USER = 1 << 1,
/**
* @brief The memory root
*
* This contains all the built-in files available to the engine.
*/
CF_LOCATION_ROOT_MEMORY = 1 << 2,
/**
* @brief Mask for extracting root type from a location bit field
*/
CF_LOCATION_ROOT_MASK = 0xFFFF,
CF_LOCATION_TYPE_ROOT = 1 << 16, //!< The basic, top-level root location
/**
* @brief The primary mod location.
*
* This is the mod that appears first on the command line. If there are no mods then the root location is considered
* to be the primary mod
*/
CF_LOCATION_TYPE_PRIMARY_MOD = 1 << 17,
/**
* @brief The remaining mods.
*
* If there are no mods on the command line then this might not include any valid location.
*/
CF_LOCATION_TYPE_SECONDARY_MODS = 1 << 18,
/**
* @brief Bitmask for extracting the type from a location bit field
*/
CF_LOCATION_TYPE_MASK = 0xFFFF0000,
/**
* @brief A combination of all flags
*
* This should be used when the default behavior without any location filtering is desired.
*/
CF_LOCATION_ALL = CF_LOCATION_ROOT_MASK | CF_LOCATION_TYPE_MASK
};
#define cfread_fix(file) (fix)cfread_int(file)
#define cfwrite_fix(i,file) cfwrite_int(i,file)
@@ -111,9 +169,6 @@ extern const char *Get_file_list_child;
#define CFILE_ROOT_DIRECTORY_LEN 256
extern char Cfile_root_dir[CFILE_ROOT_DIRECTORY_LEN];
extern char Cfile_user_dir[CFILE_ROOT_DIRECTORY_LEN];
#ifdef SCP_UNIX
extern char Cfile_user_dir_legacy[CFILE_ROOT_DIRECTORY_LEN];
#endif
//================= LOW-LEVEL FUNCTIONS ==================
int cfile_init(const char *exe_dir, const char *cdrom_dir=NULL);
@@ -130,11 +185,10 @@ char *cf_add_ext(const char *filename, const char *ext);
// return CF_TYPE (directory location type) of a CFILE you called cfopen() successfully on.
int cf_get_dir_type(CFILE *cfile);
// Opens the file. If no path is given, use the extension to look into the
// default path. If mode is NULL, delete the file.
CFILE *_cfopen(const char* source_file, int line, const char *filename, const char *mode,
int type = CFILE_NORMAL, int dir_type = CF_TYPE_ANY, bool localize = false);
// default path. If mode is NULL, delete the file.
CFILE* _cfopen(const char* source_file, int line, const char* filename, const char* mode, int type = CFILE_NORMAL,
int dir_type = CF_TYPE_ANY, bool localize = false, uint32_t location_flags = CF_LOCATION_ALL);
#define cfopen(...) _cfopen(LOCATION, __VA_ARGS__) // Pass source location to the function
// like cfopen(), but it accepts a fully qualified path only (ie, the result of a cf_find_file_location() call)
@@ -156,7 +210,7 @@ void cf_set_version( CFILE * cfile, int version );
void cf_set_max_read_len(CFILE *cfile, size_t len);
// Deletes a file. Returns 0 on error, 1 if successful
int cf_delete(const char *filename, int dir_type);
int cf_delete(const char *filename, int dir_type, uint32_t location_flags = CF_LOCATION_ALL);
// Same as _access function to read a file's access bits
int cf_access(const char *filename, int dir_type, int mode);
@@ -311,12 +365,26 @@ int cfwrite_string(const char *buf, CFILE *file);
*/
int cfwrite_string_len(const char *buf, CFILE *file);
int cf_get_file_list( SCP_vector<SCP_string> &list, int pathtype, const char *filter, int sort = CF_SORT_NONE, SCP_vector<file_list_info> *info = NULL );
int cf_get_file_list( int max, char **list, int type, const char *filter, int sort = CF_SORT_NONE, file_list_info *info = NULL );
int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char **list, int type, const char *filter, int sort = CF_SORT_NONE, file_list_info *info = NULL );
int cf_get_file_list(SCP_vector<SCP_string>& list, int pathtype, const char* filter, int sort = CF_SORT_NONE,
SCP_vector<file_list_info>* info = nullptr, uint32_t location_flags = CF_LOCATION_ALL);
int cf_get_file_list(int max, char** list, int type, const char* filter, int sort = CF_SORT_NONE,
file_list_info* info = nullptr, uint32_t location_flags = CF_LOCATION_ALL);
int cf_get_file_list_preallocated(int max, char arr[][MAX_FILENAME_LEN], char** list, int type, const char* filter,
int sort = CF_SORT_NONE, file_list_info* info = nullptr,
uint32_t location_flags = CF_LOCATION_ALL);
void cf_sort_filenames( int n, char **list, int sort, file_list_info *info = NULL );
void cf_sort_filenames( SCP_vector<SCP_string> &list, int sort, SCP_vector<file_list_info> *info = NULL );
struct CFileLocation {
bool found = false;
SCP_string full_name;
size_t size = 0;
size_t offset = 0;
const void* data_ptr = nullptr;
explicit CFileLocation(bool found_in = false) : found(found_in) {}
};
// Searches for a file. Follows all rules and precedence and searches
// CD's and pack files.
// Input: filespace - Filename & extension
@@ -326,7 +394,17 @@ void cf_sort_filenames( SCP_vector<SCP_string> &list, int sort, SCP_vector<file_
// size - File size
// offset - Offset into pack file. 0 if not a packfile.
// Returns: If not found returns 0.
int cf_find_file_location( const char *filespec, int pathtype, int max_out, char *pack_filename, size_t *size, size_t *offset, bool localize = false, const void** data_out = nullptr);
CFileLocation cf_find_file_location(const char* filespec, int pathtype, bool localize = false,
uint32_t location_flags = CF_LOCATION_ALL);
struct CFileLocationExt : public CFileLocation {
int extension_index = -1;
explicit CFileLocationExt(int extension_index_in = -1)
: CFileLocation(extension_index_in >= 0), extension_index(extension_index_in)
{
}
};
// Searches for a file. Follows all rules and precedence and searches
// CD's and pack files. Searches all locations in order for first filename using ext filter list.
@@ -340,7 +418,8 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
// offset - Offset into pack file. 0 if not a packfile.
// Returns: If not found returns -1, else returns offset into ext_list.
// (NOTE: This function is exponentially slow, so don't use it unless truely needed!!)
int cf_find_file_location_ext(const char *filename, const int ext_num, const char **ext_list, int pathtype, int max_out = 0, char *pack_filename = NULL, size_t *size = NULL, size_t *offset = NULL, bool localize = false, const void** data_out = nullptr);
CFileLocationExt cf_find_file_location_ext(const char* filename, const int ext_num, const char** ext_list, int pathtype,
bool localize = false);
// Functions to change directories
int cfile_chdir(const char *dir);
+263 -209
View File
@@ -48,9 +48,6 @@ enum CfileRootType {
CF_ROOTTYPE_MEMORY = 2,
};
// for a defined and specifically set location to get/send pilot/campaign files
SCP_string Pilot_file_path;
// Created by:
// specifying hard drive tree
// searching for pack files on hard drive // Found by searching all known paths
@@ -59,6 +56,7 @@ SCP_string Pilot_file_path;
typedef struct cf_root {
char path[CF_MAX_PATHNAME_LENGTH]; // Contains something like c:\projects\freespace or c:\projects\freespace\freespace.vp
int roottype; // CF_ROOTTYPE_PATH = Path, CF_ROOTTYPE_PACK =Pack file, CF_ROOTTYPE_MEMORY=In memory
uint32_t location_flags;
} cf_root;
// convenient type for sorting (see cf_build_pack_list())
@@ -347,9 +345,9 @@ void cf_build_pack_list( cf_root *root )
std::sort(temp_roots_sort, temp_roots_sort + temp_root_count, cf_packfile_sort_func);
// now insert them all into the real root list properly
cf_root *new_root;
for (i = 0; i < temp_root_count; i++) {
new_root = cf_create_root();
auto new_root = cf_create_root();
new_root->location_flags = root->location_flags;
strcpy_s( new_root->path, root->path );
#ifndef NDEBUG
@@ -378,10 +376,11 @@ static char normalize_directory_separator(char in)
return in;
}
static void cf_add_mod_roots(const char* rootDirectory)
static void cf_add_mod_roots(const char* rootDirectory, uint32_t basic_location)
{
if (Cmdline_mod)
{
bool primary = true;
for (const char* cur_pos=Cmdline_mod; strlen(cur_pos) != 0; cur_pos+= (strlen(cur_pos)+1))
{
SCP_stringstream ss;
@@ -405,9 +404,16 @@ static void cf_add_mod_roots(const char* rootDirectory)
cf_root* root = cf_create_root();
strncpy(root->path, rootPath.c_str(), CF_MAX_PATHNAME_LENGTH-1);
if (primary) {
root->location_flags = basic_location | CF_LOCATION_TYPE_PRIMARY_MOD;
} else {
root->location_flags = basic_location | CF_LOCATION_TYPE_SECONDARY_MODS;
}
root->roottype = CF_ROOTTYPE_PATH;
cf_build_pack_list(root);
primary = false;
}
}
}
@@ -425,10 +431,16 @@ void cf_build_root_list(const char *cdrom_dir)
#ifdef WIN32
// Nothing to do here, Windows uses the current directory as the base
#else
cf_add_mod_roots(Cfile_user_dir_legacy);
cf_add_mod_roots(os_get_legacy_user_dir(), CF_LOCATION_ROOT_USER);
root = cf_create_root();
strncpy(root->path, Cfile_user_dir_legacy, CF_MAX_PATHNAME_LENGTH - 1);
strncpy(root->path, os_get_legacy_user_dir(), CF_MAX_PATHNAME_LENGTH - 1);
root->location_flags |= CF_LOCATION_ROOT_USER | CF_LOCATION_TYPE_ROOT;
if (Cmdline_mod == nullptr || strlen(Cmdline_mod) <= 0) {
// If there are no mods then the root is the primary mod
root->location_flags |= CF_LOCATION_TYPE_PRIMARY_MOD;
}
// do we already have a slash? as in the case of a root directory install
if ((strlen(root->path) < (CF_MAX_PATHNAME_LENGTH - 1)) && (root->path[strlen(root->path) - 1] != DIR_SEPARATOR_CHAR)) {
@@ -436,10 +448,6 @@ void cf_build_root_list(const char *cdrom_dir)
}
root->roottype = CF_ROOTTYPE_PATH;
// If it wasn't set before, set the pilot path
if (Pilot_file_path.empty())
Pilot_file_path = root->path;
// Next, check any VP files under the current directory.
cf_build_pack_list(root);
#endif
@@ -449,13 +457,19 @@ void cf_build_root_list(const char *cdrom_dir)
{
// =========================================================================
// now look for mods under the users HOME directory to use before system ones
cf_add_mod_roots(Cfile_user_dir);
cf_add_mod_roots(Cfile_user_dir, CF_LOCATION_ROOT_USER);
// =========================================================================
// =========================================================================
// set users HOME directory as default for loading and saving files
root = cf_create_root();
strncpy(root->path, Cfile_user_dir, CF_MAX_PATHNAME_LENGTH - 1);
strcpy_s(root->path, Cfile_user_dir);
root->location_flags |= CF_LOCATION_ROOT_USER | CF_LOCATION_TYPE_ROOT;
if (Cmdline_mod == nullptr || strlen(Cmdline_mod) <= 0) {
// If there are no mods then the root is the primary mod
root->location_flags |= CF_LOCATION_TYPE_PRIMARY_MOD;
}
// do we already have a slash? as in the case of a root directory install
if ((strlen(root->path) < (CF_MAX_PATHNAME_LENGTH - 1)) && (root->path[strlen(root->path) - 1] != DIR_SEPARATOR_CHAR)) {
@@ -463,10 +477,6 @@ void cf_build_root_list(const char *cdrom_dir)
}
root->roottype = CF_ROOTTYPE_PATH;
// set the default player location to here
if (Pilot_file_path.empty())
Pilot_file_path = root->path;
// Next, check any VP files under the current directory.
cf_build_pack_list(root);
// =========================================================================
@@ -477,11 +487,17 @@ void cf_build_root_list(const char *cdrom_dir)
if ( !_getcwd(working_directory, CF_MAX_PATHNAME_LENGTH ) ) {
Error(LOCATION, "Can't get current working directory -- %d", errno );
}
cf_add_mod_roots(working_directory);
cf_add_mod_roots(working_directory, CF_LOCATION_ROOT_GAME);
root = cf_create_root();
root->location_flags |= CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT;
if (Cmdline_mod == nullptr || strlen(Cmdline_mod) <= 0) {
// If there are no mods then the root is the primary mod
root->location_flags |= CF_LOCATION_TYPE_PRIMARY_MOD;
}
strcpy_s(root->path, working_directory);
size_t path_len = strlen(root->path);
@@ -493,10 +509,6 @@ void cf_build_root_list(const char *cdrom_dir)
root->roottype = CF_ROOTTYPE_PATH;
// If the path wasn't set before use the working directory
if ( Pilot_file_path.empty() )
Pilot_file_path = root->path;
//======================================================
// Next, check any VP files under the current directory.
cf_build_pack_list(root);
@@ -517,6 +529,7 @@ void cf_build_root_list(const char *cdrom_dir)
// The final root is the in-memory root
root = cf_create_root();
root->location_flags = CF_LOCATION_ROOT_MEMORY | CF_LOCATION_TYPE_ROOT;
memset(root->path, 0, sizeof(root->path));
root->roottype = CF_ROOTTYPE_MEMORY;
@@ -977,15 +990,12 @@ void cf_free_secondary_filelist()
*
* @param filespec Filename & extension
* @param pathtype See CF_TYPE_ defines in CFILE.H
* @param max_out Maximum string length that should be stuffed into pack_filename
* @param pack_filename OUTPUT: Absolute path and filename of this file. Could be a packfile or the actual file.
* @param size OUTPUT: File size
* @param offset OUTPUT: Offset into pack file. 0 if not a packfile.
* @param localize Undertake localization
* @param location_flags Specifies where to search for the specified flag
*
* @return If not found returns 0.
* @return A structure which describes the found file
*/
int cf_find_file_location( const char *filespec, int pathtype, int max_out, char *pack_filename, size_t *size, size_t *offset, bool localize, const void** data_out )
CFileLocation cf_find_file_location(const char* filespec, int pathtype, bool localize, uint32_t location_flags)
{
int i;
uint ui;
@@ -993,7 +1003,6 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
char longname[MAX_PATH_LEN];
Assert( (filespec != NULL) && (strlen(filespec) > 0) ); //-V805
Assert( (pack_filename == NULL) || (max_out > 1) );
// see if we have something other than just a filename
// our current rules say that any file that specifies a direct
@@ -1009,16 +1018,15 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
#endif
FILE *fp = fopen(filespec, "rb" );
if (fp) {
if ( size ) *size = filelength(fileno(fp));
if ( offset ) *offset = 0;
if ( pack_filename ) {
strncpy( pack_filename, filespec, max_out );
}
CFileLocation res(true);
res.size = static_cast<size_t>(filelength(fileno(fp)));
res.offset = 0;
res.full_name = filespec;
fclose(fp);
return 1;
return res;
}
return 0; // If they give a full path, fail if not found.
return CFileLocation(); // If they give a full path, fail if not found.
}
// Search the hard drive for files first.
@@ -1057,43 +1065,39 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
}
if (cfs_slow_search) {
cf_create_default_path_string( longname, sizeof(longname)-1, search_order[ui], filespec, localize );
cf_create_default_path_string(longname, sizeof(longname) - 1, search_order[ui], filespec, localize,
location_flags);
#if defined _WIN32
_finddata_t findstruct;
intptr_t findhandle = _findfirst(longname, &findstruct);
if (findhandle != -1) {
if (size)
*size = findstruct.size;
CFileLocation res;
res.found = true;
res.size = static_cast<size_t>(findstruct.size);
_findclose(findhandle);
if (offset)
*offset = 0;
res.offset = 0;
res.full_name = longname;
if (pack_filename)
strncpy( pack_filename, longname, max_out );
return 1;
return res;
}
#endif
{
FILE *fp = fopen(longname, "rb" );
if (fp) {
if (size)
*size = filelength( fileno(fp) );
CFileLocation res(true);
res.size = static_cast<size_t>(filelength( fileno(fp) ));
fclose(fp);
if (offset)
*offset = 0;
res.offset = 0;
res.full_name = longname;
if (pack_filename)
strncpy(pack_filename, longname, max_out);
return 1;
return res;
}
}
}
@@ -1107,6 +1111,15 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
if ( (pathtype != CF_TYPE_ANY) && (pathtype != f->pathtype_index) )
continue;
if (location_flags != CF_LOCATION_ALL) {
// If a location flag was specified we need to check if the root of this file satisfies the request
auto root = cf_get_root(f->root_index);
if (!cf_check_location_flags(root->location_flags, location_flags)) {
// Root does not satisfy location flags
continue;
}
}
if (localize) {
// create localized filespec
@@ -1114,70 +1127,58 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
if ( lcl_add_dir_to_path_with_filename(longname, MAX_PATH_LEN - 1) ) {
if ( !stricmp(longname, f->name_ext) ) {
if (size)
*size = f->size;
CFileLocation res(true);
res.size = static_cast<size_t>(f->size);
res.offset = (size_t)f->pack_offset;
res.data_ptr = f->data;
if (offset)
*offset = (size_t)f->pack_offset;
if (f->data != nullptr) {
// This is an in-memory file so we just copy the pathtype name + file name
res.full_name = Pathtypes[f->pathtype_index].path;
res.full_name += DIR_SEPARATOR_STR;
res.full_name += f->name_ext;
} else if (f->pack_offset < 1) {
// This is a real file, return the actual file path
res.full_name = f->real_name;
} else {
// File is in a pack file
cf_root *r = cf_get_root(f->root_index);
if (data_out)
*data_out = f->data;
if (pack_filename) {
if (f->data != nullptr) {
// This is an in-memory file so we just copy the pathtype name + file name
strncpy(pack_filename, Pathtypes[f->pathtype_index].path, max_out);
strncat(pack_filename, DIR_SEPARATOR_STR, max_out);
strncat(pack_filename, f->name_ext, max_out);
} else if (f->pack_offset < 1) {
// This is a real file, return the actual file path
strncpy( pack_filename, f->real_name, max_out );
} else {
// File is in a pack file
cf_root *r = cf_get_root(f->root_index);
strncpy( pack_filename, r->path, max_out );
}
res.full_name = r->path;
}
return 1;
return res;
}
}
}
// file either not localized or localized version not found
if ( !stricmp(filespec, f->name_ext) ) {
if (size)
*size = f->size;
CFileLocation res(true);
res.size = static_cast<size_t>(f->size);
res.offset = (size_t)f->pack_offset;
res.data_ptr = f->data;
if (offset)
*offset = (size_t)f->pack_offset;
if (f->data != nullptr) {
// This is an in-memory file so we just copy the pathtype name + file name
res.full_name = Pathtypes[f->pathtype_index].path;
res.full_name += DIR_SEPARATOR_STR;
res.full_name += f->name_ext;
} else if (f->pack_offset < 1) {
// This is a real file, return the actual file path
res.full_name = f->real_name;
} else {
// File is in a pack file
cf_root *r = cf_get_root(f->root_index);
if (data_out)
*data_out = f->data;
if (pack_filename) {
if (f->data != nullptr) {
// This is an in-memory file so we just copy the pathtype name + file name
strncpy(pack_filename, Pathtypes[f->pathtype_index].path, max_out);
strncat(pack_filename, DIR_SEPARATOR_STR, max_out);
strncat(pack_filename, f->name_ext, max_out);
} else if (f->pack_offset < 1) {
// This is a real file, return the actual file path
strncpy( pack_filename, f->real_name, max_out );
} else {
// File is in a pack file
cf_root *r = cf_get_root(f->root_index);
strncpy( pack_filename, r->path, max_out );
}
res.full_name = r->path;
}
return 1;
return res;
}
}
return 0;
return CFileLocation();
}
// -- from parselo.cpp --
@@ -1194,14 +1195,11 @@ extern char *stristr(char *str, const char *substr);
* @param ext_list Extension filter list
* @param pathtype See CF_TYPE_ defines in CFILE.H
* @param max_out Maximum string length that should be stuffed into pack_filename
* @param pack_filename OUTPUT: Absolute path and filename of this file. Could be a packfile or the actual file.
* @param size OUTPUT: File size
* @param offset OUTPUT: Offset into pack file. 0 if not a packfile.
* @param localize Undertake localization
*
* @return If not found returns -1, else returns offset into ext_list.
* @return A structure containing information about the found file
*/
int cf_find_file_location_ext( const char *filename, const int ext_num, const char **ext_list, int pathtype, int max_out, char *pack_filename, size_t *size, size_t *offset, bool localize, const void** data_out)
CFileLocationExt cf_find_file_location_ext( const char *filename, const int ext_num, const char **ext_list, int pathtype, bool localize)
{
int cur_ext, i;
uint ui;
@@ -1213,7 +1211,6 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
Assert( (filename != NULL) && (strlen(filename) < MAX_FILENAME_LEN) );
Assert( (ext_list != NULL) && (ext_num > 1) ); // if we are searching for just one ext
// then this is the wrong function to use
Assert( (pack_filename == NULL) || (max_out > 1) );
// if we have a full path already then fail. this function if for searching via filter only!
@@ -1223,7 +1220,7 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
if ( strpbrk(filename,"/\\:") ) { // do we have a full path already?
#endif
Int3();
return 0;
return CFileLocationExt();
}
// Search the hard drive for files first.
@@ -1281,44 +1278,35 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
#if defined _WIN32
_finddata_t findstruct;
intptr_t findhandle = _findfirst(longname, &findstruct);
if (findhandle != -1) {
if (size)
*size = findstruct.size;
if (data_out)
*data_out = nullptr;
CFileLocationExt res(cur_ext);
res.found = true;
res.size = static_cast<size_t>(findstruct.size);
_findclose(findhandle);
if (offset)
*offset = 0;
res.offset = 0;
res.full_name = longname;
if (pack_filename)
strncpy( pack_filename, longname, max_out );
return cur_ext;
return res;
}
#endif
{
FILE *fp = fopen(longname, "rb" );
if (fp) {
if (size)
*size = filelength( fileno(fp) );
if (data_out)
*data_out = nullptr;
CFileLocationExt res(cur_ext);
res.found = true;
res.size = static_cast<size_t>(filelength( fileno(fp) ));
fclose(fp);
if (offset)
*offset = 0;
res.offset = 0;
res.full_name = longname;
if (pack_filename)
strncpy(pack_filename, longname, max_out);
return cur_ext;
return res;
}
}
}
@@ -1403,76 +1391,62 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
if ( lcl_add_dir_to_path_with_filename(longname, MAX_PATH_LEN - 1) ) {
if ( !stricmp(longname, f->name_ext) ) {
if (size)
*size = f->size;
CFileLocationExt res(cur_ext);
res.found = true;
res.size = static_cast<size_t>(f->size);
res.offset = (size_t)f->pack_offset;
res.data_ptr = f->data;
if (offset)
*offset = f->pack_offset;
if (f->data != nullptr) {
// This is an in-memory file so we just copy the pathtype name + file name
res.full_name = Pathtypes[f->pathtype_index].path;
res.full_name += DIR_SEPARATOR_STR;
res.full_name += f->name_ext;
} else if (f->pack_offset < 1) {
// This is a real file, return the actual file path
res.full_name = f->real_name;
} else {
// File is in a pack file
cf_root *r = cf_get_root(f->root_index);
if (data_out)
*data_out = f->data;
if (pack_filename) {
if (f->data != nullptr) {
// This is an in-memory file so we just copy the pathtype name + file name
strncpy(pack_filename, Pathtypes[f->pathtype_index].path, max_out);
strncat(pack_filename, DIR_SEPARATOR_STR, max_out);
strncat(pack_filename, f->name_ext, max_out);
}
else if (f->pack_offset < 1) {
// This is a real file, return the actual file path
strncpy(pack_filename, f->real_name, max_out);
}
else {
// File is in a pack file
cf_root *r = cf_get_root(f->root_index);
strncpy(pack_filename, r->path, max_out);
}
res.full_name = r->path;
}
// found it, so cleanup and return
file_list_index.clear();
return cur_ext;
return res;
}
}
}
// file either not localized or localized version not found
if ( !stricmp(filespec, f->name_ext) ) {
if (size)
*size = f->size;
CFileLocationExt res(cur_ext);
res.found = true;
res.size = static_cast<size_t>(f->size);
res.offset = (size_t)f->pack_offset;
res.data_ptr = f->data;
if (offset)
*offset = f->pack_offset;
if (f->data != nullptr) {
// This is an in-memory file so we just copy the pathtype name + file name
res.full_name = Pathtypes[f->pathtype_index].path;
res.full_name += DIR_SEPARATOR_STR;
res.full_name += f->name_ext;
} else if (f->pack_offset < 1) {
// This is a real file, return the actual file path
res.full_name = f->real_name;
} else {
// File is in a pack file
cf_root *r = cf_get_root(f->root_index);
if (data_out)
*data_out = f->data;
if (pack_filename) {
if (f->data != nullptr) {
// This is an in-memory file so we just copy the pathtype name + file name
strncpy(pack_filename, Pathtypes[f->pathtype_index].path, max_out);
strncat(pack_filename, DIR_SEPARATOR_STR, max_out);
strncat(pack_filename, f->name_ext, max_out);
}
else if (f->pack_offset < 1) {
// This is a real file, return the actual file path
strncpy(pack_filename, f->real_name, max_out);
}
else {
// File is in a pack file
cf_root *r = cf_get_root(f->root_index);
strncpy(pack_filename, r->path, max_out);
}
res.full_name = r->path;
}
// found it, so cleanup and return
file_list_index.clear();
return cur_ext;
return res;
}
// ok, we're still here, so strip off the extension again in order to
@@ -1483,7 +1457,7 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
}
}
return -1;
return CFileLocationExt();
}
@@ -1582,7 +1556,8 @@ static int cf_file_already_in_list( SCP_vector<SCP_string> &list, const char *fi
// This one has a 'type', which is a CF_TYPE_* value. Because this specifies the directory
// location, 'filter' only needs to be the filter itself, with no path information.
// See above descriptions of cf_get_file_list() for more information about how it all works.
int cf_get_file_list( SCP_vector<SCP_string> &list, int pathtype, const char *filter, int sort, SCP_vector<file_list_info> *info )
int cf_get_file_list(SCP_vector<SCP_string>& list, int pathtype, const char* filter, int sort,
SCP_vector<file_list_info>* info, uint32_t location_flags)
{
char *ptr;
uint i;
@@ -1610,7 +1585,8 @@ int cf_get_file_list( SCP_vector<SCP_string> &list, int pathtype, const char *fi
}
#if defined _WIN32
cf_create_default_path_string( filespec, sizeof(filespec)-1, pathtype, (char*)Get_file_list_child );
cf_create_default_path_string(filespec, sizeof(filespec) - 1, pathtype, (char*)Get_file_list_child, false,
location_flags);
strcat_s(filespec, DIR_SEPARATOR_STR);
strcat_s(filespec, filter);
@@ -1650,7 +1626,8 @@ int cf_get_file_list( SCP_vector<SCP_string> &list, int pathtype, const char *fi
}
#elif defined SCP_UNIX
cf_create_default_path_string( filespec, sizeof(filespec)-1, pathtype, (char*)Get_file_list_child );
cf_create_default_path_string(filespec, sizeof(filespec) - 1, pathtype, (char*)Get_file_list_child, false,
location_flags);
DIR *dirp;
struct dirent *dir;
@@ -1718,6 +1695,16 @@ int cf_get_file_list( SCP_vector<SCP_string> &list, int pathtype, const char *fi
continue;
}
if (location_flags != CF_LOCATION_ALL) {
// If a location flag was specified we need to check if the root of this file satisfies the request
auto root = cf_get_root(f->root_index);
if (!cf_check_location_flags(root->location_flags, location_flags)) {
// Root does not satisfy location flags
continue;
}
}
if ( !cf_matches_spec( filter,f->name_ext)) {
continue;
}
@@ -1795,7 +1782,8 @@ int cf_file_already_in_list( int num_files, char **list, const char *filename )
// This one has a 'type', which is a CF_TYPE_* value. Because this specifies the directory
// location, 'filter' only needs to be the filter itself, with no path information.
// See above descriptions of cf_get_file_list() for more information about how it all works.
int cf_get_file_list( int max, char **list, int pathtype, const char *filter, int sort, file_list_info *info )
int cf_get_file_list(int max, char** list, int pathtype, const char* filter, int sort, file_list_info* info,
uint32_t location_flags)
{
char *ptr;
uint i;
@@ -1818,7 +1806,7 @@ int cf_get_file_list( int max, char **list, int pathtype, const char *filter, in
char filespec[MAX_PATH_LEN];
#if defined _WIN32
cf_create_default_path_string( filespec, sizeof(filespec)-1, pathtype, filter );
cf_create_default_path_string(filespec, sizeof(filespec) - 1, pathtype, filter, false, location_flags);
_finddata_t find;
intptr_t find_handle;
@@ -1859,7 +1847,7 @@ int cf_get_file_list( int max, char **list, int pathtype, const char *filter, in
}
#elif defined SCP_UNIX
cf_create_default_path_string( filespec, sizeof(filespec)-1, pathtype, NULL );
cf_create_default_path_string(filespec, sizeof(filespec) - 1, pathtype, nullptr, false, location_flags);
DIR *dirp;
struct dirent *dir;
@@ -1932,6 +1920,16 @@ int cf_get_file_list( int max, char **list, int pathtype, const char *filter, in
continue;
}
if (location_flags != CF_LOCATION_ALL) {
// If a location flag was specified we need to check if the root of this file satisfies the request
auto root = cf_get_root(f->root_index);
if (!cf_check_location_flags(root->location_flags, location_flags)) {
// Root does not satisfy location flags
continue;
}
}
if (num_files >= max)
break;
@@ -2015,7 +2013,8 @@ int cf_file_already_in_list_preallocated( int num_files, char arr[][MAX_FILENAME
// This one has a 'type', which is a CF_TYPE_* value. Because this specifies the directory
// location, 'filter' only needs to be the filter itself, with no path information.
// See above descriptions of cf_get_file_list() for more information about how it all works.
int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char **list, int pathtype, const char *filter, int sort, file_list_info *info )
int cf_get_file_list_preallocated(int max, char arr[][MAX_FILENAME_LEN], char** list, int pathtype, const char* filter,
int sort, file_list_info* info, uint32_t location_flags)
{
int num_files = 0, own_flag = 0;
@@ -2044,7 +2043,7 @@ int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char *
// Search the default directories
#if defined _WIN32
cf_create_default_path_string( filespec, sizeof(filespec)-1, pathtype, filter );
cf_create_default_path_string(filespec, sizeof(filespec) - 1, pathtype, filter, false, location_flags);
intptr_t find_handle;
_finddata_t find;
@@ -2085,7 +2084,7 @@ int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char *
}
#elif defined SCP_UNIX
cf_create_default_path_string( filespec, sizeof(filespec)-1, pathtype, NULL );
cf_create_default_path_string(filespec, sizeof(filespec) - 1, pathtype, nullptr, false, location_flags);
DIR *dirp;
struct dirent *dir;
@@ -2121,7 +2120,7 @@ int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char *
if ( !Get_file_list_filter || (*Get_file_list_filter)(dir->d_name) ) {
strncpy(arr[num_files], dir->d_name, MAX_FILENAME_LEN - 1 );
strcpy_s(arr[num_files], dir->d_name );
char *ptr = strrchr(arr[num_files], '.');
if ( ptr ) {
*ptr = 0;
@@ -2156,6 +2155,16 @@ int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char *
continue;
}
if (location_flags != CF_LOCATION_ALL) {
// If a location flag was specified we need to check if the root of this file satisfies the request
auto root = cf_get_root(f->root_index);
if (!cf_check_location_flags(root->location_flags, location_flags)) {
// Root does not satisfy location flags
continue;
}
}
if (num_files >= max)
break;
@@ -2222,7 +2231,8 @@ int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char *
// filename - optional, if set, tacks the filename onto end of path.
// Output: path - Fully qualified pathname.
//Returns 0 if the result would be too long (invalid result)
int cf_create_default_path_string(char *path, uint path_max, int pathtype, const char *filename, bool localize )
int cf_create_default_path_string(char* path, uint path_max, int pathtype, const char* filename, bool localize,
uint32_t location_flags)
{
#ifdef SCP_UNIX
if ( filename && strpbrk(filename,"/") ) {
@@ -2233,7 +2243,22 @@ int cf_create_default_path_string(char *path, uint path_max, int pathtype, const
strncpy( path, filename, path_max );
} else {
cf_root *root = cf_get_root(0);
cf_root* root = nullptr;
for (auto i = 0; i < Num_roots; ++i) {
auto current_root = cf_get_root(i);
if (current_root->roottype != CF_ROOTTYPE_PATH) {
// We want a "real" path here so only path roots are valid
continue;
}
if (cf_check_location_flags(current_root->location_flags, location_flags)) {
// We found a valid root
root = current_root;
break;
}
}
if (!root) {
Assert( filename != NULL );
@@ -2243,12 +2268,7 @@ int cf_create_default_path_string(char *path, uint path_max, int pathtype, const
Assert(CF_TYPE_SPECIFIED(pathtype));
// force a specific directory to search for player files
if ( (pathtype == CF_TYPE_PLAYERS) || (pathtype == CF_TYPE_SINGLE_PLAYERS) || (pathtype == CF_TYPE_MULTI_PLAYERS) ) {
strncpy(path, Pilot_file_path.c_str(), path_max);
} else {
strncpy(path, root->path, path_max);
}
strncpy(path, root->path, path_max);
strcat_s(path, path_max, Pathtypes[pathtype].path);
@@ -2294,7 +2314,8 @@ int cf_create_default_path_string(char *path, uint path_max, int pathtype, const
// filename - optional, if set, tacks the filename onto end of path.
// Output: path - Fully qualified pathname.
//Returns 0 if the result would be too long (invalid result)
int cf_create_default_path_string( SCP_string &path, int pathtype, const char *filename, bool /*localize*/ )
int cf_create_default_path_string(SCP_string& path, int pathtype, const char* filename, bool /*localize*/,
uint32_t location_flags)
{
#ifdef SCP_UNIX
if ( filename && strpbrk(filename,"/") ) {
@@ -2305,7 +2326,22 @@ int cf_create_default_path_string( SCP_string &path, int pathtype, const char *f
path.assign(filename);
} else {
cf_root *root = cf_get_root(0);
cf_root* root = nullptr;
for (auto i = 0; i < Num_roots; ++i) {
auto current_root = cf_get_root(i);
if (current_root->roottype != CF_ROOTTYPE_PATH) {
// We want a "real" path here so only path roots are valid
continue;
}
if (cf_check_location_flags(current_root->location_flags, location_flags)) {
// We found a valid root
root = current_root;
break;
}
}
if (!root) {
Assert( filename != NULL );
@@ -2316,12 +2352,7 @@ int cf_create_default_path_string( SCP_string &path, int pathtype, const char *f
Assert(CF_TYPE_SPECIFIED(pathtype));
std::ostringstream s_path;
// force a specific directory to search for player files
if ( (pathtype == CF_TYPE_PLAYERS) || (pathtype == CF_TYPE_SINGLE_PLAYERS) || (pathtype == CF_TYPE_MULTI_PLAYERS) ) {
s_path << Pilot_file_path;
} else {
s_path << root->path;
}
s_path << root->path;
s_path << Pathtypes[pathtype].path;
@@ -2386,3 +2417,26 @@ void cfile_spew_pack_file_crcs()
fclose(out);
}
bool cf_check_location_flags(uint32_t check_flags, uint32_t desired_flags)
{
Assertion((check_flags & CF_LOCATION_ROOT_MASK) != 0, "check_flags must have a valid root value");
Assertion((check_flags & CF_LOCATION_TYPE_MASK) != 0, "check_flags must have a valid type value");
auto check_root = check_flags & CF_LOCATION_ROOT_MASK;
auto desired_root_flags = desired_flags & CF_LOCATION_ROOT_MASK;
// If the root part is not set then assume that every root matches
if (desired_root_flags != 0 && (check_root & desired_root_flags) == 0) {
return false;
}
auto check_type = check_flags & CF_LOCATION_TYPE_MASK;
auto desired_type_flags = desired_flags & CF_LOCATION_TYPE_MASK;
if (desired_type_flags != 0 && (check_type & desired_type_flags) == 0) {
return false;
}
return true;
}
+6 -2
View File
@@ -29,6 +29,8 @@ typedef struct cf_pathtype {
// During cfile_init, verify that Pathtypes[n].index == n for each item
extern cf_pathtype Pathtypes[CF_MAX_PATH_TYPES];
bool cf_check_location_flags(uint32_t check_flags, uint32_t desired_flags);
// Returns the default storage path for files given a
// particular pathtype. In other words, the path to
// the unpacked, non-cd'd, stored on hard drive path.
@@ -39,7 +41,9 @@ extern cf_pathtype Pathtypes[CF_MAX_PATH_TYPES];
// filename - optional, if set, tacks the filename onto end of path.
// Output: path - Fully qualified pathname.
//Returns 0 if result would be too long (invalid result)
int cf_create_default_path_string( char *path, uint path_max, int pathtype, const char *filename=NULL, bool localize = false);
int cf_create_default_path_string( SCP_string &path, int pathtype, const char *filename=NULL, bool localize = false );
int cf_create_default_path_string(char* path, uint path_max, int pathtype, const char* filename = nullptr,
bool localize = false, uint32_t location_flags = CF_LOCATION_ALL);
int cf_create_default_path_string(SCP_string& path, int pathtype, const char* filename = nullptr, bool localize = false,
uint32_t location_flags = CF_LOCATION_ALL);
#endif //_CFILESYSTEM_H
+10 -7
View File
@@ -173,7 +173,6 @@ Flag exe_params[] =
{ "-no_deferred", "Disable Deferred Lighting", true, EASY_DEFAULT_MEM, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_deferred"},
{ "-enable_shadows", "Enable Shadows", true, EASY_MEM_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_shadows"},
{ "-no_vsync", "Disable vertical sync", true, 0, EASY_DEFAULT, "Game Speed", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_vsync", },
{ "-cache_bitmaps", "Cache bitmaps between missions", true, 0, EASY_DEFAULT_MEM, "Game Speed", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-cache_bitmaps", },
{ "-dualscanlines", "Add another pair of scanning lines", true, 0, EASY_DEFAULT, "HUD", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-dualscanlines", },
{ "-targetinfo", "Enable info next to target", true, 0, EASY_DEFAULT, "HUD", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-targetinfo", },
@@ -363,11 +362,9 @@ int Cmdline_no_deferred_lighting = 0;
int Cmdline_aniso_level = 0;
// Game Speed related
cmdline_parm cache_bitmaps_arg("-cache_bitmaps", NULL, AT_NONE); // Cmdline_cache_bitmaps
cmdline_parm no_fpscap("-no_fps_capping", "Don't limit frames-per-second", AT_NONE); // Cmdline_NoFPSCap
cmdline_parm no_vsync_arg("-no_vsync", NULL, AT_NONE); // Cmdline_no_vsync
int Cmdline_cache_bitmaps = 0; // caching of bitmaps between missions (faster loads, can hit swap on reload with <512 Meg RAM though) - taylor
int Cmdline_NoFPSCap = 0; // Disable FPS capping - kazan
int Cmdline_no_vsync = 0;
@@ -546,6 +543,7 @@ cmdline_parm deprecated_htl_arg("-nohtl", "Deprecated", AT_NONE);
cmdline_parm deprecated_brieflighting_arg("-brief_lighting", "Deprecated", AT_NONE);
cmdline_parm deprecated_sndpreload_arg("-snd_preload", "Deprecated", AT_NONE);
cmdline_parm deprecated_missile_lighting_arg("-missile_lighting", "Deprecated", AT_NONE);
cmdline_parm deprecated_cache_bitmaps_arg("-cache_bitmaps", "Deprecated", AT_NONE);
int Cmdline_deprecated_spec = 0;
int Cmdline_deprecated_glow = 0;
@@ -556,6 +554,7 @@ int Cmdline_deprecated_jpgtga = 0;
int Cmdline_deprecated_nohtl = 0;
bool Cmdline_deprecated_brief_lighting = 0;
bool Cmdline_deprecated_missile_lighting = false;
bool Cmdline_deprecated_cache_bitmaps = false;
#ifndef NDEBUG
// NOTE: this assumes that os_init() has already been called but isn't a fatal error if it hasn't
@@ -626,6 +625,10 @@ void cmdline_debug_print_cmdline()
{
mprintf(("Deprecated flag '-missile_lighting' found. Please remove from your cmdline.\n"));
}
if (Cmdline_deprecated_cache_bitmaps) {
mprintf(("Deprecated flag '-cache_bitmaps' found. Please remove from your cmdline.\n"));
}
}
#endif
@@ -1965,10 +1968,6 @@ bool SetCmdlineParams()
Cmdline_ballistic_gauge = 1;
}
if ( cache_bitmaps_arg.found() ) {
Cmdline_cache_bitmaps = 1;
}
if(old_collision_system.found())
Cmdline_old_collision_sys = 1;
@@ -2159,6 +2158,10 @@ bool SetCmdlineParams()
Cmdline_deprecated_missile_lighting = true;
}
if (deprecated_cache_bitmaps_arg.found()) {
Cmdline_deprecated_cache_bitmaps = true;
}
return true;
}
-1
View File
@@ -82,7 +82,6 @@ extern int Cmdline_no_emissive;
extern int Cmdline_aniso_level;
// Game Speed related
extern int Cmdline_cache_bitmaps;
extern int Cmdline_NoFPSCap;
extern int Cmdline_no_vsync;
+6
View File
@@ -3,6 +3,12 @@
#include <memory>
namespace cutscene {
FrameSize::FrameSize(size_t in_width, size_t in_height, size_t in_stride)
: width(in_width), height(in_height), stride(in_stride)
{
}
FrameSize::FrameSize() = default;
Decoder::Decoder() : m_decoding(true) {
}
+18 -11
View File
@@ -10,28 +10,26 @@ struct FrameSize {
size_t width = 0;
size_t height = 0;
size_t stride = 0;
FrameSize(size_t width, size_t in_height, size_t in_stride);
FrameSize();
};
class VideoFrame {
protected:
VideoFrame() {}
VideoFrame() = default;
public:
virtual ~VideoFrame() {}
public:
virtual ~VideoFrame() = default;
double frameTime = -1.0;
int id = -1;
FrameSize ySize;
FrameSize uvSize;
virtual size_t getPlaneNumber() = 0;
struct DataPointers {
ubyte* y;
ubyte* u;
ubyte* v;
};
virtual FrameSize getPlaneSize(size_t plane) = 0;
virtual DataPointers getDataPointers() = 0;
virtual void* getPlaneData(size_t plane) = 0;
};
/**
@@ -43,10 +41,19 @@ using FramePtr = std::unique_ptr<T>;
typedef std::unique_ptr<VideoFrame> VideoFramePtr;
enum class FramePixelFormat {
Invalid,
YUV420,
BGR,
BGRA
};
struct MovieProperties {
FrameSize size;
float fps = -1.0f;
FramePixelFormat pixelFormat = FramePixelFormat::Invalid;
};
struct AudioFrame {
+67 -24
View File
@@ -14,46 +14,85 @@ struct movie_vertex {
namespace cutscene {
namespace player {
VideoPresenter::VideoPresenter(const MovieProperties& props) {
VideoPresenter::VideoPresenter(const MovieProperties& props) : _properties(props)
{
GR_DEBUG_SCOPE("Init video");
_planeTextureHandles.fill(-1);
auto w = static_cast<int>(props.size.width);
auto h = static_cast<int>(props.size.height);
// Create buffer textures
_yTexBuffer.reset(new uint8_t[w * h]);
_ytex = bm_create(8, w, h, _yTexBuffer.get(), BMP_AABITMAP);
switch (props.pixelFormat) {
case FramePixelFormat::YUV420:
_planeTextureBuffers[0].reset(new uint8_t[w * h]);
_planeTextureHandles[0] = bm_create(8, w, h, _planeTextureBuffers[0].get(), BMP_AABITMAP);
_uTexBuffer.reset(new uint8_t[w / 2 * h / 2]);
_utex = bm_create(8, w / 2, h / 2, _uTexBuffer.get(), BMP_AABITMAP);
_planeTextureBuffers[1].reset(new uint8_t[w / 2 * h / 2]);
_planeTextureHandles[1] = bm_create(8, w / 2, h / 2, _planeTextureBuffers[1].get(), BMP_AABITMAP);
_vTexBuffer.reset(new uint8_t[w / 2 * h / 2]);
_vtex = bm_create(8, w / 2, h / 2, _vTexBuffer.get(), BMP_AABITMAP);
_planeTextureBuffers[2].reset(new uint8_t[w / 2 * h / 2]);
_planeTextureHandles[2] = bm_create(8, w / 2, h / 2, _planeTextureBuffers[2].get(), BMP_AABITMAP);
material_set_movie(&_render_material, _ytex, _utex, _vtex);
material_set_movie(&_movie_material, _planeTextureHandles[0], _planeTextureHandles[1], _planeTextureHandles[2]);
break;
case FramePixelFormat::BGR:
_planeTextureBuffers[0].reset(new uint8_t[w * h * 3]);
_planeTextureHandles[0] = bm_create(24, w, h, _planeTextureBuffers[0].get(), 0);
material_set_unlit(&_rgb_material, _planeTextureHandles[0], 1.0f, false, false);
break;
case FramePixelFormat::BGRA:
_planeTextureBuffers[0].reset(new uint8_t[w * h * 4]);
_planeTextureHandles[0] = bm_create(32, w, h, _planeTextureBuffers[0].get(), 0);
material_set_unlit(&_rgb_material, _planeTextureHandles[0], 1.0f, true, false);
break;
default:
UNREACHABLE("Unhandled enum value!");
break;
}
}
VideoPresenter::~VideoPresenter() {
GR_DEBUG_SCOPE("Deinit video");
bm_release(_ytex);
bm_release(_utex);
bm_release(_vtex);
_ytex = _utex = _vtex = -1;
for (auto& handle : _planeTextureHandles) {
if (handle > 0) {
bm_release(handle);
handle = -1;
}
}
}
void VideoPresenter::uploadVideoFrame(const VideoFramePtr& frame) {
GR_DEBUG_SCOPE("Update video frame");
auto ptrs = frame->getDataPointers();
memcpy(_yTexBuffer.get(), ptrs.y, frame->ySize.stride * frame->ySize.height);
memcpy(_uTexBuffer.get(), ptrs.u, frame->uvSize.stride * frame->uvSize.height);
memcpy(_vTexBuffer.get(), ptrs.v, frame->uvSize.stride * frame->uvSize.height);
for (size_t i = 0; i < frame->getPlaneNumber(); ++i) {
auto size = frame->getPlaneSize(i);
auto data = frame->getPlaneData(i);
gr_update_texture(_ytex, 8, _yTexBuffer.get(), (int) frame->ySize.width, (int) frame->ySize.height);
gr_update_texture(_utex, 8, _uTexBuffer.get(), (int) frame->uvSize.width, (int) frame->uvSize.height);
gr_update_texture(_vtex, 8, _vTexBuffer.get(), (int) frame->uvSize.width, (int) frame->uvSize.height);
memcpy(_planeTextureBuffers[i].get(), data, size.stride * size.height);
int bpp = 0;
switch (_properties.pixelFormat) {
case FramePixelFormat::YUV420:
bpp = 8;
break;
case FramePixelFormat::BGR:
bpp = 24;
break;
case FramePixelFormat::BGRA:
bpp = 32;
break;
default:
UNREACHABLE("Unhandled enum value!");
break;
}
gr_update_texture(_planeTextureHandles[i], bpp, _planeTextureBuffers[i].get(), static_cast<int>(size.width),
static_cast<int>(size.height));
}
}
void VideoPresenter::displayFrame(float x1, float y1, float x2, float y2) {
@@ -85,10 +124,14 @@ void VideoPresenter::displayFrame(float x1, float y1, float x2, float y2) {
auto offset = gr_add_to_immediate_buffer(sizeof(vertex_data), vertex_data);
vertex_layout layout;
layout.add_vertex_component(vertex_format_data::POSITION2, sizeof(vertex_data[0]), offset + offsetof(movie_vertex, pos));
layout.add_vertex_component(vertex_format_data::TEX_COORD2, sizeof(vertex_data[0]), offset + offsetof(movie_vertex, uv));
layout.add_vertex_component(vertex_format_data::POSITION2, sizeof(vertex_data[0]), offsetof(movie_vertex, pos));
layout.add_vertex_component(vertex_format_data::TEX_COORD2, sizeof(vertex_data[0]), offsetof(movie_vertex, uv));
gr_render_movie(&_render_material, PRIM_TYPE_TRISTRIP, &layout, 4, gr_immediate_buffer_handle);
if (_properties.pixelFormat == FramePixelFormat::YUV420) {
gr_render_movie(&_movie_material, PRIM_TYPE_TRISTRIP, &layout, 4, gr_immediate_buffer_handle, offset);
} else {
gr_render_primitives(&_rgb_material, PRIM_TYPE_TRISTRIP, &layout, 0, 4, gr_immediate_buffer_handle, offset);
}
}
}
+5 -8
View File
@@ -12,16 +12,13 @@ namespace cutscene {
namespace player {
class VideoPresenter {
int _ytex = -1;
std::unique_ptr<uint8_t[]> _yTexBuffer;
MovieProperties _properties;
int _utex = -1;
std::unique_ptr<uint8_t[]> _uTexBuffer;
std::array<int, 3> _planeTextureHandles;
std::array<std::unique_ptr<uint8_t[]>, 3> _planeTextureBuffers;
int _vtex = -1;
std::unique_ptr<uint8_t[]> _vTexBuffer;
movie_material _render_material;
movie_material _movie_material;
material _rgb_material; // Material used when a RGB/RGBA movie is played
public:
explicit VideoPresenter(const MovieProperties& props);
+92 -19
View File
@@ -33,17 +33,18 @@ class AVPacketScope
}
};
const char* CHECKED_EXTENSIONS[] = {
"webm",
"mp4",
"ogg",
"mve"
};
const char* CHECKED_EXTENSIONS[] = {"webm", "mp4", "ogg",
"png", // This is designed to be used with APNG animations
"mve"};
const char *CHECKED_SUBT_EXTENSIONS[] = {"srt"};
const char* CHECKED_SUBT_EXTENSIONS[] = {"srt"};
double getFrameRate(AVStream* stream, AVCodecContext* codecCtx) {
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(58, 3, 102)
auto fps = av_q2d(stream->r_frame_rate);
#else
auto fps = av_q2d(av_stream_get_r_frame_rate(stream));
#endif
if (fps < 0.000001)
{
@@ -58,7 +59,7 @@ double getFrameRate(AVStream* stream, AVCodecContext* codecCtx) {
return fps;
}
CodecContextParameters getCodecParameters(AVStream *stream) {
CodecContextParameters getCodecParameters(AVStream* stream) {
CodecContextParameters paras;
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
paras.width = stream->codecpar->width;
@@ -84,7 +85,7 @@ CodecContextParameters getCodecParameters(AVStream *stream) {
return paras;
}
SCP_string normalizeLanguage(const char *langauge_name) {
SCP_string normalizeLanguage(const char* langauge_name) {
if (!stricmp(langauge_name, "eng")) {
return "English";
}
@@ -101,6 +102,72 @@ SCP_string normalizeLanguage(const char *langauge_name) {
// Default to english for everything else
return "English";
}
/**
* @brief Given a FFmpeg pixel format returns the format it should be converted to
* @param in_fmt The input format
* @return The output format
*/
AVPixelFormat getConversionFormat(AVPixelFormat in_fmt)
{
switch (in_fmt) {
case AV_PIX_FMT_RGB24:
case AV_PIX_FMT_BGR24:
case AV_PIX_FMT_BGR8:
case AV_PIX_FMT_BGR4:
case AV_PIX_FMT_BGR4_BYTE:
case AV_PIX_FMT_RGB8:
case AV_PIX_FMT_RGB4:
case AV_PIX_FMT_RGB4_BYTE:
case AV_PIX_FMT_RGB48BE:
case AV_PIX_FMT_RGB48LE:
case AV_PIX_FMT_RGB565BE:
case AV_PIX_FMT_RGB565LE:
case AV_PIX_FMT_RGB555BE:
case AV_PIX_FMT_RGB555LE:
case AV_PIX_FMT_BGR565BE:
case AV_PIX_FMT_BGR565LE:
case AV_PIX_FMT_BGR555BE:
case AV_PIX_FMT_BGR555LE:
case AV_PIX_FMT_RGB444LE:
case AV_PIX_FMT_RGB444BE:
case AV_PIX_FMT_BGR444LE:
case AV_PIX_FMT_BGR444BE:
case AV_PIX_FMT_BGR48BE:
case AV_PIX_FMT_BGR48LE:
case AV_PIX_FMT_0RGB:
case AV_PIX_FMT_RGB0:
case AV_PIX_FMT_0BGR:
case AV_PIX_FMT_BGR0:
return AV_PIX_FMT_BGR24;
case AV_PIX_FMT_RGBA64BE:
case AV_PIX_FMT_RGBA64LE:
case AV_PIX_FMT_BGRA64BE:
case AV_PIX_FMT_BGRA64LE:
case AV_PIX_FMT_ARGB:
case AV_PIX_FMT_RGBA:
case AV_PIX_FMT_ABGR:
case AV_PIX_FMT_BGRA:
return AV_PIX_FMT_BGRA;
default:
// Assume that everything else is converted to YUV 420
return AV_PIX_FMT_YUV420P;
}
}
FramePixelFormat getPixelFormat(AVPixelFormat fmt)
{
switch (fmt) {
case AV_PIX_FMT_BGR24:
return FramePixelFormat::BGR;
case AV_PIX_FMT_BGRA:
return FramePixelFormat::BGRA;
default:
return FramePixelFormat::YUV420;
}
}
}
namespace cutscene {
@@ -146,8 +213,9 @@ std::unique_ptr<InputStream> openStream(const SCP_string& name) {
return input;
}
std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream> &stream,
std::unique_ptr<InputStream> &subt) {
std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream>& stream,
std::unique_ptr<InputStream>& subt)
{
std::unique_ptr<DecoderStatus> status(new DecoderStatus());
auto ctx = stream->m_ctx->ctx();
@@ -205,18 +273,18 @@ std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream> &st
if (status->subtitleStream == nullptr) {
// We don't have an external subtitle stream or loading from that file has failed
auto &current_language = Lcl_languages[Lcl_current_lang];
auto& current_language = Lcl_languages[Lcl_current_lang];
for (uint32_t i = 0; i < ctx->nb_streams; ++i) {
auto test_stream = ctx->streams[i];
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
auto &pars = test_stream->codecpar;
auto& pars = test_stream->codecpar;
if (!(pars->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
continue;
}
#endif
AVDictionaryEntry *tag = nullptr;
AVDictionaryEntry* tag = nullptr;
if ((tag = av_dict_get(test_stream->metadata, "language", nullptr, 0)) == nullptr) {
continue;
}
@@ -340,8 +408,9 @@ std::unique_ptr<InputStream> openInputStream(const SCP_string& name) {
return nullptr;
}
std::unique_ptr<InputStream> openSubtitleStream(const SCP_string &name) {
auto &current_language = Lcl_languages[Lcl_current_lang];
std::unique_ptr<InputStream> openSubtitleStream(const SCP_string& name)
{
auto& current_language = Lcl_languages[Lcl_current_lang];
for (auto ext : CHECKED_SUBT_EXTENSIONS) {
SCP_string fileName;
@@ -397,18 +466,21 @@ bool FFMPEGDecoder::initialize(const SCP_string& fileName) {
return true;
}
MovieProperties FFMPEGDecoder::getProperties() const {
MovieProperties FFMPEGDecoder::getProperties() const
{
MovieProperties props;
props.size.width = static_cast<size_t>(m_status->videoCodecPars.width);
props.size.height = static_cast<size_t>(m_status->videoCodecPars.height);
props.fps = static_cast<float>(getFrameRate(m_status->videoStream, m_status->videoCodecCtx));
props.pixelFormat = getPixelFormat(getConversionFormat(m_status->videoCodecPars.pixel_format));
return props;
}
void FFMPEGDecoder::startDecoding() {
std::unique_ptr<VideoDecoder> videoDecoder(new VideoDecoder(m_status.get()));
std::unique_ptr<VideoDecoder> videoDecoder(new VideoDecoder(m_status.get(), getConversionFormat(m_status->videoCodecPars.pixel_format)));
std::unique_ptr<AudioDecoder> audioDecoder;
std::unique_ptr<SubtitleDecoder> subtitleDecoder;
@@ -520,7 +592,8 @@ void FFMPEGDecoder::close() {
m_subtitleInput = nullptr;
}
}
void FFMPEGDecoder::runSubtitleDecoder(SubtitleDecoder *decoder) {
void FFMPEGDecoder::runSubtitleDecoder(SubtitleDecoder* decoder)
{
auto ctx = m_subtitleInput->m_ctx->ctx();
AVPacket packet;
+1 -1
View File
@@ -20,7 +20,7 @@ class FFMPEGDecoder: public Decoder {
bool hasExternalSubtitle() const;
void runSubtitleDecoder(SubtitleDecoder *decoder);
void runSubtitleDecoder(SubtitleDecoder* decoder);
public:
FFMPEGDecoder();
+58 -62
View File
@@ -3,11 +3,9 @@
#include "tracing/tracing.h"
namespace {
const AVPixelFormat DESTINATION_FORMAT = AV_PIX_FMT_YUV420P;
SwsContext* getSWSContext(int width, int height, AVPixelFormat fmt) {
return sws_getContext(width, height, fmt, width, height, DESTINATION_FORMAT,
SWS_BILINEAR, nullptr, nullptr, nullptr);
SwsContext* getSWSContext(int width, int height, AVPixelFormat fmt, AVPixelFormat destination_fmt)
{
return sws_getContext(width, height, fmt, width, height, destination_fmt, SWS_BILINEAR, nullptr, nullptr, nullptr);
}
double getFrameTime(int64_t pts, AVRational time_base) {
@@ -18,34 +16,53 @@ double getFrameTime(int64_t pts, AVRational time_base) {
namespace cutscene {
namespace ffmpeg {
class FFMPEGVideoFrame: public VideoFrame {
public:
FFMPEGVideoFrame() : frame(nullptr) {
}
size_t _width;
size_t _height;
AVFrame* _frame;
public:
FFMPEGVideoFrame(size_t width, size_t height, AVFrame* frame) : _width(width), _height(height), _frame(frame) {}
~FFMPEGVideoFrame() override {
if (frame != nullptr) {
av_freep(&frame->data[0]);
av_frame_free(&frame);
if (_frame != nullptr) {
av_freep(&_frame->data[0]);
av_frame_free(&_frame);
}
}
DataPointers getDataPointers() override {
DataPointers ptrs;
ptrs.y = frame->data[0];
ptrs.u = frame->data[1];
ptrs.v = frame->data[2];
return ptrs;
size_t getPlaneNumber() override
{
switch (_frame->format) {
case AV_PIX_FMT_YUV420P:
// YUV data is planar
return 3;
default:
// Everything else is packed
return 1;
}
}
FrameSize getPlaneSize(size_t plane) override
{
switch (_frame->format) {
case AV_PIX_FMT_YUV420P: {
// YUV data is planar
auto width = plane > 0 ? _width / 2 : _width;
auto height = plane > 0 ? _height / 2 : _height;
AVFrame* frame;
return {width, height, (size_t)_frame->linesize[plane]};
}
default:
// Everything else is packed
return {_width, _height, (size_t)_frame->linesize[plane]};
}
}
void* getPlaneData(size_t plane) override { return _frame->data[plane]; }
};
VideoDecoder::VideoDecoder(DecoderStatus* status)
: FFMPEGStreamDecoder(status),
m_frameId(0) {
VideoDecoder::VideoDecoder(DecoderStatus* status, AVPixelFormat destination_fmt)
: FFMPEGStreamDecoder(status), m_frameId(0), m_destinationFormat(destination_fmt)
{
m_swsCtx = getSWSContext(m_status->videoCodecPars.width, m_status->videoCodecPars.height,
m_status->videoCodecPars.pixel_format);
m_status->videoCodecPars.pixel_format, destination_fmt);
}
VideoDecoder::~VideoDecoder() {
@@ -53,53 +70,32 @@ VideoDecoder::~VideoDecoder() {
}
void VideoDecoder::convertAndPushPicture(const AVFrame* frame) {
// Allocate a picture to hold the YUV data
// Allocate a picture to hold the destination data
AVFrame* yuvFrame = av_frame_alloc();
av_frame_copy(yuvFrame, frame);
yuvFrame->format = DESTINATION_FORMAT;
yuvFrame->format = m_destinationFormat;
av_image_alloc(yuvFrame->data,
yuvFrame->linesize,
m_status->videoCodecPars.width,
m_status->videoCodecPars.height,
DESTINATION_FORMAT,
1);
av_image_alloc(yuvFrame->data, yuvFrame->linesize, m_status->videoCodecPars.width, m_status->videoCodecPars.height,
m_destinationFormat, 1);
std::unique_ptr<FFMPEGVideoFrame> videoFramePtr(new FFMPEGVideoFrame());
if (m_status->videoCodecPars.pixel_format == DESTINATION_FORMAT) {
av_image_copy(yuvFrame->data,
yuvFrame->linesize,
(const uint8_t**) (frame->data),
frame->linesize,
DESTINATION_FORMAT,
m_status->videoCodecPars.width,
m_status->videoCodecPars.height);
if (m_status->videoCodecPars.pixel_format == m_destinationFormat) {
av_image_copy(yuvFrame->data, yuvFrame->linesize, (const uint8_t**)(frame->data), frame->linesize,
m_destinationFormat, m_status->videoCodecPars.width, m_status->videoCodecPars.height);
} else {
// Convert frame to YUV
sws_scale(
m_swsCtx,
(uint8_t const* const*) frame->data,
frame->linesize,
0,
m_status->videoCodecPars.height,
yuvFrame->data,
yuvFrame->linesize
);
// Convert frame to destination format
sws_scale(m_swsCtx, (uint8_t const* const*)frame->data, frame->linesize, 0, m_status->videoCodecPars.height,
yuvFrame->data, yuvFrame->linesize);
}
std::unique_ptr<FFMPEGVideoFrame> videoFramePtr(
new FFMPEGVideoFrame(static_cast<size_t>(m_status->videoCodecPars.width),
static_cast<size_t>(m_status->videoCodecPars.height), yuvFrame));
videoFramePtr->id = ++m_frameId;
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(58, 3, 102)
videoFramePtr->frameTime = getFrameTime(frame->best_effort_timestamp, m_status->videoStream->time_base);
#else
videoFramePtr->frameTime = getFrameTime(av_frame_get_best_effort_timestamp(frame), m_status->videoStream->time_base);
videoFramePtr->frame = yuvFrame;
videoFramePtr->ySize.height = static_cast<size_t>(m_status->videoCodecPars.height);
videoFramePtr->ySize.width = static_cast<size_t>(m_status->videoCodecPars.width);
videoFramePtr->ySize.stride = static_cast<size_t>(yuvFrame->linesize[0]);
// 420P means that the UV channels have half the width and height
videoFramePtr->uvSize.height = static_cast<size_t>(m_status->videoCodecPars.height / 2);
videoFramePtr->uvSize.width = static_cast<size_t>(m_status->videoCodecPars.width / 2);
videoFramePtr->uvSize.stride = static_cast<size_t>(yuvFrame->linesize[1]);
#endif
pushFrame(VideoFramePtr(videoFramePtr.release()));
}
+2 -1
View File
@@ -9,11 +9,12 @@ class VideoDecoder: public FFMPEGStreamDecoder<VideoFrame> {
private:
int m_frameId;
SwsContext* m_swsCtx;
AVPixelFormat m_destinationFormat;
void convertAndPushPicture(const AVFrame* frame);
public:
explicit VideoDecoder(DecoderStatus* status);
explicit VideoDecoder(DecoderStatus* status, AVPixelFormat destination_fmt);
~VideoDecoder() override;
+5 -3
View File
@@ -202,10 +202,12 @@ void movie_display_loop(Player* player, PlaybackState* state) {
auto passed = timestamp - lastDisplayTimestamp;
lastDisplayTimestamp = timestamp;
// Play as long as the player reports that there is more to display
state->playing = player->update(passed);
if (player->isPlaybackReady()) {
// Play as long as the player reports that there is more to display
state->playing = player->update(passed);
displayVideo(player, state);
displayVideo(player, state);
}
processEvents(state);
+21 -18
View File
@@ -17,6 +17,7 @@
#include "io/key.h"
#include "io/timer.h"
#include "player.h"
#include "parse/parselo.h"
using namespace cutscene::player;
@@ -28,7 +29,7 @@ const int MAX_AUDIO_BUFFERS = 15;
std::unique_ptr<Decoder> findDecoder(const SCP_string& name) {
{
std::unique_ptr<Decoder> ffmpeg(new ffmpeg::FFMPEGDecoder());
std::unique_ptr<Decoder> ffmpeg(new ::cutscene::ffmpeg::FFMPEGDecoder());
if (ffmpeg->initialize(name)) {
return ffmpeg;
}
@@ -272,8 +273,21 @@ bool shouldBeginPlayback(Decoder* decoder) {
}
namespace cutscene {
Player::Player(std::unique_ptr<Decoder>&& decoder) : m_decoder(std::move(decoder)) {
initPlayback();
Player::Player(std::unique_ptr<Decoder>&& decoder, bool enable_audio) : m_decoder(std::move(decoder))
{
Assertion(!m_state.videoInited,
"Internal State has been initialized before! Create a new player for replaying a movie.");
m_decoderThread.reset(new std::thread(std::bind(&Player::decoderThread, this)));
m_state.props = m_decoder->getProperties();
m_state.decoder = m_decoder.get();
videoPlaybackInit(&m_state);
if (enable_audio) {
audioPlaybackInit(&m_state);
}
}
Player::~Player() {
@@ -315,19 +329,6 @@ bool Player::processDecoderData() {
return decoding || pendingAudio || pendingVideo;
}
void Player::initPlayback() {
Assertion(!m_state.videoInited, "Internal State has been initialized before! Create a new player for replaying a movie.");
m_decoderThread.reset(new std::thread(std::bind(&Player::decoderThread, this)));
m_state.props = m_decoder->getProperties();
m_state.decoder = m_decoder.get();
videoPlaybackInit(&m_state);
audioPlaybackInit(&m_state);
}
bool Player::update(uint64_t diff_time_micro) {
if (m_state.playbackHasBegun) {
m_state.playback_time += diff_time_micro;
@@ -354,7 +355,8 @@ void Player::decoderThread() {
}
}
std::unique_ptr<Player> Player::newPlayer(const SCP_string& name) {
std::unique_ptr<Player> Player::newPlayer(const SCP_string& name, bool enable_audio)
{
mprintf(("Creating player for movie '%s'.\n", name.c_str()));
auto decoder = findDecoder(name);
@@ -362,7 +364,7 @@ std::unique_ptr<Player> Player::newPlayer(const SCP_string& name) {
if (decoder == nullptr) {
return nullptr;
}
return std::unique_ptr<Player>(new Player(std::move(decoder)));
return std::unique_ptr<Player>(new Player(std::move(decoder), enable_audio));
}
const PlayerState& Player::getInternalState() const {
return m_state;
@@ -386,4 +388,5 @@ SCP_string Player::getCurrentSubtitle() {
return m_state.currentSubtitle->text;
}
}
bool Player::isPlaybackReady() const { return m_state.playbackHasBegun || shouldBeginPlayback(m_decoder.get()); }
}
+21 -12
View File
@@ -52,7 +52,7 @@ struct PlayerState {
* @brief A movie player
*/
class Player {
private:
private:
std::unique_ptr<Decoder> m_decoder;
std::unique_ptr<std::thread> m_decoderThread;
@@ -61,13 +61,11 @@ class Player {
bool processDecoderData();
private:
private:
void decoderThread();
void initPlayback();
public:
explicit Player(std::unique_ptr<Decoder>&& decoder);
public:
explicit Player(std::unique_ptr<Decoder>&& decoder, bool enable_audio = true);
~Player();
@@ -97,6 +95,12 @@ class Player {
*/
const MovieProperties& getMovieProperties() const;
/**
* @brief Determines if this player can start displaying video.
* @return true if the cutscene is ready, false otherwise
*/
bool isPlaybackReady() const;
/**
* @brief Draws the current movie frame at the specified coordinates.
*
@@ -109,6 +113,10 @@ class Player {
*/
void draw(float x1, float y1, float x2, float y2);
/**
* @brief Gets the subtitle text that should be displayed now
* @return The text, encoded in UTF-8
*/
SCP_string getCurrentSubtitle();
/**
@@ -119,11 +127,12 @@ class Player {
void stopPlayback();
/**
* @brief Creates a player
* The player is configured to play the movie with the specified name
* @param name The movie to play
* @return @c nullptr if the specified movie could not be opened, a valid Player pointer otherwise
*/
static std::unique_ptr<Player> newPlayer(const SCP_string& name);
* @brief Creates a player
* The player is configured to play the movie with the specified name
* @param name The movie to play
* @param enable_audio Enable audio for this player instance
* @return @c nullptr if the specified movie could not be opened, a valid Player pointer otherwise
*/
static std::unique_ptr<Player> newPlayer(const SCP_string& name, bool enable_audio = true);
};
}
+2 -11
View File
@@ -33,7 +33,7 @@ layout (std140) uniform modelData {
model_light lights[MAX_LIGHTS];
float extrudeWidth;
float outlineWidth;
float fogStart;
float fogScale;
int buffer_matrix_offset;
@@ -105,11 +105,6 @@ in VertexOutput {
#endif
#ifdef FLAG_FOG
float fogDist;
#endif
#ifdef WORKAROUND_CLIPPING_PLANES
#ifdef FLAG_TRANSFORM
float notVisible;
#endif
#endif
vec4 position;
vec3 normal;
@@ -215,11 +210,6 @@ vec3 CalculateLighting(vec3 normal, vec3 diffuseMaterial, vec3 specularMaterial,
void main()
{
#ifdef WORKAROUND_CLIPPING_PLANES
#ifdef FLAG_TRANSFORM
if(vertIn.notVisible >= 0.9) { discard; }
#endif
#endif
#ifdef FLAG_SHADOW_MAP
// need depth and depth squared for variance shadow maps
fragOut0 = vec4(vertIn.position.z, vertIn.position.z * vertIn.position.z * VARIANCE_SHADOW_SCALE_INV, 0.0, 1.0);
@@ -426,6 +416,7 @@ void main()
// emissive colors won't be added later when we are using forward rendering so we need to do that here
baseColor.rgb += emissiveColor.rgb;
#endif
fragOut0 = baseColor;
#ifdef FLAG_DEFERRED
fragOut1 = vec4(vertIn.position.xyz, 1.0);
+83 -22
View File
@@ -1,9 +1,18 @@
#extension GL_ARB_gpu_shader5: enable
#ifdef FLAG_THICK_OUTLINE
layout (triangles) in;
// For every triangle line we generate 2 triangles which can be done with 4 vertices so in total we will need 12 vertices
layout (triangle_strip, max_vertices = 12) out;
#else
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;
#ifdef GL_ARB_gpu_shader5
#endif
#ifdef FLAG_SHADOW_MAP
#ifdef GL_ARB_gpu_shader5
layout(invocations = 4) in;
#endif
#endif
#define MAX_LIGHTS 8
@@ -33,7 +42,7 @@ layout (std140) uniform modelData {
model_light lights[MAX_LIGHTS];
float extrudeWidth;
float outlineWidth;
float fogStart;
float fogScale;
int buffer_matrix_offset;
@@ -106,15 +115,13 @@ in VertexOutput {
#ifdef FLAG_FOG
float fogDist;
#endif
#ifdef WORKAROUND_CLIPPING_PLANES
#ifdef FLAG_TRANSFORM
float notVisible;
#endif
#endif
#ifdef FLAG_SHADOW_MAP
#if !defined(GL_ARB_gpu_shader5)
float instance;
#endif
#ifdef FLAG_TRANSFORM
float clipModel;
#endif
#else
vec4 position;
#endif
@@ -135,11 +142,6 @@ out VertexOutput {
#endif
#ifdef FLAG_FOG
float fogDist;
#endif
#ifdef WORKAROUND_CLIPPING_PLANES
#ifdef FLAG_TRANSFORM
float notVisible;
#endif
#endif
vec4 position;
vec3 normal;
@@ -150,6 +152,7 @@ out VertexOutput {
#endif
} vertOut;
#ifdef FLAG_SHADOW_MAP
void main(void)
{
#ifdef GL_ARB_gpu_shader5
@@ -159,14 +162,25 @@ void main(void)
#endif
for(int vert = 0; vert < gl_in.length(); vert++)
{
#ifdef FLAG_TRANSFORM
if (vertIn[vert].clipModel > 0.9) {
// If the model was clipped in the vertex shader then we do not apply the shadow projection matrix here
gl_Position = gl_in[vert].gl_Position;
} else {
gl_Position = shadow_proj_matrix[instanceID] * gl_in[vert].gl_Position;
}
#else
gl_Position = shadow_proj_matrix[instanceID] * gl_in[vert].gl_Position;
#endif
if(gl_Position.z < -1.0)
gl_Position.z = -1.0;
vertOut.position = gl_in[vert].gl_Position;
vertOut.normal = vertIn[vert].normal;
vertOut.texCoord = vertIn[vert].texCoord;
gl_Layer = instanceID;
#ifdef FLAG_ENV_MAP
vertOut.envReflect = vertIn[vert].envReflect;
#endif
@@ -183,19 +197,66 @@ void main(void)
vertOut.shadowUV[3] = vertIn[vert].shadowUV[3];
vertOut.shadowPos = vertIn[vert].shadowPos;
#endif
#ifdef WORKAROUND_CLIPPING_PLANES
#ifdef FLAG_TRANSFORM
vertOut.notVisible = vertIn[vert].notVisible;
#endif
#ifdef FLAG_CLIP
#if defined(FLAG_CLIP)
gl_ClipDistance[0] = gl_in[vert].gl_ClipDistance[0];
#endif
#else
#if defined(FLAG_CLIP) || defined(FLAG_TRANSFORM)
gl_ClipDistance[0] = gl_in[vert].gl_ClipDistance[0];
#endif
#endif
EmitVertex();
}
EndPrimitive();
}
#elif defined(FLAG_THICK_OUTLINE)
const vec2 pixelOffsetDir[4] = vec2[](
vec2(0.0, 1.0),
vec2(1.0, 1.0),
vec2(1.0, -1.0),
vec2(0.0, -1.0)
);
void main(void)
{
for(int vert = 0; vert < gl_in.length(); vert++)
{
int nextVert = (vert + 1) % gl_in.length();
vec4 clip = gl_in[vert].gl_Position;
vec4 diff = gl_in[nextVert].gl_Position - clip; // vector from vert to the next vertex in the list
vec2 normal = normalize(vec2(diff.y, -diff.x)); // Computing the normal of a 2D vector is actually rather simple...
for (int lineVert = 0; lineVert < 4; ++lineVert)
{
// This is the pixel offset along the normal axis
vec2 yOffPixel = pixelOffsetDir[lineVert].y * normal * (outlineWidth / 2.0);
// This is the offset of the vertex along the vector between this vertex and the next one in the triangle
vec2 xOff = pixelOffsetDir[lineVert].x * diff.xy;
// This is the final offset in clip space
vec2 finalOffset = xOff + yOffPixel * vec2(vpwidth, vpheight) * clip.w;
gl_Position = vec4(clip.xyz + vec3(finalOffset, 0.0), clip.w);
vertOut.position = vertIn[vert].position;
vertOut.normal = vertIn[vert].normal;
vertOut.texCoord = vertIn[vert].texCoord;
#ifdef FLAG_ENV_MAP
vertOut.envReflect = vertIn[vert].envReflect;
#endif
#ifdef FLAG_NORMAL_MAP
vertOut.tangentMatrix = vertIn[vert].tangentMatrix;
#endif
#ifdef FLAG_FOG
vertOut.fogDist = vertIn[vert].fogDist;
#endif
#ifdef FLAG_SHADOWS
vertOut.shadowUV[0] = vertIn[vert].shadowUV[0];
vertOut.shadowUV[1] = vertIn[vert].shadowUV[1];
vertOut.shadowUV[2] = vertIn[vert].shadowUV[2];
vertOut.shadowUV[3] = vertIn[vert].shadowUV[3];
vertOut.shadowPos = vertIn[vert].shadowPos;
#endif
#if defined(FLAG_CLIP)
gl_ClipDistance[0] = gl_in[vert].gl_ClipDistance[0];
#endif
EmitVertex();
}
EndPrimitive();
}
}
#endif
+20 -36
View File
@@ -36,7 +36,7 @@ layout (std140) uniform modelData {
model_light lights[MAX_LIGHTS];
float extrudeWidth;
float outlineWidth;
float fogStart;
float fogScale;
int buffer_matrix_offset;
@@ -113,15 +113,15 @@ out VertexOutput {
#ifdef FLAG_FOG
float fogDist;
#endif
#ifdef WORKAROUND_CLIPPING_PLANES
#ifdef FLAG_TRANSFORM
float notVisible;
#endif
#endif
#ifdef FLAG_SHADOW_MAP
#if !defined(GL_ARB_gpu_shader5)
float instance;
#endif
#ifdef FLAG_TRANSFORM
// This flag is needed to let the geometry shader know that it doesn't need to apply the
// shadow projection to gl_Position
float clipModel;
#endif
#else
vec4 position;
#endif
@@ -152,19 +152,9 @@ void main()
vec4 texCoord;
mat4 orient = mat4(1.0);
mat4 scale = mat4(1.0);
#ifdef WORKAROUND_CLIPPING_PLANES
#ifdef FLAG_TRANSFORM
#ifdef FLAG_TRANSFORM
bool clipModel;
getModelTransform(orient, clipModel, int(vertModelID), buffer_matrix_offset);
vertOut.notVisible = clipModel ? 1.0 : 0.0;
#endif
#else
#ifdef FLAG_TRANSFORM
bool clipModel;
getModelTransform(orient, clipModel, int(vertModelID), buffer_matrix_offset);
#else
bool clipModel = false;
#endif
#endif
texCoord = textureMatrix * vertTexCoord;
vec4 vertex = vertPosition;
@@ -188,9 +178,6 @@ void main()
#else
gl_Position = projMatrix * position;
#endif
#ifdef FLAG_NORMAL_EXTRUDE
gl_Position.xy += (mat3(projMatrix) * normal.xyz).xy * gl_Position.z * extrudeWidth;
#endif
#ifdef FLAG_SHADOWS
vec4 shadowPos = shadow_mv_matrix * modelMatrix * orient * vertPosition;
vertOut.shadowPos = shadow_mv_matrix * modelMatrix * orient * vertPosition;
@@ -213,31 +200,28 @@ void main()
#ifdef FLAG_FOG
vertOut.fogDist = clamp((gl_Position.z - fogStart) * 0.75 * fogScale, 0.0, 1.0);
#endif
#ifdef WORKAROUND_CLIPPING_PLANES
if(use_clip_plane) {
gl_ClipDistance[0] = dot(clip_equation, modelMatrix * orient * vertex);
} else {
gl_ClipDistance[0] = 1.0;
}
#else
#ifdef FLAG_CLIP
#ifdef FLAG_TRANSFORM
if (clipModel) {
gl_ClipDistance[0] = -1.0;
} else if(use_clip_plane) {
// Clip this model by moving all vertices outside the clip volume
gl_Position = vec4(vec3(-2.0), 1.0);
}
#ifdef FLAG_SHADOW_MAP
vertOut.clipModel = clipModel ? 1.0 : 0.0;
#endif
#endif
#ifdef FLAG_CLIP
if(use_clip_plane) {
gl_ClipDistance[0] = dot(clip_equation, modelMatrix * orient * vertex);
} else {
gl_ClipDistance[0] = 1.0;
}
#elif defined(FLAG_TRANSFORM)
gl_ClipDistance[0] = clipModel ? -1.0 : 1.0;
#endif
#endif
#ifndef FLAG_SHADOW_MAP
#ifndef FLAG_SHADOW_MAP
vertOut.position = position;
vertOut.normal = normal;
vertOut.texCoord = texCoord;
#else
#else
vertOut.normal = normal;
vertOut.texCoord = texCoord;
#endif
#endif
}
@@ -0,0 +1,36 @@
local exts = {
"",
".lua",
".lc"
}
local function cfileLoader(name)
local file = nil
for i,v in ipairs(exts) do
local real_name = name .. v
file = cf.openFile(real_name, "r", "data/scripts")
if (file:isValid()) then
name = real_name
break;
end
end
if (file == nil or not file:isValid()) then
return "Module '" .. name .. "' is not known by the CFile system"
end
local content = file:read("*a")
file:close()
local func, err = loadstring(content, name)
if err then
return err
end
return func
end
table.insert(package.loaders, 2, cfileLoader)
+2 -2
View File
@@ -5,7 +5,7 @@ IF(MSVC)
set(RES_CONTENT)
set(ARRAY_ELEMENTS)
FOREACH(file ${file_root_def_files_files})
FOREACH(file ${default_files_files})
set(INPUT_NAME "${CMAKE_CURRENT_SOURCE_DIR}/${file}")
SET(OUTPUT "${GENERATED_SOURCE_DIR}/code/${file}")
file(RELATIVE_PATH RELATIVE_FILE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/def_files" "${INPUT_NAME}")
@@ -39,7 +39,7 @@ else()
set(INCLUDE_LIST)
set(ARRAY_ELEMENTS)
FOREACH(file ${file_root_def_files_files})
FOREACH(file ${default_files_files})
set(INPUT_NAME "${CMAKE_CURRENT_SOURCE_DIR}/${file}")
SET(OUTPUT "${GENERATED_SOURCE_DIR}/code/${file}")
file(RELATIVE_PATH RELATIVE_FILE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/def_files" "${INPUT_NAME}")
+15
View File
@@ -0,0 +1,15 @@
#include "events.h"
namespace events {
util::event<void> EngineUpdate;
util::event<void> EngineShutdown;
util::event<void, int, int> GameLeaveState;
util::event<void, int, int> GameEnterState;
util::event<void, const char*> GameMissionLoad;
}
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#include "utils/event.h"
namespace events {
extern util::event<void> EngineUpdate;
extern util::event<void> EngineShutdown;
extern util::event<void, int, int> GameLeaveState;
extern util::event<void, int, int> GameEnterState;
extern util::event<void, const char*> GameMissionLoad;
}
+1 -1
View File
@@ -1101,7 +1101,7 @@ void fs2netd_store_stats()
if (Duplicate_login_detected) {
Duplicate_login_detected = false;
multi_display_chat_msg( XSTR("<Duplicate login detected - stats have been tossed>", 1582), 0, 0 );
ml_string( XSTR("<Duplicate login detected - stats have been tossed>", 1583) );
ml_string( XSTR("<Duplicate login detected - stats have been tossed>", 1582) );
fs2netd_store_stats_results();
return;
}
+1 -1
View File
@@ -483,7 +483,7 @@ void parse_helptbl(const char *filename)
break;
case 4: // $end
default:
Assertion(false, "This should never happen.\n");
UNREACHABLE("This should never happen.\n");
break;
}
} // end while
+14 -14
View File
@@ -19,7 +19,7 @@
SCP_vector<game_snd> Snds;
SCP_vector<game_snd> Snds_iface;
SCP_vector<int> Snds_iface_handle;
SCP_vector<sound_handle> Snds_iface_handle;
// jg18 - default priorities and limits for retail gameplay sounds
static const int NUM_RETAIL_GAMEPLAY_SOUNDS = 192; // indices 0-191, from retail sounds.tbl
@@ -260,7 +260,7 @@ void gamesnd_add_retail_default_enhanced_sound_data()
void gamesnd_play_iface(interface_snd_id n)
{
if (Snds_iface_handle[n.value()] >= 0)
if (Snds_iface_handle[n.value()].isValid())
snd_stop(Snds_iface_handle[n.value()]);
Snds_iface_handle[n.value()] = snd_play(gamesnd_get_interface_sound(n));
@@ -565,9 +565,9 @@ void gamesnd_unload_gameplay_sounds()
Assert( Snds.size() <= INT_MAX );
for (SCP_vector<game_snd>::iterator gs = Snds.begin(); gs != Snds.end(); ++gs) {
for (auto& entry : gs->sound_entries) {
if (entry.id != -1) {
if (entry.id.isValid()) {
snd_unload(entry.id);
entry.id = -1;
entry.id = sound_load_id::invalid();
}
}
}
@@ -599,9 +599,9 @@ void gamesnd_unload_interface_sounds()
Assert( Snds_iface.size() < INT_MAX );
for (SCP_vector<game_snd>::iterator si = Snds_iface.begin(); si != Snds_iface.end(); ++si) {
for (auto& entry : si->sound_entries) {
if ( entry.id != -1 ) {
if (entry.id.isValid()) {
snd_unload( entry.id );
entry.id = -1;
entry.id = sound_load_id::invalid();
entry.id_sig = -1;
}
}
@@ -617,6 +617,9 @@ void parse_gamesnd_old(game_snd* gs)
gs->sound_entries.resize(1);
auto& entry = gs->sound_entries.back();
// Default pitch is 1.0. This is set here in case we don't have a valid file name
gs->pitch_range = util::UniformFloatRange(1.0f);
stuff_string(entry.filename, F_NAME, MAX_FILENAME_LEN, ",");
if (!stricmp(entry.filename, NOX("empty")))
@@ -673,9 +676,6 @@ void parse_gamesnd_old(game_snd* gs)
}
}
// Default pitch is 1.0
gs->pitch_range = util::UniformFloatRange(1.0f);
// check for extra values per Mantis #2408
ignore_gray_space();
if (stuff_int_optional(&temp, true) == 2)
@@ -840,6 +840,9 @@ void parse_gamesnd_new(game_snd* gs, bool no_create)
// New extended format found
stuff_string(name, F_NAME, MAX_FILENAME_LEN);
// Default pitch is 1.0. This is set here in case we don't have a valid file name
gs->pitch_range = util::UniformFloatRange(1.0f);
if (!stricmp(name, NOX("empty")))
{
entry->filename[0] = 0;
@@ -914,9 +917,6 @@ void parse_gamesnd_new(game_snd* gs, bool no_create)
error_display(1, "Invalid enhanced sound limit: %d\n", temp_limit);
}
}
// Default pitch is 1.0
gs->pitch_range = util::UniformFloatRange(1.0f);
}
void gamesnd_parse_entry(game_snd *gs, bool no_create, SCP_vector<game_snd> *lookupVector)
@@ -1197,7 +1197,7 @@ void parse_sound_table(const char* filename)
if (gamesnd_parse_line(&tempSound, "$Name:", &Snds_iface))
{
Snds_iface.push_back(game_snd(tempSound));
Snds_iface_handle.push_back(-1);
Snds_iface_handle.push_back(sound_handle::invalid());
}
}
@@ -1322,7 +1322,7 @@ float gamesnd_get_max_duration(game_snd* gs) {
int max_length = 0;
for (auto& entry : gs->sound_entries) {
if (entry.id < 0) {
if (!entry.id.isValid()) {
// Lazily load unloaded sound entries when required
entry.id = snd_load(&entry, gs->flags);
}
+1 -1
View File
@@ -578,7 +578,7 @@ void parse_everything_else(const char *filename)
}
break;
default:
Assertion(false, "MageKing17 made a coding error somewhere, and you should laugh at him (and report this error).\n");
UNREACHABLE("MageKing17 made a coding error somewhere, and you should laugh at him (and report this error).\n");
break;
}
}
+9
View File
@@ -81,3 +81,12 @@
#define CLANG_ANALYZER_NORETURN
#endif
#endif
#ifndef NDEBUG
#define UNREACHABLE(msg, ...) \
do { \
os::dialogs::Error(__FILE__, __LINE__, msg, ##__VA_ARGS__); \
} while (false)
#else
#define UNREACHABLE(msg, ...) __builtin_unreachable()
#endif
+7
View File
@@ -63,3 +63,10 @@
* @brief Specifies that an analyzer should consider this function as no-return
*/
#define CLANG_ANALYZER_NORETURN
/**
* @brief Specifies that the code at which point this macro appears at is unreachable
* @param msg The message to display in debug mode
* @param ... Format arguments for the message
*/
#define UNREACHABLE(msg, ...)
+9
View File
@@ -72,3 +72,12 @@
#endif
#define CLANG_ANALYZER_NORETURN
#ifndef NDEBUG
#define UNREACHABLE(msg, ...) \
do { \
os::dialogs::Error(__FILE__, __LINE__, msg, ##__VA_ARGS__); \
} while (false)
#else
#define UNREACHABLE(msg, ...) __builtin_unreachable()
#endif
+9
View File
@@ -69,3 +69,12 @@
#endif
#define CLANG_ANALYZER_NORETURN
#ifndef NDEBUG
#define UNREACHABLE(msg, ...) \
do { \
os::dialogs::Error(__FILE__, __LINE__, msg, ##__VA_ARGS__); \
} while (false)
#else
#define UNREACHABLE(msg, ...) __builtin_unreachable()
#endif
+10
View File
@@ -82,3 +82,13 @@
#define FALLTHROUGH
#define CLANG_ANALYZER_NORETURN
#ifndef NDEBUG
#define UNREACHABLE(msg, ...) \
do { \
os::dialogs::Error(__FILE__, __LINE__, msg, ##__VA_ARGS__); \
} while (false)
#else
#define UNREACHABLE(msg, ...) __assume(false)
#endif
+7 -7
View File
@@ -19,17 +19,17 @@
#include "cmdline/cmdline.h"
#include "debugconsole/console.h"
#include "gamesequence/gamesequence.h" //WMC - for scripting hooks in gr_flip()
#include "gamesequence/gamesequence.h" //WMC - for scripting hooks in gr_flip()
#include "globalincs/systemvars.h"
#include "graphics/2d.h"
#include "graphics/matrix.h"
#include "graphics/light.h"
#include "graphics/font.h"
#include "graphics/grbatch.h"
#include "graphics/grinternal.h"
#include "graphics/grstub.h"
#include "graphics/light.h"
#include "graphics/matrix.h"
#include "graphics/opengl/gropengl.h"
#include "graphics/opengl/gropengldraw.h"
#include "graphics/grstub.h"
#include "graphics/paths/PathRenderer.h"
#include "graphics/util/GPUMemoryHeap.h"
#include "graphics/util/UniformBuffer.h"
@@ -37,9 +37,10 @@
#include "io/keycontrol.h" // m!m
#include "io/timer.h"
#include "osapi/osapi.h"
#include "scripting/scripting.h"
#include "parse/parselo.h"
#include "popup/popup.h"
#include "render/3d.h"
#include "scripting/scripting.h"
#include "tracing/tracing.h"
#include "utils/boost/hash_combine.h"
@@ -2152,8 +2153,7 @@ void gr_set_bitmap(int bitmap_num, int alphablend_mode, int bitblt_mode, float a
void gr_flip(bool execute_scripting)
{
// m!m avoid running CHA_ONFRAME when the "Quit mission" popup is shown. See mantis 2446 for reference
if (execute_scripting && !quit_mission_popup_shown)
{
if (execute_scripting && !popup_active()) {
TRACE_SCOPE(tracing::LuaOnFrame);
//WMC - Do conditional hooks. Yippee!
+39 -39
View File
@@ -186,7 +186,7 @@ enum shader_type {
#define SDR_FLAG_MODEL_HDR (1<<18)
#define SDR_FLAG_MODEL_AMBIENT_MAP (1<<19)
#define SDR_FLAG_MODEL_NORMAL_ALPHA (1<<20)
#define SDR_FLAG_MODEL_NORMAL_EXTRUDE (1<<21)
#define SDR_FLAG_MODEL_THICK_OUTLINES (1<<21) // Renders the model geometry as an outline with configurable line width
#define SDR_FLAG_PARTICLE_POINT_GEN (1<<0)
@@ -776,7 +776,7 @@ typedef struct screen {
void (*gf_render_primitives)(material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle, size_t buffer_offset);
void (*gf_render_primitives_particle)(particle_material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle);
void (*gf_render_primitives_distortion)(distortion_material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle);
void (*gf_render_movie)(movie_material* material_info, primitive_type prim_type, vertex_layout* layout, int n_verts, int buffer);
void (*gf_render_movie)(movie_material* material_info, primitive_type prim_type, vertex_layout* layout, int n_verts, int buffer, size_t buffer_offset);
void (*gf_render_primitives_batched)(batched_bitmap_material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle);
void (*gf_render_nanovg)(nanovg_material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle);
void (*gf_render_decals)(decal_material* material_info, primitive_type prim_type, vertex_layout* layout, int num_elements, const indexed_vertex_source& buffers);
@@ -942,67 +942,67 @@ void gr_shield_icon(coord2d coords[6], const int resize_mode = GR_RESIZE_FULL);
// Here be the bitmap functions
#define gr_bm_free_data GR_CALL(*gr_screen.gf_bm_free_data)
#define gr_bm_create GR_CALL(*gr_screen.gf_bm_create)
#define gr_bm_init GR_CALL(*gr_screen.gf_bm_init)
#define gr_bm_page_in_start GR_CALL(*gr_screen.gf_bm_page_in_start)
#define gr_bm_data GR_CALL(*gr_screen.gf_bm_data)
#define gr_bm_free_data GR_CALL(gr_screen.gf_bm_free_data)
#define gr_bm_create GR_CALL(gr_screen.gf_bm_create)
#define gr_bm_init GR_CALL(gr_screen.gf_bm_init)
#define gr_bm_page_in_start GR_CALL(gr_screen.gf_bm_page_in_start)
#define gr_bm_data GR_CALL(gr_screen.gf_bm_data)
#define gr_bm_make_render_target GR_CALL(*gr_screen.gf_bm_make_render_target)
#define gr_bm_make_render_target GR_CALL(gr_screen.gf_bm_make_render_target)
__inline int gr_bm_set_render_target(int n, int face = -1)
{
return (*gr_screen.gf_bm_set_render_target)(n, face);
}
#define gr_set_texture_addressing GR_CALL(*gr_screen.gf_set_texture_addressing)
#define gr_set_texture_addressing GR_CALL(gr_screen.gf_set_texture_addressing)
inline int gr_create_buffer(BufferType type, BufferUsageHint usage)
{
return (*gr_screen.gf_create_buffer)(type, usage);
}
#define gr_delete_buffer GR_CALL(*gr_screen.gf_delete_buffer)
#define gr_update_buffer_data GR_CALL(*gr_screen.gf_update_buffer_data)
#define gr_update_buffer_data_offset GR_CALL(*gr_screen.gf_update_buffer_data_offset)
#define gr_update_transform_buffer GR_CALL(*gr_screen.gf_update_transform_buffer)
#define gr_delete_buffer GR_CALL(gr_screen.gf_delete_buffer)
#define gr_update_buffer_data GR_CALL(gr_screen.gf_update_buffer_data)
#define gr_update_buffer_data_offset GR_CALL(gr_screen.gf_update_buffer_data_offset)
#define gr_update_transform_buffer GR_CALL(gr_screen.gf_update_transform_buffer)
#define gr_scene_texture_begin GR_CALL(*gr_screen.gf_scene_texture_begin)
#define gr_scene_texture_end GR_CALL(*gr_screen.gf_scene_texture_end)
#define gr_copy_effect_texture GR_CALL(*gr_screen.gf_copy_effect_texture)
#define gr_scene_texture_begin GR_CALL(gr_screen.gf_scene_texture_begin)
#define gr_scene_texture_end GR_CALL(gr_screen.gf_scene_texture_end)
#define gr_copy_effect_texture GR_CALL(gr_screen.gf_copy_effect_texture)
#define gr_post_process_set_effect GR_CALL(*gr_screen.gf_post_process_set_effect)
#define gr_post_process_set_defaults GR_CALL(*gr_screen.gf_post_process_set_defaults)
#define gr_post_process_begin GR_CALL(*gr_screen.gf_post_process_begin)
#define gr_post_process_end GR_CALL(*gr_screen.gf_post_process_end)
#define gr_post_process_save_zbuffer GR_CALL(*gr_screen.gf_post_process_save_zbuffer)
#define gr_post_process_set_effect GR_CALL(gr_screen.gf_post_process_set_effect)
#define gr_post_process_set_defaults GR_CALL(gr_screen.gf_post_process_set_defaults)
#define gr_post_process_begin GR_CALL(gr_screen.gf_post_process_begin)
#define gr_post_process_end GR_CALL(gr_screen.gf_post_process_end)
#define gr_post_process_save_zbuffer GR_CALL(gr_screen.gf_post_process_save_zbuffer)
inline void gr_post_process_restore_zbuffer() {
gr_screen.gf_post_process_restore_zbuffer();
}
#define gr_deferred_lighting_begin GR_CALL(*gr_screen.gf_deferred_lighting_begin)
#define gr_deferred_lighting_end GR_CALL(*gr_screen.gf_deferred_lighting_end)
#define gr_deferred_lighting_finish GR_CALL(*gr_screen.gf_deferred_lighting_finish)
#define gr_deferred_lighting_begin GR_CALL(gr_screen.gf_deferred_lighting_begin)
#define gr_deferred_lighting_end GR_CALL(gr_screen.gf_deferred_lighting_end)
#define gr_deferred_lighting_finish GR_CALL(gr_screen.gf_deferred_lighting_finish)
#define gr_zbias GR_CALL(*gr_screen.gf_zbias)
#define gr_set_fill_mode GR_CALL(*gr_screen.gf_set_fill_mode)
#define gr_zbias GR_CALL(gr_screen.gf_zbias)
#define gr_set_fill_mode GR_CALL(gr_screen.gf_set_fill_mode)
#define gr_set_line_width GR_CALL(*gr_screen.gf_set_line_width)
#define gr_set_line_width GR_CALL(gr_screen.gf_set_line_width)
#define gr_sphere GR_CALL(*gr_screen.gf_sphere)
#define gr_sphere GR_CALL(gr_screen.gf_sphere)
#define gr_maybe_create_shader GR_CALL(*gr_screen.gf_maybe_create_shader)
#define gr_recompile_all_shaders GR_CALL(*gr_screen.gf_recompile_all_shaders)
#define gr_set_animated_effect GR_CALL(*gr_screen.gf_set_animated_effect)
#define gr_maybe_create_shader GR_CALL(gr_screen.gf_maybe_create_shader)
#define gr_recompile_all_shaders GR_CALL(gr_screen.gf_recompile_all_shaders)
#define gr_set_animated_effect GR_CALL(gr_screen.gf_set_animated_effect)
#define gr_clear_states GR_CALL(*gr_screen.gf_clear_states)
#define gr_clear_states GR_CALL(gr_screen.gf_clear_states)
#define gr_update_texture GR_CALL(*gr_screen.gf_update_texture)
#define gr_get_bitmap_from_texture GR_CALL(*gr_screen.gf_get_bitmap_from_texture)
#define gr_update_texture GR_CALL(gr_screen.gf_update_texture)
#define gr_get_bitmap_from_texture GR_CALL(gr_screen.gf_get_bitmap_from_texture)
#define gr_shadow_map_start GR_CALL(*gr_screen.gf_shadow_map_start)
#define gr_shadow_map_end GR_CALL(*gr_screen.gf_shadow_map_end)
#define gr_render_shield_impact GR_CALL(*gr_screen.gf_render_shield_impact)
#define gr_shadow_map_start GR_CALL(gr_screen.gf_shadow_map_start)
#define gr_shadow_map_end GR_CALL(gr_screen.gf_shadow_map_end)
#define gr_render_shield_impact GR_CALL(gr_screen.gf_render_shield_impact)
__inline void gr_render_primitives(material* material_info, primitive_type prim_type, vertex_layout* layout, int vert_offset, int n_verts, int buffer_handle = -1, size_t buffer_offset = 0)
{
@@ -1029,9 +1029,9 @@ __inline void gr_render_primitives_distortion(distortion_material* material_info
(*gr_screen.gf_render_primitives_distortion)(material_info, prim_type, layout, offset, n_verts, buffer_handle);
}
inline void gr_render_movie(movie_material* material_info, primitive_type prim_type, vertex_layout* layout, int n_verts, int buffer)
inline void gr_render_movie(movie_material* material_info, primitive_type prim_type, vertex_layout* layout, int n_verts, int buffer, size_t buffer_offset = 0)
{
(*gr_screen.gf_render_movie)(material_info, prim_type, layout, n_verts, buffer);
(*gr_screen.gf_render_movie)(material_info, prim_type, layout, n_verts, buffer, buffer_offset);
}
__inline void gr_render_model(model_material* material_info, indexed_vertex_source *vert_source, vertex_buffer* bufferp, size_t texi)
+5 -9
View File
@@ -158,32 +158,28 @@ int generic_anim_stream(generic_anim *ga, const bool cache)
{
CFILE *img_cfp = NULL;
int anim_fps = 0;
char full_path[MAX_PATH];
size_t size = 0, offset = 0;
const void* file_data = nullptr;
const int NUM_TYPES = 3;
const ubyte type_list[NUM_TYPES] = {BM_TYPE_EFF, BM_TYPE_ANI, BM_TYPE_PNG};
const char *ext_list[NUM_TYPES] = {".eff", ".ani", ".png"};
int rval = -1;
int bpp;
ga->type = BM_TYPE_NONE;
rval = cf_find_file_location_ext(ga->filename, NUM_TYPES, ext_list, CF_TYPE_ANY, sizeof(full_path) - 1, full_path, &size, &offset, 0, &file_data);
auto res = cf_find_file_location_ext(ga->filename, NUM_TYPES, ext_list, CF_TYPE_ANY, false);
// could not be found, or is invalid for some reason
if ( (rval < 0) || (rval >= NUM_TYPES) )
if ( !res.found )
return -1;
//make sure we can open it
img_cfp = cfopen_special(full_path, "rb", size, offset, file_data, CF_TYPE_ANY);
img_cfp = cfopen_special(res.full_name.c_str(), "rb", res.size, res.offset, res.data_ptr, CF_TYPE_ANY);
if (img_cfp == NULL) {
return -1;
}
strcat_s(ga->filename, ext_list[rval]);
ga->type = type_list[rval];
strcat_s(ga->filename, ext_list[res.extension_index]);
ga->type = type_list[res.extension_index];
//seek to the end
cfseek(img_cfp, 0, CF_SEEK_END);
+1 -1
View File
@@ -335,7 +335,7 @@ void gr_stub_render_primitives_distortion(distortion_material* /*material_info*
{
}
void gr_stub_render_movie(movie_material* /*material_info*/, primitive_type /*prim_type*/, vertex_layout* /*layout*/, int /*n_verts*/, int /*buffer*/)
void gr_stub_render_movie(movie_material* /*material_info*/, primitive_type /*prim_type*/, vertex_layout* /*layout*/, int /*n_verts*/, int /*buffer*/, size_t /*buffer_offset*/)
{
}
+12 -23
View File
@@ -635,27 +635,6 @@ float model_material::get_normal_alpha_max() const
return Normal_alpha_max;
}
void model_material::set_normal_extrude(float width)
{
Normal_extrude = true;
Normal_extrude_width = width;
}
void model_material::set_normal_extrude()
{
Normal_extrude = false;
}
bool model_material::is_normal_extrude_active() const
{
return Normal_extrude;
}
float model_material::get_normal_extrude_width() const
{
return Normal_extrude_width;
}
void model_material::set_fog(int r, int g, int b, float _near, float _far)
{
Fog_params.enabled = true;
@@ -681,6 +660,16 @@ const model_material::fog& model_material::get_fog() const
return Fog_params;
}
void model_material::set_outline_thickness(float thickness) {
Outline_thickness = thickness;
}
float model_material::get_outline_thickness() const {
return Outline_thickness;
}
bool model_material::uses_thick_outlines() const {
return Outline_thickness > 0.0f;
}
uint model_material::get_shader_flags() const
{
uint Shader_flags = 0;
@@ -768,8 +757,8 @@ uint model_material::get_shader_flags() const
Shader_flags |= SDR_FLAG_MODEL_NORMAL_ALPHA;
}
if ( Normal_extrude ) {
Shader_flags |= SDR_FLAG_MODEL_NORMAL_EXTRUDE;
if ( uses_thick_outlines() ) {
Shader_flags |= SDR_FLAG_MODEL_THICK_OUTLINES;
}
return Shader_flags;
+6 -7
View File
@@ -200,10 +200,10 @@ class model_material : public material
float Normal_alpha_min = 0.0f;
float Normal_alpha_max = 1.0f;
bool Normal_extrude = false;
float Normal_extrude_width = -1.0f;
fog Fog_params;
float Outline_thickness = -1.0f;
public:
model_material();
@@ -246,10 +246,9 @@ public:
float get_normal_alpha_min() const;
float get_normal_alpha_max() const;
void set_normal_extrude(float width);
void set_normal_extrude();
bool is_normal_extrude_active() const;
float get_normal_extrude_width() const;
void set_outline_thickness(float thickness = -1.0f);
float get_outline_thickness() const;
bool uses_thick_outlines() const;
void set_batching(bool enabled);
bool is_batched() const;
+1 -1
View File
@@ -137,7 +137,7 @@ GLenum get_gl_shader_stage(opengl::ShaderStage stage) {
case opengl::STAGE_FRAGMENT:
return GL_FRAGMENT_SHADER;
default:
Assertion(false, "Unhandled shader type found!");
UNREACHABLE("Unhandled shader type found!");
return GL_NONE;
}
}
+20 -15
View File
@@ -29,6 +29,7 @@
#include "math/floating.h"
#include "model/model.h"
#include "nebula/neb.h"
#include "libs/renderdoc/renderdoc.h"
#include "osapi/osapi.h"
#include "osapi/osregistry.h"
#include "render/3d.h"
@@ -90,7 +91,8 @@ static GLenum GL_read_format = GL_BGRA;
GLuint GL_vao = 0;
bool GL_workaround_clipping_planes = false;
SCP_string GL_implementation_id;
SCP_vector<GLint> GL_binary_formats;
static std::unique_ptr<os::OpenGLContext> GL_context = nullptr;
@@ -1365,19 +1367,6 @@ static void init_extensions() {
}
}
static void opengl_do_workaround_checks() {
auto vendor = glGetString(GL_VENDOR);
if (strstr((const char*) vendor, "NVIDIA")) {
// Nvidia has some weird issues with clipping planes. Check #1579 for more information.
GL_workaround_clipping_planes = true;
mprintf((" Applying clipping plane workaround for NVIDIA hardware.\n"));
} else {
// Assume everone else has proper support for this
GL_workaround_clipping_planes = false;
}
}
bool gr_opengl_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps)
{
if (GL_initted) {
@@ -1390,6 +1379,9 @@ bool gr_opengl_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps)
gr_screen.max_h,
gr_screen.bits_per_pixel ));
// Load the RenderDoc API if available before doing anything with OpenGL
renderdoc::loadApi();
graphic_operations = std::move(graphicsOps);
if ( opengl_init_display_device() ) {
@@ -1446,7 +1438,20 @@ bool gr_opengl_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps)
mprintf(( " OpenGL Version : %s\n", glGetString(GL_VERSION) ));
mprintf(( "\n" ));
opengl_do_workaround_checks();
// Build a string identifier for this OpenGL implementation
GL_implementation_id.clear();
GL_implementation_id += reinterpret_cast<const char*>(glGetString(GL_VENDOR));
GL_implementation_id += "\n";
GL_implementation_id += reinterpret_cast<const char*>(glGetString(GL_RENDERER));
GL_implementation_id += "\n";
GL_implementation_id += reinterpret_cast<const char*>(glGetString(GL_VERSION));
GL_implementation_id += "\n";
GL_implementation_id += reinterpret_cast<const char*>(glGetString(GL_SHADING_LANGUAGE_VERSION));
GLint formats = 0;
glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &formats);
GL_binary_formats.resize(formats);
glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, GL_binary_formats.data());
if (Cmdline_fullscreen_window || Cmdline_window) {
opengl_go_windowed();
+2 -1
View File
@@ -58,6 +58,7 @@ extern GLuint GL_vao;
extern float GL_alpha_threshold;
extern bool GL_workaround_clipping_planes; //!< If set then clipping planes can not be used for batched model rendering
extern SCP_string GL_implementation_id;
extern SCP_vector<GLint> GL_binary_formats;
#endif
+11
View File
@@ -188,6 +188,9 @@ void gr_opengl_deferred_lighting_finish()
light_data->lightDir.xyz.x = view_dir.xyzw.x;
light_data->lightDir.xyz.y = view_dir.xyzw.y;
light_data->lightDir.xyz.z = view_dir.xyzw.z;
vm_vec_scale(&light_data->specLightColor, static_light_factor);
first_directional = false;
break;
case Light_Type::Cone:
@@ -199,6 +202,9 @@ void gr_opengl_deferred_lighting_finish()
case Light_Type::Point:
light_data->diffuseLightColor = diffuse;
light_data->specLightColor = spec;
vm_vec_scale(&light_data->specLightColor, static_point_factor);
light_data->lightRadius = MAX(l.rada, l.radb) * 1.25f;
light_data->scale.xyz.x = MAX(l.rada, l.radb) * 1.28f;
light_data->scale.xyz.y = MAX(l.rada, l.radb) * 1.28f;
@@ -217,10 +223,15 @@ void gr_opengl_deferred_lighting_finish()
light_data->scale.xyz.y = l.radb * 1.53f;
light_data->scale.xyz.z = length;
vm_vec_scale(&light_data->specLightColor, static_tube_factor);
// Tube lights consist of two different types of lights with almost the same properties
light_data = uniformAligner.addTypedElement<deferred_light_data>();
light_data->diffuseLightColor = diffuse;
light_data->specLightColor = spec;
vm_vec_scale(&light_data->specLightColor, static_tube_factor);
light_data->lightRadius = l.radb * 1.5f;
light_data->lightType = LT_POINT;
+4 -6
View File
@@ -786,18 +786,16 @@ void gr_opengl_render_primitives_distortion(distortion_material* material_info,
GL_CHECK_FOR_ERRORS("start of gr_opengl_render_primitives_distortion()");
}
void gr_opengl_render_movie(movie_material* material_info,
primitive_type prim_type,
vertex_layout* layout,
int n_verts,
int buffer) {
void gr_opengl_render_movie(movie_material* material_info, primitive_type prim_type, vertex_layout* layout, int n_verts,
int buffer, size_t buffer_offset)
{
GR_DEBUG_SCOPE("Render movie frame");
gr_set_2d_matrix();
opengl_tnl_set_material_movie(material_info);
opengl_render_primitives(prim_type, layout, n_verts, buffer, 0, 0);
opengl_render_primitives(prim_type, layout, n_verts, buffer, 0, buffer_offset);
gr_end_2d_matrix();
}
+1 -1
View File
@@ -55,7 +55,7 @@ void gr_opengl_render_primitives(material* material_info, primitive_type prim_ty
void gr_opengl_render_primitives_particle(particle_material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle);
void gr_opengl_render_primitives_batched(batched_bitmap_material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle);
void gr_opengl_render_primitives_distortion(distortion_material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle);
void gr_opengl_render_movie(movie_material* material_info, primitive_type prim_type, vertex_layout* layout, int n_verts, int buffer);
void gr_opengl_render_movie(movie_material* material_info, primitive_type prim_type, vertex_layout* layout, int n_verts, int buffer, size_t buffer_offset);
void gr_opengl_render_nanovg(nanovg_material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle);
void gr_opengl_render_decals(decal_material* material_info, primitive_type prim_type, vertex_layout* layout, int num_elements, const indexed_vertex_source& binding);
+1 -1
View File
@@ -50,7 +50,7 @@ void gr_opengl_query_value(int obj, QueryType type) {
glQueryCounter(slot.name, GL_TIMESTAMP);
break;
default:
Assertion(false, "Unhandled enum value!");
UNREACHABLE("Unhandled enum value!");
break;
}
}
+97 -16
View File
@@ -8,6 +8,7 @@
*/
#include "cfile/cfile.h"
#include "cmdline/cmdline.h"
#include "def_files/def_files.h"
#include "graphics/2d.h"
@@ -213,9 +214,9 @@ static opengl_shader_variant_t GL_shader_variants[] = {
{ },
"Normal Alpha" },
{ SDR_TYPE_MODEL, false, SDR_FLAG_MODEL_NORMAL_EXTRUDE, "FLAG_NORMAL_EXTRUDE",
{ SDR_TYPE_MODEL, true, SDR_FLAG_MODEL_THICK_OUTLINES, "FLAG_THICK_OUTLINE",
{ },
"Normal Extrusion" },
"Thick outlines" },
{ SDR_TYPE_EFFECT_PARTICLE, true, SDR_FLAG_PARTICLE_POINT_GEN, "FLAG_EFFECT_GEOMETRY",
{ opengl_vert_attrib::UVEC },
@@ -337,19 +338,20 @@ void opengl_shader_shutdown()
GL_shader.clear();
}
static SCP_string opengl_shader_get_header(shader_type type_id, int flags) {
static SCP_string opengl_shader_get_header(shader_type type_id, int flags, bool has_geo_shader) {
SCP_stringstream sflags;
sflags << "#version " << GLSL_version << " core\n";
if (GL_workaround_clipping_planes) {
sflags << "#define WORKAROUND_CLIPPING_PLANES\n";
}
if (Detail.lighting < 3) {
sflags << "#define FLAG_LIGHT_MODEL_BLINN_PHONG\n";
}
if (has_geo_shader) {
// If there is a geometry shader then we define a special preprocessor symbol to make writing shaders easier
sflags << "#define HAS_GEOMETRY_SHADER\n";
}
if (type_id == SDR_TYPE_POST_PROCESS_MAIN || type_id == SDR_TYPE_POST_PROCESS_LIGHTSHAFTS || type_id == SDR_TYPE_POST_PROCESS_FXAA) {
// ignore looking for variants. main post process, lightshafts, and FXAA shaders need special headers to be hacked in
opengl_post_shader_header(sflags, type_id, flags);
@@ -476,9 +478,9 @@ static SCP_string handle_includes(const char* filename, const SCP_string& origin
return output.str();
}
static SCP_vector<SCP_string> opengl_get_shader_content(shader_type type_id, const char* filename, int flags, shader_stage) {
static SCP_vector<SCP_string> opengl_get_shader_content(shader_type type_id, const char* filename, int flags, bool has_geo_shader) {
SCP_vector<SCP_string> parts;
parts.push_back(opengl_shader_get_header(type_id, flags));
parts.push_back(opengl_shader_get_header(type_id, flags, has_geo_shader));
parts.push_back(handle_includes(filename, opengl_load_shader(filename)));
@@ -505,6 +507,9 @@ static SCP_string get_shader_hash(const SCP_vector<SCP_string>& vert,
md5.update(reinterpret_cast<const char*>(&i), sizeof(i));
}
md5.update(GL_implementation_id.data(),
(MD5::size_type)GL_implementation_id.size() * sizeof(SCP_string::value_type));
md5.finalize();
return md5.hexdigest();
@@ -532,7 +537,8 @@ static bool load_cached_shader_binary(opengl::ShaderProgram* program, const SCP_
auto metadata = base_filename + ".json";
auto binary = base_filename + ".bin";
auto metadata_fp = cfopen(metadata.c_str(), "rb", CFILE_NORMAL, CF_TYPE_CACHE);
auto metadata_fp = cfopen(metadata.c_str(), "rb", CFILE_NORMAL, CF_TYPE_CACHE, false,
CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
if (!metadata_fp) {
nprintf(("ShaderCache", "Metadata file does not exist.\n"));
return false;
@@ -559,7 +565,22 @@ static bool load_cached_shader_binary(opengl::ShaderProgram* program, const SCP_
auto binary_format = (GLenum) format;
json_decref(metadata_root);
auto binary_fp = cfopen(binary.c_str(), "rb", CFILE_NORMAL, CF_TYPE_CACHE);
bool supported = false;
for (auto supported_fmt : GL_binary_formats) {
if ((GLenum)supported_fmt == binary_format) {
supported = true;
break;
}
}
if (!supported) {
// This can happen in case an implementation stops supporting a particular binary format
nprintf(("ShaderCache", "Unsupported binary format %d encountered in shader cache.\n", binary_format));
return false;
}
auto binary_fp = cfopen(binary.c_str(), "rb", CFILE_NORMAL, CF_TYPE_CACHE, false,
CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
if (!binary_fp) {
nprintf(("ShaderCache", "Binary file does not exist.\n"));
return false;
@@ -622,7 +643,8 @@ static void cache_program_binary(GLuint program, const SCP_string& hash) {
auto metadata_name = base_filename + ".json";
auto binary_name = base_filename + ".bin";
auto metadata_fp = cfopen(metadata_name.c_str(), "wb", CFILE_NORMAL, CF_TYPE_CACHE);
auto metadata_fp = cfopen(metadata_name.c_str(), "wb", CFILE_NORMAL, CF_TYPE_CACHE, false,
CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
if (!metadata_fp) {
mprintf(("Could not open shader cache metadata file!\n"));
return;
@@ -637,7 +659,8 @@ static void cache_program_binary(GLuint program, const SCP_string& hash) {
cfclose(metadata_fp);
json_decref(metadata);
auto binary_fp = cfopen(binary_name.c_str(), "wb", CFILE_NORMAL, CF_TYPE_CACHE);
auto binary_fp = cfopen(binary_name.c_str(), "wb", CFILE_NORMAL, CF_TYPE_CACHE, false,
CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
if (!binary_fp) {
mprintf(("Could not open shader cache binary file!\n"));
return;
@@ -690,13 +713,13 @@ void opengl_compile_shader_actual(shader_type sdr, const uint &flags, opengl_sha
}
}
auto vert_content = opengl_get_shader_content(sdr_info->type_id, sdr_info->vert, flags, SDR_STAGE_VERTEX);
auto frag_content = opengl_get_shader_content(sdr_info->type_id, sdr_info->frag, flags, SDR_STAGE_FRAGMENT);
auto vert_content = opengl_get_shader_content(sdr_info->type_id, sdr_info->vert, flags, use_geo_sdr);
auto frag_content = opengl_get_shader_content(sdr_info->type_id, sdr_info->frag, flags, use_geo_sdr);
SCP_vector<SCP_string> geom_content;
if (use_geo_sdr) {
// read geometry shader
geom_content = opengl_get_shader_content(sdr_info->type_id, sdr_info->geo, flags, SDR_STAGE_GEOMETRY);
geom_content = opengl_get_shader_content(sdr_info->type_id, sdr_info->geo, flags, use_geo_sdr);
}
auto shader_hash = get_shader_hash(vert_content, geom_content, frag_content);
@@ -835,6 +858,62 @@ void gr_opengl_recompile_all_shaders(const std::function<void(size_t, size_t)>&
}
}
static void opengl_purge_shader_cache_type(const char* ext) {
SCP_string filter("*.");
filter += ext;
// Previously the cache files were stored in the mod directory. Since we have a better system now, those files
// should be cleaned out. This is only needed if we have a mod directory since otherwise we would delete the actual
// cache files
if (Cmdline_mod != nullptr && strlen(Cmdline_mod) > 0) {
SCP_vector<SCP_string> cache_files;
cf_get_file_list(cache_files, CF_TYPE_CACHE, filter.c_str(), CF_SORT_NONE, nullptr,
CF_LOCATION_TYPE_PRIMARY_MOD | CF_LOCATION_TYPE_SECONDARY_MODS);
for (auto& file : cache_files) {
cf_delete((file + "." + ext).c_str(), CF_TYPE_CACHE,
CF_LOCATION_TYPE_PRIMARY_MOD | CF_LOCATION_TYPE_SECONDARY_MODS);
}
}
SCP_vector<SCP_string> cache_files;
SCP_vector<file_list_info> file_info;
cf_get_file_list(cache_files, CF_TYPE_CACHE, filter.c_str(), CF_SORT_NONE, &file_info,
CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
Assertion(cache_files.size() == file_info.size(),
"cf_get_file_list returned different sizes for file names and file informations!");
const auto TIMEOUT = 2.0 * 30.0 * 24.0 * 60.0 * 60.0; // purge timeout in seconds which is ~2 months
const SCP_string PREFIX = "ogl_shader-";
auto now = std::time(nullptr);
for (size_t i = 0; i < cache_files.size(); ++i) {
auto& name = cache_files[i];
auto write_time = file_info[i].write_time;
if (name.compare(0, PREFIX.size(), PREFIX) != 0) {
// Not an OpenGL cache file
continue;
}
auto diff = std::difftime(now, write_time);
if (diff > TIMEOUT) {
auto full_name = name + "." + ext;
cf_delete(full_name.c_str(), CF_TYPE_CACHE);
}
}
}
static void opengl_purge_old_shader_cache()
{
opengl_purge_shader_cache_type("json");
opengl_purge_shader_cache_type("bin");
}
/**
* Initializes the shader system. Creates a 1x1 texture that can be used as a fallback texture when framebuffer support is missing.
* Also compiles the shaders used for particle rendering.
@@ -859,6 +938,8 @@ void opengl_shader_init()
// Reserve 32 shader slots. This should cover most use cases in real life.
GL_shader.reserve(32);
opengl_purge_old_shader_cache();
// compile effect shaders
gr_opengl_maybe_create_shader(SDR_TYPE_EFFECT_PARTICLE, 0);
gr_opengl_maybe_create_shader(SDR_TYPE_EFFECT_PARTICLE, SDR_FLAG_PARTICLE_POINT_GEN);
+7 -15
View File
@@ -106,7 +106,7 @@ static GLenum convertBufferType(BufferType type) {
case BufferType::Uniform:
return GL_UNIFORM_BUFFER;
default:
Assertion(false, "Unhandled enum value!");
UNREACHABLE("Unhandled enum value!");
return GL_INVALID_ENUM;
}
}
@@ -120,7 +120,7 @@ static GLenum convertUsageHint(BufferUsageHint usage) {
case BufferUsageHint::Streaming:
return GL_STREAM_DRAW;
default:
Assertion(false, "Unhandled enum value!");
UNREACHABLE("Unhandled enum value!");
return GL_INVALID_ENUM;
}
}
@@ -144,7 +144,7 @@ static GLenum convertStencilOp(const StencilOperation stencil_op) {
case StencilOperation::Invert:
return GL_INVERT;
default:
Assertion(false, "Unhandled enum value encountered!");
UNREACHABLE("Unhandled enum value encountered!");
return GL_NONE;
}
}
@@ -177,7 +177,7 @@ static GLenum convertComparisionFunction(ComparisionFunction func) {
mode = GL_NOTEQUAL;
break;
default:
Assertion(false, "Unhandled comparision function value!");
UNREACHABLE("Unhandled comparision function value!");
mode = GL_ALWAYS;
break;
}
@@ -758,18 +758,10 @@ void opengl_tnl_set_model_material(model_material *material_info)
GL_state.Texture.SetShaderMode(GL_TRUE);
if (GL_workaround_clipping_planes) {
if (Current_shader->flags & SDR_FLAG_MODEL_CLIP) {
GL_state.ClipDistance(0, true);
} else {
GL_state.ClipDistance(0, false);
}
if (Current_shader->flags & SDR_FLAG_MODEL_CLIP) {
GL_state.ClipDistance(0, true);
} else {
if (Current_shader->flags & SDR_FLAG_MODEL_CLIP || Current_shader->flags & SDR_FLAG_MODEL_TRANSFORM) {
GL_state.ClipDistance(0, true);
} else {
GL_state.ClipDistance(0, false);
}
GL_state.ClipDistance(0, false);
}
uint32_t array_index;
+18
View File
@@ -270,6 +270,12 @@ void NanoVGRenderer::renderFill(NVGpaint* paint,
const float* bounds,
const NVGpath* paths,
int npaths) {
if (npaths <= 0) {
// Ignore irrelevant render calls
mprintf(("NanoVG asked us to render filled triangles but no paths were supplied!\n"));
return;
}
auto call = addDrawCall();
call->type = CallType::Fill;
@@ -331,6 +337,12 @@ void NanoVGRenderer::renderFill(NVGpaint* paint,
}
}
void NanoVGRenderer::renderTriangles(NVGpaint* paint, NVGscissor* scissor, const NVGvertex* verts, int nverts) {
if (nverts <= 0) {
// Ignore irrelevant render calls
mprintf(("NanoVG asked us to render triangles but no vertices were supplied!\n"));
return;
}
_vertices.insert(_vertices.end(), verts, verts + nverts);
auto call = addDrawCall();
@@ -354,6 +366,12 @@ void NanoVGRenderer::renderStroke(NVGpaint* paint,
float strokeWidth,
const NVGpath* paths,
int npaths) {
if (npaths <= 0) {
// Ignore irrelevant render calls
mprintf(("NanoVG asked us to render stroke triangles but no paths were supplied!\n"));
return;
}
auto call = addDrawCall();
call->type = CallType::Stroke;
+9 -1
View File
@@ -1333,13 +1333,15 @@ int fonsTextIterNext(FONScontext* stash, FONStextIter* iter, FONSquad* quad)
{
FONSglyph* glyph = NULL;
const char* str = iter->next;
unsigned int last_dec_status = FONS_UTF8_ACCEPT;
iter->str = iter->next;
if (str == iter->end)
return 0;
for (; str != iter->end; str++) {
if (fons__decutf8(&iter->utf8state, &iter->codepoint, *(const unsigned char*)str))
last_dec_status = fons__decutf8(&iter->utf8state, &iter->codepoint, *(const unsigned char*)str);
if (last_dec_status)
continue;
str++;
// Get glyph and quad
@@ -1353,6 +1355,12 @@ int fonsTextIterNext(FONScontext* stash, FONStextIter* iter, FONSquad* quad)
}
iter->next = str;
if (last_dec_status) {
// If we are here then the iterator reached the end of the string and UTF-8 encoding failed
// In this case we do not have a valid code point so we need to return false
return 0;
}
return 1;
}
+2 -2
View File
@@ -2316,12 +2316,12 @@ float nvgText(NVGcontext* ctx, float x, float y, const char* string, const char*
while (fonsTextIterNext(ctx->fs, &iter, &q)) {
float c[4*2];
if (iter.prevGlyphIndex == -1) { // can not retrieve glyph?
if (!nvg__allocTextAtlas(ctx))
break; // no memory :(
if (nverts != 0) {
nvg__renderText(ctx, verts, nverts);
nverts = 0;
}
if (!nvg__allocTextAtlas(ctx))
break; // no memory :(
iter = prevIter;
fonsTextIterNext(ctx->fs, &iter, &q); // try again
if (iter.prevGlyphIndex == -1) // still can not find glyph?
+4 -4
View File
@@ -47,11 +47,11 @@ void convert_model_material(model_uniform_data* data_out,
data_out->color = material.get_color();
data_out->vpwidth = 1.0f / i2fl(gr_screen.max_w);
data_out->vpheight = 1.0f / i2fl(gr_screen.max_h);
if (shader_flags & SDR_FLAG_MODEL_ANIMATED) {
data_out->anim_timer = material.get_animated_effect_time();
data_out->effect_num = material.get_animated_effect();
data_out->vpwidth = 1.0f / i2fl(gr_screen.max_w);
data_out->vpheight = 1.0f / i2fl(gr_screen.max_h);
}
if (shader_flags & SDR_FLAG_MODEL_CLIP) {
@@ -267,8 +267,8 @@ void convert_model_material(model_uniform_data* data_out,
data_out->normalAlphaMinMax.y = material.get_normal_alpha_max();
}
if (shader_flags & SDR_FLAG_MODEL_NORMAL_EXTRUDE) {
data_out->extrudeWidth = material.get_normal_extrude_width();
if ( shader_flags & SDR_FLAG_MODEL_THICK_OUTLINES ) {
data_out->outlineWidth = material.get_outline_thickness();
}
}
+1 -1
View File
@@ -12,7 +12,7 @@ BufferType getBufferType(GpuHeap heap_type) {
return BufferType::Index;
case GpuHeap::NUM_VALUES:
default:
Assertion(false, "Invalid heap type detected!");
UNREACHABLE("Invalid heap type detected!");
return BufferType::Vertex;
}
}
+2 -2
View File
@@ -17,7 +17,7 @@ size_t getElementSize(uniform_block_type type) {
return sizeof(graphics::decal_info);
case uniform_block_type::NUM_BLOCK_TYPES:
default:
Assertion(false, "Invalid block type encountered!");
UNREACHABLE("Invalid block type encountered!");
return 0;
}
}
@@ -33,7 +33,7 @@ size_t getHeaderSize(uniform_block_type type) {
return 0;
case uniform_block_type::NUM_BLOCK_TYPES:
default:
Assertion(false, "Invalid block type encountered!");
UNREACHABLE("Invalid block type encountered!");
return 0;
}
}
+1 -1
View File
@@ -80,7 +80,7 @@ struct model_uniform_data {
model_light lights[MAX_UNIFORM_LIGHTS];
float extrudeWidth;
float outlineWidth;
float fogStart;
float fogScale;
int buffer_matrix_offset;
+12 -12
View File
@@ -85,7 +85,7 @@ int HUD_disable_except_messages = 0;
color HUD_color_defaults[HUD_NUM_COLOR_LEVELS]; // array of colors with different alpha blending
color HUD_color_debug; // grey debug text shown on HUD
static int Player_engine_snd_loop = -1;
static sound_handle Player_engine_snd_loop = sound_handle::invalid();
// HUD render frame offsets
float HUD_offset_x = 0.0f;
@@ -1420,7 +1420,7 @@ void hud_update_frame(float /*frametime*/)
}
if (Player_ai->target_objnum == -1) {
if ( Target_static_looping != -1 ) {
if (Target_static_looping.isValid()) {
snd_stop(Target_static_looping);
}
return;
@@ -1810,9 +1810,9 @@ void hud_render_gauges(int cockpit_display_num)
*/
void hud_stop_looped_engine_sounds()
{
if ( Player_engine_snd_loop > -1 ) {
if (Player_engine_snd_loop.isValid()) {
snd_stop(Player_engine_snd_loop);
Player_engine_snd_loop = -1;
Player_engine_snd_loop = sound_handle::invalid();
}
}
@@ -1831,9 +1831,9 @@ void update_throttle_sound()
float percent_throttle;
if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER)){
if(Player_engine_snd_loop != -1){
if (Player_engine_snd_loop.isValid()) {
snd_stop(Player_engine_snd_loop);
Player_engine_snd_loop = -1;
Player_engine_snd_loop = sound_handle::invalid();
}
return;
@@ -1851,16 +1851,16 @@ void update_throttle_sound()
percent_throttle = Player_obj->phys_info.fspeed / Ships[Player_obj->instance].current_max_speed;
}
if ( percent_throttle != last_percent_throttle || Player_engine_snd_loop == -1 ) {
if (percent_throttle != last_percent_throttle || !Player_engine_snd_loop.isValid()) {
if ( percent_throttle < ZERO_PERCENT ) {
if ( Player_engine_snd_loop > -1 ) {
if (Player_engine_snd_loop.isValid()) {
snd_stop(Player_engine_snd_loop); // Backslash - otherwise, long engine loops keep playing
Player_engine_snd_loop = -1;
Player_engine_snd_loop = sound_handle::invalid();
}
}
else {
if ( Player_engine_snd_loop == -1 ){
if (!Player_engine_snd_loop.isValid()) {
Player_engine_snd_loop = snd_play_looping( gamesnd_get_game_sound(ship_get_sound(Player_obj, GameSounds::ENGINE)), 0.0f , -1, -1, percent_throttle * ENGINE_MAX_VOL, FALSE);
} else {
// The sound may have been trashed at the low-level if sound channel overflow.
@@ -1869,7 +1869,7 @@ void update_throttle_sound()
snd_set_volume(Player_engine_snd_loop, percent_throttle * ENGINE_MAX_VOL);
}
else {
Player_engine_snd_loop = -1;
Player_engine_snd_loop = sound_handle::invalid();
}
}
}
@@ -2895,7 +2895,7 @@ void HudGaugeSupport::render(float /*frametime*/)
}
else
{
sprintf(outstr, "Waiting...");
strcpy_s(outstr, XSTR("Waiting...", 1603));
}
}
renderStringAlignCenter(position[0], position[1] + text_val_offset_y, w, outstr);
+3 -3
View File
@@ -153,7 +153,7 @@ void parse_ssm(const char *filename)
s.shape = SSM_SHAPE_SPHERE;
break;
default:
Assertion(false, "Impossible return value from required_string_one_of(); get a coder!\n");
UNREACHABLE("Impossible return value from required_string_one_of(); get a coder!\n");
}
} else {
s.shape = SSM_SHAPE_CIRCLE;
@@ -224,7 +224,7 @@ void ssm_get_random_start_pos(vec3d *out, vec3d *start, matrix *orient, size_t s
switch (s->shape) {
case SSM_SHAPE_SPHERE:
// get a random vector in a sphere around the target
vm_vec_random_in_sphere(&temp, start, orient, radius, 1);
vm_vec_random_in_sphere(&temp, start, radius, 1);
break;
case SSM_SHAPE_CIRCLE:
// get a random vector in the circle of the firing plane
@@ -235,7 +235,7 @@ void ssm_get_random_start_pos(vec3d *out, vec3d *start, matrix *orient, size_t s
vm_vec_scale_add(&temp, start, &orient->vec.fvec, radius);
break;
default:
Assertion(false, "Unknown shape '%d' in SSM type #" SIZE_T_ARG " ('%s'). This should not be possible; get a coder!\n", s->shape, ssm_index, s->name);
UNREACHABLE("Unknown shape '%d' in SSM type #" SIZE_T_ARG " ('%s'). This should not be possible; get a coder!\n", s->shape, ssm_index, s->name);
break;
}
+1 -1
View File
@@ -1013,7 +1013,7 @@ void HudGaugeBrackets::renderBoundingBrackets(int x1, int y1, int x2, int y2, in
tinfo_name = XSTR("Debris", 348);
break;
case OBJ_WEAPON:
strcpy_s(temp_name, Weapon_info[Weapons[t_objp->instance].weapon_info_index].name);
strcpy_s(temp_name, Weapon_info[Weapons[t_objp->instance].weapon_info_index].get_display_string());
end_string_at_first_hash_symbol(temp_name);
tinfo_name = temp_name;
break;
+4 -2
View File
@@ -1642,7 +1642,8 @@ void hud_config_as_player()
void hud_config_color_save(char *name)
{
int idx;
CFILE *out = cfopen(name, "wt", CFILE_NORMAL, CF_TYPE_PLAYERS);
CFILE* out = cfopen(name, "wt", CFILE_NORMAL, CF_TYPE_PLAYERS, false,
CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
char vals[255] = "";
// bad
@@ -1843,7 +1844,8 @@ void hud_config_color_init()
// get a list of all hcf files
memset(HC_filenames, 0, sizeof(char*) * MAX_HCF_FILES);
HC_num_files = cf_get_file_list(MAX_HCF_FILES, HC_filenames, CF_TYPE_PLAYERS, "*.hcf", CF_SORT_NAME);
HC_num_files = cf_get_file_list(MAX_HCF_FILES, HC_filenames, CF_TYPE_PLAYERS, "*.hcf", CF_SORT_NAME, nullptr,
CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
}
void hud_config_color_close()
+1 -1
View File
@@ -372,7 +372,7 @@ void HudGaugeEscort::renderIcon(int x, int y, int index)
}
// print out ship name
strcpy_s(buf, sp->ship_name);
strcpy_s(buf, sp->get_display_string());
font::force_fit_string(buf, 255, ship_name_max_width);
end_string_at_first_hash_symbol(buf);
+11 -11
View File
@@ -36,8 +36,8 @@ vec3d lock_world_pos;
static float Lock_start_dist;
int Missile_track_loop = -1;
int Missile_lock_loop = -1;
sound_handle Missile_track_loop = sound_handle::invalid();
sound_handle Missile_lock_loop = sound_handle::invalid();
int Lock_target_box_width[GR_NUM_RESOLUTIONS] = {
19,
@@ -606,9 +606,9 @@ void hud_do_lock_indicator(float frametime)
return;
if (Player_ai->current_target_is_locked) {
if ( Missile_track_loop > -1 ) {
if (Missile_track_loop.isValid()) {
snd_stop(Missile_track_loop);
Missile_track_loop = -1;
Missile_track_loop = sound_handle::invalid();
if (wip->hud_locked_snd.isValid())
{
@@ -622,9 +622,9 @@ void hud_do_lock_indicator(float frametime)
}
else {
Player_ai->ai_flags.set(AI::AI_Flags::Seek_lock); // set this flag so multiplayer's properly track lock on other ships
if ( Missile_lock_loop != -1 && snd_is_playing(Missile_lock_loop) ) {
if (Missile_lock_loop.isValid() && snd_is_playing(Missile_lock_loop)) {
snd_stop(Missile_lock_loop);
Missile_lock_loop = -1;
Missile_lock_loop = sound_handle::invalid();
}
}
}
@@ -840,7 +840,7 @@ void hud_calculate_lock_position(float frametime)
accumulated_y_pixels -= int_portion;
}
if ( Missile_track_loop == -1 ) {
if (!Missile_track_loop.isValid()) {
if (wip->hud_tracking_snd.isValid())
{
Missile_track_loop = snd_play_looping( gamesnd_get_game_sound(wip->hud_tracking_snd), 0.0f , -1, -1);
@@ -863,9 +863,9 @@ void hud_calculate_lock_position(float frametime)
} else {
if ( Missile_track_loop > -1 ) {
if (Missile_track_loop.isValid()) {
snd_stop(Missile_track_loop);
Missile_track_loop = -1;
Missile_track_loop = sound_handle::invalid();
}
Player_ai->current_target_is_locked = 0;
@@ -977,9 +977,9 @@ void hud_calculate_lock_start_pos()
// hud_stop_looped_locking_sounds() will terminate any hud related looping sounds that are playing
void hud_stop_looped_locking_sounds()
{
if ( Missile_track_loop > -1 ) {
if (Missile_track_loop.isValid()) {
snd_stop(Missile_track_loop);
Missile_track_loop = -1;
Missile_track_loop = sound_handle::invalid();
}
}
+1 -1
View File
@@ -558,7 +558,7 @@ void HUD_ship_sent_printf(int sh, const char *format, ...)
tmp[sizeof(tmp)-1] = '\0';
size_t len;
snprintf(tmp, sizeof(tmp)-1, NOX("%s: "), Ships[sh].ship_name);
snprintf(tmp, sizeof(tmp)-1, NOX("%s: "), Ships[sh].get_display_string());
len = strlen(tmp);
va_start(args, format);
+1
View File
@@ -30,6 +30,7 @@ void hud_observer_init(ship *shipp, ai_info *aip)
// (we used to do a memcpy here, but that doesn't work any longer, so let's just assign the values we need)
Hud_obs_ship.clear();
strcpy_s(Hud_obs_ship.ship_name, shipp->ship_name);
Hud_obs_ship.display_name = shipp->display_name;
Hud_obs_ship.team = shipp->team;
Hud_obs_ship.ai_index = shipp->ai_index;
Hud_obs_ship.flags = shipp->flags;
+1 -1
View File
@@ -404,7 +404,7 @@ int hud_squadmsg_count_ships(int add_to_menu)
if (add_to_menu)
{
Assert ( Num_menu_items < MAX_MENU_ITEMS );
strcpy_s( MsgItems[Num_menu_items].text, shipp->ship_name );
strcpy_s( MsgItems[Num_menu_items].text, shipp->get_display_string() );
end_string_at_first_hash_symbol(MsgItems[Num_menu_items].text); // truncate the name if it has a # in it
MsgItems[Num_menu_items].instance = SHIP_INDEX(shipp);
MsgItems[Num_menu_items].active = 1;
+48 -34
View File
@@ -37,6 +37,7 @@
#include "network/multi.h"
#include "network/multiutil.h"
#include "object/object.h"
#include "libs/renderdoc/renderdoc.h"
#include "parse/parselo.h"
#include "playerman/player.h"
#include "render/3dinternal.h"
@@ -437,7 +438,7 @@ weapon_flash Weapon_flash_info;
// Data used for the proximity warning
typedef struct homing_beep_info
{
int snd_handle; // sound handle for last played beep
sound_handle snd_handle; // sound handle for last played beep
fix last_time_played; // time beep was last played
int min_cycle_time; // time (in ms) for fastest cycling of the sound
int max_cycle_time; // time (in ms) for slowest cycling of the sound
@@ -446,7 +447,7 @@ typedef struct homing_beep_info
float precalced_interp; // a precalculated value used in a linear interpretation
} homing_beep_info;
homing_beep_info Homing_beep = { -1, 0, 150, 1000, 30.0f, 1500.0f, 1.729412f };
homing_beep_info Homing_beep = {sound_handle::invalid(), 0, 150, 1000, 30.0f, 1500.0f, 1.729412f};
// Set at the start of a mission, used to decide how to draw the separation for the warning missile indicators
float Min_warning_missile_dist;
@@ -1009,7 +1010,7 @@ void hud_weapons_init()
// init data used to play the homing "proximity warning" sound
void hud_init_homing_beep()
{
Homing_beep.snd_handle = -1;
Homing_beep.snd_handle = sound_handle::invalid();
Homing_beep.last_time_played = 0;
Homing_beep.precalced_interp = (Homing_beep.max_cycle_dist-Homing_beep.min_cycle_dist) / (Homing_beep.max_cycle_time - Homing_beep.min_cycle_time );
}
@@ -5292,16 +5293,18 @@ void hud_stuff_ship_name(char *ship_name_text, ship *shipp)
if ( ((Iff_info[shipp->team].flags & IFFF_WING_NAME_HIDDEN) && (shipp->wingnum != -1)) || (shipp->flags[Ship::Ship_Flags::Hide_ship_name]) ) {
*ship_name_text = 0;
} else {
strcpy(ship_name_text, shipp->ship_name);
strcpy(ship_name_text, shipp->get_display_string());
// handle hash symbol
end_string_at_first_hash_symbol(ship_name_text);
// handle translation
if (Lcl_gr) {
lcl_translate_targetbox_name_gr(ship_name_text);
} else if (Lcl_pl) {
lcl_translate_targetbox_name_pl(ship_name_text);
if (!Disable_built_in_translations) {
// handle translation
if (Lcl_gr) {
lcl_translate_targetbox_name_gr(ship_name_text);
} else if (Lcl_pl) {
lcl_translate_targetbox_name_pl(ship_name_text);
}
}
}
}
@@ -5333,11 +5336,13 @@ void hud_stuff_ship_callsign(char *ship_callsign_text, ship *shipp)
// handle hash symbol
end_string_at_first_hash_symbol(ship_callsign_text);
// handle translation
if (Lcl_gr) {
lcl_translate_targetbox_name_gr(ship_callsign_text);
} else if (Lcl_pl) {
lcl_translate_targetbox_name_pl(ship_callsign_text);
if (!Disable_built_in_translations) {
// handle translation
if (Lcl_gr) {
lcl_translate_targetbox_name_gr(ship_callsign_text);
} else if (Lcl_pl) {
lcl_translate_targetbox_name_pl(ship_callsign_text);
}
}
}
@@ -5362,11 +5367,13 @@ void hud_stuff_ship_class(char *ship_class_text, ship *shipp)
// handle hash symbol
end_string_at_first_hash_symbol(ship_class_text);
// handle translation
if (Lcl_gr) {
lcl_translate_targetbox_name_gr(ship_class_text);
} else if (Lcl_pl) {
lcl_translate_targetbox_name_pl(ship_class_text);
if (!Disable_built_in_translations) {
// handle translation
if (Lcl_gr) {
lcl_translate_targetbox_name_gr(ship_class_text);
} else if (Lcl_pl) {
lcl_translate_targetbox_name_pl(ship_class_text);
}
}
}
@@ -5592,7 +5599,7 @@ void HudGaugeWeaponEnergy::render(float /*frametime*/)
setGaugeColor(HUD_C_BRIGHT);
//Draw name
renderString(currentx, currenty, "Energy");
renderString(currentx, currenty, XSTR("Energy", 1616));
currenty += line_height;
//Draw background
@@ -5626,10 +5633,11 @@ void HudGaugeWeaponEnergy::render(float /*frametime*/)
setGaugeColor(HUD_C_NORMAL);
}
if(gr_screen.max_w_unscaled == 640) {
strcpy_s(shortened_name, Weapon_info[Player_ship->weapons.primary_bank_weapons[x]].get_display_string());
font::force_fit_string(shortened_name, NAME_LENGTH, 55);
renderString(currentx, currenty, shortened_name);
} else {
renderString(currentx, currenty, Weapon_info[Player_ship->weapons.primary_bank_weapons[x]].name);
renderString(currentx, currenty, Weapon_info[Player_ship->weapons.primary_bank_weapons[x]].get_display_string());
}
//Next 'line'
@@ -5747,7 +5755,7 @@ void HudGaugeWeaponEnergy::render(float /*frametime*/)
// show all primary banks
for ( i = 0; i < Player_ship->weapons.num_primary_banks; i++ ) {
wip = &Weapon_info[sw->primary_bank_weapons[i]];
strcpy_s(buf, (wip->alt_name[0]) ? wip->alt_name : wip->name);
strcpy_s(buf, wip->get_display_string());
if ( Armed_alignment ) {
gr_get_string_size(&w, &h, buf);
@@ -5761,7 +5769,7 @@ void HudGaugeWeaponEnergy::render(float /*frametime*/)
// just show the current armed bank
i = Player_ship->weapons.current_primary_bank;
wip = &Weapon_info[sw->primary_bank_weapons[i]];
strcpy_s(buf, (wip->alt_name[0]) ? wip->alt_name : wip->name);
strcpy_s(buf, wip->get_display_string());
if ( Armed_alignment ) {
gr_get_string_size(&w, &h, buf);
@@ -6051,8 +6059,8 @@ void HudGaugeWeapons::render(float /*frametime*/)
renderBitmap(primary_last[ballistic_hud_index].first_frame, position[0] + frame_offset_x[ballistic_hud_index], y);
}
strcpy_s(name, (Weapon_info[sw->primary_bank_weapons[i]].alt_name[0]) ? Weapon_info[sw->primary_bank_weapons[i]].alt_name : Weapon_info[sw->primary_bank_weapons[i]].name);
if (Lcl_gr) {
strcpy_s(name, Weapon_info[sw->primary_bank_weapons[i]].get_display_string());
if (Lcl_gr && !Disable_built_in_translations) {
lcl_translate_wep_name_gr(name);
}
@@ -6119,11 +6127,16 @@ void HudGaugeWeapons::render(float /*frametime*/)
maybeFlashWeapon(np+i);
// HACK - make Cluster Bomb fit on the HUD.
if(!stricmp(wip->name,"cluster bomb")){
strcpy_s(weapon_name, NOX("Cluster"));
if (wip->has_alternate_name()) {
// Do not apply the cluster bomb hack if we have an alternate name to make translating that name possible
strcpy_s(weapon_name, wip->get_display_string());
} else {
strcpy_s(weapon_name, (wip->alt_name[0]) ? wip->alt_name : wip->name);
// HACK - make Cluster Bomb fit on the HUD.
if(!stricmp(wip->name,"cluster bomb")){
strcpy_s(weapon_name, NOX("Cluster"));
} else {
strcpy_s(weapon_name, wip->get_display_string());
}
}
// get rid of #
@@ -6684,7 +6697,7 @@ void HudGaugeWarheadCount::render(float /*frametime*/)
}
char weapon_name[NAME_LENGTH + 10];
strcpy_s(weapon_name, (wip->alt_name[0]) ? wip->alt_name : wip->name);
strcpy_s(weapon_name, wip->get_display_string());
end_string_at_first_hash_symbol(weapon_name);
setGaugeColor();
@@ -6921,9 +6934,9 @@ void HudGaugePrimaryWeapons::render(float /*frametime*/)
renderBitmap(_background_entry.first_frame, position[0], position[1] + bg_y_offset);
strcpy_s(name, (Weapon_info[sw->primary_bank_weapons[i]].alt_name[0]) ? Weapon_info[sw->primary_bank_weapons[i]].alt_name : Weapon_info[sw->primary_bank_weapons[i]].name);
strcpy_s(name, Weapon_info[sw->primary_bank_weapons[i]].get_display_string());
if (Lcl_gr) {
if (Lcl_gr && !Disable_built_in_translations) {
lcl_translate_wep_name_gr(name);
}
@@ -7040,7 +7053,7 @@ void HudGaugeSecondaryWeapons::render(float /*frametime*/)
maybeFlashWeapon(num_primaries+i);
strcpy_s(weapon_name, (wip->alt_name[0]) ? wip->alt_name : wip->name);
strcpy_s(weapon_name, wip->get_display_string());
end_string_at_first_hash_symbol(weapon_name);
if ( sw->current_secondary_bank == i ) {
@@ -7182,7 +7195,8 @@ void HudGaugeHardpoints::render(float /*frametime*/)
render_info.set_color(gauge_color);
render_info.set_flags(MR_NO_LIGHTING | MR_AUTOCENTER | MR_NO_FOGGING | MR_NO_TEXTURING | MR_NO_ZBUFFER | MR_NO_CULL | MR_STENCIL_READ);
render_info.set_normal_extrude_width(_line_width * 0.01f);
// Factor was chosen pretty arbitrarily to make outline feature work with existing data
render_info.set_outline_thickness(15.f * _line_width);
model_render_immediate(
&render_info,
+23 -17
View File
@@ -55,7 +55,7 @@ object *Enemy_attacker = NULL;
static int Target_static_next;
static int Target_static_playing;
int Target_static_looping;
sound_handle Target_static_looping = sound_handle::invalid();
int Target_display_cargo;
char Cargo_string[256] = "";
@@ -1008,7 +1008,7 @@ void HudGaugeTargetBox::renderTargetWeapon(object *target_objp)
setGaugeColor();
// print out the weapon class name
sprintf( outstr,"%s", target_wip->name );
sprintf( outstr,"%s", target_wip->get_display_string() );
gr_get_string_size(&w,&h,outstr);
// drop name past the # sign
@@ -1034,7 +1034,7 @@ void HudGaugeTargetBox::renderTargetWeapon(object *target_objp)
dist = vm_vec_dist(&target_objp->pos, &wp->homing_pos);
if ( speed > 0 ) {
sprintf(outstr, NOX("impact: %.1f sec"), dist/speed);
sprintf(outstr, XSTR("impact: %.1f sec", 1596), dist/speed);
} else {
strcpy_s(outstr, XSTR( "unknown", 349));
}
@@ -1405,7 +1405,7 @@ void HudGaugeExtraTargetData::pageIn()
*/
void HudGaugeExtraTargetData::render(float /*frametime*/)
{
char outstr[256], tmpbuf[256];
char tmpbuf[256];
int has_orders = 0;
int not_training;
int extra_data_shown=0;
@@ -1440,17 +1440,22 @@ void HudGaugeExtraTargetData::render(float /*frametime*/)
!(Iff_info[target_shipp->team].flags & IFFF_ORDERS_HIDDEN)))
&& Ship_info[target_shipp->ship_info_index].is_flyable()) {
extra_data_shown = 1;
if (ship_return_orders(outstr, target_shipp)) {
auto orders = ship_return_orders(target_shipp);
if (!orders.empty()) {
char outstr[256];
strcpy_s(outstr, orders.c_str());
font::force_fit_string(outstr, 255, order_max_w);
orders = outstr;
has_orders = 1;
} else {
strcpy_s(outstr, XSTR("no orders", 337));
orders = XSTR("no orders", 337);
}
renderString(position[0] + order_offsets[0], position[1] + order_offsets[1], EG_TBOX_EXTRA1, outstr);
renderString(position[0] + order_offsets[0], position[1] + order_offsets[1], EG_TBOX_EXTRA1, orders.c_str());
}
if ( has_orders ) {
char outstr[256];
strcpy_s(outstr, XSTR( "time to: ", 338));
if ( ship_return_time_to_goal(tmpbuf, target_shipp) ) {
strcat_s(outstr, tmpbuf);
@@ -1471,10 +1476,11 @@ void HudGaugeExtraTargetData::render(float /*frametime*/)
// count the objects directly docked to me
int dock_count = dock_count_direct_docked_objects(target_objp);
char outstr[256];
// docked to only one object
if (dock_count == 1)
{
sprintf(outstr, XSTR("Docked: %s", 339), Ships[dock_get_first_docked_object(target_objp)->instance].ship_name);
sprintf(outstr, XSTR("Docked: %s", 339), Ships[dock_get_first_docked_object(target_objp)->instance].get_display_string());
end_string_at_first_hash_symbol(outstr);
}
// docked to multiple objects
@@ -2040,10 +2046,10 @@ void HudGaugeTargetBox::showTargetData(float /*frametime*/)
float dot, dist;
vec3d v2t;
if (aip->target_objnum == Player_obj-Objects)
if (aip->target_objnum == OBJ_INDEX(Player_obj))
strcpy_s(target_str, "Player!");
else
sprintf(target_str, "%s", Ships[Objects[aip->target_objnum].instance].ship_name);
sprintf(target_str, "%s", Ships[Objects[aip->target_objnum].instance].get_display_string());
gr_printf_no_resize(sx, sy, "Targ: %s", target_str);
sy += dy;
@@ -2091,14 +2097,14 @@ void HudGaugeTargetBox::showTargetData(float /*frametime*/)
eshipp = &Ships[Enemy_attacker->instance];
eaip = &Ai_info[eshipp->ai_index];
if (eaip->target_objnum == Player_obj-Objects) {
if (eaip->target_objnum == OBJ_INDEX(Player_obj)) {
found = 1;
dist = vm_vec_dist_quick(&Enemy_attacker->pos, &Player_obj->pos);
vm_vec_normalized_dir(&v2t,&Objects[eaip->target_objnum].pos, &Enemy_attacker->pos);
dot = vm_vec_dot(&v2t, &Enemy_attacker->orient.vec.fvec);
gr_printf_no_resize(sx, sy, "#%i: %s", OBJ_INDEX(Enemy_attacker), Ships[Enemy_attacker->instance].ship_name);
gr_printf_no_resize(sx, sy, "#%i: %s", OBJ_INDEX(Enemy_attacker), Ships[Enemy_attacker->instance].get_display_string());
sy += dy;
gr_printf_no_resize(sx, sy, "Targ dist: %5.1f", dist);
sy += dy;
@@ -2158,7 +2164,7 @@ void HudGaugeTargetBox::showTargetData(float /*frametime*/)
gr_printf_no_resize(sx,sy,"%s", outstr);
sy += dy;
for ( i = 0; i < swp->num_primary_banks; i++ ) {
sprintf(outstr,"%d. %s", i+1, Weapon_info[swp->primary_bank_weapons[i]].name);
sprintf(outstr,"%d. %s", i+1, Weapon_info[swp->primary_bank_weapons[i]].get_display_string());
gr_printf_no_resize(sx,sy,"%s", outstr);
sy += dy;
}
@@ -2168,7 +2174,7 @@ void HudGaugeTargetBox::showTargetData(float /*frametime*/)
gr_printf_no_resize(sx,sy,"%s", outstr);
sy += dy;
for ( i = 0; i < swp->num_secondary_banks; i++ ) {
sprintf(outstr,"%d. %s", i+1, Weapon_info[swp->secondary_bank_weapons[i]].name);
sprintf(outstr,"%d. %s", i+1, Weapon_info[swp->secondary_bank_weapons[i]].get_display_string());
gr_printf_no_resize(sx,sy,"%s", outstr);
sy += dy;
}
@@ -2222,13 +2228,13 @@ void hud_update_target_static()
}
if ( Target_static_playing ) {
if ( Target_static_looping == -1 ) {
if (!Target_static_looping.isValid()) {
Target_static_looping = snd_play_looping(gamesnd_get_game_sound(GameSounds::STATIC));
}
} else {
if ( Target_static_looping != -1 ) {
if (Target_static_looping.isValid()) {
snd_stop(Target_static_looping);
Target_static_looping = -1;
Target_static_looping = sound_handle::invalid();
}
}
}
+1 -1
View File
@@ -29,7 +29,7 @@ class object;
#define TBOX_FLASH_STATUS 3
#define TBOX_FLASH_SUBSYS 4
extern int Target_static_looping;
extern sound_handle Target_static_looping;
extern int Target_display_cargo;
extern char Cargo_string[256];
+12 -15
View File
@@ -140,7 +140,7 @@ size_t factor_table::getNext(size_t n, size_t current)
}
}
Assertion(false, "For some reason, factor_table::getNext() was unable to locate the current factor. This should never happen; get a coder!\n");
UNREACHABLE("For some reason, factor_table::getNext() was unable to locate the current factor. This should never happen; get a coder!\n");
return 1;
}
@@ -211,7 +211,6 @@ static struct Cheat cheatsTable[] = {
int Tool_enabled = 0;
bool Perspective_locked=false;
bool quit_mission_popup_shown = false;
extern int AI_watch_object;
extern int Countermeasures_enabled;
@@ -897,7 +896,7 @@ void process_debug_keys(int k)
object *objp = &Objects[Player_ai->target_objnum];
objp->flags.toggle(Object::Object_Flags::Invulnerable);
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Player's target [%s] is %s", 13), Ships[objp->instance].ship_name, objp->flags[Object::Object_Flags::Invulnerable] ? XSTR( "now INVULNERABLE!", 11) : XSTR( "no longer invulnerable...", 12));
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Player's target [%s] is %s", 13), Ships[objp->instance].get_display_string(), objp->flags[Object::Object_Flags::Invulnerable] ? XSTR( "now INVULNERABLE!", 11) : XSTR( "no longer invulnerable...", 12));
}
break;
@@ -977,7 +976,7 @@ void process_debug_keys(int k)
int *weap = &shipp->weapons.secondary_bank_weapons[shipp->weapons.current_secondary_bank];
*weap = get_next_weapon_looped(*weap, WP_MISSILE);
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Secondary Weapon forced to %s", 18), Weapon_info[*weap].name);
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Secondary Weapon forced to %s", 18), Weapon_info[*weap].get_display_string());
break;
}
@@ -990,7 +989,7 @@ void process_debug_keys(int k)
int *weap = &shipp->weapons.secondary_bank_weapons[shipp->weapons.current_secondary_bank];
*weap = get_prev_weapon_looped(*weap, WP_MISSILE);
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Secondary Weapon forced to %s", 18), Weapon_info[*weap].name);
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Secondary Weapon forced to %s", 18), Weapon_info[*weap].get_display_string());
break;
}
@@ -1019,7 +1018,7 @@ void process_debug_keys(int k)
int *weap = &shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank];
*weap = get_next_weapon_looped(*weap, WP_LASER);
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Primary Weapon forced to %s", 19), Weapon_info[*weap].name);
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Primary Weapon forced to %s", 19), Weapon_info[*weap].get_display_string());
break;
}
@@ -1031,7 +1030,7 @@ void process_debug_keys(int k)
int *weap = &shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank];
*weap = get_prev_weapon_looped(*weap, WP_LASER);
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Primary Weapon forced to %s", 19), Weapon_info[*weap].name);
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Primary Weapon forced to %s", 19), Weapon_info[*weap].get_display_string());
break;
}
@@ -1067,12 +1066,12 @@ void process_debug_keys(int k)
if (is_support_allowed(obj_to_rearm))
{
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR("Issuing rearm request for %s", -1), Ships[obj_to_rearm->instance].ship_name);
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR("Issuing rearm request for %s", 1610), Ships[obj_to_rearm->instance].get_display_string());
ai_issue_rearm_request(obj_to_rearm);
}
else
{
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR("Cannot issue rearm request for %s", -1), Ships[obj_to_rearm->instance].ship_name);
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR("Cannot issue rearm request for %s", 1611), Ships[obj_to_rearm->instance].get_display_string());
}
break;
@@ -1326,7 +1325,7 @@ void ppsk_hotkeys(int k)
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "No target to add/remove from set %d.", 26), hotkey_set+1);
else {
hud_target_hotkey_add_remove( hotkey_set, &Objects[Player_ai->target_objnum], HOTKEY_USER_ADDED);
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "%s added to set %d. (F%d)", 27), Ships[Objects[Player_ai->target_objnum].instance].ship_name, hotkey_set, 4+hotkey_set+1);
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "%s added to set %d. (F%d)", 27), Ships[Objects[Player_ai->target_objnum].instance].get_display_string(), hotkey_set, 4+hotkey_set+1);
}
break;
@@ -1442,8 +1441,6 @@ void game_do_end_mission_popup()
game_stop_looped_sounds();
snd_stop_all();
quit_mission_popup_shown = true;
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));
@@ -1459,7 +1456,6 @@ void game_do_end_mission_popup()
default:
break; // do nothing
}
quit_mission_popup_shown = false;
game_start_time();
game_flush();
@@ -1573,6 +1569,7 @@ void game_process_cheats(int k)
ship *shipp = &Ships[Objects[objnum].instance];
shipp->ship_name[0] = '\0';
shipp->display_name.clear();
shipp->orders_accepted = (1<<NUM_COMM_ORDER_ITEMS)-1;
// Goober5000 - stolen from support ship creation
@@ -2427,10 +2424,10 @@ int button_function(int n)
HUD_printf("%s", XSTR("Engine failure. Cannot engage subspace drive.", 40));
} else if (!ship_navigation_ok_to_warp(Player_ship)) {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
HUD_printf("%s", XSTR("Navigation failure. Cannot engage subspace drive.", 1596));
HUD_printf("%s", XSTR("Navigation failure. Cannot engage subspace drive.", 1572));
} else if ( (Player_obj != NULL) && object_get_gliding(Player_obj)) {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
HUD_printf("%s", XSTR("Cannot engage subspace drive while gliding.", 1597));
HUD_printf("%s", XSTR("Cannot engage subspace drive while gliding.", 1573));
} else {
gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_START );
}
-2
View File
@@ -23,8 +23,6 @@ extern bool Perspective_locked;
extern int Ignored_keys[];
extern bool quit_mission_popup_shown;
typedef struct button_info
{
int status[NUM_BUTTON_FIELDS];
+30 -11
View File
@@ -920,7 +920,7 @@ void labviewer_update_variables_window()
Assert(Lab_selected_index < Num_weapon_types);
weapon_info *wip = &Weapon_info[Lab_selected_index];
VAR_SET_VALUE(wip->name);
VAR_SET_VALUE(wip->get_display_string());
VAR_SET_VALUE_SAVE(wip->subtype, Num_weapon_subtypes - 1);
VAR_SET_VALUE_SAVE(wip->mass, 0);
@@ -1257,7 +1257,7 @@ void labviewer_update_desc_window()
}
}
else if (Lab_mode == LAB_MODE_WEAPON) {
Lab_description_window->SetCaption(Weapon_info[Lab_selected_index].name);
Lab_description_window->SetCaption(Weapon_info[Lab_selected_index].get_display_string());
if (Weapon_info[Lab_selected_index].tech_desc != NULL) {
Lab_description_text->SetText(Weapon_info[Lab_selected_index].tech_desc);
@@ -1543,7 +1543,7 @@ void labviewer_make_weap_window(Button* /*caller*/)
stip = type_nodes[Weapon_info[i].subtype];
}
cmp->AddItem(stip, Weapon_info[i].name, i, false, labviewer_change_weapon);
cmp->AddItem(stip, Weapon_info[i].get_display_string(), i, false, labviewer_change_weapon);
//if (Weapon_info[i].tech_model[0] != '\0') {
// cmp->AddItem(cwip, "Tech Model", 0, false, labviewer_show_tech_model);
@@ -1599,7 +1599,7 @@ char envmap_name[MAX_FILENAME_LEN];
const char* mission_ext_list[] = { ".fs2" };
SCP_string get_directory_or_vp(char* path)
SCP_string get_directory_or_vp(const char* path)
{
SCP_string result(path);
@@ -1806,6 +1806,7 @@ void labviewer_change_background_actual()
else {
// (DahBlount) - This spot should be used to disable rendering features that only apply to missions.
Motion_debris_override = true;
Num_stars = 0;
}
}
@@ -1832,14 +1833,15 @@ void labviewer_make_background_window(Button* /*caller*/)
cf_get_file_list(missions, CF_TYPE_MISSIONS, NOX("*.fs2"));
SCP_map<SCP_string, SCP_vector<SCP_string>> directories;
char fullpath[MAX_PATH_LEN];
for (const auto& filename : missions)
{
cf_find_file_location((filename + ".fs2").c_str(), CF_TYPE_MISSIONS, sizeof(fullpath) - 1, fullpath, NULL, NULL);
auto location = get_directory_or_vp(fullpath);
for (const auto& filename : missions) {
auto res = cf_find_file_location((filename + ".fs2").c_str(), CF_TYPE_MISSIONS);
directories[location].push_back(filename);
if (res.found) {
auto location = get_directory_or_vp(res.full_name.c_str());
directories[location].push_back(filename);
}
}
Num_mission_directories = directories.size();
@@ -1924,6 +1926,10 @@ void lab_init()
Lab_viewer_flags |= LAB_FLAG_NO_ROTATION;
Lab_viewer_flags |= LAB_FLAG_INITIAL_ROTATION;
obj_init();
//Reset the background
labviewer_change_background_actual();
flagset<Object::Object_Flags> obs_flags;
auto obj_index = obj_create(OBJ_OBSERVER, -1, 0, &vmd_identity_matrix, &vmd_zero_vector, 0, obs_flags);
@@ -1941,6 +1947,19 @@ void lab_init()
if (The_mission.ai_profile == nullptr)
The_mission.ai_profile = &Ai_profiles[Default_ai_profile];
lab_cam_distance = 100.0f;
lab_cam_phi = 1.24f;
lab_cam_theta = 2.25f;
Lab_selected_index = -1;
Lab_last_selected_ship = -1;
Lab_selected_object = -1;
Lab_last_selected_weapon = -1;
Lab_model_num = -1;
Lab_selected_mission = "None";
Lab_skybox_orientation = vmd_identity_matrix;
}
#include "controlconfig/controlsconfig.h"
@@ -2174,5 +2193,5 @@ void lab_close()
cam_delete(Lab_cam);
Missiontime = Lab_Save_Missiontime;
obj_init();
}
+254
View File
@@ -0,0 +1,254 @@
#include "discord.h"
#include "freespace.h"
#include "events/events.h"
#include "gamesequence/gamesequence.h"
#include "io/timer.h"
#include "mission/missioncampaign.h"
#include "mission/missionparse.h"
#include "parse/parselo.h"
#include "playerman/player.h"
#include "discord_rpc.h"
namespace {
struct PresenceInfo {
SCP_string state;
int64_t timestamp;
};
bool initialized = false;
bool discord_ready = false;
int next_mission_update = -1;
bool in_mission = false;
PresenceInfo current_info;
const char* APPLICATION_ID = "465270111440470016";
SCP_unordered_map<SCP_string, SCP_string> campaign_name_cache;
SCP_string get_campaign_name(const char* filename)
{
SCP_string name = filename;
auto iter = campaign_name_cache.find(name);
if (iter != campaign_name_cache.end()) {
return iter->second;
}
auto campaign_name = mission_campaign_get_name(filename);
campaign_name_cache[name] = campaign_name;
return campaign_name;
}
SCP_string get_current_campaign_name()
{
if (Game_mode & GM_CAMPAIGN_MODE) {
return Campaign.name;
} else if (Player != nullptr) {
return get_campaign_name(Player->current_campaign);
} else {
return "";
}
}
SCP_string get_details()
{
SCP_string res;
auto has_campaign = Player != nullptr && strlen(Player->current_campaign) > 0;
if (in_mission && !(Game_mode & GM_CAMPAIGN_MODE)) {
// This is a standalone mission so we don't actually have a campaign
has_campaign = false;
}
if (has_campaign && in_mission) {
sprintf(res, "%s: %s", get_current_campaign_name().c_str(), The_mission.name);
} else if (has_campaign) {
sprintf(res, "Campaign %s", get_current_campaign_name().c_str());
} else if (in_mission) {
res = The_mission.name;
} else {
res = "In game";
}
return res;
}
void update_presence() {
auto details = get_details();
DiscordRichPresence presence;
memset(&presence, 0, sizeof(presence));
presence.details = details.c_str();
presence.state = current_info.state.c_str();
presence.startTimestamp = current_info.timestamp;
Discord_UpdatePresence(&presence);
}
void set_presence(const SCP_string& state, int64_t timestamp = 0) {
if (current_info.state == state && current_info.timestamp == timestamp) {
// No changes
return;
}
current_info.state = state;
current_info.timestamp = timestamp;
if (discord_ready) {
update_presence();
}
}
void set_game_play_presence()
{
SCP_string state;
sprintf(state, "In mission (%d %s)", Player->stats.m_kill_count_ok,
Player->stats.m_kill_count_ok == 1 ? "kill" : "kills");
set_presence(state, (int64_t)time(nullptr) - f2i(Missiontime));
// Update this every 20 seconds since Discord already has a 15 second rate-limit
// This will update the "elapsed" time even if time compression is active but the clock will jump forward
next_mission_update = timestamp(20000);
}
void update_discord()
{
if (!initialized)
return;
Discord_RunCallbacks();
if (gameseq_get_state() == GS_STATE_GAME_PLAY && timestamp_elapsed(next_mission_update)) {
set_game_play_presence();
}
}
void shutdown_discord()
{
if (!initialized)
return;
Discord_Shutdown();
initialized = false;
discord_ready = false;
}
void handleEnterState(int old_state, int new_state)
{
if (old_state == new_state) {
return;
}
if (new_state == GS_STATE_GAME_PLAY) {
// Update immediately if we enter the game play state again
set_game_play_presence();
return;
}
if (gameseq_get_state_idx(GS_STATE_GAME_PLAY) >= 0) {
// Special case for when we come out of game play
switch (new_state) {
case GS_STATE_OPTIONS_MENU:
case GS_STATE_HOTKEY_SCREEN:
case GS_STATE_GAMEPLAY_HELP:
case GS_STATE_MISSION_LOG_SCROLLBACK:
set_presence("In game menu");
return;
default:
break;
}
}
switch (new_state) {
case GS_STATE_MAIN_MENU:
set_presence("In Mainhall");
break;
case GS_STATE_BRIEFING:
set_presence("In mission briefing");
break;
case GS_STATE_CMD_BRIEF:
set_presence("In command briefing");
break;
case GS_EVENT_DEBRIEF:
set_presence("In debriefing");
break;
case GS_STATE_GAME_PAUSED:
set_presence("Paused");
break;
case GS_STATE_RED_ALERT:
set_presence("Red alert briefing");
break;
case GS_STATE_INITIAL_PLAYER_SELECT:
set_presence("Selecting player");
break;
case GS_STATE_FICTION_VIEWER:
set_presence("In fiction viewer");
break;
default:
break;
}
}
void handleLeaveState(int old_state, int /*new_state*/)
{
if (old_state == GS_STATE_GAME_PAUSED) {
// Reset the game play state immediately
set_game_play_presence();
}
if (old_state == GS_STATE_GAME_PLAY) {
in_mission = false;
next_mission_update = -1;
}
}
void handleMissionLoad(const char* /*filename*/)
{
set_presence("Loading mission");
in_mission = true;
}
} // namespace
namespace libs {
namespace discord {
void init()
{
Assertion(!initialized, "Discord integration can only be initialized once!");
DiscordEventHandlers handlers;
memset(&handlers, 0, sizeof(handlers));
handlers.ready = [](const DiscordUser* connectedUser) {
mprintf(("Discord: connected to user %s#%s - %s\n", connectedUser->username, connectedUser->discriminator,
connectedUser->userId));
discord_ready = true;
update_presence();
};
handlers.errored = [](int errcode, const char* message) {
mprintf(("Discord: error (%d: %s)\n", errcode, message));
discord_ready = false;
};
handlers.disconnected = [](int errcode, const char* message) {
mprintf(("Discord: disconnected (%d: %s)\n", errcode, message));
discord_ready = false;
};
Discord_Initialize(APPLICATION_ID, &handlers, 0, nullptr);
events::EngineUpdate.add(update_discord);
events::EngineShutdown.add(shutdown_discord);
events::GameEnterState.add(handleEnterState);
events::GameLeaveState.add(handleLeaveState);
events::GameMissionLoad.add(handleMissionLoad);
initialized = true;
}
} // namespace discord
} // namespace libs
+8
View File
@@ -0,0 +1,8 @@
#pragma once
namespace libs {
namespace discord {
void init();
}
} // namespace libs
+3
View File
@@ -55,7 +55,10 @@ void initialize() {
return;
}
// This is deprecated since 58.9.100 and not needed anymore
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100)
av_register_all();
#endif
check_version("libavcodec", avcodec_version(), LIBAVCODEC_VERSION_INT);
check_version("libavformat", avformat_version(), LIBAVFORMAT_VERSION_INT);
+83
View File
@@ -0,0 +1,83 @@
#include "renderdoc.h"
#include "renderdoc_app.h"
#include "globalincs/pstypes.h"
#ifdef SCP_UNIX
#include <dlfcn.h>
#endif
namespace {
bool api_loaded = false;
RENDERDOC_API_1_1_1* api = nullptr;
pRENDERDOC_GetAPI load_getAPI() {
#ifdef SCP_UNIX
auto handle = dlopen("librenderdoc.so", RTLD_NOLOAD);
auto symbol = dlsym(handle, "RENDERDOC_GetAPI");
if (handle != nullptr) {
dlclose(handle);
}
return (pRENDERDOC_GetAPI)symbol;
#else
// Renderdoc API loading is not implemented for this platform yet!
return nullptr;
#endif
}
}
namespace renderdoc {
bool loadApi() {
if (api_loaded) {
return true;
}
auto getAPI = load_getAPI();
if (getAPI == nullptr) {
return false;
}
auto res = getAPI(eRENDERDOC_API_Version_1_1_1, reinterpret_cast<void**>(&api));
if (res != 1) {
return false;
}
api_loaded = true;
return true;
}
void triggerCapture() {
if (!api_loaded) {
// Do nothing if API is not available
return;
}
api->TriggerCapture();
}
void startCapture() {
if (api_loaded) {
api->StartFrameCapture(nullptr, nullptr);
}
}
bool isCapturing() {
if (api_loaded) {
return api->IsFrameCapturing() == 1;
}
return false;
}
void endCapture() {
if (api_loaded) {
api->EndFrameCapture(nullptr, nullptr);
}
}
}
+15
View File
@@ -0,0 +1,15 @@
#pragma once
namespace renderdoc {
bool loadApi();
void triggerCapture();
void startCapture();
bool isCapturing();
void endCapture();
}
+617
View File
@@ -0,0 +1,617 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2015-2017 Baldur Karlsson
*
* 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.
******************************************************************************/
#pragma once
//////////////////////////////////////////////////////////////////////////////////////////////////
//
// Documentation for the API is available at https://renderdoc.org/docs/in_application_api.html
//
#if !defined(RENDERDOC_NO_STDINT)
#include <cstdint>
#endif
#if defined(WIN32)
#define RENDERDOC_CC __cdecl
#elif defined(__linux__)
#define RENDERDOC_CC
#elif defined(__APPLE__)
#define RENDERDOC_CC
#else
#error "Unknown platform"
#endif
#ifdef __cplusplus
extern "C" {
#endif
//////////////////////////////////////////////////////////////////////////////////////////////////
// Constants not used directly in below API
// This is a GUID/magic value used for when applications pass a path where shader debug
// information can be found to match up with a stripped shader.
// the define can be used like so: const GUID RENDERDOC_ShaderDebugMagicValue =
// RENDERDOC_ShaderDebugMagicValue_value
#define RENDERDOC_ShaderDebugMagicValue_struct \
{ \
0xeab25520, 0x6670, 0x4865, 0x84, 0x29, 0x6c, 0x8, 0x51, 0x54, 0x00, 0xff \
}
// as an alternative when you want a byte array (assuming x86 endianness):
#define RENDERDOC_ShaderDebugMagicValue_bytearray \
{ \
0x20, 0x55, 0xb2, 0xea, 0x70, 0x66, 0x65, 0x48, 0x84, 0x29, 0x6c, 0x8, 0x51, 0x54, 0x00, 0xff \
}
// truncated version when only a uint64_t is available (e.g. Vulkan tags):
#define RENDERDOC_ShaderDebugMagicValue_truncated 0x48656670eab25520ULL
//////////////////////////////////////////////////////////////////////////////////////////////////
// RenderDoc capture options
//
typedef enum {
// Allow the application to enable vsync
//
// Default - enabled
//
// 1 - The application can enable or disable vsync at will
// 0 - vsync is force disabled
eRENDERDOC_Option_AllowVSync = 0,
// Allow the application to enable fullscreen
//
// Default - enabled
//
// 1 - The application can enable or disable fullscreen at will
// 0 - fullscreen is force disabled
eRENDERDOC_Option_AllowFullscreen = 1,
// Record API debugging events and messages
//
// Default - disabled
//
// 1 - Enable built-in API debugging features and records the results into
// the capture logfile, which is matched up with events on replay
// 0 - no API debugging is forcibly enabled
eRENDERDOC_Option_APIValidation = 2,
eRENDERDOC_Option_DebugDeviceMode = 2, // deprecated name of this enum
// Capture CPU callstacks for API events
//
// Default - disabled
//
// 1 - Enables capturing of callstacks
// 0 - no callstacks are captured
eRENDERDOC_Option_CaptureCallstacks = 3,
// When capturing CPU callstacks, only capture them from drawcalls.
// This option does nothing without the above option being enabled
//
// Default - disabled
//
// 1 - Only captures callstacks for drawcall type API events.
// Ignored if CaptureCallstacks is disabled
// 0 - Callstacks, if enabled, are captured for every event.
eRENDERDOC_Option_CaptureCallstacksOnlyDraws = 4,
// Specify a delay in seconds to wait for a debugger to attach, after
// creating or injecting into a process, before continuing to allow it to run.
//
// 0 indicates no delay, and the process will run immediately after injection
//
// Default - 0 seconds
//
eRENDERDOC_Option_DelayForDebugger = 5,
// Verify any writes to mapped buffers, by checking the memory after the
// bounds of the returned pointer to detect any modification.
//
// Default - disabled
//
// 1 - Verify any writes to mapped buffers
// 0 - No verification is performed, and overwriting bounds may cause
// crashes or corruption in RenderDoc
eRENDERDOC_Option_VerifyMapWrites = 6,
// Hooks any system API calls that create child processes, and injects
// RenderDoc into them recursively with the same options.
//
// Default - disabled
//
// 1 - Hooks into spawned child processes
// 0 - Child processes are not hooked by RenderDoc
eRENDERDOC_Option_HookIntoChildren = 7,
// By default RenderDoc only includes resources in the final logfile necessary
// for that frame, this allows you to override that behaviour.
//
// Default - disabled
//
// 1 - all live resources at the time of capture are included in the log
// and available for inspection
// 0 - only the resources referenced by the captured frame are included
eRENDERDOC_Option_RefAllResources = 8,
// By default RenderDoc skips saving initial states for resources where the
// previous contents don't appear to be used, assuming that writes before
// reads indicate previous contents aren't used.
//
// Default - disabled
//
// 1 - initial contents at the start of each captured frame are saved, even if
// they are later overwritten or cleared before being used.
// 0 - unless a read is detected, initial contents will not be saved and will
// appear as black or empty data.
eRENDERDOC_Option_SaveAllInitials = 9,
// In APIs that allow for the recording of command lists to be replayed later,
// RenderDoc may choose to not capture command lists before a frame capture is
// triggered, to reduce overheads. This means any command lists recorded once
// and replayed many times will not be available and may cause a failure to
// capture.
//
// Note this is only true for APIs where multithreading is difficult or
// discouraged. Newer APIs like Vulkan and D3D12 will ignore this option
// and always capture all command lists since the API is heavily oriented
// around it and the overheads have been reduced by API design.
//
// 1 - All command lists are captured from the start of the application
// 0 - Command lists are only captured if their recording begins during
// the period when a frame capture is in progress.
eRENDERDOC_Option_CaptureAllCmdLists = 10,
// Mute API debugging output when the API validation mode option is enabled
//
// Default - enabled
//
// 1 - Mute any API debug messages from being displayed or passed through
// 0 - API debugging is displayed as normal
eRENDERDOC_Option_DebugOutputMute = 11,
} RENDERDOC_CaptureOption;
// Sets an option that controls how RenderDoc behaves on capture.
//
// Returns 1 if the option and value are valid
// Returns 0 if either is invalid and the option is unchanged
typedef int(RENDERDOC_CC *pRENDERDOC_SetCaptureOptionU32)(RENDERDOC_CaptureOption opt, uint32_t val);
typedef int(RENDERDOC_CC *pRENDERDOC_SetCaptureOptionF32)(RENDERDOC_CaptureOption opt, float val);
// Gets the current value of an option as a uint32_t
//
// If the option is invalid, 0xffffffff is returned
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_GetCaptureOptionU32)(RENDERDOC_CaptureOption opt);
// Gets the current value of an option as a float
//
// If the option is invalid, -FLT_MAX is returned
typedef float(RENDERDOC_CC *pRENDERDOC_GetCaptureOptionF32)(RENDERDOC_CaptureOption opt);
typedef enum {
// '0' - '9' matches ASCII values
eRENDERDOC_Key_0 = 0x30,
eRENDERDOC_Key_1 = 0x31,
eRENDERDOC_Key_2 = 0x32,
eRENDERDOC_Key_3 = 0x33,
eRENDERDOC_Key_4 = 0x34,
eRENDERDOC_Key_5 = 0x35,
eRENDERDOC_Key_6 = 0x36,
eRENDERDOC_Key_7 = 0x37,
eRENDERDOC_Key_8 = 0x38,
eRENDERDOC_Key_9 = 0x39,
// 'A' - 'Z' matches ASCII values
eRENDERDOC_Key_A = 0x41,
eRENDERDOC_Key_B = 0x42,
eRENDERDOC_Key_C = 0x43,
eRENDERDOC_Key_D = 0x44,
eRENDERDOC_Key_E = 0x45,
eRENDERDOC_Key_F = 0x46,
eRENDERDOC_Key_G = 0x47,
eRENDERDOC_Key_H = 0x48,
eRENDERDOC_Key_I = 0x49,
eRENDERDOC_Key_J = 0x4A,
eRENDERDOC_Key_K = 0x4B,
eRENDERDOC_Key_L = 0x4C,
eRENDERDOC_Key_M = 0x4D,
eRENDERDOC_Key_N = 0x4E,
eRENDERDOC_Key_O = 0x4F,
eRENDERDOC_Key_P = 0x50,
eRENDERDOC_Key_Q = 0x51,
eRENDERDOC_Key_R = 0x52,
eRENDERDOC_Key_S = 0x53,
eRENDERDOC_Key_T = 0x54,
eRENDERDOC_Key_U = 0x55,
eRENDERDOC_Key_V = 0x56,
eRENDERDOC_Key_W = 0x57,
eRENDERDOC_Key_X = 0x58,
eRENDERDOC_Key_Y = 0x59,
eRENDERDOC_Key_Z = 0x5A,
// leave the rest of the ASCII range free
// in case we want to use it later
eRENDERDOC_Key_NonPrintable = 0x100,
eRENDERDOC_Key_Divide,
eRENDERDOC_Key_Multiply,
eRENDERDOC_Key_Subtract,
eRENDERDOC_Key_Plus,
eRENDERDOC_Key_F1,
eRENDERDOC_Key_F2,
eRENDERDOC_Key_F3,
eRENDERDOC_Key_F4,
eRENDERDOC_Key_F5,
eRENDERDOC_Key_F6,
eRENDERDOC_Key_F7,
eRENDERDOC_Key_F8,
eRENDERDOC_Key_F9,
eRENDERDOC_Key_F10,
eRENDERDOC_Key_F11,
eRENDERDOC_Key_F12,
eRENDERDOC_Key_Home,
eRENDERDOC_Key_End,
eRENDERDOC_Key_Insert,
eRENDERDOC_Key_Delete,
eRENDERDOC_Key_PageUp,
eRENDERDOC_Key_PageDn,
eRENDERDOC_Key_Backspace,
eRENDERDOC_Key_Tab,
eRENDERDOC_Key_PrtScrn,
eRENDERDOC_Key_Pause,
eRENDERDOC_Key_Max,
} RENDERDOC_InputButton;
// Sets which key or keys can be used to toggle focus between multiple windows
//
// If keys is NULL or num is 0, toggle keys will be disabled
typedef void(RENDERDOC_CC *pRENDERDOC_SetFocusToggleKeys)(RENDERDOC_InputButton *keys, int num);
// Sets which key or keys can be used to capture the next frame
//
// If keys is NULL or num is 0, captures keys will be disabled
typedef void(RENDERDOC_CC *pRENDERDOC_SetCaptureKeys)(RENDERDOC_InputButton *keys, int num);
typedef enum {
// This single bit controls whether the overlay is enabled or disabled globally
eRENDERDOC_Overlay_Enabled = 0x1,
// Show the average framerate over several seconds as well as min/max
eRENDERDOC_Overlay_FrameRate = 0x2,
// Show the current frame number
eRENDERDOC_Overlay_FrameNumber = 0x4,
// Show a list of recent captures, and how many captures have been made
eRENDERDOC_Overlay_CaptureList = 0x8,
// Default values for the overlay mask
eRENDERDOC_Overlay_Default = (eRENDERDOC_Overlay_Enabled | eRENDERDOC_Overlay_FrameRate |
eRENDERDOC_Overlay_FrameNumber | eRENDERDOC_Overlay_CaptureList),
// Enable all bits
eRENDERDOC_Overlay_All = ~0U,
// Disable all bits
eRENDERDOC_Overlay_None = 0,
} RENDERDOC_OverlayBits;
// returns the overlay bits that have been set
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_GetOverlayBits)();
// sets the overlay bits with an and & or mask
typedef void(RENDERDOC_CC *pRENDERDOC_MaskOverlayBits)(uint32_t And, uint32_t Or);
// this function will attempt to shut down RenderDoc.
//
// Note: that this will only work correctly if done immediately after
// the dll is loaded, before any API work happens. RenderDoc will remove its
// injected hooks and shut down. Behaviour is undefined if this is called
// after any API functions have been called.
typedef void(RENDERDOC_CC *pRENDERDOC_Shutdown)();
// This function will unload RenderDoc's crash handler.
//
// If you use your own crash handler and don't want RenderDoc's handler to
// intercede, you can call this function to unload it and any unhandled
// exceptions will pass to the next handler.
typedef void(RENDERDOC_CC *pRENDERDOC_UnloadCrashHandler)();
// Sets the logfile path template
//
// logfile is a UTF-8 string that gives a template for how captures will be named
// and where they will be saved.
//
// Any extension is stripped off the path, and captures are saved in the directory
// specified, and named with the filename and the frame number appended. If the
// directory does not exist it will be created, including any parent directories.
//
// If pathtemplate is NULL, the template will remain unchanged
//
// Example:
//
// SetLogFilePathTemplate("my_captures/example");
//
// Capture #1 -> my_captures/example_frame123.rdc
// Capture #2 -> my_captures/example_frame456.rdc
typedef void(RENDERDOC_CC *pRENDERDOC_SetLogFilePathTemplate)(const char *pathtemplate);
// returns the current logfile template, see SetLogFileTemplate above, as a UTF-8 string
typedef const char *(RENDERDOC_CC *pRENDERDOC_GetLogFilePathTemplate)();
// returns the number of captures that have been made
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_GetNumCaptures)();
// This function returns the details of a capture, by index. New captures are added
// to the end of the list.
//
// logfile will be filled with the absolute path to the capture file, as a UTF-8 string
// pathlength will be written with the length in bytes of the logfile string
// timestamp will be written with the time of the capture, in seconds since the Unix epoch
//
// Any of the parameters can be NULL and they'll be skipped.
//
// The function will return 1 if the capture index is valid, or 0 if the index is invalid
// If the index is invalid, the values will be unchanged
//
// Note: when captures are deleted in the UI they will remain in this list, so the
// logfile path may not exist anymore.
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_GetCapture)(uint32_t idx, char *logfile,
uint32_t *pathlength, uint64_t *timestamp);
// returns 1 if the RenderDoc UI is connected to this application, 0 otherwise
// This was renamed to IsTargetControlConnected in API 1.1.1, the old typedef is kept here for
// backwards compatibility with old code, it is castable either way since it's ABI compatible
// as the same function pointer type.
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_IsRemoteAccessConnected)();
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_IsTargetControlConnected)();
// This function will launch the Replay UI associated with the RenderDoc library injected
// into the running application.
//
// if connectTargetControl is 1, the Replay UI will be launched with a command line parameter
// to connect to this application
// cmdline is the rest of the command line, as a UTF-8 string. E.g. a captures to open
// if cmdline is NULL, the command line will be empty.
//
// returns the PID of the replay UI if successful, 0 if not successful.
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_LaunchReplayUI)(uint32_t connectTargetControl,
const char *cmdline);
// RenderDoc can return a higher version than requested if it's backwards compatible,
// this function returns the actual version returned. If a parameter is NULL, it will be
// ignored and the others will be filled out.
typedef void(RENDERDOC_CC *pRENDERDOC_GetAPIVersion)(int *major, int *minor, int *patch);
//////////////////////////////////////////////////////////////////////////
// Capturing functions
//
// A device pointer is a pointer to the API's root handle.
//
// This would be an ID3D11Device, HGLRC/GLXContext, ID3D12Device, etc
typedef void *RENDERDOC_DevicePointer;
// A window handle is the OS's native window handle
//
// This would be an HWND, GLXDrawable, etc
typedef void *RENDERDOC_WindowHandle;
// This sets the RenderDoc in-app overlay in the API/window pair as 'active' and it will
// respond to keypresses. Neither parameter can be NULL
typedef void(RENDERDOC_CC *pRENDERDOC_SetActiveWindow)(RENDERDOC_DevicePointer device,
RENDERDOC_WindowHandle wndHandle);
// capture the next frame on whichever window and API is currently considered active
typedef void(RENDERDOC_CC *pRENDERDOC_TriggerCapture)();
// capture the next N frames on whichever window and API is currently considered active
typedef void(RENDERDOC_CC *pRENDERDOC_TriggerMultiFrameCapture)(uint32_t numFrames);
// When choosing either a device pointer or a window handle to capture, you can pass NULL.
// Passing NULL specifies a 'wildcard' match against anything. This allows you to specify
// any API rendering to a specific window, or a specific API instance rendering to any window,
// or in the simplest case of one window and one API, you can just pass NULL for both.
//
// In either case, if there are two or more possible matching (device,window) pairs it
// is undefined which one will be captured.
//
// Note: for headless rendering you can pass NULL for the window handle and either specify
// a device pointer or leave it NULL as above.
// Immediately starts capturing API calls on the specified device pointer and window handle.
//
// If there is no matching thing to capture (e.g. no supported API has been initialised),
// this will do nothing.
//
// The results are undefined (including crashes) if two captures are started overlapping,
// even on separate devices and/oror windows.
typedef void(RENDERDOC_CC *pRENDERDOC_StartFrameCapture)(RENDERDOC_DevicePointer device,
RENDERDOC_WindowHandle wndHandle);
// Returns whether or not a frame capture is currently ongoing anywhere.
//
// This will return 1 if a capture is ongoing, and 0 if there is no capture running
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_IsFrameCapturing)();
// Ends capturing immediately.
//
// This will return 1 if the capture succeeded, and 0 if there was an error capturing.
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_EndFrameCapture)(RENDERDOC_DevicePointer device,
RENDERDOC_WindowHandle wndHandle);
//////////////////////////////////////////////////////////////////////////////////////////////////
// RenderDoc API versions
//
// RenderDoc uses semantic versioning (http://semver.org/).
//
// MAJOR version is incremented when incompatible API changes happen.
// MINOR version is incremented when functionality is added in a backwards-compatible manner.
// PATCH version is incremented when backwards-compatible bug fixes happen.
//
// Note that this means the API returned can be higher than the one you might have requested.
// e.g. if you are running against a newer RenderDoc that supports 1.0.1, it will be returned
// instead of 1.0.0. You can check this with the GetAPIVersion entry point
typedef enum {
eRENDERDOC_API_Version_1_0_0 = 10000, // RENDERDOC_API_1_0_0 = 1 00 00
eRENDERDOC_API_Version_1_0_1 = 10001, // RENDERDOC_API_1_0_1 = 1 00 01
eRENDERDOC_API_Version_1_0_2 = 10002, // RENDERDOC_API_1_0_2 = 1 00 02
eRENDERDOC_API_Version_1_1_0 = 10100, // RENDERDOC_API_1_1_0 = 1 01 00
eRENDERDOC_API_Version_1_1_1 = 10101, // RENDERDOC_API_1_1_1 = 1 01 01
} RENDERDOC_Version;
// API version changelog:
//
// 1.0.0 - initial release
// 1.0.1 - Bugfix: IsFrameCapturing() was returning false for captures that were triggered
// by keypress or TriggerCapture, instead of Start/EndFrameCapture.
// 1.0.2 - Refactor: Renamed eRENDERDOC_Option_DebugDeviceMode to eRENDERDOC_Option_APIValidation
// 1.1.0 - Add feature: TriggerMultiFrameCapture(). Backwards compatible with 1.0.x since the new
// function pointer is added to the end of the struct, the original layout is identical
// 1.1.1 - Refactor: Renamed remote access to target control (to better disambiguate from remote
// replay/remote server concept in replay UI)
// eRENDERDOC_API_Version_1_1_0
typedef struct
{
pRENDERDOC_GetAPIVersion GetAPIVersion;
pRENDERDOC_SetCaptureOptionU32 SetCaptureOptionU32;
pRENDERDOC_SetCaptureOptionF32 SetCaptureOptionF32;
pRENDERDOC_GetCaptureOptionU32 GetCaptureOptionU32;
pRENDERDOC_GetCaptureOptionF32 GetCaptureOptionF32;
pRENDERDOC_SetFocusToggleKeys SetFocusToggleKeys;
pRENDERDOC_SetCaptureKeys SetCaptureKeys;
pRENDERDOC_GetOverlayBits GetOverlayBits;
pRENDERDOC_MaskOverlayBits MaskOverlayBits;
pRENDERDOC_Shutdown Shutdown;
pRENDERDOC_UnloadCrashHandler UnloadCrashHandler;
pRENDERDOC_SetLogFilePathTemplate SetLogFilePathTemplate;
pRENDERDOC_GetLogFilePathTemplate GetLogFilePathTemplate;
pRENDERDOC_GetNumCaptures GetNumCaptures;
pRENDERDOC_GetCapture GetCapture;
pRENDERDOC_TriggerCapture TriggerCapture;
pRENDERDOC_IsRemoteAccessConnected IsRemoteAccessConnected;
pRENDERDOC_LaunchReplayUI LaunchReplayUI;
pRENDERDOC_SetActiveWindow SetActiveWindow;
pRENDERDOC_StartFrameCapture StartFrameCapture;
pRENDERDOC_IsFrameCapturing IsFrameCapturing;
pRENDERDOC_EndFrameCapture EndFrameCapture;
pRENDERDOC_TriggerMultiFrameCapture TriggerMultiFrameCapture;
} RENDERDOC_API_1_1_0;
typedef RENDERDOC_API_1_1_0 RENDERDOC_API_1_0_0;
typedef RENDERDOC_API_1_1_0 RENDERDOC_API_1_0_1;
typedef RENDERDOC_API_1_1_0 RENDERDOC_API_1_0_2;
// although this structure is identical to RENDERDOC_API_1_1_0, the member
// IsRemoteAccessConnected was renamed to IsTargetControlConnected. So that
// old code can still compile with a new header, we must declare a new struct
// type. It can be casted back and forth though, so we will still return a
// pointer to this type for all previous API versions - the above struct is
// purely legacy for compilation compatibility
// eRENDERDOC_API_Version_1_1_1
typedef struct
{
pRENDERDOC_GetAPIVersion GetAPIVersion;
pRENDERDOC_SetCaptureOptionU32 SetCaptureOptionU32;
pRENDERDOC_SetCaptureOptionF32 SetCaptureOptionF32;
pRENDERDOC_GetCaptureOptionU32 GetCaptureOptionU32;
pRENDERDOC_GetCaptureOptionF32 GetCaptureOptionF32;
pRENDERDOC_SetFocusToggleKeys SetFocusToggleKeys;
pRENDERDOC_SetCaptureKeys SetCaptureKeys;
pRENDERDOC_GetOverlayBits GetOverlayBits;
pRENDERDOC_MaskOverlayBits MaskOverlayBits;
pRENDERDOC_Shutdown Shutdown;
pRENDERDOC_UnloadCrashHandler UnloadCrashHandler;
pRENDERDOC_SetLogFilePathTemplate SetLogFilePathTemplate;
pRENDERDOC_GetLogFilePathTemplate GetLogFilePathTemplate;
pRENDERDOC_GetNumCaptures GetNumCaptures;
pRENDERDOC_GetCapture GetCapture;
pRENDERDOC_TriggerCapture TriggerCapture;
pRENDERDOC_IsTargetControlConnected IsTargetControlConnected;
pRENDERDOC_LaunchReplayUI LaunchReplayUI;
pRENDERDOC_SetActiveWindow SetActiveWindow;
pRENDERDOC_StartFrameCapture StartFrameCapture;
pRENDERDOC_IsFrameCapturing IsFrameCapturing;
pRENDERDOC_EndFrameCapture EndFrameCapture;
pRENDERDOC_TriggerMultiFrameCapture TriggerMultiFrameCapture;
} RENDERDOC_API_1_1_1;
//////////////////////////////////////////////////////////////////////////////////////////////////
// RenderDoc API entry point
//
// This entry point can be obtained via GetProcAddress/dlsym if RenderDoc is available.
//
// The name is the same as the typedef - "RENDERDOC_GetAPI"
//
// This function is not thread safe, and should not be called on multiple threads at once.
// Ideally, call this once as early as possible in your application's startup, before doing
// any API work, since some configuration functionality etc has to be done also before
// initialising any APIs.
//
// Parameters:
// version is a single value from the RENDERDOC_Version above.
//
// outAPIPointers will be filled out with a pointer to the corresponding struct of function
// pointers.
//
// Returns:
// 1 - if the outAPIPointers has been filled with a pointer to the API struct requested
// 0 - if the requested version is not supported or the arguments are invalid.
//
typedef int(RENDERDOC_CC *pRENDERDOC_GetAPI)(RENDERDOC_Version version, void **outAPIPointers);
#ifdef __cplusplus
} // extern "C"
#endif
-1
View File
@@ -278,7 +278,6 @@ void parse_stringstbl_common(const char *filename, const bool external)
if (external) {
ignore_white_space();
get_string(buf, sizeof(buf));
drop_trailing_white_space(buf);
} else {
stuff_string(buf, F_RAW, sizeof(buf));
}
+972 -953
View File
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -445,7 +445,7 @@ void vm_vec_random_in_circle(vec3d *out, const vec3d *in, const matrix *orient,
// given a start vector, an orientation, and a radius, give a point in a spherical volume
// if on_edge is 1, the point is on the very edge of the sphere
void vm_vec_random_in_sphere(vec3d *out, const vec3d *in, const matrix *orient, float radius, int on_edge);
void vm_vec_random_in_sphere(vec3d *out, const vec3d *in, float radius, int on_edge);
// find the nearest point on the line to p. if dist is non-NULL, it is filled in
// returns 0 if the point is inside the line segment, -1 if "before" the line segment and 1 ir "after" the line segment
+4 -2
View File
@@ -433,7 +433,7 @@ void barracks_init_stats(scoring_struct *stats)
Num_stat_lines++;
Assert(Num_stat_lines < Max_stat_lines);
STRCPY1(Stat_labels[Num_stat_lines], "Current Score:");
strcpy_s(Stat_labels[Num_stat_lines], XSTR( "Current Score:", 1583));
sprintf(Stats[Num_stat_lines], "%d", stats->score);
Num_stat_lines++;
@@ -952,7 +952,9 @@ void barracks_init_player_stuff(int mode)
Num_pilots = 0;
Get_file_list_filter = barracks_pilot_filter;
Num_pilots = cf_get_file_list_preallocated(MAX_PILOTS, Pilots_arr, Pilots, CF_TYPE_PLAYERS, NOX("*.plr"), CF_SORT_TIME);
Num_pilots =
cf_get_file_list_preallocated(MAX_PILOTS, Pilots_arr, Pilots, CF_TYPE_PLAYERS, NOX("*.plr"), CF_SORT_TIME,
nullptr, CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
int ranks[MAX_PILOTS];
+18 -18
View File
@@ -123,7 +123,7 @@ int Main_hall_next_intercom_sound = 0;
int Main_hall_next_intercom_sound_stamp = -1;
// handle to any playing instance of a random intercom sound
int Main_hall_intercom_sound_handle = -1;
sound_handle Main_hall_intercom_sound_handle = sound_handle::invalid();
// handle any details related to random intercom sounds
void main_hall_handle_random_intercom_sounds();
@@ -225,10 +225,10 @@ void main_hall_mouse_grab_region(int region);
#define ALLENDER_REGION 4
// handles to the sound instances of the doors opening/closing
SCP_vector<int> Main_hall_door_sound_handles;
SCP_vector<sound_handle> Main_hall_door_sound_handles;
// sound handle for looping ambient sound
int Main_hall_ambient_loop = -1;
sound_handle Main_hall_ambient_loop = sound_handle::invalid();
// cull any door sounds that have finished playing
void main_hall_cull_door_sounds();
@@ -592,7 +592,7 @@ void main_hall_init(const SCP_string &main_hall_name)
// initialize door sound handles
Main_hall_door_sound_handles.clear();
for (idx = 0; idx < Main_hall->num_door_animations; idx++) {
Main_hall_door_sound_handles.push_back(-1);
Main_hall_door_sound_handles.push_back(sound_handle::invalid());
}
// skip the first frame
@@ -607,7 +607,7 @@ void main_hall_init(const SCP_string &main_hall_name)
// initialize the random intercom sound stuff
Main_hall_next_intercom_sound = 0;
Main_hall_next_intercom_sound_stamp = -1;
Main_hall_intercom_sound_handle = -1;
Main_hall_intercom_sound_handle = sound_handle::invalid();
// set the placement of the mouse cursor (start at the ready room)
Main_hall_mouse_region = -1;
@@ -1061,9 +1061,9 @@ void main_hall_close()
// stop any playing door sounds
for (idx = 0; idx < Main_hall->num_door_animations-2; idx++) {
if ( (Main_hall_door_sound_handles.at(idx) != -1) && snd_is_playing(Main_hall_door_sound_handles.at(idx)) ) {
if ((Main_hall_door_sound_handles.at(idx).isValid()) && snd_is_playing(Main_hall_door_sound_handles.at(idx))) {
snd_stop(Main_hall_door_sound_handles.at(idx));
Main_hall_door_sound_handles.at(idx) = -1;
Main_hall_door_sound_handles.at(idx) = sound_handle::invalid();
}
}
@@ -1382,7 +1382,7 @@ void main_hall_mouse_release_region(int region)
// check for door sounds, ignoring the OPTIONS_REGION (which isn't a door)
if (Main_hall_door_anim.at(region).num_frames > 0) {
// don't stop the toaster oven or microwave regions from playing all the way through
if (Main_hall_door_sound_handles.at(region) != -1) {
if (Main_hall_door_sound_handles.at(region).isValid()) {
snd_stop(Main_hall_door_sound_handles.at(region));
}
@@ -1425,7 +1425,7 @@ void main_hall_mouse_grab_region(int region)
// check for opening/starting sounds
// kill the currently playing sounds if necessary
if (Main_hall_door_sound_handles.at(region) != -1) {
if (Main_hall_door_sound_handles.at(region).isValid()) {
snd_stop(Main_hall_door_sound_handles.at(region));
}
@@ -1508,8 +1508,8 @@ void main_hall_cull_door_sounds()
// basically just set the handle of any finished sound to be -1, so that we know its free any where else in the code we may need it
Assert(Main_hall_door_sound_handles.size() < INT_MAX);
for (idx = 0; idx < (int)Main_hall_door_sound_handles.size(); idx++) {
if ( (Main_hall_door_sound_handles.at(idx) != -1) && !snd_is_playing(Main_hall_door_sound_handles.at(idx)) ) {
Main_hall_door_sound_handles.at(idx) = -1;
if ((Main_hall_door_sound_handles.at(idx).isValid()) && !snd_is_playing(Main_hall_door_sound_handles.at(idx))) {
Main_hall_door_sound_handles.at(idx) = sound_handle::invalid();
}
}
}
@@ -1526,14 +1526,14 @@ void main_hall_handle_random_intercom_sounds()
}
// if we have no timestamp for the next random sound, then set on
if ( (Main_hall_next_intercom_sound_stamp == -1) && (Main_hall_intercom_sound_handle == -1) ) {
if ((Main_hall_next_intercom_sound_stamp == -1) && (!Main_hall_intercom_sound_handle.isValid())) {
Main_hall_next_intercom_sound_stamp = timestamp((int)((rand() * RAND_MAX_1f) *
(float)(Main_hall->intercom_delay.at(Main_hall_next_intercom_sound).at(1)
- Main_hall->intercom_delay.at(Main_hall_next_intercom_sound).at(0))) );
}
// if the there is no sound playing
if (Main_hall_intercom_sound_handle == -1) {
if (!Main_hall_intercom_sound_handle.isValid()) {
if (Main_hall_paused) {
return;
}
@@ -1571,7 +1571,7 @@ void main_hall_handle_random_intercom_sounds()
- Main_hall->intercom_delay.at(Main_hall_next_intercom_sound).at(0))) );
// release the sound handle
Main_hall_intercom_sound_handle = -1;
Main_hall_intercom_sound_handle = sound_handle::invalid();
}
}
}
@@ -1624,7 +1624,7 @@ void main_hall_start_ambient()
return;
}
if (Main_hall_ambient_loop == -1) {
if (!Main_hall_ambient_loop.isValid()) {
play_ambient_loop = 1;
} else {
if (!snd_is_playing(Main_hall_ambient_loop)) {
@@ -1642,9 +1642,9 @@ void main_hall_start_ambient()
*/
void main_hall_stop_ambient()
{
if (Main_hall_ambient_loop != -1) {
if (Main_hall_ambient_loop.isValid()) {
snd_stop(Main_hall_ambient_loop);
Main_hall_ambient_loop = -1;
Main_hall_ambient_loop = sound_handle::invalid();
}
}
@@ -1655,7 +1655,7 @@ void main_hall_stop_ambient()
*/
void main_hall_reset_ambient_vol()
{
if (Main_hall_ambient_loop >= 0) {
if (Main_hall_ambient_loop.isValid()) {
snd_set_volume(Main_hall_ambient_loop, gamesnd_get_interface_sound(InterfaceSounds::MAIN_HALL_AMBIENT)->volume_range.next());
}
}
+5 -7
View File
@@ -242,7 +242,7 @@ static int Sound_volume_int;
static int Music_volume_int;
static int Voice_volume_int;
static int Voice_vol_handle = -1;
static sound_handle Voice_vol_handle = sound_handle::invalid();
int Options_notify_stamp = -1;
char Options_notify_string[200];
@@ -465,16 +465,14 @@ UI_XSTR Options_text[GR_NUM_RESOLUTIONS][OPTIONS_NUM_TEXT] = {
void options_play_voice_clip()
{
int snd_id;
if ( snd_is_playing(Voice_vol_handle) ) {
snd_stop(Voice_vol_handle);
Voice_vol_handle=-1;
Voice_vol_handle = sound_handle::invalid();
}
auto gs = gamesnd_get_interface_sound(InterfaceSounds::VOICE_SLIDER_CLIP);
auto entry = gamesnd_choose_entry(gs);
snd_id = snd_load(entry, gs->flags, 0);
auto snd_id = snd_load(entry, gs->flags, 0);
Voice_vol_handle = snd_play_raw( snd_id, 0.0f, 1.0f, SND_PRIORITY_SINGLE_INSTANCE );
}
@@ -1047,9 +1045,9 @@ void options_menu_close()
}
}
if ( Voice_vol_handle >= 0 ) {
if (Voice_vol_handle.isValid()) {
snd_stop(Voice_vol_handle);
Voice_vol_handle = -1;
Voice_vol_handle = sound_handle::invalid();
}
options_multi_close();
+5 -5
View File
@@ -506,7 +506,7 @@ int Om_vox_voice_buffer_size = -1;
unsigned char Om_vox_comp_buffer[OM_VOX_COMP_SIZE];
int Om_vox_voice_comp_size = -1;
int Om_vox_playback_handle;
sound_handle Om_vox_playback_handle;
// status of any test voice recording
#define OM_VOX_TEST_NONE -1
@@ -1710,7 +1710,7 @@ void options_multi_disable_vox_controls()
// unset the sound buffer size so we don't display any waveforms
Om_vox_voice_buffer_size = -1;
Om_vox_voice_comp_size = -1;
Om_vox_playback_handle = -1;
Om_vox_playback_handle = sound_handle::invalid();
Om_vox_test_status = OM_VOX_TEST_NONE;
// disable the player list select button
@@ -1739,7 +1739,7 @@ void options_multi_enable_vox_controls()
// unset the sound buffer size so we don't display any waveforms
Om_vox_voice_buffer_size = -1;
Om_vox_voice_comp_size = -1;
Om_vox_playback_handle = -1;
Om_vox_playback_handle = sound_handle::invalid();
Om_vox_test_status = OM_VOX_TEST_NONE;
// select the first player on the list
@@ -1851,12 +1851,12 @@ void options_multi_vox_do()
case OM_VOX_TEST_PLAYBACK:
// if we were playing a sound back, but now the sound is done
if ( (Om_vox_playback_handle != -1) && !ds_is_channel_playing(ds_get_channel(Om_vox_playback_handle)) ) {
if ((Om_vox_playback_handle.isValid()) && !ds_is_channel_playing(ds_get_channel(Om_vox_playback_handle))) {
// flush all playing sounds safely
rtvoice_stop_playback_all();
// null the sound handle
Om_vox_playback_handle = -1;
Om_vox_playback_handle = sound_handle::invalid();
// set this so we know not to display any more waveforms
Om_vox_voice_buffer_size = -1;
Loaded 100 of 339 files, more files were not shown because too many files have changed in this diff. Show more