Compare commits

..
1044 Commits
Author SHA1 Message Date
niffiwan 82553567e1 "Fix" coverity_scan by reverting to old config
i.e. specify the compiler explicitly; otherwise the travis/coverity
integration doesn't know how to compile
2017-04-02 09:13:07 +10:00
niffiwan 37575b2fea Merge pull request #1327 from asarium/fix/1326
Apply clipping planes to passthrough shader
2017-04-01 14:14:33 +10:00
asarium 6ddca15dc5 Apply clipping planes to passthrough shader
This adds support for using clipping planes with the passthrough shader
by passing through the clip equation of the specified plane and then
using gl_ClipDistance for using the built-in clipping capabilities.
2017-03-30 23:26:20 +02:00
Fabian Woltermann 353c28176c Merge pull request #1325 from asarium/fix/1059
Validate seek offsets in cfseek
2017-03-29 14:20:25 +02:00
Fabian Woltermann 4815343854 Merge pull request #1324 from asarium/feature/loadTracing
Add tracing scopes to the mission load code
2017-03-29 10:20:07 +02:00
asarium 4e18f01438 Validate seek offsets in cfseek
Invalid values previously corrupted the internal position counter which
caused crashes on some platforms because the position counter would
overflow in the next read operation. I added some assertions to track
the position counter corruption and it's probably a good idea to leave
them in to catch possible future errors early.

The actual fix was to just ensure that the seek position it always valid
for the file.

This fixes #1059.
2017-03-29 10:17:27 +02:00
asarium abdef9f7b0 Add tracing scopes to the mission load code
This makes it easier to determine what takes the most time while loading
the mission (loading models) and how we could optimize that load time
(optimize model loading).

This is not a bug fix but it also shouldn't cause any regressions since
there are no actual code changes so this could be merged before the
release of 3.8.
2017-03-28 17:23:22 +02:00
Fabian Woltermann f67a42d89e Merge pull request #1319 from asarium/fix/envmapHandling
Improve handling of environment map redrawing
2017-03-26 08:37:50 +02:00
Fabian Woltermann 52b48bd32d Merge pull request #1321 from asarium/opengl/builtInClipPlane
Use built-in OpenGL clip plane instead of custom variant
2017-03-26 08:37:32 +02:00
Fabian Woltermann ad2fcfd22f Merge pull request #1322 from asarium/fix/distortionErrors
Fix OpenGL errors when framebuffer effects are disabled
2017-03-25 20:28:01 +01:00
asarium 507f50cd90 Fix OpenGL errors when framebuffer effects are disabled
This also promotes medium and high severity OpenGL messages to the
general logging category to help troubleshooting in the future.
2017-03-25 19:46:52 +01:00
asarium d91739b41d Use built-in OpenGL clip plane instead of custom variant
The current shaders compute the clip values in the vertex shader and
then discard fragments if those values say that the fragment is clipped.
I don't know why this was done but, as far as I can tell, this behavior
can be fully replaced by using the built-in OpenGL clip-plane feature
which should also reduce the amount of fragment shader invocations. This
won't affect performance too much since we rarely use clip planes but it
seems like the correct thing to do.
2017-03-25 00:05:48 +01:00
asarium b9413a2639 Improve handling of environment redrawing
This should make sure that the environment map is only redrawn if
necessary. In my case that should improve frame times by around 1ms for
the normal case when the environment map doesn't need to be redrawn.
2017-03-22 17:01:28 +01:00
niffiwan bb94d5bcd6 Merge pull request #1196 from asarium/fix/sprintfAttribute
Add format string annotations to all printf style functions
2017-03-20 20:19:43 +10:00
m!m 8caaf5c00c Merge pull request #1314 from SamuelCho/macDeferredLightingFix
Reorder fragment shader destination binds to fix Mac deferred lighting.
2017-03-17 16:59:24 +01:00
SamuelCho 7db1861b59 Corrected shoddy copy paste job involving shader program handle in the bind fragment data fix. 2017-03-17 08:28:12 -07:00
SamuelCho fabdc6ab8a Make sure we bind the fragment shader destinations before we link the shader. 2017-03-16 20:41:09 -07:00
asarium 07107ce9b2 Fix newly introduced format warnings 2017-03-15 19:34:11 +01:00
asarium 2a4795596f Add format string annotations to all printf style functions
This should help to catch most if not all printf mistakes since those
can then be caught by our CI.
2017-03-15 19:34:11 +01:00
Samuel Cho caaaf3213d Merge pull request #1313 from asarium/fix/1307
Fix OpenGL distortion map update
2017-03-13 20:05:43 -07:00
asarium e119be513b Fix OpenGL distortion map update
The updated values for the distortion map were rendered too close to the
edge of the screen so they were clipped which meant that there was no
distortion data available. This fixes that by moving the rendered
primitives farther away from the edge. I'm not sure why this worked in
3.7.4, maybe the fixed function rendering used some slightly different
matrix.

I also don't know why this wouldn't work consistently across GPU vendors
but maybe the rasterization rules vary a bit across drivers.

This fixes #1307.
2017-03-13 20:09:08 +01:00
Fabian Woltermann 09524fb9fe Merge pull request #1311 from SamuelCho/renderTargetNoLightingModelFix
Fix for intense glare when rendering a model in a render target with no lighting.
2017-03-13 08:43:51 +01:00
SamuelCho 9b5e7ce19d Clamp the dot product of eye direction and surface normal to prevent intense glare when rendering a model in a render target with no lighting. 2017-03-12 18:36:45 -07:00
niffiwan e39a8bbed3 Merge pull request #1305 from asarium/fix/lightshaftCockpit
Fix lightshaft rendering with cockpits
2017-03-11 10:29:39 +10:00
niffiwan d224a87828 Merge pull request #1302 from asarium/fix/openglInitError
Extend display device initialization error
2017-03-11 10:29:10 +10:00
m!m 78df244bc7 Extend display device initialization error
This should make it clearer what went wrong.
2017-03-10 23:41:14 +01:00
asarium 6718a1aba8 Fix lightshaft rendering with cockpits
Immediately clearing the z-buffer is definitely not a good way of
saving it for later use. This fixes the lightshaft rendering (which was
broken by my fix in #1282) by removing the depth buffer clear from the
z-buffer restore function. The z-Buffer is cleared anyway before
rendering into it so it shouldn't make a difference.
2017-03-10 23:34:16 +01:00
Samuel Cho 9d7c5a2b17 Merge pull request #1304 from TRBlount/shield_decal_correction
Correct shield decal selection logic
2017-03-10 12:12:39 -08:00
TRBlount f4ccab0f9f Correct shield decal logic 2017-03-10 12:10:45 -07:00
Fabian Woltermann 4bfdb9bdf0 Merge pull request #1299 from asarium/fix/sexpVarNull
Correctly terminate Sexp_variable text with a null byte
2017-03-10 18:59:53 +01:00
asarium 2b9441eeb6 Correctly terminate Sexp_variable text with a null byte
I'm pretty sure that this is a bug since the documentation of
std::string::copy says that it doesn't append a 0 byte so our code would
need to do it manually. Instead, the code appended the 0 byte to the
input buffer which also conflicts with const-correctness (the function
was used on a lua-string buffer which should be const outside Lua).
2017-03-09 18:56:42 +01:00
niffiwan 9b1b3e0a74 Merge pull request #1296 from The-E/RestoreFlagWindows
Restore the flag viewers
2017-03-08 22:48:22 +10:00
niffiwan d7a6a94808 Merge pull request #1297 from The-E/UselessWarningRemoval
Remove a couple of annoying warnings in ship flag parsing
2017-03-08 22:47:13 +10:00
Fabian Woltermann f49cad0e32 Change a few flag warnings that really do not need to be warnings to simple log prints. 2017-03-08 08:56:52 +01:00
Fabian Woltermann d2f853f601 Apparently VS2013's auto doesn't correctly resolve these? 2017-03-08 08:45:42 +01:00
Fabian Woltermann d544d42448 Addressing CI issues 2017-03-08 08:35:54 +01:00
MageKing17 3d027dc7bc Merge pull request #1295 from asarium/fix/outwndHeader
Fix log header printing
2017-03-07 19:10:55 -08:00
Fabian Woltermann 163e9175e9 Cleanup 2017-03-08 00:30:36 +01:00
asarium 91fda5386a Fix log header printing
Due to some initialization order issues the original header string
wasn't printed to the log anymore. This fixes that by initializing
outwnd_inited before doing the initial outwnd_print.
2017-03-07 23:31:47 +01:00
Fabian Woltermann 63e610e07d Rerstore the flag viewers 2017-03-07 22:31:33 +01:00
m!m 26d6e0f56f Merge pull request #1288 from SamuelCho/lightingFixes
Lighting attenuation fixes and deferred tube light stencil test removal
2017-03-07 09:47:49 +01:00
m!m aafbfb7277 Merge pull request #1291 from SamuelCho/materialSetColorFix
Fixed color struct to vec4 color conversion in material class.
2017-03-07 09:47:09 +01:00
SamuelCho 7c4e564c92 Fixed color struct to vec4 color conversion in material class. 2017-03-06 23:50:18 -08:00
SamuelCho fc5895a910 Removed stencil test setup in deferred lighting pass. 2017-03-06 23:25:51 -08:00
SamuelCho 51b4d62007 Merge branch 'master' into lightingFixes 2017-03-06 23:09:52 -08:00
niffiwan 497173d3e2 Merge pull request #1287 from asarium/fix/mantis3193
Output briefing icon lables as XSTRs
2017-03-06 19:40:19 +10:00
SamuelCho 2118cc42f0 Fixed reordered deferred lighting shader operations to ensure attenuation correctness. Killed deferred stencil operations for tube lights. Corrected attenuation in forward rendering shader. 2017-03-05 23:09:44 -08:00
asarium 4a8147dae2 Output briefing icon lables as XSTRs
The briefing icon lables previously just wrote the label string to the
mission files without surrounding it with an XSTR which made is
impossible to translate them. I fixed that by using the right function
call when saving the value.

This fixes Mantis 3193.
2017-03-05 22:00:52 +01:00
Fabian Woltermann c9763b0623 Merge pull request #1286 from asarium/fix/cmakeDebugPrints
Remove CMake debug print statements
2017-03-05 21:36:30 +01:00
m!m 63ecfcff6b Remove CMake debug print statements
I accidentally left these in an earlier pull request and they are not supposed to be here.
2017-03-05 18:41:12 +01:00
Fabian Woltermann a1670f9e1d Merge pull request #1283 from asarium/fix/localizedKeyPress
Always use the english key name in the scripting interface
2017-03-05 13:22:12 +01:00
Fabian Woltermann 1287cfacae Merge pull request #1282 from asarium/fix/cockpitDepthBuffer
Fix depth test of lasers when using a cockpit ... again
2017-03-05 13:21:04 +01:00
Fabian Woltermann d8fac09281 Merge pull request #1281 from asarium/fix/luaTrivialTypes
Disallow to use non-trivial types as scripting handles
2017-03-05 13:20:03 +01:00
Fabian Woltermann 3ac9821907 Merge pull request #1280 from asarium/fix/dradisColorIcon
Restore color icon behavior in DRADIS HUD gauge
2017-03-05 13:19:15 +01:00
asarium e7a923bef6 Always use the english key name in the scripting interface
Previously, the key text would use the localized key name which made it
hard for scripts to consistently handle key presses across different
languages. This changes that interface so that it always returns the
english name of the key.
2017-03-04 20:11:29 +01:00
asarium 840c1802e6 Use libc++ for clang builds on Travis CI
This should ensure that our code also works with that C++ standard
library implementation and should catch more cross-platform
incompatibilities.
2017-03-04 16:47:14 +01:00
asarium 772a02f56f Disallow to use non-trivial types as scripting handles
As described in #1278, the current scripting system has issues with
handling non-trivial C++ types. Since fixing that deficiency is too much
work, especially since we are in a feature freeze, I decided to simply
enforce the usage of trivial types for scripting handles. Fortunately,
only two handles used non-trivial types so it was relatively easy to fix
those instances by dynamically allocating those and only storing the
pointers in the lua memory.

This fixes a bug in JAD-XA where the game would crash at the last boss.

Also, I noticed that the HudGauge handle used a copy of the hud gauge
rather than a pointer to the actual instance so I'm pretty sure that any
scripting changes to a custom HUD gauge simply didn't work before.
2017-03-04 16:16:22 +01:00
asarium 6a803c0550 Fix depth test of lasers when using a cockpit ... again
This introduces code to explicitly restore the z-buffer binding to the
previous value instead of relying on the lightshaft code to restore it.
2017-03-04 15:59:13 +01:00
asarium 485a5989c8 Restore color icon behavior in DRADIS HUD gauge
The DRADIS has two icon types, one where the color is scaled with the
IFF color and once which isn't. Due to a regression, both icons were
previously scaled with the IFF color which made the icons look bad. This
fixes that.
2017-03-04 13:12:03 +01:00
niffiwan 10bbead9ec Merge pull request #1270 from asarium/fix/bmpmanAssert
Require that the energy bar animation has 4 frames
2017-03-04 11:44:16 +10:00
MageKing17 aea4d1d414 Merge pull request #1277 from asarium/fix/weaponDescriptingLength
Fix assertion failure in weapon choice screen
2017-03-03 15:21:59 -08:00
MageKing17 3a321251f7 Merge pull request #1275 from asarium/fix/changeClassAssert
Remove unneded assert in change_ship_class
2017-03-03 15:17:47 -08:00
MageKing17 079a3f96eb Merge pull request #1276 from asarium/fix/objectSignature
Adjust object_h validity check to avoid assertion failure
2017-03-03 15:17:07 -08:00
asarium a94bf2e9e2 Skip parse tests in release mode 2017-03-03 19:58:54 +01:00
asarium 92e8db7ff4 Ignore .fuse_hidden files 2017-03-03 19:02:05 +01:00
asarium 81f5cf4446 Fix assertion failure in weapon choice screen
If the descripting of a weapon is too long it would currently cause a
very unhelpful assertion message. This fixes that by checking the length
of the lines when parsing the weapon description. I removed the
assertions since the string is just cut of if it is too long so that
fixes the actual assertion.

I also added two unit tests for making sure that too long descriptions
cause warnings.
2017-03-03 18:59:30 +01:00
asarium 842858f9b8 Adjust object_h validity check to avoid assertion failure
I found this issue while debugging the JAD gauntlet where a script calls
getSignature() on an invalid object. However, object_h does not see the
object as invalid even though its signature is 0 which is defined to be
an invalid sigature. This should fix that by making sure that
object_h::isValid returns false if the saved signature is not valid.
2017-03-03 17:46:00 +01:00
asarium 415b2b4933 Remove unneded assert in change_ship_class
I just encountered this assertion while debugging another issue. As far
as I can tell, this can happen if the ship dies the same frame that
change_ship_class is called. Since a negative hull_strength value is a
valid value this assert is invalid. The CLAMP should ensure that the
following code still behaves as expected.
2017-03-03 17:27:45 +01:00
Fabian Woltermann e243601cf0 Merge pull request #1274 from asarium/fix/generatedShieldRtt
Fix generated shields rendering in cockpits
2017-03-03 15:26:35 +01:00
asarium 808231dd7d Fix generated shields rendering in cockpits
The generated shields did not respect the display offset specified in
the table so they were drawn out of the clipping bounds of the gauge
which meant that they were not visible. This fixes that by respecting
the specified display offset when rendering the shield icons.
2017-03-03 13:18:00 +01:00
Cliff Gordon 44093bd88c Merge pull request #1273 from asarium/fix/macHighDPI
Fix rendering on high DPI displays on Mac
2017-03-02 13:09:28 -06:00
asarium 4d7324dddf Fix rendering on high DPI displays on Mac
I added the "allow high DPI windows" SDL-flag while investigating #998
but since that flag isn't used on Windows we can safely remove it again
without causing issues.
2017-03-02 16:15:53 +01:00
Fabian Woltermann 83dd78a95f Merge pull request #1271 from SamuelCho/fresnelFactor
Adjustable fresnel term in lighting model. Model shader cleanup. Deferred lighting shader fix.
2017-03-02 09:36:42 +01:00
SamuelCho d31083cabc Restore environment map attenuation following shader cleanup. 2017-03-01 21:26:50 -08:00
m!m c154581d6e Merge pull request #1269 from asarium/fix/windowsManifest
Add a Windows executable manifest to FreeSpace2
2017-03-01 09:29:07 +01:00
SamuelCho 2fd72258f4 Added adjustable fresnel term to Blinn-Phong lighting model. Cleaned up the model shader. Fixed deferred lighting shader to use correct specular material color instead of specular light color for F_0 term. 2017-02-28 22:31:52 -08:00
asarium 67051463bd Require that the energy bar animation has 4 frames
Since the rendering code always accesses all four frames it must be
ensured that they are all present. Currently, there is a bmpman
assertion about an invalid handle if the animation does not have enough
frames. This fixes that by warning about that and then resetting the
bitmap handle to -1 so that the rendering code doesn't try to use the
handle.
2017-02-28 14:30:42 +01:00
m!m 930e435ffd Add comment for clarifying Windows XP compatibility 2017-02-28 09:09:07 +01:00
asarium 6b62146388 Add a Windows executable manifest to FreeSpace2
This sets the dpiAware flag which should improve the compatibility with
High-DPI displays. It also sets a few values for specfying what Windows
versions we support and it also enabled the nicer dialog boxes which
makes the error and warning dialogs look a bit nicer.
2017-02-27 17:27:02 +01:00
Fabian Woltermann 1f648f58e5 Merge pull request #1268 from asarium/fix/msvcPCHMemory
Allocate more memory for the Visual Studio compiler
2017-02-27 12:37:16 +01:00
asarium e7fb0dacc5 Allocate more memory for the Visual Studio compiler
One of the nightly builds failed to compile with an error saying that it
had run out of heap space. This adds the suggested flag which should
hopefully fix this issue.
2017-02-27 09:48:01 +01:00
m!m 989c010a64 Merge pull request #1265 from The-E/ReplaceAllTextures
Make table-based texture replacement work
2017-02-26 23:24:38 +01:00
Fabian Woltermann 9e3f07305b Merge pull request #1260 from asarium/fix/1224
Make Skip_packfile_search restrict search to actual files
2017-02-26 15:42:04 +01:00
Fabian Woltermann 9e93ebde03 Merge pull request #1266 from asarium/cmake_/gccReturnWarning
Enable GCC and Clang warning for missing return
2017-02-26 15:40:31 +01:00
Fabian Woltermann 8774f0480d Delete the = operator as well 2017-02-26 14:03:08 +01:00
Fabian Woltermann 17b33317de Addressing feedback. This disables the copy operator for model_render_params and changes the one place where it was actually used. 2017-02-26 13:45:03 +01:00
asarium db4fbe8fd6 Enable GCC and Clang warning for missing return
The C++ standard allows to have no return in a function but in most
cases that is not the desired behavior. There are currently no instances
of this warning in our code but I encountered this error while
developing something else.
2017-02-26 12:58:19 +01:00
Fabian Woltermann 9e4c6df219 Applies table-based texture replacement settings in the lab, techroom and the weapon/ship select screens 2017-02-25 21:38:58 +01:00
Fabian Woltermann 9e50680685 Merge pull request #1262 from asarium/fix/1261
Render correct number of vertices for shield icon
2017-02-25 15:17:41 +01:00
asarium a02c2deb69 Render correct number of vertices for shield icon
I also added a few graphics debug scopes since I needed those for
tracking down which code renders the shield icons.

This fixes #1261.
2017-02-25 12:59:51 +01:00
asarium df5679c9d1 Make Skip_packfile_search restrict search to actual files
The flag was previously used to restrict searching of mission files to
the root directory of the mod. Since the SDL merge changed what the
default root directory is (now it's the mod folder in the user folder)
this broke the mission editor and it didn't show any missions anymore.

This fixes that by altering how Skip_packfile_search affects the file
search. Now that causes the search to skip files in VPs but it still
includes all other files that are present on the disk.

I also fixed some inconsistent behavior in the various file enumeration
functions since they weren't doing the same thing.

This changes the original behavior slightly since new files aren't found
in this search since the file list is only initialized when CFile is
started so if a new file is added after that, it is not reflected in the
mission list. Since that is pretty rare we can probably ignore that
here.

This fixes #1224.
2017-02-25 12:20:05 +01:00
Fabian Woltermann 12c9ba07f8 Merge pull request #1247 from asarium/fix/1244
Fix or suppress warnings in stb_image
2017-02-23 09:49:27 +01:00
Fabian Woltermann 7ef78fd17b Merge pull request #1254 from asarium/cmake_/prefixHeader
Use a manually maintained prefix header for cotire
2017-02-23 09:47:00 +01:00
asarium d7274b85f9 Use a manually maintained prefix header for cotire
Cotire (the CMake module we use for handling precompiled headers) can
auotmaically generate a prefix header by examining the includes of the
project. However, if a system include changes, the prefix header may
change as well which triggers a complete project rebuild. To avoid this
and to add the ability to customize the prefix header, I added a
manually maintaned header which will be used by all platforms and which
will only change if that file is manually changed.
2017-02-22 23:21:46 +01:00
m!m 4f9f0b6868 Merge pull request #1259 from The-E/scriptEvalCleanup
Like script-eval, script-eval-string should also return SEXP_TRUE
2017-02-22 19:41:41 +01:00
Fabian Woltermann 98169f9f2e Merge pull request #1258 from asarium/fix/playerVariableSimulation
Set the Player scripting variable for the whole frame
2017-02-22 18:29:54 +01:00
Fabian Woltermann 99e1f22d12 Like script-eval, script-eval-string should also return SEXP_TRUE 2017-02-22 17:00:57 +01:00
MageKing17 59769894f3 Merge pull request #1255 from asarium/doc/sexpCarCdr
Add documentation for CAR and CDR
2017-02-22 07:09:27 -08:00
asarium b7e46e49d3 Set the Player scripting variable for the whole frame
Otherwise the Simulation hook would be called without a Player variable
which breaks some scripts.
2017-02-22 15:42:50 +01:00
m!m d96295e923 Merge pull request #1257 from The-E/ScriptEvalReturns
Make script-eval return SEXP_TRUE
2017-02-22 13:44:03 +01:00
Fabian Woltermann 47aa9a6237 Make script-eval return SEXP_TRUE so that it behaves as expected when used in an event without a when conditional 2017-02-22 12:32:18 +01:00
asarium e374637df2 Fix or suppress warnings in stb_image
This fixes #1244.
2017-02-22 12:04:35 +01:00
asarium 8e71c392ab Add documentation for CAR and CDR
This should clear up some confusion about what the functions do since
their behavior is not obvious from looking at the code.
2017-02-22 11:28:21 +01:00
Cliff Gordon bad7254692 Merge pull request #1252 from asarium/fix/macosxBundle
Use the correct variables in MacOSX Info.plist
2017-02-21 19:52:48 -06:00
Fabian Woltermann 0af2736327 Load the Fire particle animations (#1251)
Load the Fire particle animations too. Fixes #1245.
2017-02-21 16:20:35 -08:00
asarium df01822c2a Use the correct variables in MacOSX Info.plist
This fixes #1228.
2017-02-21 21:56:45 +01:00
Fabian Woltermann 8e04c6c8e0 Merge pull request #1250 from asarium/fix/debugWindowWidth
Fix assertion in debug window when width is too low
2017-02-21 14:13:16 +01:00
asarium e71b9629fe Fix assertion in debug window when width is too low 2017-02-20 11:59:02 +01:00
Fabian Woltermann c3e3337802 Merge pull request #1235 from asarium/fix/ffmpegVersionConstraint
Add a sensible version constraint for FFmpeg
2017-02-20 09:12:24 +01:00
Fabian Woltermann f70adedfaf Merge pull request #1249 from MageKing17/bugfix/debris-ship-class-alt-name
Make debris from a ship use the ship class's alt name, if specified.
2017-02-20 09:11:52 +01:00
Fabian Woltermann 1edd6e8297 Merge pull request #1248 from MageKing17/bugfix/player-variable-reset
Clear the player's variable vector in init_new_pilot() if reset is true.
2017-02-20 09:10:56 +01:00
MageKing17 77a71f3445 Make debris from a ship use the ship class's alt name, if specified.
A piece of debris spawned from a ship will say what class of ship it came from. If that ship has an alternate class name defined in FRED, that's used instead. If the ship class table entry specifies an "$Alt name:", however, that isn't used, which could potentially be confusing. This fixes that oversight.
2017-02-19 14:56:53 -08:00
MageKing17 0b6a8c11f6 Clear the player's variable vector in init_new_pilot() if reset is true.
This fixes a bug whereby creating a pilot in the barracks screen (not the initial pilot selection screen) would effectively clone the variable vector from whatever pilot was selected beforehand.
2017-02-19 14:54:01 -08:00
Fabian Woltermann 08f80fe190 Merge pull request #1234 from asarium/fix/mantis3183
Render all damage elements of the damage HUD gauge
2017-02-19 00:08:23 +01:00
m!m fe8ead6609 Merge pull request #1240 from vazor222/bugfix/addSubmoduleNoteToReadme
minor readme updates
2017-02-18 22:34:24 +01:00
niffiwan df8f20f208 Merge pull request #1242 from asarium/fix/1241
Copy all relevant values in the LuaFunction copy-constructor
2017-02-19 07:33:56 +10:00
asarium 5bf2b956f6 Copy all relevant values in the LuaFunction copy-constructor
This fixes #1241.
2017-02-18 19:33:44 +01:00
vazor e218c3967e formatting update 2017-02-18 11:01:57 -07:00
z64555 d68370ade7 Merge pull request #1239 from asarium/fix/timeroverflow
Fix standalone timer overflow
2017-02-18 11:57:38 -06:00
vazor 8c79033819 added note to readme that would have saved me some time, minor typo fix 2017-02-18 10:46:32 -07:00
asarium 15af2bb1a2 Fix standalone timer overflow
If FSO runs for a very long time (5 hours to be exact) then the SDL
performance counter reaches a value so hight that rescaling it to
microseconds causes an overflow which is bad.

This fixes that by implementing the rescaling by computing the factor in
the timer initialization code and then multiplying the SDL time with
that. This uses the same principle as the changes done by @TheMatthew in #1082.

According to the tests done by @chief1983, this fixes #1237.
2017-02-18 16:54:58 +01:00
Cliff Gordon 82d8f5df74 Merge pull request #1236 from asarium/cmake_/formatDefinition
Always define __STDC_FORMAT_MACROS for GCC and Clang
2017-02-17 12:23:16 -06:00
m!m cb12cbef45 Merge pull request #1233 from The-E/CfileToolsCmakeFix
Cfile tools cmake fix
2017-02-17 13:59:47 +01:00
MageKing17 b8a9c520f3 Merge pull request #1226 from asarium/fix/briefingWrapping
Fix briefing word wrapping when a script changes the font
2017-02-17 02:31:15 -08:00
m!m bffe4b787d Merge pull request #1223 from Yarn366/fred_max_missile_count
Change get_max_ammo_count_for_bank to return "correct" max missile count
2017-02-17 10:46:17 +01:00
asarium 76db58932e Always define __STDC_FORMAT_MACROS for GCC and Clang
This caused some issues for @chief1983 when trying to compile on an
older Linux distribution.
2017-02-16 19:41:55 +01:00
asarium 7f73d35753 Add a sensible version constraint for FFmpeg
2.7 is the last version we can support with our current code so we
should check for that.
2017-02-16 19:16:56 +01:00
Fabian Woltermann cd5e276102 Changes the usage printout as per discussion 2017-02-16 10:24:51 +01:00
asarium 900218e3e4 Render all damage elements of the damage HUD gauge
Previously, the hud gauge was hidden if the player ship had taken no
damage. However, this made it impossible to see if subsystems have been
damaged.

These changes make sure that the subsystem values are shown even if the
hull integrity is at 100%. This is done by first collecting all the
necessary information about each line in the gauge and then, if that list
is non-empty, rendering it. This is necessary since the gauge code can't
decide if anything will be visible before looking at the entire
subsystem list.

There is a minor behavior change with how popups are handled.
Previously, the code would return if the HUD gauge was a popup and its
strength was at 100%. However, I think that this was dead code anyway
since that condition could never be true at that point because the code
would have returned earlier if there was no damage.

This fixes Mantis 3183.
2017-02-15 19:29:09 +01:00
Fabian Woltermann af285fbdbd Merge pull request #1232 from asarium/fix/mantis3177
Unload models after loading them for -pofspew
2017-02-15 16:28:16 +01:00
Fabian Woltermann d78a9fe8e3 Removes unnecessary stuff from the commandline help for cfilearchiver 2017-02-15 16:13:00 +01:00
Fabian Woltermann 792cbf20a9 Fixes Configuration error for the CFileArchiver/Extractor projects 2017-02-15 16:12:59 +01:00
asarium 0641437803 Unload models after loading them for -pofspew
In large mods this caused memory issues since we reached the 32-bit
memory limit when loading all models of a large mod (e.g. Blue Planet).

I fixed that by explicitly unloading the loaded model once the code is
done with it.

This fixes Mantis 3177.
2017-02-15 10:29:03 +01:00
Fabian Woltermann fa5db4fcfa Merge pull request #1230 from asarium/fix/mantis3175
Fix "On Object Render" behavior regression
2017-02-15 10:06:39 +01:00
m!m bea4c628ec Merge pull request #1231 from jg18/xcode_debug_symbols
Configure Xcode projects to generate debug symbols for Debug builds.
2017-02-15 09:45:07 +01:00
jg18 11e2491124 Configure Xcode projects to generate .dSYM file. 2017-02-14 21:33:58 -08:00
jg18 09021f3141 Configure Xcode projects to generate debug symbols for Debug builds.
Set CMake to configure Xcode projects to generate debug symbols for Debug builds.
2017-02-14 21:05:54 -08:00
asarium bd4b845290 Fix "On Object Render" behavior regression
This regression was introduced with the new model draw list which separates
collecting the drawing information and actually drawing the objects.

Previously, the scripting hook was always executed and the override
condition was used to determine if the normal rendering should happen.
Since 3.7.4, the scripting code is only executed if the condition was
overridden by Lua and if that override is active then the model isn't
rendered at all.

This executes the scripting hook in all cases and then checks if the
scripting system specified if rendering of that object should be
skipped. This introduces some slight changes in behavior since, when the
scripting hook is executed, the object isn't actually being rendered but
instead it's added to the draw list. IMO, that is not a major issue for
any existing application or else we would have heard about that until
now.

This fixes Mantis 3175.
2017-02-14 20:11:04 +01:00
Fabian Woltermann e0e7f141ad Merge pull request #1229 from asarium/fix/mantis3188
Fix wrong control flow in stars_draw_sun
2017-02-14 17:28:14 +01:00
Fabian Woltermann 7bdaac55e5 Merge pull request #1225 from asarium/fix/cfileTests
Actually add CFile to the unit test project
2017-02-14 15:06:21 +01:00
asarium c473601875 Fix wrong control flow in stars_draw_sun
The code wrongly used return instead of continue. This caused a second
sun to disappear if the bitmap of the first sun wasn't drawn.

This fixes Mantis 3188.
2017-02-14 14:54:46 +01:00
m!m bd0a1440e7 Merge pull request #1227 from chief1983/fix/967
Fix for #967 - Enable APPLE_APP in Mac CMake project
2017-02-14 11:00:24 +01:00
asarium 6508f47625 Fix briefing word wrapping when a script changes the font
This happened in BtA where a script changed the font after rendering its
UI. Since the briefing code didn't account for that, the word wrapping
code used the wrong font for calculating how long a line would be which
made the display look wrong.
2017-02-14 10:37:55 +01:00
Cliff Gordon 05a12213de fix/967: Define APPLE_APP to fix some issues introduced on Mac in the CMake conversion (may have other effects we aren't yet aware of). 2017-02-13 13:09:36 -06:00
asarium e90563c437 Actually add CFile to the unit test project
For some reason these weren't included in the PR that was supposed to
contain them.
2017-02-13 14:52:09 +01:00
m!m 7e8005033d Merge pull request #1222 from Yarn366/fred_retail_red_alert
Fix for improper setting of +Red Alert:
2017-02-13 10:07:51 +01:00
Yarn366 6be290ed8b Change get_max_ammo_count_for_bank to return what the rest of the game considers to be the max missile count 2017-02-13 00:00:27 -05:00
Yarn366 82735a0cfd In retail mode, set +Red Alert: according to the Red_alert flag rather than the Fullneb flag 2017-02-12 23:26:53 -05:00
m!m 5f5dbf5139 Merge pull request #1220 from The-E/ExportNoEmissive
Export the -no_emissive_light flag to the Launcher
2017-02-13 00:07:24 +01:00
Fabian Woltermann be3f86cd65 Export the -no_emissive_light flag to the Launcher 2017-02-12 22:17:53 +01:00
Fabian Woltermann 3df8b53570 Merge pull request #1219 from PeterMitsis/parallel-fix
vecmat: Fix vm_test_parallel()
2017-02-12 18:30:21 +01:00
MageKing17 8eafa260d2 Merge pull request #1218 from The-E/RotationWarningFix
Removes log spam
2017-02-12 09:18:21 -08:00
Fabian Woltermann ea5342bc70 Merge pull request #1216 from asarium/fix/1051
Create main window at 0,0 if its the same size as the display
2017-02-12 17:38:04 +01:00
Fabian Woltermann 8ffb0fe407 When converting an Assertion to a Warning or log print, remember to invert the Assertion's condition to get correct behaviour 2017-02-12 17:26:11 +01:00
Peter Mitsis f448150156 vecmat: Fix vm_test_parallel()
Fixes a subtle problem with vm_test_parallel() wherein a relative error
was accidentally converted into an absolute error.

Instead of comparing the result of the cross product to the zero vector,
the two calculated components of the cross product are compared against
each other. This permits vectors whose cross product is a large number
but whose cross product partials are within relative error of each other
to be treated as parallel.

For example, the following two vectors may now be considered as parallel
whereas before they were not:
   v1 = (1000004.0, 1.0, 1.0)
   v2 = (1000000.0, 1.0, 1.0)
The relative difference between them is sufficiently small according to
vm_vec_equal() for them to be considered equal, but their cross product
would have elements whose magnitudes would be near 4.0 which would
otherwise indicate that they are not parallel. By comparing the partials
instead, a higher degree of consistency is maintained.

Signed-off-by: Peter Mitsis <[email protected]>
2017-02-12 11:04:38 -05:00
asarium 6c1d5263f1 Create main window at 0,0 if its the same size as the display
This fixes #1051 by explicity telling SDL to create the window in the
display corner instead of centering the window. This has caused some
problems because the window borders aren't visible anymore in this case
which lead to some confusion.
2017-02-12 15:42:19 +01:00
m!m 58b49486ce Merge pull request #1215 from Goober5000/issue_1176_bugfix
make sure we find the correct operator for logging in short-circuited sexps
2017-02-12 10:36:29 +01:00
Goober5000 b2a2c7b0bd make sure we find the correct operator for logging in short-circuited sexps 2017-02-12 00:50:11 -05:00
niffiwan df6b2d4cdd Merge pull request #1214 from asarium/fix/btaSystemMapNodes
Return correct bits-per-pixel data for 16-bit PNGs
2017-02-12 11:02:27 +10:00
asarium 6f84fcbf6d Return correct bits-per-pixel data for 16-bit PNGs
PNGs can have 16 bits per channel but we always tell libpng to reduce
that to 8 bits per channel. However, we do not tell the caller of
png_read_header that this will happen so instead of 32-bits per pixel,
we tell bmpman that the image has 64 bits per pixel which causes some
issues.

The specific issue I fixed was the system map of BtA where the jump
nodes used a 16-bit PNG which broke the alpha blending of those bitmaps
since bmpan though that the image had no alpha channel.
2017-02-11 23:24:09 +01:00
Fabian Woltermann 028ae98c21 Merge pull request #1212 from TRBlount/Lab_initial_orient
Change Initial Orientation in the Lab
2017-02-11 21:25:53 +01:00
TRBlount f4d11325c6 Change Initial Orientation in the Lab 2017-02-11 10:39:12 -07:00
m!m 2b83c73f8f Merge pull request #1213 from Yarn366/weapons_dialog_rounding
Fix for rounding errors in weapons dialog
2017-02-11 11:43:50 +01:00
Yarn366 39e1ae18a4 Added proper rounding to missile counts in the weapons dialog. 2017-02-10 20:23:10 -05:00
m!m eb1389d738 Merge pull request #1208 from The-E/LikeARecordBabyRightRound
Changes the "Object rotated too far" assertion to a log message
2017-02-09 15:48:13 +01:00
Fabian Woltermann 589eb7533c Merge pull request #1195 from asarium/opengl/moreObjectLabels
Assign OpenGL labels to more objects
2017-02-09 12:41:52 +01:00
Fabian Woltermann fbe9cc156c Merge pull request #1204 from asarium/fix/1182
Search for path types regardless of case
2017-02-09 12:40:36 +01:00
Fabian Woltermann b319143a67 Changes the "Object rotated too far" assertion to a log message, as per discussion for PR #1171 2017-02-09 12:35:23 +01:00
m!m d71a6b0ba7 Merge pull request #1175 from MageKing17/bugfix/energy-transfer-oddities
Fix two bugs with transferring energy to/from shields/weapons.
2017-02-09 10:11:11 +01:00
z64555 5d7b64fcbf Merge pull request #1207 from z64555/fix/vec_parallel
Fix minor bug with parallel vector testing
2017-02-08 23:16:17 -06:00
z64555 39912e025b Use vm_vec_equal, like you intended. 2017-02-08 18:38:56 -06:00
MageKing17 4a3f9f1d84 Merge pull request #1203 from asarium/ci/fixNightlyBuilds
Fix wrong variable usage in test script
2017-02-08 12:56:20 -08:00
z64555 8195fd50ab Fix minor bug with parallel vector testing 2017-02-08 12:42:59 -06:00
Goober5000 a64468200e Merge pull request #1200 from chief1983/fix/dircreate
Stops debug log printing "Creating new directory"
2017-02-08 13:39:17 -05:00
asarium 6ff7662c29 Search for path types regarless of case
Previously, if a mod used an upper case "Data" folder (which is the case
for the Diaspora development files) the file enumeration would fail on
case sensitive platforms (e.g. Linux) since FSO searched for a path with
a lower case "data". These changes make it so that FSO looks for all
instances of the path type name regeardless of case. Since the real path
was also needed elsewhere I added a new cf_file field which stores the
actual path which can then be used by fopen operations.

This fixes #1182.
2017-02-08 19:17:33 +01:00
Cliff Gordon d3480f70f2 Fix for log printing creating directory lines for directories that already exist. 2017-02-08 10:35:36 -06:00
Fabian Woltermann 2907c7ab94 Merge pull request #1197 from asarium/fix/712
Boost the color of nebula bitmaps to make them visible again
2017-02-08 14:19:50 +01:00
Fabian Woltermann 1a130c794a Merge pull request #1199 from asarium/fix/highestObjectCrash
Fix negative array index
2017-02-08 14:18:58 +01:00
asarium c589c72817 Fix wrong variable usage in test script 2017-02-08 13:08:50 +01:00
Fabian Woltermann 695bee61c8 Merge pull request #1201 from asarium/fix/643
Remove object instance from lab render info
2017-02-08 12:33:16 +01:00
Fabian Woltermann 7c8abe0f16 Merge pull request #1202 from scp-fs2open/revert-1187-fix/1182_2
Revert "Show error message when a data directory uses the wrong case"
2017-02-08 12:32:41 +01:00
m!m 07c86cd9c8 Revert "Show error message when a data directory uses the wrong case" 2017-02-08 10:52:46 +01:00
asarium cb531f8a88 Remove object instance from lab render info
If the object number is set for the render info the renderer uses the
instance information of that object to render the model. That is not
correct for the lab since the instance data is handled by the lab code
in that case.

This fixes #643.
2017-02-07 22:37:38 +01:00
MageKing17 86cb91f9f2 Merge pull request #1194 from asarium/unittests/appveyor
Execute unit tests on appveyor
2017-02-07 12:57:49 -08:00
asarium f87a72bc15 Fix negative array index
If there was only one object and that got deleted the code that keeps
track of the highest object index would cause a negativ array index. I
added a check to make sure that the index was positive but that still
means that Highest_object_index will be negativ after that function
returns. I looked at the usages of the value and that value seems to be
fine with that code so I think this should be safe.
2017-02-07 19:55:27 +01:00
asarium 33496419f9 Boost the color of nebula bitmaps to make them visible again
The HDR changes made the nebula bitmaps a lot less visible. This fixes
that by boosting the color of the bitmaps when they are rendered.

I choose 3 since that gives a similar look to 3.7.4 but that can be
further tweaked if desired.

I also added two debug scopes to help track down where that stuff was
actually rendered.

This fixes #712.
2017-02-07 18:33:15 +01:00
Fabian Woltermann 4321fd364d Merge pull request #1187 from asarium/fix/1182_2
Show error message when a data directory uses the wrong case
2017-02-07 17:34:03 +01:00
Fabian Woltermann d40cf7a3cd Merge pull request #1179 from asarium/fix/651
Make sure that team glow colors don't go negativ
2017-02-07 17:33:25 +01:00
Fabian Woltermann fa90542b00 Merge pull request #1193 from asarium/fix/611
Disable resizing for cubemaps
2017-02-07 17:32:56 +01:00
asarium cdc6f7d907 Disable lua args tests since MSVC 2013 doesn't like them
The code the test was testing isn't used by anyway so we don't loose
test coverage. I'm also quite certain that the failure is caused by some
sort of compiler bug or wrong standard library implementation.
2017-02-07 17:09:39 +01:00
asarium 084d237437 Assign OpenGL labels to more objects
The texture labels make it easier to debug which texture is currently
bound when tracing with APItrace.
2017-02-07 16:30:21 +01:00
asarium 62f6494299 Execute unit tests on appveyor
Appveyor didn't have the OpenAL DLLs so I included those with our
existing files. They are currently not used by FreeSpace or FRED.
2017-02-07 14:50:37 +01:00
Fabian Woltermann 19583bc788 Merge pull request #1192 from asarium/fix/1191
Restore original flag parsing behavior
2017-02-07 06:11:07 +01:00
asarium fff62a85e0 Restore original flag parsing behavior
THe flagset changes misplaced the post-parsing flag processing so that
it was only executed if a special flag was found. That was not the case
previously and this restores that behavior. I also simplified the code a
bit while I was at it.

This fixes #1191.
2017-02-06 22:37:15 +01:00
asarium e52b144510 Disable resizing for cubemaps
Since the cubmap loading code explicitly states that it doesn't support
resizing it's only logical to skip that if the bitmap that is currently
being loaded is a cube map.

This fixes #611.
2017-02-06 18:42:06 +01:00
Fabian Woltermann e8d21a020f Merge pull request #1189 from asarium/fix/940
Set the registry key for FRED
2017-02-06 09:32:39 +01:00
Fabian Woltermann 8b24877f9e Merge pull request #1190 from asarium/fix/bloomAccumulator
Fix post processing framebuffer binding
2017-02-05 18:45:41 +01:00
Fabian Woltermann 6efceb2017 Merge pull request #1188 from asarium/fix/objectLabelCrash
Fix crash when using glObjectLabel
2017-02-05 17:19:37 +01:00
asarium c28bfcf959 Fix post processing framebuffer binding
The framebuffer stack operations were at the wrong locations which
caused problems since the wrong buffers were used for rendering.
2017-02-05 17:17:33 +01:00
asarium 0b472ea463 Set the registry key for FRED
The default key is probably not valid anymore since we don't use the
registry virtualization anymore.

This fixes #940.
2017-02-05 17:02:44 +01:00
asarium ec82cb15ce Fix cmpilation errors 2017-02-05 15:44:13 +01:00
asarium 69dba707e0 Fix crash when using glObjectLabel
Apparently OpenGL contexts aren't supposed to expose the KHR variant so
this version should work better if the extension is supported.
2017-02-05 15:40:40 +01:00
Fabian Woltermann f50be50b18 Merge pull request #1173 from asarium/cleanup/tcache
Remove tcache_set from rendering API
2017-02-05 15:28:29 +01:00
Fabian Woltermann 90a5af60c4 Merge pull request #1186 from asarium/fix/976
Fix wrong usage of cockpit depth buffer
2017-02-05 15:26:15 +01:00
asarium 33c1b788df Clean up Unix code a bit 2017-02-05 14:46:16 +01:00
asarium 5265627b8f Add case check for Windows 2017-02-05 14:43:58 +01:00
asarium 94ce0ad2dd Add test for wrong case in data directory 2017-02-05 13:06:01 +01:00
asarium 0eeb895432 Issue error when a data directory uses the wrong case
Since Unix is case senssitive this should make sure that case errors are
cought early in mod development. This is an Error and not a Warning
since a mod with such a folder structure would never work under Unix and
as such it's justified to break mods that currently use this.
2017-02-05 13:03:57 +01:00
asarium 5d7f10d4f8 Add utility function for assigning labels to OpenGL objects 2017-02-05 12:06:37 +01:00
asarium 9013d398db Fix wrong usage of cockpit depth buffer
The root issue of #976 was that the code that reset the depth buffer of
the scene framebuffer was actually setting the depth buffer of the bloom
framebuffer since that didn't get reset properly. To fix this I
introduced a system in our GL_state which keeps track of a stack of
"bound" framebuffers which allows us to return to the previous
framebuffer with a simple function call.

I also added support for GL_KHR_debug since that help me while debugging
which texture was in use. In the future I'll probably extend that to
other areas of the OpenGL code as needed.

This fixes #976.
2017-02-05 12:03:26 +01:00
asarium 7c556854af Add more graphics debug scopes for code called in the main frame 2017-02-05 12:03:23 +01:00
MageKing17 ce519f006d Merge pull request #1185 from z64555/fix/github_1177
Fixes pointer access violation when docked ships warp out by moving dock_undock_all call to red_alert_delete.

It was previously thought that dock_undock_all() was supposed to be within ship_cleanup() and was safe to do so. Nope.

dock_evaluate_all_docked_objects makes the assumption that the dock_list is still valid, so if the function called by it happens to nuke the dock_list (like with ship_cleanup) then it'll work with invalid pointer values.
2017-02-04 22:37:28 -08:00
z64555 4129551341 Fixes pointer access violation when docked ships warp out by moving dock_undock_all call to red_alert_delete.
It was previously thought that dock_undock_all() was supposed to be within ship_cleanup() and was safe to do so. Nope.

dock_evaluate_all_docked_objects makes the assumption that the dock_list is still valid, so if the function called by it happens to nuke the dock_list (like with ship_cleanup) then it'll work with invalid pointer values.
2017-02-04 22:12:14 -06:00
niffiwan 9be888f55a Merge pull request #1183 from asarium/fix/newVMFree
Fix new/vm_free mismatch reported by AddressSanitizer
2017-02-05 09:21:14 +10:00
m!m b185d1bfea Merge pull request #1178 from The-E/VS2017ignores
Updates the gitignore for VS2017
2017-02-05 00:09:46 +01:00
MageKing17 19a37eb04d Merge pull request #1024 from asarium/feature/defaultConfigLoc
Improve logic for determining legacy mode
2017-02-04 11:33:45 -08:00
asarium ca2f9b788f Fix new/vm_free mismatch reported by AddressSanitizer 2017-02-04 19:12:34 +01:00
Fabian Woltermann 9a1eb4e794 Update .gitignore
Removes duplicate entry
2017-02-04 13:38:01 +01:00
m!m 592282448b Merge pull request #1180 from niffiwan/coverity/1370830
Fix Coverity 1370830
2017-02-04 10:15:59 +01:00
niffiwan e6bff4f864 Fix Coverity 1370830
Use after free; use the copied string for the Warning
2017-02-04 16:16:18 +10:00
asarium 1cf0bacc6e Make sure that team glow colors don't go negativ 2017-02-03 22:30:39 +01:00
Fabian Woltermann 1f352967c7 Updates the gitignore for files that VS2017 writes when opening the repository 2017-02-03 15:49:20 +01:00
MageKing17 cf14728757 Avoid silly behavior when transferring almost-nonexistent energy.
This is a bit complicated to explain, so stick with me.

When transferring energy from shields to weapons (or vice versa), the values modified are the so-called "target deltas" rather than directly modifying the shield strength or weapon energy values. The ship_chase_shield_energy_targets() function carries out actually meeting these targets without exceeding a change of ETS_RECHARGE_RATE percent per second. At least, that's what it's supposed to do, and obviously works that way when the target delta is positive.

When the target delta is negative, however, a logic error with the conditional meant to limit the rate of change instead functions backwards; if the amount of desired change exceeds the per-frame limit, the amount of change is set to the total desired change, and if the amount of desired change is smaller than the per-frame limit, than the amount of change is the per-frame limit (even though that's more than the amount that's supposed to be drained).

Since the target delta is modified by the amount by which the value changed, this leads to an interesting consequence whereby the "extra" amount taken away is added back in the next frame... which has another interesting side-effect if the "extra" drain tried to reduce shields below 0. Namely, the shield code doesn't let it, while ship_chase_shield_energy_targets() remains blissfully unaware that the actual change was smaller than requested. So on the next frame, you spontaneously get some fraction of a percent of your shields back. Which, naturally, you can then transfer energy from to your weapons ad infinitum; the amount is small, but you can continually transfer it, so you're getting weapon energy out of nowhere.

Now, straight-up fixing the logic error would be a major retail balance change; if transferring energy from your shields to your weapons only gradually reduced your shields, instead of taking a huge chunk at the start, it would be a much safer option. Therefore, the only non-balance-changing fix is to just remove the broken conditional entirely (so that it always drains the full amount instantaneously, regardless of how big or small it is).

I've left the fixed conditional commented out so that somebody, when we're not in a feature freeze, can add an AI profile or mod table flag to restore the check, allowing for slow energy transfers.
2017-02-03 02:26:34 -08:00
MageKing17 c5278e2e95 Allow transferring energy from shields to work properly at full shields.
A conditional originally added to shield_add_strength() to make shields not recharge beyond the recharge limit forgot to check that the amount shields are changing by was positive (unlike a couple other conditionals added/modified around the same time), so a call to shield_add_strength() with a negative delta (e.g. when transferring energy from shields to weapons) when the current shield strength is at or above the recharge limit (i.e. full strength when a recharge limit isn't specified) would immediately return without doing anything. This would, of course, result in no change to shield strength... so if you had full shields and had drained your weapon batteries dry, you could get free energy by hitting the button to transfer energy from your shields.
2017-02-03 02:05:51 -08:00
MageKing17 fe1e9ca996 Merge pull request #1174 from asarium/cleanup/GLSL_version
Remove some unneeded OpenGL version checks
2017-02-03 01:55:31 -08:00
asarium 4ed9231983 Simplify condition 2017-02-02 23:25:50 +01:00
asarium ca1a844f08 Remove GL_version checks that are always true
Same as the GLSL version checks, these conditions were always true since
we only support OpenGL 3.2 now.

There was also an assertion condition that didn't make sense so I fixed
that.
2017-02-02 22:38:31 +01:00
asarium 833df59d0e Remove GLSL version checks that are always true
These checks were from a time when we supported lower OpenGL version
than 3.2. Since we don't do that anymore and show an error if the
drivers don't support that, these conditions always evaluated to true
and could be removed.
2017-02-02 22:35:03 +01:00
asarium 7cb652b5d2 Remove tcache_set from rendering API
It wasn't used anywhere and has been superseded by the material system.
It would also interfere with a possible texture array usage.
2017-02-02 22:26:14 +01:00
MageKing17 cd06284f50 Merge pull request #1172 from The-E/MoreTraceScopes
Adds more trace scopes
2017-02-02 10:04:08 -08:00
MageKing17 1305f1dbe2 Merge pull request #1170 from The-E/PaletteCleanup
Removes the Palette Manager
2017-02-02 10:03:51 -08:00
Fabian Woltermann b3a8824d68 Adds more trace scopes to get a better look at the internals of render_frame 2017-02-02 15:07:43 +01:00
Fabian Woltermann b42fb8272a Removes code that had been #ifdefed out 2017-02-02 13:16:28 +01:00
z64555 36c134fcb8 Merge pull request #1154 from z64555/cleanup/dock_swabber
Fixes two crashes in red-alert missions, cleans up and refactors some of the docking code
2017-02-02 00:18:34 -06:00
z64555 d648091de4 Merge pull request #1168 from MageKing17/bugfix/ship_weapon-constructor
Add missing variable to ship_weapon constructor.
2017-02-02 00:18:17 -06:00
z64555 2829c293df Merge pull request #1166 from z64555/fix/pr_1163_amend
Harmony to 1163's malady
2017-02-01 21:28:20 -06:00
MageKing17 094d117764 Merge pull request #1167 from asarium/fix/autoaimSpeed
Use the correct pointer in vm_vector_2_matrix
2017-02-01 18:19:59 -08:00
Fabian Woltermann 0c0f7b9986 Removes unused variable 2017-02-01 19:58:58 +01:00
z64555 f30f955058 Update doxy on ship_cleanup to reference the object cleanup path 2017-02-01 12:58:26 -06:00
Fabian Woltermann 38e803c3c3 Restores accidentally deleted assertion from aicode 2017-02-01 19:04:09 +01:00
Fabian Woltermann 2c4c337907 Removes the palette code entirely. 2017-02-01 18:57:52 +01:00
Fabian Woltermann 7a1c587a9c Remove palette manager 2017-02-01 18:29:18 +01:00
MageKing17 8c59d8fb6d Add missing variable to ship_weapon constructor.
secondary_animation_position wasn't being set by the ship_weapon constructor, which could cause potential issues with whatever uninitialized data it wound up being set to (like, say, being unable to fire any weapons in the second secondary bank until you've cycled through it once). Since it depended on uninitialized data, the behavior could even change between 32-bit and 64-bit builds (and Release/Debug, of course).

While I was at it, I also noticed some variables were getting set twice; in one instance (primary_animation_done_time), it was even being set to the wrong value the second time (according to the pre-flagset code that used memset() on it and then overrode some values that shouldn't have been zero). Not sure what problems that could've caused; possibly some issues with animations and primary weapons, I guess, if the "done" timestamp was invalid when it shouldn't have been.
2017-02-01 02:49:57 -08:00
asarium 1623d39eea Use the correct pointer in vm_vector_2_matrix
This probably caused a lot of issues throughout the code. I fixed the
autoaim issue that happened in the capship command mission by JSRNerdo.
2017-02-01 09:36:00 +01:00
z64555 73504f80a5 Treat cleanup_mode as enumeration
*Use Assertions instead of the clunky Error/Warning pairs.
2017-02-01 01:36:16 -06:00
z64555 95315d7f8a Optimizes dock_undock_objects() and dock_dead_undock_objects() methods by removing their dock pair check, because the same check is done in the remove_instance subroutines.
* Adds a warning for debug users when an unknown ship_state is passed to red_alert_delete.
* Removes commented-out code
* Doxy's ship_cleanup()

*Conform to each file's style.

*Extend ship_cleanup to better handle red-alert deletion.
*Also treat cleanup_mode as a flagset, instead of an enum as it was previously.
2017-02-01 01:35:45 -06:00
z64555 6577d53df8 Fixes red-alert missions where escorted ships were dead or otherwise not carried into the red-alert mission.
*Use existing methods to determine dock status and find the head of the dock list.
*Fixes a derp with dock_dead_undock_all()
*Doccument some docking methods in object.h
*Address requested changes.
2017-02-01 01:35:09 -06:00
z64555 63e44beb9c When deleting an object in red-alert missions, undock all objects docked with it. 2017-02-01 01:34:29 -06:00
z64555 944ed03553 Added undock_all routines. Added asserts to public methods. 2017-02-01 01:34:29 -06:00
z64555 a5a927dd71 Get that other weapons assignment, while we're still thinking about it 2017-01-31 16:36:06 -06:00
z64555 4153aa80a9 Harmony to 1163's malady
* Looks like a shallow copy wasn't enough, so this fix creates ship_weapons::clear() which is called by ship_weapons's constructor and by ship::clear().
2017-01-31 12:04:32 -06:00
Goober5000 2a574ef267 some riffs on PR #806 (#1163)
In ship::clear(), The E removed

memset(&weapons, 0, sizeof(ship_weapon));

but did not add a corresponding

weapons = ship_weapon();

This fixes that.  Additionally, this PR removes one of the two uses of ship::clear() by tweaking hud_observer_init.  Originally, the code used memcpy, but if the assignment operator works for ai_info, it should be suitable for ship too.
2017-01-29 21:58:15 -08:00
m!m 1767b7a87b Merge pull request #1164 from z64555/cleanup/doxy_vecmat
Doxy vm_vector_2_matrix functions.
2017-01-29 23:39:49 +01:00
z64555 db3e2ae183 Doxy vm_vector_2_matrix functions.
*Enforce if-else block style within vecmat.cpp.
2017-01-29 15:35:02 -06:00
z64555 340b8d3136 Merge pull request #1158 from asarium/fix/shipSelectNullVector
Fix null vector normalization in ship select screen
2017-01-29 15:09:54 -06:00
m!m 39649e9e11 Merge pull request #1156 from MageKing17/cleanup/demo-compatibility
Improves FSO's compatibility with the FS2 Demo data
2017-01-28 20:11:16 +01:00
MageKing17 6bc1e1c3d9 Merge pull request #1161 from asarium/fix/653
Fix double rendering of effect ships
2017-01-26 18:31:28 -08:00
asarium 2997633d0d Fix double rendering of effect ships
This fixes #653.
2017-01-27 00:03:28 +01:00
m!m e0cf1301fa Merge pull request #1160 from chief1983/libupgrade/libpng_1_6_28
libupgrade/libpng_1_6_28: Upgrade libpng to 1.6.28.
2017-01-26 11:11:35 +01:00
m!m ed15b7e551 Merge pull request #1159 from chief1983/libupgrade/zlib_1_2_11
libupgrade/zlib_1_2_11: Update bundled zlib version to 1.2.11.
2017-01-26 11:08:38 +01:00
Cliff Gordon 863604d3a5 libupgrade/libpng_1_6_28: Upgrade libpng to 1.6.28. Fixes several published security vulnerabilities in most older versions. 2017-01-25 16:59:40 -06:00
Cliff Gordon f750a43b87 libupgrade/zlib_1_2_11: Update bundled zlib version to 1.2.11. Fixes a warning in inflate.c on latest clang. See issue #1103. 2017-01-25 16:47:45 -06:00
asarium b13ee73546 Fix null vector normalization in ship select screen
vm_vector_2_matrix was improperly guarded against bad parameters. In the
case I encountered the uvec was the negative of fvec which produced a
null vector when the cross product of the two vector was constructed.

These changes should fix that bug by ignoring the uvec parameter. Since
vm_vector_2_matrix and vm_vector_2_matrix_norm are basically the same, I
converted the former into an alias of the latter and only fixed that
code.
2017-01-25 19:57:07 +01:00
MageKing17 377751ab28 Avoid crashing if certain interface artwork is missing.
Changes a few windows (tech room, campaign room, medal case, and HUD config menu) to issue Warnings instead of Errors if certain pieces of interface art are missing. If their mask bitmap is missing, they automatically close themselves and display the old "Sorry, this feature is available only in the retail version" popup from the demo, allowing FSO to run the demo data without crashing when you click on the wrong button.

It also restores the special demo popup for the campaign room, which allows you to at least restart the demo campaign without deleting and recreating your pilot.
2017-01-24 13:18:42 -08:00
MageKing17 e1d3677f58 Fix bitmap release ordering mistake in medals.cpp.
Initialization of the medal window locks the mask twice (once directly and once indirectly, through set_mask_bmap()), then closing the medal window tries to release it after only unlocking it once. bm_release() will refuse to do anything if the BMPMAN entry is still locked, though, so the first release therefore does nothing, and since it will then only be released once (indirectly, by Medals_window.destroy()) after being loaded twice, the mask stays loaded in memory until FSO exits. By moving the release until after Medals_window is destroyed, the mask should be successfully released when the medals window closes.
2017-01-24 12:03:06 -08:00
MageKing17 559b07da63 Change check for 1024x768 interface art to not check 2_TechShipData-m.
The demo doesn't include techroom art because the demo doesn't have a techroom (or a campaign room, or a HUD config menu), but it still otherwise works with the higher-resolution interface.
2017-01-24 12:03:06 -08:00
MageKing17 b91e3c6ab1 Remove unhelpful assertions from comp_training_lines_by_born_on_date().
If an event with a directive contains both an is-destroyed/is-destroyed-delay for a wing with multiple waves AND the event's Sexp_useful_number is 0 (either the event contains an "is-event-*" SEXP (or one of the "-delay" ones with the optional third argument not set), and that SEXP didn't return true, or some part of the event evaluated to SEXP_CANT_EVAL) AND the wing currently has 0 ships in the mission (so Directive_count gets set to DIRECTIVE_WING_ZERO to mark the directive as being "temporarily" true, until the next wave arrives), then the directive winds up in the list of displayed directives without actually having a born_on_date set, so it fails this assertion. Since this is caused by the data supplied (in the mission) rather than a coding mistake, and since this assertion doesn't actually seem to be guarding against anything (because nothing bad happens if the comparison happens anyway, just with a born_on_date of 0), and it behaves just fine in Release builds where the assertion isn't checked, the simplest solution would seem to be to just remove the assertions altogether.

Found this issue while testing with demo data, so blame whatever Canadian wrote the first demo mission to make the "Destroy Libra" event check for either Libra being destroyed OR an event (that can't ever become true until after at least one wave of Libra gets destroyed) becoming true.
2017-01-24 12:03:06 -08:00
MageKing17 7767fdd933 Make bm_unload() check for a handle of -1.
Somewhat related to the previous commit: if, in the future, we have another instance of trying to unload a nonexistent graphic, it would make much more sense if BMPMAN returned -1 (like it already does for other failure conditions, like trying to unload an unused slot) rather than tripping the "n >= 0" assertion down below (calling with -2 or other negative values that can still trip that assertion unaccounted for, because those would definitely be mistakes in the code).
2017-01-24 12:03:06 -08:00
MageKing17 0bd8754064 Don't try to do anything with a nonexistent Fade_anim.
If Fade_anim.first_frame was -1 (like, for instance, if the animation did not exist, which it doesn't in the demo data), the briefing code would still try to do stuff with it, and then unload it when it closed. This seems like a bad idea in general.
2017-01-24 12:03:06 -08:00
MageKing17 bedfc47273 Make "+Music:" optional in mainhalls.
It defaults to an empty string (resulting in no music) anyway, so there's no harm in it being missing, and the demo's mainhall.tbl doesn't contain these lines, so this change makes it possible to reach the mainhall with demo data.
2017-01-24 12:03:06 -08:00
Fabian Woltermann f376142d57 Merge pull request #1153 from asarium/fix/testCompilation
Fix linking error in unit tests
2017-01-24 14:47:00 +01:00
Cliff Gordon 0cce8fb34c Merge pull request #1054 from asarium/fix/830
Use CMake version in Mac strings file
2017-01-24 07:33:12 -06:00
asarium 5caa85ffa5 Use CMake version in Mac strings file
Fixes #830.
2017-01-23 23:35:14 +01:00
MageKing17 c0c6d4b572 Merge pull request #1152 from asarium/fix/debugWindowFixes
Fix a few minor issues with the new debug window
2017-01-21 13:45:03 -08:00
asarium 7516800c62 Fix default parameter value of gr_flip 2017-01-21 21:56:45 +01:00
asarium cb465d789f Fix linking error in unit tests 2017-01-21 21:48:08 +01:00
asarium 25fa3543f2 Fix a few minor issues with the new debug window
This makes the debug window resizable and also reduces the default size
to ~80% of the used display. This also makes sure that the main window
has input focus after the debug window was created.
2017-01-21 11:48:09 +01:00
niffiwan cb81894632 Merge pull request #1150 from asarium/fix/versionString
Unify version string handling
2017-01-21 10:46:24 +10:00
m!m 18921e720a Merge pull request #1151 from The-E/NoFedoraError
Fixes an assertion due to insufficient amount of hats
2017-01-20 19:03:17 +01:00
m!m 09e18c1164 Merge pull request #1147 from asarium/feature/debugWindow
Reimplement debug window
2017-01-20 18:37:07 +01:00
Fabian Woltermann 637e44d8d2 This would be the correct way to do it 2017-01-20 15:12:23 +01:00
Fabian Woltermann 82ce160093 The logic for joy_down was missing a safety check, which could cause an assertion in Joystick::getHatDownTime if a joystick without a hat (or no joystick at all?) was attached. 2017-01-20 14:31:02 +01:00
asarium 04e5c7e484 Unify version string handling
Currently there are multiple locations in the code where the version is
constructed by printing the individual numbers together. This is mostly
sufficient but it hides information such as the commit hash or the build
name (e.g. RC1). These changes unify that behavior by always using the
version string generated by CMake.
2017-01-20 12:28:47 +01:00
m!m 09586df300 Merge pull request #1037 from asarium/build/macPrebuilts
Use prebuilt libraries for SDL2 framework
2017-01-20 10:47:29 +01:00
m!m 534285324d Merge pull request #1148 from Yarn366/gr_bitmap_offset
Make gr_bitmap obey clip offsets as it did before the OpenGL Core merge
2017-01-19 09:59:28 +01:00
Yarn366 af2514755b Make gr_bitmap obey clip offsets as it did before the OpenGL Core merge 2017-01-18 23:06:43 -05:00
asarium e6dc4d71b6 Add word wrapping 2017-01-18 22:50:14 +01:00
asarium dae0f59911 Add doxygen comments to DebugWindow 2017-01-18 22:17:54 +01:00
asarium c7f523ae46 Add debug window
This allows to show the debug output in a second window in real time.
This system could be expanded further to allow more interactivity but
the current status is good enough.
2017-01-18 18:18:47 +01:00
m!m 288e1ba907 Merge pull request #1146 from Echelon9/fix/documentation-readme
Fixes to better document README.md
2017-01-17 09:59:54 +01:00
Echelon9 d4f15a2f96 Add AppVeyor continuous integration build status to README.md 2017-01-16 19:12:23 -05:00
Echelon9 fb3c70126e Document the means of compiling Debug build with cmake
Compiling a debug build is a frequent developer task, so worth specifying upfront.
2017-01-16 18:36:36 -05:00
m!m a1cae77142 Merge pull request #1145 from niffiwan/fix/consistent_error_keys
Make shortcuts for Warning/Errors consistent
2017-01-15 17:49:31 +01:00
niffiwan 868959499c Make shortcuts for Warning/Errors consistent
LuaError, Error & Warning use RETURN for Exit
LuaError & Warning use ESCAPE for Continue
2017-01-15 10:51:33 +10:00
niffiwan 9ff7df0f71 Merge pull request #1144 from SamuelCho/env_map_fix
Removed unnecessary conditional when making render targets.
2017-01-15 10:16:30 +10:00
niffiwan 692da9d5e2 Merge pull request #1143 from MageKing17/bugfix/timestamp-display-fix
Fix gr_print_timestamp() to actually display timestamps properly.
2017-01-15 09:40:06 +10:00
SamuelCho 2a2c8a5ac3 Removed unnecessary conditional when making render targets. 2017-01-14 15:29:01 -08:00
MageKing17 8bb6861efc Fix gr_print_timestamp() to actually display timestamps properly.
When the function was rewritten as part of the TrueType PR, its logic was also unintentionally changed so that it expected timestamps in milliseconds when everything calling it provides "fix"es, which represent 65536ths of a second.
2017-01-14 13:19:45 -08:00
MageKing17 994e3cf708 Merge pull request #1140 from asarium/fix/1139
Fix off-by-one error in script_state::EvalString
2017-01-07 10:19:25 -08:00
asarium edbddf0fd5 Fix off-by-one error in script_state::EvalString
This also fixes a small inefficiency in sexp_script_eval.
2017-01-07 18:45:23 +01:00
Samuel Cho 3e0fbbbd90 Merge pull request #1113 from asarium/feature/screenTracing
Add previous on-screen profiling readout again
2017-01-06 12:31:07 -08:00
SamuelCho 74a5975afc Fixed events being sorted the wrong way. Fixed profiler history casting int instead of uint64_t. 2017-01-06 19:01:38 +01:00
Samuel Cho 9304a7f137 Merge pull request #1136 from SamuelCho/ambient_behavior_restore
Restore original OGL compatibility ambient light behavior.
2017-01-06 09:49:38 -08:00
SamuelCho ee675a19b5 Restore original OGL compatibility ambient light behavior. 2017-01-05 22:13:31 -08:00
MageKing17 9d92d273e4 Merge pull request #1134 from asarium/cleanup/stringConst
Fix the rest of the string conversion warnings
2017-01-05 05:48:54 -08:00
asarium 06aeb403dd Remove percentage profiling 2017-01-05 10:50:29 +01:00
asarium 14baaf9154 Use event IDs to establish a total event ordering 2017-01-05 10:43:36 +01:00
asarium 609cca7fc0 Enable write-strings warning 2017-01-05 00:16:11 +01:00
asarium 4a9f1a2d56 Fix the rest of the string conversion warnings 2017-01-05 00:15:01 +01:00
MageKing17 5958f9126a Merge pull request #1133 from asarium/cmake_/Wdeprecated
Reenable the deprecated warnings of GCC and Clang
2017-01-04 07:18:19 -08:00
asarium 599e24cf91 Remove unneeded tracing scope 2017-01-04 12:41:32 +01:00
Fabian Woltermann eea97601b5 Merge pull request #1132 from asarium/cleanup/stringConst
More string const correctness fixes
2017-01-04 10:48:58 +01:00
asarium d88f4d6488 Reenable the deprecated warnings of GCC and Clang
This warning isn't caused by our code at the moment so there is no
reason to keep them disabled.
2017-01-04 10:06:50 +01:00
asarium 59dc59c318 Fix compilation error 2017-01-04 09:56:16 +01:00
asarium 7195ec9856 A few more fixes... 2017-01-04 00:28:22 +01:00
asarium f819db3ac5 More string const correctness fixes 2017-01-04 00:12:41 +01:00
Fabian Woltermann 6839d1c3d1 Merge pull request #1130 from asarium/fix/drawListGlobals
Remove usage of a static global variable in draw_list
2017-01-03 15:43:09 +01:00
Fabian Woltermann 91c04a2cfe Merge pull request #1131 from asarium/fix/noGlobalHooks
Remove global hook system and emulate it with conditional hooks
2017-01-03 15:42:55 +01:00
asarium 845276bac3 Remove global hook system and emulate it with conditional hooks
This changes some functionality but it shouldn't cause too many issues
since the previous functionality was kind of a hack anyway.

This also adds a simulation conditional hook that has only been
available through global hooks before.
2017-01-03 10:50:36 +01:00
asarium 1106898454 Remove usage of a static global variable in draw_list
Instead, this uses a lambda function which is better since it doesn't
require storing any global pointers.
2017-01-03 09:43:48 +01:00
Fabian Woltermann 1cb838afe5 Merge pull request #1114 from asarium/feature/pngCallbacks
Use libpng callbacks for reporting errors and memory allocation
2017-01-03 08:46:04 +01:00
Fabian Woltermann dd6e706412 Merge pull request #1125 from asarium/cleanup/stringConst
Fix some string literal conversion warnings
2017-01-03 08:45:51 +01:00
Fabian Woltermann 75df49cd03 Merge pull request #1126 from asarium/fix/evalStringCrash
Fix null pointer usage in EvalString
2017-01-03 08:45:32 +01:00
Fabian Woltermann 87a52efaae Merge pull request #1128 from asarium/fix/scriptCleanup
Clean up Lua function references before destroying the Lua state
2017-01-03 08:44:49 +01:00
Fabian Woltermann 94b6a418c7 Merge pull request #1129 from SamuelCho/model_code_cleanup
Model code cleanup
2017-01-03 08:44:03 +01:00
Samuel Cho 347dca5e60 Renamed draw_list to a more descriptive model_draw_list. Removed unlit maps since those aren't needed anymore. Changed transforms in model_draw_list to use the transform_stack instead of using duplicate code. Removed some unused graphics code. Fixed scaling when using batched transforms. 2017-01-02 20:15:37 -08:00
asarium f7a3d65e0c Clean up Lua function references before destroying the Lua state 2017-01-03 00:19:47 +01:00
asarium 455ffd827a Fix unresolved linking errors 2017-01-02 19:06:59 +01:00
asarium 20cab0c235 Fix null pointer usage in EvalString 2017-01-02 19:04:48 +01:00
Fabian Woltermann 5581ecb643 Merge pull request #1073 from asarium/lua/luaReferences
Add lua references utilities library
2017-01-02 17:55:35 +01:00
asarium 9a8bfc0217 More const correctness 2017-01-02 13:17:59 +01:00
asarium bcf2ddefba Begin fixing string const correctness 2017-01-02 12:29:14 +01:00
asarium ef382c125a Make strings in flag_def_list const-correct. 2017-01-01 22:24:14 +01:00
asarium 1a7e2f42d4 Fix more Clang warnings 2017-01-01 22:13:40 +01:00
asarium 6aaa40fef3 Remove unused boolean flag 2017-01-01 22:13:40 +01:00
asarium 0a5a3a9dd4 Fix GCC warning 2017-01-01 22:13:40 +01:00
asarium aa60444ca4 Add upvalue setting capability to LuaFunction 2017-01-01 22:13:40 +01:00
asarium c4ede0d7ae Use the right constant for an invalid reference 2017-01-01 22:13:40 +01:00
asarium f2b61fb399 Add better iterator interface
Now LuaTable can be used in range-based for loops
2017-01-01 22:13:40 +01:00
asarium 9bab9769e4 Fix warnings 2017-01-01 22:13:40 +01:00
asarium 408101f7eb Add function and table parameter capability
This allows to accept and return function and table parameters from
scripting API functions by using the LuaFunction and LuaTable types.
2017-01-01 22:13:40 +01:00
asarium 0110954518 Add improved lua reference handling
This adds a utility library for handling all the nasty lua referencing
stuff. It also provides functions for convienent usage of lua objects
such as tables and functions which allows to use them directly from C++
code without using the ugly Lua C-API.
2017-01-01 22:13:40 +01:00
Fabian Woltermann 988c61f2e1 Merge pull request #1123 from MageKing17/bugfix/fred-messages-vector
Resize Messages vector before storing messages into it in FRED.
2017-01-01 13:09:13 +01:00
MageKing17 011d74bb4d Resize Messages vector before storing messages into it in FRED.
Not resizing the Messages vector here was leading to a debug error about an out-of-range vector subscript, and who knows what other problems were being caused by overwriting whatever memory was after the Messages vector. There's no equivalent problem when parsing, because as each message is parsed, it gets pushed onto the back of the vector instead of assigned directly to an index.
2016-12-31 21:10:17 -08:00
m!m cf71eda1ad Merge pull request #1122 from MageKing17/feature/beam-collision-groups
Add collision group support to beams.
2016-12-31 12:05:40 +01:00
MageKing17 a6c8af28f2 Add collision group support to beams.
Makes beams inherit their firing ship's collision group if "$Weapons inherit parent collision group:" is enabled, and adds a collision group check to beam/ship collisions (and only beam/ship collisions, since collision groups are only currently checked for ship/ship and ship/weapon collisions).

This shouldn't break any existing mods, since usage of collision groups is surprisingly rare, and so is usage of weapons inheriting their parent's collision groups, and this change should only affect mods that do both at the same time; from a (very quick, non-representative) survey of modders, it's entirely possible that the mod requesting this change is the only one that does so (theoretically, there could be a mod out there that uses scripting to explicitly set the collision group of a beam object, but if they did so and then relied on it not actually doing anything, that's incredibly silly of them).
2016-12-30 23:39:07 -08:00
MageKing17 14704a3415 Merge pull request #1121 from asarium/fix/luaTesting
Fix definition of scripting testing library
2016-12-30 22:19:10 -08:00
asarium 9bbff82c73 Fix definition of scripting testing library
Also fixed an unresolved external error.
2016-12-30 22:56:52 +01:00
m!m ce30c433ba Merge branch 'master' into feature/screenTracing 2016-12-30 22:36:53 +01:00
Fabian Woltermann 04da71448f Merge pull request #1120 from asarium/lua/graphics
The final batch of scripting API movements
2016-12-30 20:55:06 +01:00
asarium c17dcb1835 Move source files into category directories 2016-12-30 19:13:39 +01:00
asarium 6e5531adcc IT IS DONE! Moved testing library into separate file 2016-12-30 18:59:19 +01:00
asarium ad6ab9b95b Move tables scripting library into separate file 2016-12-30 18:52:34 +01:00
asarium ad6cbfb328 Move mission scripting library to separate file 2016-12-30 18:48:21 +01:00
asarium 9b8b7e0dce Move Hook variables library into separate folder 2016-12-30 18:33:02 +01:00
asarium 1cb5dbf99b Add include for the hud library 2016-12-30 18:24:59 +01:00
Fabian Woltermann f08f72c90a Merge pull request #1119 from asarium/lua/weapon
Move the rest of the scripting classes into separate files
2016-12-30 14:55:35 +01:00
asarium 46116362c5 Move graphics scripting library into separate file 2016-12-30 12:57:03 +01:00
asarium 98e8a0f041 Remove ade_api.cpp since it has no content 2016-12-30 12:40:58 +01:00
asarium 8cd3352af7 Fix test compilation 2016-12-30 12:33:32 +01:00
asarium 2c85c93136 Move hud scripting library into separate file 2016-12-30 12:33:32 +01:00
asarium 9251ec56ce Move controls scripting library to separate file 2016-12-30 12:33:32 +01:00
asarium deff6c9ec1 Remove now unused lua.h file 2016-12-30 12:33:32 +01:00
asarium 3fa4a8dbdc Move cfile scripting library into separate file 2016-12-30 12:33:32 +01:00
asarium bf2d996bd0 Move base scripting library to separate file 2016-12-30 12:33:32 +01:00
asarium 79709b2372 Move audio library into separate file 2016-12-30 12:33:32 +01:00
asarium 584b9cadd7 Move particle scripting class into separate file 2016-12-30 12:33:32 +01:00
asarium 2f1057f3c3 Move control_info scripting class into separate file 2016-12-30 12:33:32 +01:00
asarium 374bcacddd Move camera scripting class into separate file 2016-12-30 12:33:32 +01:00
asarium 94c7fbda6b Move player scripting class into separate file 2016-12-30 12:33:32 +01:00
asarium a049152e99 Move beam scripting class into separate file 2016-12-30 12:33:32 +01:00
asarium 7686163957 Move weapon scripting class into separate file 2016-12-30 12:33:32 +01:00
Fabian Woltermann ca62bd67ed Merge pull request #1111 from asarium/lua/order
And another batch of lua scripting class movements
2016-12-30 12:22:05 +01:00
Samuel Cho ac2b864aaa Merge pull request #1117 from The-E/Mantis3182
Don't do autorepair if we're already dead
2016-12-29 23:59:44 -08:00
Samuel Cho 1904330ebb Merge pull request #1116 from The-E/parse_object_flag_fix
Fix for #1115
2016-12-29 23:59:24 -08:00
Fabian Woltermann 876922c547 Don't do autorepair if we're already dead 2016-12-29 21:17:36 +01:00
m!m 4e0a879c4b Merge pull request #1084 from Yarn366/fiction_viewer_character_conversion
Fiction viewer character conversion
2016-12-29 17:58:24 +01:00
Fabian Woltermann b258a1d159 this needs to be an underscore 2016-12-29 16:54:59 +01:00
Fabian Woltermann df33974f88 The "no collide" parse object flag needs to be written as "no_collide" in the flags list, and the "no-disabled-self-destruct" flag needs to be parsed 2016-12-29 16:30:55 +01:00
asarium 8221bc3f04 Process frame profile data at end of frame
This matches what was done before the removal more closely so hopefully
the results will be the same or at least similar.
2016-12-29 12:29:55 +01:00
asarium 82750b238a Fix Assertion when events have the same timestamp
The timers on Windows apparently have a lower resolution than Linux
which causes issues with overlapping events. These changes apply an
offset to all timestamps if the same timestamp is detected while
processing the buffered events.
2016-12-29 00:44:59 +01:00
niffiwan 6b0ad43fb6 Merge pull request #1109 from asarium/fix/nightlyWarnings
Fix warnings in nightly builds
2016-12-29 07:19:40 +10:00
Yarn366 d55451195e Merge pull request #1 from asarium/fiction_viewer_character_conversion
Add const specifiers where possible
2016-12-28 15:16:47 -05:00
asarium 9cff51b6bb Use utility function for lua target 2016-12-28 17:55:56 +01:00
asarium 771eb9c875 Use included libraries when doing CI builds
This should make sure that nightly builds should fail less often.
2016-12-28 17:55:15 +01:00
asarium 12fec3026b Suppress warnings for all third-party libraries 2016-12-28 17:55:15 +01:00
asarium df80f64598 Add const specifiers where possible 2016-12-28 17:47:46 +01:00
asarium ada29fd266 Add previous on-screen prifiling readout again
This is basically the old code but it has been ported to the new tracing
system.

There is still some weirdness with the percentages but I have no idea
where that comes from since I don't know the code.
2016-12-28 10:30:38 +01:00
niffiwan 07ad4cf2e0 Merge pull request #1110 from asarium/fix/luaWarnings
Use the correct Lua defines for Linux and Mac
2016-12-28 12:23:17 +10:00
asarium c07cfc7210 Use memory allocation callbacks 2016-12-27 14:15:44 +01:00
asarium c3243cc243 Use the libpng callbacks to log the warnings to the debug log 2016-12-27 14:10:47 +01:00
m!m 2d52ffa2a4 Merge pull request #1112 from SamuelCho/anim_alpha_channel_fix
Use user defined alpha regardless of if blend filter is on.
2016-12-26 22:42:33 +01:00
Samuel Cho f2156292e4 Use user defined alpha regardless of if blend filter is on. 2016-12-26 11:07:40 -08:00
asarium 4cb0ca42e3 Move ship scripting class into separate file 2016-12-26 15:16:15 +01:00
asarium 3737249459 Move wing scripting class to separate file 2016-12-26 15:00:52 +01:00
asarium fecca89447 Move message scripting classes into separate file 2016-12-26 14:40:53 +01:00
asarium 080e40d1da Move sound scripting classes into separate file 2016-12-26 14:27:14 +01:00
asarium 4c77bc7edf Move CockpitDisplays scripting class into correct file 2016-12-26 14:14:52 +01:00
asarium 334e9d4abf Move ShipTextures scripting class into separate file 2016-12-26 14:12:31 +01:00
asarium b1404d8bbf Move order scripting classes into separate file 2016-12-26 14:02:17 +01:00
asarium 6fd62e6ebd Use the correct Lua defines for Linux and Mac
This fixes the warning that tmpnam shouldn't be used anymore.
2016-12-26 12:59:47 +01:00
Fabian Woltermann f01730e722 Merge pull request #1107 from asarium/lua/waypoint
Move more scripting classes into separate files
2016-12-26 12:49:25 +01:00
niffiwan d4bd640280 Merge pull request #1108 from SamuelCho/anim_alpha_channel_fix
Fix for incorrect alpha channel detection for animations.
2016-12-26 20:05:58 +10:00
Samuel Cho 4e053b234b Made sure bm_create sets a value for true_bpp so alpha channel can be correctly detected for blending in animations. 2016-12-26 00:16:09 -08:00
asarium 6b9b2a45ab Move subsystem scripting class into separate file 2016-12-25 19:09:47 +01:00
asarium 698e49d595 Move weapon bank scripting classes into own files 2016-12-25 18:49:12 +01:00
asarium 15886a64b1 Move waypoint classes into separate file 2016-12-25 18:33:03 +01:00
Fabian Woltermann d4844ab7ed Merge pull request #1106 from asarium/lua/mcInfo
Another batch of scripting class movement
2016-12-25 15:27:45 +01:00
Fabian Woltermann 94721d06de Merge pull request #1100 from asarium/feature/monitorRevival
Integrate the existing monitor system into the new tracing system
2016-12-25 15:26:52 +01:00
asarium 417b12129d Move debris scripting class into separate file 2016-12-25 13:08:43 +01:00
asarium fc391736ec Move shipclass and cockpit display classes into separate files 2016-12-24 23:51:25 +01:00
asarium c42fc4fc6f Move asteroid scripting class into separate file
This also adds a macro for specifying from which class a scripting class
derives.
2016-12-24 19:36:42 +01:00
asarium 4360340bd4 Move object scripting class into separate file 2016-12-24 19:08:08 +01:00
asarium 72ffa6a052 Move mc_info scripting class into own folder 2016-12-24 18:04:44 +01:00
Fabian Woltermann 2fc8a12138 Merge pull request #1105 from asarium/fix/fixShaderAgain
Readd accidentially removed lines to shader code
2016-12-23 14:27:51 +01:00
Fabian Woltermann 842076e3b9 Merge pull request #1104 from SamuelCho/blending_fix
Blending fixes for interface materials.
2016-12-23 14:27:23 +01:00
asarium 44cac0de49 Readd accidentially removed lines to shader code 2016-12-23 10:39:07 +01:00
SamuelCho 2dc097ecb6 Return interface materials to use the standard blending selection function. Make sure we set the appropriate alpha for interface materials depending on if we're additive or alpha blended. 2016-12-22 23:15:43 -08:00
Fabian Woltermann 966bc0a0b9 Merge pull request #1101 from asarium/lua/shiptype
Move more scripting classes into separate files
2016-12-22 12:52:24 +01:00
Fabian Woltermann 03d81a7429 Merge pull request #1096 from asarium/build/iteratorDebugLevel
Disable iterator debugging for FastDebug
2016-12-22 12:51:27 +01:00
asarium d6a556cd31 Move weaponclass scripting file into separate file 2016-12-21 17:57:26 +01:00
asarium 1c36ff40ba Move material scripting class into separate file 2016-12-21 17:52:05 +01:00
asarium 60fc558a3b Move texture scripting class into separate file 2016-12-21 17:42:59 +01:00
asarium ce5dfe148d Move streaminganim scripting class into separate file 2016-12-21 17:37:26 +01:00
asarium 9a8e3ba09c Move team scripting class into own file 2016-12-21 17:30:39 +01:00
asarium 06066e0c52 Move species scripting class into own file 2016-12-21 17:25:14 +01:00
asarium f10cee9f58 Move shiptype scripting class into own file 2016-12-21 16:47:23 +01:00
asarium 6922d3ca2c Integrate the existing monitor system into the new tracing system
This writes the monitor updates as counter events into the event trace
file.
2016-12-21 16:10:01 +01:00
Fabian Woltermann a10b403748 Merge pull request #1095 from asarium/fix/beamHook
Fix scripting hook object parameter
2016-12-21 15:49:19 +01:00
Fabian Woltermann 6c1a55644e Merge pull request #1097 from asarium/lua/physics
Move a few scripting classes into their own files
2016-12-21 15:48:46 +01:00
Fabian Woltermann 64f5554c90 Merge pull request #1099 from asarium/gl/shaderVersion
Remove unnecessary __VERSION__ usages in shaders
2016-12-21 15:47:37 +01:00
asarium c2a368534f Remove unnecessary __VERSION__ usages in shaders
The previous usages were always true since we require a more recent GLSL
version now.
2016-12-21 12:16:18 +01:00
asarium 9274925ddf Disable iterator debugging for FastDebug
This is a feature for developers that is not needed in FastDebug builds.
This should speed up these builds a bit since iterator debugging causes
quite a performance penalty.
2016-12-20 19:25:42 +01:00
asarium 5725562435 Improve logic for determining legacy mode
Now it will also check if the old config location exists and if it
doesn't then the new config mode will be used by default. This should
fix #858.
2016-12-20 17:59:41 +01:00
asarium 5f6fe0288c Move shields scripting class to separate file 2016-12-20 17:58:27 +01:00
asarium d5973346ec Move sexpvar scripting class 2016-12-20 17:58:27 +01:00
asarium c23c65596f Move physics_info scripting class into own file 2016-12-20 17:58:26 +01:00
asarium 7e1ca2ce51 Fix scripting hook object parameter
It was using the object pointer of the User before which is not correct
since the object pointer of the beam is needed.
2016-12-20 17:57:43 +01:00
Fabian Woltermann ba1674a9d3 Merge pull request #1090 from asarium/fix/extraGccWarnings
Enable extra GCC and Clang warnings again
2016-12-20 17:52:10 +01:00
MageKing17 fb4e20e364 Merge pull request #1094 from asarium/fix/1092
Initialize ffmpeg when starting FRED
2016-12-16 13:42:05 -08:00
asarium 911302c918 Initialize ffmpeg when starting FRED
This fixes #1092.
2016-12-16 19:24:35 +01:00
m!m 2d387c4b6a Merge pull request #1093 from MageKing17/bugfix/fire-secondary-scripting-fix
Make ship_fire_secondary() call into the scripting engine earlier.
2016-12-16 14:59:54 +01:00
MageKing17 d8e7b95e07 Make ship_fire_secondary() call into the scripting engine earlier.
Swaps the order of the scripting call block and the cycle-to-next-bank-if-out-of-ammo block so that e.g. "$On Weapon Fired:" scripts for a specific weapon type (which checks the currently-selected bank) will work properly when firing the last missile in the bank. Fixes issue #1091.
2016-12-15 18:03:11 -08:00
asarium 5e23c5d5e1 Fix Visual Studio 2015 compiler bug 2016-12-14 20:11:43 +01:00
asarium 40d9cc3293 Remove unused function 2016-12-14 11:56:15 +01:00
asarium d191b6cedc Remove unused class 2016-12-14 11:53:57 +01:00
asarium b13c816ecb Fix missing braces warnings 2016-12-14 11:31:35 +01:00
asarium 3b0866bfe1 Fix braces warnings 2016-12-14 11:29:47 +01:00
asarium 95e0b6fe6a Remove now unused variables and function from GL_State 2016-12-14 11:27:19 +01:00
asarium 4cf8a32c1e Fix braces warning 2016-12-14 11:24:51 +01:00
asarium e04fc5edb7 Fix move warning 2016-12-14 11:21:12 +01:00
asarium ef4431e8b1 Enable extra warnings for Clang 2016-12-14 11:20:58 +01:00
asarium 865946b97d Fix misleading indentation warning 2016-12-14 11:15:21 +01:00
asarium b024d8f44a Fix unused variable warning 2016-12-14 11:14:54 +01:00
asarium 1d3f2c1da8 Fix unused variable warning 2016-12-14 11:14:19 +01:00
asarium 49bb57478c Fix misleading indentation warning 2016-12-14 11:13:47 +01:00
asarium 278c78e4f4 Fix unused variable warning 2016-12-14 11:13:23 +01:00
asarium 0ba4e49106 Fix signed/unsigned warnings 2016-12-14 11:12:25 +01:00
asarium 789c13f792 Fix misleading indentation warnings 2016-12-14 11:10:23 +01:00
asarium 667e257d64 Remove unused variable 2016-12-14 11:08:19 +01:00
asarium 3f7728d328 Fix member initialization order of model_material
Since there are so many member I decided it would be better to use the
new member assignment syntax since that automatically guarantees the
right initialization order.
2016-12-14 11:06:15 +01:00
asarium 3fb6b7c51c Fix member initialization order of polymodel 2016-12-14 11:05:51 +01:00
asarium 16e428c5ae Enable extra warnings again 2016-12-14 11:05:37 +01:00
m!m 04dcb4cf60 Merge pull request #1089 from jg18/fix_ml_string
Fix double newlines in multi.log caused by ml_string()
2016-12-14 10:53:34 +01:00
jg18 2de73b50fe Fix double newlines in multi.log caused by ml_string()
Remove extra \n that was added in ml_string().
2016-12-13 23:50:12 -08:00
m!m 04541c7e27 Merge pull request #1088 from MageKing17/fix/joystick-hat-assumption
Make joy_down_time() and joy_down_count() check current->numHats().
2016-12-10 21:41:23 +01:00
MageKing17 514a90805d Make joy_down_time() and joy_down_count() check current->numHats().
Before, they were assuming any joystick had at least 1 hat; this way, they now treat it similarly to buttons. If requesting the status of a button the joystick doesn't have, they return 0. If the joystick doesn't have a hat, querying a hat position will likewise now also return 0. This code will obviously need changed when we get around to proper (e.g. multiple) hat support.
2016-12-10 11:08:04 -08:00
MageKing17 0e66e63086 Fix for Mantis 3187.
When this line was converted by the bitset flags PR, it was accidentally changed from setting the flag to reading the flag, making it a do-nothing line and causing the flag to be cleared on mission load.
2016-12-10 00:18:20 -08:00
MageKing17 da58874390 Merge pull request #1086 from asarium/fix/parseCatch
Add catch clauses everywhere where parselo is used
2016-12-09 07:49:33 -08:00
asarium 52aa0ac031 Add catch clauses everywhere where parselo is used
Before, if any parsing call failed it would throw an exception which
would have been propagated to the exception handler in main() which
terminates the program. This should fix that.
2016-12-09 10:46:51 +01:00
MageKing17 80511c9337 Merge pull request #1085 from Goober5000/jettison_cargo
jettison-cargo sexp
2016-12-08 14:51:00 -08:00
Goober5000 4e922b976e tweak variable per comments 2016-12-08 00:00:44 -05:00
m!m bfe496e22a Merge pull request #1082 from TheMatthew/tracing
timer: Increase precision of timer as well as reducing potential of o…
2016-12-07 10:39:49 +01:00
Goober5000 1a898ac834 jettison-cargo sexp
Upgrades and deprecates the original jettison-cargo-delay sexp by removing the unused delay parameter and adding a new parameter to control the speed of jettisoning.  It further fixes the physics calculations by using the dockpoint normal instead of the vector between the center of the host ship to the center of the cargo.

See also the thread on HLP: http://www.hard-light.net/forums/index.php?topic=92844.0
2016-12-04 21:31:52 -05:00
Matthew Khouzam b5b4a88775 timer: Increase precision of timer as well as reducing potential of overflows.
This creates a factor that is used to multiply the timestamp. It will
overflow less, (once every 300 years or so) and not lose as much precision
as the previous implementation.

The performance is slightly improved, there are no more branches and one
floating point multiply.

Note: this relies on long double having a 64 bit mantissa. This is the
case on x86 Windows, Linux, and Mac OS. However, it is unconfirmed to
work on other architechtures.

Signed-off-by: Matthew Khouzam <[email protected]>
2016-12-04 05:44:02 -05:00
Yarn366 73cd575ea1 Merge branch 'master' of https://github.com/Yarn366/fs2open.github.com into fiction_viewer_character_conversion 2016-12-01 03:44:37 -05:00
Yarn366 bff65254a1 Added character conversion to fiction viewer text to allow accented characters and such to display properly, provided that an appropriate font is in use. 2016-12-01 03:43:59 -05:00
Fabian Woltermann be27e65df2 Merge pull request #1081 from asarium/lua/moveModel
Move model scripting class into own file
2016-11-30 13:16:22 +01:00
Fabian Woltermann 2e7cfc5cf1 Merge pull request #1083 from DahBlount/fix/dont_spawn_if_shot
Fix Don't Spawn If Shot
2016-11-30 13:15:53 +01:00
DahBlount 4a3287457d Fix Don't Spawn If Shot 2016-11-29 11:54:43 -07:00
m!m e07f3a41cb Merge pull request #539 from z64555/cleanup/shield_refactor
Cleanup/shield refactor
2016-11-27 21:46:26 +01:00
z64555 b4a628b3e5 Merge pull request #1015 from asarium/feature/betterTracing
Refactor tracing subsystem. Removes on-screen profiling printouts in favor of using third-party viewers (such as chrome's viewer and spacecompass)
2016-11-27 13:24:54 -06:00
niffiwan d2ee8e873b Merge pull request #1070 from asarium/cmake_/sanitizeUndefined
Add option for enabling -fsanitize=undefined
2016-11-27 12:47:59 +10:00
asarium eb6295e375 Move model scripting class into own file
This also includes the various associated classes.
2016-11-26 14:21:47 +01:00
z64555 cc774b83d4 Rename Goober's factor to shield_scale_factor and change its type to a float. 2016-11-25 16:16:24 -06:00
z64555 020c7e70fd Use correct abs function. 2016-11-25 15:12:12 -06:00
z64555 f4b455dd98 Replace apply_damage_to_shield() with shield_apply_damage().
Also remove a declaration of shield_get_max_quad() in object.h
2016-11-25 15:12:09 -06:00
z64555 b0d9c53688 Remove duplicate function get_max_shield_quad() 2016-11-25 15:07:37 -06:00
z64555 b30a801f25 (Safety) Add asserts to all functions that use an objp.
(Perf) Add early bail-outs to some functions that could be called on non-ship objects
2016-11-25 15:05:40 -06:00
z64555 260673fcea Remove unused variables. 2016-11-25 15:04:11 -06:00
z64555 6f0888e30b Combine shield transfers from AI and Players into one code path
Fixed an Assert()
2016-11-25 15:04:08 -06:00
z64555 0a81104723 AI and Player shield balancing now share same codepath. 2016-11-25 15:01:28 -06:00
z64555 4cd9c847f3 Implemented shield_balance 2016-11-25 10:42:39 -06:00
z64555 14c4e553dd Doxy and organize objectshield functions. Declared shield_balance. 2016-11-25 10:42:37 -06:00
Fabian Woltermann 2cf4f7e4e7 Merge pull request #1078 from asarium/lua/functionMovement
Move gamestate, hudgauge, and eye scripting classes into own files
2016-11-25 16:32:29 +01:00
Fabian Woltermann 09b76c601a Merge pull request #1079 from asarium/fix/glslWarnings
Fix a few Mesa warnings in the shader code
2016-11-25 16:31:22 +01:00
asarium 173d41522e Fix a few Mesa warnings in the shader code
GL_EXT_gpu_shader4 is part of the GLSL 1.50 language standard so the
FXAA shader doesn't need to check against that. I also added a
conditional define for FXAA_GATHER4_ALPHA if the GLSL version supports
it which is the case when it's >= 4.00.

The other issue was a minor change from inout to out where Mesa
complained that the target variable might not have been initialized.
2016-11-25 11:02:26 +01:00
asarium d64196eff0 Refactor tracing subsystem
The new design is centered around the Event Trace JSON format but it
should still be possible to adapt it for other profiling tools. The old
profiling system has been removed.
2016-11-24 10:26:21 +01:00
asarium 45fa09d9cb Move eye scripting class into own file 2016-11-23 18:57:52 +01:00
asarium 2e1d2116b1 Move hudgauge scripting class 2016-11-23 18:50:21 +01:00
asarium a17249eef6 Move gamestate scripting class 2016-11-23 18:45:01 +01:00
Fabian Woltermann 1ce3b3486d Merge pull request #1072 from asarium/lua/functionMovement
Move even more scripting classes into own files
2016-11-22 14:21:00 +01:00
Fabian Woltermann 404b205f31 Merge pull request #1076 from z64555/fix/issue_965a
Actually Fixes Issue 965.
2016-11-22 14:19:14 +01:00
MageKing17 a2ea205239 Merge pull request #1075 from z64555/fix/issue_1097
Fixes issue #1097:
2016-11-20 22:27:26 -08:00
z64555 b9d98a3aa3 Adds scripting support for VM_CAMERA_LOCKED and VM_CENTERING. VM_EXTERNAL_CAMERA_LOCKED is now a soft-state that is equal to (VM_EXTERNAL && VM_CAMERA_LOCKED) 2016-11-20 19:38:23 -06:00
z64555 5990dbce08 Actually Fixes Issue 965.
Previous fixed used a logical NOT (!) instead of a bitwise NOT (~), derp!
In addition, the LE_VM_INTERNAL state now ignores VM_CENTERING, so it won't go false if the camera is returning to center.
2016-11-20 19:30:43 -06:00
z64555 de12c0ae0c Fixes issue #1097:
primative_batch_buffer:desired_buffer_size was not properly initialized in vc120 compilers during debugging. Default constructors proved insufficient, and std:map::operator[] seems to ignore them anyway. This fix gets around that by explicitly clearing desired_buffer)size from within batching_init_buffer()
2016-11-20 16:01:50 -06:00
asarium 69db392407 Move gameevent scripting class into own file 2016-11-14 23:39:47 +01:00
asarium a43429f658 Move font scripting class into own file 2016-11-14 23:28:39 +01:00
asarium 32b2ed5093 Move file scripting class into own file 2016-11-14 22:51:03 +01:00
asarium 4ca0f86c74 Move event scripting class own file 2016-11-14 22:47:25 +01:00
Fabian Woltermann 8fffa4b5e9 Merge pull request #1040 from asarium/lua/enums
Move sripting enums to own file
2016-11-14 22:13:02 +01:00
m!m aa1bc354cb Merge pull request #1071 from MageKing17/bugfix/repair-subsystem-submodel-fix
Make repair-subsystem/set-subsystem-strength fix submodels by default.
2016-11-14 21:47:04 +01:00
MageKing17 b42fb9c97c Make repair-subsystem/set-subsystem-strength fix submodels by default.
When this functionality was added in commit 0662cb6959 it made an explicit check to see if the node was -1, and if so (meaning the node is not present), defaulted the value to true; a month later commit 57c4855e25 "simplified" this to a single is_sexp_true() call, which returns false if the node isn't present... but the documentation still claimed that the default value was true.

Ten years later, and Axem wanted to know why his submodel wasn't being fixed by the repair-subsystem SEXP. I don't know if this is the first time in ten years anybody's wanted to use repair-subsystem on a destroyable submodel, or if everyone was just assuming it worked as intended and never noticing it didn't; regardless, while the "simple" solution would seem to be to fix the documentation (since the current behavior has been the actual behavior for almost as long as the feature has existed), it seems unlikely that there would be many unintended consequences of just fixing submodels by default, and if anyone has used these SEXPs in the intervening ten years, it was probably under the assumption that they worked as the documentation claimed.
2016-11-13 15:55:44 -08:00
asarium c7ae91edef Add option for enabling -fsanitize=undefined
There are a few issues I found with this option which should probably be
fixed.
2016-11-13 22:37:28 +01:00
MageKing17 9f60839faf Merge pull request #1065 from z64555/fix/issue_965
Fixes issue #965 by making the VM_INTERNAL view state ignore the camera lock bit
2016-11-06 20:57:55 -08:00
z64555 9d859066f7 Let LE_VM_INTERNAL ignore the state of VM_CAMERA_LOCKED, which should have gr.hasViewMode(VM_INTERNAL) return TRUE again. 2016-11-04 20:57:13 -05:00
m!m 6b3d5b39ba Merge pull request #1063 from PeterMitsis/dead-code-elimination
cmake, gcc: Enable garbage collection
2016-11-04 10:21:05 +01:00
Peter Mitsis 9fd95d8ba6 cmake, gcc: Enable garbage collection
Enable compiler and linker garbage collection to eliminate dead
code from the final image.

Signed-off-by: Peter Mitsis <[email protected]>
2016-11-01 11:56:47 -04:00
m!m b5258c494a Merge pull request #1060 from niffiwan/coverity/1365316
Fix Coverity 1365316
2016-10-30 22:21:08 +01:00
niffiwan b8826835e2 Fix Coverity 1365316
Move check for -1 to before we use weapon_index as an array index :)
Also fixes coverity 1365315; which seems like a redundant issue...
2016-10-30 22:43:21 +10:00
Fabian Woltermann c930d1a32e Merge pull request #1058 from asarium/fix/carriageReturn
Ignore Carriage return characters when rendering strings
2016-10-23 10:24:04 +02:00
m!m 18e63d9700 Merge pull request #1057 from X3N0-Life-Form/config_tbl
More file types for data/config
2016-10-22 19:30:14 +02:00
asarium dfd04a45fe Ignore Carriage return characters when rendering strings
Since Windows line endings include this character it needs to be ignored
since the text rendering would display it as an unknown character
otherwise.

This was reported by @AxemP.
2016-10-22 16:16:59 +02:00
MageKing17 7b79b04bad Merge pull request #1056 from asarium/cleanup/cdCheck
Remove old CD code
2016-10-21 12:39:54 -07:00
X3N0-Life-Form 20a22e6a31 add .tbl, .tbm, .xml and .csv to the list of supported /config file types 2016-10-21 20:21:53 +02:00
asarium c409dde698 Remove old CD code 2016-10-21 17:35:15 +02:00
m!m 302192f7fe Merge pull request #1055 from PeterMitsis/absolute-values
Absolute values
2016-10-21 13:03:53 +02:00
Fabian Woltermann 8885bb0c35 Merge pull request #1048 from asarium/fix/casecmp
Cleanup case insensitive string comparision
2016-10-17 09:59:13 +02:00
Fabian Woltermann cdf6a21276 Merge pull request #1049 from asarium/test/safe_strings
Move safe strings tests to unit tests
2016-10-17 09:57:40 +02:00
Fabian Woltermann b2ca49edfe Merge pull request #1053 from asarium/fix/timeroverflow
Fix timestamp overflow check
2016-10-17 09:48:55 +02:00
asarium eda4cdffa7 Fix timestamp overflow check 2016-10-17 09:16:01 +02:00
MageKing17 1d77af86e7 Merge pull request #1052 from Goober5000/fix_issue_1050
fix reversal of toggle caused by flag -> enum conversion
2016-10-16 19:54:03 -07:00
Goober5000 ae49a7ca24 fix reversal of toggle caused by flag -> enum conversion 2016-10-16 22:21:33 -04:00
m!m c321432392 Merge pull request #1047 from niffiwan/fix/max_shield_recharge
Fix issues with $Max Shield Recharge
2016-10-16 14:09:42 +02:00
asarium d2204fdb11 Move safe strings tests to unit tests 2016-10-16 13:40:23 +02:00
niffiwan 7b324b7153 Keep Appveyor happy 2016-10-16 20:14:30 +10:00
asarium f00ca7c7f9 Only enable "errors are warnings" on project sourcce code 2016-10-16 11:54:43 +02:00
niffiwan bf21913708 Updates to max shield recharge fix
Use a helper function in appropriate places, add comments where not
Avoid a potential div/0 & add Assertion to shield_get_max_strength
2016-10-16 16:31:11 +10:00
asarium 92cb2140aa Replace _isnan with std::isnan 2016-10-15 19:37:18 +02:00
asarium 599260f2e5 Use platform checks to determine case compare function 2016-10-15 19:37:18 +02:00
niffiwan 4c44934d7a Fix issues with $Max Shield Recharge
Fix unlimited transfer of energy to shields (energy lost)
Fix thresholds in ai balance shields, rearm timer & call4help
Fix scaling in shield pain flash
Fix variable number of shield segments in shield pain flash
Lastly includes formatting tidy-up in shield pain flash
2016-10-15 20:01:07 +10:00
Fabian Woltermann b08d6c9837 Merge pull request #1042 from asarium/fix/ffmpegCompat
Add compatibility code for older FFmpeg versions
2016-10-15 10:04:10 +02:00
Fabian Woltermann ce5badaf78 Merge pull request #1039 from asarium/fix/960
Fix wrong negation in HudGaugeExtraTargetData
2016-10-15 10:03:37 +02:00
Fabian Woltermann 2c18b8129c Merge pull request #1043 from asarium/fix/1038
Fix TTF rendering on cockpit displays
2016-10-15 10:03:14 +02:00
m!m 83e95705ea Merge pull request #1046 from niffiwan/fix/1044
Fix mprintf format strings in apng code
2016-10-15 10:01:39 +02:00
niffiwan fd7f291b87 Fix mprintf format strings in apng code
See #1044
2016-10-15 08:21:28 +10:00
asarium 1d16bb2a04 Fix TTF rendering on cockpit displays
I needed to disable backface culling but I don't think it actually
matters.

Fixes #1038.
2016-10-14 18:39:24 +02:00
asarium 2bf5828c17 Add compatibility code for older FFmpeg versions 2016-10-14 17:06:42 +02:00
Fabian Woltermann bd5fb3896b Merge pull request #1035 from asarium/feature/videoInfoOutput
Add option for showing video debug informations
2016-10-14 09:53:50 +02:00
asarium a42e9ff90f Move Enums to own file
Also added unit tests to check if enums exist and work as intended.
2016-10-14 09:50:30 +02:00
Fabian Woltermann 2a4dded277 Merge pull request #1036 from asarium/lua/docSort
Move BitOps scripting library into own file
2016-10-14 09:49:43 +02:00
asarium 45e374221c Fix wrong negation in HudGaugeExtraTargetData
This fixes #960. The flagsets patch negated the flyable logic but this
one spot was missed when negating the conditions.
2016-10-14 09:44:38 +02:00
asarium b4f37f46cc Make semicolon manditory after definition and declaration 2016-10-13 12:22:47 +02:00
asarium ecd7f61956 Sort the scripting documentation entries 2016-10-13 12:22:47 +02:00
asarium 11483057e5 Add unit tests
This also fixes the toggleBit function which was broken until now.
2016-10-13 12:22:47 +02:00
asarium 4382b577ae Move BitOps scripting library into own file 2016-10-13 12:22:47 +02:00
Fabian Woltermann fe6fafdbfb Merge pull request #1008 from asarium/lua/vecmathApi
Move vecmath scripting functions into own file
2016-10-13 12:22:08 +02:00
asarium 20e36e8190 Add option for showing video debug informations. 2016-10-13 12:11:29 +02:00
asarium 65d0576a91 Use prebuilt libraries for SDL2 framework 2016-10-13 11:58:10 +02:00
asarium b3a342c796 Change video rendering so that text can be rendered 2016-10-13 10:38:47 +02:00
niffiwan 7e35461c08 Merge pull request #1034 from DahBlount/LUA/DescriptionFix
Fix isWeaponUsed Description
2016-10-13 15:00:46 +10:00
DahBlount 0a22d601fd Fix isWeaponUsed Description 2016-10-12 18:59:02 -06:00
niffiwan 4f4832f67f Merge pull request #1033 from DahBlount/LUA/WeaponPageIn
Add isWeaponUsed scripting function
2016-10-13 09:23:24 +10:00
DahBlount 214b2dc053 Fix comments, arguments, and initialize some vars 2016-10-12 15:10:42 -06:00
DahBlount c323917db9 Splits up isWeaponUsed into two functions 2016-10-12 14:18:08 -06:00
DahBlount 5575e65eb6 Add isWeaponUsed scripting function 2016-10-12 14:18:08 -06:00
Fabian Woltermann a410654575 Merge pull request #1032 from asarium/fix/cutscenePlayback
Fix a few cutscene playback issues
2016-10-12 20:57:20 +02:00
asarium ea17916de7 Fix video cutscene timing
Also includes a few other minor fixes
2016-10-12 17:45:01 +02:00
asarium db8abecc68 Log FFmpeg warnings in debug builds instead of only errors 2016-10-12 17:44:19 +02:00
asarium 621e1692c9 Improve FFmpeg error handling 2016-10-12 17:44:02 +02:00
asarium aa5447c072 Actually do what the comment says 2016-10-12 17:43:17 +02:00
niffiwan 280c275c4e Merge pull request #1031 from asarium/fix/wavefileExtension
Remove extension from a filename passed to WaveFile::Open
2016-10-12 21:20:50 +10:00
m!m 5ed2b6070e Merge pull request #1026 from The-E/ship_flag_sexp_fix
Fixes a few instances of using the wrong overload for sexp_deal_with_ship_flag
2016-10-12 12:42:57 +02:00
asarium a614a8ecfc Remove extension from a filename passed to WaveFile::Open
This fixes #1029. Special thanks to @AxemP for providing a test mod for
reproducing the bug.
2016-10-12 11:53:25 +02:00
Fabian Woltermann b5eca62785 Merge pull request #1030 from SamuelCho/specGlossAndAOFix
Fixed reflectance maps and ambient/cavity maps not being used
2016-10-12 11:38:45 +02:00
Fabian Woltermann a69b0e337e Merge pull request #1027 from asarium/ci/noFormatter
Disable xcpretty travis formatter since it's broken
2016-10-12 11:05:33 +02:00
SamuelCho 5a25de0885 Removed extra brace from the ambient map fix attempt. 2016-10-12 01:56:40 -07:00
SamuelCho 4c4d5c2310 Fixed reflectance maps not being used if no shine map isn't available. Fixed ambient/cavity maps not being used. 2016-10-11 23:42:46 -07:00
asarium e99b4716c6 Disable xcpretty travis since it's broken 2016-10-11 17:18:12 +02:00
Fabian Woltermann e7a79cf1c8 Fixes a few instances of using the wrong overload for sexp_deal_with_ship_flag 2016-10-11 14:19:20 +02:00
niffiwan 378df6c06a Merge pull request #1025 from asarium/fix/creditsReading
Fix reading credits table without #end
2016-10-11 13:43:56 +10:00
asarium c005602e8f Fix reading credits table without #end
This just checks if the end of the file has been reached so existing
tables without the #end will still work (I'm looking at you
FSPort...).
2016-10-10 20:16:33 +02:00
Fabian Woltermann 3f65b059f6 Merge pull request #1017 from asarium/fix/mainExceptionError
Show an error dialog when an exception is thrown in main
2016-10-10 12:00:28 +02:00
Fabian Woltermann 1c773fb3ca Merge pull request #1023 from DahBlount/weapon_sub_fixes
Fixes for $Substitute
2016-10-10 11:59:40 +02:00
DahBlount ffab766a38 Clarify flag choice dependent upon weapon type
Ensures that primary weapons can't launch secondary weapons and vice
versa.
2016-10-10 01:59:31 -06:00
DahBlount 8bebea455a Make linked/dual fire consistent
Make sure we've got initialized values in the secondary pattern indexes
for a ship_weapon and also allow linked/dual fire to be in sequence
instead of swapping in the base weapon at the beginning of each pattern
loop.
2016-10-10 01:24:25 -06:00
DahBlount c2b98654fc Make sure substitution weapons get counted as used.
This will ensure the weapons get properly paged in.
2016-10-10 01:24:25 -06:00
niffiwan 8d58adc848 Merge pull request #1022 from asarium/fix/audiosttCutoff
Reset AudioStream data when beginning playback
2016-10-10 12:19:04 +10:00
niffiwan 5ab36f0629 Merge pull request #1021 from asarium/fix/rotationNaN
Fix computation that causes NaN errors
2016-10-10 12:17:09 +10:00
Peter Mitsis 4437766a2a Introduce IS_NEAR_ZERO() macro
The IS_NEAR_ZERO() macro offers a convenient and efficient way
to test if a float is near zero.

Signed-off-by: Peter Mitsis <[email protected]>
2016-10-09 19:35:44 -04:00
asarium 787630e9de Reset AudioStream data when beginning playback
This fixes an issue where the event music cuts off after ~ 3 seconds
because the fields tracking how much data has been read so far were not
reset. I also fixed the calculation of how much data may be read since
that was slightly broken by the new audio stream reading code.
2016-10-09 21:44:05 +02:00
asarium a62d13468c Fix computation that causes NaN errors
I'm not entirely sure if this is the correct way to do the computation
but I see no other way of fixing it but since the zero vector is a valid
value for the relative velocity this seems to be the most sensible
solution.

Also, related to this I found out that FSO causes a lot of NaN errors at
runtime which may need to be investigated at some point to make sure
they don't cause issues like this bug.
2016-10-09 19:26:47 +02:00
niffiwan a42dba8316 Merge pull request #1019 from niffiwan/cleanup/remove_msaa
Remove MSAA
2016-10-09 22:17:07 +10:00
niffiwan 00948ec261 Minimal disable, leave infrastructure intact 2016-10-09 21:01:54 +10:00
niffiwan c6c4f54f79 Remove MSAA
Reasons being; it's incompatible with FXAA, it's slow, and it's causing
OGL init to fail on certain systems. Oh, and it probably doesn't work
anyway :)
2016-10-09 20:00:06 +10:00
asarium 3b06c0a18e Show an error dialog when an exception is thrown in main
This will make sure that an exception doesn't just silently crash the
game (if the dialog can be shown at that point). This caused some issues
in the past so I thought it would be a good idea. I also added a check
for a preprocessor define to disable exception catching completely which
should make it possible to use a debugger to debug uncaught exceptions.
2016-10-09 10:03:51 +02:00
niffiwan 62efff7b97 Merge pull request #1016 from asarium/cleanup/moreconfigh
Cleanup config.h a bit more
2016-10-09 08:34:11 +10:00
niffiwan 9f9b4e8430 Merge pull request #1013 from asarium/fix/retailSoundWarnings
Suppress 3D sound warning for retail sounds
2016-10-09 08:31:05 +10:00
Peter Mitsis ff3de3a2b4 vecmat: Remove broken vm_vec_normalize_quick_mag()
The routine vm_vec_normalize_quick_mag() did not normalize a vector.
Instead of dividing the vector by the 'quick magnitude', it multiplied
it. This routine was only called by one other routine (which was
fortunately unused)--vm_vec_normalized_dir_quick_mag().

Given both the incorrect behavior as well as their lack of use, those
routines have been removed.

Signed-off-by: Peter Mitsis <[email protected]>
2016-10-08 16:06:57 -04:00
Peter Mitsis 98876e99bb vecmat: Use fl_abs() in vm_vec_mag_quick()
Uses fl_abs() (which evaluates to fabsf()) instead of an if-else
statement to get the absolute value of a float. A compiler for the
x86 platform is able use SSE instructions to optimize calls to fabsf().

Signed-off-by: Peter Mitsis <[email protected]>
2016-10-08 16:06:57 -04:00
asarium 033402c261 Fix Cross-compilation 2016-10-08 21:27:28 +02:00
asarium 43ceefde5f Cleanup config.h a bit more 2016-10-08 21:27:17 +02:00
asarium 322060024c Suppress 3D sound warning for retail sounds
@niffiwan discovered that some retail sounds trigger the newly
introduced so the warning needs to be suppressed for those few files.
See #1005 for the full discussion.
2016-10-08 15:55:49 +02:00
m!m bb9d6fa4c5 Merge pull request #1014 from niffiwan/feature/alt_techroom_pof
Add alternate pof for use in techroom
2016-10-08 15:54:13 +02:00
niffiwan d96a8d031a Add alternate pof for use in techroom
Designed to work around issues with gunpoints on animated subsystems,
and those gunpoints being in the "triggered" position, and thus there's
lines pointing to empty space in the weapon loadout screen.

Use this to specify an alternate model that has the gunpoints in the
"correct" position.
2016-10-08 21:42:32 +10:00
Fabian Woltermann 1a407d3fb3 Merge pull request #1010 from asarium/cleanup/noOgg
Remove Ogg/Theora/Vorbis and ACM library files
2016-10-08 13:32:13 +02:00
m!m 5fce4b3408 Merge pull request #1012 from niffiwan/fix/coverity_1364083
Fix coverity 1364083
2016-10-08 11:34:32 +02:00
niffiwan 4b4b8657a0 Merge pull request #1011 from asarium/coverity/particleEffects
Fix a few Coverity issues in the Particle effects code
2016-10-08 11:53:21 +10:00
niffiwan 31ebefefe1 Fix coverity 1364083 2016-10-08 11:40:16 +10:00
asarium 62226e71e7 Remove Ogg/Theora/Vorbis and ACM library files
They are no longer needed since decoding is provided by FFmpeg
2016-10-07 11:27:43 +02:00
asarium 7be17c9656 Fix a few Coverity issues in the Particle effects code 2016-10-07 11:09:45 +02:00
Fabian Woltermann b7dc661fe7 Merge pull request #1005 from asarium/merge/soundBuffer
Use FFmpeg for normal audio loading
2016-10-07 10:05:37 +02:00
asarium 33be5b0372 Fix some audio issues 2016-10-06 13:15:23 +02:00
asarium 73034ed9d2 Fix audio clipping of sounds 2016-10-05 14:57:13 +02:00
asarium c58195f20d Fix MSVC warnings 2016-10-05 11:02:36 +02:00
asarium 1cf11d31fe Use FFmpeg for normal audio loading
This is the last part of our code that does audio loading on its own.
After this is merged the WAV/ACM/Ogg code can be removed.
2016-10-05 11:02:36 +02:00
MageKing17 34469c72b4 Merge pull request #1009 from asarium/fix/ffmpegCoverity
Fix various Coverity issues in the FFmpeg code
2016-10-04 12:32:28 -07:00
m!m 5b6ff638e3 Merge pull request #1007 from niffiwan/fix/coverity_1363662
Fix Coverity 1363662
2016-10-04 15:34:57 +02:00
asarium df40777e5f Move vecmath scripting functions into own file 2016-10-04 15:09:52 +02:00
asarium 070edd9ad4 Fix various Coverity issues in the FFmpeg code 2016-10-04 14:57:26 +02:00
Fabian Woltermann 438945c691 Merge pull request #1006 from asarium/cleanup/luaFiles
Cleanup and reorganize scripting files
2016-10-04 14:43:11 +02:00
niffiwan 4547b5775f Fix Coverity 1363662
Missing break in switch
2016-10-04 22:32:00 +10:00
asarium 5535311087 Move ade functions into own files 2016-10-03 22:24:09 +02:00
asarium 6dbf200cc3 Move lua to scripting folder 2016-10-03 21:38:29 +02:00
Fabian Woltermann 778cb6f473 Merge pull request #1002 from asarium/fix/adpcmPlayback
Fix ADPCM playback with older FFmpeg versions
2016-10-03 19:04:46 +02:00
m!m 1cf0d17449 Merge pull request #1004 from niffiwan/cleanup/htl_remnants
Cleanup some non-HTL code
2016-10-03 15:08:43 +02:00
niffiwan a9261477ba Add func def to .h & remove extern 2016-10-03 22:31:56 +10:00
m!m a86ba780ec Merge pull request #1003 from niffiwan/fix/coverity_1363382
Fix Coverity 1363382
2016-10-03 11:13:31 +02:00
niffiwan 484d810896 Cleanup some non-HTL code
This was probably missed in removal of -nohtl
Also "fixes" Coverity 1363380
2016-10-03 12:22:57 +10:00
niffiwan 2e59f68e22 Fix Coverity 1363382
Init center_text in ctor, safety/defensive measure only since is
currently correctly set via init function in all code paths
2016-10-03 09:35:28 +10:00
asarium 45ae61d17d Remove unused function 2016-10-02 23:25:53 +02:00
asarium 66b62ee4f0 Fix ADPCM with older FFmpeg versions
ADPCM playback was broken by #991 when an older FFmpeg version (< 3.1)
was used. The newer version has a better API for handling decoder that
return multiple frames of data per packet which I already used. However,
I didn't bother implementing that for the older API since I haven't seen
a decoder that actually returned multiple frames per packet but ADPCM is
such a decoder. This fixes that by implementing the correct behavior
with the old API.
2016-10-02 19:52:52 +02:00
Fabian Woltermann 41f619c1ff Merge pull request #991 from asarium/merge/audiostr
Use FFmpeg for audio stream decoding
2016-10-02 17:21:20 +02:00
Fabian Woltermann b33ad0d271 Merge pull request #1000 from asarium/build/crossCompilation
Cross compilation fixes
2016-10-02 17:20:01 +02:00
Fabian Woltermann d3f78a9354 Merge pull request #1001 from asarium/build/nightlyFixes
Fix Travis nightly builds
2016-10-02 17:19:27 +02:00
asarium 85cc7caf18 Cross compilation fixes
This makes it possible to compile windows builds on Linux.
2016-10-02 14:24:48 +02:00
niffiwan c10927a7ae Merge pull request #999 from asarium/fix/oglShaderCache
Fix parameter oder for shader hashes
2016-10-02 21:21:14 +10:00
asarium 5ee68a653f Fix Travis nightly builds
1) I accidentally used subshells for matching the tag patterns which
broke the regex match.
2) The destination directory for the library files wasn't created by
default so it broke the build.
2016-10-02 12:43:55 +02:00
asarium f1f7b32980 Fix parameter oder for shader hashes 2016-10-02 11:47:46 +02:00
m!m 8aa66b7ed0 Merge pull request #996 from ashdnazg/fix_mingw_openal
Fixed mingw openal linking
2016-10-02 11:46:42 +02:00
m!m de8c63e263 Merge pull request #997 from Yarn366/ffmpeg_multimonitor
Display videos only on the center monitor
2016-10-02 11:46:31 +02:00
Yarn366 0779085d30 Display videos only on the center monitor, just like before the FFmpeg merge. 2016-10-01 19:10:27 -04:00
Eshed 15e9942eee Fixed mingw openal linking 2016-10-02 00:41:38 +03:00
m!m ca0e1cb2c1 Merge pull request #993 from ashdnazg/master
Enable mingw builds & remove boost dep.
2016-10-01 23:09:32 +02:00
m!m 7c623b7314 Merge pull request #990 from MageKing17/bugfix/previous-weapon-selection
Fix previous_primary_bank and previous_secondary_bank.
2016-10-01 22:32:24 +02:00
Eshed ade14624e8 Fix copyright symbol 2016-10-01 23:27:34 +03:00
Eshed c722aa6e49 move syncboundedqueue.h and readd original license 2016-10-01 23:01:05 +03:00
Eshed 260072b97f use SCP_string instead of std::string 2016-10-01 22:47:41 +03:00
Eshed 23e41970f2 Remove boost dependency
Add syncboundedqueue.h which is basically boost::sync_bounded_queue ported to std::* line for line.
2016-10-01 21:33:32 +03:00
Eshed 581e808733 Enable mingw builds (both 32&64 bit)
- Add libs prebuilt with mxe
- Update cmake scripts to use them
- Make MINGW builds use the generic def_files inclusion method
- Some minor fixes to compilation
2016-10-01 21:31:16 +03:00
Fabian Woltermann 2ce5010f26 Merge pull request #994 from asarium/fix/boost
Fix boost for FastDebug
2016-10-01 20:26:06 +02:00
asarium 357449a95f Fix boost for FastDebug
The previous version simply ignored that configuration but these changes
should fix that.
2016-10-01 19:19:08 +02:00
MageKing17 5d990772b5 Fix previous_primary_bank and previous_secondary_bank.
previous_primary_bank was only getting set if the ship had a ballistic weapon or if secondary banks were changed, so previous_secondary_bank wasn't getting set at all. I fixed the second problem my simply using the correct variables, and the first problem by consolidating the ballistic and non-ballistic code so that there was less code redundancy (without that redundancy, it's unlikely the mistake would've been made in the first place); I figured this was a better solution than just copying the code to set previous_primary_bank into the non-ballistic codepath.

Also simplified the code for setting the previous weapon bank according to asarium's suggestion.
2016-09-30 14:51:32 -07:00
asarium e760c58522 Use FFmpeg for audio stream decoding
This is the first step towards moving all audio decoding to FFmpeg which
will reduce the amount of external code we will need to include. This
only replaces the AudioStream code with an FFmpeg based solution which
should make the code easier to review.
2016-09-30 18:35:48 +02:00
Fabian Woltermann 679094c6f1 Merge pull request #987 from asarium/fix/appimageFiles
Fix nightly AppImages
2016-09-30 14:28:45 +02:00
Fabian Woltermann 5be84cace3 Merge pull request #979 from asarium/cmakeMerge/ffmpeg
Add improved video player
2016-09-30 13:59:17 +02:00
asarium 0ada262dcd Remove unused declarations and fields 2016-09-30 13:12:09 +02:00
asarium 9203388d6c Remove unused function 2016-09-30 13:06:09 +02:00
MageKing17 f516809959 Merge pull request #989 from asarium/feature/fofLuaApi
Add lua option for accessing the FOF cooldown
2016-09-29 17:27:16 -07:00
asarium f49f8d6aea Use FFmpeg for MVE decoding
It turns out that FFmpeg is actually able to decode the Interplay MVE
movies so we can drop the old MVE code and just use FFMpeg and the new
video player interface for that.
2016-09-29 18:57:01 +02:00
asarium 4c2ebf53b6 Add lua option for accessing the FOF cooldown
This was requested by @AxemP.
The implementation is a bit more complicated than simply retrieving the
value since that is only updated when the weapon is fired. Instead, the
function calculates what the current value should be based on the code
from the function that updates the value when the weapon is fired.

Setting the value is disabled since the extra processing code could
alter the calculation a script does so that after setting the value,
reading it again would return a different value.
2016-09-29 10:35:39 +02:00
asarium e41b44ff1d Fix nightly AppImages
Fixes #985.
2016-09-27 15:36:01 +02:00
asarium 1bcb937fe3 Add improved video player
Uses FFmpeg for video decoding and multiple threads for reading and
decoding files. Can handle 1080p with no stuttering.
2016-09-26 22:43:19 +02:00
Cliff Gordon d0600a697e Merge pull request #790 from asarium/build/minGW
Fix a few issues with MinGW
2016-09-26 14:07:09 -05:00
Fabian Woltermann 3dfad4b251 Merge pull request #982 from asarium/ogl/ppScopes
Add more tracing scopes to post processing code
2016-09-25 18:49:45 +02:00
Fabian Woltermann 486f35d1bf Merge pull request #983 from asarium/fix/weaponImpact
Fix unitialized particle variable
2016-09-25 18:47:36 +02:00
asarium 27e6507a5e Fix unitialized particle variable 2016-09-25 18:22:30 +02:00
asarium 0b07eedcfc Add more tracing scopes to post processing code 2016-09-25 11:36:51 +02:00
MageKing17 1ab3a289c7 Merge pull request #980 from asarium/ci/win3264
Build both 32- and 64-bit builds for nightlies
2016-09-20 14:46:55 -07:00
m!m 7f1d65c765 Merge pull request #981 from chief1983/fix/SDL2_framework
fix/SDL2_framework: Use an unmodified copy of the SDL2 framework
2016-09-20 23:14:47 +02:00
chief1983 2c9f289188 fix/SDL2_framework: Use an unmodified copy of the SDL2 framework on mac, with symlinks in place, halving the Framework archive's size. 2016-09-20 15:19:36 -05:00
asarium 59789a3c25 Build both 32- and 64-bit builds for nightlies 2016-09-20 18:24:00 +02:00
MageKing17 5a984a95ba Merge pull request #978 from asarium/fix/teamColorGlow
Readd team color glows
2016-09-18 13:35:57 -07:00
asarium 7af854a57c Readd team color glows
This was missed in the OpenGL core changes. The new code should behave
like the code in 3.7.4.
2016-09-18 22:06:43 +02:00
Fabian Woltermann 130bac0c83 Merge pull request #962 from asarium/cmake_/performanceScript
Add script for doing automated performance test
2016-09-18 10:51:39 +02:00
m!m 5bbb00d589 Merge pull request #977 from SamuelCho/FredAllocationFix
Make sure we tell the batcher to render in FRED.
2016-09-18 10:50:00 +02:00
Goober5000 d9c9647919 Merge pull request #947 from MageKing17/cleanup/miscellaneous
Some miscelleaneous cleanup commits.
2016-09-17 23:15:17 -04:00
SamuelCho 54c73bdbc3 Make sure we tell the batcher to render in FRED. 2016-09-17 11:51:29 -07:00
Fabian Woltermann c6726f10f3 Merge pull request #972 from asarium/feature/gpuTracing
Add GPU time tracing to JSON output
2016-09-15 06:07:42 +02:00
Fabian Woltermann 81071bb69a Merge pull request #975 from asarium/ci/betterNightlies
Improve Appveyor nightly setup
2016-09-15 06:07:26 +02:00
asarium aff9bcf08e Improve appveyor nightly setup
This allows to build multiple configurations per nightly and prepares
the setup for future use for release builds.
2016-09-14 22:46:29 +02:00
asarium caeecf111e Remove environment variable usage in CI scripts 2016-09-14 20:54:02 +02:00
m!m f9bc01cca6 Merge pull request #973 from The-E/aicode_fix
Fixes a little nuance that was missed during the ship flag conversion
2016-09-14 20:25:54 +02:00
asarium 8333d15f12 Move all AppVeyor scripts into one script 2016-09-14 19:36:59 +02:00
Fabian Woltermann 07ae236642 Fixes a little nuance that was missed during the ship flag conversion 2016-09-14 18:50:48 +02:00
asarium 8ece00541f Fix conversion warning 2016-09-14 15:32:18 +02:00
asarium acbac94685 Add GPU time tracing
This also adds nanosecond precision tracing for normal CPU events
2016-09-14 12:26:53 +02:00
asarium 26f45732da Move profiling functions into separate folder 2016-09-14 12:26:53 +02:00
asarium 547adbfaba Add graphics API for query objects 2016-09-14 12:23:53 +02:00
m!m 6ac6a38bf1 Merge pull request #970 from SamuelCho/envReflectRemoval
Remove unused varying envReflect from main fragment shader.
2016-09-13 10:14:29 +02:00
SamuelCho 59eeb39b8c Remove unused varying envReflect from main fragment shader. 2016-09-12 21:56:01 -07:00
MageKing17 ae7bb818cc Merge pull request #968 from asarium/fix/vcruntime
Fix dependency on VSRUNTIME DLL
2016-09-12 15:13:28 -07:00
asarium ceda6a9869 Fix dependency on VSRUNTIME DLL
The ogg/vorbis DLLs were linked with a dynamic runtime which caused the
error that was reported in the nightly thread. These new DLLs statically
link the runtime which should eliminate the dependency on the runtime
DLL.
2016-09-12 17:57:34 +02:00
m!m 157de87f15 Merge pull request #966 from rtoijala/species-tbl-tests
Species tbl test improvements
2016-09-12 16:44:41 +02:00
Risto Toijala 6fb90421f9 Add unit test for wrong order in intel entry. 2016-09-12 14:05:35 +03:00
Risto Toijala 8bb14d1a1f Uncomment now working test for missing $end_multi_text
This test works since 16d5f8830e
and c9f9e1b2f0.
2016-09-12 13:13:51 +03:00
SamuelCho f8c714a4e1 Merge pull request #958 from asarium/fix/luaImage
Fix lua drawImage rendering
2016-09-11 12:07:02 -07:00
m!m 6a9922eaa3 Merge pull request #963 from The-E/mfcgraphicsops_fix
Initializes the SDL Video subsystem for FRED
2016-09-11 18:59:06 +02:00
Fabian Woltermann ea35421a4f Quit SDL Video in the destructor 2016-09-11 17:38:57 +02:00
Fabian Woltermann 948d0590b4 Initializes the SDL Video subsystem for FRED 2016-09-11 17:35:18 +02:00
asarium dd56493543 Add script for doing automated performance test
This script allows to compare the performance of a branch to master by
running both versions and generating a graph of frametimes for both
versions.
2016-09-11 16:21:32 +02:00
MageKing17 01c50727ac Merge pull request #959 from Yarn366/fixed_messages_fix
Fix for Fixed Messages gauge position
2016-09-11 01:15:33 -07:00
asarium 032d6a15a9 Fix alpha blend mode for APNGs and in scripts
Apaprently the alpha blend behavior has been broken for a long time and
alpha blending was always enabled. I changed the default lua opacity
type to match this behavior so that older scripts don't get broken by
this.
2016-09-11 09:48:03 +02:00
Yarn366 ac0aae23fa Fixed the position of the Fixed Messages gauge so that it's actually on the screen. (Its X-position was 0x8000, which used to be a magic number indicating that the string should be horizontally centered on the screen. Since the TrueType merge, this number no longer has any special meaning.)
Also added the "Center Text On Gauge X-Position:" option for the Fixed Messages gauge, which by default is enabled only if the gauge's position is not overridden.
2016-09-10 21:17:50 -04:00
asarium 8dbea5eeb8 Fix lua drawImage rendering 2016-09-10 18:58:52 +02:00
SamuelCho 03ddd51063 Merge pull request #957 from asarium/fix/credits-bitmaps
Always use alpha blending for interface materials
2016-09-10 09:06:48 -07:00
asarium 03591b33ce Always use alpha blending for interface materials 2016-09-10 14:22:40 +02:00
asarium ace67bf6ea Add additional graphics debug scopes 2016-09-10 14:03:42 +02:00
Fabian Woltermann de6c5582ce Merge pull request #955 from chief1983/fix/macNightlies
Various fixes for #836 - Resolve Mac CMake issues
2016-09-10 07:53:57 +02:00
chief1983 5bf9db07a8 fix/macNightlies: Fix for #836 - Set the deployment target as low as will still compile to broaden compatibility, fix setting the rpath during the build process for SDL2 linking, and copy the resource bundles while preserving symlinks and other attributes. 2016-09-09 15:46:10 -05:00
Fabian Woltermann 40fba4f304 Merge pull request #954 from asarium/fix/mission-time
Fix integer overflow in mission-time-msecs SEXP
2016-09-09 20:03:11 +02:00
asarium 0d8fc66bc8 Remove gr_cross_fade
It was just a wrapper around existing functions so I removed the
function and replaced the only usage with the equivalent code.
2016-09-09 20:00:35 +02:00
asarium 107946d012 Fix integer overflow in mission-time-msecs SEXP 2016-09-09 19:34:25 +02:00
MageKing17 9eaba0acc2 Merge pull request #953 from asarium/fix/cursorLock
Fix return value check in cursor code
2016-09-09 05:45:10 -07:00
asarium e7add258b0 Disable cursors in standalone mode 2016-09-09 10:13:42 +02:00
MageKing17 d3f89c1042 Also use MAX_DETAIL_LEVEL for resetting detail_distance_mult.
Same as 816e792770 but for ai_profile_t::reset(), instead of when parsing.
2016-09-08 13:24:05 -07:00
asarium 89bdef89dc Fix return value check 2016-09-08 17:39:08 +02:00
Fabian Woltermann 1e2b6460a3 Merge pull request #951 from asarium/fix/standaloneCursor
Fix cursor handling in standalone server
2016-09-08 13:38:23 +02:00
Fabian Woltermann a6831ef217 Merge pull request #952 from asarium/fix/noMemoryTracking
Remove memory tracking code
2016-09-08 13:38:16 +02:00
asarium e0395ab51a Remove memory tracking code 2016-09-08 12:22:35 +02:00
Fabian Woltermann 5334c44451 Merge pull request #950 from asarium/fix/standaloneGraphicsOps
Don't initialize graphics operations in standalone mode
2016-09-08 11:59:54 +02:00
Fabian Woltermann 27d57ab1b0 Merge pull request #949 from asarium/ci/win64Nightly
Build 64-bit nightly builds
2016-09-08 11:59:46 +02:00
asarium 1d998e4709 Fix cursor handling in standalone server 2016-09-08 11:54:31 +02:00
asarium 5492df3a43 Don't initialize graphics operations in standalone mode 2016-09-08 11:08:46 +02:00
m!m 9dad552a4e Merge pull request #946 from MageKing17/bugfix/initialize-ignore-list
Actually initialize Ignore_List.
2016-09-08 10:46:56 +02:00
asarium 9fa373b493 Build 64-bit nightly builds 2016-09-08 10:38:35 +02:00
niffiwan 932c05c64b Merge pull request #948 from MageKing17/feature/remove-pointless-warning
Remove pointless main_hall_init() warning about an empty string.
2016-09-08 13:43:38 +10:00
MageKing17 1dad62d7ae Remove pointless main_hall_init() warning about an empty string.
cmission.main_hall defaults to an empty string, so calling main_hall_init() with an empty string is neither unsurprising nor uncommon. Since it's not actually caused by bad data, the warning can be considered actively harmful by training users that sometimes FSO just gives you a pointless warning.
2016-09-07 18:44:53 -07:00
MageKing17 bce17561ed Change pointless .size() calls into .empty() calls.
The codebase had quite a few instances of .size() being called and then checked to see if it was 0 or not (or less than 1, or greater-than-or-equal-to 1, which are basically equivalent), when .empty() could be called instead (negated or not, depending on what the original condition was).
2016-09-07 18:36:12 -07:00
MageKing17 bac77085da Minor hud_target_common() cleanup.
Changes "A-Objects" to "OBJ_INDEX(A)" (not sure why that one didn't generate warnings, but whatever), removes a redundant should_be_ignored() call (it will have already been called for that ship for the code to be in that block in the first place), and adds an assertion to make sure that the jnp iterator is valid before trying to dereference it.
2016-09-07 18:31:15 -07:00
MageKing17 816e792770 Explicitly make "$Detail Distance Multiplier:" based on detail levels.
Most AI profile-related five-value lists are related to the number of difficulty levels. "$Detail Distance Multiplier:", however, is related to the number of detail levels (MAX_DETAIL_LEVEL + 1, because detail levels go from 0-MAX_DETAIL_LEVEL; MAX_DETAIL_LEVEL + 1 is also the size the detail_distance_mult array is defined with). Those two numbers happen to be the same (5); however, this may not always be the case in the future, and this way it's explicit that this field isn't related to difficulty at all.
2016-09-07 17:58:25 -07:00
MageKing17 634a8a06fc Actually initialize Ignore_List.
Ignore_List (the list of flags used to determine if a ship is an invalid target) was originally a statically-initialized bitfield stored in an int; the new bitset flags code added a set_default_ignore_list() function to provide the default values, but then forgot to call it anywhere. As a result, "hidden-from-sensors" (and the other, less-likely-to-be-noticed flags) was having no effect on the player's ability to target anything. This adds a call to set_default_ignore_list() to ship_init() so that the original functionality is restored.
2016-09-07 17:52:45 -07:00
Fabian Woltermann 2cc153abea Merge pull request #944 from asarium/build/clangAsan
Add CMake option for AddressSanitizer with Clang
2016-09-07 16:03:23 +02:00
asarium a1cee67e15 Add CMake option for AddressSanitizer with Clang 2016-09-07 11:01:51 +02:00
Cliff Gordon 60fff3f82f Merge pull request #943 from asarium/ci/fixNightly
Fix nightly build configuration
2016-09-06 11:43:29 -05:00
asarium 1c712a7448 Fix nightly build configuration 2016-09-06 15:19:20 +02:00
asarium facac997f1 Fix a few issues with MinGW
This does not mean that MinGW can compile FSO yet, these are just a few
fixes that are needed.
2016-09-06 10:49:48 +02:00
MageKing17 8d05393ba0 Merge pull request #942 from Goober5000/ai_chase_ship_class_followup
Ai chase ship class followup
2016-09-05 15:24:52 -07:00
Goober5000 03fa181c2d add back in something incorrectly removed during PR #931 2016-09-05 16:12:45 -04:00
Goober5000 6ab508415c add useful Assert 2016-09-05 16:12:45 -04:00
Goober5000 92931ff541 fix the hexadecimal number 2016-09-05 16:12:44 -04:00
Fabian Woltermann ee0811b097 Merge pull request #932 from asarium/fix/memoryAlignment
Use aligned storage for the memory header
2016-09-05 17:42:43 +02:00
Fabian Woltermann 76f2d72d30 Merge pull request #935 from asarium/ogl/moreDebugScopes
Some graphics debug group improvments
2016-09-05 17:42:20 +02:00
asarium a5ac021076 Add a few more debug scopes 2016-09-05 15:31:20 +02:00
asarium f693d49f95 Remove variable name from GR_DEBUG_SCOPE 2016-09-05 15:29:49 +02:00
asarium c2b5fe7f28 Use CMake platform checks for max_align_t
The platforms we support have no common definition of max_align_t so I
used CMake platform checks to determine what is available.
2016-09-05 12:31:48 +02:00
asarium 2f5c690175 Fix warnings from new compiler versions 2016-09-05 11:30:03 +02:00
Fabian Woltermann 8ed93bb0e4 Merge pull request #939 from Goober5000/ai_chase_ship_class
Ai chase ship class
2016-09-05 11:07:08 +02:00
asarium f266583a47 Use aligned storage for the memory header
This should ensure that the pointer returned by vm_malloc is suitably
aligned for any type.
2016-09-05 10:52:59 +02:00
Goober5000 1d08e8543f let's assume that the ship types that can attack-any are the same ship types that can attack-any-ship-class 2016-09-05 03:22:50 -04:00
Goober5000 03418796ab missed this flag conversion 2016-09-05 02:51:50 -04:00
Goober5000 b93a3902dc the actual guts of the chase-ship-class goal 2016-09-05 02:35:24 -04:00
Goober5000 c14af70287 all the goal infrastructure for chase-ship-class except for the actual chase logic 2016-09-05 02:35:23 -04:00
Fabian Woltermann 3e4a289cc5 Merge pull request #937 from asarium/fix/parseloPausing
Don't initialize mission text when it's not used
2016-09-05 08:31:09 +02:00
Fabian Woltermann 5b504bcd4e Merge pull request #938 from asarium/ogl/programBinaries
Add shader caching
2016-09-05 08:20:59 +02:00
Fabian Woltermann d53074c9ea Merge pull request #931 from Goober5000/minor_aicode_tweaks
minor tweaks and adjustments to AI goal code
2016-09-05 08:17:13 +02:00
asarium f8f3cd33ce Add shader caching
This uses the program binary support included in OpenGL 4.1 to build a
cache of compiled shaders. It does this by computing the MD5 of the
source code of the shaders and using that hash to save the files. That
should make sure that a change to a shader is automatically reflected in
the shader cache.
2016-09-04 19:11:40 +02:00
asarium 4964fccd7e Don't initialize mission text when it's not used
As far as I can tell this issue has been present for a very long time,
maybe even since retail. It was only uncovered since the recent changes
initialized the mission text by default which corrupted the table text
that was currently being parsed.

This also adds a unit test that validated that pausing works correctly.
2016-09-04 16:32:11 +02:00
Fabian Woltermann 5f46aa1444 Merge pull request #936 from asarium/fix/moreParseloCStrings
Make sure that Mission_text is always initialized
2016-09-04 12:42:41 +02:00
asarium 16d5f8830e Make sure that Mission_text is always initialized
This should fix #933.
2016-09-04 11:15:02 +02:00
Goober5000 bbafbf1ffd additional refinements 2016-09-03 20:45:18 -04:00
Goober5000 2fdcd1e772 add a clarifying comment 2016-09-03 11:30:14 -04:00
Goober5000 2b680f861c Merge pull request #934 from asarium/fix/parseloCString
Make sure that the parse strings are c strings
2016-09-03 11:26:55 -04:00
asarium c9f9e1b2f0 Make sure that the parse strings are c strings
Fixes #933.
2016-09-03 13:57:36 +02:00
Goober5000 1d3ff1b6c0 minor tweaks and adjustments to AI goal code
A few things I noticed while working on ai-chase-ship-class, split out into a separate PR.  Some code is reordered, some is cleaned up; nothing too extensive.  The most notable changes are a) the modification of the Ai_goal_text function to work on the AI_GOAL_X #define directly rather than unnecessarily calculate the bit; b) changing the HUD text of "fly to ship" to "rendezvous with" plus the ship name; c) adding a Warning in ai_update_goal_references; and d) changing ship_name to target_name in ship_return_orders for clarity
2016-09-02 23:25:46 -04:00
SamuelCho 8d2674eaf2 Merge pull request #929 from asarium/ogl/texture2D
Replace texture2D with texture in shaders
2016-09-02 14:51:50 -07:00
asarium 458c9f30fb Replace texture2D with texture in shaders
texture2D has been deprecated for some time and Mac also doesn't support
it anymore. The 1.50 GLSL specification says that texture is the correct
function for texel lookup so I used that.
2016-09-02 20:54:18 +02:00
Fabian Woltermann e1dd3784e2 Merge pull request #925 from asarium/ci/shuffledUnitTests
Shuffle the order in which unit tests are executed
2016-09-02 15:57:39 +02:00
Fabian Woltermann 417eb20a3e Merge pull request #927 from asarium/feature/shipExplosionEffects
Add support for ship death particle effect
2016-09-02 15:57:25 +02:00
asarium 648751445a Fix shape of generated particles 2016-09-02 14:24:26 +02:00
m!m 5b4199aca2 Merge pull request #924 from rtoijala/species-tbl-tests
Introduce tests for parsing species.tbl
2016-09-02 14:10:17 +02:00
asarium 29a74af3bd Create ship death particle effect 2016-09-02 11:39:51 +02:00
asarium 60554601bd Fix animation page in 2016-09-02 11:33:46 +02:00
asarium c112f093a8 Add ship explosion particle effects 2016-09-02 11:05:03 +02:00
Risto Toijala c400a8a2ba Implement tests for species.tbl parsing
This adds unit tests (or maybe these count more as functional tests) for
parsing the intelligence data displayed in the tech room. It is parsed
from species.tbl by code/menuui/techroom.cpp and stored in the global
array Intel_info. The number of entries is saved in the global int
Integer_info_size.

Every test has its own mod dir with a species.tbl that it parses by
calling techroom_intel_init(). The test fixture resets the intel state
with techroom_intel_reset() between tests.

These tests assume that the file is preprocessed correctly, so it does
not try to test if e.g. comments are removed correctly, ... Only the
parsing that is unique to species.tbl is tested.
2016-09-02 11:05:46 +03:00
Fabian Woltermann 0c240c398e Merge pull request #926 from asarium/ogl/fredCoreProfile
Add OpenGL Core context creation to FRED2
2016-09-02 09:27:24 +02:00
Risto Toijala d6e47f35d4 Log start of each test in FSTestFixture.
All log output is ignored in an unpatched FSO, but when patching to save
test logs, this is useful for navigating the log.
2016-09-01 23:01:20 +03:00
Risto Toijala 045276d7bf Implement techroom_intel_reset for testing. 2016-09-01 23:01:20 +03:00
asarium 22758e9a4a Add OpenGL Core context creation to FRED2
While it isn't strictly necessary since the Windows drivers typically
support the features we need it's still the better solution.

It also allows WINE to run FRED2 on Linux since there the code profile
is actually needed.
2016-09-01 21:49:59 +02:00
asarium 05e70efc4f Shuffle the order in which unit tests are executed 2016-09-01 19:06:18 +02:00
m!m 61091ad95a Merge pull request #923 from SamuelCho/shader_material_handling
Refactored material handling of shaders
2016-09-01 11:36:47 +02:00
SamuelCho 5c5a2f6a07 Merge pull request #708 from asarium/fix/timer
Always use high resolution timers
2016-08-31 22:43:24 -07:00
Fabian Woltermann c9d8cb47d0 Merge pull request #921 from asarium/ogl/noGLU
Remove GLU dependency
2016-08-31 17:03:21 +02:00
m!m c449de9710 Merge pull request #922 from The-E/other_ai_flags
Convert the remaining AI flags
2016-08-31 17:00:52 +02:00
Fabian Woltermann f8fb23b9f2 Cleanup in ai_profiles.h 2016-08-31 15:59:41 +02:00
Fabian Woltermann 0d7edb9d0a Maneuver override flags converted 2016-08-31 15:47:20 +02:00
Fabian Woltermann 99a59efdbf AI Goal flags converted 2016-08-31 15:30:49 +02:00
asarium 04cf483161 Remove GLU dependency 2016-08-31 14:51:09 +02:00
asarium 213238ce38 Remove all references to high_res_microseconds timer function 2016-08-31 14:37:24 +02:00
asarium baf7746986 Rename high res timer function to timer_get_microseconds 2016-08-31 14:32:53 +02:00
asarium e8bd7363c8 Use microsecond precision for timestamps
This only increases resolution for the internal ticker but not for the
external timestamps
2016-08-31 14:32:53 +02:00
asarium ca2a9ca725 Replace microsecond timer 2016-08-31 14:32:53 +02:00
asarium 0169a5477c Always use high resolution timers 2016-08-31 14:32:53 +02:00
m!m 328327bea6 Merge pull request #919 from rtoijala/fix/test-cmdline
Remove old cmdline parms before parsing new ones.
2016-08-31 14:31:36 +02:00
Fabian Woltermann 8951441311 Merge pull request #920 from SamuelCho/specular_unlit
Better handling of specular maps when using unlit rendering
2016-08-31 11:19:58 +02:00
Fabian Woltermann f439a5c5a4 Merge pull request #918 from SamuelCho/additional_render_cleanup
Cleaned up more rendering code.
2016-08-31 10:45:21 +02:00
SamuelCho fef0e7e1f8 Specular unlit rendering. 2016-08-31 01:32:12 -07:00
Risto Toijala 49fb506628 Remove old cmdline parms before parsing new ones.
This was causing my (yet unpublished) tests to fail because the mod list
was just being appended to instead of being reset for each test.
2016-08-31 10:49:15 +03:00
SamuelCho b754fa56b9 Simplified material/shader handling. 2016-08-31 00:45:15 -07:00
SamuelCho c67f7b66aa Reconciled changes with new shield rendering code. 2016-08-31 00:34:26 -07:00
Fabian Woltermann 71c296391d Merge pull request #903 from SamuelCho/better_shields
Better Shields
2016-08-31 09:27:54 +02:00
SamuelCho b75a354505 Cleaned up more rendering code. Shrunk the vertex struct since we don't use spec_rgb anymore. Removed any declarations using the old geometry batcher. Streamlined desaturation in the model shader to use the main color uniform. Removed old unneeded interp_ code. Removed stored geometry shader parameters from the shader constants since we're no longer using the EXT version of geometry shaders. 2016-08-30 23:22:09 -07:00
SamuelCho a8cb9aabf1 Removed accidental comma. 2016-08-30 21:19:57 -07:00
SamuelCho 99b427f224 Fixed shield uniforms. 2016-08-30 21:19:06 -07:00
SamuelCho 17bd4a2fa8 Reconciled shield changes with recent changes. 2016-08-30 20:36:08 -07:00
SamuelCho 81a5d228d4 Merge pull request #917 from asarium/fix/fredWaypointCrash
Fix FRED crash when rendering waypoints
2016-08-30 16:03:51 -07:00
asarium ce8cf62cd8 Remove some unused graphics functions 2016-08-30 23:12:55 +02:00
asarium 46d5c81b57 Fix FRED2 waypoint rendering crash 2016-08-30 23:12:55 +02:00
SamuelCho 802f09b947 Merge pull request #916 from asarium/fix/fredGLContext
Fix OpenGL context creation for FRED
2016-08-30 13:56:35 -07:00
asarium 6848eff404 Fix OpenGL context creation for FRED
This is not technically correct since the FRED code is not able to
create an OpenGL Core context but since FRED is Windows only it's not a
problem because those drivers usually support the Core profile features
in the Compatibility profile.
2016-08-30 21:39:13 +02:00
m!m 82ec8af3aa Merge pull request #915 from rtoijala/fix/techmenu-crash
Fix crash/Error in techmenu with 0 intel entries.
2016-08-30 13:41:12 +02:00
Risto Toijala 30cbebf527 Fix crash/Error in techmenu with 0 intel entries.
tech_render_anim did not check whether there were any intel/weapon
entries before trying to read from Current_list, which means that it
read at Current_list[-1], which is a Bad Thing (TM).

Do not try to render an anim if there is no entry.
2016-08-30 13:33:14 +03:00
Fabian Woltermann ee689cbb9f Merge pull request #912 from asarium/feature/chromeTracing
Add support for outputting profiling data as JSON
2016-08-30 09:29:07 +02:00
Fabian Woltermann b065d75beb Merge pull request #907 from rtoijala/small-debug-fixes
Small imporvements to debug messages
2016-08-29 20:46:14 +02:00
asarium 1a212868a0 Add support for outputting profiling data as JSON
This output is compatible with the Chromium tracing viewer which
provides a very nice visual overview of what FSO does in a frame.
2016-08-29 20:18:51 +02:00
m!m 174cff3eac Merge pull request #913 from rtoijala/fix/pilotfile-writing
Fix writing binary pilot files.
2016-08-29 18:22:41 +02:00
Risto Toijala 67677e06b8 Small imporvements to debugging
Add missing new line to BSP Parse timing and make it nprintf("Model").

Log value of HUD_config.rp_dist when it is not valid.

Fail reading a .plr file  if it has a zero-length section.
2016-08-29 19:06:16 +03:00
m!m 16668f3fb9 Merge pull request #911 from rtoijala/fix/outwnd-mkdir
Create data path for log file
2016-08-29 17:39:43 +02:00
Risto Toijala d3f615fe30 Fix writing binary pilot files.
startSectionWrite would push unnamed sections on _sectionOffsets, but
endSectionWrite was not removing them, leading to _sectionOffsets
containing tens of unnamed sections when parsing the HUD config.

Pop the unnamed sections in endSectionWrite.
2016-08-29 18:29:58 +03:00
Risto Toijala cea600b265 Create data path for log file
Opening the log file failed when the data path did not exists, e.g.
during the user's first run. Create it before trying to open the log
file.

Also, include <direct.h> in windows_stubs/config.h since the equivalent
stubs for Unix are also declared there.
2016-08-29 17:19:31 +03:00
Fabian Woltermann 7b47965509 Merge pull request #896 from asarium/ogl/shaderRefactor
Refactor shader handling
2016-08-29 13:26:05 +02:00
Fabian Woltermann 14395bc5cd Merge pull request #908 from SamuelCho/jumpnode_color_fix
Fixed jumpnode colors following OGL Core changes
2016-08-29 13:06:46 +02:00
Fabian Woltermann 87db55b4ac Merge pull request #909 from asarium/fix/starNVGRendering
Fix performance regression in star rendering code
2016-08-29 13:06:23 +02:00
asarium 3fcb731621 Refactor shader handling
This fixes a few of the bad design descisions of previous shader
iterations. This uses a dedicated class for managing the resources and
uniform locations of a shader program.

Uniforms are also stored in this object which makes a lot more sense
than storing them in the OpenGL state where they had to be reset every
time a new shader was used.

There are still a lot of possible enhancments to make, e.g. by using
uniform blocks and buffers instead of standard uniforms which would make
uniform location handling easier.

Another optimization that I will investigate is reducing the amount or
different compiled shaders by turning some of the current compile-time
defines into bool uniforms.
2016-08-29 12:38:38 +02:00
Fabian Woltermann 82eadd3983 Merge pull request #906 from SamuelCho/bloom_intensity_fix
Fixed bloom intensity weirdness when set it's set to 0.
2016-08-29 10:47:07 +02:00
SamuelCho d20aa57508 Fixed jumpnode colors not matching HUD. 2016-08-29 01:02:40 -07:00
Fabian Woltermann 4cb9e5cc04 Merge pull request #904 from SamuelCho/cleanup_rendering
Remove a crapload of unused rendering code
2016-08-29 09:36:18 +02:00
SamuelCho bd21cd0c48 Removed unused boolean left behind following the bloom intensity revisions. 2016-08-29 00:16:34 -07:00
SamuelCho 6e9d3223c8 Fixes bloom intensity weirdness when set it's set to 0. Removed unneeded bloom compositing code in the main post processing shader. Cleaned up the bloom compositing shader. 2016-08-28 23:13:21 -07:00
SamuelCho ba826df963 Removed a bunch of unused rendering code. 2016-08-28 18:47:34 -07:00
MageKing17 6987914a2c Merge pull request #901 from SamuelCho/gl_state_cleanup
OpenGL state tracking cleanup
2016-08-28 16:59:02 -07:00
SamuelCho bb78e74646 Improved shields. Added shield decal rendering technique. Fixed inaccurate shield normals and shield collision detection timing. Bumped up shield impacts count to 200. 2016-08-28 15:36:10 -07:00
SamuelCho f693413e26 Removed orphaned GL_state code. 2016-08-28 14:24:10 -07:00
Fabian Woltermann 87366d11ca Merge pull request #895 from asarium/ogl/debugGroups
Add OpenGL debug group support
2016-08-28 18:01:47 +02:00
asarium d7e3b61210 Add debug group support
This uses GL_KHR_debug for exposing debug group information. This is
very useful for tools like apitrace where it's used for assiciating
OpenGL commands with a specific application function.

The groups are created using a utility macro which is removed in release
builds so it should have no impact on the release performance.
2016-08-28 14:13:42 +02:00
m!m 4f6b907e3a Merge pull request #892 from rtoijala/remove-my_errno
Remove global my_errno
2016-08-28 14:07:52 +02:00
asarium a2eaccfc48 Fix performance regression in star rendering code
The previous code generated a lot of OpenGL function calls because every
star was rendered using a separate NanoVG frame. This fixes that by
using the path renderer directly which removes most of the
inefficiencies.

This is related to #898.
2016-08-28 13:46:57 +02:00
MageKing17 864e218e20 Merge pull request #897 from asarium/fix/wavStruct
Fix WAV parsing on UNIX
2016-08-27 14:53:55 -07:00
SamuelCho 319067c537 Merge pull request #894 from asarium/ogl/shaderCleanup
Improve shader value handling
2016-08-27 11:51:12 -07:00
SamuelCho f18bd8af24 Merge pull request #893 from asarium/ogl/no_fixed_function
Remove is_minimum_GLSL_version()
2016-08-27 11:50:35 -07:00
asarium 3942de94f6 Fix WAV parsing on UNIX
The code was using the 32-bit types while being compiled under 64-bit
because a header was missing. I fixed this issue by using fixed width
integer types.
2016-08-27 18:24:08 +02:00
asarium 5d6dc2e1a6 Improve shader value handling
Removes fixed arrays and replaces them with vectors.
2016-08-26 22:17:52 +02:00
asarium 478c86d3a6 Remove fixed function rendering code
Most of the removed functions didn't contain any code at all and aren't
referenced anymore.
2016-08-26 22:17:07 +02:00
asarium 173041e03a Remove is_minimum_GLSL_version()
Since OpenGL Core is required now that function would always return true
so it can be removed.
2016-08-26 22:16:30 +02:00
Fabian Woltermann 1fa84b4f7d Merge pull request #891 from asarium/ci/vs2015_64bit
Use 64 bit build for appveyor
2016-08-26 22:15:25 +02:00
asarium ef97279a67 Fix newly introduced warnings 2016-08-26 21:03:14 +02:00
asarium b064a84fd0 Use 64 bit build for appveyor
Nightly builds are still compiled as 32-bit build though.
2016-08-26 20:00:26 +02:00
Fabian Woltermann edecb1ca73 Merge pull request #844 from SamuelCho/opengl_core_materials
OpenGL Core, material draw system, and geometry batching rewrite
2016-08-26 19:07:32 +02:00
Risto Toijala 3040fb8c7a remove executable file permissions from sexp.{cpp,h} 2016-08-26 15:13:01 +03:00
Risto Toijala a55b94b08a Refractor atol2 to remove my_errno. 2016-08-26 15:04:36 +03:00
Risto Toijala b898b04168 Refractor atof2 to remove my_errno. 2016-08-26 14:59:46 +03:00
Risto Toijala b12b56d13f Refractor atoi2 to remove my_errno. 2016-08-26 14:56:57 +03:00
SamuelCho ca91f8f49f Fixed incorrect texType assignment in nanovg header. 2016-08-26 01:41:59 -07:00
Fabian Woltermann 989f799766 Fix for parsing the no pierce flag (#890)
Removes "no pierce shields" from the `Weapon_Info_Flags[]` array as it's not actually a flag (fixes usage of it tripping an assertion).
2016-08-26 01:41:20 -07:00
Fabian Woltermann 4a418a6691 Merge pull request #888 from MageKing17/bugfix/beam-flag-parsing-logic
Fix minor problem with the logic for parsing the beam flag.
2016-08-26 09:00:11 +02:00
SamuelCho c6243cbfd9 Mopped up some graphics related warnings. 2016-08-25 23:04:47 -07:00
MageKing17 1a9867593b Fix minor problem with the logic for parsing the beam flag.
It was setting the Pierce_shields flag based on whether or not the Beam flag was set, rather than based on whether or not the beam flag was explicitly provided; as such, a TBM entry for a non-piercing beam that contained a "$Flags:" entry but didn't re-set "no pierce shields" could spontaneously regain its piercing status (explicitly setting "beam" again will re-add piercing, but this should match previous behavior).
2016-08-25 22:55:37 -07:00
SamuelCho e74af5ad53 Merge branch 'master' into opengl_core_materials 2016-08-25 21:43:14 -07:00
Fabian Woltermann 7ab516e715 Merge pull request #885 from asarium/warnings/fred64bit
Fix 64-bit warnings in FRED2
2016-08-26 06:30:39 +02:00
SamuelCho 6442307c27 Merge branch 'master' into opengl_core_materials 2016-08-25 20:04:14 -07:00
Fabian Woltermann fd1e10d29e Merge pull request #884 from asarium/fix/aiDestroyedBeforeMission
Mark ship destroyed before a mission as exited
2016-08-25 20:15:42 +02:00
asarium 1e534cfc9f Fix 64-bit warnings in FRED2 2016-08-25 14:50:46 +02:00
Fabian Woltermann 05abf8b041 Merge pull request #882 from asarium/ci/appveyorFatalWarnings
Turn Visual Studio warnings on Appveyor to errors
2016-08-25 12:26:42 +02:00
m!m fceaf9eb06 Merge pull request #870 from The-E/ai_info_flags
Ai info flags conversion
2016-08-25 12:22:07 +02:00
asarium d4186ba774 Mark ship destroyed before a mission as exited
This fixes an Int3 in the ai code where it couldn't find a ship that was
destroyed before a mission. This was found through a mission bug in
FreeSpace Blue "Slaying Ravana" where the "Somtus" is marked as
destroyed before mission but then the AI is given orders which target
that ship.
2016-08-25 12:19:22 +02:00
SamuelCho 6fd1f8fbb0 Merge branch 'opengl_core_materials' of https://github.com/SamuelCho/fs2open.github.com into opengl_core_materials 2016-08-24 21:57:23 -07:00
SamuelCho 9592e67af2 Quick size_t fix to a batching vertex loop. 2016-08-24 21:56:22 -07:00
SamuelCho 67916a4efb Cleaned up various warnings from orphaned variables or added by the new rendering code. 2016-08-24 21:28:24 -07:00
asarium edc7f9e5d5 Fix warnings 2016-08-24 20:48:23 +02:00
asarium 3b0e5d8c44 Make Visual Studio warnings fatal 2016-08-24 20:48:22 +02:00
Fabian Woltermann 0a67a788e4 Merge pull request #878 from asarium/fix/freelook
Fix issue with head tracking and freelook interaction
2016-08-24 13:05:34 +02:00
Fabian Woltermann 1f4a30395b Merge pull request #872 from asarium/cmake_/msvcReleaseDebug
Add CMake option for generating debuggable executables
2016-08-24 13:04:40 +02:00
Fabian Woltermann 61cf5bef9b Merge pull request #850 from asarium/warnings/more64bit
64-bit warning fixes...
2016-08-24 13:04:12 +02:00
Fabian Woltermann 01c1b308ca Merge pull request #881 from asarium/fix/debugCC
Use the APIENTRY calling convention for the debug callback
2016-08-24 13:03:48 +02:00
asarium 892c6f5c61 Use the APIENTRY calling convention for the debug callback 2016-08-24 11:08:36 +02:00
Fabian Woltermann 09e379214a Merge pull request #818 from asarium/cleanup/pstypes
Cleanup pstypes.h a bit
2016-08-24 08:20:53 +02:00
SamuelCho f595e94e82 Merge pull request #3 from asarium/ogl_core/merge
Merge materials branch with master
2016-08-23 20:39:50 -07:00
SamuelCho 1adf52bb04 Make sure we scale sphere meshes before rendering them. 2016-08-23 20:38:14 -07:00
MageKing17 a141e5d4f4 Merge pull request #877 from The-E/weapon_flag_parsing_fix
Fixes an issue when parsing the weapon info flagset.
2016-08-23 14:47:19 -07:00
asarium 20beb2eec1 64-bit warning fixes... 2016-08-23 23:17:41 +02:00
asarium 782de278e5 Fix issue with head tracking and freelook interaction
Also adds code for detecting if the FreeTrack client is actually
reporting valid values. I only tested it with FaceTrackNoIR so it may
not work for other head trackers.
2016-08-23 22:29:15 +02:00
Fabian Woltermann e535cf566b Fix a few issues found while reviewing, thanks MageKing 2016-08-23 22:01:57 +02:00
asarium c081e83aae Remove weird stamp checking code
For some reason, FRED has some code that checks a checksum and if it
doesn't match it exits after a certain time with an obscure error
message. It doesn't affect us since the checksum is always right but it
was probably some kind of DRM at some point.
2016-08-23 16:35:40 +02:00
asarium beb9288c73 Merge branch 'opengl_core_materials' of https://github.com/SamuelCho/fs2open.github.com into ogl_core/merge
Conflicts:
	code/graphics/gropengl.cpp
	code/io/cursor.cpp
	freespace2/SDLGraphicsOperations.cpp
2016-08-23 16:05:28 +02:00
Fabian Woltermann 4fa09480c4 Merge pull request #849 from asarium/wxFRED/viewportInterface
Add interface for viewport management
2016-08-23 15:51:12 +02:00
asarium ef1e1e5551 Remove unused macros 2016-08-23 15:45:06 +02:00
asarium 09e32c0b3c Turn macro into function 2016-08-23 15:45:05 +02:00
asarium c72015394d Remove compatibility files 2016-08-23 15:45:04 +02:00
asarium 04a8262712 Remove HARDWARE_ONLY define 2016-08-23 15:45:03 +02:00
asarium cd598a1cf8 Move 64-bit detection to CMake 2016-08-23 15:45:02 +02:00
Fabian Woltermann 2c6576b162 Merge pull request #838 from asarium/cleanup/config_h
Cleanup config.h a bit
2016-08-23 15:30:53 +02:00
Fabian Woltermann 444ae43aa4 Fixes an issue when parsing the weapon info flagset. 2016-08-23 14:37:43 +02:00
MageKing17 56870dd5c5 Merge pull request #876 from asarium/fix/weaponFlagsParsing
Fix weapon flag parsing when +override is present
2016-08-23 05:32:03 -07:00
m!m 330882cad4 Merge pull request #875 from niffiwan/fix/coverity_1361824
Fix coverity 1361824
2016-08-23 14:27:06 +02:00
asarium a11b95ef56 Fix weapon flag parsing when +override is present 2016-08-23 13:41:28 +02:00
niffiwan 120385b819 Merge pull request #874 from asarium/fix/luaStackOverflow
Fix stack overflow reported by ASan
2016-08-23 20:48:48 +10:00
m!m 4e5b68149a Merge pull request #873 from niffiwan/fix/coverity_1361854
Fix Coverity 1361854
2016-08-23 12:48:06 +02:00
niffiwan 3f203b4d94 Fix coverity 1361824
Avoid potential uint overflow if joystick returns a range greater than
the maximum expected range. I guess this could also be fixed by
limiting raw to rng-1 (?)
2016-08-23 20:42:11 +10:00
asarium c94427ef2c Fix stack overflow reported by ASan
It's a small miracle that it worked but these changes should fix the
issue.
2016-08-23 11:32:41 +02:00
niffiwan 6158846438 Fix Coverity 1361854
Restore primitive sensors to Ship_flag_names[]
2016-08-23 19:24:24 +10:00
Fabian Woltermann 3e6022b000 Merge pull request #869 from asarium/fix/weaponsMemoryLeak
Fix memory leak reported by LeakSanitizer
2016-08-23 10:38:28 +02:00
Fabian Woltermann 3bcda9ae1f Merge pull request #863 from asarium/feature/nograb
Add -nograb commandline option
2016-08-23 10:38:10 +02:00
SamuelCho 7b2c7b6ccc Make sure distortions are rendered after the effect framebuffer is copied. 2016-08-22 20:49:09 -07:00
SamuelCho 537ddd9b4a Changed batcher data structure field types. Added shutdown function. 2016-08-22 20:33:06 -07:00
asarium 942817b4f6 Add CMake option for generating debuggable executables 2016-08-22 22:34:41 +02:00
asarium e8fe940287 Cleanup config.h 2016-08-22 22:17:34 +02:00
MageKing17 eb086dab3e Merge pull request #871 from The-E/subsys_mem_management_fix
Fixes breaking issues in subsystem memory management
2016-08-22 12:20:15 -07:00
MageKing17 40187b0bbc Merge pull request #868 from asarium/fix/fontHeapOverflow
Fix heap overflow reported by AddressSanitizer
2016-08-22 11:43:57 -07:00
MageKing17 8d1a03d087 Merge pull request #848 from z64555/fix/freelook1
Fix/freelook1
2016-08-22 11:42:01 -07:00
Fabian Woltermann 50c22d9457 Fixes breaking issues in subsystem memory management 2016-08-22 20:30:53 +02:00
Fabian Woltermann ee6d863f57 ai.h cleanup 2016-08-22 20:08:56 +02:00
Fabian Woltermann fe7a8aa3e9 Addressing feedback 2016-08-22 20:02:38 +02:00
Fabian Woltermann b6986087a3 not sure how these managed to slip through, but here we are 2016-08-22 17:54:53 +02:00
Fabian Woltermann c1cc83e363 more cleanup 2016-08-22 16:42:29 +02:00
Fabian Woltermann 791b7cc7b8 Cleanup 2016-08-22 16:41:26 +02:00
Fabian Woltermann add8662737 Converts AI Info flags 2016-08-22 16:39:42 +02:00
Fabian Woltermann 10e7aba7c0 Converts AI Info flags 2016-08-22 16:33:59 +02:00
m!m f59134d191 Merge pull request #859 from The-E/model_flags
Converts model flags
2016-08-22 14:25:35 +02:00
Fabian Woltermann adcc3327ae Addressing some feedback 2016-08-22 13:33:13 +02:00
Fabian Woltermann ed84ac348e Merge with master 2016-08-22 11:37:50 +02:00
Fabian Woltermann 607bc02c79 Merge pull request #867 from asarium/test/cotire
Enable cotire by default for Visual Studio
2016-08-22 11:34:21 +02:00
m!m 38fb41909b Merge pull request #861 from The-E/ai_profile_flags
Ai profile flags converted
2016-08-22 11:32:55 +02:00
asarium a3e458ba49 Fix memory leak reported by LeakSanitizer 2016-08-22 11:28:51 +02:00
asarium 043c1aef11 Fix heap overflow reported by AddressSanitizer 2016-08-22 11:17:32 +02:00
Fabian Woltermann 10e88b7f57 Merge pull request #812 from Goober5000/SIF_BALLISTIC_PRIMARIES_removal
remove the SIF_BALLISTIC_PRIMARIES flag
2016-08-22 09:22:57 +02:00
z64555 4ec4de1d43 Moves player_set_padlock_state()'s code into do_view_slew() and deletes player_set_padlock_state();
* Moves a camera lock statement into do_view_chase() to coincide with do_view_slew()'s style;
* Resets camera angles when transitioning into chase and external views from target padlock view;
2016-08-21 18:42:11 -05:00
z64555 9bce334c65 Move Padlock view angle modification to view_modify() 2016-08-21 18:41:07 -05:00
Goober5000 795bb86148 additional tweaks for WIF flag refactoring 2016-08-21 18:02:20 -04:00
Goober5000 d87babfd92 remove the SIF_BALLISTIC_PRIMARIES flag
See also my comments on #762.  The flag is almost entirely redundant, so this PR removes it in all instances where it's used in the ballistic primaries code.  There are one or two places where removing it was not a no-op, so I adjusted the rest of the code accordingly (most notably in the parsing validation when it checks that primary weapon cargo has been assigned).  I also added a few divide-by-zero checks and slightly tweaked the support ship rearm code.  The use of the SIF_BALLISTIC_PRIMARIES flag in the ingame_join code was replaced with a dummy value to avoid bumping the multiplayer packet version number.
2016-08-21 17:38:42 -04:00
SamuelCho e43e7e8534 Enable distortions again in gameplay. 2016-08-21 12:43:45 -07:00
SamuelCho b3b825470d Merge pull request #2 from asarium/ogl_core/fixes2
Use core functionality instead of extensions
2016-08-21 11:53:17 -07:00
asarium c74eb9a88b Enable cotire by default for Visual Studio 2016-08-21 16:54:07 +02:00
asarium fc92dba498 Disable forward compatibility bit 2016-08-21 11:50:55 +02:00
asarium 1876e3f219 Merge branch 'opengl_core_materials' of https://github.com/SamuelCho/fs2open.github.com into ogl_core/fixes2 2016-08-21 11:47:15 +02:00
SamuelCho 5ffcdb5de4 Fixed the light shafts fragment shader texcoord input. 2016-08-21 02:26:56 -07:00
SamuelCho 151081e533 Fixed shadowed variables in model_render_insignias. 2016-08-20 22:17:00 -07:00
SamuelCho 637d0fb1dd Removed unneccesary color variable in the model material setup function. 2016-08-20 21:57:28 -07:00
SamuelCho 75ae6ba4db Removed experimental uniform handling code. 2016-08-20 21:31:43 -07:00
SamuelCho e41b115a59 Fixed byte offset cast to pointer in opengl_render_primitives. 2016-08-20 21:26:15 -07:00
SamuelCho 08793c9231 Removed shadowed variable references from the materials code. Removed vestigal OpenGL vertex component code. 2016-08-20 20:52:17 -07:00
SamuelCho 311cf769df Reconciled bit flags. 2016-08-20 19:39:10 -07:00
SamuelCho 1e22118b39 Eliminated the no GLSL and no VBOs flags. 2016-08-20 19:18:50 -07:00
SamuelCho 89046b536a Fixed use of erroneous frame number for rendering shockwave distortions. 2016-08-20 17:36:57 -07:00
SamuelCho 27a1bb564e Convert shaders to pure core shaders. Eliminated compatibility shader preprocessors. Set minimum required GL version to 3.2. 2016-08-20 17:33:04 -07:00
asarium cb11e6bcd2 Only set OpenGL line width if it's valid 2016-08-20 21:44:20 +02:00
asarium 1f1d6ceecf Remove extensions that are included in OpenGL Core 2016-08-20 21:43:48 +02:00
Fabian Woltermann be12b629a1 Merge pull request #866 from rtoijala/fix/deferred-lighting-shader
Fix deferred lighting shader compilation
2016-08-20 20:44:22 +02:00
Fabian Woltermann c57e59d76a Addressing feedback 2016-08-20 20:42:22 +02:00
asarium 3c1cf4e963 Use a forward compatible context 2016-08-20 20:38:43 +02:00
asarium c74f540ed5 Fix bmpman assertion 2016-08-20 20:38:27 +02:00
Risto Toijala 16883beeb0 Fix deferred lighting shader compilation 2016-08-20 17:31:54 +03:00
m!m a34bcd60ed Merge pull request #852 from The-E/weapon_flags
Weapon flags
2016-08-20 15:57:05 +02:00
m!m 4f58758234 Merge pull request #864 from rtoijala/fix/remove-debug-window-leftovers
Remove leftovers of -debug_window cmdline arg
2016-08-20 15:55:54 +02:00
Risto Toijala 204bb600ab Remove leftovers of -debug_window cmdline arg 2016-08-20 16:15:51 +03:00
asarium c0a120106b Add -nograb commandline option
This disables all mouse grabbing which is useful for debugging when SDL gets interrupted without giving up
control of the mouse. That usually leads to problems since you can't
interact with the debugger window anymore.
2016-08-20 15:01:50 +02:00
asarium f7de25b73c Merge branch 'master' into ogl_core/fixes 2016-08-20 15:00:17 +02:00
asarium af2696e71d Update GLAD config 2016-08-20 13:45:16 +02:00
asarium a51197eaae Remove shader compatibility
This makes the shaders compile on the Linux Mesa drivers.
2016-08-20 13:44:32 +02:00
asarium 0567e9286f Fix invalid usage of GL_ALPHA 2016-08-20 13:43:57 +02:00
asarium a03452eaf1 Fix OpenGL Context creation code 2016-08-20 13:39:23 +02:00
Fabian Woltermann 325442207c Addressing feedback 2016-08-20 12:57:32 +02:00
Fabian Woltermann bf93beb33e Merge pull request #854 from asarium/feature/jsonPilot
Add option for writing pilot files in JSON format
2016-08-20 09:13:49 +02:00
m!m b2b504cca3 Merge pull request #860 from The-E/missionmessage_fix
Fixes an assert that got inadvertently inverted
2016-08-19 23:16:58 +02:00
Fabian Woltermann c72376b0c6 Fix compilation 2016-08-19 22:54:42 +02:00
Fabian Woltermann 69f33c5d95 Fixes an assert that got inadvertently inverted 2016-08-19 22:45:35 +02:00
Fabian Woltermann 0591b7ef49 ai profile flags 2016-08-19 22:44:39 +02:00
Fabian Woltermann 9942bf7e19 Add to cmake 2016-08-19 21:12:21 +02:00
Fabian Woltermann 1471cfac38 Adds ai_flags master file 2016-08-19 21:11:57 +02:00
Fabian Woltermann 90a2644d62 More cleanup 2016-08-19 21:08:14 +02:00
Fabian Woltermann 6a1aa4c5d3 More cleanup 2016-08-19 20:59:01 +02:00
Fabian Woltermann 5ed8fb87b1 Merge pull request #857 from rtoijala/fix/mkdir
Fix _mkdir on non-Windows
2016-08-19 20:46:39 +02:00
Risto Toijala c1307fc213 Fix _mkdir on non-Windows
_mkdir was horribly broken. It was creating all directories in the given
path but failed to create the actually wanted last portion.

On Windows, _mkdir only creates the last portion.

Fix this by simply calling mkdir, which does the Right Thing (TM).
2016-08-19 20:45:39 +03:00
Fabian Woltermann 9f27973147 Fixes various bugs 2016-08-19 19:23:55 +02:00
Fabian Woltermann 2a1deb1a76 Merge pull request #856 from rtoijala/fix/weapon-flag-parsing
Fix weapon flag parsing
2016-08-19 19:10:13 +02:00
asarium 41e370fd2e Add option for writing pilot files in JSON format
This is a new implementation of the JSON dumping which was already
proposed in #22 but this version tries to allow implementing both
reading and writing JSON files without having to change the existing
code too much. This is done by using an abstract class to hide the
differences between writing the JSON and binary files.

This is currently only capable of writing the files but not reading them
so if the option is enabled all changes to the pilot file are lost. I
will implement reading after this PR has been merged since I would like
to reduce the amount of changes that need to be reviewed.
2016-08-19 18:48:29 +02:00
Risto Toijala 5d96e49354 Fix weapon flag parsing
Starting with git 127976c (#851), FSO fails to start, displaying an
error. This is my attempt to fix it. FSO starts, but I do not know how
to check that the flags are parsed correctly.
2016-08-19 19:19:46 +03:00
asarium efdd4fae68 Add interface for viewport management
This separates OpenGL context creation from window creation and also
allows to implement multiple viewports in the future.
2016-08-19 17:44:17 +02:00
Fabian Woltermann 1acfaa8157 Converts model subsystem flags 2016-08-19 14:59:15 +02:00
asarium 02670f5558 Merge branch 'opengl_core_materials' of https://github.com/SamuelCho/fs2open.github.com into SamuelCho-opengl_core_materials 2016-08-19 11:31:33 +02:00
SamuelCho 789b694519 Rename glIsFramebufferEXT hiding in Assert. 2016-08-19 02:20:57 -07:00
asarium 5d570f6d84 Merge branch 'opengl_core_materials' of https://github.com/SamuelCho/fs2open.github.com into SamuelCho-opengl_core_materials 2016-08-19 11:14:13 +02:00
SamuelCho 2022f6a792 Replaced GLAD loader with 4.1 Core specification. Removed traces of fixed function rendering code. 2016-08-19 02:12:47 -07:00
Fabian Woltermann 941129f460 weapon.h cleanup 2016-08-19 09:26:57 +02:00
Fabian Woltermann 1a060aa6d7 Converts the other weapon flags 2016-08-19 09:24:54 +02:00
Fabian Woltermann 127976cd74 Weapon info flags conversion (#851) 2016-08-18 23:17:41 -07:00
SamuelCho fb30819765 Fixed shaders with unneeded semicolons 2016-08-18 06:35:04 -07:00
m!m e9cc4601eb Merge pull request #846 from MageKing17/bugfix/freetrack-empty-string-check
Add a check for an empty string to the freetrack loading code.
2016-08-18 09:34:53 +02:00
z64555 1e40f71ff0 * Renames VM_EXTERNAL_CAMERA_LOCKED into VM_CAMERA_LOCKED and uses it for both freelook and external views. (Replaces slew_active)
* Adds VM_CENTERING to replace view_centering
* view_modify() now takes care of centering the view
* Reorganized view-related controls and logic to be cleaner
2016-08-18 01:00:10 -05:00
MageKing17 780035657a Add a check for an empty string to the freetrack loading code.
If "value" is empty, then attempting to access "value[value.length() - 1]" is equivalent to trying to access "value[-1]", which is an out-of-bounds access (causing debug builds to complain and undefined behavior).
2016-08-17 16:46:53 -07:00
Fabian Woltermann 3648b47570 Merge pull request #845 from MageKing17/bugfix/sexp-msec-overflow
Fix overflow problem accidentally introduced to is-event-*-msecs-delay.
2016-08-17 22:01:32 +02:00
MageKing17 20cd5111ac Fix overflow problem accidentally introduced to is-event-*-msecs-delay.
When PR #831 got rid of a warning in sexp_event_delay_status(), it did so by getting rid of the 64-bit temporary variable (in order to get rid of a warning in the non-use_msecs branch). However, that 64-bit variable was protecting against overflow when using numbers of milliseconds >= 65535, which are used by e.g. the Icarus cutscene mission from Blue Planet, leading to interesting (but wrong) behavior.

This restores usage of the uint64_t temporary variable by reverting that specific change, but then avoids the warning by moving that temporary variable to be inside the use_msecs branch; I get no warnings when compiling this version of sexp.cpp, and Icarus works again.
2016-08-17 12:33:30 -07:00
asarium e92dccb21b Merge branch 'opengl_core_materials' of https://github.com/SamuelCho/fs2open.github.com into SamuelCho-opengl_core_materials 2016-08-17 17:45:21 +02:00
MageKing17 2081647443 Merge pull request #841 from The-E/distortion_framebuffere_fix
Fixes issue with framebuffer initialization
2016-08-17 05:50:09 -07:00
Fabian Woltermann 98f72f9378 Finishes converting the remaining ship-related flags (#843) 2016-08-17 05:49:40 -07:00
SamuelCho a481999a24 OpenGL Core support. Introduction of material based draw system. Rewrote geometry batcher. 2016-08-17 00:13:19 -07:00
MageKing17 d840f9d0c7 Merge pull request #842 from asarium/fix/fsanitize
Fix -fsanitize flag setting
2016-08-16 15:48:50 -07:00
z64555 c2b6417372 [Cleanup] Changes player_set_padlock_state() to take parameters instead of directly operating on globals. 2016-08-16 16:24:42 -05:00
asarium 9cc654909c Fix -fsanitize flag setting 2016-08-16 22:51:03 +02:00
Fabian Woltermann 42394bf723 Fixes issue with framebuffer initialization 2016-08-16 18:10:06 +02:00
Fabian Woltermann 37c6413fa0 Merge pull request #837 from MageKing17/bugfix/joystick-issues
Fix a couple joystick issues.
2016-08-16 16:23:17 +02:00
Fabian Woltermann e55718caa7 Merge pull request #840 from scp-fs2open/revert-839-fix/freelok
Revert "Fix FreeTrack and headtracking"
2016-08-16 16:21:29 +02:00
Fabian Woltermann 59f3ef6fab Revert "Fix FreeTrack and headtracking" 2016-08-16 16:21:17 +02:00
Fabian Woltermann f7bbea248c Merge pull request #839 from asarium/fix/freelok
Fix FreeTrack and headtracking
2016-08-16 16:18:00 +02:00
asarium 94412da2de Fix FreeTrack and headtracking 2016-08-16 15:44:40 +02:00
m!m 31fdcfdfbb Merge pull request #806 from The-E/ship_weapon_flags
Converts the flags of ship_weapon to use the new flag system
2016-08-16 11:37:01 +02:00
Fabian Woltermann ed974844e4 Merge pull request #795 from asarium/cmakeMerge/freetrack
Add improved head tracking code
2016-08-16 11:33:06 +02:00
MageKing17 5886bf4c80 Re-restore force feedback.
The new joystick API (commit f91c681ee1) didn't include calls to joy_ff_init() and joy_ff_shutdown(), disabling haptic support. Simply restoring these calls was enough to make it work on my system again.
2016-08-16 01:37:29 -07:00
MageKing17 a33502d5aa Treat an empty joystick GUID as though no GUID were set.
If CurrentJoystickGUID was present but set to an empty string, the new code was comparing all joystick GUIDs against the empty string, and therefore concluding that no joystick was currently selected. This just treats an empty string as though CurrentJoystickGUID weren't set at all, allowing the index-based CurrentJoystick to take over.
2016-08-16 01:35:54 -07:00
Fabian Woltermann 418c47e426 Merge with master 2016-08-16 09:58:09 +02:00
MageKing17 384b4b9413 Merge pull request #834 from The-E/multi_server_version_bump
Bumps multi server version due to changes in the multiplayer sexp code
2016-08-15 23:39:48 -07:00
Fabian Woltermann 8248ac2516 Encapsulates the multi_sexp infrastructure in its own class (#833)
While working on #824, I found out that cleaning up that particular piece of code would not be doable cleanly without a refactor of the multi_sexp infrastructure. This is that refactor; it encapsulates the code of multi_sexp inside a class, an instance of which is then used to manage all the network stuff that sexps need to do.
2016-08-15 23:39:40 -07:00
MageKing17 e108f555c3 Merge pull request #835 from asarium/fix/awacsBug
Fix wrong condition introduced by #829
2016-08-15 23:39:03 -07:00
asarium 925e8df36e Fix wrong condition introduced by #829 2016-08-15 22:21:10 +02:00
MageKing17 8f4972aab9 Merge pull request #618 from Karajorma/RemoveOldSEXPPackets
Remove several packets used in multiplayer that can now be handled by…
2016-08-15 12:52:11 -07:00
Fabian Woltermann e0314eecd0 Bumps multi server version due to changes in the multiplayer sexp code 2016-08-15 21:42:38 +02:00
Fabian Woltermann 5b29d5449b Merge pull request #831 from asarium/warnings/evenmore64bit
And another batch of warning fixes
2016-08-15 20:45:41 +02:00
Fabian Woltermann 8c939d0050 Merge pull request #814 from asarium/fix/selectedJoystick
Refine joystick selection
2016-08-15 20:44:52 +02:00
Fabian Woltermann 26c189aa73 Merge pull request #828 from asarium/unittests/msvcFolders
Fix Visual studio solution folders
2016-08-15 20:43:53 +02:00
Fabian Woltermann 5ffe4b3168 Merge pull request #829 from asarium/feature/flagsetMultiple
Add support for indexing flagset with multiple flags
2016-08-15 20:43:37 +02:00
Fabian Woltermann 22f92bad55 Merge pull request #832 from z64555/fix/freelook1
Fixes an issue where the regular padlock view was disabled.
2016-08-15 20:43:21 +02:00
z64555 84a16c72ff Fixes an issue where the regular padlock view was disabled. 2016-08-15 13:06:57 -05:00
asarium 0a7800d3ea And another batch of warning fixes 2016-08-15 18:55:35 +02:00
asarium 9f26c51d47 Fix unit test checks for the new logic operations 2016-08-15 16:55:10 +02:00
asarium bf6d3aac07 Fix GCC test compilation 2016-08-15 16:23:46 +02:00
asarium 9aff8d9b62 Fix logic operation 2016-08-15 16:22:39 +02:00
m!m 02ecdf6cf7 Merge pull request #817 from The-E/aiming_flags
Changes aiming flags to the new system
2016-08-15 15:29:26 +02:00
m!m d637ccd8ed Merge pull request #816 from The-E/ship_exit_flags
Changes ship exit flags to the new system
2016-08-15 15:28:13 +02:00
asarium 25e0209026 Add unit tests for multiple flag checks 2016-08-15 15:24:55 +02:00
asarium 86cdb905db Add support for indexing flagset with multiple flags
This uses the , operator for combining the flag values.
2016-08-15 15:24:48 +02:00
Fabian Woltermann 4e410f56e6 Merge pull request #826 from asarium/build/gccfsanitize
Add option for enabling AddressSanizizer in gcc
2016-08-15 15:22:49 +02:00
Fabian Woltermann 5bc8837298 Merge pull request #827 from asarium/unittests/windowsFix
Fix Windows unit tests
2016-08-15 15:22:20 +02:00
asarium 4cc9118b4d Fix Visual studio solution folders 2016-08-15 15:06:47 +02:00
asarium 1258067264 Fix Windows unit tests 2016-08-15 14:27:09 +02:00
Fabian Woltermann e1da184702 Merge pull request #825 from asarium/unittests/initial
Add unit test setup
2016-08-15 14:13:37 +02:00
asarium fa30cd9028 Add option for enabling AddressSanizizer in gcc 2016-08-15 11:57:12 +02:00
asarium 4274a6da76 Add unit test setup 2016-08-15 11:40:08 +02:00
asarium 8f034b08d4 Refine joystick selection
This uses the device-id as a tie-breaker if more than one joystick in
the system have the same GUID.
2016-08-14 20:26:03 +02:00
Fabian Woltermann 43b68c5b22 Changes aiming flags to the new system 2016-08-14 16:59:22 +02:00
Fabian Woltermann 3160bdaa00 Changes ship exit flags to the new system 2016-08-14 16:48:11 +02:00
asarium 4e1334dbd2 Add code for printing information about connected joysticks 2016-08-14 12:32:09 +02:00
asarium 60afa1431a Add improved head tracking code
This adds an abstraction layer over the previous TrackIR implementation
and also adds an interface for the FreeTrack protocol.
2016-08-13 21:43:23 +02:00
Fabian Woltermann 64153da3bd Converts the flags of ship_weapon to use the new flag system 2016-08-13 10:42:47 +02:00
Karajorma bcf007376d Remove several packets used in multiplayer that can now be handled by the SEXP packet system instead. 2016-06-02 12:20:07 +08:00
936 changed files with 104608 additions and 70595 deletions

No files matched your search

+3
View File
@@ -2,3 +2,6 @@ root = true
[*.{h,cpp}]
indent_style = tab
[*.sdr]
indent_style = tab
+5
View File
@@ -281,3 +281,8 @@ documentation/doxygen/*
.idea/*
projects/*
/.vs
CMakeSettings.json
# Weird files created by Linux
.fuse_hidden*
+3 -5
View File
@@ -9,15 +9,13 @@ addons:
packages:
- ninja-build
- libopenal-dev
- libogg-dev
- libvorbis-dev
- libtheora-dev
- libreadline6-dev
- libpng12-dev
- libjpeg62-dev
- liblua5.1-0-dev
- libjansson-dev
- libsdl2-dev
- valgrind
coverity_scan:
project:
name: "scp-fs2open/fs2open.github.com"
@@ -29,13 +27,13 @@ deploy:
- provider: releases
api_key:
secure: "Wdt4Ccefo7a0ZDjEJQJgpghh7n72FtNJuKSAPUvoz4gtEX6Ct9J8yJI1t9V3jE3CTbbLJ21/Q6eZRDfT7UfNJe5DdepoJsP9DeFhKMWqQCq+AChqQWlm0KeZAffJoJreL8vXYhnRYcLT9ceZHEH6AqwN9TPV+xJziGPISAkYNZ8="
skip_cleanup: true
skip_cleanup: true
file_glob: true
file: "/tmp/builds/*"
on:
condition: '"$RELEASE_BUILD" == true'
tags: true
- provider: bintray
user: sirknightly
key:
+9 -8
View File
@@ -81,6 +81,8 @@ ENDIF(WIN32)
OPTION(FSO_BUILD_TOOLS "Build tools related to FSO" OFF)
OPTION(FSO_BUILD_TESTS "Build unit tests" OFF)
OPTION(FSO_DEVELOPMENT_MODE "Generate binaries in development mode, only use if you know what you're doing!" OFF)
OPTION(FSO_BUILD_WXFRED2 "Build wxFRED2 binary" OFF)
@@ -106,21 +108,16 @@ SET(FSO_RUN_ARGUMENTS "" CACHE STRING "Additional arguments passed to a generate
option(FSO_INSTALL_DEBUG_FILES "Install some debug files (currently only PDB files on windows)" OFF)
OPTION(COTIRE_ENABLE "Enable cotire, this speeds up builds but may cause issues while developing (default = OFF)" OFF)
MARK_AS_ADVANCED(FORCE FSO_CMAKE_DEBUG)
MARK_AS_ADVANCED(FORCE FSO_BUILD_INCLUDED_LIBS)
MARK_AS_ADVANCED(FORCE FSO_USE_OPENALSOFT)
MARK_AS_ADVANCED(FORCE FSO_USE_LUAJIT)
MARK_AS_ADVANCED(FORCE FSO_DEVELOPMENT_MODE)
MARK_AS_ADVANCED(FORCE FSO_FATAL_WARNINGS)
MARK_AS_ADVANCED(FORCE COTIRE_ENABLE)
mark_as_advanced(FORCE FSO_INSTALL_DEBUG_FILES)
IF(COTIRE_ENABLE)
# Include cotire file from https://github.com/sakra/cotire/
include(cotire)
ENDIF(COTIRE_ENABLE)
# Include cotire file from https://github.com/sakra/cotire/
include(cotire)
INCLUDE(globals)
INCLUDE(toolchain)
@@ -154,6 +151,10 @@ IF(FSO_BUILD_WXFRED2)
ADD_SUBDIRECTORY(wxfred2)
ENDIF(FSO_BUILD_WXFRED2)
if(FSO_BUILD_TESTS)
add_subdirectory(test)
endif()
if ("${CMAKE_VERSION}" VERSION_GREATER "3.5")
# Default to using Freespace2 as startup project if CMake supports it.
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT Freespace2)
@@ -183,4 +184,4 @@ elseif(UNIX)
ENDIF()
message(STATUS "Building FSO tools: ${FSO_BUILD_TOOLS}")
message(STATUS "Building wxFRED: ${FSO_BUILD_WXFRED2}")
message(STATUS "Fatal warnings: ${FSO_FATAL_WARNINGS}")
message(STATUS "Fatal warnings: ${FSO_FATAL_WARNINGS}")
+6 -2
View File
@@ -1,10 +1,13 @@
FreeSpace2 *S*ource *C*ode *P*roject
==
[![Build Status](https://travis-ci.org/scp-fs2open/fs2open.github.com.svg?branch=master)](https://travis-ci.org/scp-fs2open/fs2open.github.com)
[![Travis-CI Build Status](https://travis-ci.org/scp-fs2open/fs2open.github.com.svg?branch=master)](https://travis-ci.org/scp-fs2open/fs2open.github.com)
[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/scp-fs2open/fs2open.github.com?branch=master&svg=true)](https://ci.appveyor.com/project/SirKnightly/fs2open-github-com/branch/master)
[![Coverity](https://img.shields.io/coverity/scan/870.svg)](https://scan.coverity.com/projects/870)
Building
--
Before you do anything, make sure you have updated your git submodules, either by running `git submodule update --init --recursive` or by cloning the repository with the `--recursive` flag.<br/>
<br/>
For building you will need [CMake](http://www.cmake.org/cmake/resources/software.html). Version 3.4 is required. Once you have installed CMake you should create a build directory where the project/make files should be created, **do not create them inside the source tree!**<br>
<br>
On Windows you can use the `cmake-gui` executable to get a nice GUI, on Unix just use `cmake`. Use the newly created directory as build directory (change to this directory on Unix) and run cmake. On Windows this can be done by clicking the `Configure` button. Choose your compiler version and hit `Generate` when configuring is done. <br>
@@ -14,6 +17,7 @@ Depending on the makefile generator used build the `all` or `ALL_BUILD` target t
* `FSO_BUILD_WXFRED2`: Build the wxfred2 project, requires wxWidgets
* `FSO_FREESPACE_PATH`: Sets the path of your FreeSpace install, can be used to automatically run the generated executables with the correct working directory, this is an optional variable. By default this will use the value of the `FS2PATH` environment variable.
* `FSO_BUILD_TOOLS`: Build some tools related to FSO
* `CMAKE_BUILD_TYPE`: Sets the binary build type between `Debug` and `Release` (default)
#### Windows only variables
* `FSO_BUILD_FRED2`: Build FRED2, requires a Visual Studio version that ships with MFC
@@ -35,4 +39,4 @@ You should only use these variables if you know what you're doing
* `MSVC_SIMD_INSTRUCTIONS`: The instruction set the executables will be optimized for.
### Generating an installation package
CMake can automaticall generate installation packages of the project. To do this you will just need to run the `package` target of the build system and the package will be placed inside your build directory. On Windows you will have to install [NSIS](http://nsis.sourceforge.net/Main_Page) to use this.
CMake can automatically generate installation packages of the project. To do this you will just need to run the `package` target of the build system and the package will be placed inside your build directory. On Windows you will have to install [NSIS](http://nsis.sourceforge.net/Main_Page) to use this.
+6 -7
View File
@@ -5,19 +5,18 @@ configuration:
clone_depth: 10
environment:
matrix:
- VS_VERSION: 12
- BuildID: 0
CMAKE_GENERATOR: Visual Studio 12 2013
PlatformToolset: v120_xp
- VS_VERSION: 14
CMAKE_GENERATOR: Visual Studio 14 2015
- BuildID: 1
CMAKE_GENERATOR: Visual Studio 14 2015 Win64
PlatformToolset: v140_xp
before_build:
- git submodule update --init --recursive
- ps: . $Env:APPVEYOR_BUILD_FOLDER/ci/appveyor/check_release.ps1
- ps: . $Env:APPVEYOR_BUILD_FOLDER/ci/appveyor/before_build.ps1
build_script:
- ps: . $Env:APPVEYOR_BUILD_FOLDER/ci/appveyor/build.ps1
test_script:
- ps: . $Env:APPVEYOR_BUILD_FOLDER/ci/appveyor/test.ps1
deploy:
- provider: GitHub
@@ -37,4 +36,4 @@ deploy:
publish: true
override: true
on:
NightlyBuild: true # deploy on nightly push only
NightlyBuild: true # deploy on nightly push only
-5
View File
@@ -1,5 +0,0 @@
New-Item build -type directory
Set-Location -Path build
cmake -DCMAKE_INSTALL_PREFIX="$env:APPVEYOR_BUILD_FOLDER/../install" -DFSO_USE_SPEECH="ON" `
-DFSO_USE_VOICEREC="ON" -DMSVC_SIMD_INSTRUCTIONS=SSE2 -G "$Env:CMAKE_GENERATOR" -T "$Env:PlatformToolset" ..
+102 -8
View File
@@ -1,12 +1,103 @@
write "$env:DeployBuild"
write "$env:DeployConfig"
class BuildConfig {
[string]$Generator
[string]$PackageType
[string]$Toolset
[string]$SimdType
}
if ([System.Convert]::ToBoolean($env:DeployBuild)) {
# Release build
if (![System.Convert]::ToBoolean($env:DeployConfig)) {
exit 0 # End the build
$NightlyConfigurations = @(
[BuildConfig]@{
Generator="Visual Studio 14 2015 Win64";
PackageType="Win64";
Toolset="v140_xp";
SimdType="SSE2";
},
[BuildConfig]@{
Generator="Visual Studio 14 2015";
PackageType="Win32";
Toolset="v140_xp";
SimdType="SSE2";
}
)
$ReleaseConfigurations = @(
[BuildConfig]@{
Generator="Visual Studio 14 2015";
PackageType="Win32";
Toolset="v140_xp";
SimdType="SSE2";
}
[BuildConfig]@{
Generator="Visual Studio 14 2015";
PackageType="Win32-AVX";
Toolset="v140_xp";
SimdType="AVX";
}
[BuildConfig]@{
Generator="Visual Studio 14 2015 Win64";
PackageType="Win64";
Toolset="v140_xp";
SimdType="SSE2";
}
[BuildConfig]@{
Generator="Visual Studio 14 2015 Win64";
PackageType="Win64-AVX";
Toolset="v140_xp";
SimdType="AVX";
}
)
$BuildConfigurations = $null
# Default values
$ReleaseBuild = $false
$NightlyBuild = $false
$DeployBuild = $false
if ([System.Convert]::ToBoolean($env:APPVEYOR_REPO_TAG) -And ("$env:APPVEYOR_REPO_TAG_NAME" -match "^release_(.*)")) {
# Tag matches
$ReleaseBuild = $true
$PackageName = "fs2_open_$($matches[1])"
$BuildConfigurations = $ReleaseConfigurations
}
if ([System.Convert]::ToBoolean($env:APPVEYOR_REPO_TAG) -And ("$env:APPVEYOR_REPO_TAG_NAME" -match "^nightly_(.*)")) {
# Tag matches
$NightlyBuild = $true
$PackageName = "nightly_$($matches[1])"
Set-AppveyorBuildVariable 'VersionName' "$($matches[1])"
$BuildConfigurations = $NightlyConfigurations
}
# Multiply by 2 so that we can add 0 or 1 for debug or release Configs
$buildID = [convert]::ToInt32($env:BuildID) * 2
if ($Env:Configuration -eq "Release") {
$buildID = $buildID + 1
}
Write-Host "$buildID"
if ($ReleaseBuild -Or $NightlyBuild) {
$DeployBuild = $true
}
Set-AppveyorBuildVariable 'ReleaseBuild' "$ReleaseBuild"
Set-AppveyorBuildVariable 'NightlyBuild' "$NightlyBuild"
New-Item build -type directory
Set-Location -Path build
if ($DeployBuild) {
# Release build
if ($buildID -ge $BuildConfigurations.Length) {
# Not needed
exit 0
}
$buildConfig = $BuildConfigurations[$buildID]
cmake -DCMAKE_INSTALL_PREFIX="$env:APPVEYOR_BUILD_FOLDER/../install" -DFSO_USE_SPEECH="ON" `
-DFSO_USE_VOICEREC="ON" -DMSVC_SIMD_INSTRUCTIONS="$($buildConfig.SimdType)" `
-G "$($buildConfig.Generator)" -T "$($buildConfig.Toolset)" ..
$Configs = @("Release", "FastDebug")
foreach ($config in $Configs) {
@@ -17,9 +108,12 @@ if ([System.Convert]::ToBoolean($env:DeployBuild)) {
}
}
7z a "$($env:PackageName)-builds-Win32.zip" "$env:APPVEYOR_BUILD_FOLDER/../install/*"
Push-AppveyorArtifact "$($env:PackageName)-builds-Win32.zip"
7z a "$($PackageName)-builds-$($buildConfig.PackageType).zip" "$env:APPVEYOR_BUILD_FOLDER/../install/*"
Push-AppveyorArtifact "$($PackageName)-builds-$($buildConfig.PackageType).zip"
} else {
cmake -DFSO_USE_SPEECH="ON" -DFSO_FATAL_WARNINGS="ON" -DFSO_USE_VOICEREC="ON" -DFSO_BUILD_TESTS="ON" -DMSVC_SIMD_INSTRUCTIONS=SSE2 `
-G "$Env:CMAKE_GENERATOR" -T "$Env:PlatformToolset" ..
cmake --build . --config "$Env:CONFIGURATION" -- /verbosity:minimal
if (! ($?)) {
-30
View File
@@ -1,30 +0,0 @@
# Default values
Set-AppveyorBuildVariable 'ReleaseBuild' 'false'
Set-AppveyorBuildVariable 'NightlyBuild' 'false'
Set-AppveyorBuildVariable 'DeployBuild' 'false'
Set-AppveyorBuildVariable 'PackagePrefix' ''
Set-AppveyorBuildVariable 'VersionName' ''
if ([System.Convert]::ToBoolean($env:APPVEYOR_REPO_TAG) -And ("$env:APPVEYOR_REPO_TAG_NAME" -match "^release_(.*)")) {
# Tag matches
Set-AppveyorBuildVariable 'ReleaseBuild' 'true'
Set-AppveyorBuildVariable 'PackageName' "fs2_open_$($matches[1])"
}
if ([System.Convert]::ToBoolean($env:APPVEYOR_REPO_TAG) -And ("$env:APPVEYOR_REPO_TAG_NAME" -match "^nightly_(.*)")) {
# Tag matches
Set-AppveyorBuildVariable 'NightlyBuild' 'true'
Set-AppveyorBuildVariable 'PackageName' "nightly_$($matches[1])"
Set-AppveyorBuildVariable 'VersionName' "$($matches[1])"
}
if (($Env:Configuration -eq "Release") -And ($Env:VS_VERSION -eq "14")) {
Set-AppveyorBuildVariable 'DeployConfig' 'true'
} else {
Set-AppveyorBuildVariable 'DeployConfig' 'false'
}
if ([System.Convert]::ToBoolean($env:ReleaseBuild) -Or [System.Convert]::ToBoolean($env:NightlyBuild)) {
Set-AppveyorBuildVariable 'DeployBuild' 'true'
}
+26
View File
@@ -0,0 +1,26 @@
if ([System.Convert]::ToBoolean($env:ReleaseBuild) -Or [System.Convert]::ToBoolean($env:NightlyBuild)) {
# Skip tests for deployment
exit 0
} else {
# Appveyor doesn't have OpenAL so copy our DLLs to the output FOLDER
$arch=""
if ($Env:CMAKE_GENERATOR -Match "Win64") {
$arch="win64"
} else {
$arch="win32"
}
$dllPath = "$Env:APPVEYOR_BUILD_FOLDER\lib\openal\libs\$arch\OpenAL32.dll"
$copyDestination = "$pwd\bin\$Env:CONFIGURATION\"
write "Copying OpenAL DLL..."
Copy-Item "$dllPath" "$copyDestination"
write "Running unit tests..."
# Run unit tests
&"$pwd\bin\$Env:CONFIGURATION\unittests.exe" --gtest_shuffle 2>&1
if (! ($?)) {
exit 1
}
}
+18 -6
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env sh
#!/usr/bin/env bash
set -ex
@@ -6,21 +6,33 @@ mkdir -p build
cd build
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
export CXXFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
CXXFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
CFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
if [[ "$CC" =~ ^clang.*$ ]]; then
CXXFLAGS="$CXXFLAGS -stdlib=libc++"
fi
export CXXFLAGS
export CFLAGS
CMAKE="cmake -G Ninja -DFSO_FATAL_WARNINGS=ON"
if [ "$BUILD_DEPLOYMENT" = true ]; then
for config in $BUILD_CONFIGS
do
mkdir -p $config
cd $config
eval $CMAKE -DFSO_INSTALL_DEBUG_FILES=ON -DCMAKE_BUILD_TYPE=$config -DCMAKE_INSTALL_PREFIX="/tmp/release" \
eval $CMAKE -DFSO_INSTALL_DEBUG_FILES=ON -DCMAKE_BUILD_TYPE=$config -DCMAKE_INSTALL_PREFIX="/tmp/release/$config" \
-DFSO_BUILD_APPIMAGE=ON -DAPPIMAGE_ASSISTANT="$HOME/AppImageAssistant" \
-DFSO_BUILD_INCLUDED_LIBS=ON ../..
-DFSO_BUILD_INCLUDED_LIBS=ON -DFFMPEG_USE_PRECOMPILED=ON ../..
cd ..
done
else
eval $CMAKE -DCMAKE_BUILD_TYPE=$CONFIGURATION ..
eval $CMAKE -DCMAKE_BUILD_TYPE=$CONFIGURATION -DFSO_BUILD_TESTS=ON -DFSO_BUILD_INCLUDED_LIBS=ON ..
fi
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
cmake -G "Xcode" -DFSO_FATAL_WARNINGS=ON -DFSO_INSTALL_DEBUG_FILES=ON -DCMAKE_INSTALL_PREFIX="/tmp/release" ..
if [ "$BUILD_DEPLOYMENT" = true ]; then
cmake -G "Xcode" -DFSO_FATAL_WARNINGS=ON -DFSO_INSTALL_DEBUG_FILES=ON -DCMAKE_INSTALL_PREFIX="/tmp/release" ..
else
cmake -G "Xcode" ..
fi
fi
+9 -5
View File
@@ -10,15 +10,19 @@ PACKAGE_NAME=""
RELEASE_PATTERN="^release_(.*)$"
NIGHTLY_PATTERN="^nightly_(.*)$"
if [[ "$TRAVIS_TAG" =~ $RELEASE_PATTERN ]]; then
# These are for testing
NIGHTLY_TEST=false
RELEASE_TEST=false
if [ "$RELEASE_TEST" = true ] || [[ "$TRAVIS_TAG" =~ $RELEASE_PATTERN ]]; then
echo "This is a release tag!";
RELEASE_BUILD=true;
PACKAGE_NAME="fs2_open_${BASH_REMATCH[1]}";
fi
if [[ "$TRAVIS_TAG" =~ $NIGHTLY_PATTERN ]]; then
if [ "$NIGHTLY_TEST" = true ] || [[ "$TRAVIS_TAG" =~ $NIGHTLY_PATTERN ]]; then
echo "This is a nightly tag!";
NIGHTLY_BUILD=true;
VERSION_NAME="${BASH_REMATCH[1]}"
VERSION_NAME="${BASH_REMATCH[1]}";
PACKAGE_NAME="nightly_${BASH_REMATCH[1]}";
fi
@@ -27,7 +31,7 @@ if ([ "$RELEASE_BUILD" = true ] || [ "$NIGHTLY_BUILD" = true ]); then
fi
if [ "$BUILD_DEPLOYMENT" = true ]; then
if ([ "$TRAVIS_OS_NAME" = "linux" ] && [ "$CC" = "clang" ]); then
if ([ "$TRAVIS_OS_NAME" = "linux" ] && (! [[ "$CC" =~ ^gcc.*$ ]])); then
echo "Skipping non-release compiler";
exit 0;
fi
@@ -43,4 +47,4 @@ export NIGHTLY_BUILD
export BUILD_DEPLOYMENT
export BUILD_CONFIGS
export VERSION_NAME
export PACKAGE_NAME
export PACKAGE_NAME
+1 -1
View File
@@ -22,7 +22,7 @@ if [ "$TRAVIS_OS_NAME" = "linux" ]; then
chmod a+x ./AppImageAssistant
fi
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
gem install xcpretty xcpretty-travis-formatter thefox-pastebin
gem install xcpretty
brew update
brew outdated cmake || brew upgrade cmake
+3 -3
View File
@@ -8,11 +8,11 @@ if [ "$TRAVIS_OS_NAME" = "linux" ]; then
for config in $BUILD_CONFIGS
do
cd "$config"
ninja install appimage
ninja appimage
cd ..
done
ls -al /tmp/release
cp `find /tmp/release -name '*.AppImage' -print` /tmp/release
(cd /tmp/release && tar -cvzf /tmp/builds/$PACKAGE_NAME-builds-Linux.tar.gz *.AppImage)
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
cd build
@@ -20,7 +20,7 @@ elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
for config in $BUILD_CONFIGS
do
cmake --build . --config "$config" --target install | tee build.log \
| xcpretty -f `xcpretty-travis-formatter`
| xcpretty
XCODE_RET=${PIPESTATUS[0]}
if [ "$XCODE_RET" -ne "0" ]; then
tar -cvzf build.log.tar.gz build.log
+6 -3
View File
@@ -5,13 +5,16 @@ set -e
cd build
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
ninja
ninja all
valgrind --leak-check=full --error-exitcode=1 --gen-suppressions=all \
--suppressions="$TRAVIS_BUILD_DIR/ci/travis/valgrind.supp" ./bin/unittests --gtest_shuffle
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
cmake --build . --config "$CONFIGURATION" | tee build.log | xcpretty -f `xcpretty-travis-formatter`
cmake --build . --config "$CONFIGURATION" | tee build.log | xcpretty
XCODE_RET=${PIPESTATUS[0]}
if [ "$XCODE_RET" -ne "0" ]; then
tar -cvzf build.log.tar.gz build.log
curl --upload-file build.log.tar.gz "https://transfer.sh/build.log.tar.gz"
exit $XCODE_RET
fi
fi
fi
+28
View File
@@ -0,0 +1,28 @@
{
liblsan Invalid read
Memcheck:Addr8
obj:/usr/lib64/liblsan.so.0.0.0
obj:/usr/lib64/liblsan.so.0.0.0
obj:/usr/lib64/liblsan.so.0.0.0
obj:*
obj:*
obj:*
}
{
Travis memleak
Memcheck:Leak
match-leak-kinds: definite
fun:malloc
fun:_dl_signal_error
fun:_dl_open
fun:dlopen_doit
fun:_dl_catch_error
fun:_dlerror_run
fun:dlopen@@GLIBC_2.2.5
obj:/usr/lib/x86_64-linux-gnu/libmirclient.so.7
fun:call_init.part.0
fun:call_init
fun:_dl_init
fun:dl_open_worker
fun:_dl_catch_error
}
+26
View File
@@ -0,0 +1,26 @@
# Sample toolchain file for building for Windows from a Linux system.
#
# Typical usage:
# *) install cross compiler: `sudo apt-get install mingw-w64 g++-mingw-w64`
# *) cd build
# *) cmake -DCMAKE_TOOLCHAIN_FILE=~/Toolchain-Ubuntu-mingw64.cmake ..
set(CMAKE_SYSTEM_NAME Windows)
set(TOOLCHAIN_PREFIX x86_64-w64-mingw32)
# cross compilers to use for C and C++
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++)
set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres)
# target environment on the build host system
# set 1st to dir with the cross compiler's C/C++ headers/libs
set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX})
# modify default behavior of FIND_XXX() commands to
# search for headers/libs in the target environment and
# don't search for programs in the build host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+6 -23
View File
@@ -1,33 +1,16 @@
include(CheckIncludeFile)
add_library(speech INTERFACE)
if (WIN32)
find_package(WindowsSDK REQUIRED)
foreach(dir ${WINDOWSSDK_DIRS})
get_windowssdk_library_dirs("${dir}" LIB_DIRS)
CHECK_INCLUDE_FILE_CXX("sapi.h" HAVE_SAPI_H)
find_library(SPEECH_LIBRARY
NAMES sapi
PATHS ${LIB_DIRS}
NO_DEFAULT_PATH)
if (SPEECH_LIBRARY)
set(SDK_DIR "${dir}")
break()
endif()
endforeach()
if (NOT SPEECH_LIBRARY)
message(SEND_ERROR "Text to speech library could not be found! Either install it or disable the speech option.")
return()
if (NOT HAVE_SAPI_H)
message(SEND_ERROR "sapi.h could not be found on your platform. Please disable speech support.")
endif()
get_windowssdk_include_dirs("${SDK_DIR}" INCLUDE_DIRS)
target_include_directories(speech INTERFACE ${INCLUDE_DIRS})
else()
message(SEND_ERROR "Text to Speech is not supported on this platform!")
endif()
target_compile_definitions(speech INTERFACE -DFS2_SPEECH)
target_compile_definitions(speech INTERFACE -DFS2_SPEECH)
+6
View File
@@ -1,3 +1,9 @@
SET(BINARY_DESTINATION ".")
SET(LIBRAY_DESTINATION "${BINARY_DESTINATION}")
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
set(IS_64BIT TRUE)
else()
set(IS_64BIT FALSE)
endif()
+23
View File
@@ -1,5 +1,6 @@
MESSAGE(STATUS "Doing Mac OSX specific things...")
target_compile_definitions(platform INTERFACE APPLE_APP)
SET(EXE_GUI_TYPE MACOSX_BUNDLE)
FIND_LIBRARY(COCOA_LIBRARY Cocoa)
@@ -9,3 +10,25 @@ if (NOT COCOA_LIBRARY)
endif()
target_link_libraries(platform INTERFACE ${COCOA_LIBRARY})
SET(CMAKE_OSX_DEPLOYMENT_TARGET "10.9")
SET(CMAKE_SKIP_RPATH FALSE)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
SET(CMAKE_INSTALL_RPATH @loader_path/../Frameworks/)
# Set the path where library dependencies are copied to
SET(LIBRAY_DESTINATION "../Frameworks")
set(PLATFORM_MAC TRUE CACHE INTERNAL "" FORCE)
# Generate and don't strip debug symbols
# These settings don't seem to generate debug symbols for code and Freespace2
# so those settings are set manually in code and Freespace2's CMakeLists.txt files
set(CMAKE_XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS "YES")
set(CMAKE_XCODE_ATTRIBUTE_COPY_PHASE_STRIP "NO")
set(CMAKE_XCODE_ATTRIBUTE_STRIP_INSTALLED_PRODUCT "NO")
set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN "NO")
# Generate .dSYM file
set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT "dwarf-with-dsym")
+1 -1
View File
@@ -7,4 +7,4 @@ if (NOT EXECINFO_LIB)
message(FATAL_ERROR "Couldn't find libexecinfo! Please install it and rerun the configuration.")
else()
target_link_libraries(platform INTERFACE "${EXECINFO_LIB}")
endif()
endif()
+7
View File
@@ -4,3 +4,10 @@ INCLUDE(util)
MESSAGE(STATUS "Configuring UNIX specific things and stuff...")
target_compile_definitions(platform INTERFACE SCP_UNIX USE_OPENAL)
# Set RPATH
set(CMAKE_SKIP_BUILD_RPATH TRUE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH "\$ORIGIN")
set(PLATFORM_UNIX TRUE CACHE INTERNAL "" FORCE)
+16 -9
View File
@@ -1,20 +1,27 @@
MESSAGE(STATUS "Configuring Windows specific things and stuff...")
target_link_libraries(platform INTERFACE
comctl32.lib
msacm32.lib
odbc32.lib
odbccp32.lib
vfw32.lib
winmm.lib
wsock32.lib
Psapi.lib
SET(WIN32_LIBS
comctl32
msacm32
odbc32
odbccp32
vfw32
winmm
wsock32
psapi
)
IF (MINGW)
SET(WIN32_LIBS ${WIN32_LIBS} mingw32)
ENDIF (MINGW)
target_link_libraries(platform INTERFACE ${WIN32_LIBS})
target_compile_definitions(platform INTERFACE WIN32 USE_OPENAL _WINDOWS)
# Specify minimum Windows version for the headers (currently this is XP)
target_compile_definitions(platform INTERFACE NTDDI_VERSION=0x05010000 _WIN32_WINNT=0x0501)
SET(EXE_GUI_TYPE WIN32)
set(PLATFORM_WINDOWS TRUE CACHE INTERNAL "" FORCE)
+15
View File
@@ -12,6 +12,21 @@ include(CheckTypeSize)
CHECK_INCLUDE_FILE("execinfo.h" HAVE_EXECINFO_H)
CHECK_INCLUDE_FILE_CXX("cxxabi.h" HAVE_CXXAPI_H)
CHECK_TYPE_SIZE("max_align_t" MAX_ALIGN_T)
set(CMAKE_EXTRA_INCLUDE_FILES "cstddef")
CHECK_TYPE_SIZE("std::max_align_t" STD_MAX_ALIGN_T LANGUAGE CXX)
set(CMAKE_EXTRA_INCLUDE_FILES)
CHECK_FUNCTION_EXISTS(strcasecmp HAVE_STRCASECMP)
CHECK_FUNCTION_EXISTS(strncasecmp HAVE_STRNCASECMP)
CHECK_FUNCTION_EXISTS(_stricmp HAVE__STRICMP)
CHECK_FUNCTION_EXISTS(_strnicmp HAVE__STRNICMP)
CHECK_FUNCTION_EXISTS(strlwr HAVE_STRLWR)
CHECK_INCLUDE_FILE("strings.h" HAVE_STRINGS_H)
set(PLATFORM_CHECK_HEADER "${GENERATED_SOURCE_DIR}/platformChecks.h")
CONFIGURE_FILE(${CMAKE_CURRENT_LIST_DIR}/platformChecks.h.in "${PLATFORM_CHECK_HEADER}")
+13
View File
@@ -5,5 +5,18 @@
#cmakedefine HAVE_EXECINFO_H
#cmakedefine HAVE_CXXAPI_H
#cmakedefine HAVE_MAX_ALIGN_T
#cmakedefine HAVE_STD_MAX_ALIGN_T
#cmakedefine01 IS_64BIT
#cmakedefine01 HAVE_STRCASECMP
#cmakedefine01 HAVE_STRNCASECMP
#cmakedefine01 HAVE__STRICMP
#cmakedefine01 HAVE__STRNICMP
#cmakedefine01 HAVE_STRLWR
#cmakedefine01 HAVE_STRINGS_H
#endif // __PLATFORM_CHECKS_H__
+8 -1
View File
@@ -5,6 +5,11 @@ IF(FSO_CMAKE_DEBUG)
INCLUDE(debug-vars)
ENDIF(FSO_CMAKE_DEBUG)
set(PLATFORM_WINDOWS FALSE CACHE INTERNAL "" FORCE)
set(PLATFORM_UNIX FALSE CACHE INTERNAL "" FORCE)
set(PLATFORM_LINUX FALSE CACHE INTERNAL "" FORCE)
set(PLATFORM_MAC FALSE CACHE INTERNAL "" FORCE)
IF(WIN32)
INCLUDE(platform-win32)
ELSEIF(UNIX)
@@ -16,7 +21,9 @@ ELSEIF(UNIX)
INCLUDE(platform-solaris)
ELSEIF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
include(platform-darwin)
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(PLATFORM_LINUX TRUE CACHE INTERNAL "" FORCE)
ENDIF()
ELSE(WIN32)
MESSAGE(STATUS "This platform is not supported, good luck!")
ENDIF(WIN32)
+64 -16
View File
@@ -4,16 +4,28 @@ include(CheckCXXCompilerFlag)
MESSAGE(STATUS "Doing configuration specific to clang...")
unset(COMPILER_FLAGS)
option(CLANG_ENABLE_LEAK_CHECK "Enable -fsanitize=leak" OFF)
option(CLANG_ENABLE_ADDRESS_SANITIZER "Enable -fsanitize=address" OFF)
# These are the default values
set(C_BASE_FLAGS "-march=native -pipe")
set(CXX_BASE_FLAGS "-march=native -pipe")
# For C and C++, the values can be overwritten independently
if(DEFINED ENV{CXXFLAGS})
set(COMPILER_FLAGS $ENV{CXXFLAGS})
set(CXX_BASE_FLAGS $ENV{CXXFLAGS})
endif()
if(DEFINED ENV{CFLAGS})
set(C_BASE_FLAGS $ENV{CFLAGS})
endif()
if(NOT COMPILER_FLAGS)
set(COMPILER_FLAGS "-march=native -pipe")
endif()
# Initialize with an empty string to make sure we always get a clean start
set(COMPILER_FLAGS "")
# This is a slight hack since our flag setup is a bit more complicated
_enable_extra_compiler_warnings_flags()
set(COMPILER_FLAGS "${COMPILER_FLAGS} ${_flags}")
globally_enable_extra_compiler_warnings()
set(COMPILER_FLAGS "${COMPILER_FLAGS} -funroll-loops -fsigned-char -Wno-unknown-pragmas")
# Omit "argument unused during compilation" when clang is used with ccache.
@@ -26,12 +38,40 @@ if ("${CMAKE_GENERATOR}" STREQUAL "Ninja")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -fdiagnostics-color")
endif()
# Omit "deprecated conversion from string constant to 'char*'" warnings.
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-write-strings")
# Start with an empty list
set(SANITIZE_FLAGS)
if(CLANG_ENABLE_ADDRESS_SANITIZER)
set(CMAKE_REQUIRED_FLAGS "-fsanitize=address")
CHECK_C_COMPILER_FLAG("-fsanitize=address" SUPPORTS_SANITIZE_ADDRESS)
if (SUPPORTS_SANITIZE_ADDRESS)
set(SANITIZE_FLAGS ${SANITIZE_FLAGS} "address")
endif()
endif()
if (CLANG_ENABLE_LEAK_CHECK)
check_linker_flag("-fsanitize=leak" SUPPORTS_FSANITIZE_LEAK)
if (SUPPORTS_FSANITIZE_LEAK)
set(SANITIZE_FLAGS ${SANITIZE_FLAGS} "leak")
endif()
endif()
string(REPLACE ";" "," SANITIZE_FLAGS "${SANITIZE_FLAGS}")
if (NOT "${SANITIZE_FLAGS}" STREQUAL "")
set(SANITIZE_FLAGS "-fsanitize=${SANITIZE_FLAGS}")
endif()
set(COMPILER_FLAGS "${COMPILER_FLAGS} ${SANITIZE_FLAGS}")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wformat-security")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-unused-function")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-deprecated -Wno-char-subscripts")
# Dear Clang, please tell us if a function does not return a value since that part of the standard is stupid!
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wreturn-type")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-char-subscripts")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-unused-parameter")
@@ -44,13 +84,9 @@ set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable")
set(COMPILER_FLAGS_DEBUG "-O0 -g -Wshadow")
if (FSO_FATAL_WARNINGS)
# Make warnings fatal if the right variable is set
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Werror")
endif()
set(CMAKE_CXX_FLAGS ${COMPILER_FLAGS})
set(CMAKE_C_FLAGS ${COMPILER_FLAGS})
# Always use the base flags and add our compiler flags at the bacl
set(CMAKE_CXX_FLAGS "${CXX_BASE_FLAGS} ${COMPILER_FLAGS}")
set(CMAKE_C_FLAGS "${C_BASE_FLAGS} ${COMPILER_FLAGS}")
set(CMAKE_CXX_FLAGS_RELEASE ${COMPILER_FLAGS_RELEASE})
set(CMAKE_C_FLAGS_RELEASE ${COMPILER_FLAGS_RELEASE})
@@ -61,5 +97,17 @@ set(CMAKE_C_FLAGS_DEBUG ${COMPILER_FLAGS_DEBUG})
set(CMAKE_EXE_LINKER_FLAGS "")
if (SANITIZE_FLAGS)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${SANITIZE_FLAGS}")
endif()
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "-g -rdynamic")
if (FSO_FATAL_WARNINGS)
# Make warnings fatal if the right variable is set
target_compile_options(compiler INTERFACE "-Werror")
endif()
# Always define this to make sure that the fixed width format macros are available
target_compile_definitions(compiler INTERFACE __STDC_FORMAT_MACROS)
+83 -22
View File
@@ -5,20 +5,35 @@ include(util)
MESSAGE(STATUS "Doing configuration specific to gcc...")
option(GCC_ENABLE_LEAK_CHECK "Enable the -fsanitize=leak" OFF)
option(GCC_ENABLE_LEAK_CHECK "Enable -fsanitize=leak" OFF)
option(GCC_ENABLE_ADDRESS_SANITIZER "Enable -fsanitize=address" OFF)
option(GCC_ENABLE_SANITIZE_UNDEFINED "Enable -fsanitize=undefined" OFF)
unset(COMPILER_FLAGS)
# These are the default values
set(C_BASE_FLAGS "-march=native -pipe")
set(CXX_BASE_FLAGS "-march=native -pipe")
# For C and C++, the values can be overwritten independently
if(DEFINED ENV{CFLAGS})
set(C_BASE_FLAGS $ENV{CFLAGS})
endif()
if(DEFINED ENV{CXXFLAGS})
set(COMPILER_FLAGS $ENV{CXXFLAGS})
set(CXX_BASE_FLAGS $ENV{CXXFLAGS})
endif()
if(NOT COMPILER_FLAGS)
set(COMPILER_FLAGS "-march=native -pipe")
endif()
# Initialize with an empty string to make sure we always get a clean start
set(COMPILER_FLAGS "")
# This is a slight hack since our flag setup is a bit more complicated
_enable_extra_compiler_warnings_flags()
set(COMPILER_FLAGS "${COMPILER_FLAGS} ${_flags}")
globally_enable_extra_compiler_warnings()
set(COMPILER_FLAGS "${COMPILER_FLAGS} -funroll-loops -fsigned-char -Wno-unknown-pragmas")
# Place each function and data in its own section so the linker can
# perform dead code elimination
set(COMPILER_FLAGS "${COMPILER_FLAGS} -fdata-sections -ffunction-sections")
if ("${CMAKE_GENERATOR}" STREQUAL "Ninja")
# Force color diagnostics for Ninja generator
CHECK_C_COMPILER_FLAG(-fdiagnostics-color SUPPORTS_DIAGNOSTIC_COLOR)
@@ -28,11 +43,46 @@ if ("${CMAKE_GENERATOR}" STREQUAL "Ninja")
endif()
endif()
# Omit "deprecated conversion from string constant to 'char*'" warnings.
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-write-strings")
# Start with an empty list
set(SANITIZE_FLAGS)
if(GCC_ENABLE_ADDRESS_SANITIZER)
set(CMAKE_REQUIRED_FLAGS "-fsanitize=address")
CHECK_C_COMPILER_FLAG("-fsanitize=address" SUPPORTS_SANITIZE_ADDRESS)
if (SUPPORTS_SANITIZE_ADDRESS)
set(SANITIZE_FLAGS ${SANITIZE_FLAGS} "address")
endif()
endif()
if (GCC_ENABLE_LEAK_CHECK)
check_linker_flag("-fsanitize=leak" SUPPORTS_FSANITIZE_LEAK)
if (SUPPORTS_FSANITIZE_LEAK)
set(SANITIZE_FLAGS ${SANITIZE_FLAGS} "leak")
endif()
endif()
if (GCC_ENABLE_SANITIZE_UNDEFINED)
check_linker_flag("-fsanitize=undefined" SUPPORTS_SANITIZE_UNDEFINED)
if (SUPPORTS_SANITIZE_UNDEFINED)
set(SANITIZE_FLAGS ${SANITIZE_FLAGS} "undefined")
endif()
endif()
string(REPLACE ";" "," SANITIZE_FLAGS "${SANITIZE_FLAGS}")
if (NOT "${SANITIZE_FLAGS}" STREQUAL "")
set(SANITIZE_FLAGS "-fsanitize=${SANITIZE_FLAGS}")
endif()
set(COMPILER_FLAGS "${COMPILER_FLAGS} ${SANITIZE_FLAGS}")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wformat-security")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-unused-function")
# Dear GCC, please tell us if a function does not return a value since that part of the standard is stupid!
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wreturn-type")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-deprecated -Wno-char-subscripts")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-unused-parameter")
@@ -41,13 +91,9 @@ set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable -Wno-unused-but-set-variabl
set(COMPILER_FLAGS_DEBUG "-O0 -g -Wshadow")
if (FSO_FATAL_WARNINGS)
# Make warnings fatal if the right variable is set
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Werror")
endif()
set(CMAKE_CXX_FLAGS ${COMPILER_FLAGS})
set(CMAKE_C_FLAGS ${COMPILER_FLAGS})
# Always use the base flags and add our compiler flags at the bacl
set(CMAKE_CXX_FLAGS "${CXX_BASE_FLAGS} ${COMPILER_FLAGS}")
set(CMAKE_C_FLAGS "${C_BASE_FLAGS} ${COMPILER_FLAGS}")
set(CMAKE_CXX_FLAGS_RELEASE ${COMPILER_FLAGS_RELEASE})
set(CMAKE_C_FLAGS_RELEASE ${COMPILER_FLAGS_RELEASE})
@@ -57,17 +103,32 @@ set(CMAKE_C_FLAGS_DEBUG ${COMPILER_FLAGS_DEBUG})
set(CMAKE_EXE_LINKER_FLAGS "")
if (GCC_ENABLE_LEAK_CHECK)
check_linker_flag("-fsanitize=leak" SUPPORTS_FSANITIZE_LEAK)
IF (MINGW)
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static -static-libgcc -static-libstdc++ -Wl,--enable-auto-import")
ENDIF(MINGW)
if (SUPPORTS_FSANITIZE_LEAK)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=leak")
endif()
if (SANITIZE_FLAGS)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${SANITIZE_FLAGS}")
endif()
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "-g -rdynamic")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "-g")
IF(NOT MINGW)
SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -rdynamic")
# Allow the linker to perform dead code elimination; this is considered
# experimental for COFF and PE formats and thus disabled for Windows builds
# (https://sourceware.org/binutils/docs/ld/Options.html)
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
ENDIF(NOT MINGW)
IF(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
SET(CMAKE_EXE_LINKER_FLAGS "-Wl,-zignore")
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
if (FSO_FATAL_WARNINGS)
# Make warnings fatal if the right variable is set
target_compile_options(compiler INTERFACE "-Werror")
endif()
# Always define this to make sure that the fixed width format macros are available
target_compile_definitions(compiler INTERFACE __STDC_FORMAT_MACROS)
+38 -26
View File
@@ -8,36 +8,39 @@ MESSAGE(STATUS "Doing configuration specific to visual studio...")
set_property(GLOBAL PROPERTY DEBUG_CONFIGURATIONS Debug)
option(MSVC_USE_RUNTIME_DLL "Use the dynamically linked version of the runtime" OFF)
option(MSVC_RELEASE_DEBUGGING "Set options that allow to debug release builds" OFF)
MARK_AS_ADVANCED(FORCE MSVC_USE_RUNTIME_DLL)
MARK_AS_ADVANCED(FORCE MSVC_RELEASE_DEBUGGING)
# These are the warnings we disable
set(WARNING_FLAGS
/wd"4100" # unreferenced formal parameters
/wd"4127" # constant conditional (assert)
/wd"4201" # nonstandard extension used: nameless struct/union (happens a lot in Windows include headers)
/wd"4290" # C++ exception specification ignored except to indicate a function is not __declspec(nothrow)
/wd"4390" # empty control statement (triggered by nprintf and mprintf's inside of one-line if's, etc)
/wd"4410" # illegal size for operand... ie... fxch st(1)
/wd"4511" # copy constructor could not be generated (happens a lot in Windows include headers)
/wd"4512" # assignment operator could not be generated (happens a lot in Windows include headers)
/wd"4514" # unreferenced inline function removed
/wd"4611" # _setjmp warning. Since we use setjmp alot, and we don't really use constructors or destructors, this warning doesn't really apply to us.
/wd"4663" # C++ language change (template specification)
/wd"4710" # is inline function not expanded (who cares?)
/wd"4711" # tells us an inline function was expanded (who cares?)
/wd"4786" # is identifier truncated to 255 characters (happens all the time in Microsoft #includes) -- Goober5000"
/wd"4996" # deprecated strcpy, strcat, sprintf, etc. (from MSVC 2005) - taylor
/wd"4311" # Disables warnings about casting pointer types to ints. The funny thing is these warnings can't be resolved, just disabled... - m!m
/wd"4302" # Same as above - m!m
/wd"4366" # The result of the unary '&' operator may be unaligned - m!m
$<$<CONFIG:Release>:/wd"4101"> # In release mode there are unreferenced variables because debug needs them
/wd4100 # unreferenced formal parameters
/wd4127 # constant conditional (assert)
/wd4201 # nonstandard extension used: nameless struct/union (happens a lot in Windows include headers)
/wd4290 # C++ exception specification ignored except to indicate a function is not __declspec(nothrow)
/wd4390 # empty control statement (triggered by nprintf and mprintf's inside of one-line if's, etc)
/wd4410 # illegal size for operand... ie... fxch st(1)
/wd4511 # copy constructor could not be generated (happens a lot in Windows include headers)
/wd4512 # assignment operator could not be generated (happens a lot in Windows include headers)
/wd4514 # unreferenced inline function removed
/wd4611 # _setjmp warning. Since we use setjmp alot, and we don't really use constructors or destructors, this warning doesn't really apply to us.
/wd4663 # C++ language change (template specification)
/wd4710 # is inline function not expanded (who cares?)
/wd4711 # tells us an inline function was expanded (who cares?)
/wd4786 # is identifier truncated to 255 characters (happens all the time in Microsoft #includes) -- Goober5000"
/wd4996 # deprecated strcpy, strcat, sprintf, etc. (from MSVC 2005) - taylor
/wd4311 # Disables warnings about casting pointer types to ints. The funny thing is these warnings can't be resolved, just disabled... - m!m
/wd4302 # Same as above - m!m
/wd4366 # The result of the unary '&' operator may be unaligned - m!m
$<$<CONFIG:Release>:/wd4101> # In release mode there are unreferenced variables because debug needs them
)
target_compile_options(compiler INTERFACE ${WARNING_FLAGS})
# Base
set(CMAKE_C_FLAGS "/MP /GS- /analyze- /Zc:wchar_t /errorReport:prompt /WX- /Zc:forScope /Gd /EHsc /nologo")
set(CMAKE_CXX_FLAGS "/MP /GS- /analyze- /Zc:wchar_t /errorReport:prompt /WX- /Zc:forScope /Gd /EHsc /nologo")
set(CMAKE_C_FLAGS "/MP /GS- /analyze- /Zc:wchar_t /errorReport:prompt /WX- /Zc:forScope /Gd /EHsc /nologo /Zm200")
set(CMAKE_CXX_FLAGS "/MP /GS- /analyze- /Zc:wchar_t /errorReport:prompt /WX- /Zc:forScope /Gd /EHsc /nologo /Zm200")
set(CMAKE_EXE_LINKER_FLAGS "/MANIFEST /DYNAMICBASE:NO /SAFESEH:NO /ERRORREPORT:PROMPT /NOLOGO")
set(CMAKE_STATIC_LINKER_FLAGS "")
@@ -50,11 +53,15 @@ set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "/LTCG")
globally_enable_extra_compiler_warnings()
CHECK_CXX_COMPILER_FLAG("/Zo" MSVC_COMPILER_SUPPORTS_ARCH_ZO)
if (MSVC_RELEASE_DEBUGGING)
CHECK_CXX_COMPILER_FLAG("/Zo" MSVC_COMPILER_SUPPORTS_ARCH_ZO)
if (MSVC_COMPILER_SUPPORTS_ARCH_ZO)
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Zo")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zo")
if (MSVC_COMPILER_SUPPORTS_ARCH_ZO)
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Zo")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zo")
endif()
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG")
endif()
IF(MSVC_USE_RUNTIME_DLL)
@@ -127,4 +134,9 @@ else()
endif()
target_compile_definitions(compiler INTERFACE _CRT_SECURE_NO_DEPRECATE
_CRT_SECURE_NO_WARNINGS _SECURE_SCL=0 NOMINMAX)
_CRT_SECURE_NO_WARNINGS _SECURE_SCL=0 NOMINMAX "$<$<CONFIG:FastDebug>:_ITERATOR_DEBUG_LEVEL=0>")
if (FSO_FATAL_WARNINGS)
# Make warnings fatal if the right variable is set
target_compile_options(compiler INTERFACE "/WX")
endif()
+1 -1
View File
@@ -30,4 +30,4 @@ if (MSVC)
string(REPLACE "/MD" "/MDd" CMAKE_CXX_FLAGS_FASTDEBUG "${CMAKE_CXX_FLAGS_FASTDEBUG}")
string(REPLACE "/MT" "/MTd" CMAKE_CXX_FLAGS_FASTDEBUG "${CMAKE_CXX_FLAGS_FASTDEBUG}")
endif()
endif()
+50 -22
View File
@@ -66,13 +66,33 @@ ENDIF(EXISTS \"${CMAKE_CURRENT_BINARY_DIR}/${TARGET}/${FILE}\")
SET(${OUTVAR} "${CMAKE_COMMAND}" -P ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}/${NAME} PARENT_SCOPE)
ENDFUNCTION(EP_CHECK_FILE_EXISTS)
MACRO(COPY_FILES_TO_TARGET _target)
FOREACH(file IN LISTS TARGET_COPY_FILES)
MACRO(COPY_FILE_TO_TARGET _target _file)
if(UNIX)
ADD_CUSTOM_COMMAND(
TARGET ${_target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${file}" "$<TARGET_FILE_DIR:${_target}>"
COMMENT "copying '${file}'..."
COMMAND cp -a "${_file}" "$<TARGET_FILE_DIR:${_target}>/${LIBRAY_DESTINATION}/"
COMMENT "copying '${_file}'..."
)
else()
ADD_CUSTOM_COMMAND(
TARGET ${_target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_file}" "$<TARGET_FILE_DIR:${_target}>/${LIBRAY_DESTINATION}/"
COMMENT "copying '${_file}'..."
)
endif()
endmacro(COPY_FILE_TO_TARGET)
MACRO(COPY_FILES_TO_TARGET _target)
if(UNIX)
ADD_CUSTOM_COMMAND(
TARGET ${_target} POST_BUILD
COMMAND mkdir -p "$<TARGET_FILE_DIR:${_target}>/${LIBRAY_DESTINATION}/"
COMMENT "Creating '$<TARGET_FILE_DIR:${_target}>/${LIBRAY_DESTINATION}/'..."
)
endif()
FOREACH(file IN LISTS TARGET_COPY_FILES)
COPY_FILE_TO_TARGET("${_target}" "${file}")
ENDFOREACH(file)
ENDMACRO(COPY_FILES_TO_TARGET)
@@ -96,7 +116,7 @@ function(CONVERT_OLD_LIBRARIES)
else("${lib}" STREQUAL "debug")
# Expecting normal library
if(is_debug)
list(APPEND out_list "$<$<CONFIG:Debug>:${lib}>")
list(APPEND out_list "$<$<CONFIG:Debug>:${lib}>" "$<$<CONFIG:FastDebug>:${lib}>")
elseif(is_optimized)
list(APPEND out_list "$<$<CONFIG:Release>:${lib}>")
else(is_debug)
@@ -121,28 +141,26 @@ macro(set_if_not_defined VAR VALUE)
endmacro(set_if_not_defined)
macro(configure_cotire target)
IF(COTIRE_ENABLE)
# Disable unity build as it doesn't work well for us
set_target_properties(${target} PROPERTIES COTIRE_ADD_UNITY_BUILD FALSE)
# Disable unity build as it doesn't work well for us
set_target_properties(${target} PROPERTIES COTIRE_ADD_UNITY_BUILD FALSE)
# add ignored paths for the precompiled header here
set_target_properties(code PROPERTIES COTIRE_PREFIX_HEADER_IGNORE_PATH
"${CMAKE_SOURCE_DIR};${CMAKE_BINARY_DIR}")
IF(DEFINED CMAKE_CONFIGURATION_TYPES)
cotire(${target} CONFIGURATIONS ${CMAKE_CONFIGURATION_TYPES})
ELSE(DEFINED CMAKE_CONFIGURATION_TYPES)
cotire(${target})
ENDIF(DEFINED CMAKE_CONFIGURATION_TYPES)
ENDIF(COTIRE_ENABLE)
cotire(${target})
endmacro(configure_cotire)
macro(add_target_copy_files)
INSTALL(FILES ${ARGN}
DESTINATION ${BINARY_DESTINATION}
)
foreach(file ${ARGN})
if (IS_DIRECTORY "${file}")
INSTALL(DIRECTORY ${file}
DESTINATION ${LIBRAY_DESTINATION}
)
else()
INSTALL(FILES ${file}
DESTINATION ${LIBRAY_DESTINATION}
)
endif()
SET(TARGET_COPY_FILES ${TARGET_COPY_FILES} ${ARGN} CACHE INTERNAL "" FORCE)
SET(TARGET_COPY_FILES ${TARGET_COPY_FILES} ${file} CACHE INTERNAL "" FORCE)
endforeach()
endmacro(add_target_copy_files)
function(detect_simd_instructions _out_var)
@@ -167,3 +185,13 @@ function (check_linker_flag _flag _out_var)
SET(CMAKE_REQUIRED_FLAGS "${_flag}")
CHECK_C_COMPILER_FLAG("" ${_out_var})
endfunction(check_linker_flag)
# Suppresses warnings for the specified target
function(suppress_warnings _target)
if (MSVC)
target_compile_options(${_target} PRIVATE "/W0")
else()
# Assume everything else uses GCC style options
target_compile_options(${_target} PRIVATE "-w")
endif()
endfunction(suppress_warnings)
+1 -1
View File
@@ -35,7 +35,7 @@ ELSE()
SET(FSO_BINARY_SUFFIX "${FSO_VERSION_MAJOR}_${FSO_VERSION_MINOR}_${FSO_VERSION_BUILD}_${FSO_VERSION_REVISION_STR}")
ENDIF()
IF(CMAKE_SIZEOF_VOID_P EQUAL 8)
IF(IS_64BIT)
# This is a 64-bit builds
SET(FSO_BINARY_SUFFIX "${FSO_BINARY_SUFFIX}_x64")
ENDIF()
+15 -4
View File
@@ -19,28 +19,31 @@ TARGET_INCLUDE_DIRECTORIES(code PUBLIC ${FREESPACE_HEADERS})
TARGET_INCLUDE_DIRECTORIES(code PUBLIC ${GENERATED_SOURCE_DIR})
TARGET_INCLUDE_DIRECTORIES(code PUBLIC ${GENERATED_SOURCE_DIR}/code)
target_link_libraries(code PUBLIC gl_12)
target_link_libraries(code PUBLIC OpenGL)
TARGET_LINK_LIBRARIES(code PUBLIC ${OPENAL_LIBS})
TARGET_LINK_LIBRARIES(code PUBLIC ${LUA_LIBS})
TARGET_LINK_LIBRARIES(code PUBLIC ${PNG_LIBS})
TARGET_LINK_LIBRARIES(code PUBLIC ${JPEG_LIBS})
TARGET_LINK_LIBRARIES(code PUBLIC oggvorbis)
TARGET_LINK_LIBRARIES(code PUBLIC sdl2)
TARGET_LINK_LIBRARIES(code PUBLIC ${SDL_LIBS})
TARGET_LINK_LIBRARIES(code PUBLIC ffmpeg)
TARGET_LINK_LIBRARIES(code PUBLIC platform)
TARGET_LINK_LIBRARIES(code PUBLIC compiler)
target_link_libraries(code PUBLIC md5)
IF (FSO_USE_SPEECH)
find_package(Speech REQUIRED)
target_link_libraries(code PUBLIC speech)
ENDIF(FSO_USE_SPEECH)
TARGET_LINK_LIBRARIES(code PUBLIC jansson)
# Headers for standalone "gui" on UNIX
IF(UNIX)
TARGET_LINK_LIBRARIES(code PUBLIC jansson)
TARGET_LINK_LIBRARIES(code PUBLIC ${MONGOOSE_LIBS})
ENDIF(UNIX)
@@ -50,7 +53,15 @@ IF(FSO_BUILD_TOOLS)
ADD_SUBDIRECTORY(cfileextractor)
ENDIF(FSO_BUILD_TOOLS)
set_target_properties(code PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "prefix_header.h")
include(util)
configure_cotire(code)
include(../cmake/Cxx11.cmake)
# Ensure that Xcode generates debug symbols on macOS for Debug builds
set_target_properties(code PROPERTIES XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS[variant=Debug] "YES")
set_target_properties(code PROPERTIES XCODE_ATTRIBUTE_COPY_PHASE_STRIP[variant=Debug] "NO")
set_target_properties(code PROPERTIES XCODE_ATTRIBUTE_STRIP_INSTALLED_PRODUCT[variant=Debug] "NO")
set_target_properties(code PROPERTIES XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN[variant=Debug] "NO")
+13 -73
View File
@@ -18,8 +18,9 @@
#include "globalincs/systemvars.h"
#include "object/waypoint.h"
#include "physics/physics.h"
#include "ship/ship_flags.h"
struct ship_weapon;
class ship_weapon;
class ship_subsys;
class object;
class ship_info;
@@ -27,48 +28,13 @@ class ship_info;
#define AI_DEFAULT_CLASS 3 // default AI class for new ships (Fred)
typedef struct ai_flag_name {
int flag;
AI::AI_Flags flag;
char flag_name[TOKEN_LENGTH];
int flag_list;
} ai_flag_name;
#define MAX_AI_FLAG_NAMES 2
extern ai_flag_name Ai_flag_names[];
#define AIF_FORMATION_WING (1 << 0) // Fly in formation as part of wing.
#define AIF_AWAITING_REPAIR (1 << 1) // Awaiting a repair ship.
#define AIF_BEING_REPAIRED (1 << 2) // Currently docked with repair ship.
#define AIF_REPAIRING (1 << 3) // Repairing a ship (or going to repair a ship)
#define AIF_SEEK_LOCK (1 << 4) // set if should focus on gaining aspect lock, not hitting with lasers
#define AIF_FORMATION_OBJECT (1 << 5) // Fly in formation off a specific object.
#define AIF_TEMPORARY_IGNORE (1 << 6) // Means current ignore_objnum is only temporary, not an order from the player.
#define AIF_USE_EXIT_PATH (1 << 7) // Used by path code, to flag path as an exit path
#define AIF_USE_STATIC_PATH (1 << 8) // Used by path code, use fixed path, don't try to recreate
#define AIF_TARGET_COLLISION (1 << 9) // Collided with aip->target_objnum last frame. Avoid that ship for half a second or so.
#define AIF_UNLOAD_SECONDARIES (1 << 10) // Fire secondaries as fast as possible!
#define AIF_ON_SUBSYS_PATH (1 << 11) // Current path leads to a subsystem
#define AIF_AVOID_SHOCKWAVE_SHIP (1 << 12) // Avoid an existing shockwave from a ship.
#define AIF_AVOID_SHOCKWAVE_WEAPON (1 << 13) // Avoid an expected shockwave from a weapon. shockwave_object field contains object index.
#define AIF_AVOID_SHOCKWAVE_STARTED (1 << 14) // Already started avoiding shockwave, don't keep deciding whether to avoid.
#define AIF_ATTACK_SLOWLY (1 << 15) // Move slowly while attacking.
#define AIF_REPAIR_OBSTRUCTED (1 << 16) // Ship wants to be repaired, but path is obstructed.
#define AIF_KAMIKAZE (1 << 17) // Crash into target
#define AIF_NO_DYNAMIC (1 << 18) // Not allowed to get dynamic goals
#define AIF_AVOIDING_SMALL_SHIP (1 << 19) // Avoiding a player ship.
#define AIF_AVOIDING_BIG_SHIP (1 << 20) // Avoiding a large ship.
#define AIF_BIG_SHIP_COLLIDE_RECOVER_1 (1 << 21) // Collided into a big ship. Recovering by flying away.
#define AIF_BIG_SHIP_COLLIDE_RECOVER_2 (1 << 22) // Collided into a big ship. Fly towards big ship sphere perimeter.
#define AIF_STEALTH_PURSUIT (1 << 23) // AI is trying to fight stealth ship
// Goober5000
#define AIF_UNLOAD_PRIMARIES (1 << 24) // Fire primaries as fast as possible!
#define AIF_TRYING_UNSUCCESSFULLY_TO_WARP (1 << 25) // Trying to warp, but can't warp at the moment
#define AIF_FREE_AFTERBURNER_USE (1 << 26) // Use afterburners while following waypoints or flying towards objects
#define AIF_AVOID_SHOCKWAVE (AIF_AVOID_SHOCKWAVE_SHIP | AIF_AVOID_SHOCKWAVE_WEAPON)
#define AIF_FORMATION (AIF_FORMATION_WING | AIF_FORMATION_OBJECT)
// dock_orient_and_approach() modes.
#define DOA_APPROACH 1 // Approach the current point on the path (aip->path_cur)
#define DOA_DOCK 2 // Dock with goal object.
@@ -100,19 +66,6 @@ extern ai_flag_name Ai_flag_names[];
#define AIG_TYPE_PLAYER_WING 4 // from player direct to wing
#define AIG_TYPE_DYNAMIC 5 // created on the fly
// flags for AI_GOALS
#define AIGF_DOCKER_INDEX_VALID (1<<0) // when set, index field for docker is valid
#define AIGF_DOCKEE_INDEX_VALID (1<<1) // when set, index field for dockee is valid
#define AIGF_GOAL_ON_HOLD (1<<2) // when set, this goal cannot currently be satisfied, although it could be in the future
#define AIGF_SUBSYS_NEEDS_FIXUP (1<<3) // when set, the subsystem index (for a destroy subsystem goal) is invalid and must be gotten from the subsys name stored in docker.name field!!
#define AIGF_GOAL_OVERRIDE (1<<4) // paired with AIG_TYPE_DYNAMIC to mean this goal overrides any other goal
#define AIGF_PURGE (1<<5) // purge this goal next time we process
#define AIGF_GOALS_PURGED (1<<6) // this goal has already caused other goals to get purged
#define AIGF_DEPART_SOUND_PLAYED (1<<7) // Goober5000 - replacement for AL's hack ;)
#define AIGF_TARGET_OWN_TEAM (1<<8) // Goober5000 - removes standard precautions against AI ships taking traitorous actions
#define AIGF_DOCK_INDEXES_VALID (AIGF_DOCKER_INDEX_VALID|AIGF_DOCKEE_INDEX_VALID)
// Flags to ai_turn_towards_vector().
#define AITTV_FAST (1<<0) // Turn fast, not slowed down based on skill level.
#define AITTV_VIA_SEXP (1<<1) // Goober5000 - via sexp
@@ -120,23 +73,13 @@ extern ai_flag_name Ai_flag_names[];
#define KAMIKAZE_HULL_ON_DEATH -1000.0f // Hull strength ship gets set to if it crash-dies.
// flags for possible ai overrides
#define AIORF_FULL (1<<0) // Full sexp control
#define AIORF_ROLL (1<<1) // Sexp forced roll maneuver
#define AIORF_PITCH (1<<2) // Sexp forced pitch change
#define AIORF_HEADING (1<<3) // Sexp forced heading change
#define AIORF_FULL_LAT (1<<4) // full control over up/side/forward movement
#define AIORF_UP (1<<5) // vertical movement
#define AIORF_SIDEWAYS (1<<6) // horizontal movement
#define AIORF_FORWARD (1<<7) // forward movement
// structure for AI goals
typedef struct ai_goal {
int signature; // Unique identifier. All goals ever created (per mission) have a unique signature.
int ai_mode; // one of the AIM_* modes for this goal
int ai_submode; // maybe need a submode
int type; // one of the AIG_TYPE_* values above
int flags; // one of the AIGF_* values above
flagset<AI::Goal_Flags> flags; // one of the AIGF_* values above
fix time; // time at which this goal was issued.
int priority; // how important is this goal -- number 0 - 100
@@ -227,10 +170,8 @@ typedef struct ai_class {
int ai_chance_to_use_missiles_on_plr[NUM_SKILL_LEVELS];
float ai_max_aim_update_delay[NUM_SKILL_LEVELS];
float ai_turret_max_aim_update_delay[NUM_SKILL_LEVELS];
int ai_profile_flags; //Holds the state of flags that are set
int ai_profile_flags_set; //Holds which flags are set and which are just left alone
int ai_profile_flags2;
int ai_profile_flags2_set;
flagset<AI::Profile_Flags> ai_profile_flags; //Holds the state of flags that are set
flagset<AI::Profile_Flags> ai_profile_flags_set; //Holds which flags are set and which are just left alone
//SUSHI: These are optional overrides to an AI class to prevent the automatic scaling based on AI class index
int ai_aburn_use_factor[NUM_SKILL_LEVELS];
@@ -327,7 +268,7 @@ extern pnode *Ppfp; // Free pointer in path points.
#define MAX_IGNORE_NEW_OBJECTS 7
typedef struct ai_info {
int ai_flags; // Special flags for AI behavior.
flagset<AI::AI_Flags> ai_flags; // Special flags for AI behavior.
int shipnum; // Ship using this slot, -1 means none.
int type; //
int wing; // Member of what wing? -1 means none.
@@ -460,8 +401,7 @@ typedef struct ai_info {
int ai_chance_to_use_missiles_on_plr;
float ai_max_aim_update_delay;
float ai_turret_max_aim_update_delay;
int ai_profile_flags; //Holds AI_Profiles flags (possibly overriden by AI class) that actually apply to AI
int ai_profile_flags2;
flagset<AI::Profile_Flags> ai_profile_flags; //Holds AI_Profiles flags (possibly overriden by AI class) that actually apply to AI
union {
@@ -545,7 +485,7 @@ typedef struct ai_info {
vec3d artillery_lock_pos; // base position of the lock point on (in model's frame of reference)
float lethality; // measure of how dangerous ship is to enemy BIG|HUGE ships (likelyhood of targeting)
int ai_override_flags; // flags for marking ai overrides from sexp or lua systems
flagset<AI::Maneuver_Override_Flags> ai_override_flags; // flags for marking ai overrides from sexp or lua systems
control_info ai_override_ci; // ai override control info
int ai_override_timestamp; // mark for when to end the current override
} ai_info;
@@ -619,7 +559,7 @@ void set_wingnum(int objnum, int wingnum);
char *ai_get_goal_target_name(const char *name, int *index);
extern void init_ai_system(void);
extern void ai_attack_object(object *attacker, object *attacked, ship_subsys *ssp);
extern void ai_attack_object(object *attacker, object *attacked, ship_subsys *ssp, int ship_info_index = -1);
extern void ai_evade_object(object *evader, object *evaded);
extern void ai_ignore_object(object *ignorer, object *ignored, int ignore_new);
extern void ai_ignore_wing(object *ignorer, int wingnum);
@@ -628,7 +568,7 @@ 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, int method);
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 init_ai_object(int objnum);
extern void ai_init(void); // Call this one to parse ai.tbl.
@@ -689,7 +629,7 @@ extern int ai_maybe_fire_afterburner(object *objp, ai_info *aip);
extern void set_predicted_enemy_pos(vec3d *predicted_enemy_pos, object *pobjp, vec3d *enemy_pos, vec3d *enemy_vel, ai_info *aip);
extern int is_instructor(object *objp);
extern int find_enemy(int objnum, float range, int max_attackers);
extern int find_enemy(int objnum, float range, int max_attackers, int ship_info_index = -1);
float ai_get_weapon_speed(ship_weapon *swp);
void set_predicted_enemy_pos_turret(vec3d *predicted_enemy_pos, vec3d *gun_pos, object *pobjp, vec3d *enemy_pos, vec3d *enemy_vel, float weapon_speed, float time_enemy_in_range);
@@ -711,7 +651,7 @@ extern int find_danger_weapon(object *sobjp, float dtime, float *atime, float do
void ai_set_mode_warp_out(object *objp, ai_info *aip);
// prototyped by Goober5000
int get_nearest_objnum(int objnum, int enemy_team_mask, int enemy_wing, float range, int max_attackers);
int get_nearest_objnum(int objnum, int enemy_team_mask, int enemy_wing, float range, int max_attackers, int ship_info_index);
// moved to header file by Goober5000
void ai_announce_ship_dying(object *dying_objp);
+121
View File
@@ -0,0 +1,121 @@
#ifndef AI_FLAGS_H
#define AI_FLAGS_H
#include "globalincs/flagset.h"
namespace AI {
FLAG_LIST(AI_Flags) {
Formation_wing, // Fly in formation as part of wing.
Awaiting_repair, // Awaiting a repair ship.
Being_repaired, // Currently docked with repair ship.
Repairing, // Repairing a ship (or going to repair a ship)
Seek_lock, // set if should focus on gaining aspect lock, not hitting with lasers
Formation_object, // Fly in formation off a specific object.
Temporary_ignore, // Means current ignore_objnum is only temporary, not an order from the player.
Use_exit_path, // Used by path code, to flag path as an exit path
Use_static_path, // Used by path code, use fixed path, don't try to recreate
Target_collision, // Collided with aip->target_objnum last frame. Avoid that ship for half a second or so.
Unload_secondaries, // Fire secondaries as fast as possible!
On_subsys_path, // Current path leads to a subsystem
Avoid_shockwave_ship, // Avoid an existing shockwave from a ship.
Avoid_shockwave_weapon, // Avoid an expected shockwave from a weapon. shockwave_object field contains object index.
Avoid_shockwave_started, // Already started avoiding shockwave, don't keep deciding whether to avoid.
Attack_slowly, // Move slowly while attacking.
Repair_obstructed, // Ship wants to be repaired, but path is obstructed.
Kamikaze, // Crash into target
No_dynamic, // Not allowed to get dynamic goals
Avoiding_small_ship, // Avoiding a player ship.
Avoiding_big_ship, // Avoiding a large ship.
Big_ship_collide_recover_1, // Collided into a big ship. Recovering by flying away.
Big_ship_collide_recover_2, // Collided into a big ship. Fly towards big ship sphere perimeter.
Stealth_pursuit, // AI is trying to fight stealth ship
Unload_primaries, // Fire primaries as fast as possible!
Trying_unsuccessfully_to_warp, // Trying to warp, but can't warp at the moment
Free_afterburner_use, // Use afterburners while following waypoints or flying towards objects
NUM_VALUES
};
FLAG_LIST(Goal_Flags) {
Docker_index_valid, // when set, index field for docker is valid
Dockee_index_valid, // when set, index field for dockee is valid
Goal_on_hold, // when set, this goal cannot currently be satisfied, although it could be in the future
Subsys_needs_fixup, // when set, the subsystem index (for a destroy subsystem goal) is invalid and must be gotten from the subsys name stored in docker.name field!!
Goal_override, // paired with AIG_TYPE_DYNAMIC to mean this goal overrides any other goal
Purge, // purge this goal next time we process
Goals_purged, // this goal has already caused other goals to get purged
Depart_sound_played,// Goober5000 - replacement for AL's hack ;)
Target_own_team,
NUM_VALUES
};
FLAG_LIST(Maneuver_Override_Flags) {
Full, // Full sexp control
Roll, // Sexp forced roll maneuver
Pitch, // Sexp forced pitch change
Heading, // Sexp forced heading change
Full_lat, // full control over up/side/forward movement
Up, // vertical movement
Sideways, // horizontal movement
Forward, // forward movement
NUM_VALUES
};
FLAG_LIST(Profile_Flags) {
Advanced_turret_fov_edge_checks,
Ai_aims_from_ship_center,
Ai_can_slow_down_attacking_big_ships,
Ai_guards_specific_ship_in_wing,
All_ships_manage_shields,
Allow_multi_event_scoring,
Allow_primary_link_at_start,
Allow_rapid_secondary_dumbfire,
Allow_turrets_target_weapons_freely,
Allow_vertical_dodge,
Aspect_invulnerability_fix,
Aspect_lock_countermeasure,
Assist_scoring_scales_with_damage,
Beams_damage_weapons,
Big_ships_can_attack_beam_turrets_on_untargeted_ships,
Disable_linked_fire_penalty,
Disable_weapon_damage_scaling,
Dont_insert_random_turret_fire_delay,
Fix_ai_class_bug,
Fix_ai_path_order_bug,
Fix_heat_seeker_stealth_bug,
Fix_linked_primary_bug,
Force_beam_turret_fov,
Glide_decay_requires_thrust,
Hack_improve_non_homing_swarm_turret_fire_accuracy,
Huge_turret_weapons_ignore_bombs,
Include_beams_in_stat_calcs,
Kill_scoring_scales_with_damage,
Multi_allow_empty_primaries,
Multi_allow_empty_secondaries,
Navigation_subsys_governs_warp,
No_min_dock_speed_cap,
No_special_player_avoid,
No_warp_camera,
Perform_fewer_scream_checks,
Player_weapon_scale_fix,
Prevent_targeting_bombs_beyond_range,
Require_turret_to_have_target_in_fov,
Shockwaves_damage_small_ship_subsystems,
Smart_afterburner_management,
Smart_primary_weapon_selection,
Smart_secondary_weapon_selection,
Smart_shield_management,
Smart_subsystem_targeting_for_turrets,
Strict_turred_tagged_only_targeting,
Turrets_ignore_target_radius,
Use_additive_weapon_velocity,
Use_newtonian_dampening,
Use_only_single_fov_for_turrets,
NUM_VALUES
};
}
#endif
+126 -74
View File
@@ -28,28 +28,17 @@ static char Default_profile_name[NAME_LENGTH];
// utility
void set_flag(ai_profile_t *profile, char *name, int flag, int type)
void set_flag(ai_profile_t *profile, const char *name, AI::Profile_Flags flag)
{
if (optional_string(name))
{
bool val;
stuff_boolean(&val);
if (type == AIP_FLAG) {
if (val)
profile->flags |= flag;
else
profile->flags &= ~flag;
} else {
if (val)
profile->flags2 |= flag;
else
profile->flags2 &= ~flag;
}
profile->flags.set(flag, val);
}
}
char *AI_path_types[] = {
const char *AI_path_types[] = {
"normal",
"alt1",
};
@@ -152,12 +141,12 @@ void parse_ai_profiles_tbl(const char *filename)
// base profile, so zero it out
if (profile == &Ai_profiles[0])
{
memset(profile, 0, sizeof(ai_profile_t));
profile->reset();
}
// brand new profile, so set it to the base defaults
else
{
memcpy(profile, &Ai_profiles[0], sizeof(ai_profile_t));
*profile = Ai_profiles[0];
}
}
@@ -356,93 +345,93 @@ void parse_ai_profiles_tbl(const char *filename)
}
if (optional_string("$Detail Distance Multiplier:"))
parse_float_list(profile->detail_distance_mult, NUM_SKILL_LEVELS);
parse_float_list(profile->detail_distance_mult, MAX_DETAIL_LEVEL + 1);
set_flag(profile, "$big ships can attack beam turrets on untargeted ships:", AIPF_BIG_SHIPS_CAN_ATTACK_BEAM_TURRETS_ON_UNTARGETED_SHIPS, AIP_FLAG);
set_flag(profile, "$big ships can attack beam turrets on untargeted ships:", AI::Profile_Flags::Big_ships_can_attack_beam_turrets_on_untargeted_ships);
set_flag(profile, "$smart primary weapon selection:", AIPF_SMART_PRIMARY_WEAPON_SELECTION, AIP_FLAG);
set_flag(profile, "$smart primary weapon selection:", AI::Profile_Flags::Smart_primary_weapon_selection);
set_flag(profile, "$smart secondary weapon selection:", AIPF_SMART_SECONDARY_WEAPON_SELECTION, AIP_FLAG);
set_flag(profile, "$smart secondary weapon selection:", AI::Profile_Flags::Smart_secondary_weapon_selection);
set_flag(profile, "$smart shield management:", AIPF_SMART_SHIELD_MANAGEMENT, AIP_FLAG);
set_flag(profile, "$smart shield management:", AI::Profile_Flags::Smart_shield_management);
set_flag(profile, "$smart afterburner management:", AIPF_SMART_AFTERBURNER_MANAGEMENT, AIP_FLAG);
set_flag(profile, "$smart afterburner management:", AI::Profile_Flags::Smart_afterburner_management);
set_flag(profile, "$allow rapid secondary dumbfire:", AIPF_ALLOW_RAPID_SECONDARY_DUMBFIRE, AIP_FLAG);
set_flag(profile, "$allow rapid secondary dumbfire:", AI::Profile_Flags::Allow_rapid_secondary_dumbfire);
set_flag(profile, "$huge turret weapons ignore bombs:", AIPF_HUGE_TURRET_WEAPONS_IGNORE_BOMBS, AIP_FLAG);
set_flag(profile, "$huge turret weapons ignore bombs:", AI::Profile_Flags::Huge_turret_weapons_ignore_bombs);
set_flag(profile, "$don't insert random turret fire delay:", AIPF_DONT_INSERT_RANDOM_TURRET_FIRE_DELAY, AIP_FLAG);
set_flag(profile, "$don't insert random turret fire delay:", AI::Profile_Flags::Dont_insert_random_turret_fire_delay);
set_flag(profile, "$hack improve non-homing swarm turret fire accuracy:", AIPF_HACK_IMPROVE_NON_HOMING_SWARM_TURRET_FIRE_ACCURACY, AIP_FLAG);
set_flag(profile, "$hack improve non-homing swarm turret fire accuracy:", AI::Profile_Flags::Hack_improve_non_homing_swarm_turret_fire_accuracy);
set_flag(profile, "$shockwaves damage small ship subsystems:", AIPF_SHOCKWAVES_DAMAGE_SMALL_SHIP_SUBSYSTEMS, AIP_FLAG);
set_flag(profile, "$shockwaves damage small ship subsystems:", AI::Profile_Flags::Shockwaves_damage_small_ship_subsystems);
set_flag(profile, "$navigation subsystem governs warpout capability:", AIPF_NAVIGATION_SUBSYS_GOVERNS_WARP, AIP_FLAG);
set_flag(profile, "$navigation subsystem governs warpout capability:", AI::Profile_Flags::Navigation_subsys_governs_warp);
set_flag(profile, "$ignore lower bound for minimum speed of docked ship:", AIPF_NO_MIN_DOCK_SPEED_CAP, AIP_FLAG);
set_flag(profile, "$ignore lower bound for minimum speed of docked ship:", AI::Profile_Flags::No_min_dock_speed_cap);
set_flag(profile, "$disable linked fire penalty:", AIPF_DISABLE_LINKED_FIRE_PENALTY, AIP_FLAG);
set_flag(profile, "$disable linked fire penalty:", AI::Profile_Flags::Disable_linked_fire_penalty);
set_flag(profile, "$disable weapon damage scaling:", AIPF_DISABLE_WEAPON_DAMAGE_SCALING, AIP_FLAG);
set_flag(profile, "$disable weapon damage scaling:", AI::Profile_Flags::Disable_weapon_damage_scaling);
set_flag(profile, "$use additive weapon velocity:", AIPF_USE_ADDITIVE_WEAPON_VELOCITY, AIP_FLAG);
set_flag(profile, "$use additive weapon velocity:", AI::Profile_Flags::Use_additive_weapon_velocity);
set_flag(profile, "$use newtonian dampening:", AIPF_USE_NEWTONIAN_DAMPENING, AIP_FLAG);
set_flag(profile, "$use newtonian dampening:", AI::Profile_Flags::Use_newtonian_dampening);
set_flag(profile, "$include beams for kills and assists:", AIPF_INCLUDE_BEAMS_IN_STAT_CALCS, AIP_FLAG);
set_flag(profile, "$include beams for kills and assists:", AI::Profile_Flags::Include_beams_in_stat_calcs);
set_flag(profile, "$score kills based on damage caused:", AIPF_KILL_SCORING_SCALES_WITH_DAMAGE, AIP_FLAG);
set_flag(profile, "$score kills based on damage caused:", AI::Profile_Flags::Kill_scoring_scales_with_damage);
set_flag(profile, "$score assists based on damage caused:", AIPF_ASSIST_SCORING_SCALES_WITH_DAMAGE, AIP_FLAG);
set_flag(profile, "$score assists based on damage caused:", AI::Profile_Flags::Assist_scoring_scales_with_damage);
set_flag(profile, "$allow event and goal scoring in multiplayer:", AIPF_ALLOW_MULTI_EVENT_SCORING, AIP_FLAG);
set_flag(profile, "$allow event and goal scoring in multiplayer:", AI::Profile_Flags::Allow_multi_event_scoring);
set_flag(profile, "$fix linked primary weapon decision bug:", AIPF_FIX_LINKED_PRIMARY_BUG, AIP_FLAG);
set_flag(profile, "$fix linked primary weapon decision bug:", AI::Profile_Flags::Fix_linked_primary_bug);
set_flag(profile, "$prevent turrets targeting too distant bombs:", AIPF_PREVENT_TARGETING_BOMBS_BEYOND_RANGE, AIP_FLAG);
set_flag(profile, "$prevent turrets targeting too distant bombs:", AI::Profile_Flags::Prevent_targeting_bombs_beyond_range);
set_flag(profile, "$smart subsystem targeting for turrets:", AIPF_SMART_SUBSYSTEM_TARGETING_FOR_TURRETS, AIP_FLAG);
set_flag(profile, "$smart subsystem targeting for turrets:", AI::Profile_Flags::Smart_subsystem_targeting_for_turrets);
set_flag(profile, "$fix heat seekers homing on stealth ships bug:", AIPF_FIX_HEAT_SEEKER_STEALTH_BUG, AIP_FLAG);
set_flag(profile, "$fix heat seekers homing on stealth ships bug:", AI::Profile_Flags::Fix_heat_seeker_stealth_bug);
set_flag(profile, "$multi allow empty primaries:", AIPF_MULTI_ALLOW_EMPTY_PRIMARIES, AIP_FLAG);
set_flag(profile, "$multi allow empty primaries:", AI::Profile_Flags::Multi_allow_empty_primaries);
set_flag(profile, "$multi allow empty secondaries:", AIPF_MULTI_ALLOW_EMPTY_SECONDARIES, AIP_FLAG);
set_flag(profile, "$multi allow empty secondaries:", AI::Profile_Flags::Multi_allow_empty_secondaries);
set_flag(profile, "$allow turrets target weapons freely:", AIPF_ALLOW_TURRETS_TARGET_WEAPONS_FREELY, AIP_FLAG);
set_flag(profile, "$allow turrets target weapons freely:", AI::Profile_Flags::Allow_turrets_target_weapons_freely);
set_flag(profile, "$use only single fov for turrets:", AIPF_USE_ONLY_SINGLE_FOV_FOR_TURRETS, AIP_FLAG);
set_flag(profile, "$use only single fov for turrets:", AI::Profile_Flags::Use_only_single_fov_for_turrets);
set_flag(profile, "$allow vertical dodge:", AIPF_ALLOW_VERTICAL_DODGE, AIP_FLAG);
set_flag(profile, "$allow vertical dodge:", AI::Profile_Flags::Allow_vertical_dodge);
set_flag(profile, "$force beam turrets to use normal fov:", AIPF_FORCE_BEAM_TURRET_FOV, AIP_FLAG);
set_flag(profile, "$force beam turrets to use normal fov:", AI::Profile_Flags::Force_beam_turret_fov);
set_flag(profile, "$fix ai class bug:", AIPF_FIX_AI_CLASS_BUG, AIP_FLAG);
set_flag(profile, "$fix ai class bug:", AI::Profile_Flags::Fix_ai_class_bug);
set_flag(profile, "$turrets ignore targets radius in range checks:", AIPF2_TURRETS_IGNORE_TARGET_RADIUS, AIP_FLAG2);
set_flag(profile, "$turrets ignore targets radius in range checks:", AI::Profile_Flags::Turrets_ignore_target_radius);
set_flag(profile, "$no extra collision avoidance vs player:", AIPF2_NO_SPECIAL_PLAYER_AVOID, AIP_FLAG2);
set_flag(profile, "$no extra collision avoidance vs player:", AI::Profile_Flags::No_special_player_avoid);
set_flag(profile, "$perform fewer checks for death screams:", AIPF2_PERFORM_FEWER_SCREAM_CHECKS, AIP_FLAG2);
set_flag(profile, "$perform fewer checks for death screams:", AI::Profile_Flags::Perform_fewer_scream_checks);
set_flag(profile, "$advanced turret fov edge checks:", AIPF2_ADVANCED_TURRET_FOV_EDGE_CHECKS, AIP_FLAG2);
set_flag(profile, "$advanced turret fov edge checks:", AI::Profile_Flags::Advanced_turret_fov_edge_checks);
set_flag(profile, "$require turrets to have target in fov:", AIPF2_REQUIRE_TURRET_TO_HAVE_TARGET_IN_FOV, AIP_FLAG2);
set_flag(profile, "$require turrets to have target in fov:", AI::Profile_Flags::Require_turret_to_have_target_in_fov);
set_flag(profile, "$all ships manage shields:", AIPF2_ALL_SHIPS_MANAGE_SHIELDS, AIP_FLAG2);
set_flag(profile, "$all ships manage shields:", AI::Profile_Flags::All_ships_manage_shields);
set_flag(profile, "$ai aims from ship center:", AIPF2_AI_AIMS_FROM_SHIP_CENTER, AIP_FLAG2);
set_flag(profile, "$ai aims from ship center:", AI::Profile_Flags::Ai_aims_from_ship_center);
set_flag(profile, "$allow primary link at mission start:", AIPF2_ALLOW_PRIMARY_LINK_AT_START, AIP_FLAG2);
set_flag(profile, "$allow primary link at mission start:", AI::Profile_Flags::Allow_primary_link_at_start);
set_flag(profile, "$allow beams to damage bombs:", AIPF2_BEAMS_DAMAGE_WEAPONS, AIP_FLAG2);
set_flag(profile, "$allow beams to damage bombs:", AI::Profile_Flags::Beams_damage_weapons);
set_flag(profile, "$disable weapon damage scaling for player:", AIPF2_PLAYER_WEAPON_SCALE_FIX, AIP_FLAG2);
set_flag(profile, "$disable weapon damage scaling for player:", AI::Profile_Flags::Player_weapon_scale_fix);
set_flag(profile, "$countermeasures affect aspect seekers:", AIPF2_ASPECT_LOCK_COUNTERMEASURE, AIP_FLAG2);
set_flag(profile, "$countermeasures affect aspect seekers:", AI::Profile_Flags::Aspect_lock_countermeasure);
set_flag(profile, "$ai guards specific ship in wing:", AIPF2_AI_GUARDS_SPECIFIC_SHIP_IN_WING, AIP_FLAG2);
set_flag(profile, "$ai guards specific ship in wing:", AI::Profile_Flags::Ai_guards_specific_ship_in_wing);
profile->ai_path_mode = AI_PATH_MODE_NORMAL;
if (optional_string("$ai path mode:"))
@@ -457,17 +446,17 @@ void parse_ai_profiles_tbl(const char *filename)
}
}
set_flag(profile, "$no warp camera:", AIPF2_NO_WARP_CAMERA, AIP_FLAG2);
set_flag(profile, "$no warp camera:", AI::Profile_Flags::No_warp_camera);
set_flag(profile, "$fix ai path order bug:", AIPF2_FIX_AI_PATH_ORDER_BUG, AIP_FLAG2);
set_flag(profile, "$fix ai path order bug:", AI::Profile_Flags::Fix_ai_path_order_bug);
set_flag(profile, "$strict turret-tagged-only targeting:", AIPF2_STRICT_TURRET_TAGGED_ONLY_TARGETING, AIP_FLAG2);
set_flag(profile, "$strict turret-tagged-only targeting:", AI::Profile_Flags::Strict_turred_tagged_only_targeting);
set_flag(profile, "$aspect bomb invulnerability fix:", AIPF2_ASPECT_INVULNERABILITY_FIX, AIP_FLAG2);
set_flag(profile, "$aspect bomb invulnerability fix:", AI::Profile_Flags::Aspect_invulnerability_fix);
set_flag(profile, "$glide decay requires thrust:", AIPF2_GLIDE_DECAY_REQUIRES_THRUST, AIP_FLAG2);
set_flag(profile, "$glide decay requires thrust:", AI::Profile_Flags::Glide_decay_requires_thrust);
set_flag(profile, "$ai can slow down when attacking big ships:", AIPF2_AI_CAN_SLOW_DOWN_ATTACKING_BIG_SHIPS, AIP_FLAG2);
set_flag(profile, "$ai can slow down when attacking big ships:", AI::Profile_Flags::Ai_can_slow_down_attacking_big_ships);
profile->bay_arrive_speed_mult = 1.0f;
profile->bay_depart_speed_mult = 1.0f;
@@ -486,20 +475,14 @@ void parse_ai_profiles_tbl(const char *filename)
mprintf(("Warning: \"$perform less checks for death screams\" flag is deprecated in favor of \"$perform fewer checks for death screams\"\n"));
bool temp;
stuff_boolean(&temp);
if (temp)
profile->flags2 |= AIPF2_PERFORM_FEWER_SCREAM_CHECKS;
else
profile->flags2 &= ~AIPF2_PERFORM_FEWER_SCREAM_CHECKS;
profile->flags.set(AI::Profile_Flags::Perform_fewer_scream_checks, temp);
}
if (optional_string("$allow primary link delay:"))
{
mprintf(("Warning: \"$allow primary link delay\" flag is deprecated in favor of \"$allow primary link at mission start\"\n"));
bool temp;
stuff_boolean(&temp);
if (temp)
profile->flags2 &= ~AIPF2_ALLOW_PRIMARY_LINK_AT_START;
else
profile->flags2 |= AIPF2_ALLOW_PRIMARY_LINK_AT_START;
profile->flags.set(AI::Profile_Flags::Allow_primary_link_at_start, !temp);
}
@@ -570,3 +553,72 @@ int ai_profile_lookup(char *name)
return -1;
}
void ai_profile_t::reset()
{
memset(profile_name, 0, sizeof(profile_name));
flags.reset();
ai_path_mode = 0;
bay_arrive_speed_mult = 0;
bay_depart_speed_mult = 0;
for (int i = 0; i < NUM_SKILL_LEVELS; ++i) {
max_incoming_asteroids[i] = 0;
max_allowed_player_homers[i] = 0;
max_attackers[i] = 0;
predict_position_delay[i] = 0;
in_range_time[i] = 0;
shield_manage_delay[i] = 0;
link_energy_levels_always[i] = 0;
link_energy_levels_maybe[i] = 0;
link_ammo_levels_always[i] = 0;
link_ammo_levels_maybe[i] = 0;
primary_ammo_burst_mult[i] = 0;
cmeasure_life_scale[i] = 0;
cmeasure_fire_chance[i] = 0;
weapon_energy_scale[i] = 0;
shield_energy_scale[i] = 0;
afterburner_recharge_scale[i] = 0;
player_damage_scale[i] = 0;
subsys_damage_scale[i] = 0;
beam_friendly_damage_cap[i] = 0;
turn_time_scale[i] = 0;
glide_attack_percent[i] = 0;
circle_strafe_percent[i] = 0;
glide_strafe_percent[i] = 0;
random_sidethrust_percent[i] = 0;
stalemate_time_thresh[i] = 0;
stalemate_dist_thresh[i] = 0;
max_aim_update_delay[i] = 0;
turret_max_aim_update_delay[i] = 0;
ship_fire_delay_scale_hostile[i] = 0;
ship_fire_delay_scale_friendly[i] = 0;
ship_fire_secondary_delay_scale_hostile[i] = 0;
ship_fire_secondary_delay_scale_friendly[i] = 0;
max_turret_ownage_target[i] = 0;
max_turret_ownage_player[i] = 0;
kill_percentage_scale[i] = 0;
assist_percentage_scale[i] = 0;
assist_award_percentage_scale[i] = 0;
repair_penalty[i] = 0;
delay_bomb_arm_timer[i] = 0;
chance_to_use_missiles_on_plr[i] = 0;
player_autoaim_fov[i] = 0;
}
for (int i = 0; i <= MAX_DETAIL_LEVEL; ++i) {
detail_distance_mult[i] = 0;
}
}
+7 -62
View File
@@ -12,63 +12,7 @@
#include "globalincs/globals.h"
#include "globalincs/pstypes.h"
#include "globalincs/systemvars.h"
// flag int defines
#define AIP_FLAG 1
#define AIP_FLAG2 2
// flags
#define AIPF_SMART_SHIELD_MANAGEMENT (1 << 0)
#define AIPF_BIG_SHIPS_CAN_ATTACK_BEAM_TURRETS_ON_UNTARGETED_SHIPS (1 << 1)
#define AIPF_SMART_PRIMARY_WEAPON_SELECTION (1 << 2)
#define AIPF_SMART_SECONDARY_WEAPON_SELECTION (1 << 3)
#define AIPF_ALLOW_RAPID_SECONDARY_DUMBFIRE (1 << 4)
#define AIPF_HUGE_TURRET_WEAPONS_IGNORE_BOMBS (1 << 5)
#define AIPF_DONT_INSERT_RANDOM_TURRET_FIRE_DELAY (1 << 6)
#define AIPF_HACK_IMPROVE_NON_HOMING_SWARM_TURRET_FIRE_ACCURACY (1 << 7)
#define AIPF_SHOCKWAVES_DAMAGE_SMALL_SHIP_SUBSYSTEMS (1 << 8)
#define AIPF_NAVIGATION_SUBSYS_GOVERNS_WARP (1 << 9)
#define AIPF_NO_MIN_DOCK_SPEED_CAP (1 << 10)
#define AIPF_DISABLE_LINKED_FIRE_PENALTY (1 << 11)
#define AIPF_DISABLE_WEAPON_DAMAGE_SCALING (1 << 12)
#define AIPF_USE_ADDITIVE_WEAPON_VELOCITY (1 << 13)
#define AIPF_USE_NEWTONIAN_DAMPENING (1 << 14)
#define AIPF_INCLUDE_BEAMS_IN_STAT_CALCS (1 << 15)
#define AIPF_KILL_SCORING_SCALES_WITH_DAMAGE (1 << 16)
#define AIPF_ASSIST_SCORING_SCALES_WITH_DAMAGE (1 << 17)
#define AIPF_ALLOW_MULTI_EVENT_SCORING (1 << 18)
#define AIPF_SMART_AFTERBURNER_MANAGEMENT (1 << 19)
#define AIPF_FIX_LINKED_PRIMARY_BUG (1 << 20)
#define AIPF_PREVENT_TARGETING_BOMBS_BEYOND_RANGE (1 << 21)
#define AIPF_SMART_SUBSYSTEM_TARGETING_FOR_TURRETS (1 << 22)
#define AIPF_FIX_HEAT_SEEKER_STEALTH_BUG (1 << 23)
#define AIPF_MULTI_ALLOW_EMPTY_PRIMARIES (1 << 24)
#define AIPF_MULTI_ALLOW_EMPTY_SECONDARIES (1 << 25)
#define AIPF_ALLOW_TURRETS_TARGET_WEAPONS_FREELY (1 << 26)
#define AIPF_USE_ONLY_SINGLE_FOV_FOR_TURRETS (1 << 27)
#define AIPF_ALLOW_VERTICAL_DODGE (1 << 28) //Allows AI ships to evade weapons vertically as well as horizontally
#define AIPF_FORCE_BEAM_TURRET_FOV (1 << 29)
#define AIPF_FIX_AI_CLASS_BUG (1 << 30)
// flags2
#define AIPF2_TURRETS_IGNORE_TARGET_RADIUS (1 << 0)
#define AIPF2_NO_SPECIAL_PLAYER_AVOID (1 << 1)
#define AIPF2_PERFORM_FEWER_SCREAM_CHECKS (1 << 2)
#define AIPF2_ALL_SHIPS_MANAGE_SHIELDS (1 << 3)
#define AIPF2_ADVANCED_TURRET_FOV_EDGE_CHECKS (1 << 4)
#define AIPF2_REQUIRE_TURRET_TO_HAVE_TARGET_IN_FOV (1 << 5)
#define AIPF2_AI_AIMS_FROM_SHIP_CENTER (1 << 6)
#define AIPF2_ALLOW_PRIMARY_LINK_AT_START (1 << 7)
#define AIPF2_BEAMS_DAMAGE_WEAPONS (1 << 8)
#define AIPF2_PLAYER_WEAPON_SCALE_FIX (1 << 9)
#define AIPF2_NO_WARP_CAMERA (1 << 10)
#define AIPF2_ASPECT_LOCK_COUNTERMEASURE (1 << 11)
#define AIPF2_AI_GUARDS_SPECIFIC_SHIP_IN_WING (1 << 12)
#define AIPF2_FIX_AI_PATH_ORDER_BUG (1 << 13)
#define AIPF2_STRICT_TURRET_TAGGED_ONLY_TARGETING (1 << 14)
#define AIPF2_ASPECT_INVULNERABILITY_FIX (1 << 15)
#define AIPF2_GLIDE_DECAY_REQUIRES_THRUST (1 << 16)
#define AIPF2_AI_CAN_SLOW_DOWN_ATTACKING_BIG_SHIPS (1 << 17)
#include "ai/ai_flags.h"
// AI Path types
#define AI_PATH_MODE_NORMAL 0
@@ -76,12 +20,11 @@
#define MAX_AI_PROFILES 5
typedef struct ai_profile_t {
class ai_profile_t {
public:
char profile_name[NAME_LENGTH];
int flags;
int flags2;
flagset<AI::Profile_Flags> flags;
// difficulty-related values
int max_incoming_asteroids[NUM_SKILL_LEVELS]; // max number of asteroids thrown at friendlies
@@ -159,13 +102,15 @@ typedef struct ai_profile_t {
float bay_arrive_speed_mult;
float bay_depart_speed_mult;
} ai_profile_t;
void reset();
};
extern int Num_ai_profiles;
extern int Default_ai_profile;
extern ai_profile_t Ai_profiles[MAX_AI_PROFILES];
#define AI_PROFILES_INDEX(ai_p) ((int)((ai_p) - Ai_profiles))
void ai_profiles_init();
+33 -33
View File
@@ -350,8 +350,8 @@ void ai_big_avoid_ship()
// reset path following information
void ai_big_subsys_path_cleanup(ai_info *aip)
{
if ( aip->ai_flags & AIF_ON_SUBSYS_PATH ) {
aip->ai_flags &= ~AIF_ON_SUBSYS_PATH;
if ( aip->ai_flags[AI::AI_Flags::On_subsys_path] ) {
aip->ai_flags.remove(AI::AI_Flags::On_subsys_path);
aip->path_goal_dist = -1;
aip->path_start = -1;
aip->path_cur = -1;
@@ -438,7 +438,7 @@ int ai_big_maybe_follow_subsys_path(int do_dot_check)
Assert(aip->target_objnum >= 0);
ai_find_path(Pl_objp, aip->target_objnum, subsys_path_num, 0, 1);
if ( aip->path_start >= 0 ) {
aip->ai_flags |= AIF_ON_SUBSYS_PATH;
aip->ai_flags.set(AI::AI_Flags::On_subsys_path);
}
}
}
@@ -593,7 +593,7 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
} // end if ( Pl_objp->phys_info.speed < 3.0f )
//Maybe enter glide strafe (check every 8 seconds, on a different schedule for each ship)
if ((sip->can_glide == true) && !(aip->ai_flags & AIF_KAMIKAZE) && static_randf((Missiontime + static_rand(aip->shipnum)) >> 19) < aip->ai_glide_strafe_percent) {
if ((sip->can_glide == true) && !(aip->ai_flags[AI::AI_Flags::Kamikaze]) && static_randf((Missiontime + static_rand(aip->shipnum)) >> 19) < aip->ai_glide_strafe_percent) {
aip->previous_mode = aip->mode;
aip->mode = AIM_STRAFE;
aip->submode_parm0 = Missiontime; // use parm0 as time strafe mode entered (i.e. MODE start time)
@@ -604,7 +604,7 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
// see if Pl_objp needs to reposition to get a good shot at subsystem which is being attacked
if ( ai_big_maybe_follow_subsys_path() ) {
if ((Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) && !(aip->ai_flags & AIF_KAMIKAZE)) {
if ((Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) && !(aip->ai_flags[AI::AI_Flags::Kamikaze])) {
afterburners_stop(Pl_objp);
}
return;
@@ -641,19 +641,19 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
accelerate_ship(aip, 1.0f);
ship *shipp = &Ships[Pl_objp->instance];
if ((aip->ai_flags & AIF_FREE_AFTERBURNER_USE) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (dot_to_enemy > 0.75f)) {
if ((aip->ai_flags[AI::AI_Flags::Free_afterburner_use]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (dot_to_enemy > 0.75f)) {
if (ai_maybe_fire_afterburner(Pl_objp, aip)) {
afterburners_start(Pl_objp);
aip->afterburner_stop_time = Missiontime + 3*F1_0;
}
} else if ((Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) && !(aip->ai_flags & AIF_KAMIKAZE)) {
} else if ((Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) && !(aip->ai_flags[AI::AI_Flags::Kamikaze])) {
afterburners_stop(Pl_objp);
}
} else {
// AL 12-31-97: Move at least as quickly as your target is moving...
accelerate_ship(aip, MAX(1.0f - dot_to_enemy, Objects[aip->target_objnum].phys_info.fspeed/sip->max_speed));
if ((Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) && !(aip->ai_flags & AIF_KAMIKAZE)) {
if ((Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) && !(aip->ai_flags[AI::AI_Flags::Kamikaze])) {
afterburners_stop(Pl_objp);
}
}
@@ -676,19 +676,19 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
if (dist_to_enemy < ATTACK_STOP_DISTANCE) {
// accelerate_ship(aip, accel * 0.5f);
accelerate_ship(aip, -1.0f);
if ((Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) && !(aip->ai_flags & AIF_KAMIKAZE)) {
if ((Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) && !(aip->ai_flags[AI::AI_Flags::Kamikaze])) {
afterburners_stop(Pl_objp);
}
} else {
accelerate_ship(aip, accel);
ship *shipp = &Ships[Pl_objp->instance];
if ((aip->ai_flags & AIF_FREE_AFTERBURNER_USE) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (accel > 0.95f)) {
if ((aip->ai_flags[AI::AI_Flags::Free_afterburner_use]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (accel > 0.95f)) {
if (ai_maybe_fire_afterburner(Pl_objp, aip)) {
afterburners_start(Pl_objp);
aip->afterburner_stop_time = Missiontime + 3*F1_0;
}
} else if ((Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) && !(aip->ai_flags & AIF_KAMIKAZE)) {
} else if ((Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) && !(aip->ai_flags[AI::AI_Flags::Kamikaze])) {
afterburners_stop(Pl_objp);
}
}
@@ -754,10 +754,10 @@ void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy, vec3d *f
if (current_bank > -1) {
weapon_info *swip = &Weapon_info[tswp->secondary_bank_weapons[current_bank]];
if(!(En_objp->flags[Object::Object_Flags::Protected]) || ((aip->goals[0].ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP)) && swip->wi_flags & WIF_PUNCTURE )) { //override lockdown on protected ships when using anti subsystem weapons - Valathil
if(!(En_objp->flags[Object::Object_Flags::Protected]) || ((aip->goals[0].ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP)) && swip->wi_flags[Weapon::Info_Flags::Puncture] )) { //override lockdown on protected ships when using anti subsystem weapons - Valathil
// If ship is protected and very low on hits, don't fire missiles.
if (!(En_objp->flags[Object::Object_Flags::Protected]) || (En_objp->hull_strength > 10*swip->damage)) {
if (aip->ai_flags & AIF_UNLOAD_SECONDARIES) {
if (aip->ai_flags[AI::AI_Flags::Unload_secondaries]) {
if (timestamp_until(swp->next_secondary_fire_stamp[current_bank]) > swip->fire_wait*1000.0f) {
swp->next_secondary_fire_stamp[current_bank] = timestamp((int) (swip->fire_wait*1000.0f));
}
@@ -765,7 +765,7 @@ void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy, vec3d *f
if (timestamp_elapsed(swp->next_secondary_fire_stamp[current_bank])) {
float firing_range;
if (swip->wi_flags2 & WIF2_LOCAL_SSM)
if (swip->wi_flags[Weapon::Info_Flags::Local_ssm])
firing_range=swip->lssm_lock_range;
else
firing_range = MIN((swip->max_speed * swip->lifetime), swip->weapon_range);
@@ -786,13 +786,13 @@ void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy, vec3d *f
int current_bank_adjusted = MAX_SHIP_PRIMARY_BANKS + current_bank;
if ((aip->ai_flags & AIF_UNLOAD_SECONDARIES) || (swip->burst_flags & WBF_FAST_FIRING)) {
if ((aip->ai_flags[AI::AI_Flags::Unload_secondaries]) || (swip->burst_flags[Weapon::Burst_Flags::Fast_firing])) {
if (swip->burst_shots > swp->burst_counter[current_bank_adjusted]) {
t = swip->burst_delay;
swp->burst_counter[current_bank_adjusted]++;
} else {
t = swip->fire_wait;
if ((swip->burst_shots > 0) && (swip->burst_flags & WBF_RANDOM_LENGTH)) {
if ((swip->burst_shots > 0) && (swip->burst_flags[Weapon::Burst_Flags::Random_length])) {
swp->burst_counter[current_bank_adjusted] = myrand() % swip->burst_shots;
} else {
swp->burst_counter[current_bank_adjusted] = 0;
@@ -804,7 +804,7 @@ void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy, vec3d *f
swp->burst_counter[current_bank_adjusted]++;
} else {
t = set_secondary_fire_delay(aip, temp_shipp, swip, false);
if ((swip->burst_shots > 0) && (swip->burst_flags & WBF_RANDOM_LENGTH)) {
if ((swip->burst_shots > 0) && (swip->burst_flags[Weapon::Burst_Flags::Random_length])) {
swp->burst_counter[current_bank_adjusted] = myrand() % swip->burst_shots;
} else {
swp->burst_counter[current_bank_adjusted] = 0;
@@ -881,7 +881,7 @@ void ai_big_chase()
dist_to_enemy = vm_vec_normalized_dir(&vec_to_enemy, &enemy_pos, &player_pos); // - En_objp->radius;
dot_to_enemy = vm_vec_dot(&vec_to_enemy, &Pl_objp->orient.vec.fvec);
if (aip->ai_flags & AIF_TARGET_COLLISION) {
if (aip->ai_flags[AI::AI_Flags::Target_collision]) {
if ( ai_big_strafe_maybe_retreat(dist_to_enemy, &enemy_pos) ) {
aip->mode = AIM_STRAFE;
aip->submode_parm0 = Missiontime; // use parm0 as time strafe mode entered (i.e. MODE start time)
@@ -894,7 +894,7 @@ void ai_big_chase()
}
}
if (aip->ai_flags & AIF_KAMIKAZE) {
if (aip->ai_flags[AI::AI_Flags::Kamikaze]) {
//nprintf(("AI", "Kamikaze: %7.3f %7.3f\n", dot_to_enemy, dist_to_enemy));
accelerate_ship(aip, 1.0f);
if ((dist_to_enemy < 400.0f) && ai_maybe_fire_afterburner(Pl_objp, aip)) {
@@ -904,7 +904,7 @@ void ai_big_chase()
}
// If just acquired target, or target is not in reasonable cone, don't refine believed enemy position.
if ((dot_to_enemy < 0.25f) || (aip->target_time < 1.0f) || (aip->ai_flags & AIF_SEEK_LOCK)) {
if ((dot_to_enemy < 0.25f) || (aip->target_time < 1.0f) || (aip->ai_flags[AI::AI_Flags::Seek_lock])) {
update_aspect_lock_information(aip, &vec_to_enemy, dist_to_enemy - En_objp->radius, En_objp->radius);
} else if (aip->targeted_subsys != NULL) {
Assert(aip->targeted_subsys != NULL);
@@ -931,7 +931,7 @@ void ai_big_chase()
case SM_SUPER_ATTACK:
if (vm_vec_dist_quick(&Pl_objp->pos, &predicted_enemy_pos) > 100.0f + En_objp->radius * 2.0f) {
if (maybe_avoid_big_ship(Pl_objp, En_objp, aip, &predicted_enemy_pos, 10.0f)) {
if ((Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) && !(aip->ai_flags & AIF_KAMIKAZE)) {
if ((Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) && !(aip->ai_flags[AI::AI_Flags::Kamikaze])) {
afterburners_stop(Pl_objp);
}
return;
@@ -953,7 +953,7 @@ void ai_big_chase()
//
if (((aip->submode != SM_ATTACK) && (aip->submode != SM_SUPER_ATTACK) && (aip->submode != SM_ATTACK_FOREVER) && (aip->submode != SM_EVADE_WEAPON)) || (aip->mode == AIM_STRAFE)){
if ((Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) && !(aip->ai_flags & AIF_KAMIKAZE)) {
if ((Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) && !(aip->ai_flags[AI::AI_Flags::Kamikaze])) {
afterburners_stop(Pl_objp);
}
}
@@ -1198,7 +1198,7 @@ void ai_big_attack_get_data(vec3d *enemy_pos, float *dist_to_enemy, float *dot_t
// If just acquired target, or target is not in reasonable cone, don't refine believed enemy position.
vm_vec_normalized_dir(&vec_to_enemy, enemy_pos, &player_pos);
*dot_to_enemy=vm_vec_dot(&vec_to_enemy, &Pl_objp->orient.vec.fvec);
if ((*dot_to_enemy < 0.25f) || (aip->target_time < 1.0f) || (aip->ai_flags & AIF_SEEK_LOCK)) {
if ((*dot_to_enemy < 0.25f) || (aip->target_time < 1.0f) || (aip->ai_flags[AI::AI_Flags::Seek_lock])) {
predicted_enemy_pos=*enemy_pos;
} else {
vec3d gun_pos, pnt;
@@ -1206,7 +1206,7 @@ void ai_big_attack_get_data(vec3d *enemy_pos, float *dist_to_enemy, float *dot_t
float weapon_speed;
// Compute position of gun in absolute space and use that as fire position.
if (po->n_guns > 0 && !(The_mission.ai_profile->flags2 & AIPF2_AI_AIMS_FROM_SHIP_CENTER)) {
if (po->n_guns > 0 && !(The_mission.ai_profile->flags[AI::Profile_Flags::Ai_aims_from_ship_center])) {
pnt = po->gun_banks[0].pnt[0];
vm_vec_unrotate(&gun_pos, &pnt, &Pl_objp->orient);
vm_vec_add2(&gun_pos, &Pl_objp->pos);
@@ -1254,10 +1254,10 @@ int ai_big_strafe_maybe_retreat(float dist, vec3d *target_pos)
// Inside 2 sec retreat, setting goal point to box point + 300m
// If collision, use std collision resolution.
if ( !(aip->ai_flags & AIF_KAMIKAZE) && ((aip->ai_flags & AIF_TARGET_COLLISION) || (time_to_target < STRAFE_RETREAT_COLLIDE_TIME) || (dist_normal_to_target < STRAFE_RETREAT_COLLIDE_DIST + speed_to_dist_penalty)) ) {
if (aip->ai_flags & AIF_TARGET_COLLISION) {
if ( !(aip->ai_flags[AI::AI_Flags::Kamikaze]) && ((aip->ai_flags[AI::AI_Flags::Target_collision]) || (time_to_target < STRAFE_RETREAT_COLLIDE_TIME) || (dist_normal_to_target < STRAFE_RETREAT_COLLIDE_DIST + speed_to_dist_penalty)) ) {
if (aip->ai_flags[AI::AI_Flags::Target_collision]) {
// use standard collision resolution
aip->ai_flags &= ~AIF_TARGET_COLLISION;
aip->ai_flags.remove(AI::AI_Flags::Target_collision);
big_ship_collide_recover_start(Pl_objp, En_objp, &Pl_objp->pos, NULL);
} else {
// too close for comfort so fly to box point + 300
@@ -1301,7 +1301,7 @@ void ai_big_strafe_attack()
if ( ai_big_strafe_maybe_retreat(target_dist, &target_pos) )
return;
if (aip->ai_flags & AIF_KAMIKAZE) {
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);
accelerate_ship(aip, 1.0f);
@@ -1313,7 +1313,7 @@ void ai_big_strafe_attack()
}
}
if (!(aip->ai_flags & AIF_SEEK_LOCK) || (aip->aspect_locked_time < 2.0f)) {
if (!(aip->ai_flags[AI::AI_Flags::Seek_lock]) || (aip->aspect_locked_time < 2.0f)) {
t = ai_endangered_by_weapon(aip);
if ( t > 0.0f && t < 1.5f ) {
// set up goal_point for avoid path to turn towards
@@ -1351,7 +1351,7 @@ void ai_big_strafe_attack()
turn_towards_point(Pl_objp, &target_pos, NULL, 0.0f);
fix last_hit = Missiontime - aip->last_hit_time;
if ( aip->ai_profile_flags2 & AIPF2_AI_CAN_SLOW_DOWN_ATTACKING_BIG_SHIPS ) {
if ( aip->ai_profile_flags[AI::Profile_Flags::Ai_can_slow_down_attacking_big_ships] ) {
// Slow down if we've not been hit for a while
if ( target_dist > 1200 || last_hit < F1_0*6) {
accel = 1.0f;
@@ -1622,7 +1622,7 @@ void ai_big_strafe_position()
aip = &Ai_info[Ships[Pl_objp->instance].ai_index];
//Maybe use AIS_STRAFE_GLIDE_ATTACK
if ((sip->can_glide == true) && !(aip->ai_flags & AIF_KAMIKAZE) && (frand() < aip->ai_glide_strafe_percent)) {
if ((sip->can_glide == true) && !(aip->ai_flags[AI::AI_Flags::Kamikaze]) && (frand() < aip->ai_glide_strafe_percent)) {
aip->submode = AIS_STRAFE_GLIDE_ATTACK;
aip->submode_parm1 = 0;
} else {
@@ -1809,8 +1809,8 @@ void ai_big_strafe_maybe_attack_turret(object *ship_objp, object *weapon_objp)
// the ai will not always go after different ships firing beams at them.
// Approx 1/4 chance we'll go after the other ship's beam.
bool attack_turret_on_different_ship = (aip->ai_profile_flags & AIPF_BIG_SHIPS_CAN_ATTACK_BEAM_TURRETS_ON_UNTARGETED_SHIPS)
&& (Weapon_info[Weapons[weapon_objp->instance].weapon_info_index].wi_flags & WIF_BEAM) && (frand()*100 < 25.0f);
bool attack_turret_on_different_ship = (aip->ai_profile_flags[AI::Profile_Flags::Big_ships_can_attack_beam_turrets_on_untargeted_ships])
&& (Weapon_info[Weapons[weapon_objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Beam]) && (frand()*100 < 25.0f);
// unless we're making an exception, we should only attack a turret if it sits on the current target
if ( !attack_turret_on_different_ship )
+454 -511
View File
File diff suppressed because it is too large. Load diff
+130 -81
View File
@@ -59,6 +59,7 @@ int Ai_goal_signature;
int Num_ai_dock_names = 0;
char Ai_dock_names[MAX_AI_DOCK_NAMES][NAME_LENGTH];
// Used in objecttypes.tbl to define custom ship types
ai_goal_list Ai_goal_names[] =
{
{ "Attack ship", AI_GOAL_CHASE, 0 },
@@ -85,6 +86,7 @@ ai_goal_list Ai_goal_names[] =
{ "Play dead", AI_GOAL_PLAY_DEAD, 0 },
{ "Attack weapon", AI_GOAL_CHASE_WEAPON, 0 },
{ "Fly to ship", AI_GOAL_FLY_TO_SHIP, 0 },
{ "Attack ship class", AI_GOAL_CHASE_SHIP_CLASS, 0 },
};
int Num_ai_goals = sizeof(Ai_goal_names) / sizeof(ai_goal_list);
@@ -96,34 +98,34 @@ int Num_ai_goals = sizeof(Ai_goal_names) / sizeof(ai_goal_list);
const char *Ai_goal_text(int goal)
{
switch(goal) {
case 1:
case AI_GOAL_CHASE:
case AI_GOAL_CHASE_WING:
case AI_GOAL_CHASE_SHIP_CLASS:
return XSTR( "attack ", 474);
case 2:
case AI_GOAL_DOCK:
return XSTR( "dock ", 475);
case 3:
case AI_GOAL_WAYPOINTS:
case AI_GOAL_WAYPOINTS_ONCE:
return XSTR( "waypoints", 476);
case 4:
return XSTR( "waypoints", 476);
case 6:
case AI_GOAL_DESTROY_SUBSYSTEM:
return XSTR( "destroy ", 477);
case 7:
case AI_GOAL_FORM_ON_WING:
return XSTR( "form on ", 478);
case 8:
case AI_GOAL_UNDOCK:
return XSTR( "undock ", 479);
case 9:
return XSTR( "attack ", 474);
case 10:
case AI_GOAL_GUARD:
case AI_GOAL_GUARD_WING:
return XSTR( "guard ", 480);
case 11:
case AI_GOAL_DISABLE_SHIP:
return XSTR( "disable ", 481);
case 12:
case AI_GOAL_DISARM_SHIP:
return XSTR( "disarm ", 482);
case 15:
return XSTR( "guard ", 480);
case 16:
case AI_GOAL_EVADE_SHIP:
return XSTR( "evade ", 483);
case 19:
case AI_GOAL_REARM_REPAIR:
return XSTR( "rearm ", 484);
case AI_GOAL_FLY_TO_SHIP:
return XSTR( "rendezvous with ", -1);
}
// Avoid compiler warning
@@ -238,7 +240,7 @@ void ai_remove_ship_goal( ai_info *aip, int index )
aip->goals[index].ai_mode = AI_GOAL_NONE;
aip->goals[index].signature = -1;
aip->goals[index].priority = -1;
aip->goals[index].flags = 0; // must reset the flags since not doing so will screw up goal sorting.
aip->goals[index].flags.reset(); // must reset the flags since not doing so will screw up goal sorting.
if ( index == aip->active_goal )
aip->active_goal = AI_GOAL_NONE;
@@ -287,7 +289,7 @@ void ai_clear_wing_goals( int wingnum )
wingp->ai_goals[i].ai_mode = AI_GOAL_NONE;
wingp->ai_goals[i].signature = -1;
wingp->ai_goals[i].priority = -1;
wingp->ai_goals[i].flags = 0;
wingp->ai_goals[i].flags.reset();
}
@@ -347,7 +349,7 @@ void ai_mission_wing_goal_complete( int wingnum, ai_goal *remove_goalp )
wingp->ai_goals[i].ai_mode = AI_GOAL_NONE;
wingp->ai_goals[i].signature = -1;
wingp->ai_goals[i].priority = -1;
wingp->ai_goals[i].flags = 0;
wingp->ai_goals[i].flags.reset();
break;
}
}
@@ -408,31 +410,41 @@ void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list, ai_info *ai
if ( purge_goal->target_name == NULL )
continue;
// determine if the purge goal is acting either on the ship or the ship's wing.
purge_wing = wing_name_lookup( purge_goal->target_name, 1 );
// if the target of the purge goal is a ship (purge_wing will be -1), then if the names
// don't match, we can continue; if the wing is valid, don't process if the wing numbers
// are different.
if ( purge_wing == -1 ) {
if ( stricmp(purge_goal->target_name, name ) )
// goals operating on ship classes are handled slightly differently
if ( purge_ai_mode == AI_GOAL_CHASE_SHIP_CLASS ) {
// if the target of the purge goal is the same class of ship we are concerned about, then we have a match;
// if it is not, then we can continue (see standard ship check below)
if ( stricmp(purge_goal->target_name, Ship_info[Ships[ship_index].ship_info_index].name) )
continue;
} else if ( purge_wing != wingnum )
continue;
}
// standard goals operating on either wings or ships
else {
// determine if the purge goal is acting either on the ship or the ship's wing.
purge_wing = wing_name_lookup( purge_goal->target_name, 1 );
// if the target of the purge goal is a ship (purge_wing will be -1), then if the names
// don't match, we can continue; if the wing is valid, don't process if the wing numbers
// are different.
if ( purge_wing == -1 ) {
if ( stricmp(purge_goal->target_name, name ) )
continue;
} else if ( purge_wing != wingnum )
continue;
}
switch (mode)
{
// ignore goals should get rid of any kind of attack goal
case AI_GOAL_IGNORE:
case AI_GOAL_IGNORE_NEW:
if ( purge_ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP | AI_GOAL_CHASE | AI_GOAL_CHASE_WING | AI_GOAL_DESTROY_SUBSYSTEM) )
purge_goal->flags |= AIGF_PURGE;
if ( purge_ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP | AI_GOAL_CHASE | AI_GOAL_CHASE_WING | AI_GOAL_CHASE_SHIP_CLASS | AI_GOAL_DESTROY_SUBSYSTEM) )
purge_goal->flags.set(AI::Goal_Flags::Purge);
break;
// disarm/disable goals should remove attacks from certain ships types
case AI_GOAL_DISARM_SHIP:
case AI_GOAL_DISABLE_SHIP:
if ( purge_ai_mode & (AI_GOAL_CHASE | AI_GOAL_CHASE_WING) ) {
if ( purge_ai_mode & (AI_GOAL_CHASE | AI_GOAL_CHASE_WING | AI_GOAL_CHASE_SHIP_CLASS) ) {
int ai_ship_type;
// for wings we grab the ship type of the wing leader
@@ -452,7 +464,7 @@ void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list, ai_info *ai
// being disarmed/disabled
for ( j=0 ; j < (int)crippled_ships_type->ai_cripple_ignores.size(); j++) {
if (crippled_ships_type->ai_cripple_ignores[j] == ai_ship_type) {
purge_goal->flags |= AIGF_PURGE;
purge_goal->flags.set(AI::Goal_Flags::Purge);
}
}
}
@@ -601,7 +613,8 @@ void ai_goal_fixup_dockpoints(ai_info *aip, ai_goal *aigp)
aigp->docker.index = docker_index;
aigp->dockee.index = dockee_index;
aigp->flags |= AIGF_DOCK_INDEXES_VALID;
aigp->flags.set(AI::Goal_Flags::Dockee_index_valid);
aigp->flags.set(AI::Goal_Flags::Docker_index_valid);
}
// these functions deal with adding goals sent from the player. They are slightly different
@@ -739,7 +752,8 @@ void ai_add_ship_goal_scripting(int mode, int submode, int priority, char *shipn
if ( mode == AI_GOAL_DOCK ) {
aigp->docker.name = Ships[aip->shipnum].ship_name;
aigp->dockee.name = shipname;
aigp->flags &= ~AIGF_DOCK_INDEXES_VALID;
aigp->flags.remove(AI::Goal_Flags::Dockee_index_valid);
aigp->flags.remove(AI::Goal_Flags::Docker_index_valid);
}
ai_add_goal_sub_scripting(AIG_TYPE_PLAYER_SHIP, mode, submode, priority, shipname, aigp);
@@ -818,7 +832,7 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
aigp->target_name = NULL;
aigp->time = Missiontime;
aigp->type = type;
aigp->flags = 0;
aigp->flags.reset();
op = get_operator_const( text );
@@ -851,7 +865,7 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
// store the name of the subsystem in the docker.name field for now -- this field must get
// fixed up when the goal is valid since we need to locate the subsystem on the ship's model
aigp->docker.name = ai_get_goal_target_name(CTEXT(CDR(CDR(node))), &dummy);
aigp->flags |= AIGF_SUBSYS_NEEDS_FIXUP;
aigp->flags.set(AI::Goal_Flags::Subsys_needs_fixup);
aigp->priority = atoi( CTEXT(CDR(CDR(CDR(node)))) );
break;
@@ -905,7 +919,8 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
aigp->target_name = ai_get_goal_target_name( CTEXT(CDR(node)), &aigp->target_name_index );
aigp->docker.name = ai_add_dock_name(CTEXT(CDR(CDR(node))));
aigp->dockee.name = ai_add_dock_name(CTEXT(CDR(CDR(CDR(node)))));
aigp->flags &= ~AIGF_DOCK_INDEXES_VALID;
aigp->flags.remove(AI::Goal_Flags::Dockee_index_valid);
aigp->flags.remove(AI::Goal_Flags::Docker_index_valid);
aigp->priority = atoi( CTEXT(CDR(CDR(CDR(CDR(node))))) );
aigp->ai_mode = AI_GOAL_DOCK;
@@ -934,9 +949,10 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
break;
case OP_AI_CHASE:
case OP_AI_CHASE_WING:
case OP_AI_CHASE_SHIP_CLASS:
case OP_AI_GUARD:
case OP_AI_GUARD_WING:
case OP_AI_CHASE_WING:
case OP_AI_EVADE_SHIP:
case OP_AI_STAY_NEAR_SHIP:
case OP_AI_IGNORE:
@@ -965,6 +981,8 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
aigp->ai_mode = AI_GOAL_GUARD_WING;
} else if ( op == OP_AI_CHASE_WING ) {
aigp->ai_mode = AI_GOAL_CHASE_WING;
} else if (op == OP_AI_CHASE_SHIP_CLASS) {
aigp->ai_mode = AI_GOAL_CHASE_SHIP_CLASS;
} else if ( op == OP_AI_STAY_NEAR_SHIP ) {
aigp->ai_mode = AI_GOAL_STAY_NEAR_SHIP;
} else if ( op == OP_AI_IGNORE ) {
@@ -986,13 +1004,13 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
}
// Goober5000 - we now have an extra optional chase argument to allow chasing our own team
if ( op == OP_AI_CHASE || op == OP_AI_CHASE_WING || op == OP_AI_DISABLE_SHIP || op == OP_AI_DISARM_SHIP ) {
if ( op == OP_AI_CHASE || op == OP_AI_CHASE_WING || op == OP_AI_CHASE_SHIP_CLASS || op == OP_AI_DISABLE_SHIP || op == OP_AI_DISARM_SHIP ) {
if ((CDDDR(node) != -1) && is_sexp_true(CDDDR(node)))
aigp->flags |= AIGF_TARGET_OWN_TEAM;
aigp->flags.set(AI::Goal_Flags::Target_own_team);
}
if ( op == OP_AI_DESTROY_SUBSYS ) {
if ((CDDDDR(node) != -1) && is_sexp_true(CDDDDR(node)))
aigp->flags |= AIGF_TARGET_OWN_TEAM;
aigp->flags.set(AI::Goal_Flags::Target_own_team);
}
// Goober5000 - since none of the goals act on the actor,
@@ -1004,7 +1022,7 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
aigp->ai_mode = AI_GOAL_NONE;
aigp->signature = -1;
aigp->priority = -1;
aigp->flags = 0;
aigp->flags.reset();
}
}
@@ -1032,7 +1050,7 @@ int ai_find_goal_index( ai_goal* aigp, int mode, int submode, int priority )
/* Remove a goal from the given goals structure
* Returns the index of the goal that it clears out.
* This is importnat so that if active_goal == index you can set AI_GOAL_NONE
* This is important so that if active_goal == index you can set AI_GOAL_NONE
*/
int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp )
{
@@ -1134,6 +1152,10 @@ int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp )
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
goalmode = AI_GOAL_CHASE_WING;
break;
case OP_AI_CHASE_SHIP_CLASS:
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
goalmode = AI_GOAL_CHASE_SHIP_CLASS;
break;
case OP_AI_EVADE_SHIP:
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
goalmode = AI_GOAL_EVADE_SHIP;
@@ -1166,7 +1188,7 @@ int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp )
aigp[goalindex].ai_mode = AI_GOAL_NONE;
aigp[goalindex].signature = -1;
aigp[goalindex].priority = -1;
aigp[goalindex].flags = 0; // must reset the flags since not doing so will screw up goal sorting.
aigp[goalindex].flags.reset(); // must reset the flags since not doing so will screw up goal sorting.
return goalindex;
}
@@ -1264,7 +1286,8 @@ void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int doc
aigp->time = Missiontime;
aigp->type = AIG_TYPE_DYNAMIC;
aigp->flags = AIGF_GOAL_OVERRIDE;
aigp->flags.reset();
aigp->flags.set(AI::Goal_Flags::Goal_override);
switch ( goal_type ) {
@@ -1302,7 +1325,7 @@ void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int doc
aigp->ai_submode = 0;
aigp->target_name = name;
aigp->priority = PLAYER_PRIORITY_MIN-1; // make the priority always less than what the player's is
aigp->flags &= ~AIGF_GOAL_OVERRIDE; // don't override this goal. rearm repair requests should happen in order
aigp->flags.remove(AI::Goal_Flags::Goal_override); // don't override this goal. rearm repair requests should happen in order
ai_goal_fixup_dockpoints( aip, aigp );
break;
@@ -1413,7 +1436,7 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
if (sindex < 0)
return AI_GOAL_NOT_ACHIEVABLE;
aigp->flags |= AIGF_GOAL_OVERRIDE;
aigp->flags.set(AI::Goal_Flags::Goal_override);
return AI_GOAL_ACHIEVABLE;
}
@@ -1431,6 +1454,18 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
return AI_GOAL_ACHIEVABLE;
}
// chasing all ships of a certain ship class is achievable if there are ships of that class present;
// if not, the status is not known because more ships of that class could arrive in the future
// (c.f. AI_GOAL_CHASE_WING subsequent to the next switch statement)
if ( aigp->ai_mode == AI_GOAL_CHASE_SHIP_CLASS ) {
for (objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp)) {
if ((objp->type == OBJ_SHIP) && !strcmp(aigp->target_name, Ship_info[Ships[objp->instance].ship_info_index].name)) {
return AI_GOAL_ACHIEVABLE;
}
}
return AI_GOAL_NOT_KNOWN;
}
return_val = AI_GOAL_SATISFIED;
@@ -1456,7 +1491,7 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// can't determine the status of this goal if ship not valid
// or we haven't found a valid subsystem index yet
if ( (sindex == -1) || (aigp->flags & AIGF_SUBSYS_NEEDS_FIXUP) ) {
if ( (sindex == -1) || (aigp->flags[AI::Goal_Flags::Subsys_needs_fixup]) ) {
status = 0;
break;
}
@@ -1573,7 +1608,7 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
wing *wingp = &Wings[sindex];
if ( wingp->flags & WF_WING_GONE )
if ( wingp->flags[Ship::Wing_Flags::Gone] )
return AI_GOAL_NOT_ACHIEVABLE;
else if ( wingp->total_arrived_count == 0 )
return AI_GOAL_NOT_KNOWN;
@@ -1620,15 +1655,15 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// if the goal is an ignore/disable/disarm goal, then
// Goober5000 - see note at PURGE_GOALS_ALL_SHIPS... this is bizarre
if ((status == SHIP_STATUS_ARRIVED) && !(aigp->flags & AIGF_GOALS_PURGED))
if ((status == SHIP_STATUS_ARRIVED) && !(aigp->flags[AI::Goal_Flags::Goals_purged]))
{
if (aigp->ai_mode & PURGE_GOALS_ALL_SHIPS) {
ai_goal_purge_all_invalid_goals(aigp);
aigp->flags |= AIGF_GOALS_PURGED;
aigp->flags.set(AI::Goal_Flags::Goals_purged);
}
else if (aigp->ai_mode & PURGE_GOALS_ONE_SHIP) {
ai_goal_purge_invalid_goals(aigp, aip->goals, aip, -1);
aigp->flags |= AIGF_GOALS_PURGED;
aigp->flags.set(AI::Goal_Flags::Goals_purged);
}
}
@@ -1636,21 +1671,21 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// only enter this calculation if the ship we are docking with has arrived. If the ship is gone, then
// this goal will get removed.
if ( (aigp->ai_mode == AI_GOAL_DOCK) && (status == SHIP_STATUS_ARRIVED) ) {
if (!(aigp->flags & AIGF_DOCKER_INDEX_VALID)) {
if (!(aigp->flags[AI::Goal_Flags::Docker_index_valid])) {
modelnum = Ship_info[Ships[objp->instance].ship_info_index].model_num;
Assert( modelnum >= 0 );
index = model_find_dock_name_index(modelnum, aigp->docker.name);
aigp->docker.index = index;
aigp->flags |= AIGF_DOCKER_INDEX_VALID;
aigp->flags.set(AI::Goal_Flags::Docker_index_valid);
}
if (!(aigp->flags & AIGF_DOCKEE_INDEX_VALID)) {
if (!(aigp->flags[AI::Goal_Flags::Dockee_index_valid])) {
sindex = ship_name_lookup(aigp->target_name);
if ( sindex != -1 ) {
modelnum = Ship_info[Ships[sindex].ship_info_index].model_num;
index = model_find_dock_name_index(modelnum, aigp->dockee.name);
aigp->dockee.index = index;
aigp->flags |= AIGF_DOCKEE_INDEX_VALID;
aigp->flags.set(AI::Goal_Flags::Dockee_index_valid);
} else
aigp->dockee.index = -1; // this will force code into if statement below making goal not achievable.
}
@@ -1700,7 +1735,7 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
else if (obstacle_objp != goal_objp)
{
// if this goal isn't on hold yet, then issue the undock goal
if ( !(aigp->flags & AIGF_GOAL_ON_HOLD) )
if ( !(aigp->flags[AI::Goal_Flags::Goal_on_hold]) )
ai_add_goal_ship_internal( aip, AI_GOAL_UNDOCK, Ships[obstacle_objp->instance].ship_name, -1, -1, 0 );
// return NOT_KNOWN which will place the goal on hold until the undocking is complete.
@@ -1725,12 +1760,12 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// if the ship has arrived, and the goal is destroy subsystem, then check to see that we
// have fixed up the subsystem name (of the subsystem to destroy) into an index into
// the ship's subsystem list
if ( aigp->flags & AIGF_SUBSYS_NEEDS_FIXUP ) {
if ( aigp->flags[AI::Goal_Flags::Subsys_needs_fixup] ) {
sindex = ship_name_lookup( aigp->target_name );
if ( sindex != -1 ) {
aigp->ai_submode = ship_get_subsys_index( &Ships[sindex], aigp->docker.name );
aigp->flags &= ~AIGF_SUBSYS_NEEDS_FIXUP;
aigp->flags.remove(AI::Goal_Flags::Subsys_needs_fixup);
} else {
Int3();
return AI_GOAL_NOT_ACHIEVABLE; // force this goal to be invalid
@@ -1802,7 +1837,7 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
}
// if desitnation currently being repaired, then goal is stil active
if ( Ai_info[Ships[sindex].ai_index].ai_flags & AIF_BEING_REPAIRED )
if ( Ai_info[Ships[sindex].ai_index].ai_flags[AI::AI_Flags::Being_repaired] )
return AI_GOAL_ACHIEVABLE;
// if the destination ship is dying or departing (but not completed yet), the mark goal as
@@ -1811,11 +1846,11 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
return AI_GOAL_NOT_ACHIEVABLE;
// if the destination object is no longer awaiting repair, then remove the item
if ( !(Ai_info[Ships[sindex].ai_index].ai_flags & AIF_AWAITING_REPAIR) )
if ( !(Ai_info[Ships[sindex].ai_index].ai_flags[AI::AI_Flags::Awaiting_repair]) )
return AI_GOAL_NOT_ACHIEVABLE;
// not repairing anything means that he can do this goal!!!
if ( !(aip->ai_flags & AIF_REPAIRING) )
if ( !(aip->ai_flags[AI::AI_Flags::Repairing]) )
return AI_GOAL_ACHIEVABLE;
// test code!!!
@@ -1852,17 +1887,17 @@ int ai_goal_priority_compare(const void *a, const void *b)
// If the flag is set, don't push the goal higher in the list even if priority
// is higher since goal cannot currently be achieved.
if ( (ga->flags & AIGF_GOAL_ON_HOLD) && !(gb->flags & AIGF_GOAL_ON_HOLD) )
if ( (ga->flags[AI::Goal_Flags::Goal_on_hold]) && !(gb->flags[AI::Goal_Flags::Goal_on_hold]) )
return 1;
else if ( !(ga->flags & AIGF_GOAL_ON_HOLD) && (gb->flags & AIGF_GOAL_ON_HOLD) )
else if ( !(ga->flags[AI::Goal_Flags::Goal_on_hold]) && (gb->flags[AI::Goal_Flags::Goal_on_hold]) )
return -1;
// check whether or not the goal override flag is set. If it is set, then push this goal higher
// in the list
else if ( (ga->flags & AIGF_GOAL_OVERRIDE) && !(gb->flags & AIGF_GOAL_OVERRIDE) )
else if ( (ga->flags[AI::Goal_Flags::Goal_override]) && !(gb->flags[AI::Goal_Flags::Goal_override]) )
return -1;
else if ( !(ga->flags & AIGF_GOAL_OVERRIDE) && (gb->flags & AIGF_GOAL_OVERRIDE) )
else if ( !(ga->flags[AI::Goal_Flags::Goal_override]) && (gb->flags[AI::Goal_Flags::Goal_override]) )
return 1;
// now normal priority processing
@@ -1917,7 +1952,7 @@ void validate_mission_goals(int objnum, ai_info *aip)
continue;
// purge any goals which should get purged
if ( aigp->flags & AIGF_PURGE ) {
if ( aigp->flags[AI::Goal_Flags::Purge] ) {
ai_remove_ship_goal( aip, i );
continue;
}
@@ -1931,19 +1966,19 @@ void validate_mission_goals(int objnum, ai_info *aip)
}
// if the status is achievable, and the on_hold flag is set, clear the flagb
if ( (state == AI_GOAL_ACHIEVABLE) && (aigp->flags & AIGF_GOAL_ON_HOLD) )
aigp->flags &= ~AIGF_GOAL_ON_HOLD;
if ( (state == AI_GOAL_ACHIEVABLE) && (aigp->flags[AI::Goal_Flags::Goal_on_hold]) )
aigp->flags.remove(AI::Goal_Flags::Goal_on_hold);
// if the goal is not known, then set the ON_HOLD flag so that it doesn't get counted as
// a goal to be pursued
if ( state == AI_GOAL_NOT_KNOWN )
aigp->flags |= AIGF_GOAL_ON_HOLD; // put this goal on hold until it becomes true
if (state == AI_GOAL_NOT_KNOWN)
aigp->flags.set(AI::Goal_Flags::Goal_on_hold); // put this goal on hold until it becomes true
}
// if we had an active goal, and that goal is now in hold, make the mode AIM_NONE. If a new valid
// goal is produced after prioritizing, then the mode will get reset immediately. Otherwise, setting
// the mode to none will force ship to do default behavior.
if ( (aip->goals[0].ai_mode != AI_GOAL_NONE) && (aip->goals[0].flags & AIGF_GOAL_ON_HOLD) )
if ( (aip->goals[0].ai_mode != AI_GOAL_NONE) && (aip->goals[0].flags[AI::Goal_Flags::Goal_on_hold]) )
aip->mode = AIM_NONE;
// if the active goal is a rearm/repair goal, the put all other valid goals (which are not repair goals)
@@ -1952,7 +1987,7 @@ void validate_mission_goals(int objnum, ai_info *aip)
for ( i = 1; i < MAX_AI_GOALS; i++ ) {
if ( (aip->goals[i].ai_mode == AI_GOAL_NONE) || (aip->goals[i].ai_mode == AI_GOAL_REARM_REPAIR) )
continue;
aip->goals[i].flags |= AIGF_GOAL_ON_HOLD;
aip->goals[i].flags.set(AI::Goal_Flags::Goal_on_hold);
}
}
}
@@ -2020,7 +2055,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
// if the first goal in the list has the ON_HOLD flag, set, there is no current valid goal
// to pursue.
if ( aip->goals[0].flags & AIGF_GOAL_ON_HOLD )
if ( aip->goals[0].flags[AI::Goal_Flags::Goal_on_hold] )
return;
// Kind of a hack for now. active_goal means the goal currently being pursued.
@@ -2038,7 +2073,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
// if this object was flying in formation off of another object, remove the flag that tells him
// to do this. The form-on-my-wing command is removed from the goal list as soon as it is called, so
// we are safe removing this bit here.
aip->ai_flags &= ~AIF_FORMATION_OBJECT;
aip->ai_flags.remove(AI::AI_Flags::Formation_object);
// Goober5000 - we may want to use AI for the player
// AL 3-7-98: If this is a player ship, and the goal is not a formation goal, then do a quick out
@@ -2116,7 +2151,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
// be sure that we have indices for docking points here! If we ever had names, they should
// get fixed up in goal_achievable so that the points can be checked there for validity
Assert (current_goal->flags & AIGF_DOCK_INDEXES_VALID);
Assert (current_goal->flags[AI::Goal_Flags::Dockee_index_valid] && current_goal->flags[AI::Goal_Flags::Docker_index_valid]);
ai_dock_with_object( objp, current_goal->docker.index, other_obj, current_goal->dockee.index, AIDO_DOCK );
break;
}
@@ -2198,7 +2233,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
if (current_goal->ai_mode != AI_GOAL_DESTROY_SUBSYSTEM) {
if (aip->target_objnum != -1) {
// Only protect if _not_ a capital ship. We don't want the Lucifer accidentally getting protected.
if (Ship_types[Ship_info[Ships[shipnum].ship_info_index].class_type].ai_bools & STI_AI_PROTECTED_ON_CRIPPLE)
if (Ship_types[Ship_info[Ships[shipnum].ship_info_index].class_type].flags[Ship::Type_Info_Flags::AI_protected_on_cripple])
Objects[aip->target_objnum].flags.set(Object::Object_Flags::Protected);
}
} else // Just in case this ship had been protected, unprotect it.
@@ -2210,7 +2245,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
case AI_GOAL_CHASE_WING:
wingnum = wing_name_lookup( current_goal->target_name );
Assert( wingnum >= 0 );
Assertion( wingnum >= 0, "The target of AI_GOAL_CHASE_WING must refer to a valid wing!" );
ai_attack_wing(objp, wingnum);
break;
@@ -2218,6 +2253,13 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
ai_attack_object( objp, NULL, NULL );
break;
// chase-ship-class is chase-any but restricted to a subset of ships
case AI_GOAL_CHASE_SHIP_CLASS:
shipnum = ship_info_lookup( current_goal->target_name );
Assertion( shipnum >= 0, "The target of AI_GOAL_CHASE_SHIP_CLASS must refer to a valid ship class!" );
ai_attack_object( objp, NULL, NULL, shipnum );
break;
case AI_GOAL_WARP: {
mission_do_departure( objp, true );
break;
@@ -2347,15 +2389,22 @@ void ai_update_goal_references(ai_goal *goals, int type, const char *old_name, c
flag = 1;
}
break;
default:
Warning(LOCATION, "unhandled FRED reference type %d in ai_update_goal_references", type);
break;
}
if (flag) // is this a valid goal to parse for this conversion?
if (!stricmp(goals[i].target_name, old_name)) {
{
if (!stricmp(goals[i].target_name, old_name))
{
if (*new_name == '<') // target was just deleted..
goals[i].ai_mode = AI_GOAL_NONE;
else
goals[i].target_name = ai_get_goal_target_name(new_name, &dummy);
}
}
}
}
+4 -1
View File
@@ -26,6 +26,7 @@ struct ai_goal;
// Fred. If the goal you add doesn't have a target (such as chase_any), then you don't have
// to worry about doing this. Also add it to list in Fred\Management.cpp, and let Hoffoss know!
// WMC - Oh and add them to Ai_goal_names plz. TY! :)
// Goober5000 - As well as Ai_goal_text and Ai_goal_list, if appropriate
#define AI_GOAL_CHASE (1<<1) // 0x00000002
#define AI_GOAL_DOCK (1<<2) // 0x00000004 // used for undocking as well
#define AI_GOAL_WAYPOINTS (1<<3) // 0x00000008
@@ -51,10 +52,12 @@ struct ai_goal;
// resume regular goals
#define AI_GOAL_STAY_STILL (1<<20) // 0x00100000
#define AI_GOAL_PLAY_DEAD (1<<21) // 0x00200000
#define AI_GOAL_CHASE_WEAPON (1<<22) // 0x00400000
// added by SCP
#define AI_GOAL_CHASE_WEAPON (1<<22) // 0x00400000
#define AI_GOAL_FLY_TO_SHIP (1<<23) // 0x00800000
#define AI_GOAL_IGNORE_NEW (1<<24) // 0x01000000
#define AI_GOAL_CHASE_SHIP_CLASS (1<<25) // 0x02000000
// now the masks for ship types
+121 -177
View File
@@ -14,7 +14,7 @@
#include "network/multi.h"
#include "network/multimsgs.h"
#include "object/objectdock.h"
#include "parse/scripting.h"
#include "scripting/scripting.h"
#include "render/3d.h"
#include "ship/ship.h"
#include "ship/shipfx.h"
@@ -47,7 +47,7 @@ float Player_lethality_bump[NUM_SKILL_LEVELS] = {
0.0f, 0.0f, 0.0f, 0.0f, 0.0f
};
char *Turret_target_order_names[NUM_TURRET_ORDER_TYPES] = {
const char *Turret_target_order_names[NUM_TURRET_ORDER_TYPES] = {
"Bombs",
"Ships",
"Asteroids",
@@ -158,7 +158,7 @@ bool is_object_radius_in_turret_fov(object *objp, ship_subsys *ss, vec3d *tvec,
fix_elevation = true;
}
if (tp->flags & MSS_FLAG_TURRET_ALT_MATH) {
if (tp->flags[Model::Subsystem_Flags::Turret_alt_math]) {
vec3d temp_vec2;
vm_vec_rotate(&temp_vec2, &temp_vec, &ss->world_to_turret_matrix);
@@ -256,54 +256,46 @@ int turret_select_best_weapon(ship_subsys *turret, object *target)
/**
* Returns true if all weapons in swp have the specified flag
*
* @note doesn't work for WIF2
*/
bool all_turret_weapons_have_flags(ship_weapon *swp, int flags)
bool all_turret_weapons_have_flags(ship_weapon *swp, flagset<Weapon::Info_Flags> flags)
{
int i;
for(i = 0; i < swp->num_primary_banks; i++)
{
if(!(Weapon_info[swp->primary_bank_weapons[i]].wi_flags & flags))
if(!(Weapon_info[swp->primary_bank_weapons[i]].wi_flags & flags).any_set())
return false;
}
for(i = 0; i < swp->num_secondary_banks; i++)
{
if(!(Weapon_info[swp->secondary_bank_weapons[i]].wi_flags & flags))
if(!(Weapon_info[swp->secondary_bank_weapons[i]].wi_flags & flags).any_set())
return false;
}
return true;
}
/**
* Returns true if all weapons in swp have the specified flag
*
* @note does work for WIF2, but not WIF
*/
bool all_turret_weapons_have_flags2(ship_weapon *swp, int flags)
bool all_turret_weapons_have_flags(ship_weapon *swp, Weapon::Info_Flags flags)
{
int i;
for(i = 0; i < swp->num_primary_banks; i++)
{
if(!(Weapon_info[swp->primary_bank_weapons[i]].wi_flags2 & flags))
return false;
}
for(i = 0; i < swp->num_secondary_banks; i++)
{
if(!(Weapon_info[swp->secondary_bank_weapons[i]].wi_flags2 & flags))
return false;
}
int i;
for (i = 0; i < swp->num_primary_banks; i++)
{
if (!(Weapon_info[swp->primary_bank_weapons[i]].wi_flags[flags]))
return false;
}
for (i = 0; i < swp->num_secondary_banks; i++)
{
if (!(Weapon_info[swp->secondary_bank_weapons[i]].wi_flags[flags]))
return false;
}
return true;
return true;
}
/**
* Returns true if any of the weapons in swp have flags
*
* @note doesn't work for WIF2
*/
bool turret_weapon_has_flags(ship_weapon *swp, int flags)
bool turret_weapon_has_flags(ship_weapon *swp, Weapon::Info_Flags flags)
{
Assert(swp != NULL);
@@ -311,42 +303,14 @@ bool turret_weapon_has_flags(ship_weapon *swp, int flags)
for(i = 0; i < swp->num_primary_banks; i++)
{
if(swp->primary_bank_weapons[i] >=0) {
if(Weapon_info[swp->primary_bank_weapons[i]].wi_flags & flags)
if(Weapon_info[swp->primary_bank_weapons[i]].wi_flags[flags])
return true;
}
}
for(i = 0; i < swp->num_secondary_banks; i++)
{
if(swp->secondary_bank_weapons[i] >=0) {
if(Weapon_info[swp->secondary_bank_weapons[i]].wi_flags & flags)
return true;
}
}
return false;
}
/**
* Returns true if any of the weapons in swp have flags
*
* @note does work for WIF2, but not WIF
*/
bool turret_weapon_has_flags2(ship_weapon *swp, int flags)
{
Assert(swp != NULL);
int i = 0;
for(i = 0; i < swp->num_primary_banks; i++)
{
if(swp->primary_bank_weapons[i] >=0) {
if(Weapon_info[swp->primary_bank_weapons[i]].wi_flags2 & flags)
return true;
}
}
for(i = 0; i < swp->num_secondary_banks; i++)
{
if(swp->secondary_bank_weapons[i] >=0) {
if(Weapon_info[swp->secondary_bank_weapons[i]].wi_flags2 & flags)
if(Weapon_info[swp->secondary_bank_weapons[i]].wi_flags[flags])
return true;
}
}
@@ -357,11 +321,12 @@ bool turret_weapon_has_flags2(ship_weapon *swp, int flags)
/**
* Just gloms all the flags from all the weapons into one variable. More efficient if all you need to do is test for the existence of a flag.
*/
int turret_weapon_aggregate_flags(ship_weapon *swp)
flagset<Weapon::Info_Flags> turret_weapon_aggregate_flags(ship_weapon *swp)
{
Assert(swp != NULL);
int i = 0, flags = 0;
int i = 0;
flagset<Weapon::Info_Flags> flags;
for (i = 0; i < swp->num_primary_banks; i++)
{
if (swp->primary_bank_weapons[i] >= 0) {
@@ -378,30 +343,6 @@ int turret_weapon_aggregate_flags(ship_weapon *swp)
return flags;
}
/**
* Just gloms all the flags from all the weapons into one variable. More efficient if all you need to do is test for the existence of a flag.
*/
int turret_weapon_aggregate_flags2(ship_weapon *swp)
{
Assert(swp != NULL);
int i = 0, flags2 = 0;
for (i = 0; i < swp->num_primary_banks; i++)
{
if (swp->primary_bank_weapons[i] >= 0) {
flags2 |= Weapon_info[swp->primary_bank_weapons[i]].wi_flags2;
}
}
for (i = 0; i < swp->num_secondary_banks; i++)
{
if (swp->secondary_bank_weapons[i] >= 0) {
flags2 |= Weapon_info[swp->secondary_bank_weapons[i]].wi_flags2;
}
}
return flags2;
}
/**
* Returns true if any of the weapons in swp have the subtype specified
*
@@ -473,7 +414,7 @@ float longest_turret_weapon_range(ship_weapon *swp)
for(i = 0; i < swp->num_primary_banks; i++)
{
wip = &Weapon_info[swp->primary_bank_weapons[i]];
if (wip->wi_flags2 & WIF2_LOCAL_SSM)
if (wip->wi_flags[Weapon::Info_Flags::Local_ssm])
weapon_range = wip->lssm_lock_range;
else
weapon_range = MIN(wip->lifetime * wip->max_speed, wip->weapon_range);
@@ -484,7 +425,7 @@ float longest_turret_weapon_range(ship_weapon *swp)
for(i = 0; i < swp->num_secondary_banks; i++)
{
wip = &Weapon_info[swp->secondary_bank_weapons[i]];
if (wip->wi_flags2 & WIF2_LOCAL_SSM)
if (wip->wi_flags[Weapon::Info_Flags::Local_ssm])
weapon_range = wip->lssm_lock_range;
else
weapon_range = MIN(wip->lifetime * wip->max_speed, wip->weapon_range);
@@ -537,7 +478,7 @@ int valid_turret_enemy(object *objp, object *turret_parent)
}
// Goober5000 - don't fire at cargo containers (now specified in ship_types)
if ( (sip->class_type >= 0) && !(Ship_types[sip->class_type].ai_bools & STI_AI_TURRETS_ATTACK) ) {
if ( (sip->class_type >= 0) && !(Ship_types[sip->class_type].flags[Ship::Type_Info_Flags::AI_turrets_attack]) ) {
return 0;
}
@@ -549,15 +490,15 @@ int valid_turret_enemy(object *objp, object *turret_parent)
weapon *wp = &Weapons[objp->instance];
weapon_info *wip = &Weapon_info[wp->weapon_info_index];
if (wip->subtype == WP_LASER && !(wip->wi_flags3 & WIF3_TURRET_INTERCEPTABLE)) { // If the thing can't be shot down, don't try. -MageKing17
if (wip->subtype == WP_LASER && !(wip->wi_flags[Weapon::Info_Flags::Turret_Interceptable])) { // If the thing can't be shot down, don't try. -MageKing17
return 0;
}
if ( (!((wip->wi_flags & WIF_BOMB) || (wip->wi_flags3 & WIF3_TURRET_INTERCEPTABLE)) && !(Ai_info[Ships[turret_parent->instance].ai_index].ai_profile_flags & AIPF_ALLOW_TURRETS_TARGET_WEAPONS_FREELY) ) ) {
if ( (!((wip->wi_flags[Weapon::Info_Flags::Bomb]) || (wip->wi_flags[Weapon::Info_Flags::Turret_Interceptable])) && !(Ai_info[Ships[turret_parent->instance].ai_index].ai_profile_flags[AI::Profile_Flags::Allow_turrets_target_weapons_freely]) ) ) {
return 0;
}
if ( (wip->wi_flags2 & WIF2_LOCAL_SSM) && (wp->lssm_stage == 3) ) {
if ( (wip->wi_flags[Weapon::Info_Flags::Local_ssm]) && (wp->lssm_stage == 3) ) {
return 0;
}
@@ -657,8 +598,8 @@ void evaluate_obj_as_target(object *objp, eval_enemy_obj_struct *eeo)
// however if this is removed turrets still track targets but don't fire at them (which looks silly)
if (eeo->eeo_flags & EEOF_TAGGED_ONLY) {
if (!ship_is_tagged(objp) &&
( (The_mission.ai_profile->flags2 & AIPF2_STRICT_TURRET_TAGGED_ONLY_TARGETING) ||
( !(objp->type == OBJ_WEAPON) && !(turret_weapon_has_flags(&eeo->turret_subsys->weapons, WIF_SPAWN))) )) {
( (The_mission.ai_profile->flags[AI::Profile_Flags::Strict_turred_tagged_only_targeting]) ||
( !(objp->type == OBJ_WEAPON) && !(turret_weapon_has_flags(&eeo->turret_subsys->weapons, Weapon::Info_Flags::Spawn))) )) {
return;
}
}
@@ -715,7 +656,7 @@ void evaluate_obj_as_target(object *objp, eval_enemy_obj_struct *eeo)
// check if bomb is homing on the turret parent ship
bool check_weapon = true;
if ((Ai_info[Ships[turret_parent_obj->instance].ai_index].ai_profile_flags & AIPF_PREVENT_TARGETING_BOMBS_BEYOND_RANGE) && (dist > eeo->weapon_travel_dist)) {
if ((Ai_info[Ships[turret_parent_obj->instance].ai_index].ai_profile_flags[AI::Profile_Flags::Prevent_targeting_bombs_beyond_range]) && (dist > eeo->weapon_travel_dist)) {
check_weapon = false;
}
@@ -842,12 +783,12 @@ void evaluate_obj_as_target(object *objp, eval_enemy_obj_struct *eeo)
int is_target_beam_valid(ship_weapon *swp, object *objp)
{
// check if turret has beam weapon
if (all_turret_weapons_have_flags(swp, WIF_BEAM)) {
if (all_turret_weapons_have_flags(swp, Weapon::Info_Flags::Beam)) {
if (objp->flags[Object::Object_Flags::Beam_protected]) {
return 0;
}
if (all_turret_weapons_have_flags(swp, WIF_HUGE)) {
if (all_turret_weapons_have_flags(swp, Weapon::Info_Flags::Huge)) {
if (objp->type == OBJ_SHIP && !(Ship_info[Ships[objp->instance].ship_info_index].is_big_or_huge()) ) {
return 0;
}
@@ -889,7 +830,7 @@ int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subs
//wip=&Weapon_info[tp->turret_weapon_type];
//weapon_travel_dist = MIN(wip->lifetime * wip->max_speed, wip->weapon_range);
//if (wip->wi_flags2 & WIF2_LOCAL_SSM)
//if (wip->wi_flags[Weapon::Info_Flags::Local_ssm])
// weapon_travel_dist=wip->lssm_lock_range;
// Set flag based on strength of weapons subsystem. If weapons subsystem is destroyed, don't let turrets fire at bombs
@@ -960,8 +901,8 @@ int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subs
n_tgt_priorities = Weapon_info[priority_weapon_idx].num_targeting_priorities;
}
if (n_tgt_priorities > 0) {
if (n_tgt_priorities > 0)
{
for(int i = 0; i < n_tgt_priorities; i++) {
// courtesy of WMC...
ai_target_priority *tt;
@@ -1008,10 +949,8 @@ int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subs
}
}
if( ( (tt->wif_flags != 0) || (tt->wif2_flags != 0) || (tt->wif3_flags != 0) ) && (ptr->type == OBJ_WEAPON) ) {
if( ( (Weapon_info[Weapons[ptr->instance].weapon_info_index].wi_flags & tt->wif_flags ) == tt->wif_flags)
&& ( (Weapon_info[Weapons[ptr->instance].weapon_info_index].wi_flags2 & tt->wif2_flags ) == tt->wif2_flags)
&& ( (Weapon_info[Weapons[ptr->instance].weapon_info_index].wi_flags3 & tt->wif3_flags ) == tt->wif3_flags) ) {
if( (tt->wif_flags.any_set()) && (ptr->type == OBJ_WEAPON) ) {
if( ( (Weapon_info[Weapons[ptr->instance].weapon_info_index].wi_flags & tt->wif_flags ) == tt->wif_flags) ) {
found_something = true;
}
}
@@ -1087,7 +1026,11 @@ int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subs
return return_objnum;
}
}
} else {
} else
{
flagset<Weapon::Info_Flags> tmp_flagset;
const Weapon::Info_Flags weapon_flags[] = { Weapon::Info_Flags::Huge, Weapon::Info_Flags::Flak, Weapon::Info_Flags::Homing_aspect, Weapon::Info_Flags::Homing_heat, Weapon::Info_Flags::Homing_javelin, Weapon::Info_Flags::Spawn };
tmp_flagset.set_multiple(std::begin(weapon_flags), std::end(weapon_flags));
for(int i = 0; i < NUM_TURRET_ORDER_TYPES; i++)
{
@@ -1101,14 +1044,14 @@ int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subs
case 0:
//Return if a bomb is found
//don't fire anti capital ship turrets at bombs.
if ( !((aip->ai_profile_flags & AIPF_HUGE_TURRET_WEAPONS_IGNORE_BOMBS) && big_only_flag) )
if ( !((aip->ai_profile_flags[AI::Profile_Flags::Huge_turret_weapons_ignore_bombs]) && big_only_flag) )
{
// Missile_obj_list
for( mo = GET_FIRST(&Missile_obj_list); mo != END_OF_LIST(&Missile_obj_list); mo = GET_NEXT(mo) ) {
objp = &Objects[mo->objnum];
Assert(objp->type == OBJ_WEAPON);
if ((Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags & WIF_BOMB) || (Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags3 & WIF3_TURRET_INTERCEPTABLE))
if ((Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Bomb]) || (Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Turret_Interceptable]))
{
evaluate_obj_as_target(objp, &eeo);
}
@@ -1151,7 +1094,8 @@ int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subs
// - lasers
// - dumbfire type missiles
// - AAA beams
if ( !all_turret_weapons_have_flags(swp, WIF_HUGE | WIF_FLAK | WIF_HOMING | WIF_SPAWN) ) {
if ( !all_turret_weapons_have_flags(swp, tmp_flagset) ) {
// Asteroid_obj_list
for ( ao = GET_FIRST(&Asteroid_obj_list); ao != END_OF_LIST(&Asteroid_obj_list); ao = GET_NEXT(ao) ) {
objp = &Objects[ao->objnum];
@@ -1192,12 +1136,12 @@ int find_turret_enemy(ship_subsys *turret_subsys, int objnum, vec3d *tpos, vec3d
enemy_team_mask = iff_get_attackee_mask(obj_team(&Objects[objnum]));
bool big_only_flag = all_turret_weapons_have_flags(&turret_subsys->weapons, WIF_HUGE);
bool small_only_flag = all_turret_weapons_have_flags2(&turret_subsys->weapons, WIF2_SMALL_ONLY);
bool tagged_only_flag = all_turret_weapons_have_flags2(&turret_subsys->weapons, WIF2_TAGGED_ONLY) || (turret_subsys->weapons.flags & SW_FLAG_TAGGED_ONLY);
bool big_only_flag = all_turret_weapons_have_flags(&turret_subsys->weapons, Weapon::Info_Flags::Huge);
bool small_only_flag = all_turret_weapons_have_flags(&turret_subsys->weapons, Weapon::Info_Flags::Small_only);
bool tagged_only_flag = all_turret_weapons_have_flags(&turret_subsys->weapons, Weapon::Info_Flags::Tagged_only) || (turret_subsys->weapons.flags[Ship::Weapon_Flags::Tagged_Only]);
bool beam_flag = turret_weapon_has_flags(&turret_subsys->weapons, WIF_BEAM);
bool flak_flag = turret_weapon_has_flags(&turret_subsys->weapons, WIF_FLAK);
bool beam_flag = turret_weapon_has_flags(&turret_subsys->weapons, Weapon::Info_Flags::Beam);
bool flak_flag = turret_weapon_has_flags(&turret_subsys->weapons, Weapon::Info_Flags::Flak);
bool laser_flag = turret_weapon_has_subtype(&turret_subsys->weapons, WP_LASER);
bool missile_flag = turret_weapon_has_subtype(&turret_subsys->weapons, WP_MISSILE);
@@ -1205,7 +1149,7 @@ int find_turret_enemy(ship_subsys *turret_subsys, int objnum, vec3d *tpos, vec3d
ai_info *aip = &Ai_info[Ships[Objects[objnum].instance].ai_index];
sip = &Ship_info[Ships[Objects[objnum].instance].ship_info_index];
if ((Ship_types[sip->class_type].ship_bools & STI_TURRET_TGT_SHIP_TGT) && (aip->target_objnum != -1)) {
if ((Ship_types[sip->class_type].flags[Ship::Type_Info_Flags::Turret_tgt_ship_tgt]) && (aip->target_objnum != -1)) {
int target_objnum = aip->target_objnum;
if (Objects[target_objnum].signature == aip->target_signature) {
@@ -1339,7 +1283,7 @@ void ship_get_global_turret_gun_info(object *objp, ship_subsys *ssp, vec3d *gpos
if (use_angles) {
model_instance_find_world_dir(gvec, &tp->turret_norm, Ships[objp->instance].model_instance_num, tp->turret_gun_sobj, &objp->orient);
} else if (tp->flags2 & MSS_FLAG2_SHARE_FIRE_DIRECTION) {
} else if (tp->flags[Model::Subsystem_Flags::Share_fire_direction]) {
vec3d avg, tmp_pos, tmp_target, enemy_point, turret_norm;
vm_vec_avg_n(&avg, tp->turret_num_firing_points, tp->turret_firing_point);
@@ -1377,7 +1321,7 @@ void ship_get_global_turret_gun_info(object *objp, ship_subsys *ssp, vec3d *gpos
vec3d target_moving_direction = ssp->last_aim_enemy_vel;
//Try to guess where the enemy will be, and store that spot in predicted_enemy_pos
if (The_mission.ai_profile->flags & AIPF_USE_ADDITIVE_WEAPON_VELOCITY) {
if (The_mission.ai_profile->flags[AI::Profile_Flags::Use_additive_weapon_velocity]) {
vm_vec_scale_sub2(&target_moving_direction, &objp->phys_info.vel, wip->vel_inherit_amount);
}
@@ -1473,7 +1417,7 @@ int aifft_rotate_turret(ship *shipp, int parent_objnum, ship_subsys *ss, object
target_moving_direction = ss->last_aim_enemy_vel;
//Try to guess where the enemy will be, and store that spot in predicted_enemy_pos
if (The_mission.ai_profile->flags & AIPF_USE_ADDITIVE_WEAPON_VELOCITY) {
if (The_mission.ai_profile->flags[AI::Profile_Flags::Use_additive_weapon_velocity]) {
vm_vec_scale_sub2(&target_moving_direction, &objp->phys_info.vel, wip->vel_inherit_amount);
}
@@ -1507,10 +1451,10 @@ int aifft_rotate_turret(ship *shipp, int parent_objnum, ship_subsys *ss, object
tp, &Objects[parent_objnum].orient,
&ss->submodel_info_1.angs, &ss->submodel_info_2.angs,
&Objects[parent_objnum].pos, predicted_enemy_pos, shipp->objnum);
} else if ((tp->flags & MSS_FLAG_TURRET_RESET_IDLE) &&(timestamp_elapsed(ss->rotation_timestamp))) {
} else if ((tp->flags[Model::Subsystem_Flags::Turret_reset_idle]) &&(timestamp_elapsed(ss->rotation_timestamp))) {
ret_val = model_rotate_gun(Ship_info[shipp->ship_info_index].model_num, tp, &Objects[parent_objnum].orient, &ss->submodel_info_1.angs, &ss->submodel_info_2.angs, &Objects[parent_objnum].pos, predicted_enemy_pos, shipp->objnum, true);
}
} else if ((ss->system_info->flags & MSS_FLAG_TURRET_RESET_IDLE) && (timestamp_elapsed(ss->rotation_timestamp))) {
} else if ((ss->system_info->flags[Model::Subsystem_Flags::Turret_reset_idle]) && (timestamp_elapsed(ss->rotation_timestamp))) {
ret_val = model_rotate_gun(Ship_info[shipp->ship_info_index].model_num, ss->system_info, &Objects[parent_objnum].orient, &ss->submodel_info_1.angs, &ss->submodel_info_2.angs, &Objects[parent_objnum].pos, predicted_enemy_pos, shipp->objnum, true);
}
@@ -1521,7 +1465,7 @@ int aifft_rotate_turret(ship *shipp, int parent_objnum, ship_subsys *ss, object
// return 0 by default (to preserve retail behavior) but allow for a per-subsystem option
// for using the turret normals for firing
if (ss->system_info->flags & MSS_FLAG_FIRE_ON_NORMAL)
if (ss->system_info->flags[Model::Subsystem_Flags::Fire_on_normal])
return 1;
return 0;
@@ -1546,7 +1490,7 @@ float aifft_compute_turret_dot(object *objp, object *enemy_objp, vec3d *abs_gunp
vm_vec_unrotate(&turret_norm, &turret_subsysp->system_info->turret_norm, &objp->orient);
float dot_return = vm_vec_dot(&turret_norm, &vector_out);
if (Ai_info[Ships[objp->instance].ai_index].ai_profile_flags & AIPF_SMART_SUBSYSTEM_TARGETING_FOR_TURRETS) {
if (Ai_info[Ships[objp->instance].ai_index].ai_profile_flags[AI::Profile_Flags::Smart_subsystem_targeting_for_turrets]) {
if (dot_return > turret_subsysp->system_info->turret_fov) {
// target is in sight and in fov
return dot_return;
@@ -1675,7 +1619,7 @@ ship_subsys *aifft_find_turret_subsys(object *objp, ship_subsys *ssp, object *en
int idx;
float dot_fov_modifier = 0.0f;
if (Ai_info[shipp->ai_index].ai_profile_flags & AIPF_SMART_SUBSYSTEM_TARGETING_FOR_TURRETS) {
if (Ai_info[shipp->ai_index].ai_profile_flags[AI::Profile_Flags::Smart_subsystem_targeting_for_turrets]) {
if (ssp->system_info->turret_fov < 0)
dot_fov_modifier = ssp->system_info->turret_fov;
}
@@ -1733,7 +1677,7 @@ void turret_set_next_fire_timestamp(int weapon_num, weapon_info *wip, ship_subsy
turret->weapons.burst_counter[weapon_num]++;
} else {
wait *= wip->fire_wait;
if ((wip->burst_shots > 0) && (wip->burst_flags & WBF_RANDOM_LENGTH)) {
if ((wip->burst_shots > 0) && (wip->burst_flags[Weapon::Burst_Flags::Random_length])) {
turret->weapons.burst_counter[weapon_num] = (myrand() % wip->burst_shots);
} else {
turret->weapons.burst_counter[weapon_num] = 0;
@@ -1747,13 +1691,13 @@ void turret_set_next_fire_timestamp(int weapon_num, weapon_info *wip, ship_subsy
fs_dest = &turret->weapons.next_secondary_fire_stamp[weapon_num - MAX_SHIP_PRIMARY_BANKS];
//Check for the new cooldown flag
if(!((wip->wi_flags2 & WIF2_SAME_TURRET_COOLDOWN) || ((wip->burst_shots > 0) && (wip->burst_flags & WBF_FAST_FIRING))))
if(!((wip->wi_flags[Weapon::Info_Flags::Same_turret_cooldown]) || ((wip->burst_shots > 0) && (wip->burst_flags[Weapon::Burst_Flags::Fast_firing]))))
{
// make side even for team vs. team
if (MULTI_TEAM) {
// flak guns need to fire more rapidly
if (wip->wi_flags & WIF_FLAK) {
if (wip->wi_flags[Weapon::Info_Flags::Flak]) {
wait *= aip->ai_ship_fire_delay_scale_friendly * 0.5f;
if (aip->ai_class_autoscale)
wait += (Num_ai_classes - aip->ai_class - 1) * 40.0f;
@@ -1764,7 +1708,7 @@ void turret_set_next_fire_timestamp(int weapon_num, weapon_info *wip, ship_subsy
}
} else {
// flak guns need to fire more rapidly
if (wip->wi_flags & WIF_FLAK) {
if (wip->wi_flags[Weapon::Info_Flags::Flak]) {
if (Ships[aip->shipnum].team == Player_ship->team) {
wait *= aip->ai_ship_fire_delay_scale_friendly * 0.5f;
} else {
@@ -1773,7 +1717,7 @@ void turret_set_next_fire_timestamp(int weapon_num, weapon_info *wip, ship_subsy
if (aip->ai_class_autoscale)
wait += (Num_ai_classes - aip->ai_class - 1) * 40.0f;
} else if (wip->wi_flags & WIF_HUGE) {
} else if (wip->wi_flags[Weapon::Info_Flags::Huge]) {
// make huge weapons fire independently of team
wait *= aip->ai_ship_fire_delay_scale_friendly;
if (aip->ai_class_autoscale)
@@ -1842,7 +1786,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
object *objp;
bool last_shot_in_salvo = true;
if (turret->system_info->flags & MSS_FLAG_TURRET_SALVO)
if (turret->system_info->flags[Model::Subsystem_Flags::Turret_salvo])
{
if ((turret->turret_next_fire_pos + 1) == (turret->system_info->turret_num_firing_points))
{
@@ -1869,12 +1813,12 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
object *tobjp = &Objects[turret->turret_enemy_objnum];
// should not get this far. check if ship is protected from beam and weapon is type beam
if ( (wip->wi_flags & WIF_BEAM) && (tobjp->flags[Object::Object_Flags::Beam_protected]) ) {
if ( (wip->wi_flags[Weapon::Info_Flags::Beam]) && (tobjp->flags[Object::Object_Flags::Beam_protected]) ) {
Int3();
return 0;
}
// should not get this far. check if ship is protected from flak and weapon is type flak
else if ( (wip->wi_flags & WIF_FLAK) && (tobjp->flags[Object::Object_Flags::Flak_protected]) ) {
else if ( (wip->wi_flags[Weapon::Info_Flags::Flak]) && (tobjp->flags[Object::Object_Flags::Flak_protected]) ) {
Int3();
return 0;
}
@@ -1900,9 +1844,9 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
turret_set_next_fire_timestamp(weapon_num, wip, turret, parent_aip);
// if this weapon is a beam weapon, handle it specially
if (wip->wi_flags & WIF_BEAM) {
if (wip->wi_flags[Weapon::Info_Flags::Beam]) {
// if this beam isn't free to fire
if (!(turret->weapons.flags & SW_FLAG_BEAM_FREE)) {
if (!(turret->weapons.flags[Ship::Weapon_Flags::Beam_Free])) {
return false;
}
beam_fire_info fire_info;
@@ -1914,7 +1858,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
fire_info.beam_info_override = NULL;
fire_info.shooter = &Objects[parent_objnum];
fire_info.target = &Objects[turret->turret_enemy_objnum];
if (wip->wi_flags2 & WIF2_ANTISUBSYSBEAM)
if (wip->wi_flags[Weapon::Info_Flags::Antisubsysbeam])
fire_info.target_subsys = turret->targeted_subsys;
else
fire_info.target_subsys = NULL;
@@ -1938,14 +1882,14 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
return true;
}
// don't fire swam, but set up swarm info instead
else if ((wip->wi_flags & WIF_SWARM) || (wip->wi_flags & WIF_CORKSCREW)) {
else if ((wip->wi_flags[Weapon::Info_Flags::Swarm]) || (wip->wi_flags[Weapon::Info_Flags::Corkscrew])) {
ship_weapon *swp = &turret->weapons;
if (swp->current_secondary_bank < 0) {
swp->current_secondary_bank = 0;
}
int bank_to_fire = swp->current_secondary_bank;
if ((turret->system_info->flags2 & MSS_FLAG2_TURRET_USE_AMMO) && (swp->secondary_bank_ammo[bank_to_fire] < 0)) {
if (!(turret->system_info->flags & MSS_FLAG_USE_MULTIPLE_GUNS)) {
if ((turret->system_info->flags[Model::Subsystem_Flags::Turret_use_ammo]) && (swp->secondary_bank_ammo[bank_to_fire] < 0)) {
if (!(turret->system_info->flags[Model::Subsystem_Flags::Use_multiple_guns])) {
swp->current_secondary_bank++;
if (swp->current_secondary_bank >= swp->num_secondary_banks) {
swp->current_secondary_bank = 0;
@@ -1964,7 +1908,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
// now do anything else
else {
for (int i = 0; i < wip->shots; i++) {
if (turret->system_info->flags2 & MSS_FLAG2_TURRET_USE_AMMO) {
if (turret->system_info->flags[Model::Subsystem_Flags::Turret_use_ammo]) {
ship_weapon *swp;
swp = &turret->weapons;
int bank_to_fire, num_slots = turret->system_info->turret_num_firing_points;
@@ -1988,7 +1932,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
bank_to_fire = swp->current_primary_bank;
if (turret->system_info->flags & MSS_FLAG_TURRET_SALVO) {
if (turret->system_info->flags[Model::Subsystem_Flags::Turret_salvo]) {
points = num_slots;
} else {
points = 1;
@@ -1996,7 +1940,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
if (swp->primary_bank_ammo[bank_to_fire] >= 0) {
swp->primary_bank_ammo[bank_to_fire] -= points;
} else if (!(turret->system_info->flags & MSS_FLAG_USE_MULTIPLE_GUNS) && (swp->primary_bank_ammo[bank_to_fire] < 0)) {
} else if (!(turret->system_info->flags[Model::Subsystem_Flags::Use_multiple_guns]) && (swp->primary_bank_ammo[bank_to_fire] < 0)) {
swp->current_primary_bank++;
if (swp->current_primary_bank >= swp->num_primary_banks) {
swp->current_primary_bank = 0;
@@ -2032,7 +1976,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
if (swp->secondary_bank_ammo[bank_to_fire] >= 0) {
swp->secondary_bank_ammo[bank_to_fire]--;
} else if (!(turret->system_info->flags & MSS_FLAG_USE_MULTIPLE_GUNS) && (swp->secondary_bank_ammo[bank_to_fire] < 0)) {
} else if (!(turret->system_info->flags[Model::Subsystem_Flags::Use_multiple_guns]) && (swp->secondary_bank_ammo[bank_to_fire] < 0)) {
swp->current_secondary_bank++;
if (swp->current_secondary_bank >= swp->num_secondary_banks) {
swp->current_secondary_bank = 0;
@@ -2069,7 +2013,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
Script_system.RemHookVars(4, "Ship", "Weapon", "Beam", "Target");
// if the gun is a flak gun
if (wip->wi_flags & WIF_FLAK) {
if (wip->wi_flags[Weapon::Info_Flags::Flak]) {
// show a muzzle flash
flak_muzzle_flash(turret_pos, turret_fvec, &Objects[parent_ship->objnum].phys_info, turret_weapon_class);
@@ -2097,7 +2041,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
subsys_index = ship_get_index_from_subsys(turret, parent_objnum );
Assert( subsys_index != -1 );
if(wip->wi_flags & WIF_FLAK){
if(wip->wi_flags[Weapon::Info_Flags::Flak]){
send_flak_fired_packet( parent_objnum, subsys_index, weapon_objnum, flak_range );
} else {
send_turret_fired_packet( parent_objnum, subsys_index, weapon_objnum );
@@ -2121,7 +2065,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
}
}
//Not useful -WMC
else if (!(parent_aip->ai_profile_flags & AIPF_DONT_INSERT_RANDOM_TURRET_FIRE_DELAY) && last_shot_in_salvo)
else if (!(parent_aip->ai_profile_flags[AI::Profile_Flags::Dont_insert_random_turret_fire_delay]) && last_shot_in_salvo)
{
float wait = 1000.0f * frand_range(0.9f, 1.1f);
turret->turret_next_fire_stamp = timestamp((int) wait);
@@ -2147,7 +2091,7 @@ void turret_swarm_fire_from_turret(turret_swarm_info *tsi)
}
// if fixed fp make sure to use constant fp
if (tsi->turret->system_info->flags & MSS_FLAG_TURRET_FIXED_FP)
if (tsi->turret->system_info->flags[Model::Subsystem_Flags::Turret_fixed_fp])
tsi->turret->turret_next_fire_pos = tsi->weapon_num;
// change firing point
@@ -2155,13 +2099,13 @@ void turret_swarm_fire_from_turret(turret_swarm_info *tsi)
tsi->turret->turret_next_fire_pos++;
//check if this really is a swarm. If not, how the hell did it get here?
Assert((Weapon_info[tsi->weapon_class].wi_flags & WIF_SWARM) || (Weapon_info[tsi->weapon_class].wi_flags & WIF_CORKSCREW));
Assert((Weapon_info[tsi->weapon_class].wi_flags[Weapon::Info_Flags::Swarm]) || (Weapon_info[tsi->weapon_class].wi_flags[Weapon::Info_Flags::Corkscrew]));
// *If it's a non-homer, then use the last fire direction instead of turret orientation to fix inaccuracy
// problems with non-homing swarm weapons -Et1
if ( (Weapon_info[tsi->weapon_class].subtype == WP_LASER) || ((The_mission.ai_profile->flags & AIPF_HACK_IMPROVE_NON_HOMING_SWARM_TURRET_FIRE_ACCURACY)
&& !(Weapon_info[tsi->weapon_class].wi_flags & WIF_HOMING)) )
if ( (Weapon_info[tsi->weapon_class].subtype == WP_LASER) || ((The_mission.ai_profile->flags[AI::Profile_Flags::Hack_improve_non_homing_swarm_turret_fire_accuracy])
&& !(Weapon_info[tsi->weapon_class].is_homing())) )
{
turret_fvec = tsi->turret->turret_last_fire_direction;
}
@@ -2250,7 +2194,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
}
// Check turret free
if (ss->weapons.flags & SW_FLAG_TURRET_LOCK) {
if (ss->weapons.flags[Ship::Weapon_Flags::Turret_Lock]) {
return;
}
@@ -2273,7 +2217,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
}
// If beam weapon, check beam free
if ( all_turret_weapons_have_flags(swp, WIF_BEAM) && !(swp->flags & SW_FLAG_BEAM_FREE) ) {
if ( all_turret_weapons_have_flags(swp, Weapon::Info_Flags::Beam) && !(swp->flags[Ship::Weapon_Flags::Beam_Free]) ) {
return;
}
@@ -2311,7 +2255,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
//aip = &Ai_info[Ships[objp->instance].ai_index];
// Wanderer - make sure turrets already have all the data
if ( !(tp->flags & MSS_FLAG_TURRET_MATRIX) )
if ( !(tp->flags[Model::Subsystem_Flags::Turret_matrix]) )
{
if (!(tp->turret_gun_sobj == tp->subobj_num))
{
@@ -2323,14 +2267,14 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
vec3d gvec, gpos;
ship_get_global_turret_info(&Objects[parent_objnum], tp, &gpos, &gvec);
if (tp->flags & MSS_FLAG_TURRET_ALT_MATH) {
if (tp->flags[Model::Subsystem_Flags::Turret_alt_math]) {
vm_matrix_x_matrix( &ss->world_to_turret_matrix, &Objects[parent_objnum].orient, &tp->turret_matrix );
}
// Rotate the turret even if time hasn't elapsed, since it needs to turn to face its target.
int use_angles = aifft_rotate_turret(shipp, parent_objnum, ss, objp, lep, &predicted_enemy_pos, &gvec);
if ((tp->flags & MSS_FLAG_FIRE_ON_TARGET) && (ss->points_to_target >= 0.0f))
if ((tp->flags[Model::Subsystem_Flags::Fire_on_target]) && (ss->points_to_target >= 0.0f))
{
// value probably needs tweaking... could perhaps be made into table option?
if (ss->points_to_target > 0.010f)
@@ -2348,7 +2292,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
//WMC - build a list of valid weapons. Fire spawns if there are any.
float dist_to_enemy = 0.0f;
if(lep != NULL) {
if (The_mission.ai_profile->flags2 & AIPF2_TURRETS_IGNORE_TARGET_RADIUS)
if (The_mission.ai_profile->flags[AI::Profile_Flags::Turrets_ignore_target_radius])
dist_to_enemy = MAX(0,vm_vec_normalized_dir(&v2e, &predicted_enemy_pos, &gpos));
else
dist_to_enemy = MAX(0,vm_vec_normalized_dir(&v2e, &predicted_enemy_pos, &gpos) - lep->radius);
@@ -2364,7 +2308,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
for(i = 0; i < (MAX_SHIP_WEAPONS); i++)
{
//WMC - Only fire more than once if we have multiple guns flag set.
if(num_valid > 0 && !(tp->flags & MSS_FLAG_USE_MULTIPLE_GUNS))
if(num_valid > 0 && !(tp->flags[Model::Subsystem_Flags::Use_multiple_guns]))
break;
if(i < MAX_SHIP_PRIMARY_BANKS)
@@ -2396,7 +2340,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
//If this is a spawning type weapon, shoot it!
//If 'smart spawn' just use it like normal weapons
if ( (wip->wi_flags & WIF_SPAWN) && !(wip->wi_flags2 & WIF2_SMART_SPAWN) )
if ( (wip->wi_flags[Weapon::Info_Flags::Spawn]) && !(wip->wi_flags[Weapon::Info_Flags::Smart_spawn]) )
{
if (( num_ships_nearby >= 3 ) || ((num_ships_nearby >= 2) && (frand() < 0.1f))) {
turret_fire_weapon(i, ss, parent_objnum, &gpos, &ss->turret_last_fire_direction);
@@ -2409,7 +2353,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
}
if(wip->wi_flags2 & WIF2_LOCAL_SSM)
if(wip->wi_flags[Weapon::Info_Flags::Local_ssm])
{
weapon_firing_range=wip->lssm_lock_range;
WeaponMinRange = 0.0f;
@@ -2421,7 +2365,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
}
if (wip->wi_flags & WIF_BEAM) {
if (wip->wi_flags[Weapon::Info_Flags::Beam]) {
if ( !((shipp->tag_left > 0) || (shipp->level2_tag_left > 0)) ) {
if (Nebula_sec_range)
{
@@ -2439,7 +2383,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
{
if( (dist_to_enemy <= weapon_firing_range) && (dist_to_enemy >= WeaponMinRange) )
{
if ( wip->wi_flags & WIF_HUGE ) {
if ( wip->wi_flags[Weapon::Info_Flags::Huge] ) {
if ( lep->type != OBJ_SHIP ) {
continue;
}
@@ -2448,13 +2392,13 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
}
}
if ( wip->wi_flags2 & WIF2_SMALL_ONLY ) {
if ( wip->wi_flags[Weapon::Info_Flags::Small_only] ) {
if ( (lep->type == OBJ_SHIP) && (Ship_info[Ships[lep->instance].ship_info_index].is_big_or_huge()) ) {
continue;
}
}
bool tagged_only = ((wip->wi_flags2 & WIF2_TAGGED_ONLY) || (ss->weapons.flags & SW_FLAG_TAGGED_ONLY));
bool tagged_only = ((wip->wi_flags[Weapon::Info_Flags::Tagged_only]) || (ss->weapons.flags[Ship::Weapon_Flags::Tagged_Only]));
if (lep->type == OBJ_SHIP) {
// Check if we're targeting a protected ship
@@ -2465,13 +2409,13 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
}
// Check if we're targeting a beam protected ship with a beam weapon
if ( (lep->flags[Object::Object_Flags::Beam_protected]) && (wip->wi_flags & WIF_BEAM) ) {
if ( (lep->flags[Object::Object_Flags::Beam_protected]) && (wip->wi_flags[Weapon::Info_Flags::Beam]) ) {
ss->turret_enemy_objnum = -1;
ss->turret_time_enemy_in_range = 0.0f;
continue;
}
// Check if we're targeting a flak protected ship with a flak weapon
else if ( (lep->flags[Object::Object_Flags::Flak_protected]) && (wip->wi_flags & WIF_FLAK) ) {
else if ( (lep->flags[Object::Object_Flags::Flak_protected]) && (wip->wi_flags[Weapon::Info_Flags::Flak]) ) {
ss->turret_enemy_objnum = -1;
ss->turret_time_enemy_in_range = 0.0f;
continue;
@@ -2497,7 +2441,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
else
{
// check tagged-only for non-ship targets
if (tagged_only && (!(lep->type == OBJ_WEAPON) || (The_mission.ai_profile->flags2 & AIPF2_STRICT_TURRET_TAGGED_ONLY_TARGETING))) {
if (tagged_only && (!(lep->type == OBJ_WEAPON) || (The_mission.ai_profile->flags[AI::Profile_Flags::Strict_turred_tagged_only_targeting]))) {
continue;
}
}
@@ -2599,7 +2543,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
// Do salvo thing separately - to prevent messing up things
int number_of_firings;
if (tp->flags & MSS_FLAG_TURRET_SALVO)
if (tp->flags[Model::Subsystem_Flags::Turret_salvo])
{
number_of_firings = tp->turret_num_firing_points;
ss->turret_next_fire_pos = 0;
@@ -2611,7 +2555,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
for(i = 0; i < number_of_firings; i++)
{
if (tp->flags & MSS_FLAG_TURRET_FIXED_FP)
if (tp->flags[Model::Subsystem_Flags::Turret_fixed_fp])
{
int ffp_pos = 0;
int ffp_bank;
@@ -2637,7 +2581,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
dist_to_enemy = vm_vec_normalize(&v2e);
dot = vm_vec_dot(&v2e, &gvec);
if (tp->flags & MSS_FLAG_TURRET_SALVO)
if (tp->flags[Model::Subsystem_Flags::Turret_salvo])
wip = get_turret_weapon_wip(&ss->weapons, valid_weapons[0]);
else
wip = get_turret_weapon_wip(&ss->weapons, valid_weapons[i]);
@@ -2653,7 +2597,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
// if the weapon is a flak gun, add some jitter to its aim so it fires in a "cone"
// to make a cool visual effect and make them less lethal
if(wip->wi_flags & WIF_FLAK){
if(wip->wi_flags[Weapon::Info_Flags::Flak]){
flak_jitter_aim(&tv2e, dist_to_enemy, ship_get_subsystem_strength(shipp, SUBSYSTEM_WEAPONS), wip);
}
@@ -2664,11 +2608,11 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
//turret_weapon_class = tp->turret_weapon_type;
bool in_sight = false;
if (The_mission.ai_profile->flags & AIPF_USE_ONLY_SINGLE_FOV_FOR_TURRETS) {
if (The_mission.ai_profile->flags[AI::Profile_Flags::Use_only_single_fov_for_turrets]) {
// we have already passed the FOV test of the turret so...
in_sight = true;
} else {
if (wip->wi_flags & WIF_HOMING_HEAT) {
if (wip->wi_flags[Weapon::Info_Flags::Homing_heat]) {
if (dot > AICODE_TURRET_HEATSEEK_ANGLE) {
in_sight = true;
}
@@ -2679,7 +2623,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
}
}
if ( !(wip->wi_flags & WIF_HOMING) )
if ( !(wip->is_homing()) )
{
if ((dist_to_enemy < 75.0f) || in_sight)
{
@@ -2687,7 +2631,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
ok_to_fire = true;
}
}
else if ( wip->wi_flags & WIF_HOMING_HEAT )
else if ( wip->wi_flags[Weapon::Info_Flags::Homing_heat] )
{ // if heat seekers
if ((dist_to_enemy < 50.0f) || in_sight)
{
@@ -2695,7 +2639,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
ok_to_fire = true;
}
}
else if ( wip->wi_flags & WIF_HOMING_ASPECT )
else if ( wip->wi_flags[Weapon::Info_Flags::Homing_aspect] )
{ // if aspect seeker
if ((dist_to_enemy < 50.0f) || in_sight)
{
@@ -2706,7 +2650,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
ok_to_fire = true;
}
}
else if ( wip->wi_flags & WIF_HOMING_JAVELIN )
else if ( wip->wi_flags[Weapon::Info_Flags::Homing_javelin] )
{ // if javelin heat seeker
if ((dist_to_enemy < 50.0f) || in_sight)
{
@@ -2721,7 +2665,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
}
}
if ( ok_to_fire && (tp->flags & MSS_FLAG_TURRET_HULL_CHECK) ) {
if ( ok_to_fire && (tp->flags[Model::Subsystem_Flags::Turret_hull_check]) ) {
int model_num = Ship_info[shipp->ship_info_index].model_num;
vec3d end;
vm_vec_scale_add(&end, &gpos, &gvec, model_get_radius(model_num));
@@ -2752,7 +2696,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
}
//Wait until the animation is done to actually fire
if (tp->flags & MSS_FLAG_TURRET_ANIM_WAIT && (ss->turret_animation_position != MA_POS_READY))
if (tp->flags[Model::Subsystem_Flags::Turret_anim_wait] && (ss->turret_animation_position != MA_POS_READY))
{
ok_to_fire = false;
}
@@ -2764,13 +2708,13 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
Num_turrets_fired++;
//Pass along which gun we are using
if (tp->flags & MSS_FLAG_TURRET_SALVO)
if (tp->flags[Model::Subsystem_Flags::Turret_salvo])
turret_fire_weapon(valid_weapons[0], ss, parent_objnum, &gpos, &tv2e, &predicted_enemy_pos);
else
turret_fire_weapon(valid_weapons[i], ss, parent_objnum, &gpos, &tv2e, &predicted_enemy_pos);
} else {
// make sure salvo fire mode does not turn into autofire
if ((tp->flags & MSS_FLAG_TURRET_SALVO) && ((i + 1) == number_of_firings)) {
if ((tp->flags[Model::Subsystem_Flags::Turret_salvo]) && ((i + 1) == number_of_firings)) {
ai_info *parent_aip = &Ai_info[Ships[Objects[parent_objnum].instance].ai_index];
turret_set_next_fire_timestamp(valid_weapons[0], wip, ss, parent_aip);
}
@@ -2790,7 +2734,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
// If nothing is OK to fire (lost track of the target?)
// reset the target (so we don't continue to track what we can't hit)
if (tp->flags2 & MSS_FLAG2_TURRET_ONLY_TARGET_IF_CAN_FIRE)
if (tp->flags[Model::Subsystem_Flags::Turret_only_target_if_can_fire])
{
ss->turret_enemy_objnum = -1; // Reset enemy objnum, find a new one next frame.
ss->turret_time_enemy_in_range = 0.0f;
@@ -2874,7 +2818,7 @@ bool turret_adv_fov_test(ship_subsys *ss, vec3d *gvec, vec3d *v2e, float size_mo
bool turret_fov_test(ship_subsys *ss, vec3d *gvec, vec3d *v2e, float size_mod)
{
bool in_fov = false;
if (ss->system_info->flags & MSS_FLAG_TURRET_ALT_MATH)
if (ss->system_info->flags[Model::Subsystem_Flags::Turret_alt_math])
in_fov = turret_adv_fov_test(ss, gvec, v2e, size_mod);
else
in_fov = turret_std_fov_test(ss, gvec, v2e, size_mod);
+7 -4
View File
@@ -19,8 +19,8 @@
#include "io/timer.h"
#include "pcxutils/pcxutils.h"
#include "render/3d.h"
#include "graphics/material.h"
#include "tracing/Monitor.h"
static color Color_xparent;
@@ -505,7 +505,10 @@ int anim_show_next_frame(anim_instance *instance, float frametime)
else {
g3_rotate_vertex(&image_vertex,instance->world_pos);
Assert(instance->radius != 0.0f);
g3_draw_bitmap(&image_vertex, 0, instance->radius*1.5f, TMAP_FLAG_TEXTURED | TMAP_HTL_2D);
//g3_draw_bitmap(&image_vertex, 0, instance->radius*1.5f, TMAP_FLAG_TEXTURED | TMAP_HTL_2D);
material mat_params;
material_set_unlit(&mat_params, bitmap_id, 1.0f, false, false);
g3_render_rect_screen_aligned_2d(&mat_params, &image_vertex, 0, instance->radius*1.5f);
}
instance->last_bitmap = bitmap_id;
@@ -684,7 +687,7 @@ void anim_read_header(anim *ptr, CFILE *fp)
* @details Memory-mapped files will page in the animation from disk as it is needed, but performance is not as good.
* @return Pointer to anim that is loaded if sucess, NULL if failure.
*/
anim *anim_load(char *real_filename, int cf_dir_type, int file_mapped)
anim *anim_load(const char *real_filename, int cf_dir_type, int file_mapped)
{
anim *ptr;
CFILE *fp;
+1 -1
View File
@@ -59,7 +59,7 @@ int anim_stop_playing(anim_instance* anim_instance);
int anim_show_next_frame(anim_instance *instance, float frametime);
void anim_release_all_instances(int screen_id = 0);
void anim_release_render_instance(anim_instance* instance);
anim *anim_load(char *name, int cf_dir_type = CF_TYPE_ANY, int file_mapped = PAGE_FROM_MEM);
anim *anim_load(const char *name, int cf_dir_type = CF_TYPE_ANY, int file_mapped = PAGE_FROM_MEM);
int anim_free(anim *ptr);
int anim_playing(anim_instance *ai);
int anim_write_frames_out(char *filename);
+3 -4
View File
@@ -14,7 +14,6 @@
#include "fireball/fireballs.h"
#include "freespace.h"
#include "gamesnd/gamesnd.h"
#include "globalincs/compatibility.h"
#include "globalincs/linklist.h"
#include "globalincs/systemvars.h"
#include "hud/hud.h"
@@ -33,7 +32,7 @@
#include "object/objcollide.h"
#include "object/object.h"
#include "parse/parselo.h"
#include "parse/scripting.h"
#include "scripting/scripting.h"
#include "particle/particle.h"
#include "render/3d.h"
#include "ship/ship.h"
@@ -1181,7 +1180,7 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
}
}
void asteroid_render(object * obj, draw_list *scene)
void asteroid_render(object * obj, model_draw_list *scene)
{
if (Asteroids_enabled) {
int num;
@@ -1917,7 +1916,7 @@ void asteroid_parse_tbl()
char impact_ani_file[MAX_FILENAME_LEN];
// How did we get here without having any species defined?
Assertion(Species_info.size() > 0,
Assertion(!Species_info.empty(),
"Cannot parse asteroids/debris if there "
"are no species for them to belong to."
);
+2 -2
View File
@@ -19,7 +19,7 @@
class object;
class polymodel;
struct collision_info_struct;
class draw_list;
class model_draw_list;
#define MAX_ASTEROIDS 512
@@ -152,7 +152,7 @@ void asteroid_init();
void asteroid_level_init();
void asteroid_level_close();
void asteroid_create_all();
void asteroid_render(object * obj, draw_list *scene);
void asteroid_render(object * obj, model_draw_list *scene);
void asteroid_delete( object *asteroid_objp );
void asteroid_process_pre( object *asteroid_objp );
void asteroid_process_post( object *asteroid_objp);
+13 -13
View File
@@ -335,7 +335,7 @@ bool StartAutopilot()
{
if (Ships[i].objnum != -1 &&
(Ships[i].flags[Ship::Ship_Flags::Navpoint_carry] ||
(Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags & WF_NAV_CARRY)
(Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags[Ship::Wing_Flags::Nav_carry])
)
)
{
@@ -368,7 +368,7 @@ bool StartAutopilot()
{
if (Ships[i].objnum != -1 &&
(Ships[i].flags[Ship::Ship_Flags::Navpoint_carry] ||
(Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags & WF_NAV_CARRY)
(Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags[Ship::Wing_Flags::Nav_carry])
)
)
{
@@ -423,7 +423,7 @@ bool StartAutopilot()
// snap wings into formation
if (The_mission.flags[Mission::Mission_Flags::Use_ap_cinematics] && // only if using cinematics
(Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags & WF_NAV_CARRY) // only if in a wing
(Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags[Ship::Wing_Flags::Nav_carry]) // only if in a wing
&& Autopilot_flight_leader != &Objects[Ships[i].objnum]) //only if not flight leader's object
{
ai_info *aip = &Ai_info[Ships[i].ai_index];
@@ -434,7 +434,7 @@ bool StartAutopilot()
if (leader_objp != &Objects[Ships[i].objnum])
{
// not leader.. get our position relative to leader
get_absolute_wing_pos_autopilot(&goal_point, leader_objp, wing_index, aip->ai_flags & AIF_FORMATION_OBJECT);
get_absolute_wing_pos_autopilot(&goal_point, leader_objp, wing_index, aip->ai_flags[AI::AI_Flags::Formation_object]);
}
else
{
@@ -501,7 +501,7 @@ bool StartAutopilot()
{
for (i = 0; i < MAX_WINGS; i++)
{
if (Wings[i].flags & WF_NAV_CARRY )
if (Wings[i].flags[Ship::Wing_Flags::Nav_carry] )
{
//ai_add_ship_goal_player( int type, int mode, int submode, char *shipname, ai_info *aip );
@@ -540,7 +540,7 @@ bool StartAutopilot()
if (Ships[i].objnum != -1)
{
if (Ships[i].flags[Ship::Ship_Flags::Navpoint_carry] ||
(Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags & WF_NAV_CARRY))
(Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags[Ship::Wing_Flags::Nav_carry]))
for (j = 0; j < MAX_AI_GOALS; j++)
{
if (Ai_info[Ships[i].ai_index].goals[j].ai_mode == AI_GOAL_WAYPOINTS_ONCE ||
@@ -915,7 +915,7 @@ void EndAutoPilot()
if (Ships[i].objnum != -1 &&
(
Ships[i].flags[Ship::Ship_Flags::Navpoint_carry] ||
(Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags & WF_NAV_CARRY )
(Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags[Ship::Wing_Flags::Nav_carry] )
)
)
{
@@ -950,7 +950,7 @@ void EndAutoPilot()
aigp->ai_mode = AI_GOAL_NONE;
aigp->signature = -1;
aigp->priority = -1;
aigp->flags = 0;
aigp->flags.reset();
}
}
}
@@ -962,7 +962,7 @@ void EndAutoPilot()
{
for (i = 0; i < MAX_WINGS; i++)
{
if (Wings[i].flags & WF_NAV_CARRY )
if (Wings[i].flags[Ship::Wing_Flags::Nav_carry] )
{
for (j = 0; j < MAX_AI_GOALS; j++)
{
@@ -974,7 +974,7 @@ void EndAutoPilot()
aigp->ai_mode = AI_GOAL_NONE;
aigp->signature = -1;
aigp->priority = -1;
aigp->flags = 0;
aigp->flags.reset();
}
}
}
@@ -1045,7 +1045,7 @@ void nav_warp(bool prewarp=false)
{
if (Ships[i].objnum != -1
&& (Ships[i].flags[Ship::Ship_Flags::Navpoint_carry]
|| (Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags & WF_NAV_CARRY)))
|| (Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags[Ship::Wing_Flags::Nav_carry])))
{
vm_vec_add(&Objects[Ships[i].objnum].pos, &Objects[Ships[i].objnum].pos, &targetPos);
Objects[Ships[i].objnum].phys_info.vel = velocity;
@@ -1272,7 +1272,7 @@ void NavSystem_Init()
// ********************************************************************************************
void parse_autopilot_table(char *filename)
void parse_autopilot_table(const char *filename)
{
SCP_vector<SCP_string> lines;
@@ -1315,7 +1315,7 @@ void parse_autopilot_table(char *filename)
Cmdline_autopilot_interruptable = 0;
// No Nav selected message
char *msg_tags[] = { "$No Nav Selected:", "$Gliding:",
const char *msg_tags[] = { "$No Nav Selected:", "$Gliding:",
"$Too Close:", "$Hostiles:", "$Linked:", "$Hazard:",
"$Support Present:", "$Support Working:" };
for (int i = 0; i < NP_NUM_MESSAGES; i++)
+1 -1
View File
@@ -118,7 +118,7 @@ void NavSystem_Do();
void NavSystem_Init();
// parse autopilot.tbl
void parse_autopilot_table(char *filename);
void parse_autopilot_table(const char *filename);
// Finds a Nav point by name
int FindNav(char *Nav);
+17 -7
View File
@@ -29,12 +29,13 @@
#include "io/timer.h"
#include "jpgutils/jpgutils.h"
#include "network/multiutil.h"
#include "palman/palman.h"
#include "parse/parselo.h"
#include "pcxutils/pcxutils.h"
#include "pngutils/pngutils.h"
#include "ship/ship.h"
#include "tgautils/tgautils.h"
#include "tracing/Monitor.h"
#include "tracing/tracing.h"
#include <ctype.h>
#include <limits.h>
@@ -55,7 +56,6 @@ MONITOR(SizeBitmapPage)
// --------------------------------------------------------------------------------------------------------------------
// Definition of public variables (declared as extern in bmpman.h).
int UNLITMAP = -1;
int GLOWMAP = -1;
int SPECMAP = -1;
int SPECGLOSSMAP = -1;
@@ -419,7 +419,7 @@ DCF(bmpman, "Shows/changes bitmap caching parameters and usage") {
}
if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
dc_printf("Total RAM usage: %d bytes\n", bm_texture_ram);
dc_printf("Total RAM usage: " SIZE_T_ARG " bytes\n", bm_texture_ram);
if (Bm_max_ram > 1024 * 1024) {
dc_printf("\tMax RAM allowed: %.1f MB\n", i2fl(Bm_max_ram) / (1024.0f*1024.0f));
@@ -435,14 +435,14 @@ DCF(bmpman, "Shows/changes bitmap caching parameters and usage") {
if (dc_optional_string("flush")) {
dc_printf("Total RAM usage before flush: %d bytes\n", bm_texture_ram);
dc_printf("Total RAM usage before flush: " SIZE_T_ARG " bytes\n", bm_texture_ram);
int i;
for (i = 0; i < MAX_BITMAPS; i++) {
if (bm_bitmaps[i].type != BM_TYPE_NONE) {
bm_free_data(i);
}
}
dc_printf("Total RAM after flush: %d bytes\n", bm_texture_ram);
dc_printf("Total RAM after flush: " SIZE_T_ARG " bytes\n", bm_texture_ram);
} else if (dc_optional_string("ram")) {
dc_stuff_int(&Bm_max_ram);
@@ -525,6 +525,7 @@ int bm_create(int bpp, int w, int h, void *data, int flags) {
bm_bitmaps[n].bm.h = (short)h;
bm_bitmaps[n].bm.rowsize = (short)w;
bm_bitmaps[n].bm.bpp = (ubyte)bpp;
bm_bitmaps[n].bm.true_bpp = (ubyte)bpp;
bm_bitmaps[n].bm.flags = (ubyte)flags;
bm_bitmaps[n].bm.data = 0;
bm_bitmaps[n].bm.palette = NULL;
@@ -2158,7 +2159,7 @@ void bm_lock_apng(int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int
cumulative_frame_delay += the_apng->frame.delay;
be->info.ani.apng.frame_delay = cumulative_frame_delay;
nprintf(("apng", "locking apng frame: %s (%i|%i|%i) (%f) %lu\n", be->filename, bpp, bmp->bpp, bm->true_bpp, be->info.ani.apng.frame_delay, be->mem_taken));
nprintf(("apng", "locking apng frame: %s (%i|%i|%i) (%f) " SIZE_T_ARG "\n", be->filename, bpp, bmp->bpp, bm->true_bpp, be->info.ani.apng.frame_delay, be->mem_taken));
}
}
@@ -2279,7 +2280,7 @@ void bm_lock_pcx(int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int b
data = (ubyte *)bm_malloc(bitmapnum, be->mem_taken);
bmp->bpp = bpp;
bmp->data = (ptr_u)data;
bmp->palette = (bpp == 8) ? gr_palette : NULL;
bmp->palette = NULL;
memset(data, 0, be->mem_taken);
Assert(&be->bm == bmp);
@@ -2577,6 +2578,8 @@ void bm_page_in_start() {
}
void bm_page_in_stop() {
TRACE_SCOPE(tracing::PageInStop);
int i;
#ifndef NDEBUG
@@ -2593,6 +2596,7 @@ void bm_page_in_stop() {
for (i = 0; i < MAX_BITMAPS; i++) {
if ((bm_bitmaps[i].type != BM_TYPE_NONE) && (bm_bitmaps[i].type != BM_TYPE_RENDER_TARGET_DYNAMIC) && (bm_bitmaps[i].type != BM_TYPE_RENDER_TARGET_STATIC)) {
if (bm_bitmaps[i].preloaded) {
TRACE_SCOPE(tracing::PageInSingleBitmap);
if (bm_preloading) {
if (!gr_preload(bm_bitmaps[i].handle, (bm_bitmaps[i].preloaded == 2))) {
mprintf(("Out of VRAM. Done preloading.\n"));
@@ -2994,6 +2998,8 @@ void bm_set_low_mem(int mode) {
}
bool bm_set_render_target(int handle, int face) {
GR_DEBUG_SCOPE("Set render target");
int n = handle % MAX_BITMAPS;
if (n >= 0) {
@@ -3077,6 +3083,10 @@ int bm_unload(int handle, int clear_render_targets, bool nodebug) {
bitmap_entry *be;
bitmap *bmp;
if (handle == -1) {
return -1;
}
int n = handle % MAX_BITMAPS;
Assert((n >= 0) && (n < MAX_BITMAPS));
+4 -4
View File
@@ -26,7 +26,7 @@ camid Main_camera;
//*************************CLASS: camera*************************
//This is where the camera class beings! :D
camera::camera(char *in_name, int in_signature)
camera::camera(const char *in_name, int in_signature)
{
set_name(in_name);
sig = in_signature;
@@ -78,7 +78,7 @@ void camera::reset()
}
}
void camera::set_name(char *in_name)
void camera::set_name(const char *in_name)
{
if(in_name != NULL)
strncpy(name, in_name, NAME_LENGTH-1);
@@ -885,14 +885,14 @@ int cam_get_next_sig()
return next_sig++;
}
camid cam_create(char *n_name, vec3d *n_pos, vec3d *n_norm, object *n_object, int n_object_host_submodel)
camid cam_create(const char *n_name, vec3d *n_pos, vec3d *n_norm, object *n_object, int n_object_host_submodel)
{
matrix ori;
vm_vector_2_matrix_norm(&ori, n_norm);
return cam_create(n_name, n_pos, &ori, n_object, n_object_host_submodel);
}
camid cam_create(char *n_name, vec3d *n_pos, matrix *n_ori, object *n_object, int n_object_host_submodel)
camid cam_create(const char *n_name, vec3d *n_pos, matrix *n_ori, object *n_object, int n_object_host_submodel)
{
camera *cam = NULL;
camid cid;
+4 -4
View File
@@ -43,13 +43,13 @@ protected:
vec3d c_pos;
matrix c_ori;
public:
camera(char *in_name=NULL, int in_signature=-1);
camera(const char *in_name=NULL, int in_signature=-1);
~camera();
void clear();
void reset();
//Set
void set_name(char *in_name);
void set_name(const char *in_name);
void set_object_host(object *objp, int n_object_host_submodel = -1);
void set_object_target(object *objp, int n_object_target_submodel = -1);
@@ -158,8 +158,8 @@ extern float Sexp_fov;
void cam_init();
void cam_close();
void cam_do_frame(float frametime);
camid cam_create(char *n_name=NULL, vec3d *n_pos=NULL, matrix *n_ori=NULL, object *n_object=NULL, int n_submodel_parent=-1);
camid cam_create(char *n_name, vec3d *n_pos, vec3d *n_norm, object *n_object=NULL, int n_submodel_parent=-1);
camid cam_create(const char *n_name=NULL, vec3d *n_pos=NULL, matrix *n_ori=NULL, object *n_object=NULL, int n_submodel_parent=-1);
camid cam_create(const char *n_name, vec3d *n_pos, vec3d *n_norm, object *n_object=NULL, int n_submodel_parent=-1);
void cam_delete(camid cid);
bool cam_set_camera(camid cid);
void cam_reset_camera();
+12 -10
View File
@@ -14,6 +14,7 @@
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>
#ifdef _WIN32
#include <io.h>
@@ -23,7 +24,6 @@
#endif
#ifdef SCP_UNIX
#include <sys/stat.h>
#include <glob.h>
#include <sys/mman.h>
#endif
@@ -69,7 +69,7 @@ cf_pathtype Pathtypes[CF_MAX_PATH_TYPES] = {
{ 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", CF_TYPE_DATA },
{ CF_TYPE_MOVIES, "data" DIR_SEPARATOR_STR "movies", ".mve .msb .ogg .mp4", 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 },
@@ -82,7 +82,7 @@ cf_pathtype Pathtypes[CF_MAX_PATH_TYPES] = {
{ 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", 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 },
@@ -128,12 +128,14 @@ static void dump_opened_files()
}
}
static void cfile_close()
void cfile_close()
{
mprintf(("Still opened files:\n"));
dump_opened_files();
cf_free_secondary_filelist();
cfile_inited = 0;
}
#ifdef SCP_UNIX
@@ -239,8 +241,6 @@ int cfile_init(const char *exe_dir, const char *cdrom_dir)
Cfile_cdrom_dir = cdrom_dir;
cf_build_secondary_filelist(Cfile_cdrom_dir);
atexit(cfile_close);
return 0;
}
@@ -608,7 +608,7 @@ static void mkdir_recursive(const char *path) {
while ((pos = tmp.find_first_of(DIR_SEPARATOR_CHAR, pre)) != std::string::npos) {
dir = tmp.substr(0, pos++);
pre = pos;
if (dir.size() == 0) continue; // if leading / first time is 0 length
if (dir.empty()) continue; // if leading / first time is 0 length
_mkdir(dir.c_str());
}
@@ -621,6 +621,7 @@ void cf_create_directory( int dir_type )
int num_dirs = 0;
int dir_tree[CF_MAX_PATH_TYPES];
char longname[MAX_PATH_LEN];
struct stat statbuf;
Assertion( CF_TYPE_SPECIFIED(dir_type), "Invalid dir_type passed to cf_create_directory." );
@@ -634,13 +635,14 @@ void cf_create_directory( int dir_type )
} while( current_dir != CF_TYPE_ROOT );
int i;
for (i=num_dirs-1; i>=0; i-- ) {
cf_create_default_path_string( longname, sizeof(longname)-1, dir_tree[i], NULL );
mprintf(( "CFILE: Creating new directory '%s'\n", longname ));
mkdir_recursive(longname);
if (stat(longname, &statbuf) != 0) {
mprintf(( "CFILE: Creating new directory '%s'\n", longname ));
mkdir_recursive(longname);
}
}
}
+1
View File
@@ -116,6 +116,7 @@ extern char Cfile_user_dir_legacy[CFILE_ROOT_DIRECTORY_LEN];
//================= LOW-LEVEL FUNCTIONS ==================
int cfile_init(const char *exe_dir, const char *cdrom_dir=NULL);
void cfile_close();
// Call this if pack files got added or removed or the
// cdrom changed. This will refresh the list of filenames
+10 -2
View File
@@ -161,10 +161,15 @@ int cfseek( CFILE *cfile, int offset, int where )
default:
Int3();
return 1;
}
}
// Make sure we don't seek beyond the end of the file
CAP(goal_position, cb->lib_offset, cb->lib_offset + cb->size);
int result = fseek(cb->fp, (long)goal_position, SEEK_SET );
Assertion(goal_position >= cb->lib_offset, "Invalid offset values detected while seeking! Goal was " SIZE_T_ARG ", lib_offset is " SIZE_T_ARG ".", goal_position, cb->lib_offset);
cb->raw_position = goal_position - cb->lib_offset;
Assertion(cb->raw_position <= cb->size, "Invalid raw_position value detected!");
#if defined(CHECK_POSITION) && !defined(NDEBUG)
auto tmp_offset = ftell(cb->fp) - cb->lib_offset;
@@ -200,6 +205,7 @@ int cfread(void *buf, int elsize, int nelem, CFILE *cfile)
}
if ( (cb->raw_position+size) > cb->size ) {
Assertion(cb->raw_position <= cb->size, "Invalid raw_position value detected!");
size = cb->size - cb->raw_position;
if ( size < 1 ) {
return 0;
@@ -219,6 +225,7 @@ int cfread(void *buf, int elsize, int nelem, CFILE *cfile)
size_t bytes_read = fread( buf, 1, size, cb->fp );
if ( bytes_read > 0 ) {
cb->raw_position += bytes_read;
Assertion(cb->raw_position <= cb->size, "Invalid raw_position value detected!");
}
#if defined(CHECK_POSITION) && !defined(NDEBUG)
@@ -249,7 +256,8 @@ int cfread_lua_number(double *buf, CFILE *cfile)
long orig_pos = ftell(cb->fp);
int items_read = fscanf(cb->fp, LUA_NUMBER_SCAN, buf);
cb->raw_position += ftell(cb->fp)-orig_pos;
cb->raw_position += ftell(cb->fp)-orig_pos;
Assertion(cb->raw_position <= cb->size, "Invalid raw_position value detected!");
#if defined(CHECK_POSITION) && !defined(NDEBUG)
auto tmp_offset = ftell(cb->fp) - cb->lib_offset;
+159 -63
View File
@@ -30,6 +30,7 @@
#include <fnmatch.h>
#include <sys/stat.h>
#include <unistd.h>
#include <libgen.h>
#endif
#include "cfile/cfile.h"
@@ -38,12 +39,13 @@
#include "globalincs/pstypes.h"
#include "localization/localize.h"
#include "osapi/osapi.h"
#include "parse/parselo.h"
#define CF_ROOTTYPE_PATH 0
#define CF_ROOTTYPE_PACK 1
// for a defined and specifically set location to get/send pilot/campaign files
char *Pilot_file_path = NULL;
SCP_string Pilot_file_path;
// Created by:
// specifying hard drive tree
@@ -77,12 +79,13 @@ static int Num_path_roots = 0;
// Created by searching all roots in order. This means Files is then sorted by precedence.
typedef struct cf_file {
char name_ext[CF_MAX_FILENAME_LENGTH]; // Filename and extension
int root_index; // Where in Roots this is located
int pathtype_index; // Where in Paths this is located
time_t write_time; // When it was last written
int size; // How big it is in bytes
int pack_offset; // For pack files, where it is at. 0 if not in a pack file. This can be used to tell if in a pack file.
char name_ext[CF_MAX_FILENAME_LENGTH]; // Filename and extension
int root_index; // Where in Roots this is located
int pathtype_index; // Where in Paths this is located
time_t write_time; // When it was last written
int size; // How big it is in bytes
int pack_offset; // For pack files, where it is at. 0 if not in a pack file. This can be used to tell if in a pack file.
char* real_name; // For real files, the full path
} cf_file;
#define CF_NUM_FILES_PER_BLOCK 512
@@ -115,6 +118,7 @@ cf_file *cf_create_file()
if ( File_blocks[block] == NULL ) {
File_blocks[block] = (cf_file_block *)vm_malloc( sizeof(cf_file_block) );
Assert( File_blocks[block] != NULL);
memset(File_blocks[block], 0, sizeof(cf_file_block));
}
Num_files++;
@@ -428,7 +432,7 @@ 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 == NULL)
if (Pilot_file_path.empty())
Pilot_file_path = root->path;
// Next, check any VP files under the current directory.
@@ -455,7 +459,7 @@ 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 == NULL)
if (Pilot_file_path.empty())
Pilot_file_path = root->path;
// Next, check any VP files under the current directory.
@@ -485,7 +489,7 @@ 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 == NULL )
if ( Pilot_file_path.empty() )
Pilot_file_path = root->path;
//======================================================
@@ -534,6 +538,10 @@ void cf_search_root_path(int root_index)
mprintf(( "Searching root '%s' ... ", root->path ));
char search_path[CF_MAX_PATHNAME_LENGTH];
#ifdef SCP_UNIX
// This map stores the mapping between a specific path type and the actual path that we use for it
SCP_unordered_map<int, SCP_string> pathTypeToRealPath;
#endif
for (i=CF_TYPE_ROOT; i<CF_MAX_PATH_TYPES; i++ ) {
@@ -552,6 +560,7 @@ void cf_search_root_path(int root_index)
}
#if defined _WIN32
SCP_string search_directory = search_path;
strcat_s( search_path, "*.*" );
intptr_t find_handle;
@@ -576,6 +585,11 @@ void cf_search_root_path(int root_index)
file->size = find.size;
file->pack_offset = 0; // Mark as a non-packed file
SCP_string file_name;
sprintf(file_name, "%s%s%s", search_directory.c_str(), DIR_SEPARATOR_STR, find.name);
file->real_name = vm_strdup(file_name.c_str());
num_files++;
//mprintf(( "Found file '%s'\n", file->name_ext ));
}
@@ -588,21 +602,80 @@ void cf_search_root_path(int root_index)
_findclose( find_handle );
}
#elif defined SCP_UNIX
DIR *dirp;
struct dirent *dir;
DIR *dirp = nullptr;
SCP_string search_dir;
{
if (i == CF_TYPE_ROOT) {
// Don't search for the same name for the root case since we would be searching in other mod directories in that case
dirp = opendir (search_path);
search_dir.assign(search_path);
} else {
// On Unix we can have a different case for the search paths so we also need to account for that
// We do that by looking at the parent of search_path and enumerating all directories and the check if any of
// them are a case-insensitive match
SCP_string directory_name;
auto parentPathIter = pathTypeToRealPath.find(Pathtypes[i].parent_index);
if (parentPathIter == pathTypeToRealPath.end()) {
// No parent known yet, use the standard dirname
char dirname_copy[CF_MAX_PATHNAME_LENGTH];
memcpy(dirname_copy, search_path, sizeof(search_path));
// According to the documentation of directory_name and basename, the return value does not need to be freed
directory_name.assign(dirname(dirname_copy));
} else {
// we have a valid parent path -> use that
directory_name = parentPathIter->second;
}
char basename_copy[CF_MAX_PATHNAME_LENGTH];
memcpy(basename_copy, search_path, sizeof(search_path));
// According to the documentation of dirname and basename, the return value does not need to be freed
auto search_name = basename(basename_copy);
auto parentDirP = opendir(directory_name.c_str());
if (parentDirP) {
struct dirent *dir = nullptr;
while ((dir = readdir (parentDirP)) != nullptr) {
if (stricmp(search_name, dir->d_name)) {
continue;
}
SCP_string fn;
sprintf(fn, "%s/%s", directory_name.c_str(), dir->d_name);
struct stat buf;
if (stat(fn.c_str(), &buf) == -1) {
continue;
}
if (S_ISDIR(buf.st_mode)) {
// Found a case insensitive match
dirp = opendir(fn.c_str());
search_dir = fn;
// We also need to store this in our mapping since we may need it in the future
pathTypeToRealPath.insert(std::make_pair(i, fn));
break;
}
}
closedir(parentDirP);
}
}
}
dirp = opendir (search_path);
if ( dirp ) {
struct dirent *dir = nullptr;
while ((dir = readdir (dirp)) != NULL)
{
if (!fnmatch ("*.*", dir->d_name, 0))
{
char fn[MAX_PATH];
snprintf(fn, MAX_PATH-1, "%s%s", search_path, dir->d_name);
fn[MAX_PATH-1] = 0;
SCP_string fn;
sprintf(fn, "%s/%s", search_dir.c_str(), dir->d_name);
struct stat buf;
if (stat(fn, &buf) == -1) {
if (stat(fn.c_str(), &buf) == -1) {
continue;
}
@@ -626,6 +699,8 @@ void cf_search_root_path(int root_index)
file->pack_offset = 0; // Mark as a non-packed file
file->real_name = vm_strdup(fn.c_str());
num_files++;
//mprintf(( "Found file '%s'\n", file->name_ext ));
}
@@ -827,6 +902,14 @@ void cf_free_secondary_filelist()
// Init the file blocks
for (i=0; i<CF_MAX_FILE_BLOCKS; i++ ) {
if ( File_blocks[i] ) {
// Free file paths
for (auto& f : File_blocks[i]->files) {
if (f.real_name) {
vm_free(f.real_name);
f.real_name = nullptr;
}
}
vm_free( File_blocks[i] );
File_blocks[i] = NULL;
}
@@ -985,17 +1068,14 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
*offset = (size_t)f->pack_offset;
if (pack_filename) {
cf_root *r = cf_get_root(f->root_index);
strncpy( pack_filename, r->path, max_out );
if (f->pack_offset < 1) {
strcat_s( pack_filename, max_out, Pathtypes[f->pathtype_index].path );
// 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);
if ( pack_filename[strlen(pack_filename)-1] != DIR_SEPARATOR_CHAR )
strcat_s( pack_filename, max_out, DIR_SEPARATOR_STR );
strcat_s( pack_filename, max_out, f->name_ext );
strncpy( pack_filename, r->path, max_out );
}
}
@@ -1013,19 +1093,14 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
*offset = (size_t)f->pack_offset;
if (pack_filename) {
cf_root *r = cf_get_root(f->root_index);
strcpy( pack_filename, r->path );
if (f->pack_offset < 1) {
if ( strlen(Pathtypes[f->pathtype_index].path) ) {
strcat_s( pack_filename, max_out, Pathtypes[f->pathtype_index].path );
// 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);
if ( pack_filename[strlen(pack_filename)-1] != DIR_SEPARATOR_CHAR )
strcat_s( pack_filename, max_out, DIR_SEPARATOR_STR );
}
strcat_s( pack_filename, max_out, f->name_ext );
strncpy( pack_filename, r->path, max_out );
}
}
@@ -1260,17 +1335,14 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
*offset = f->pack_offset;
if (pack_filename) {
cf_root *r = cf_get_root(f->root_index);
strncpy( pack_filename, r->path, max_out );
if (f->pack_offset < 1) {
strcat_s( pack_filename, max_out, Pathtypes[f->pathtype_index].path );
// 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);
if ( pack_filename[strlen(pack_filename)-1] != DIR_SEPARATOR_CHAR )
strcat_s( pack_filename, max_out, DIR_SEPARATOR_STR );
strcat_s( pack_filename, max_out, f->name_ext );
strncpy( pack_filename, r->path, max_out );
}
}
@@ -1291,20 +1363,14 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
*offset = f->pack_offset;
if (pack_filename) {
cf_root *r = cf_get_root(f->root_index);
strcpy( pack_filename, r->path );
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);
if ( strlen(Pathtypes[f->pathtype_index].path) ) {
strcat_s( pack_filename, max_out, Pathtypes[f->pathtype_index].path );
if ( pack_filename[strlen(pack_filename)-1] != DIR_SEPARATOR_CHAR )
strcat_s( pack_filename, max_out, DIR_SEPARATOR_STR );
}
strcat_s( pack_filename, max_out, f->name_ext );
strncpy( pack_filename, r->path, max_out );
}
}
@@ -1537,8 +1603,7 @@ int cf_get_file_list( SCP_vector<SCP_string> &list, int pathtype, const char *fi
}
#endif
bool skip_packfiles = (Skip_packfile_search != 0);
bool skip_packfiles = false;
if ( (pathtype == CF_TYPE_PLAYERS) || (pathtype == CF_TYPE_SINGLE_PLAYERS) || (pathtype == CF_TYPE_MULTI_PLAYERS) ) {
skip_packfiles = true;
} else if (Get_file_list_child != NULL) {
@@ -1563,6 +1628,11 @@ int cf_get_file_list( SCP_vector<SCP_string> &list, int pathtype, const char *fi
continue;
}
if (Skip_packfile_search && f->pack_offset != 0) {
// If the packfile skip flag is set we skip files in VPs but still search in directories
continue;
}
if ( !Get_file_list_filter || (*Get_file_list_filter)(f->name_ext) ) {
//mprintf(( "Found '%s' in root %d path %d\n", f->name_ext, f->root_index, f->pathtype_index ));
@@ -1739,8 +1809,16 @@ int cf_get_file_list( int max, char **list, int pathtype, const char *filter, in
}
#endif
bool skip_packfiles = false;
if ((pathtype == CF_TYPE_PLAYERS) || (pathtype == CF_TYPE_SINGLE_PLAYERS) || (pathtype == CF_TYPE_MULTI_PLAYERS)) {
skip_packfiles = true;
}
else if (Get_file_list_child != NULL) {
skip_packfiles = true;
}
// Search all the packfiles and CD.
if ( !Skip_packfile_search ) {
if ( !skip_packfiles) {
for (i=0; i<Num_files; i++ ) {
cf_file * f = cf_get_file(i);
@@ -1760,6 +1838,11 @@ int cf_get_file_list( int max, char **list, int pathtype, const char *filter, in
continue;
}
if (Skip_packfile_search && f->pack_offset != 0) {
// If the packfile skip flag is set we skip files in VPs but still search in directories
continue;
}
if ( !Get_file_list_filter || (*Get_file_list_filter)(f->name_ext) ) {
//mprintf(( "Found '%s' in root %d path %d\n", f->name_ext, f->root_index, f->pathtype_index ));
@@ -1943,8 +2026,16 @@ int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char *
}
#endif
bool skip_packfiles = false;
if ((pathtype == CF_TYPE_PLAYERS) || (pathtype == CF_TYPE_SINGLE_PLAYERS) || (pathtype == CF_TYPE_MULTI_PLAYERS)) {
skip_packfiles = true;
}
else if (Get_file_list_child != NULL) {
skip_packfiles = true;
}
// Search all the packfiles and CD.
if ( !Skip_packfile_search ) {
if (!skip_packfiles) {
for (uint i=0; i<Num_files; i++ ) {
cf_file * f = cf_get_file(i);
@@ -1965,6 +2056,11 @@ int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char *
continue;
}
if (Skip_packfile_search && f->pack_offset != 0) {
// If the packfile skip flag is set we skip files in VPs but still search in directories
continue;
}
if ( !Get_file_list_filter || (*Get_file_list_filter)(f->name_ext) ) {
//mprintf(( "Found '%s' in root %d path %d\n", f->name_ext, f->root_index, f->pathtype_index ));
@@ -2032,7 +2128,7 @@ int cf_create_default_path_string(char *path, uint path_max, int pathtype, const
// 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, path_max);
strncpy(path, Pilot_file_path.c_str(), path_max);
} else {
strncpy(path, root->path, path_max);
}
+4 -4
View File
@@ -20,10 +20,10 @@ void cf_free_secondary_filelist();
// Internal stuff
typedef struct cf_pathtype {
int index; // To verify that the CF_TYPE define is correctly indexed into this array
char *path; // Path relative to FreeSpace root, has ending backslash.
char *extensions; // Extensions used in this pathtype, separated by spaces
int parent_index; // Index of this directory's parent. Used for creating directories when writing.
int index; // To verify that the CF_TYPE define is correctly indexed into this array
const char* path; // Path relative to FreeSpace root, has ending backslash.
const char* extensions; // Extensions used in this pathtype, separated by spaces
int parent_index; // Index of this directory's parent. Used for creating directories when writing.
} cf_pathtype;
// During cfile_init, verify that Pathtypes[n].index == n for each item
+1 -1
View File
@@ -8,7 +8,7 @@ set_target_properties(cfilearchiver
PROPERTIES
FOLDER "FSOTools"
)
TARGET_LINK_LIBRARIES(cfilearchiver PUBLIC ${SDL_LIBS})
TARGET_LINK_LIBRARIES(cfilearchiver PUBLIC sdl2)
TARGET_INCLUDE_DIRECTORIES(cfilearchiver PUBLIC ${GENERATED_SOURCE_DIR})
TARGET_INCLUDE_DIRECTORIES(cfilearchiver PUBLIC ${GENERATED_SOURCE_DIR}/code)
+10 -31
View File
@@ -315,28 +315,16 @@ int verify_directory( char *filespec )
void print_instructions()
{
printf( "Creates a vp archive out of a FreeSpace data tree.\n\n" );
printf( "Usage: cfilearchiver archive_name src_dir\n");
printf( "Example: cfilearchiver freespace /tmp/freespace/data\n\n");
printf( "Directory structure options:\n" );
printf( " Effects (.ani .pcx .neb .tga)\n" );
printf( " Fonts (.vf)\n" );
printf( " Hud (.ani .pcx .tga\n" );
printf( " Interface (.pcx .ani .tga)\n" );
printf( " Maps (.pcx .ani .tga)\n" );
printf( " Missions (.ntl .ssv), FS1(.fsm .fsc), FS2(.fs2 .fc2)\n" );
printf( " Models (.pof)\n" );
printf( " Music (.wav)\n" );
printf( " Sounds/8b22k (.wav)\n" );
printf( " Sounds/16b11k (.wav)\n" );
printf( " Tables (.tbl)\n" );
printf( " Voice/Briefing (.wav)\n" );
printf( " Voice/Command briefings (.wav)\n" );
printf( " Voice/Debriefing (.wav)\n" );
printf( " Voice/Personas (.wav)\n" );
printf( " Voice/Special (.wav)\n" );
printf( " Voice/Training (.wav)\n" );
printf("Creates a vp archive out of a FreeSpace data tree.\n\n");
printf("Usage: cfilearchiver archive_name src_dir\n");
#ifdef _WIN32
printf("Example: cfilearchiver freespace c:\\freespace\\data\n");
#else
printf("Example: cfilearchiver freespace /tmp/freespace/data\n\n");
#endif
printf("Creates an archive named freespace out of the freespace data tree\n");
printf("For information about the FS2 directory structure, please consult\n");
printf("http://www.hard-light.net/wiki/index.php/FS2_Data_Structure\n");
exit(0);
}
@@ -352,16 +340,7 @@ int main(int argc, char *argv[] )
char *p;
if ( argc < 3 ) {
#ifdef _WIN32
printf( "Usage: %s archive_name src_dir\n", argv[0] );
printf( "Example: %s freespace c:\\freespace\\data\n", argv[0] );
printf( "Creates an archive named freespace out of the\nfreespace data tree\n" );
printf( "Press any key to exit...\n" );
getch();
return 1;
#else
print_instructions();
#endif
}
strcpy_s( archive, argv[1] );
+1 -1
View File
@@ -8,7 +8,7 @@ set_target_properties(cfileextractor
PROPERTIES
FOLDER "FSOTools"
)
TARGET_LINK_LIBRARIES(cfileextractor PUBLIC ${SDL_LIBS})
TARGET_LINK_LIBRARIES(cfileextractor PUBLIC sdl2)
TARGET_INCLUDE_DIRECTORIES(cfileextractor PUBLIC ${GENERATED_SOURCE_DIR})
TARGET_INCLUDE_DIRECTORIES(cfileextractor PUBLIC ${GENERATED_SOURCE_DIR}/code)
+82 -49
View File
@@ -17,7 +17,7 @@
#include "globalincs/version.h"
#include "hud/hudconfig.h"
#include "network/multi.h"
#include "parse/scripting.h"
#include "scripting/scripting.h"
#include "parse/sexp.h"
#include "globalincs/version.h"
#include "globalincs/pstypes.h"
@@ -150,6 +150,7 @@ Flag exe_params[] =
{ "-noscalevid", "Disable scale-to-window for movies", true, 0, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noscalevid", },
{ "-missile_lighting", "Apply lighting to missiles" , true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-missile_lighting", },
{ "-nonormal", "Disable normal maps", true, EASY_DEFAULT_MEM, EASY_MEM_ALL_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-normal" },
{ "-no_emissive_light", "Disable emissive light from ships", true, 0, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_emissive_light" },
{ "-noheight", "Disable height/parallax maps", true, EASY_DEFAULT_MEM, EASY_MEM_ALL_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-height" },
{ "-3dshockwave", "Enable 3D shockwaves", true, EASY_MEM_ALL_ON, EASY_DEFAULT_MEM, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-3dshockwave" },
{ "-post_process", "Enable post processing", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-post_process" },
@@ -195,11 +196,9 @@ Flag exe_params[] =
{ "-nomovies", "Disable video playback", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nomovies", },
{ "-noparseerrors", "Disable parsing errors", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noparseerrors", },
{ "-query_speech", "Check if this build has speech", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-query_speech", },
{ "-novbo", "Disable OpenGL VBO", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-novbo", },
{ "-loadallweps", "Load all weapons, even those not used", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-loadallweps", },
{ "-disable_fbo", "Disable OpenGL RenderTargets", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-disable_fbo", },
{ "-disable_pbo", "Disable OpenGL Pixel Buffer Objects", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-disable_pbo", },
{ "-no_glsl", "Disable GLSL (shader) support", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_glsl", },
{ "-ati_swap", "Fix colour issues on some ATI cards", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-ati_swap", },
{ "-no_3d_sound", "Use only 2D/stereo for sound effects", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_3d_sound", },
{ "-mipmap", "Enable mipmapping", true, 0, EASY_DEFAULT_MEM, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-mipmap", },
@@ -209,6 +208,8 @@ Flag exe_params[] =
{ "-no_batching", "Disable batched model rendering", true, 0, EASY_DEFAULT, "Troubleshoot", "", },
{ "-no_geo_effects", "Disable geometry shader for effects", true, 0, EASY_DEFAULT, "Troubleshoot", "", },
{ "-set_cpu_affinity", "Sets processor affinity to config value", true, 0, EASY_DEFAULT, "Troubleshoot", "", },
{ "-nograb", "Disables mouse grabbing", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nograb", },
{ "-noshadercache", "Disables the shader cache", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noshadercache", },
#ifdef WIN32
{ "-fix_registry", "Use a different registry path", true, 0, EASY_DEFAULT, "Troubleshoot", "", },
#endif
@@ -231,14 +232,16 @@ Flag exe_params[] =
{ "-output_sexps", "Output SEXPs to sexps.html", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-output_sexps", },
{ "-output_scripting", "Output scripting to scripting.html", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-output_scripting", },
{ "-save_render_target", "Save render targets to file", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-save_render_target", },
{ "-debug_window", "Display debug window", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-debug_window", },
{ "-verify_vps", "Spew VP CRCs to vp_crcs.txt", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-verify_vps", },
{ "-reparse_mainhall", "Reparse mainhall.tbl when loading halls", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-reparse_mainhall", },
{ "-profile_frame_time","Profile engine subsystems", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-profile_frame_timings", },
{ "-profile_write_file", "Write profiling information to file", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-profile_write_file", },
{ "-no_unfocused_pause","Don't pause if the window isn't focused", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_unfocused_pause", },
{ "-benchmark_mode", "Puts the game into benchmark mode", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-benchmark_mode", },
{ "-noninteractive", "Disables interactive dialogs", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noninteractive", },
{ "-json_pilot", "Dump pilot files in JSON format", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-json_pilot", },
{ "-json_profiling", "Generate JSON profiling output", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-json_profiling", },
{ "-profile_frame_time","Profile engine subsystems", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-profile_frame_timings", },
{ "-debug_window", "Enable the debug window", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-debug_window", },
};
// forward declaration
@@ -427,10 +430,8 @@ bool Cmdline_portable_mode = false;
cmdline_parm loadallweapons_arg("-loadallweps", NULL, AT_NONE); // Cmdline_load_all_weapons
cmdline_parm nomovies_arg("-nomovies", NULL, AT_NONE); // Cmdline_nomovies -- Allows video streaming
cmdline_parm no_set_gamma_arg("-no_set_gamma", NULL, AT_NONE); // Cmdline_no_set_gamma
cmdline_parm no_vbo_arg("-novbo", NULL, AT_NONE); // Cmdline_novbo
cmdline_parm no_fbo_arg("-disable_fbo", NULL, AT_NONE); // Cmdline_no_fbo
cmdline_parm no_pbo_arg("-disable_pbo", NULL, AT_NONE); // Cmdline_no_pbo
cmdline_parm noglsl_arg("-no_glsl", NULL, AT_NONE); // Cmdline_noglsl -- disable GLSL support in OpenGL
cmdline_parm mipmap_arg("-mipmap", NULL, AT_NONE); // Cmdline_mipmap
cmdline_parm atiswap_arg("-ati_swap", NULL, AT_NONE); // Cmdline_atiswap - Fix ATI color swap issue for screenshots.
cmdline_parm no3dsound_arg("-no_3d_sound", NULL, AT_NONE); // Cmdline_no_3d_sound - Disable use of full 3D sounds
@@ -440,6 +441,8 @@ cmdline_parm old_collision_system("-old_collision", NULL, AT_NONE); // Cmdline_o
cmdline_parm gl_finish ("-gl_finish", NULL, AT_NONE);
cmdline_parm no_geo_sdr_effects("-no_geo_effects", NULL, AT_NONE);
cmdline_parm set_cpu_affinity("-set_cpu_affinity", NULL, AT_NONE);
cmdline_parm nograb_arg("-nograb", NULL, AT_NONE);
cmdline_parm noshadercache_arg("-noshadercache", NULL, AT_NONE);
#ifdef WIN32
cmdline_parm fix_registry("-fix_registry", NULL, AT_NONE);
#endif
@@ -447,10 +450,8 @@ cmdline_parm fix_registry("-fix_registry", NULL, AT_NONE);
int Cmdline_load_all_weapons = 0;
int Cmdline_nomovies = 0;
int Cmdline_no_set_gamma = 0;
int Cmdline_novbo = 0; // turn off OGL VBO support, troubleshooting
int Cmdline_no_fbo = 0;
int Cmdline_no_pbo = 0;
int Cmdline_noglsl = 0;
int Cmdline_ati_color_swap = 0;
int Cmdline_no_3d_sound = 0;
int Cmdline_drawelements = 0;
@@ -458,6 +459,8 @@ char* Cmdline_keyboard_layout = NULL;
bool Cmdline_gl_finish = false;
bool Cmdline_no_geo_sdr_effects = false;
bool Cmdline_set_cpu_affinity = false;
bool Cmdline_nograb = false;
bool Cmdline_noshadercache = false;
#ifdef WIN32
bool Cmdline_alternate_registry_path = false;
#endif
@@ -469,7 +472,6 @@ cmdline_parm dis_weapons("-dis_weapons", NULL, AT_NONE); // Cmdline_dis_weapons
cmdline_parm noparseerrors_arg("-noparseerrors", NULL, AT_NONE); // Cmdline_noparseerrors -- turns off parsing errors -C
cmdline_parm extra_warn_arg("-extra_warn", "Enable 'extra' warnings", AT_NONE); // Cmdline_extra_warn
cmdline_parm fps_arg("-fps", NULL, AT_NONE); // Cmdline_show_fps
cmdline_parm show_mem_usage_arg("-show_mem_usage", NULL, AT_NONE); // Cmdline_show_mem_usage
cmdline_parm pos_arg("-pos", NULL, AT_NONE); // Cmdline_show_pos
cmdline_parm stats_arg("-stats", NULL, AT_NONE); // Cmdline_show_stats
cmdline_parm save_render_targets_arg("-save_render_target", NULL, AT_NONE); // Cmdline_save_render_targets
@@ -480,11 +482,15 @@ cmdline_parm center_res_arg("-center_res", "Resolution of center monitor, format
cmdline_parm verify_vps_arg("-verify_vps", NULL, AT_NONE); // Cmdline_verify_vps -- spew VP crcs to vp_crcs.txt
cmdline_parm parse_cmdline_only(PARSE_COMMAND_LINE_STRING, "Ignore any cmdline_fso.cfg files", AT_NONE);
cmdline_parm reparse_mainhall_arg("-reparse_mainhall", NULL, AT_NONE); //Cmdline_reparse_mainhall
cmdline_parm frame_profile_arg("-profile_frame_time", NULL, AT_NONE); //Cmdline_frame_profile
cmdline_parm frame_profile_write_file("-profile_write_file", NULL, AT_NONE); // Cmdline_profile_write_file
cmdline_parm no_unfocused_pause_arg("-no_unfocused_pause", NULL, AT_NONE); //Cmdline_no_unfocus_pause
cmdline_parm benchmark_mode_arg("-benchmark_mode", NULL, AT_NONE); //Cmdline_benchmark_mode
cmdline_parm noninteractive_arg("-noninteractive", NULL, AT_NONE); //Cmdline_noninteractive
cmdline_parm json_pilot("-json_pilot", NULL, AT_NONE); //Cmdline_json_pilot
cmdline_parm json_profiling("-json_profiling", NULL, AT_NONE); //Cmdline_json_profiling
cmdline_parm show_video_info("-show_video_info", NULL, AT_NONE); //Cmdline_show_video_info
cmdline_parm frame_profile_arg("-profile_frame_time", NULL, AT_NONE); //Cmdline_frame_profile
cmdline_parm debug_window_arg("-debug_window", NULL, AT_NONE); // Cmdline_debug_window
char *Cmdline_start_mission = NULL;
@@ -496,7 +502,6 @@ int Cmdline_noparseerrors = 0;
int Cmdline_nowarn = 0; // turn warnings off in FRED
#endif
int Cmdline_extra_warn = 0;
int Cmdline_show_mem_usage = 0;
int Cmdline_show_pos = 0;
int Cmdline_show_stats = 0;
int Cmdline_save_render_targets = 0;
@@ -506,11 +511,15 @@ char *Cmdline_res = 0;
char *Cmdline_center_res = 0;
int Cmdline_verify_vps = 0;
int Cmdline_reparse_mainhall = 0;
bool Cmdline_frame_profile = false;
bool Cmdline_profile_write_file = false;
bool Cmdline_no_unfocus_pause = false;
bool Cmdline_benchmark_mode = false;
bool Cmdline_noninteractive = false;
bool Cmdline_json_pilot = false;
bool Cmdline_json_profiling = false;
bool Cmdline_frame_profile = false;
bool Cmdline_show_video_info = false;
bool Cmdline_debug_window = false;
// Other
cmdline_parm get_flags_arg("-get_flags", "Output the launcher flags file", AT_NONE);
@@ -780,12 +789,7 @@ void os_validate_parms(int argc, char *argv[])
if (parm_found == 0) {
// if we got a -help, --help, -h, or -? then show the help text, otherwise show unknown option
if (!stricmp(token, "-help") || !stricmp(token, "--help") || !stricmp(token, "-h") || !stricmp(token, "-?")) {
if (FS_VERSION_HAS_REVIS == 0) {
printf("FreeSpace 2 Open, version %i.%i.%i\n", FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD);
}
else {
printf("FreeSpace 2 Open, version %i.%i.%i.%i\n", FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD, FS_VERSION_REVIS);
}
printf("FreeSpace 2 Open, version %s\n", FS_VERSION_FULL);
printf("Website: http://scp.indiegames.us\n");
printf("Mantis (bug reporting): http://scp.indiegames.us/mantis/\n\n");
printf("Usage: fs2_open [options]\n");
@@ -922,32 +926,45 @@ bool has_cmdline_only_flag(int argc, char *argv[])
return false;
}
// remove old parms - needed for tests
static void reset_cmdline_parms()
{
for (cmdline_parm *parmp = GET_FIRST(&Parm_list); parmp != END_OF_LIST(&Parm_list); parmp = GET_NEXT(parmp)) {
if (parmp->args != NULL) {
delete[] parmp->args;
parmp->args = NULL;
}
parmp->name_found = 0;
}
}
// Call once to initialize the command line system
//
// cmdline - command line string passed to the application
void os_init_cmdline(int argc, char *argv[])
{
// Tests call this multiple times, so reset the params here.
// Otherwise e.g. the modlist just grows and grows...
reset_cmdline_parms();
FILE *fp;
if (!has_cmdline_only_flag(argc, argv)) {
// Only parse the config file in the current directory if we are in legacy config mode
if (os_is_legacy_mode()) {
// read the cmdline_fso.cfg file from the data folder, and pass the command line arguments to
// the the parse_parms and validate_parms line. Read these first so anything actually on
// the command line will take precedence
#ifdef _WIN32
fp = fopen("data\\cmdline_fso.cfg", "rt");
#elif defined(APPLE_APP)
#ifdef APPLE_APP
char resolved_path[MAX_PATH], data_path[MAX_PATH_LEN];
GetCurrentDirectory(MAX_PATH_LEN - 1, data_path);
getcwd(data_path, sizeof(data_path));
snprintf(resolved_path, MAX_PATH, "%s/data/cmdline_fso.cfg", data_path);
fp = fopen(resolved_path, "rt");
#else
fp = fopen("data/cmdline_fso.cfg", "rt");
fp = fopen("data" DIR_SEPARATOR_STR "cmdline_fso.cfg", "rt");
#endif
// if the file exists, get a single line, and deal with it
if (fp) {
char *buf, *p;
@@ -961,7 +978,6 @@ void os_init_cmdline(int argc, char *argv[])
if ((p = strrchr(buf, '\n')) != NULL) {
*p = '\0';
}
#ifdef SCP_UNIX
// append a space for the os_parse_parms() check
strcat_s(buf, len, " ");
@@ -992,14 +1008,14 @@ void os_init_cmdline(int argc, char *argv[])
// append a space for the os_parse_parms() check
strcat_s(buf, len, " ");
os_process_cmdline(buf);
}
delete [] buf;
fclose(fp);
}
} // If cmdline included PARSE_COMMAND_LINE_STRING
// By parsing cmdline last, anything actually on the command line will take precedence.
os_parse_parms(argc, argv);
os_validate_parms(argc, argv);
@@ -1194,7 +1210,8 @@ static void handle_unix_modlist(char **modlist, size_t *len)
for (char *cur_mod = strtok(*modlist, ","); cur_mod != NULL; cur_mod = strtok(NULL, ","))
{
SCP_vector<SCP_string> this_mod_paths = unix_get_dir_names(".", cur_mod);
if (this_mod_paths.empty()) {
// Ignore non-existing mods for unit tests
if (!running_unittests && this_mod_paths.empty()) {
ReleaseWarning(LOCATION, "Can't find mod '%s'. Ignoring.", cur_mod);
}
mod_paths.insert(mod_paths.end(), this_mod_paths.begin(), this_mod_paths.end());
@@ -1613,11 +1630,7 @@ bool SetCmdlineParams()
if ( height_arg.found() ) {
Cmdline_height = 0;
}
if ( noglsl_arg.found() ) {
Cmdline_noglsl = 1;
}
if (fxaa_arg.found() ) {
Cmdline_fxaa = true;
@@ -1640,9 +1653,6 @@ bool SetCmdlineParams()
if ( weapon_choice_3d_arg.found() )
Cmdline_weapon_choice_3d = 1;
if ( show_mem_usage_arg.found() )
Cmdline_show_mem_usage = 1;
if (ingamejoin_arg.found() )
Cmdline_ingamejoin = 1;
@@ -1660,11 +1670,6 @@ bool SetCmdlineParams()
output_sexps("sexps.html");
}
if ( no_vbo_arg.found() )
{
Cmdline_novbo = 1;
}
if ( no_pbo_arg.found() )
{
Cmdline_no_pbo = 1;
@@ -1695,6 +1700,16 @@ bool SetCmdlineParams()
Cmdline_set_cpu_affinity = true;
}
if (nograb_arg.found())
{
Cmdline_nograb = true;
}
if (noshadercache_arg.found())
{
Cmdline_noshadercache = true;
}
if (portable_mode.found())
{
Cmdline_portable_mode = true;
@@ -1826,14 +1841,8 @@ bool SetCmdlineParams()
Cmdline_no_deferred_lighting = 1;
}
if (frame_profile_arg.found() )
{
Cmdline_frame_profile = true;
}
if (frame_profile_write_file.found())
{
Cmdline_frame_profile = true;
Cmdline_profile_write_file = true;
}
@@ -1852,6 +1861,30 @@ bool SetCmdlineParams()
Cmdline_noninteractive = true;
}
if (json_pilot.found())
{
Cmdline_json_pilot = true;
}
if (json_profiling.found())
{
Cmdline_json_profiling = true;
}
if (frame_profile_arg.found() )
{
Cmdline_frame_profile = true;
}
if (debug_window_arg.found()) {
Cmdline_debug_window = true;
}
if (show_video_info.found())
{
Cmdline_show_video_info = true;
}
//Deprecated flags - CommanderDJ
if( deprecated_spec_arg.found() )
{
+8 -4
View File
@@ -80,6 +80,7 @@ extern bool Cmdline_fb_thrusters;
extern bool Cmdline_no_batching;
extern int Cmdline_shadow_quality;
extern int Cmdline_no_deferred_lighting;
extern int Cmdline_no_emissive;
// Game Speed related
extern int Cmdline_cache_bitmaps;
@@ -124,10 +125,8 @@ extern bool Cmdline_portable_mode;
extern int Cmdline_load_all_weapons;
extern int Cmdline_nomovies; // WMC Toggles movie playing support
extern int Cmdline_no_set_gamma;
extern int Cmdline_novbo;
extern int Cmdline_no_fbo;
extern int Cmdline_no_pbo;
extern int Cmdline_noglsl;
extern int Cmdline_mipmap;
extern int Cmdline_ati_color_swap;
extern int Cmdline_no_3d_sound;
@@ -136,6 +135,8 @@ extern char* Cmdline_keyboard_layout;
extern bool Cmdline_gl_finish;
extern bool Cmdline_no_geo_sdr_effects;
extern bool Cmdline_set_cpu_affinity;
extern bool Cmdline_nograb;
extern bool Cmdline_noshadercache;
#ifdef WIN32
extern bool Cmdline_alternate_registry_path;
#endif
@@ -147,16 +148,19 @@ extern int Cmdline_dis_collisions;
extern int Cmdline_dis_weapons;
extern int Cmdline_noparseerrors;
extern int Cmdline_extra_warn;
extern int Cmdline_show_mem_usage;
extern int Cmdline_show_pos;
extern int Cmdline_show_stats;
extern int Cmdline_save_render_targets;
extern int Cmdline_verify_vps;
extern int Cmdline_reparse_mainhall;
extern bool Cmdline_frame_profile;
extern bool Cmdline_profile_write_file;
extern bool Cmdline_no_unfocus_pause;
extern bool Cmdline_benchmark_mode;
extern bool Cmdline_noninteractive;
extern bool Cmdline_json_pilot;
extern bool Cmdline_json_profiling;
extern bool Cmdline_frame_profile;
extern bool Cmdline_show_video_info;
extern bool Cmdline_debug_window;
#endif
+2 -2
View File
@@ -62,7 +62,7 @@ void cmeasure_select_next(ship *shipp)
{
new_index = (shipp->current_cmeasure + i) % Num_weapon_types;
if(Weapon_info[new_index].wi_flags & WIF_CMEASURE)
if(Weapon_info[new_index].wi_flags[Weapon::Info_Flags::Cmeasure])
{
shipp->current_cmeasure = new_index;
return;
@@ -88,7 +88,7 @@ void cmeasure_maybe_alert_success(object *objp)
return;
}
Assert(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags & WIF_CMEASURE);
Assert(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Cmeasure]);
if ( objp->parent == OBJ_INDEX(Player_obj) ) {
hud_start_text_flash(XSTR("Evaded", 1430), 800);
+16 -16
View File
@@ -25,7 +25,7 @@
#include "missionui/missionscreencommon.h"
#include "network/multi_pmsg.h"
#include "network/multiutil.h"
#include "parse/scripting.h"
#include "scripting/scripting.h"
#include "pilotfile/pilotfile.h"
#include "popup/popup.h"
#include "ui/ui.h"
@@ -48,12 +48,12 @@
#define CONTROL_W_COORD 2
#define CONTROL_H_COORD 3
char* Conflict_background_bitmap_fname[GR_NUM_RESOLUTIONS] = {
const char* Conflict_background_bitmap_fname[GR_NUM_RESOLUTIONS] = {
"ControlConfig", // GR_640
"2_ControlConfig" // GR_1024
};
char* Conflict_background_bitmap_mask_fname[GR_NUM_RESOLUTIONS] = {
const char* Conflict_background_bitmap_mask_fname[GR_NUM_RESOLUTIONS] = {
"ControlConfig-m", // GR_640
"2_ControlConfig-m" // GR_1024
};
@@ -369,7 +369,7 @@ static int joy_get_unscaled_reading(int raw, int axn)
if (raw > rng)
raw = rng;
return (int) ((uint) raw * (uint) F1_0 / (uint) rng); // convert to 0 - F1_0 range.
return (int) ((std::uint64_t) raw * (std::uint64_t) F1_0 / (std::uint64_t) rng); // convert to 0 - F1_0 range, 64bit ints used to avoid uint overflow
}
int joy_get_scaled_reading(int raw)
@@ -919,7 +919,7 @@ int control_config_do_reset()
bool cycling_presets = false;
// If there are presets, then we'll cycle to the next preset and reset to that
if (Control_config_presets.size() >= 1) {
if (!Control_config_presets.empty()) {
cycling_presets = true;
if (++Defaults_cycle_pos >= Control_config_presets.size())
@@ -1974,7 +1974,7 @@ void control_config_do_frame(float frametime)
if (t % 2) {
gr_set_color_fast(&Color_text_normal);
gr_get_string_size(&w, NULL, XSTR( "?", 208));
gr_printf_menu(x - w / 2, y - font_height / 2, XSTR( "?", 208));
gr_printf_menu(x - w / 2, y - font_height / 2, "%s", XSTR( "?", 208));
}
} else if (!(z & JOY_AXIS) && ((Conflicts[z].key >= 0) || (Conflicts[z].joy >= 0))) {
@@ -1986,7 +1986,7 @@ void control_config_do_frame(float frametime)
gr_set_color_fast(&Color_text_normal);
str = XSTR( "Control conflicts with:", 209);
gr_get_string_size(&w, NULL, str);
gr_printf_menu(x - w / 2, y - font_height, str);
gr_printf_menu(x - w / 2, y - font_height, "%s", str);
if (Control_config[i].hasXSTR) {
strcpy_s(buf, XSTR(Control_config[i].text, CONTROL_CONFIG_XSTR + i));
@@ -1996,12 +1996,12 @@ void control_config_do_frame(float frametime)
font::force_fit_string(buf, 255, Conflict_wnd_coords[gr_screen.res][CONTROL_W_COORD]);
gr_get_string_size(&w, NULL, buf);
gr_printf_menu(x - w / 2, y, buf);
gr_printf_menu(x - w / 2, y, "%s", buf);
} else if (*bound_string) {
gr_set_color_fast(&Color_text_normal);
gr_get_string_size(&w, NULL, bound_string);
gr_printf_menu(x - w / 2, y - font_height / 2, bound_string);
gr_printf_menu(x - w / 2, y - font_height / 2, "%s", bound_string);
if (timestamp_elapsed(bound_timestamp)) {
*bound_string = 0;
}
@@ -2009,7 +2009,7 @@ void control_config_do_frame(float frametime)
if (Cc_lines[Num_cc_lines - 1].y + font_height > Cc_lines[Scroll_offset].y + Control_list_coords[gr_screen.res][CONTROL_H_COORD]) {
gr_set_color_fast(&Color_white);
gr_printf_menu(Control_more_coords[gr_screen.res][CONTROL_X_COORD], Control_more_coords[gr_screen.res][CONTROL_Y_COORD], XSTR( "More...", 210));
gr_printf_menu(Control_more_coords[gr_screen.res][CONTROL_X_COORD], Control_more_coords[gr_screen.res][CONTROL_Y_COORD], "%s", XSTR( "More...", 210));
}
conflict = 0;
@@ -2035,7 +2035,7 @@ void control_config_do_frame(float frametime)
if (Cc_lines[line].label) {
strcpy_s(buf, Cc_lines[line].label);
font::force_fit_string(buf, 255, Control_list_ctrl_w[gr_screen.res]);
gr_printf_menu(Control_list_coords[gr_screen.res][CONTROL_X_COORD], y, buf);
gr_printf_menu(Control_list_coords[gr_screen.res][CONTROL_X_COORD], y, "%s", buf);
}
if (!(z & JOY_AXIS)) {
@@ -2046,7 +2046,7 @@ void control_config_do_frame(float frametime)
if ((k < 0) && (j < 0)) {
gr_set_color_fast(&Color_grey);
gr_printf_menu(x, y, XSTR( "None", 211));
gr_printf_menu(x, y, "%s", XSTR( "None", 211));
} else {
if (k >= 0) {
@@ -2066,7 +2066,7 @@ void control_config_do_frame(float frametime)
gr_set_color_fast(c);
}
gr_printf_menu(x, y, buf);
gr_printf_menu(x, y, "%s", buf);
Cc_lines[line].kx = x - Control_list_coords[gr_screen.res][CONTROL_X_COORD];
gr_get_string_size(&w, NULL, buf);
@@ -2075,7 +2075,7 @@ void control_config_do_frame(float frametime)
if (j >= 0) {
gr_set_color_fast(&Color_text_normal);
gr_printf_menu(x, y, XSTR( ", ", 212));
gr_printf_menu(x, y, "%s", XSTR( ", ", 212));
gr_get_string_size(&w, NULL, XSTR( ", ", 212));
x += w;
}
@@ -2099,7 +2099,7 @@ void control_config_do_frame(float frametime)
}
font::force_fit_string(buf, 255, Control_list_key_w[gr_screen.res] + Control_list_key_x[gr_screen.res] - x);
gr_printf_menu(x, y, buf);
gr_printf_menu(x, y, "%s", buf);
Cc_lines[line].jx = x - Control_list_coords[gr_screen.res][CONTROL_X_COORD];
gr_get_string_size(&Cc_lines[line].jw, NULL, buf);
@@ -2115,7 +2115,7 @@ void control_config_do_frame(float frametime)
if (j < 0) {
gr_set_color_fast(&Color_grey);
gr_printf_menu(x, y, XSTR( "None", 211));
gr_printf_menu(x, y, "%s", XSTR( "None", 211));
} else {
if (Conflicts_axes[z & ~JOY_AXIS] >= 0) {
+23 -4
View File
@@ -63,7 +63,7 @@ typedef struct config_item {
short joy_default; //!< default joystick button bound to action
char tab; //!< what tab (category) it belongs in
bool hasXSTR; //!< whether we should translate this with an XSTR
char *text; //!< describes the action in the config screen
const char *text; //!< describes the action in the config screen
char type; //!< manner control should be checked in
short key_id; //!< actual key bound to action
short joy_id; //!< joystick button bound to action
@@ -296,8 +296,8 @@ extern int Control_config_overlay_id;
extern config_item Control_config[]; //!< Stores the keyboard configuration
extern SCP_vector<config_item*> Control_config_presets; // tabled control presets; pointers to config_item arrays
extern SCP_vector<SCP_string> Control_config_preset_names; // names for Control_config_presets (identical order of items)
extern char **Scan_code_text;
extern char **Joy_button_text;
extern const char **Scan_code_text;
extern const char **Joy_button_text;
void control_config_common_init(); //!< initialize common control config stuff - call at game startup after localization has been initialized
void control_config_common_close(); //!< close common control config stuff - call at game shutdown
@@ -311,7 +311,26 @@ void control_config_cancel_exit();
void control_config_reset_defaults(int presetnum=-1);
int translate_key_to_index(const char *key, bool find_override=true);
char *translate_key(char *key);
char *textify_scancode(int code);
/**
* @brief Converts the specified key code to a human readable string
*
* @note The returned value is localized to the current language
*
* @param code The key code to convert
* @return The text representation of the code. The returned value is stored in a temporary location, copy it to your
* own buffer if you want to continue using it.
*/
const char *textify_scancode(int code);
/**
* @note Same as textify_scancode but always returns the same value regardless of current language
* @param code The key code to convert
* @return The name of the key
* @see textify_scancode
*/
const char *textify_scancode_universal(int code);
float check_control_timef(int id);
int check_control(int id, int key = -1);
void control_get_axes_readings(int *h, int *p, int *b, int *ta, int *tr);
+131 -102
View File
@@ -199,7 +199,7 @@ config_item Control_config[CCFG_MAX + 1] = {
{ -1, -1, -1, false, "", CC_TYPE_TRIGGER, -1, -1, 0, false, false }
};
char *Scan_code_text_german[] = {
const char *Scan_code_text_german[] = {
"", "Esc", "1", "2", "3", "4", "5", "6",
"7", "8", "9", "0", "Akzent '", "Eszett", "R\x81""cktaste", "Tab",
"Q", "W", "E", "R", "T", "Z", "U", "I",
@@ -241,7 +241,7 @@ char *Scan_code_text_german[] = {
"", "", "", "", "", "", "", "",
};
char *Joy_button_text_german[] = {
const char *Joy_button_text_german[] = {
"Knopf 1", "Knopf 2", "Knopf 3", "Knopf 4", "Knopf 5", "Knopf 6",
"Knopf 7", "Knopf 8", "Knopf 9", "Knopf 10", "Knopf 11", "Knopf 12",
"Knopf 13", "Knopf 14", "Knopf 15", "Knopf 16", "Knopf 17", "Knopf 18",
@@ -250,7 +250,7 @@ char *Joy_button_text_german[] = {
"Knopf 31", "Knopf 32", "Hut Hinten", "Hut Vorne", "Hut Links", "Hut Rechts"
};
char *Scan_code_text_french[] = {
const char *Scan_code_text_french[] = {
"", "\x90""chap", "1", "2", "3", "4", "5", "6",
"7", "8", "9", "0", "-", "=", "Fl\x82""che Ret.", "Tab",
"Q", "W", "E", "R", "T", "Y", "U", "I",
@@ -292,7 +292,7 @@ char *Scan_code_text_french[] = {
"", "", "", "", "", "", "", "",
};
char *Joy_button_text_french[] = {
const char *Joy_button_text_french[] = {
"Bouton 1", "Bouton 2", "Bouton 3", "Bouton 4", "Bouton 5", "Bouton 6",
"Bouton 7", "Bouton 8", "Bouton 9", "Bouton 10", "Bouton 11", "Bouton 12",
"Bouton 13", "Bouton 14", "Bouton 15", "Bouton 16", "Bouton 17", "Bouton 18",
@@ -301,7 +301,7 @@ char *Joy_button_text_french[] = {
"Bouton 31", "Bouton 32", "Chapeau Arri\x8Are", "Chapeau Avant", "Chapeau Gauche", "Chapeau Droite"
};
char *Scan_code_text_polish[] = {
const char *Scan_code_text_polish[] = {
"", "Esc", "1", "2", "3", "4", "5", "6",
"7", "8", "9", "0", "-", "=", "Backspace", "Tab",
"Q", "W", "E", "R", "T", "Y", "U", "I",
@@ -343,7 +343,7 @@ char *Scan_code_text_polish[] = {
"", "", "", "", "", "", "", "",
};
char *Joy_button_text_polish[] = {
const char *Joy_button_text_polish[] = {
"Przyc.1", "Przyc.2", "Przyc.3", "Przyc.4", "Przyc.5", "Przyc.6",
"Przyc.7", "Przyc.8", "Przyc.9", "Przyc.10", "Przyc.11", "Przyc.12",
"Przyc.13", "Przyc.14", "Przyc.15", "Przyc.16", "Przyc.17", "Przyc.18",
@@ -353,7 +353,7 @@ char *Joy_button_text_polish[] = {
};
//! This is the text that is displayed on the screen for the keys a player selects
char *Scan_code_text_english[] = {
const char *Scan_code_text_english[] = {
"", "Esc", "1", "2", "3", "4", "5", "6",
"7", "8", "9", "0", "-", "=", "Backspace", "Tab",
"Q", "W", "E", "R", "T", "Y", "U", "I",
@@ -395,7 +395,7 @@ char *Scan_code_text_english[] = {
"", "", "", "", "", "", "", "",
};
char *Joy_button_text_english[] = {
const char *Joy_button_text_english[] = {
"Button 1", "Button 2", "Button 3", "Button 4", "Button 5", "Button 6",
"Button 7", "Button 8", "Button 9", "Button 10", "Button 11", "Button 12",
"Button 13", "Button 14", "Button 15", "Button 16", "Button 17", "Button 18",
@@ -404,8 +404,8 @@ char *Joy_button_text_english[] = {
"Button 31", "Button 32", "Hat Back", "Hat Forward", "Hat Left", "Hat Right"
};
char **Scan_code_text = Scan_code_text_english;
char **Joy_button_text = Joy_button_text_english;
const char **Scan_code_text = Scan_code_text_english;
const char **Joy_button_text = Joy_button_text_english;
SCP_vector<config_item*> Control_config_presets;
SCP_vector<SCP_string> Control_config_preset_names;
@@ -510,8 +510,8 @@ int translate_key_to_index(const char *key, bool find_override)
char *translate_key(char *key)
{
int index = -1, key_code = -1, joy_code = -1;
char *key_text = NULL;
char *joy_text = NULL;
const char *key_text = NULL;
const char *joy_text = NULL;
static char text[40] = {"None"};
@@ -553,7 +553,7 @@ char *translate_key(char *key)
return text;
}
char *textify_scancode(int code)
const char *textify_scancode(int code)
{
static char text[40];
@@ -586,6 +586,28 @@ char *textify_scancode(int code)
strcat_s(text, Scan_code_text[keycode]);
return text;
}
const char *textify_scancode_universal(int code)
{
if (code < 0)
return "None";
int keycode = code & KEY_MASK;
static char text[40];
*text = 0;
if (code & KEY_ALTED && !(keycode == KEY_LALT || keycode == KEY_RALT)) {
strcat_s(text, "Alt-");
}
if (code & KEY_SHIFTED && !(keycode == KEY_LSHIFT || keycode == KEY_RSHIFT)) {
strcat_s(text, "Shift-");
}
// Always use the english version here
strcat_s(text, Scan_code_text_english[keycode]);
return text;
}
//XSTR:ON
void control_config_common_load_overrides();
@@ -811,118 +833,125 @@ void control_config_common_load_overrides()
{
LoadEnumsIntoMaps();
if (cf_exists_full("controlconfigdefaults.tbl", CF_TYPE_TABLES)) {
read_file_text("controlconfigdefaults.tbl", CF_TYPE_TABLES);
} else {
read_file_text_from_default(defaults_get_file("controlconfigdefaults.tbl"));
}
reset_parse();
// start parsing
// TODO: Split this out into more helps. Too many tabs!
while(optional_string("#ControlConfigOverride")) {
config_item *cfg_preset = new config_item[CCFG_MAX + 1];
std::copy(Control_config, Control_config + CCFG_MAX + 1, cfg_preset);
Control_config_presets.push_back(cfg_preset);
SCP_string preset_name;
if (optional_string("$Name:")) {
stuff_string_line(preset_name);
try {
if (cf_exists_full("controlconfigdefaults.tbl", CF_TYPE_TABLES)) {
read_file_text("controlconfigdefaults.tbl", CF_TYPE_TABLES);
} else {
preset_name = "<unnamed preset>";
read_file_text_from_default(defaults_get_file("controlconfigdefaults.tbl"));
}
Control_config_preset_names.push_back(preset_name);
while (required_string_either("#End","$Bind Name:")) {
const int iBufferLength = 64;
char szTempBuffer[iBufferLength];
reset_parse();
required_string("$Bind Name:");
stuff_string(szTempBuffer, F_NAME, iBufferLength);
// start parsing
// TODO: Split this out into more helps. Too many tabs!
while(optional_string("#ControlConfigOverride")) {
config_item *cfg_preset = new config_item[CCFG_MAX + 1];
std::copy(Control_config, Control_config + CCFG_MAX + 1, cfg_preset);
Control_config_presets.push_back(cfg_preset);
const size_t cCntrlAryLength = sizeof(Control_config) / sizeof(Control_config[0]);
for (size_t i = 0; i < cCntrlAryLength; ++i) {
config_item& r_ccConfig = cfg_preset[i];
SCP_string preset_name;
if (optional_string("$Name:")) {
stuff_string_line(preset_name);
} else {
preset_name = "<unnamed preset>";
}
Control_config_preset_names.push_back(preset_name);
if (!strcmp(szTempBuffer, r_ccConfig.text)) {
/**
* short key_default;
* short joy_default;
* char tab;
* bool hasXSTR;
* char type;
*/
while (required_string_either("#End","$Bind Name:")) {
const int iBufferLength = 64;
char szTempBuffer[iBufferLength];
int iTemp;
required_string("$Bind Name:");
stuff_string(szTempBuffer, F_NAME, iBufferLength);
if (optional_string("$Key Default:")) {
if (optional_string("NONE")) {
r_ccConfig.key_default = (short)-1;
} else {
stuff_string(szTempBuffer, F_NAME, iBufferLength);
r_ccConfig.key_default = (short)mKeyNameToVal[szTempBuffer];
const size_t cCntrlAryLength = sizeof(Control_config) / sizeof(Control_config[0]);
for (size_t i = 0; i < cCntrlAryLength; ++i) {
config_item& r_ccConfig = cfg_preset[i];
if (!strcmp(szTempBuffer, r_ccConfig.text)) {
/**
* short key_default;
* short joy_default;
* char tab;
* bool hasXSTR;
* char type;
*/
int iTemp;
if (optional_string("$Key Default:")) {
if (optional_string("NONE")) {
r_ccConfig.key_default = (short)-1;
} else {
stuff_string(szTempBuffer, F_NAME, iBufferLength);
r_ccConfig.key_default = (short)mKeyNameToVal[szTempBuffer];
}
}
}
if (optional_string("$Joy Default:")) {
stuff_int(&iTemp);
r_ccConfig.joy_default = (short)iTemp;
}
if (optional_string("$Joy Default:")) {
stuff_int(&iTemp);
r_ccConfig.joy_default = (short)iTemp;
}
if (optional_string("$Key Mod Shift:")) {
stuff_int(&iTemp);
r_ccConfig.key_default |= (iTemp == 1) ? KEY_SHIFTED : 0;
}
if (optional_string("$Key Mod Shift:")) {
stuff_int(&iTemp);
r_ccConfig.key_default |= (iTemp == 1) ? KEY_SHIFTED : 0;
}
if (optional_string("$Key Mod Alt:")) {
stuff_int(&iTemp);
r_ccConfig.key_default |= (iTemp == 1) ? KEY_ALTED : 0;
}
if (optional_string("$Key Mod Alt:")) {
stuff_int(&iTemp);
r_ccConfig.key_default |= (iTemp == 1) ? KEY_ALTED : 0;
}
if (optional_string("$Key Mod Ctrl:")) {
stuff_int(&iTemp);
r_ccConfig.key_default |= (iTemp == 1) ? KEY_CTRLED : 0;
}
if (optional_string("$Key Mod Ctrl:")) {
stuff_int(&iTemp);
r_ccConfig.key_default |= (iTemp == 1) ? KEY_CTRLED : 0;
}
if (optional_string("$Category:")) {
stuff_string(szTempBuffer, F_NAME, iBufferLength);
r_ccConfig.tab = (char)mCCTabNameToVal[szTempBuffer];
}
if (optional_string("$Category:")) {
stuff_string(szTempBuffer, F_NAME, iBufferLength);
r_ccConfig.tab = (char)mCCTabNameToVal[szTempBuffer];
}
if (optional_string("$Has XStr:")) {
stuff_int(&iTemp);
r_ccConfig.hasXSTR = (iTemp == 1);
}
if (optional_string("$Has XStr:")) {
stuff_int(&iTemp);
r_ccConfig.hasXSTR = (iTemp == 1);
}
if (optional_string("$Type:")) {
stuff_string(szTempBuffer, F_NAME, iBufferLength);
r_ccConfig.type = (char)mCCTypeNameToVal[szTempBuffer];
}
if (optional_string("$Type:")) {
stuff_string(szTempBuffer, F_NAME, iBufferLength);
r_ccConfig.type = (char)mCCTypeNameToVal[szTempBuffer];
}
if (optional_string("+Disable")) {
r_ccConfig.disabled = true;
if (optional_string("+Disable")) {
r_ccConfig.disabled = true;
}
if (optional_string("$Disable:")) {
stuff_boolean(&r_ccConfig.disabled);
}
// Nerf the buffer now.
szTempBuffer[0] = '\0';
} else if ((i + 1) == cCntrlAryLength) {
error_display(1, "Bind Name not found: %s\n", szTempBuffer);
advance_to_eoln(NULL);
ignore_white_space();
return;
}
if (optional_string("$Disable:")) {
stuff_boolean(&r_ccConfig.disabled);
}
// Nerf the buffer now.
szTempBuffer[0] = '\0';
} else if ((i + 1) == cCntrlAryLength) {
error_display(1, "Bind Name not found: %s\n", szTempBuffer);
advance_to_eoln(NULL);
ignore_white_space();
return;
}
}
}
required_string("#End");
required_string("#End");
}
}
catch (const parse::ParseException& e)
{
mprintf(("TABLES: Unable to parse 'controlconfigdefaults.tbl'! Error message = %s.\n", e.what()));
return;
}
// Overwrite the control config with the first preset that was found
if (Control_config_presets.size() > 0) {
if (!Control_config_presets.empty()) {
std::copy(Control_config_presets[0], Control_config_presets[0] + CCFG_MAX + 1, Control_config);
}
}
+65
View File
@@ -0,0 +1,65 @@
#include "cutscene/Decoder.h"
#include <memory>
namespace cutscene {
Decoder::Decoder() : m_decoding(true) {
}
Decoder::~Decoder() {
}
bool Decoder::tryPopAudioData(AudioFramePtr& out) {
auto res = m_audioQueue->try_pull_front(out);
return res == queue_op_status::success;
}
bool Decoder::tryPopVideoFrame(VideoFramePtr& out) {
auto res = m_videoQueue->try_pull_front(out);
return res == queue_op_status::success;
}
void Decoder::initializeQueues(size_t queueSize) {
m_queueSize = queueSize;
m_videoQueue.reset(new sync_bounded_queue<VideoFramePtr>(m_queueSize));
m_audioQueue.reset(new sync_bounded_queue<AudioFramePtr>(m_queueSize));
}
void Decoder::stopDecoder() {
m_decoding = false;
m_videoQueue->close();
m_audioQueue->close();
}
bool Decoder::canPushAudioData() {
return !isAudioQueueFull();
}
void Decoder::pushAudioData(AudioFramePtr&& data) {
Assertion(data, "Invalid audio data passed!");
try {
m_audioQueue->push_back(std::move(data));
}
catch (sync_queue_is_closed&) {
// Ignore
}
}
bool Decoder::canPushVideoData() {
return !isVideoQueueFull();
}
void Decoder::pushFrameData(VideoFramePtr&& frame) {
Assertion(frame, "Invalid video data passed!");
try {
m_videoQueue->push_back(std::move(frame));
}
catch (sync_queue_is_closed&) {
// Ignore
}
}
}
+148
View File
@@ -0,0 +1,148 @@
#pragma once
#include <memory>
#include "globalincs/pstypes.h"
#include "utils/boost/syncboundedqueue.h"
namespace cutscene {
struct FrameSize {
size_t width = 0;
size_t height = 0;
size_t stride = 0;
};
class VideoFrame {
protected:
VideoFrame() {}
public:
virtual ~VideoFrame() {}
double frameTime = -1.0;
int id = -1;
FrameSize ySize;
FrameSize uvSize;
struct DataPointers {
ubyte* y;
ubyte* u;
ubyte* v;
};
virtual DataPointers getDataPointers() = 0;
};
/**
* @brief Pointer type for passing frame data between threads
*
*/
template<typename T>
using FramePtr = std::unique_ptr<T>;
typedef std::unique_ptr<VideoFrame> VideoFramePtr;
struct MovieProperties {
FrameSize size;
float fps = -1.0f;
};
struct AudioFrame {
SCP_vector<short> audioData;
int channels = -1;
int rate = -1;
};
typedef std::unique_ptr<AudioFrame> AudioFramePtr;
/**
* @brief Abstract class for decoding a video or audio stream
*
* A decoder maintaines two queues of decoded audio and video frames which are filled from a background thread and
* retrieved by the main thread.
*/
class Decoder {
private:
std::unique_ptr<sync_bounded_queue<VideoFramePtr>> m_videoQueue;
std::unique_ptr<sync_bounded_queue<AudioFramePtr>> m_audioQueue;
bool m_decoding;
size_t m_queueSize = 0;
Decoder(const Decoder&) SCP_DELETED_FUNCTION;
Decoder& operator=(const Decoder&) SCP_DELETED_FUNCTION;
protected:
Decoder();
public:
virtual ~Decoder();
/**
* @brief Initializes the decoder
*
* @note A implementation should initialize the datastructures required for decoding here.
*
* @param fileName The name of the file that should be opened
* @return @c true if the initialization was successfull, @c false otherwise
*/
virtual bool initialize(const SCP_string& fileName) = 0;
/**
* @brief Returns the properties of the video
* @return The properties
*/
virtual MovieProperties getProperties() = 0;
/**
* @brief Starts decoding the video
*/
virtual void startDecoding() = 0;
/**
* @brief Determines if the video has audio
* @return @c true if audio is included in the video
*/
virtual bool hasAudio() = 0;
/**
* @brief Ends decoding of the video file
*/
virtual void close() = 0;
bool isAudioQueueFull() { return m_audioQueue->size() == m_queueSize; }
bool isAudioFrameAvailable() { return !m_audioQueue->empty(); }
size_t getAudioQueueSize() { return m_audioQueue->size(); }
bool tryPopAudioData(AudioFramePtr&);
bool isVideoQueueFull() { return m_videoQueue->size() == m_queueSize; }
bool isVideoFrameAvailable() { return !m_videoQueue->empty(); }
size_t getVideoQueueSize() { return m_videoQueue->size(); }
bool tryPopVideoFrame(VideoFramePtr&);
void stopDecoder();
bool isDecoding() { return m_decoding; }
protected:
void initializeQueues(size_t queueSize);
bool canPushAudioData();
void pushAudioData(AudioFramePtr&& data);
bool canPushVideoData();
void pushFrameData(VideoFramePtr&& frame);
};
}
+197 -215
View File
@@ -5,7 +5,7 @@
* or otherwise commercially exploit the source or things you created based on the
* source.
*
*/
*/
@@ -26,13 +26,13 @@
extern int Cmdline_nomovies;
char *Cutscene_bitmap_name[GR_NUM_RESOLUTIONS] = {
"ViewFootage",
"2_ViewFootage"
const char* Cutscene_bitmap_name[GR_NUM_RESOLUTIONS] = {
"ViewFootage",
"2_ViewFootage"
};
char *Cutscene_mask_name[GR_NUM_RESOLUTIONS] = {
"ViewFootage-m",
"2_ViewFootage-m"
const char* Cutscene_mask_name[GR_NUM_RESOLUTIONS] = {
"ViewFootage-m",
"2_ViewFootage-m"
};
int Description_index;
@@ -40,8 +40,9 @@ SCP_vector<cutscene_info> Cutscenes;
void cutscene_close()
{
for(SCP_vector<cutscene_info>::iterator cut = Cutscenes.begin(); cut != Cutscenes.end(); ++cut)
if(cut->description != NULL) {
for (SCP_vector<cutscene_info>::iterator cut = Cutscenes.begin(); cut != Cutscenes.end(); ++cut)
if (cut->description != NULL)
{
vm_free(cut->description);
cut->description = NULL;
}
@@ -81,19 +82,24 @@ void cutscene_init()
cutinfo.description = vm_strdup(buf);
if (optional_string("$cd:"))
stuff_int(&cutinfo.cd);
else
cutinfo.cd = 0;
{
// Option isn't needed anymore. Consume the token and ignore it
int junk;
stuff_int(&junk);
}
cutinfo.viewable = false;
if (isFirstCutscene) {
if (isFirstCutscene)
{
isFirstCutscene = false;
// The original code assumes the first movie is the intro, so always viewable
cutinfo.viewable = true;
}
if (optional_string("$Always Viewable:")) {
if (optional_string("$Always Viewable:"))
{
stuff_boolean(&cutinfo.viewable);
}
@@ -109,44 +115,34 @@ void cutscene_init()
}
}
// function to return 0 based index of which CD a particular movie is on
// returns -1 on failure.
int cutscenes_get_cd_num( char *filename )
{
for (SCP_vector<cutscene_info>::iterator cut = Cutscenes.begin(); cut != Cutscenes.end(); ++cut) {
if ( !stricmp(cut->filename, filename) ) {
return (cut->cd - 1);
}
}
return -1;
}
// marks a cutscene as viewable
void cutscene_mark_viewable(char *filename)
void cutscene_mark_viewable(const char* filename)
{
char cut_file[MAX_FILENAME_LEN];
char file[MAX_FILENAME_LEN];
Assert(filename!=NULL);
Assert(filename != NULL);
// strip off extension
strcpy_s( file, filename );
char *p = strchr( file, '.' );
if ( p ) {
strcpy_s(file, filename);
char* p = strchr(file, '.');
if (p)
{
*p = 0;
}
// change to lower case
strlwr(file);
int i = 0;
for (SCP_vector<cutscene_info>::iterator cut = Cutscenes.begin(); cut != Cutscenes.end(); ++cut) {
for (SCP_vector<cutscene_info>::iterator cut = Cutscenes.begin(); cut != Cutscenes.end(); ++cut)
{
// change the cutscene file name to lower case
strcpy_s(cut_file, cut->filename);
strlwr(cut_file);
// see if the stripped filename matches the cutscene filename
if ( strstr(cut_file, file) != NULL ) {
if (strstr(cut_file, file) != NULL)
{
cut->viewable = true;
return;
}
@@ -156,17 +152,17 @@ void cutscene_mark_viewable(char *filename)
Warning(LOCATION, "Could not find cutscene '%s' in listing; cannot mark it viewable...", filename);
}
#define NUM_BUTTONS 8
#define NUM_BUTTONS 8
#define TECH_DATABASE_BUTTON 0
#define SIMULATOR_BUTTON 1
#define CUTSCENES_BUTTON 2
#define CREDITS_BUTTON 3
#define TECH_DATABASE_BUTTON 0
#define SIMULATOR_BUTTON 1
#define CUTSCENES_BUTTON 2
#define CREDITS_BUTTON 3
#define SCROLL_UP_BUTTON 4
#define SCROLL_DOWN_BUTTON 5
#define PLAY_BUTTON 6
#define EXIT_BUTTON 7
#define SCROLL_UP_BUTTON 4
#define SCROLL_DOWN_BUTTON 5
#define PLAY_BUTTON 6
#define EXIT_BUTTON 7
static SCP_vector<int> Cutscene_list;
//static int Stats_scroll_offset; // not used - taylor
@@ -177,155 +173,102 @@ static UI_BUTTON List_region;
static UI_WINDOW Ui_window;
static ui_button_info Buttons[GR_NUM_RESOLUTIONS][NUM_BUTTONS] = {
{ // GR_640
ui_button_info("TDB_00", 7, 3, 37, 7, 0), // tech database 1
ui_button_info("TDB_01", 7, 18, 37, 23, 1), // tech database 2
ui_button_info("TDB_02", 7, 34, 37, 38, 2), // tech database 3
ui_button_info("TDB_03", 7, 49, 37, 54, 3), // tech database 4
{ // GR_640
ui_button_info("TDB_00", 7, 3, 37, 7, 0), // tech database 1
ui_button_info("TDB_01", 7, 18, 37, 23, 1), // tech database 2
ui_button_info("TDB_02", 7, 34, 37, 38, 2), // tech database 3
ui_button_info("TDB_03", 7, 49, 37, 54, 3), // tech database 4
ui_button_info("VFB_04", 6, 318, -1, -1, 4), // scroll up
ui_button_info("VFB_05", 36, 318, -1, -1, 5), // scroll down
ui_button_info("VFB_06", 578, 319, 587, 366, 6), // play
ui_button_info("VFB_07", 574, 431, 587, 413, 7), // exit
},
{ // GR_1024
ui_button_info("2_TDB_00", 12, 5, 59, 12, 0), // tech database 1
ui_button_info("2_TDB_01", 12, 31, 59, 37, 1), // tech database 2
ui_button_info("2_TDB_02", 12, 56, 59, 62, 2), // tech database 3
ui_button_info("2_TDB_03", 12, 81, 59, 88, 3), // tech database 4
ui_button_info("VFB_04", 6, 318, -1, -1, 4), // scroll up
ui_button_info("VFB_05", 36, 318, -1, -1, 5), // scroll down
ui_button_info("VFB_06", 578, 319, 587, 366, 6), // play
ui_button_info("VFB_07", 574, 431, 587, 413, 7), // exit
},
{ // GR_1024
ui_button_info("2_TDB_00", 12, 5, 59, 12, 0), // tech database 1
ui_button_info("2_TDB_01", 12, 31, 59, 37, 1), // tech database 2
ui_button_info("2_TDB_02", 12, 56, 59, 62, 2), // tech database 3
ui_button_info("2_TDB_03", 12, 81, 59, 88, 3), // tech database 4
ui_button_info("2_VFB_04", 9, 509, -1, -1, 4), // scroll up
ui_button_info("2_VFB_05", 58, 509, -1, -1, 5), // scroll down
ui_button_info("2_VFB_06", 925, 511, 940, 586, 6), // play
ui_button_info("2_VFB_07", 918, 689, 940, 661, 7), // exit
}
ui_button_info("2_VFB_04", 9, 509, -1, -1, 4), // scroll up
ui_button_info("2_VFB_05", 58, 509, -1, -1, 5), // scroll down
ui_button_info("2_VFB_06", 925, 511, 940, 586, 6), // play
ui_button_info("2_VFB_07", 918, 689, 940, 661, 7), // exit
}
};
// text
#define NUM_CUTSCENE_TEXT 6
#define NUM_CUTSCENE_TEXT 6
UI_XSTR Cutscene_text[GR_NUM_RESOLUTIONS][NUM_CUTSCENE_TEXT] = {
{ // GR_640
{"Technical Database", 1055, 37, 7, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][TECH_DATABASE_BUTTON].button },
{"Mission Simulator", 1056, 37, 23, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][SIMULATOR_BUTTON].button },
{"Cutscenes", 1057, 37, 38, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][CUTSCENES_BUTTON].button },
{"Credits", 1058, 37, 54, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][CREDITS_BUTTON].button },
{"Play", 1335, 587, 366, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][PLAY_BUTTON].button },
{"Exit", 1419, 587, 413, UI_XSTR_COLOR_PINK, -1, &Buttons[0][EXIT_BUTTON].button },
},
{ // GR_1024
{"Technical Database", 1055, 59, 12, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][TECH_DATABASE_BUTTON].button },
{"Mission Simulator", 1056, 59, 37, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][SIMULATOR_BUTTON].button },
{"Cutscenes", 1057, 59, 62, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][CUTSCENES_BUTTON].button },
{"Credits", 1058, 59, 88, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][CREDITS_BUTTON].button },
{"Play", 1335, 940, 586, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][PLAY_BUTTON].button },
{"Exit", 1419, 940, 661, UI_XSTR_COLOR_PINK, -1, &Buttons[1][EXIT_BUTTON].button },
}
{ // GR_640
{"Technical Database", 1055, 37, 7, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][TECH_DATABASE_BUTTON].button},
{"Mission Simulator", 1056, 37, 23, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][SIMULATOR_BUTTON].button},
{"Cutscenes", 1057, 37, 38, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][CUTSCENES_BUTTON].button},
{"Credits", 1058, 37, 54, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][CREDITS_BUTTON].button},
{"Play", 1335, 587, 366, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][PLAY_BUTTON].button},
{"Exit", 1419, 587, 413, UI_XSTR_COLOR_PINK, -1, &Buttons[0][EXIT_BUTTON].button},
},
{ // GR_1024
{"Technical Database", 1055, 59, 12, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][TECH_DATABASE_BUTTON].button},
{"Mission Simulator", 1056, 59, 37, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][SIMULATOR_BUTTON].button},
{"Cutscenes", 1057, 59, 62, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][CUTSCENES_BUTTON].button},
{"Credits", 1058, 59, 88, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][CREDITS_BUTTON].button},
{"Play", 1335, 940, 586, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][PLAY_BUTTON].button},
{"Exit", 1419, 940, 661, UI_XSTR_COLOR_PINK, -1, &Buttons[1][EXIT_BUTTON].button},
}
};
int Cutscene_list_coords[GR_NUM_RESOLUTIONS][4] = {
{ // GR_640
9, 117, 621, 198
},
{ // GR_1024
14, 188, 994, 316
}
{ // GR_640
9, 117, 621, 198
},
{ // GR_1024
14, 188, 994, 316
}
};
int Cutscene_desc_coords[GR_NUM_RESOLUTIONS][4] = {
{ // GR_640
9, 378, 484, 73
},
{ // GR_1024
14, 605, 775, 117
}
{ // GR_640
9, 378, 484, 73
},
{ // GR_1024
14, 605, 775, 117
}
};
#define MAX_TEXT_LINES 20
#define MAX_TEXT_LINES 20
int Cutscene_max_text_lines[GR_NUM_RESOLUTIONS] = {
10,
MAX_TEXT_LINES
10,
MAX_TEXT_LINES
};
#define MAX_TEXT_LINE_LEN 256
#define MAX_TEXT_LINE_LEN 256
static int Text_size;
static int Text_offset = 0;
static int Text_line_size[MAX_TEXT_LINES];
static const char *Text_lines[MAX_TEXT_LINES];
static const char* Text_lines[MAX_TEXT_LINES];
int cutscenes_validate_cd(char *mve_name, int prompt_for_cd)
{
int cd_present = 0;
int cd_drive_num;
int cd_mve_is_on;
char volume_name[MAX_PATH_LEN];
int num_attempts = 0;
while(1) {
int path_set_ok;
cd_mve_is_on = cutscenes_get_cd_num(mve_name);
if ((cd_mve_is_on != 0) && (cd_mve_is_on != 1) && (cd_mve_is_on != 2)) {
cd_present = 0;
break;
}
sprintf(volume_name, NOX("FREESPACE2_%c"), '1' + cd_mve_is_on);
cd_drive_num = find_freespace_cd(volume_name);
path_set_ok = set_cdrom_path(cd_drive_num);
if ( path_set_ok ) {
cd_present = 1;
break;
}
if ( !prompt_for_cd ) {
cd_present = 0;
break;
}
// no CD found, so prompt user
char popup_msg[256];
int popup_rval;
sprintf(popup_msg, XSTR( "Movie not found\n\nInsert FreeSpace CD #%d to continue", 203), cd_mve_is_on+1);
popup_rval = popup(PF_BODY_BIG, 2, POPUP_CANCEL, POPUP_OK, popup_msg);
if ( popup_rval != 1 ) {
cd_present = 0;
break;
}
if ( num_attempts++ > 5 ) {
cd_present = 0;
break;
}
}
return cd_present;
}
void cutscenes_screen_play()
{
char name[MAX_FILENAME_LEN]; // *full_name
int which_cutscene;
Assert( (Selected_line >= 0) && (Selected_line < (int)Cutscene_list.size()) );
Assert((Selected_line >= 0) && (Selected_line < (int) Cutscene_list.size()));
which_cutscene = Cutscene_list[Selected_line];
strcpy_s(name, Cutscenes[which_cutscene].filename );
strcpy_s(name, Cutscenes[which_cutscene].filename);
// full_name = cf_add_ext(name, NOX(".mve"));
main_hall_stop_music(true);
main_hall_stop_ambient();
int rval = movie_play(name);
auto rval = movie::play(name);
main_hall_start_music();
if ( !rval ) {
if (!rval)
{
char str[256];
if (Cmdline_nomovies)
@@ -333,20 +276,21 @@ void cutscenes_screen_play()
else
sprintf(str, XSTR("Unable to play movie %s.", 204), Cutscenes[which_cutscene].name);
popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, str );
popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, str);
}
}
void cutscenes_screen_scroll_line_up()
{
if (Selected_line) {
if (Selected_line)
{
Selected_line--;
gamesnd_play_iface(SND_SCROLL);
} else
gamesnd_play_iface(SND_GENERAL_FAIL);
if (Selected_line < Scroll_offset)
Scroll_offset = Selected_line;
}
@@ -355,15 +299,17 @@ void cutscenes_screen_scroll_line_down()
{
int h;
if (Selected_line < (int)Cutscene_list.size() - 1) {
if (Selected_line < (int) Cutscene_list.size() - 1)
{
Selected_line++;
gamesnd_play_iface(SND_SCROLL);
} else
gamesnd_play_iface(SND_GENERAL_FAIL);
h = Cutscene_list_coords[gr_screen.res][3] / gr_get_font_height();
if (Selected_line >= Scroll_offset + h){
if (Selected_line >= Scroll_offset + h)
{
Scroll_offset++;
}
}
@@ -372,17 +318,20 @@ void cutscenes_screen_scroll_screen_up()
{
int h;
if (Scroll_offset) {
if (Scroll_offset)
{
Scroll_offset--;
Assert(Selected_line > Scroll_offset);
h = Cutscene_list_coords[gr_screen.res][3] / gr_get_font_height();
while (Selected_line >= Scroll_offset + h){
while (Selected_line >= Scroll_offset + h)
{
Selected_line--;
}
gamesnd_play_iface(SND_SCROLL);
} else {
} else
{
gamesnd_play_iface(SND_GENERAL_FAIL);
}
}
@@ -392,21 +341,25 @@ void cutscenes_screen_scroll_screen_down()
int h;
h = Cutscene_list_coords[gr_screen.res][3] / gr_get_font_height();
if (Scroll_offset + h < (int)Cutscene_list.size()) {
if (Scroll_offset + h < (int) Cutscene_list.size())
{
Scroll_offset++;
if (Selected_line < Scroll_offset){
if (Selected_line < Scroll_offset)
{
Selected_line = Scroll_offset;
}
gamesnd_play_iface(SND_SCROLL);
} else {
} else
{
gamesnd_play_iface(SND_GENERAL_FAIL);
}
}
int cutscenes_screen_button_pressed(int n)
{
switch (n) {
switch (n)
{
case TECH_DATABASE_BUTTON:
gamesnd_play_iface(SND_SWITCH_SCREENS);
gameseq_post_event(GS_EVENT_TECH_MENU);
@@ -447,12 +400,13 @@ int cutscenes_screen_button_pressed(int n)
void cutscenes_screen_init()
{
int i;
ui_button_info *b;
ui_button_info* b;
Ui_window.create(0, 0, gr_screen.max_w_unscaled, gr_screen.max_h_unscaled, 0);
Ui_window.set_mask_bmap(Cutscene_mask_name[gr_screen.res]);
for (i=0; i<NUM_BUTTONS; i++) {
for (i = 0; i < NUM_BUTTONS; i++)
{
b = &Buttons[gr_screen.res][i];
b->button.create(&Ui_window, "", b->x, b->y, 60, 30, (i < 2), 1);
@@ -463,15 +417,17 @@ void cutscenes_screen_init()
}
// add xstrs
for(i=0; i<NUM_CUTSCENE_TEXT; i++){
for (i = 0; i < NUM_CUTSCENE_TEXT; i++)
{
Ui_window.add_XSTR(&Cutscene_text[gr_screen.res][i]);
}
Buttons[gr_screen.res][EXIT_BUTTON].button.set_hotkey(KEY_CTRLED | KEY_ENTER);
Buttons[gr_screen.res][SCROLL_UP_BUTTON].button.set_hotkey(KEY_PAGEUP);
Buttons[gr_screen.res][SCROLL_DOWN_BUTTON].button.set_hotkey(KEY_PAGEDOWN);
Buttons[gr_screen.res][SCROLL_DOWN_BUTTON].button.set_hotkey(KEY_PAGEDOWN);
List_region.create(&Ui_window, "", Cutscene_list_coords[gr_screen.res][0], Cutscene_list_coords[gr_screen.res][1], Cutscene_list_coords[gr_screen.res][2], Cutscene_list_coords[gr_screen.res][3], 0, 1);
List_region.create(&Ui_window, "", Cutscene_list_coords[gr_screen.res][0], Cutscene_list_coords[gr_screen.res][1],
Cutscene_list_coords[gr_screen.res][2], Cutscene_list_coords[gr_screen.res][3], 0, 1);
List_region.hide();
// set up hotkeys for buttons so we draw the correct animation frame when a key is pressed
@@ -482,11 +438,13 @@ void cutscenes_screen_init()
Scroll_offset = Selected_line = 0;
Description_index = -1;
Cutscene_list.clear();
Cutscene_list.clear();
int u = 0;
for (SCP_vector<cutscene_info>::iterator cut = Cutscenes.begin(); cut != Cutscenes.end(); ++cut, u++) {
if ( (*cut).viewable ) {
for (SCP_vector<cutscene_info>::iterator cut = Cutscenes.begin(); cut != Cutscenes.end(); ++cut, u++)
{
if ((*cut).viewable)
{
Cutscene_list.push_back(u);
}
}
@@ -507,7 +465,8 @@ void cutscenes_screen_do_frame()
int select_tease_line = -1;
k = Ui_window.process();
switch (k) {
switch (k)
{
case KEY_DOWN: // select next line
cutscenes_screen_scroll_line_down();
break;
@@ -542,96 +501,117 @@ void cutscenes_screen_do_frame()
gameseq_post_event(GS_EVENT_OPTIONS_MENU);
break;
// the "show-all" hotkey
// the "show-all" hotkey
case KEY_CTRLED | KEY_SHIFTED | KEY_S:
{
Cutscene_list.clear();
Cutscene_list.clear();
size_t size = Cutscenes.size();
for (size_t t = 0; t < size; t++) {
Cutscene_list.push_back((int)t);
for (size_t t = 0; t < size; t++)
{
Cutscene_list.push_back((int) t);
}
break;
}
} // end switch
} // end switch
for (i=0; i<NUM_BUTTONS; i++){
if (Buttons[gr_screen.res][i].button.pressed()){
if (cutscenes_screen_button_pressed(i)){
for (i = 0; i < NUM_BUTTONS; i++)
{
if (Buttons[gr_screen.res][i].button.pressed())
{
if (cutscenes_screen_button_pressed(i))
{
return;
}
}
}
if (List_region.button_down()) {
if (List_region.button_down())
{
List_region.get_mouse_pos(NULL, &y);
z = Scroll_offset + y / font_height;
if ((z >= 0) && (z < (int)Cutscene_list.size()))
if ((z >= 0) && (z < (int) Cutscene_list.size()))
select_tease_line = z;
}
if (List_region.pressed()) {
if (List_region.pressed())
{
List_region.get_mouse_pos(NULL, &y);
z = Scroll_offset + y / font_height;
if ((z >= 0) && (z < (int)Cutscene_list.size()))
if ((z >= 0) && (z < (int) Cutscene_list.size()))
Selected_line = z;
}
GR_MAYBE_CLEAR_RES(Background_bitmap);
if (Background_bitmap >= 0) {
if (Background_bitmap >= 0)
{
gr_set_bitmap(Background_bitmap);
gr_bitmap(0, 0, GR_RESIZE_MENU);
}
}
Ui_window.draw();
for (i=TECH_DATABASE_BUTTON; i<=CREDITS_BUTTON; i++){
if (Buttons[gr_screen.res][i].button.button_down()){
for (i = TECH_DATABASE_BUTTON; i <= CREDITS_BUTTON; i++)
{
if (Buttons[gr_screen.res][i].button.button_down())
{
break;
}
}
if (i > CREDITS_BUTTON){
if (i > CREDITS_BUTTON)
{
Buttons[gr_screen.res][CUTSCENES_BUTTON].button.draw_forced(2);
}
y = 0;
z = Scroll_offset;
while (y + font_height <= Cutscene_list_coords[gr_screen.res][3]) {
if (z >= (int)Cutscene_list.size()){
while (y + font_height <= Cutscene_list_coords[gr_screen.res][3])
{
if (z >= (int) Cutscene_list.size())
{
break;
}
if (z == Selected_line){
if (z == Selected_line)
{
gr_set_color_fast(&Color_text_selected);
} else if (z == select_tease_line) {
} else if (z == select_tease_line)
{
gr_set_color_fast(&Color_text_subselected);
} else {
} else
{
gr_set_color_fast(&Color_text_normal);
}
gr_printf_menu(Cutscene_list_coords[gr_screen.res][0], Cutscene_list_coords[gr_screen.res][1] + y, Cutscenes[Cutscene_list[z]].name);
gr_printf_menu(Cutscene_list_coords[gr_screen.res][0], Cutscene_list_coords[gr_screen.res][1] + y,
"%s", Cutscenes[Cutscene_list[z]].name);
y += font_height;
z++;
}
if (Description_index != Selected_line) {
char *src = NULL;
if (Description_index != Selected_line)
{
char* src = NULL;
Description_index = Selected_line;
Text_size = 0;
if ( Description_index < (int)Cutscene_list.size( ) &&
(int)Cutscene_list[ Description_index ] < (int)Cutscenes.size( ) ) {
if (Description_index < (int) Cutscene_list.size() &&
(int) Cutscene_list[Description_index] < (int) Cutscenes.size())
{
src = Cutscenes[Cutscene_list[Description_index]].description;
if (src) {
Text_size = split_str(src, Cutscene_desc_coords[gr_screen.res][2], Text_line_size, Text_lines, Cutscene_max_text_lines[gr_screen.res]);
if (src)
{
Text_size = split_str(src, Cutscene_desc_coords[gr_screen.res][2], Text_line_size, Text_lines,
Cutscene_max_text_lines[gr_screen.res]);
Assert(Text_size >= 0 && Text_size < Cutscene_max_text_lines[gr_screen.res]);
}
}
}
if (Description_index >= 0) {
if (Description_index >= 0)
{
int len;
char line[MAX_TEXT_LINE_LEN + 1];
@@ -639,8 +619,9 @@ void cutscenes_screen_do_frame()
y = 0;
z = Text_offset;
while (y + font_height <= Cutscene_desc_coords[gr_screen.res][3]) {
if (z >= Text_size || z >= MAX_TEXT_LINES-1)
while (y + font_height <= Cutscene_desc_coords[gr_screen.res][3])
{
if (z >= Text_size || z >= MAX_TEXT_LINES - 1)
break;
len = Text_line_size[z];
@@ -649,7 +630,8 @@ void cutscenes_screen_do_frame()
strncpy(line, Text_lines[z], len);
line[len] = 0;
gr_string(Cutscene_desc_coords[gr_screen.res][0], Cutscene_desc_coords[gr_screen.res][1] + y, line, GR_RESIZE_MENU);
gr_string(Cutscene_desc_coords[gr_screen.res][0], Cutscene_desc_coords[gr_screen.res][1] + y, line,
GR_RESIZE_MENU);
y += font_height;
z++;
+17 -9
View File
@@ -13,25 +13,33 @@
#include "globalincs/globals.h"
#include "globalincs/pstypes.h"
typedef struct cutscene_info {
char filename[MAX_FILENAME_LEN];
char name[NAME_LENGTH];
char *description;
int cd;
bool viewable;
typedef struct cutscene_info
{
char filename[MAX_FILENAME_LEN];
char name[NAME_LENGTH];
char* description;
bool viewable;
} cutscene_info;
#if SCP_COMPILER_IS_GNU
#pragma GCC diagnostic push
// This suppresses a GCC bug where it thinks that the Cutscenes from the enum class below shadows a global variable
#pragma GCC diagnostic ignored "-Wshadow"
#endif
extern SCP_vector<cutscene_info> Cutscenes;
#if SCP_COMPILER_IS_GNU
#pragma GCC diagnostic pop
#endif
// initializa table data
void cutscene_init();
int cutscene_get_cd_num(char *filename);
void cutscenes_screen_init();
void cutscenes_screen_close();
void cutscenes_screen_do_frame();
int cutscenes_validate_cd(char *mve_name, int prompt_for_cd = 1);
void cutscene_mark_viewable(char *filename);
void cutscene_mark_viewable(const char* filename);
#endif
-570
View File
@@ -1,570 +0,0 @@
#include "globalincs/pstypes.h"
extern int g_width, g_height;
extern void *g_vBackBuf1, *g_vBackBuf2;
/* 16 bit decoding routines */
static ushort *backBuf1, *backBuf2;
static int lookup_initialized;
static void dispatchDecoder16(ushort **pFrame, ubyte codeType, ubyte **pData, ubyte **pOffData, int *pDataRemain, int *curXb, int *curYb);
static void genLoopkupTable();
void decodeFrame16(ubyte *pFrame, ubyte *pMap, int mapRemain, unsigned char *pData, int dataRemain)
{
ubyte *pOrig, *pOffData, op;
ushort offset;
int length = 0, i, j, xb, yb;
if (!lookup_initialized) {
genLoopkupTable();
}
backBuf1 = (ushort *)g_vBackBuf1;
backBuf2 = (ushort *)g_vBackBuf2;
xb = g_width >> 3;
yb = g_height >> 3;
offset = pData[0]|(pData[1]<<8);
pOffData = pData + offset;
pData += 2;
pOrig = pData;
length = offset - 2; /*dataRemain-2;*/
for (j=0; j<yb; j++) {
for (i=0; i<xb/2; i++) {
op = (*pMap) & 0xf;
dispatchDecoder16((ushort **)&pFrame, op, &pData, &pOffData, &dataRemain, &i, &j);
op = ((*pMap) >> 4) & 0xf;
dispatchDecoder16((ushort **)&pFrame, op, &pData, &pOffData, &dataRemain, &i, &j);
pMap++;
mapRemain--;
}
pFrame += 7*g_width*2;
}
if ((length-(pData-pOrig)) != 0) {
nprintf(("MVE", "DEBUG: junk left over: " PTRDIFF_T_ARG ",%d," PTRDIFF_T_ARG "\n",
(pData-pOrig), length, (length-(pData-pOrig))));
}
}
static ushort GETPIXEL(unsigned char **buf, int off)
{
ushort val = (*buf)[0+off] | ((*buf)[1+off] << 8);
return val;
}
static ushort GETPIXELI(unsigned char **buf, int off)
{
ushort val = (*buf)[0+off] | ((*buf)[1+off] << 8);
(*buf) += 2;
return val;
}
static void relClose(int i, int *x, int *y)
{
int ma, mi;
ma = i >> 4;
mi = i & 0xf;
*x = mi - 8;
*y = ma - 8;
}
static void relFar(int i, int sign, int *x, int *y)
{
if (i < 56) {
*x = sign * (8 + (i % 7));
*y = sign * (i / 7);
} else {
*x = sign * (-14 + (i - 56) % 29);
*y = sign * (8 + (i - 56) / 29);
}
}
static int close_table[512];
static int far_p_table[512];
static int far_n_table[512];
static void genLoopkupTable()
{
int i;
int x, y;
for (i = 0; i < 256; i++) {
relClose(i, &x, &y);
close_table[i*2+0] = x;
close_table[i*2+1] = y;
relFar(i, 1, &x, &y);
far_p_table[i*2+0] = x;
far_p_table[i*2+1] = y;
relFar(i, -1, &x, &y);
far_n_table[i*2+0] = x;
far_n_table[i*2+1] = y;
}
lookup_initialized = 1;
}
static void copyFrame(ushort *pDest, ushort *pSrc)
{
int i;
for (i=0; i<8; i++) {
memcpy(pDest, pSrc, 16);
pDest += g_width;
pSrc += g_width;
}
}
static void patternRow4Pixels(ushort *pFrame, unsigned char pat0, unsigned char pat1, ushort *p)
{
ushort mask=0x0003;
ushort shift=0;
ushort pattern = (pat1 << 8) | pat0;
while (mask != 0) {
*pFrame++ = p[(mask & pattern) >> shift];
mask <<= 2;
shift += 2;
}
}
static void patternRow4Pixels2(ushort *pFrame, unsigned char pat0, ushort *p)
{
unsigned char mask=0x03;
unsigned char shift=0;
ushort pel;
while (mask != 0) {
pel = p[(mask & pat0) >> shift];
pFrame[0] = pel;
pFrame[1] = pel;
pFrame[g_width + 0] = pel;
pFrame[g_width + 1] = pel;
pFrame += 2;
mask <<= 2;
shift += 2;
}
}
static void patternRow4Pixels2x1(ushort *pFrame, unsigned char pat, ushort *p)
{
unsigned char mask=0x03;
unsigned char shift=0;
ushort pel;
while (mask != 0) {
pel = p[(mask & pat) >> shift];
pFrame[0] = pel;
pFrame[1] = pel;
pFrame += 2;
mask <<= 2;
shift += 2;
}
}
static void patternQuadrant4Pixels(ushort *pFrame, unsigned char pat0, unsigned char pat1, unsigned char pat2, unsigned char pat3, ushort *p)
{
unsigned long mask = 0x00000003UL;
int shift=0;
int i;
unsigned long pat = (pat3 << 24) | (pat2 << 16) | (pat1 << 8) | pat0;
for (i=0; i<16; i++) {
pFrame[i&3] = p[(pat & mask) >> shift];
if ((i&3) == 3) {
pFrame += g_width;
}
mask <<= 2;
shift += 2;
}
}
static void patternRow2Pixels(ushort *pFrame, unsigned char pat, ushort *p)
{
unsigned char mask=0x01;
while (mask != 0) {
*pFrame++ = p[(mask & pat) ? 1 : 0];
mask <<= 1;
}
}
static void patternRow2Pixels2(ushort *pFrame, unsigned char pat, ushort *p)
{
ushort pel;
unsigned char mask=0x1;
while (mask != 0x10) {
pel = p[(mask & pat) ? 1 : 0];
pFrame[0] = pel;
pFrame[1] = pel;
pFrame[g_width + 0] = pel;
pFrame[g_width + 1] = pel;
pFrame += 2;
mask <<= 1;
}
}
static void patternQuadrant2Pixels(ushort *pFrame, unsigned char pat0, unsigned char pat1, ushort *p)
{
ushort mask = 0x0001;
int i;
ushort pat = (pat1 << 8) | pat0;
for (i=0; i<16; i++) {
pFrame[i&3] = p[(pat & mask) ? 1 : 0];
if ((i&3) == 3) {
pFrame += g_width;
}
mask <<= 1;
}
}
static void dispatchDecoder16(ushort **pFrame, unsigned char codeType, unsigned char **pData, unsigned char **pOffData, int *pDataRemain, int *curXb, int *curYb)
{
ushort p[4];
unsigned char pat[16];
int i, j, k;
int x, y;
ushort *pDstBak;
pDstBak = *pFrame;
switch(codeType) {
case 0x0:
copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1));
break; // ADDED
case 0x1:
break;
case 0x2:
k = *(*pOffData)++;
x = far_p_table[k*2+0];
y = far_p_table[k*2+1];
copyFrame(*pFrame, *pFrame + x + y*g_width);
(*pDataRemain)--;
break;
case 0x3:
k = *(*pOffData)++;
x = far_n_table[k*2+0];
y = far_n_table[k*2+1];
copyFrame(*pFrame, *pFrame + x + y*g_width);
(*pDataRemain)--;
break;
case 0x4:
k = *(*pOffData)++;
x = close_table[k*2+0];
y = close_table[k*2+1];
copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1) + x + y*g_width);
(*pDataRemain)--;
break;
case 0x5:
x = (char)*(*pData)++;
y = (char)*(*pData)++;
copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1) + x + y*g_width);
*pDataRemain -= 2;
break;
case 0x6:
nprintf(("MVE", "STUB: encoding 6 not tested\n"));
for (i=0; i<2; i++) {
*pFrame += 16;
if (++*curXb == (g_width >> 3)) {
*pFrame += 7*g_width;
*curXb = 0;
if (++*curYb == (g_height >> 3)) {
return;
}
}
}
break;
case 0x7:
p[0] = GETPIXELI(pData, 0);
p[1] = GETPIXELI(pData, 0);
if (!((p[0]/*|p[1]*/)&0x8000)) {
for (i=0; i<8; i++) {
patternRow2Pixels(*pFrame, *(*pData), p);
(*pData)++;
*pFrame += g_width;
}
} else {
for (i=0; i<2; i++) {
patternRow2Pixels2(*pFrame, *(*pData) & 0xf, p);
*pFrame += 2*g_width;
patternRow2Pixels2(*pFrame, *(*pData) >> 4, p);
(*pData)++;
*pFrame += 2*g_width;
}
}
break;
case 0x8:
p[0] = GETPIXEL(pData, 0);
if (!(p[0] & 0x8000)) {
for (i=0; i<4; i++) {
p[0] = GETPIXELI(pData, 0);
p[1] = GETPIXELI(pData, 0);
pat[0] = (*pData)[0];
pat[1] = (*pData)[1];
(*pData) += 2;
patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
if (i & 1) {
*pFrame -= (4*g_width - 4);
} else {
*pFrame += 4*g_width;
}
}
} else {
p[2] = GETPIXEL(pData, 8);
if (!(p[2]&0x8000)) {
for (i=0; i<4; i++) {
if ((i & 1) == 0) {
p[0] = GETPIXELI(pData, 0);
p[1] = GETPIXELI(pData, 0);
}
pat[0] = *(*pData)++;
pat[1] = *(*pData)++;
patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
if (i & 1) {
*pFrame -= (4*g_width - 4);
} else {
*pFrame += 4*g_width;
}
}
} else {
for (i=0; i<8; i++) {
if ((i & 3) == 0) {
p[0] = GETPIXELI(pData, 0);
p[1] = GETPIXELI(pData, 0);
}
patternRow2Pixels(*pFrame, *(*pData), p);
(*pData)++;
*pFrame += g_width;
}
}
}
break;
case 0x9:
p[0] = GETPIXELI(pData, 0);
p[1] = GETPIXELI(pData, 0);
p[2] = GETPIXELI(pData, 0);
p[3] = GETPIXELI(pData, 0);
*pDataRemain -= 8;
if (!(p[0] & 0x8000)) {
if (!(p[2] & 0x8000)) {
for (i=0; i<8; i++) {
pat[0] = (*pData)[0];
pat[1] = (*pData)[1];
(*pData) += 2;
patternRow4Pixels(*pFrame, pat[0], pat[1], p);
*pFrame += g_width;
}
*pDataRemain -= 16;
} else {
patternRow4Pixels2(*pFrame, (*pData)[0], p);
*pFrame += 2*g_width;
patternRow4Pixels2(*pFrame, (*pData)[1], p);
*pFrame += 2*g_width;
patternRow4Pixels2(*pFrame, (*pData)[2], p);
*pFrame += 2*g_width;
patternRow4Pixels2(*pFrame, (*pData)[3], p);
(*pData) += 4;
*pDataRemain -= 4;
}
} else {
if (!(p[2] & 0x8000)) {
for (i=0; i<8; i++) {
pat[0] = (*pData)[0];
(*pData) += 1;
patternRow4Pixels2x1(*pFrame, pat[0], p);
*pFrame += g_width;
}
*pDataRemain -= 8;
} else {
for (i=0; i<4; i++) {
pat[0] = (*pData)[0];
pat[1] = (*pData)[1];
(*pData) += 2;
patternRow4Pixels(*pFrame, pat[0], pat[1], p);
*pFrame += g_width;
patternRow4Pixels(*pFrame, pat[0], pat[1], p);
*pFrame += g_width;
}
*pDataRemain -= 8;
}
}
break;
case 0xa:
p[0] = GETPIXEL(pData, 0);
if (!(p[0] & 0x8000)) {
for (i=0; i<4; i++) {
p[0] = GETPIXELI(pData, 0);
p[1] = GETPIXELI(pData, 0);
p[2] = GETPIXELI(pData, 0);
p[3] = GETPIXELI(pData, 0);
pat[0] = (*pData)[0];
pat[1] = (*pData)[1];
pat[2] = (*pData)[2];
pat[3] = (*pData)[3];
(*pData) += 4;
patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
if (i & 1) {
*pFrame -= (4*g_width - 4);
} else {
*pFrame += 4*g_width;
}
}
} else {
p[0] = GETPIXEL(pData, 16);
if (!(p[0] & 0x8000)) {
for (i=0; i<4; i++) {
if ((i&1) == 0) {
p[0] = GETPIXELI(pData, 0);
p[1] = GETPIXELI(pData, 0);
p[2] = GETPIXELI(pData, 0);
p[3] = GETPIXELI(pData, 0);
}
pat[0] = (*pData)[0];
pat[1] = (*pData)[1];
pat[2] = (*pData)[2];
pat[3] = (*pData)[3];
(*pData) += 4;
patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
if (i & 1) {
*pFrame -= (4*g_width - 4);
} else {
*pFrame += 4*g_width;
}
}
} else {
for (i=0; i<8; i++) {
if ((i&3) == 0) {
p[0] = GETPIXELI(pData, 0);
p[1] = GETPIXELI(pData, 0);
p[2] = GETPIXELI(pData, 0);
p[3] = GETPIXELI(pData, 0);
}
pat[0] = (*pData)[0];
pat[1] = (*pData)[1];
patternRow4Pixels(*pFrame, pat[0], pat[1], p);
*pFrame += g_width;
(*pData) += 2;
}
}
}
break;
case 0xb:
for (i=0; i<8; i++) {
#if BYTE_ORDER == BIG_ENDIAN
ubyte frame_tmp[16];
memcpy(&frame_tmp, *pData, 16);
ushort *swap_tmp;
for (j = 0; j < 16; j += 2) {
swap_tmp = (ushort*)(frame_tmp + j);
*swap_tmp = INTEL_SHORT(*swap_tmp);
}
memcpy(*pFrame, &frame_tmp, 16);
#else
memcpy(*pFrame, *pData, 16);
#endif
*pFrame += g_width;
*pData += 16;
*pDataRemain -= 16;
}
break;
case 0xc:
for (i=0; i<4; i++) {
p[0] = GETPIXEL(pData, 0);
p[1] = GETPIXEL(pData, 2);
p[2] = GETPIXEL(pData, 4);
p[3] = GETPIXEL(pData, 6);
for (j=0; j<2; j++) {
for (k=0; k<4; k++) {
(*pFrame)[2*k] = p[k];
(*pFrame)[2*k+1] = p[k];
}
*pFrame += g_width;
}
*pData += 8;
*pDataRemain -= 8;
}
break;
case 0xd:
for (i=0; i<2; i++) {
p[0] = GETPIXEL(pData, 0);
p[1] = GETPIXEL(pData, 2);
for (j=0; j<4; j++) {
for (k=0; k<4; k++) {
(*pFrame)[k*g_width+j] = p[0];
(*pFrame)[k*g_width+j+4] = p[1];
}
}
*pFrame += 4*g_width;
*pData += 4;
*pDataRemain -= 4;
}
break;
case 0xe:
p[0] = GETPIXEL(pData, 0);
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
(*pFrame)[j] = p[0];
}
*pFrame += g_width;
}
*pData += 2;
*pDataRemain -= 2;
break;
case 0xf:
p[0] = GETPIXEL(pData, 0);
p[1] = GETPIXEL(pData, 1);
for (i=0; i<8; i++) {
for (j=0; j<8; j++) {
(*pFrame)[j] = p[(i+j)&1];
}
*pFrame += g_width;
}
*pData += 4;
*pDataRemain -= 4;
break;
default:
break;
}
*pFrame = pDstBak+8;
}
-533
View File
@@ -1,533 +0,0 @@
#include "globalincs/pstypes.h"
extern int g_width, g_height;
extern void *g_vBackBuf1, *g_vBackBuf2;
static void dispatchDecoder8(ubyte **pFrame, ubyte codeType, ubyte **pData, int *pDataRemain, int *curXb, int *curYb);
void decodeFrame8(ubyte *pFrame, ubyte *pMap, int mapRemain, ubyte *pData, int dataRemain)
{
int i, j;
int xb, yb;
xb = g_width >> 3;
yb = g_height >> 3;
for (j = 0; j < yb; j++) {
for (i = 0; i < (xb / 2); i++) {
dispatchDecoder8(&pFrame, (*pMap) & 0xf, &pData, &dataRemain, &i, &j);
dispatchDecoder8(&pFrame, (*pMap) >> 4, &pData, &dataRemain, &i, &j);
pMap++;
mapRemain--;
}
pFrame += 7*g_width;
}
}
static void relClose(int i, int *x, int *y)
{
int ma, mi;
ma = i >> 4;
mi = i & 0xf;
*x = mi - 8;
*y = ma - 8;
}
static void relFar(int i, int sign, int *x, int *y)
{
if (i < 56) {
*x = sign * (8 + (i % 7));
*y = sign * (i / 7);
} else {
*x = sign * (-14 + (i - 56) % 29);
*y = sign * (8 + (i - 56) / 29);
}
}
/* copies an 8x8 block from pSrc to pDest.
pDest and pSrc are both g_width bytes wide */
static void copyFrame(ubyte *pDest, ubyte *pSrc)
{
int i;
for (i = 0; i < 8; i++) {
memcpy(pDest, pSrc, 8);
pDest += g_width;
pSrc += g_width;
}
}
// Fill in the next eight bytes with p[0], p[1], p[2], or p[3],
// depending on the corresponding two-bit value in pat0 and pat1
static void patternRow4Pixels(ubyte *pFrame, ubyte pat0, ubyte pat1, ubyte *p)
{
ushort mask = 0x0003;
ushort shift = 0;
ushort pattern = (pat1 << 8) | pat0;
while (mask != 0) {
*pFrame++ = p[(mask & pattern) >> shift];
mask <<= 2;
shift += 2;
}
}
// Fill in the next four 2x2 pixel blocks with p[0], p[1], p[2], or p[3],
// depending on the corresponding two-bit value in pat0.
static void patternRow4Pixels2(ubyte *pFrame, ubyte pat0, ubyte *p)
{
ubyte mask = 0x03;
ubyte shift = 0;
ubyte pel;
while (mask != 0) {
pel = p[(mask & pat0) >> shift];
pFrame[0] = pel;
pFrame[1] = pel;
pFrame[g_width + 0] = pel;
pFrame[g_width + 1] = pel;
pFrame += 2;
mask <<= 2;
shift += 2;
}
}
// Fill in the next four 2x1 pixel blocks with p[0], p[1], p[2], or p[3],
// depending on the corresponding two-bit value in pat.
static void patternRow4Pixels2x1(ubyte *pFrame, ubyte pat, ubyte *p)
{
ubyte mask = 0x03;
ubyte shift = 0;
ubyte pel;
while (mask != 0) {
pel = p[(mask & pat) >> shift];
pFrame[0] = pel;
pFrame[1] = pel;
pFrame += 2;
mask <<= 2;
shift += 2;
}
}
// Fill in the next 4x4 pixel block with p[0], p[1], p[2], or p[3],
// depending on the corresponding two-bit value in pat0, pat1, pat2, and pat3.
static void patternQuadrant4Pixels(ubyte *pFrame, ubyte pat0, ubyte pat1, ubyte pat2, ubyte pat3, ubyte *p)
{
unsigned long mask = 0x00000003UL;
int shift=0;
int i;
unsigned long pat = (pat3 << 24) | (pat2 << 16) | (pat1 << 8) | pat0;
for (i = 0; i < 16; i++) {
pFrame[i&3] = p[(pat & mask) >> shift];
if ( (i & 3) == 3 )
pFrame += g_width;
mask <<= 2;
shift += 2;
}
}
// fills the next 8 pixels with either p[0] or p[1], depending on pattern
static void patternRow2Pixels(ubyte *pFrame, ubyte pat, ubyte *p)
{
ubyte mask=0x01;
while (mask != 0) {
*pFrame++ = p[(mask & pat) ? 1 : 0];
mask <<= 1;
}
}
// fills the next four 2 x 2 pixel boxes with either p[0] or p[1], depending on pattern
static void patternRow2Pixels2(ubyte *pFrame, ubyte pat, ubyte *p)
{
ubyte pel;
ubyte mask=0x1;
while (mask != 0x10) {
pel = p[(mask & pat) ? 1 : 0];
pFrame[0] = pel; // upper-left
pFrame[1] = pel; // upper-right
pFrame[g_width + 0] = pel; // lower-left
pFrame[g_width + 1] = pel; // lower-right
pFrame += 2;
mask <<= 1;
}
}
// fills pixels in the next 4 x 4 pixel boxes with either p[0] or p[1], depending on pat0 and pat1.
static void patternQuadrant2Pixels(ubyte *pFrame, ubyte pat0, ubyte pat1, ubyte *p)
{
ubyte pel;
ushort mask = 0x0001;
int i, j;
ushort pat = (pat1 << 8) | pat0;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
pel = p[(pat & mask) ? 1 : 0];
pFrame[j + i * g_width] = pel;
mask <<= 1;
}
}
}
static void dispatchDecoder8(ubyte **pFrame, ubyte codeType, ubyte **pData, int *pDataRemain, int *curXb, int *curYb)
{
ubyte p[4];
ubyte pat[16];
int i, j, k;
int x, y;
switch(codeType) {
case 0x0:
copyFrame(*pFrame, *pFrame + ((ubyte *)g_vBackBuf2 - (ubyte *)g_vBackBuf1));
*pFrame += 8;
break;
case 0x1:
*pFrame += 8;
break;
case 0x2:
relFar(*(*pData)++, 1, &x, &y);
copyFrame(*pFrame, *pFrame + x + y*g_width);
*pFrame += 8;
(*pDataRemain)--;
break;
case 0x3:
relFar(*(*pData)++, -1, &x, &y);
copyFrame(*pFrame, *pFrame + x + y*g_width);
*pFrame += 8;
(*pDataRemain)--;
break;
case 0x4:
relClose(*(*pData)++, &x, &y);
copyFrame(*pFrame, *pFrame + ((ubyte *)g_vBackBuf2 - (ubyte *)g_vBackBuf1) + x + y*g_width);
*pFrame += 8;
(*pDataRemain)--;
break;
case 0x5:
x = (signed char)*(*pData)++;
y = (signed char)*(*pData)++;
copyFrame(*pFrame, *pFrame + ((ubyte *)g_vBackBuf2 - (ubyte *)g_vBackBuf1) + x + y*g_width);
*pFrame += 8;
*pDataRemain -= 2;
break;
case 0x6:
for (i = 0; i < 2; i++) {
*pFrame += 16;
if (++*curXb == (g_width >> 3)) {
*pFrame += 7*g_width;
*curXb = 0;
if (++*curYb == (g_height >> 3))
return;
}
}
break;
case 0x7:
p[0] = *(*pData)++;
p[1] = *(*pData)++;
if (p[0] <= p[1]) {
for (i = 0; i < 8; i++) {
patternRow2Pixels(*pFrame, *(*pData)++, p);
*pFrame += g_width;
}
} else {
for (i = 0; i < 2; i++) {
patternRow2Pixels2(*pFrame, *(*pData) & 0xf, p);
*pFrame += 2*g_width;
patternRow2Pixels2(*pFrame, *(*pData)++ >> 4, p);
*pFrame += 2*g_width;
}
}
*pFrame -= (8*g_width - 8);
break;
case 0x8:
if ( (*pData)[0] <= (*pData)[1] ) {
// four quadrant case
for (i = 0; i < 4; i++) {
p[0] = *(*pData)++;
p[1] = *(*pData)++;
pat[0] = *(*pData)++;
pat[1] = *(*pData)++;
patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
// alternate between moving down and moving up and right
if (i & 1)
*pFrame += 4 - 4*g_width; // up and right
else
*pFrame += 4*g_width; // down
}
} else if ( (*pData)[6] <= (*pData)[7] ) {
// split horizontal
for (i = 0; i < 4; i++) {
if ((i & 1) == 0) {
p[0] = *(*pData)++;
p[1] = *(*pData)++;
}
pat[0] = *(*pData)++;
pat[1] = *(*pData)++;
patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
if (i & 1)
*pFrame -= (4*g_width - 4);
else
*pFrame += 4*g_width;
}
} else {
// split vertical
for (i = 0; i < 8; i++) {
if ((i & 3) == 0) {
p[0] = *(*pData)++;
p[1] = *(*pData)++;
}
patternRow2Pixels(*pFrame, *(*pData)++, p);
*pFrame += g_width;
}
*pFrame -= (8*g_width - 8);
}
break;
case 0x9:
if ( (*pData)[0] <= (*pData)[1] ) {
if ( (*pData)[2] <= (*pData)[3] ) {
p[0] = *(*pData)++;
p[1] = *(*pData)++;
p[2] = *(*pData)++;
p[3] = *(*pData)++;
for (i = 0; i < 8; i++) {
pat[0] = *(*pData)++;
pat[1] = *(*pData)++;
patternRow4Pixels(*pFrame, pat[0], pat[1], p);
*pFrame += g_width;
}
*pFrame -= (8*g_width - 8);
} else {
p[0] = *(*pData)++;
p[1] = *(*pData)++;
p[2] = *(*pData)++;
p[3] = *(*pData)++;
patternRow4Pixels2(*pFrame, *(*pData)++, p);
*pFrame += 2*g_width;
patternRow4Pixels2(*pFrame, *(*pData)++, p);
*pFrame += 2*g_width;
patternRow4Pixels2(*pFrame, *(*pData)++, p);
*pFrame += 2*g_width;
patternRow4Pixels2(*pFrame, *(*pData)++, p);
*pFrame -= (6*g_width - 8);
}
} else {
if ( (*pData)[2] <= (*pData)[3] ) {
// draw 2x1 strips
p[0] = *(*pData)++;
p[1] = *(*pData)++;
p[2] = *(*pData)++;
p[3] = *(*pData)++;
for (i = 0; i < 8; i++) {
pat[0] = *(*pData)++;
patternRow4Pixels2x1(*pFrame, pat[0], p);
*pFrame += g_width;
}
*pFrame -= (8*g_width - 8);
} else {
// draw 1x2 strips
p[0] = *(*pData)++;
p[1] = *(*pData)++;
p[2] = *(*pData)++;
p[3] = *(*pData)++;
for (i = 0; i < 4; i++) {
pat[0] = *(*pData)++;
pat[1] = *(*pData)++;
patternRow4Pixels(*pFrame, pat[0], pat[1], p);
*pFrame += g_width;
patternRow4Pixels(*pFrame, pat[0], pat[1], p);
*pFrame += g_width;
}
*pFrame -= (8*g_width - 8);
}
}
break;
case 0xa:
if ( (*pData)[0] <= (*pData)[1] ) {
for (i = 0; i < 4; i++) {
p[0] = *(*pData)++;
p[1] = *(*pData)++;
p[2] = *(*pData)++;
p[3] = *(*pData)++;
pat[0] = *(*pData)++;
pat[1] = *(*pData)++;
pat[2] = *(*pData)++;
pat[3] = *(*pData)++;
patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
if (i & 1)
*pFrame -= (4*g_width - 4);
else
*pFrame += 4*g_width;
}
} else {
if ( (*pData)[12] <= (*pData)[13] ) {
// split vertical
for (i = 0; i < 4; i++) {
if ((i&1) == 0) {
p[0] = *(*pData)++;
p[1] = *(*pData)++;
p[2] = *(*pData)++;
p[3] = *(*pData)++;
}
pat[0] = *(*pData)++;
pat[1] = *(*pData)++;
pat[2] = *(*pData)++;
pat[3] = *(*pData)++;
patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
if (i & 1)
*pFrame -= (4*g_width - 4);
else
*pFrame += 4*g_width;
}
} else {
// split horizontal
for (i = 0; i < 8; i++) {
if ((i&3) == 0) {
p[0] = *(*pData)++;
p[1] = *(*pData)++;
p[2] = *(*pData)++;
p[3] = *(*pData)++;
}
pat[0] = *(*pData)++;
pat[1] = *(*pData)++;
patternRow4Pixels(*pFrame, pat[0], pat[1], p);
*pFrame += g_width;
}
*pFrame -= (8*g_width - 8);
}
}
break;
case 0xb:
for (i = 0; i < 8; i++) {
memcpy(*pFrame, *pData, 8);
*pFrame += g_width;
*pData += 8;
*pDataRemain -= 8;
}
*pFrame -= (8*g_width - 8);
break;
case 0xc:
for (i = 0; i < 4; i++) {
for (j = 0; j < 2; j++) {
for (k = 0; k < 4; k++) {
(*pFrame)[2*k] = (*pData)[k];
(*pFrame)[2*k+1] = (*pData)[k];
}
*pFrame += g_width;
}
*pData += 4;
*pDataRemain -= 4;
}
*pFrame -= (8*g_width - 8);
break;
case 0xd:
for (i = 0; i < 2; i++) {
for (j = 0; j < 4; j++) {
for (k = 0; k < 4; k++) {
(*pFrame)[k*g_width+j] = (*pData)[0];
(*pFrame)[k*g_width+j+4] = (*pData)[1];
}
}
*pFrame += 4*g_width;
*pData += 2;
*pDataRemain -= 2;
}
*pFrame -= (8*g_width - 8);
break;
case 0xe:
for (i = 0; i < 8; i++) {
memset(*pFrame, **pData, 8);
*pFrame += g_width;
}
(*pData)++;
(*pDataRemain)--;
*pFrame -= (8*g_width - 8);
break;
case 0xf:
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
(*pFrame)[j] = (*pData)[(i+j)&1];
}
*pFrame += g_width;
}
*pData += 2;
*pDataRemain -= 2;
*pFrame -= (8*g_width - 8);
break;
default:
break;
}
}
+224
View File
@@ -0,0 +1,224 @@
#include "cutscene/ffmpeg/AudioDecoder.h"
#include "tracing/tracing.h"
namespace {
const int OUT_CH_LAYOUT = AV_CH_LAYOUT_STEREO;
const int OUT_SAMPLE_RATE = 48000;
const AVSampleFormat OUT_SAMPLE_FORMAT = AV_SAMPLE_FMT_S16;
const int OUT_NUM_CHANNELS = av_get_channel_layout_nb_channels(OUT_CH_LAYOUT);
const int DEFAULT_SRC_NUM_SAMPLES = 1024;
SwrContext* getSWRContext(uint64_t layout, int rate, AVSampleFormat inFmt) {
auto swr = swr_alloc();
av_opt_set_int(swr, "in_channel_layout", layout, 0);
av_opt_set_int(swr, "in_sample_rate", rate, 0);
av_opt_set_int(swr, "in_sample_fmt", inFmt, 0);
av_opt_set_int(swr, "out_channel_layout", OUT_CH_LAYOUT, 0);
av_opt_set_int(swr, "out_sample_rate", OUT_SAMPLE_RATE, 0);
av_opt_set_int(swr, "out_sample_fmt", OUT_SAMPLE_FORMAT, 0);
swr_init(swr);
return swr;
}
int alloc_array_and_samples(uint8_t*** outData, int* linesize, int channels, int samples, AVSampleFormat format) {
auto planes = av_sample_fmt_is_planar(format) ? channels : 1;
*outData = reinterpret_cast<uint8_t**>(av_mallocz(planes * sizeof(**outData)));
auto ret = av_samples_alloc(*outData, linesize, channels, samples, format, 0);
if (ret < 0) {
av_freep(outData);
}
return ret;
}
int64_t getDelay(SwrContext* ctx, int64_t sampleRate) {
#ifdef WITH_LIBAV
return avresample_get_delay(ctx);
#else
return swr_get_delay(ctx, sampleRate);
#endif
}
int resample_convert(SwrContext* ctx, uint8_t** output,
int out_plane_size, int out_samples, uint8_t** input,
int in_plane_size, int in_samples) {
#ifdef WITH_LIBAV
return avresample_convert(ctx, output, out_plane_size, out_samples, input, in_plane_size, in_samples);
#else
return swr_convert(ctx, output, out_samples, (const uint8_t**) input, in_samples);
#endif
}
}
namespace cutscene {
namespace ffmpeg {
AudioDecoder::AudioDecoder(DecoderStatus* status)
: FFMPEGStreamDecoder(status) {
m_audioBuffer.reserve(static_cast<size_t>(OUT_SAMPLE_RATE * OUT_NUM_CHANNELS / 2));
m_resampleCtx = getSWRContext(m_status->audioCodecPars.channel_layout, m_status->audioCodecPars.sample_rate,
m_status->audioCodecPars.audio_format);
/*
* compute the number of converted samples: buffering is avoided
* ensuring that the output buffer will contain at least all the
* converted input samples
*/
m_maxOutNumSamples = m_outNumSamples = static_cast<int>(av_rescale_rnd(DEFAULT_SRC_NUM_SAMPLES,
OUT_SAMPLE_RATE,
m_status->audioCodecPars.sample_rate,
AV_ROUND_UP));
auto ret = alloc_array_and_samples(&m_outData, &m_outLinesize, OUT_NUM_CHANNELS,
m_outNumSamples, OUT_SAMPLE_FORMAT);
if (ret < 0) {
mprintf(("FFMPEG: Failed to allocate samples array!\n"));
}
}
AudioDecoder::~AudioDecoder() {
if (m_outData) {
av_freep(&m_outData[0]);
}
av_freep(&m_outData);
swr_free(&m_resampleCtx);
}
void AudioDecoder::flushAudioBuffer() {
if (m_audioBuffer.empty()) {
// Nothing to do here
return;
}
AudioFramePtr audioFrame(new AudioFrame());
audioFrame->channels = OUT_NUM_CHANNELS;
audioFrame->rate = OUT_SAMPLE_RATE;
audioFrame->audioData.assign(m_audioBuffer.begin(), m_audioBuffer.end());
pushFrame(std::move(audioFrame));
m_audioBuffer.clear();
}
void AudioDecoder::handleDecodedFrame(AVFrame* frame) {
/* compute destination number of samples */
m_outNumSamples = static_cast<int>(av_rescale_rnd(getDelay(m_resampleCtx, frame->sample_rate)
+ frame->nb_samples, OUT_SAMPLE_RATE, frame->sample_rate,
AV_ROUND_UP));
if (m_outNumSamples > m_maxOutNumSamples) {
av_freep(&m_outData[0]);
auto ret = av_samples_alloc(m_outData, &m_outLinesize, OUT_NUM_CHANNELS, m_outNumSamples,
OUT_SAMPLE_FORMAT, 1);
if (ret < 0) {
mprintf(("FFMPEG: Failed to allocate samples!!!"));
return;
}
m_maxOutNumSamples = m_outNumSamples;
}
/* convert to destination format */
auto ret = resample_convert(m_resampleCtx, m_outData, 0, m_outNumSamples,
(uint8_t**) frame->data, 0, frame->nb_samples);
if (ret < 0) {
mprintf(("FFMPEG: Error while converting audio!\n"));
return;
}
auto outBufsize = av_samples_get_buffer_size(&m_outLinesize, OUT_NUM_CHANNELS, ret, OUT_SAMPLE_FORMAT, 1);
if (outBufsize < 0) {
mprintf(("FFMPEG: Could not get sample buffer size!\n"));
return;
}
auto begin = reinterpret_cast<short*>(m_outData[0]);
auto end = reinterpret_cast<short*>(m_outData[0] + outBufsize);
auto size = std::distance(begin, end);
auto newSize = m_audioBuffer.size() + size;
if (newSize <= m_audioBuffer.capacity()) {
// We haven't filled the buffer yet
m_audioBuffer.insert(m_audioBuffer.end(), begin, end);
} else {
flushAudioBuffer();
m_audioBuffer.assign(begin, end);
}
}
void AudioDecoder::decodePacket(AVPacket* packet) {
TRACE_SCOPE(tracing::CutsceneFFmpegAudioDecoder);
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
int send_result;
do {
send_result = avcodec_send_packet(m_status->audioCodecCtx, packet);
while (avcodec_receive_frame(m_status->audioCodecCtx, m_decodeFrame) == 0) {
handleDecodedFrame(m_decodeFrame);
}
} while (send_result == AVERROR(EAGAIN));
#else
int finishedFrame = 0;
auto err = avcodec_decode_audio4(m_status->audioCodecCtx, m_decodeFrame, &finishedFrame, packet);
if (err >= 0 && finishedFrame) {
handleDecodedFrame(m_decodeFrame);
}
#endif
}
void AudioDecoder::finishDecoding() {
TRACE_SCOPE(tracing::CutsceneFFmpegAudioDecoder);
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
// Send flush packet
avcodec_send_packet(m_status->audioCodecCtx, nullptr);
// Handle those decoders that have a delay
while (true) {
auto ret = avcodec_receive_frame(m_status->audioCodecCtx, m_decodeFrame);
if (ret == 0) {
handleDecodedFrame(m_decodeFrame);
}
else {
// Everything consumed or error
break;
}
}
#else
// Handle those decoders that have a delay
AVPacket nullPacket;
memset(&nullPacket, 0, sizeof(nullPacket));
nullPacket.data = nullptr;
nullPacket.size = 0;
while (true) {
int finishedFrame = 1;
auto err = avcodec_decode_audio4(m_status->audioCodecCtx, m_decodeFrame, &finishedFrame, &nullPacket);
if (err < 0 || !finishedFrame) {
break;
}
handleDecodedFrame(m_decodeFrame);
}
#endif
// Push the last bits of audio data into the queue
flushAudioBuffer();
}
}
}
+35
View File
@@ -0,0 +1,35 @@
#pragma once
#include "cutscene/ffmpeg/internal.h"
#include "cutscene/ffmpeg/FFMPEGDecoder.h"
namespace cutscene {
namespace ffmpeg {
class AudioDecoder: public FFMPEGStreamDecoder<AudioFrame> {
private:
SwrContext* m_resampleCtx;
uint8_t** m_outData;
int m_outLinesize;
int m_maxOutNumSamples;
int m_outNumSamples;
SCP_vector<short> m_audioBuffer;
void handleDecodedFrame(AVFrame* frame);
void flushAudioBuffer();
public:
explicit AudioDecoder(DecoderStatus* status);
virtual ~AudioDecoder();
virtual void decodePacket(AVPacket* packet) SCP_OVERRIDE;
virtual void finishDecoding() SCP_OVERRIDE;
};
}
}
+363
View File
@@ -0,0 +1,363 @@
#include <limits>
#include "cutscene/ffmpeg/FFMPEGDecoder.h"
#include "cfile/cfile.h"
#include "libs/ffmpeg/FFmpegContext.h"
#include "cutscene/ffmpeg/internal.h"
#include "cutscene/ffmpeg/AudioDecoder.h"
#include "cutscene/ffmpeg/VideoDecoder.h"
using namespace libs::ffmpeg;
namespace {
using namespace cutscene;
using namespace cutscene::ffmpeg;
class AVPacketScope
{
AVPacket* _packet;
public:
explicit AVPacketScope(AVPacket* av_packet)
: _packet(av_packet) {
}
~AVPacketScope() {
av_packet_unref(_packet);
}
};
const char* CHECKED_EXTENSIONS[] = {
"webm",
"mp4",
"ogg",
"mve"
};
double getFrameRate(AVStream* stream, AVCodecContext* codecCtx) {
auto fps = av_q2d(av_stream_get_r_frame_rate(stream));
if (fps < 0.000001)
{
fps = av_q2d(stream->avg_frame_rate);
}
if (fps < 0.000001)
{
fps = 1.0 / av_q2d(codecCtx->time_base);
}
return fps;
}
CodecContextParameters getCodecParameters(AVStream* stream) {
CodecContextParameters paras;
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
paras.width = stream->codecpar->width;
paras.height = stream->codecpar->height;
paras.pixel_format = (AVPixelFormat)stream->codecpar->format;
paras.channel_layout = stream->codecpar->channel_layout;
paras.sample_rate = stream->codecpar->sample_rate;
paras.audio_format = (AVSampleFormat)stream->codecpar->format;
#else
paras.width = stream->codec->width;
paras.height = stream->codec->height;
paras.pixel_format = stream->codec->pix_fmt;
paras.channel_layout = stream->codec->channel_layout;
paras.sample_rate = stream->codec->sample_rate;
paras.audio_format = stream->codec->sample_fmt;
#endif
return paras;
}
}
namespace cutscene {
namespace ffmpeg {
struct InputStream {
std::unique_ptr<FFmpegContext> m_ctx;
};
FFMPEGDecoder::FFMPEGDecoder() {
}
FFMPEGDecoder::~FFMPEGDecoder() {
}
namespace {
std::unique_ptr<InputStream> openStream(const SCP_string& name) {
// Only check the root and movies folders
int dirType;
if (cf_exists_full(name.c_str(), CF_TYPE_ROOT)) {
dirType = CF_TYPE_ROOT;
} else if (cf_exists_full(name.c_str(), CF_TYPE_MOVIES)) {
dirType = CF_TYPE_MOVIES;
} else {
return nullptr;
}
std::unique_ptr<InputStream> input(new InputStream());
try {
// Create the FFmpeg context
input->m_ctx = FFmpegContext::createContext(name, dirType);
// This may fail, in that case return null
if (!input->m_ctx) {
return nullptr;
}
}
catch (const FFmpegException& e) {
mprintf(("Error opening %s: %s\n", name.c_str(), e.what()));
return nullptr;
}
return input;
}
std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream>& stream) {
std::unique_ptr<DecoderStatus> status(new DecoderStatus());
auto ctx = stream->m_ctx->ctx();
auto videoStream = av_find_best_stream(ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &status->videoCodec, 0);
if (videoStream < 0) {
if (videoStream == AVERROR_STREAM_NOT_FOUND) {
mprintf(("FFmpeg: No video stream found in file!\n"));
} else if (videoStream == AVERROR_DECODER_NOT_FOUND) {
mprintf(("FFmpeg: Codec for video stream could not be found!\n"));
} else {
mprintf(("FFmpeg: Unknown error while finding video stream!\n"));
}
return nullptr;
}
auto audioStream = av_find_best_stream(ctx, AVMEDIA_TYPE_AUDIO, -1, videoStream, &status->audioCodec, 0);
if (audioStream < 0) {
if (audioStream == AVERROR_STREAM_NOT_FOUND) {
mprintf(("FFmpeg: No audio stream found in file!\n"));
} else if (videoStream == AVERROR_DECODER_NOT_FOUND) {
mprintf(("FFmpeg: Codec for audio stream could not be found!\n"));
} else {
mprintf(("FFmpeg: Unknown error while finding audio stream!\n"));
}
}
status->videoStreamIndex = videoStream;
status->videoStream = ctx->streams[videoStream];
if (audioStream >= 0) {
status->audioStreamIndex = audioStream;
status->audioStream = ctx->streams[audioStream];
}
status->videoCodecPars = getCodecParameters(status->videoStream);
int err;
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
status->videoCodecCtx = avcodec_alloc_context3(status->videoCodec);
// Copy codec parameters from input stream to output codec context
err = avcodec_parameters_to_context(status->videoCodecCtx, status->videoStream->codecpar);
if (err < 0) {
char errorStr[512];
av_strerror(err, errorStr, sizeof(errorStr));
mprintf(("FFMPEG: Failed to copy context parameters! Error: %s\n", errorStr));
return nullptr;
}
#else
status->videoCodecCtx = status->videoStream->codec;
#endif
err = avcodec_open2(status->videoCodecCtx, status->videoCodec, nullptr);
if (err < 0) {
char errorStr[512];
av_strerror(err, errorStr, sizeof(errorStr));
mprintf(("FFMPEG: Failed to open video codec! Error: %s\n", errorStr));
return nullptr;
}
mprintf(("FFmpeg: Using video codec %s (%s).\n", status->videoCodec->long_name ? status->videoCodec->long_name : "<Unknown>",
status->videoCodec->name ? status->videoCodec->name : "<Unknown>"));
// Now initialize audio, if this fails it's not a fatal error
if (audioStream >= 0) {
status->audioCodecPars = getCodecParameters(status->audioStream);
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
status->audioCodecCtx = avcodec_alloc_context3(status->audioCodec);
err = avcodec_parameters_to_context(status->audioCodecCtx, status->audioStream->codecpar);
if (err < 0) {
char errorStr[512];
av_strerror(err, errorStr, sizeof(errorStr));
mprintf(("FFMPEG: Failed to copy context parameters! Error: %s\n", errorStr));
return nullptr;
}
#else
status->audioCodecCtx = status->audioStream->codec;
#endif
err = avcodec_open2(status->audioCodecCtx, status->audioCodec, nullptr);
if (err < 0) {
char errorStr[512];
av_strerror(err, errorStr, sizeof(errorStr));
mprintf(("FFMPEG: Failed to open audio codec! Error: %s\n", errorStr));
}
mprintf(("FFmpeg: Using audio codec %s (%s).\n", status->audioCodec->long_name ? status->audioCodec->long_name : "<Unknown>",
status->audioCodec->name ? status->audioCodec->name : "<Unknown>"));
}
return status;
}
std::unique_ptr<InputStream> openInputStream(const SCP_string& name) {
// Check a list of extensions we might use
// The actual format of the file may be whatever FFmpeg supports
for (auto ext : CHECKED_EXTENSIONS) {
auto fileName = name + "." + ext;
auto input = openStream(fileName);
if (input) {
return input;
}
}
return nullptr;
}
}
bool FFMPEGDecoder::initialize(const SCP_string& fileName) {
SCP_string movieName = fileName;
// First make the file name lower case
std::transform(movieName.begin(), movieName.end(), movieName.begin(), ::tolower);
// Then remove the extension
size_t dotPos = movieName.find('.');
if (dotPos != SCP_string::npos) {
movieName.resize(dotPos);
}
// Try to open the input stream
auto input = openInputStream(movieName);
if (!input) {
return false;
}
// We now have a valid input stream, try to find the correct streams
auto status = initializeStatus(input);
if (!status) {
return false;
}
// Buffer ~ 2 seconds of video and audio
initializeQueues(static_cast<size_t>(ceil(getFrameRate(status->videoStream, status->videoCodecCtx))) * 2);
// We're done, now just put the pointer into this
std::swap(m_input, input);
std::swap(m_status, status);
return true;
}
MovieProperties FFMPEGDecoder::getProperties() {
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));
return props;
}
void FFMPEGDecoder::startDecoding() {
std::unique_ptr<VideoDecoder> videoDecoder(new VideoDecoder(m_status.get()));
std::unique_ptr<AudioDecoder> audioDecoder;
if (hasAudio()) {
audioDecoder.reset(new AudioDecoder(m_status.get()));
}
auto ctx = m_input->m_ctx->ctx();
AVPacket packet;
while (isDecoding()) {
auto read_err = av_read_frame(ctx, &packet);
AVPacketScope scope(&packet);
if (avio_feof(ctx->pb) != 0) {
// EOF!!
break;
} else if (read_err < 0) {
if (read_err == AVERROR_EOF) {
// Finished reading -> break out of loop
break;
} else {
// Some kind of other error, try to continue reading
char errorStr[512];
av_strerror(read_err, errorStr, sizeof(errorStr));
mprintf(("FFMPEG: Failed to read frame! Error: %s\n", errorStr));
// Skip packet
continue;
}
}
if (packet.stream_index == m_status->videoStreamIndex) {
videoDecoder->decodePacket(&packet);
VideoFramePtr ptr;
while((ptr = videoDecoder->getFrame()) != nullptr) {
pushFrameData(std::move(ptr));
}
} else if (audioDecoder && packet.stream_index == m_status->audioStreamIndex) {
audioDecoder->decodePacket(&packet);
AudioFramePtr ptr;
while ((ptr = audioDecoder->getFrame()) != nullptr) {
pushAudioData(std::move(ptr));
}
}
}
if (isDecoding()) {
// If we are still alive then read the last frames from the decoders
videoDecoder->finishDecoding();
VideoFramePtr video_ptr;
while ((video_ptr = videoDecoder->getFrame()) != nullptr) {
pushFrameData(std::move(video_ptr));
}
if (audioDecoder) {
audioDecoder->finishDecoding();
AudioFramePtr audio_frame;
while ((audio_frame = audioDecoder->getFrame()) != nullptr) {
pushAudioData(std::move(audio_frame));
}
}
}
stopDecoder();
}
bool FFMPEGDecoder::hasAudio() {
return m_status->audioStreamIndex >= 0;
}
void FFMPEGDecoder::close() {
if (m_status) {
m_status = nullptr;
}
if (m_input) {
// This will delete the InputStream pointer and free all data
m_input = nullptr;
}
}
}
}
+33
View File
@@ -0,0 +1,33 @@
#pragma once
#include "cutscene/Decoder.h"
namespace cutscene {
namespace ffmpeg {
struct InputStream;
struct DecoderStatus;
class FFMPEGDecoder: public Decoder {
private:
std::unique_ptr<InputStream> m_input;
std::unique_ptr<DecoderStatus> m_status;
public:
FFMPEGDecoder();
virtual ~FFMPEGDecoder();
bool initialize(const SCP_string& fileName) SCP_OVERRIDE;
MovieProperties getProperties() SCP_OVERRIDE;
void startDecoding() SCP_OVERRIDE;
bool hasAudio() SCP_OVERRIDE;
void close() SCP_OVERRIDE;
};
}
}
+166
View File
@@ -0,0 +1,166 @@
#include "cutscene/ffmpeg/VideoDecoder.h"
#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);
}
double getFrameTime(int64_t pts, AVRational time_base) {
return pts * av_q2d(time_base);
}
}
namespace cutscene {
namespace ffmpeg {
class FFMPEGVideoFrame: public VideoFrame {
public:
FFMPEGVideoFrame() : frame(nullptr) {
}
virtual ~FFMPEGVideoFrame() {
if (frame != nullptr) {
av_freep(&frame->data[0]);
av_frame_free(&frame);
}
}
virtual DataPointers getDataPointers() {
DataPointers ptrs;
ptrs.y = frame->data[0];
ptrs.u = frame->data[1];
ptrs.v = frame->data[2];
return ptrs;
}
AVFrame* frame;
};
VideoDecoder::VideoDecoder(DecoderStatus* status)
: FFMPEGStreamDecoder(status),
m_frameId(0) {
m_swsCtx = getSWSContext(m_status->videoCodecPars.width, m_status->videoCodecPars.height,
m_status->videoCodecPars.pixel_format);
}
VideoDecoder::~VideoDecoder() {
sws_freeContext(m_swsCtx);
}
void VideoDecoder::convertAndPushPicture(const AVFrame* frame) {
// Allocate a picture to hold the YUV data
AVFrame* yuvFrame = av_frame_alloc();
av_frame_copy(yuvFrame, frame);
yuvFrame->format = DESTINATION_FORMAT;
av_image_alloc(yuvFrame->data,
yuvFrame->linesize,
m_status->videoCodecPars.width,
m_status->videoCodecPars.height,
DESTINATION_FORMAT,
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);
} 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
);
}
videoFramePtr->id = ++m_frameId;
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]);
pushFrame(VideoFramePtr(videoFramePtr.release()));
}
void VideoDecoder::decodePacket(AVPacket* packet) {
TRACE_SCOPE(tracing::CutsceneFFmpegVideoDecoder);
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
int send_result;
do {
send_result = avcodec_send_packet(m_status->videoCodecCtx, packet);
while(avcodec_receive_frame(m_status->videoCodecCtx, m_decodeFrame) == 0) {
convertAndPushPicture(m_decodeFrame);
}
} while (send_result == AVERROR(EAGAIN));
#else
int finishedFrame = 0;
auto result = avcodec_decode_video2(m_status->videoCodecCtx, m_decodeFrame, &finishedFrame, packet);
if (result >= 0 && finishedFrame) {
convertAndPushPicture(m_decodeFrame);
}
#endif
}
void VideoDecoder::finishDecoding() {
TRACE_SCOPE(tracing::CutsceneFFmpegVideoDecoder);
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
// Send flush packet
avcodec_send_packet(m_status->videoCodecCtx, nullptr);
// Handle those decoders that have a delay
while (true) {
auto ret = avcodec_receive_frame(m_status->videoCodecCtx, m_decodeFrame);
if (ret == 0) {
convertAndPushPicture(m_decodeFrame);
} else {
// Everything consumed or error
break;
}
}
#else
// Handle those decoders that have a delay
AVPacket nullPacket;
memset(&nullPacket, 0, sizeof(nullPacket));
nullPacket.data = nullptr;
nullPacket.size = 0;
while (true) {
int finishedFrame = 1;
auto err = avcodec_decode_video2(m_status->videoCodecCtx, m_decodeFrame, &finishedFrame, &nullPacket);
if (err < 0 || !finishedFrame) {
break;
}
convertAndPushPicture(m_decodeFrame);
}
#endif
}
}
}
+25
View File
@@ -0,0 +1,25 @@
#pragma once
#include "cutscene/ffmpeg/internal.h"
#include "cutscene/ffmpeg/FFMPEGDecoder.h"
namespace cutscene {
namespace ffmpeg {
class VideoDecoder: public FFMPEGStreamDecoder<VideoFrame> {
private:
int m_frameId;
SwsContext* m_swsCtx;
void convertAndPushPicture(const AVFrame* frame);
public:
explicit VideoDecoder(DecoderStatus* status);
virtual ~VideoDecoder();
virtual void decodePacket(AVPacket* packet) SCP_OVERRIDE;
virtual void finishDecoding() SCP_OVERRIDE;
};
}
}
+36
View File
@@ -0,0 +1,36 @@
#include "cutscene/ffmpeg/internal.h"
namespace cutscene {
namespace ffmpeg {
DecoderStatus::DecoderStatus() {}
DecoderStatus::~DecoderStatus() {
videoStreamIndex = -1;
videoStream = nullptr;
videoCodec = nullptr;
if (videoCodecCtx != nullptr) {
avcodec_close(videoCodecCtx);
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
avcodec_free_context(&videoCodecCtx);
#endif
videoCodecCtx = nullptr;
}
audioStreamIndex = -1;
audioStream = nullptr;
audioCodec = nullptr;
if (audioCodecCtx != nullptr) {
avcodec_close(audioCodecCtx);
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
avcodec_free_context(&audioCodecCtx);
#endif
audioCodecCtx = nullptr;
}
}
} // namespace ffmpeg
} // namespace cutscene
+101
View File
@@ -0,0 +1,101 @@
#pragma once
#include <functional>
#include "libs/ffmpeg/FFmpegHeaders.h"
#include "cutscene/Decoder.h"
namespace cutscene {
namespace ffmpeg {
struct CodecContextParameters {
int width = -1;
int height = -1;
AVPixelFormat pixel_format = AV_PIX_FMT_NONE;
uint64_t channel_layout = 0;
int sample_rate = -1;
AVSampleFormat audio_format = AV_SAMPLE_FMT_NONE;
};
struct DecoderStatus {
int videoStreamIndex = -1;
AVStream* videoStream = nullptr;
CodecContextParameters videoCodecPars;
AVCodec* videoCodec = nullptr;
AVCodecContext* videoCodecCtx = nullptr;
int audioStreamIndex = -1;
AVStream* audioStream = nullptr;
CodecContextParameters audioCodecPars;
AVCodec* audioCodec = nullptr;
AVCodecContext* audioCodecCtx = nullptr;
DecoderStatus();
~DecoderStatus();
private:
DecoderStatus(const DecoderStatus&) SCP_DELETED_FUNCTION;
DecoderStatus& operator=(const DecoderStatus&) SCP_DELETED_FUNCTION;
};
template<typename Frame>
class FFMPEGStreamDecoder {
protected:
typedef Frame frame_type;
DecoderStatus* m_status = nullptr;
AVFrame* m_decodeFrame = nullptr;
SCP_queue<FramePtr<frame_type>> m_decodedFrames;
void pushFrame(FramePtr<frame_type>&& frame);
public:
explicit FFMPEGStreamDecoder(DecoderStatus* status);
virtual ~FFMPEGStreamDecoder();
FFMPEGStreamDecoder(const FFMPEGStreamDecoder&) SCP_DELETED_FUNCTION;
FFMPEGStreamDecoder& operator=(const FFMPEGStreamDecoder&) SCP_DELETED_FUNCTION;
virtual void decodePacket(AVPacket* packet) = 0;
virtual void finishDecoding() = 0;
virtual FramePtr<frame_type> getFrame();
};
template <typename Frame>
void FFMPEGStreamDecoder<Frame>::pushFrame(FramePtr<frame_type>&& frame)
{
m_decodedFrames.push(std::move(frame));
}
template <typename Frame>
FFMPEGStreamDecoder<Frame>::FFMPEGStreamDecoder(DecoderStatus* status):m_status(status)
{
m_decodeFrame = av_frame_alloc();
}
template <typename Frame>
FFMPEGStreamDecoder<Frame>::~FFMPEGStreamDecoder()
{
av_frame_free(&m_decodeFrame);
}
template <typename Frame>
FramePtr<typename FFMPEGStreamDecoder<Frame>::frame_type> FFMPEGStreamDecoder<Frame>::getFrame()
{
if (m_decodedFrames.empty()) {
return nullptr;
}
auto frame = std::move(m_decodedFrames.front());
m_decodedFrames.pop();
return frame;
}
}
}
+20 -106
View File
@@ -13,64 +13,21 @@
#include <windows.h>
#endif
#include "globalincs/pstypes.h"
#include "globalincs/systemvars.h"
#include "io/cursor.h"
#include "graphics/2d.h"
#include "cfile/cfile.h"
#include "cmdline/cmdline.h"
#include "cutscene/cutscenes.h" // cutscene_mark_viewable()
#include "cutscene/movie.h"
#include "cutscene/mvelib.h"
#include "cutscene/oggplayer.h"
#include "globalincs/systemvars.h"
#include "graphics/2d.h"
#include "osapi/osapi.h"
#include "cutscene/player.h" // cutscene_mark_viewable()
extern int Game_mode;
extern int Is_standalone;
const char *movie_ext_list[] = { ".ogg", ".mve" };
const int NUM_MOVIE_EXT = sizeof(movie_ext_list) / sizeof(char*);
#define MOVIE_NONE -1
#define MOVIE_OGG 0
#define MOVIE_MVE 1
// This module links freespace movie calls to the actual API calls the play the movie.
// This module handles all the different requires of OS and gfx API and finding the file to play
// filename - file to search for
// out_name - output, full path to file
// returns non-zero if file is found
int movie_find(char *filename, char *out_name)
{
char full_path[MAX_PATH];
char tmp_name[MAX_PATH];
size_t size, offset = 0;
if (out_name == NULL)
return MOVIE_NONE;
memset( full_path, 0, sizeof(full_path) );
memset( tmp_name, 0, sizeof(tmp_name) );
// remove extension
strcpy_s( tmp_name, filename );
char *p = strrchr(tmp_name, '.');
if ( p ) *p = 0;
int rc = cf_find_file_location_ext(tmp_name, NUM_MOVIE_EXT, movie_ext_list, CF_TYPE_ANY, sizeof(full_path) - 1, full_path, &size, &offset, 0);
if (rc == MOVIE_NONE)
return MOVIE_NONE;
strcpy( out_name, full_path );
return rc;
}
namespace movie {
// Play one movie
bool movie_play(char *name)
{
bool play(const char* name) {
// mark the movie as viewable to the player when in a campaign
// do this before anything else so that we're sure the movie is available
// to the player even if it's not going to play right now
@@ -78,25 +35,7 @@ bool movie_play(char *name)
cutscene_mark_viewable(name);
}
extern int Is_standalone;
if (Cmdline_nomovies || Is_standalone)
return false;
char full_name[MAX_PATH];
int rc = 0;
memset(full_name, 0, sizeof(full_name));
rc = movie_find(name, full_name);
if (rc == MOVIE_NONE) {
strcpy_s(full_name, name);
char *p = strrchr(full_name, '.');
if ( p ) *p = 0;
mprintf(("Movie Error: Unable to open '%s' movie in any supported format.\n", full_name));
if (Cmdline_nomovies || Is_standalone) {
return false;
}
@@ -116,38 +55,12 @@ bool movie_play(char *name)
// clear third buffer (may not be one, but that's ok)
gr_clear();
if (rc == MOVIE_OGG) {
THEORAFILE *movie_ogg = theora_open(name);
if (movie_ogg) {
// start playing ...
theora_play(movie_ogg);
// ... done playing, close the movie
theora_close(movie_ogg);
} else {
// uh-oh, movie is invalid... Abory, Retry, Fail?
mprintf(("MOVIE ERROR: Found invalid movie! (%s)\n", name));
io::mouse::CursorManager::get()->popStatus();
return false;
}
} else if (rc == MOVIE_MVE) {
MVESTREAM *movie_mve = mve_open(name);
if (movie_mve) {
// start playing ...
mve_init(movie_mve);
mve_play(movie_mve);
// ... done playing, close the movie
mve_shutdown();
mve_close(movie_mve);
} else {
// uh-oh, movie is invalid... Abory, Retry, Fail?
mprintf(("MOVIE ERROR: Found invalid movie! (%s)\n", name));
io::mouse::CursorManager::get()->popStatus();
return false;
}
auto player = cutscene::Player::newPlayer(name);
if (player) {
player->startPlayback();
} else {
// uh-oh, movie is invalid... Abory, Retry, Fail?
mprintf(("MOVIE ERROR: Found invalid movie! (%s)\n", name));
}
// show the mouse cursor again
@@ -156,8 +69,9 @@ bool movie_play(char *name)
return true;
}
void movie_play_two(char *name1, char *name2)
{
if ( movie_play(name1) )
movie_play(name2);
void play_two(const char* name1, const char* name2) {
if (play(name1)) {
play(name2);
}
}
}
+6 -4
View File
@@ -12,10 +12,12 @@
#ifndef _MOVIE_HEADER_FILE
#define _MOVIE_HEADER_FILE
extern const char *movie_ext_list[];
extern const int NUM_MOVIE_EXT;
namespace movie {
bool movie_play(char *name);
void movie_play_two(char *name1, char *name2);
bool play(const char* name);
void play_two(const char* name1, const char* name2);
}
#endif
-56
View File
@@ -1,56 +0,0 @@
static int audio_exp_table[256] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 47, 51, 56, 61,
66, 72, 79, 86, 94, 102, 112, 122, 133, 145, 158, 173, 189, 206, 225, 245,
267, 292, 318, 348, 379, 414, 452, 493, 538, 587, 640, 699, 763, 832, 908, 991,
1081, 1180, 1288, 1405, 1534, 1673, 1826, 1993, 2175, 2373, 2590, 2826, 3084, 3365, 3672, 4008,
4373, 4772, 5208, 5683, 6202, 6767, 7385, 8059, 8794, 9597, 10472, 11428, 12471, 13609, 14851, 16206,
17685, 19298, 21060, 22981, 25078, 27367, 29864, 32589, -29973, -26728, -23186, -19322, -15105, -10503, -5481, -1,
1, 1, 5481, 10503, 15105, 19322, 23186, 26728, 29973, -32589, -29864, -27367, -25078, -22981, -21060, -19298,
-17685, -16206, -14851, -13609, -12471, -11428, -10472, -9597, -8794, -8059, -7385, -6767, -6202, -5683, -5208, -4772,
-4373, -4008, -3672, -3365, -3084, -2826, -2590, -2373, -2175, -1993, -1826, -1673, -1534, -1405, -1288, -1180,
-1081, -991, -908, -832, -763, -699, -640, -587, -538, -493, -452, -414, -379, -348, -318, -292,
-267, -245, -225, -206, -189, -173, -158, -145, -133, -122, -112, -102, -94, -86, -79, -72,
-66, -61, -56, -51, -47, -43, -42, -41, -40, -39, -38, -37, -36, -35, -34, -33,
-32, -31, -30, -29, -28, -27, -26, -25, -24, -23, -22, -21, -20, -19, -18, -17,
-16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1
};
static int getWord(unsigned char **fin)
{
int value = ((*fin)[1] << 8) | (*fin)[0];
*fin += 2;
return value;
}
static void sendWord(short **fout, int nOffset)
{
*(*fout)++ = (short)nOffset;
}
static void processSwath(short *fout, unsigned char *data, int swath, int *offsets)
{
int i;
for (i=0; i<swath; i++) {
offsets[i&1] += audio_exp_table[data[i]];
sendWord(&fout, offsets[i&1]);
}
}
void mveaudio_uncompress(short *buffer, unsigned char *data)
{
int nCurOffsets[2];
int swath;
data += 4;
swath = getWord(&data) / 2;
nCurOffsets[0] = getWord(&data);
nCurOffsets[1] = getWord(&data);
sendWord(&buffer, nCurOffsets[0]);
sendWord(&buffer, nCurOffsets[1]);
processSwath(buffer, data, swath, nCurOffsets);
}
-371
View File
@@ -1,371 +0,0 @@
#include "cfile/cfile.h"
#include "cutscene/mvelib.h"
#include "globalincs/pstypes.h"
static const char MVE_HEADER[] = "Interplay MVE File\x1A";
static const short MVE_HDRCONST1 = 0x001A;
static const short MVE_HDRCONST2 = 0x0100;
static const short MVE_HDRCONST3 = 0x1133;
// -----------------------------------------------------------
// public MVEFILE functions
// -----------------------------------------------------------
// utility functions for mvefile and mveplayer
short mve_get_short(ubyte *data)
{
short value;
value = data[0] | (data[1] << 8);
return value;
}
ushort mve_get_ushort(ubyte *data)
{
ushort value;
value = data[0] | (data[1] << 8);
return value;
}
int mve_get_int(ubyte *data)
{
int value;
value = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
return value;
}
// open an MVE file
MVEFILE *mvefile_open(char *filename)
{
int cf_opened = 0;
int mve_valid = 1;
char lower_name[MAX_FILENAME_LEN];
char buffer[20];
MVEFILE *file;
// create the file
file = (MVEFILE *)vm_malloc(sizeof(MVEFILE));
// set defaults
file->stream = NULL;
file->cur_chunk = NULL;
file->buf_size = 0;
file->cur_fill = 0;
file->next_segment = 0;
// lower case filename for checking
strncpy(lower_name, filename, strlen(filename)+1);
strlwr(lower_name);
char *p = strchr( lower_name, '.' );
if ( p ) *p = 0;
strcat_s( lower_name, ".mve" );
// NOTE: CF_TYPE *must* be ANY to get movies off of the CDs
// assume lower case filename for *nix
file->stream = cfopen(lower_name, "rb", CFILE_NORMAL, CF_TYPE_ANY);
if ( file->stream ) {
cf_opened = 1;
}
if (!cf_opened) {
mvefile_close(file);
return NULL;
}
// initialize the buffer
file->cur_chunk = (ubyte *)vm_malloc(100 + 1024);
file->buf_size = 100 + 1024;
// verify the file's header
cfread_string(buffer, 20, file->stream);
if (strcmp(buffer, MVE_HEADER))
mve_valid = 0;
if (cfread_short(file->stream) != MVE_HDRCONST1)
mve_valid = 0;
if (cfread_short(file->stream) != MVE_HDRCONST2)
mve_valid = 0;
if (cfread_short(file->stream) != MVE_HDRCONST3)
mve_valid = 0;
if (!mve_valid) {
mvefile_close(file);
return NULL;
}
// now, prefetch the next chunk
mvefile_fetch_next_chunk(file);
return file;
}
// close a MVE file
void mvefile_close(MVEFILE *file)
{
// free the stream
if (file->stream)
cfclose(file->stream);
file->stream = NULL;
// free the buffer
if (file->cur_chunk)
vm_free(file->cur_chunk);
file->cur_chunk = NULL;
// not strictly necessary
file->buf_size = 0;
file->cur_fill = 0;
file->next_segment = 0;
// free the struct
vm_free(file);
}
// get the size of the next segment
int mvefile_get_next_segment_size(MVEFILE *file)
{
// if nothing is cached, fail
if (file->cur_chunk == NULL || file->next_segment >= file->cur_fill)
return -1;
// if we don't have enough data to get a segment, fail
if (file->cur_fill - file->next_segment < 4)
return -1;
// otherwise, get the data length
return mve_get_short(file->cur_chunk + file->next_segment);
}
// get type of next segment in chunk (0xff if no more segments in chunk)
ubyte mvefile_get_next_segment_major(MVEFILE *file)
{
// if nothing is cached, fail
if (file->cur_chunk == NULL || file->next_segment >= file->cur_fill)
return 0xff;
// if we don't have enough data to get a segment, fail
if (file->cur_fill - file->next_segment < 4)
return 0xff;
// otherwise, get the data length
return file->cur_chunk[file->next_segment + 2];
}
// get subtype (version) of next segment in chunk (0xff if no more segments in chunk)
ubyte mvefile_get_next_segment_minor(MVEFILE *file)
{
// if nothing is cached, fail
if (file->cur_chunk == NULL || file->next_segment >= file->cur_fill)
return 0xff;
// if we don't have enough data to get a segment, fail
if (file->cur_fill - file->next_segment < 4)
return 0xff;
// otherwise, get the data length
return file->cur_chunk[file->next_segment + 3];
}
// see next segment (return NULL if no next segment)
ubyte *mvefile_get_next_segment(MVEFILE *file)
{
// if nothing is cached, fail
if (file->cur_chunk == NULL || file->next_segment >= file->cur_fill)
return NULL;
// if we don't have enough data to get a segment, fail
if (file->cur_fill - file->next_segment < 4)
return NULL;
// otherwise, get the data length
return file->cur_chunk + file->next_segment + 4;
}
// advance to next segment
void mvefile_advance_segment(MVEFILE *file)
{
// if nothing is cached, fail
if (file->cur_chunk == NULL || file->next_segment >= file->cur_fill)
return;
// if we don't have enough data to get a segment, fail
if (file->cur_fill - file->next_segment < 4)
return;
// else, advance to next segment
file->next_segment += (4 + mve_get_ushort(file->cur_chunk + file->next_segment));
}
// fetch the next chunk (return 0 if at end of stream)
int mvefile_fetch_next_chunk(MVEFILE *file)
{
ubyte buffer[4];
ubyte *new_buffer;
ushort length;
// fail if not open
if (file->stream == NULL)
return 0;
// fail if we can't read the next segment descriptor
if (cfread(buffer, 1, 4, file->stream) < 4)
return 0;
// pull out the next length
length = mve_get_short(buffer);
// setup a new buffer if needed --
// only allocate new buffer is old one is too small
if (length > file->buf_size) {
// allocate new buffer
new_buffer = (ubyte *)vm_malloc(100 + length);
// copy old data
if (file->cur_chunk && file->cur_fill)
memcpy(new_buffer, file->cur_chunk, file->cur_fill);
// free old buffer
if (file->cur_chunk) {
vm_free(file->cur_chunk);
file->cur_chunk = NULL;
}
// install new buffer
file->cur_chunk = new_buffer;
file->buf_size = 100 + length;
}
// read the chunk
if (length > 0) {
if (cfread(file->cur_chunk, 1, length, file->stream) < length)
return 0;
}
file->cur_fill = length;
file->next_segment = 0;
return 1;
}
// -----------------------------------------------------------
// public MVESTREAM functions
// -----------------------------------------------------------
// open an MVE stream
MVESTREAM *mve_open(char *filename)
{
MVESTREAM *stream;
// allocate
stream = (MVESTREAM *)vm_malloc(sizeof(MVESTREAM));
// defaults
stream->movie = NULL;
// open
stream->movie = mvefile_open(filename);
if (stream->movie == NULL) {
mve_close(stream);
return NULL;
}
return stream;
}
// close an MVE stream
void mve_close(MVESTREAM *stream)
{
// close MVEFILE
if (stream->movie)
mvefile_close(stream->movie);
stream->movie = NULL;
vm_free(stream);
}
// play next chunk
int mve_play_next_chunk(MVESTREAM *stream)
{
ubyte major, minor;
ubyte *data;
int len;
// loop over segments
major = mvefile_get_next_segment_major(stream->movie);
while (major != 0xff) {
// check whether to handle the segment
if (major < 32) {
minor = mvefile_get_next_segment_minor(stream->movie);
len = mvefile_get_next_segment_size(stream->movie);
data = mvefile_get_next_segment(stream->movie);
switch (major) {
case 0x00:
mve_end_movie();
break;
case 0x01:
mve_end_chunk();
break;
case 0x02:
mve_timer_create(data);
break;
case 0x03:
mve_audio_createbuf(minor, data);
break;
case 0x04:
mve_audio_play();
break;
case 0x05:
if (!mve_video_createbuf(minor, data))
return 0;
break;
case 0x07:
mve_video_display();
break;
case 0x08:
mve_audio_data(major, data);
break;
case 0x09:
mve_audio_data(major, data);
break;
case 0x0a:
if (!mve_video_init(data))
return 0;
break;
case 0x0c:
mve_video_palette(data);
break;
case 0x0f:
mve_video_codemap(data, len);
break;
case 0x11:
mve_video_data(data, len);
break;
default:
break;
}
}
// advance to next segment
mvefile_advance_segment(stream->movie);
major = mvefile_get_next_segment_major(stream->movie);
}
if (!mvefile_fetch_next_chunk(stream->movie))
return 0;
// return status
return 1;
}
-89
View File
@@ -1,89 +0,0 @@
#ifndef INCLUDED_MVELIB_H
#define INCLUDED_MVELIB_H
#include "globalincs/pstypes.h"
struct CFILE;
// structure for maintaining info on a MVEFILE stream
typedef struct MVEFILE
{
CFILE *stream;
ubyte *cur_chunk;
int buf_size;
int cur_fill;
int next_segment;
} MVEFILE;
// open a .MVE file
MVEFILE *mvefile_open(char *filename);
// close a .MVE file
void mvefile_close(MVEFILE *movie);
// get size of next segment in chunk (-1 if no more segments in chunk)
int mvefile_get_next_segment_size(MVEFILE *movie);
// get type of next segment in chunk (0xff if no more segments in chunk)
ubyte mvefile_get_next_segment_major(MVEFILE *movie);
// get subtype (version) of next segment in chunk (0xff if no more segments in chunk)
ubyte mvefile_get_next_segment_minor(MVEFILE *movie);
// see next segment (return NULL if no next segment)
ubyte *mvefile_get_next_segment(MVEFILE *movie);
// advance to next segment
void mvefile_advance_segment(MVEFILE *movie);
// fetch the next chunk (return 0 if at end of stream)
int mvefile_fetch_next_chunk(MVEFILE *movie);
// structure for maintaining an MVE stream
typedef struct MVESTREAM
{
MVEFILE *movie;
} MVESTREAM;
// open an MVE stream
MVESTREAM *mve_open(char *filename);
// close an MVE stream
void mve_close(MVESTREAM *movie);
// play next chunk
int mve_play_next_chunk(MVESTREAM *movie);
// basic movie playing functions
void mve_init(MVESTREAM *mve);
void mve_play(MVESTREAM *mve);
void mve_shutdown();
// utility functions
short mve_get_short(ubyte *data);
ushort mve_get_ushort(ubyte *data);
int mve_get_int(ubyte *data);
// callbacks for data handling
// audio
void mve_audio_createbuf(ubyte minor, ubyte *data);
int mve_audio_data(ubyte major, ubyte *data);
void mve_audio_play();
// video
int mve_video_createbuf(ubyte minor, ubyte *data);
int mve_video_init(ubyte *data);
void mve_video_palette(ubyte *data);
void mve_video_data(ubyte *data, int len);
void mve_video_codemap(ubyte *data, int len);
void mve_video_display();
// misc
void mve_end_movie();
void mve_end_chunk();
int mve_timer_create(ubyte *data);
typedef short mves;
#endif /* INCLUDED_MVELIB_H */
-803
View File
@@ -1,803 +0,0 @@
#ifdef SCP_UNIX
#include <errno.h>
#include <time.h>
#include <sys/time.h>
#endif
#include "bmpman/bmpman.h"
#include "cutscene/movie.h"
#include "cutscene/mvelib.h"
#include "globalincs/pstypes.h"
#include "graphics/2d.h"
#include "graphics/gropengl.h"
#include "graphics/gropengldraw.h"
#include "graphics/gropenglstate.h"
#include "graphics/gropenglshader.h"
#include "graphics/gropengltexture.h"
#include "io/key.h"
#include "io/timer.h"
#include "osapi/osapi.h"
#include "sound/openal.h"
#include "sound/sound.h"
extern int Cmdline_noscalevid;
static int mve_playing;
// timer variables
static int micro_frame_delay = 0;
static int timer_started = 0;
#ifdef SCP_UNIX
static struct timeval timer_expire = { 0, 0 };
#else
static int timer_expire;
#endif
// audio variables
#define MVE_AUDIO_BUFFERS 64 // total buffers to interact with stream
static int mve_audio_buffer_tail = 0;
static int mve_audio_playing = 0;
static int mve_audio_canplay = 0;
static int mve_audio_compressed = 0;
static int audiobuf_created;
// struct for the audio stream information
typedef struct MVE_AUDIO_T {
ALenum format;
int sample_rate;
int bytes_per_sec;
int channels;
int bitsize;
ALuint source_id;
ALuint audio_buffer[MVE_AUDIO_BUFFERS];
} mve_audio_t;
mve_audio_t *mas; // mve_audio_stream
// audio decompressor
extern void mveaudio_uncompress(short *buffer, unsigned char *data);
// video variables
int g_width, g_height;
void *g_vBuffers = NULL;
void *g_vBackBuf1, *g_vBackBuf2;
ushort *pixelbuf = NULL;
static GLuint GLtex = 0;
static GLfloat gl_screenYH = 0;
static GLfloat gl_screenXW = 0;
static GLfloat glVertices[4][4] = {{0}};
static int g_screenWidth, g_screenHeight;
static float g_screenX, g_screenY;
static int g_truecolor = 0;
static ubyte g_palette[768];
static ubyte *g_pCurMap = NULL;
static int g_nMapLength = 0;
static int videobuf_created, video_inited;
static uint mve_video_skiptimer = 0;
static int mve_scale_video = 0;
// video externs from API graphics functions
extern GLenum GL_previous_texture_target;
// the decoders
extern void decodeFrame16(ubyte *pFrame, ubyte *pMap, int mapRemain, ubyte *pData, int dataRemain);
extern void decodeFrame8(ubyte *pFrame, ubyte *pMap, int mapRemain, ubyte *pData, int dataRemain);
/*************************
* general handlers
*************************/
void mve_end_movie()
{
mve_playing = 0;
}
/*************************
* timer handlers
*************************/
int mve_timer_create(ubyte *data)
{
int rate = mve_get_int(data);
int subd = mve_get_short(data+4);
micro_frame_delay = rate * subd;
return 1;
}
static void mve_timer_start(void)
{
#ifdef SCP_UNIX
int nsec = 0;
gettimeofday(&timer_expire, NULL);
timer_expire.tv_usec += micro_frame_delay;
if (timer_expire.tv_usec > 1000000) {
nsec = timer_expire.tv_usec / 1000000;
timer_expire.tv_sec += nsec;
timer_expire.tv_usec -= nsec * 1000000;
}
#else
timer_expire = timer_get_microseconds();
timer_expire += micro_frame_delay;
#endif
timer_started = 1;
}
static int mve_do_timer_wait(void)
{
if (!timer_started) {
return 0;
}
#ifdef SCP_UNIX
int nsec = 0;
struct timespec ts, tsRem;
struct timeval tv;
gettimeofday(&tv, NULL);
if (tv.tv_sec > timer_expire.tv_sec) {
goto end;
}
if ( (tv.tv_sec == timer_expire.tv_sec) && (tv.tv_usec >= timer_expire.tv_usec) ) {
goto end;
}
ts.tv_sec = timer_expire.tv_sec - tv.tv_sec;
ts.tv_nsec = 1000 * (timer_expire.tv_usec - tv.tv_usec);
if (ts.tv_nsec < 0) {
ts.tv_nsec += 1000000000UL;
--ts.tv_sec;
}
if ( (nanosleep(&ts, &tsRem) == -1) && (errno == EINTR) ) {
// so we got an error that was a signal interupt, try to sleep again with remainder of time
if ( (nanosleep(&tsRem, NULL) == -1) && (errno == EINTR) ) {
mprintf(("MVE: Timer error! Aborting movie playback!\n"));
return 1;
}
}
end:
timer_expire.tv_usec += micro_frame_delay;
if (timer_expire.tv_usec > 1000000) {
nsec = timer_expire.tv_usec / 1000000;
timer_expire.tv_sec += nsec;
timer_expire.tv_usec -= nsec * 1000000;
}
#else
int tv, ts, ts2;
tv = timer_get_microseconds();
if (tv > timer_expire) {
goto end;
}
ts = timer_expire - tv;
ts2 = ts/1000;
Sleep(ts2);
end:
timer_expire += micro_frame_delay;
#endif
return 0;
}
static void mve_timer_stop()
{
#ifdef SCP_UNIX
timer_expire.tv_sec = 0;
timer_expire.tv_usec = 0;
#else
timer_expire = 0;
#endif
timer_started = 0;
}
/*************************
* audio handlers
*************************/
// setup the audio information from the data stream
void mve_audio_createbuf(ubyte minor, ubyte *data)
{
if (audiobuf_created) {
return;
}
// if game sound disabled don't try and play movie audio
if (!Sound_enabled) {
mve_audio_canplay = 0;
return;
}
int flags, sample_rate;
mas = (mve_audio_t *) vm_malloc ( sizeof(mve_audio_t) );
memset(mas, 0, sizeof(mve_audio_t));
mas->format = AL_INVALID;
flags = mve_get_ushort(data + 2);
sample_rate = mve_get_ushort(data + 4);
mas->channels = (flags & 0x0001) ? 2 : 1;
mas->bitsize = (flags & 0x0002) ? 16 : 8;
mas->sample_rate = sample_rate;
if (minor > 0) {
mve_audio_compressed = flags & 0x0004 ? 1 : 0;
} else {
mve_audio_compressed = 0;
}
if (mas->bitsize == 16) {
if (mas->channels == 2) {
mas->format = AL_FORMAT_STEREO16;
} else if (mas->channels == 1) {
mas->format = AL_FORMAT_MONO16;
}
} else if (mas->bitsize == 8) {
if (mas->channels == 2) {
mas->format = AL_FORMAT_STEREO8;
} else if (mas->channels == 1) {
mas->format = AL_FORMAT_MONO8;
}
}
// somethings wrong, bail now
if (mas->format == AL_INVALID) {
mve_audio_canplay = 0;
audiobuf_created = 1;
return;
}
OpenAL_ErrorCheck( alGenSources(1, &mas->source_id), { mve_audio_canplay = 0; return; } );
mve_audio_canplay = 1;
OpenAL_ErrorPrint( alSourcef(mas->source_id, AL_GAIN, 1.0f) );
memset(mas->audio_buffer, 0, MVE_AUDIO_BUFFERS * sizeof(ALuint));
mve_audio_buffer_tail = 0;
audiobuf_created = 1;
}
// play and stream the audio
void mve_audio_play()
{
if (mve_audio_canplay) {
ALint status, bqueued;
OpenAL_ErrorCheck( alGetSourcei(mas->source_id, AL_SOURCE_STATE, &status), return );
OpenAL_ErrorCheck( alGetSourcei(mas->source_id, AL_BUFFERS_QUEUED, &bqueued), return );
mve_audio_playing = 1;
if (status != AL_PLAYING && bqueued > 0) {
OpenAL_ErrorPrint( alSourcePlay(mas->source_id) );
}
}
}
// call this in shutdown to stop and close audio
static void mve_audio_stop()
{
if (!audiobuf_created || mas == NULL) {
return;
}
ALint p = 0;
mve_audio_playing = 0;
OpenAL_ErrorPrint( alSourceStop(mas->source_id) );
OpenAL_ErrorPrint( alGetSourcei(mas->source_id, AL_BUFFERS_PROCESSED, &p) );
OpenAL_ErrorPrint( alSourceUnqueueBuffers(mas->source_id, p, mas->audio_buffer) );
OpenAL_ErrorPrint( alDeleteSources(1, &mas->source_id) );
for (int i = 0; i < MVE_AUDIO_BUFFERS; i++) {
// make sure that the buffer is real before trying to delete, it could crash for some otherwise
if ( (mas->audio_buffer[i] != 0) && alIsBuffer(mas->audio_buffer[i]) ) {
OpenAL_ErrorPrint( alDeleteBuffers(1, &mas->audio_buffer[i]) );
}
}
if (mas != NULL) {
vm_free(mas);
mas = NULL;
}
}
int mve_audio_data(ubyte major, ubyte *data)
{
static const int selected_chan=1;
int chan;
int nsamp;
if (mve_audio_canplay) {
chan = mve_get_ushort(data + 2);
nsamp = mve_get_ushort(data + 4);
if (chan & selected_chan) {
ALint bprocessed, bqueued, status;
ALuint bid;
OpenAL_ErrorCheck( alGetSourcei(mas->source_id, AL_BUFFERS_PROCESSED, &bprocessed), return 0 );
while (bprocessed-- > 2) {
OpenAL_ErrorPrint( alSourceUnqueueBuffers(mas->source_id, 1, &bid) );
}
OpenAL_ErrorCheck( alGetSourcei(mas->source_id, AL_BUFFERS_QUEUED, &bqueued), return 0 );
if (bqueued == 0) {
mprintf(("MVE: Buffer underun (First is normal)\n"));
}
OpenAL_ErrorCheck( alGetSourcei(mas->source_id, AL_SOURCE_STATE, &status), return 0 );
if ( (mve_audio_playing) && (status != AL_PLAYING) && (bqueued > 0) ) {
OpenAL_ErrorCheck( alSourcePlay(mas->source_id), return 0 );
}
if (bqueued < MVE_AUDIO_BUFFERS) {
short *buf = NULL;
/* HACK: +4 mveaudio_uncompress adds 4 more bytes */
if (major == 8) {
if (mve_audio_compressed) {
nsamp += 4;
buf = (short *)vm_malloc(nsamp);
mveaudio_uncompress(buf, data); /* XXX */
} else {
nsamp -= 8;
data += 8;
buf = (short *)vm_malloc(nsamp);
memcpy(buf, data, nsamp);
}
} else {
buf = (short *)vm_malloc(nsamp);
memset(buf, 0, nsamp); /* XXX */
}
if (!mas->audio_buffer[mve_audio_buffer_tail]) {
OpenAL_ErrorCheck( alGenBuffers(1,&mas->audio_buffer[mve_audio_buffer_tail]), { vm_free(buf); return 0; } );
}
OpenAL_ErrorCheck( alBufferData(mas->audio_buffer[mve_audio_buffer_tail], mas->format, buf, nsamp, mas->sample_rate), { vm_free(buf); return 0; } );
OpenAL_ErrorCheck( alSourceQueueBuffers(mas->source_id, 1, &mas->audio_buffer[mve_audio_buffer_tail]), { vm_free(buf); return 0;} );
//fprintf(stderr,"Queued buffer %d(%d)\n", mve_audio_buftail, mas->audio_buffer[mve_audio_buftail]);
if (++mve_audio_buffer_tail == MVE_AUDIO_BUFFERS) {
mve_audio_buffer_tail = 0;
}
bqueued++;
vm_free(buf);
} else {
mprintf(("MVE: Buffer overrun: Queue full\n"));
}
}
}
return 1;
}
/*************************
* video handlers
*************************/
int mve_video_createbuf(ubyte minor, ubyte *data)
{
if (videobuf_created) {
return 1;
}
short w, h;
short truecolor;
w = mve_get_short(data);
h = mve_get_short(data+2);
if (minor > 1) {
truecolor = mve_get_short(data+6);
} else {
truecolor = 0;
}
g_width = w << 3;
g_height = h << 3;
g_vBackBuf1 = g_vBuffers = vm_malloc(g_width * g_height * 4);
if (g_vBackBuf1 == NULL) {
nprintf(("MOVIE", "ERROR: Can't allocate video buffer"));
videobuf_created = 1;
return 0;
}
if (truecolor) {
g_vBackBuf2 = (ushort *)g_vBackBuf1 + (g_width * g_height);
} else {
g_vBackBuf2 = (ubyte *)g_vBackBuf1 + (g_width * g_height);
}
memset(g_vBackBuf1, 0, g_width * g_height * 4);
g_truecolor = truecolor;
videobuf_created = 1;
if (gr_screen.mode == GR_OPENGL) {
GLfloat scale_by = 1.0f;
float screen_ratio = (float)gr_screen.center_w / (float)gr_screen.center_h;
float movie_ratio = (float)g_width / (float)g_height;
if (screen_ratio > movie_ratio) {
scale_by = (float)gr_screen.center_h / (float)g_height;
} else {
scale_by = (float)gr_screen.center_w / (float)g_width;
}
// don't bother setting anything if we aren't going to need it
if (!Cmdline_noscalevid && (scale_by != 1.0f)) {
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glScalef( scale_by, scale_by, 1.0f );
mve_scale_video = 1;
}
if (mve_scale_video) {
g_screenX = ((ceil((gr_screen.center_w / scale_by) - 0.5f) - g_width) / 2) + ceil((gr_screen.center_offset_x / scale_by) - 0.5f);
g_screenY = ((ceil((gr_screen.center_h / scale_by) - 0.5f) - g_height) / 2) + ceil((gr_screen.center_offset_y / scale_by) - 0.5f);
} else {
// centers on 1024x768, fills on 640x480
g_screenX = ((float)(gr_screen.center_w - g_width) / 2.0f) + gr_screen.center_offset_x;
g_screenY = ((float)(gr_screen.center_h - g_height) / 2.0f) + gr_screen.center_offset_y;
}
// set additional values for screen width/height and UV coords
if (gr_screen.mode == GR_OPENGL) {
gl_screenYH = g_screenY + g_height;
gl_screenXW = g_screenX + g_width;
}
glVertices[0][0] = g_screenX;
glVertices[0][1] = g_screenY;
glVertices[0][2] = 0;
glVertices[0][3] = 0;
glVertices[1][0] = g_screenX;
glVertices[1][1] = gl_screenYH;
glVertices[1][2] = 0;
glVertices[1][3] = 1.f;
glVertices[2][0] = gl_screenXW;
glVertices[2][1] = g_screenY;
glVertices[2][2] = 1.f;
glVertices[2][3] = 0;
glVertices[3][0] = gl_screenXW;
glVertices[3][1] = gl_screenYH;
glVertices[3][2] = 1.f;
glVertices[3][3] = 1.f;
GL_state.Array.BindArrayBuffer(0);
vertex_layout vertex_def;
vertex_def.add_vertex_component(vertex_format_data::POSITION2, sizeof(glVertices[0]), glVertices);
vertex_def.add_vertex_component(vertex_format_data::TEX_COORD, sizeof(glVertices[0]), &(glVertices[0][2]));
opengl_bind_vertex_layout(vertex_def);
}
return 1;
}
static void mve_convert_and_draw()
{
ushort *pDests;
ushort *pSrcs = NULL;
ushort *pixels = (ushort *)g_vBackBuf1;
int x, y;
ubyte *pSrcs8 = NULL;
ubyte *pixels8 = (ubyte *)g_vBackBuf1;
ubyte r, g, b;
ushort bit_16;
if (g_truecolor) {
pSrcs = pixels;
} else {
pSrcs8 = pixels8;
}
pDests = pixelbuf;
if (gr_screen.mode != GR_OPENGL) {
if (g_screenWidth > g_width) {
pDests += ((g_screenWidth - g_width) / 2) / 2;
}
if (g_screenHeight > g_height) {
pDests += ((g_screenHeight - g_height) / 2) * g_screenWidth;
}
}
for (y=0; y<g_height; y++) {
for (x = 0; x < g_width; x++) {
if (g_truecolor) {
Assert( pSrcs != NULL );
pDests[x] = (1<<15)|*pSrcs;
pSrcs++;
} else {
Assert( pSrcs8 != NULL );
// grab rgb color
r = (g_palette[(*pSrcs8)*3] / 2);
g = (g_palette[(*pSrcs8)*3 + 1] / 2);
b = (g_palette[(*pSrcs8)*3 + 2] / 2);
// stuff the color
bit_16 = (ushort)(r << Gr_t_red.shift);
bit_16 |= (ushort)(g << Gr_t_green.shift);
bit_16 |= (ushort)(b << Gr_t_blue.shift);
bit_16 |= (ushort)(Gr_t_alpha.mask);
// stuff the pixel
pDests[x] = (1<<15)|bit_16;
pSrcs8++;
}
}
pDests += g_screenWidth;
}
}
void mve_video_display()
{
fix t1 = timer_get_fixed_seconds();
mve_convert_and_draw();
// this thing is basically stupid but I don't care
// micro_frame_delay is divided by 10 to match mve_video_skiptimer overflow catch
if ( mve_video_skiptimer > (uint)(micro_frame_delay/10) ) {
// we are running slow so subtract desired time from actual and skip this frame
mve_video_skiptimer -= (micro_frame_delay/10);
return;
} else {
// zero out so we can get a new count
mve_video_skiptimer = 0;
}
if (gr_screen.mode == GR_OPENGL) {
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexSubImage2D(GL_state.Texture.GetTarget(), 0, 0, 0, g_width, g_height, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, pixelbuf);
opengl_shader_set_passthrough(true);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
} else {
// DDOI - This is probably really fricking slow
int bitmap = bm_create (16, g_screenWidth, g_screenHeight, pixelbuf, 0);
gr_set_bitmap (bitmap);
gr_bitmap ((int)g_screenX, (int)g_screenY, GR_RESIZE_FULL);
bm_release (bitmap);
}
gr_flip();
os_poll();
fix t2 = timer_get_fixed_seconds();
// only get a new count if we are definitely through with old count
if ( mve_video_skiptimer == 0 ) {
// for a more accurate count convert the frame rate to a float and multiply
// by one-hundred-thousand before converting to an uint.
mve_video_skiptimer = (uint)(f2fl(t2-t1) * 100000);
}
int k = key_inkey();
switch (k) {
case KEY_ESC:
case KEY_ENTER:
case KEY_SPACEBAR:
mve_playing = 0;
}
//mprintf(("mve frame took this long: %.6f\n", f2fl(t2-t1) / 1000.0f));
}
int mve_video_init(ubyte *data)
{
if (video_inited) {
return 1;
}
short width, height;
width = mve_get_short(data);
height = mve_get_short(data+2);
g_screenWidth = width;
g_screenHeight = height;
// DDOI - Allocate RGB565 pixel buffer
pixelbuf = (ushort *)vm_malloc(g_screenWidth * g_screenHeight * 2);
if (pixelbuf == NULL) {
nprintf(("MOVIE", "ERROR: Can't allocate memory for pixelbuf"));
video_inited = 1;
return 0;
}
memset(pixelbuf, 0, g_screenWidth * g_screenHeight * 2);
if (gr_screen.mode == GR_OPENGL) {
opengl_set_texture_target(GL_TEXTURE_2D);
glGenTextures(1, &GLtex);
Assert( GLtex != 0 );
if ( GLtex == 0 ) {
nprintf(("MOVIE", "ERROR: Can't create a GL texture"));
video_inited = 1;
return 0;
}
gr_set_lighting(false, false);
GL_state.Texture.DisableAll();
GL_state.Texture.SetActiveUnit(0);
GL_state.Texture.SetTarget(GL_texture_target);
GL_state.Texture.Enable(GLtex);
GL_state.SetTextureSource(TEXTURE_SOURCE_DECAL);
GL_state.SetAlphaBlendMode(ALPHA_BLEND_NONE);
GL_state.SetZbufferType(ZBUFFER_TYPE_NONE);
glTexParameteri(GL_texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// NOTE: using NULL instead of pixelbuf crashes some drivers, but then so does pixelbuf
glTexImage2D(GL_state.Texture.GetTarget(), 0, GL_RGB5_A1, g_screenWidth, g_screenHeight, 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, NULL);
// set our color so that we can make sure that it's correct
GL_state.Color(255, 255, 255, 255);
}
memset(g_palette, 0, 768);
video_inited = 1;
return 1;
}
void mve_video_palette(ubyte *data)
{
short start, count;
start = mve_get_short(data);
count = mve_get_short(data+2);
memcpy(g_palette + 3*start, data+4, 3*count);
}
void mve_video_codemap(ubyte *data, int len)
{
g_pCurMap = data;
g_nMapLength = len;
}
void mve_video_data(ubyte *data, int len)
{
ushort nFlags;
ubyte *temp;
nFlags = mve_get_ushort(data+12);
if (nFlags & 1) {
temp = (ubyte *)g_vBackBuf1;
g_vBackBuf1 = g_vBackBuf2;
g_vBackBuf2 = temp;
}
if (g_truecolor) {
decodeFrame16((ubyte *)g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14);
} else {
decodeFrame8((ubyte *)g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14);
}
}
void mve_end_chunk()
{
g_pCurMap = NULL;
}
void mve_init(MVESTREAM *mve)
{
// reset to default values
mve_audio_buffer_tail = 0;
mve_audio_playing = 0;
mve_audio_canplay = 0;
mve_audio_compressed = 0;
audiobuf_created = 0;
videobuf_created = 0;
video_inited = 0;
mve_scale_video = 0;
mve_playing = 1;
}
void mve_play(MVESTREAM *mve)
{
int init_timer = 0, timer_error = 0;
int cont = 1;
if (!timer_started) {
mve_timer_start();
}
while (cont && mve_playing && !timer_error) {
cont = mve_play_next_chunk(mve);
if (micro_frame_delay && !init_timer) {
mve_timer_start();
init_timer = 1;
}
timer_error = mve_do_timer_wait();
}
}
void mve_shutdown()
{
if (gr_screen.mode == GR_OPENGL) {
if (mve_scale_video) {
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
GL_state.Texture.Disable();
GL_state.Texture.Delete(GLtex);
glDeleteTextures(1, &GLtex);
GLtex = 0;
}
if (pixelbuf != NULL) {
vm_free(pixelbuf);
pixelbuf = NULL;
}
if (g_vBuffers != NULL) {
vm_free(g_vBuffers);
g_vBuffers = NULL;
}
mve_audio_stop();
mve_timer_stop();
}
File diff suppressed because it is too large. Load diff
-40
View File
@@ -1,40 +0,0 @@
#ifndef _OGGPLAYER_H
#define _OGGPLAYER_H
#include "globalincs/pstypes.h"
#include "theora/theora.h"
#include "vorbis/codec.h"
struct CFILE;
// structure for maintaining info on a THEORAFILE stream
typedef struct THEORAFILE
{
CFILE *cfp;
ubyte theora_p;
ubyte vorbis_p;
ogg_sync_state osyncstate;
ogg_page opage;
ogg_packet opacket;
ogg_stream_state v_osstate;
ogg_stream_state t_osstate;
theora_info tinfo;
theora_comment tcomment;
theora_state tstate;
vorbis_info vinfo;
vorbis_dsp_state vstate;
vorbis_block vblock;
vorbis_comment vcomment;
} THEORAFILE;
void theora_play(THEORAFILE *movie);
THEORAFILE *theora_open(char *filename);
void theora_close(THEORAFILE *movie);
#endif
+469
View File
@@ -0,0 +1,469 @@
#include "cutscene/player.h"
#include "cutscene/Decoder.h"
#include "cutscene/player/VideoPresenter.h"
#include "cutscene/ffmpeg/FFMPEGDecoder.h"
#include "graphics/2d.h"
#include "globalincs/alphacolors.h"
#include "osapi/osapi.h"
#include "sound/openal.h"
#include "tracing/tracing.h"
#include "io/key.h"
#include "io/timer.h"
#include "parse/parselo.h"
#include "cutscene/player/OpenGLVideoPresenter.h"
using namespace cutscene::player;
namespace cutscene {
struct PlayerState {
MovieProperties props;
Decoder* decoder = nullptr;
bool playing = true;
bool playbackHasBegun = false;
// Timing state
std::uint64_t playback_time = 0;
// Audio state
bool audioInited = false;
bool hasAudio = false;
ALuint audioSid = 0;
SCP_vector<ALuint> audioBuffers;
SCP_queue<ALuint> unqueuedAudioBuffers;
// Graphics state following
bool videoInited = false;
VideoFramePtr currentFrame;
VideoFramePtr nextFrame;
bool newFrameAdded = false;
std::unique_ptr<VideoPresenter> videoPresenter;
PlayerState() : decoder(nullptr), playing(true), playbackHasBegun(false),
playback_time(0),
audioInited(0), hasAudio(false), audioSid(0),
videoInited(false), newFrameAdded(false) {}
private:
PlayerState(const PlayerState&) SCP_DELETED_FUNCTION;
PlayerState& operator=(const PlayerState&) SCP_DELETED_FUNCTION;
};
}
namespace {
using namespace cutscene;
const int MAX_AUDIO_BUFFERS = 15;
Decoder* findDecoder(const SCP_string& name) {
{
auto ffmpeg = new ffmpeg::FFMPEGDecoder();
if (ffmpeg->initialize(name)) {
return ffmpeg;
}
delete ffmpeg;
}
return nullptr;
}
// get relative time since beginning playback, compensating for A/V drift
double playbackGetTime(PlayerState* state) {
return state->playback_time * 0.000001;
}
void videoPlaybackInit(PlayerState* state) {
if (state->videoInited) {
return;
}
Assert(state != NULL);
if (gr_screen.mode == GR_OPENGL) {
state->videoPresenter.reset(new OpenGLVideoPresenter(state->props));
}
state->videoInited = true;
}
void audioPlaybackInit(PlayerState* state) {
if (state->audioInited) {
return;
}
if (!state->decoder->hasAudio() || Cmdline_freespace_no_sound) {
state->hasAudio = false;
return;
}
state->hasAudio = true;
OpenAL_ErrorCheck(alGenSources(1, &state->audioSid), return);
OpenAL_ErrorPrint(alSourcef(state->audioSid, AL_GAIN, 1.0f));
state->audioBuffers.clear();
state->audioBuffers.resize(MAX_AUDIO_BUFFERS, 0);
OpenAL_ErrorCheck(alGenBuffers(static_cast<ALsizei>(state->audioBuffers.size()), state->audioBuffers.data()),
return);
for (auto buffer : state->audioBuffers) {
state->unqueuedAudioBuffers.push(buffer);
}
state->audioInited = true;
}
void processVideoData(PlayerState* state) {
TRACE_SCOPE(tracing::CutsceneProcessVideoData);
state->newFrameAdded = false;
if (!state->decoder->isVideoFrameAvailable()) {
// Nothing to do here...
return;
}
if (state->currentFrame == nullptr && state->nextFrame == nullptr) {
// Load the initial frame
VideoFramePtr firstFrame;
auto r = state->decoder->tryPopVideoFrame(firstFrame);
// This shouldn't happen...
Assertion(r, "Failed to pop frame!");
// At this point the new frame is the next frame
state->nextFrame = std::move(firstFrame);
}
if (!state->nextFrame) {
// No next frame, try getting a new one
if (!state->decoder->tryPopVideoFrame(state->nextFrame)) {
// No new frame available :(
return;
}
}
auto currentTime = playbackGetTime(state);
if (currentTime < state->nextFrame->frameTime) {
// Old frame is still valid, nothing to do here
return;
}
while(currentTime >= state->nextFrame->frameTime) {
// Move the next frame to the current frame slot
state->currentFrame = std::move(state->nextFrame);
// Get a new frame from the decoder
auto success = state->decoder->tryPopVideoFrame(state->nextFrame);
if (!success) {
// Make sure the pointer is actually empty
state->nextFrame = nullptr;
// No more frames available
break;
}
}
// Now upload the new frame
if (state->videoPresenter) {
state->videoPresenter->uploadVideoFrame(state->currentFrame);
state->newFrameAdded = true;
}
}
bool processAudioData(PlayerState* state) {
TRACE_SCOPE(tracing::CutsceneProcessAudioData);
if (!state->hasAudio) {
if (state->decoder->hasAudio()) {
// Even if we don't play the sound we still need to remove it from the queue
AudioFramePtr audioData;
while(state->decoder->tryPopAudioData(audioData)) {
// Intentionally left empty
}
}
return false;
}
ALint processed = 0;
OpenAL_ErrorCheck(alGetSourcei(state->audioSid, AL_BUFFERS_PROCESSED, &processed), return false);
// First check for free buffers and push them int the audio queue
for (int i = 0; i < processed; ++i) {
ALuint buffer;
OpenAL_ErrorPrint(alSourceUnqueueBuffers(state->audioSid, 1, &buffer));
state->unqueuedAudioBuffers.push(buffer);
}
AudioFramePtr audioData;
while (!state->unqueuedAudioBuffers.empty() && state->decoder->tryPopAudioData(audioData)) {
auto buffer = state->unqueuedAudioBuffers.front();
state->unqueuedAudioBuffers.pop();
ALenum format = (audioData->channels == 2) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16;
OpenAL_ErrorCheck(alBufferData(buffer, format, audioData->audioData.data(),
static_cast<ALsizei>(audioData->audioData.size() * sizeof(short)),
static_cast<ALsizei>(audioData->rate)), return false);
OpenAL_ErrorCheck(alSourceQueueBuffers(state->audioSid, 1, &buffer), return false);
}
ALint status = 0, queued = 0;
OpenAL_ErrorCheck(alGetSourcei(state->audioSid, AL_SOURCE_STATE, &status), return false);
OpenAL_ErrorCheck(alGetSourcei(state->audioSid, AL_BUFFERS_QUEUED, &queued), return false);
if ((status != AL_PLAYING) && (queued > 0)) {
OpenAL_ErrorPrint(alSourcePlay(state->audioSid));
}
// Get status again in cause we just started playback
OpenAL_ErrorCheck(alGetSourcei(state->audioSid, AL_SOURCE_STATE, &status), return false);
return status == AL_PLAYING;
}
void audioPlaybackClose(PlayerState* state) {
if (!state->audioInited) {
return;
}
ALint p = 0;
OpenAL_ErrorPrint(alSourceStop(state->audioSid));
OpenAL_ErrorPrint(alGetSourcei(state->audioSid, AL_BUFFERS_PROCESSED, &p));
OpenAL_ErrorPrint(alSourceUnqueueBuffers(state->audioSid, p, state->audioBuffers.data()));
OpenAL_ErrorPrint(alDeleteSources(1, &state->audioSid));
for (auto buffer : state->audioBuffers) {
// make sure that the buffer is real before trying to delete, it could crash for some otherwise
if ((buffer != 0) && alIsBuffer(buffer)) {
OpenAL_ErrorPrint(alDeleteBuffers(1, &buffer));
}
}
state->audioInited = false;
}
void videoPlaybackClose(PlayerState* state) {
if (!state->videoInited) {
return;
}
state->videoPresenter.reset();
state->videoInited = false;
}
template<typename... Args>
float print_string(float x, float y, const char* fmt, Args... params) {
SCP_string text;
sprintf(text, fmt, params...);
gr_string(x, y, text.c_str(), GR_RESIZE_NONE);
return y + font::get_current_font()->getHeight();
}
void showVideoInfo(PlayerState* state) {
gr_set_color_fast(&Color_white);
float y = 200.f;
float x = 100.f;
y = print_string(x, y, "Movie FPS: %f", state->props.fps);
y = print_string(x, y, "Size: %dx%d", state->props.size.width, state->props.size.height);
y = gr_screen.max_h - 200.f;
size_t audio_queue_size = state->decoder->getAudioQueueSize();
if (state->hasAudio) {
ALint queued;
OpenAL_ErrorPrint(alGetSourcei(state->audioSid, AL_BUFFERS_QUEUED, &queued));
audio_queue_size += queued;
}
y = print_string(x, y, "Audio Queue size: " SIZE_T_ARG, audio_queue_size);
y = print_string(x, y, "Video Queue size: " SIZE_T_ARG, state->decoder->getVideoQueueSize());
y += font::get_current_font()->getHeight();
// Estimate the size of the video buffer
// We use YUV420p frames so one pixel uses 1.5 bytes of storage
size_t single_frame_size = (size_t) (state->props.size.width * state->props.size.height * 1.5);
size_t total_size = single_frame_size * state->decoder->getVideoQueueSize();
print_string(x, y, "Video buffer size: " SIZE_T_ARG "B", total_size);
}
void displayVideo(PlayerState* state) {
if (!state->currentFrame) {
return;
}
TRACE_SCOPE(tracing::CutsceneDrawVideoFrame);
gr_clear();
if (state->videoPresenter) {
state->videoPresenter->displayFrame();
}
if (Cmdline_show_video_info) {
showVideoInfo(state);
}
gr_flip();
}
void processEvents(PlayerState* state) {
io::mouse::CursorManager::get()->showCursor(false);
os_poll();
int k = key_inkey();
switch (k) {
case KEY_ESC:
case KEY_ENTER:
case KEY_SPACEBAR:
state->playing = false;
break;
default:
break;
}
}
bool shouldBeginPlayback(Decoder* decoder) {
auto video = decoder->isVideoQueueFull();
auto audio = decoder->isAudioQueueFull();
// Wait until one of the queues is full, that should make sure
// that we have enough frames at the beginning of playback and that
// we don't wait indefinitely if the cutscene has a weird amount of audio
// or video at the beginning
// Also only wait while the decoder is still working. Otherwise we will wait indefinitely if the video
// is very short.
return (audio || video) || !decoder->isDecoding();
}
}
namespace cutscene {
Player::Player() {
}
Player::~Player() {
if (m_decoder) {
m_decoder->close();
}
}
void Player::processDecoderData(PlayerState* state) {
if (!state->playbackHasBegun) {
// Wait until video and audio are available
// If we don't have audio, don't wait for it (obviously...)
if (!shouldBeginPlayback(state->decoder)) {
return;
}
state->playbackHasBegun = true;
}
TRACE_SCOPE(tracing::CutsceneProcessDecoder);
processVideoData(state);
auto audioPlaying = processAudioData(state);
// Set the playing flag if the decoder is still active or there is still data available
auto decoding = m_decoder->isDecoding();
// Audio is pending if there is data left in the queue or of OpenAL is still playing audio
auto pendingAudio = (m_decoder->isAudioFrameAvailable() && m_decoder->hasAudio()) || audioPlaying;
auto pendingVideo = m_decoder->isVideoFrameAvailable();
state->playing = decoding || pendingAudio || pendingVideo;
}
void Player::startPlayback() {
m_decoderThread.reset(new std::thread(std::bind(&Player::decoderThread, this)));
PlayerState state;
state.props = m_decoder->getProperties();
state.decoder = m_decoder.get();
// Compute the maximum time we will sleep to make sure we can still maintain the movie FPS
// and not waste too much CPU time
// We will sleep at most half the time a frame would be displayed
auto sleepTime = static_cast<std::uint64_t>((1. / (4. * state.props.fps)) * 1000.);
videoPlaybackInit(&state);
audioPlaybackInit(&state);
auto lastDisplayTimestamp = timer_get_microseconds();
while (state.playing) {
TRACE_SCOPE(tracing::CutsceneStep);
processDecoderData(&state);
displayVideo(&state);
processEvents(&state);
auto timestamp = timer_get_microseconds();
auto passed = timestamp - lastDisplayTimestamp;
lastDisplayTimestamp = timestamp;
if (state.playbackHasBegun) {
state.playback_time += passed;
}
if (passed < sleepTime) {
auto sleep = sleepTime - passed;
os_sleep(static_cast<uint>(sleep));
}
}
m_decoder->stopDecoder();
audioPlaybackClose(&state);
videoPlaybackClose(&state);
m_decoderThread->join();
}
void Player::decoderThread() {
try {
m_decoder->startDecoding();
} catch (const std::exception& e) {
mprintf(("Video: An exception was thrown while decoding the video: %s\n", e.what()));
} catch (...) {
mprintf(("Video: An exception was thrown while decoding the video!\n"));
}
}
std::unique_ptr<Player> Player::newPlayer(const SCP_string& name) {
mprintf(("Creating player for movie '%s'.\n", name.c_str()));
auto decoder = findDecoder(name);
if (decoder == nullptr) {
return nullptr;
}
std::unique_ptr<Player> player(new Player());
player->m_decoder.reset(decoder);
return player;
}
}
+48
View File
@@ -0,0 +1,48 @@
#pragma once
#include <memory>
#include <thread>
#include "globalincs/pstypes.h"
namespace cutscene {
class Decoder;
struct PlayerState;
/**
* @brief A movie player
*/
class Player {
private:
std::unique_ptr<Decoder> m_decoder;
std::unique_ptr<std::thread> m_decoderThread;
void processDecoderData(PlayerState* state);
private:
Player(const Player&) = delete;
void decoderThread();
public:
Player();
~Player();
/**
* @brief Begin playing the previously selected movie
*/
void startPlayback();
/**
* @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);
};
}
@@ -0,0 +1,223 @@
#include "OpenGLVideoPresenter.h"
#include "graphics/opengl/gropenglstate.h"
#include "graphics/opengl/gropengltnl.h"
#include "graphics/opengl/gropengldraw.h"
using namespace cutscene;
using namespace cutscene::player;
namespace cutscene {
namespace player {
OpenGLVideoPresenter::OpenGLVideoPresenter(const MovieProperties& props) : _scaleVideo(false),
_ytex(0), _utex(0), _vtex(0) {
GR_DEBUG_SCOPE("Init video");
opengl_set_texture_target(GL_TEXTURE_2D);
_vertexBuffer = gr_create_vertex_buffer(true);
auto w = static_cast<int>(props.size.width);
auto h = static_cast<int>(props.size.height);
_sdr_handle = gr_maybe_create_shader(SDR_TYPE_VIDEO_PROCESS, 0);
glGenTextures(1, &_ytex);
glGenTextures(1, &_utex);
glGenTextures(1, &_vtex);
if (_ytex + _utex + _vtex == 0) {
throw std::runtime_error("Can't create a GL texture");
}
opengl_shader_set_current(_sdr_handle);
gr_set_lighting(false, false);
GL_state.SetAlphaBlendMode(ALPHA_BLEND_NONE);
GL_state.SetZbufferType(ZBUFFER_TYPE_NONE);
GL_state.Texture.SetActiveUnit(0);
GL_state.Texture.SetTarget(GL_texture_target);
GL_state.Texture.Enable(_ytex);
glTexParameteri(GL_texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// NOTE: using NULL instead of pixelbuf crashes some drivers, but then so does pixelbuf
glTexImage2D(GL_state.Texture.GetTarget(), 0, GL_RED, w, h, 0, GL_RED,
GL_UNSIGNED_BYTE, NULL);
GL_state.Texture.SetActiveUnit(1);
GL_state.Texture.SetTarget(GL_texture_target);
GL_state.Texture.Enable(_utex);
glTexParameteri(GL_texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// NOTE: using NULL instead of pixelbuf crashes some drivers, but then so does pixelbuf
glTexImage2D(GL_state.Texture.GetTarget(), 0, GL_RED, w / 2, h / 2, 0, GL_RED,
GL_UNSIGNED_BYTE, NULL);
GL_state.Texture.SetActiveUnit(2);
GL_state.Texture.SetTarget(GL_texture_target);
GL_state.Texture.Enable(_vtex);
glTexParameteri(GL_texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// NOTE: using NULL instead of pixelbuf crashes some drivers, but then so does pixelbuf
glTexImage2D(GL_state.Texture.GetTarget(), 0, GL_RED, w / 2, h / 2, 0, GL_RED,
GL_UNSIGNED_BYTE, NULL);
float screen_ratio = (float) gr_screen.center_w / (float) gr_screen.center_h;
float movie_ratio = (float) props.size.width / (float) props.size.height;
float scale_by;
if (screen_ratio > movie_ratio) {
scale_by = (float) gr_screen.center_h / (float) props.size.height;
} else {
scale_by = (float) gr_screen.center_w / (float) props.size.width;
}
// don't bother setting anything if we aren't going to need it
if (!Cmdline_noscalevid && (scale_by != 1.0f)) {
vec3d scale;
scale.xyz.x = scale_by;
scale.xyz.y = scale_by;
scale.xyz.z = -1.0f;
gr_push_scale_matrix(&scale);
_scaleVideo = true;
}
int screenX;
int screenY;
if (_scaleVideo) {
screenX = fl2i(((gr_screen.center_w / 2.0f + gr_screen.center_offset_x) / scale_by) - (static_cast<int>(props.size.width) / 2.0f) + 0.5f);
screenY = fl2i(((gr_screen.center_h / 2.0f + gr_screen.center_offset_y) / scale_by) - (static_cast<int>(props.size.height) / 2.0f) + 0.5f);
} else {
// centers on 1024x768, fills on 640x480
screenX = ((gr_screen.center_w - static_cast<int>(props.size.width)) / 2) + gr_screen.center_offset_x;
screenY = ((gr_screen.center_h - static_cast<int>(props.size.height)) / 2) + gr_screen.center_offset_y;
}
// set additional values for screen width/height and UV coords
int screenXW = screenX + static_cast<int>(props.size.width);
int screenYH = screenY + static_cast<int>(props.size.height);
Current_shader->program->Uniforms.setUniformi("ytex", 0);
Current_shader->program->Uniforms.setUniformi("utex", 1);
Current_shader->program->Uniforms.setUniformi("vtex", 2);
Current_shader->program->Uniforms.setUniformMatrix4f("projMatrix", GL_projection_matrix);
Current_shader->program->Uniforms.setUniformMatrix4f("modelViewMatrix", GL_model_view_matrix);
GLfloat glVertices[4][4] = {{0}};
glVertices[0][0] = (GLfloat)screenX;
glVertices[0][1] = (GLfloat)screenY;
glVertices[0][2] = 0.0f;
glVertices[0][3] = 0.0f;
glVertices[1][0] = (GLfloat)screenX;
glVertices[1][1] = (GLfloat)screenYH;
glVertices[1][2] = 0.0f;
glVertices[1][3] = 1.0f;
glVertices[2][0] = (GLfloat)screenXW;
glVertices[2][1] = (GLfloat)screenY;
glVertices[2][2] = 1.0f;
glVertices[2][3] = 0.0f;
glVertices[3][0] = (GLfloat)screenXW;
glVertices[3][1] = (GLfloat)screenYH;
glVertices[3][2] = 1.0f;
glVertices[3][3] = 1.0f;
_vertexLayout.add_vertex_component(vertex_format_data::POSITION2, sizeof(glVertices[0]), 0);
_vertexLayout.add_vertex_component(vertex_format_data::TEX_COORD, sizeof(glVertices[0]), sizeof(GLfloat) * 2);
gr_update_buffer_data(_vertexBuffer, sizeof(glVertices[0]) * 4, glVertices);
}
OpenGLVideoPresenter::~OpenGLVideoPresenter() {
GR_DEBUG_SCOPE("Deinit video");
if (_scaleVideo) {
gr_pop_scale_matrix();
}
gr_delete_buffer(_vertexBuffer);
_vertexBuffer = -1;
GL_state.Texture.Delete(_ytex);
GL_state.Texture.Delete(_utex);
GL_state.Texture.Delete(_vtex);
glDeleteTextures(1, &_ytex);
glDeleteTextures(1, &_utex);
glDeleteTextures(1, &_vtex);
opengl_set_texture_target();
_ytex = _utex = _vtex = 0;
opengl_shader_set_current();
}
void OpenGLVideoPresenter::uploadVideoFrame(const VideoFramePtr& frame) {
GR_DEBUG_SCOPE("Update video frame");
auto ptrs = frame->getDataPointers();
auto stride = static_cast<GLint>(frame->ySize.stride);
auto width = static_cast<GLint>(frame->ySize.width);
auto height = static_cast<GLint>(frame->ySize.height);
GL_state.Texture.SetActiveUnit(0);
GL_state.Texture.Enable(_ytex);
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
glTexSubImage2D(GL_state.Texture.GetTarget(), 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE,
ptrs.y);
stride = static_cast<int>(frame->uvSize.stride);
width = static_cast<int>(frame->uvSize.width);
height = static_cast<int>(frame->uvSize.height);
GL_state.Texture.SetActiveUnit(1);
GL_state.Texture.Enable(_utex);
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
glTexSubImage2D(GL_state.Texture.GetTarget(), 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE,
ptrs.u);
GL_state.Texture.SetActiveUnit(2);
GL_state.Texture.Enable(_vtex);
glTexSubImage2D(GL_state.Texture.GetTarget(), 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE,
ptrs.v);
// Reset this back to default
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
}
void OpenGLVideoPresenter::displayFrame() {
opengl_shader_set_current(_sdr_handle);
opengl_bind_buffer_object(_vertexBuffer);
opengl_bind_vertex_layout(_vertexLayout);
// Bind textures
GL_state.Texture.SetActiveUnit(0);
GL_state.Texture.Enable(_ytex);
GL_state.Texture.SetActiveUnit(1);
GL_state.Texture.Enable(_utex);
GL_state.Texture.SetActiveUnit(2);
GL_state.Texture.Enable(_vtex);
GR_DEBUG_SCOPE("Draw video frame");
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
}
}
@@ -0,0 +1,38 @@
#ifndef FS2_OPEN_OPENGLVIDEOPRESENTER_H
#define FS2_OPEN_OPENGLVIDEOPRESENTER_H
#include "globalincs/pstypes.h"
#include "cutscene/player/VideoPresenter.h"
#include <glad/glad.h>
#include <memory>
#include <graphics/2d.h>
namespace cutscene {
namespace player {
class OpenGLVideoPresenter: public VideoPresenter {
int _vertexBuffer = -1;
vertex_layout _vertexLayout;
int _sdr_handle = -1;
bool _scaleVideo = false;
GLuint _ytex = 0;
GLuint _utex = 0;
GLuint _vtex = 0;
public:
OpenGLVideoPresenter(const MovieProperties& props);
virtual ~OpenGLVideoPresenter();
virtual void uploadVideoFrame(const VideoFramePtr& frame) SCP_OVERRIDE;
virtual void displayFrame() SCP_OVERRIDE;
};
}
}
#endif //FS2_OPEN_OPENGLVIDEOPRESENTER_H
+21
View File
@@ -0,0 +1,21 @@
#ifndef FS2_OPEN_VIDEOPRESENTER_H
#define FS2_OPEN_VIDEOPRESENTER_H
#include "globalincs/pstypes.h"
#include "cutscene/Decoder.h"
namespace cutscene {
namespace player {
class VideoPresenter {
public:
virtual ~VideoPresenter() {}
virtual void uploadVideoFrame(const VideoFramePtr& frame) = 0;
virtual void displayFrame() = 0;
};
}
}
#endif //FS2_OPEN_VIDEOPRESENTER_H
+2 -1
View File
@@ -29,6 +29,7 @@
#include "ship/shipfx.h"
#include "species_defs/species_defs.h"
#include "weapon/weapon.h"
#include "tracing/Monitor.h"
#define MAX_LIFE 10.0f
#define MIN_RADIUS_FOR_PERSISTANT_DEBRIS 50 // ship radius at which debris from it becomes persistant
@@ -1051,7 +1052,7 @@ void calc_debris_physics_properties( physics_info *pi, vec3d *mins, vec3d *maxs
/**
* Renders debris
*/
void debris_render(object * obj, draw_list *scene)
void debris_render(object * obj, model_draw_list *scene)
{
int i, num, swapped;
polymodel *pm;
+2 -2
View File
@@ -16,7 +16,7 @@
class object;
struct CFILE;
class draw_list;
class model_draw_list;
#define MAX_DEBRIS_ARCS 8 // Must be less than MAX_ARC_EFFECTS in model.h
@@ -63,7 +63,7 @@ extern int Num_debris_pieces;
struct collision_info_struct;
void debris_init();
void debris_render(object * obj, draw_list *scene);
void debris_render(object * obj, model_draw_list *scene);
void debris_delete( object * obj );
void debris_process_post( object * obj, float frame_time);
object *debris_create( object * source_obj, int model_num, int submodel_num, vec3d *pos, vec3d *exp_center, int hull_flag, float exp_force );
+1 -1
View File
@@ -306,7 +306,7 @@ void dc_init(void)
dc_command_buf.reserve(MAX_CLI_LEN);
dc_command_buf.clear();
sprintf(dc_title, "FreeSpace Open v%i.%i.%i", FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD);
sprintf(dc_title, "FreeSpace Open v%s", FS_VERSION_FULL);
dc_printf("Debug console started.\n" );
}
+1 -1
View File
@@ -268,7 +268,7 @@ bool dc_pause_output(void);
* @brief Prints the given char string to the debug console
* @details See the doc for std::printf() for formating and more details
*/
void dc_printf(const char *format, ...);
void dc_printf(SCP_FORMAT_STRING const char *format, ...) SCP_FORMAT_STRING_ARGS(1, 2);
/**
* @brief Opens and processes the debug console. (Blocking call)
+2 -2
View File
@@ -957,7 +957,7 @@ long dc_parse_long(const char *ch, dc_token type) {
dc_printf("Error: Could not convert all of the buffer '%s'.\n", buffer_str.c_str());
if (Dc_debug_on) {
dc_printf("<debug> Buffer value: %s\n", buffer_str.c_str());
dc_printf("<debug> Return value: %i", ret);
dc_printf("<debug> Return value: %ld", ret);
}
throw errParse(ch, type);
}
@@ -1046,7 +1046,7 @@ ulong dc_parse_ulong(const char *ch, dc_token type) {
dc_printf("Error: Could not convert all of the buffer '%s'.\n", buffer_str.c_str());
if (Dc_debug_on) {
dc_printf("<debug> Buffer value: %s\n", buffer_str.c_str());
dc_printf("<debug> Return value: %i", ret);
dc_printf("<debug> Return value: %ld", ret);
}
throw errParse(ch, type);
}
+12 -14
View File
@@ -1,19 +1,17 @@
in vec4 fragTexCoord;
out vec4 fragOut0;
uniform sampler2D bloomed;
uniform float bloom_intensity;
uniform int levels;
void main() { // Global constant
void main() {
vec4 color_out = vec4(0.0, 0.0, 0.0, 1.0);
// Bloom
if (bloom_intensity > 0.0) {
vec3 bloom = vec3(0.0, 0.0, 0.0);
float factor = 0.0;
for (int mipmap = 0; mipmap < levels; ++mipmap) {
float scale = 1.0/exp2(float(mipmap));
factor += scale;
bloom += texture2DLod(bloomed, gl_TexCoord[0].xy, float(mipmap)).rgb * scale;
}
bloom /= factor;
color_out.rgb += bloom * bloom_intensity;
float factor = 0.0;
for (int mipmap = 0; mipmap < levels; ++mipmap) {
float scale = 1.0/exp2(float(mipmap));
factor += scale;
color_out.rgb += textureLod(bloomed, fragTexCoord.xy, float(mipmap)).rgb * scale;
}
gl_FragColor = color_out;
}
color_out.rgb /= factor;
color_out.rgb *= bloom_intensity;
fragOut0 = color_out;
}
+9 -7
View File
@@ -1,6 +1,8 @@
out vec4 fragOut0;
uniform float texSize;
uniform float tapSize;
uniform int level;
in vec4 fragTexCoord;
uniform sampler2D tex;
// Gaussian Blur
// 2 passes required
@@ -15,18 +17,18 @@ void main()
BlurWeights[2] = 0.1120;
BlurWeights[1] = 0.1297;
BlurWeights[0] = 0.1362;
vec4 sum = texture2DLod(tex, gl_TexCoord[0].xy, float(level)) * BlurWeights[0];
vec4 sum = textureLod(tex, fragTexCoord.xy, float(level)) * BlurWeights[0];
#ifdef PASS_0
for (int i = 1; i < 6; i++) {
sum += texture2DLod(tex, vec2(clamp(gl_TexCoord[0].x - float(i) * (texSize) * tapSize, 0.0, 1.0), gl_TexCoord[0].y), float(level)) * BlurWeights[i];
sum += texture2DLod(tex, vec2(clamp(gl_TexCoord[0].x + float(i) * (texSize) * tapSize, 0.0, 1.0), gl_TexCoord[0].y), float(level)) * BlurWeights[i];
sum += textureLod(tex, vec2(clamp(fragTexCoord.x - float(i) * (texSize) * tapSize, 0.0, 1.0), fragTexCoord.y), float(level)) * BlurWeights[i];
sum += textureLod(tex, vec2(clamp(fragTexCoord.x + float(i) * (texSize) * tapSize, 0.0, 1.0), fragTexCoord.y), float(level)) * BlurWeights[i];
}
#endif
#ifdef PASS_1
for (int i = 1; i < 6; i++) {
sum += texture2DLod(tex, vec2(gl_TexCoord[0].x, clamp(gl_TexCoord[0].y - float(i) * (texSize) * tapSize, 0.0, 1.0)), float(level)) * BlurWeights[i];
sum += texture2DLod(tex, vec2(gl_TexCoord[0].x, clamp(gl_TexCoord[0].y + float(i) * (texSize) * tapSize, 0.0, 1.0)), float(level)) * BlurWeights[i];
sum += textureLod(tex, vec2(fragTexCoord.x, clamp(fragTexCoord.y - float(i) * (texSize) * tapSize, 0.0, 1.0)), float(level)) * BlurWeights[i];
sum += textureLod(tex, vec2(fragTexCoord.x, clamp(fragTexCoord.y + float(i) * (texSize) * tapSize, 0.0, 1.0)), float(level)) * BlurWeights[i];
}
#endif
gl_FragColor = vec4(sum.rgb, 1.0);
}
fragOut0 = sum;
}
+4 -3
View File
@@ -1,3 +1,5 @@
in vec4 fragTexCoord;
out vec4 fragOut0;
uniform sampler2D tex;
const float Luminance = 0.08;
const float fMiddleGray = 0.2;
@@ -9,13 +11,12 @@ float luminance(vec3 color)
return dot(color, vec3(0.299, 0.587, 0.114));
}
void main() {
vec4 ColorOut = texture2D(tex, gl_TexCoord[0].xy);
vec4 ColorOut = texture(tex, fragTexCoord.xy);
//ColorOut *= fMiddleGray / (Luminance + 0.001);
//ColorOut *= (1.0 + (ColorOut / (fWhiteCutoff * fWhiteCutoff)));
//ColorOut -= 6.0;
//ColorOut /= (10.0 + ColorOut);
gl_FragColor.rgb = max(vec3(0.0, 0.0, 0.0), ColorOut.rgb - vec3(1.0, 1.0, 1.0));
gl_FragColor.a = 1.0;
fragOut0 = vec4(max(vec3(0.0, 0.0, 0.0), ColorOut.rgb - vec3(1.0, 1.0, 1.0)), 1.0);
//float luminance = luminance(ColorOut.rgb);
//gl_FragColor.rgb = luminance > threshold ? ColorOut.rgb : vec3(0.0);
}
Loaded 100 of 936 files, more files were not shown because too many files have changed in this diff. Show more