Compare commits

..
Author SHA1 Message Date
Tyler Blount 0945dee99e Update test-pull_request.yaml 2025-06-09 09:51:29 -07:00
Tyler Blount 9e8003bd8a Update build-test.yaml 2025-06-09 09:50:22 -07:00
Tyler Blount 47d77aa9d5 Update build-release.yaml 2025-06-09 09:49:15 -07:00
Tyler Blount 2b49a0d780 Update nightly build to use windows 2022 2025-06-09 09:47:05 -07:00
Mike Nelson 8410ed0249 Lab asteroid viewer (#6710)
* Allow viewing asteroid and debris objects in the Lab

* Address feedback

* Minor UI string tweak
2025-06-08 14:37:12 -04:00
Mike Nelson 4d39287de1 LuaLS meta file generation (scripting.lua) (#6516) 2025-06-08 11:29:30 -04:00
Kestrellius ad5b2372fa A couple of particle-related fixes (#6754) 2025-06-07 10:49:49 -04:00
Goober5000 546d0af38b Merge pull request #6751 from Goober5000/scripted_movie_audio
enable audio in movie files with this one simple trick
2025-06-07 00:45:56 -04:00
BMagnu 0399e13e3d Fix window_res related bugs (#6753) 2025-06-06 19:33:55 +02:00
Goober5000 0bf5714dd5 Merge pull request #6725 from Goober5000/time_lib_stuff
enhance scripted time library a bit
2025-06-05 23:15:55 -04:00
Goober5000 6ddb57b6c2 Merge pull request #6744 from Goober5000/script_debug_console_commands
add a few debug console commands for running scripts
2025-06-05 23:15:46 -04:00
Taylor Richards 552f9990d9 remove support for memory mapped files (#6748)
FSO doesn't appear to use this any longer. And even when it was enabled the
requirements made it largely useless anyway. Removing to clean up cfile a
bit and so we don't have to keep maintaining it.
2025-06-05 17:53:13 -04:00
Taylor Richards 9e9fc22b13 fix type conversion issue in vecmat (#6749) 2025-06-05 08:02:02 -04:00
Goober5000 c04a23e4f9 add a few debug console commands for running scripts
We have debug commands for sexps, so here are a few for scripts.  These will be very useful for script developers to perform diagnostics and troubleshooting.
2025-06-05 00:40:52 -04:00
Goober5000 a3aea10889 enable audio in movie files with this one simple trick
Turns out, audio works in scripted movies just fine.  So, add a parameter to the Lua API to allow movies to play audio.
2025-06-04 23:58:58 -04:00
Mike Nelson 829edaaa3e Fix Lua API polluting the game context (#6739)
* split rendering values into lua and fso contexts

* address feedback
2025-06-04 09:43:33 -04:00
Kestrellius 3cf3aa9ecd Launch curves followup (#6742)
* this went very badly

* fix burst mult bug

* increment multi

* fix uninitialized variable

* fixes

* further fixes

* concision
2025-06-04 07:07:14 -04:00
wookieejedi 6e7128f26c Mod setting to disable shield effects (#6746)
Mods like FotG do not use the FS style shield hit effects, and simply disabling the shield rendering and checking is useful with one simple global variable.

Tested and works as expected.
2025-06-04 07:06:46 -04:00
Goober5000 921c597f30 Merge pull request #6709 from vmedea/fix-vulkan-build
Fix Vulkan build issues, enable Vulkan build in CI
2025-06-03 21:44:29 -04:00
wookieejedi 66a85113a7 Very small debug log cleanup (#6747) 2025-06-03 21:07:05 -04:00
Asteroth 7502cf37da Stationary jump types should not try to avoid collision (#6738)
* no sweeper jump collision avoidance

* few adjustments

* only use short range distance check
2025-06-02 21:57:41 -04:00
Kestrellius 787c19e71f Fix laser frustum culling (#6741)
* the naive method

* bugfixing

* respect radius
2025-06-03 00:46:27 +02:00
Mara Huldra 20ad23396c clang-tidy: Pass Vulkan defines
`clang-tidy` doesn't pass in the compilation flags normally provided by cmake,
so add the vulkan flags manually to make sure that everything is checked
as it should be, and thus prevent it from choosing the static dispatcher
and complaining about `.init()` being used.
2025-06-02 10:20:37 +00:00
Goober5000 4bc0a21432 Merge pull request #6745 from Goober5000/object_flag_documentation
update object flag documentation
2025-06-01 22:16:31 -04:00
Goober5000 d55061981e update object flag documentation
Fix one copy-paste error (for `Object_Flags::Collides`), and update the other descriptions as these flags can apply to any object, not just ships.
2025-06-01 21:25:49 -04:00
Goober5000 2cb76e8d70 revise documentation 2025-06-01 21:04:15 -04:00
BMagnu e1810ed522 Allow curves to be tabled inline (#6674)
* Add inline curve definitions

* Fix comma parsing

* Fix cast

* Incorporate feedback

* Fix parsing call
2025-06-02 01:41:06 +02:00
BMagnu dd62bc2033 Fix type mismatch (#6743) 2025-06-01 19:25:24 -04:00
BMagnu b3a1b8fc62 Get cross-compilation working again. (#6652)
* Get cross-compilation working again.

* Improve user handling
2025-06-02 00:48:54 +02:00
Tyler Blount 6c193860b5 Add Vulkan Build Checks 2025-06-01 13:30:53 +00:00
Mara Huldra b8634ec7eb ci: Switch to new Linux docker image
Switch to the new Linux docker image with Vulkan headers from
scp-fs2open/docker-images#7, for all github builds.
2025-06-01 13:30:01 +00:00
Mara Huldra 566d8f3e21 Explicitly ignore return values from Vulkan functions in RenderFrame
Because these functions can return statuses that aren't strictly an
error (and thus don't raise an exception), but might have to be handled,
they return a `vk::Result` that's `[[nodiscard]]`. Ideally some of the
result statuses would be handled here, but to get it to compile, cast
the result to void.
2025-06-01 13:30:01 +00:00
Mara Huldra 2f74acad1c Fix invalid assignment in Vulkan renderer
In 133b033ea0, SCP_vector was made into a
subclass, so direct assignment from the vulkan-hpp result isn't possible
anymore. Use an intermediate vector.
2025-06-01 13:30:01 +00:00
wookieejedi 78d2e663d7 One fix and one enhancement to AI shield behavior (#6737)
* One fix and one enhancement to AI shield behavior

This PR adds one fix and one enhancement to AI shield behavior.

1) Fix: Testing, especially in FotG, revealed an edge-case bug with shield management where the AI will not direct shield energy to a quadrant if it was hit when that quadrant was down. In other words, if a shield quadrant is knocked down to 0 and continues to be shot the AI will not realize it needs to direct energy to that quadrant. This is because `quadrant` is set to -1 if a shield segment is down. This ensures that the resulting effects and damage calculations properly ignore that quadrant downstream, but it also results in `aip->last_hit_quadrant` being set to -1. This PR adds a fix to properly record which shield was actually hit, so that the AI knows to direct energy to that quadrant.

2) Enhancement: In combat situations with fire coming from many directions, it is good practice to keep shields equalized, so this PR adds a flag for the AI to always attempt to balance shields, even if it is being fired upon (instead of the current behavior to always direct energy to the hit shield quadrant).

Both flags are tested and work as expected.

* fix copy paste

* rename to avoid previous confusion

* also make as ai class flag
2025-05-30 21:24:01 -04:00
Kestrellius 106afbe2ee scale effects for muzzle and hits (#6731)
* scale effects for muzzle and hits

* move calcs into if block

* aesthetics
2025-05-27 12:04:15 -04:00
Mike Nelson 25dbfc666b Misc hud config fixes (#6727)
* Fix crash when clicking inside the hud area but not on a gauge

* add dogfight_variant weapon flag for sorting purposes

* fix weapon display for default hud and skip dogfight weapons on auto-select

* cleanup the mouse check function
2025-05-27 08:55:12 -04:00
Kestrellius 66d9335dab Weapon launch curves (#6732)
* it's broken and i don't like it

* it's fixed and i approve

* add multi support maybe

* appease clang

* appease clang ii: electric boogaloo

* const refs

* increment multi version
2025-05-27 00:48:40 +02:00
BMagnu b3c3627f54 Allow using seeded noise for particle velocity and spawn position offset (#6675)
* Add noise backend for particles

# Conflicts:
#	code/particle/ParticleEffect.cpp

* noise frontend

* Proper scaling for noise

* make normalize safe
2025-05-26 20:43:56 +09:00
Mike Nelson 5078826340 Lab Weapon Viewer (#6704)
* Activate Lab Weapon viewer

* Allow displaying weapon tech models

* check for a valid tech model when switching

* enable render options for weapons and tech models

* Some cleanup

* Clang

* address feedback
2025-05-26 07:40:08 -04:00
Kestrellius ce4522d4bd tiny optimization (#6733) 2025-05-26 07:39:18 -04:00
Goober5000 778e2a5cb9 enhance scripted time library a bit
1. Add __tostring functions for both the `l_Timestamp` and `l_TimeSpan` types
2. Add a `getSeconds` function for the `l_Timestamp` type
2025-05-21 23:37:04 -04:00
Goober5000 2e65831fa2 add int64 support to toolchain, and fix errors
Add `UINT64_T_ARG` and `INT64_T_ARG` macros for printf arguments, similar to `SIZE_T_ARG` and `PTRDIFF_T_ARG`.

In the process, fix some issues with the toolchain: in certain CI runs the toolchain headers were being #included multiple times, and certain CI runs produced collisions between clang definitions and gcc definitions.  Resolve these issues with `#pragma once` and preprocessor guards in the event of both gcc and clang being active.

Also remove toolchain.h from sexp_container.cpp since it is already #included via pstypes.h.
2025-05-21 23:32:35 -04:00
wookieejedi 381f9fde58 Mod Specific Visual Culling Size for Lasers (#6729)
* Mod Specific Visual Culling Size for Lasers

Currently, lasers will not render if the length or both head and tail radii are < `0.0001`. This is very small, and in many mods the smallest visual size is `0.01`, so this PR exposes that culling size value to allow mods to optimize and tune visual culling of lasers, which can be quite useful especially in laser heavy missions.

* update names

* actually push all files
2025-05-21 17:56:55 -04:00
Kestrellius 61b3d82ecf make particle curves respect weapon curves (#6728) 2025-05-19 22:01:06 -04:00
Kestrellius 5ca64215c6 Weapon curves followup (#6722) 2025-05-19 22:00:53 -04:00
Goober5000 a28b152b2c Merge pull request #6726 from Goober5000/add_comment
add an ETS comment
2025-05-18 23:27:44 -04:00
Goober5000 26fd770c97 add an ETS comment
Clarify the conditions here.
2025-05-18 22:58:47 -04:00
Goober5000 a1a453a217 Merge pull request #6671 from Goober5000/ets_updates
ETS updates
2025-05-18 22:55:37 -04:00
Goober5000 6503b878fc Merge pull request #6723 from Goober5000/coverity_things
Various more Coverity issues
2025-05-17 17:37:26 -04:00
Goober5000 17a91273d1 FIELD_T is assumed to be a pointer here, so mark it as such 2025-05-17 17:14:26 -04:00
Goober5000 4b2a2d747b array and iterator bounds 2025-05-17 17:14:26 -04:00
Goober5000 7702d53fd7 string length 2025-05-17 17:14:26 -04:00
Goober5000 3b51c890fc these lines are things we want to allow 2025-05-17 17:14:26 -04:00
Goober5000 298869e517 properly convert main hall 2025-05-17 00:27:00 -04:00
Goober5000 4422821ff5 avoid accessing variable outside of scope 2025-05-17 00:27:00 -04:00
Goober5000 9c2f080235 initialize fields 2025-05-17 00:27:00 -04:00
Goober5000 d5e3325bef fix unsigned check 2025-05-16 23:32:32 -04:00
Goober5000 85f7ccc083 fix use-after-move 2025-05-16 23:32:13 -04:00
wookieejedi 8102febb08 Extra Visual Indication for Scramble Missions (#6720)
* Extra Visual Indication for `Scramble` Missions

Currently, if a mission is set as scramble then there is no visual way for the player to see that the Ship Selection and Weapon Loadout screens are locked, instead the player has to click on the buttons and hear the fail sounds or assess that the hover states are not triggering. This PR adds a text line right below the words Weapons Loadout that states "Ships/Weapons Locked" (XSTR 749) if the mission is scramble thus the player can easily see this right away and not have to check the buttons on every mission.

Tested and works as expected. Happy to put behind a flag if desired.

* whitespace

* incorporate feedback
2025-05-15 07:42:54 -04:00
wookieejedi 4b7817e5ab Fix highlighting color discrepancy for player ship in loadout screen (#6716)
* Few Minor Visual Indicator Enhancements to Loadout

This PR adds a few visual indicator tune-ups to the loadout screens.

1.
Currently, if a mission is set as `scramble` then there is no visual way for the player to see that the Ship Selection and Weapon Loadout screens are locked, instead the player has to click on the buttons and hear the fail sounds or assess that the hover states are not triggering.

This PR adds a text line right below the words `Weapons Loadout` that states "Ships/Weapons Locked" (XSTR 749) if the mission is `scramble` thus the player can easily see this right away and not have to check the buttons on every mission.

2.
Currently there is a nice orange coloration of the player ship icon in the Ship Selection wing loadout. This immediately shows the player which ship is theirs, but this usefulness does not translate to the Weapon Loadout screen.  The player must select another ship, besides the player ship, to have the player ship show up as orange.

This PR adds a bool `always_highlight_ply` which is specifically for the weapon `draw_wing_block` function when called as as part of the weapon loadout routine.

Both PRs are tested and work as expected. I currently have these PRs on without a flag, but if folks really do not want the PRs or would prefer them to be behind a flag, then I'm happy to do that, too.

* separate PRs
2025-05-15 07:42:34 -04:00
Mike Nelson f1f95717d1 Support Custom Gauges in HUD Config UI (#6670)
* Support coloring custom gauges

* remove NULL
2025-05-14 13:18:03 -04:00
Goober5000 9ea44f0479 ETS updates
Two updates to the energy transfer system.
1. Previously, for fighters missing a system (e.g. shields), the energy would be treated as if all energy from that system was routed to the other systems.  So, for example, a fighter's typical speed would be faster without shields than with shields.  A new AI profile flag now treats the other systems as if the energy had not been transferred.
2. At some point in development, Volition intended the `$Power Output` ships.tbl field to affect ETS.  A new AI profile flag now treats the power output as a factor of energy applied to energy systems.
2025-05-14 01:33:28 -04:00
Goober5000 42dd1eb3c2 Merge pull request #6713 from Goober5000/various_small_issues
Various Coverity issues
2025-05-13 23:18:43 -04:00
Goober5000 1e8ea06854 Merge pull request #6711 from Baezon/small-turret-swarm-fix
Small fix for turret swarm stuff
2025-05-12 21:59:22 -04:00
Goober5000 49cd8c3158 Merge pull request #6717 from Goober5000/improve_scripted_waypoints
improve scripting support for waypoint lists
2025-05-12 21:59:06 -04:00
Goober5000 a294559ee2 improve scripting support for waypoint lists
1. Add an explicit `mn.createWaypointList` function
2. Allow `mn.createWaypoint` to be used with an empty waypoint list
3. Update documentation of `mn.createWaypoint` to clarify optional arguments
2025-05-10 23:36:22 -04:00
Goober5000 04a671c836 simplify list index 2025-05-10 21:43:17 -04:00
Goober5000 ceee045b35 coverity: move instead of copy 2025-05-10 01:15:46 -04:00
Goober5000 e0082447d1 coverity: integer division, string resize, printf arg, float/double 2025-05-10 01:15:46 -04:00
Goober5000 067c65773a coverity: possible use of invalid iterator (especially with jump nodes) 2025-05-10 01:15:46 -04:00
Goober5000 d7796b3767 coverity: use references to avoid unnecessary copies 2025-05-10 01:15:46 -04:00
Goober5000 11b085ca66 Merge pull request #6714 from Goober5000/goto_considered_useful
goto considered useful
2025-05-09 20:36:12 -04:00
Goober5000 aabc0df3be Merge pull request #6686 from Goober5000/enhance_look_at
enhance look_at
2025-05-09 20:35:10 -04:00
Goober5000 56d8c48927 Merge pull request #6712 from Goober5000/a_few_fixes
A few fixes
2025-05-09 20:35:03 -04:00
Mike Nelson 1f7903fb23 add a few hud lua methods (#6692) 2025-05-08 09:33:21 -04:00
Goober5000 3d68bf2c7a goto considered useful
The `continue` statement in these error checks had no effect because the error checks are macros implemented in a `do` ... `while (false)` loop.  So, use `goto`.  There is precedent with other instances of `OpenAL_ErrorCheck` in the code.

This may fix the issue where sound would occasionally randomly stop, requiring a pause or a screen change to get it back.  This would be difficult to verify though.

Thanks to Coverity for flagging this situation!
2025-05-08 02:50:29 -04:00
Goober5000 e0c4c3033f fix bounds check 2025-05-08 02:37:33 -04:00
Goober5000 6c42d9cc82 prevent negative array index when AI has no target 2025-05-08 02:37:24 -04:00
Goober5000 a9ff3c55b9 fix compiler warning 2025-05-08 02:36:47 -04:00
Goober5000 80384e00b3 fix a copy-paste error 2025-05-08 02:36:19 -04:00
Asteroth c085f87e6f clean up condition 2025-05-07 23:31:22 -04:00
Asteroth 447119ed7e small fix for turret swarm stuff 2025-05-07 23:07:33 -04:00
wookieejedi 2576515040 Allow Trigger Radius curve input to work with muzzle effects (#6706)
The Input of `Trigger Radius` for curves within new particle effects was never hooked up for muzzle flashes, so this PR adds in the necessary lines to get it working. This allows modders to make a muzzle effect that can scale to the weapon radius through curves, and thus modders can simply make one curve scaled muzzle flash and avoid making a many muzzle flashes for each sized weapon that uses the same base effect.

Tested and works as expected.
2025-05-04 12:36:27 -04:00
Goober5000 c2314f6a04 Merge pull request #6708 from Goober5000/dockpoint_fix
check dockpoints when changing ship class
2025-05-03 13:54:57 -04:00
Goober5000 d79f5062bf Merge pull request #6698 from Goober5000/update_shield_saving
fix hull/shield checks in missionsave
2025-05-03 13:54:30 -04:00
Goober5000 1f813717e6 check dockpoints when changing ship class
If a ship changes class, the dockpoints on the new model may not match the dockpoints on the old model.  This is most likely to happen when changing a docked ship in FRED to an incompatible ship class, but it can also happen when using the `change-ship-class` SEXP.  So check the dockpoints, update them if they should be updated, and undock them if they can't.
2025-05-02 16:53:45 -04:00
Goober5000 2296d7d330 check for null item array 2025-05-02 14:45:00 -04:00
Tyler Blount 099fc3790d Merge pull request #6705 from TRBlount/update/changelog_script
Update Changelog script to sort by labels
2025-05-02 11:28:31 -07:00
Mike Nelson 1977c083c7 Allow defining separate player and target shield icons for config (#6691)
* Allow defining separate player and target shield icons for config

* rename define to prevent confusion with a similar define in shield.cpp

* address some feedback
2025-05-02 07:58:25 -04:00
DahBlount 98bad1201f Update Changelog script to sort by labels 2025-05-01 16:22:56 -07:00
Mike Nelson 36d6fbe7e5 Lab firing upgrades (#6703)
* Fix some issues preventing various secondary types from firing in the lab

* Add ability to fire turrets from the lab

* const char*, mjn please

* more cleanup

* range-based for loop

* Update comment
2025-05-01 09:50:27 -04:00
Mike Nelson 4c209f83ad Add mission name as hook variable (#6699) 2025-04-25 11:09:48 -04:00
Goober5000 84c8892015 Merge pull request #6701 from Goober5000/eye_script_virtvars
add a few eye virtvars
2025-04-24 23:02:40 -04:00
Goober5000 e409d19365 Merge pull request #6702 from Baezon/fix-2d-camera
Fix for 2d mission camera
2025-04-24 23:02:08 -04:00
Asteroth 1a38350797 2d camera fix 2025-04-24 13:59:21 -04:00
Goober5000 dcd1c97b42 also getMagnitudeSquared 2025-04-23 21:25:07 -04:00
Goober5000 6aa449c8e1 add a few eye virtvars
For displaying things in a scene, because the eye position is not necessarily the ship position.
2025-04-23 21:25:07 -04:00
Goober5000 1abb96a835 Merge pull request #6700 from Goober5000/set_absolute_relative
add Absolute/Relative coordinate selector
2025-04-23 01:33:04 -04:00
Goober5000 321ace9ad3 Merge pull request #6695 from Goober5000/eyepoint_normal_flag
add flag to control model eyepoint normal usage
2025-04-23 01:32:53 -04:00
Goober5000 3d062cb873 add Absolute/Relative coordinate selector
This enhances the Object Position/Orientation Editor to set relative coordinates and angles in addition to absolute coordinates and angles.
2025-04-22 21:15:54 -04:00
Goober5000 d98a90e74a fix hull/shield checks in missionsave
Both the hull and shield save conditions have had benign bugs since the original retail release.  Fix the conditions and use the `fl2i` macro.
2025-04-22 00:42:06 -04:00
Goober5000 7a2f254680 Merge pull request #6696 from Goober5000/animation_set_speed
add setSpeed for animations
2025-04-20 20:32:00 -04:00
Goober5000 354c57cd5c add setSpeed for animations
Most of the functions in ship.cpp that operate on submodel animations are mirrored in animation_handle.cpp, but `setAnimationSpeed` was overlooked.  Add this function so it can be called from a submodel animation handle.
2025-04-20 00:13:49 -04:00
Goober5000 42a973acf9 add flag to control model eyepoint normal usage
PR #6598 caused eyepoint normals to be used for viewing direction, whereas previously the host object's orientation was used for viewing direction.  Since this could cause compatibility issues, return to the previous behavior and make the new behavior depend on a flag that is set in post-25.0 builds.  (This only applies to eyepoint normals; eyepoint *positions* were respected both before and after #6598).
2025-04-19 02:01:20 -04:00
Goober5000 fd194d4bd6 Merge pull request #6694 from Baezon/fix-eye-normals
Some fixes to eye point normals
2025-04-19 01:45:20 -04:00
Asteroth 7e3971a77e some fixes to eye point normals 2025-04-18 11:25:11 -04:00
Asteroth 3b5668c4e5 Add freespace 1 style missile behavior (#6681)
* add fs1 style missile behavior

* add weapon flag, and various tweaks

* remove superfluous check
2025-04-17 21:45:45 -04:00
Goober5000 b755d61381 Merge pull request #6690 from Goober5000/fowarders_supplemental
add supplemental code to forwarders.lua
2025-04-17 20:51:09 -04:00
Mike Nelson d41cb49661 make sure drop shadows don't polute the color context (#6689) 2025-04-17 08:33:15 -04:00
Mike Nelson 524d36332d per-hud config weapons and shield gauge ship (#6651) 2025-04-17 08:31:48 -04:00
Mike Nelson aef3e014c0 Display scrollback with even one message (#6687)
* Display scrollback with even 1 message

* use .empty()
2025-04-17 08:22:02 -04:00
Mike Nelson f9d91d568e Add disable intro movie flag (#6688) 2025-04-17 08:21:49 -04:00
Goober5000 88e6542441 add supplemental code to forwarders.lua
The `println` function is a semi-recent addition to zLoadFirst-sct.tbm, while the `Globals` table should have the vector and orientation values.  The `string.starts` and `string.ends` functions were in the original version of zLoadFirst-sct.tbm but were not included in #6545, and `string.ends` is required by cfile_include.lua.
2025-04-16 23:58:28 -04:00
wookieejedi df445fa8a6 Wingmen and Squad Message QoL Updates (#6682)
* Wingmen and Squad Message QoL Updates

This PR adds a few assorted HUD updates/quality of life enhancements. FotG will be using these, though they relatively general and are likely useful to most other mods, too.

1) Adds a 'Ship Name Max Width:' to the Squad Message Gauge (following the same logic as the Escort Gauge). The Escort Gauge will truncate display names of ships if they are too long, that way all the text fits in the gauge without spilling over. It would also be very useful to do this with the Squad Message Gauge, as long display names can overflow out of the gauge's boundaries currently.

2) Adds `Wingname Align Mode:` to the Wingmen Gauge, which allows modders to set how the wingnames are aligned. Currently they are centered on the calculated x-position, though this PR also adds right and left justification options (which is useful especially if displaying the full wing names).

All options are tested and work as expected.

* appease clang

* whitespace

* more safety and error checking

* and extra error helpfulness

* use safer str copy
2025-04-16 22:47:14 -04:00
Goober5000 3fb82e5ac3 enhance look_at
Some QoL improvements:
1. Update `$fvec` and `$uvec` parsing to also allow parsing `$rvec` and to allow only `$fvec` to be specified; also make parsing more robust against failure
2. Allow `$fvec` and `$uvec` to specify the "facing" direction if `$look_at_offset` is not specified
3. Add a few additional warnings for incomplete or invalid POF data
2025-04-15 21:52:13 -04:00
wookieejedi eb60a87b28 Allow mods to hide main Rearm/Repair items in Message Gauge (#6684)
* Allow mods to hide main Rearm/Repair items in Message Gauge

Adds a game_settings option to hide/disable the Rearm/Repair commands in the Squad Message Gauge. FotG does not use repair ships, so it is somewhat confusing to players to always see the `Rearm/Repair` order options (IE 5. Rearm/Repair Subsys and 6. Abort Rearm) and never be able to use them.

I wanted to make this PR as surgical as possible, while still giving some degree of generality, thus I went with the solution to use `active` as a true integer instead of simply an old int in the bool style. Now -1 is hidden, 0 is greyed out, and 1 is bright.

Tested and works as expected.

* update comment

* update with better name

* add another clarifying comment
2025-04-14 07:22:10 -04:00
Taylor Richards a2d3e6aeb7 add arm64 Linux builds to workflow (#6683)
Github runners for Linux arm64 are now in public beta with the same
free limits as normal github runners. Our Linux build images already
have arm64 support so this finally enables it as part of the official
workflow.
2025-04-13 22:05:40 -04:00
Goober5000 72b7ea9bd3 Merge pull request #6678 from Goober5000/particle_orientation_fix
fix bogus direction vector in particle code
2025-04-13 18:19:12 -04:00
John Fernandez 5f3f7efe7d Merge pull request #6545 from MjnMixael/lua_load_first
Build in the common z load first methods and forwarders
2025-04-12 17:42:45 -04:00
Goober5000 596f6e75da check in more places in the particle code 2025-04-12 15:38:57 -04:00
wookieejedi 0964ee5e23 Fix wingmen custom dot for starting ships (#6677) 2025-04-10 21:14:10 -04:00
Goober5000 77cbee7bcb fix bogus direction vector in particle code
This was discovered thanks to the new assertions from #6596.  For particles with 0 velocity, the code would attempt to normalize a 0,0,0 vector with predictably undesirable results.  So, pick the global `z` vector in these cases, while normalizing in the usual case.
2025-04-10 19:57:06 -04:00
John Fernandez cc50010b8f Merge pull request #6340 from MjnMixael/enhance_vasudan_cheats
Enhance Vasudan Mainhall Cheats
2025-04-10 11:53:51 -04:00
Goober5000 c17560a0d8 Merge pull request #6665 from Goober5000/intrinsic_no_shields_fix
refine intrinsic_no_shields behavior
2025-04-09 21:46:10 -04:00
Mike Nelson 8f6f4d7834 address feedback 2025-04-09 20:02:27 -05:00
wookieejedi a88d34151b Fix wingmen custom dot for ship changes (#6676) 2025-04-09 20:47:59 -04:00
Goober5000 ec8416c582 prevent negative array access when ship has no weapons 2025-04-09 20:40:11 -04:00
Goober5000 2d86572b36 initialize the Pre_player_entry flag to false in case anything checks it before the first mission 2025-04-09 20:40:11 -04:00
Goober5000 982a550211 don't save the no-shields flag in the mission file for intrinsic-no-shields ships 2025-04-09 20:40:11 -04:00
Goober5000 9cef39dab6 enhance shield checks to consider shield strength in addition to the Intrinsic_no_shields ship class flag 2025-04-09 20:40:11 -04:00
Goober5000 78b556a672 Merge pull request #6667 from Goober5000/player_use_ai_fix
fix chaotic player targeting in rare situations
2025-04-09 20:34:06 -04:00
Goober5000 42b837bd63 Merge pull request #6672 from Goober5000/weapon_editor_tweak
tweak weapon editor UI
2025-04-09 20:33:28 -04:00
Taylor Richards 1a642185fe fix text input crash on Linux, and plug memory leak (#6648)
Linux iconv does not support "UCS-2-INTERNAL" and conversion will fail if SDL
is compiled with native iconv support. SDL version 2.32.2 fixed this by
changing the macro to use "UCS-2" instead. Unfortunately in my tests this
worked perfectly in Linux but was broken on Mac in the rocket_ui code. However
simply using proper endianess appears to work on all test platforms.

Additionally this fixes a bad memory leak as SDL_iconv_string() allocates it's
return string and this was never free'd before. So every character of text
input resulted in a memory leak of 6+ bytes.
2025-04-08 04:41:20 -04:00
BMagnu 01b09aae1c Fix SoundDuring animation segments with the loop flag set (#6669)
* Properly stop sounds even with the non-interrupt flag

* Respect tabled flags
2025-04-08 10:00:04 +02:00
Goober5000 b6c7a4c28f tweak weapon editor UI
Widen the weapon editor UI fields by KJakker's request.
2025-04-08 01:18:43 -04:00
Taylor Richards d49f3ca743 update and fix force feedback code (#6664)
Update haptic code with changes from icculus.org tree which optimizes
effect loading to better support low-memory devices and no longer
requires full support of every haptic effect type. Additionally...

 - avoids attempting FF init for non-haptic devices
 - avoids attempting FF init for gamepads
 - properly resets FF when device is hot-plugged
 - better start/stop/update of effects
 - avoid stopping effects unless really needed
 - use timestamp for dir effect restarts instead of sys calls
 - avoid playing FF effects when window is in background
 - general code cleanup
2025-04-08 01:01:54 -04:00
Goober5000 7246bc331a Merge pull request #6659 from Goober5000/supernova_stage_and_missionsave_tweaks
add sexp to get the current supernova stage
2025-04-07 18:06:50 -04:00
Goober5000 67a4244152 add sexp to get the current supernova stage
Return the current supernova stage.  This sexp, in conjunction with mission cutscene editor, makes it possible to reproduce the FreeSpace 2 end-of-campaign cutscene behavior purely in FRED.  The resulting cutscene section looks like this:
```

$Campaign End Cutscene: endpart1.mve
+formula: ( true )

$Campaign End Cutscene: endprt2a.mve
+formula: ( < ( get-supernova-stage ) 3 )

$Campaign End Cutscene: endprt2b.mve
+formula: ( >= ( get-supernova-stage ) 3 )

```
Also add a new status subcategory and fix newline behavior when saving the cutscene section.

Fixes #6657.
2025-04-06 22:37:01 -04:00
BMagnu 2043a079c4 Fix scaling of subspace glows (#6668) 2025-04-06 17:53:27 +02:00
Mike Nelson cacf1fb002 match get/set colors for gauges to graphics (#6563) 2025-04-06 11:10:16 -04:00
Mike Nelson 1a503faa6b Better color preset handling (#6655) 2025-04-06 11:09:43 -04:00
Goober5000 052dfd8c14 clean up AI state when turning off player AI 2025-04-06 02:45:17 -04:00
Goober5000 60b676cba9 change Player_use_ai from int to bool 2025-04-06 02:11:52 -04:00
Goober5000 3bf6d43022 Merge pull request #6649 from Goober5000/update_yaml_again
update workflows to use official release of setup-vulkan-sdk
2025-04-04 00:02:40 -04:00
Mike Nelson a7b47e7a34 Hash check retail strings and weapons tables (#6662)
* hash check retail strings and weapons tables

* const
2025-04-03 21:56:28 +02:00
Taylor Richards 2764d06fdb update zlib to 1.3.1 and libpng to 1.6.47 (#6661) 2025-04-03 14:34:20 -04:00
Goober5000 0097355dc2 Merge pull request #6654 from Goober5000/red_alert_weapon_fix
fix a subtle red-alert weapon bug
2025-04-02 19:39:34 -04:00
Goober5000 15cbe259f4 Merge pull request #6663 from TRBlount/coverity_large_build
Update coverity workflow to use large build endpoint
2025-04-02 19:39:15 -04:00
Mike Nelson 7c38273f5b Lua hooks for the comm board (#6450)
* lua access to the comm board menu

* On Order Issued Lua Hook

* Some cleanup and safety checks

* Add mn.sendBuiltinMessage and perform more cleanup

* Send the correct ship to the hook for Sender

* clang cleanup

* address feedback

* fix build errors introduced from upstream

* basic hook conditions

* properly link the condition and the oswpt struct

* some requested cleanup

* allow for sending custom built-in messages

* address more feedback

* more prefix
2025-04-03 00:55:20 +02:00
wookieejedi c6f2d05998 Allow normal, AO, and misc maps at higher detail settings (#6658)
Previously, FSO did not show normal, AO, or misc maps at LODs 3 or higher. This was  a relic from original retail days, so this PR allows players to see those textures if the model detail level is at 3 or 4. I put this under the model slider because it is related to LODs, and b/c changing the model slider is something folks actually use compared to the other hardware tex slider which really makes things look ancient if turned to anything other than the max.
2025-04-02 07:44:16 -04:00
DahBlount bb904dd37d Use github ref instead of rev-parse HEAD 2025-04-01 19:19:15 -07:00
DahBlount 9331f25b79 Initial test commit for using large build endpoint 2025-04-01 18:53:03 -07:00
wookieejedi 4a7bbc5b24 Tune how the default_settings.tbl handles options it cannot find (#6656)
In-game options may be removed/inaccessible, such as VR mode removing the Window, but still valid for listing in the `default_settings.tbl` table.

In other words, we don't want error messages displaying if a player is playing  in VR mode (which will remove the Window option for that instance) but the window option is listed in the table.

Thus, downgrade the error to a debug print for options within the `default_settings.tbl`. As MJN stated, the table itself controls the parser here, so downgrading the warning is the best choice.
2025-04-01 13:58:14 -04:00
BMagnu 893fb9fef9 Add an ingame setting to disable sunglare (#6645)
* Add an ingame setting to disable sunglare

# Conflicts:
#	code/localization/localize.cpp

* Update XSTR
2025-04-01 12:56:23 +00:00
wookieejediandBirk Magnussen 46e7df7941 Make VR mode more seamless (#6636)
* Make VR mode more seamless

Works to make the `-vr` command flag more seamlessly work (which means the new KNet button, `Play in VR` will also now actually work). Fixes #6430.

First, creates a new in-game option called VR Resolution and have the default be 2500x2500, with a range that goes from 1000x1000 to 6000x6000.

Second, if `-vr` flag is used, then it auto sets flags of `-capture_mouse` `-stretch_menu` and `-window_res 1000x1000` (or anything that's for sure smaller than the screen but not too small, to maintain mouse precision).

It also overrides settings of `-vysnc` and `-window` to off, by ignoring the in-game values (and does not show these options in menu while in VR mode).

Finally, it reads the in-game value of `VR Resolution` instead of `Resolution`. It also shows the `VR Resolution` in-game option in the menu, while hiding the options of `Resolution`, `Windowed Mode` and `Vsync`.

If the game is run in standard mode then FSO does what it current does, including using the `Resolution` value for screen resolution. It also does not display the new in-game option for `VR Resolution`.

* actually use the vr_enumerator

* use emplace_back instead

* update res vr importance

* Fixes for VR one-button mode

* try reordering removes for clang

* fix string ids

* test to see if clang is being weird

* revert clang test

* strings index update

* cleanup options manager

---------

Co-authored-by: Birk Magnussen <[email protected]>
2025-04-01 14:18:19 +02:00
Goober5000 7b0a5d6daa fix a subtle red-alert weapon bug
Ships that red-alerted, but that departed before red-alert was triggered, would have 0 weapons on the subsequent mission.  Since exited ships do not store weapon information, that information was never saved in the red-alert status, and so `num_primary_banks` and `num_secondary_banks` would inadvertently be set to 0.  This bug has been around since the pilotfile upgrade in 2013, and apparently was common knowledge among several players, but was never reported. :-/  The fix is easy enough: skip setting weapon information if that information is not saved in red-alert status.  (We should also skip setting subsystem information in the same circumstances, although that did not cause any subsystem misbehavior.)
2025-03-31 00:40:23 -04:00
Goober5000 44ff94a72f Merge pull request #6622 from Goober5000/move_semantics
audit move semantics in the codebase
2025-03-30 18:40:05 -04:00
BMagnu 7aeee3d569 Make faraway objects actually render faraway (#6653) 2025-03-30 01:00:44 +01:00
Goober5000 86f75c5d17 fix normalized vector handling (#6650)
Although normalized vectors in FSO are supposed to stay normalized, occasionally small floating point errors can pop up.  In most cases these do not cause a problem, but in certain cases these errors can rapidly accumulate and corrupt an otherwise well-behaved matrix.  This can most easily be seen with daisy-chained dock sequences or docked ships with angled dockpoints.

This PR audits the usage of `vm_vector_2_matrix_norm` to re-normalize vectors in cases where floating point errors could accumulate.  There are also a few new Assertions for extra vigilance.

Follow-up to #6596.  Fixes #6634.
2025-03-28 23:54:51 +01:00
Goober5000 750348a4c0 Merge pull request #6643 from Goober5000/skipmemymissionyo_in_space
skipmemymissionyo fixes
2025-03-26 23:24:32 -04:00
Goober5000 f86a28a274 update workflows to use official release of setup-vulkan-sdk
The official 1.2.1 release of humbletim/setup-vulkan-sdk was recently published.  Update the repo version and, incidentally, also the vulkan version.  See https://github.com/humbletim/setup-vulkan-sdk

Follow-up to #6582.
2025-03-26 23:09:58 -04:00
Goober5000 8613ccde76 skipmemymissionyo fixes
Improve skipmemymissionyo in several ways, based on RedMageJoe's recent experience:
1. Allow spaces to be accepted in the mission prompt
2. If the requested mission can't be found, just abort rather than restarting the entire campaign
3. Clarify that the prompt needs a filename and add a message if the mission can't be found
4. Improve handling of the .fs2 extension
5. Fix a bounds check in `popup_input`
2025-03-26 22:56:21 -04:00
Goober5000 c5f17bf7c3 Merge pull request #6646 from Goober5000/player_start_check
handle starting shipname mismatch
2025-03-26 22:46:49 -04:00
Taylor Richards cd77ec0c51 fix compilation on linux arm64 (#6647) 2025-03-26 12:47:45 -04:00
Goober5000 a5308d67d3 handle starting shipname mismatch
If the player starting ship name does not refer to an actual ship, gracefully fail to load the mission instead of crashing.
2025-03-26 01:11:51 -04:00
BMagnu 285b385a67 Don't override blend mode for skyboxes (#6644) 2025-03-25 16:19:03 +01:00
John Fernandez 783f495091 Merge pull request #6555 from MjnMixael/remove_warp_options
Move warp options to tables
2025-03-25 09:49:33 -04:00
wookieejedi 310a170bca Fix/cleanup using intrinsic no shields and ship loadout switching (#6641)
* Fix/cleanup using `intrinsic no shields` and ship loadout switching

The flag `intrinsic no shields` is used to allow switching between both shielded and unshielded craft in loadout. There is one edge case that was not accounted for though, which is that if a ship has no shields, and is switched to a ship with shields, the mission will start with that ship having a current shield strength of 0 and only slow get it's shield strength up via shield recharge.

This is not expected behavior, so this PR adds the extra conditional check that if that flag is on, then treat shield percent as full instead of empty. This ensures that switching to a ship with shields in loadout will begin the mission with full shield strength (instead of 0 and waiting for a full recharge).

Tested and works as expected. If desired I can put this behind a game settings flag, but I figured this was the expected behavior (and I'm not even sure how many mods besides FotG uses `intrinsic no shields`.

* also fix initial ets setting with intrinsic no shields

* format consistency
2025-03-24 08:20:08 -04:00
wookieejedi f2108ab4d8 Fix fire-point and flight cursor positions (#6642)
Fixes a bug where the fire-point and flight cursor position components of the center reticle were improperly calculated. Also fixes bug where the fire-point component was missing an argument for `renderCircle`.

Tested and fixes work as expected.
2025-03-23 21:24:50 +01:00
Mike Nelson 60777154be Hud config upgrades (#6581)
* base working version

* localization and minor tweaks

* add retail UI controls

* Add way to hide gauges from Config view

* convert hud config from index matching to id matching

* clang
2025-03-22 22:47:38 -04:00
John Fernandez 9f38451fd4 Merge pull request #6631 from Dark-Visor/change_ship_display_name
Change ship display name
2025-03-22 11:44:38 -04:00
BMagnu 95d1cd5d47 Actually return the correct field (#6639) 2025-03-18 20:18:01 +00:00
Goober5000 4b3894c0a5 audit move semantics in the codebase
For every move and move-assignment constructor, do the following:
1. Make it default if possible
2. Add or delete where appropriate
3. Check for move-onto-self
4. Apply `std::move` where needed

Also fix problematic moves in `player_h`
2025-03-17 00:31:59 -04:00
Dark-Visor 600b6def7b Updates to change-ship-display-name
Update to allow changes to alt name, callsign and display name.
2025-03-16 21:41:55 +00:00
Dark-Visor e82d3936ce Improve code
Make changes to change_alt_name_or_display_name_or_callsign both single
and multi.
2025-03-16 21:41:54 +00:00
Dark-Visor 9c87f08832 Create sexp for change-ship-display-name
Copy existing code from change-ship-alt-name into new sexp
change-ship-display-name and likewise from OP_SHIP_CHANGE_ALT_NAME to
new OP_SHIP_CHANGE_DISPLAY_NAME. Create new blank function
"sexp_ship_change_alt_name_or_callsign" and a function for multi too.
2025-03-16 21:41:16 +00:00
Goober5000 737f4f2b47 Merge pull request #6633 from Goober5000/normalize_orientations
ensure matrices are well-behaved
2025-03-16 01:31:55 -04:00
Goober5000 819404f791 ensure matrices are well-behaved
When an orientation matrix is constructed using one or more vectors, all such vectors must be normalized.  Previously, the code did not enforce this for matrices parsed from a mission or table file.  Although FRED will use correct matrices, it also truncates floating point values to six decimal places, so non-normalized vectors might be written to the mission file as happened in #6632.  And there is always the possibility that someone could manually edit the mission file to corrupt the matrices.

While we're at it, per suggestions from Asteroth and qazwsxal, make sure the matrix is orthogonal as well.  The `vm_fix_matrix` function handles all relevant calculations.

Fixes #6632.  Follow-up to #6596.
2025-03-15 23:01:29 -04:00
Goober5000 a92368da96 Merge pull request #6624 from Goober5000/shield_tweaks
some refinement of shield quadrants
2025-03-11 00:58:50 -04:00
Goober5000 9716bdbbc1 Merge pull request #6629 from Goober5000/coverity_upload_fix
attempt to fix Coverity
2025-03-11 00:58:08 -04:00
Goober5000 32f979d3c6 attempt to fix Coverity
Coverity hasn't run since September 27.  A close look at the log shows that the workflow makes it almost all the way through but fails on the "Upload to Coverity" step:
`fatal: detected dubious ownership in repository at '/__w/fs2open.github.com/fs2open.github.com'`

There are various questionable ways that people have tried to fix this, but it might be possible to completely avoid the issue by not using `git` in that step.  So let's try to get the commit hash from GitHub context rather than by running `git rev-parse HEAD`.
2025-03-11 00:27:57 -04:00
wookieejedi 303070d76e Fix script setting of subsystem hitpoints max (#6628)
Currently if you try to set a subsystem's hit points via scripting it only sets the value to 0 b/c of what was likely a copy paste bug. This 1 line PR fixes that. Tested and fix works as expected.
2025-03-09 21:09:46 -04:00
Mike Nelson a7754e637a Fix hud errors (#6627)
* fix weapon energy text in config mode

* fix x,y  mismatch

* fix squad message copy/paste error
2025-03-09 21:09:37 -04:00
wookieejedi e89917e20d Allows mods to fully disable energy transfering (#6623) 2025-03-08 17:41:12 -05:00
wookieejedi 10d59399c6 Fix mini-shield custom filename (#6625) 2025-03-08 17:40:53 -05:00
Goober5000 44cdb29135 some refinement of shield quadrants
Remove the `n_quadrants` field because it is entirely redundant to the size of `shield_quadrant`.  Also, be more rigorous about the difference between `shield_get_quad(i)` (which can fluctuate) and `shield_quadrant[i]` (which gives the exact quadrant strength).  Finally add some C++ casts and move some checks to better places.
2025-03-08 01:10:59 -05:00
wookieejedi eaebcf8ee6 Fix asteroids spawning outside active fields (#6615)
* Fix asteroids spawning outside active fields

Found an interesting edge case bug with active asteroid fields that has been present since retail:  if a large ship is just outside an active asteroid field, that field will end up spawning asteroids outside the field bounds. This is because the game thinks that the large ship is within the asteroid field when it is actually not. Specifically, the check `asteroid_is_ship_inside_field` does not properly account for the ship the addition of the ship's diameter to the bounding box check.

This PR adds a flag to fix that bounding box check and fix the bug of spawing asteroids outside the asteroid field bounds. Note, `asteroid_is_ship_inside_field` is used twice in the code, once within `set_asteroid_throw_objnum` and once following that call within `maybe_throw_asteroid`. Also note, `asteroid_in_inner_bound` uses a delta of 0 in all cases except when being called within `asteroid_is_ship_inside_field`.

Tested and this fixes the bug while still having asteroid fields work as expected. (Also took this chance to rename a local variable for newly create asteroids to more descriptive name).

* enable by default for 25.0
2025-03-07 08:19:21 -05:00
Goober5000 5bd9f705ac Merge pull request #6618 from Goober5000/fred_fixes
a few minor fixes
2025-03-06 21:53:27 -05:00
Mike Nelson 32befb83a9 fix ets copy/paste error (#6619) 2025-03-06 10:47:22 -05:00
Goober5000 25aa3d71aa a few minor fixes
1. `Neb2_poof_flags` is a ubyte array, and so should be of type ubyte[], not ubyte
2. Save the substitute main hall in qtFRED
2025-03-05 22:12:24 -05:00
wookieejedi d9f93d1ca9 Update conditional check for wingmen dots (#6617) 2025-03-05 21:00:45 -05:00
Goober5000 a99aa35c7c Merge pull request #6614 from Goober5000/parse_line_updates
upgrade line parsing and end-of-line checks
2025-03-05 19:38:20 -05:00
Mike Nelson 44d3ea9353 Fix small non-config oversights (#6616) 2025-03-05 13:13:02 -05:00
Goober5000 c1910b210a Merge pull request #6607 from Goober5000/unique_ptr_ships_weapons
std::unique_ptr refactoring
2025-03-04 23:26:41 -05:00
Goober5000 343d9a36d4 std::unique_ptr refactoring
Use `std::unique_ptr` rather than `vm_malloc` and `vm_free` to handle optional strings in ship classes.  This makes the code more robust and increases memory safety.  This also allows several string variables to be consolidated in the ship class and weapon class script APIs.

Also add new `stuff_string()` overloads and a new `F_TRIMMED` string parsing type to handle the new fields and the string trimming done inside `stuff_malloc_string()`.
2025-03-04 22:52:53 -05:00
Goober5000 f4099f5000 a few cleanup and efficiency tweaks
1. Use `const char *flag_desc` because constructing a SCP_string for each flag description is not needed
2. Make `VALID_FNAME` check for nullptr
3. Modify the signature of `coalesce()` to allow capturing of mixed `const` and non-`const` arguments
4. Use `std::for_each` (via `SCP_tolower`) rather than `std::transform` to fix compilation warnings
2025-03-04 22:48:20 -05:00
Mike Nelson cf57df37d3 config rendering methods for orb and standard radar gauges (#6579) 2025-03-04 13:31:56 -05:00
Mike Nelson 7a5f4b1d80 HUD Config Rendering Methods PR 6/7 (#6578)
* config rendering methods for wingman status and training msg gauges

* table define example wing names
2025-03-03 21:56:57 -05:00
Goober5000 9e4287e7b0 Merge pull request #6596 from Goober5000/vm_vector_2_matrix_norm
use vm_vector_2_matrix_norm on normalized vectors
2025-03-03 21:00:02 -05:00
Mike Nelson 681206a356 config rendering methods for 3d targeting gauges (#6577) 2025-03-03 08:24:05 -05:00
Goober5000 4797ce55a2 use vm_vector_2_matrix_norm on normalized vectors
Most places in the code that use `vm_vector_2_matrix` do so on already-normalized vectors.  Changing these to `vm_vector_2_matrix_norm` avoids redundant normalization.
2025-03-02 23:07:09 -05:00
wookieejedi 1756648322 Fixes cursor not restoring when exiting IMU GUI (#6613)
Currently, the cursor does not revert correctly after visiting F3 options screen or lab due to IMGUI unsetting the FSO cursor image.

This PR reloads the FSO cursor image when those screens end. Fixes #6436.

Tested and works as expected.
2025-03-02 17:02:21 -05:00
Mike Nelson 94587100df config rendering methods for reticle and target box gauges (#6576) 2025-03-02 16:17:53 -05:00
Goober5000 791c250c30 upgrade line parsing and end-of-line checks
Upgrade `parse_get_line` to detect all three EOL types: CR, LF, and CRLF.  The function is now more robust against line ending mismatches and will now also warn the modder if a file contains mixed line endings.

Fixes #6395.
2025-03-02 12:48:02 -05:00
Mike Nelson acc382d169 config rendering method for messages, talking heads, and shield gauges (#6575) 2025-03-02 08:02:09 -05:00
Goober5000 f2b9a99bed Merge pull request #6610 from Goober5000/model_parsing_enhancements
enhance detection of model property errors
2025-03-02 01:10:34 -05:00
Goober5000 93a816bc39 Merge pull request #6599 from LuytenKy/model_eyepoint_for_set_camera_host
Model eyepoint for set camera host flag
2025-03-02 01:10:26 -05:00
wookieejedi 67b2987e20 Hide Disabled Controls in the F1 Screen (#6612) 2025-03-01 21:33:31 -05:00
wookieejedi fad0dce530 Fixes missing XSTRs for Joysticks (#6611)
There were rather prominent strings shown for joysticks that were never localized. This PR localizes them to allow for proper translation support.

Tested and works as expected.
2025-03-01 08:36:21 -05:00
LuytenKy 3c907f2607 Add eyepoint flag for set-camera-host
Original issue post #6509. This flag controls if set-camera-host sexp uses the model's eyepoint for the camera position and orientation when no submodel is specified.
Without the flag, the camera will use the model's origin position and orientation.
2025-03-01 08:45:43 +02:00
Mike Nelson 22f34e7d91 config rendering for escort and ets gauges (#6574) 2025-02-28 21:36:24 -05:00
Goober5000 c2829ceb23 enhance detection of model property errors
1. Trim trailing whitespace on any property values, just as leading whitespace is trimmed.  All places where `get_user_prop_value()` is used implicitly or explicitly require this.
2. Warn the user if an invalid `$special` value is parsed.  This would have caught #1, and will now catch related errors, such as misspellings, in the future.
3. Enhance `string_lookup()` with the ability to print the list being searched, if desired.  Remove an unused version of `string_lookup()`.
4. Check for lower-detail submodels being recognized as subsystems.
2025-02-28 01:52:05 -05:00
Mike Nelson 36819bf8b2 config rendering for gauges in hud.cpp (#6573) 2025-02-27 17:16:08 -05:00
Goober5000 f8d71f704a Merge pull request #6603 from Goober5000/qol_audio
audio QoL update
2025-02-26 23:58:26 -05:00
wookieejedi ff85d13709 Create scripting hooks On HUD Config Menu Close and On Control Config Menu Close (#6608) 2025-02-26 19:30:34 -05:00
wookieejedi f854947abc Localize a missing Controls Popup text string (#6605)
There were two rather prominent strings shown in popup windows related to the more modern control presets that were never localized. This PR localizes them to allow for proper translation support.

Tested and works as expected.
2025-02-24 22:54:09 -05:00
wookieejedi dd9144f3f6 Create scripting hook: 'On Options Menu Closed' (#6604)
* Create scripting hook: 'On Options Menu Closed'

Complements #6591. This PR creates a hook, 'On Options Menu Closed' that provides a hook variable of `hv.OptionsAccepted` which is true if the options are accepted/saved, false if the options are discarded and not accepted/saved.
2025-02-23 12:59:02 -05:00
Goober5000 4337ec822f Merge pull request #6598 from Goober5000/ship_get_eye
refactor ship_get_eye
2025-02-22 22:35:37 -05:00
Goober5000 e30690475e Merge pull request #6602 from Goober5000/ship_sparks_fixes
several fixes to ship sparks
2025-02-22 22:35:29 -05:00
Goober5000 b2c44e1a71 clarify which sound type is being parsed when warning about retail-style sounds 2025-02-22 21:12:58 -05:00
Goober5000 1cfe107ef2 audio QoL update
When searching to see if there is an extension mismatch for a soundtrack audio file, go ahead and substitute the mismatched extension if found.  Matching extensions is important, so continue to display a Warning; but for the benefit of players and out-of-maintenance mods, it is more friendly to play the mismatched file even if the audio data is inaccurate.
2025-02-22 21:12:29 -05:00
wookieejedi 0cb01f50ca Fix changes to Options not properly discarding when escape key pressed (#6597) 2025-02-22 20:55:01 -05:00
Goober5000 b1e69023ef rename ship_get_eye to object_get_eye and consolidate object/ship cases where appropriate 2025-02-22 19:29:11 -05:00
Goober5000 29804918dd refactor ship_get_eye
1. Allow `ship_get_eye` to be used for any objects, not just ships
2. Remove the unused `from_origin` parameter and add `local_pos` and `local_orient` instead
3. Simplify the implementation and take advantage of upgrades to `model_instance_local_to_global_*` functions
4. Consolidate `ship_get_eye_local` into `ship_get_eye`
2025-02-22 19:29:11 -05:00
Goober5000 d31f0a1b79 several fixes to ship sparks
1. Refactor `num_hits` to `num_sparks` and `MAX_SHIP_HITS` to `MAX_SHIP_SPARKS` to be consistent with their current (since FS1 pre-release) usage.
2. Remove the unused `HP_SCALE`.
3. Always initialize at least one spark pair.  If `choose_next_spark()` was entered when `num_sparks` was 1, `num_spark_pairs` would be 0 and none of the spark pairs would be initialized.  Consequently, accessing the pair at index 0 would return garbage data.
4. Iterate through `num_spark_pairs` when counting the indexes, rather than the hardcoded (and incorrect) magic number 6.

Fixes a crash discovered by Dawnesya that can only occur when a ship has both the "fighter" and "cruiser" flags.  Normally, fighters never enter the `choose_next_spark()` function and 'big' ships always have at least 3 sparks.
2025-02-22 01:59:07 -05:00
Goober5000 5e156d7055 Merge pull request #6601 from Goober5000/list_box_tweak
change the selection style on the nebula poof list box
2025-02-21 23:17:55 -05:00
Goober5000 b413ed388f change the selection style on the nebula poof list box
With the old style, `LBS_MULTIPLESEL`, clicking once allows the user to select/deselect a poof, and multiple selection/deselection is done by clicking multiple times.  With the new style, `LBS_EXTENDEDSEL`, clicking once changes to a new single selection, but clicking and dragging, or clicking with Shift or Ctrl, creates or modifies a multiple selection.  This should be a more user-friendly selection style for lists with large numbers of poofs.
2025-02-21 17:18:31 -05:00
BMagnu ae501e21c9 Fix particle name assignment when using legacy-type composite effects that address child effects by name (#6600) 2025-02-21 21:37:21 +01:00
wookieejedi 5392131a09 Option to unify setting options with easy flag (#6595)
* Option to unify setting options with easy flag

Most modern UIs, including KNet 1.3, have options that are always set and do not require the user to click save, or on the few cases where options will not be saved automatically, the program shows a popup telling the user the changes are not saved. In addition, the user experience of setting many options then forgetting to press save is far more common and annoying then the opposite. As a last example, even the F3 in-game options menu presents Escape as the leave and save button, not the leave and discard button.

Currently, there are two screens where FSO allows users to press escape after setting options and leave without warning. The main options screen and the HUD screen. As it turns out, half of the options in the main options screen get saved even if the player presses escape (all the detail slider options along with the joystick and mouse sensitivity and dead zone settings), so current behavior is inconsistent to users.

This PR, aimed to be strategic and efficient, creates a game settings table option that allows mods to set so that the escape key for the HUD and Options screen does the same thing as pressing Ctrl-Enter/Accept. This optional setting unifies behavior, so that setting an option sets it whenever the user leaves that screen (whether it is pressing Escape, Ctrl-Enter, or the Accept button). The other screen that involves options and an escape is the control config menu, but that already methods in place to deal with escape in a consistent way.

Tested and everything works as expected.

* fix oversight of saving when going to F3 menu

* update to enum for future additions

* cleanup with better naming

* update warning message

* one more warning cleanup
2025-02-20 08:35:24 -05:00
Goober5000 facaae79a7 Merge pull request #6593 from Baezon/linked-loop-firing-snd
add linked loop firing sounds
2025-02-19 20:44:15 -05:00
wookieejedi bfd8463f30 Make Cockpit Deferred an In-game Option (#6594)
* Make Cockpit Deferred an In-game Option

After testing and consideration, this PR adds the Cockpit Deferred setting to the in-game options. Also adds a parser to the new default_settings.tbl.

* cleanup comments
2025-02-19 07:51:57 -05:00
wookieejedi 881520b225 Update in-game joystick settings to work without restarting FSO (#6592)
* Setting in-game joysticks does not require restart

* have unsetting now work too

* use opportunity to cleanup og setting
2025-02-19 07:51:42 -05:00
Mike Nelson a1e0fe9f13 Add many options to default settings table (#6517)
* Add many options to default settings table

* typo

* clang
2025-02-16 21:55:07 -05:00
Asteroth 8c95178d19 add linked loop firing sounds 2025-02-15 22:33:20 -05:00
wookieejedi 7f506377bf Create scripting hook: 'On Options Menu Tab Changed' (#6591)
* Create scripting hook: 'On Options Menu Tab Changed'

It would be very useful to know which options tab is active (IE Options, Multi, Detail) but it's all under one single Game State `GS_STATE_OPTIONS_MENU`.

This PR creates a hook,  'On Options Menu Tab Changed'  that returns the value of the newly switched to options tab. Lafiel and I both discussed making this an ENUM, but the ENUM list is already quite bloated and this integer value seems like the cleanest solution.

Tested and works as expected.

* fix description typo
2025-02-14 21:37:47 -05:00
wookieejedi 07aedd195f Unify AI Usage of Shield Manage Delay (#6589)
* Unify AI Usage of Shield Manage Delay

`$AI Shield Manage Delay:` can be set in the AI profiles, but also set for AI specific classes. Currently, The values set for the specific AI class are only used `if (iff_x_attacks_y(Player_ship->team, Ships[objp->instance].team))`, otherwise the values in the AI profile are used.

Being able to have the shield delay work in a unified way according to the AI class values is very useful, especially for friendly wingmen that you want have different shield manage delays.

This PR adds a AI profiles flag to unify Shield Manage Delay behavior, so that it always works in the same way regardless of AI team conditions.

* cleanup unifying behavior along with CM firing chance

* restore what sushi had for now
2025-02-12 14:29:23 +00:00
Goober5000 271c83575d Merge pull request #6590 from Goober5000/optional_string_either_fix
fix two uses of optional_string_either
2025-02-11 23:22:55 -05:00
Goober5000 47c538f1be fix two uses of optional_string_either 2025-02-11 22:50:00 -05:00
Goober5000 43b8b579a1 Merge pull request #6582 from Goober5000/update_yaml
update workflows to accommodate actions/cache deprecation
2025-02-11 19:37:29 -05:00
BMagnu 7f13cb6287 Fix incorrect position calculation for thruster glows. (#6588) 2025-02-11 08:27:59 -05:00
Goober5000 e3d11dfb31 Merge pull request #6570 from Goober5000/order_updates
update script API for AI orders
2025-02-10 22:01:21 -05:00
Goober5000 55706d8937 Merge pull request #6569 from Goober5000/smol_tweaks
misceallaneous small fixes and tweaks
2025-02-09 15:17:31 -05:00
wookieejedi c76cb554c3 Allow modders to always show first game tip at start (#6585)
* Allow modders to always show first game tip at start

This PR adds a simple boolean that allows mods the ability to always show the game tips in the same order, starting with the first entry. This is particularly useful if the mod is introducing something to new players.

The current behavior is to pick a random starting location, so this PR just always starts at tip index 0.

Tested and works as expected.

* add comment clarification

* make into integer instead of bool

* better tips index setting method

* spelling and static cast

* one more static cast

* make actual warning

* clang and consistent order
2025-02-09 20:01:07 +00:00
Goober5000 6421116760 Merge pull request #6586 from Goober5000/weapon_detonation_addendum
addendum to fixed missile detonation
2025-02-09 14:45:41 -05:00
wookieejedi 1342f17a2d Allow mods to Always Show Directive Value Count (#6584)
* Allow mods to Always Show Directive Value Count

Previously, directive counts were not shown if the value was <= 1.
This PR adds a flag to always show the value, and tests work as expected. It also fullfills a longstanding statement from Mage

```
given that, aside from directive-value, all the code involving Directive_count seems to be volition:-original, it really is past time for a flag skipping this > 1 check
```

* cleanup
2025-02-09 13:45:37 -05:00
Goober5000 ad8dee0f2b addendum to fixed missile detonation
As discovered by PDFCommand and tracked down by Asteroth, there was another "missed target" check in `ship_weapon_check_collision()`, in addition to the more comprehensive check in `weapon_home()`.  Since the check is redundant and there is an existing `$Fixed Missile Detonation:`, skip the check if the flag is active.
2025-02-09 01:28:33 -05:00
Goober5000 e4553855ba update to a specific git commit, pending official v1.2.1 release 2025-02-07 22:27:58 -05:00
Goober5000 76b54c7be1 Merge pull request #6583 from Goober5000/lcase_stringcost
allow stringcost to be case-insensitive
2025-02-07 21:13:29 -05:00
Goober5000 97a06bda71 allow stringcost to be case-insensitive
Allow `stringcost()` to use a specified function to check equality, and provide both case-sensitive and case-insensitive sample functions.  Use case-insensitive checks for sexp operator lookup.
2025-02-07 00:39:50 -05:00
Goober5000 531494c4a3 update workflows to accommodate actions/cache deprecation
As reported by MjnMixael and tracked down by qazwsxal, actions/cache V2 is being removed at the end of the month:
<https://github.blog/changelog/2024-12-05-notice-of-upcoming-releases-and-breaking-changes-for-github-actions/#actions-cache-v1-v2-and-actions-toolkit-cache-package-closing-down>

Quoting qazwsxal:
> It's being hit inside humbletim/[email protected] as that's the last line before the error was hit. I've investigated that repo and a version bump to 1.2.1 should fix it as humbletim has updated the actions/cache version.

So, this bumps all the relevant humbletim repository references to 1.2.1.
2025-02-06 20:56:46 -05:00
Goober5000 ced716df35 Merge pull request #6580 from Goober5000/fix_6572
fix wing creation dialog
2025-02-05 20:28:35 -05:00
Goober5000 3b54488d3b Merge pull request #6565 from Goober5000/utility_functions
add some utility functions
2025-02-04 22:05:05 -05:00
Goober5000 3d1fce99ac fix wing creation dialog
When forming a wing, if there is a name conflict but the ship will actually be used in the wing, don't report the conflict.  Fixes #6572.
2025-02-04 00:36:51 -05:00
Goober5000 811507c62f update tostring functions 2025-02-04 00:34:39 -05:00
Goober5000 85cb0480e7 fix waypoint scripted sexp type to return a waypoint 2025-02-04 00:34:39 -05:00
Goober5000 1492e9c785 smol cleanup 2025-02-04 00:34:37 -05:00
Goober5000 417ba3bd25 Merge pull request #6566 from Goober5000/substitute_main_hall_fred
add Substitute Main Hall field to FRED campaign editor
2025-02-04 00:31:41 -05:00
Goober5000 c1c2079e46 fred support for substitute main hall 2025-02-03 22:14:58 -05:00
Goober5000 21531a2825 fix spelling and update dialog 2025-02-03 22:14:58 -05:00
Goober5000 5f73220cd1 Merge pull request #6559 from Goober5000/mission_goal_scripted_sexps
enable mission goals for scripted sexps
2025-02-03 21:42:07 -05:00
Goober5000 e7029c2ddb Merge pull request #6469 from Goober5000/vmallocator_update
some upgrades to vmallocator.h
2025-02-03 21:35:37 -05:00
BMagnu 23dc22e172 Unify Particle Attachment (#6571)
* Fix incorrect ship legacy particle curve assignment

* Setup trigger radius

* Properly attach particle sources to objects and subobjects

* Add trigger velocity for weapon impacts

* Onetime particle source timing fix

* Warnings

* Allow global_to_local to work with no submodel

* Allow global_to_local to work with no submodel, again
2025-02-03 22:14:19 +01:00
Mike Nelson 5b736b1ddc Hud config framework (#6495)
* Add scaling for vfnts and scale multipler to gr_string

* nullptr

* Add scaling to a couple other string operations

* Add scaling features to additional bitmap drawing methods

* Implement framework for rendering hud gauges in config mode

* fix merge error

* address feedback
2025-02-03 07:01:47 -05:00
Goober5000 f7396d53a8 Merge pull request #6567 from Goober5000/collect_magic_numbers
reduce magic numbers in missionweaponchoice
2025-02-02 22:28:40 -05:00
Goober5000 a533300b9e add getters for waypoint information 2025-02-02 15:25:47 -05:00
Goober5000 133b033ea0 some upgrades to vmallocator.h
Make `SCP_vector`, `SCP_list`, `SCP_set`, and `SCP_multiset` subclasses of their STL counterparts.  This allows helper functions to be added to each, including the `contains()` function which is not available until C++20.  (This has minor effects on other parts of the codebase that treated `SCP_` and `std::` as synonyms.)  Since there is now a nontrivial amount of code that needs to be in a .cpp file, create vmallocator.cpp.

Note that `SCP_string` truncation has been refactored to use length rather than C-string size to be consistent with other `std::basic_string` functions.

Also, remove some enum class hashing code which is no longer necessary now that the codebase is at C++17.
2025-02-02 14:54:26 -05:00
Goober5000 89e2f264fd update script API for AI orders
Allow waypoint orders to target a specific waypoint and go in reverse.  Add script access to waypoints and waypoint lists belonging to orders.

Fix assignment of targets and goal start times.  Assign targets when they are different (and thus need to be assigned), not when they are the same.
2025-02-02 12:04:43 -05:00
Goober5000 0a4ca56268 Merge pull request #6557 from Goober5000/update_gitmodules
update .gitmodules references
2025-02-02 11:33:02 -05:00
Mike Nelson 103ad70587 Allow preloading briefing icons (#6548)
* allow preloading briefing icons

* nullptr

* oops

* Fix from rebase
2025-02-02 16:42:36 +01:00
Mike Nelson 8afb41a368 allow scripted gauges to be off by default (#6562) 2025-02-02 11:05:35 +01:00
BMagnu 7c37e9932d Merge pull request #6564 from BMagnu/cpp_17_cleanup
C++17 cleanup followup
2025-02-02 18:31:14 +09:00
Goober5000 adf9ac0e22 Merge pull request #6561 from Goober5000/subsystemname
add subsystemname scripted sexp type
2025-02-02 02:31:02 -05:00
Goober5000 34e467b3a7 also update 2d.cpp to reduce warnings 2025-02-01 23:16:33 -05:00
Goober5000 2ec344d826 add some utility functions
Useful functions for utility.h and string_utils.h.  Adapt existing code accordingly.
2025-02-01 23:16:33 -05:00
Goober5000 8dc2d49e6a reduce magic numbers in missionweaponchoice
Use the existing definitions to improve code readability.
2025-02-01 23:04:20 -05:00
Goober5000 95a6438a77 change _SETTINGS to _LAYOUTS as it's more descriptive 2025-02-01 23:04:20 -05:00
Goober5000 5323cc32d6 Merge pull request #6506 from Goober5000/pstypes_changes
a few pstypes changes and refinements
2025-02-01 21:07:28 -05:00
Birk Magnussen ea002628a7 Clang Tidy 2025-02-01 22:46:43 +01:00
Birk Magnussen d9b9863e2a Clang Tidy 2025-02-01 22:26:11 +01:00
Birk Magnussen ada62c6c59 missing includes 2025-02-01 13:33:43 +01:00
Birk Magnussen 540d841f06 Remove any and variant libs 2025-02-01 13:26:28 +01:00
Birk Magnussen 1f2a8dce2a remove optional 2025-02-01 13:17:26 +01:00
Mike Nelson 7bb85b8604 Allow VFNTs to auto scale and disallow auto scaling in FRED (#6546)
* allow VFNTs to auto scale and disallow auto scaling in FRED

* fix shadowing

* Update FSFont.cpp

* don't code from your phone, mjn

* refactor to use one central method
2025-01-31 09:35:57 -05:00
Mike Nelson 65c4e333a4 this should be local 2025-01-31 08:18:00 -06:00
Goober5000 2a6017cb73 enable mission goals for scripted sexps
Add "goal" as a type recognized by scripted sexps.  Also add `mn.Goals` as a collection to complement `mn.Events` and move the goal type to goal.cpp and goal.h to match event.cpp and event.h.  The new `mn.Goals` collection contains the same data as the existing `Objectives` collection in the briefing UI library, so the latter could be deprecated.
2025-01-30 22:09:29 -05:00
Goober5000 ca624f86e2 a few pstypes changes and refinements
Several changes related to the volumetrics model fix:
1. Update the `model_load()` prototype with better parameter names, including a new `ErrorType` enum defined in pstypes.h
2. Update the `MIN`, `MAX`, and `CLAMP` macros, all of which were susceptible to performance issues because they duplicated their tokens.  This could cause functions or calculations to be re-run unnecessarily.  Since the codebase is now on C++17, `std::clamp()` can be used.
3. Update the rest of the codebase to fix any associated issues.
2025-01-30 21:35:03 -05:00
Goober5000 2f75155721 add subsystemname scripted sexp type
This type for subsystems is analogous to the shipname type for ships.  Sometimes it is useful to refer to a subsystem even if its parent ship is not present.  Whereas the subsystem object would be invalid, the subsystemname string still contains the string that the mission designer specified.

Relatedly, upgrade the parsing of `+Parent Parameter Index:` to be checked on both parented and non-parented parameters.  This will help both modders who put the field in the wrong place and programmers who may want to add a parented parameter in the future.
2025-01-30 21:05:38 -05:00
Goober5000 028a03748f Merge pull request #6556 from Goober5000/fix_sidethrust
fix random sidethrust call
2025-01-30 20:31:15 -05:00
BMagnu b4905d111f Fix outputs being not passed along in input-only derive case (#6558) 2025-01-30 17:52:18 +00:00
BMagnu 82236ccd9f Merge pull request #6465 from BMagnu/particle_cleanup
The definitive Particle Effect rework
2025-01-30 17:20:42 +09:00
Goober5000 de7345c710 update .gitmodules references
Use the repository URLs, rather than @asarium's user-specific URLs.  Follow-up to #6552.
2025-01-29 17:39:14 -05:00
Mike Nelson 922ff160e2 Check for invalid player progress (#6554)
* check for invalid player progress

* clarity

* requested change
2025-01-29 13:37:01 -05:00
BMagnu d9e859aac0 Remove Typo and fix volumetrics merge issue 2025-01-29 09:30:43 +01:00
Goober5000 88d7bbf57b fix random sidethrust call
This function call checked the acceleration of the targeted object, rather than the active object as it should have.  Fix it to check the active object.  For mods that use `$Random Sidethrust Percent:` (such as Inferno), this fixes a bug that could cause an invalid memory access in situations where the targeted object is -1.
2025-01-29 02:32:44 -05:00
Mike Nelson 4f503ec419 fix countermeasure virtvars (#6553) 2025-01-28 17:14:52 -05:00
Mike Nelson 949a37267b move warp flash option to table 2025-01-28 15:33:54 -06:00
Mike Nelson 7e5a07dc0f move 3d warp option to table 2025-01-28 15:25:21 -06:00
Goober5000 3f44bf4f9f Merge pull request #6552 from Goober5000/update_libRocket
update libRocket reference
2025-01-27 18:12:31 -05:00
Goober5000 f2c2fd2644 Merge pull request #6547 from Goober5000/campaign_tree_fix
fix crashing in campaign tree in FRED
2025-01-27 18:12:16 -05:00
Goober5000 f25b57851e update libRocket reference
Update the libRocket commit hash to the latest revision in scp-fs2open/libRocket.  Fixes #6551.
2025-01-26 22:49:07 -05:00
BMagnu 64bfc4a329 Allow Submodel hosts for non-ship objects 2025-01-26 23:42:19 +01:00
Goober5000 51c485ea23 Merge pull request #6550 from jg18/fix/issue-6549
Fix map container mutation issues
2025-01-26 17:26:28 -05:00
Joshua Glatt 19b849fd71 disallow all forms of add-to-map with a container used in special arg 2025-01-25 16:47:05 -08:00
Joshua Glatt 05e1a7a429 fix map container mutation issues 2025-01-25 16:08:49 -08:00
Goober5000 a76d3528fc fix crashing in campaign tree in FRED
Occasionally a link endpoint could be -1, such as with End of Campaign links, but there were no checks in the `add_link` and `remove_link` functions to protect against array accesses with a -1 index.  Add checks in several places for this.
2025-01-24 21:45:27 -05:00
wookieejedi c4341518bb Allow Modders to Tune Guarding (#6544) 2025-01-23 19:14:51 -05:00
Gamma39er ab004848ee Table based warp parameters and new custom warp animations. (#6500)
* Made lens flare size proportional to model size.

* Updated fireball_wormhole_intensity function to be smooth and unbreakable

* Added variable frame frate warp and new lens flare animation.

* Last animation changes made since I stopped coding.

* Made cinematic animation, warp-size ratio, and flare-size-ratio parameters configurable by table. New exp_to_line function to be more consistent and to fix a bug.

* Made everything configurable by table.

* Updated default values for cinematic warp animation.

* Fixed the usage of MAX() so that it assigns to the variable.

* Fixed obvious freakin' double to float casting warnings.

* Made requested changes. Flare animation can now be specified with an enum and default else statements will not override earlier entries.

* Changed warp table parameters to Warp flare style and Warp model style.

* Added defaults to switch statements, and made this backwards compatible with older mediavps.

* Removed commented code.

* Opened up flare flickering for table editing.

* Restored cinematic warp flare ratio default.
2025-01-24 00:35:38 +01:00
Mike Nelson 9271da7e7c build in the common z load first methods and forwarders 2025-01-23 10:42:19 -06:00
Mike Nelson 2047bfacd0 Fix child enums in lua sexps (#6543)
* fix child enums in lua sexps

* variable shadow

* comments
2025-01-22 07:55:06 -05:00
Goober5000 f102cc3ebf Merge pull request #6537 from Goober5000/functional_if_then_else_fix
fix NaN for functional-if-then-else
2025-01-21 23:06:58 -05:00
wookieejedi a80dfd8961 Cleanup few In-game Defaults (#6542) 2025-01-21 20:25:28 -05:00
Goober5000 39438e1049 Merge pull request #6514 from Goober5000/hitpoint_fixes
make hitpoint sexps safer to use in debriefing
2025-01-20 20:28:23 -05:00
Goober5000 57fb8dbf8a Merge pull request #6541 from Goober5000/sexp_documentation
update sexp documentation
2025-01-20 20:27:54 -05:00
Goober5000 584e9e85d5 update sexp documentation
Clarify some sexp help descriptions.
2025-01-20 18:07:19 -05:00
wookieejedi 750c3845ff Fix more Popup Button Alignments (#6539)
There were 2 popup dialogs that were missing an `Affirmative` flag, which mean the button was not in the right position and thus showed a visual misalignment. This PR fixes that and in tests works as expected.
2025-01-20 15:41:31 -05:00
wookieejedi bd2094c2b6 Ensure that Ext Game Popup sends Affirmative and Negative Flags (#6538)
`On Dialog Start` (used in SCPUI and within `popup_init`) reads popup options by affirmative or negative flags, and the popup for exiting the Mainhall did not set these flags. Notably, most popups that use `POPUP_NO` or `POPUP_YES`  already, so this PR sets those flags for this popup. Now `On Dialog Start` within `popup_init` has access to the correct flags.

PR tested and works as expected, both in retail UI and SCPUI
2025-01-20 15:41:16 -05:00
Goober5000 a606ed73a4 fix NaN for functional-if-then-else
Any NaN encountered in the evaluation of functional-if-then-else should be isolated to the branch on which it occurs.  Fixes #6536.

Also improve some help text for clarity.
2025-01-20 08:47:04 -05:00
BMagnu 5ce7881a27 Merge branch 'master' into particle_cleanup 2025-01-19 19:56:18 +09:00
Goober5000 1c821412cf Merge pull request #6529 from Goober5000/fix_event_editor_modification_check
fix event editor modification check
2025-01-18 13:41:25 -05:00
Goober5000 b1406bcb3e Merge pull request #6535 from Goober5000/set_with_breed
make line-of-sight objects aware of its subclasses
2025-01-18 13:41:10 -05:00
Mike Nelson adb0fa6ade fix input text string rendering (#6533) 2025-01-18 08:04:08 -05:00
Mike Nelson bcea174509 Mission goals hook (#6534)
* mission goals hook

* Change hook name

* text
2025-01-18 08:03:50 -05:00
Goober5000 1c2117095a make object aware of its subclasses
Looking through all places in the scripting API where `l_Object.Set()` is called, here is one where we might want to know about the object's breed.

(Normally we would return the result of `ade_set_object_with_breed()`, but the `testLineOfSight_internal()` function has multiple return arguments.)
2025-01-17 18:00:27 -05:00
Goober5000 5f2cefd130 Merge pull request #6527 from Goober5000/kamikaze_ships_attack_subsystems
fix kamikaze attack of subsystems
2025-01-17 17:00:19 -05:00
Goober5000 f63c550e03 Merge pull request #6530 from Goober5000/update_window_2
re-remove Update_window check
2025-01-17 17:00:09 -05:00
Goober5000 af11d1c8c6 fix event editor modification check
The `query_modified()` function in FRED did not correctly check whether messages were modified, although interestingly, it did so in qtFRED.  Even in qtFRED, there were a few minor omissions.  Overall, this fixes FRED and syncs up the FRED and qtFRED versions.

Fixes #6528.
2025-01-16 21:27:30 -05:00
Goober5000 9a0fa3c289 re-remove Update_window check
At some point between 2002 and 2006, the Update_window code was removed, but since we don't have FRED history from that period, we don't know the exact rationale.  However, since FRED appears to have no difficulty rendering every frame, and since there may be parts of FRED that don't set Update_window when they need to (for example, the background editor), let's keep this disabled.

Follow-up to #6435.  Fixes the background not updating when a bitmap is moved in the background editor.
2025-01-16 21:22:55 -05:00
Goober5000 c4d17053d6 Merge pull request #6524 from Goober5000/object_model_functions
tweak object model/instance convenience functions
2025-01-16 21:00:43 -05:00
Goober5000 04068fc83a fix kamikaze attack of subsystems
Kamikaze ships entering broadside mode (`ai_cruiser_chase()`) would always point toward the center of the ship.  With this fix, they will point toward a subsystem if attacking one.  (In practice this situation had not been encountered before, since by default the ai-destroy-subsystem order is only available to fighters and bombers, which do not use broadside mode.)
2025-01-16 15:47:49 -05:00
Mike Nelson c9ccace89a Lua set mainhall (#6498)
* lua set mainhall

* boolEAN

* tidy
2025-01-16 07:44:38 -05:00
Mike Nelson b367fe8441 Some minor Control Config UI changes for SCPUI (#6508)
* allow preset override from Lua and change a warning to a popup if we're in the UI

* const it up

* headers might help, too, dummy
2025-01-16 07:44:16 -05:00
Goober5000 fa10f8e8eb tweak object model/instance convenience functions
Make these convenient functions even more convenient:
1. Change `object_get_model()` to `object_get_model_num()` and `object_get_model_instance()` to `object_get_model_instance_num()` to more accurately reflect what they do
2. Add new `object_get_model()` and `object_get_model_instance()` functions to return `polymodel*` and `polymodel_instance*` values.
2025-01-16 01:10:53 -05:00
Goober5000 9880694dcc Merge pull request #6526 from wookieejedi/failsafe-for-tex-replace-fix
Add failsafe check for new texture replace fix
2025-01-16 00:29:21 -05:00
wookieejedi 454b80e3eb Add failsafe check for new texture replace fix
One line failsafe condition
2025-01-15 16:50:20 -05:00
Goober5000 a4d9b23802 Merge pull request #6523 from Goober5000/fix_precedence_per_bank
fix player weapon precedence to include per-bank restriction
2025-01-15 15:02:25 -05:00
mjn-mixael 15c4e35ac4 match updated signature 2025-01-15 08:52:58 -06:00
mjn-mixael 9fc0f35cc7 Merge branch 'master' into enhance_vasudan_cheats
# Conflicts:
#	code/graphics/2d.cpp
#	code/graphics/2d.h
2025-01-15 08:46:02 -06:00
Mike Nelson f94e12db4a Add missed popup for on dialog frame and add text hook var (#6522)
* add missed popup for on dialog frame and add text hook var

* int to bool

* redundant bool
2025-01-15 09:42:58 -05:00
Mike Nelson a42a3fb49d Add scaling features to additional bitmap drawing methods (#6487) 2025-01-15 09:42:21 -05:00
Mike Nelson 8a09caab97 Fix font multiplier in release builds (#6525)
(cherry picked from commit 763616f824b86d74bd7e2ded7abc48770e3e8d1c)
2025-01-15 09:41:20 -05:00
Mike Nelson d27f735588 Add scaling for vfnts and scale multipler to gr_string() (#6481)
* Add scaling for vfnts and scale multipler to gr_string

* nullptr

* Add scaling to a couple other string operations

* Don't scale fonts in FRED
2025-01-14 15:05:06 -05:00
wookieejedi b29e397fa7 Fixes Debris not inheriting parent ship texture replacements (#6519)
* Fixes Debris not inheriting parent ship texture replacements

Debris chunks that use the same texture as the actual hull model are not updated when `texture-replace` methods are used. For example, a clean grey base textures that has texture replace via table or FRED is changed to red/brown. But when the ship is destroyed the debris objects are using the original lighter texture instead of the newer darker one.

#6154 provided the groundwork to fix this, but one step fell through the cracks; setting the debris hull textures to what the parent ship used.

This PR sets the debris texture replacements when debris is created to fix this (and fixes #2462).

Fix is tested and works as expected.

* cleanup setting shared

* get pmi correctly
2025-01-14 07:42:46 -05:00
Goober5000 60ed388826 give loop counter variable a better name 2025-01-13 22:35:55 -05:00
Goober5000 f9aa53c569 fix player weapon precedence to include per-bank restriction
Inferno reported a bug where the unavailability of weapon A could result in weapon B being assigned to a particular weapon bank, even if weapon B was disallowed for that bank.  Add a per-bank restriction check to fix this.
2025-01-13 22:26:31 -05:00
wookieejedi 7a07c995ca Add Mod Option to Limit 'Show Ship' when Toggling Cockpits (#6513)
* Add Mod Option to Limit 'Show Ship' when Toggling Cockpits

FotG uses cockpits and 'show ship', and also provides a way for players to toggle off cockpits. Unfortunately, if the player disables cockpits, 'show ship' still appears and looks very odd (since it appears the player is flying a ship with a hole in the center where the cockpit would be). Other mods have made entire ships with their cockpits, but FotG needs to use 'show ship' to match team colors and moving external ship animations.

This PR adds a game_settings option that allows mods to set to only use 'show ship' if cockpits are enabled.

Tested and works as expected.

* simplify logic

* fix typo
2025-01-13 19:30:30 +00:00
Mike Nelson feb0932015 lua access to max ships per wing (#6510) 2025-01-14 00:57:08 +09:00
Asteroth 48e5ea0688 shrink minimum warning for modelss (#6515) 2025-01-14 00:56:52 +09:00
EatThePath 976ac04369 updating my own name (#6518) 2025-01-14 00:56:24 +09:00
Goober5000 cecfd9f7ff fix calculation of percent_killed
This has been broken ever since commit 6c17ef09ab in 2005.  Since `get_hull_pct()` did not return negative values, `percent_killed` was always 0.  Allow negative values in this case.
2025-01-12 16:52:16 -05:00
Goober5000 0e98d01ce5 use the ship pointer version of shield_get_max_strength() where appropriate 2025-01-12 16:52:16 -05:00
Goober5000 eeffbd692f make hitpoint sexps safer to use in debriefing
There is a rather large design flaw in FreeSpace debriefings... debriefing SEXPs can refer to in-mission ship data, while all ships (and all objects) are deleted as soon as the mission completes.  Specifically, `obj_delete()` is called which sets all objects to `OBJ_NONE` and marks them as freed, although the data still exists in the various arrays.  This is the use-after-free problem, but applied to the in-game object system, rather than memory accessed by pointers.

It's probably best to defer fixes to an as-needed basis.  As for hitpoint SEXPs, this change updates them to use the object and ship references from the ship registry, since the ship registry is not cleared by the time the debriefing is loaded.  (Using `objp->instance` and `shipp->objnum` at this point would be problematic.)  Since subsystems are also cleared at this point, this also updates the warning messages in those functions.

Fixes an Assert seen in debug mode in Inferno.
2025-01-12 16:52:16 -05:00
Goober5000 7cf7f0ea4e Merge pull request #6512 from Goober5000/looping_sound_fixes
fix volume updates for looping sounds
2025-01-12 16:00:12 -05:00
mjn-mixael 0326db10ff Merge branch 'master' into enhance_vasudan_cheats
# Conflicts:
#	code/utils/string_utils.cpp
2025-01-12 12:20:59 -06:00
Mike Nelson 4dfaa85b6f Default settings tbl (#6491)
* initial version of default_settings.tbl

* Add a way to change player detail level defaults and implement a couple more options to detail_settings.tbl

* support the rest of 2d.cpp options

* Allow enforcing options to a specific value

* modernize detail defaults, levels, and values

* Fix parsing issue and remove lambda capture by reference

* fix print

* clang

* More efficient +Enforce parsing

* cleanup

* typo

* don't negate this

* error_display

* clarify language between presets, levels, and values

* add default case

* small fix

* use a map to minimize string lookups
2025-01-12 11:29:11 -05:00
wookieejedi de969b5e76 Allow Modders to Tune Strafing (#6511)
* Allow Modders to Tune Strafing

Many mods change ship velocities and damp values, but this commonly leads to poor behaviors attacking large ships within strafe mode (which is the main method for attacking big ships in a sustained way). As an example, FotG has damp and velocity values that are higher than base FS, thus the defined strafe values result in behavior where fighters never can complete a sustained firing pass against a large ship unless they are sitting and parking (which does not fit our goals to match the movie).

The values for dictating how strafe behavior occurs are easily editable by changing some key values, which this PR exposes to modders. Furthermore, mods may give large ships very long range weapons, so being able to set how far away a ship should do a strafe run begins is very valuable.

In testing it was very easy to get desired behavior of having AI do long sustained strafing runs. I estimate other mods will likely be able to leverage these values to tune strafing behavior.

I did numerous tests and evaluations finding the best balance of values to expose. I would be happy to discuss these changes in detail too, as I know this exposes a number of values.

* clang

* incorporate feedback
2025-01-12 08:08:05 -05:00
Goober5000 acfe6a17ac fix volume updates for looping sounds
Now that `snd_do_frame()` has been tightened up to specifically only adjust audio for the adjust-audio-volume sexp, the redundancy-avoiding code in `snd_set_volume()` is obsolete.  So, set the sound volume immediately, even if it is a looping sound.

This is a two-for-one fix; the proper setting of volume fixes both #6504 and #6507.
2025-01-11 15:23:57 -05:00
Goober5000 b40fab6739 update looping sound data structures
Change `currentlyLoopingSoundInfos` and `currentlyLooping3dSoundInfos` from lists to maps.  The data structure should keep track of the volumes currently, as opposed to historically, associated with each sound handle.

Since the map requires `util::ID` and its derivatives to be hashable, add `util::ID_Hash`.
2025-01-11 15:23:57 -05:00
Goober5000 a2141865e1 Merge pull request #6467 from Goober5000/ai_goal_refactor
Ai-goal refactor
2025-01-11 15:10:48 -05:00
Goober5000 49de71d269 Merge pull request #6505 from Goober5000/hull_pof_graceful_fail
gracefully fail if volumetrics model is not found
2025-01-06 13:02:18 -05:00
Mike Nelson b49db4ef7b Add Lua global variables library (#6472)
* add global variables library

* nested namespaces
2025-01-06 17:36:59 +09:00
Goober5000 1527824f77 gracefully fail if volumetrics model is not found
If the volumetrics model cannot be loaded, fail gracefully by warning and not generating volumetrics.  This prevents a hard exit in the event of a model problem, particularly when a mission is being edited in FRED.
2025-01-06 01:56:46 -05:00
wookieejedi 65dd3a72d6 Fix offset dialog option image with controls preset confirmation (#6502) 2025-01-05 16:55:46 -05:00
Mike Nelson 402ca07c13 Allow per-stage briefing grid colors (#6448)
* Allow per-stage briefing grid colors

* parameter name

* remove redundant initializer

* const const const

* check for 25_0 mission data

* 24.3 instead of 25.0

* clang
2025-01-05 22:48:32 +01:00
Birk Magnussen 467bc32633 Merge branch 'particle_cleanup' of github:BMagnu/fs2open.github.com into particle_cleanup 2025-01-05 17:04:13 +01:00
Birk Magnussen 45c7ee1a45 Get rid of cast warnings on MSVC 2025-01-05 17:03:16 +01:00
Mike Nelson 297a9389cd Func to get a ship's persona directly (#6497)
* func to get a ship's persona directly

* virtvar instead of func

* get persona index

* lua index
2025-01-05 10:22:32 -05:00
BMagnu a0e9f0d450 Merge branch 'master' into particle_cleanup 2025-01-03 05:50:23 +09:00
Goober5000 8baee0470a refactor AIG_TYPE_* into enum classes 2025-01-02 14:05:21 -05:00
Goober5000 423042bf11 refactor AI_GOAL_* #defines into enums, and remove bitwise operations on them [FRED and qtFRED] 2025-01-02 14:05:21 -05:00
Goober5000 c38882a51e refactor AI_GOAL_* #defines into enums, and remove bitwise operations on them [non-FRED] 2025-01-02 14:05:21 -05:00
wookieejedi fa8e5845af Merge pull request #6493 from TheForce172/fix/QTFRED_Title_Bar
QT Fred Boillerplate Removal and Memory Safety
2025-01-02 13:30:58 -05:00
Asteroth ca243a0a6a Make explicit shield hit radius for ships and weapons (#6478)
* allow shield effect radius overrides

* this should be a float

* change variable name

* skip rendering 0 radius
2025-01-02 12:56:46 +01:00
wookieejedi fe722cbab7 Fix Mouse XSTR Index in In-game options (#6501)
In the In-game options for `mouse_mode` the XSTR index for "Mouse" was set to 1774, which is already used for "Glide When Pressed". Luckily "Mouse" XSTR already exists with Index 1373, so this PR changes it to that.
2025-01-02 12:53:39 +01:00
Mike Nelson 369ed0f5c0 prefer ship tech model if it exists (#6499) 2025-01-01 09:54:32 -05:00
Goober5000 a8a9fea4dc Merge pull request #6451 from Goober5000/set_squadron_wings
add set-squadron-wings sexp
2024-12-30 21:06:23 -05:00
Goober5000 8a86254aeb Merge pull request #6496 from daftmugi/fix-antlr4-cmake-deprecation-warnings
Fix antlr4 CMake deprecation warnings
2024-12-30 21:05:40 -05:00
Goober5000 ca9edc0c6b Merge pull request #6483 from daftmugi/add-campaign-cmdline
Add '-campaign' cmdline option to set current campaign
2024-12-30 21:03:13 -05:00
The Force 77de5c0aa7 Address Feedback 2024-12-30 17:37:05 +00:00
Daft Mugi cda02de4a0 Fix antlr4 CMake deprecation warnings
The deprecation warning that required changes:

* CMP0054: Only interpret if() arguments as variables/keywords when unquoted.

The deprecation warnings that did NOT require changes as those
features were not used:

* CMP0026
* CMP0042
* CMP0045
* CMP0059
2024-12-29 17:45:30 -06:00
Goober5000 c3e9099e9d Merge pull request #6492 from Goober5000/immobile_flag_migration_checks
add safeguards to the "immobile" flag migration
2024-12-29 18:32:53 -05:00
Mike Nelson a99dd120f7 Merge branch 'master' into enhance_vasudan_cheats 2024-12-29 11:07:44 -06:00
Mike Nelson f1271cde03 fix warp flash option (#6494) 2024-12-29 12:01:59 -05:00
Goober5000 755512ca00 Merge pull request #6488 from Goober5000/adjust_audio_volume_adjustments
adjust-audio-volume adjustments
2024-12-29 00:35:01 -05:00
Goober5000 9770888376 Merge pull request #6480 from daftmugi/ensure-pref-path-trailing-slash
Ensure custom preferences path ends with path separator
2024-12-29 00:34:18 -05:00
The Force 22ec235c22 Add missing override 2024-12-28 15:53:36 +00:00
The Force 5b3df07473 And unused 2024-12-28 15:39:05 +00:00
The Force d6c9ff43d7 Asteroid editor and add delete on close to a few more unchanged dialogs 2024-12-28 15:17:23 +00:00
The Force 76abb2819d Update Command Briefing Dialog 2024-12-28 14:52:53 +00:00
The Force bb589059c5 Update Wing names dialog 2024-12-28 14:44:31 +00:00
The Force 30bc3c78ac Add delete on close to dialogs that don't need other changes 2024-12-28 14:29:11 +00:00
The Force 68c2fcc31c Update Ship editor dialog 2024-12-28 14:28:32 +00:00
The Force abdef2ca07 Update Object Orientation dialog 2024-12-28 14:26:45 +00:00
The Force 2b1bf2c1bb Update Mission Goals dialog 2024-12-28 14:23:35 +00:00
The Force d94da96ca4 Update Shield Dialog 2024-12-28 14:22:16 +00:00
The Force 5892edaf57 Update Reinforcements dialog 2024-12-28 14:17:41 +00:00
The Force 069a30c190 Update Mission Spec dialog 2024-12-28 14:16:27 +00:00
The Force 5b23d9d3b8 Update loadout dialog 2024-12-28 14:15:14 +00:00
The Force 24590dd548 Update Fiction Viewer 2024-12-28 14:09:48 +00:00
The Force a26d52dcea Revert "Slightly off topic but remove C style casts from selection dialog"
This reverts commit 2a7806d690.
2024-12-28 14:07:11 +00:00
wookieejedi 7931a55744 Update JOY_NUM_BUTTONS to 128 (#6479)
Follow-up to #6371 (and replaces #5960 since the goal of that PR was already taken care of with #6371 adding the procedural translation).

Overall tagging this as 25.0 since multiple folks have asking about bumping the limit
2024-12-28 08:37:22 -05:00
wookieejedi 0832667744 Fixes Joystick Hat Labeling (#6486)
* Fixes Joystick Hat Labeling

Fixes mislabeling of joystick hat names that appeared in #6371. Tested and confirms this fixes the issue.

* fix ordering oversight
2024-12-28 08:37:07 -05:00
Goober5000 2f18741258 add safeguards to the "immobile" flag migration
When a mission is loaded in FRED the "immobile" flag is migrated to "don't-change-position" and "don't-change-orientation".  So, notify the FREDder that this is happening, and add checks to the "potential issues" checker to guard against mixing the old and new flags.

Follow-up to #6304.  Resolves #6489.
2024-12-27 17:07:47 -05:00
Goober5000 04d36a31c8 add the FredOnMissionLoad hook (sync with original FRED) 2024-12-27 01:03:22 -05:00
Goober5000 e3393c1bea adjust-audio-volume adjustments
Make some modifications to the adjust-audio-volume infrastructure:
1. Add an `aav_volume` array for ease of access to all three volume variables.  Refactor `snd_adjust_audio_volume()` to use this array to avoid duplicating code.
2. Move `update_looping_sound_volumes()` to be handled in parallel with `audiostream_set_volume_all()`, and for the same reason: avoid setting the sound volume for every looping sound on every frame if the volume has not changed.
3. If the volume is to be adjusted immediately, apply the relevant changes without waiting for `snd_do_frame()` to be called on the next frame.  Resolves #6291.
4. Fix some edge cases in `adjust_volume_on_frame()`.
2024-12-24 22:36:31 -05:00
Goober5000 7c82072f0c Merge pull request #6484 from Kestrellius/weapon-light-followup
Weapon light followup
2024-12-24 19:31:27 -05:00
Goober5000 08b24dba62 use range-based for 2024-12-24 15:52:50 -05:00
Goober5000 d73eaf08ca add set-squadron-wings, part 3
Move a lot of the logic into hudwingmanstatus, and preserve the wing information that is common from one display to the next.
2024-12-24 15:52:50 -05:00
Goober5000 123d68d94d add set-squadron-wings, part 2
Refresh the ship position and HUD status for the new wings.
2024-12-24 15:52:50 -05:00
Goober5000 7af523bdf3 convert ignore and used to bool 2024-12-24 15:52:50 -05:00
Goober5000 e58573158c add set-squadron-wings, part 1
SEXP infrastructure and partial implementation, excluding refresh of ship position and HUD status for the new wings.
2024-12-24 15:52:48 -05:00
Goober5000 6487abd57f put operators in proper category; add newlines to sexp help 2024-12-24 15:51:21 -05:00
Goober5000 82304a2a2d Merge pull request #6482 from daftmugi/cmake-build-with-discord-option
Add FSO_BUILD_WITH_DISCORD cmake option
2024-12-24 13:46:58 -05:00
Goober5000 a3b709cd12 Merge pull request #6453 from Goober5000/add_remove_goal_sexp_updates
enhance the add-goal and remove-goal sexps
2024-12-24 13:42:15 -05:00
Goober5000 5c737a5bf9 improve campaign file extension handling (#6443)
As discovered by WouterSmits, campaigns with periods in their filenames caused issues with FSO's campaign handling.  Specifically, in The Babylon Project, the EA-Minbari war v1.0.fc2 campaign would not save progress because FSO expected EA-Minbari war v1.fc2 in certain places.  This is because the `_splitpath()` function attempted to remove an extension from a filename that already had it removed.  For most campaigns this did not matter, but WouterSmits found a campaign where it did.

To solve this, there is now a new `util::get_file_part()` function to remove the path without removing the extension.  This replaces `_splitpath()` for campaign files, as well as the similar `clean_filename()` and `GetFilePart()` functions in other places.  All code paths were inspected for any chance of inadvertent extension adding, and Assertions were added to verify future code.  The only potential problem area was `player:loadCampaignSavefile()` which now pre-removes the campaign extension if needed.
2024-12-22 22:31:58 +01:00
Daft Mugi 642ff82833 Add FSO_BUILD_WITH_DISCORD cmake option 2024-12-21 22:50:51 -06:00
Kestrellius 2375ea380e Cleans up weapon light casting. 2024-12-21 19:09:10 -08:00
mjn-mixael 75a8e8ca9c remove duplicates from rebase 2024-12-21 12:51:13 -06:00
Mike Nelson 9781da6bad hardcode the retail details at parse time instead of run time 2024-12-21 12:45:52 -06:00
Mike Nelson 9f41075adf manually merge pr 6426 2024-12-21 12:45:51 -06:00
Mike Nelson 72c2d7b25f Fix rebase error 2024-12-21 12:45:15 -06:00
Mike Nelson bdb2e7cd8c Only change sounds for headz regions 2024-12-21 12:45:15 -06:00
mjn-mixael 734e3e25bd a little additional cleanliness and clarity 2024-12-21 12:45:14 -06:00
mjn-mixael 09d1461b06 Clang clang clang! Clanging on muh brain! 2024-12-21 12:45:14 -06:00
mjn-mixael 463cac74bd Upgrade fishtank to allow for all anim types and allow mainhalls to manually set the fish anim file 2024-12-21 12:45:14 -06:00
mjn-mixael f82f86ca82 Expose fish and headz cheat for custom mainhalls to use 2024-12-21 12:45:14 -06:00
Goober5000 c20ec965c0 fix a few bugs in the Vasudan heads cheat (#6426)
There were several bugs and design issues in the Vasudan headz cheat, probably due to being coded in a hurry right before release:
1. Although the cheat activated on the main hall, it was not immediately apparent, requiring the player to switch screens and come back
2. The detection of whether the main hall is Vasudan did not work after the cheat was activated, due to the background filename changing (this one is actually not Volition's fault)
3. The implementation of the cheat was actually in the wrong section of code, resulting in some confusion

These are now fixed.  The cheat can be enabled or disabled from one function, the graphics are reloaded properly, and the main hall detection includes the cheat-active version of the main hall.  Also, the door sounds have been slightly refactored to use a `std::pair` rather than a vector, since there are exactly two sounds, an open and a close.
2024-12-21 12:43:41 -05:00
Daft Mugi 440eed69d2 Ensure custom preferences path ends with path separator
Example:
  Given: FSO_PREFERENCES_PATH='./config' fs2_open
  Path becomes: './config/'
2024-12-21 02:35:01 -06:00
Kestrellius d81b48bd74 Weapon light bugfix (#6474)
* Fixes weapon light bug.

* Improves elegance.

* Extends fix to missiles.

* further elegance

* more cleanup

* optimization
2024-12-21 02:28:21 +01:00
Mike Nelson 6ca9555218 Upgrade head ani handling (#6338)
* null -> nullptr

* always loop head anis feature

* Add newer head ani choice method

* properly handle death messages
2024-12-20 09:04:32 -05:00
Daft Mugi c7025f47e0 Add FSO_BUILD_WITH_OPENXR cmake option (#6477)
* Windows and Linux default to ON
* macOS defaults to OFF
* User can override default on the command line
2024-12-20 12:06:29 +01:00
Daft Mugi 32a71e6b55 Add '-campaign' cmdline option to set current campaign
This allows the current campaign to be set on FSO launch so that the
player isn't interrupted by the "The currently active campaign cannot
be found" dialog when changing mods.

Example usage:
  fs2_open -campaign freespace -mod fsport
2024-12-19 16:05:11 -06:00
Mike Nelson 7f48375a6d Add underlining as a custom decorator (#6399)
* add underlining and corner border custom decorators

* some cleanup

* CLANG
2024-12-18 17:33:39 +09:00
Goober5000 9b1d4258e9 Merge pull request #6464 from Goober5000/fix_engine_wash
fix engine wash
2024-12-17 14:25:11 -05:00
BMagnu f4bd6aa003 Correctly process ImGUI flags (#6468) 2024-12-17 10:56:29 +01:00
The Force 2a7806d690 Slightly off topic but remove C style casts from selection dialog 2024-12-17 08:32:08 +00:00
Goober5000 91b54c759e Merge pull request #6424 from Goober5000/credits_substitute_music
add $Substitute Music: for credits.tbl
2024-12-16 12:15:49 -05:00
Goober5000 b7c676132a Merge pull request #6446 from Goober5000/docked_warpIn
fix ship:warpIn() behavior for docked ships
2024-12-16 12:12:46 -05:00
Goober5000 1c9066485c STL fixes and cleanup (#6455)
* fix some usages of std::transform

* change parse_string_flag_list to use a reference

* add a variant of parse_string_flag_list that can use a SCP_set, and make a templated version of flag_def_list
2024-12-16 18:12:30 +01:00
Goober5000 2456f02b23 Merge pull request #6463 from Goober5000/subsystem_flag_fix
fix sexp_ship_deal_with_subsystem_flag()
2024-12-16 12:11:56 -05:00
Birk Magnussen 284fb4a305 Even More MSVC warnings 2024-12-16 15:53:07 +01:00
Birk Magnussen a2a1910826 More MSVC warnings + clang tidy 2024-12-16 15:29:40 +01:00
Birk Magnussen 05259a5b6c Make sure that clang does accept implicit random range copy constructors 2024-12-16 15:06:26 +01:00
Birk Magnussen aecc2ab31f Fix macos target 2024-12-16 15:01:17 +01:00
Birk Magnussen 6ab3d5310a Fix template deduction for GCC pre 14 2024-12-16 15:01:01 +01:00
Birk Magnussen 55bb2095bb Clang tends to have weird behaviour for is_convertible apparently 2024-12-16 14:45:37 +01:00
Birk Magnussen d19f36a58d Remove incorrect forward 2024-12-16 14:24:01 +01:00
Birk Magnussen ec0e55d077 De-movify random ranges 2024-12-16 14:22:29 +01:00
Birk Magnussen ec027bde87 Fix compile issues 2024-12-16 13:26:47 +01:00
Birk Magnussen 8323d9ed2f Fix parsing 2024-12-16 13:05:38 +01:00
Birk Magnussen b22716a4d2 remove no longer required delay restriction 2024-12-16 12:55:19 +01:00
Birk Magnussen 783ebba5ac Finish parsing 2024-12-16 11:17:17 +01:00
Goober5000 dfbf4da3fb fix engine wash
An idiosyncrasy of the original implementation of `timestamp_until()` is that "immediate" timestamps that expired would be negative.  Only one remaining spot in the codebase relied on this: engine wash.  When #6258 fixed `timestamp_until()` to return 0 for immediate timestamps, engine wash broke.  Changing the comparison from `<` to `<=` fixes it.  I searched the code and there are no similar uses of `timestamp_until()` or `timestamp_since()`.

In the process of searching, though, I found two uses of `timestamp_since()` that were converted from `timestamp_until()` in PR #4286.  These particular conversions more properly include the 0 rather than exclude it, so I changed these as well.
2024-12-16 02:07:57 -05:00
Goober5000 17706a0a6d fix sexp_ship_deal_with_subsystem_flag()
Due to broken node iteration, the `sexp_ship_deal_with_subsystem_flag()` function incorrectly treated the first sexp node as a subsystem, but previous versions of the function would fail silently and ignore it, and subsequent nodes would work as expected.  With the new `process_ship_subsystems()` function, this error is properly flagged (and the incorrect node is again bypassed).  So, fix the error by fixing the node iteration.

Follow-up to #6221.
2024-12-15 23:52:59 -05:00
Birk Magnussen bcaac067f5 Modern basic particle parsing 2024-12-16 00:40:23 +01:00
Goober5000 e37763f8a6 Merge pull request #6452 from Goober5000/6402_followup
default the connection speed to Fast even if it has been set to None
2024-12-13 22:15:24 -05:00
Goober5000 376be3652e Merge pull request #6459 from Baezon/fix-mtp-init
Fix maneuvering thruster initialization
2024-12-13 22:15:15 -05:00
BMagnu 621d88e9b7 Make length a modular curve output 2024-12-13 16:44:49 +01:00
BMagnu 7390e686cc Allow actual cones 2024-12-13 14:35:38 +01:00
The Force 104847c4bd Apply #6457 and #6458 to Ship sub-editors 2024-12-13 09:19:40 +00:00
Asteroth 326d8e5bdc reorder init 2024-12-12 18:26:48 -05:00
Asteroth 4d278097e3 change reset to a constructor 2024-12-12 18:18:03 -05:00
Goober5000 6b18caa965 Merge pull request #6322 from TheForce172/feature/customWarp
QtFRED: Custom Warp Dialog
2024-12-12 15:59:32 -05:00
Birk Magnussen a2e14b0580 Add parser modules for everything 2024-12-12 19:02:20 +01:00
Birk Magnussen df4c12330e Volume Parsing 2024-12-12 18:38:53 +01:00
Goober5000 58f90c22a8 warn and adapt when adding and removing NaN priorities 2024-12-12 11:35:52 -05:00
Birk Magnussen 40312e7419 Add modular curve sets to volumes 2024-12-12 16:44:34 +01:00
Birk Magnussen 5272604c83 Integrate type_traits
# Conflicts:
#	code/globalincs/type_traits.h
2024-12-11 22:14:46 +01:00
BMagnu 7773b429dc Typo 2024-12-11 16:03:28 +01:00
BMagnu 2aac63e0a9 Allow particle volumes to have access to the source for modular curves 2024-12-11 16:01:07 +01:00
BMagnu 2ed3b62e03 Curvify thruster particles 2024-12-11 15:04:35 +01:00
BMagnu 13e3f577ef Deal with split particle velocity curves 2024-12-11 14:14:03 +01:00
BMagnu c2051578d6 Basic modular curves for particles 2024-12-11 13:55:36 +01:00
BMagnu 6050821343 make modular_curves work with member funcs and smart pointers 2024-12-11 11:00:27 +01:00
Goober5000 09552bb195 bypass the SEXP caching code if running in FRED 2024-12-10 23:28:09 -05:00
Goober5000 02cbfbc347 enhance the add-goal and remove-goal sexps
1. Allow the goal priority to be an evaluated number, not just a literal number.  This allows the goal priority to be obtained from operators or calculations.
2. Since the priority can now be evaluated, it can be NaN.  In that case, default to the max priority.
3. Consolidate `CDR(CDR(...))` to `CDDR()` in the aigoal implementation
4. Clarify that `remove-goal` removes the first goal of a given type and priority, not necessarily the first fully matching goal.
5. Enhance `remove-goal` to remove all goals matching the constraints, not just the first goal.
6. Allow `remove-goal` to disregard priority when checking for matching goals.
2024-12-10 23:28:09 -05:00
Birk Magnussen e955a7f1be Merge branch 'master' into particle_cleanup 2024-12-10 23:41:07 +01:00
KestrelliusandBMagnu 228fd17ff1 Modular curves for weapon attributes during lifetime (#6319)
* Partially builds weapon curves.

* Further curve implementation

* Implementation of more output types.

* Cleanup

* Adjusts warning.

* Appeases clang.

* further appeasement

* Appeasement and time-traveling review changes

* change the enum branch too that'd be good

* More requested changes

* Basic abstraction for generic modular curves

* Make curve list by output statically sized

* Make instance-randomization consistent and mapless

* Add parsing

* Add derived modular curve sets

* Fix incorrect unpack

* Split modular curve set and definition, properly comment struct usage

* Split off specific type-traits into own file

* Fix modular curves for multi-derive case

* Implement some basic weapon curves, as well as the damage multiplier hit curve

* Merges in generified system built by Lafiel.

* Fills out beam curvesets.

* Renames curvesets.

* Removes launch curves for now.

* Testing, bugfixing.

* Various cleanup

* Returns extern do_subobj_hit_stuff

* Fixes compile errors

* Beam flag checking

* Rearranges beam flag checking.

---------

Co-authored-by: BMagnu <[email protected]>
2024-12-10 23:32:46 +01:00
The Force 43c153c127 Address Feedback 2024-12-10 20:49:39 +00:00
Goober5000 a742b6c067 add missing newline 2024-12-10 15:46:50 -05:00
The Force 91221d7dce Fix new C++17 Clang issues 2024-12-10 09:48:05 +00:00
The Force b1e96bd49e Address Review
Spelling Fix, Add explanatory note, Change Dialog title based on Warp In/Out
2024-12-10 09:31:46 +00:00
The Force 3965e1f327 Appease Clang and fix cancelling 2024-12-10 09:31:44 +00:00
The Force 5bbb74151f Add documentation and fix gcc errors 2024-12-10 09:31:42 +00:00
The Force 59f66a9d24 Finish Up 2024-12-10 09:31:40 +00:00
The Force 3bcc6b8c65 Load data 2024-12-10 09:31:29 +00:00
BMagnu 12ad35e10a restore shield_impact_explosion_radius 2024-12-09 13:28:16 +01:00
Goober5000 bcdcba7b8f default the connection speed to Fast even if it has been set to None
A connection speed of "None" is really just the default used by launchers if the user hasn't explicitly set the speed yet.  Additionally, `CONNECTION_SPEED_NONE` isn't really used by the engine except for error checking.  So, fall back to the default connection speed even when the speed has been set to "None".

Follow-up to #6402.
2024-12-08 23:34:58 -05:00
Goober5000 25a04fca53 Merge pull request #6438 from Goober5000/mod_string_tweak
allow the mod title and version to be displayed independently
2024-12-08 23:27:37 -05:00
Goober5000 de5421d241 Merge pull request #6449 from Goober5000/nebula_set_range
add nebula-set-range
2024-12-08 23:25:43 -05:00
Goober5000 d83f6ccdaf add nebula-set-range
Add a simple SEXP operator for changing the range of the current nebula.  Also, slightly reorder the existing nebula operators.
2024-12-02 12:41:26 -05:00
Goober5000 2b84233b91 Merge pull request #6439 from Goober5000/weapon_script_enhancements
add scripting support for weapon class "turret names"
2024-12-02 12:39:51 -05:00
Goober5000 5526f757ed Merge pull request #6221 from Goober5000/turret_ai_enhancements
create a `process_ship_subsystems` routine for subsystem operations
2024-12-02 00:18:18 -05:00
Goober5000 b2204a50a5 Merge pull request #6447 from Kestrellius/beam-cycle-fix
Beam cycle fix
2024-11-29 23:22:52 -05:00
Goober5000 8115589941 address feedback 2024-11-29 23:22:43 -05:00
Goober5000 c33e21f1c2 create a process_ship_subsystems routine for subsystem operations
Many SEXP operators that work on subsystems use very similar code.  This new function allows the operator implementations to be streamlined and makes future modifications easier.  For example, the `change-ai-class` operator now works with names such as `<all turrets>` as well as specific subsystems.
2024-11-29 21:39:29 -05:00
Goober5000 6bdd80bed3 fix ship:warpIn() behavior for docked ships
As described in #6445, the `warpIn()` script function did not work correctly for docked ships because the dock leader flag was not set.  So, set the flag, but make sure to set it only for the first ship for which `warpIn()` is called.  And make sure the flag is removed after the ship finishes arriving.

Also remove an `Int3()` in `shipfx_warpin_start()`.  (This Int3() was not actually in the original Volition source code release.)

Fixes #6445.
2024-11-29 21:32:04 -05:00
Kestrellius 2735404b18 Makes it actually cycle properly 2024-11-29 10:16:21 -08:00
Kestrellius 630f6c29d7 Gives Type 3s higher priority. 2024-11-29 10:03:49 -08:00
Kestrellius 2fe9c94f63 Adds fix for missing Type 3 beam behavior. 2024-11-29 10:02:00 -08:00
Goober5000 d21fb62207 Merge pull request #6387 from Shivansps/custom-preferences-path
Support custom preferences path
2024-11-28 20:18:38 -05:00
Goober5000 fa30b464a2 Merge pull request #6385 from Goober5000/which_personas_to_sync
allow voice acting manager to handle non-wingman personas
2024-11-28 20:15:01 -05:00
Mike Nelson 0a312263cb Allow defining custom overhead line colors (#6341)
* Allow defining custom overhead line colors

* Update asserts
2024-11-27 18:50:47 +09:00
Mike Nelson 06b0966580 Ttf font scaling option (#6330)
* Add option to set a font size multiplier for ttf fonts

* remove the option if we have no scaling fonts

* Clang the conquerer strikes again

* Update XSTRs

* clang

* Clarify comments
2024-11-27 18:50:35 +09:00
Goober5000 5e57e5ec64 Merge pull request #6440 from Goober5000/small_fixes
several small fixes
2024-11-26 22:46:36 -05:00
Goober5000 0332bae95c fix bolt texture checks
Having a missing bolt texture is not fatal; TBP uses it for `b_invisible`.  Modify the bolt checks to display a non-fatal warning if the bolt texture is explicitly specified but not found.
2024-11-26 14:10:26 -05:00
Goober5000 403a067103 fix compile warnings for briefing icon scaling 2024-11-26 14:10:26 -05:00
Goober5000 c254f39247 remove these Verifys since new already throws an exception; use std::move since sorting does not require copying 2024-11-26 14:10:26 -05:00
Goober5000 854b9abc89 fix distinction between lasers and beams
Many beams are lumped into the #Primary Weapons section of weapons.tbl, which will mark them as WP_LASER.  Fix the few instances of code that are intended for beams that may have omitted most beams by mistake.

Randomization of weapon impact particle radius is also affected, but since this affects existing visual effects, it was not changed.
2024-11-26 14:10:26 -05:00
Asteroth c28842739e Allow beams to do energy leeching (#6377)
* allow beams to do esuck

* dont forget to use mult

* consistent comments
2024-11-26 19:13:54 +01:00
Goober5000 df6de0e0b8 enhance help text for script functions that do weapon category checks 2024-11-26 12:51:50 -05:00
Goober5000 d31c33ac29 allow $Distance Unit Multiplier: as a synonym for $Length Unit Multiplier: 2024-11-25 21:12:09 -05:00
Mike Nelson e31100da95 Add hud-set-xstr sexp (#6406) 2024-11-25 17:45:34 -05:00
Goober5000 089c870ad8 add scripting support for weapon class "turret names"
A recent-ish FSO feature, `$Turret Name:`, allows turrets to be displayed differently on the HUD depending on the weapon they carry.  It is useful for scripts to be aware of this, so this PR adds a `TurretName` virtvar for weapon classes, as well as a `NameOnHUD` virtvar for subsystems.  The `NameOnHUD` virtvar shares exactly the same code as the HUD uses, so any future HUD modifications will be reflected in scripting as well.  This required a small amount of refactoring: changing `get_turret_subsys_name()` to return a value rather than stuffing a string, renaming it to `ship_subsys_get_name_on_hud()`, and moving it to ship.cpp.
2024-11-25 16:35:00 -05:00
BMagnu 68f3fa6d8c Actually compile with proper optimizations in a release build. (#6336)
* Change optimization to O3 and enable LTO

* Remove ODR violations

# Conflicts:
#	code/menuui/playermenu.cpp
#	code/osapi/osregistry.cpp

* Fix uninitialized structs

* Remove negative alloc warning

* O3 for mac

* Remove GCC13 warnings

* Fix warning

* Properly fix weapon alloc size

* Try to placate GCC9's Psnet_socket estimation

* remove warnin

* Fix safe fd set check
2024-11-25 20:10:38 +01:00
Goober5000 0bf30db7cd Merge pull request #6315 from Goober5000/fontmanager_improvements
fix memory management in FontManager
2024-11-25 13:30:55 -05:00
Goober5000 1f8227b990 Merge pull request #6435 from Goober5000/update_window
re-add Update_window tracking
2024-11-23 14:37:41 -05:00
Goober5000 84f1b2be9f Merge pull request #6411 from Goober5000/all_the_consts
all the consts!
2024-11-23 14:36:56 -05:00
Goober5000 d3addfcf5b clang overuses the [[nodiscard]] attribute; it should be used conservatively: see C++17 standard at https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0600r1.pdf 2024-11-22 23:40:05 -05:00
Goober5000 94e7ac84a5 use initializers and initialize m_specialCharacters; use default constructors and destructors 2024-11-22 23:32:48 -05:00
Goober5000 b3470af307 fix memory management in FontManager
This refactors FontManager to improve it in several ways:
1. Change all the dynamic memory management to use `new`, rather than mixing `new` and `vm_malloc`
2. Change the current font to use an index rather than a pointer
3. Take advantage of more C++11 features to avoid redundant lookups
4. Use case-insensitive name comparison
5. Avoid overflowing the `fnt->filename` field
6. Use `Warning` rather than `Error` in a non-critical error situation
2024-11-22 20:12:17 -05:00
Goober5000 c0ca5ff63d allow the mod title and version to be displayed independently
Tweak the mod string to display one or the other if both are not present.
2024-11-22 19:48:14 -05:00
Goober5000 0373db6b30 Merge pull request #6437 from Goober5000/weapon_bank_followup
improve bank-compatibility check
2024-11-22 14:05:41 -05:00
Goober5000 f89085b5e9 improve bank-compatibility check
1. Don't set the `can_use_for_bank` flag to FALSE if the bank is primary but the weapon is secondary, or vice versa
2. Make sure to only restrict the weapons by bank if the ship has per-bank restrictions

In support of this, add `is_primary()` and `is_secondary()` helper functions to `weapon_info` and use them in logical places.

Follow-up to #6434.  Fixes a few subtle bugs from that PR.
2024-11-22 00:35:10 -05:00
Salvador Cipolla aadd55e501 Check portable_mode flag before get_flags
Because -get_flags prints the value of pref_path, and this changes depending if portable_mode is also set.
2024-11-21 20:13:41 -03:00
Birk Magnussen 50ac2b8105 remove redundant function 2024-11-21 23:43:27 +01:00
Goober5000 54c2bb95b1 Merge pull request #6434 from Goober5000/per_bank_weapon_enabling
enable or disable weapon icons according to bank compatibility
2024-11-21 17:21:51 -05:00
Goober5000 bcf23dbfe6 Merge pull request #6419 from Goober5000/barracks_stats
use proper stats in barracks (take two)
2024-11-21 17:21:27 -05:00
Goober5000 1ac580b9d3 enable or disable weapon icons according to bank compatibility
When clicking on a weapon bank, mark the weapons as enabled or disabled according to their compatibility for that bank.  Do not actually prevent the weapons from being selected and dragged, as they may be dropped on a bank that isn't selected.

Also add a new `TriStateBool` for situations where the value is true, false, or unknown.

Fixes #6398.
2024-11-21 00:33:47 -05:00
Goober5000 1af285e1fe re-add Update_window tracking
FRED has code to keep track of whether the main window should be rerendered on each frame.  It looks like this was accidentally removed at some point.

(Discovered by comparing FRED source files while investigating #5568.)
2024-11-20 19:51:06 -05:00
Goober5000 3e055ec33e Merge pull request #6428 from Goober5000/mfc_ddv_fixes
fix DDV_ validation in FRED, especially DDV_MaxChars
2024-11-20 16:57:44 -05:00
Goober5000 e853dc29c2 Merge pull request #6433 from Goober5000/6364_followup
Cycle expansion followup
2024-11-20 16:42:46 -05:00
Goober5000 a939d5e15a Cycle expansion followup
A few addenda to PR #6364:
1. Use `std::swap` in the move constructor, since the fields are specifically being moved, not assigned
2. Fix off-by-one error when parsing firing patterns, and make the pattern count non-fatal
3. Standardize the setting of fire points since it's done in three different places, and in the case of `ship_set_default_weapons()`, `primary_firepoint_next_to_fire_index` was not reset to 0.  It might be useful to refactor this code into its own function.
4. Make the setting of `primary_firepoint_next_to_fire_index` consistent between forward and reverse cycling
5. Remove a couple redundant `.clear()` calls and fix a typo
2024-11-19 19:49:58 -05:00
Goober5000 e2065f50b5 Merge pull request #6432 from Kestrellius/firing-pattern-increment-fix
Fixes pattern_index oversight.
2024-11-19 19:46:36 -05:00
Kestrellius 51fb24f558 Fixes pattern_index oversight. 2024-11-19 14:22:42 -08:00
Goober5000 4026d30bdc fix DDV_ validation in FRED, especially DDV_MaxChars
Any DDV (Dialog Data Validation) routine must appear immediately after the field it validates in order for the enforcement to work in real-time.  If the DDV_ routine is not linked to the field, it will perform validation after-the-fact by displaying a dialog box and returning an error.  This is an alternate way of handling validation, but in order for the dialog box not to generate an endless loop, it would be necessary to check the return value of every `UpdateData(TRUE)` call in the FRED codebase (or at least the first `UpdateData(TRUE)` in a pair of them) and then, if the return value is `FALSE`, doing an early return from the enclosing function.

Fixes #6427 as well as all similar cases in FRED.
2024-11-18 23:01:21 -05:00
Goober5000 c8210c9bac Merge pull request #6422 from Goober5000/protect_weapon_bank_overflow
protect against weapon bank overflow
2024-11-18 13:24:07 -05:00
Goober5000 8de03d1d27 Merge pull request #6425 from wookieejedi/fix-cycle-weapon-update
Fix CTD from recent cycle expansion
2024-11-18 13:23:51 -05:00
Goober5000 97bf652774 address feedback 2024-11-17 23:07:16 -05:00
Goober5000 e60d44a366 Merge pull request #6371 from z64555/controls/moreaxis
More Axes!
2024-11-17 22:48:13 -05:00
wookieejedi 47fa82ef3f Update localize.cpp with xstr size comment 2024-11-17 14:34:28 -05:00
wookieejedi 217982b92c update xstrs for U and V axes 2024-11-17 14:33:32 -05:00
wookieejedi 24b0020e16 Merge branch 'master' into controls/moreaxis 2024-11-17 14:27:52 -05:00
wookieejedi 5e7af132fc Fix CTD from recent cycle expansion
The recent cycle expansion PR (#6364) causes a CTD when change-ship-type is used. This PR fixes that crash by using `pm->n_guns` instead of 'MAX_SHIP_PRIMARY_BANKS' and clarifies the definition comment for the  `pm->n_guns` to help avoid this kind of quandary in the furture.

Tested and works as expected.
2024-11-17 12:15:45 -05:00
Goober5000 b9964f3be3 Merge pull request #6403 from Goober5000/run_freespace_update
revise Run FreeSpace menu option
2024-11-14 19:54:46 -05:00
Goober5000 2c60b532a0 Merge pull request #6423 from Goober5000/mainhall_ambient
allow ambient sound to be specified on a per-main-hall basis
2024-11-14 19:53:04 -05:00
Goober5000 f612677b3e Merge pull request #6378 from Goober5000/fixed_ai_avoid_weapon_shockwave
fix ai behavior when avoiding ship and weapon shockwaves
2024-11-14 19:47:20 -05:00
Goober5000 b412d93032 add $Substitute Music: for credits.tbl
Similar to Substitute Music in other places, this allows the credits music to be changed if an optional music pack is present.
2024-11-14 19:46:30 -05:00
Goober5000 b72d67c074 default to using Vasudan ambient sound in the Vasudan main hall 2024-11-14 19:30:19 -05:00
Goober5000 0deafdcb5c allow ambient sound to be specified on a per-main-hall basis
Adds a new `+Ambient Sound:` field to mainhall.tbl, allowing any interface sound (or even no interface sound) to be used for the main hall ambient sound.  The default ambient sound, as well as the sound played on the pilot select screen, is interface sound 12.

Implements #6421.
2024-11-14 13:39:39 -05:00
Goober5000 a8245a8fb4 protect against weapon bank overflow
If the mission is edited in a text editor, and a ship is given too many weapon banks, this can cause issues in the weapon firing code.  Protect against this by checking the number of banks when the ship is created.
2024-11-14 12:07:50 -05:00
BMagnu 189803a6a4 Allow modern particles for ship / thruster particles 2024-11-14 14:52:53 +01:00
Goober5000 1bcad06461 remove the avoid-shockwave flag when too far away from a weapon; and add a should-be-dead check 2024-11-14 00:07:26 -05:00
Goober5000 722ed575d2 only refine the expected homing pos if it really does need to be refined 2024-11-14 00:07:18 -05:00
Goober5000 5dfe398af2 add a cache for the expected homing pos 2024-11-14 00:07:06 -05:00
Kestrellius d6b444c9e6 Cycle expansion (#6364)
* Adds different firing patterns for weapons.

* cleanup

* further cleanup

* appeasement

* appeasement^3

* Requested changes.

* Deals with targeting flag issue.

* Resolves merge conflicts.

* blood for the blood god, tidy for the tidy throne

* Increments XSTR again.
2024-11-13 08:05:06 -05:00
Mike Nelson 17e857c819 Define whether or not to render the game strings on the mainhall 2024-11-12 10:59:38 -08:00
Goober5000 124293a92e use proper stats in medals screen
Related to the previous two commits, the medals screen should use the actual all-time stats from the pilot file instead of the active campaign stats.  This required tweaking the DCF "medals" debug command to work with the exported stats.  Also, some C casts were changed to C++ and an obsolete variable was removed.
2024-11-12 01:14:08 -05:00
Goober5000 b407681c5a use proper stats in debriefing
Related to the previous commit, the debriefing should use the actual all-time stats from the pilot file instead of the active campaign stats.  In multi, however, use the active campaign stats; because the debriefing can display stats for different players, and all-time stats are only available for the local player.

Also, clean up and slightly refactor `show_stats_label()` and `show_stats_numbers()`.  Duplicate code has been removed, string output has been streamlined, and a few bugs with percentages (especially divide-by-zero checks) have been fixed.
2024-11-12 01:14:08 -05:00
Goober5000 03bf756d5c fix ai behavior when avoiding ship and weapon shockwaves
The FreeSpace AI includes behavior to run away from shockwaves to try to avoid explosion damage.  This is implemented for both ships and missiles, although the missile implementation has been buggy ever since retail.  There are several issues:

1. The AI attempts to evade a weapon immediately upon launch.  Many missiles have a period of free flight before they start homing on their target.  During the free flight period, the homing position is not set.  Consequently, the AI will not know the position to avoid and will make assumptions.
2. The AI assumes the shockwave-producing weapon will detonate at the center of the ship it is targeting, although missiles detonate on the surface.  A capital ship is likely to be significantly larger than the weapon's blast radius, leading the AI to believe the detonation will be much farther away than it actually is.
3. When avoiding ship shockwaves, the `shockwave_object` field is not cleared when avoiding is complete.  This can result in stale references (though not crashes, due to object type checks), causing AI to not avoid future explosions in certain cases.
4. When avoiding ship shockwaves, the code does not check the correct ship for the amount of damage caused by the shockwave.

All of these issues are now fixed.  Since this is a change in AI behavior, these fixes are tied to a new AI profiles flag.
2024-11-12 00:40:05 -05:00
Goober5000 86afcb3405 use proper stats in barracks (take two)
The barracks should use the actual all-time/multi stats from the pilot file instead of the active campaign stats.  Export the all-time stats from the pilot file in order to populate the barracks.

Follow-up to #6238.
2024-11-11 19:17:04 -05:00
Goober5000 ad3fc5c0b7 Merge pull request #6418 from Goober5000/check_for_hud_drawing
add hud drawing and pre-player-entry checks
2024-11-11 10:56:11 -05:00
Goober5000 ad08452307 Merge pull request #6409 from Goober5000/generic_all_subsystems
enhance sexp handling of generic subsystems
2024-11-11 10:54:16 -05:00
Goober5000 753d1225a9 Merge pull request #6417 from pastalian/fix-odr
Fix ODR violations
2024-11-11 10:53:40 -05:00
Takuya Wakazono c78e252509 Replace NULL with nullptr
Make clang-tidy happy.
2024-11-11 14:17:16 +09:00
Goober5000 e2f8de72e7 add hud drawing and pre-player-entry checks
1. add `hu.isOnHudDrawCalled()` and clarify documentation for `hu.HUDDrawn`
2. add `mn.isPrePlayerEntry()`
2024-11-10 12:58:02 -05:00
Takuya Wakazono 6c623266a2 Fix ODR violations
```
code/menuui/barracks.cpp:188:8: error: type ‘struct barracks_buttons’ violates the C++ One Definition Rule [-Werror=odr]
  188 | struct barracks_buttons {
      |        ^
code/menuui/playermenu.cpp:82:8: note: a different type is defined in another translation unit
   82 | struct barracks_buttons {
      |        ^
code/osapi/osregistry.cpp:478: error: type ‘struct Section’ violates the C++ One Definition Rule [-Werror=odr]
  478 | typedef struct Section
code/pilotfile/FileHandler.h:18: note: a different type is defined in another translation unit
   18 | enum class Section {
```
2024-11-10 16:40:07 +09:00
Goober5000 df4ad18009 Merge pull request #6415 from Goober5000/is_true_for_duration
add is-true-for-duration sexp
2024-11-09 23:39:20 -05:00
Goober5000 57b966cbee add is-true-for-duration sexp
This adds a sexp to allow any boolean condition, or series of conditions, to be evaluated not only instantaneously, but also for a period of time.  For example, this can be used with `is-facing` to check if a ship has been facing another ship for a specified duration.  Previously this had to be done through scripting or through a group of sexps.

Implements #5754.
2024-11-08 13:01:06 -05:00
Goober5000 524ecbe826 handle clang warnings 2024-11-07 23:33:13 -05:00
Goober5000 31a86e3f3d all the consts!
Some experimentation resulted in a lot of const-cascading.  This PR applies `const` to a large number of functions.
2024-11-07 23:33:13 -05:00
Goober5000 9f61a6b7f5 Merge pull request #6414 from Goober5000/skip_mission_tweak
make mission skipping more robust
2024-11-07 23:20:52 -05:00
Goober5000 a0b26bdc0a Merge pull request #6241 from Goober5000/some_collision_optimizations
optimize collision code a bit
2024-11-07 23:20:40 -05:00
Mike Nelson 0e88007571 auto size font for screen resolutions (#6342) 2024-11-07 22:48:08 -05:00
Mike Nelson 53653fd03b Remove model_pointer in favor of using model_number (#6337) 2024-11-07 22:46:41 -05:00
Goober5000 8bbe0a0364 make mission skipping more robust
When a player tries to skip a mission during a campaign, all goals and events are marked true.  Thus it's possible for the campaign condition to unexpectedly *not* evaluate to the next mission (e.g. `if is-previous-goal-false` or `is-previous-event-false` is used without the optional argument).  So add a failsafe check, with a warning, to handle this case.  Also update the documentation to clarify that the optional argument is checked for the mission-skipped case.

Fixes an endless skip-to-the-same-mission loop discovered by ShivanSlayer in Shrouding the Light.
2024-11-05 15:15:16 -05:00
Mike Nelson 1a1bd84290 Grant lua access to countermeasure parameters (#6345)
* grant lua access to countermeasure parameters

* you win this round, Clang

* and Wookie wins the next round
2024-11-05 08:29:02 -05:00
Goober5000 9eba363ddf Merge pull request #6413 from Goober5000/update_github_artifact
sync upload and download artifacts
2024-11-05 01:16:14 -05:00
Goober5000 611fa1ffd8 sync upload and download artifacts
PR #6335 did not update actions/upload-artifact; both upload and download need to use the same major version number.

Also move from v4.1.7 to just v4 because that appears to be the common practice.
2024-11-05 00:51:03 -05:00
Goober5000 89605651ca Merge pull request #6359 from Goober5000/waypoint_pointer_to_index
replace waypoint pointers with waypoint indexes
2024-11-04 13:37:20 -05:00
Goober5000 6cbde28858 Merge pull request #6412 from Goober5000/connection_speed
handle connection speed in a user-friendly way
2024-11-04 13:37:05 -05:00
Goober5000 37a24b2a14 handle connection speed in a user-friendly way
1. Use a sensible default for the connection speed
2. Remove the `Psnet_connection` variable which is now obsolete: "its only purpose now is to change the default object update value for a player if it's set to dialup, and that's easily done in-game already"

The "You must define your connection speed" popup will now no longer appear unless it has been explicitly set to an invalid value.

Applies recommendations from, and fixes, #6402.
2024-11-03 23:09:32 -05:00
Goober5000 1493774f80 Merge pull request #6261 from Goober5000/timestamp_valid_tweak
refine timestamp_valid
2024-11-03 22:31:14 -05:00
Goober5000 b48a55e825 Merge pull request #6410 from Goober5000/hide_variable_index_operators
hide variable -index SEXP operators in FRED
2024-11-03 22:31:04 -05:00
Goober5000 f71f02e0b1 Merge pull request #6376 from Goober5000/malformed_xstr_release_warning
make malformed XSTR a release warning
2024-11-03 17:11:47 -05:00
Birk Magnussen fe815f89ca Set pre-curve lifetime for damage-spew and similar to 1 2024-11-03 21:54:35 +01:00
Birk Magnussen 32835b06fd Small cleanups 2024-11-03 21:00:39 +01:00
Birk Magnussen 1f7909112c Remove particle properties 2024-11-03 20:22:34 +01:00
Goober5000 2507ada110 hide variable -index SEXP operators in FRED
Hide these SEXP operators to reduce confusion for FREDders.  They still work, but using them properly requires a certain amount of knowledge of the inner workings of variables, and the operators can break if new variables are added causing the list to be re-indexed.

Implements half of #6400.
2024-11-03 14:02:35 -05:00
Goober5000 0d543b0ed4 Merge pull request #6335 from scp-fs2open/dependabot/github_actions/dot-github/workflows/actions/download-artifact-4.1.7
Bump actions/download-artifact from 3 to 4.1.7 in /.github/workflows
2024-11-03 13:34:52 -05:00
Birk Magnussen 3d171eb858 Remove EffectTiming 2024-11-03 15:00:32 +01:00
Birk Magnussen e2dbb46b9c Fold OmniEffect into ParticleEffect 2024-11-03 14:45:16 +01:00
Goober5000 ed7af6acd1 enhance sexp handling of generic subsystems
1. Since we already handle `<all engines>` and `<all turrets>`, it's simple to extend this to all generic subsystems of any type
2. Add an `<all subsystems>` case for handling every subsystem on a ship
3. Add some compiler directives to enforce preconditions for subsystem type `#define`s
2024-11-03 01:56:02 -04:00
Mike Nelson 99e263343a Optional icon scaling (#6329)
* optional briefing icon scaling

* cleanup

* fix merge conflict issue
2024-11-02 22:04:38 -04:00
Birk Magnussen 1aa67c9342 Properly use new effect host 2024-11-02 14:48:58 +01:00
Birk Magnussen 98ddb1500f Add sensible particle host class 2024-11-01 16:23:11 +01:00
Goober5000 e9be8d2424 Merge pull request #6393 from Goober5000/proper_fighter-bomber_fix
proper fix for fighter/bomber
2024-10-29 19:08:12 -04:00
Goober5000 42de74a62e Merge pull request #6349 from Goober5000/hud_gauge_api_functions
add several useful hud gauge functions
2024-10-29 19:07:45 -04:00
Goober5000 c582f77965 Merge pull request #6405 from Goober5000/getBreedName_for_parse_objects
adds getBreedName() in a few places
2024-10-29 19:07:38 -04:00
Goober5000 e58f8f9a5b Merge pull request #6365 from Baezon/disambiguate-shockwave-damage
Disambiguate `ShockwaveDamage` cases
2024-10-29 19:07:30 -04:00
Goober5000 e3d28b7fb1 adds getBreedName() in a few places
There are a few places in the Lua script API where a variable could be some type of "object" or something that is not an "object" but is still useful - one example is the return value from oswpt:get().  With this function, scripts will be able to tell what the variable is without risking an exception.
2024-10-29 00:20:05 -04:00
Birk Magnussen e28671ff92 Assign the correct flash particle variable 2024-10-28 18:29:03 +01:00
BMagnu 95fef2af39 Fix x86 SIMD Extension Handling (#6384)
* Fix AVX2 detection

* Also query for proper OS support

* Actually properly set ISA level on all platforms

* Expose level of x86-SIMD instructions to the code.

* Fix handling of forced instruction set

* Fix errors

* Fix MSVC

* Properly deal with linux CI builds

* fix clang
2024-10-28 17:58:31 +09:00
Shivansps 2eb2af6f76 Add RISC-V to cmake linux (#6375)
* Add support for RISC-V compile to cmake

* No need to pass -march for gcc in riscv

* -march=native is not supported in Risc-V clang

* fix comment and remove unnecessary newline

* Remove incorrect values while checking CMAKE_SYSTEM_PROCESSOR

* Support 32bit RISCV as well

I dont think this will be ever be needed, but i dont like that compilation will fail due to incorrect compiler flags if you try.
2024-10-28 17:27:39 +09:00
BMagnu 80625fd307 Change Build to C++17 (#3710)
* Set ver to C++17

* remove deprecated shuffle

* Fix std::iterator being deprecated

* Work around codecvt deprecation

* Fix std::result_of deprecation

* Another random_shuffle

* another text conversion replacement
2024-10-28 17:27:14 +09:00
Goober5000 d38f7256a7 Merge pull request #6396 from Shivansps/fix-legacy-config-default-true-windows
Set old_config_exists to false in Windows if the registry key are not present
2024-10-27 23:18:45 -04:00
Goober5000 89e546099a Merge pull request #6332 from Goober5000/movie_hooks
add pre-movie hook
2024-10-27 23:15:55 -04:00
Goober5000 79a9acbb90 Merge pull request #6394 from Goober5000/fix_camera_shudder
fix camera shudder
2024-10-27 23:15:46 -04:00
Goober5000 98522476e5 Merge pull request #6404 from Goober5000/version_24_3
bump version to 24.3
2024-10-27 23:03:29 -04:00
Goober5000 961e06df0b bump version to 24.3 2024-10-27 22:43:26 -04:00
Birk Magnussen bb3e50832d Fix particle end conditions and vector-based orientations for offset 2024-10-27 21:13:51 +01:00
Birk Magnussen c0f5b0ba86 Properly deal with always-particle sources 2024-10-27 20:55:52 +01:00
Goober5000 846608e949 add command-line arguments to Run FreeSpace command
Takes the command-line arguments used to launch FRED and reuses them to launch FSO.

As part of this, slightly refactor the `cmdline_print_cmdline_multi()` function so that it calls a new `cmdline_build_string()` function.
2024-10-25 15:52:52 -04:00
Goober5000 d288dcb3fd revise Run FreeSpace menu option
Fix some memory leaks and make the application name detection slightly more reliable.
2024-10-25 14:55:24 -04:00
Birk Magnussen c513ab5ad3 Fix legacy particle lifetime when built-in bitmap is used 2024-10-25 12:45:57 +02:00
BMagnu bd1792d777 Move Effect timing into the ParticleSource. 2024-10-24 16:54:02 +02:00
Salvador Cipolla 9c67434be2 Use a different variable for the optional 2024-10-23 19:22:30 -03:00
BMagnu c937bc6bbb Actually get rid of particle emitters 2024-10-23 17:04:35 +02:00
BMagnu a79c23be07 Add orientation-based velocity inherit for beampiercingeffects 2024-10-23 15:27:02 +02:00
Birk Magnussen c16dfba843 Fix directional scaling 2024-10-22 22:40:53 +02:00
Birk Magnussen 9b2d069bfd Actually apply rotation to the cone volume 2024-10-22 22:31:01 +02:00
Birk Magnussen 39c6dc788d Fix default ship particle parameters 2024-10-22 21:56:28 +02:00
Birk Magnussen 2bba61a4b8 Account for negative velocities in particle setup for weapons, again 2024-10-22 21:51:47 +02:00
Birk Magnussen 8e1474f018 Account for negative velocities in particle setup for weapons 2024-10-22 21:47:32 +02:00
Tyler Blount 91a2291c03 Merge pull request #6386 from MjnMixael/fix_skip_to_string
Return false if skip to string can't find the string
2024-10-20 10:36:57 -07:00
Salvador Cipolla 7176c73fd0 Unix dosent use a optional type here 2024-10-19 08:25:19 -03:00
Salvador Cipolla ccefc988c2 Use optional type 2024-10-19 07:46:19 -03:00
Salvador Cipolla a48d101c92 Look for specific registry key not found error 2024-10-18 20:08:23 -03:00
Salvador Cipolla 94907eac7f Set old_config_exists to false if the registry key are not present 2024-10-14 20:58:34 -03:00
Goober5000 1570f72df3 fix camera shudder
The enhanced controls and flags in #4552 were intended to allow the camera to shudder in all views, not just the cockpit view.  And indeed, the shudder does apply in all other views... except for cutscene cameras, due to the `VM_FREECAMERA` check in `game_render_frame()`.  So, add a separate check for cutscene cameras when shuddering everywhere.  The cutscene camera can be jittered just like the cockpit camera, but the rotation should not be modified or it will produce feedback.

Follow-up to #4552.  Also removes an unused variable that was made obsolete in #5656.
2024-10-14 00:36:13 -04:00
Goober5000 a9d2605c0e proper fix for fighter/bomber
This fixes the fighter/bomber type which had been broken ever since the objecttypes.tbl upgrade in 246cfcfa65: the fighter/bomber type is again treated as a union of fighters and bombers, not a unique type of its own.  This requires special handling for the `OPF_SHIP_TYPE` SEXP argument type, and all four SEXPs that use `OPF_SHIP_TYPE` have been modified to check for the special case.  The explicit fighter/bomber type has again been removed from the built-in objecttypes.tbl.

The requirements for "fighter/bomber" to be valid are 1) there is no explicit "fighter/bomber" type in the mod; 2) a "fighter" type exists; 3) a "bomber" type exists.  If any of these conditions is not met, the special case behavior is not enabled.

Follow-up to #6390.  Properly fixes #6388.
2024-10-13 21:43:18 -04:00
Goober5000 947b3d4f21 Revert "add the fighter/bomber type back to objecttypes.tbl"
This re-removes the fighter/bomber type by reverting commit 565d91b6dc.
2024-10-13 17:03:50 -04:00
Goober5000 83d12684e4 Merge pull request #6390 from Goober5000/re_add_fighter-bomber
add the fighter/bomber type back to objecttypes.tbl
2024-10-13 17:02:11 -04:00
Goober5000 565d91b6dc add the fighter/bomber type back to objecttypes.tbl
A few missions used the fighter/bomber ship type, so this adds the type back to make those missions work again.

Temporary fix for #6388.  A more proper fix will be applied after the official 24.2 release.
2024-10-12 22:12:22 -04:00
Salvador Cipolla da68c223ae Remove an unintentional new line 2024-10-10 19:39:19 -03:00
Salvador Cipolla 096aa4ed65 Move env pref path detection from os_get_config_path() to getPreferencesPath()
It is a better place for it, it enables the regular path checks and warnings
2024-10-09 20:19:28 -03:00
Goober5000 66bf2aefb0 remove redundant cutscene_mark_viewable()
This is already done in `movie::play()` and shouldn't be done again if a script overrides the function.  The extra calls were added in 251285cacc and cbccf655fa (the former copied from the latter), originally as an unsuccessful attempt to fix Mantis 61.
2024-10-09 14:39:34 -04:00
Goober5000 3d8fbc0e97 add pre-movie hook
Add an `$On Movie About To Play:` hook to match `$On Intro About To Play:`.  Also make the two hooks overridable, since that might be useful.

Additionally, change a few (nonexhaustive) `name` parameters to `filename` to make it clearer that the string is a filename.
2024-10-09 14:39:34 -04:00
Salvador Cipolla e43612c9c4 Read a custom optional path for the preferences path 2024-10-08 22:23:56 -03:00
mjn-mixael a1a5780104 return false if skip to string can't find the string 2024-10-07 16:17:49 -05:00
Goober5000 44ddc5f21c allow voice acting manager to handle non-wingman personas
Augments the voice acting manager to handle non-wingman as well as wingman personas, plus limit operations to a specific persona.  This also modifies the editor to only increment the number of modifications when something *is* modified, not merely when something *could be* modified but is currently the expected value.

Resolves #6379.
2024-10-06 18:22:26 -04:00
wookieejedi 49ee006dd5 Fix overlappig XSTRs (#6381)
The XSTR entry 1779 (strings.tbl) is used for two different texts:

"Disabled" in shadows.cpp;
"Toggle Auto Pilot" in controlsconfigcommon.cpp;

"Disabled" is already assigned to XSTR 413. ATM I have this set to shadow's usage (even though 413 is related to Disabled ships). Alternatively I would be happy to use `"Off", 1693`, which is what the other graphic settings use (though the actual value in the code would still remain `Disabled` of course).
2024-10-06 09:32:07 -04:00
Goober5000 b734d6017f Merge pull request #6382 from Goober5000/cargo_title_initialization
properly initialize cargo titles
2024-10-04 22:20:13 -04:00
Goober5000 349a9927cc properly initialize cargo titles
This adds several missing initializations of cargo titles for both ships and subsystems.  Note that `Subsys_status` initialization needs to happen in `allocate_subsys_status()`, because subsystems can be allocated in red-alert or in the `ship-copy-damage` SEXP, not just parsing.

Follow-up to #6000.  Fixes a rather insidious ERANGE error in Inferno.
2024-10-04 00:56:47 -04:00
Goober5000 6ed64e796d make malformed XSTR a release warning
1. Tweak the API of `error_display` so that an error level of 2 displays a `ReleaseWarning`.
2. Use this error level for the malformed XSTR warnings in the localization code.

Resolves #6374.
2024-10-01 00:36:43 -04:00
z64555 f459d687f3 Revert JOY_NUM_BUTTONS value back to 32 2024-09-29 20:58:10 -05:00
z64555 0f14b61dfb Add lazy constants for hat positions
* Reorder hat position labels to match SDL order (christian cross -> clockwise)
2024-09-29 20:40:18 -05:00
z64555 b3f2f8b257 Use sprintf instead of sprintf_s 2024-09-29 20:33:29 -05:00
z64555 97e1c6de04 Make button labels procedural. Hat position labels still use a LUT.
* Remove unneeded comment on U and V axis. (Comments there are for original axis XSTR indices)
* Fix UI issue where bound button message did not display which controller it belonged to
* Removed unused extern reference of Joy_button_text
2024-09-29 20:02:59 -05:00
Tyler Blount da9ae0dd69 Merge pull request #6368 from Baezon/tmap-25-verts-error
Have TMAP chunks report >25 verts polygon error as well
2024-09-29 13:27:43 -07:00
Tyler Blount 04f5c2ff84 Merge pull request #6363 from Goober5000/voice_manager_modifications
set the modified flag in the Voice Acting Manager
2024-09-29 13:27:26 -07:00
Tyler Blount d723300c86 Merge pull request #6370 from MageKing17/bugfix/ingame-shockwave-options-clarity
Make Shockwaves in-game option force multi-value selection.
2024-09-29 13:26:08 -07:00
wookieejedi c9e9b9849a Fixes Lab Rendering when Zooming (#6373)
Fixes #6372 by more specifically setting the `MR_ATTACHED_MODEL` value and by correctly setting the `MR_NO_INSIGNIA`.

Tested and fixes the issue.
2024-09-29 11:19:16 -04:00
z64555 bbf029b1b2 Oops! Labels!
Update XSTR_SIZE to 1859
2024-09-28 09:09:19 -05:00
z64555 9ffcf94195 Add two axis names and bump button limit to 128. 2024-09-28 08:00:31 -05:00
MageKing17 44b4c04058 Make Shockwaves in-game option force multi-value selection.
This makes it so that the "3D"/"2D" display is actually respected in the in-game options menu, rather than just having an ambiguous checkbox labelled "Shockwaves".
2024-09-26 22:23:52 -07:00
Goober5000 fbee2b8f49 Merge pull request #6367 from Goober5000/remove_bogus_ship_types
remove bogus ship types from objecttypes.tbl
2024-09-26 19:54:22 -04:00
Asteroth 6c1bb9a617 make 25 verts error for tmap too 2024-09-25 19:34:41 -04:00
Goober5000 09d89066ec remove bogus ship types from objecttypes.tbl
The "stealth" and "fighter/bomber" ship class flags are not actual ship types, so they should never have been added to objecttypes.tbl.  Remove them from the built-in table.

Additionally, if a mod *does* use "stealth" in its own objecttypes.tbl, remove it.  This prevents the invalid "stealth" type from overriding a valid existing type, which fixes #6366.
2024-09-25 01:27:39 -04:00
Birk Magnussen 92473780d5 Fix correct random range constructor overlaod 2024-09-24 17:54:16 +02:00
Birk Magnussen b9b7a13586 Fix source bugs 2024-09-24 17:42:19 +02:00
Birk Magnussen 0ec845b4ce Make builtin particle sources actually anonymous 2024-09-24 17:34:43 +02:00
Birk Magnussen 562c39d8b4 fix parse 2024-09-24 17:24:32 +02:00
Birk Magnussen 09d8ffe66d Do legacy parsin 2024-09-24 17:24:31 +02:00
Birk Magnussen db4ec11fd9 Remove redundant effects 2024-09-24 17:24:27 +02:00
Birk Magnussen 53047638bc Replace final legacy effect with omni effect 2024-09-24 17:23:01 +02:00
Birk Magnussen 63a18b28fa Update Ship and Supernova effects to Omni 2024-09-24 17:23:01 +02:00
BMagnu 8503c8a068 Start replacing legacy effects with omnieffect 2024-09-24 17:23:01 +02:00
Birk Magnussen e0c2ba7011 Prepare for the removal of composite effects 2024-09-24 17:23:01 +02:00
BMagnu 989e21622d Allow creating of OmniParticleEffects as needed for the non-part-tbm effects 2024-09-24 17:23:01 +02:00
Birk Magnussen efed4647aa Code volumes 2024-09-24 17:23:00 +02:00
Birk Magnussen e5afc04829 Add OmniEffect 2024-09-24 17:23:00 +02:00
Birk Magnussen 5dfc2108dc Fix bugs from particle_emitter refactor 2024-09-24 17:23:00 +02:00
BMagnu 2f2e8b2e14 Remove particle_effect and ParticleType 2024-09-24 17:23:00 +02:00
BMagnu 97dbd2fa83 Removal of effects, pt. 2 2024-09-24 17:23:00 +02:00
Birk Magnussen 7d10ed44fa Removal of effects, pt. 1 2024-09-24 17:22:59 +02:00
Asteroth 649d458e83 fix spelling 2024-09-23 15:16:35 -04:00
Asteroth 40e334fc94 Disambiguate shockwave cases 2024-09-23 03:16:45 -04:00
Goober5000 03b99a3fd0 Merge pull request #6361 from Goober5000/derp
derp
2024-09-22 22:05:23 -04:00
Goober5000 6f089d74cb set the modified flag in the Voice Acting Manager
When actions in the Voice Acting Manager modify the mission, set the modified flag so that FRED will prompt to save the mission.  And since this requires tracking the number of modifications, enhance the dialog boxes to display this information to the user.

Fixes #6362.
2024-09-22 22:01:21 -04:00
Goober5000 62180212f5 derp
Counting is A-1 SUPAR.
2024-09-21 18:06:35 -04:00
Goober5000 385bf49b39 replace waypoint pointers with waypoint indexes
Several locations in the code (notably `ai_info` and `waypoint_h`) previously stored pointers for waypoints and waypoint lists that need to be valid for more than one frame.  Since both waypoint lists and waypoint paths may change size, resulting in vector reallocation, the information should be stored as indexes instead.

Fixes #6353.
2024-09-21 01:00:24 -04:00
Tyler Blount c6cd2de577 Merge pull request #6357 from Goober5000/swarminfo_corkscrewinfo_functions
use functions for getting swarm info and corkscrew info
2024-09-20 09:32:38 -07:00
Tyler Blount 466995a909 Merge pull request #6355 from MjnMixael/adjust_options_message
Clarify options popup message text
2024-09-20 09:32:11 -07:00
Goober5000 56fc5b457f Merge pull request #6352 from Goober5000/allow_explicitly_empty_sounds
allow explicitly empty sounds
2024-09-17 22:27:56 -04:00
Goober5000 461c62823c Merge pull request #6356 from Goober5000/retail_style_warning_fix
retail-style warning fix
2024-09-17 22:27:48 -04:00
Goober5000 24555ac739 add functions for getting swarm info and corkscrew info
Apparently virtvars can only return one value.  This deprecates the virtvars and adds function equivalents for getting weapon class swarm info and corkscrew info.  Fixes a bug reported by Woolie Wool in Discord.
2024-09-17 14:07:26 -04:00
Goober5000 d67fe30982 retail-style warning fix
The warning for mismatched names-and-indexes implicitly assumed that retail-style sounds would only be added with numeric indexes.  Since adding named sounds in the retail style is, in fact, allowed, update the logic to not warn in that case.

Fixes #6354.
2024-09-16 23:39:58 -04:00
mjn-mixael e35b03dc61 Clarify options popup message text 2024-09-16 09:56:42 -05:00
Goober5000 b596fa305d allow explicitly empty sounds
Make sounds that are specified as "empty" or "none" in sounds.tbl ineligible for treatment as placeholder sounds.  Resolves #6350.
2024-09-13 16:42:13 -04:00
Goober5000 0fd2e9396b add several useful hud gauge functions
1. a `hud-reset-color` SEXP operator, to complement the existing `hud-set-color` and set a gauge back to its configured color
2. `ConfigType` and `ObjectType` Lua virtvars which are essentially the built-in gauges' equivalents of `Name` for custom gauges
3. `getColor` and `setColor` Lua functions
2024-09-11 14:42:07 -04:00
Goober5000 f08d82be23 Merge pull request #6348 from Goober5000/hud_gauge_bugfix
two HUD fixes
2024-09-11 14:03:21 -04:00
Goober5000 dfe34ec58d update documentation 2024-09-11 02:03:40 -04:00
Goober5000 2f3423d70e fix "hudgauge" custom parameter
Since the `OPF_ANY_HUD_GAUGE` type checks for any default or custom HUD gauge in regular SEXP operators, it should do so in scripted SEXP operators as well.
2024-09-11 01:45:44 -04:00
Goober5000 98de7323aa fix crash in hud_get_custom_gauge()
The `Player_ship` variable can sometimes be NULL, especially in FRED, so revise the conditional to check for this.
2024-09-11 01:31:22 -04:00
BMagnu b6879da96d Fix deferred lighting Option (#6346)
* Fix deferred lighting option

* Fix issue

* Fix premature cache

* Appease Clang

* cache specific option not options in general
2024-09-09 21:37:49 +00:00
Goober5000 45d99265b8 Merge pull request #6339 from Goober5000/empty_sounds_fix
further refinement of sound fixes
2024-09-08 21:09:56 -04:00
Goober5000 ee9770d418 properly fill sounds into placeholder slots 2024-09-05 02:36:49 -04:00
Goober5000 9d6c8509ab proactively set placeholder sounds to invalid 2024-09-05 02:36:28 -04:00
dependabot[bot] 728a841ce9 Bump actions/download-artifact from 3 to 4.1.7 in /.github/workflows
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 3 to 4.1.7.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v3...v4.1.7)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-09-03 22:12:52 +00:00
Goober5000 854b0139d2 fix sound initialization (#6333)
Fix a small oversight from #6112.  In the empty/placeholder indexed sound situation, although the sound should not be appended (since it indexed), it should still be treated as a new sound, in order for all the first-parse and first-initialize logic to run properly.  Set the right value and add some comments to illuminate the logic.
2024-08-30 08:42:33 -04:00
Goober5000 c59a967f46 Merge pull request #6331 from Goober5000/save_version_update
update detection of save version
2024-08-28 21:45:56 -04:00
Tyler Blount e6f46cf031 Merge pull request #6328 from MjnMixael/fix_fade_icons
Fix fade icons not matching parent
2024-08-28 18:44:48 -07:00
Tyler Blount 10f6f47819 Merge pull request #6327 from MjnMixael/fix_briefing_icons_4k
Fix Briefing Icons at 4K in SCPUI
2024-08-28 18:44:35 -07:00
Goober5000 328e7d37e0 update detection of save version
Looking at the log of missionsave.cpp, the presence of a ship or subsystem cargo title will necessitate a minimum version of 24.1.
2024-08-28 21:23:19 -04:00
mjn-mixael b4ace94637 remove the whole block 2024-08-28 17:05:50 -05:00
mjn-mixael 68943d2c06 cleanup 2024-08-28 16:58:31 -05:00
mjn-mixael a3e62433f2 you're killing me, clang 2024-08-28 13:09:59 -05:00
mjn-mixael 5475c63309 Fix fade icons not matching the scaling and orientation of their parent icons 2024-08-28 12:55:00 -05:00
mjn-mixael 3a7c532d1a remove unncessary return 2024-08-28 10:13:35 -05:00
Goober5000 39565d36e2 Merge pull request #6325 from Goober5000/probability-curves-followup
follow-up to probability curves
2024-08-28 01:02:29 -04:00
Goober5000 c8aa28b1cc follow-up to probability curves
Fix the inadvertent swapping of the two utility functions for parsing sounds.  While we're at it, streamline a few lines, remove a few C-style casts, and remove an unused function prototype.

Follow-up to #6314.  Fixes a crash encountered by Inferno on 24.2-RC1.
2024-08-27 23:30:25 -04:00
Goober5000 b98b8f2d07 Merge pull request #6324 from Goober5000/fotg_sound_fix
fix deletion of looping sounds
2024-08-27 15:27:52 -04:00
Goober5000 28659bb1f9 fix deletion of looping sounds
Per the comment earlier in this function, both -1 and -2 are expected values for sound indexes.  Update the sound validity check accordingly.  Fixes an assertion in `obj_snd_delete()` encountered by FotG when a sound index was -2.
2024-08-27 15:10:14 -04:00
Mike Nelson d68b18dfc8 Upgraded Asteroid Field SEXPs (#6295)
* upgrade asteroid sexps to match new asteroid field features

* clang is a needy boy

* unify the sexp operators into one since there are minimal changes

* cleanup for readability

* address feedback
2024-08-27 20:36:54 +02:00
Mike Nelson 40bbced2f9 Reset hotkey lines before populating (#6318)
* reset hotkey lines before building

* clang is the most high maintenance partner i've ever had
2024-08-27 20:36:46 +02:00
Goober5000 a84941e6d1 Merge pull request #6323 from Goober5000/6317_followup
follow-up to BWO crash fix
2024-08-27 14:29:27 -04:00
John FernandezandGoober5000 faaa235c84 Fix: Always check for nullptrs and make red-alert respect cur_waves from last mission (#6262)
* keep from crashing

* Also, bash the number of waves if necessary

* Add Debug warning to modders

* address feedback

* formatting

---------

Co-authored-by: Goober5000 <[email protected]>
2024-08-27 14:18:37 -04:00
Goober5000 33f136dd26 follow-up to BWO crash fix
The BWO fix in PR #6317 was not quite the correct fix.  The `sim_room_lines` array contains the maximum number of scrollable lines, not the maximum number of lines on the screen at one time.  This partially reverts commit 20338ff28b and implements a new fix that allows the full `MAX_LINES` but also properly checks the list button limit.  Additionally, this adds the list button limit check to other vulnerable code sections.

Fixes the tech room being limited to a single page of missions after #6317.  Testing confirms that the BWO crash is still fixed with this update.
2024-08-27 14:06:13 -04:00
Asteroth bec860e9d8 Small optimization (#6321)
* small optimization

* put this comment where it was before
2024-08-27 02:30:03 -04:00
Mike Nelson 6280ffe0e1 Accessibility IFF colors (#6300)
* accessibility iff colors

* appease clang the conqueror
2024-08-27 00:36:18 +02:00
Kestrellius 91a673ac58 Generic random distributions, including curve-based (#6314)
* Adds PDF to CDF function.

* Further implementation; not complete

* Implements curve integration.

* Implements binary search.

* Finalizes random-range reorganization

* Extends generic range support to various things.

* Removes infinities.

* Fixes bugs.

* Adds handling of invalid prob curves.

* Adjusts warning.

* Exception handling

* Addresses issues raised during review.

* Cleanup

* Appeases clang

* Further appeasement

* even further appeasement

* appeasement^3

* appeasement^4
2024-08-27 00:27:33 +02:00
Goober5000 a74bfab94b Merge pull request #6278 from Goober5000/timestamp_refinement
some timestamp refinements
2024-08-26 16:09:31 -04:00
Goober5000 12784be019 use new isFinite() in several existing expressions 2024-08-26 15:11:15 -04:00
Mike Nelson 23f7fa7f02 Fix brown asteroid being an immortal member of the asteroids kingdom (#6320) 2024-08-26 14:55:31 -04:00
Goober5000 8da346dee3 Merge pull request #6304 from Goober5000/immobile_flags
implement don't-change-position and don't-change-orientation
2024-08-26 13:47:47 -04:00
Goober5000 ac16a54bec Merge pull request #6312 from Goober5000/fred_lock_from_editing
add option in FRED to lock objects from being edited
2024-08-26 13:47:39 -04:00
Goober5000 ddfd0c6fca update comment 2024-08-26 01:54:23 -04:00
Goober5000 dccb7dc8cf Merge pull request #6317 from Goober5000/fix_bwo_crash
fix the mysterious crash in BWO
2024-08-25 22:36:38 -04:00
Goober5000 20338ff28b fix the mysterious crash in BWO
This is an error that existed all the way back in retail.  Each line in the simulator room (i.e. each mission name in the list) is also a "button" in the sense that clicking on it will highlight the line and set some values.  The maximum number of buttons is `LIST_BUTTONS_MAX`, but the maximum number of `sim_room_lines` was a different #define, `MAX_LINES`.  This was set to 200, a far higher value than the `LIST_BUTTONS_MAX` value of 42.  The code responsibly checked the limit, but the limit was incorrect.

(This had not been seen in previous mods because the number of lines was never high enough to reach 42.  BWO happened to use a font that was small enough to fit that many lines in the mission simulator screen.  This explains why removing fonts.tbl prevented the bug from occurring.)

Thus when the number of lines reached 42, the sim room started writing to out-of-bounds memory.  This didn't cause a crash immediately, but did corrupt the `Static_lights` vector, which in turn caused a crash as soon as a model was lit in-mission or in the ship loadout screen.  It's rather strange that this crash only occurred in optimized SSE2 builds though.

The fix is simply to use `LIST_BUTTONS_MAX` as the limit, rather than `MAX_LINES`.  This also removes the unused `MAX_DESC_LINES` and `Num_desc_lines` at the same time.

Fixes #6313.
2024-08-25 21:56:37 -04:00
Goober5000 c8010e5447 some timestamp refinements
1. Make sure the legacy `timestamp_until()` and `timestamp_since()` functions check for any type of invalid timestamp
2. Add a useful `isFinite()` function
3. A timestamp delta on an immediate timestamp is more properly the actual delta, rather than another immediate timestamp
2024-08-24 17:24:39 -04:00
Goober5000 92b628353f Merge pull request #6286 from Goober5000/sound_indexing_refinement
improve sounds.tbl index ordering
2024-08-24 16:22:23 -04:00
Goober5000 ff69743836 Merge pull request #6311 from Goober5000/fix_waypoint_marking
fix waypoint marking
2024-08-24 10:37:15 -04:00
Goober5000 38f8943ccf Merge pull request #6316 from Kestrellius/const-matrices
Adds const to a couple batching matrices.
2024-08-23 21:18:31 -04:00
Goober5000 df0f3da79c Merge pull request #6306 from Kestrellius/conditional-impacts-warning
Adds warning if cond-impact armor type not found.
2024-08-23 21:01:17 -04:00
Kestrellius f5ccf98b17 Adds const to a couple batching matrices. 2024-08-23 17:59:15 -07:00
Kestrellius e87d311d92 further cleanup 2024-08-22 18:35:11 -07:00
Goober5000 b5acdd607f add option in FRED to lock objects from being edited
Add options to the Edit menu to lock and unlock objects.  Locked objects cannot be selected or dragged.  They can still be edited in the various editors (e.g. Ships, Objects) but not in the main viewing area.

Also add the Selection Lock option to the Edit menu.  It was previously available in the toolbar but this provides another way to access it.
2024-08-22 15:25:30 -04:00
Goober5000 332ccbc2df fix waypoint marking
When the Show Waypoints option is toggled, the marking was not updated as it was for the other options (Show Ships, Show Starts, Show IFFs).  Fix this by calling `correct_marking()`.
2024-08-22 14:23:39 -04:00
EatThePath 32b69eda2a Merge pull request #6307 from naomimyselfandi/fix-weapon-class-swarm-info
Fix WeaponClass.SwarmInfo
2024-08-22 14:13:27 -04:00
Kestrellius a569bd9ab7 Cleanup 2024-08-22 07:01:23 -07:00
Kestrellius ca70a5a242 Adds support for explicit no-armor; cleanup 2024-08-20 12:31:13 -07:00
Mike Nelson 397a1c84ba Grant access to shipclass shield hitpoints value (#6308) 2024-08-20 01:18:07 +02:00
Naomi Coffman ce6a6b447e Fix WeaponClass.SwarmInfo 2024-08-19 14:01:53 -04:00
Kestrellius 5531dfc58d Adds warning if cond-impact armor type not found. 2024-08-19 10:10:00 -07:00
wookieejedi db13168729 Cleanup variable name in weapon_do_area_effect function (#6303)
* Cleanup variable name in `weapon_do_area_effect` function

Per discussion in #6302, this PR renames `other_obj` to `impacted_obj` to minimize confusion

* update other functions with impacted_obj naming

* nullptr

* appease clang's strange rules

* fighting clang continues

* use !empty check instead of > 0

* remove un-needed no lint comment
2024-08-18 20:59:18 +00:00
Goober5000 cc5bb307c0 Merge pull request #6268 from Baezon/remove-some-prints
Remove some overzealous prints
2024-08-17 19:16:14 -04:00
Goober5000 6b0fe5a763 fix template warnings when compiling 2d.cpp (#6305)
Fix several compilation warnings related to templates by properly casting these values.  See also the existing example that uses casts in cmdline.cpp.
2024-08-18 00:59:21 +02:00
Goober5000 704bf95a75 implement don't-change-position and don't-change-orientation
Per #4294, this adds two new flag that, together, are equivalent to the legacy "immobile" flag but individually provide more fine-grained control.  Since the physics for position and orientation have a bit of overlap, the new flag functionality simply reverts whatever position or orientation changes were done by the physics sim.

In the FRED and qtFRED ship flags dialogs, the "immobile" flag (aka "Does Not Move") is replaced by the two new flags, but in FSO the situation is more complicated.  The old and new flags coexist and have overlapping functionality, so the mission designer must be careful to set and unset the appropriate flag (that is, it is possible for both "immobile" and "don't-change-position" to be set at the same time, in which case the ship cannot change position without both flags being unset).  The `set-immobile` and `set-mobile` legacy SEXPs ensure that the new flags are removed so as not to conflict with the legacy flag, but the `alter-ship-flag` and `are-ship-flags-set` SEXPs and the `getFlag` and `setFlag` script functions use exactly what the FREDder/scripter specifies and nothing else.

(I attempted to completely replace "immobile" with the two newer flags, but it proved intractable to do this while maintaining reverse compatibility: retrofitting single-flag functions to apply dual flags for one particular situation made the functions harder to understand as well as introducing many edge cases and opportunities for bugs or "gotchas".)

Implements #4294.
2024-08-17 16:46:48 -04:00
Goober5000 9887a7b638 move secondary_point_reload_pct maintenance to a more sensible location 2024-08-17 16:46:48 -04:00
wookieejedi 908c1c7b32 Fixes CTD with new Friendly Fire Feature (#6302)
* Fixes CTD with new Friendly Fire Feature

On current master I was hitting a CTD when firing a weapon with a shockwave at close range (ie player is within the shockwave zone). The minidump showed `other_obj` was null, so this PR adds some safety checks.

Tested and this fixes the crashes.

* fix obj usage

* one more obj cleanup
2024-08-17 18:30:21 +00:00
BMagnu 619591f680 Fix shuffling of older but active directives (#6299) 2024-08-16 22:01:28 +02:00
EatThePath 16447b7c7b Remove routine exceptions for unset option values (#6296) 2024-08-15 23:38:18 +02:00
Asteroth 05a0220f4a Merge remote-tracking branch 'upstream/master' into remove-some-prints 2024-08-15 17:30:32 -04:00
Asteroth 20bd8b4bf4 switch to nprintf 2024-08-15 17:29:16 -04:00
EatThePath 57c160623a Stop checking the options value for deferred lighting all the time when it requires restart to change. (#6297) 2024-08-15 14:09:25 +02:00
Asteroth 590cfa5f81 Merge pull request #6293 from Baezon/remove-some-int3s-from-hud-code
Remove some int3s from offscreen indicator drawing
2024-08-14 18:10:29 -04:00
Goober5000 8390304a6e Merge pull request #6292 from Goober5000/lua_tostring_nullcheck
safety check for lua_tostring()
2024-08-13 22:39:16 -04:00
Goober5000 f7e934440c parameter deconfliction (#6282)
Prevent compiler warnings caused by the `value` parameter of the external serializers hiding the `value` member of `std::integral_constant`.

Follow-up to #6276.
2024-08-13 23:17:28 +02:00
Kestrellius 6da7830b7b Add offset for tabled particle effects (#6264)
* Adds particle effect offset.

* bugfixing

* Switches to a cleaner approach.

* Futureproofing for particle parenting.

* actually let's just bundle parenting into this one

* working on turrets

* grinding toward turret correctness

* still grinding toward correctness

* Gets turrets working correctly.

* Fixes merge artifact

* appeases clang-tidy

* Updates some comments.

* Updates some comments.

* Tiny bit of cleanup.

* Deduplicates comments.
2024-08-13 23:06:44 +02:00
Kestrellius 67a9f6f5b7 Friendly fire control flags and SEXP (#6265)
* Adds flags.

* Basic structures built; still needs work.

* Fills out SEXP.

* bugfixing

* appeases clang-tidy

* Adds flags.

* Basic structures built; still needs work.

* Fills out SEXP.

* bugfixing

* appeases clang-tidy

* further appeasement

* Makes implementation more consistent.

* Fixes and cleanup as requested.

* Adjusts is_nan handling.
2024-08-13 20:32:02 +02:00
John Fernandez e1be949d0e Merge pull request #6288 from JohnAFernandez/Fix-lead-indicator-behavior
Fix renderLeadCurrentTarget
2024-08-13 13:52:33 -04:00
Asteroth c64a3e5e6a shouldnt lose target either 2024-08-13 13:26:04 -04:00
Asteroth 65d281e3cb remove some int3s 2024-08-13 01:40:31 -04:00
Goober5000 4cbd84d59e safety check for lua_tostring()
The return value of `lua_tostring()` is NULL if (and only if) the string conversion failed.  Many places in the code did not check for this situation, which led to the crash in #6290.

Fixes #6290.
2024-08-12 16:00:24 -04:00
Kestrellius d4cd767679 Beam slash curves (#6269)
* Adds curves for slash completion and rotation.

* Finalization.

* Fixes pointer comparison.

* Updates table parameter to better match behavior.

* Makes requested changes.

* Changes rotation amount to use raw curve.

* Sets curve-1.0 to be equal to full turn rotation.
2024-08-12 19:58:37 +02:00
Goober5000 e9592bc4d7 add scripting support for wing wave min/max delay (#6280)
There was scripting support for wing arrival/departure delays, but not for wave delays.  Now there is.
2024-08-12 19:58:25 +02:00
Goober5000 5bc929d06e add is-species SEXP operator (#6283)
As noted on Discord, there was previously no `is-species` operator.  Now there is.

As a bonus, this also fixes a bug where the pre-existing `is-iff` operator did not work with wings that had not yet arrived.
2024-08-12 19:58:16 +02:00
Goober5000 8dc1ffea94 Merge pull request #6260 from Goober5000/coverity_fixes
some coverity fixes
2024-08-11 17:01:39 -04:00
JohnAFernandez a9fdbac199 Fix one comment's accuracy 2024-08-10 01:29:05 -04:00
JohnAFernandez 01d3e14dc1 Fix renderLeadCurrentTarget
This fixes an edge case in the Average and Multiple modes, where secondary lead indicator rendering was skipped by continue statements when the primary weapons were out of range.   I also added some comments that help people actually understand what this function does as it is very confusing.
2024-08-10 01:09:10 -04:00
Goober5000 61e94636ac Merge pull request #6284 from Goober5000/directive_timing
fix a minor bug with directive marking
2024-08-08 19:01:11 -04:00
Goober5000 d16eb20aea improve sounds.tbl index ordering
Although sound indexing is now done by name, mods which index by number (sc. a number that is treated as a name) expect the indexes to be in numeric order.  When multiple levels of -snd.tbm files add mixed retail-style and new-style sounds, this assumption can be violated due to named sounds being placed into indexes that later files expect to be available.

This PR refines the parsing so that sounds which use a numeric index can pre-empt existing named sounds that have been assigned to that index.  Since named sounds can go anywhere, they are just moved to the end of the list.  This allows the ranges 192-199 and 202-249 to be available for numeric indexes as expected under the old style.  MediaVPs named sounds which were previously parsed into those indexes are bumped to the next available index.

Additionally, this PR doubles the range of numbers that are treated as indexes, to more realistically accommodate additional numbered sounds.  (The number/index distinction is rather arbitrary and is primarily used to avoid creating large sections of unused sounds if a mod were to specify a very large number, e.g. 10001, for a sound name.)

Finally, this changes parse warnings to use `error_display()` so that the warning displays the parsed file and line number.
2024-08-08 19:00:20 -04:00
Goober5000 f2bffd3234 fix a minor bug with directive marking
Fix units are denominated in seconds, while timestamp units are denominated in milliseconds.  This fixes the directive timing check which, after the timestamp upgrade, would time out after 5 and 7 milliseconds instead of 5 and 7 seconds.

Follow-up to #4633.
2024-08-07 02:28:20 -04:00
Kestrellius 35db8e31c9 Adds weapon support, switches parse ordering (#6254) 2024-07-29 22:35:57 +02:00
Kestrellius cb75da4de6 Interpolate particle spawning positions for moving spawner objects (#6249)
* Sets up linear interpolation for object particles.

* Makes interpolation time-based.

* Updates comments to match changes.

* appeases clang-tidy

* Adds interpolation for particle particles.
2024-07-29 22:35:44 +02:00
Goober5000 d057c0b830 Merge pull request #6277 from Goober5000/improve_model_texture_parsing
improve model texture parsing
2024-07-29 16:11:32 -04:00
Goober5000 693a4a346d Merge pull request #6276 from BMagnu/ade_rpc_serialize_cleanup
Slightly clean up RPC API
2024-07-29 16:11:21 -04:00
Goober5000 734efbdb54 variable checks and message enhancements 2024-07-29 16:04:23 -04:00
Goober5000 c6844755d3 address false positives in smart pointers 2024-07-29 16:04:23 -04:00
Goober5000 1ca56897bb some coverity fixes
Check the return value of `eval_wing()`, and tweak the checks for `closeup_pos` in `draw_model_rotating()`.  This addresses a few Coverity defects.
2024-07-29 16:04:16 -04:00
Goober5000 1fae61b873 improve model texture parsing
Model textures that are too long will cause a very unfriendly and hard-to-track down "ERANGE: String" error.  The situation can be greatly improved by checking the string length ahead of time, printing a friendly Warning, and truncating the filename.  This will alert the modder to the source of the problem while also allowing gameplay to continue.
2024-07-29 15:47:22 -04:00
Birk Magnussen 500bf1c2ca Add clang NOLINTs
To explain: Clang's being stupid here, and seemingly does not recognize that the placement new in the deserializers requires a non-const ptr.
2024-07-29 19:59:02 +02:00
John Fernandez 19b415e524 Merge pull request #6275 from JohnAFernandez/Fix-Duplicate-Interface-Sound-Entries-Crash
Fix a sound crash
2024-07-29 08:52:38 -04:00
BMagnu 558f922209 add implicit-only includes 2024-07-29 10:26:59 +02:00
Birk Magnussen 7caef527d4 Slightly clean up RPC API 2024-07-28 11:15:02 +02:00
JohnAFernandez 72b5135df4 Fix an interface sound crash
This would crash because duplicate sounds were not being populated with the original entries.  When snd_set_pos was called, the handle to the Sounds array would not be set, making our code think it was not loaded.
2024-07-28 01:01:10 -04:00
Kestrellius f041b8dace Adds consts to parameters for a couple laser rendering functions. (#6270)
* Adds consts to parameters for a couple functions.

* makes it actually compile
2024-07-25 22:58:24 +02:00
Goober5000 372d2dd18e Merge pull request #6267 from vmedea/2024-07-sdl2
Fix SDL2 pkg-config name
2024-07-25 14:57:10 -04:00
BMagnu 81da8a8499 disable misc-no-recursion (#6266) 2024-07-24 23:33:15 +02:00
Asteroth 6a5cd9fcc5 remove some prints 2024-07-24 13:41:13 -04:00
mara 4ea0757950 Fix SDL2 pkg-config name
The pkg-config name for SDL 2 is lowercase 'sdl2', and it was passed in
upper-case so the proper library was never detected on Linux. Fix the name.
2024-07-24 14:47:02 +00:00
Goober5000 ea00032d7e by request, add an additional comment 2024-07-23 00:01:09 -04:00
Goober5000 44c949f8d5 optimize collision code a bit
This was motivated by the recent Coverity report.  Coverity noticed that a few of the copy assignments could be replaced by move assignments, but on further investigation one copy each in `ship_weapon_check_collision()` and `beam_collide_ship()` can be entirely removed, another either/or copy in each can be replaced with an either/or pointer assignment, and a few copies can be done only when needed.  Another vec3d copy (`hit_dir`) can be replaced with a vec3d pointer; it is no longer modified locally, so there is no longer a need to keep a local copy.
2024-07-22 23:57:20 -04:00
Mike Nelson 79d0c93ba5 Print in game options data to scripting output files (#6257) 2024-07-21 12:25:32 -04:00
Tyler Blount eeba1085c9 Merge pull request #6243 from MjnMixael/per_weapon_convergence
Per weapon auto convergence
2024-07-20 11:57:55 -07:00
Goober5000 ebb5a27922 refine timestamp_valid
Change `timestamp_valid()` to also catch the common case of -1 being used for invalid as well as the "official" 0.
2024-07-20 01:19:23 -04:00
Mike Nelson 70629876b9 allow accepting a pilot without changing gamestate (#6235) 2024-07-18 22:44:59 -04:00
Goober5000 e1458ae8ab Merge pull request #6259 from Goober5000/6258_followup
fix copy-paste error in timestamp_since
2024-07-17 18:35:41 -04:00
Goober5000 bac4eb84c0 fix copy-paste error in timestamp_since
The time since an invalid timestamp should be INT_MIN, not INT_MAX.  Follow up to #6258.
2024-07-17 14:24:40 -04:00
Goober5000 20602b19c2 Merge pull request #6255 from Goober5000/atan2_safe_to_atan2
change atan2_safe to atan2
2024-07-17 13:30:13 -04:00
Goober5000 3c3289a3cc Merge pull request #6258 from Goober5000/fix_6256
fix `NextFireTimestamp`
2024-07-17 13:30:04 -04:00
Goober5000 2166c756ab per review, make the delta check silent 2024-07-16 20:59:30 -04:00
Goober5000 5faed98e3a handle special timestamp values in timestamp_until and timestamp_since 2024-07-16 20:27:14 -04:00
Goober5000 fe3b72b01e fix NextFireTimestamp
Changes `NextFireTimestamp` to work as advertised.  Fixes #6256.
2024-07-16 17:27:41 -04:00
Asteroth 8914ac6e2d guards ignore protected attackers (#6253) 2024-07-16 15:46:12 -04:00
Goober5000 87ea04fa53 change atan2_safe to atan2
According to DahBlount:
> Most atan2 implementations for a long time had problems when the inputs were close to machine epsilon or when x was less than or equal to 0

And according to z64555:
> Modern versions of C++ should have an atan2() that works correctly when the inputs are at 0 or near epsilon of the floating point specification, meaning Volition's workaround shouldn't be needed anymore.

So this removes `atan2_safe` and changes all instances to `atan2`.  Consequently, the angle range in FRED now shows as [-180, 180] as expected.

Fixes #3730.
2024-07-15 20:55:57 -04:00
wookieejedi f5a268bcef Expose Minimum LoS Detection Radius (#6252)
The somewhat modern AI flag for `Require_exact_los` is extremely useful in multiple different situations, for example making large capital ship weapons not fire into friendly surrounding ships on accident. When the feature was added, the `check_los` function was provided with a default value of `10.0` meters for minimum radius detection. This PR exposes that value to modders so they can set it to a reasonable value depending on the ship sizes of their specific needs. And as a note, the los value just uses a simple numerical comparison check, so the los detection could be set to a negative value with no consequence (hence why error messages were not added, though if folks would like I can certainly add them).
2024-07-15 08:30:31 -04:00
Goober5000 1db093e1d6 Merge pull request #6251 from Goober5000/popup_keys_fix
fix incorrect processing of keys during ESC popup
2024-07-14 20:07:18 -04:00
Goober5000 3d556af391 Merge pull request #1451 from Goober5000/pilot_stats_fixes
better stats handling when switching or resetting campaigns
2024-07-14 20:06:51 -04:00
mjn-mixael e1fd863dd0 cleanup whitespace 2024-07-14 10:11:22 -05:00
mjn-mixael 1744718a03 We can remove this bool now that we have bools for each flag set 2024-07-14 10:08:50 -05:00
mjn-mixael d9cfd1f626 Fix boolean checks that determine the which aiming style to use 2024-07-14 09:53:19 -05:00
Mike Nelson d9f9996c2d expose shockwave damage (#6245) 2024-07-13 09:29:48 -04:00
Goober5000 6f05c26542 fix incorrect processing of keys during ESC popup
In retail, the processing of certain keys during a popup, in the `popup_process_keys()` function, was dependent upon the `PF_ALLOW_DEAD_KEYS` flag.  This flag was never used in retail, causing the if() block to be marked as dead code.  In a4e623db23, the dead code warning was addressed by removing the dependency on `PF_ALLOW_DEAD_KEYS`, which is incorrect.  The "dead keys" should only be processed during the "dead popup".  Since the "dead popup" was moved to its own de[a]dicated "popupdead" section, the "dead keys" processing can be entirely removed from the "normal popup".

Fixes a bug noticed by @PremiumColt where certain keys, especially the time compression keys, were processed while the ESC popup was active.
2024-07-12 20:08:57 -04:00
Goober5000 944549ae5f Merge pull request #6246 from notimaginative/update_prebuilt_libs
update to newest prebuilt libs
2024-07-12 17:33:41 -04:00
Goober5000 fbab427943 Merge pull request #6250 from Goober5000/coverity_on_scp
only run the Coverity workflow on the SCP repository
2024-07-12 17:32:54 -04:00
Goober5000 705238a184 only run the Coverity workflow on the SCP repository
This prevents Coverity from running on any forked repository, by default; both because the workflow will fail, and also because the workflow's results would be identical.  (Any forked repository can, of course, change this within its own scope.)
2024-07-12 16:28:25 -04:00
Goober5000 7557c54aa9 restore clearing of stats based on comments from #6238 2024-07-11 21:53:16 -04:00
Goober5000 f341987471 Merge pull request #6248 from Baezon/bugfix-invulnerability-time-again
Bug fix for aspect invulnerability timing... again
2024-07-11 21:19:33 -04:00
Goober5000 cdbf525877 Merge pull request #6233 from JohnAFernandez/Add-Insignia-Renderer
Fix Insignia Checkbox in the Lab
2024-07-11 21:19:01 -04:00
Goober5000 cc790a00bd Merge pull request #6223 from Goober5000/address_6010
address 6010
2024-07-11 21:17:40 -04:00
Asteroth b565376a02 account for original retail handling 2024-07-11 01:50:13 -04:00
wookieejedi 52f417500c Fix Settings Localization IDs (#6242)
In `strings.tbl` the graphics settings localization IDs are as follows:
1160, "Low"
1161, "Medium"
1162, "High"
1163, "Very High"

These values are used throughout the code, but in some cases with SCPUI upgrades, the IDs got off by 1. This PR fixes those incorrect IDs.
2024-07-09 18:07:18 -04:00
Taylor Richards 79d6e91403 additional fixes 2024-07-09 12:23:35 -04:00
naomimyselfandi 5235aac95b Respect tabled delay for arrival and backup messages (#6239)
* Respect the tabled delay for Arrive Enemy messages

* Respect the tabled delay for Backup messages
2024-07-09 07:59:22 -04:00
Taylor Richards bebed48bf8 address errors 2024-07-09 04:39:39 -04:00
Taylor Richards 38e27f8a25 update to newest prebuilt libs
Supports newer SDL2 from the prebuilt package on win32/win64
Adds support for Windows ARM64
Adds option to use prebuilt SDL2/OpenAL/Freetype libs on Linux
2024-07-09 03:17:29 -04:00
BMagnu 98d5de9d13 Make clang const correctness a little less aggressive (#6244) 2024-07-08 19:40:48 +00:00
mjn-mixael 6fdaf87717 du const 2024-07-08 14:32:09 -05:00
mjn-mixael acccc90ded per weapon auto convergence 2024-07-08 14:06:56 -05:00
John Fernandez de570875d0 Merge pull request #6231 from JohnAFernandez/Fix-unreliable-channel-soundid-chacing
Fix unreliable Sounds index retrieval
2024-07-07 20:51:22 -04:00
BMagnu e17f0260f6 Update clang tidy to 16 as used to compile (#6236) 2024-07-06 23:01:32 +00:00
BMagnu 6b6a622c4d Fix clang-tidy (#6234)
* Allow clang-tidy to run

* Amend CI check
2024-07-06 15:16:44 +02:00
Goober5000 e90416e199 Several coverity fixes (#6232)
* coverity - using `std::move` instead of copying, and change some parameters from value to reference

* coverity - fix or mark potential copy-paste mistakes

* coverity - various checking of parameter and return values

* coverity - miscellaneous fixes, and change some 'intentional' markers to 'false positive' markers
2024-07-06 12:51:31 +02:00
JohnAFernandez a319adad76 Use constexpr and value, because we broke defines 2024-07-05 17:26:36 -04:00
John Fernandez 97e36d8af6 Don't forget to remove the declaration 2024-07-05 15:24:11 -04:00
wookieejedi f20c1bddfd Fix short read error with red alert csg file reading (#6229)
In current master, the debug log commonly shows `CSG => Warning: (0x0011) Short read, information may have been lost!`.

Thanks to Taylor for pointing the following issue out:
The function `pilotfile::csg_read_redalert()` returns if `ship_list_size` is zero, but it still needs to check the `wing_list_size` a bit below that. This has likely not caused data loss issues ATM, because it's reasonable to assume that if `ship_list_size` is zero then so is `wing_list_size`. But it's still a bug and should be fixed before it does cause some real data loss.

This PR moves the relevant read sections to within each respective if-block. That way the function is capable of checking both `ship_list_size` and `wing_list_size` on every load (even if `ship_list_size` is zero).
2024-07-05 12:50:56 -04:00
JohnAFernandez c50b425fee More type fixes 2024-07-05 01:14:36 -04:00
JohnAFernandez 7a99e9a7c9 Even more type conversions 2024-07-05 01:11:48 -04:00
John Fernandez 84ccd1375e Fix Flag Negation 2024-07-05 00:57:06 -04:00
John Fernandez a7fc64389f Use the correct method to get index to Sounds
Our sound code is extremely confusing, so it's no wonder that the author of these functions could not find snd_get_sound_id.
2024-07-05 00:44:29 -04:00
John Fernandez ac44f1478e Merge pull request #6226 from JohnAFernandez/Try-Saving-Config-Name-As-Default
Save current preset name and use as default when saving new preset name
2024-07-04 21:42:03 -04:00
John Fernandez ffd78555a0 Enable turning off insignias in the LAB 2024-07-04 19:33:33 -04:00
John Fernandez 1f834aa406 change render flags to uint64_t
32 more flags, yay!
2024-07-04 18:08:27 -04:00
JohnAFernandez 4f2f8c9f25 Save Current Preset name and Use when Saving 2024-07-04 00:35:55 -04:00
Goober5000 200ef1093c Merge pull request #6225 from Baezon/fix-poof-alignment
fix poof alignment
2024-07-03 21:12:45 -04:00
Goober5000 691fe96151 Merge branch 'master' into pilot_stats_fixes 2024-07-03 20:56:56 -04:00
Asteroth 840759d59a fix poof alignment 2024-07-03 19:41:21 -04:00
Goober5000 83d07277f2 Merge pull request #6224 from Goober5000/fix_coverity_task
fix coverity task
2024-07-03 17:12:36 -04:00
Goober5000 cccf76863f fix coverity task
Per @notimaginative, change the `compiler` variable to uppercase to match its usage in the rest of the file.  This should allow the coverity task to start running again.
2024-07-03 16:41:18 -04:00
Goober5000 c03207f141 address 6010
I took a close look at the code involved in parsing particle tables.  There is no smoking gun, but there are several ways to polish the code which I have implemented here.  The most likely culprits for the slowdown, IMO, are the repeated conversions between SCP_string and C-string, especially in `ParticleManager::getEffectByName()`; followed by the omission of `std::move` in several places.
2024-07-03 15:06:33 -04:00
John Fernandez 5df0acf3ef Merge pull request #6185 from MjnMixael/assign_hud_in_ships
Assign hud in ships.tbl
2024-07-03 10:40:54 -04:00
Mike Nelson 75221b0ff5 deprecate some commandlines and make some options not require restart (#6214) 2024-07-02 22:44:44 -04:00
Mike Nelson 6a4774dcc4 Change warning print 2024-07-02 17:06:28 -05:00
Goober5000 eed055d41a Merge pull request #6219 from Goober5000/lock_perspective_and_slew
enhance lock-perspective to also lock slew mode
2024-07-01 16:29:22 -04:00
Goober5000 e374db538c Merge pull request #6220 from Goober5000/enhance_stuff_int_list
enhance stuff_int_list to allow turning off the warning
2024-07-01 16:29:14 -04:00
Goober5000 6468901c0d address feedback 2024-07-01 16:01:31 -04:00
Kestrellius d14b66456f Adds conditional impact functionality. (#6218)
* Adds conditional impact functionality.

* Changes as requested.

* Second batch of changes.

* Switches out insert_or_assign so the checks pass.
2024-07-01 21:45:48 +02:00
naomimyselfandi 723209ce29 Clarify some SEXP operator documentation (#6216)
* Clarify some SEXP operator documentation

* Reword SEXP operator descriptions per feedback
2024-07-01 21:45:41 +02:00
Goober5000 98da98c53b enhance stuff_int_list to allow turning off the warning
This will be useful for situations where a missing lookup entry is not valid but nevertheless does not merit a warning.
2024-06-30 22:37:20 -04:00
Goober5000 558a8333e4 add an option to not change the view mode 2024-06-30 21:42:51 -04:00
Goober5000 ffcbfeb70b enhance lock-perspective to also lock slew mode
Adds an optional argument to the `lock-perspective` sexp to allow locking of the 'free look' or 'padlock' view.  This prevents the player from looking around which might not be desired in certain forced perspective situations.
2024-06-30 21:41:17 -04:00
Goober5000 c5de5149a9 Merge pull request #6217 from Goober5000/debris_type_parsing
another follow-up to #6021
2024-06-30 17:08:53 -04:00
Mike Nelson e868d94927 cleanup message_kill_all (#6213) 2024-06-29 11:03:15 -04:00
naomimyselfandi 253d97a3df Allow defining custom message types (#6142)
* Vectorize Builtin_messages

* Allow defining custom message types

* Add OPF_MESSAGE_TYPE

* Add send-builtin-message SEXP operator
2024-06-29 12:32:17 +02:00
Goober5000 da93cc6047 another follow-up to #6021
When loading a legacy mission that contains a debris field, FSO will try to index into an empty vector, causing an out-of-bounds exception.  This can be seen by loading Derelict mission dl1-08, "The Horror in the Deep".

The `// Obsolete and only for backwards compatibility` code added in #6021 properly handles asteroid fields, but not debris fields; so the fix is simply to apply the logic to debris fields as well.
2024-06-28 21:35:12 -04:00
BMagnu b57278ab18 Adds Voluemtrics Toggle SEXP (#6215)
* Allow toggle of volumetrics

* enhance description

* Typo
2024-06-28 17:56:22 +02:00
Goober5000 630f479fd9 properly handle game sounds with numeric IDs (#6212)
Patches the gamesnd system in several ways to properly fix the bug identified in #6196.  Due to the way the new sound system was written, sounds with numeric IDs were not necessarily added in their indexed location, even though the code assumed (even prior to #6112) that this would be the case.  The code now uses the proper index for both old *and* new style sounds.  This is done by ensuring, in `gamesnd_parse_entry()`, that the vector contains an entry for the specified numeric ID before doing a search for that ID.

Due to the slightly modified population of the gamesnd vectors, the `Snds_iface_handle` vector is now populated after parsing the various sounds.tbl files rather than during parsing.

Separately, this makes consistent the handling of the `sound_entries` vector which could potentially be empty but also treated an empty state as an assertion failure.
2024-06-27 23:55:42 -04:00
John Fernandez e7a7c830f0 Merge pull request #6184 from MjnMixael/ship_wep_custom_strings
Custom Strings for ships and weapons
2024-06-27 10:21:01 -04:00
Mike Nelson d6e7d56081 expose method to kill all current voice messages (#6207) 2024-06-27 08:07:35 -04:00
Mike Nelson 5c5bcf72e9 don't kill paused messages either (#6206) 2024-06-27 08:07:19 -04:00
wookieejedi 06f909d7e3 Followup to #6187 (#6211)
#6187 fixed transparency for cockpits, but the positioning for deferred lighting alas fell through the cracks. This PR fixes that and allows deferred lighting in cockpits to once again work as intended.

Tested and fix works as expected.
2024-06-26 14:08:38 +00:00
Mike Nelson 46d4a1f219 fix screenshudder option being optimized out by the compiler (#6204) 2024-06-26 16:51:41 +09:00
BMagnu 7e71d4c194 Add ugly hack to prevent SCPUI flicker on Win11 (#6199) 2024-06-26 16:50:38 +09:00
Goober5000 2314294a8c Merge pull request #6209 from Goober5000/parse_names_clear
clear Parse_names on mission init
2024-06-25 19:50:54 -04:00
Goober5000 3bce3fd631 clear Parse_names on mission init
When a new mission is loaded, clear the parse names vector, in lieu of the old `Num_parse_names = 0;` line.  This fixes a bug where FRED will complain about nonexistent ships when loading a different mission.  Follow-up to #5937.
2024-06-25 17:33:39 -04:00
wookieejedi 31452e397b One more follow-up to #6021 (#6202)
* One more follow-up to #6021

Update assertion message and mission saving check since older builds are not going to be able to read fields created with newer builds

* update to use empty
2024-06-24 02:59:31 +00:00
wookieejedi 80e3030a0c Follow-up to asteroids update #6021 (#6201)
The Unlimited Asteroid/Debris Field Types & Subtypes PR (#6021) updated to using vectors to allow for unlimited asteroid and debris types. That update removed the count field, `num_used_field _debris_types`, which counted both asteroids and debris pieces (even though the name only has debris in it). The counter variable was removed in favor of `.size()` but now both asteroid and debris field sizes needed to be checked, so this PR updates the code to account for that. Allows asteroid fields to properly pass the count check and properly again spawn in mission.

Tested on asteroid fields passive and active along with debris fields (both created from sexps and the asteroid mission editor) and everything now works as expected. Also tested on missions with no fields and those also still work as expected.
2024-06-23 10:53:39 -04:00
John Fernandez 4a739c988f Merge pull request #6198 from MjnMixael/fix_ingame_options_init
Fix ingame options init bugs
2024-06-21 19:40:45 -04:00
mjn-mixael 7b4deb6c6b Fix ingame options init bugs 2024-06-21 14:16:43 -05:00
BMagnu 3d285f2f42 Fix transparent cockpit by ensuring ordering (#6187) 2024-06-21 17:38:47 +02:00
BMagnu 7403f4a1c9 Improve Volumetrics Performance (#6159)
* properly trace volumetrics and explicitly set texture setting

* UDF-ify volumetrics

* Fix warning

* only apply lower bound when actually correct
2024-06-21 17:10:14 +02:00
John Fernandez 9f99a9eae4 Merge pull request #4489 from JohnAFernandez/Ensure-break
Simplify logic here
2024-06-20 01:30:56 -04:00
John Fernandez d11003a869 Simply logic here
Break when you've found a match, instead of just mindlessly comparing the rest.

This is technically just an optimization and safety change, but potentially, before, if the loops had been switched, it would have caused unexpected behavior if two copies of the same flag were listed.
2024-06-20 01:11:19 -04:00
Taylor Richards 1b855044c7 fix data length bug in PXO hole punch packet (#6195)
The header length from the tracker is 1 byte larger than the size calculated
by the client due to psnet removing that byte internally. The header length
is adjusted to compensate for this, but only *after* the deserialization
process, so we have to use the received packet size instead.
2024-06-18 20:39:43 +00:00
John Fernandez a390b5a01a Generalize linear interpolation (#5003)
* Remove old interpolate angles quick

* Remove old interpolate functions

These are no longer used.

* Add linear interpolate vm function

More clearing functions

* Add physics snapshot struct to silo interpolation

Two of these two functions require an object pointer, so they cannot be in physics_state.cpp

With doxygen documentation

* Try to placate Linux

* Address Feedback

* And update declaration, of course

* Attempt to appease linter
2024-06-18 20:10:01 +02:00
John Fernandez 8c913c8cc5 Merge pull request #6192 from notimaginative/pxo_hole_punch
add support for PXO's UDP hole punch feature
2024-06-18 12:04:01 -04:00
Goober5000 ebeec69a6d add API for glow point banks (#6107)
* add API for glow point banks

Previously, a model API existed for glow points mounted on thrusters, but not glow points mounted on glow point banks.  This adds glow point bank support.  Also, this refactors and cleans up the implementation of the model API a bit.

* NULL -> nullptr
2024-06-17 21:28:40 +02:00
Taylor Richards 1821df58cf limit debug log spam from file shadows (#6027)
Always log the possible shadow if:
 1) it's a critical file
 2) it's in the same root

Otherwise log it behind a debug filter ("CFileSystem").
2024-06-16 11:04:01 -04:00
Taylor Richards 3f9ec121ae add support for PXO's UDP hole punch feature
Should allow for most games, even those behind CG-NAT, to work without having
to set up port forwarding. This set of changes is only needed for game servers
to work with the new feature. No special handling is required for clients, so
any build from the last few years should work for them.
2024-06-16 01:58:47 -04:00
Goober5000 408f116d95 Merge pull request #6190 from Goober5000/tactical_goals_allowed
make sure 'tactical' variants of disable and disarm are allowed
2024-06-14 21:51:20 -04:00
Goober5000 ce34f77780 add the attack-ship-class goal as valid for player orders 2024-06-14 00:08:47 -04:00
Goober5000 1bb34cc0ae make sure 'tactical' variants of disable and disarm are allowed
The new `ai-disable-ship-tactical` and `ai-disarm-ship-tactical` goals were inadvertently omitted from the ship type default table, causing these goals to not be available in the Event Editor drop-down menu or Ship Editor initial orders.  Testing did not catch this because testing was done using the HUD squad message system which assigned the new goal (if the flag is enabled) without explicitly checking the validity.

Follow-up to #5512.  Fixes #6189.
2024-06-13 23:52:43 -04:00
Goober5000 f733414403 make mission log dynamic (#6111)
* make mission log dynamic

Change the mission log from a static array to a dynamic vector.  This removes any chance of the mission log running into a limit (as regularly happened with the last mission of Shepherds before the limit bump) and also prevents strange mission bugs caused by culling obsolete entries.

This also unifies the API a bit by renaming the public `message_log_` function prefixes to `mission_log_`, removing the redundant `Num_log_lines` variable, and removing `Log_scrollback_vec` from the header.

Implements #5878.

* feedback

* refactor to reference rather than pointer
2024-06-13 00:17:47 +02:00
Goober5000 9a26d1fba5 Merge pull request #6112 from Goober5000/fix_primary_ammo_rearm
fix ballistic primary banks exploding
2024-06-12 02:29:23 -04:00
John Fernandez c7334de3bd Merge pull request #6188 from MjnMixael/fix_warning_every_frame
Prevent printing a warning every frame
2024-06-11 18:43:04 -04:00
mjn-mixael e1f0042e99 prevent printing a warning every frame 2024-06-11 09:51:28 -05:00
BMagnu 559a2616f3 Fix edge case in MSAA shader (#6186) 2024-06-11 13:41:19 +02:00
Mike Nelson 7f20b9cf64 Unlimited Asteroid/Debris Field Types & Subtypes (#6021)
* base working version of unlimited debris types

* Proper FRED support

* make qtFRED handle asteroids properly

* fix qtFRED assertion

* further clean out MAX_RETAIL_DEBRIS_TYPES

* These should be sizes not POFs

* Move this to it's own method

* convert asteroid subtypes to a vector

* unlimit asteroid subtypes

* fix some global shadowing

* signed/unsigned mismatch

* Address feedback
2024-06-10 22:06:10 +02:00
John Fernandez e1b44892e5 Merge pull request #6170 from TheForce172/feature/ShipPathsDialog
Arrival/Departure Paths Dialog
2024-06-10 15:47:02 -04:00
mjn-mixael 866f907e27 comment clarity 2024-06-10 13:00:30 -05:00
mjn-mixael a1aac15e5a Make $Name style gauge config its own thing 2024-06-10 12:54:39 -05:00
mjn-mixael 49e2d60551 Allow setting gauges in ships.tbl per ship 2024-06-10 12:08:55 -05:00
mjn-mixael 67ebeb438e custom strings for ships and weapons 2024-06-10 09:43:20 -05:00
Goober5000 0f4c3ce8c7 Merge pull request #6181 from Kestrellius/beam-multishot
Make the $Shots parameter work for beams.
2024-06-10 00:33:40 -04:00
wookieejedi 786a4eff42 Follow-up to Unified Scanning (#6183)
Fixes a bug with new unified scanning PR (#6000) and adds a bit of cleanup, including consistent brackets, whitespace cleanup, and removing vestigial function from the original PR.

Tested and works as expected.
2024-06-09 22:26:23 +02:00
BMagnu d87e997d79 Increase Lua safety (#6179)
* disable popen

* Check file type when opening with io lib

* Compile on Windows

* Windows include

* Properly conserve function environment

* Correctly copy fenv
2024-06-09 17:43:54 +02:00
Mike Nelson aee0123587 Allow player-specific options even when using In-Game Options (#6045)
* Move these functions into OptionsManager for more global use

* Make sure player options are preferred even when using OptionsManager

* persist the newly loaded options to disk

* Actually let's persist these only if the load is successful and also handle the multi option

* Comment this out for now I guess
2024-06-09 12:29:15 +02:00
Kestrellius be454f74b0 Merge branch 'master' into beam-multishot 2024-06-09 01:33:44 -07:00
Goober5000 c1985656d1 Merge pull request #6105 from Goober5000/object_h_index
replace pointers with indexes in object_h
2024-06-09 02:24:46 -04:00
Goober5000 d5e387479e replace pointers with indexes in object_h
This refactors the object_h struct to store objects as indexes rather than pointers.  This is a prerequisite for making the collection of objects dynamic in the future.  See also #6100.

Follow-up to #5800 and #5829.
2024-06-09 02:06:22 -04:00
Mike Nelson 574c39210f Ingame options respect mods (#5917)
* Save/Load player options to a mod-specific ini file if possible

* use rfind instead of find to ensure it's the last dash character used for trimming

* cleanup + comments + nullptr

* A more robust way of getting the mod root using lambdas

* prevent infinite loop for non Knossos/Knet mods

* Notify the player if options may need updating and pull settings from fs2_open.ini if we can

* proper localization

* update xstr
2024-06-09 00:26:51 +02:00
Mike Nelson 4432341694 Scanning is chaos, let's make it sane (#6000)
* Unify scanning behavior

* Allow modifying the cargo title

* update localization

* update documentation

* update localization

* address feedback

* fix conflict merge resolution error

* fix oversights, missed subsys title # feature, additional xstrs

* don't need sprintf here
2024-06-08 22:20:22 +02:00
Mike Nelson 8b43b5d325 split up debris and asteroid type handling within the asteroid field struct (#6011) 2024-06-08 21:16:06 +02:00
Asteroth 836840154c Merge pull request #6180 from Goober5000/utility_find
utility functions for counting and searching
2024-06-08 13:43:10 -04:00
Asteroth 41bdcfe720 Merge pull request #6182 from Baezon/beam-fixes
Assorted beam fixes
2024-06-08 13:42:42 -04:00
Goober5000 4cdc0b9c0b change Asserts 2024-06-06 00:39:14 -04:00
John Fernandez c4a7a9dd15 Merge pull request #6157 from Kestrellius/fix-beam-particle-vel
Fix beam particle velocity
2024-06-05 12:51:44 -04:00
Kestrellius f4921b6d01 Makes minor structural changes as requested. 2024-06-05 09:39:10 -07:00
The Force 900199d97f Add confirmation on cancel 2024-06-04 22:57:10 +01:00
Asteroth 230fdf4d03 assorted beam fixes 2024-06-04 17:32:30 -04:00
Kestrellius 0da93ec5fd Adds multishot for beams. 2024-06-04 13:10:54 -07:00
Goober5000 4ed38896d2 Merge pull request #6177 from Goober5000/fix_warnings
fix compilation warnings
2024-06-04 12:05:33 -04:00
Goober5000 3529e49466 utility functions for counting and searching
Inspired by #6178, this moves the existing `count_items_with_name()` functions into utility.h and adds additional functions for finding specific items with a given `.name` or, more generally, a given field.  The `Damage_types` search has been converted to illustrate how these functions can be used.
2024-06-03 23:09:32 -04:00
Goober5000 64c17f4830 fix compilation warnings
Fixes the few remaining compilation warnings in the current codebase.  Also adds comments to the various casting macros for clarity.
2024-06-03 22:19:29 -04:00
wookieejedi b831c773dd Expose Impact Damage Type to Scripting (#6178)
* Expose Impact Damage Type to Scripting

There's already a sexp that does this, but having the script version for ships is quite useful, too. For example, scripters can set impact damage types for just the player at various difficulties.

Tested and works as expected.

* always set damage type
2024-06-03 21:59:35 -04:00
Goober5000 350130ce9d Merge pull request #6100 from Goober5000/model_and_submodel_indexes
convert model_h and submodel_h to use indexes
2024-06-01 21:20:07 -04:00
wookieejedi 1fa0f43c6f Exposes the New Flight Cursor Mode to Scripting and Fixed Aiming Setting (#6173)
* Exposes the New Flight Cursor Mode to Scripting

Thanks to #6136, FSO supports switching between two methods of flying. This PR exposes those settings and values to scripters. Tested and works as expected.

* fix aiming setting

* add reset position function

* cleanup setting pitch and heading

* one more cleanup

* update to enum support

* remove older version

* one more fix for setting flight mode
2024-06-01 02:47:03 +00:00
Goober5000 b5351c7ca8 Merge pull request #6120 from Goober5000/fred_autorecover
Fred autorecover
2024-05-31 21:46:56 -04:00
Goober5000 e4b5d5fb7e Merge pull request #6149 from Kestrellius/fix-headon-discrepancies
Make headon transition behavior consistent between laser and glow bitmaps
2024-05-31 21:46:45 -04:00
Asteroth b1d4e0a5e2 better option ordering comparison (#6133) 2024-05-31 15:05:33 +02:00
BMagnu 6a83875d93 Fix effect framebuffer blit (#6175) 2024-05-31 14:53:50 +02:00
BMagnu 01bb406b3d Allow overriding low-level keypresses (#6174)
* Clean unneeded properties

* properly queue-ify keys

* Refactor key checking to use functions instead of globals

* Update hooks and cache checked-against key

* Documentation and Naming

* match tilde

* only remove control not debug
2024-05-31 14:53:39 +02:00
Goober5000 14aa38eea9 Merge pull request #6172 from Kestrellius/fix-type-5-beam-rand
Sets type 5 end point rand to use correct values.
2024-05-29 11:48:02 -04:00
Goober5000 e991872c22 Merge pull request #6171 from Baezon/uniform-rand-vector-script
Use uniform random vector for createRandomVector
2024-05-29 11:47:39 -04:00
Kestrellius e9a91f9c1f Sets type 5 end point rand to use correct values. 2024-05-28 17:46:32 -07:00
Kestrellius e710b651de Inlines headon glow render; converts some casts. 2024-05-28 10:58:59 -07:00
Asteroth f0f7eb513f fix 2024-05-27 13:28:13 -04:00
Asteroth 3164261152 update to better random vector 2024-05-27 13:27:46 -04:00
The Force 120b76b21e GCC 2024-05-27 09:30:25 +01:00
Kestrellius c6efd0a0a3 Makes random life factor of children configurable. (#6166)
* Makes random life factor of children configurable.

* Renames parameter and associated variables.
2024-05-26 20:42:53 +02:00
John Fernandez 914f895cac Merge pull request #6162 from TheForce172/MoveShipFileQT
Move Ship Editor Files And Coverity Clean-up
2024-05-26 13:46:00 -04:00
John Fernandez b3a51d776f Merge pull request #6136 from Baezon/aim-cursor
Add 'Flight Cursor' flying style option
2024-05-26 13:23:43 -04:00
Asteroth dbac7d1259 make the options beginner instead of advanced 2024-05-26 13:05:52 -04:00
The Force 42355b2384 Add Paths Editor 2024-05-26 10:48:20 +01:00
The Force 16a0268bd7 Missed a bit 2024-05-26 06:10:05 +01:00
Asteroth 73bbc94e5e (int) -> fl2i 2024-05-24 23:19:44 -04:00
Goober5000 a0d1ad163d Merge pull request #6165 from Baezon/fix-decloaking
Fix for 'decloaking' effect
2024-05-22 21:53:28 -04:00
Asteroth 3b0d4558ca fix for decloaking 2024-05-22 19:35:01 -04:00
The Force ad8d9484c8 Hopfully Last ones 2024-05-22 20:07:20 +01:00
The Force e93a60c68a Missed a reference 2024-05-22 20:02:39 +01:00
The Force d2af199f14 Address GCC Issues 2024-05-22 19:59:22 +01:00
John Fernandez b122c7a10c Merge pull request #6160 from scp-fs2open/dependabot/pip/ci/post/requests-2.32.0
Bump requests from 2.31.0 to 2.32.0 in /ci/post
2024-05-22 14:11:20 -04:00
BMagnu 8b3e36b3c9 Allow replacement of skybox textures (#6161)
* Add skybox texture replace sexp

* Expose Skybox and Skybox instance to scripting

* first batch of comments

* change sexp name

* remove code repetition

* rebake skybox if required
2024-05-22 16:26:18 +09:00
BMagnu 87704fc817 Refactor replacement texture to a modelinstance parameter (#6154)
* Move replacement textures from ship to modelinstance

* Actually set pmi

* Fix texture replace in fred as well

* Fix bad indent

* incorporate feedback
2024-05-21 17:18:32 +02:00
dependabot[bot] 0f67b85ac0 ---
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-05-21 05:43:09 +00:00
The Force 8e082e7293 Change to size_ts and C++ style casts 2024-05-20 16:46:40 +01:00
The Force aa3192aa94 Remove Code that snuck in from another branch 2024-05-20 16:45:51 +01:00
The Force 6419adfbe4 Move Ship Files To there own folder for legibility 2024-05-20 16:45:40 +01:00
Goober5000 27caca5d2f handle modification of placeholder sounds 2024-05-18 17:34:09 -04:00
Goober5000 e3bdc106f3 fix ballistic primary banks exploding
When game sounds were changed to allow named entries, it became possible for named entries to unexpectedly replace numbered entries.  This was noticed most obviously in the ballistic rearm sound effect, which started using explosions rather than the standard rearm sound effects.  This occurred because MV_Tiny and MV_Small were added into indexes 200 and 201.

To restore the original behavior, the code now prevents sound effects added via TBM from being placed into reserved indexes.  The reserved indexes are instead assigned placeholders, which can subsequently be updated or left alone as the modder prefers.

This also makes the code a bit more robust including patching some sound validity checks in `gamesnd_game_sound_try_load` and `snd_load`.
2024-05-18 17:34:09 -04:00
Goober5000 c1af4317d4 Merge pull request #6156 from Baezon/rand-vec-adjustment
Better rand vec for createRandomorientation
2024-05-18 15:58:59 -04:00
Kestrellius 3f5a154e7a Updates beam-source particle velocity each frame. 2024-05-17 19:58:57 -07:00
Asteroth 8bd8e785b1 adjustments to rand vecs for random orientation 2024-05-17 21:09:36 -04:00
Goober5000 24e9a3a0c1 Merge pull request #6151 from Goober5000/cloaked_flag
add "cloaked" to list of flags
2024-05-17 12:34:53 -04:00
Goober5000 122e29fcaa Merge pull request #6152 from Goober5000/createRandomOrientation
add createRandomOrientation
2024-05-17 12:34:44 -04:00
BMagnu 03311c1527 Remove illegal assignment (#6153) 2024-05-17 10:11:16 -04:00
Goober5000 379077242a it's uniformly random, per Asteroth 2024-05-17 00:45:10 -04:00
Goober5000 cb4258e31f add createRandomOrientation
Considering that we have `ba.createRandomVector()`, we should have `ba.createRandomOrientation()` too.  This is based on an algorithm devised by @Baezon.
2024-05-17 00:16:54 -04:00
Goober5000 8ce463daf5 add "cloaked" to list of flags
This allows "cloaked" to be set and unset using `alter-ship-flag`.  Also clarify documentation on the primitive sensors flag.
2024-05-16 22:58:20 -04:00
Goober5000 fd32abad25 Merge pull request #6144 from Goober5000/emp_voice_fix
properly distinguish between adjusting voice and effects volume
2024-05-15 23:22:43 -04:00
Kestrellius f1c521413c Makes headon transition rate consistent. 2024-05-15 12:34:10 -07:00
Kestrellius 3b31034688 Removes const keyword from a couple things 2024-05-15 11:33:41 -07:00
Goober5000 30d1653cae Merge pull request #6148 from Goober5000/physics_whack_nocap
refine process for capping speed due to physics whack/shock/collide
2024-05-15 03:05:54 -04:00
Goober5000 724e2e7f68 properly distinguish between adjusting voice and effects volume
When messages are distorted due to EMP effects, the voice volume should be controlled by the voice setting, not the effects setting.  Fixes a bug noticed by @skdKitsune, a portion of which dates back to the original public source release.

Also, when volume is adjusted in `snd_set_volume`, make sure the correct voice volumes are used.  Fixes a copy-paste bug from #5694.
2024-05-14 16:42:23 -04:00
Goober5000 5ccc3d5a78 Merge pull request #6130 from Kestrellius/min-pixel-per-weapon
Created per-weapon field for laser min pixel size.
2024-05-14 16:30:25 -04:00
Goober5000 49777052ac Merge branch 'master' into min-pixel-per-weapon 2024-05-14 15:58:56 -04:00
Goober5000 b9466193f5 Merge pull request #6141 from Goober5000/emp_scramble_flag
add ship flag to disable message scrambling when EMP is active
2024-05-14 15:50:25 -04:00
Goober5000 6fdb9459b5 Merge pull request #6147 from Kestrellius/const-particle-functions
Changes particle effect functions to take consts.
2024-05-14 15:50:04 -04:00
Goober5000 0d1c86e0cd Merge pull request #6146 from Kestrellius/bolt-offset
Laser bolt offset
2024-05-14 15:49:52 -04:00
Kestrellius cb93748898 Removes const keyword from copied parameters. 2024-05-14 07:29:54 -07:00
Kestrellius 9192bb00b1 Alters other files to match previous changes. 2024-05-13 13:23:41 -07:00
Kestrellius ebd39bb5df Changes particle effect functions to take consts. 2024-05-13 13:03:42 -07:00
Goober5000 30b0026ca5 refine process for capping speed due to physics whack/shock/collide
The three functions `physics_apply_whack`, `physics_apply_shock`, and `physics_collide_whack` limited speed after the physics had been applied, but they limited absolute speed, not the speed due to the physics.  This modifies the process to limit the change in speed.  It also adds an AI profiles flag to disable the limit if desired.

This also tweaks the three functions (by editing comments and moving lines) to be more consistent, since all three are doing very similar calculations near the end.
2024-05-13 15:53:20 -04:00
Kestrellius c14a62e9d3 Adds comments clarifying positioning details. 2024-05-13 11:25:11 -07:00
Goober5000 046f302458 Merge pull request #6139 from Kestrellius/muzzle-effect
Adds muzzle effect functionality.
2024-05-13 14:02:56 -04:00
wookieejedi 4b6cbb9c01 Expose Collision Rotation Factor to Players (#6145)
* Expose Collision Rotation Factor to Players

Previously, there were hardcoded checks in place to make players have 0 rotational effects when colliding with another ship. This PR adds a new value, "+Player Multiplier for Rotation Factor:" that allows modders to have players experience rotational effects from collisions. Also performed some cleanup of the light and heavy collisional rotational calculations by removing older if-blocks following useful recommendation from Asteroth.

Tested and works as expected.

* make  rot_fac_multiplier_ply_collisions into global value

* update name to better match with ships table

* restore repeated comments to help with separation
2024-05-13 16:57:41 +00:00
Mike Nelson ed78fd84ea remove more ui stuff from API mode debrief (#6137) 2024-05-13 07:38:49 -04:00
Goober5000 393a9d4eba Merge pull request #6140 from Goober5000/small_fixes
several small fixes, mostly for FRED/qtFRED
2024-05-13 00:06:15 -04:00
Goober5000 9b94655250 Merge pull request #6125 from Goober5000/sync_initialization
make initialization consistent among FSO, FRED, and qtFRED
2024-05-13 00:06:08 -04:00
wookieejedi 5a501a8447 Update Align to target when guarding still (#6143)
Follow-up to #6047. This method better accounts for matching the guardee ship orientation when using the new AI flag.

Tested and works as expected. Thanks @BMagnu!
2024-05-12 23:09:58 -04:00
Kestrellius 3747a45dbe Adds three-dimensional bolt offset. 2024-05-12 16:07:24 -07:00
Kestrellius 5d30c07e31 Removes unnecessary commented-out code. 2024-05-12 11:06:21 -07:00
Kestrellius e2bf3bbd46 Adds one-dimensional bolt offset, with bugs. 2024-05-12 10:54:05 -07:00
Asteroth 5d6e68b8fd tweaks and fixes 2024-05-12 13:09:59 -04:00
Goober5000 d51f53fb30 add ship flag to disable message scrambling when EMP is active
What it says on the tin.  This supersedes PR #2917, as it puts the flag check in the proper function and uses a ship flag rather than a mission flag.
2024-05-11 23:38:18 -04:00
John Fernandez 23dda4ba43 Merge pull request #6135 from MjnMixael/fix_debrief_ui_murderer
Do not unload debrief bitmaps in API mode
2024-05-11 22:50:57 -04:00
Goober5000 499a5f4a02 several small fixes, mostly for FRED/qtFRED
1. Add the "Override #Command in event messages" checkbox to qtFRED
2. Add the "Preload Subspace Tunnel" checkbox to the proper button group in qtFRED
3. Reorder lines in fred.rc so the declarations match the order they appear in the dialog
4. Use the correct name when reporting fireball index errors for ship classes
2024-05-11 22:42:38 -04:00
Kestrellius 67e689106c Makes muzzle effects work properly on turrets. 2024-05-11 17:23:27 -07:00
Kestrellius 67999a3fe8 Clean version of shipfx move. 2024-05-11 15:29:24 -07:00
Asteroth 5cb0633314 fixes 2024-05-11 13:38:15 -04:00
Asteroth 2bbc052e7f Merge pull request #6128 from Goober5000/vanilla_time_compression
allow restriction to vanilla time compression range
2024-05-11 12:36:29 -04:00
mjn-mixael a222b29586 Do not unload debrief bitmaps in API mode 2024-05-11 11:32:50 -05:00
Asteroth 49a1e8458f add in game options and adjustments 2024-05-11 12:19:14 -04:00
Kestrellius b5efed380f Adds muzzle effect functionality. 2024-05-10 19:47:51 -07:00
Goober5000 9d9714f0bb Merge pull request #6126 from Goober5000/hud_support_find_closest_fix
patch hud_support_find_closest
2024-05-10 14:38:03 -04:00
Goober5000 edeabbbd58 Merge pull request #6129 from Goober5000/cmdbrief_modify_check
call set_modified() when cmd_brief data has changed
2024-05-10 14:37:48 -04:00
Kestrellius 62f25d7400 Changed variable names to specify laser. 2024-05-10 10:57:24 -07:00
Kestrellius d43818f7dc Merge branch 'min-pixel-per-weapon' 2024-05-10 10:41:25 -07:00
Kestrellius 6c9bf8def4 Implementation changes as requested by BMagnu. 2024-05-10 10:38:02 -07:00
Kestrellius c73c0ef889 Merge branch 'master' into min-pixel-per-weapon 2024-05-10 10:07:13 -07:00
Goober5000 a9141e9733 call set_modified() when cmd_brief data has changed
Fixes #6032.
2024-05-09 22:42:33 -04:00
Goober5000 fc4024ab66 allow restriction to vanilla time compression range
This provides a command-line argument to restrict the time compression range to the classic 1x - 4x.  Implements #6075.

I'm not entirely satisfied with `-orig_speedx_range` but it's the best I came up with that fit into the 19-character limit.  I'd be open to other suggestions.
2024-05-09 19:05:14 -04:00
Goober5000 c2335640ad Merge pull request #6113 from Goober5000/when-argument-fix
don't short-circuit eval_sexp on any nodes in a when-argument tree
2024-05-09 17:39:34 -04:00
Goober5000 8b984781fd Merge pull request #6121 from Goober5000/fix_dradis_blips
Fix DRADIS blips
2024-05-09 17:39:25 -04:00
Asteroth c3b01da2d1 reduce volume threshold (#6127) 2024-05-09 08:01:43 -04:00
Kestrellius 68a936504f Make laser glow scaling configurable. (#6123) 2024-05-08 17:41:50 +02:00
Goober5000 6edaea6056 Merge pull request #6122 from Dark-Visor/color_and_colour
Accept "color" and "colour" in game_settings.tbl
2024-05-07 01:12:43 -04:00
Goober5000 bf7c923020 patch hud_support_find_closest
Rework `hud_support_find_closest()` slightly to do a quick out if the player is no longer a valid object.  Fixes an assertion noticed by Darius that occurs if the player dies when a rearm is imminent.
2024-05-07 01:06:15 -04:00
Goober5000 bfe40e12c6 make initialization consistent among FSO, FRED, and qtFRED
Make the initialization sequence consistent so that FSO, FRED, and qtFRED call their initialization functions in the same order.  Most of the changes involve bringing FRED and qtFRED into sync with FSO.  This fixes fireball prerequisites for the ship types table, applies the script initialization fixes from #5946 to FRED, and generally removes the possibility of any surprises due to FRED differing from FSO.

Also remove the empty `brief_init_colors()` function.
2024-05-07 00:14:18 -04:00
Kestrellius 8d9736d3e3 Created per-weapon field for laser min pixel size. 2024-05-06 16:26:44 -07:00
Goober5000 322f807ac0 Merge pull request #6114 from Goober5000/dynamic_fireballs
make fireball types dynamic
2024-05-06 01:40:14 -04:00
Goober5000 209f5636b0 Merge pull request #6115 from Goober5000/setClip_enhancement
setClip enhancement
2024-05-06 01:39:59 -04:00
Asteroth dea9437c04 add waypoints no formation flag (#6119) 2024-05-05 22:10:19 -04:00
Goober5000 b624019f32 Merge pull request #6094 from Goober5000/hide_key_reset
hide key-reset
2024-05-03 11:02:22 -04:00
Goober5000 d1d173b99f Merge pull request #6116 from Dark-Visor/subtitles
Update Settings for movie subtitles #6064
2024-05-03 11:01:40 -04:00
Dark-Visor b7f4ad9780 Accept "color" and "colour" in game_settings.tbl
Allow optional strings in game_settings.tbl to recognise both
spellings - color/colour.
2024-05-02 13:57:16 +01:00
Goober5000 69c8957500 several improvements to DRADIS blips
1. fix a bug where blips expired immediately every frame; they now track their expiration by object
3. store object numbers rather than object pointers
3. clamp both the high bound and the low bound of alpha values
2024-05-02 01:33:31 -04:00
Goober5000 76359c649f remove some obsolete commented code 2024-05-02 01:32:17 -04:00
Goober5000 855331bcd6 change sweep_percent field to sweep_angle to be more accurate 2024-05-02 01:31:27 -04:00
Goober5000 fa6d64ae7e fix sweep_duration and disambiguate overall frametime
Convert `sweep_duration` from seconds to milliseconds to work correctly with the timestamp system.  Also clarify use of `game_get_overall_frametime()`, especially with `ba.getFrametimeOverall()`; and add `ba.getSecondsOverall()` to do what `ba.getFrametimeOverall()` allegedly did.
2024-05-02 00:01:47 -04:00
Goober5000 bc4cc598c9 qtfred too 2024-05-01 22:42:06 -04:00
Goober5000 3d92d469ac move backup info and make them consistent 2024-05-01 22:22:24 -04:00
Goober5000 9edcf5f450 add routine to recover autosaved mission 2024-05-01 21:42:39 -04:00
Goober5000 2f5e7a4de2 tweak MessageBox call 2024-05-01 21:42:39 -04:00
Goober5000 8d6a8721f9 taylor's patch for file modification time 2024-05-01 21:42:39 -04:00
Goober5000 7ebfa52bf5 standardize file modification time formatting between FRED and qtFRED 2024-05-01 21:42:32 -04:00
Dark-Visor 89e8961984 Add allowances for no alpha and spelling colour
User should be able to input 3 values (r,g,b) and let alpha default to
opaque. Also add "$Movie subtitle colour:" for English spelling of
color.
2024-05-01 15:23:06 +01:00
Dark-Visor 0f4dc47db9 Correction to subtitle_color check
Update check from checking the validity of state color to
Movie_Subtitle_rgba color values.
2024-04-29 18:10:04 +01:00
Dark-Visor eacba95b7b Update to #6064 fix to correct code
Update movie.cpp to correct subtitle declaration and checks.
2024-04-29 17:30:29 +01:00
Asteroth f40941304c Account for scripting when dealing with velocity (#6110)
* add scripted velocity

* fix

* rejigger to handle displacement as well, and add flag

* review tweaks

* one more fix
2024-04-29 01:40:26 -04:00
Dark-Visor eb9c58dc2d Update Settings for movie subtitles #6064
Update mod_table and movie files to include settings for the color and
transparency of the subtitles.
2024-04-28 22:36:07 +01:00
Goober5000 742fd321d5 setClip enhancement
Allow the resize mode to be specified to `gr_set_clip()` without changing the active graphics-wide resize mode.  Along with `drawStringResized`, this provides a shorthand to allow text to be drawn at different sizes, with the appropriate clipping regions, without requiring access to the `CurrentResizeMode` virtvar.
2024-04-27 02:48:08 -04:00
Goober5000 3851832db5 make fireball types dynamic
As requested by Event Horizon, this removes the limit on fireball types.  The fixed array has been replaced with a vector and the relevant code updated accordingly.  There is also a new version of `stuff_int_list()` to parse ints into a vector.

This also adds bounds checking for explosion animations that are parsed for ship classes, ship types, and asteroids, since previously there was no guarantee that the indexes would be in range.
2024-04-25 21:26:35 -04:00
Goober5000 539d89ca8c don't short-circuit eval_sexp on any nodes in a when-argument tree
This is a follow-up to #2942.  That PR solved most of the short-circuiting issues with nested conditionals under when-argument, but it was still possible for the code to incorrectly short-circuit on a nested conditional that had `<argument>` in an action operator but not a condition operator.  The cleanest way to fix this is to not short-circuit on *any* nodes that are part of a when-argument tree.
2024-04-25 00:10:27 -04:00
Goober5000 289d0b66d1 Merge pull request #6093 from Goober5000/sexp_error_check_fix
fix bad node identification for certain SEXP errors
2024-04-23 16:52:39 -04:00
Goober5000 f3c6b0f8f3 Merge pull request #6108 from Goober5000/no_escort_callsigns
add flag to not show callsigns in escort list
2024-04-21 23:29:35 -04:00
Asteroth 1bd65192ba Allow for more field of fire cooldown shenanigans (#6086)
* allow for more fof cd shenanigans

* review fix

* switch to per frame management

* unused variable

* review tweaks
2024-04-20 23:33:24 -04:00
Taylor Richards 2642fa22de add preliminary support for Windows ARM64 (#6079)
First step in the process of working Windows ARM64 support. This adds the most
basic support needed, but by itself will not succesfully build. However these
changes should not interfere with builds for other architectures or platforms,
and should still allow for x86/x64 builds on ARM64 Windows.
2024-04-19 04:30:20 -04:00
Goober5000 ac8d774bc7 Merge pull request #6095 from Baezon/debris-big-damage
Add flag for debris respecting big damage
2024-04-18 15:58:54 -04:00
Goober5000 a57ae15c72 Merge pull request #6109 from Goober5000/fighter_beam_fov_fix
fix fighter beam FOV calculation
2024-04-18 15:58:45 -04:00
Goober5000 26c4ea1057 fix fighter beam FOV calculation
Remarkable that we're still finding bugs in fighter beams after 20 years...

Since field-of-fire angles are specified in degrees, and `cosf` accepts radians, the angle needs to be converted (and then halved, per usage elsewhere).  Although this is a bugfix, this should technically not affect fighter beam behavior because fighter beams always fire down their normals.
2024-04-18 14:39:37 -04:00
Goober5000 148efb4713 add flag to not show callsigns in escort list
As a follow-up to #5523, some mods use callsigns for their ships but prefer not to display the callsigns in the escort list.  In lieu of a more flexible way to configure escort lists, a simple flag is sufficient to implement the desired behavior.
2024-04-18 13:46:58 -04:00
Goober5000 88bf67a64f Merge pull request #6104 from Goober5000/locations_to_enums
convert arrival/departure locations to enum classes
2024-04-18 03:53:30 -04:00
Goober5000 a18b122b19 Merge pull request #6106 from Goober5000/checkVisibility_fix
fix checkVisibility
2024-04-17 23:18:55 -04:00
Goober5000 0a59c533c2 fix checkVisibility
The checkVisibility function did not check its arguments' validity, leaving open the possibility of a null pointer access.
2024-04-17 22:32:54 -04:00
Goober5000 3ad0d3713d convert arrival/departure locations to enum classes
To enforce type safety for arrival and departure locations, this converts them to enum classes.  Various casts are added when appropriate to convert between the indexed and enum values.
2024-04-17 15:05:48 -04:00
Goober5000 7acf56f4f5 Merge pull request #6103 from Goober5000/in_back_of_ship
add 'In back of ship' arrival location
2024-04-17 15:05:24 -04:00
Goober5000 55c41c96a7 add above/below and left/right 2024-04-17 14:37:47 -04:00
Mike Nelson e63383d324 Ingame prejoin API (#6099)
* ingame prejoin api

* fix type mismatch

* return boolean here

* address feedback
2024-04-17 17:48:57 +00:00
Mike Nelson 7ae8c79dea Team Loadout API for SCPUI (#6096)
* team loadout methods

* documentation

* address feedback

* better assertions
2024-04-17 13:24:27 -04:00
Mike Nelson 002783ce7c miscellaneous methods needed (#6090) 2024-04-17 12:48:27 -04:00
Asteroth 72b6ded0ac fix circ default curves (#6102) 2024-04-17 12:48:02 -04:00
Goober5000 4c7f16fb1b add 'In back of ship' arrival location
Allows ships and wings to arrive behind a ship, to complement 'In front of ship'.  In fact, the arrival code is nearly identical, with just a small tweak to distinguish ahead from behind.

Since the new arrival location represents a change in mission format, this also adds code to detect for its usage and set the mission format to 24.1.  Most missions can continue to be saved as version 23.1.
2024-04-16 19:27:47 -04:00
Mike Nelson ecb9fae3c4 check if inputbox is valid (#6092) 2024-04-11 17:49:25 -04:00
wookieejedi 55c20636d9 Improve Mainhall Button Responsiveness (#6098)
* Improve Mainhall Button Responsiveness

Previously, there was a 175 millisecond delay when hovering over a mainhall animation before it triggered. This PR makes that value settable via the mainhall table.

Tested and works as expected. Now custom mainhalls have much more of a spring int their step.

* cleanup num res location
2024-04-11 17:48:28 -04:00
Goober5000 e8d164c926 Merge pull request #6097 from Goober5000/model_range_fix
model range fix
2024-04-11 17:01:43 -04:00
Goober5000 89f4fe54c3 convert model_h and submodel_h to use indexes
Indexes are a more robust way than pointers to manage model and submodel handles, and in the event that models are made dynamic in the future, indexes will be necessary anyway.
2024-04-11 15:15:44 -04:00
Goober5000 7fba753f9d model range fix
Use the correct upper bounds check for `model_get()`.
2024-04-11 14:53:24 -04:00
Asteroth bd05f13f07 add flag for debris respecting big damage 2024-04-11 14:21:44 -04:00
Goober5000 d5a3813e8b hide key-reset
Hides the `key-reset` operator in FRED and elaborates on the help descriptions for both it and `key-reset-multiple`.  Implements #6076.
2024-04-10 21:14:59 -04:00
Goober5000 735d4ab678 fix bad node identification for certain SEXP errors
Set the bad node to the ship node, so that the FREDder can see which ship is receiving the invalid order.  Without this change, the bad node would point to the last value parsed, which is typically the goal priority.

Fixes a misleading error dialog reported in Discord.
2024-04-10 17:54:57 -04:00
Goober5000 71543c9c10 Merge pull request #6058 from Goober5000/skybox_orientation_and_alpha
add skybox alpha, and add scripted functions for alpha and orientation
2024-04-10 17:06:24 -04:00
Goober5000 b2e1ae43a9 Merge pull request #6039 from Goober5000/percent_ships_scanned
add percent-ships-scanned
2024-04-10 17:04:46 -04:00
Goober5000 c7cffcb311 Merge pull request #6091 from notimaginative/fix_chatbox_crash
fix crash when chatbox message is all whitespace
2024-04-10 17:04:37 -04:00
Goober5000 c96f1af375 Merge pull request #1 from BMagnu/skybox_alpha
Fix Skybox Alpha Setting
2024-04-10 12:53:41 -04:00
BMagnu c2d1b69ea2 Set alpha as alpha mult and only if actually required 2024-04-10 12:49:58 +02:00
Taylor Richards 861e5f9813 fix crash when chatbox message is all whitespace
When attempting to add a chat message which is all whitespace the split_str()
function will produce no lines. The strcpy() that follows will then crash
due to an attempt to copy a nullptr.
2024-04-10 05:03:16 -04:00
Taylor Richards f288ef7101 fix issues with get_text() and set_text() for INPUTBOX (#6089) 2024-04-08 19:19:03 -04:00
Taylor Richards 067f862c4d add support for decompression of DDS textures (#6025)
Adds bcdec lib to convert compressed DDS textures to RGBA based on what the
system supports. BC7 if BPTC extension not supported, DXT? if S3TC extension
not supported.

Should support cubemaps and volume textures but those were not tested.

Addtional changes:
 - remove indexed DDS support since it had bugs but didn't work anyway
   (R8 should be used instead)
 - fix issues with volume textures (nothing to test with)
 - remove old compression support flags as they are now obsolete

Fixes #4920
2024-04-08 16:56:33 -04:00
Taylor Richards 3478640b4d fix deprecated/removed code in cutscene ffmpeg (#6088) 2024-04-07 18:43:15 -04:00
Mike Nelson 66204287e6 properly validate mission custom data keys (#6082) 2024-04-07 16:46:05 -04:00
Mike Nelson 6b1d9304ed Multi general api (#6078) 2024-04-07 16:45:51 -04:00
Mike Nelson 66ec2c8154 multi dogfight debrief api (#6084) 2024-04-07 16:48:23 +00:00
Mike Nelson e3918a14f2 API for the Multi Pause UI (#6083) 2024-04-07 12:28:24 -04:00
Mike Nelson 4b1476c101 on loading complete hook (#6085) 2024-04-07 08:09:51 -04:00
Goober5000 86db536bf5 Merge pull request #6071 from Goober5000/support_ship_specific_checks
adjust ship registry checks to accommodate support ships
2024-04-06 20:51:58 -04:00
Goober5000 b3b811841b Merge pull request #6080 from Goober5000/electrical_arc_stuff
more electrical arc API features
2024-04-06 20:51:50 -04:00
Goober5000 cc62643001 Merge pull request #6081 from Goober5000/goal_cheat_fix
mission goal cheat fix
2024-04-06 20:51:41 -04:00
Goober5000 3b7157e2de mission goal cheat fix
If the goals are marked complete, a mission log entry should be added as well.  Fixes some goal weirdness first noticed by DAK on Discord.
2024-04-03 20:32:12 -04:00
Goober5000 a5630d63a5 more electrical arc API features
Follow-up to #6034.  This slightly changes the function signature of `AddElectricArc` but it should be fine since it hasn't appeared in a stable release yet.
2024-04-03 20:27:14 -04:00
Mike Nelson 052b4b29e9 Multi sync API (#6077)
* multi host settings ui initial setup

(cherry picked from commit bcb31c327653329e62e4430815fe1e981751f9dc)

* Finish the rest of the API

* include enums

* set these

* Close game needed

* Handle accepting the host setup

* Don't need to be master to set these and add ways to check master and self

* add client ui to this PR because

* Allow getting the player state string

* Multi sync api methods

* unused variables

* Fix state checking

(cherry picked from commit fcde973cdf)

* typo

* address feedback

(cherry picked from commit ecb33e7cc6)
2024-04-02 17:34:06 +00:00
Mike Nelson ea8e356b63 Multi Start Game UI API (#6068)
* methods for the Multi Start Game UI API

* missed a comma

* properly close the session

* name instead of password
2024-04-02 16:56:56 +00:00
Mike Nelson 9bba53c3e8 Multi Join API (#6059)
* methods required for the multi join ui api

* Move color setting because the API doesn't need it either
2024-04-02 12:19:20 -04:00
Asteroth 3df616e69d Merge remote-tracking branch 'upstream/master' into aim-cursor 2024-04-01 23:09:31 -04:00
Goober5000 0fb18a15c4 Merge pull request #6069 from Baezon/bad-rearm-time
Add bad-rearm-time sexp
2024-03-31 15:01:50 -04:00
Goober5000 e1503a8ac8 Merge pull request #6002 from Goober5000/game_settings_order
allow game_settings options to be read in any order
2024-03-31 15:01:41 -04:00
Goober5000 b11cf2c2db Merge pull request #5887 from Goober5000/wing_destruction_sanity_check
check for potential issues in FRED missions
2024-03-31 15:01:32 -04:00
Asteroth 9c8d02b69b Add 'alignment' for poofs (#6072)
* add poof alignment

* put this back

* review fixes
2024-03-31 10:49:34 -04:00
John Fernandez 055cc6e4c8 Merge pull request #4210 from JohnAFernandez/Team-Loadout-Editor-Possible-Rebase
QTFred Loadout Editor
2024-03-31 00:25:16 -04:00
Goober5000 e3447223eb allow game_settings options to be read in any order
The ai_profiles.tbl options can already be read in any order, so it is modder-friendly to extend this capability to game_settings.tbl as well.  This also updates the "unrecognized parameter" log statement to indicate the filename.

Note that this commit should be viewed while ignoring whitespace changes.
2024-03-30 19:37:29 -04:00
Goober5000 8b575e7a72 add checkbox to control behavior 2024-03-30 19:27:10 -04:00
Goober5000 30547ff026 check for potential issues in FRED missions
Add a routine to the sexp syntax checker that also checks for potential issues.  These are not definitive errors, but situations that might trip up mission designers.  Currently there is one issue checked: the destruction of a wing that has multiple waves and arrives from a docking bay.
2024-03-30 19:27:05 -04:00
JohnAFernandez d564329ffb Remove old TODOs and add confirmation
Copying to other team can erase a lot of progress, therefore make sure we ask for confirmation.
2024-03-30 18:16:42 -04:00
Goober5000 18c5662584 adjust ship registry checks to accommodate support ships
This does two things:

1. Fix a bug in `mission_bring_in_support_ship` that assigns an incorrect parse object index to the support ship's ship registry entry.  Since `Arriving_support_ship` is not an item of `Parse_objects`, it should not have an index.
2. Adjust the in-game join checks at the bottom of `parse_create_object_sub` to more scrupulously account for index mismatches and bounds errors, with a specific exception for the arriving support ship.
2024-03-30 16:00:04 -04:00
JohnAFernandez 534c69ee60 More dialog adjustments 2024-03-30 15:56:48 -04:00
JohnAFernandez b3bafb83b4 Remove Unused Code and Add Skip Validation 2024-03-30 14:23:52 -04:00
JohnAFernandez 9783e96207 No Shadowing and more Column Adjustments 2024-03-30 13:13:34 -04:00
JohnAFernandez 103275e488 Don't for get to save required status 2024-03-30 13:07:53 -04:00
JohnAFernandez 16ff22cce1 Add Functionality for Required Weapons 2024-03-30 12:49:48 -04:00
JohnAFernandez ef31905f3e Appease Clang by not having prefix by accident 2024-03-30 00:41:26 -04:00
JohnAFernandez 18f76652cf It's no longer crashing
And it is now updating correctly.

I don't like it but I don't want to touch it.
2024-03-30 00:38:56 -04:00
Goober5000 d3c43732fa Merge pull request #6074 from Goober5000/fast_fred_reload
speed up FRED reloading with this one weird trick
2024-03-30 00:03:41 -04:00
Goober5000 e6b2cbf900 Merge pull request #5870 from Goober5000/any_wingman_check
add a new check to the Voice Acting Manager
2024-03-30 00:03:35 -04:00
Goober5000 0267fb539c speed up FRED reloading with this one weird trick
Thanks to @notimaginative's detective work, nearly all of the FRED stalling when saving a mission can be avoided by simply not calling `model_free_all()`.  By checking a flag in `clear_mission()`, multiple situations can avoid this slowdown, including reload-after-save and import-FSM.
2024-03-29 23:34:54 -04:00
wookieejedi 218a98dde3 Merge pull request #5978 from BMagnu/shader_backwards_compat
Add runtime flag to split up the main render shader
2024-03-29 23:14:36 -04:00
JohnAFernandez f52ebc8ccb Save my progress ....
Even though it crashes and I have no idea why.
2024-03-29 20:25:59 -04:00
JohnAFernandez 88897b907c Fix Setting 2024-03-29 20:25:59 -04:00
JohnAFernandez 9ab82ae607 Adding Functionality to CombobBox 2024-03-29 20:25:59 -04:00
JohnAFernandez c01c7da121 Version 2, Adding Buttons
And fixing existing issues
2024-03-29 20:25:59 -04:00
JohnAFernandez 817fa2cd98 Save progress because this is a huge headache 2024-03-29 20:25:59 -04:00
JohnAFernandez 41be934485 Finish Polishing Regular List behavior
Also start adding many variable enabler functions
2024-03-29 20:25:59 -04:00
JohnAFernandez b870675cc9 Properly Clear list when switching modes 2024-03-29 20:25:59 -04:00
JohnAFernandez 5b3dddff4a New way of "Clearing" rows
Empty and move text instead of deleting items to avoid apparently inevitable memory bugs.
2024-03-29 20:25:59 -04:00
JohnAFernandez 8c904c36f9 Add extra allocated to newly enabled
So that items do not keep switching places.
2024-03-29 20:25:59 -04:00
JohnAFernandez c7f80725fe Fix copy paste mistake 2024-03-29 20:25:59 -04:00
JohnAFernandez 5af559d1cf Update Window size and Label names 2024-03-29 20:25:59 -04:00
JohnAFernandez d4246432d7 Make List selection update on multiselect 2024-03-29 20:25:59 -04:00
JohnAFernandez 95bc875ac2 Fix Updating the UI
The model was not updating its sending to front end list when getting new info from user input.  It would save it in the model, but not where it was sending information back to the dialog (UI).
2024-03-29 20:25:59 -04:00
JohnAFernandez 6b72772ac9 More Polishing 2024-03-29 20:25:59 -04:00
JohnAFernandez 6de2897347 Ok, making progress on fixing spinbox 2024-03-29 20:25:59 -04:00
JohnAFernandez 7a83c71b87 Starting to fix Functionality
And polish things that already work
2024-03-29 20:25:59 -04:00
JohnAFernandez 74805c83ba Make sure Usable ships make more sense 2024-03-29 20:25:59 -04:00
JohnAFernandez c9f3244268 Ok, prevent some crashes due to missing items 2024-03-29 20:25:59 -04:00
JohnAFernandez 308e2edb3e Ok, it is at least updating correctly. 2024-03-29 20:25:59 -04:00
JohnAFernandez 2baec05a55 More Linter fixes 2024-03-29 20:25:59 -04:00
JohnAFernandez bf2dbb4a02 Trying hard to fix things 2024-03-29 20:25:59 -04:00
JohnAFernandez 228a8994ee Appease linters
Remove unused variables
2024-03-29 20:25:58 -04:00
JohnAFernandez fe2561c893 Fixn 2024-03-29 20:25:58 -04:00
JohnAFernandez ee73fadad1 Get the code to compile at least 2024-03-29 20:25:58 -04:00
JohnAFernandez d75e4e46ab A good chunk of further fixes 2024-03-29 20:25:58 -04:00
JohnAFernandez 2d90756fed Gotta keep chipping away at the boulder 2024-03-29 20:25:58 -04:00
JohnAFernandez 807e416ebb Why yes, there's tons more errors 2024-03-29 20:25:58 -04:00
JohnAFernandez b8bb4d445b Fix some compilation errors 2024-03-29 20:25:58 -04:00
JohnAFernandez f0f57bf576 Remove duplicate function definitions 2024-03-29 20:25:58 -04:00
JohnAFernandez 8b081bf2ed Fix no class declaration 2024-03-29 20:25:58 -04:00
JohnAFernandez 1f034209d0 Fix incomplete line 2024-03-29 20:25:58 -04:00
JohnAFernandez cef7abb1db Disable Reset Lists 2024-03-29 20:25:58 -04:00
JohnAFernandez d9909e2a21 Cleaning out further functions to fit new paradigm. 2024-03-29 20:25:58 -04:00
JohnAFernandez 90097293cb Refactor UpdateUI() to reflect new UI structure 2024-03-29 20:25:58 -04:00
JohnAFernandez c2aa94bdde Properly update list widgets 2024-03-29 20:25:58 -04:00
JohnAFernandez 404a8c9bb7 Cleaning things up a little 2024-03-29 20:25:58 -04:00
JohnAFernandez 209583b449 Save changes.
Still plenty to do to finish converting.
2024-03-29 20:25:58 -04:00
JohnAFernandez 5c746f13a6 Pretty Much Completely Redone 2024-03-29 20:25:58 -04:00
JohnAFernandez dae99e5b80 Also, add add/remove to ui file 2024-03-29 20:25:58 -04:00
JohnAFernandez e5f0b674b5 Rearrange Editor to use add/remove
More edits to follow ...
2024-03-29 20:25:58 -04:00
JohnAFernandez eebc2bfd59 Fix 2024-03-29 20:25:58 -04:00
JohnAFernandez 7eb64e59bb Fixes 2024-03-29 20:25:58 -04:00
JohnAFernandez 7db278410c A little more cleanup 2024-03-29 20:25:58 -04:00
JohnAFernandez ed4d187365 Getting Close hopefully to properly functioning 2024-03-29 20:25:58 -04:00
JohnAFernandez 1bbcdc3dc5 Finish the Loadout Dialog
Finished the Model And Dialog files for the Loadout Editor
2024-03-29 20:25:57 -04:00
JohnAFernandez c36551fbd6 Edits to the Dialog for Clarity. Conciseness
In preparation for writing the model and dialog cpp and h files

And a quick rename

Don't need these

done
2024-03-29 20:25:57 -04:00
Goober5000 6f94d67cfa Merge pull request #6063 from Goober5000/sexp_boolean
allow boolean and numeric scripted SEXPs to return special values
2024-03-26 15:18:07 -04:00
Goober5000 0ffd9bc421 Merge pull request #6067 from Goober5000/fix_fix_missile_detonation
fix fixed-missile-detonation
2024-03-26 15:15:11 -04:00
Goober5000 4899e6454e Merge pull request #6066 from Goober5000/override_submodel_impact
add "override submodel impact" subsystem flag
2024-03-26 15:15:03 -04:00
John Fernandez 8f6f6ab970 Merge pull request #6070 from Baezon/fix-anim-directions
Fix an issue with animation directions
2024-03-25 22:48:58 -04:00
Asteroth 3388341343 fix an issue with animation directions 2024-03-25 20:58:22 -04:00
Asteroth e65803b747 add bad-rearm-time sexp 2024-03-25 20:13:16 -04:00
Goober5000 197356077d fix fixed-missile-detonation
The logic to handle the `$Fixed Missile Detonation:` flag missed an important case: subsystems with concave hull geometry but without destroyable submodels.  The original flag was tested on a bowl-shaped turret, which could be destroyed.  However the bowl-shaped engine on the SSG Rahu was susceptible to the same detonation problem.  By changing the check to always use the radius, whether obtained from a submodel or from the subsystem, the flag fixes the detonation in both cases.
2024-03-25 16:02:30 -04:00
Goober5000 168d3c9ddf add "override submodel impact" subsystem flag
With the `$Damage Impacted Subsystem First:` game_settings flag, weapons will damage submodels over subsystems, even if the subsystem is closer.  Yet occasionally this is not the correct behavior (e.g. for the Rahu's engines).  The new subsystem flag allows this behavior to be selectively overridden.
2024-03-25 15:49:52 -04:00
Goober5000 55ead5c2c6 Merge pull request #6065 from Goober5000/6014_followup
additional lighting fixes
2024-03-25 14:05:09 -04:00
Goober5000 db8a3651cd additional lighting fixes
Fix a minor oversight from #6014; in the ship lab, there are sometimes no suns at all, so remove the assertion.  The lighting check is only needed for supernovas anyway, so make that clear.

Additionally, add further clarification for the distinction between suns, lights, and variables used only for the supernova.  Finally fix one more sun/light discrepancy that escaped notice from #6014.

Fixes an assertion in the ship lab.  Follow-up to #6014.
2024-03-25 13:33:21 -04:00
Mike Nelson 620afa0c1e Cockpit fov option (#5924)
* add cockpit fov to in-game options and use a define for the default fov value for both fov options

* Add a controlling toggle option

* constexpr

* localization
2024-03-25 07:28:24 -04:00
Mike Nelson 7fdcd4abc7 Basic implementation of some audio options in-game (#5927)
* Basic implementation of some audio options in-game

* Unused param

* do localization
2024-03-24 21:46:02 -04:00
John Fernandez 18394f7074 Merge pull request #6061 from MjnMixael/fix_api_debrief
Don't init the debrief ui in API mode
2024-03-24 14:55:14 -04:00
Goober5000 897e388d1c allow boolean and numeric scripted SEXPs to return special values
This adds the special SEXP return values (SEXP_KNOWN_TRUE, SEXP_NAN, and so forth) as enums, and adds code to intercept these enums if they are returned where the code would normally expect a boolean or number.  If an enum is found, it is converted to its special return value equivalent.

With this change, a script can end a function with `return SEXP_KNOWN_TRUE` or similar.  No other API changes are needed; in particular, no special `$Return Type:`s are needed.

Implements #5959.
2024-03-23 23:35:36 -04:00
mjn-mixael 8bde63a9ae Don't init the debrief ui in API mode 2024-03-23 14:42:22 -05:00
Goober5000 f021e9df8a Merge pull request #6060 from Goober5000/fix_std_move_crash
fix crash caused by using a moved variable
2024-03-23 13:09:14 -04:00
Goober5000 4a1d794a64 fix crash caused by using a moved variable
In #5894, in the `add_dynamic_sexp` function in sexp_lookup.cpp, a call to `sexp->getHelpText()` was moved to the bottom of the function.  Normally this would be fine, except that this occasion caused the `sexp` variable to be accessed after a `std::move`.  The crash can be avoided by moving the last access of the `sexp` variable just a little bit earlier.
2024-03-23 02:04:48 -04:00
Goober5000 fecb9b16af Merge pull request #6014 from Goober5000/sun_light_index_fixes
fix a few lighting bugs
2024-03-22 15:58:42 -04:00
Goober5000 aa12ec7790 add skybox alpha, and add scripted functions for alpha and orientation
This allows the skybox orientation and alpha to be accessed and changed through Lua virtvars, and also adds a sexp to change the alpha.

Unfortunately, changing the alpha has no perceptible effect on the skybox.  This will need the attention of a graphics coder to figure out what might need updating.
2024-03-22 13:23:05 -04:00
John Fernandez 7e637d5d5a Merge pull request #5893 from JohnAFernandez/Fix-Coverity-Time-T-issues
Fix coverity time t issues
2024-03-22 12:16:29 -04:00
John Fernandez ff5bc2f6a0 Merge pull request #5894 from JohnAFernandez/Coverity-Reference-Issues
Coverity: Change many auto calls to const auto& to avoid unnecessary copies.
2024-03-22 12:09:34 -04:00
John Fernandez c08a669c2e Merge branch 'scp-fs2open:master' into Fix-Coverity-Time-T-issues 2024-03-22 11:51:27 -04:00
John Fernandez 03f6f09c93 Merge branch 'scp-fs2open:master' into Coverity-Reference-Issues 2024-03-22 11:50:46 -04:00
Mike Nelson 74c2a204c7 API to get the PXO urls (#6054)
* API to get the PXO urls

* whitespace
2024-03-22 08:30:33 -04:00
Goober5000 a9ad87ea08 Merge pull request #6023 from Goober5000/preload_weapon_create
add weapon preloader
2024-03-21 14:25:48 -04:00
Goober5000 0a86623e9e Merge pull request #6056 from Goober5000/fix_ai_path_update
update Fix_ai_path_order_bug for new waypoint options
2024-03-21 13:24:41 -04:00
Goober5000 2f957668e3 update Fix_ai_path_order_bug for new waypoint options
When waypoint start index and direction were added in #5698 / 42fc989 et seq., the `Fix_ai_path_order_bug` flag needed to be updated to account for those new options.  This fixes that.

Fixes #6052.
2024-03-21 00:13:05 -04:00
Goober5000 38d9a975ce Merge pull request #6055 from Goober5000/shipB_submodel
add ShipBSubmodel to ship collisions
2024-03-20 22:52:01 -04:00
Goober5000 f26643c43d add ShipBSubmodel to ship collisions
Since the On Ship Collision hook can potentially be called twice, with the ships reversed, it is necessary for both parameters to have submodels specified.  Otherwise +Override would not be able to handle both cases.

Followup to #6035.
2024-03-20 21:15:33 -04:00
Mike Nelson c2cb07ded3 Allow skipping using retail mainhall defaults (#6042) 2024-03-18 07:40:49 -04:00
Goober5000 7a04f76a46 Merge pull request #6049 from Goober5000/gr_string_size
add getStringHeight and getStringSize
2024-03-17 19:55:31 -04:00
Goober5000 006d2a49b1 Merge pull request #6050 from Goober5000/hud_high_contrast
add a HUD virtvar for contrast
2024-03-17 19:55:20 -04:00
Goober5000 a281f35f1a add a HUD virtvar for contrast
Adds a hu.HUDHighContrast virtvar.  Also renames `HUD_contrast` to `HUD_high_contrast` for clarity and makes it a boolean.
2024-03-17 16:18:02 -04:00
wookieejedi 88f7e41d8c Add AI Flag to align to target when guarding stationary ship (#6047)
* Add AI Flag to `align to target when guarding stationary ship`

When a ship is ordered to guard another ship that is stationary and not incredibly large, the AI will fly to a position then turn and face away from the targeted ship. This behavior is not ideal in various scenarios, including both blockade style formations and overall visuals.

The PR adds a flag that tells the AI to align to the target ship it is guarding once the AI has reached it's guarding position in this situation, which allows all the guarding ships to have the same orientation and look much better and work better for directional defenses.

Tested and works as expected. Also changed some `NULL` to `nullptr` in this function for cleanup.

* remove duplicate brackets
2024-03-17 08:16:55 -04:00
Goober5000 f2998a2c69 add getStringHeight and getStringSize
We already have `gr.getStringWidth()`, but these functions are useful too.
2024-03-16 21:15:40 -04:00
Mike Nelson 1b0a3ea6f9 Default framebuffer effects to off (#6046) 2024-03-16 21:14:22 -04:00
Mike Nelson 5e274a008c Add lua function to validate a string as a valid IP (#6043) 2024-03-16 21:14:00 -04:00
Mike Nelson 38be5c248c Convert multi team chat to use a struct/list setup (#5850)
* convert multi team chat to use a struct/list setup

* use the correct array size define

* cleanup local vars & Asserts

* address feedback

* remove uncessary if
2024-03-16 11:10:09 -04:00
Mike Nelson 0450ef0d1a Fix multi option virtvars so they can be read without being set (#6044) 2024-03-16 08:14:19 -04:00
Mike Nelson e6a2a2a7f9 Fix retail options not saving (#6020)
* Make sure retail options are saved properly when Using_in_game_options is true

* don't need this
2024-03-15 15:43:45 -04:00
Goober5000 bbb6a6f199 Merge pull request #6016 from Goober5000/sexp_help_tweak
fix help descriptions for string-greater-than and string-less-than
2024-03-15 13:22:21 -04:00
Goober5000 1c0b58e11b Merge pull request #6041 from Goober5000/support_ship_sexp_update
improve set-support-ship description
2024-03-15 13:19:40 -04:00
Goober5000 0bf0735cd9 Merge pull request #6034 from Baezon/scripted-model-arcs
Add scripted model 'lightning' arcs
2024-03-15 13:03:34 -04:00
Goober5000 cc3791b594 improve set-support-ship description
Per Durandal, a few attributes of this SEXP can be documented a little better.
2024-03-15 13:00:25 -04:00
John Fernandez 799906a921 Merge pull request #6040 from MjnMixael/default_postproc_on
Default post processing to on because so many things require it
2024-03-14 19:45:54 -04:00
mjn-mixael 043e3fab79 Default post processing to on because so many things require it 2024-03-14 17:23:58 -05:00
Mike Nelson 2e34c29215 Scpui multi pxo api (#5845)
* multi pxo api

(cherry picked from commit 9af26da728a19b9d6c890968a314e8e56ecc1ddf)

* multi pxo help api

(cherry picked from commit f4df704576ddb648e9c486907b07ae172c859feb)

* minor fixes

* not extern

* break out chat message data into a table

* address some feedback

* return empty strings if not in multi

* use GetChannelByUser() instead

* once more with feeling

* correct documentation
2024-03-13 15:23:44 -04:00
Goober5000 8ac68c5b8b make the percent operators correctly return KNOWN_FALSE when they are known false 2024-03-13 14:03:32 -04:00
Goober5000 b92f50e94f add percent-ships-scanned
Kind of surprised this SEXP operator hasn't been added before now.  It complements the existing percent-X operators in the Objectives category.

Also, this fixes and clarifies the help documentation for the various percent-X operators.
2024-03-13 12:05:35 -04:00
Goober5000 96228d6e98 Merge pull request #5937 from Goober5000/some_parse_upgrades
some parse upgrades
2024-03-13 12:04:56 -04:00
Asteroth dc4daafd61 fix for a merge mistake 2024-03-12 15:39:00 -04:00
Asteroth 4b37796628 Merge remote-tracking branch 'upstream/master' into scripted-model-arcs 2024-03-12 15:38:13 -04:00
Goober5000 45a434a60a some parse upgrades
Turn `Parse_names` into a vector and add SCP_string overloads of ship registry functions.  Refactor calling code to use registry as appropriate.  Remove an unused overload of `mission_parse_get_parse_object`.
2024-03-12 14:30:07 -04:00
Asteroth 488ec8d5a8 review tweaks 2024-03-12 13:50:38 -04:00
Goober5000 b1460eb3fa Merge pull request #6035 from Goober5000/submodel_collision
enhancements for submodel collisions
2024-03-12 13:42:41 -04:00
Goober5000 671fe21a75 additional collision info
* Add the submodel that was hit to the On Ship Collision scripting hook.  (This will only be non-nil if the ship was the "heavy object".)
* Add a `getModel()` function to the scripted submodel object.
* Fix some incorrect documentation in `OnShipCollision`.
2024-03-12 13:02:58 -04:00
Goober5000 d6606ad642 enhancements for submodel collisions
* Expose NoCollide and NoCollideThisOnly as virtual variables for submodels
* Allow submodels to be optionally specified in object:checkRayCollision
* Be sure to calculate ship-to-ship hit position before the override collision hook is called, in case the hook needs this value.  (The other collision hooks already calculate the hit position before the override hook.)
2024-03-12 13:02:57 -04:00
Taylor Richards d9b2b428a0 remove Docker setup for standalone servers (#6036) 2024-03-12 09:02:34 -04:00
Asteroth e87fcfaf28 add player orders afterburn hard flag (#6019) 2024-03-11 09:25:22 -04:00
Joshua Glatt 65d1b7f99a Handle container data correctly with eval_num() (#6031) 2024-03-10 21:33:58 -07:00
Joshua Glatt 712337a2da fix crash when right-clicking on container modifier (#6030) 2024-03-10 08:12:14 -07:00
Asteroth b9169cc425 add some real docs 2024-03-09 21:27:32 -05:00
Asteroth b7a0124a9b limit damge and emp arcs 2024-03-09 14:00:16 -05:00
Asteroth 27925607b8 add scripted model arcs 2024-03-09 12:46:34 -05:00
Mike Nelson 38d8f17990 Fix message api out of bounds check (#6013) 2024-03-09 11:35:09 -05:00
Mike Nelson 5143855863 Add opf custom string as a lua sexp return type (#5964)
* add opf custom string as a lua sexp return type

* maybe just return the table directly

* break statement
2024-03-08 14:03:43 -05:00
Mike Nelson 648a1d009d Lua method to get the number of object sounds that can be used in tandem with removeSoundByIndex() to effectively silence a ship (#5958) 2024-03-07 21:42:31 -05:00
Goober5000 df531fc595 Merge pull request #6006 from Goober5000/lua_invalid_returns_nil
allow invalid arguments to be nil
2024-03-07 21:32:13 -05:00
Taylor Richards 5802f718f6 clean up and update macOS bundle info (#6028)
- Set app name properly per Apple docs
 - Use correct "FreeSpace Open" name
 - Set version properly per Apple docs
 - Add bundle identifier
 - Update copyright date
 - Remove localized strings since they are all English already
2024-03-06 05:22:59 -05:00
Mike Nelson 7d62d741b9 expose parse skip_to_string (#5936) 2024-03-05 10:48:51 -05:00
Mike Nelson 45258aabb4 allow ba.xstr to lookup from strings.tbl (#5949) 2024-03-05 10:42:29 -05:00
Goober5000 db34b4d53c Merge pull request #5987 from Goober5000/misc_timestamps
make several miscellaneous timestamps type-safe
2024-03-05 00:05:04 -05:00
Mike Nelson 7c2077baf2 Code to check if a medal is rank or badge (#5934) 2024-03-04 07:46:19 -05:00
Mike Nelson eef7623e9f Push back instead of direct assignment (#6024)
* push back instead of direct assignment

* remove i
2024-03-04 18:08:00 +09:00
Goober5000 529ac05034 add a useful function 2024-03-03 11:47:28 -05:00
Goober5000 6ac8559630 Lafiel's template magic to treat all invalid objects as nil 2024-03-03 11:47:28 -05:00
Goober5000 2626e7862b allow invalid arguments to be nil
A design choice very early in FSO's scripting development established that invalid results return invalid objects.  By using a game_settings.tbl flag, this allows invalid results to return nil instead.
2024-03-03 11:47:28 -05:00
John Fernandez b3cd35258c Merge pull request #5849 from MjnMixael/listify_active_games
Make Active_games_head an SCP_list
2024-03-03 11:01:55 -05:00
Goober5000 0fb12b89eb Merge pull request #6012 from Goober5000/more_composition_h
scripting refactor to compose handle types
2024-03-03 10:58:39 -05:00
Mike Nelson c082babd9c Allow lua to lock/unlock cutscenes (#5928)
* allow lua to lock/unlock cutscenes

* fix issue from rebase
2024-03-03 10:48:06 -05:00
Goober5000 d5f3be091c add weapon preloader
`ship-create` has had a preloader for many years, but `weapon-create` and `beam-create` did not.  This remedies that.
2024-03-02 21:25:24 -05:00
wookieejedi 790227a2bf Fix CTD with HUD Preset Switching (#6022)
* Fix CTD with HUD Preset Switching

After #5302 it was discoved that pressing the `Next` button in the HUD presets would cause a CTD.

Thanks for Lafiel for figuring this out
`If HC_current_file is HC_preset_filenames.size() - 1, then it'll oob on a vector access.`

Testing this PR fixes that crash.

* use static cast
2024-03-02 18:20:02 +00:00
Goober5000 803f08f969 Merge pull request #5992 from MageKing17/cleanup/iff-modular-special-colors
Change special IFF color `#define`s into `extern int`s.
2024-03-02 11:36:17 -05:00
Goober5000 f2c40a2669 Merge pull request #5971 from JohnAFernandez/Fix-QT-FRED-Command-Briefing
Fix "missing" command brief data
2024-03-02 11:35:47 -05:00
Goober5000 63756c00af add extra ways to modify background elements in missions (#6005)
* add extra ways to modify background elements in missions

This adds Lua API methods for getting suns and bitaps by index, as well as modifying their scale and position.  This removes the need to completely add and remove a background element that only needs to be modified.

* big pruning of (int) casts
2024-03-02 11:24:58 -05:00
Goober5000 2147571dff make several miscellaneous timestamps type-safe
Trail timestamps and a few top-level timestamps.  Also a few `static` and `constexpr` keywords for good measure.
2024-03-02 00:10:31 -05:00
Goober5000 bb9c76103b Merge pull request #5997 from ferralverrall/user/joverral/subsystem_under_reticule
allow targeting subsystems on already targeted ship under reticule
2024-03-01 15:33:12 -05:00
Goober5000 857e61f638 Merge pull request #5956 from Goober5000/coverity_1
several coverity fixes
2024-03-01 15:33:05 -05:00
Goober5000 58053a02b2 several coverity fixes
Some false positive annotations, some range checks, and commenting dead code.
2024-03-01 13:47:00 -05:00
BMagnu e8ea8733d0 Animation Drivers for Cockpits (#5925)
* Add control_info driver sources

* Properly deal with cockpits and their 'objnum's

* Add driven animation sets to weapons and cockpits

* enumify objnums
2024-03-01 10:03:27 +01:00
Goober5000 184bbb52bb Merge pull request #5974 from Goober5000/coverity_casts
use C++ casts for floating.h and floating.cpp
2024-02-29 20:23:05 -05:00
Goober5000 b00410ab01 Merge pull request #5967 from Goober5000/bitstring_poofs
bitstring poofs
2024-02-29 01:22:50 -05:00
Goober5000 525d8e34d0 Merge pull request #5950 from Goober5000/has_time_elapsed_msecs
add a has-time-elapsed-msecs SEXP
2024-02-29 01:22:37 -05:00
Goober5000 4cdf10b399 Merge pull request #6018 from Goober5000/another_isValid_fix
another isValid fix
2024-02-28 14:10:27 -05:00
Goober5000 c652d5a84c another isValid fix
Another #6009 follow-up, this one from PR #5935.
2024-02-28 12:51:49 -05:00
Goober5000 1a356834b4 Merge pull request #5998 from Goober5000/allow_resetting_ship_type
allow a ship class's type to be set more than once
2024-02-28 12:40:46 -05:00
Goober5000 3f48f7c4ad Merge pull request #5944 from Goober5000/implement_5941
allow finer control of particle rotation randomization
2024-02-28 12:39:13 -05:00
Goober5000 3e8a9d9738 Merge pull request #5935 from Goober5000/ship_to_parsed_ship_api
connect ship and parsed ship in Lua API
2024-02-28 12:39:03 -05:00
Goober5000 592eefb60f scripting refactor to compose handle types
Several handle types in the scripting API used inheritance where composition would be more appropriate.  This refactors those types, as well as removing the various handle types that were just aliases for `model_h`.  These are just the C++-side types; all the Lua types remain as-is.

This also refactors `sound_h` to move the previous `isSoundValid` to `isValid` so that `ade_set_args` will work properly for sounds with the `Lua_API_returns_nil_instead_of_invalid_object` flag.  The subclassing from `sound_entry_h` was removed and the "full validity check" was moved to `isValidWithEntry`.  The Lua side remains unaffected, but additional documentation was added to clarify the usage.

Follow-up to #6009 and prerequisite to #6006 due to the `isValid` refactor for `sound_h`.
2024-02-28 02:51:08 -05:00
Goober5000 373218d7d9 fix help descriptions for string-greater-than and string-less-than 2024-02-28 02:50:41 -05:00
Goober5000 1bdd6c3c4c Merge pull request #6015 from Goober5000/reconcile_isValid
reconcile isValid between PRs
2024-02-28 02:45:59 -05:00
Goober5000 1313434e11 reconcile isValid between PRs
PRs #6009 and #5995 passed CI checking independently of each other, but compilation broke after merging.  This patches things.
2024-02-28 02:01:30 -05:00
Goober5000 bf996313dc Merge pull request #6009 from Goober5000/isValid_refactor
isValid refactor
2024-02-28 01:41:42 -05:00
Goober5000 2eb5a3ecde Merge pull request #5993 from MageKing17/bugfix/ssm-random-count-fix
Fix SSM strikes with a variable count.
2024-02-28 00:04:06 -05:00
Goober5000 1aee2401e5 fix a few lighting bugs
There was confusion in the lighting code between light indexes and sun indexes.  These are usually the same, but not always.  This makes several changes to fix light/sun handling.

1. Clarify the distinction between lights and suns and add a `sun_index` field
2. Add a flags field and assign the `dual_cone` boolean to it, as well as a new glare flag
3. Determine light glare by checking the light flag, not the sun (which never worked in the first place as the `stars_sun_has_glare` function checked bitmaps rather than suns)
2024-02-27 20:21:42 -05:00
Goober5000 f8203e9da3 Merge pull request #5995 from Goober5000/ship_arrival_functions
cover all stages of ship warping in the Lua API
2024-02-27 13:14:13 -05:00
Goober5000 b24bcbcc62 Merge pull request #5886 from Goober5000/is_in_mission_update
make is-in-mission work for wings
2024-02-27 13:13:52 -05:00
Goober5000 0b8c1b6853 Merge pull request #5933 from Goober5000/for_subsystem
add for-subsystems
2024-02-27 13:13:43 -05:00
Goober5000 6ae6c550a7 Merge pull request #6001 from Goober5000/parse_object_team
add Team virtvar to parse objects
2024-02-27 13:12:13 -05:00
Mike Nelson 9c521d04d8 Retail ingame options (#5895)
* Create the ingame options game state

* Base working version of in-game options

* Cleanup + Optimization

* Localization pass

* more cleanup + documentation

* tooltips on option hover

* documentation and better inbounds check

* match case

* format strings instead of direct strings

* unused parameter

* address feedback

* localization id conflict with master

* Add this line back in

* pass the new option flags as well

* resolve xstr id conflict
2024-02-27 13:09:34 -05:00
Goober5000 c6c9945e50 check objh specifically for validity 2024-02-27 12:19:04 -05:00
mjn-mixael 8dfeca4ac3 address feedback 2024-02-26 22:30:59 -06:00
mjn-mixael bb4898cb04 assertion error 2024-02-26 22:30:59 -06:00
mjn-mixael 6e38656658 Convert Active_games_head to an SCP_list to prepare for the SCPUI API 2024-02-26 22:30:59 -06:00
Goober5000 e72dd4c2ca Merge pull request #6007 from BMagnu/collision_4096_fix
Fix broken collision pair caching
2024-02-26 19:23:40 -05:00
Goober5000 be8725c6c6 change isSubsytemValid to isValid 2024-02-26 16:19:53 -05:00
Goober5000 15c921223b compose object_h within the structs/classes that use it 2024-02-26 16:19:53 -05:00
Goober5000 ec241fcab3 standardize on isValid() and make validity member functions const 2024-02-26 15:56:41 -05:00
Birk Magnussen 0e00ab670c Add comment on MAX_OBJECTS 2024-02-26 21:07:37 +01:00
Birk Magnussen 1f9a2ca4ce Increase collision pair cache bitshift 2024-02-26 20:53:46 +01:00
Goober5000 0d697672dc Merge pull request #5943 from Goober5000/fix_time_to_goal
fix time-to-goal edge cases
2024-02-26 12:56:05 -05:00
Goober5000 1fe62ea8d1 Merge pull request #5996 from Goober5000/fix_ship_name_in_use_bug
fix "this ship name is already in use" bug
2024-02-26 12:26:15 -05:00
Goober5000 687694c732 Merge pull request #5884 from Goober5000/str_wrap_followup
str_wrap_to_width followup
2024-02-26 12:19:45 -05:00
Goober5000 9093af9b95 Merge pull request #5881 from Goober5000/hud_gauge_filename
add method for determining whether the HUD is hi-res
2024-02-26 12:19:37 -05:00
Goober5000 3b0dca6cd9 Merge pull request #6003 from Goober5000/version_24_1
bump version to 24.1
2024-02-26 03:03:48 -05:00
Goober5000 817b7dc975 bump version to 24.1 2024-02-26 00:49:25 -05:00
Goober5000 d4d7c8dbd2 add Team virtvar to parse objects
Previously, Team was an attribute available on ships, but not parsed ships.
2024-02-22 23:08:59 -05:00
Goober5000 bb89553b0a allow a ship class's type to be set more than once
There was an extra check during ship class parsing that prevented a ship class's type from being set if it had been set already.  This dates back to commit 5f3a6ec7 and was added as a parsing safeguard rather than as part of any modular table checks.  Since the parsing has changed, this extra check is no longer applicable.  Removing the check allows a ship class with a different type to be created using an existing ship class as a template.
2024-02-21 22:05:34 -05:00
joverral e4acd15a1e fix the string too! 2024-02-21 16:48:53 -08:00
joverral d16f46fb1c name change per feedback 2024-02-21 16:42:30 -08:00
joverral 77ad3ba0aa Fixes per feedback 2024-02-21 10:25:52 -08:00
Goober5000 da31995331 fix "this ship name is already in use" bug
This rather insidious FRED bug was all down to an improper check for the current ship.  It is possible for multiple objects of different types to be selected at the same time.  If, for example, a waypoint and ship are selected, and the waypoint was selected first, the waypoint will be what `cur_object_index` refers to.  Since the ship is the one and only ship selected, it will be what `single_ship` refers to.  Therefore, to avoid flagging its own ship name as a duplicate, the loop should exclude the single ship, not the current object.

The bug can be reliably triggered by selecting a waypoint, then adding a ship to the selection, then switching the focus to another application and back to FRED.  This finally squashes the bug.
2024-02-21 02:00:06 -05:00
joverral 25d326567e allow targeting subsystems on already targeted ship under reticule 2024-02-20 18:07:13 -08:00
Goober5000 03696d07ca cover all stages of ship warping in the Lua API
This improves the ability of Lua to check for ship arrival status:

1. Deprecates the `isWarpingIn` function, which can be misleading, and replaces it with the equivalent `isWarpingStage1`
2. Adds an `isWarpingStage2` function to fill a gap in functionality
3. Adds an `isArrivingWarp` function (complementing the existing `isDepartingWarp` function) to cover both stage 1 and stage 2
2024-02-19 22:08:15 -05:00
MageKing17 0528538a6f Fix SSM strikes with a variable count.
In #2464, a somewhat hard-to-understand equation involving taking the modulo of a random number was replaced with a function that would do those calculations instead. The problem is that the function performed the *entire* formula, while the code it replaced was only operating on the *difference* between the two numbers. Fortunately, this is as easy to fix as changing a `+=` into just an `=`.
2024-02-19 01:02:11 -08:00
MageKing17 3a48613a2d Add some security to avoid invalid Random::next() calls. (#5988)
There were a few instances of `Random::next()` being called without ensuring its arguments couldn't trip an assertion. This should hopefully catch them all.
2024-02-14 15:03:51 -05:00
MageKing17 a7b795e965 Change special IFF color #defines into extern ints.
Before this commit, `IFF_COLOR_SELECTION`, `IFF_COLOR_MESSAGE`, and `IFF_COLOR_TAGGED` were hardcoded indices into the `Iff_colors` vector. This could cause problems if any of these three colors were set to the same RGB values (since `iff_init_color()` doesn't create a new entry if the color already exists in the vector), and if a modular table tried to change any of these colors nothing would happen (since it would just create a new entry in `Iff_colors` without doing anything to the hardcoded indices).

This commit instead changes the `#define`s into `extern int`s, and assigns the return value of `iff_init_color()` to those global variables upon parsing the special color values, meaning that any combination of the three can be set to the same color without causing issues, and modular tables can actually modify them.

Potential clutter from unused values in the `Iff_colors` vector is basically unchanged (technically slightly worse if a modular table overrides any of these special colors with a color that doesn't already exist in the vector), but should maybe be looked at in the future.
2024-02-13 13:51:09 -08:00
Goober5000 99875810c6 Merge pull request #5986 from Goober5000/24_0_RC2_edits
edit the release template
2024-02-11 01:53:27 -05:00
Goober5000 13420121dd edit the release template
A bit of wordsmithing and link updating for the release thread.
2024-02-10 00:34:28 -05:00
Goober5000 26c5152d4a Merge pull request #5985 from Goober5000/pof_file_valid_fname_checks
make model file checks consistent
2024-02-09 17:24:08 -05:00
BMagnu 5066e498a3 Virtual POF fixes (#5984)
* Fix wrong filename being used

* Fix replacement map not used for collision check

* Fix poly count and incorrect submodel numbers
2024-02-09 23:10:39 +01:00
Goober5000 4bf806c485 make model file checks consistent
The general expectation is that model filenames can be specified as 'none' or '<none>' for no model, but as discovered by no tea, this was not consistent across the code base.  For example, `$Model File: none` was handled as expected but `$External Model File: none` was not.  This PR makes the handling consistent for all ship, weapon, and shockwave POF files, and also adds some extra checks when models are loaded.
2024-02-09 17:00:45 -05:00
Goober5000 2403f13483 Merge pull request #5983 from Goober5000/fred_popup_enhancement
fix FRED's "new object type" popup
2024-02-09 00:29:52 -05:00
Goober5000 8e98cddd6e Merge pull request #5982 from Goober5000/issue_5980
address issue 5980
2024-02-08 12:56:54 -05:00
Goober5000 30cabc4174 fix FRED's "new object type" popup
1. Fix the item ID indexing on the popup submenus and make sure they correspond with the ship dropdown menu
2. Remove the "player start" popup menu option as it has very limited utility and was already removed in qtFRED
3. Reduce a bunch of casts by using more appropriate popup menu types
4. Actually place an object in the mission when one is chosen from the popup menu

Also:
1. Remove the `Default_player_model` variable as its use is redundant
2. Remove unused arguments of `create_player()`
2024-02-08 03:26:25 -05:00
Goober5000 8a3b36d921 uncorrect angles if we're saving without the corrected angles flag (which will happen if the save format isn't STANDARD) 2024-02-07 22:51:37 -05:00
Goober5000 b74824f793 use a different method for removing blank backgrounds 2024-02-07 18:27:52 -05:00
Goober5000 6a26ca5061 only display these warnings once, and only on explicit save 2024-02-07 18:27:52 -05:00
Goober5000 9b78fad1c5 address feedback 2024-02-07 15:29:13 -05:00
John Fernandez d34570ae90 Merge pull request #5979 from MjnMixael/fix_select_zoom
Unhardcode renderSelectModel zoom value
2024-02-06 23:40:41 -05:00
mjn-mixael a0f4c4d2b3 documentation error 2024-02-05 16:20:33 -06:00
mjn-mixael 63990c54a9 unhardcode zoom value 2024-02-05 16:14:07 -06:00
Goober5000 6593565165 Merge pull request #5976 from notimaginative/fix_cmdline_mod_on_unix
refactor unix modlist handling to fix serveral issues
2024-02-05 17:00:59 -05:00
Goober5000 af93922ba5 Merge pull request #5975 from notimaginative/fix_chdir_bug
fix error handling in cfile_push_chdir()
2024-02-05 17:00:47 -05:00
Birk Magnussen 6ca68151a1 Remove Compiler Warning 2024-02-05 19:23:55 +01:00
Birk Magnussen f61407d899 Introduce shadow map amd optimization 2024-02-05 19:22:33 +01:00
Birk Magnussen 86ef5c356e Optimize uniforms 2024-02-05 19:22:33 +01:00
Birk Magnussen a127a35eee Optimize inter-stage data 2024-02-05 19:22:33 +01:00
Birk Magnussen 2a6c14d3b5 Make it properly configurable 2024-02-05 19:22:33 +01:00
Birk Magnussen 4f28615c6c Set flags correctly 2024-02-05 19:22:33 +01:00
Birk Magnussen 46408cce3a Conditionally set shader flags at run or compiletime 2024-02-05 19:22:33 +01:00
Birk Magnussen 3f1e67330c Large shader capability 2024-02-05 19:22:32 +01:00
Birk Magnussen e16ae385fa Predefine system 2024-02-05 19:22:32 +01:00
Birk Magnussen 2e90c8eed6 Conditional shader includes 2024-02-05 19:22:32 +01:00
Birk Magnussen da352c3eea Refactor gr_capability 2024-02-05 19:22:32 +01:00
Fabian Woltermann daeb1a7940 Merge pull request #5977 from BMagnu/shadow_map_ifdef
Fix faulty / missing optimization for AMD shader compilation
2024-02-05 18:34:08 +01:00
Birk Magnussen f56cbc59f1 improve shader for shadow map generation 2024-02-05 14:43:54 +01:00
Taylor Richards 79418a073d use proper SCP types 2024-02-05 00:04:34 -05:00
Goober5000 ce2e165510 Merge pull request #5962 from Goober5000/warp_duration_fixes
fix warp time durations
2024-02-04 23:49:15 -05:00
Goober5000 e9ee311709 fix warp time durations
Properly set the warp durations when ships arrive and depart, so that the warp animation can open and close smoothly without any discontinuities.
2024-02-04 23:30:22 -05:00
Taylor Richards 7576d4f2fe refactor unix modlist handling to fix serveral issues
The result of this special parsing should produce a mod string identical
to the string passed on the command line with the following exceptions:
  directory name case, directory separators

Should address the following:
 - no fundamental difference in modlist compared to Windows
 - no errors or warnings that are not produced on Windows
 - do not remove mods from list if missing
 - verify mod directory is accessible and actually a directory
 - do minimum amount of work to see if mod directory is valid
 - fix bug with trainling slashes
2024-02-04 22:08:28 -05:00
Taylor Richards 866b06ca35 fix error handling in cfile_push_chdir()
Old Volition bug where the original directory is pushed onto a stack
before the chdir() call. If that call fails then the stack is left with
a used entry that won't be removed until restart and can cause the stack
to fill up. Now it's added only if the chdir() call succeeds.

Also take the opportunity to make Cfile_stack dynamic.
2024-02-04 22:03:56 -05:00
Goober5000 f4d7b45e4d bitstring poofs
Change `Neb2_poof_flags` to use a bit string of unlimited length to allow for an arbitrary number of nebula poofs.
2024-02-04 19:07:29 -05:00
Goober5000 d23e4b8e87 use C++ casts for floating.h and floating.cpp
Change the casts used in the convenience #defines in floating.h.  Since these #defines are used pretty widely, this should reduce the count of C-style casts in the codebase by quite a bit.

Also change the casts in floating.cpp while we're at it, and remove some obsolete or unused code.
2024-02-04 18:33:25 -05:00
Goober5000 f3d15f8ddc Merge pull request #5972 from Goober5000/send_message_clarification
update sexp help for send-message
2024-02-04 15:19:10 -05:00
Goober5000 c9fe191d31 Merge pull request #5973 from Goober5000/modular_medals_fix
ensure medal information is correctly assigned
2024-02-04 15:18:53 -05:00
John Fernandez bad255fffb Merge pull request #5970 from Goober5000/sexp_exited_refinement
be mindful of death rolls when checking for ship stats
2024-02-03 23:31:01 -05:00
Goober5000 be260ef74c ensure medal information is correctly assigned
Make sure all medal fields are properly assigned.  In particular, if a modular -mdl.tbm is parsed, don't overwrite information from the base medals.tbl.  Fixes a bug reported in Discord.
2024-02-03 21:25:05 -05:00
Goober5000 0ac3d52261 update sexp help for send-message
Clarify message priorities, especially the conditions that allow High messages to be sent by Command.  Motivated by #5968.
2024-02-03 19:14:40 -05:00
John Fernandez f7df03c654 Merge pull request #5932 from Dark-Visor/sexp_ship_helps_final
Clarify which SEXPS work on ships not arrived
2024-02-03 17:14:34 -05:00
John Fernandez a7e1a27e36 Merge pull request #5963 from MjnMixael/fix_custom_string_dlg
Fix assert when adding custom strings
2024-02-03 16:03:56 -05:00
John Fernandez d83de47ef2 Fix wave filename copy. 2024-02-03 15:33:53 -05:00
JohnAFernandez 59435abfb2 fix missing command brief data
This fixes command briefing data apparently disappearing.  The ui was not being properly initialized because model_changed was being called before the ui was initialized, leading to default values.

This also fixes a few other minor issues.
2024-02-03 00:55:19 -05:00
Goober5000 ab319a631c be mindful of death rolls when checking for ship stats
In #5649 / b6c0e8b, the ship registry was updated to take ship death rolls into account.  There was one small wrinkle that it did not account for, however: SEXP operators that return numeric values had previously (i.e. before the introduction of the ship registry) checked the mission log for ship destruction, but after #5649 the EXITED status was not set until after the ship had completely exploded, resulting in certain SEXPs having their conditions slightly modified.  The equivalent of checking the mission log for ship destruction is now checking the ship status for DEATH_ROLL, so it is necessary to make that change for the numeric SEXPs to behave as they did before.

The motivating result for all this is to fix SEXPs like `hits-left` firing after a ship has been destroyed but before it has finished exploding.  This can be seen by loading the first non-training mission of FSPort and comparing the messages that are sent if you use cheats to kill Alpha 2.
2024-02-02 16:51:38 -05:00
John Fernandez 7c2950480e Merge pull request #5969 from Goober5000/fix_blink_locked_anim
fix Blink Locked Animation: option
2024-02-01 07:48:00 -05:00
Goober5000 a80bc26bfc fix Blink Locked Animation: option
Due to a copy-paste error in #4581, this option was not set properly.
2024-02-01 02:08:56 -05:00
John Fernandez ead3c62d23 Merge pull request #5966 from MjnMixael/unfocused_pause_again
Prevent compiler optimization
2024-01-30 22:22:19 -05:00
mjn-mixael 5cd502fb79 prevent compiler optimization 2024-01-30 15:26:25 -06:00
Dark-Visor 905d777e18 Update to wording of sexp helps PR
Clarify wording on SEXP helps so that it is clear whether an Event will
be evaluated or have delayed evaluation.
2024-01-30 21:12:14 +00:00
Dark-Visor 66deb83980 Clarify which SEXPS work on ships not arrived
SEXP helps should let the FREDder know whether a given ship argument
needs to be already in-mission for the SEXPression to operate. Update
the helps to include (ship needs to be in-mission) or (ship does not
need to be in-mission) or other relevant helpful information.
2024-01-30 21:12:14 +00:00
mjn-mixael de3e382180 better defense 2024-01-30 08:11:58 -06:00
mjn-mixael 0190fda7ee fix assert when adding custom strings 2024-01-30 08:11:58 -06:00
Goober5000 9651dc1598 Merge pull request #5957 from Goober5000/fix_subsystem_message
fix ship subsystem parse warning
2024-01-29 22:53:18 -05:00
Goober5000 743cf779bf Merge pull request #5961 from Goober5000/another_gravity_fix
Third gravity fix
2024-01-29 22:38:49 -05:00
Goober5000 da1e2c1049 add a new check to the Voice Acting Manager
This adds a new button to check if messages sent by `"<any wingman>"` have at least one ship with that persona.
2024-01-29 22:08:09 -05:00
Goober5000 bf13ce54a8 add method for determining whether the HUD is hi-res
Check the filenames used to initialize HUD gauges and mark the gauge as hi-res if the filename starts with 2_.  Also add a script method to return this value.

Additionally, make accessor methods `const`.
2024-01-29 22:07:54 -05:00
Goober5000 fcd3264fad implement C-str version of str_wrap_to_width 2024-01-29 22:07:37 -05:00
Goober5000 e33419c48d refactor str_wrap_to_width to use string starting offsets and lengths 2024-01-29 22:07:37 -05:00
Goober5000 a73df5bcb4 int to size_t 2024-01-29 22:07:37 -05:00
Goober5000 4e707fc8e9 make is-in-mission work for wings
Since its creation, the `is-in-mission` sexp operator has only checked for ships.  But mission designers might assume this also works for wings, leading to a situation where the sexp always returns false because no ship can have the same name as a wing.  Fortunately wing functionality can be added to this sexp without affecting ship functionality.
2024-01-29 22:07:18 -05:00
Goober5000 2e7057ed8d add for-subsystems
This is a new argument provider that lists all the subsystems of a ship, optionally restricted to one or more subsystem types.
2024-01-29 22:06:31 -05:00
Goober5000 ba9285e09a connect ship and parsed ship in Lua API
Add `getShip()` to parsed ships and `getParsedShip()` to ships to allow the two APIs to connect to one another.
2024-01-29 22:06:15 -05:00
Goober5000 138eddfbd2 fix time-to-goal edge cases
This fixes a few items that were revealed in the course of Dark Visor's SEXP documentation PR.  The EXITED status should return NAN_FOREVER, not just NAN.  The CANT_EVAL value is never returned from the sexp on account of ship status, due to the preceding check, and is not an appropriate return value anyway; so that is removed.  Finally, for a ship that can't move, the NAN return value is better than CANT_EVAL, since it represents the numeric situation more accurately and can also be checked by `is-nan`.
2024-01-29 22:05:38 -05:00
Goober5000 66be185d0c allow finer control of particle rotation randomization
This adds a new field to particle effects so that particle rotation can be configured on a per-type basis, not just on a blanket basis.  Implements #5941.
2024-01-29 22:05:23 -05:00
Goober5000 0c355efaa2 add a has-time-elapsed-msecs SEXP
Also fix a small mistake in the SEXP help.  The `sexp_has_time_elapsed()` function has been moved to take advantage of the existing time functions.
2024-01-29 22:05:00 -05:00
Goober5000 89a6e2aa7d fix ship subsystem parse warning
As reported by Trivial Psychic, if the number of subsystems exceeds the max as the result of a modular table, the error message was very misleading.  This fixes the error message and also makes it report the correct number of parsed subsystems.
2024-01-29 22:04:25 -05:00
Goober5000 84033d901c Third gravity fix
`ai_get_weapon` is not guaranteed to return a valid `wip`, so check for that here.  This should now cover all uses of `ai_get_weapon` in the codebase.

Fixes an Event Horizon crash reported in Discord.  Follow-up to #5842, commit 8dbe0e7.
2024-01-29 22:04:02 -05:00
Asteroth 46226a6cbe tweaks 2024-01-29 19:34:36 -05:00
John Fernandez 4b49123070 Merge pull request #5965 from notimaginative/fix_linux_build_image
switch to new linux build image
2024-01-29 16:36:40 -05:00
Taylor Richards 213bcbc80b find&replace ALL the things 2024-01-29 15:04:47 -05:00
Taylor Richards 0da34f0bc8 switch to new linux build image
Upgrades to Ubuntu 20.04 to fix Node v20 problem.
Bumps compiler to gcc-9.

NOTE: This breaks support for Linux distros older than Ubuntu 20.04
2024-01-29 14:57:38 -05:00
John Fernandez 8fcf385e7e Merge pull request #5955 from MjnMixael/no_ui_pause
Pause the UI properly based on user settings
2024-01-28 00:53:37 -05:00
mjn-mixael 4f4722ccad also pause the UI properly based on user settings 2024-01-25 13:14:24 -06:00
John Fernandez 7d94561ea5 Merge pull request #5920 from MjnMixael/properly_check_windowed
Properly check if we're running in a windowed mode
2024-01-25 00:21:43 -05:00
John Fernandez 248cec7cf9 Merge pull request #5921 from MjnMixael/save_multi_settings
Save these to the ini file
2024-01-25 00:20:50 -05:00
John Fernandez e987d1cd7b Merge pull request #5929 from MjnMixael/clean_cutscene_info
Cleanup ui cutscene api
2024-01-25 00:20:18 -05:00
John Fernandez f1aa29551b Merge pull request #5954 from MjnMixael/fix_discord_option
Fix discord option needing restart
2024-01-24 17:21:34 -05:00
Goober5000 76734fb5ed Merge pull request #5946 from Goober5000/splash_fix
fix splash crash and add supplemental script hook
2024-01-24 14:42:29 -05:00
mjn-mixael fb0a62c400 fix discord option needing restart 2024-01-24 10:07:37 -06:00
Goober5000 1403301b65 add variable to prevent any hooks from running until OnGameInit has run 2024-01-23 14:51:06 -05:00
John Fernandez 1d1eb5ec4d Merge pull request #5952 from MjnMixael/fix_custom_string_save
Fix custom string saving
2024-01-23 14:29:45 -05:00
Goober5000 7283412880 Merge pull request #5953 from Goober5000/fix_fire_at_coords
fix crash in fire-beam-at-coordinates
2024-01-23 00:40:12 -05:00
Mike Nelson 1d2ca8eb5a print option settings to the log (#5914) 2024-01-23 00:40:04 -05:00
Goober5000 130ddb41f1 Merge pull request #5947 from JohnAFernandez/keep-observers-from-crashing
Fix: Keep Chase view from crashing in multi
2024-01-23 00:13:07 -05:00
Goober5000 9462241c0b Merge pull request #5948 from BMagnu/fix_msaa_compile
Fix MSAA for some graphics drivers
2024-01-23 00:12:58 -05:00
Goober5000 14bba9aea1 fix crash in fire-beam-at-coordinates
A small oversight in #5837 - beam jitter is not done when targeting coordinates.
2024-01-23 00:07:33 -05:00
mjn-mixael c7b43b0e0e fix custom string saving 2024-01-22 12:18:25 -06:00
Birk Magnussen 1355c484fe Remove language-defined declaration 2024-01-19 22:15:29 +01:00
JohnAFernandez 1866c6adb5 Whoops, forgot to push typo fix 2024-01-19 01:49:43 -05:00
JohnAFernandez a11517984e Keep Chase view from crashing
For Observers in multi
2024-01-19 01:29:08 -05:00
Goober5000 f207d2d12c add new On Splash End hook for scripts that have been doing post-splash stuff in On Game Init 2024-01-18 17:00:02 -05:00
Goober5000 4970252e9f tweak initialization sequence to head off potential future problems 2024-01-18 16:51:36 -05:00
Goober5000 d789e9b33a fix crash caused by incomplete script initialization 2024-01-18 00:43:14 -05:00
Fabian Woltermann 292f7d3b03 Merge pull request #5938 from MjnMixael/unload_pilot_scpui
Fix SCPUI overwriting campaign data
2024-01-15 19:09:47 +01:00
mjn-mixael 3bfc37172a Expose unloading a player and campaign file 2024-01-14 22:32:25 -06:00
Goober5000 2bb1c10557 Merge pull request #5916 from Goober5000/number_hack_upgrade
upgrade the OPF_POSITIVE number hack
2024-01-14 19:19:16 -05:00
Asteroth 84f97936aa Merge remote-tracking branch 'upstream/master' into aim-cursor 2024-01-13 00:53:37 -05:00
Goober5000 40fac5dd5f Merge pull request #5838 from Goober5000/turret_constify
constify some turret code
2024-01-12 20:46:03 -05:00
John Fernandez 2a33e374c2 Merge pull request #5926 from MjnMixael/is_movie_playing
LUA method to check if a movie is currently playing
2024-01-10 02:52:31 -05:00
mjn-mixael d48d00d946 static cast 2024-01-09 08:11:03 -06:00
mjn-mixael 562875130c Cleanup ui cutscene handling 2024-01-08 13:57:51 -06:00
mjn-mixael 4401101fea lua method to check if a movie is currently playing 2024-01-07 14:41:01 -06:00
mjn-mixael 509f887f6c Save these to the ini file 2024-01-05 17:04:58 -06:00
mjn-mixael 266079997a remove unused code 2024-01-05 13:31:31 -06:00
mjn-mixael f4a3903478 properly check if we're running in a windowed mode 2024-01-05 13:13:24 -06:00
Taylor Richards f4202df450 codesign Mac builds to prevent broken app message (#5919)
Apple Silicon Macs require that all code is signed in order to run. Our builds
are partially signed due to the SDL framework already being signed, so it is
seen as broken. To fix that we need to codesign all the rest of the necessary
files with an ad-hoc signature in order to allow the builds to work properly.
2024-01-04 22:25:59 -05:00
Goober5000 e619c0c3d3 Merge pull request #5910 from Goober5000/campaign_load_refactor
campaign error message improvement
2024-01-04 21:51:24 -05:00
Goober5000 ff0b79b6be move this and make it static 2024-01-04 13:49:27 -05:00
Goober5000 701d20c112 upgrade the OPF_POSITIVE number hack
This is a new method of ensuring that OPF_POSITIVE numbers are positive.  It works for all numeric arguments, including variables and literals, and caches the status of the node to avoid lookups for every negative number on every frame.  Tested on both operator and non-operator cases.

Follow-up to #5915.
2024-01-04 13:43:19 -05:00
Goober5000 9a45c9fd05 Merge pull request #5915 from Goober5000/number_hack_update
restore number hack sign checking in all builds
2024-01-04 13:41:47 -05:00
JohnAFernandez 146102e82c Merge pull request #5909 from Goober5000/remove_mht
remove mainhalltemp
2024-01-04 11:33:41 -05:00
Goober5000 be2c18d608 add back exceptions 2024-01-03 18:46:10 -05:00
Goober5000 c9644cdcae Merge pull request #5913 from Goober5000/5911_followup
5911 followup
2024-01-03 18:03:05 -05:00
Goober5000 d088e895f8 restore number hack sign checking in all builds
Operators that specify OPF_POSITIVE should be guaranteed to get positive numbers.  This code was previously disabled for performance reasons, but following the contract of the SEXP system is more important.  A future PR will improve the performance of the functions used here.

Also, the `num-players` operator takes no arguments, so fix that.
2024-01-03 14:24:43 -05:00
Goober5000 f1a9b2639b 5911 followup
In consultation with @BMagnu, code that validates data in the POF file itself should happen in `read_model_file_no_subsys`, as virtual POFs rely on their source files having correct data.  I've added comments and slightly rearranged things to make this clearer, and also moved the new code from `read_and_process_model_file`.  Additionally, I fixed two bugs by changing `parent > pm->n_models` to `parent >= pm->n_models` and adding a newline to the `nprintf`.
2024-01-03 11:34:18 -05:00
Fabian Woltermann a1690dcb90 Merge pull request #5911 from The-E/fix/invalid_eye_point_data
Fixes an issue with faulty eyepoint data causing a crash.
2024-01-03 14:45:26 +01:00
Fabian Woltermann 2c4088efdd Fixes an issue with faulty eyepoint data causing a crash. 2024-01-03 13:50:23 +01:00
Goober5000 da3725a3ac Merge pull request #5902 from Goober5000/refine_number_checking
refine numeric error checking in FRED
2024-01-03 00:00:22 -05:00
JohnAFernandez 81b7460e57 Merge pull request #5908 from MjnMixael/lua_enum_validation
Add some better error and validation checking to lua enums scripting API
2024-01-02 23:41:58 -05:00
Goober5000 c9a1127764 fall back to default campaign when starting the game or choosing a new pilot 2024-01-02 02:27:37 -05:00
Goober5000 6eb9ae2aec remove mainhalltemp
These files are not referenced anywhere and haven't been used since before FreeSpace 2 was released.
2024-01-01 23:51:45 -05:00
Goober5000 d3d9ee3092 refine campaign failure error messages 2024-01-01 17:41:42 -05:00
Goober5000 f66fc92859 int to boolean 2024-01-01 17:41:42 -05:00
Goober5000 94cbc350a4 handle main hall if campaign could not be loaded 2024-01-01 17:41:42 -05:00
Goober5000 550e9ec5b2 distinguish between corrupt and missing campaign files 2024-01-01 17:41:30 -05:00
mjn-mixael de3463958d Add some better error and validation checking to lua enums 2024-01-01 13:27:11 -06:00
Asteroth 03d7845124 improve comments (#5903) 2023-12-31 15:56:41 -05:00
Goober5000 661dceb0d8 Merge pull request #5906 from Goober5000/fix_vr_aspect_lock
additional HUD fixes for VR
2023-12-31 12:53:59 -05:00
m!m 202686dab6 Merge pull request #5907 from asarium/fix/balanceLuaStack
Fix unbalanced stack when retrieving Lua main thread
2023-12-31 18:18:41 +01:00
asarium b8da1106eb Fix unbalanced stack when retrieving Lua main thread
After getting the main state from the Lua registry, this function had
two Lua thread values on its Lua stack but we only removed one which
lead to a value being left on the stack.

Why did this not blow up before? Because undefined behavior.

The only place where this was called was when creating a Lua reference
value where luaL_ref is called in the same expression (see
UniqueLuaReference::create). The evaluation order of the parameters for
the make_shared call is not defined by the standard and for some reason
all major compilers (except clang) choose to execute the luaL_ref call
before the getMainThread call.

For those compilers, everything is fine. We have some extra values on
the Lua stack but that gets cleaned up after the API function finishes.

However, clang first evaluates the getMainThread which leaves an extra
Lua thread on the Lua stack. The luaL_ref call then references this
thread value instead of the intended value. In the concrete case, this
meant that LuaFunction saw that the reference points to a thread and
rightfully threw an exception.

This fixes #5904.
2023-12-31 17:44:58 +01:00
Goober5000 43f7921121 additional HUD fixes for VR
Use a single canonical `frametime` value for all HUD rendering, in both `hud_render_preprocess` and `hud_render_all`.  Previously, certain functions called through `hud_render_preprocess` were using the full frametime, rather than the half frametime needed for VR when the HUD is rendered twice.

Fixes #5882.
2023-12-30 20:35:15 -05:00
Goober5000 f4669db41c constify some turret code
Apply `const` to a whole bunch of functions.  Also change a bunch of ints to bools.
2023-12-30 00:00:31 -05:00
Tyler Blount b3df3364e4 Merge pull request #5837 from Goober5000/turret_refactor
untangle turret code a bit
2023-12-29 21:31:51 -07:00
Goober5000 b6a76b788d reuse beam points for collision test 2023-12-29 16:51:36 -05:00
Goober5000 e21b07662e refactor 'share fire direction'
Use a simpler, more robust, and more correct method of sharing the fire direction among beams: replicate the actual beam vector for all firing points.  This further cleans up and simplifies the beam firing code and also clarifies some vector math.
2023-12-29 16:35:34 -05:00
Goober5000 9b4b0b552b fix use of target position, and also don't get gvec if we don't need it 2023-12-29 16:34:22 -05:00
Goober5000 bdab7a0c55 untangle turret code a bit
1. make `check_ok_to_fire` return a boolean (like `check_los`)
2. make `check_ok_to_fire` and `check_los` both use a position argument since we don't need the whole turret
3. remove the redundant position prediction code from `ship_get_global_turret_gun_info` (since that needs to be a "pure" function) while making sure "share fire direction" still works
4. skip calculation of the vector in `ship_get_global_turret_gun_info` if we don't need it
5. move the position prediction code out of `aifft_rotate_turret` and into its own function
6. prune some gun position calculation calls since in most cases one will suffice
7. fix position "jitter" with weapon subsystem damage in missions that use gravity
8. `model_rotate_gun` now uses a nullptr position for a reset instead of an extra boolean argument
9. use a more efficient method to calculate gun barrel length
10. a couple variable name changes for clarity
2023-12-29 16:28:24 -05:00
Goober5000 e269cdab6e Merge pull request #5863 from Baezon/beams-respect-hull-check-self-damage
Make beams respect 'check hull' and 'can damage shooter' flags
2023-12-29 16:27:50 -05:00
wookieejedi edc76bcb40 Fix typo in lua error prints (#5901)
2 line typo fix `refere` -> `refer`
2023-12-29 13:42:35 -05:00
Goober5000 cbde5a8e85 refine numeric error checking in FRED
1. Allow a `+` to appear in front of numbers, just as with `-`
2. Check for `.` and `,` within numbers to give a less misleading error message than "not a number"
3. The old number hack inadvertently skipped numeric literals, so specifically check for those
2023-12-28 14:46:47 -05:00
Goober5000 7fcfc35820 Merge pull request #5898 from Goober5000/invalid_point_message_fix
make error messages more accurate
2023-12-24 14:31:06 -05:00
Goober5000 f852421d76 update messages per feedback 2023-12-24 13:27:51 -05:00
Goober5000 2321311725 make error messages more accurate
There are several SEXP argument types that themselves encompass multiple argument types: for example, ships and wings.  This could be misleading when there is an error message displayed.  So, this updates the error codes to explicitly cover all of the possibilities.
2023-12-24 13:27:51 -05:00
John Fernandez 38cd1bff86 Restore accidental const removals 2023-12-21 16:33:31 -05:00
John Fernandez 71ee9501f9 Turns out coverity was optimistic 2023-12-20 21:05:36 -05:00
John Fernandez 221670589e Undo Overzealous changes 2023-12-20 20:30:40 -05:00
John Fernandez 9a47a664f7 Whoops, no std::move here 2023-12-20 19:54:13 -05:00
John Fernandez 7b7b19b71b Change many references to const auto&
A few uses of auto were also removed, where using a direct function call was superior.
2023-12-20 19:43:11 -05:00
John Fernandez 666b9a5751 Missed another conversion specifier 2023-12-20 16:21:35 -05:00
JohnAFernandez 733e1adcba Merge pull request #5892 from JohnAFernandez/Fix-Coverity-Workflow
Fix Coverity WorkFlow
2023-12-20 16:17:29 -05:00
John Fernandez 8421d8d8e6 Adjust conversion specifiers 2023-12-20 16:14:55 -05:00
John Fernandez 63ed4c8254 Remove this time tracking
It is no longer used and has low resolution compared to the current method used elsewhere.
2023-12-20 16:06:49 -05:00
John Fernandez 3124c55642 Change various varibales to time_t
These variables were previously int's or uint's
2023-12-20 16:06:49 -05:00
Goober5000 485eb16fe3 Merge pull request #5827 from Goober5000/delay_status_tweak
tweak event status evaluation when the game is not in-mission
2023-12-19 19:34:35 -05:00
John Fernandez a493f07333 Fix Coverity WorkFlow
By using app image and switching to Checkout V1.

Also removes Vulkan SDK install, since it seems to be taken care of by the app image or is disabled.  I can't figure it out from the app images.
2023-12-19 12:12:56 -05:00
Asteroth e543c1aea2 make beams respect check hull and self damage 2023-12-05 16:46:32 -05:00
Goober5000 0d1d6fdf44 tweak event status evaluation when the game is not in-mission
The requirement for delayed event status checks to be strictly greater than the event fired timestamp (see commit eed50619ca / PR #5267) means that `is-event-true-delay 0` will not work in debriefings if the event becomes true and the debriefing SEXPs are evaluated on the exact same timestamp.  Normally this is not a problem, but one important exception is the `end-mission` operator which instantly sends the player to debriefing.

This timestamp behavior is working as designed and should be consistent as long as the `end-mission` operator has been around (I've verified it as far back as 3.7.4).  But it does lead to inconvenient situations where the event that called `end-mission` cannot be evaluated by the debriefing.  This makes it slightly more complicated to plan debriefing stages based on these events.

Therefore, it makes sense to add an exception to the event status function to ignore the delay if the evaluation is not in-mission.  This is consistent with evaluating events that *never* fired and also satisfies the principle of least astonishment for mission designers.

This also adds relevant documentation to the event and goal status operators.
2023-11-27 18:08:59 -05:00
Asteroth 8460218707 first draft 2023-09-20 12:20:38 -04:00
Goober5000 676fb4b17d better stats handling when switching or resetting campaigns 2017-08-26 16:40:16 -04:00
1073 changed files with 73151 additions and 79586 deletions

No files matched your search

+12 -1
View File
@@ -4,20 +4,28 @@ modernize-*,\
-modernize-avoid-c-arrays,\
-modernize-make-unique,\
-modernize-raw-string-literal,\
-modernize-use-default-member-init,\
-modernize-use-nodiscard,\
-modernize-use-trailing-return-type,\
-modernize-use-using,\
performance-*,\
-performance-no-int-to-ptr,\
-performance-type-promotion-in-math-fn,\
misc-*,\
-misc-include-cleaner,\
-misc-macro-parentheses,\
-misc-misplaced-widening-cast,\
-misc-no-recursion,\
-misc-non-private-member-variables-in-classes,\
-misc-static-assert,\
-misc-unused-parameters,\
-misc-use-anonymous-namespace,\
readability-*,\
-readability-avoid-const-params-in-decls,\
-readability-else-after-return,\
-readability-function-cognitive-complexity,\
-readability-function-size,\
-readability-identifier-length,\
-readability-identifier-naming,\
-readability-implicit-bool-conversion,\
-readability-inconsistent-declaration-parameter-name,\
@@ -29,10 +37,13 @@ readability-*,\
"
WarningsAsErrors: ''
HeaderFilterRegex: 'code/.*$|freespace2/.*$|qtfred/.*$|test/src/.*$|build/.*$'
AnalyzeTemporaryDtors: false
CheckOptions:
- key: 'misc-assert-side-effect.AssertMacros'
value: 'assert,Assert,Assertion'
- key: 'misc-const-correctness.AnalyzeValues'
value: 'false'
- key: 'misc-const-correctness.TransformValues'
value: 'false'
- key: 'modernize-use-emplace.ContainersWithPushBack'
value: 'std::vector;std::deque;std::list;SCP_vector;SCP_deque;SCP_list'
- key: 'readability-braces-around-statements.ShortStatementLines'
+49 -22
View File
@@ -13,9 +13,15 @@ jobs:
strategy:
matrix:
configuration: [FastDebug, Release]
os: [ubuntu-latest, ubuntu-24.04-arm]
include:
- os: ubuntu-latest
arch: x86_64
- os: ubuntu-24.04-arm
arch: arm64
name: Linux
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/linux_build:sha-5ac6f70
runs-on: ${{ matrix.os }}
container: ghcr.io/scp-fs2open/linux_build:sha-71099c9
steps:
- uses: actions/checkout@v1
name: Checkout
@@ -24,7 +30,7 @@ jobs:
- name: Configure CMake
env:
CONFIGURATION: ${{ matrix.configuration }}
COMPILER: gcc-5
COMPILER: gcc-9
ENABLE_QTFRED: OFF
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
- name: Compile
@@ -45,15 +51,18 @@ jobs:
CONFIGURATION: ${{ matrix.configuration }}
run: $GITHUB_WORKSPACE/ci/linux/generate_appimage.sh $GITHUB_WORKSPACE/build/install
- name: Upload build result
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: linux-${{ matrix.configuration }}
name: linux-${{ matrix.configuration }}-${{ matrix.arch }}
path: ${{ github.workspace }}/build/install/*.AppImage
linux_zip:
name: Build Linux distribution zip
needs: build_linux
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/sftp_upload:sha-748b19d
strategy:
matrix:
arch: [x86_64, arm64]
steps:
- uses: actions/checkout@v1
name: Checkout
@@ -61,17 +70,23 @@ jobs:
submodules: true
fetch-depth: '0'
- name: Download Release builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: linux-Release
name: linux-Release-${{ matrix.arch }}
path: builds
- name: Download FastDebug builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: linux-FastDebug
name: linux-FastDebug-${{ matrix.arch }}
path: builds
- name: Fix permissions
working-directory: ./builds
shell: bash
run: chmod 755 *.AppImage
- name: Create Distribution package
working-directory: ./builds
env:
ARCH: ${{ matrix.arch }}
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Linux
- name: Upload result package
working-directory: ./builds
@@ -89,7 +104,7 @@ jobs:
arch: [Win32, x64]
simd: [SSE2]
name: Windows
runs-on: windows-2019
runs-on: windows-2022
steps:
- uses: actions/checkout@v1
name: Checkout
@@ -120,9 +135,9 @@ jobs:
# cached: ${{ steps.cache-qt-win.outputs.cache-hit }}
# aqtversion: ==0.8
- name: Prepare Vulkan SDK
uses: humbletim/[email protected].0
uses: humbletim/[email protected].1
with:
vulkan-query-version: 1.3.204.0
vulkan-query-version: 1.4.304.1
vulkan-components: Vulkan-Headers, Vulkan-Loader
vulkan-use-cache: true
- name: Configure CMake
@@ -137,13 +152,13 @@ jobs:
if [ "$ARCHITECTURE" = "Win32" ]; then
cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DFSO_USE_SPEECH="ON" \
-DFSO_USE_VOICEREC="ON" -DMSVC_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_USE_VOICEREC="ON" -DFORCED_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_BUILD_QTFRED=OFF -DFSO_BUILD_TESTS=ON \
-DFSO_INSTALL_DEBUG_FILES="ON" -DFSO_BUILD_WITH_VULKAN="OFF" -A "$ARCHITECTURE" \
-G "Visual Studio 16 2019" -T "v142" ..
else
cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DFSO_USE_SPEECH="ON" \
-DFSO_USE_VOICEREC="ON" -DMSVC_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_USE_VOICEREC="ON" -DFORCED_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_BUILD_QTFRED=OFF -DFSO_BUILD_TESTS=ON \
-DFSO_INSTALL_DEBUG_FILES="ON" -A "$ARCHITECTURE" \
-G "Visual Studio 16 2019" -T "v142" ..
@@ -164,7 +179,7 @@ jobs:
shell: bash
run: ./bin/$CONFIGURATION/unittests --gtest_shuffle
- name: Upload build result
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: windows-${{ matrix.configuration }}-${{ matrix.arch }}-${{ matrix.simd }}
path: ${{ github.workspace }}/build/install/*
@@ -184,12 +199,12 @@ jobs:
submodules: true
fetch-depth: '0'
- name: Download Release builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: windows-Release-${{ matrix.arch }}-${{ matrix.simd }}
path: builds
- name: Download FastDebug builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: windows-FastDebug-${{ matrix.arch }}-${{ matrix.simd }}
path: builds
@@ -240,9 +255,9 @@ jobs:
submodules: true
fetch-depth: 0
- name: Prepare Vulkan SDK
uses: humbletim/[email protected].0
uses: humbletim/[email protected].1
with:
vulkan-query-version: 1.3.204.0
vulkan-query-version: 1.4.304.1
vulkan-components: Vulkan-Headers, Vulkan-Loader
vulkan-use-cache: true
- name: Set up test version
@@ -269,13 +284,25 @@ jobs:
ARCH: ${{ matrix.arch }}
XDG_RUNTIME_DIR: /root
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
- name: Sign builds
working-directory: ./build/bin
run: |
# make sure OpenAL framework is signed
find . -name OpenAL -type f | while read xx; do codesign --force -s - $xx; done
find . -name OpenAL.framework -type d | while read xx; do codesign --force -s - $xx; done
# make sure dylibs are signed
find . -name \*.dylib -type f | while read xx; do codesign --force -s - $xx; done
# sign binaries
find . -perm +111 -type f | grep MacOS | while read xx; do codesign --force -s - $xx; done
# sign apps
find . -name \*.app -maxdepth 1 | while read xx; do codesign --force -s - $xx; done
- name: Package build result
working-directory: ./build/bin
# Use GNU tar here (part of runner image) to avoid weird corruption bug with bsdtar
# Ref: https://github.com/actions/runner-images/issues/2619
run: gtar -cvzf macos-build-${{ matrix.configuration }}-${{ matrix.arch }}.tgz *.app
- name: Upload build result
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: mac-${{ matrix.configuration }}-${{ matrix.arch }}
path: ${{ github.workspace }}/build/bin/macos-build-${{ matrix.configuration }}-${{ matrix.arch }}.tgz
@@ -295,12 +322,12 @@ jobs:
fetch-depth: '0'
ref: '${{ github.ref }}'
- name: Download Release builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: mac-Release-${{ matrix.arch }}
path: builds
- name: Download FastDebug builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: mac-FastDebug-${{ matrix.arch }}
path: builds
+53 -26
View File
@@ -41,10 +41,16 @@ jobs:
# Run this job for each configuration
# The current config running is accesible with `matrix.configuration`
configuration: [FastDebug, Release]
os: [ubuntu-latest, ubuntu-24.04-arm]
include:
- os: ubuntu-latest
arch: x86_64
- os: ubuntu-24.04-arm
arch: arm64
name: Linux
needs: create_release # Don't run this job until create_release is done and successful
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/linux_build:sha-5ac6f70
runs-on: ${{ matrix.os }}
container: ghcr.io/scp-fs2open/linux_build:sha-71099c9
steps:
- uses: actions/checkout@v1
# checks-out your repository under $GITHUB_WORKSPACE, so your workflow can access it.
@@ -55,7 +61,7 @@ jobs:
- name: Configure CMake
env:
CONFIGURATION: ${{ matrix.configuration }}
COMPILER: gcc-5
COMPILER: gcc-9
ENABLE_QTFRED: OFF
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
- name: Compile
@@ -76,7 +82,7 @@ jobs:
CONFIGURATION: ${{ matrix.configuration }}
run: $GITHUB_WORKSPACE/ci/linux/generate_appimage.sh $GITHUB_WORKSPACE/build/install
- name: Upload build result
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
# Upload the url file for use with other runners
# upload-artifact.inputs:
# if-no-files-found=warn What to do if path fails to find any files.
@@ -87,13 +93,16 @@ jobs:
# 0 Use default retention policy of the repo
# 1~90 Min 1, Max 90 days to keep the artifact unless changed by repo settings page
with:
name: linux-${{ matrix.configuration }}
name: linux-${{ matrix.configuration }}-${{ matrix.arch }}
path: ${{ github.workspace }}/build/install/*.AppImage
linux_zip:
name: Build Linux distribution zip
needs: build_linux
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/sftp_upload:sha-748b19d
strategy:
matrix:
arch: [x86_64, arm64]
steps:
- uses: actions/checkout@v1
name: Checkout
@@ -103,24 +112,30 @@ jobs:
ref: '${{ github.ref }}'
- name: Download Release builds
# Grab the release builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: linux-Release
name: linux-Release-${{ matrix.arch }}
path: builds
- name: Download FastDebug builds
# Grab the debug builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: linux-FastDebug
name: linux-FastDebug-${{ matrix.arch }}
path: builds
- name: Fix permissions
working-directory: ./builds
shell: bash
run: chmod 755 *.AppImage
- name: Create Distribution package
# Zip both builds together
id: generate_package
working-directory: ./builds
env:
ARCH: ${{ matrix.arch }}
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Linux
- name: Upload result package
# Stash the result to artifact filespace
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ steps.generate_package.outputs.package_name }}
path: ${{ steps.generate_package.outputs.package_path }}
@@ -140,7 +155,7 @@ jobs:
simd: [SSE2, AVX]
needs: create_release
name: Windows
runs-on: windows-2019
runs-on: windows-2022
steps:
- uses: actions/checkout@v1
# Checkout repo
@@ -176,9 +191,9 @@ jobs:
# cached: ${{ steps.cache-qt-win.outputs.cache-hit }}
# aqtversion: ==0.8
- name: Prepare Vulkan SDK
uses: humbletim/[email protected].0
uses: humbletim/[email protected].1
with:
vulkan-query-version: 1.3.204.0
vulkan-query-version: 1.4.304.1
vulkan-components: Vulkan-Headers, Vulkan-Loader
vulkan-use-cache: true
- name: Configure CMake
@@ -193,13 +208,13 @@ jobs:
if [ "$ARCHITECTURE" = "Win32" ]; then
cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DFSO_USE_SPEECH="ON" \
-DFSO_USE_VOICEREC="ON" -DMSVC_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_USE_VOICEREC="ON" -DFORCED_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_BUILD_QTFRED=OFF -DFSO_BUILD_TESTS=ON \
-DFSO_INSTALL_DEBUG_FILES="ON" -DFSO_BUILD_WITH_VULKAN="OFF" -A "$ARCHITECTURE" \
-G "Visual Studio 16 2019" -T "v142" ..
else
cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DFSO_USE_SPEECH="ON" \
-DFSO_USE_VOICEREC="ON" -DMSVC_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_USE_VOICEREC="ON" -DFORCED_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_BUILD_QTFRED=OFF -DFSO_BUILD_TESTS=ON \
-DFSO_INSTALL_DEBUG_FILES="ON" -A "$ARCHITECTURE" \
-G "Visual Studio 16 2019" -T "v142" ..
@@ -220,7 +235,7 @@ jobs:
shell: bash
run: ./bin/$CONFIGURATION/unittests --gtest_shuffle
- name: Upload build result
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: windows-${{ matrix.configuration }}-${{ matrix.arch }}-${{ matrix.simd }}
path: ${{ github.workspace }}/build/install/*
@@ -244,13 +259,13 @@ jobs:
fetch-depth: '0'
ref: '${{ github.ref }}'
- name: Download Release builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: windows-Release-${{ matrix.arch }}-${{ matrix.simd }}
path: builds
- name: Download FastDebug builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: windows-FastDebug-${{ matrix.arch }}-${{ matrix.simd }}
path: builds
@@ -265,13 +280,13 @@ jobs:
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Windows
- name: Upload result package
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ steps.generate_package.outputs.package_name }}
path: ${{ steps.generate_package.outputs.package_path }}
- name: Upload debug package
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ steps.generate_package.outputs.debug_name }}
path: ${{ steps.generate_package.outputs.debug_path }}
@@ -316,9 +331,9 @@ jobs:
fetch-depth: 0
ref: '${{ github.ref }}'
- name: Prepare Vulkan SDK
uses: humbletim/[email protected].0
uses: humbletim/[email protected].1
with:
vulkan-query-version: 1.3.204.0
vulkan-query-version: 1.4.304.1
vulkan-components: Vulkan-Headers, Vulkan-Loader
vulkan-use-cache: true
- name: Configure CMake
@@ -339,13 +354,25 @@ jobs:
ARCH: ${{ matrix.arch }}
XDG_RUNTIME_DIR: /root
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
- name: Sign builds
working-directory: ./build/bin
run: |
# make sure OpenAL framework is signed
find . -name OpenAL -type f | while read xx; do codesign --force -s - $xx; done
find . -name OpenAL.framework -type d | while read xx; do codesign --force -s - $xx; done
# make sure dylibs are signed
find . -name \*.dylib -type f | while read xx; do codesign --force -s - $xx; done
# sign binaries
find . -perm +111 -type f | grep MacOS | while read xx; do codesign --force -s - $xx; done
# sign apps
find . -name \*.app -maxdepth 1 | while read xx; do codesign --force -s - $xx; done
- name: Package build result
working-directory: ./build/bin
# Use GNU tar here (part of runner image) to avoid weird corruption bug with bsdtar
# Ref: https://github.com/actions/runner-images/issues/2619
run: gtar -cvzf macos-build-${{ matrix.configuration }}-${{ matrix.arch }}.tgz *.app
- name: Upload build result
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: mac-${{ matrix.configuration }}-${{ matrix.arch }}
path: ${{ github.workspace }}/build/bin/macos-build-${{ matrix.configuration }}-${{ matrix.arch }}.tgz
@@ -365,12 +392,12 @@ jobs:
fetch-depth: '0'
ref: '${{ github.ref }}'
- name: Download Release builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: mac-Release-${{ matrix.arch }}
path: builds
- name: Download FastDebug builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: mac-FastDebug-${{ matrix.arch }}
path: builds
@@ -386,7 +413,7 @@ jobs:
ARCH: ${{ matrix.arch }}
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Mac
- name: Upload result package
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ steps.generate_package.outputs.package_name }}
path: ${{ steps.generate_package.outputs.package_path }}
-53
View File
@@ -1,53 +0,0 @@
name: Publish Standalone docker image
on:
push:
tags:
- 'nightly_*'
- 'release_*'
jobs:
build_images:
if: github.repository == 'scp-fs2open/fs2open.github.com'
strategy:
matrix:
configuration: [FastDebug, Release]
include:
- configuration: FastDebug
tag_suffix: -debug
- configuration: Release
tag_suffix: ""
fail-fast: false
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
name: Checkout
with:
submodules: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Docker meta
id: docker_meta
uses: crazy-max/ghaction-docker-meta@v1
with:
images: ghcr.io/scp-fs2open/standalone_server
tag-latest: false
- name: Login to GitHub Docker Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.CR_PAT }}
- name: Build and push
id: docker_build
uses: docker/build-push-action@v2
with:
context: .
file: ./docker/standalone/Dockerfile
push: true
tags: ${{ steps.docker_meta.outputs.tags }}${{ matrix.tag_suffix }}
labels: ${{ steps.docker_meta.outputs.labels }}
build-args: |
build_type=${{ matrix.configuration }}
+30 -18
View File
@@ -15,7 +15,7 @@ jobs:
configuration: [FastDebug, Release]
name: Linux
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/linux_build:sha-5ac6f70
container: ghcr.io/scp-fs2open/linux_build:sha-71099c9
steps:
- uses: actions/checkout@v1
name: Checkout
@@ -30,7 +30,7 @@ jobs:
- name: Configure CMake
env:
CONFIGURATION: ${{ matrix.configuration }}
COMPILER: gcc-5
COMPILER: gcc-9
ENABLE_QTFRED: OFF
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
- name: Compile
@@ -51,7 +51,7 @@ jobs:
CONFIGURATION: ${{ matrix.configuration }}
run: $GITHUB_WORKSPACE/ci/linux/generate_appimage.sh $GITHUB_WORKSPACE/build/install
- name: Upload build result
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: linux-${{ matrix.configuration }}
path: ${{ github.workspace }}/build/install/*.AppImage
@@ -68,12 +68,12 @@ jobs:
fetch-depth: '0'
ref: '${{ github.ref }}'
- name: Download Release builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: linux-Release
path: builds
- name: Download FastDebug builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: linux-FastDebug
path: builds
@@ -96,7 +96,7 @@ jobs:
arch: [Win32, x64]
simd: [SSE2]
name: Windows
runs-on: windows-2019
runs-on: windows-2022
steps:
- uses: actions/checkout@v1
name: Checkout
@@ -133,9 +133,9 @@ jobs:
# cached: ${{ steps.cache-qt-win.outputs.cache-hit }}
# aqtversion: ==0.8
- name: Prepare Vulkan SDK
uses: humbletim/[email protected].0
uses: humbletim/[email protected].1
with:
vulkan-query-version: 1.3.204.0
vulkan-query-version: 1.4.304.1
vulkan-components: Vulkan-Headers, Vulkan-Loader
vulkan-use-cache: true
- name: Configure CMake
@@ -150,13 +150,13 @@ jobs:
if [ "$ARCHITECTURE" = "Win32" ]; then
cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DFSO_USE_SPEECH="ON" \
-DFSO_USE_VOICEREC="ON" -DMSVC_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_USE_VOICEREC="ON" -DFORCED_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_BUILD_QTFRED=OFF -DFSO_BUILD_TESTS=ON \
-DFSO_INSTALL_DEBUG_FILES="ON" -DFSO_BUILD_WITH_VULKAN="OFF" -A "$ARCHITECTURE" \
-G "Visual Studio 16 2019" -T "v142" ..
else
cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DFSO_USE_SPEECH="ON" \
-DFSO_USE_VOICEREC="ON" -DMSVC_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_USE_VOICEREC="ON" -DFORCED_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_BUILD_QTFRED=OFF -DFSO_BUILD_TESTS=ON \
-DFSO_INSTALL_DEBUG_FILES="ON" -A "$ARCHITECTURE" \
-G "Visual Studio 16 2019" -T "v142" ..
@@ -177,7 +177,7 @@ jobs:
shell: bash
run: ./bin/$CONFIGURATION/unittests --gtest_shuffle
- name: Upload build result
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: windows-${{ matrix.configuration }}-${{ matrix.arch }}-${{ matrix.simd }}
path: ${{ github.workspace }}/build/install/*
@@ -198,12 +198,12 @@ jobs:
fetch-depth: '0'
ref: '${{ github.ref }}'
- name: Download Release builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: windows-Release-${{ matrix.arch }}-${{ matrix.simd }}
path: builds
- name: Download FastDebug builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: windows-FastDebug-${{ matrix.arch }}-${{ matrix.simd }}
path: builds
@@ -254,9 +254,9 @@ jobs:
submodules: true
fetch-depth: 0
- name: Prepare Vulkan SDK
uses: humbletim/[email protected].0
uses: humbletim/[email protected].1
with:
vulkan-query-version: 1.3.204.0
vulkan-query-version: 1.4.304.1
vulkan-components: Vulkan-Headers, Vulkan-Loader
vulkan-use-cache: true
- name: Set up test version
@@ -282,13 +282,25 @@ jobs:
ARCH: ${{ matrix.arch }}
XDG_RUNTIME_DIR: /root
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
- name: Sign builds
working-directory: ./build/bin
run: |
# make sure OpenAL framework is signed
find . -name OpenAL -type f | while read xx; do codesign --force -s - $xx; done
find . -name OpenAL.framework -type d | while read xx; do codesign --force -s - $xx; done
# make sure dylibs are signed
find . -name \*.dylib -type f | while read xx; do codesign --force -s - $xx; done
# sign binaries
find . -perm +111 -type f | grep MacOS | while read xx; do codesign --force -s - $xx; done
# sign apps
find . -name \*.app -maxdepth 1 | while read xx; do codesign --force -s - $xx; done
- name: Package build result
working-directory: ./build/bin
# Use GNU tar here (part of runner image) to avoid weird corruption bug with bsdtar
# Ref: https://github.com/actions/runner-images/issues/2619
run: gtar -cvzf macos-build-${{ matrix.configuration }}-${{ matrix.arch }}.tgz *.app
- name: Upload build result
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: mac-${{ matrix.configuration }}-${{ matrix.arch }}
path: ${{ github.workspace }}/build/bin/macos-build-${{ matrix.configuration }}-${{ matrix.arch }}.tgz
@@ -308,12 +320,12 @@ jobs:
fetch-depth: '0'
ref: '${{ github.ref }}'
- name: Download Release builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: mac-Release-${{ matrix.arch }}
path: builds
- name: Download FastDebug builds
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: mac-FastDebug-${{ matrix.arch }}
path: builds
+2 -2
View File
@@ -13,7 +13,7 @@ jobs:
strategy:
matrix:
configuration: [Debug, Release]
compiler: [gcc-5, gcc-13, clang-16]
compiler: [gcc-9, gcc-13, clang-16]
cmake_options: [""]
include:
# Also include configurations that check if the code compiles without the graphics backends
@@ -25,7 +25,7 @@ jobs:
cmake_options: -DFSO_BUILD_WITH_OPENGL=OFF -DFSO_BUILD_WITH_VULKAN=OFF
name: Linux
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/linux_build:sha-5ac6f70
container: ghcr.io/scp-fs2open/linux_build:sha-71099c9
steps:
- uses: actions/checkout@v1
name: Checkout
+15 -9
View File
@@ -10,7 +10,7 @@ jobs:
strategy:
matrix:
configuration: [Debug, Release]
compiler: [gcc-5, gcc-13, clang-16]
compiler: [gcc-9, gcc-13, clang-16]
cmake_options: [""]
include:
# Also include configurations that check if the code compiles without the graphics backends
@@ -20,9 +20,15 @@ jobs:
- configuration: Release
compiler: gcc-13
cmake_options: -DFSO_BUILD_WITH_OPENGL=OFF -DFSO_BUILD_WITH_VULKAN=OFF
- configuration: Debug
compiler: gcc-13
cmake_options: -DFSO_BUILD_WITH_OPENGL=OFF -DFSO_BUILD_WITH_VULKAN=ON
- configuration: Release
compiler: gcc-13
cmake_options: -DFSO_BUILD_WITH_OPENGL=OFF -DFSO_BUILD_WITH_VULKAN=ON
name: Linux
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/linux_build:sha-5ac6f70
container: ghcr.io/scp-fs2open/linux_build:sha-71099c9
steps:
- uses: actions/checkout@v1
name: Checkout
@@ -74,7 +80,7 @@ jobs:
compiler: [MSVC]
arch: [Win32, x64]
name: Windows
runs-on: windows-2019
runs-on: windows-2022
steps:
- name: Prepare Environment
run: choco install ninja
@@ -107,9 +113,9 @@ jobs:
# cached: ${{ steps.cache-qt-win.outputs.cache-hit }}
# aqtversion: ==0.8
- name: Prepare Vulkan SDK
uses: humbletim/[email protected].0
uses: humbletim/[email protected].1
with:
vulkan-query-version: 1.3.204.0
vulkan-query-version: 1.4.304.1
vulkan-components: Vulkan-Headers, Vulkan-Loader
vulkan-use-cache: true
- name: Configure CMake
@@ -133,11 +139,11 @@ jobs:
else
if [ "$ARCHITECTURE" = "Win32" ]; then
cmake -DFSO_USE_SPEECH="ON" -DFSO_FATAL_WARNINGS="ON" -DFSO_USE_VOICEREC="OFF" -DFSO_BUILD_TESTS="ON" \
-DMSVC_SIMD_INSTRUCTIONS=SSE2 -DFSO_BUILD_FRED2="ON" -DFSO_BUILD_WITH_VULKAN="OFF" -G "Visual Studio 16 2019" \
-DFORCED_SIMD_INSTRUCTIONS=SSE2 -DFSO_BUILD_FRED2="ON" -DFSO_BUILD_WITH_VULKAN="OFF" -G "Visual Studio 16 2019" \
-DFSO_BUILD_QTFRED=OFF -T "v142" -A "$ARCHITECTURE" ..
else
cmake -DFSO_USE_SPEECH="ON" -DFSO_FATAL_WARNINGS="ON" -DFSO_USE_VOICEREC="OFF" -DFSO_BUILD_TESTS="ON" \
-DMSVC_SIMD_INSTRUCTIONS=SSE2 -DFSO_BUILD_FRED2="ON" -G "Visual Studio 16 2019" \
-DFORCED_SIMD_INSTRUCTIONS=SSE2 -DFSO_BUILD_FRED2="ON" -G "Visual Studio 16 2019" \
-DFSO_BUILD_QTFRED=OFF -T "v142" -A "$ARCHITECTURE" ..
fi
fi
@@ -202,9 +208,9 @@ jobs:
key: ${{ runner.os }}-${{ matrix.configuration }}-${{ matrix.compiler }}-${{ matrix.arch }}
save: false # Caches are created by a separate job and only restored for PRs
- name: Prepare Vulkan SDK
uses: humbletim/[email protected].0
uses: humbletim/[email protected].1
with:
vulkan-query-version: 1.3.204.0
vulkan-query-version: 1.4.304.1
vulkan-components: Vulkan-Headers, Vulkan-Loader
vulkan-use-cache: true
- name: Configure CMake
+12 -7
View File
@@ -3,12 +3,12 @@ name: Weekly Coverity Scan for Freespace Open
# many thanks for figuring this out first so it could be less painful for us!
#This mode is for testing
on: [push, pull_request]
#on: [push, pull_request]
# In production, push on a specific schedule
#on:
# schedule:
# - cron: "5 0 * * 5" # Run once per a week on Friday morning (midnight UTC, 4 AM EST), to avoid Coverity's submission limits
on:
schedule:
- cron: "5 0 * * 5" # Run once per a week on Friday morning (midnight UTC, 4 AM EST), to avoid Coverity's submission limits
env:
QT_VERSION: 5.12.12
@@ -18,8 +18,9 @@ env:
jobs:
build:
name: Build FSO With Coverity Wrapper
if: github.repository == 'scp-fs2open/fs2open.github.com'
runs-on: ${{ matrix.config.os }}
container: ghcr.io/scp-fs2open/linux_build:sha-5ac6f70
container: ghcr.io/scp-fs2open/linux_build:sha-71099c9
strategy:
fail-fast: false
matrix:
@@ -47,7 +48,7 @@ jobs:
- name: Configure CMake for FSO
env:
CONFIGURATION: Release
compiler: gcc-5
COMPILER: gcc-9
ENABLE_QTFRED: OFF
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
@@ -65,4 +66,8 @@ jobs:
- name: Upload to Coverity
run: |
cd build
curl --form token=${{ env.coverity_token }} --form email=${{ env.coverity_email }} --form file=@cov-scan.tgz --form version="$(git rev-parse HEAD)" --form description="Automatic GHA scan" 'https://scan.coverity.com/builds?project=scp-fs2open/fs2open.github.com'
curl -X POST -d token=${{ env.coverity_token }} -d email=${{ env.coverity_email }} -d file_name="'cov-scan.tgz'" -d version=${{ github.ref }} -d description="Automatic GHA scan" 'https://scan.coverity.com/projects/870/builds/init' | tee response
upload_url=$(jq -r '.url' response)
build_id=$(jq -r '.build_id' response)
curl -X PUT --header 'Content-Type: application/json' --upload-file cov-scan.tgz $upload_url
curl -X PUT -d token=${{ env.coverity_token }} https://scan.coverity.com/projects/870/builds/$build_id/enqueue
+2 -3
View File
@@ -1,7 +1,6 @@
[submodule "cmake/external/rpavlik-cmake-modules"]
path = cmake/external/rpavlik-cmake-modules
url = https://github.com/asarium/cmake-modules.git
url = https://github.com/rpavlik/cmake-modules.git
[submodule "lib/libRocket"]
path = lib/libRocket
url = https://github.com/asarium/libRocket.git
url = https://github.com/scp-fs2open/libRocket.git
+28 -6
View File
@@ -1,5 +1,5 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.4)
CMAKE_MINIMUM_REQUIRED(VERSION 3.9)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# Make sure the source and binary directory are not the sample
@@ -47,11 +47,6 @@ endif()
PROJECT(FS2_Open LANGUAGES ${FSO_LANGUAGES})
IF(CMAKE_CROSSCOMPILING)
SET(IMPORT_EXE_DIR "IMPORT_EXE_DIR-NOTFOUND" CACHE FILEPATH "Required for a cross compiling build, point to binary directory of a cmake build for the real OS")
INCLUDE(${IMPORT_EXE_DIR}/ImportExecutables.cmake)
ENDIF(CMAKE_CROSSCOMPILING)
# Check if the external modules exists
IF(NOT IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/cmake/external/rpavlik-cmake-modules/launcher-templates")
message(FATAL_ERROR "External submodules could not be found. Please make sure you have updated your submodules.")
@@ -122,13 +117,28 @@ option(FSO_RELEASE_LOGGING "Enable logging output for release builds" OFF)
OPTION(FSO_BUILD_WITH_FFMPEG "Enable the usage of FFmpeg for sound and custscenes" ON)
OPTION(FSO_BUILD_WITH_DISCORD "Build with Discord support" ON)
OPTION(FSO_BUILD_WITH_OPENGL "Enable compilation of the OpenGL renderer" ON)
OPTION(FSO_BUILD_WITH_OPENGL_DEBUG "Enables debug option for OpenGL" OFF)
OPTION(FSO_BUILD_WITH_VULKAN "Enable compilation of the Vulkan renderer" OFF)
IF(NOT APPLE)
SET(OPENXR_BUILD_DEFAULT ON)
ELSE()
SET(OPENXR_BUILD_DEFAULT OFF)
ENDIF()
OPTION(FSO_BUILD_WITH_OPENXR "Build with OpenXR support" ${OPENXR_BUILD_DEFAULT})
IF(FSO_BUILD_WITH_OPENXR AND APPLE)
MESSAGE(WARNING "FSO_BUILD_WITH_OPENXR is ON. Not supported on macOS - setting to OFF.")
SET(FSO_BUILD_WITH_OPENXR OFF CACHE BOOL "" FORCE)
ENDIF()
OPTION(FSO_BUILD_WITH_OPENXR_DEBUG "Enables debug option for OpenXR" OFF)
OPTION(FSO_USE_LTO "Build using LTO (only for release builds)" ON)
MARK_AS_ADVANCED(FORCE FSO_CMAKE_DEBUG)
MARK_AS_ADVANCED(FORCE FSO_BUILD_INCLUDED_LIBS)
MARK_AS_ADVANCED(FORCE FSO_USE_OPENALSOFT)
@@ -139,9 +149,11 @@ mark_as_advanced(FORCE FSO_INSTALL_DEBUG_FILES)
mark_as_advanced(FORCE ENABLE_COTIRE)
mark_as_advanced(FORCE FSO_RELEASE_LOGGING)
mark_as_advanced(FORCE FSO_BUILD_WITH_FFMPEG)
mark_as_advanced(FORCE FSO_BUILD_WITH_DISCORD)
mark_as_advanced(FORCE FSO_BUILD_WITH_OPENGL)
mark_as_advanced(FORCE FSO_BUILD_WITH_OPENGL_DEBUG)
mark_as_advanced(FORCE FSO_BUILD_WITH_VULKAN)
mark_as_advanced(FORCE FSO_BUILD_WITH_OPENXR)
mark_as_advanced(FORCE FSO_BUILD_WITH_OPENXR_DEBUG)
# Include cotire file from https://github.com/sakra/cotire/
@@ -164,6 +176,14 @@ endif()
include(clang-tidy)
include(CheckIPOSupported)
check_ipo_supported(RESULT LTO_AVAILABLE)
if (CMAKE_BUILD_TYPE STREQUAL "Release" AND FSO_USE_LTO AND LTO_AVAILABLE)
set(CMAKE_POLICY_DEFAULT_CMP0069 NEW)
message("Enabled LTO")
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
endif (CMAKE_BUILD_TYPE STREQUAL "Release" AND FSO_USE_LTO AND LTO_AVAILABLE)
# This includes source code for some tools, either used in the build or also for something else
ADD_SUBDIRECTORY(tools)
@@ -221,5 +241,7 @@ message(STATUS "Building qtFRED: ${FSO_BUILD_QTFRED}")
message(STATUS "Fatal warnings: ${FSO_FATAL_WARNINGS}")
message(STATUS "Release logging: ${FSO_RELEASE_LOGGING}")
message(STATUS "With FFmpeg: ${FSO_BUILD_WITH_FFMPEG}")
message(STATUS "With Discord: ${FSO_BUILD_WITH_DISCORD}")
message(STATUS "With OpenGL: ${FSO_BUILD_WITH_OPENGL}")
message(STATUS "With Vulkan: ${FSO_BUILD_WITH_VULKAN}")
message(STATUS "With OpenXR: ${FSO_BUILD_WITH_OPENXR}")
+8 -1
View File
@@ -5,6 +5,8 @@ set -e
SCRIPT=$(readlink -f "$0")
HERE=$(dirname "$SCRIPT")
git config --global --add safe.directory "$GITHUB_WORKSPACE"
COMMIT_RANGE=$1..$2
if ! git rev-list $COMMIT_RANGE 2>&1 >/dev/null; then
@@ -16,8 +18,13 @@ fi
# branch
BASE_COMMIT=$(git merge-base $1 $2)
# Note: Manually passing in the Vulkan flags that are normally provided by cmake (but are not so, here), to ensure
# that the source files are checked with the actual configuration used.
echo "Running clang-tidy on changed files"
git diff -U0 --no-color "$BASE_COMMIT..$2" | \
$HERE/clang-tidy-diff.py -path "$(pwd)/build" -p1 \
-extra-arg="-DWITH_VULKAN" \
-extra-arg="-DVULKAN_HPP_DISPATCH_LOADER_DYNAMIC=1" \
-extra-arg="-DVK_NO_PROTOTYPES" \
-regex '(code(?!((\/graphics\/shaders\/compiled)|(\/globalincs\/windebug)))|freespace2|qtfred|test|build|tools)\/.*\.(cpp|h)' \
-clang-tidy-binary /usr/bin/clang-tidy-9 -j$(nproc) -export-fixes "$(pwd)/clang-fixes.yaml"
-clang-tidy-binary /usr/bin/clang-tidy-16 -j$(nproc) -export-fixes "$(pwd)/clang-fixes.yaml"
+4 -7
View File
@@ -1,8 +1,8 @@
#!/usr/bin/env bash
if [ "$COMPILER" = "gcc-5" ]; then
export CC=gcc-5
export CXX=g++-5
if [ "$COMPILER" = "gcc-9" ]; then
export CC=gcc-9
export CXX=g++-9
fi
if [ "$COMPILER" = "gcc-13" ]; then
export CC=gcc-13
@@ -21,16 +21,13 @@ if [ "$RUNNER_OS" = "macOS" ]; then
PLATFORM_CMAKE_OPTIONS="-DFSO_BUILD_WITH_VULKAN=OFF"
export CMAKE_OSX_ARCHITECTURES="$ARCHITECTURE"
else
CXXFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas -static-libstdc++"
CFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
PLATFORM_CMAKE_OPTIONS="-DFSO_BUILD_APPIMAGE=ON"
PLATFORM_CMAKE_OPTIONS="-DFSO_BUILD_APPIMAGE=ON -DFORCED_SIMD_INSTRUCTIONS=SSE2 -DUSE_STATIC_LIBCXX=ON"
fi
CMAKE_OPTIONS="$JOB_CMAKE_OPTIONS"
if [[ "$COMPILER" =~ ^clang.*$ ]]; then
CMAKE_OPTIONS="$CMAKE_OPTIONS -DCLANG_USE_LIBCXX=ON"
# force clang to silently allow -static-libstdc++ flag
CXXFLAGS="$CXXFLAGS -Qunused-arguments"
fi
if [ ! "$CCACHE_PATH" = "" ]; then
+4 -4
View File
@@ -8,11 +8,11 @@ OS="$1"
source $HERE/dist_functions.sh
if [ "$OS" = "Linux" ]; then
tar -cvzf "$(get_package_name)-builds-Linux.tar.gz" *
tar -cvzf "$(get_package_name)-builds-Linux-$ARCH.tar.gz" *
echo "package_path=$(pwd)/$(get_package_name)-builds-Linux.tar.gz" >> $GITHUB_OUTPUT
echo "package_name=$(get_package_name)-builds-Linux.tar.gz" >> $GITHUB_OUTPUT
echo "package_mime=$(file -b --mime-type "$(pwd)/$(get_package_name)-builds-Linux.tar.gz")" >> $GITHUB_OUTPUT
echo "package_path=$(pwd)/$(get_package_name)-builds-Linux-$ARCH.tar.gz" >> $GITHUB_OUTPUT
echo "package_name=$(get_package_name)-builds-Linux-$ARCH.tar.gz" >> $GITHUB_OUTPUT
echo "package_mime=$(file -b --mime-type "$(pwd)/$(get_package_name)-builds-Linux-$ARCH.tar.gz")" >> $GITHUB_OUTPUT
elif [ "$OS" = "Windows" ]; then
7z a -xr'!*.pdb' "$(get_package_name)-builds-$ARCH-$SIMD.zip" "*"
+95 -5
View File
@@ -12,6 +12,61 @@ from subprocess import check_output
MAX_PAGES = 100 # maximum number of PR pages to go through
warnings = 0
label_scores = {
"fred" : 6,
"qtfred" : 6,
"vr" : 6,
"multi" : 6,
"Lab" : 6,
"pilot file" : 6,
"scripting" : 6,
"sexps" : 6,
"ai" : 6,
"controls" : 6,
"HUD" : 6,
"models" : 6,
"sound" : 6,
"graphics" : 6,
"physics" : 6,
"ui" : 6,
"localization / translation" : 6,
"optimization" : 6,
"gameplay" : 5,
"general modding" : 4,
"fix" : 3,
"enhancement" : 2,
"backport" : 1,
"cleanup" : 0
}
label_to_category = {
"fred" : "FRED",
"qtfred" : "QtFRED",
"vr" : "VR",
"multi" : "Multiplayer",
"Lab" : "Lab",
"pilot file" : "Pilot File",
"scripting" : "Scripting",
"sexps" : "SEXPs",
"ai" : "AI",
"controls" : "Controls",
"HUD" : "HUD",
"models" : "Models",
"sound" : "Sound",
"graphics" : "Graphics",
"physics" : "Physics",
"ui" : "UI",
"localization / translation" : "Localization",
"optimization" : "Optimization",
"gameplay" : "Gameplay",
"general modding" : "General Modding",
"fix" : "Fix",
"enhancement" : "Enhancement",
"backport" : "Backport",
"cleanup" : "Cleanup",
"misc" : "Misc."
}
def get_last_page(response: requests.Response) -> int:
"""
@brief Extract the last page number from the response header
@@ -40,7 +95,33 @@ def get_last_page(response: requests.Response) -> int:
return MAX_PAGES
else:
return last_page
def label_score(label):
try:
return label_scores[label['name']]
except KeyError:
return -1
def get_label(labels) -> str:
"""
@brief Get the primary label from a list of labels
@param[in] labels The list of labels from a pull request
@returns The primary label to be used for sorting in the changelog
"""
if len(labels) < 1:
return "misc"
# Sort the labels based on their score and grab the highest valued label
name = sorted(labels, key=label_score, reverse=True)[0]['name']
# If a label couldn't be found, toss it into a miscellaneous bin
if name not in label_scores:
name = "misc"
return name
def main():
parser = argparse.ArgumentParser(description="Retrieves a log of commit messages and attempts to pretty them into a human-readable format")
@@ -138,11 +219,16 @@ def main():
print("Found old pull #{} ({}), stopping loop...".format(pull['number'], pull['updated_at']))
page = last_page + 1
break
# If a label isn't in the changelog, create a bin for it
label = get_label(pull['labels'])
if label not in changelog:
changelog[label] = {}
# Add the pull to the changelog, indexed by its pull.number
if pull['number'] not in changelog:
if pull['number'] not in changelog[label]:
# only add if the key isn't there already
changelog[pull['number']] = {
changelog[label][pull['number']] = {
"date": merge_date,
"title": pull['title'],
"labels": pull['labels'],
@@ -158,9 +244,13 @@ def main():
# 2021-09-28 | (#3661) Fix homing child weapons in niche circumstances
print("Writing to change.log...")
str = ''
for key, value in changelog.items():
str += "{} | (#{}) {} \n".format(value['date'].strftime("%Y-%m-%d"), key, value['title'])
for label, pulls in dict(sorted(changelog.items())).items():
str += "[size=18pt]{}[/size]\n".format(label_to_category[label])
str += "[list]\n"
for key, value in pulls.items():
str += "[li](#{}) {} [/li]\n".format(key, value['title'])
str += "[/list]\n\n"
with open("change.log", "w") as file:
file.write(str)
+9 -5
View File
@@ -7,7 +7,8 @@ import requests
from file_list import ReleaseFile
from util import retry_multi, GLOBAL_TIMEOUT
LINUX_KEY = "Linux"
LINUX_X64_KEY = "Linux-x86_64"
LINUX_ARM64_KEY = "Linux-arm64"
MACOSX_X64_KEY = "Mac-x86_64"
MACOSX_ARM64_KEY = "Mac-arm64"
WIN32_SSE2_KEY = "Win32-SSE2"
@@ -34,7 +35,8 @@ metadata = {
}
platforms = {
LINUX_KEY: 'linux',
LINUX_X64_KEY: 'linux',
LINUX_ARM64_KEY: 'linux',
MACOSX_X64_KEY: 'macosx',
MACOSX_ARM64_KEY: 'macosx',
WIN32_SSE2_KEY: 'windows',
@@ -44,7 +46,8 @@ platforms = {
}
envs = {
LINUX_KEY: 'linux && x86_64', # Linux only has 64bit builds
LINUX_X64_KEY: 'linux && x86_64',
LINUX_ARM64_KEY: 'linux && arm64',
MACOSX_X64_KEY: 'macosx && x86_64',
MACOSX_ARM64_KEY: 'macosx && arm64',
WIN32_SSE2_KEY: 'windows',
@@ -113,7 +116,7 @@ def render_nebula_release(version, stability, files, config):
'filename': dest_fn
})
if group == LINUX_KEY and fn.endswith('.AppImage'):
if group.startswith('Linux') and fn.endswith('.AppImage'):
if 'qtfred' in fn:
if '-FASTDBG' in fn:
label = 'QtFRED Debug'
@@ -127,7 +130,8 @@ def render_nebula_release(version, stability, files, config):
label = None
props = {
"x64": True, # All Linux builds are 64-bit
"arm64": "arm64" in fn,
"x64": "x64" in fn,
"sse2": True, # Linux builds are forced to compile with SSE2 but not AVX
"avx": False,
"avx2": False,
+9 -8
View File
@@ -7,15 +7,15 @@ PLACEHOLDER
[b]Deprecations:[/b]
PLACEHOLDER
Deprecations are a mechanism in FSO where a certain feature or aspect of the engine has changed or is no longer supported. Since this would normally break existing mods we have the mod table feature "[tt]$Target Version:[/tt]" with which a mod can specify what version of FSO it was developed with. The features listed above will be removed or changed when the target version of a mod is at least the version released in this post.
Deprecations are a mechanism in FSO where a certain feature or aspect of the engine has changed or is no longer supported. Since this would normally break existing mods, we have the mod table feature "[tt]$Target Version:[/tt]" with which a mod can specify what version of FSO it was developed with. Any features listed under Deprecations will be removed or changed when the target version of a mod is at least the version released in this post.
[size=5pt]Previous [url=https://www.hard-light.net/forums/index.php?topic=98682.0]23.0.0 Release Thread[/url][/size]
[size=5pt]Previous [url=https://www.hard-light.net/forums/index.php?topic=99015.0]23.2.1 Release Thread[/url][/size]
Launchers, if you don't have one already:
[b]All platforms: [/b] For every day use, we recommend [url=https://www.hard-light.net/forums/index.php?topic=94068.0]Knossos[/url], an integrated solution for downloading and launching mods.
[b]All platforms: [/b] For every day use, we recommend [url=https://knossosnet.github.io/Knossos-Release-Page/]Knossos.NET[/url], an integrated solution for downloading and launching mods.
[hidden=Alternative Launchers]
Cross-platform: [url=https://www.hard-light.net/forums/index.php?topic=89162]wxLauncher 0.12.x Test Build[/url] (ongoing project for a unified launcher, you should upgrade to the latest RC/test build if you have not yet)
Cross-platform: [url=https://www.hard-light.net/forums/index.php?topic=89162]wxLauncher 0.12.x Test Build[/url] (legacy project for a unified launcher)
[b]Important:[/b] For best compatibility with FSO 3.8 and later you should use at least wxLauncher 0.12.
Windows: [url=http://scp.fsmods.net/builds/Launcher55g.zip]Launcher 5.5g[/url] ([url=https://scp.indiegames.us/builds/Launcher55g.zip]Mirror[/url]) ([url=https://www.mediafire.com/?wdvzn7hhhzh418m]Mirror[/url]) Not compatible with Windows 8+, use wxLauncher above
@@ -41,12 +41,13 @@ Linux: [url=https://www.hard-light.net/forums/index.php/topic,53206.0.html]YAL[
[b]What are those SSE, SSE2 and AVX builds I keep seeing everywhere?[/b]
[url=https://www.hard-light.net/forums/index.php?topic=65628.0]Your answer is in this topic.[/url]
Don't want to deal with that? Use [url=https://www.hard-light.net/forums/index.php?topic=94068.0]Knossos[/url] and it will download the best build specifically for your PC!
Don't want to deal with that? Use [url=https://knossosnet.github.io/Knossos-Release-Page/]Knossos.NET[/url] and it will download the best build specifically for your PC!
[/hidden]
[img]https://scp.indiegames.us/img/linux-icon.png[/img] [color=green][size=12pt]Linux 64-bit[/size][/color]
[size=8pt]Compiled with Ubuntu 16.04 LTS 64-bit, GCC 5[/size]
${build(groups["Linux"].mainFile)}
[img]https://scp.indiegames.us/img/linux-icon.png[/img] [color=green][size=12pt]Linux[/size][/color]
[size=8pt]Compiled with Ubuntu 20.04 LTS, GCC 9[/size]
[b]x86_64:[/b] ${build(groups["Linux"].subFiles["x86_64"])}
[b]arm64:[/b] ${build(groups["Linux"].subFiles["arm64"])}
These builds use a mechanism called [url=https://appimage.org/]AppImage[/url] which should allow these builds to run on most Linux distributions. However, we recommend that you compile your own builds which will result in less issues.
Alternatively, if there is a package in your software repository then you should use that. If you are the maintainer of such a package for a distribution then let us know and we will include that here.
+1 -1
View File
@@ -1,3 +1,3 @@
Mako==1.2.2
requests==2.31.0
requests==2.32.0
semantic-version==2.8.5
+36 -14
View File
@@ -2,50 +2,72 @@
#ifdef _WIN32
#include <intrin.h>
// Windows
#define cpuid __cpuid
#define cpuid __cpuidex
#define xgetbv _xgetbv
#else
#include <cstdint>
// GCC Inline Assembly
void cpuid(int CPUInfo[4],int InfoType){
void cpuid(int CPUInfo[4], int InfoType, int SubType){
__asm__ __volatile__ (
"cpuid":
"=a" (CPUInfo[0]),
"=b" (CPUInfo[1]),
"=c" (CPUInfo[2]),
"=d" (CPUInfo[3]) :
"a" (InfoType)
"a" (InfoType),
"c" (SubType)
);
}
uint64_t xgetbv(uint32_t xcr) {
uint32_t lower, higher;
__asm__ __volatile__ (
"xgetbv":
"=a"(lower),
"=d"(higher) :
"c"(xcr)
);
return (static_cast<uint64_t>(higher) << static_cast<uint64_t>(32)) | static_cast<uint64_t>(lower);
}
#endif
#include <iostream>
int main( int argc, char* argv[] )
{
int SSE = false;
int SSE2 = false;
int AVX = false;
int AVX2 = false;
bool SSE = false;
bool SSE2 = false;
bool OSXSAVE = false;
bool AVX = false;
bool AVX2 = false;
int info[4];
cpuid(info, 0);
cpuid(info, 0, 0);
int nIds = info[0];
// Detect Instruction Set
if (nIds >= 1){
cpuid(info,0x00000001);
SSE = (info[3] & ((int)1 << 25)) != 0;
SSE2 = (info[3] & ((int)1 << 26)) != 0;
AVX = (info[2] & ((int)1 << 28)) != 0;
cpuid(info, 0x00000001, 0);
SSE = (info[3] & ((int)1 << 25)) != 0;
SSE2 = (info[3] & ((int)1 << 26)) != 0;
OSXSAVE = (info[2] & ((int)1 << 27)) != 0;
AVX = (info[2] & ((int)1 << 28)) != 0;
}
if (nIds >= 7){
cpuid(info,0x00000007);
cpuid(info,0x00000007, 0);
AVX2 = (info[1] & ((int)1 << 5)) != 0;
}
// Detect OS Support
if (!OSXSAVE || (xgetbv(0) & 0x6) == 0) {
AVX = false;
AVX2 = false;
}
if (AVX2)
std::cout << "AVX2";
else if(AVX)
+16
View File
@@ -24,3 +24,19 @@ set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
if (FSO_BUILD_WITH_DISCORD)
message(WARNING "Discord support is not tested for cross-compilation. Here be dragons! To disable, set -DFSO_BUILD_WITH_DISCORD:BOOL=OFF")
endif()
if (FSO_BUILD_FRED2)
message(WARNING "FRED2 support is not tested for cross-compilation. Here be dragons! To disable, set -DFSO_BUILD_FRED2:BOOL=OFF")
endif()
if (FSO_USE_SPEECH)
message(WARNING "Speech support is not tested for cross-compilation. Here be dragons! To disable, set -DFSO_USE_SPEECH:BOOL=OFF")
endif()
if (FSO_USE_VOICEREC)
message(WARNING "Voice recognition support is not tested for cross-compilation. Here be dragons! To disable, set -DFSO_USE_VOICEREC:BOOL=OFF")
endif()
+11 -1
View File
@@ -97,9 +97,19 @@ function(handle_embedded_files _target)
set(INCLUDE_LIST "${INCLUDE_LIST}\n#include \"${HEADER_FILE}\"")
set(ARRAY_ELEMENTS "${ARRAY_ELEMENTS}\n\t{ \"${_pathType}\", \"${FILE_NAME}\" , ${FIELD_NAME} , ${FIELD_NAME}_size },")
IF(CMAKE_CROSSCOMPILING)
SET(EMBEDFILE_PATH "EMBEDFILE-NOTFOUND" CACHE FILEPATH "Required for a cross compiling build, point to an embedfile of a cmake build for the host OS")
IF(EMBEDFILE_PATH STREQUAL "EMBEDFILE-NOTFOUND")
#This could, possibly, be configured to compile an embedfile using host compilation automatically, but that seems to be a challenge.
message(FATAL_ERROR "A manual embedfile path must be configured for cross compilation. Set EMBEDFILE_PATH to the location of an embedfile executable, found in the build directories for the host OS.")
ENDIF()
ELSE(CMAKE_CROSSCOMPILING)
SET(EMBEDFILE_PATH "embedfile")
ENDIF(CMAKE_CROSSCOMPILING)
add_custom_command(
OUTPUT ${ALL_OUTPUTS}
COMMAND embedfile "${_filePath}" "${_outputBasePath}" "${FIELD_NAME}"
COMMAND ${EMBEDFILE_PATH} "${_filePath}" "${_outputBasePath}" "${FIELD_NAME}"
MAIN_DEPENDENCY "${_filePath}"
COMMENT "Generating string file for ${_filePath}"
)
+27 -4
View File
@@ -8,8 +8,31 @@ else()
set(IS_64BIT FALSE)
endif()
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64|ARM64)")
set(IS_ARM64 TRUE)
set(IS_ARM64 FALSE)
if (NOT "${CMAKE_GENERATOR_PLATFORM}" STREQUAL "") # needed to cover Visual Studio generator
if(CMAKE_GENERATOR_PLATFORM MATCHES "^(aarch64|arm64|ARM64)")
set(IS_ARM64 TRUE)
endif()
else()
set(IS_ARM64 FALSE)
endif()
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64|ARM64)")
set(IS_ARM64 TRUE)
endif()
endif()
set(IS_RISCV FALSE)
if (NOT "${CMAKE_GENERATOR_PLATFORM}" STREQUAL "") # needed to cover Visual Studio generator
if(CMAKE_GENERATOR_PLATFORM MATCHES "^(riscv64|RISCV64|riscv32|RISCV32)")
set(IS_RISCV TRUE)
endif()
else()
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(riscv64|RISCV64|riscv32|RISCV32)")
set(IS_RISCV TRUE)
endif()
endif()
set(IS_X86 FALSE)
if (NOT IS_ARM64 AND NOT IS_RISCV)
set(IS_X86 TRUE)
endif()
+2 -1
View File
@@ -11,7 +11,8 @@ endif()
target_link_libraries(platform INTERFACE ${COCOA_LIBRARY})
SET(CMAKE_OSX_DEPLOYMENT_TARGET "10.9")
# To support C++17 we need to target at least 10.13. maybe 10.14 for some rare features
SET(CMAKE_OSX_DEPLOYMENT_TARGET "10.13")
SET(CMAKE_SKIP_RPATH FALSE)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
+1
View File
@@ -10,6 +10,7 @@
#cmakedefine01 IS_64BIT
#cmakedefine01 IS_ARM64
#cmakedefine01 IS_RISCV
#cmakedefine01 SCP_HAVE_STRCASECMP
#cmakedefine01 SCP_HAVE_STRNCASECMP
+1 -1
View File
@@ -13,6 +13,6 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated -Wno-char-subscripts")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcolor-diagnostics")
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -Wno-unused-variable -Wno-unused-parameter")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -Wno-unused-variable -Wno-unused-parameter")
set(CMAKE_CXX_FLAGS_DEBUG "-Og -g -Wshadow")
+38 -9
View File
@@ -10,8 +10,41 @@ option(CLANG_ENABLE_ADDRESS_SANITIZER "Enable -fsanitize=address" OFF)
option(CLANG_USE_LIBCXX "Use libc++" OFF)
# These are the default values
set(C_BASE_FLAGS "-march=native -pipe")
set(CXX_BASE_FLAGS "-march=native -pipe")
set(C_BASE_FLAGS "-pipe")
set(CXX_BASE_FLAGS "-pipe")
if(IS_X86)
if(FORCED_NATIVE_SIMD_INSTRUCTIONS)
set(CLANG_EXTENSIONS "-march=native")
elseif (FSO_INSTRUCTION_SET STREQUAL "")
set(CLANG_EXTENSIONS "-march=x86-64")
elseif (FSO_INSTRUCTION_SET STREQUAL "SSE")
set(CLANG_EXTENSIONS "-march=x86-64 -msse -mfpmath=sse")
elseif (FSO_INSTRUCTION_SET STREQUAL "SSE2")
set(CLANG_EXTENSIONS "-march=x86-64 -msse -msse2 -mfpmath=sse")
elseif (FSO_INSTRUCTION_SET STREQUAL "AVX")
set(CLANG_EXTENSIONS "-march=x86-64-v2 -msse -msse2 -mavx -mfpmath=sse")
elseif (FSO_INSTRUCTION_SET STREQUAL "AVX2")
set(CLANG_EXTENSIONS "-march=x86-64-v3 -msse -msse2 -mavx -mavx2 -mfpmath=sse")
else ()
message( FATAL_ERROR "Unknown instruction set encountered for clang. Update toolchain-clang.cmake!" )
endif()
set(C_BASE_FLAGS "${C_BASE_FLAGS} ${CLANG_EXTENSIONS}")
set(CXX_BASE_FLAGS "${CXX_BASE_FLAGS} ${CLANG_EXTENSIONS}")
elseif(IS_ARM)
if(FORCED_NATIVE_SIMD_INSTRUCTIONS)
set(C_BASE_FLAGS "${C_BASE_FLAGS} -march=native")
set(CXX_BASE_FLAGS "${CXX_BASE_FLAGS} -march=native")
endif ()
elseif(IS_RISCV)
# Default C/CXX_BASE_FLAGS are fine for RISC-V
endif()
if (USE_STATIC_LIBCXX)
set(CXX_BASE_FLAGS "${CXX_BASE_FLAGS} -static-libstdc++ -Qunused-arguments")
set(CLANG_USE_LIBCXX ON)
endif()
# For C and C++, the values can be overwritten independently
if(DEFINED ENV{CXXFLAGS})
@@ -35,10 +68,6 @@ set(COMPILER_FLAGS "${COMPILER_FLAGS} ${_flags}")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -fsigned-char -Wno-unknown-pragmas")
# Omit "argument unused during compilation" when clang is used with ccache.
if(${CMAKE_CXX_COMPILER} MATCHES "ccache")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Qunused-arguments")
endif()
if ("${CMAKE_GENERATOR}" STREQUAL "Ninja")
# Force color diagnostics for Ninja generator
@@ -87,16 +116,16 @@ endif()
string(REGEX MATCH "-O[a-zA-Z|0-9]+" CXX_OPT_FLAG ${CXX_BASE_FLAGS})
string(REGEX MATCH "-O[a-zA-Z|0-9]+" C_OPT_FLAG ${C_BASE_FLAGS})
# If no user-set opt flag, set -O2 and -Og
# If no user-set opt flag, set -O3 and -Og
if ("${CXX_OPT_FLAG}" STREQUAL "")
set(CXX_OPT_FLAG_RELEASE "-O2")
set(CXX_OPT_FLAG_RELEASE "-O3")
set(CXX_OPT_FLAG_DEBUG "-Og")
else()
set(CXX_OPT_FLAG_RELEASE "${CXX_OPT_FLAG}")
set(CXX_OPT_FLAG_DEBUG "${CXX_OPT_FLAG}")
endif()
if ("${C_OPT_FLAG}" STREQUAL "")
set(C_OPT_FLAG_RELEASE "-O2")
set(C_OPT_FLAG_RELEASE "-O3")
set(C_OPT_FLAG_DEBUG "-Og")
else()
set(C_OPT_FLAG_RELEASE "${C_OPT_FLAG}")
+46 -5
View File
@@ -12,8 +12,49 @@ option(GCC_USE_GOLD "Use the gold linker instead of the standard linker" OFF)
option(GCC_GENERATE_GDB_INDEX "Adds linker option to generate the gdb index for debug builds" OFF)
# These are the default values
set(C_BASE_FLAGS "-march=native -pipe")
set(CXX_BASE_FLAGS "-march=native -pipe")
set(C_BASE_FLAGS "-pipe")
set(CXX_BASE_FLAGS "-pipe")
if(IS_X86)
if(FORCED_NATIVE_SIMD_INSTRUCTIONS)
set(GCC_EXTENSIONS "-march=native")
elseif (FSO_INSTRUCTION_SET STREQUAL "")
set(GCC_EXTENSIONS "-march=x86-64")
elseif (FSO_INSTRUCTION_SET STREQUAL "SSE")
set(GCC_EXTENSIONS "-march=x86-64 -msse -mfpmath=sse")
elseif (FSO_INSTRUCTION_SET STREQUAL "SSE2")
set(GCC_EXTENSIONS "-march=x86-64 -msse -msse2 -mfpmath=sse")
elseif (FSO_INSTRUCTION_SET STREQUAL "AVX")
set(GCC_EXTENSIONS "-march=x86-64-v2 -msse -msse2 -mavx -mfpmath=sse")
elseif (FSO_INSTRUCTION_SET STREQUAL "AVX2")
set(GCC_EXTENSIONS "-march=x86-64-v3 -msse -msse2 -mavx -mavx2 -mfpmath=sse")
else ()
message( FATAL_ERROR "Unknown instruction set encountered for GCC. Update toolchain-gcc.cmake!" )
endif()
set(C_BASE_FLAGS "${C_BASE_FLAGS} ${GCC_EXTENSIONS}")
set(CXX_BASE_FLAGS "${CXX_BASE_FLAGS} ${GCC_EXTENSIONS}")
if (IS_64BIT)
set(C_BASE_FLAGS "${C_BASE_FLAGS} -m64")
set(CXX_BASE_FLAGS "${CXX_BASE_FLAGS} -m64")
endif()
elseif(IS_ARM)
if(FORCED_NATIVE_SIMD_INSTRUCTIONS)
set(C_BASE_FLAGS "${C_BASE_FLAGS} -march=native")
set(CXX_BASE_FLAGS "${CXX_BASE_FLAGS} -march=native")
endif ()
elseif(IS_RISCV)
# You do not need to pass a -march, passing nothing will make gcc to choose itself.
# If you want a specific set of instructions like vectors, set -march in CFLAGS and CXXFLAGS env variables
# Example for vectors: -march=rv64gcv
# https://gcc.gnu.org/onlinedocs/gcc/RISC-V-Options.html
# As such, default C/CXX_BASE_FLAGS are sufficient.
endif()
if (USE_STATIC_LIBCXX)
set(CXX_BASE_FLAGS "${CXX_BASE_FLAGS} -static-libstdc++")
endif()
# For C and C++, the values can be overwritten independently
if(DEFINED ENV{CFLAGS})
@@ -117,16 +158,16 @@ endif()
string(REGEX MATCH "-O[a-zA-Z|0-9]+" CXX_OPT_FLAG ${CXX_BASE_FLAGS})
string(REGEX MATCH "-O[a-zA-Z|0-9]+" C_OPT_FLAG ${C_BASE_FLAGS})
# If no user-set opt flag, set -O2 and -Og
# If no user-set opt flag, set -O3 and -Og
if ("${CXX_OPT_FLAG}" STREQUAL "")
set(CXX_OPT_FLAG_RELEASE "-O2")
set(CXX_OPT_FLAG_RELEASE "-O3")
set(CXX_OPT_FLAG_DEBUG "-Og")
else()
set(CXX_OPT_FLAG_RELEASE "${CXX_OPT_FLAG}")
set(CXX_OPT_FLAG_DEBUG "${CXX_OPT_FLAG}")
endif()
if ("${C_OPT_FLAG}" STREQUAL "")
set(C_OPT_FLAG_RELEASE "-O2")
set(C_OPT_FLAG_RELEASE "-O3")
set(C_OPT_FLAG_DEBUG "-Og")
else()
set(C_OPT_FLAG_RELEASE "${C_OPT_FLAG}")
+25 -39
View File
@@ -46,9 +46,13 @@ target_compile_options(compiler INTERFACE ${WARNING_FLAGS})
set(CMAKE_C_FLAGS "/MP /GS- /analyze- /Zc:wchar_t /errorReport:prompt /Zc:forScope /Gd /EHsc /nologo /Zm200")
set(CMAKE_CXX_FLAGS "/MP /GS- /analyze- /Zc:wchar_t /errorReport:prompt /Zc:forScope /Gd /EHsc /nologo /Zm200")
set(CMAKE_EXE_LINKER_FLAGS "/MANIFEST /DYNAMICBASE:NO /SAFESEH:NO /ERRORREPORT:PROMPT /NOLOGO")
set(CMAKE_EXE_LINKER_FLAGS "/MANIFEST /SAFESEH:NO /ERRORREPORT:PROMPT /NOLOGO")
set(CMAKE_STATIC_LINKER_FLAGS "")
if(NOT IS_ARM64)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DYNAMICBASE:NO")
endif()
# Release
set(CMAKE_C_FLAGS_RELEASE "/GL /Gy- /Ox /Ot /Ob2 /fp:precise /GF /Oy /Oi /Zi /W3")
set(CMAKE_CXX_FLAGS_RELEASE "/GL /Gy- /Ox /Ot /Ob2 /fp:precise /GF /Oy /Oi /Zi /W3")
@@ -91,49 +95,31 @@ ENDIF(MSVC_USE_RUNTIME_DLL)
INCLUDE(MSVCMultipleProcessCompile)
# Visual Studio supports compiling for multiple vector instruction sets
SET(POSSIBLE_INSTUCTION_SETS "" SSE SSE2 AVX AVX2)
if (NOT DEFINED MSVC_SIMD_INSTRUCTIONS)
detect_simd_instructions(MSVC_DETECTED_SIMD_INSTRUCTIONS)
if(IS_X86)
if(FORCED_NATIVE_SIMD_INSTRUCTIONS)
# MSVC has no direct -march=native equivalent, so just use the detected extensions.
SET(FSO_INSTRUCTION_SET ${DETECTED_SIMD_INSTRUCTIONS})
endif()
SET(MSVC_SIMD_INSTRUCTIONS "${MSVC_DETECTED_SIMD_INSTRUCTIONS}" CACHE FILEPATH "The SIMD instructions which will be used, possible values are ${POSSIBLE_INSTUCTION_SETS}")
MARK_AS_ADVANCED(FORCE MSVC_SIMD_INSTRUCTIONS)
endif()
set(FSO_INSTRUCTION_SET ${MSVC_SIMD_INSTRUCTIONS})
if(FSO_INSTRUCTION_SET STREQUAL "")
set(MSVC_SIMD_INSTRUCTIONS "IA32")
else()
set(MSVC_SIMD_INSTRUCTIONS ${FSO_INSTRUCTION_SET})
endif()
LIST(FIND POSSIBLE_INSTUCTION_SETS "${MSVC_SIMD_INSTRUCTIONS}" SET_INDEX)
if (NOT (IS_64BIT AND (MSVC_SIMD_INSTRUCTIONS STREQUAL "IA32" OR MSVC_SIMD_INSTRUCTIONS STREQUAL "SSE" OR MSVC_SIMD_INSTRUCTIONS STREQUAL "SSE2")))
# 32-Bit and SSE(2) mustn't be set, as these are implied in x86_64 and thus MSVC does not support it for the /arch argument
CHECK_CXX_COMPILER_FLAG("/arch:${MSVC_SIMD_INSTRUCTIONS}" COMPILER_SUPPORTS_ARCH)
if (SET_INDEX LESS 0)
MESSAGE(STATUS "An invalid instruction set was specified, defaulting to no special compiler options.")
else()
IF (NOT SET_INDEX EQUAL 0)
SET(FOUND)
IF(COMPILER_SUPPORTS_ARCH)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /arch:${MSVC_SIMD_INSTRUCTIONS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:${MSVC_SIMD_INSTRUCTIONS}")
ELSE()
message( FATAL_ERROR "Your version of MSVC does not support the requested instruction set. Consider updating!" )
ENDIF()
endif()
FOREACH(list_index RANGE ${SET_INDEX} 1)
list(GET POSSIBLE_INSTUCTION_SETS ${list_index} _simd_set)
CHECK_CXX_COMPILER_FLAG("/arch:${_simd_set}" COMPILER_SUPPORTS_ARCH_${_simd_set})
IF(COMPILER_SUPPORTS_ARCH_${_simd_set})
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /arch:${_simd_set}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:${_simd_set}")
SET(FOUND TRUE)
BREAK()
ENDIF()
ENDFOREACH(list_index)
IF(NOT FOUND)
# Don't set anything, it will likely not work
MESSAGE(STATUS "Your compiler does not support any optimization flags, defaulting to none")
ENDIF(NOT FOUND)
ELSE()
CHECK_CXX_COMPILER_FLAG("/arch:IA32" COMPILER_SUPPORTS_ARCH_IA32)
IF(COMPILER_SUPPORTS_ARCH_IA32)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /arch:IA32")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:IA32")
ENDIF(COMPILER_SUPPORTS_ARCH_IA32)
ENDIF()
endif()
target_compile_definitions(compiler INTERFACE _CRT_SECURE_NO_DEPRECATE _CRT_SECURE_NO_WARNINGS _SECURE_SCL=0 NOMINMAX
+49
View File
@@ -5,6 +5,55 @@ add_library(compiler INTERFACE)
target_compile_definitions(compiler INTERFACE "$<$<CONFIG:Release>:NDEBUG>;$<$<CONFIG:Debug>:_DEBUG>;$<$<CONFIG:FastDebug>:_DEBUG>")
set(FORCED_NATIVE_SIMD_INSTRUCTIONS ON CACHE BOOL "Override instruction set detection and compile with the maximum possible instructions for the current system.")
IF(IS_X86)
SET(POSSIBLE_INSTRUCTION_SETS "" SSE SSE2 AVX AVX2)
if (CMAKE_CROSSCOMPILING)
message("Cross-Compile cannot detect supported instruction sets. Defaulting to SSE2. Disabling host-optimization.")
set(FORCED_NATIVE_SIMD_INSTRUCTIONS OFF)
set(DETECTED_SIMD_INSTRUCTIONS SSE2)
else()
detect_simd_instructions(DETECTED_SIMD_INSTRUCTIONS)
endif()
set(FORCED_SIMD_INSTRUCTIONS "" CACHE STRING "Overrides any instruction set settings (including forced-native). Any of ${POSSIBLE_INSTRUCTION_SETS}.")
if (NOT FORCED_SIMD_INSTRUCTIONS STREQUAL "")
set(FORCED_NATIVE_SIMD_INSTRUCTIONS OFF)
LIST(FIND POSSIBLE_INSTRUCTION_SETS "${FORCED_SIMD_INSTRUCTIONS}" SET_INDEX)
if (SET_INDEX LESS 0)
MESSAGE(STATUS "An invalid instruction set was specified, defaulting to no special compiler options.")
set(FSO_INSTRUCTION_SET "")
else ()
LIST(FIND POSSIBLE_INSTRUCTION_SETS "${DETECTED_SIMD_INSTRUCTIONS}" SET_INDEX)
if (SET_INDEX LESS 0)
MESSAGE(STATUS "An instruction set was specified which is unsupported on this platform. Compiled binary might not be executable.")
endif()
set(FSO_INSTRUCTION_SET ${FORCED_SIMD_INSTRUCTIONS})
endif()
else()
SET(FSO_INSTRUCTION_SET ${DETECTED_SIMD_INSTRUCTIONS})
endif()
MESSAGE(STATUS "Using instruction set level ${FSO_INSTRUCTION_SET}. Optimizations for host-system specifically: ${FORCED_NATIVE_SIMD_INSTRUCTIONS}.")
if (FSO_INSTRUCTION_SET STREQUAL "SSE")
add_compile_definitions(FSO_SIMD_SSE)
elseif (FSO_INSTRUCTION_SET STREQUAL "SSE2")
add_compile_definitions(FSO_SIMD_SSE)
add_compile_definitions(FSO_SIMD_SSE2)
elseif (FSO_INSTRUCTION_SET STREQUAL "AVX")
add_compile_definitions(FSO_SIMD_SSE)
add_compile_definitions(FSO_SIMD_SSE2)
add_compile_definitions(FSO_SIMD_AVX)
elseif (FSO_INSTRUCTION_SET STREQUAL "AVX2")
add_compile_definitions(FSO_SIMD_SSE)
add_compile_definitions(FSO_SIMD_SSE2)
add_compile_definitions(FSO_SIMD_AVX)
add_compile_definitions(FSO_SIMD_AVX2)
endif()
ENDIF()
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
include(toolchain-gcc)
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
+8 -2
View File
@@ -6,7 +6,7 @@ if (EXISTS "${PROJECT_SOURCE_DIR}/version_override.cmake")
include("${PROJECT_SOURCE_DIR}/version_override.cmake")
endif()
set_if_not_defined(FSO_VERSION_MAJOR 23)
set_if_not_defined(FSO_VERSION_MAJOR 24)
set_if_not_defined(FSO_VERSION_MINOR 3)
set_if_not_defined(FSO_VERSION_BUILD 0)
@@ -35,7 +35,13 @@ ELSE()
SET(FSO_BINARY_SUFFIX "${FSO_VERSION_MAJOR}_${FSO_VERSION_MINOR}_${FSO_VERSION_BUILD}_${FSO_VERSION_REVISION_STR}")
ENDIF()
IF(IS_ARM64)
IF(IS_RISCV)
IF(IS_64BIT)
SET(FSO_BINARY_SUFFIX "${FSO_BINARY_SUFFIX}_riscv64")
ELSE()
SET(FSO_BINARY_SUFFIX "${FSO_BINARY_SUFFIX}_riscv32")
ENDIF()
ELSEIF(IS_ARM64)
SET(FSO_BINARY_SUFFIX "${FSO_BINARY_SUFFIX}_arm64")
ELSEIF(IS_64BIT)
# This is a 64-bit builds
+12 -11
View File
@@ -6,7 +6,7 @@ INCLUDE(voice_rec.cmake)
ADD_LIBRARY(code STATIC ${source_files} ${VOICE_REC_FILES})
target_compile_features(code PUBLIC cxx_std_11)
target_compile_features(code PUBLIC cxx_std_17)
if (MSVC)
target_compile_definitions(code PUBLIC "PDB_DEBUGGING=1")
@@ -25,7 +25,11 @@ if (FSO_BUILD_WITH_OPENGL)
endif()
endif()
if(FSO_BUILD_WITH_OPENXR_DEBUG)
if(FSO_BUILD_WITH_OPENXR)
add_definitions(-DFS_OPENXR)
endif()
if(FSO_BUILD_WITH_OPENXR_DEBUG AND FSO_BUILD_WITH_OPENXR)
add_definitions(-DFS_OPENXR_DEBUG)
endif()
@@ -48,7 +52,10 @@ TARGET_LINK_LIBRARIES(code PUBLIC compiler)
target_link_libraries(code PUBLIC md5)
target_link_libraries(code PUBLIC discord-rpc)
if (FSO_BUILD_WITH_DISCORD)
target_link_libraries(code PUBLIC discord-rpc)
add_definitions(-DWITH_DISCORD)
endif()
target_link_libraries(code PUBLIC libRocket)
@@ -67,19 +74,13 @@ ENDIF(FSO_USE_SPEECH)
TARGET_LINK_LIBRARIES(code PUBLIC jansson)
target_link_libraries(code PUBLIC variant)
target_link_libraries(code PUBLIC any)
target_link_libraries(code PUBLIC optional)
target_link_libraries(code PUBLIC anl)
target_link_libraries(code PUBLIC hidapi::hidapi)
target_link_libraries(code PUBLIC imgui)
IF(NOT APPLE)
IF(FSO_BUILD_WITH_OPENXR)
target_link_libraries(code PUBLIC OpenXR::openxr_loader)
target_include_directories(code PUBLIC OpenXR::Headers)
ENDIF()
@@ -139,4 +140,4 @@ set_target_properties(code PROPERTIES XCODE_ATTRIBUTE_STRIP_INSTALLED_PRODUCT[va
set_target_properties(code PROPERTIES XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN[variant=Debug] "NO")
# Prevent GCC warnings in third-party BitOp... see GitHub #4366
suppress_file_warnings(scripting/lua/bitop/bit.c)
suppress_file_warnings(scripting/lua/bitop/bit.c)
+1 -1
View File
@@ -47,7 +47,7 @@ ProgramInstance::ProgramInstance(const actions::Program* program) : _program(pro
ProgramState ProgramInstance::step()
{
if (!_locals.host.IsValid()) {
if (!_locals.host.isValid()) {
return ProgramState::Done;
}
+3 -3
View File
@@ -122,9 +122,9 @@ class ExpressionBuilderVisitor : public ActionExpressionVisitor {
}
antlrcpp::Any visitVec3d_constructor(ActionExpressionParser::Vec3d_constructorContext* context) override
{
auto xExpression = visit(context->expression(0)).as<std::shared_ptr<nodes::AbstractExpression>>();
auto yExpression = visit(context->expression(1)).as<std::shared_ptr<nodes::AbstractExpression>>();
auto zExpression = visit(context->expression(2)).as<std::shared_ptr<nodes::AbstractExpression>>();
const auto xExpression = visit(context->expression(0)).as<std::shared_ptr<nodes::AbstractExpression>>();
const auto yExpression = visit(context->expression(1)).as<std::shared_ptr<nodes::AbstractExpression>>();
const auto zExpression = visit(context->expression(2)).as<std::shared_ptr<nodes::AbstractExpression>>();
auto expression = std::make_shared<nodes::VectorConstructorExpression>(context->L_PAREN()->getSymbol(),
xExpression,
+4 -4
View File
@@ -2,7 +2,7 @@
#include "globalincs/pstypes.h"
#include <mpark/variant.hpp>
#include <variant>
namespace actions {
namespace expression {
@@ -85,10 +85,10 @@ class Value {
if (currentType == expectedType) {
// No conversion necessary
return mpark::get<T>(m_value);
return std::get<T>(m_value);
}
return mpark::visit(detail::implicit_conversion<T>{}, m_value);
return std::visit(detail::implicit_conversion<T>{}, m_value);
}
friend bool operator==(const Value& lhs, const Value& rhs);
@@ -97,7 +97,7 @@ class Value {
friend std::ostream& operator<<(std::ostream& os, const Value& value);
private:
mpark::variant<mpark::monostate, int, float, vec3d, SCP_string> m_value;
std::variant<std::monostate, int, float, vec3d, SCP_string> m_value;
};
} // namespace expression
+3 -5
View File
@@ -26,10 +26,8 @@ ActionResult MoveToSubmodel::execute(ProgramLocals& locals) const
// The calling code should ensure that this never happens
Assertion(locals.hostSubobject >= 0, "Did not have a valid host subobject.");
auto instance = object_get_model_instance(locals.host.objp);
Assertion(instance != -1, "Model instances are required if a host subobject is specified.");
auto pmi = model_get_instance(instance);
auto pmi = object_get_model_instance(locals.host.objp());
Assertion(pmi != nullptr, "Model instances are required if a host subobject is specified.");
auto pm = model_get(pmi->model_num);
const auto destinationSubObject = m_subObjectExpression.execute(locals.variables);
@@ -57,7 +55,7 @@ ActionResult MoveToSubmodel::execute(ProgramLocals& locals) const
// We need to do a linear search for the right subobject
for (int i = 0; i < pm->n_models; ++i) {
const auto submodel = pm->submodel[i];
const auto& submodel = pm->submodel[i];
if (subsystem_stricmp(destinationSubObject.c_str(), submodel.name) == 0) {
// Found something!
+8 -8
View File
@@ -3,6 +3,8 @@
#include "math/vecmat.h"
#include "parse/parselo.h"
#include "particle/hosts/EffectHostObject.h"
#include "particle/ParticleManager.h"
#include "ship/ship.h"
#include <utility>
@@ -37,10 +39,8 @@ ActionResult ParticleEffectAction::execute(ProgramLocals& locals) const
vec3d local_pos;
matrix local_orient;
if (locals.hostSubobject != -1) {
auto instance = object_get_model_instance(locals.host.objp);
Assertion(instance != -1, "Model instances are required if a host subobject is specified.");
auto pmi = model_get_instance(instance);
auto pmi = object_get_model_instance(locals.host.objp());
Assertion(pmi != nullptr, "Model instances are required if a host subobject is specified.");
auto pm = model_get(pmi->model_num);
model_instance_local_to_global_point_orient(&local_pos,
@@ -58,11 +58,11 @@ ActionResult ParticleEffectAction::execute(ProgramLocals& locals) const
local_pos += locals.variables.getValue({"locals", "position"}).getVector();
auto direction = locals.variables.getValue({"locals", "direction"}).getVector();
matrix orientation;
vm_vector_2_matrix_norm(&orientation, &direction); // direction is normalized in SetDirectionAction::execute
source.moveToObject(locals.host.objp, &local_pos);
source.setOrientationFromNormalizedVec(&direction, true);
source.finish();
source->setHost(make_unique<EffectHostObject>(locals.host.objp(), local_pos, orientation, true));
source->finishCreation();
return ActionResult::Finished;
}
@@ -2,7 +2,6 @@
#include "actions/Action.h"
#include "actions/expression/ActionExpression.h"
#include "particle/ParticleManager.h"
namespace actions {
namespace types {
+4 -6
View File
@@ -26,10 +26,8 @@ ActionResult PlaySoundAction::execute(ProgramLocals& locals) const
vec3d local_pos;
matrix local_orient;
if (locals.hostSubobject != -1) {
auto instance = object_get_model_instance(locals.host.objp);
Assertion(instance != -1, "Model instances are required if a host subobject is specified.");
auto pmi = model_get_instance(instance);
auto pmi = object_get_model_instance(locals.host.objp());
Assertion(pmi != nullptr, "Model instances are required if a host subobject is specified.");
auto pm = model_get(pmi->model_num);
model_instance_local_to_global_point_orient(&local_pos,
@@ -47,8 +45,8 @@ ActionResult PlaySoundAction::execute(ProgramLocals& locals) const
local_pos += locals.variables.getValue({"locals", "position"}).getVector();
vec3d global_pos;
vm_vec_unrotate(&global_pos, &local_pos, &locals.host.objp->orient);
global_pos += locals.host.objp->pos;
vm_vec_unrotate(&global_pos, &local_pos, &locals.host.objp()->orient);
global_pos += locals.host.objp()->pos;
const auto soundId = gamesnd_get_by_name(m_soundIdExpression.execute(locals.variables).c_str());
+14 -12
View File
@@ -36,7 +36,7 @@ typedef struct ai_flag_name {
typedef struct ai_flag_description {
AI::AI_Flags flag;
SCP_string flag_desc;
const char *flag_desc;
} ai_flag_description;
extern ai_flag_name Ai_flag_names[];
@@ -96,6 +96,7 @@ extern const int Num_ai_flag_names;
#define MAX_ENEMY_DISTANCE 2500.0f // Maximum distance from which a ship will pursue an enemy.
#define MAX_AI_GOALS 5
#define AI_ACTIVE_GOAL_NONE -1
#define AI_ACTIVE_GOAL_DYNAMIC 999
typedef struct ai_class {
@@ -276,8 +277,8 @@ typedef struct ai_info {
int ai_class; // Class. Might be override of default.
// Probably become obsolete, to be replaced by path_start, path_cur, etc.
waypoint_list *wp_list; // waypoint list being followed
int wp_index; // waypoint index in list
int wp_list_index; // index of waypoint list being followed
int wp_index; // index of waypoint in list
int wp_flags; // waypoint flags, see WPF_xxxx
int waypoint_speed_cap; // -1 no cap, otherwise cap - changed to int by Goober5000
@@ -317,7 +318,7 @@ typedef struct ai_info {
//Unlike the predicted position stuff, also takes into account velocity
//Only used against small ships
fix next_aim_pos_time;
vec3d last_aim_enemy_pos;
vec3d last_aim_enemy_pos; // Normally this is the position of the enemy a turret is targeting but in the F3 Lab, this is used to pass raw target coordinates to the turret firing methods.
vec3d last_aim_enemy_vel;
ai_goal goals[MAX_AI_GOALS];
@@ -329,7 +330,7 @@ typedef struct ai_info {
float time_enemy_near; // SUSHI: amount of time enemy continuously "near" the player
fix last_attack_time; // Missiontime of last time this ship attacked its enemy.
fix last_hit_time; // Missiontime of last time this ship was hit by anyone.
int last_hit_quadrant; // Shield section of last hit.
int danger_shield_quadrant; // Shield section AI will prefer to prioritize for recharging, it if possible.
fix last_hit_target_time; // Missiontime of last time this ship successfully hit target.
int hitter_objnum; // Object index of ship that hit this ship last time.
int hitter_signature; // Signature of hitter. Prevents stupidity if hitter gets killed.
@@ -484,7 +485,7 @@ typedef struct {
#define SUBSYS_PATH_DIST 500.0f
// Friendly damage defines
#define MAX_BURST_DAMAGE 20 // max damage that can be done in BURST_DURATION
#define MAX_BURST_DAMAGE 20.0f // max damage that can be done in BURST_DURATION
#define BURST_DURATION 500 // decay time over which Player->damage_this_burst falls from MAX_BURST_DAMAGE to 0
extern int Mission_all_attack; // !0 means all teams attack all teams.
@@ -533,8 +534,8 @@ extern void ai_ignore_wing(object *ignorer, int wingnum);
extern void ai_dock_with_object(object *docker, int docker_index, object *dockee, int dockee_index, int dock_type);
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, int start_index);
extern void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hit_normal);
extern void ai_start_waypoints(object *objp, int wl_index, int wp_flags, int start_index, bool force = false);
extern void ai_ship_hit(object *objp_ship, object *hit_objp, const vec3d *hit_normal);
extern void ai_ship_destroy(int shipnum);
extern vec3d ai_get_acc_limit(vec3d* vel_limit, const object* objp);
extern void ai_turn_towards_vector(const vec3d *dest, object *objp, const vec3d *slide_vec, const vec3d *rel_pos, float bank_override, int flags, const vec3d *rvec = nullptr, const vec3d* turnrate_mod = nullptr);
@@ -597,11 +598,12 @@ extern void set_predicted_enemy_pos(vec3d *predicted_enemy_pos, object *pobjp, v
extern int is_instructor(object *objp);
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);
float ai_get_weapon_speed(const ship_weapon *swp);
void set_predicted_enemy_pos_turret(vec3d *predicted_enemy_pos, const vec3d *gun_pos, const object *pobjp, const vec3d *enemy_pos, const vec3d *enemy_vel, float weapon_speed, float time_enemy_in_range);
// function to change rearm status for ai ships (called from sexpression code)
extern void ai_set_rearm_status( int team, int new_status );
extern void ai_set_good_rearm_time( int team, int time );
extern void ai_set_bad_rearm_time(int team, int time);
extern void ai_good_secondary_time( int team, int weapon_index, int num_weapons, const char *shipname );
extern void ai_do_objects_docked_stuff(object *docker, int docker_point, object *dockee, int dockee_point, bool update_clients = true);
@@ -634,6 +636,6 @@ void do_random_sidethrust(ai_info *aip, ship_info *sip);
void ai_formation_object_recalculate_slotnums(int form_objnum, int exiting_objnum = -1);
bool test_line_of_sight(vec3d* from, vec3d* to, std::unordered_set<const object*>&& excluded_objects = {}, float threshold = 10.0f, bool test_for_shields = false, bool test_for_hull = true, float* first_intersect_dist = nullptr, object** first_intersect_obj = nullptr);
bool test_line_of_sight(const vec3d* from, const vec3d* to, SCP_unordered_set<int>&& excluded_object_ids = {}, float threshold = 10.0f, bool test_for_shields = false, bool test_for_hull = true, float* first_intersect_dist = nullptr, object** first_intersect_obj = nullptr);
#endif
+23 -3
View File
@@ -32,6 +32,8 @@ namespace AI {
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
Waypoints_no_formation, // wont get into formation when running waypoints as part of a wing
NUM_VALUES
};
@@ -41,7 +43,7 @@ namespace AI {
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
Goal_override, // paired with ai_goal_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 ;)
@@ -99,6 +101,10 @@ namespace AI {
Fix_heat_seeker_stealth_bug,
Fix_linked_primary_bug,
Fix_ramming_stationary_targets_bug,
Fix_avoid_shockwave_bugs, // a) waiting until a homing weapon actually homes before evading;
// b) picking the correct expected impact position for capships;
// c) not clearing shockwave_object for ships;
// d) checking the explosion damage of the correct ship
Force_beam_turret_fov,
Free_afterburner_use,
Glide_decay_requires_thrust,
@@ -135,10 +141,11 @@ namespace AI {
All_nonshielded_ships_can_manage_ets,
Fightercraft_nonshielded_ships_can_manage_ets,
Ships_playing_dead_dont_manage_ets,
Better_collision_avoidance,
Better_combat_collision_avoidance,
Better_guard_collision_avoidance,
Require_exact_los,
Improved_missile_avoidance,
Friendlies_use_countermeasure_firechance,
Unify_usage_countermeasure_firechance,
Improved_subsystem_attack_pathing,
Fixed_ship_weapon_collision,
No_shield_damage_from_ship_collisions,
@@ -157,7 +164,20 @@ namespace AI {
Whackable_debris,
Whackable_asteroids,
Dynamic_goals_afterburn_hard,
Player_orders_afterburn_hard,
Hudsquadmsg_tactical_disarm_disable,
Align_to_target_when_guarding_still,
Debris_respects_big_damage,
Dont_limit_change_in_speed_due_to_physics_whack,
Guards_ignore_protected_attackers,
Standard_strafe_used_more,
Unify_usage_ai_shield_manage_delay,
Fix_AI_shield_management_bug,
AI_balances_shields_when_attacked,
Disable_ai_transferring_energy,
Freespace_1_missile_behavior,
ETS_uses_power_output,
ETS_energy_same_regardless_of_system_presence,
NUM_VALUES
};
+116 -7
View File
@@ -184,6 +184,14 @@ void parse_ai_profiles_tbl(const char *filename)
if (optional_string("$Max Beam Friendly Fire Damage:"))
parse_float_list(profile->beam_friendly_damage_cap, NUM_SKILL_LEVELS);
if (optional_string("$Max Weapon Friendly Fire Damage:")) {
parse_float_list(profile->weapon_friendly_damage_cap, NUM_SKILL_LEVELS);
}
if (optional_string("$Max Weapon Self Damage:")) {
parse_float_list(profile->weapon_self_damage_cap, NUM_SKILL_LEVELS);
}
if (optional_string("$Player Countermeasure Life Scale:"))
parse_float_list(profile->cmeasure_life_scale, NUM_SKILL_LEVELS);
@@ -369,7 +377,7 @@ void parse_ai_profiles_tbl(const char *filename)
}
if (optional_string("$Detail Distance Multiplier:"))
parse_float_list(profile->detail_distance_mult, MAX_DETAIL_LEVEL + 1);
parse_float_list(profile->detail_distance_mult, MAX_DETAIL_VALUE + 1);
set_flag(profile, "$big ships can attack beam turrets on untargeted ships:", AI::Profile_Flags::Big_ships_can_attack_beam_turrets_on_untargeted_ships);
@@ -471,10 +479,20 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$firing requires exact los:", AI::Profile_Flags::Require_exact_los);
if (optional_string("$exact los minimum detection radius:")) {
stuff_float(&profile->los_min_detection_radius);
}
set_flag(profile, "$fighterbay arrivals use carrier orientation:", AI::Profile_Flags::Fighterbay_arrivals_use_carrier_orient);
set_flag(profile, "$fighterbay departures use carrier orientation:", AI::Profile_Flags::Fighterbay_departures_use_carrier_orient);
set_flag(profile, "$debris damage respects 'big damage' flag:", AI::Profile_Flags::Debris_respects_big_damage);
set_flag(profile, "$don't limit change in speed due to physics whack:", AI::Profile_Flags::Dont_limit_change_in_speed_due_to_physics_whack);
set_flag(profile, "$guards ignore protected attackers:", AI::Profile_Flags::Guards_ignore_protected_attackers);
if (optional_string("$ai path mode:"))
{
stuff_string(buf, F_NAME, NAME_LENGTH);
@@ -564,11 +582,25 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$ships playing dead don't manage ETS:", AI::Profile_Flags::Ships_playing_dead_dont_manage_ets);
set_flag(profile, "$better combat collision avoidance for fightercraft:", AI::Profile_Flags::Better_collision_avoidance);
set_flag(profile, "$better combat collision avoidance for fightercraft:", AI::Profile_Flags::Better_combat_collision_avoidance);
if (optional_string("+combat collision avoidance aggression for fightercraft:")) {
stuff_float(&profile->better_collision_avoid_aggression_combat);
}
set_flag(profile, "$better guard collision avoidance for fightercraft:", AI::Profile_Flags::Better_guard_collision_avoidance);
if (optional_string("+guard collision avoidance aggression for fightercraft:")) {
stuff_float(&profile->better_collision_avoid_aggression_guard);
}
set_flag(profile, "$improved missile avoidance for fightercraft:", AI::Profile_Flags::Improved_missile_avoidance);
set_flag(profile, "$friendly ships use AI profile countermeasure chance:", AI::Profile_Flags::Friendlies_use_countermeasure_firechance);
if (optional_string_either("$friendly ships use AI profile countermeasure chance:", "$unify usage of AI profile countermeasure chance:", true) >= 0) {
bool val;
stuff_boolean(&val);
profile->flags.set(AI::Profile_Flags::Unify_usage_countermeasure_firechance, val);
}
set_flag(profile, "$improved subsystem attack pathing:", AI::Profile_Flags::Improved_subsystem_attack_pathing);
@@ -625,15 +657,70 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$dynamic goals afterburn hard:", AI::Profile_Flags::Dynamic_goals_afterburn_hard);
set_flag(profile, "$player orders afterburn hard:", AI::Profile_Flags::Player_orders_afterburn_hard);
set_flag(profile, "$hud squad messages use tactical disarm/disable:", AI::Profile_Flags::Hudsquadmsg_tactical_disarm_disable);
set_flag(profile, "$align to target when guarding stationary ship:", AI::Profile_Flags::Align_to_target_when_guarding_still);
if (optional_string("$rotation factor multiplier for player collisions:")) {
stuff_float(&profile->rot_fac_multiplier_ply_collisions);
}
set_flag(profile, "$fix avoid-shockwave bugs:", AI::Profile_Flags::Fix_avoid_shockwave_bugs);
set_flag(profile, "$standard strafe used more:", AI::Profile_Flags::Standard_strafe_used_more);
if (optional_string("$standard strafe triggers under this speed:")) {
stuff_float(&profile->standard_strafe_when_below_speed);
}
if (optional_string("$strafe distance from target bounding box:")) {
stuff_float(&profile->strafe_retreat_box_dist);
}
if (optional_string("$strafe stops after time unhit:")) {
stuff_float(&profile->strafe_max_unhit_time);
}
if (optional_string("$guard uses big-orbit for target radius above:")) {
stuff_float(&profile->guard_big_orbit_above_target_radius);
}
if (optional_string("$guard with big-orbit uses max speed percent:")) {
float max_percent;
stuff_float(&max_percent);
if (max_percent > 0.0f && max_percent <= 1.0f) {
profile->guard_big_orbit_max_speed_percent = max_percent;
} else {
mprintf(("Warning: \"$guard with big-orbit uses max speed percent:\" should be > 0 and <= 1 (read %f). Value will not be used.\n", max_percent));
}
}
set_flag(profile, "$unify usage of AI Shield Manage Delay:", AI::Profile_Flags::Unify_usage_ai_shield_manage_delay);
set_flag(profile, "$fix AI shield management bug:", AI::Profile_Flags::Fix_AI_shield_management_bug);
set_flag(profile, "$AI balances shields instead of directs when attacked:", AI::Profile_Flags::AI_balances_shields_when_attacked);
set_flag(profile, "$disable AI transferring energy:", AI::Profile_Flags::Disable_ai_transferring_energy);
set_flag(profile, "$enable freespace 1 style missile behavior:", AI::Profile_Flags::Freespace_1_missile_behavior);
set_flag(profile, "$ETS uses ship class power output:", AI::Profile_Flags::ETS_uses_power_output);
set_flag(profile, "$ETS energy same regardless of system presence:", AI::Profile_Flags::ETS_energy_same_regardless_of_system_presence);
// end of options ----------------------------------------
// if we've been through once already and are at the same place, force a move
if (saved_Mp && (saved_Mp == Mp))
{
char tmp[60];
memset(tmp, 0, 60);
strncpy(tmp, Mp, 59);
mprintf(("WARNING: Unrecognized parameter in ai_profiles: %s\n", tmp));
mprintf(("WARNING: Unrecognized parameter in %s: %s\n", filename, tmp));
Mp++;
}
@@ -707,6 +794,7 @@ void ai_profile_t::reset()
flags.reset();
los_min_detection_radius = 10.0f;
ai_path_mode = AI_PATH_MODE_NORMAL;
subsystem_path_radii = 0;
bay_arrive_speed_mult = 1.0f;
@@ -714,6 +802,17 @@ void ai_profile_t::reset()
second_order_lead_predict_factor = 0;
ai_range_aware_secondary_select_mode = AI_RANGE_AWARE_SEC_SEL_MODE_RETAIL;
turret_target_recheck_time = 2000.0f;
rot_fac_multiplier_ply_collisions = 0.0f;
better_collision_avoid_aggression_combat = 3.5f;
better_collision_avoid_aggression_guard = 3.5f;
standard_strafe_when_below_speed = 3.0f;
strafe_retreat_box_dist = 300.0f;
strafe_max_unhit_time = 20.0f;
guard_big_orbit_above_target_radius = 500.0f;
guard_big_orbit_max_speed_percent = 1.0f;
for (int i = 0; i < NUM_SKILL_LEVELS; ++i) {
max_incoming_asteroids[i] = 0;
@@ -736,10 +835,12 @@ void ai_profile_t::reset()
shield_energy_scale[i] = 0;
afterburner_recharge_scale[i] = 0;
player_damage_scale[i] = 0;
player_damage_inflicted_scale[i] = 0;
player_damage_inflicted_scale[i] = 0;
subsys_damage_scale[i] = 0;
beam_friendly_damage_cap[i] = 0;
beam_friendly_damage_cap[i] = -1.f;
weapon_friendly_damage_cap[i] = -1.f;
weapon_self_damage_cap[i] = -1.f;
turn_time_scale[i] = 0;
glide_attack_percent[i] = 0;
circle_strafe_percent[i] = 0;
@@ -770,7 +871,7 @@ void ai_profile_t::reset()
player_autoaim_fov[i] = 0;
}
for (int i = 0; i <= MAX_DETAIL_LEVEL; ++i) {
for (int i = 0; i <= MAX_DETAIL_VALUE; ++i) {
detail_distance_mult[i] = 0;
}
@@ -819,4 +920,12 @@ void ai_profile_t::reset()
if (mod_supports_version(23, 4, 0)) {
flags.set(AI::Profile_Flags::Hudsquadmsg_tactical_disarm_disable);
}
if (mod_supports_version(24, 2, 0)) {
flags.set(AI::Profile_Flags::Debris_respects_big_damage);
flags.set(AI::Profile_Flags::Force_beam_turret_fov);
flags.set(AI::Profile_Flags::Guards_ignore_protected_attackers);
}
if (mod_supports_version(25, 0, 0)) {
flags.set(AI::Profile_Flags::Fix_avoid_shockwave_bugs);
}
}
+27 -1
View File
@@ -57,6 +57,8 @@ public:
float subsys_damage_scale[NUM_SKILL_LEVELS]; // damage applied to a player subsystem
float beam_friendly_damage_cap[NUM_SKILL_LEVELS]; // damage cap values for friendly beam fire
float weapon_friendly_damage_cap[NUM_SKILL_LEVELS];
float weapon_self_damage_cap[NUM_SKILL_LEVELS];
float turn_time_scale[NUM_SKILL_LEVELS]; // speed at which enemy ships turn
float glide_attack_percent[NUM_SKILL_LEVELS]; // SUSHI: The likelihood (0.0-1.0) of the AI to use the "glide attack" move
float circle_strafe_percent[NUM_SKILL_LEVELS]; // SUSHI: The likelihood (0.0-1.0) of the AI to use the "circle strafe" move
@@ -97,7 +99,10 @@ public:
// Player-specific autoaim FOV override
float player_autoaim_fov[NUM_SKILL_LEVELS];
float detail_distance_mult[MAX_DETAIL_LEVEL + 1]; //MAX_DETAIL_LEVEL really needs to be 4
float detail_distance_mult[MAX_DETAIL_VALUE + 1]; //MAX_DETAIL_VALUE really needs to be 4
// minimum radius for the line-of-sight (los) detection --wookieejedi
float los_min_detection_radius;
int ai_path_mode;
@@ -118,6 +123,27 @@ public:
// how often turrets shoulds check for new targets, milliseconds
float turret_target_recheck_time;
// Multiplier value so the player can also experience rotational effects from collisions --wookieejedi
float rot_fac_multiplier_ply_collisions;
// Collision avoidance options --developed by asteroth, exposed by wookieejedi
// Velocity / turn rate gives us a vector which represents the minimum 'bug out' distance.
// However this will be a significant underestimate, it doesn't take into account acceleration
// with regards to its turn speed, nor already existing rotvel, nor the angular distance
// to the particular avoidance vector it comes up with.
// These would significantly complicate the calculation, so for now, it is all bundled into these magic numbers.
float better_collision_avoid_aggression_combat;
float better_collision_avoid_aggression_guard;
// AI strafing options --wookieejedi
float standard_strafe_when_below_speed; // Speed at which standard strafing large ships is possibly triggered
float strafe_retreat_box_dist; // Distance beyond the bounding box to retreat to strafing point
float strafe_max_unhit_time; // Maximum amount of time to stay in strafe mode if not hit
// AI guard options --wookieejedi
float guard_big_orbit_above_target_radius; // Radius of guardee that triggers ai_big_guard()
float guard_big_orbit_max_speed_percent; // Max percent of forward speed that is used in ai_big_guard()
void reset();
};
+38 -35
View File
@@ -39,10 +39,9 @@
#define MIN_DOT_TO_ATTACK_MOVING_SUBSYS 0.97f
// AI BIG MAGIC NUMBERS
// Select strafing options are now exposed to modders --wookieejedi
#define STRAFE_RETREAT_COLLIDE_TIME 2.0 // when anticipated collision time is less than this, begin retreat
#define STRAFE_RETREAT_COLLIDE_DIST 100 // when perpendicular distance to *surface* is less than this, begin retreat
#define STRAFE_RETREAT_BOX_DIST 300 // distance beyond the bounding box to retreat
#define STRAFE_MAX_UNHIT_TIME 20 // Maximum amount of time to stay in strafe mode if not hit
#define EVADE_BOX_BASE_DISTANCE 300 // standard distance to end evade submode
#define EVADE_BOX_MIN_DISTANCE 200 // minimun distance to end evade submode, after long time
@@ -67,8 +66,8 @@ int ai_big_maybe_follow_subsys_path(int do_dot_check=1);
void ai_big_strafe_position();
static int ai_big_strafe_maybe_retreat(const vec3d *target_pos);
extern void compute_desired_rvec(vec3d *rvec, vec3d *goal_pos, vec3d *cur_pos);
extern void big_ship_collide_recover_start(object *objp, object *big_objp, vec3d *collision_normal);
extern void compute_desired_rvec(vec3d *rvec, const vec3d *goal_pos, const vec3d *cur_pos);
extern void big_ship_collide_recover_start(const object *objp, const object *big_objp, const vec3d *collision_normal);
// Called by ai_big_pick_attack_point.
@@ -76,7 +75,7 @@ extern void big_ship_collide_recover_start(object *objp, object *big_objp, vec3d
// If truly_random flag set (haha), then generate a pretty random number. Otherwise, generate a static rand which
// tends to not change from frame to frame.
// Try four times and choose nearest point to increase chance of getting a good point.
void ai_bpap(object *objp, vec3d *attacker_objp_pos, vec3d *attacker_objp_fvec, vec3d *attack_point, vec3d *local_attack_point, float fov, float weapon_travel_dist, vec3d *surface_normal, ship_subsys *ss)
void ai_bpap(const object *objp, const vec3d *attacker_objp_pos, const vec3d *attacker_objp_fvec, vec3d *attack_point, vec3d *local_attack_point, float fov, float weapon_travel_dist, vec3d *surface_normal, const ship_subsys *ss)
{
float nearest_dist;
vec3d result_point, best_point;
@@ -193,7 +192,7 @@ done_1:
//
// Note: Default value for fov is 1.0f 1.0f means don't use fov parameter.
// If fov != 1.0f, try up to four times to find a point that's in the field of view.
void ai_big_pick_attack_point_turret(object *objp, ship_subsys *ssp, vec3d *gpos, vec3d *gvec, vec3d *attack_point, float fov, float weapon_travel_dist)
void ai_big_pick_attack_point_turret(const object *objp, ship_subsys *ssp, const vec3d *gpos, const vec3d *gvec, vec3d *attack_point, float fov, float weapon_travel_dist)
{
if (!timestamp_elapsed(ssp->turret_pick_big_attack_point_timestamp)) {
vec3d result_point;
@@ -213,7 +212,7 @@ void ai_big_pick_attack_point_turret(object *objp, ship_subsys *ssp, vec3d *gpos
// Note: Default value for fov is 1.0f 1.0f means don't use fov parameter.
// If fov != 1.0f, try up to four times to find a point that's in the field of view.
// Note, attacker_objp can be a ship or a weapon.
void ai_big_pick_attack_point(object *objp, object *attacker_objp, vec3d *attack_point, float fov)
void ai_big_pick_attack_point(const object *objp, const object *attacker_objp, vec3d *attack_point, float fov)
{
Assert(objp->instance > -1);
Assert(objp->type == OBJ_SHIP);
@@ -411,7 +410,7 @@ int ai_big_maybe_follow_subsys_path(int do_dot_check)
}
}
if ( ship_subsystem_in_sight(En_objp, aip->targeted_subsys, &geye, &gsubpos, 1) ) {
if ( ship_subsystem_in_sight(En_objp, aip->targeted_subsys, &geye, &gsubpos, true) ) {
subsys_in_sight = 1;
}
}
@@ -541,7 +540,7 @@ bool ai_new_maybe_reposition_attack_subsys() {
get_subsystem_pos(&gsubpos, target_objp, aip->targeted_subsys);
// you're in sight! shoot it!
if (ship_subsystem_in_sight(En_objp, aip->targeted_subsys, &geye, &gsubpos, 0))
if (ship_subsystem_in_sight(En_objp, aip->targeted_subsys, &geye, &gsubpos, false))
return false;
// not in sight, gotta get there
@@ -719,19 +718,21 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
}
}
}
// Since ship is moving slowly and attacking a large ship, scan if enemy fighters are near, if so
// then enter strafe mode
if ( ai_big_maybe_start_strafe(aip, sip) ) {
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)
ai_big_strafe_position();
return;
}
} // end if ( Pl_objp->phys_info.speed < 3.0f )
// if moving slowly and attacking a large ship,
// check if need to enter standard strafe mode
// including ai_profile flag and if enemy fighters are near
if (Pl_objp->phys_info.speed < The_mission.ai_profile->standard_strafe_when_below_speed &&
(The_mission.ai_profile->flags[AI::Profile_Flags::Standard_strafe_used_more] || ai_big_maybe_start_strafe(aip, sip))) {
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)
ai_big_strafe_position();
return;
}
//Maybe enter glide strafe (check every 8 seconds, on a different schedule for each ship)
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;
@@ -913,13 +914,13 @@ static void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy)
}
if (tswp->num_secondary_banks > 0) {
if (!(En_objp->flags[Object::Object_Flags::Protected]) || (aip->goals[0].ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISABLE_SHIP_TACTICAL | AI_GOAL_DISARM_SHIP | AI_GOAL_DISARM_SHIP_TACTICAL))) {
if ( !(En_objp->flags[Object::Object_Flags::Protected]) || ai_goal_is_disable_or_disarm(aip->goals[0].ai_mode) ) {
bool valid_secondary = ai_choose_secondary_weapon(Pl_objp, aip, En_objp);
int current_bank = tswp->current_secondary_bank;
if (current_bank > -1 && valid_secondary) {
weapon_info *swip = &Weapon_info[tswp->secondary_bank_weapons[current_bank]];
if(!(En_objp->flags[Object::Object_Flags::Protected]) || ((aip->goals[0].ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISABLE_SHIP_TACTICAL | AI_GOAL_DISARM_SHIP | AI_GOAL_DISARM_SHIP_TACTICAL)) && swip->wi_flags[Weapon::Info_Flags::Puncture] )) { //override lockdown on protected ships when using anti subsystem weapons - Valathil
if ( !(En_objp->flags[Object::Object_Flags::Protected]) || (ai_goal_is_disable_or_disarm(aip->goals[0].ai_mode) && swip->wi_flags[Weapon::Info_Flags::Puncture]) ) { //override lockdown on protected ships when using anti subsystem weapons - Valathil
// If ship is protected and very low on hits, don't fire missiles.
if (!(En_objp->flags[Object::Object_Flags::Protected]) || (En_objp->hull_strength > 10*swip->damage)) {
if (aip->ai_flags[AI::AI_Flags::Unload_secondaries]) {
@@ -1034,7 +1035,7 @@ void ai_big_chase()
ai_big_pick_attack_point(En_objp, Pl_objp, &enemy_pos, 0.8f);
weapon_info* wip = ai_get_weapon(&shipp->weapons);
bool ballistic_aiming = !IS_VEC_NULL(&The_mission.gravity) && wip->gravity_const != 0.0f;
bool ballistic_aiming = !IS_VEC_NULL(&The_mission.gravity) && wip && wip->gravity_const != 0.0f;
bool valid_ballistic_trajectory = true;
if (!ballistic_aiming) {
@@ -1439,7 +1440,7 @@ static int ai_big_strafe_maybe_retreat(const vec3d *target_pos)
//if ((dot_to_enemy > 1.0f - 0.1f * En_objp->radius/(dist_to_enemy + 1.0f)) && (Pl_objp->phys_info.speed > dist_to_enemy/5.0f))
// Inside 2 sec retreat, setting goal point to box point + 300m
// Inside 2 sec retreat, setting goal point to box point + strafe_retreat_box_dist
// If collision, use std collision resolution.
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]) {
@@ -1447,13 +1448,13 @@ static int ai_big_strafe_maybe_retreat(const vec3d *target_pos)
aip->ai_flags.remove(AI::AI_Flags::Target_collision);
big_ship_collide_recover_start(Pl_objp, En_objp, nullptr);
} else {
// too close for comfort so fly to box point + 300
// too close for comfort so fly to box point + strafe_retreat_box_dist
aip->submode = AIS_STRAFE_RETREAT1;
aip->submode_start_time = Missiontime;
int is_inside;
vec3d goal_point;
get_world_closest_box_point_with_delta(&goal_point, En_objp, &Pl_objp->pos, &is_inside, STRAFE_RETREAT_BOX_DIST);
get_world_closest_box_point_with_delta(&goal_point, En_objp, &Pl_objp->pos, &is_inside, The_mission.ai_profile->strafe_retreat_box_dist);
// set goal point
aip->goal_point = goal_point;
@@ -1568,8 +1569,7 @@ void ai_big_strafe_attack()
accelerate_ship(aip, accel);
// if haven't been hit in quite a while, leave strafe mode
fix long_enough;
long_enough = F1_0 * STRAFE_MAX_UNHIT_TIME;
fix long_enough = fl2f(The_mission.ai_profile->strafe_max_unhit_time);
if ( (last_hit > long_enough) && ( (Missiontime - aip->submode_parm0) > long_enough) ) {
ai_big_switch_to_chase_mode(aip);
}
@@ -1616,11 +1616,11 @@ void ai_big_strafe_glide_attack()
//If we haven't chosen the goal point yet, do so now
if (aip->submode_parm1 == 0) {
//Pick goal point. This should be a random point that passes through the circle whose normal is the vector between attacker and target
vec3d targetToAttacker;
vec3d tangentPoint;
vm_vec_sub(&targetToAttacker, &Pl_objp->pos, &target_objp->pos);
vec3d targetToAttackerDir;
vm_vec_normalized_dir(&targetToAttackerDir, &Pl_objp->pos, &target_objp->pos);
matrix orient;
vm_vector_2_matrix(&orient, &targetToAttacker, NULL, NULL);
vm_vector_2_matrix_norm(&orient, &targetToAttackerDir, nullptr, nullptr);
vec3d tangentPoint;
vm_vec_random_in_circle(&tangentPoint, &target_objp->pos, &orient, target_objp->radius + GLIDE_STRAFE_DISTANCE, true);
//Get tangent point in coords relative to ship, scale it up so the actual goal point is far away, then put back in world coords
vm_vec_sub2(&tangentPoint, &Pl_objp->pos);
@@ -1641,7 +1641,7 @@ void ai_big_strafe_glide_attack()
//Keep going until we are too far away.
//If we are still on approach but too far away, this will still trigger. This will allow us to reposition the target
//point and allow for a "jinking" effect.
if (target_ship_dist > (STRAFE_RETREAT_BOX_DIST + target_objp->radius) &&
if (target_ship_dist > (The_mission.ai_profile->strafe_retreat_box_dist + target_objp->radius) &&
Missiontime - aip->submode_start_time > i2f(GLIDE_STRAFE_MIN_TIME)) {
//This checks whether we are moving toward the target or away from it. If moving towards, we reset the stage so that we
//pick a new attack vector (jinking). If moving away, we're at the end of a run so do a full reset (possibly allowing a
@@ -1691,7 +1691,7 @@ void ai_big_strafe_glide_attack()
// if haven't been hit in quite a while, leave strafe mode
// (same as ai_big_strafe_attack)
fix long_enough = F1_0 * STRAFE_MAX_UNHIT_TIME;
fix long_enough = fl2f(The_mission.ai_profile->strafe_max_unhit_time);
if ( (Missiontime - aip->last_hit_time > long_enough) && ( (Missiontime - aip->submode_parm0) > long_enough) ) {
ai_big_switch_to_chase_mode(aip);
}
@@ -1887,7 +1887,7 @@ void ai_big_strafe()
{
//Re-roll for random sidethrust every 2 seconds
if (static_randf((Missiontime + static_rand(aip->shipnum)) >> 17) < aip->ai_random_sidethrust_percent) {
do_random_sidethrust(aip, &Ship_info[Ships[Objects[aip->target_objnum].instance].ship_info_index]);
do_random_sidethrust(aip, &Ship_info[Ships[aip->shipnum].ship_info_index]);
}
}
}
@@ -1933,7 +1933,10 @@ int ai_big_maybe_enter_strafe_mode(const object *pl_objp, int weapon_objnum)
weapon_objp = &Objects[weapon_objnum];
Assert(weapon_objp->type == OBJ_WEAPON);
Assert(weapon_objp->parent >= 0 && weapon_objp->parent < MAX_OBJECTS);
if (weapon_objp->parent < 0) {
return 0;
}
Assert(weapon_objp->parent < MAX_OBJECTS);
parent_objp = &Objects[weapon_objp->parent];
if ( (parent_objp->signature != weapon_objp->parent_sig) || (parent_objp->type != OBJ_SHIP) ) {
return 0;
+2 -2
View File
@@ -24,8 +24,8 @@ void ai_big_subsys_path_cleanup(ai_info *aip);
void ai_big_strafe();
int ai_big_maybe_enter_strafe_mode(const object *objp, int weapon_objnum);
void ai_big_strafe_maybe_attack_turret(const object *ship_objp, const object *weapon_objp);
void ai_big_pick_attack_point(object *objp, object *attacker_objp, vec3d *attack_point, float fov=1.0f);
void ai_big_pick_attack_point_turret(object *objp, ship_subsys *ssp, vec3d *gpos, vec3d *gvec, vec3d *attack_point, float weapon_travel_dist, float fov=1.0f);
void ai_big_pick_attack_point(const object *objp, const object *attacker_objp, vec3d *attack_point, float fov=1.0f);
void ai_big_pick_attack_point_turret(const object *objp, ship_subsys *ssp, const vec3d *gpos, const vec3d *gvec, vec3d *attack_point, float weapon_travel_dist, float fov=1.0f);
// default distance for following subsystem path points --wookieejedi
// the value is 5 because that was the original value specified in ai_big_maybe_follow_subsys_path()
+340 -156
View File
File diff suppressed because it is too large. Load diff
+165 -105
View File
@@ -53,8 +53,14 @@ struct ship_registry_entry;
// PURGE_GOALS_ONE_SHIP for goals which should only purge other goals in the one ship.
// Goober5000 - note that the new disable and disarm goals (AI_GOAL_DISABLE_SHIP_TACTICAL and
// AI_GOAL_DISARM_SHIP_TACTICAL) do not purge ANY goals, not even the ones in the one ship
#define PURGE_GOALS_ALL_SHIPS (AI_GOAL_IGNORE | AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP)
#define PURGE_GOALS_ONE_SHIP (AI_GOAL_IGNORE_NEW)
inline bool purge_goals_all_ships(ai_goal_mode ai_mode)
{
return ai_mode == AI_GOAL_IGNORE || ai_mode == AI_GOAL_DISABLE_SHIP || ai_mode == AI_GOAL_DISARM_SHIP;
}
inline bool purge_goals_one_ship(ai_goal_mode ai_mode)
{
return ai_mode == AI_GOAL_IGNORE_NEW;
}
// goals given from the player to other ships in the game are also handled in this
// code
@@ -86,7 +92,7 @@ ai_goal_list Ai_goal_names[] =
{ "Guard wing", AI_GOAL_GUARD_WING, 0 },
{ "Evade ship", AI_GOAL_EVADE_SHIP, 0 },
{ "Stay near ship", AI_GOAL_STAY_NEAR_SHIP, 0 },
{ "keep safe dist", AI_GOAL_KEEP_SAFE_DISTANCE, 0 },
{ "Keep safe dist", AI_GOAL_KEEP_SAFE_DISTANCE, 0 },
{ "Rearm ship", AI_GOAL_REARM_REPAIR, 0 },
{ "Stay still", AI_GOAL_STAY_STILL, 0 },
{ "Play dead", AI_GOAL_PLAY_DEAD, 0 },
@@ -102,7 +108,7 @@ int Num_ai_goals = sizeof(Ai_goal_names) / sizeof(ai_goal_list);
// HUD what a ship's current orders are. If the AI goal doesn't correspond to something that
// ought to be printable, then NULL is used.
// JAS: Converted to a function in order to externalize the strings
const char *Ai_goal_text(int goal, int submode)
const char *Ai_goal_text(ai_goal_mode goal, int submode)
{
switch(goal) {
case AI_GOAL_CHASE:
@@ -135,22 +141,22 @@ const char *Ai_goal_text(int goal, int submode)
return XSTR( "rearm ", 484);
case AI_GOAL_FLY_TO_SHIP:
return XSTR( "rendezvous with ", 1597);
case AI_GOAL_LUA:
case AI_GOAL_LUA: {
auto mode = ai_lua_find_mode(submode);
if (mode == nullptr)
return nullptr;
return mode->hudText;
}
// Avoid compiler warning
return nullptr;
default:
return nullptr;
}
}
/**
* Reset all fields to their uninitialized defaults. But if this is being called before adding a new goal, the function will set the correct signature and time.
* Similarly the added mode, submode, and type can be assigned.
*/
void ai_goal_reset(ai_goal *aigp, bool adding_goal, int ai_mode, int ai_submode, int type)
void ai_goal_reset(ai_goal *aigp, bool adding_goal, ai_goal_mode ai_mode, int ai_submode, ai_goal_type type)
{
if (ai_mode != AI_GOAL_NONE)
Assertion(adding_goal, "If a goal mode is being assigned, the adding_goal parameter must be true so that the signature and mission time can be set");
@@ -166,7 +172,7 @@ void ai_goal_reset(ai_goal *aigp, bool adding_goal, int ai_mode, int ai_submode,
aigp->target_name = nullptr;
aigp->target_name_index = -1;
aigp->wp_list = nullptr;
aigp->wp_list_index = -1;
aigp->target_instance = -1;
aigp->target_signature = -1;
@@ -215,13 +221,13 @@ void ai_maybe_add_form_goal(wing* wingp)
if (Netgame.type_flags & NG_TYPE_TEAM) {
const ship_registry_entry* ship_regp = ship_registry_get(Ships[wingp->ship_index[j]].ship_name);
wingnum = TVT_wings[ship_regp->p_objp()->team];
ai_add_ship_goal_player(AIG_TYPE_PLAYER_SHIP, AI_GOAL_FORM_ON_WING, -1, Ships[Wings[wingnum].ship_index[Wings[wingnum].special_ship]].ship_name, aip);
ai_add_ship_goal_player(ai_goal_type::PLAYER_SHIP, AI_GOAL_FORM_ON_WING, -1, Ships[Wings[wingnum].ship_index[Wings[wingnum].special_ship]].ship_name, aip);
} else {
wingnum = Starting_wings[0];
ai_add_ship_goal_player(AIG_TYPE_PLAYER_SHIP, AI_GOAL_FORM_ON_WING, -1, Ships[Wings[wingnum].ship_index[Wings[wingnum].special_ship]].ship_name, aip);
ai_add_ship_goal_player(ai_goal_type::PLAYER_SHIP, AI_GOAL_FORM_ON_WING, -1, Ships[Wings[wingnum].ship_index[Wings[wingnum].special_ship]].ship_name, aip);
}
} else if (!(Game_mode & GM_MULTIPLAYER)) {
ai_add_ship_goal_player(AIG_TYPE_PLAYER_SHIP, AI_GOAL_FORM_ON_WING, -1, Player_ship->ship_name, aip);
ai_add_ship_goal_player(ai_goal_type::PLAYER_SHIP, AI_GOAL_FORM_ON_WING, -1, Player_ship->ship_name, aip);
}
}
}
@@ -280,13 +286,13 @@ void ai_post_process_mission()
* Determines if a goal is valid for a particular type of ship
*
* @param ship Ship type to test
* @param ai_goal_type Goal type to test
* @param ai_mode Goal type to test
*/
int ai_query_goal_valid( int ship, int ai_goal_type )
int ai_query_goal_valid( int ship, ai_goal_mode ai_mode )
{
int accepted;
if (ai_goal_type == AI_GOAL_NONE || ai_goal_type == AI_GOAL_LUA)
if (ai_mode == AI_GOAL_NONE || ai_mode == AI_GOAL_LUA)
return 1; // anything can have no orders or Lua'd orders.
accepted = 0;
@@ -296,7 +302,8 @@ int ai_query_goal_valid( int ship, int ai_goal_type )
int ship_type = Ship_info[Ships[ship].ship_info_index].class_type;
if(ship_type > -1)
{
if(ai_goal_type & Ship_types[ship_type].ai_valid_goals) {
const auto &set = Ship_types[ship_type].ai_valid_goals;
if (set.find(ai_mode) != set.end()) {
accepted = 1;
}
}
@@ -341,7 +348,7 @@ void ai_remove_ship_goal( ai_info *aip, int index )
}
}
aip->active_goal = AI_GOAL_NONE;
aip->active_goal = AI_ACTIVE_GOAL_NONE;
}
ai_goal_reset(&aip->goals[index]);
@@ -358,7 +365,7 @@ void ai_clear_ship_goals( ai_info *aip )
for (i = 0; i < MAX_AI_GOALS; i++)
ai_remove_ship_goal( aip, i ); // resets active_goal and default behavior
aip->active_goal = AI_GOAL_NONE; // for good measure
aip->active_goal = AI_ACTIVE_GOAL_NONE; // for good measure
// next line moved here on 8/5/97 by MWA
// Don't reset player ai (and hence target)
@@ -458,9 +465,8 @@ void ai_mission_wing_goal_complete( int wingnum, ai_goal *remove_goalp )
void ai_mission_goal_complete( ai_info *aip )
{
// if the active goal is dynamic or none, just return. (AI_GOAL_NONE is probably an error, but
// I don't think that this is a problem)
if ( (aip->active_goal == AI_GOAL_NONE) || (aip->active_goal == AI_ACTIVE_GOAL_DYNAMIC) )
// if the active goal is dynamic or none, just return.
if ( (aip->active_goal == AI_ACTIVE_GOAL_NONE) || (aip->active_goal == AI_ACTIVE_GOAL_DYNAMIC) )
return;
ai_remove_ship_goal( aip, aip->active_goal );
@@ -497,9 +503,7 @@ void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list, ai_info *ai
purge_goal = goal_list;
for ( i = 0; i < MAX_AI_GOALS; purge_goal++, i++ ) {
int purge_ai_mode, purge_wing;
purge_ai_mode = purge_goal->ai_mode;
auto purge_ai_mode = purge_goal->ai_mode;
// don't need to process AI_GOAL_NONE
if ( purge_ai_mode == AI_GOAL_NONE )
@@ -519,7 +523,7 @@ void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list, ai_info *ai
// 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 );
int 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
@@ -536,7 +540,7 @@ void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list, ai_info *ai
// ignore goals should get rid of any kind of attack goal
case AI_GOAL_IGNORE:
case AI_GOAL_IGNORE_NEW:
if ( purge_ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISABLE_SHIP_TACTICAL | AI_GOAL_DISARM_SHIP | AI_GOAL_DISARM_SHIP_TACTICAL | AI_GOAL_CHASE | AI_GOAL_CHASE_WING | AI_GOAL_CHASE_SHIP_CLASS | AI_GOAL_DESTROY_SUBSYSTEM) )
if (ai_goal_is_disable_or_disarm(purge_ai_mode) || ai_goal_is_specific_chase(purge_ai_mode) || (purge_ai_mode == AI_GOAL_DESTROY_SUBSYSTEM))
purge_goal->flags.set(AI::Goal_Flags::Purge);
break;
@@ -544,7 +548,7 @@ void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list, ai_info *ai
// (but not tactical disarm/disable)
case AI_GOAL_DISARM_SHIP:
case AI_GOAL_DISABLE_SHIP:
if ( purge_ai_mode & (AI_GOAL_CHASE | AI_GOAL_CHASE_WING | AI_GOAL_CHASE_SHIP_CLASS) ) {
if (ai_goal_is_specific_chase(purge_ai_mode)) {
int ai_ship_type;
// for wings we grab the ship type of the wing leader
@@ -585,7 +589,7 @@ void ai_goal_purge_all_invalid_goals(ai_goal *aigp)
ship_obj *sop;
// only purge goals if a new goal is one of the types in next statement
if (!(aigp->ai_mode & PURGE_GOALS_ALL_SHIPS))
if (!purge_goals_all_ships(aigp->ai_mode))
return;
for (sop = GET_FIRST(&Ship_obj_list); sop != END_OF_LIST(&Ship_obj_list); sop = GET_NEXT(sop))
@@ -728,9 +732,9 @@ void ai_goal_fixup_dockpoints(ai_info *aip, ai_goal *aigp)
// from the mission goals (i.e. those goals which come from events) in that we don't
// use sexpressions for goals from the player...so we enumerate all the parameters
void ai_add_goal_sub_player(int type, int mode, int submode, const char *target_name, ai_goal *aigp, const ai_lua_parameters& lua_target )
void ai_add_goal_sub_player(ai_goal_type type, ai_goal_mode mode, int submode, const char *target_name, ai_goal *aigp, const ai_lua_parameters& lua_target )
{
Assert ( (type == AIG_TYPE_PLAYER_WING) || (type == AIG_TYPE_PLAYER_SHIP) );
Assert ( (type == ai_goal_type::PLAYER_WING) || (type == ai_goal_type::PLAYER_SHIP) );
ai_goal_reset(aigp, true, mode, submode, type);
@@ -738,8 +742,8 @@ void ai_add_goal_sub_player(int type, int mode, int submode, const char *target_
if ( mode == AI_GOAL_WARP ) {
if (submode >= 0) {
aigp->wp_list = find_waypoint_list_at_index(submode);
Assert(aigp->wp_list != NULL);
aigp->wp_list_index = submode;
Assert(find_waypoint_list_at_index(aigp->wp_list_index) != nullptr);
}
}
@@ -751,6 +755,9 @@ void ai_add_goal_sub_player(int type, int mode, int submode, const char *target_
if ( target_name != NULL )
aigp->target_name = ai_get_goal_target_name( target_name, &aigp->target_name_index );
if (The_mission.ai_profile->flags[AI::Profile_Flags::Player_orders_afterburn_hard])
aigp->flags.set(AI::Goal_Flags::Afterburn_hard);
// special case certain orders from player so that ships continue to do the right thing
@@ -763,7 +770,7 @@ void ai_add_goal_sub_player(int type, int mode, int submode, const char *target_
else if ( mode == AI_GOAL_FORM_ON_WING )
aigp->priority = PLAYER_PRIORITY_SUPPORT_LOW;
else if ( aigp->type == AIG_TYPE_PLAYER_WING )
else if ( aigp->type == ai_goal_type::PLAYER_WING ) // NOLINT(readability-braces-around-statements)
aigp->priority = PLAYER_PRIORITY_WING; // player wing goals not as high as ship goals
else
aigp->priority = PLAYER_PRIORITY_SHIP;
@@ -815,9 +822,9 @@ int ai_goal_num(ai_goal *goals)
}
void ai_add_goal_sub_scripting(int type, int mode, int submode, int priority, const char *target_name, ai_goal *aigp )
void ai_add_goal_sub_scripting(ai_goal_type type, ai_goal_mode mode, int submode, int priority, const char *target_name, ai_goal *aigp, int int_data, float float_data)
{
Assert ( (type == AIG_TYPE_PLAYER_WING) || (type == AIG_TYPE_PLAYER_SHIP) );
Assert ( (type == ai_goal_type::PLAYER_WING) || (type == ai_goal_type::PLAYER_SHIP) );
ai_goal_reset(aigp, true, mode, submode, type);
@@ -830,16 +837,18 @@ void ai_add_goal_sub_scripting(int type, int mode, int submode, int priority, co
aigp->target_name = ai_get_goal_target_name( target_name, &aigp->target_name_index );
aigp->priority = priority;
aigp->int_data = int_data;
aigp->float_data = float_data;
}
void ai_add_ship_goal_scripting(int mode, int submode, int priority, const char *shipname, ai_info *aip)
void ai_add_ship_goal_scripting(ai_goal_mode mode, int submode, int priority, const char *shipname, ai_info *aip, int int_data, float float_data)
{
int empty_index;
ai_goal *aigp;
empty_index = ai_goal_find_empty_slot(aip->goals, aip->active_goal);
aigp = &aip->goals[empty_index];
ai_add_goal_sub_scripting(AIG_TYPE_PLAYER_SHIP, mode, submode, priority, shipname, aigp);
ai_add_goal_sub_scripting(ai_goal_type::PLAYER_SHIP, mode, submode, priority, shipname, aigp, int_data, float_data);
//WMC - hack to get docking setup correctly
if ( mode == AI_GOAL_DOCK ) {
@@ -856,7 +865,7 @@ void ai_add_ship_goal_scripting(int mode, int submode, int priority, const char
// is issued to ship or wing (from player), mode is AI_GOAL_*. submode is the submode the
// ship should go into. shipname is the object of the action. aip is the ai_info pointer
// of the ship receiving the order
void ai_add_ship_goal_player( int type, int mode, int submode, const char *shipname, ai_info *aip, const ai_lua_parameters& lua_target)
void ai_add_ship_goal_player(ai_goal_type type, ai_goal_mode mode, int submode, const char *shipname, ai_info *aip, const ai_lua_parameters& lua_target)
{
int empty_index;
ai_goal *aigp;
@@ -877,7 +886,7 @@ void ai_add_ship_goal_player( int type, int mode, int submode, const char *shipn
// adds a goal from the player to the given wing (which in turn will add it to the proper
// ships in the wing
void ai_add_wing_goal_player( int type, int mode, int submode, const char *shipname, int wingnum, const ai_lua_parameters& lua_target)
void ai_add_wing_goal_player(ai_goal_type type, ai_goal_mode mode, int submode, const char *shipname, int wingnum, const ai_lua_parameters& lua_target)
{
int i, empty_index;
wing *wingp = &Wings[wingnum];
@@ -901,9 +910,10 @@ void ai_add_wing_goal_player( int type, int mode, int submode, const char *shipn
// common routine to add a sexpression mission goal to the appropriate goal structure.
void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, const char *actor_name )
void ai_add_goal_sub_sexp( int sexp, ai_goal_type type, ai_info *aip, ai_goal *aigp, const char *actor_name )
{
int node, dummy, op;
bool priority_is_nan = false, priority_is_nan_forever = false;
Assert ( Sexp_nodes[sexp].first != -1 );
node = Sexp_nodes[sexp].first;
@@ -929,7 +939,7 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, cons
aigp->target_name = ai_get_goal_target_name(CTEXT(CDR(node)), &aigp->target_name_index); // waypoint path name;
aigp->priority = atoi( CTEXT(CDR(CDR(node))) );
aigp->priority = eval_num(CDDR(node), priority_is_nan, priority_is_nan_forever);
aigp->ai_mode = AI_GOAL_WAYPOINTS;
if ( op == OP_AI_WAYPOINTS_ONCE )
aigp->ai_mode = AI_GOAL_WAYPOINTS_ONCE;
@@ -947,9 +957,9 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, cons
aigp->target_name = ai_get_goal_target_name( CTEXT(CDR(node)), &aigp->target_name_index );
// 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->docker.name = ai_get_goal_target_name(CTEXT(CDDR(node)), &dummy);
aigp->flags.set(AI::Goal_Flags::Subsys_needs_fixup);
aigp->priority = atoi( CTEXT(CDR(CDR(CDR(node)))) );
aigp->priority = eval_num(CDDDR(node), priority_is_nan, priority_is_nan_forever);
break;
case OP_AI_DISABLE_SHIP:
@@ -957,7 +967,7 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, cons
aigp->ai_mode = (op == OP_AI_DISABLE_SHIP) ? AI_GOAL_DISABLE_SHIP : AI_GOAL_DISABLE_SHIP_TACTICAL;
aigp->target_name = ai_get_goal_target_name( CTEXT(CDR(node)), &aigp->target_name_index );
aigp->ai_submode = -SUBSYSTEM_ENGINE;
aigp->priority = atoi( CTEXT(CDR(CDR(node))) );
aigp->priority = eval_num(CDDR(node), priority_is_nan, priority_is_nan_forever);
break;
case OP_AI_DISARM_SHIP:
@@ -965,27 +975,27 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, cons
aigp->ai_mode = (op == OP_AI_DISARM_SHIP) ? AI_GOAL_DISARM_SHIP : AI_GOAL_DISARM_SHIP_TACTICAL;
aigp->target_name = ai_get_goal_target_name( CTEXT(CDR(node)), &aigp->target_name_index );
aigp->ai_submode = -SUBSYSTEM_TURRET;
aigp->priority = atoi( CTEXT(CDR(CDR(node))) );
aigp->priority = eval_num(CDDR(node), priority_is_nan, priority_is_nan_forever);
break;
case OP_AI_WARP_OUT:
aigp->ai_mode = AI_GOAL_WARP;
aigp->priority = atoi( CTEXT(CDR(node)) );
aigp->priority = eval_num(CDR(node), priority_is_nan, priority_is_nan_forever);
break;
// the following goal is obsolete, but here for compatibility
case OP_AI_WARP:
aigp->ai_mode = AI_GOAL_WARP;
aigp->target_name = ai_get_goal_target_name(CTEXT(CDR(node)), &aigp->target_name_index); // waypoint path name;
aigp->priority = atoi( CTEXT(CDR(CDR(node))) );
aigp->priority = eval_num(CDDR(node), priority_is_nan, priority_is_nan_forever);
break;
case OP_AI_UNDOCK:
aigp->priority = atoi( CTEXT(CDR(node)) );
aigp->priority = eval_num(CDR(node), priority_is_nan, priority_is_nan_forever);
// Goober5000 - optional undock with something
if (CDR(CDR(node)) != -1)
aigp->target_name = ai_get_goal_target_name( CTEXT(CDR(CDR(node))), &aigp->target_name_index );
if (CDDR(node) != -1)
aigp->target_name = ai_get_goal_target_name( CTEXT(CDDR(node)), &aigp->target_name_index );
aigp->ai_mode = AI_GOAL_UNDOCK;
aigp->ai_submode = AIS_UNDOCK_0;
@@ -995,7 +1005,7 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, cons
{
aigp->ai_mode = AI_GOAL_REARM_REPAIR;
aigp->target_name = ai_get_goal_target_name(CTEXT(CDR(node)), &aigp->target_name_index);
aigp->priority = atoi( CTEXT(CDR(CDR(node))) );
aigp->priority = eval_num(CDDR(node), priority_is_nan, priority_is_nan_forever);
// this goal needs some extra setup
// if this doesn't work, the goal will be immediately removed
@@ -1013,36 +1023,36 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, cons
case OP_AI_STAY_STILL:
aigp->ai_mode = AI_GOAL_STAY_STILL;
aigp->target_name = ai_get_goal_target_name(CTEXT(CDR(node)), &aigp->target_name_index); // waypoint path name;
aigp->priority = atoi( CTEXT(CDR(CDR(node))) );
aigp->priority = eval_num(CDDR(node), priority_is_nan, priority_is_nan_forever);
break;
case OP_AI_DOCK:
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->priority = atoi( CTEXT(CDR(CDR(CDR(CDR(node))))) );
aigp->docker.name = ai_add_dock_name(CTEXT(CDDR(node)));
aigp->dockee.name = ai_add_dock_name(CTEXT(CDDDR(node)));
aigp->priority = eval_num(CDDDDR(node), priority_is_nan, priority_is_nan_forever);
aigp->ai_mode = AI_GOAL_DOCK;
aigp->ai_submode = AIS_DOCK_0; // be sure to set the submode
break;
case OP_AI_CHASE_ANY:
aigp->priority = atoi( CTEXT(CDR(node)) );
aigp->priority = eval_num(CDR(node), priority_is_nan, priority_is_nan_forever);
aigp->ai_mode = AI_GOAL_CHASE_ANY;
break;
case OP_AI_PLAY_DEAD:
aigp->priority = atoi( CTEXT(CDR(node)) );
aigp->priority = eval_num(CDR(node), priority_is_nan, priority_is_nan_forever);
aigp->ai_mode = AI_GOAL_PLAY_DEAD;
break;
case OP_AI_PLAY_DEAD_PERSISTENT:
aigp->priority = atoi( CTEXT(CDR(node)) );
aigp->priority = eval_num(CDR(node), priority_is_nan, priority_is_nan_forever);
aigp->ai_mode = AI_GOAL_PLAY_DEAD_PERSISTENT;
break;
case OP_AI_KEEP_SAFE_DISTANCE:
aigp->priority = atoi( CTEXT(CDR(node)) );
aigp->priority = eval_num(CDR(node), priority_is_nan, priority_is_nan_forever);
aigp->ai_mode = AI_GOAL_KEEP_SAFE_DISTANCE;
break;
@@ -1052,7 +1062,7 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, cons
bool is_nan, is_nan_forever;
aigp->target_name = ai_get_goal_target_name( CTEXT(CDR(node)), &aigp->target_name_index );
aigp->priority = atoi( CTEXT(CDDR(node)) );
aigp->priority = eval_num(CDDR(node), priority_is_nan, priority_is_nan_forever);
// distance from ship
if ( CDDDR(node) < 0 )
@@ -1088,7 +1098,7 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, cons
case OP_AI_IGNORE:
case OP_AI_IGNORE_NEW:
aigp->target_name = ai_get_goal_target_name( CTEXT(CDR(node)), &aigp->target_name_index );
aigp->priority = atoi( CTEXT(CDR(CDR(node))) );
aigp->priority = eval_num(CDDR(node), priority_is_nan, priority_is_nan_forever);
if ( op == OP_AI_CHASE ) {
aigp->ai_mode = AI_GOAL_CHASE;
@@ -1138,7 +1148,7 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, cons
localnode = CDR(localnode);
}
aigp->priority = atoi( CTEXT(localnode) );
aigp->priority = eval_num(localnode, priority_is_nan, priority_is_nan_forever);
aigp->lua_ai_target = { std::move(target), luaAIMode->sexp.getSEXPArgumentList(CDR(localnode)) };
}
@@ -1147,8 +1157,12 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, cons
}
}
if ( aigp->priority > MAX_GOAL_PRIORITY ) {
nprintf (("AI", "bashing sexpression priority of goal %s from %d to %d.\n", CTEXT(node), aigp->priority, MAX_GOAL_PRIORITY));
if ( priority_is_nan || priority_is_nan_forever ) {
Warning(LOCATION, "add-goal tried to add %s with a NaN priority; aborting...", Sexp_nodes[CAR(sexp)].text);
ai_goal_reset(aigp);
return;
} else if ( aigp->priority > MAX_GOAL_PRIORITY ) {
nprintf (("AI", "bashing add-goal sexpression priority of goal %s from %d to %d.\n", Sexp_nodes[CAR(sexp)].text, aigp->priority, MAX_GOAL_PRIORITY));
aigp->priority = MAX_GOAL_PRIORITY;
}
@@ -1224,9 +1238,10 @@ 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 important 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_ACTIVE_GOAL_NONE.
* NOTE: Callers should check the value of remove_more. If it is true, the function should be called again.
*/
int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp )
int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp, bool &remove_more )
{
/* Sanity check */
Assert( Sexp_nodes[ sexp ].first != -1 );
@@ -1242,115 +1257,150 @@ int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp )
/* The operator to use */
int op = get_operator_const( node );
// since this logic is common to all goals removed by the remove-goal sexp
auto eval_priority_et_seq = [sexp, &remove_more](int n, int priority_if_no_n = -1)->int
{
bool _priority_is_nan = false, _priority_is_nan_forever = false;
int _priority = (n >= 0) ? eval_num(n, _priority_is_nan, _priority_is_nan_forever) : priority_if_no_n;
n = CDR(sexp); // we want the first node after the goal sub-tree
if (_priority_is_nan || _priority_is_nan_forever)
{
Warning(LOCATION, "remove-goal tried to remove %s with a NaN priority; the priority will not be used for goal comparison", Sexp_nodes[CAR(sexp)].text);
_priority = -1;
}
else if (_priority > MAX_GOAL_PRIORITY)
{
nprintf(("AI", "bashing remove-goal sexpression priority of goal %s from %d to %d.\n", Sexp_nodes[CAR(sexp)].text, _priority, MAX_GOAL_PRIORITY));
_priority = MAX_GOAL_PRIORITY;
}
if (n >= 0)
{
remove_more = is_sexp_true(n);
n = CDR(n);
}
if (n >= 0)
{
if (is_sexp_true(n))
_priority = -1;
n = CDR(n);
}
return _priority;
};
/* We now need to determine what the mode and submode values are*/
switch( op )
{
case OP_AI_WAYPOINTS_ONCE:
goalmode = AI_GOAL_WAYPOINTS_ONCE;
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
priority = eval_priority_et_seq(CDDR(node));
break;
case OP_AI_WAYPOINTS:
goalmode = AI_GOAL_WAYPOINTS;
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
priority = eval_priority_et_seq(CDDR(node));
break;
case OP_AI_DESTROY_SUBSYS:
goalmode = AI_GOAL_DESTROY_SUBSYSTEM;
priority = ( CDR( CDR( CDR(node) ) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( CDR( node ) ) ) ) ) : -1;
priority = eval_priority_et_seq(CDDDR(node));
break;
case OP_AI_DISABLE_SHIP:
case OP_AI_DISABLE_SHIP_TACTICAL:
goalmode = (op == OP_AI_DISABLE_SHIP) ? AI_GOAL_DISABLE_SHIP : AI_GOAL_DISABLE_SHIP_TACTICAL;
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
priority = eval_priority_et_seq(CDDR(node));
break;
case OP_AI_DISARM_SHIP:
case OP_AI_DISARM_SHIP_TACTICAL:
goalmode = (op == OP_AI_DISARM_SHIP) ? AI_GOAL_DISARM_SHIP : AI_GOAL_DISARM_SHIP_TACTICAL;
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
priority = eval_priority_et_seq(CDDR(node));
break;
case OP_AI_WARP_OUT:
goalmode = AI_GOAL_WARP;
priority = ( CDR(node) >= 0 ) ? atoi( CTEXT( CDR( node ) ) ) : -1;
priority = eval_priority_et_seq(CDR(node));
break;
case OP_AI_WARP:
goalmode = AI_GOAL_WARP;
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
priority = eval_priority_et_seq(CDDR(node));
break;
case OP_AI_UNDOCK:
goalmode = AI_GOAL_UNDOCK;
goalsubmode = AIS_UNDOCK_0;
priority = ( CDR(node) >= 0 ) ? atoi( CTEXT( CDR( node ) ) ) : -1;
priority = eval_priority_et_seq(CDR(node));
break;
case OP_AI_STAY_STILL:
goalmode = AI_GOAL_STAY_STILL;
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
priority = eval_priority_et_seq(CDDR(node));
break;
case OP_AI_DOCK:
goalmode = AI_GOAL_DOCK;
goalsubmode = AIS_DOCK_0;
priority = ( CDR( CDR( CDR( CDR(node) ) ) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( CDR( CDR( node ) ) ) ) ) ) : -1;
priority = eval_priority_et_seq(CDDDDR(node));
break;
case OP_AI_CHASE_ANY:
goalmode = AI_GOAL_CHASE_ANY;
priority = ( CDR(node) >= 0 ) ? atoi( CTEXT( CDR( node ) ) ) : -1;
priority = eval_priority_et_seq(CDR(node));
break;
case OP_AI_PLAY_DEAD:
case OP_AI_PLAY_DEAD_PERSISTENT:
goalmode = (op == OP_AI_PLAY_DEAD) ? AI_GOAL_PLAY_DEAD : AI_GOAL_PLAY_DEAD_PERSISTENT;
priority = ( CDR(node) >= 0 ) ? atoi( CTEXT( CDR( node ) ) ) : -1;
priority = eval_priority_et_seq(CDR(node));
break;
case OP_AI_KEEP_SAFE_DISTANCE:
priority = ( CDR(node) >= 0 ) ? atoi( CTEXT( CDR( node ) ) ) : -1;
priority = eval_priority_et_seq(CDR(node));
goalmode = AI_GOAL_KEEP_SAFE_DISTANCE;
break;
case OP_AI_CHASE:
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
priority = eval_priority_et_seq(CDDR(node));
if ( wing_name_lookup( CTEXT( CDR( node ) ), 1 ) != -1 )
goalmode = AI_GOAL_CHASE_WING;
else
goalmode = AI_GOAL_CHASE;
break;
case OP_AI_GUARD:
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
priority = eval_priority_et_seq(CDDR(node));
if ( wing_name_lookup( CTEXT( CDR( node ) ), 1 ) != -1 )
goalmode = AI_GOAL_GUARD_WING;
else
goalmode = AI_GOAL_GUARD;
break;
case OP_AI_GUARD_WING:
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
priority = eval_priority_et_seq(CDDR(node));
goalmode = AI_GOAL_GUARD_WING;
break;
case OP_AI_CHASE_WING:
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
priority = eval_priority_et_seq(CDDR(node));
goalmode = AI_GOAL_CHASE_WING;
break;
case OP_AI_CHASE_SHIP_CLASS:
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
priority = eval_priority_et_seq(CDDR(node));
goalmode = AI_GOAL_CHASE_SHIP_CLASS;
break;
case OP_AI_EVADE_SHIP:
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
priority = eval_priority_et_seq(CDDR(node));
goalmode = AI_GOAL_EVADE_SHIP;
break;
case OP_AI_STAY_NEAR_SHIP:
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
priority = eval_priority_et_seq(CDDR(node));
goalmode = AI_GOAL_STAY_NEAR_SHIP;
break;
case OP_AI_IGNORE:
case OP_AI_IGNORE_NEW:
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
priority = eval_priority_et_seq(CDDR(node));
goalmode = (op == OP_AI_IGNORE) ? AI_GOAL_IGNORE : AI_GOAL_IGNORE_NEW;
break;
case OP_AI_FORM_ON_WING:
priority = 99;
priority = eval_priority_et_seq(-1, 99);
goalmode = AI_GOAL_FORM_ON_WING;
break;
case OP_AI_FLY_TO_SHIP:
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
priority = eval_priority_et_seq(CDDR(node));
goalmode = AI_GOAL_FLY_TO_SHIP;
break;
case OP_AI_REARM_REPAIR:
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
priority = eval_priority_et_seq(CDDR(node));
goalmode = AI_GOAL_REARM_REPAIR;
break;
default:
@@ -1366,7 +1416,7 @@ int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp )
localnode = CDR(localnode);
}
priority = localnode >= 0 ? atoi( CTEXT(localnode) ) : -1;
priority = eval_priority_et_seq(localnode);
}
else {
UNREACHABLE("Invalid SEXP-OP %s (number %d) for an AI goal!", Sexp_nodes[node].text, op);
@@ -1378,7 +1428,10 @@ int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp )
int goalindex = ai_find_goal_index( aigp, goalmode, goalsubmode, priority );
if ( goalindex == -1 )
{
remove_more = false;
return -1; /* no more to do; */
}
/* Clear out the contents of the goal. We can't use ai_remove_ship_goal since it needs ai_info and
* we've only got ai_goals */
@@ -1392,6 +1445,7 @@ void ai_remove_wing_goal_sexp(int sexp, wing *wingp)
{
int i;
int goalindex = -1;
bool remove_more = false;
// remove the ai goal for any ship that is currently arrived in the game (only if fred isn't running)
if ( !Fred_running ) {
@@ -1399,9 +1453,13 @@ void ai_remove_wing_goal_sexp(int sexp, wing *wingp)
int num = wingp->ship_index[i];
if ( num == -1 ) // ship must have been destroyed or departed
continue;
goalindex = ai_remove_goal_sexp_sub( sexp, Ai_info[Ships[num].ai_index].goals );
if ( Ai_info[Ships[num].ai_index].active_goal == goalindex )
Ai_info[Ships[num].ai_index].active_goal = AI_GOAL_NONE;
auto aip = &Ai_info[Ships[num].ai_index];
do {
goalindex = ai_remove_goal_sexp_sub(sexp, aip->goals, remove_more);
if (aip->active_goal == goalindex)
aip->active_goal = AI_ACTIVE_GOAL_NONE;
} while (remove_more);
}
}
@@ -1409,13 +1467,15 @@ void ai_remove_wing_goal_sexp(int sexp, wing *wingp)
// there are more waves to come
if ((wingp->num_waves - wingp->current_wave > 0) || Fred_running)
{
ai_remove_goal_sexp_sub( sexp, wingp->ai_goals );
do {
ai_remove_goal_sexp_sub(sexp, wingp->ai_goals, remove_more);
} while (remove_more);
}
}
// adds an ai goal for an individual ship
// type determines who has issues this ship a goal (i.e. the player/mission event/etc)
void ai_add_ship_goal_sexp( int sexp, int type, ai_info *aip )
void ai_add_ship_goal_sexp( int sexp, ai_goal_type type, ai_info *aip )
{
int gindex;
@@ -1424,7 +1484,7 @@ void ai_add_ship_goal_sexp( int sexp, int type, ai_info *aip )
}
// code to add ai goals to wings.
void ai_add_wing_goal_sexp(int sexp, int type, wing *wingp)
void ai_add_wing_goal_sexp(int sexp, ai_goal_type type, wing *wingp)
{
int i;
@@ -1470,7 +1530,7 @@ void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int /*
aigp = &(aip->goals[gindex]);
ai_goal_reset(aigp, true);
aigp->type = AIG_TYPE_DYNAMIC;
aigp->type = ai_goal_type::DYNAMIC;
aigp->flags.set(AI::Goal_Flags::Goal_override);
switch ( goal_type ) {
@@ -1602,10 +1662,10 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// check to see if we have a valid list. If not, then try to set one up. If that
// fails, then we must pitch this order
if ( (aigp->ai_mode == AI_GOAL_WAYPOINTS_ONCE) || (aigp->ai_mode == AI_GOAL_WAYPOINTS) ) {
if ( aigp->wp_list == NULL ) {
aigp->wp_list = find_matching_waypoint_list(aigp->target_name);
if ( aigp->wp_list_index < 0 ) {
aigp->wp_list_index = find_matching_waypoint_list_index(aigp->target_name);
if ( aigp->wp_list == NULL ) {
if ( aigp->wp_list_index < 0 ) {
Warning(LOCATION, "Unknown waypoint list %s - not found in mission file. Killing ai goal", aigp->target_name );
return ai_achievability::NOT_ACHIEVABLE;
}
@@ -1857,11 +1917,11 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// Goober5000 - see note at PURGE_GOALS_ALL_SHIPS... this is bizarre
if ((status == SHIP_STATUS_ARRIVED) && !(aigp->flags[AI::Goal_Flags::Goals_purged]))
{
if (aigp->ai_mode & PURGE_GOALS_ALL_SHIPS) {
if (purge_goals_all_ships(aigp->ai_mode)) {
ai_goal_purge_all_invalid_goals(aigp);
aigp->flags.set(AI::Goal_Flags::Goals_purged);
}
else if (aigp->ai_mode & PURGE_GOALS_ONE_SHIP) {
else if (purge_goals_one_ship(aigp->ai_mode)) {
ai_goal_purge_invalid_goals(aigp, aip->goals, aip, -1);
aigp->flags.set(AI::Goal_Flags::Goals_purged);
}
@@ -2341,7 +2401,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
flags |= WPF_REPEAT;
if (current_goal->flags[AI::Goal_Flags::Waypoints_in_reverse])
flags |= WPF_BACKTRACK;
ai_start_waypoints(objp, current_goal->wp_list, flags, current_goal->int_data);
ai_start_waypoints(objp, current_goal->wp_list_index, flags, current_goal->int_data);
break;
}
+82 -74
View File
@@ -24,81 +24,87 @@ struct ai_info;
// macros for goals which get set via sexpressions in the mission code
// types of ai goals -- tyese types will help us to determination on which goals should
// types of ai goals -- these will help us to determine which goals should
// have priority over others (i.e. when a player issues a goal to a wing, then a seperate
// goal to a ship in that wing). We would probably use this type in conjunction with
// goal priority to establish which goal to follow
#define AIG_TYPE_EVENT_SHIP 1 // from mission event direct to ship
#define AIG_TYPE_EVENT_WING 2 // from mission event direct to wing
#define AIG_TYPE_PLAYER_SHIP 3 // from player direct to ship
#define AIG_TYPE_PLAYER_WING 4 // from player direct to wing
#define AIG_TYPE_DYNAMIC 5 // created on the fly
enum class ai_goal_type
{
INVALID = 0,
EVENT_SHIP, // from mission event direct to ship
EVENT_WING, // from mission event direct to wing
PLAYER_SHIP, // from player direct to ship
PLAYER_WING, // from player direct to wing
DYNAMIC // created on the fly
};
#define AI_GOAL_NONE -1
// IMPORTANT! If you add a new AI_GOAL_x define, be sure to update the functions
// IMPORTANT! If you add a new AI_GOAL_x enum, be sure to update the functions
// ai_update_goal_references() and query_referenced_in_ai_goals() or else risk breaking
// 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
#define AI_GOAL_WAYPOINTS_ONCE (1<<4) // 0x00000010
#define AI_GOAL_WARP (1<<5) // 0x00000020
#define AI_GOAL_DESTROY_SUBSYSTEM (1<<6) // 0x00000040
#define AI_GOAL_FORM_ON_WING (1<<7) // 0x00000080
#define AI_GOAL_UNDOCK (1<<8) // 0x00000100
#define AI_GOAL_CHASE_WING (1<<9) // 0x00000200
#define AI_GOAL_GUARD (1<<10) // 0x00000400
#define AI_GOAL_DISABLE_SHIP (1<<11) // 0x00000800
#define AI_GOAL_DISARM_SHIP (1<<12) // 0x00001000
#define AI_GOAL_CHASE_ANY (1<<13) // 0x00002000
#define AI_GOAL_IGNORE (1<<14) // 0x00004000
#define AI_GOAL_GUARD_WING (1<<15) // 0x00008000
#define AI_GOAL_EVADE_SHIP (1<<16) // 0x00010000
enum ai_goal_mode : uint8_t
{
AI_GOAL_NONE = 0,
AI_GOAL_PLACEHOLDER_1,
// the next goals are for support ships only
#define AI_GOAL_STAY_NEAR_SHIP (1<<17) // 0x00020000
#define AI_GOAL_KEEP_SAFE_DISTANCE (1<<18) // 0x00040000
#define AI_GOAL_REARM_REPAIR (1<<19) // 0x00080000
AI_GOAL_CHASE, // per the original #define list, AI_GOAL_CHASE started at 2 (1<<1)
AI_GOAL_DOCK, // used for undocking as well
AI_GOAL_WAYPOINTS,
AI_GOAL_WAYPOINTS_ONCE,
AI_GOAL_WARP,
AI_GOAL_DESTROY_SUBSYSTEM,
AI_GOAL_FORM_ON_WING,
AI_GOAL_UNDOCK,
AI_GOAL_CHASE_WING,
AI_GOAL_GUARD,
AI_GOAL_DISABLE_SHIP,
AI_GOAL_DISARM_SHIP,
AI_GOAL_CHASE_ANY,
AI_GOAL_IGNORE,
AI_GOAL_GUARD_WING,
AI_GOAL_EVADE_SHIP,
// resume regular goals
#define AI_GOAL_STAY_STILL (1<<20) // 0x00100000
#define AI_GOAL_PLAY_DEAD (1<<21) // 0x00200000
// the next goals are for support ships only
AI_GOAL_STAY_NEAR_SHIP,
AI_GOAL_KEEP_SAFE_DISTANCE,
AI_GOAL_REARM_REPAIR,
// 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
#define AI_GOAL_PLAY_DEAD_PERSISTENT (1<<26) // 0x04000000
#define AI_GOAL_LUA (1<<27) // 0x08000000
#define AI_GOAL_DISARM_SHIP_TACTICAL (1<<28) // 0x10000000
#define AI_GOAL_DISABLE_SHIP_TACTICAL (1<<29) // 0x20000000
// resume regular goals
AI_GOAL_STAY_STILL,
AI_GOAL_PLAY_DEAD,
// now the masks for ship types
// added by SCP
AI_GOAL_CHASE_WEAPON,
AI_GOAL_FLY_TO_SHIP,
AI_GOAL_IGNORE_NEW,
AI_GOAL_CHASE_SHIP_CLASS,
AI_GOAL_PLAY_DEAD_PERSISTENT,
AI_GOAL_LUA,
AI_GOAL_DISARM_SHIP_TACTICAL,
AI_GOAL_DISABLE_SHIP_TACTICAL,
// Goober5000: added AI_GOAL_STAY_NEAR_SHIP and AI_GOAL_KEEP_SAFE_DISTANCE as valid for fighters
//WMC - Don't need these anymore. Whee!
/*
#define AI_GOAL_ACCEPT_FIGHTER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_CHASE | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_WARP | AI_GOAL_DESTROY_SUBSYSTEM | AI_GOAL_CHASE_WING | AI_GOAL_GUARD | AI_GOAL_DISABLE_SHIP | AI_GOAL_DISABLE_SHIP_TACTICAL | AI_GOAL_DISARM_SHIP | AI_GOAL_DISARM_SHIP_TACTICAL | AI_GOAL_CHASE_ANY | AI_GOAL_IGNORE | AI_GOAL_IGNORE_NEW | AI_GOAL_GUARD_WING | AI_GOAL_EVADE_SHIP | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_PLAY_DEAD_PERSISTENT | AI_GOAL_STAY_NEAR_SHIP | AI_GOAL_KEEP_SAFE_DISTANCE )
#define AI_GOAL_ACCEPT_BOMBER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_FIGHTER | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_STEALTH ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_FIGHTER | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_TRANSPORT ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_CHASE | AI_GOAL_CHASE_WING | AI_GOAL_DOCK | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_WARP | AI_GOAL_UNDOCK | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_PLAY_DEAD_PERSISTENT | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_FREIGHTER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_TRANSPORT | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_CRUISER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_FREIGHTER | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_CORVETTE ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_CRUISER | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_GAS_MINER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_CRUISER | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_AWACS ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_CRUISER | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_CAPITAL ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_CRUISER & ~(AI_GOAL_DOCK | AI_GOAL_UNDOCK) | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_SUPERCAP ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_CAPITAL | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_SUPPORT ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_DOCK | AI_GOAL_UNDOCK | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_STAY_NEAR_SHIP | AI_GOAL_KEEP_SAFE_DISTANCE | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_PLAY_DEAD_PERSISTENT )
#define AI_GOAL_ACCEPT_ESCAPEPOD ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_TRANSPORT| AI_GOAL_STAY_NEAR_SHIP )
*/
AI_GOAL_NUM_VALUES
};
#define MAX_AI_DOCK_NAMES 25
inline ai_goal_mode int_to_ai_goal_mode(int int_mode)
{
if (int_mode >= 0 && int_mode < AI_GOAL_NUM_VALUES)
return static_cast<ai_goal_mode>(int_mode);
Warning(LOCATION, "ai_goal_mode %d out of range! Setting to AI_GOAL_NONE.", int_mode);
return AI_GOAL_NONE;
}
inline bool ai_goal_is_disable_or_disarm(ai_goal_mode ai_mode)
{
return ai_mode == AI_GOAL_DISABLE_SHIP || ai_mode == AI_GOAL_DISABLE_SHIP_TACTICAL || ai_mode == AI_GOAL_DISARM_SHIP || ai_mode == AI_GOAL_DISARM_SHIP_TACTICAL;
}
inline bool ai_goal_is_specific_chase(ai_goal_mode ai_mode)
{
return ai_mode == AI_GOAL_CHASE || ai_mode == AI_GOAL_CHASE_WING || ai_mode == AI_GOAL_CHASE_SHIP_CLASS;
}
enum class ai_achievability { ACHIEVABLE, NOT_ACHIEVABLE, NOT_KNOWN, SATISFIED };
@@ -110,16 +116,16 @@ struct ai_lua_parameters {
// 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
ai_goal_mode ai_mode; // one of the AI_GOAL_* modes for this goal
int ai_submode; // maybe need a submode
int type; // one of the AIG_TYPE_* values above
ai_goal_type type; // one of the ai_goal_type (originally AIG_TYPE_*) 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
const char *target_name; // name of the thing that this goal acts upon
int target_name_index; // index of goal_target_name in Goal_target_names[][]
waypoint_list *wp_list; // waypoints that this ship might fly.
int wp_list_index; // waypoints that this ship might fly.
int target_instance; // instance of thing this ship might be chasing (currently only used for weapons; note, not the same as objnum!)
int target_signature; // signature of object this ship might be chasing (currently only used for weapons; paired with above value to confirm target)
@@ -144,18 +150,20 @@ typedef struct ai_goal {
} ai_goal;
extern void ai_goal_reset(ai_goal *aigp, bool adding_goal = false, int ai_mode = AI_GOAL_NONE, int ai_submode = -1, int type = -1);
extern void ai_goal_reset(ai_goal *aigp, bool adding_goal = false, ai_goal_mode ai_mode = AI_GOAL_NONE, int ai_submode = -1, ai_goal_type type = ai_goal_type::INVALID);
typedef flag_def_list ai_goal_list;
typedef flag_def_list_templated<ai_goal_mode> ai_goal_list;
extern ai_goal_list Ai_goal_names[];
extern int Num_ai_goals;
#define MAX_AI_DOCK_NAMES 25
extern int Num_ai_dock_names;
extern char Ai_dock_names[MAX_AI_DOCK_NAMES][NAME_LENGTH];
extern const char *Ai_goal_text(int goal, int submode);
extern const char *Ai_goal_text(ai_goal_mode goal, int submode);
// every goal in a mission gets a unique signature
extern int Ai_goal_signature;
@@ -168,17 +176,17 @@ extern void ai_process_mission_orders( int objnum, ai_info *aip );
extern int ai_goal_num(ai_goal *goals);
// adds goals to ships/wing through sexpressions
extern void ai_add_ship_goal_scripting(int mode, int submode, int priority, const char *shipname, ai_info *aip);
extern void ai_add_ship_goal_sexp( int sexp, int type, ai_info *aip );
extern void ai_add_wing_goal_sexp( int sexp, int type, wing *wingp );
extern void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, const char *actor_name);
extern void ai_add_ship_goal_scripting(ai_goal_mode mode, int submode, int priority, const char *shipname, ai_info *aip, int int_data, float float_data);
extern void ai_add_ship_goal_sexp(int sexp, ai_goal_type type, ai_info *aip);
extern void ai_add_wing_goal_sexp(int sexp, ai_goal_type type, wing *wingp);
extern void ai_add_goal_sub_sexp(int sexp, ai_goal_type type, ai_info *aip, ai_goal *aigp, const char *actor_name);
extern int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp );
extern int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp, bool &remove_more );
extern void ai_remove_wing_goal_sexp( int sexp, wing *wingp );
// adds goals to ships/sings through player orders
extern void ai_add_ship_goal_player(int type, int mode, int submode, const char* shipname, ai_info* aip, const ai_lua_parameters& lua_target = { object_ship_wing_point_team(), luacpp::LuaValueList{} });
extern void ai_add_wing_goal_player(int type, int mode, int submode, const char* shipname, int wingnum, const ai_lua_parameters& lua_target = { object_ship_wing_point_team(), luacpp::LuaValueList{} });
extern void ai_add_ship_goal_player(ai_goal_type type, ai_goal_mode mode, int submode, const char* shipname, ai_info* aip, const ai_lua_parameters& lua_target = { object_ship_wing_point_team(), luacpp::LuaValueList{} });
extern void ai_add_wing_goal_player(ai_goal_type type, ai_goal_mode mode, int submode, const char* shipname, int wingnum, const ai_lua_parameters& lua_target = { object_ship_wing_point_team(), luacpp::LuaValueList{} });
extern void ai_remove_ship_goal( ai_info *aip, int index );
extern void ai_clear_ship_goals( ai_info *aip );
@@ -193,7 +201,7 @@ extern void ai_update_goal_references(ai_goal *goals, sexp_ref_type type, const
extern bool query_referenced_in_ai_goals(ai_goal *goals, sexp_ref_type type, const char *name);
extern char *ai_add_dock_name(const char *str);
extern int ai_query_goal_valid( int ship, int ai_goal_type );
extern int ai_query_goal_valid( int ship, ai_goal_mode ai_mode );
extern void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int docker_point, int dockee_point, int immediate = 1 );
+7 -7
View File
@@ -14,24 +14,24 @@
#include "weapon/weapon.h"
//Returns true if the specified object is a stealth ship, false if not
bool is_object_stealth_ship(object* objp);
bool is_object_stealth_ship(const object* objp);
//Number of live turrets on the object attacking
int num_turrets_attacking(object *turret_parent, int target_objnum);
int num_turrets_attacking(const object *turret_parent, int target_objnum);
//Determine whether an object is targetable within a nebula (checks for stealth)
int object_is_targetable(object *target, ship *viewer);
bool object_is_targetable(const object *target, const ship *viewer);
//Returns the number of enemy fighters within threshold of pos.
int num_nearby_fighters(int enemy_team_mask, vec3d *pos, float threshold);
int num_nearby_fighters(int enemy_team_mask, const vec3d *pos, float threshold);
//Returns true if OK for *aip to fire its current weapon at its current target.
int check_ok_to_fire(int objnum, int target_objnum, weapon_info *wip, int secondary_bank, ship_subsys* turret);
bool check_ok_to_fire(int objnum, int target_objnum, const weapon_info *wip, int secondary_bank, const vec3d *firing_pos_global);
//Returns true if *aip has a line of sight to its current target.
bool check_los(int objnum, int target_objnum, float threshold, int primary_bank, int secondary_bank, ship_subsys* turret);
bool check_los(int objnum, int target_objnum, float threshold, int primary_bank, int secondary_bank, const vec3d *firing_pos_global);
//Does all the stuff needed to aim and fire a turret.
void ai_turret_execute_behavior(ship *shipp, ship_subsys *ss);
void ai_turret_execute_behavior(const ship *shipp, ship_subsys *ss);
#endif
+1 -1
View File
@@ -389,7 +389,7 @@ ai_achievability ai_lua_is_achievable(const ai_goal* aigp, int objnum){
if (!retVals.empty() && retVals[0].getValueType() == luacpp::ValueType::USERDATA) {
scripting::api::enum_h enumData;
retVals[0].getValue(scripting::api::l_Enum.Get(&enumData));
if (!enumData.IsValid()) {
if (!enumData.isValid()) {
Error(LOCATION, "LuaAI SEXP achievability hook returned an invalid avilability enum.");
return ai_achievability::ACHIEVABLE;
}
+402 -333
View File
File diff suppressed because it is too large. Load diff
+6 -17
View File
@@ -667,12 +667,10 @@ void anim_read_header(anim *ptr, CFILE *fp)
*
* @param real_filename Filename of animation
* @param cf_dir_type
* @param file_mapped Whether to use memory-mapped file or not.
*
* @details Memory-mapped files will page in the animation from disk as it is needed, but performance is not as good.
*
* @return Pointer to anim that is loaded if success, NULL if failure.
*/
anim *anim_load(const char *real_filename, int cf_dir_type, int file_mapped)
anim *anim_load(const char *real_filename, int cf_dir_type)
{
anim *ptr;
CFILE *fp;
@@ -697,7 +695,7 @@ anim *anim_load(const char *real_filename, int cf_dir_type, int file_mapped)
}
if (!ptr) {
fp = cfopen(name, "rb", CFILE_NORMAL, cf_dir_type);
fp = cfopen(name, "rb", cf_dir_type);
if ( !fp )
return NULL;
@@ -743,18 +741,9 @@ anim *anim_load(const char *real_filename, int cf_dir_type, int file_mapped)
ptr->cfile_ptr = NULL;
if ( file_mapped == PAGE_FROM_MEM) {
// Try mapping the file to memory
ptr->flags |= ANF_MEM_MAPPED;
ptr->cfile_ptr = cfopen(name, "rb", CFILE_MEMORY_MAPPED, cf_dir_type);
}
// couldn't memory-map file... must be in a packfile, so stream manually
if ( file_mapped == PAGE_FROM_MEM && !ptr->cfile_ptr ) {
ptr->flags &= ~ANF_MEM_MAPPED;
ptr->flags |= ANF_STREAMED;
ptr->cfile_ptr = cfopen(name, "rb", CFILE_NORMAL, cf_dir_type);
}
// NOTE: mapped files no longer supported!!
ptr->flags |= ANF_STREAMED;
ptr->cfile_ptr = cfopen(name, "rb", cf_dir_type);
ptr->cache = NULL;
+1 -7
View File
@@ -38,12 +38,6 @@ typedef struct {
int ping_pong;
} anim_play_struct;
enum
{
PAGE_FROM_DISK = 0,
PAGE_FROM_MEM = 1
};
extern int Anim_paused;
void anim_init();
@@ -57,7 +51,7 @@ void anim_ignore_next_frametime();
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(const char *name, int cf_dir_type = CF_TYPE_ANY, int file_mapped = PAGE_FROM_DISK);
anim *anim_load(const char *name, int cf_dir_type = CF_TYPE_ANY);
int anim_free(anim *ptr);
void anim_read_header(anim *ptr, CFILE *fp);
void anim_reverse_direction(anim_instance *ai); // called automatically for ping-ponging, and can also be called externally
+316 -193
View File
@@ -42,6 +42,7 @@
#include "weapon/weapon.h"
#include <algorithm>
#include <random>
#define ASTEROID_OBJ_USED (1<<0) // flag used in asteroid_obj struct
#define MAX_ASTEROID_OBJS MAX_ASTEROIDS // max number of asteroids tracked in asteroid list
@@ -217,22 +218,38 @@ static float asteroid_cap_speed(int asteroid_info_index, float speed)
*/
static bool asteroid_in_inner_bound(asteroid_field *asfieldp, vec3d *pos, float delta) {
if (!asfieldp->has_inner_bound)
if (!asfieldp->has_inner_bound) {
return false;
}
if (Fix_asteroid_bounding_box_check) {
return (pos->xyz.x > asfieldp->inner_min_bound.xyz.x + delta) && (pos->xyz.x < asfieldp->inner_max_bound.xyz.x - delta) &&
(pos->xyz.y > asfieldp->inner_min_bound.xyz.y + delta) && (pos->xyz.y < asfieldp->inner_max_bound.xyz.y - delta) &&
(pos->xyz.z > asfieldp->inner_min_bound.xyz.z + delta) && (pos->xyz.z < asfieldp->inner_max_bound.xyz.z - delta);
} else {
return (pos->xyz.x > asfieldp->inner_min_bound.xyz.x - delta) && (pos->xyz.x < asfieldp->inner_max_bound.xyz.x + delta) &&
(pos->xyz.y > asfieldp->inner_min_bound.xyz.y - delta) && (pos->xyz.y < asfieldp->inner_max_bound.xyz.y + delta) &&
(pos->xyz.z > asfieldp->inner_min_bound.xyz.z - delta) && (pos->xyz.z < asfieldp->inner_max_bound.xyz.z + delta);
}
return (pos->xyz.x > asfieldp->inner_min_bound.xyz.x - delta) && (pos->xyz.x < asfieldp->inner_max_bound.xyz.x + delta) &&
(pos->xyz.y > asfieldp->inner_min_bound.xyz.y - delta) && (pos->xyz.y < asfieldp->inner_max_bound.xyz.y + delta) &&
(pos->xyz.z > asfieldp->inner_min_bound.xyz.z - delta) && (pos->xyz.z < asfieldp->inner_max_bound.xyz.z + delta);
}
static bool asteroid_is_ship_inside_field(asteroid_field* asfieldp, vec3d* pos, float radius) {
radius *= 2.0f;
return pos->xyz.x + radius > Asteroid_field.min_bound.xyz.x && pos->xyz.x - radius < Asteroid_field.max_bound.xyz.x &&
pos->xyz.y + radius > Asteroid_field.min_bound.xyz.y && pos->xyz.y - radius < Asteroid_field.max_bound.xyz.y &&
pos->xyz.z + radius > Asteroid_field.min_bound.xyz.z && pos->xyz.z - radius < Asteroid_field.max_bound.xyz.z &&
!asteroid_in_inner_bound(asfieldp, pos, radius);
if (Fix_asteroid_bounding_box_check) {
return pos->xyz.x - radius > Asteroid_field.min_bound.xyz.x && pos->xyz.x + radius < Asteroid_field.max_bound.xyz.x &&
pos->xyz.y - radius > Asteroid_field.min_bound.xyz.y && pos->xyz.y + radius < Asteroid_field.max_bound.xyz.y &&
pos->xyz.z - radius > Asteroid_field.min_bound.xyz.z && pos->xyz.z + radius < Asteroid_field.max_bound.xyz.z &&
!asteroid_in_inner_bound(asfieldp, pos, radius);
} else {
return pos->xyz.x + radius > Asteroid_field.min_bound.xyz.x && pos->xyz.x - radius < Asteroid_field.max_bound.xyz.x &&
pos->xyz.y + radius > Asteroid_field.min_bound.xyz.y && pos->xyz.y - radius < Asteroid_field.max_bound.xyz.y &&
pos->xyz.z + radius > Asteroid_field.min_bound.xyz.z && pos->xyz.z - radius < Asteroid_field.max_bound.xyz.z &&
!asteroid_in_inner_bound(asfieldp, pos, radius);
}
}
/**
@@ -262,6 +279,25 @@ static void inner_bound_pos_fixup(asteroid_field *asfieldp, vec3d *pos)
}
}
/**
* Randomly select an asteroid subtype
*/
const SCP_string& pick_random_asteroid_type()
{
return Asteroid_field.field_asteroid_type[Random::next(static_cast<int>(Asteroid_field.field_asteroid_type.size()))];
}
int get_asteroid_subtype_index_by_name(const SCP_string &name, int asteroid_idx) {
asteroid_info* this_asteroid = &Asteroid_info[asteroid_idx];
for (int i = 0; i < static_cast<int>(this_asteroid->subtypes.size()); i++) {
if (this_asteroid->subtypes[i].type_name == name) {
return i;
}
}
return -1;
}
/**
* Create a single asteroid
*/
@@ -279,8 +315,8 @@ object *asteroid_create(asteroid_field *asfieldp, int asteroid_type, int asteroi
int rand_base;
// bogus
if(asfieldp == NULL) {
return NULL;
if(asfieldp == nullptr) {
return nullptr;
}
for (n=0; n<MAX_ASTEROIDS; n++) {
@@ -291,15 +327,11 @@ object *asteroid_create(asteroid_field *asfieldp, int asteroid_type, int asteroi
if (n >= MAX_ASTEROIDS) {
nprintf(("Warning","Could not create asteroid, no more slots left\n"));
return NULL;
return nullptr;
}
if((asteroid_type < 0) || (asteroid_type >= (int)Asteroid_info.size())) {
return NULL;
}
if((asteroid_subtype < 0) || (asteroid_subtype >= NUM_ASTEROID_POFS)) {
return NULL;
if (!SCP_vector_inbounds(Asteroid_info, asteroid_type)) {
return nullptr;
}
// HACK: multiplayer asteroid subtype always 0 to keep subtype in sync
@@ -309,9 +341,13 @@ object *asteroid_create(asteroid_field *asfieldp, int asteroid_type, int asteroi
asip = &Asteroid_info[asteroid_type];
// bogus
if(asip->modelp[asteroid_subtype] == NULL) {
return NULL;
if (!SCP_vector_inbounds(asip->subtypes, asteroid_subtype)) {
return nullptr;
}
// if the model is not loaded then abort
if(asip->subtypes[asteroid_subtype].model_number == -1) {
return nullptr;
}
asp = &Asteroids[n];
@@ -326,7 +362,7 @@ object *asteroid_create(asteroid_field *asfieldp, int asteroid_type, int asteroi
asp->collide_objsig = -1;
asp->target_objnum = -1;
radius = model_get_radius(asip->model_num[asteroid_subtype]);
radius = model_get_radius(asip->subtypes[asteroid_subtype].model_number);
vm_vec_sub(&delta_bound, &asfieldp->max_bound, &asfieldp->min_bound);
@@ -379,8 +415,8 @@ object *asteroid_create(asteroid_field *asfieldp, int asteroid_type, int asteroi
asp->objnum = objnum;
asp->model_instance_num = -1;
if (model_get(asip->model_num[asteroid_subtype])->flags & PM_FLAG_HAS_INTRINSIC_MOTION) {
asp->model_instance_num = model_create_instance(objnum, asip->model_num[asteroid_subtype]);
if (model_get(asip->subtypes[asteroid_subtype].model_number)->flags & PM_FLAG_HAS_INTRINSIC_MOTION) {
asp->model_instance_num = model_create_instance(objnum, asip->subtypes[asteroid_subtype].model_number);
}
// Add to Asteroid_used_list
@@ -435,8 +471,8 @@ object *asteroid_create(asteroid_field *asfieldp, int asteroid_type, int asteroi
objp->phys_info.max_vel.xyz.y = 0.0f;
objp->phys_info.max_vel.xyz.z = vm_vec_mag(&objp->phys_info.desired_vel);
objp->phys_info.mass = asip->modelp[asteroid_subtype]->rad * 700.0f;
objp->phys_info.I_body_inv.vec.rvec.xyz.x = 1.0f / (objp->phys_info.mass*asip->modelp[asteroid_subtype]->rad);
objp->phys_info.mass = model_get(asip->subtypes[asteroid_subtype].model_number)->rad * 700.0f;
objp->phys_info.I_body_inv.vec.rvec.xyz.x = 1.0f / (objp->phys_info.mass*model_get(asip->subtypes[asteroid_subtype].model_number)->rad);
objp->phys_info.I_body_inv.vec.uvec.xyz.y = objp->phys_info.I_body_inv.vec.rvec.xyz.x;
objp->phys_info.I_body_inv.vec.fvec.xyz.z = objp->phys_info.I_body_inv.vec.rvec.xyz.x;
objp->hull_strength = asip->initial_asteroid_strength * (0.8f + (float)Game_skill_level/NUM_SKILL_LEVELS)/2.0f;
@@ -465,7 +501,8 @@ void asteroid_sub_create(object *parent_objp, int asteroid_type, vec3d *relvec)
int subtype = Asteroids[parent_objp->instance].asteroid_subtype;
new_objp = asteroid_create(&Asteroid_field, asteroid_type, subtype);
if (new_objp == NULL)
// New asteroid size doesn't have this subtype, so abort
if (new_objp == nullptr)
return;
if ( MULTIPLAYER_MASTER ){
@@ -497,32 +534,40 @@ void asteroid_sub_create(object *parent_objp, int asteroid_type, vec3d *relvec)
/**
* Load in an asteroid model
*/
static void asteroid_load(int asteroid_info_index, int asteroid_subtype)
void asteroid_load(int asteroid_info_index, int asteroid_subtype)
{
int i;
asteroid_info *asip;
Assertion(asteroid_info_index < (int)Asteroid_info.size(), "Command to load asteroid at index %i, but only %i asteroids exist", asteroid_info_index, (int)Asteroid_info.size());
Assertion(asteroid_subtype < NUM_ASTEROID_POFS, "Command to load asteroid pof %i, but only %i pofs are allowed", asteroid_subtype, NUM_ASTEROID_POFS);
Assertion(asteroid_info_index < static_cast<int>(Asteroid_info.size()),
"Command to load asteroid at index %i, but only %i asteroids exist",
asteroid_info_index,
static_cast<int>(Asteroid_info.size()));
if ( (asteroid_info_index >= (int)Asteroid_info.size()) || (asteroid_subtype >= NUM_ASTEROID_POFS) ) {
// invalid asteroid index
if (!SCP_vector_inbounds(Asteroid_info, asteroid_info_index)) {
return;
}
asip = &Asteroid_info[asteroid_info_index];
if ( !VALID_FNAME(asip->pof_files[asteroid_subtype]) )
// This asteroid does not have this subtype so just return
if (!SCP_vector_inbounds(asip->subtypes, asteroid_subtype)) {
return;
}
if ( !VALID_FNAME(asip->subtypes[asteroid_subtype].pof_filename) )
return;
//Check if the model is already loaded
if (asip->model_num[asteroid_subtype] >= 0)
if (asip->subtypes[asteroid_subtype].model_number >= 0)
return;
asip->model_num[asteroid_subtype] = model_load( asip->pof_files[asteroid_subtype], 0, NULL );
asip->subtypes[asteroid_subtype].model_number = model_load( asip->subtypes[asteroid_subtype].pof_filename );
if (asip->model_num[asteroid_subtype] >= 0)
if (asip->subtypes[asteroid_subtype].model_number >= 0)
{
polymodel *pm = asip->modelp[asteroid_subtype] = model_get(asip->model_num[asteroid_subtype]);
polymodel *pm = model_get(asip->subtypes[asteroid_subtype].model_number);
if ( asip->num_detail_levels != pm->n_detail_levels )
{
@@ -553,10 +598,11 @@ void asteroid_create_all()
// each different type (size) of debris piece has a diffenent weight, smaller weighted more heavily than larger.
// choose next type from table ship_debris_odds_table by Random::next()%max_weighted_range,
// the threshold *below* which the debris type is selected.
struct {
struct ShipDebrisOdds {
float random_threshold;
int debris_type;
} ship_debris_odds_table[MAX_ACTIVE_DEBRIS_TYPES];
};
std::vector<ShipDebrisOdds> shipDebrisOddsTable(Asteroid_field.field_debris_type.size());
float max_weighted_range = 0.0f;
@@ -567,7 +613,8 @@ void asteroid_create_all()
return;
}
if (Asteroid_field.num_used_field_debris_types <= 0) {
if ((Asteroid_field.debris_genre == DG_DEBRIS && Asteroid_field.field_debris_type.empty()) ||
(Asteroid_field.debris_genre == DG_ASTEROID && Asteroid_field.field_asteroid_type.empty())) {
Warning(LOCATION, "An asteroid field is enabled, but no asteroid types were enabled.");
return;
}
@@ -598,49 +645,33 @@ void asteroid_create_all()
return;
}
int max_asteroids = Asteroid_field.num_initial_asteroids; // * (1.0f - 0.1f*(MAX_DETAIL_LEVEL-Detail.asteroid_density)));
int max_asteroids = Asteroid_field.num_initial_asteroids; // * (1.0f - 0.1f*(MAX_DETAIL_VALUE-Detail.asteroid_density)));
int num_debris_types = 0;
// get number of ship debris types
// get number of debris types
if (Asteroid_field.debris_genre == DG_DEBRIS) {
for (idx=0; idx<MAX_ACTIVE_DEBRIS_TYPES; idx++) {
if (Asteroid_field.field_debris_type[idx] != -1) {
num_debris_types++;
}
}
num_debris_types = static_cast<int>(Asteroid_field.field_debris_type.size());
// Calculate the odds table
for (idx=0; idx<num_debris_types; idx++) {
float debris_weight = Asteroid_info[Asteroid_field.field_debris_type[idx]].spawn_weight;
ship_debris_odds_table[idx].random_threshold = max_weighted_range + debris_weight;
ship_debris_odds_table[idx].debris_type = Asteroid_field.field_debris_type[idx];
shipDebrisOddsTable[idx].random_threshold = max_weighted_range + debris_weight;
shipDebrisOddsTable[idx].debris_type = Asteroid_field.field_debris_type[idx];
max_weighted_range += debris_weight;
}
}
// Load Asteroid/ship models
// Load Asteroid/debris models
if (Asteroid_field.debris_genre == DG_DEBRIS) {
for (idx=0; idx<num_debris_types; idx++) {
asteroid_load(Asteroid_field.field_debris_type[idx], 0);
}
} else {
if (Asteroid_field.field_debris_type[0] != -1) {
asteroid_load(ASTEROID_TYPE_SMALL, 0);
asteroid_load(ASTEROID_TYPE_MEDIUM, 0);
asteroid_load(ASTEROID_TYPE_LARGE, 0);
}
if (Asteroid_field.field_debris_type[1] != -1) {
asteroid_load(ASTEROID_TYPE_SMALL, 1);
asteroid_load(ASTEROID_TYPE_MEDIUM, 1);
asteroid_load(ASTEROID_TYPE_LARGE, 1);
}
if (Asteroid_field.field_debris_type[2] != -1) {
asteroid_load(ASTEROID_TYPE_SMALL, 2);
asteroid_load(ASTEROID_TYPE_MEDIUM, 2);
asteroid_load(ASTEROID_TYPE_LARGE, 2);
for (const auto& subtype : Asteroid_field.field_asteroid_type) {
asteroid_load(ASTEROID_TYPE_SMALL, get_asteroid_subtype_index_by_name(subtype, ASTEROID_TYPE_SMALL));
asteroid_load(ASTEROID_TYPE_MEDIUM, get_asteroid_subtype_index_by_name(subtype, ASTEROID_TYPE_MEDIUM));
asteroid_load(ASTEROID_TYPE_LARGE, get_asteroid_subtype_index_by_name(subtype, ASTEROID_TYPE_LARGE));
}
}
@@ -650,17 +681,7 @@ void asteroid_create_all()
// For asteroid, load only large asteroids
// get a valid subtype
int counter = Random::next(Asteroid_field.num_used_field_debris_types);
int subtype = -1;
for (int j = 0; j < NUM_ASTEROID_POFS; j++) {
if (Asteroid_field.field_debris_type[j] >= 0) {
if (counter == 0) {
subtype = j;
break;
} else
counter--;
}
}
int subtype = get_asteroid_subtype_index_by_name(pick_random_asteroid_type(), ASTEROID_TYPE_LARGE);
if (subtype >= 0)
asteroid_create(&Asteroid_field, ASTEROID_TYPE_LARGE, subtype);
@@ -669,10 +690,10 @@ void asteroid_create_all()
float rand_choice = frand() * max_weighted_range;
for (idx=0; idx<MAX_ACTIVE_DEBRIS_TYPES; idx++) {
for (idx = 0; idx < static_cast<int>(Asteroid_field.field_debris_type.size()); idx++) {
// for ship debris, choose type according to odds table
if (rand_choice < ship_debris_odds_table[idx].random_threshold) {
asteroid_create(&Asteroid_field, ship_debris_odds_table[idx].debris_type, 0);
if (rand_choice < shipDebrisOddsTable[idx].random_threshold) {
asteroid_create(&Asteroid_field, shipDebrisOddsTable[idx].debris_type, 0);
break;
}
}
@@ -698,7 +719,7 @@ void remove_all_asteroids()
}
// will replace any existing asteroid or debris field with an asteroid field
void asteroid_create_asteroid_field(int num_asteroids, int field_type, int asteroid_speed, bool brown, bool blue, bool orange, vec3d o_min, vec3d o_max, bool inner_box, vec3d i_min, vec3d i_max, SCP_vector<SCP_string> targets)
void asteroid_create_asteroid_field(int num_asteroids, int field_type, int asteroid_speed, vec3d o_min, vec3d o_max, bool inner_box, vec3d i_min, vec3d i_max, SCP_vector<SCP_string> asteroid_types)
{
remove_all_asteroids();
@@ -732,25 +753,11 @@ void asteroid_create_asteroid_field(int num_asteroids, int field_type, int aster
Asteroid_field.speed = (float)asteroid_speed;
Asteroid_field.debris_genre = DG_ASTEROID;
Asteroid_field.field_debris_type[0] = -1;
Asteroid_field.field_debris_type[1] = -1;
Asteroid_field.field_debris_type[2] = -1;
Asteroid_field.field_debris_type.clear();
int count = 0;
if (brown) {
Asteroid_field.field_debris_type[0] = 1;
count++;
}
if (blue) {
Asteroid_field.field_debris_type[1] = 1;
count++;
}
if (orange) {
Asteroid_field.field_debris_type[2] = 1;
count++;
}
Asteroid_field.field_asteroid_type.clear();
Asteroid_field.num_used_field_debris_types = count;
Asteroid_field.field_asteroid_type = std::move(asteroid_types);
Asteroid_field.min_bound = o_min;
Asteroid_field.max_bound = o_max;
@@ -768,16 +775,14 @@ void asteroid_create_asteroid_field(int num_asteroids, int field_type, int aster
Asteroid_field.inner_max_bound = i_max;
}
Asteroid_field.target_names = targets;
// Only create asteroids if we have some to create
if ((count > 0) && (num_asteroids > 0)) {
if ((!Asteroid_field.field_asteroid_type.empty()) && (num_asteroids > 0)) {
asteroid_create_all();
}
}
// will replace any existing asteroid or debris field with a debris field
void asteroid_create_debris_field(int num_asteroids, int asteroid_speed, int debris1, int debris2, int debris3, vec3d o_min, vec3d o_max, bool enhanced)
void asteroid_create_debris_field(int num_asteroids, int asteroid_speed, SCP_vector<int> debris_types, vec3d o_min, vec3d o_max, bool enhanced)
{
remove_all_asteroids();
@@ -792,33 +797,11 @@ void asteroid_create_debris_field(int num_asteroids, int asteroid_speed, int deb
Asteroid_field.speed = (float)asteroid_speed;
Asteroid_field.debris_genre = DG_DEBRIS;
Asteroid_field.field_debris_type[0] = -1;
Asteroid_field.field_debris_type[1] = -1;
Asteroid_field.field_debris_type[2] = -1;
Asteroid_field.field_debris_type.clear();
int count = 0;
for (int i = 0; i < MAX_ACTIVE_DEBRIS_TYPES; i++) {
if (debris1 >= 0) {
Asteroid_field.field_debris_type[i] = debris1;
debris1 = -1;
count++;
continue;
}
if (debris2 >= 0) {
Asteroid_field.field_debris_type[i] = debris2;
debris2 = -1;
count++;
continue;
}
if (debris3 >= 0) {
Asteroid_field.field_debris_type[i] = debris3;
debris3 = -1;
count++;
continue;
}
}
Asteroid_field.field_asteroid_type.clear();
Asteroid_field.num_used_field_debris_types = count;
Asteroid_field.field_debris_type = std::move(debris_types);
Asteroid_field.min_bound = o_min;
Asteroid_field.max_bound = o_max;
@@ -831,7 +814,7 @@ void asteroid_create_debris_field(int num_asteroids, int asteroid_speed, int deb
Asteroid_field.bound_rad = MAX(3000.0f, b_rad);
// Only create debris if we have some to create
if ((count > 0) && (num_asteroids > 0)) {
if ((!Asteroid_field.field_debris_type.empty()) && (num_asteroids > 0)) {
asteroid_create_all();
}
}
@@ -850,10 +833,8 @@ void asteroid_level_init()
Asteroid_field.has_inner_bound = false;
Asteroid_field.field_type = FT_ACTIVE;
Asteroid_field.debris_genre = DG_ASTEROID;
Asteroid_field.field_debris_type[0] = -1;
Asteroid_field.field_debris_type[1] = -1;
Asteroid_field.field_debris_type[2] = -1;
Asteroid_field.num_used_field_debris_types = 0;
Asteroid_field.field_debris_type.clear();
Asteroid_field.field_asteroid_type.clear();
Asteroid_field.target_names.clear();
if (!Fred_running)
@@ -1049,6 +1030,7 @@ bool asteroid_is_within_view(vec3d *pos, float range, bool range_override)
*/
static void maybe_throw_asteroid()
{
Assertion(!Asteroid_field.field_asteroid_type.empty(), "maybe_throw_asteroid() called while field_asteroid_type.size was 0; this should never happen, get a coder!");
for (asteroid_target& target : Asteroid_targets) {
if (!timestamp_elapsed(target.throw_stamp))
@@ -1066,36 +1048,26 @@ static void maybe_throw_asteroid()
target.throw_stamp = _timestamp(1000 + 1200 * target.incoming_asteroids / (Game_skill_level+1));
int counter = Random::next(Asteroid_field.num_used_field_debris_types);
int subtype = -1;
for (int i = 0; i < NUM_ASTEROID_POFS; i++) {
if (Asteroid_field.field_debris_type[i] >= 0) {
if (counter == 0) {
subtype = i;
break;
}
else
counter--;
}
}
// get a valid subtype
int subtype = get_asteroid_subtype_index_by_name(pick_random_asteroid_type(), ASTEROID_TYPE_LARGE);
// this really shouldn't happen but just in case...
if (subtype < 0)
return;
object *objp = asteroid_create(&Asteroid_field, ASTEROID_TYPE_LARGE, subtype, Asteroid_field.enhanced_visibility_checks);
if (objp != nullptr) {
asteroid_aim_at_target(target_objp, objp, ASTEROID_MIN_COLLIDE_TIME + frand() * 20.0f);
object *ast_objp = asteroid_create(&Asteroid_field, ASTEROID_TYPE_LARGE, subtype, Asteroid_field.enhanced_visibility_checks);
if (ast_objp != nullptr) {
asteroid_aim_at_target(target_objp, ast_objp, ASTEROID_MIN_COLLIDE_TIME + frand() * 20.0f);
// if asteroid is inside inner bound, kill it
if (asteroid_in_inner_bound(&Asteroid_field, &objp->pos, 0.0f)) {
objp->flags.set(Object::Object_Flags::Should_be_dead);
if (asteroid_in_inner_bound(&Asteroid_field, &ast_objp->pos, 0.0f)) {
ast_objp->flags.set(Object::Object_Flags::Should_be_dead);
} else {
Asteroids[objp->instance].target_objnum = target.objnum;
Asteroids[ast_objp->instance].target_objnum = target.objnum;
target.incoming_asteroids++;
if ( MULTIPLAYER_MASTER ) {
send_asteroid_throw( objp );
send_asteroid_throw( ast_objp );
}
}
}
@@ -1254,7 +1226,7 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
// asteroid weapon collision
Assert( other_obj->type == OBJ_WEAPON );
mc.model_instance_num = Asteroids[num].model_instance_num;
mc.model_num = Asteroid_info[Asteroids[num].asteroid_type].model_num[asteroid_subtype]; // Fill in the model to check
mc.model_num = Asteroid_info[Asteroids[num].asteroid_type].subtypes[asteroid_subtype].model_number; // Fill in the model to check
mc.orient = &pasteroid->orient; // The object's orient
mc.pos = &pasteroid->pos; // The object's position
mc.p0 = &other_obj->last_pos; // Point 1 of ray to check
@@ -1435,7 +1407,7 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
} else {
// Asteroid is heavier obj
mc.model_instance_num = Asteroids[num].model_instance_num;
mc.model_num = Asteroid_info[Asteroids[num].asteroid_type].model_num[asteroid_subtype]; // Fill in the model to check
mc.model_num = Asteroid_info[Asteroids[num].asteroid_type].subtypes[asteroid_subtype].model_number; // Fill in the model to check
mc.orient = &pasteroid->orient; // The object's orient
mc.radius = model_get_core_radius(Ship_info[Ships[pship_obj->instance].ship_info_index].model_num);
@@ -1516,14 +1488,62 @@ void asteroid_render(object * obj, model_draw_list *scene)
Assert( asp->flags & AF_USED );
model_clear_instance( Asteroid_info[asp->asteroid_type].model_num[asp->asteroid_subtype]);
model_clear_instance( Asteroid_info[asp->asteroid_type].subtypes[asp->asteroid_subtype].model_number);
model_render_params render_info;
render_info.set_object_number( OBJ_INDEX(obj) );
render_info.set_flags(MR_IS_ASTEROID);
uint64_t render_flags = MR_IS_ASTEROID;
model_render_queue(&render_info, scene, Asteroid_info[asp->asteroid_type].model_num[asp->asteroid_subtype], &obj->orient, &obj->pos); // Replace MR_NORMAL with 0x07 for big yellow blobs
if (asp->render_flags[Object::Raw_Pof_Flags::Render_without_light])
render_flags |= MR_NO_LIGHTING;
if (asp->render_flags[Object::Raw_Pof_Flags::Glowmaps_disabled]) {
render_flags |= MR_NO_GLOWMAPS;
}
if (asp->render_flags[Object::Raw_Pof_Flags::Draw_as_wireframe]) {
render_flags |= MR_SHOW_OUTLINE_HTL | MR_NO_POLYS | MR_NO_TEXTURING;
render_info.set_color(Wireframe_color);
}
if (asp->render_flags[Object::Raw_Pof_Flags::Render_full_detail]) {
render_flags |= MR_FULL_DETAIL;
}
uint debug_flags = render_info.get_debug_flags();
if (asp->render_flags[Object::Raw_Pof_Flags::Render_without_diffuse]) {
debug_flags |= MR_DEBUG_NO_DIFFUSE;
}
if (asp->render_flags[Object::Raw_Pof_Flags::Render_without_glowmap]) {
debug_flags |= MR_DEBUG_NO_GLOW;
}
if (asp->render_flags[Object::Raw_Pof_Flags::Render_without_normalmap]) {
debug_flags |= MR_DEBUG_NO_NORMAL;
}
if (asp->render_flags[Object::Raw_Pof_Flags::Render_without_ambientmap]) {
debug_flags |= MR_DEBUG_NO_AMBIENT;
}
if (asp->render_flags[Object::Raw_Pof_Flags::Render_without_specmap]) {
debug_flags |= MR_DEBUG_NO_SPEC;
}
if (asp->render_flags[Object::Raw_Pof_Flags::Render_without_reflectmap]) {
debug_flags |= MR_DEBUG_NO_REFLECT;
}
render_info.set_object_number( OBJ_INDEX(obj) );
render_info.set_flags(render_flags);
render_info.set_debug_flags(debug_flags);
if (asp->model_instance_num >= 0)
render_info.set_replacement_textures(model_get_instance(asp->model_instance_num)->texture_replace);
model_render_queue(&render_info, scene, Asteroid_info[asp->asteroid_type].subtypes[asp->asteroid_subtype].model_number, &obj->orient, &obj->pos); // Replace MR_NORMAL with 0x07 for big yellow blobs
}
}
@@ -1592,9 +1612,8 @@ static float asteroid_create_explosion(object *objp)
fireball_type = FIREBALL_ASTEROID;
}
if (fireball_type >= Num_fireball_types) {
Warning(LOCATION, "Invalid fireball type %i specified for an asteroid, only %i fireball types are defined.", fireball_type, Num_fireball_types);
if (fireball_type >= static_cast<int>(Fireball_info.size())) {
Warning(LOCATION, "Invalid fireball type %i specified for an asteroid; only " SIZE_T_ARG " fireball types are defined.", fireball_type, Fireball_info.size());
return 0;
}
@@ -1733,7 +1752,7 @@ void asteroid_hit( object * pasteroid_obj, object * other_obj, vec3d * hitpos, f
wip = &Weapon_info[Weapons[other_obj->instance].weapon_info_index];
// If the weapon didn't play any impact animation, play custom asteroid impact animation
if (!wip->impact_weapon_expl_effect.isValid()) {
particle::create( hitpos, &vmd_zero_vector, 0.0f, Asteroid_impact_explosion_radius, particle::PARTICLE_BITMAP, Asteroid_impact_explosion_ani );
particle::create( hitpos, &vmd_zero_vector, 0.0f, Asteroid_impact_explosion_radius, Asteroid_impact_explosion_ani );
}
}
}
@@ -1758,9 +1777,9 @@ void asteroid_level_close()
//when a level is closed, all models are cleared, so let's make sure that
//is tracked for asteroids as well -Mjn
for (int i = 0; i < (int)Asteroid_info.size(); i++) {
for (int j = 0; j < NUM_ASTEROID_POFS; j++) {
Asteroid_info[i].model_num[j] = -1;
for (size_t i = 0; i < Asteroid_info.size(); i++) {
for (size_t j = 0; j < Asteroid_info[i].subtypes.size(); j++) {
Asteroid_info[i].subtypes[j].model_number = -1;
}
}
@@ -1856,7 +1875,8 @@ static void asteroid_maybe_break_up(object *pasteroid_obj)
roids_to_create.push_back(split->asteroid_type);
}
random_shuffle(roids_to_create.begin(), roids_to_create.end());
std::random_device rd;
std::shuffle(roids_to_create.begin(), roids_to_create.end(), std::mt19937(rd()));
size_t total_roids = roids_to_create.size();
for (size_t i = 0; i < total_roids; i++) {
@@ -2218,16 +2238,78 @@ static void asteroid_parse_section()
asteroid_p->type = ASTEROID_TYPE_DEBRIS;
}
auto insert_or_replace_subtype_pof = [](SCP_vector<asteroid_subtype_info>& subtypes, const asteroid_subtype_info& new_subtype) {
for (auto& subtype : subtypes) {
if (lcase_equal(subtype.type_name, new_subtype.type_name)) {
strcpy_s(subtype.pof_filename, new_subtype.pof_filename);
return;
}
}
subtypes.push_back(new_subtype);
};
if (optional_string("$POF file1:")) {
stuff_string(asteroid_p->pof_files[0], F_NAME, MAX_FILENAME_LEN);
asteroid_subtype_info thisType;
thisType.type_name = "Brown";
stuff_string(thisType.pof_filename, F_NAME, MAX_FILENAME_LEN);
thisType.model_number = -1;
insert_or_replace_subtype_pof(asteroid_p->subtypes, thisType);
}
if (optional_string("$POF file2:")) {
stuff_string(asteroid_p->pof_files[1], F_NAME, MAX_FILENAME_LEN);
asteroid_subtype_info thisType;
thisType.type_name = "Blue";
stuff_string(thisType.pof_filename, F_NAME, MAX_FILENAME_LEN);
thisType.model_number = -1;
insert_or_replace_subtype_pof(asteroid_p->subtypes, thisType);
}
if (optional_string("$POF file3:")) {
stuff_string(asteroid_p->pof_files[2], F_NAME, MAX_FILENAME_LEN);
asteroid_subtype_info thisType;
thisType.type_name = "Orange";
stuff_string(thisType.pof_filename, F_NAME, MAX_FILENAME_LEN);
thisType.model_number = -1;
insert_or_replace_subtype_pof(asteroid_p->subtypes, thisType);
}
// For asteroid types we can have unlimited subtypes
if (asteroid_p->type != ASTEROID_TYPE_DEBRIS) {
while (optional_string("$Subtype:")) {
asteroid_subtype_info thisType;
stuff_string(thisType.type_name, F_NAME);
required_string("+POF file:");
stuff_string(thisType.pof_filename, F_NAME, MAX_FILENAME_LEN);
thisType.model_number = -1;
bool exists = false;
for (const auto& type : asteroid_p->subtypes) {
if (type.type_name == thisType.type_name) {
exists = true;
}
}
if (exists) {
error_display(0,
"Asteroid subtype %s already exists for asteroid %s",
thisType.type_name.c_str(),
asteroid_p->name);
} else {
asteroid_p->subtypes.push_back(thisType);
}
}
}
if (optional_string("$Detail distance:")) {
@@ -2250,10 +2332,7 @@ static void asteroid_parse_section()
}
if(optional_string("$Explosion Animations:")){
int temp[MAX_FIREBALL_TYPES];
auto parsed_ints = stuff_int_list(temp, MAX_FIREBALL_TYPES, RAW_INTEGER_TYPE);
asteroid_p->explosion_bitmap_anims.clear();
asteroid_p->explosion_bitmap_anims.insert(asteroid_p->explosion_bitmap_anims.begin(), temp, temp + parsed_ints);
stuff_fireball_index_list(asteroid_p->explosion_bitmap_anims, asteroid_p->name);
}
if (optional_string("$Explosion Radius Mult:")) {
@@ -2419,7 +2498,7 @@ static void asteroid_parse_tbl(const char* filename)
// Gets the index of an asteroid by name from Asteroid_info
int get_asteroid_index(const char* asteroid_name)
{
for (int i = 0; i < (int)Asteroid_info.size(); i++) {
for (int i = 0; i < static_cast<int>(Asteroid_info.size()); i++) {
if (!stricmp(asteroid_name, Asteroid_info[i].name)) {
return i;
}
@@ -2428,6 +2507,31 @@ int get_asteroid_index(const char* asteroid_name)
return -1;
}
// For FRED. Gets a list of unique asteroid subtype names
SCP_vector<SCP_string> get_list_valid_asteroid_subtypes()
{
SCP_vector<SCP_string> list;
for (const auto& this_asteroid : Asteroid_info) {
if (this_asteroid.type != ASTEROID_TYPE_DEBRIS) {
for (const auto& subtype : this_asteroid.subtypes) {
bool exists = false;
for (const auto& entry : list) {
if (subtype.type_name == entry) {
exists = true;
}
}
if (!exists) {
list.push_back(subtype.type_name);
}
}
}
}
return list;
}
static void verify_asteroid_splits()
{
@@ -2486,7 +2590,14 @@ static void verify_asteroid_list()
}
// Rest should be debris type
for (int i = 0; i < (int)asteroid_list.size(); i++) {
// Remove all subtypes except the first one
asteroid_list[i].subtypes.resize(1);
// Make sure the first subtype is set as debris
asteroid_list[i].subtypes[0].type_name = "Debris";
if (asteroid_list[i].type < 0) {
Asteroid_info.push_back(asteroid_list[i]);
} else {
@@ -2500,14 +2611,8 @@ static void verify_asteroid_list()
//Check that we have the appropriate POF files-Mjn
for (int i = 0; i < (int)Asteroid_info.size(); i++) {
if (Asteroid_info[i].pof_files[0][0] == '\0')
Error(LOCATION, "Missing [POF File 1] for %s", Asteroid_info[i].name);
if (Asteroid_info[i].type != ASTEROID_TYPE_DEBRIS) {
if (Asteroid_info[i].pof_files[1][0] == '\0')
Error(LOCATION, "Missing [POF File 2] for %s", Asteroid_info[i].name);
if (Asteroid_info[i].pof_files[2][0] == '\0')
Error(LOCATION, "Missing [POF File 3] for %s", Asteroid_info[i].name);
if (Asteroid_info[i].subtypes.size() == 0) {
Error(LOCATION, "Asteroid %s needs at least one subtype!", Asteroid_info[i].name);
}
}
}
@@ -2544,7 +2649,7 @@ void asteroid_init()
}
if (Asteroid_icon_closeup_model[0] == '\0')
strcpy_s(Asteroid_icon_closeup_model, Asteroid_info[ASTEROID_TYPE_LARGE].pof_files[0]); // magic file from retail
strcpy_s(Asteroid_icon_closeup_model, Asteroid_info[ASTEROID_TYPE_LARGE].subtypes[0].pof_filename); // magic file from retail
}
@@ -2584,6 +2689,11 @@ void asteroid_frame()
return;
}
// If no asteroid types are defined for the field, abort.
if (Asteroid_field.field_asteroid_type.empty()) {
return;
}
// If there are no explicit targets, fall back to default retail targeting behavior
if (Asteroid_field.target_names.empty()) {
int objnum = set_asteroid_throw_objnum();
@@ -2692,21 +2802,26 @@ void asteroid_page_in()
return;
if (Asteroid_field.num_initial_asteroids > 0 ) {
int i, j, k;
nprintf(( "Paging", "Paging in asteroids\n" ));
size_t num_debris_types = NUM_ASTEROID_SIZES;
if (Asteroid_field.debris_genre == DG_DEBRIS) {
num_debris_types = Asteroid_field.field_debris_type.size();
}
// max of MAX_ACTIVE_DEBRIS_TYPES possible debris field models
for (i=0; i<MAX_ACTIVE_DEBRIS_TYPES; i++) {
// for asteroids this will loop over all three possible sizes
// for debris this will loop over all selected types
for (size_t i = 0; i < num_debris_types; i++) {
asteroid_info *asip;
if (Asteroid_field.debris_genre == DG_ASTEROID) {
// asteroid
Assertion(i < NUM_ASTEROID_SIZES, "Got invalid call to load a debris type instead of asteroid type!");
Assertion(i < NUM_ASTEROID_SIZES, "Got invalid call to load non-existent asteroid size!");
asip = &Asteroid_info[i];
} else {
// ship debris - always full until empty
// debris - always full until empty
if (Asteroid_field.field_debris_type[i] != -1) {
asip = &Asteroid_info[Asteroid_field.field_debris_type[i]];
} else {
@@ -2715,28 +2830,36 @@ void asteroid_page_in()
}
for (k=0; k<NUM_ASTEROID_POFS; k++) {
for (size_t k = 0; k < asip->subtypes.size(); k++) {
// SHIP DEBRIS - use subtype 0
// DEBRIS FIELDS - always use subtype 0
if (Asteroid_field.debris_genre == DG_DEBRIS) {
if (k > 0) {
break;
}
} else {
// ASTEROID DEBRIS - use subtype (Asteroid_field.field_debris_type[] != -1)
if (Asteroid_field.field_debris_type[k] == -1) {
// ASTEROID FIELDS - use subtype k, if active
bool active = false;
for (const auto& active_type : Asteroid_field.field_asteroid_type) {
if (active_type == asip->subtypes[k].type_name) {
active = true;
}
}
if (!active) {
continue;
}
}
if (asip->model_num[k] < 0)
// model is already paged in
if (asip->subtypes[k].model_number < 0)
continue;
asip->modelp[k] = model_get(asip->model_num[k]);
const auto mp = model_get(asip->subtypes[k].model_number);
// Page in textures
for (j=0; j<asip->modelp[k]->n_textures; j++ ) {
asip->modelp[k]->maps[j].PageIn();
for (int j = 0; j < mp->n_textures; j++) {
mp->maps[j].PageIn();
}
}
+23 -20
View File
@@ -14,6 +14,7 @@
#include "globalincs/globals.h" // for NAME_LENGTH
#include "globalincs/pstypes.h"
#include "object/object_flags.h"
#include "io/timer.h"
class object;
@@ -24,15 +25,14 @@ class model_draw_list;
#define MAX_ASTEROIDS 2000 //Increased from 512 to 2000 in 2022
#define NUM_ASTEROID_SIZES 3
#define NUM_ASTEROID_POFS 3 // Number of POFs per debris size
#define ASTEROID_TYPE_DEBRIS -1
#define ASTEROID_TYPE_SMALL 0
#define ASTEROID_TYPE_MEDIUM 1
#define ASTEROID_TYPE_LARGE 2
// these should always be equal for the benefit of generic asteroids (c.f. asteroid_page_in)
#define MAX_ACTIVE_DEBRIS_TYPES NUM_ASTEROID_SIZES
// Only used for parsing & saving retail compatible mission files
#define MAX_RETAIL_DEBRIS_TYPES 3
// Goober5000 - currently same as MAX_SHIP_DETAIL_LEVELS (put here to avoid an #include)
#define MAX_ASTEROID_DETAIL_LEVELS 5
@@ -54,13 +54,19 @@ typedef struct asteroid_split_info {
int max; //maximum asteroids to spawn
} asteroid_split_info;
// Data structure for storing asteroid subtype info. POFs, model pointer, model num, etc.
typedef struct asteroid_subtype_info {
char pof_filename[MAX_FILENAME_LEN];
int model_number;
SCP_string type_name;
} asteroid_subtype_info;
class asteroid_info
{
public:
char name[NAME_LENGTH]; // name for the asteroid
int type; // type of asteroid, 0 = small, 1 = medium, 2 = large, -1 = debris
char pof_files[NUM_ASTEROID_POFS][MAX_FILENAME_LEN]; // POF files to load/associate with ship
int num_detail_levels; // number of detail levels for this ship
int num_detail_levels; // number of detail levels for this asteroid
int detail_distance[MAX_ASTEROID_DETAIL_LEVELS]; // distance to change detail levels at
float max_speed; // cap on speed for asteroid
float rotational_vel_multiplier; // rotational velocity multiplier for asteroid --wookieejedi
@@ -72,13 +78,12 @@ public:
float blast; // maximum blast impulse from area effect explosion
float initial_asteroid_strength; // starting strength of asteroid
SCP_vector< asteroid_split_info > split_info;
polymodel *modelp[NUM_ASTEROID_POFS];
int model_num[NUM_ASTEROID_POFS];
SCP_vector<int> explosion_bitmap_anims;
float fireball_radius_multiplier; // the model radius is multiplied by this to determine the fireball size
SCP_string display_name; // only used for hud targeting display and for 'ship' asteroids
float spawn_weight; // ship asteroids only, relative proportion to spawn compared to other types in its asteroid field
SCP_string display_name; // only used for hud targeting display and for debris
float spawn_weight; // debris only, relative proportion to spawn compared to other types in its asteroid field
float gravity_const; // multiplier for mission gravity
SCP_vector<asteroid_subtype_info> subtypes;
asteroid_info( )
: type(ASTEROID_TYPE_DEBRIS), num_detail_levels(0), max_speed(0),
@@ -90,13 +95,6 @@ public:
name[ 0 ] = 0;
display_name = "";
memset( detail_distance, 0, sizeof( detail_distance ) );
for (int i = 0; i < NUM_ASTEROID_POFS; i++)
{
modelp[i] = NULL;
model_num[i] = -1;
pof_files[i][0] = '\0';
}
}
};
@@ -105,6 +103,7 @@ public:
typedef struct asteroid {
int flags;
flagset<Object::Raw_Pof_Flags> render_flags; // Render flags
int objnum;
int model_instance_num;
int asteroid_type; // 0..MAX_DEBRIS_TYPES
@@ -143,8 +142,8 @@ typedef struct asteroid_field {
int num_initial_asteroids; // Number of asteroids at creation.
field_type_t field_type; // active throws and wraps, passive does not
debris_genre_t debris_genre; // type of debris (ship or asteroid) [generic type]
int field_debris_type[MAX_ACTIVE_DEBRIS_TYPES]; // one of the debris type defines above
int num_used_field_debris_types; // how many of the above are used
SCP_vector<int> field_debris_type; // one of the debris type defines above
SCP_vector<SCP_string> field_asteroid_type; // one of the asteroid subtypes
bool enhanced_visibility_checks; // if true then range checks are overridden for spawning and wrapping asteroids in the field
SCP_vector<SCP_string> target_names; // default retail behavior is to just throw at the first big ship in the field
@@ -165,8 +164,8 @@ bool asteroid_is_within_view(vec3d *pos, float range, bool range_override = f
void asteroid_level_init();
void asteroid_level_close();
void asteroid_create_all();
void asteroid_create_asteroid_field(int num_asteroids, int field_type, int asteroid_speed, bool brown, bool blue, bool orange, vec3d o_min, vec3d o_max, bool inner_box, vec3d i_min, vec3d i_max, SCP_vector<SCP_string> targets);
void asteroid_create_debris_field(int num_asteroids, int asteroid_speed, int debris1, int debris2, int debris3, vec3d o_min, vec3d o_max, bool enhanced);
void asteroid_create_asteroid_field(int num_asteroids, int field_type, int asteroid_speed, vec3d o_min, vec3d o_max, bool inner_box, vec3d i_min, vec3d i_max, SCP_vector<SCP_string> asteroid_types);
void asteroid_create_debris_field(int num_asteroids, int asteroid_speed, SCP_vector<int> debris_types, vec3d o_min, vec3d o_max, bool enhanced);
void asteroid_render(object* obj, model_draw_list* scene);
void asteroid_delete( object *asteroid_objp );
void asteroid_process_pre( object *asteroid_objp );
@@ -180,6 +179,10 @@ void asteroid_show_brackets();
void asteroid_target_closest_danger();
void asteroid_add_target(object* objp);
int get_asteroid_index(const char* asteroid_name);
SCP_vector<SCP_string> get_list_valid_asteroid_subtypes();
// extern for the lab
void asteroid_load(int asteroid_info_index, int asteroid_subtype);
// need to extern for keycontrol debug commands
object *asteroid_create(asteroid_field *asfieldp, int asteroid_type, int asteroid_subtype, bool check_visibility = false);
+32 -27
View File
@@ -30,7 +30,7 @@
#include <map>
// Extern functions/variables
extern int Player_use_ai;
extern bool Player_use_ai;
extern int get_wing_index(object *objp, int wingnum);
extern object * get_wing_leader(int wingnum);
extern int Cmdline_autopilot_interruptable;
@@ -66,7 +66,7 @@ int start_dist;
void autopilot_ai_waypoint_goal_fixup(ai_goal* aigp)
{
// this function sets wp_index properly;
aigp->wp_list = find_matching_waypoint_list(aigp->target_name);
aigp->wp_list_index = find_matching_waypoint_list_index(aigp->target_name);
}
@@ -111,13 +111,15 @@ const vec3d *NavPoint::GetPosition()
{
if (flags & NP_WAYPOINT)
{
waypoint *wpt = find_waypoint_at_index((waypoint_list*) target_obj, waypoint_num-1);
Assert(wpt != NULL);
auto wpt = find_waypoint_at_indexes(target_index, waypoint_num-1);
Assert(wpt != nullptr);
if (wpt == nullptr)
return &vmd_zero_vector;
return wpt->get_pos();
}
else
{
return &Objects[((ship*) target_obj)->objnum].pos;
return &Objects[target_index].pos;
}
}
@@ -239,7 +241,7 @@ bool StartAutopilot()
// is support ship trying to rearm-repair
if ( ai_find_goal_index( support_ship_aip->goals, AI_GOAL_REARM_REPAIR ) == -1 ) {
// no, so tell it to depart
ai_add_ship_goal_player( AIG_TYPE_PLAYER_SHIP, AI_GOAL_WARP, -1, NULL, support_ship_aip );
ai_add_ship_goal_player( ai_goal_type::PLAYER_SHIP, AI_GOAL_WARP, -1, nullptr, support_ship_aip );
} else {
// yes
send_autopilot_msgID(NP_MSG_FAIL_SUPPORT_WORKING);
@@ -268,7 +270,7 @@ bool StartAutopilot()
LockAPConv = _timestamp(); // lock convergence instantly
else
LockAPConv = _timestamp(3 * MILLISECONDS_PER_SECOND); // 3 seconds before we lock convergence
Player_use_ai = 1;
Player_use_ai = true;
set_time_compression(1);
lock_time_compression(true);
@@ -298,15 +300,16 @@ bool StartAutopilot()
autopilot_wings.clear();
// vars for usage w/ cinematic
vec3d pos, norm1, perp, tpos, rpos = Player_obj->pos, zero;
vec3d pos, perp, tpos, rpos = Player_obj->pos, zero;
memset(&zero, 0, sizeof(vec3d));
// instantly turn player toward tpos
if (The_mission.flags[Mission::Mission_Flags::Use_ap_cinematics])
{
vm_vec_sub(&norm1, Navs[CurrentNav].GetPosition(), &Player_obj->pos);
vm_vector_2_matrix(&Player_obj->orient, &norm1, NULL, NULL);
vec3d norm1;
vm_vec_normalized_dir(&norm1, Navs[CurrentNav].GetPosition(), &Player_obj->pos);
vm_vector_2_matrix_norm(&Player_obj->orient, &norm1, nullptr, nullptr);
}
for (i = 0; i < MAX_SHIPS; i++)
@@ -393,10 +396,12 @@ bool StartAutopilot()
radius = Objects[Ships[i].objnum].radius;
}
// instantly turn the ship to match the direction player is looking
if (The_mission.flags[Mission::Mission_Flags::Use_ap_cinematics])
{// instantly turn the ship to match the direction player is looking
//vm_vec_sub(&norm1, Navs[CurrentNav].GetPosition(), &Player_obj->pos);
vm_vector_2_matrix(&Objects[Ships[i].objnum].orient, &norm1, NULL, NULL);
{
vec3d norm1;
vm_vec_normalized_dir(&norm1, Navs[CurrentNav].GetPosition(), &Player_obj->pos);
vm_vector_2_matrix_norm(&Objects[Ships[i].objnum].orient, &norm1, nullptr, nullptr);
}
// snap wings into formation
@@ -462,12 +467,12 @@ bool StartAutopilot()
{
if (Navs[CurrentNav].flags & NP_WAYPOINT)
{
ai_add_ship_goal_player( AIG_TYPE_PLAYER_SHIP, AI_GOAL_WAYPOINTS_ONCE, 0, ((waypoint_list*)Navs[CurrentNav].target_obj)->get_name(), &Ai_info[Ships[i].ai_index] );
ai_add_ship_goal_player( ai_goal_type::PLAYER_SHIP, AI_GOAL_WAYPOINTS_ONCE, 0, Waypoint_lists[Navs[CurrentNav].target_index].get_name(), &Ai_info[Ships[i].ai_index] );
//fixup has to wait until after wing goals
}
else
{
ai_add_ship_goal_player( AIG_TYPE_PLAYER_SHIP, AI_GOAL_FLY_TO_SHIP, 0, ((ship*)Navs[CurrentNav].target_obj)->ship_name, &Ai_info[Ships[i].ai_index] );
ai_add_ship_goal_player( ai_goal_type::PLAYER_SHIP, AI_GOAL_FLY_TO_SHIP, 0, Ships[Objects[Navs[CurrentNav].target_index].instance].ship_name, &Ai_info[Ships[i].ai_index] );
}
}
@@ -483,15 +488,15 @@ bool StartAutopilot()
{
//ai_add_ship_goal_player( int type, int mode, int submode, char *shipname, ai_info *aip );
//ai_add_wing_goal_player( AIG_TYPE_PLAYER_WING, AI_GOAL_STAY_NEAR_SHIP, 0, target_shipname, wingnum );
//ai_add_wing_goal_player( AIG_TYPE_PLAYER_WING, AI_GOAL_WAYPOINTS_ONCE, 0, target_shipname, wingnum );
//ai_add_wing_goal_player( ai_goal_type::PLAYER_WING, AI_GOAL_STAY_NEAR_SHIP, 0, target_shipname, wingnum );
//ai_add_wing_goal_player( ai_goal_type::PLAYER_WING, AI_GOAL_WAYPOINTS_ONCE, 0, target_shipname, wingnum );
//ai_clear_ship_goals( &(Ai_info[Ships[num].ai_index]) );
ai_clear_wing_goals( &Wings[i] );
if (Navs[CurrentNav].flags & NP_WAYPOINT)
{
ai_add_wing_goal_player( AIG_TYPE_PLAYER_WING, AI_GOAL_WAYPOINTS_ONCE, 0, ((waypoint_list*)Navs[CurrentNav].target_obj)->get_name(), i );
ai_add_wing_goal_player( ai_goal_type::PLAYER_WING, AI_GOAL_WAYPOINTS_ONCE, 0, Waypoint_lists[Navs[CurrentNav].target_index].get_name(), i );
// "fix up" the goal
for (j = 0; j < MAX_AI_GOALS; j++)
@@ -505,7 +510,7 @@ bool StartAutopilot()
}
else
{
ai_add_wing_goal_player( AIG_TYPE_PLAYER_WING, AI_GOAL_FLY_TO_SHIP, 0, ((ship*)Navs[CurrentNav].target_obj)->ship_name, i );
ai_add_wing_goal_player( ai_goal_type::PLAYER_WING, AI_GOAL_FLY_TO_SHIP, 0, Ships[Objects[Navs[CurrentNav].target_index].instance].ship_name, i );
}
}
@@ -853,7 +858,7 @@ void EndAutoPilot()
set_time_compression(1);
lock_time_compression(false);
Player_use_ai = 0;
Player_use_ai = false;
//Clear AI Goals
if (CinematicStarted) // clear cinematic if we need to
@@ -874,12 +879,12 @@ void EndAutoPilot()
if (Navs[CurrentNav].flags & NP_WAYPOINT)
{
goal = AI_GOAL_WAYPOINTS_ONCE;
goal_name = ((waypoint_list*)Navs[CurrentNav].target_obj)->get_name();
goal_name = Waypoint_lists[Navs[CurrentNav].target_index].get_name();
}
else
{
goal = AI_GOAL_FLY_TO_SHIP;
goal_name = ((ship*)Navs[CurrentNav].target_obj)->ship_name;
goal_name = Ships[Objects[Navs[CurrentNav].target_index].instance].ship_name;
}
// assign ship goals
@@ -1094,9 +1099,9 @@ void NavSystem_Do()
for (i = 0; i < MAX_NAVPOINTS; i++)
{
if ((Navs[i].flags & NP_SHIP) && (Navs[i].target_obj != NULL))
if ((Navs[i].flags & NP_SHIP) && (Navs[i].target_index >= 0))
{
if (((ship*)Navs[i].target_obj)->objnum == -1)
if (Objects[Navs[i].target_index].flags[Object::Object_Flags::Should_be_dead])
{
if (CurrentNav == i)
CurrentNav = -1;
@@ -1108,7 +1113,7 @@ void NavSystem_Do()
// check if we're reached a Node
for (i = 0; i < MAX_NAVPOINTS; i++)
{
if (Navs[i].target_obj != NULL)
if (Navs[i].target_index >= 0)
{
if (Navs[i].flags & NP_VALIDTYPE && DistanceTo(i) < 1000)
Navs[i].flags |= NP_VISITED;
@@ -1392,7 +1397,7 @@ bool AddNav_Ship(const char *Nav, const char *TargetName, int flags)
{
if (Ships[i].objnum != -1 && !stricmp(TargetName, Ships[i].ship_name))
{
tnav.target_obj = (void *)&Ships[i];
tnav.target_index = Ships[i].objnum;
}
}
@@ -1433,7 +1438,7 @@ bool AddNav_Waypoint(const char *Nav, const char *WP_Path, int node, int flags)
Assert(!(tnav.flags & NP_SHIP));
tnav.target_obj = find_matching_waypoint_list(WP_Path);
tnav.target_index = find_matching_waypoint_list_index(WP_Path);
tnav.waypoint_num = node;
// copy it into it's location
+2 -2
View File
@@ -34,7 +34,7 @@ public:
ubyte normal_color[3] = { 0x80, 0x80, 0xFF };
ubyte visited_color[3] = { 0xFF, 0xFF, 0x00 };
const void *target_obj = nullptr;
int target_index = -1; //waypoint list index if NP_WAYPOINT, otherwise object index
int waypoint_num = -1; //only used when flags & NP_WAYPOINT
const vec3d *GetPosition();
@@ -53,7 +53,7 @@ public:
visited_color[1] = 0xFF;
visited_color[2] = 0x00;
target_obj = nullptr;
target_index = -1;
waypoint_num = -1;
}
};
-4
View File
@@ -1027,10 +1027,6 @@ int bm_is_compressed(int num) {
auto entry = bm_get_entry(num);
BM_TYPE type = BM_TYPE_NONE;
//duh
if (!Use_compressed_textures)
return 0;
type = entry->comp_type;
switch (type) {
+106 -77
View File
@@ -14,8 +14,8 @@
#include "ship/ship.h" //compute_slew_matrix
//*************************IMPORTANT GLOBALS*************************
fov_t VIEWER_ZOOM_DEFAULT = 0.75f; // Default viewer zoom, 0.625 as per multi-lateral agreement on 3/24/97
fov_t COCKPIT_ZOOM_DEFAULT = 0.75f;
fov_t VIEWER_ZOOM_DEFAULT = DEFAULT_FOV;
fov_t COCKPIT_ZOOM_DEFAULT = DEFAULT_FOV;
float Sexp_fov = 0.0f;
warp_camera Warp_camera;
@@ -48,12 +48,15 @@ struct apply_##name##_to_fov { \
} \
}; \
fov_t operator op (const fov_t& zoom, const float& scale) { \
return mpark::visit(apply_##name##_to_fov{scale}, zoom); \
return std::visit(apply_##name##_to_fov{scale}, zoom); \
}
APPLY_TO_FOV_T(*, mul)
APPLY_TO_FOV_T(+, add)
APPLY_TO_FOV_T(-, sub)
// Used to set the default value for in-game options
static float fov_default = DEFAULT_FOV;
static SCP_string fov_display(float val)
{
auto degrees = fl_degrees(val);
@@ -61,19 +64,66 @@ static SCP_string fov_display(float val)
sprintf(out, u8"%.1f\u00B0", degrees);
return out;
}
static void parse_fov_func()
{
float value;
stuff_float(&value);
CLAMP(value, 0.436332f, 1.5708f);
fov_default = value;
}
auto FovOption = options::OptionBuilder<float>("Graphics.FOV",
std::pair<const char*, int>{"Field Of View", 1703},
std::pair<const char*, int>{"The vertical field of view", 1704})
.category("Graphics")
.category(std::make_pair("Graphics", 1825))
.range(0.436332f, 1.5708f)
.change_listener([](const float& val, bool) {
VIEWER_ZOOM_DEFAULT = val;
return true;
})
.display(fov_display)
.default_val(0.75f)
.default_func([]() { return fov_default; })
.level(options::ExpertLevel::Advanced)
.importance(60)
.parser(parse_fov_func)
.finish();
bool Use_cockpit_fov = false;
auto CockpitFOVToggleOption = options::OptionBuilder<bool>("Graphics.CockpitFOVToggle",
std::pair<const char*, int>{"Cockpit FOV Toggle", 1838},
std::pair<const char*, int>{"Whether or not to use a different FOV for cockpit rendering from normal rendering", 1839})
.category(std::make_pair("Graphics", 1825))
.default_val(false)
.change_listener([](bool val, bool) {
if (!val) {
COCKPIT_ZOOM_DEFAULT = VIEWER_ZOOM_DEFAULT;
}
return true; // This option will always persist so we never return false
})
.level(options::ExpertLevel::Advanced)
.bind_to(&Use_cockpit_fov)
.importance(61)
.finish();
auto CockpitFovOption = options::OptionBuilder<float>("Graphics.CockpitFOV",
std::pair<const char*, int>{"Cockpit Field Of View", 1840},
std::pair<const char*, int>{"The vertical field of view for cockpit rendering. Only works if cockpits are active and cockpit FOV toggle is turned on.", 1841})
.category(std::make_pair("Graphics", 1825))
.range(0.436332f, 1.5708f)
.change_listener([](const float& val, bool) {
if (Use_cockpit_fov){
COCKPIT_ZOOM_DEFAULT = val;
} else {
COCKPIT_ZOOM_DEFAULT = VIEWER_ZOOM_DEFAULT;
}
return true;
})
.display(fov_display)
.default_val(fov_default)
.level(options::ExpertLevel::Advanced)
.importance(62)
.finish();
//*************************CLASS: camera*************************
@@ -160,25 +210,35 @@ void camera::set_object_host(object *objp, int n_object_host_submodel)
object_host_submodel = n_object_host_submodel;
set_custom_position_function(NULL);
set_custom_orientation_function(NULL);
if(n_object_host_submodel > 0)
if (n_object_host_submodel >= 0 && objp != nullptr && objp->type == OBJ_SHIP)
{
if(objp != nullptr && objp->type == OBJ_SHIP)
ship_subsys* ssp = GET_FIRST(&Ships[objp->instance].subsys_list);
while (ssp != END_OF_LIST(&Ships[objp->instance].subsys_list))
{
ship_subsys* ssp = GET_FIRST(&Ships[objp->instance].subsys_list);
while ( ssp != END_OF_LIST( &Ships[objp->instance].subsys_list ) )
if (ssp->system_info->subobj_num == n_object_host_submodel)
{
if(ssp->system_info->subobj_num == n_object_host_submodel)
if (ssp->system_info->type == SUBSYSTEM_TURRET)
{
if(ssp->system_info->type == SUBSYSTEM_TURRET)
{
set_custom_position_function(get_turret_cam_pos);
set_custom_orientation_function(get_turret_cam_orient);
}
set_custom_position_function(get_turret_cam_pos);
set_custom_orientation_function(get_turret_cam_orient);
}
ssp = GET_NEXT( ssp );
}
ssp = GET_NEXT(ssp);
}
}
else if (Use_model_eyepoint_for_set_camera_host && object_host.isValid())
{
const object* host = object_host.objp();
vec3d eye_pos;
matrix eye_orient;
object_get_eye(&eye_pos, &eye_orient, host, false, true, true);
set_position(&eye_pos);
set_rotation(&eye_orient);
}
}
void camera::set_object_target(object *objp, int n_object_target_submodel)
@@ -297,11 +357,11 @@ void camera::set_rotation_facing(vec3d *in_target, float in_rotation_time, float
if (Use_host_orientation_for_set_camera_facing)
{
// point along the target vector, but using the host orient's roll
vm_vector_2_matrix(&temp_matrix, &targetvec, &orient->vec.uvec, nullptr);
vm_vector_2_matrix_norm(&temp_matrix, &targetvec, &orient->vec.uvec, nullptr);
// if we have a host, we need the difference between the camera's current orient and the orient we want
// if not, we will later set the absolute orientation, rather than the orientation relative to the host
if (object_host.IsValid())
if (object_host.isValid())
{
vm_transpose(orient);
temp_matrix = temp_matrix * *orient;
@@ -310,7 +370,7 @@ void camera::set_rotation_facing(vec3d *in_target, float in_rotation_time, float
else
{
// point directly along the target vector
vm_vector_2_matrix(&temp_matrix, &targetvec, nullptr, nullptr);
vm_vector_2_matrix_norm(&temp_matrix, &targetvec, nullptr, nullptr);
}
}
@@ -324,10 +384,7 @@ void camera::do_frame(float /*in_frametime*/)
object *camera::get_object_host()
{
if(object_host.IsValid())
return object_host.objp;
else
return NULL;
return object_host.objp_or_null();
}
int camera::get_object_host_submodel()
@@ -337,10 +394,7 @@ int camera::get_object_host_submodel()
object *camera::get_object_target()
{
if(object_target.IsValid())
return object_target.objp;
else
return NULL;
return object_target.objp_or_null();
}
int camera::get_object_target_submodel()
@@ -373,7 +427,7 @@ void camera::get_info(vec3d *position, matrix *orientation, bool apply_camera_or
bool use_host_orient = false;
//POSITION
if(!(flags & CAM_STATIONARY_POS) || object_host.IsValid())
if(!(flags & CAM_STATIONARY_POS) || object_host.isValid())
{
c_pos = vmd_zero_vector;
@@ -382,24 +436,16 @@ void camera::get_info(vec3d *position, matrix *orientation, bool apply_camera_or
pos_y.get(&pt.xyz.y, NULL);
pos_z.get(&pt.xyz.z, NULL);
if(object_host.IsValid())
if(object_host.isValid())
{
object *objp = object_host.objp;
int model_num = object_get_model(objp);
polymodel *pm = nullptr;
polymodel_instance *pmi = nullptr;
if(model_num >= 0)
{
pm = model_get(model_num);
if (objp->type == OBJ_SHIP)
pmi = model_get_instance(Ships[objp->instance].model_instance_num);
}
object *objp = object_host.objp();
polymodel *pm = object_get_model(objp);
polymodel_instance *pmi = object_get_model_instance(objp);
if(object_host_submodel < 0 || pm == NULL)
{
vm_vec_unrotate(&c_pos, &pt, &object_host.objp->orient);
vm_vec_add2(&c_pos, &object_host.objp->pos);
vm_vec_unrotate(&c_pos, &pt, &object_host.objp()->orient);
vm_vec_add2(&c_pos, &object_host.objp()->pos);
}
else
{
@@ -444,23 +490,14 @@ void camera::get_info(vec3d *position, matrix *orientation, bool apply_camera_or
if(orientation != NULL)
{
bool target_set = false;
if(!(flags & CAM_STATIONARY_ORI) || object_target.IsValid() || object_host.IsValid())
if(!(flags & CAM_STATIONARY_ORI) || object_target.isValid() || object_host.isValid())
{
if(object_target.IsValid())
if(object_target.isValid())
{
object *target_objp = object_target.objp;
int model_num = object_get_model(target_objp);
polymodel *target_pm = nullptr;
polymodel_instance *target_pmi = nullptr;
object *target_objp = object_target.objp();
polymodel *target_pm = object_get_model(target_objp);
polymodel_instance *target_pmi = object_get_model_instance(target_objp);
vec3d target_pos = vmd_zero_vector;
//See if we can get the model
if(model_num >= 0)
{
target_pm = model_get(model_num);
if (target_objp->type == OBJ_SHIP)
target_pmi = model_get_instance(Ships[target_objp->instance].model_instance_num);
}
//If we don't have a submodel or don't have the model use object pos
//Otherwise, find the submodel pos as it is rotated
@@ -478,14 +515,14 @@ void camera::get_info(vec3d *position, matrix *orientation, bool apply_camera_or
vec3d targetvec;
vm_vec_normalized_dir(&targetvec, &target_pos, &c_pos);
vm_vector_2_matrix(&c_ori, &targetvec, NULL, NULL);
vm_vector_2_matrix_norm(&c_ori, &targetvec, nullptr, nullptr);
target_set = true;
}
else if(object_host.IsValid())
else if(object_host.isValid())
{
if(eyep)
{
vm_vector_2_matrix(&c_ori, &host_normal, vm_vec_same(&host_normal, &object_host.objp->orient.vec.uvec)?NULL:&object_host.objp->orient.vec.uvec, NULL);
vm_vector_2_matrix_norm(&c_ori, &host_normal, vm_vec_same(&host_normal, &object_host.objp()->orient.vec.uvec) ? nullptr : &object_host.objp()->orient.vec.uvec, nullptr);
target_set = true;
}
else if (use_host_orient)
@@ -494,7 +531,7 @@ void camera::get_info(vec3d *position, matrix *orientation, bool apply_camera_or
}
else
{
c_ori = object_host.objp->orient;
c_ori = object_host.objp()->orient;
}
}
else
@@ -541,7 +578,7 @@ warp_camera::warp_camera(object *objp)
vec3d object_pos = objp->pos;
matrix tmp;
ship_get_eye(&object_pos, &tmp, objp);
object_get_eye(&object_pos, &tmp, objp);
vm_vec_scale_add2( &object_pos, &Player_obj->orient.vec.rvec, 0.0f );
vm_vec_scale_add2( &object_pos, &Player_obj->orient.vec.uvec, 0.952f );
@@ -754,7 +791,7 @@ subtitle::subtitle(int in_x_pos, int in_y_pos, const char* in_text, const char*
//Get text size
for(int i = 0; i < num_text_lines; i++)
{
gr_get_string_size(&w, &h, text_line_ptrs[i], text_line_lens[i]);
gr_get_string_size(&w, &h, text_line_ptrs[i], 1.0f, static_cast<size_t>(text_line_lens[i]));
if(w > tw)
tw = w;
@@ -1011,7 +1048,7 @@ int camid::getSignature()
return sig;
}
bool camid::isValid()
bool camid::isValid() const
{
if(idx >= Cameras.size())
return false;
@@ -1048,13 +1085,6 @@ int cam_get_next_sig()
return next_sig++;
}
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(const char *n_name, vec3d *n_pos, matrix *n_ori, object *n_object, int n_object_host_submodel)
{
camera *cam = NULL;
@@ -1198,12 +1228,12 @@ void subtitles_do_frame_post_shaded(float frametime)
}
}
vec3d normal_cache;
static vec3d normal_cache;
void get_turret_cam_pos(camera *cam, vec3d *pos)
{
object_h obj(cam->get_object_host());
if(!obj.IsValid())
if(!obj.isValid())
return;
ship* shipp = &Ships[cam->get_object_host()->instance];
ship_subsys* ssp = GET_FIRST(&shipp->subsys_list);
@@ -1211,7 +1241,7 @@ void get_turret_cam_pos(camera *cam, vec3d *pos)
{
if(ssp->system_info->subobj_num == cam->get_object_host_submodel())
{
ship_get_global_turret_gun_info(cam->get_object_host(), ssp, pos, &normal_cache, 1, NULL);
ship_get_global_turret_gun_info(cam->get_object_host(), ssp, pos, true, &normal_cache, true, nullptr);
vec3d offset = vmd_zero_vector;
offset.xyz.x = 0.0001f;
vm_vec_add2(pos, &offset); // prevent beam turrets from crashing with a nullvec
@@ -1224,9 +1254,9 @@ void get_turret_cam_pos(camera *cam, vec3d *pos)
void get_turret_cam_orient(camera *cam, matrix *ori)
{
object_h obj(cam->get_object_host());
if(!obj.IsValid())
if(!obj.isValid())
return;
vm_vector_2_matrix(ori, &normal_cache, vm_vec_same(&normal_cache, &cam->get_object_host()->orient.vec.uvec)?NULL:&cam->get_object_host()->orient.vec.uvec, NULL);
vm_vector_2_matrix_norm(ori, &normal_cache, vm_vec_same(&normal_cache, &cam->get_object_host()->orient.vec.uvec) ? nullptr : &cam->get_object_host()->orient.vec.uvec, nullptr);
}
eye* get_submodel_eye(polymodel *pm, int submodel_num)
@@ -1263,8 +1293,7 @@ float cam_get_bbox_dist(const object* viewer_obj, float preferred_distance, cons
if (preferred_distance > (viewer_obj->radius * EXTERN_CAM_BBOX_MULTIPLIER_PADDING + EXTERN_CAM_BBOX_CONSTANT_PADDING) * 1.5f)
return preferred_distance;
int modelnum = object_get_model(viewer_obj);
polymodel* pm = model_get(modelnum);
polymodel* pm = object_get_model(viewer_obj);
vec3d adjusted_bbox;
const vec3d* cam_vec = &cam_orient->vec.fvec;
+4 -3
View File
@@ -10,7 +10,7 @@
#include <string>
#include <mpark/variant.hpp>
#include <variant>
#define CAM_STATIONARY_FOV (1<<0)
#define CAM_STATIONARY_ORI (1<<1)
@@ -20,13 +20,15 @@
#define EXTERN_CAM_BBOX_CONSTANT_PADDING 5.0f
#define EXTERN_CAM_BBOX_MULTIPLIER_PADDING 1.5f
#define DEFAULT_FOV 0.75f;
struct asymmetric_fov {
float left, right, up, down;
friend asymmetric_fov operator* (const asymmetric_fov&, const float&);
friend asymmetric_fov operator+ (const asymmetric_fov&, const float&);
friend asymmetric_fov operator- (const asymmetric_fov&, const float&);
};
using fov_t = mpark::variant<float, asymmetric_fov>;
using fov_t = std::variant<float, asymmetric_fov>;
fov_t operator* (const fov_t&, const float&);
fov_t operator+ (const fov_t&, const float&);
fov_t operator- (const fov_t&, const float&);
@@ -177,7 +179,6 @@ void cam_init();
void cam_close();
void cam_do_frame(float frametime);
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();
+23 -157
View File
@@ -20,12 +20,10 @@
#include <io.h>
#include <direct.h>
#include <windows.h>
#include <winbase.h> /* needed for memory mapping of file functions */
#endif
#ifdef SCP_UNIX
#include <glob.h>
#include <sys/mman.h>
#endif
#include "cfile/cfile.h"
@@ -91,12 +89,10 @@ cf_pathtype Pathtypes[CF_MAX_PATH_TYPES] = {
};
// clang-format on
#define CFILE_STACK_MAX 8
int cfile_inited = 0;
static int Cfile_stack_pos = 0;
static char Cfile_stack[CFILE_STACK_MAX][CFILE_ROOT_DIRECTORY_LEN];
static SCP_vector<SCP_string> Cfile_stack;
std::array<CFILE, MAX_CFILE_BLOCKS> Cfile_block_list;
@@ -110,12 +106,6 @@ static CFILE *cf_open_fill_cfblock(const char* source, int line, const char* ori
static CFILE *cf_open_packed_cfblock(const char* source, int line, const char* original_filename, FILE *fp, int type, size_t offset, size_t size);
static CFILE *cf_open_memory_fill_cfblock(const char* source, int line, const char* original_filename, const void* data, size_t size, int dir_type);
#if defined _WIN32
static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, const char* original_filename, HANDLE hFile, int type);
#elif defined SCP_UNIX
static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, const char* original_filename, FILE *fp, int type);
#endif
static void cf_chksum_long_init();
static void dump_opened_files()
@@ -330,17 +320,16 @@ int cfile_push_chdir(int type)
_getcwd(OriginalDirectory, CFILE_ROOT_DIRECTORY_LEN - 1);
Assert(Cfile_stack_pos < CFILE_STACK_MAX);
if (Cfile_stack_pos >= CFILE_STACK_MAX) {
return -1;
}
strcpy_s(Cfile_stack[Cfile_stack_pos++], OriginalDirectory);
cf_create_default_path_string(dir, type, NULL);
return _cfile_chdir(dir.c_str(), OriginalDirectory);
int rc = _cfile_chdir(dir.c_str(), OriginalDirectory);
// if success then push the original directory on to the stack
if (rc == 0) {
Cfile_stack.push_back(OriginalDirectory);
}
return rc;
}
/**
@@ -363,13 +352,16 @@ int cfile_chdir(const char *dir)
int cfile_pop_dir()
{
Assert(Cfile_stack_pos);
if ( !Cfile_stack_pos )
if (Cfile_stack.empty())
return -1;
Cfile_stack_pos--;
return cfile_chdir(Cfile_stack[Cfile_stack_pos]);
int rc = cfile_chdir(Cfile_stack.back().c_str());
Assertion(rc == 0, "Failed to chdir() to previous directory (%s)!", Cfile_stack.back().c_str());
Cfile_stack.pop_back();
return rc;
}
// flush (delete all files in) the passed directory (by type), return the # of files deleted
@@ -632,18 +624,13 @@ void cf_create_directory(int dir_type, uint32_t location_flags)
// parameters: *filepath ==> name of file to open (may be path+name)
// *mode ==> specifies how file should be opened (eg "rb" for read binary)
// passing NULL to mode triggers an assert and returns NULL
// type ==> one of: CFILE_NORMAL
// CFILE_MEMORY_MAPPED
// dir_type => override extension check, value is one of CF_TYPE* #defines
//
// NOTE: type parameter is an optional parameter. The default value is CFILE_NORMAL
//
//
// returns: success ==> address of CFILE structure
// error ==> NULL
//
CFILE* _cfopen(const char* source, int line, const char* file_path, const char* mode, int type, int dir_type,
CFILE* _cfopen(const char* source, int line, const char* file_path, const char* mode, int dir_type,
bool /* localize */, uint32_t location_flags)
{
/* Bobboau, what is this doing here? 31 is way too short... - Goober5000
@@ -659,12 +646,6 @@ CFILE* _cfopen(const char* source, int line, const char* file_path, const char*
// Check that all the parameters make sense
Assert(file_path && strlen(file_path));
Assert( mode != NULL );
// Can only open read-only binary files in memory mapped mode.
if ( (type & CFILE_MEMORY_MAPPED) && strcmp(mode,"rb") != 0 ) {
Int3();
return NULL;
}
//===========================================================
// If in write mode, just try to open the file straight off
@@ -689,7 +670,6 @@ CFILE* _cfopen(const char* source, int line, const char* file_path, const char*
cf_create_default_path_string(longname, dir_type, file_path, location_flags);
}
Assert( !(type & CFILE_MEMORY_MAPPED) );
// JOHN: TODO, you should create the path if it doesn't exist.
@@ -740,35 +720,11 @@ CFILE* _cfopen(const char* source, int line, const char* file_path, const char*
auto find_res = cf_find_file_location(file_path, dir_type, location_flags);
if ( find_res.found ) {
// Fount it, now create a cfile out of it
nprintf(("CFileDebug", "Requested file %s found at: %s\n", file_path, find_res.full_name.c_str()));
if ( type & CFILE_MEMORY_MAPPED ) {
// Can't open memory mapped files out of pack or memory files
if ( find_res.offset == 0 && find_res.data_ptr != nullptr ) {
#if defined _WIN32
HANDLE hFile;
hFile = CreateFile(find_res.full_name.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
return cf_open_mapped_fill_cfblock(source, line, file_path, hFile, dir_type);
}
#elif defined SCP_UNIX
FILE* fp = fopen(find_res.full_name.c_str(), "rb");
if (fp) {
return cf_open_mapped_fill_cfblock(source, line, file_path, fp, dir_type);
}
#endif
}
} else {
// since cfopen_special already has all the code to handle the opening we can just use that here
return _cfopen_special(source, line, find_res, mode, dir_type);
}
// since cfopen_special already has all the code to handle the opening we can just use that here
return _cfopen_special(source, line, find_res, mode, dir_type);
}
return NULL;
@@ -893,27 +849,7 @@ int cfclose( CFILE * cfile )
Assert(cfile != NULL);
result = 0;
if ( cfile->data && cfile->mem_mapped ) {
// close memory mapped file
#if defined _WIN32
result = UnmapViewOfFile((void*)cfile->data);
Assert(result);
result = CloseHandle(cfile->hInFile);
Assert(result); // Ensure file handle is closed properly
result = CloseHandle(cfile->hMapFile);
Assert(result); // Ensure file handle is closed properly
result = 0;
#elif defined SCP_UNIX
// FIXME: result is wrong after munmap() but it is successful
//result = munmap(cfile->data, cfile->data_length);
//Assert(result);
// This const_cast is safe since the pointer returned by mmap was also non-const
munmap(const_cast<void*>(cfile->data), cfile->data_length);
if ( cfile->fp != nullptr)
result = fclose(cfile->fp);
#endif
} else if ( cfile->fp != nullptr ) {
if ( cfile->fp != nullptr ) {
Assert(cfile->fp != nullptr);
result = fclose(cfile->fp);
} else {
@@ -958,7 +894,6 @@ static CFILE *cf_open_fill_cfblock(const char* source, int line, const char* ori
} else {
CFILE *cfp = &Cfile_block_list[cfile_block_index];
cfp->data = nullptr;
cfp->mem_mapped = false;
cfp->fp = fp;
cfp->dir_type = type;
cfp->max_read_len = 0;
@@ -997,7 +932,6 @@ static CFILE *cf_open_packed_cfblock(const char* source, int line, const char* o
cfp->data = nullptr;
cfp->fp = fp;
cfp->mem_mapped = false;
cfp->dir_type = type;
cfp->max_read_len = 0;
@@ -1012,70 +946,6 @@ static CFILE *cf_open_packed_cfblock(const char* source, int line, const char* o
}
// cf_open_mapped_fill_cfblock() will fill up a Cfile_block element in the Cfile_block_list[] array
// for the case of a file being opened by cf_open_mapped();
//
// returns: ptr CFILE structure.
//
#if defined _WIN32
static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, const char* original_filename, HANDLE hFile, int type)
#elif defined SCP_UNIX
static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, const char* original_filename, FILE *fp, int type)
#endif
{
int cfile_block_index;
cfile_block_index = cfget_cfile_block();
if ( cfile_block_index == -1 ) {
#ifdef SCP_UNIX
fclose(fp);
#endif
return NULL;
}
else {
CFILE *cfp = &Cfile_block_list[cfile_block_index];
cfp->max_read_len = 0;
cfp->fp = nullptr;
cfp->mem_mapped = true;
#if defined _WIN32
cfp->hInFile = hFile;
#endif
cfp->dir_type = type;
cfp->original_filename = original_filename;
cfp->source_file = source;
cfp->line_num = line;
cf_init_lowlevel_read_code(cfp, 0, 0, 0 );
#if defined _WIN32
cfp->hMapFile = CreateFileMapping(cfp->hInFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (cfp->hMapFile == NULL) {
nprintf(("Error", "Could not create file-mapping object.\n"));
return NULL;
}
cfp->data = (ubyte*)MapViewOfFile(cfp->hMapFile, FILE_MAP_READ, 0, 0, 0);
Assert( cfp->data != NULL );
#elif defined SCP_UNIX
cfp->fp = fp;
cfp->data_length = filelength(fileno(fp));
cfp->data = mmap(nullptr, // start
cfp->data_length, // length
PROT_READ, // prot
MAP_SHARED, // flags
fileno(fp), // fd
0); // offset
Assert(cfp->data != nullptr);
#endif
return cfp;
}
}
static CFILE *cf_open_memory_fill_cfblock(const char* source, int line, const char* original_filename, const void* data, size_t size, int dir_type)
{
int cfile_block_index;
@@ -1089,7 +959,6 @@ static CFILE *cf_open_memory_fill_cfblock(const char* source, int line, const ch
cfp->max_read_len = 0;
cfp->fp = nullptr;
cfp->mem_mapped = false;
cfp->dir_type = dir_type;
cfp->original_filename = original_filename;
@@ -1333,9 +1202,6 @@ int cfwrite_string_len(const char *buf, CFILE *file)
int cfilelength(CFILE* cfile) {
Assert(cfile != NULL);
// TODO: return length of memory mapped file
Assert(!cfile->mem_mapped);
// cfile->size gets set at cfopen
// The rest of the code still uses ints, do an overflow check to detect cases where this fails
@@ -1728,7 +1594,7 @@ int cf_chksum_short(const char *filename, ushort *chksum, int max_size, int cf_t
*chksum = 0;
// attempt to open the file
cfile = cfopen(filename,"rt",CFILE_NORMAL,cf_type);
cfile = cfopen(filename,"rt",cf_type);
if(cfile == NULL){
return 0;
}
@@ -1778,7 +1644,7 @@ int cf_chksum_long(const char *filename, uint *chksum, int max_size, int cf_type
*chksum = 0;
// attempt to open the file
cfile = cfopen(filename,"rt",CFILE_NORMAL,cf_type);
cfile = cfopen(filename,"rt",cf_type);
if(cfile == NULL){
return 0;
}
+2 -5
View File
@@ -85,10 +85,6 @@ typedef struct {
// TRUE if type is specified and valid
#define CF_TYPE_SPECIFIED(path_type) (((path_type)>CF_TYPE_INVALID) && ((path_type)<CF_MAX_PATH_TYPES))
// #define's for the type parameter in cfopen.
#define CFILE_NORMAL 0 // open file normally
#define CFILE_MEMORY_MAPPED (1<<0) // open file as a memory-mapped file
#define CF_SORT_NONE 0
#define CF_SORT_NAME 1
#define CF_SORT_TIME 2
@@ -181,7 +177,7 @@ int cf_get_dir_type(const CFILE *cfile);
// Opens the file. If no path is given, use the extension to look into the
// default path. If mode is NULL, delete the file.
CFILE* _cfopen(const char* source_file, int line, const char* filename, const char* mode, int type = CFILE_NORMAL,
CFILE* _cfopen(const char* source_file, int line, const char* filename, const char* mode,
int dir_type = CF_TYPE_ANY, bool localize = false, uint32_t location_flags = CF_LOCATION_ALL);
#define cfopen(...) _cfopen(LOCATION, __VA_ARGS__) // Pass source location to the function
@@ -377,6 +373,7 @@ struct CFileLocation {
SCP_string full_name;
size_t size = 0;
size_t offset = 0;
time_t m_time = 0;
const void* data_ptr = nullptr;
explicit CFileLocation(bool found_in = false) : found(found_in) {}
-3
View File
@@ -149,9 +149,6 @@ int cfseek( CFILE *cfile, int offset, int where )
if (cfile->compression_info.header != 0)
return comp_fseek(cfile, offset, where);
// TODO: seek to offset in memory mapped file
Assert( !cfile->mem_mapped );
size_t goal_position;
switch( where ) {
-7
View File
@@ -38,13 +38,6 @@ struct CFILE {
int dir_type; // directory location
FILE* fp; // File pointer if opening an individual file
const void* data; // Pointer for memory-mapped file access. NULL if not mem-mapped.
bool mem_mapped; // Flag for memory mapped files (if data is not null and this is false it means that it's an embedded file)
#ifdef _WIN32
HANDLE hInFile; // Handle from CreateFile()
HANDLE hMapFile; // Handle from CreateFileMapping()
#else
size_t data_length; // length of data for mmap
#endif
size_t lib_offset;
size_t raw_position;
size_t size; // for packed files
+25 -2
View File
@@ -22,6 +22,7 @@
#include <windows.h>
#include <winbase.h> /* needed for memory mapping of file functions */
#include <shlwapi.h>
#include <sys/stat.h>
#endif
#ifdef SCP_UNIX
@@ -595,7 +596,7 @@ static void cf_add_mod_roots(const char* rootDirectory, uint32_t basic_location)
cf_root* root = cf_create_root();
root->path = rootPath;
root->path = std::move(rootPath);
if (primary) {
root->location_flags = basic_location | CF_LOCATION_TYPE_PRIMARY_MOD;
} else {
@@ -826,7 +827,8 @@ static void check_file_shadows(const int root_index __UNUSED, const int pathtype
}
// this log message occurs in the middle of an existing line, hence the extra new lines
mprintf(("\nWARNING! A %sfile being indexed may be shadowed by an existing file!\n New:\n %s\n Existing:\n %s\n",
// critical files and files in same root are always logged, files in different root are behind a filter
nprintf(((critical || !root->path.compare(r->path)) ? "General" : "CFileSystem", "\nWARNING! A %sfile being indexed may be shadowed by an existing file!\n New:\n %s\n Existing:\n %s\n",
critical ? "critical " : "",
newfile.c_str(), curfile.c_str()));
@@ -1236,6 +1238,22 @@ static bool sub_path_match(const SCP_string &search, const SCP_string &index)
return !stricmp(search.c_str(), index.c_str());
}
static time_t get_mtime(int fd)
{
#ifdef _WIN32
struct _stat buf;
#define fstat _fstat
#else
struct stat buf;
#endif
if (fstat(fd, &buf) != 0) {
return 0;
}
return buf.st_mtime;
}
/**
* Searches for a file.
*
@@ -1270,6 +1288,7 @@ CFileLocation cf_find_file_location(const char* filespec, int pathtype, uint32_t
if (fp) {
CFileLocation res(true);
res.size = static_cast<size_t>(filelength(fileno(fp)));
res.m_time = get_mtime(fileno(fp));
fclose(fp);
@@ -1332,6 +1351,7 @@ CFileLocation cf_find_file_location(const char* filespec, int pathtype, uint32_t
if (fp) {
CFileLocation res(true);
res.size = static_cast<size_t>(filelength( fileno(fp) ));
res.m_time = get_mtime(fileno(fp));
fclose(fp);
@@ -1388,6 +1408,7 @@ CFileLocation cf_find_file_location(const char* filespec, int pathtype, uint32_t
res.offset = (size_t)f->pack_offset;
res.data_ptr = f->data;
res.name_ext = f->name_ext;
res.m_time = f->write_time;
if (f->data != nullptr) {
// This is an in-memory file so we just copy the pathtype name + file name
@@ -1523,6 +1544,7 @@ CFileLocationExt cf_find_file_location_ext(const char *filename, const int ext_n
CFileLocationExt res(cur_ext);
res.found = true;
res.size = static_cast<size_t>(filelength( fileno(fp) ));
res.m_time = get_mtime(fileno(fp));
fclose(fp);
@@ -1611,6 +1633,7 @@ CFileLocationExt cf_find_file_location_ext(const char *filename, const int ext_n
res.offset = (size_t)f->pack_offset;
res.data_ptr = f->data;
res.name_ext = f->name_ext;
res.m_time = f->write_time;
if (f->data != nullptr) {
// This is an in-memory file so we just copy the pathtype name + file name
+187 -132
View File
@@ -40,6 +40,7 @@
#ifdef SCP_UNIX
#include "osapi/osapi.h"
#include <dirent.h>
#include <sys/stat.h>
#endif
#include <cstring>
@@ -164,11 +165,9 @@ Flag exe_params[] =
{ "-nonormal", "Disable normal maps", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nonormal" },
{ "-emissive_light", "Enable emissive light from ships", true, 0, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-emissive_light" },
{ "-noheight", "Disable height/parallax maps", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noheight" },
{ "-3dshockwave", "Enable 3D shockwaves", true, EASY_ALL_ON | EASY_HI_MEM_ON, EASY_DEFAULT | EASY_HI_MEM_OFF, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-3dshockwave" },
{ "-no_post_process", "Disable post-processing", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_post_process" },
{ "-soft_particles", "Enable soft particles", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-soft_particles" },
{ "-aa", "Enable Post-process anti-aliasing", true, EASY_ALL_ON | EASY_HI_MEM_ON, EASY_DEFAULT | EASY_HI_MEM_OFF, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-aa" },
{ "-nolightshafts", "Disable lightshafts", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nolightshafts"},
{ "-fb_explosions", "Enable Framebuffer Shockwaves", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fb_explosions", },
{ "-fb_thrusters", "Enable Framebuffer Thrusters", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fb_thrusters", },
{ "-no_deferred", "Disable Deferred Lighting", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_deferred"},
@@ -192,13 +191,10 @@ Flag exe_params[] =
{ "-capture_mouse", "Capture the mouse within the window", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-capture_mouse", },
{ "-stretch_menu", "Stretch interface to fill screen", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-stretch_menu", },
{ "-noscalevid", "Disable scale-to-window for movies", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noscalevid", },
{ "-nomotiondebris", "Disable motion debris", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nomotiondebris",},
{ "-3dwarp", "Enable 3D warp", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-3dwarp", },
{ "-warp_flash", "Enable flash upon warp", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-warp_flash", },
{ "-no_ap_interrupt", "Disable interrupting autopilot", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_ap_interrupt", },
{ "-no_screenshake", "Disable screen shaking", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_screenshake", },
{ "-vr", "Enable Virtual Reality Mode", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-vr", },
{ "-no_unfocused_pause","Don't pause if the window isn't focused", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_unfocused_pause", },
{ "-orig_speedx_range", "Restrict speedup/slowdown (1x to 4x)", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-orig_speedx_range", },
//flag launcher text FSO on_flags off_flags category reference URL
{ "-nosound", "Disable all sound", false, 0, EASY_DEFAULT, "Audio", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nosound", },
@@ -241,6 +237,8 @@ Flag exe_params[] =
{ "-prefer_ipv6", "Prefer IPv6 DNS lookups", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-prefer_ipv6", },
{ "-log_multi_packet", "Log multi packet types ", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-log_multi_packet",},
{ "-no_bsp_align", "Disable pof BSP data alignment", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_bsp_align", },
{ "-no_large_shaders", "Split large shader into smaller shaders", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_large_shaders", },
#ifdef WIN32
{ "-fix_registry", "Use a different registry path", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fix_registry", },
#endif
@@ -263,6 +261,7 @@ 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", },
{ "-output_script_json", "Output scripting doc to scripting.json", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-output_script_json", },
{ "-output_script_lua", "Output scripting doc to scripting.lua", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-output_script_luastub", },
{ "-controlconfig_tbl", "Save control presets to table", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-controlconfig_tbl", },
{ "-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", },
{ "-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", },
@@ -317,7 +316,6 @@ int Cmdline_cd_check = 1;
int Cmdline_closed_game = 0;
int Cmdline_freespace_no_music = 0;
int Cmdline_freespace_no_sound = 0;
int Cmdline_gimme_all_medals = 0;
int Cmdline_mouse_coords = 0;
int Cmdline_multi_log = 0;
int Cmdline_multi_stream_chat_to_file = 0;
@@ -341,15 +339,12 @@ cmdline_parm emissive_power_arg("-emissive", "Multiplies the brightness of all a
cmdline_parm emissive_arg("-emissive_light", "Enable emissive light from ships", AT_NONE); // semi-deprecated but still functional
cmdline_parm env("-noenv", NULL, AT_NONE); // Cmdline_env
cmdline_parm glow_arg("-noglow", NULL, AT_NONE); // Cmdline_glow -- use Bobs glow code
cmdline_parm nomotiondebris_arg("-nomotiondebris", NULL, AT_NONE); // Cmdline_nomotiondebris -- Removes those ugly floating rocks -C
cmdline_parm noscalevid_arg("-noscalevid", NULL, AT_NONE); // Cmdline_noscalevid -- disable video scaling that fits to window
cmdline_parm spec_arg("-nospec", NULL, AT_NONE); // Cmdline_spec --
cmdline_parm normal_arg("-nonormal", NULL, AT_NONE); // Cmdline_normal -- disable normal mapping
cmdline_parm height_arg("-noheight", NULL, AT_NONE); // Cmdline_height -- enable support for parallax mapping
cmdline_parm enable_3d_shockwave_arg("-3dshockwave", NULL, AT_NONE);
cmdline_parm softparticles_arg("-soft_particles", NULL, AT_NONE);
cmdline_parm no_postprocess_arg("-no_post_process", "Disables post-processing", AT_NONE);
cmdline_parm bloom_intensity_arg("-bloom_intensity", "Set bloom intensity, requires post-processing", AT_INT);
cmdline_parm post_process_aa_arg("-aa", "Enables post-process antialiasing", AT_NONE);
cmdline_parm post_process_aa_preset_arg("-aa_preset", "Sets the AA effect to use. See the wiki for details", AT_INT);
cmdline_parm deprecated_fxaa_arg("-fxaa", nullptr, AT_NONE);
@@ -359,7 +354,6 @@ cmdline_parm deprecated_smaa_preset_arg("-smaa_preset", "SMAA quality (0-3), req
cmdline_parm msaa_enabled_arg("-msaa", nullptr, AT_INT);
cmdline_parm fb_explosions_arg("-fb_explosions", NULL, AT_NONE);
cmdline_parm fb_thrusters_arg("-fb_thrusters", NULL, AT_NONE);
cmdline_parm flightshaftsoff_arg("-nolightshafts", NULL, AT_NONE);
cmdline_parm shadow_quality_arg("-shadow_quality", NULL, AT_INT);
cmdline_parm enable_shadows_arg("-enable_shadows", NULL, AT_NONE);
cmdline_parm no_deferred_lighting_arg("-no_deferred", NULL, AT_NONE); // Cmdline_no_deferred
@@ -377,10 +371,7 @@ int Cmdline_spec = 1;
int Cmdline_emissive = 0;
int Cmdline_normal = 1;
int Cmdline_height = 1;
int Cmdline_enable_3d_shockwave = 0;
int Cmdline_softparticles = 0;
int Cmdline_bloom_intensity = 25;
bool Cmdline_force_lightshaft_off = false;
int Cmdline_no_deferred_lighting = 0;
bool Cmdline_deferred_lighting_cockpit = false;
int Cmdline_aniso_level = 0;
@@ -391,7 +382,7 @@ cmdline_parm no_fpscap("-no_fps_capping", "Don't limit frames-per-second", AT_NO
cmdline_parm no_vsync_arg("-no_vsync", NULL, AT_NONE); // Cmdline_no_vsync
int Cmdline_NoFPSCap = 0; // Disable FPS capping - kazan
int Cmdline_no_vsync = 0;
bool Cmdline_no_vsync = false;
// HUD related
cmdline_parm ballistic_gauge("-ballistic_gauge", NULL, AT_NONE); // Cmdline_ballistic_gauge
@@ -406,22 +397,16 @@ int Cmdline_orb_radar = 0;
int Cmdline_rearm_timer = 0;
// Gameplay related
cmdline_parm use_3dwarp("-3dwarp", nullptr, AT_NONE); // Is now Fireball_use_3d_warp
cmdline_parm use_warp_flash("-warp_flash", nullptr, AT_NONE); // Cmdline_warp_flash
cmdline_parm allow_autpilot_interrupt("-no_ap_interrupt", nullptr, AT_NONE);
cmdline_parm stretch_menu("-stretch_menu", nullptr, AT_NONE); // Cmdline_stretch_menu
cmdline_parm capture_mouse("-capture_mouse", nullptr, AT_NONE); // Cmdline_capture_mouse
cmdline_parm no_screenshake("-no_screenshake", nullptr, AT_NONE); // Cmdline_no_screenshake
cmdline_parm vr("-vr", nullptr, AT_NONE);
cmdline_parm deadzone("-deadzone",
"Sets the joystick deadzone. Integer value from 0 to 100 as a percentage of the joystick's range (100% would make the stick do nothing). Disables deadzone slider in the in-game Options menu.", AT_INT); //Cmdline_deadzone
int Cmdline_ship_choice_3d = 0;
int Cmdline_weapon_choice_3d = 0;
int Cmdline_autopilot_interruptable = 1;
int Cmdline_stretch_menu = 0;
bool Cmdline_stretch_menu = false;
bool Cmdline_capture_mouse = false;
int Cmdline_no_screenshake = 0;
int Cmdline_deadzone = -1;
bool Cmdline_enable_vr = false;
@@ -433,8 +418,10 @@ int Cmdline_no_enhanced_sound = 0;
// MOD related
cmdline_parm mod_arg("-mod", "List of folders to overwrite/add-to the default data", AT_STRING, true); // Cmdline_mod -- DTP modsupport
cmdline_parm campaign_arg("-campaign", "Set current campaign", AT_STRING); // Cmdline_campaign
char *Cmdline_mod = NULL; //DTP for mod argument
char *Cmdline_campaign = nullptr; // for campaign argument
// Multiplayer/Network related
cmdline_parm almission_arg("-almission", "Autoload multiplayer mission", AT_STRING); // Cmdline_almission -- DTP for autoload Multi mission
@@ -478,6 +465,7 @@ cmdline_parm prefer_ipv4_arg("-prefer_ipv4", nullptr, AT_NONE);
cmdline_parm prefer_ipv6_arg("-prefer_ipv6", nullptr, AT_NONE);
cmdline_parm log_multi_packet_arg("-log_multi_packet", nullptr, AT_NONE);
cmdline_parm no_bsp_align_arg("-no_bsp_align", nullptr, AT_NONE);
cmdline_parm no_large_shaders("-no_large_shaders", NULL, AT_NONE);
#ifdef WIN32
cmdline_parm fix_registry("-fix_registry", NULL, AT_NONE);
#endif
@@ -501,6 +489,7 @@ bool Cmdline_prefer_ipv4 = false;
bool Cmdline_prefer_ipv6 = false;
bool Cmdline_dump_packet_type = false;
bool Cmdline_no_bsp_align = false;
bool Cmdline_no_large_shaders = false;
#ifdef WIN32
bool Cmdline_alternate_registry_path = false;
#endif
@@ -529,6 +518,7 @@ cmdline_parm parse_cmdline_only(PARSE_COMMAND_LINE_STRING, "Ignore any cmdline_f
cmdline_parm reparse_mainhall_arg("-reparse_mainhall", NULL, AT_NONE); //Cmdline_reparse_mainhall
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 retail_time_compression_range_arg("-orig_speedx_range", NULL, AT_NONE); //Cmdline_retail_time_compression_range
cmdline_parm benchmark_mode_arg("-benchmark_mode", NULL, AT_NONE); //Cmdline_benchmark_mode
cmdline_parm pilot_arg("-pilot", nullptr, AT_STRING); //Cmdline_pilot
cmdline_parm noninteractive_arg("-noninteractive", NULL, AT_NONE); //Cmdline_noninteractive
@@ -558,15 +548,16 @@ int Cmdline_bmpman_usage = 0;
int Cmdline_show_pos = 0;
int Cmdline_show_stats = 0;
int Cmdline_save_render_targets = 0;
int Cmdline_window = 0;
int Cmdline_fullscreen_window = 0;
tl::optional<std::pair<uint16_t, uint16_t>>Cmdline_window_res = tl::nullopt;
bool Cmdline_window = false;
bool Cmdline_fullscreen_window = false;
std::optional<std::pair<uint16_t, uint16_t>>Cmdline_window_res = std::nullopt;
char *Cmdline_res = 0;
char *Cmdline_center_res = 0;
int Cmdline_verify_vps = 0;
int Cmdline_reparse_mainhall = 0;
bool Cmdline_profile_write_file = false;
bool Cmdline_no_unfocus_pause = false;
bool Cmdline_retail_time_compression_range = false;
bool Cmdline_benchmark_mode = false;
const char *Cmdline_pilot = nullptr;
bool Cmdline_noninteractive = false;
@@ -587,6 +578,7 @@ cmdline_parm get_flags_arg(GET_FLAGS_STRING, "Output the launcher flags file", A
cmdline_parm output_sexp_arg("-output_sexps", NULL, AT_NONE); //WMC - outputs all SEXPs to sexps.html
cmdline_parm output_scripting_arg("-output_scripting", NULL, AT_NONE); //WMC
cmdline_parm output_script_json_arg("-output_script_json", nullptr, AT_NONE); // m!m
cmdline_parm output_script_luastub_arg("-output_script_lua", nullptr, AT_NONE); // mjnmixael
cmdline_parm generate_controlconfig_arg("-controlconfig_tbl", nullptr, AT_NONE);
// Deprecated flags - CommanderDJ
@@ -609,6 +601,13 @@ cmdline_parm deprecated_spec_tube_arg("-spec_tube", "Deprecated", AT_NONE);
cmdline_parm deprecated_ambient_factor_arg("-ambient_factor", "Deprecated", AT_NONE); //
cmdline_parm deprecated_ship_choice_3d_arg("-ship_choice_3d", "Deprecated", AT_NONE);
cmdline_parm deprecated_weapon_choice_3d_arg("-weapon_choice_3d", "Deprecated", AT_NONE);
cmdline_parm deprecated_no_screenshake("-no_screenshake", "Deprecated", AT_NONE);
cmdline_parm deprecated_bloom_intensity_arg("-bloom_intensity", "Deprecated", AT_INT);
cmdline_parm deprecated_nomotiondebris_arg("-nomotiondebris", "Deprecated", AT_NONE);
cmdline_parm deprecated_flightshaftsoff_arg("-nolightshafts", "Deprecated", AT_NONE);
cmdline_parm deprecated_use_warp_flash("-warp_flash", "Deprecated", AT_NONE);
cmdline_parm deprecated_use_3dwarp("-3dwarp", "Deprecated", AT_NONE);
cmdline_parm deprecated_enable_3d_shockwave_arg("-3dshockwave", "Deprecated", AT_NONE);
#ifndef NDEBUG
// NOTE: this assumes that os_init() has already been called but isn't a fatal error if it hasn't
@@ -644,8 +643,8 @@ void cmdline_debug_print_cmdline()
}
#endif
// prints simple cmdline to multi.log
void cmdline_print_cmdline_multi()
// builds simple cmdline
SCP_string cmdline_build_string()
{
cmdline_parm *parmp;
int found = 0;
@@ -664,10 +663,18 @@ void cmdline_print_cmdline_multi()
}
if ( !found ) {
cmdline << " <none>";
return "";
}
ml_printf("Command line:%s", cmdline.str().c_str());
return cmdline.str();
}
// prints simple cmdline to multi.log
void cmdline_print_cmdline_multi()
{
auto str = cmdline_build_string();
ml_printf("Command line:%s", str.empty() ? " <none>" : str.c_str());
}
// Return true if this character is an extra char (white space and quotes)
@@ -676,7 +683,6 @@ int is_extra_space(char ch)
return ((ch == ' ') || (ch == '\t') || (ch == 0x0a) || (ch == '\'') || (ch == '\"'));
}
// eliminates all leading and trailing extra chars from a string. Returns pointer passed in.
char *drop_extra_chars(char *str)
{
@@ -1208,93 +1214,133 @@ bool cmdline_parm::has_param() {
}
#ifdef SCP_UNIX
// Return a vector with all filesystem names of "parent/dir" relative to parent.
// dir must not contain a slash.
static SCP_vector<SCP_string> unix_get_single_dir_names(const SCP_string& parent, const SCP_string& dir)
extern void normalize_directory_separators(SCP_string &str);
static SCP_string get_real_mod_path(const char *mod)
{
SCP_vector<SCP_string> ret;
DIR *dirp;
SCP_string fullpath;
SCP_string mod_path = mod;
DIR *dp;
if ((dp = opendir(parent.c_str())) == NULL) {
Warning(LOCATION, "Can't open directory '%s' when searching mod paths. Ignoring. errno=%d", parent.c_str(), errno);
return ret;
normalize_directory_separators(mod_path);
fullpath = SCP_string(".") + DIR_SEPARATOR_STR;
fullpath += mod_path;
// check if path already exists
dirp = opendir(fullpath.c_str());
if (dirp) {
// found it, return unchanged
closedir(dirp);
return mod_path;
}
dirent *dirp;
while ((dirp = readdir(dp)) != NULL) {
if (!stricmp(dirp->d_name, dir.c_str())) {
ret.push_back(dirp->d_name);
// not found, check for a difference in case
SCP_string new_mod_path;
SCP_string part;
struct dirent *dir;
SCP_string::size_type separator;
SCP_string::size_type offset = 0;
fullpath = SCP_string(".") + DIR_SEPARATOR_STR;
do {
separator = mod_path.find(DIR_SEPARATOR_CHAR, offset);
if (separator != SCP_string::npos) {
part = mod_path.substr(offset, separator-offset);
offset += separator-offset + 1;
} else {
part = mod_path.substr(offset);
offset += part.length();
}
}
(void)closedir(dp);
return ret;
}
dirp = opendir(fullpath.c_str());
// Return a vector with all filesystem names of "parent/dir" relative to parent.
// Recurses to deal with slashes in dir.
static SCP_vector<SCP_string> unix_get_dir_names(const SCP_string& parent, const SCP_string& dir)
{
size_t slash = dir.find_first_of("/\\");
// no subdirectories, no need to recurse
if (slash == std::string::npos) {
return unix_get_single_dir_names(parent, dir);
}
// get the names of the first component of dir
SCP_vector<SCP_string> this_dir_names = unix_get_single_dir_names(parent, dir.substr(0, slash));
SCP_string rest = dir.substr(slash + 1);
SCP_vector<SCP_string> ret;
// search for the rest of dir in each of these
SCP_vector<SCP_string>::iterator ii, end = this_dir_names.end();
for (ii = this_dir_names.begin(); ii != end; ++ii) {
SCP_string this_dir_path = parent + "/" + *ii;
SCP_vector<SCP_string> mod_path = unix_get_dir_names(this_dir_path, rest);
// add all found paths relative to parent
SCP_vector<SCP_string>::iterator ii2, end2 = mod_path.end();
for (ii2 = mod_path.begin(); ii2 != end2; ++ii2) {
ret.push_back(*ii + "/" + *ii2);
if ( !dirp ) {
break;
}
while ((dir = readdir(dirp)) != nullptr) {
if (stricmp(dir->d_name, part.c_str())) {
continue;
}
SCP_string fn = fullpath + dir->d_name;
// make sure it accessible and a directory
struct stat buf;
if (stat(fn.c_str(), &buf) == -1) {
continue;
}
if ( !S_ISDIR(buf.st_mode) ) {
continue;
}
if ( !new_mod_path.empty() ) {
new_mod_path += DIR_SEPARATOR_STR;
}
new_mod_path += dir->d_name;
fullpath += dir->d_name;
fullpath += DIR_SEPARATOR_STR;
break;
}
if (dirp) {
closedir(dirp);
}
} while (offset < mod_path.length());
// Append anything left from mod_path onto the new path. This will catch trailing separators
// as well as mod folders which don't exist so that the mod string remains unchanged except
// for the directory name case.
if (new_mod_path.length() != mod_path.length()) {
new_mod_path += mod_path.substr(new_mod_path.length());
}
return ret;
return new_mod_path;
}
// For case sensitive filesystems (e.g. Linux/BSD) perform case-insensitive dir matches.
//
// NOTE: Aside from change in case no alterations should be made to the modlist. Missing
// mod folders should be left in place and no errors or warnings should be generated.
// There should be no difference between Windows and non-Windows modlist handling.
static void handle_unix_modlist(char **modlist, size_t *len)
{
// search filesystem for given paths
SCP_vector<SCP_string> mod_paths;
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);
// 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());
for (char *cur_mod = strtok(*modlist, ","); cur_mod != NULL; cur_mod = strtok(NULL, ",")) {
SCP_string path = get_real_mod_path(cur_mod);
mod_paths.push_back(path);
}
// create new char[] to replace modlist
size_t total_len = 0;
SCP_vector<SCP_string>::iterator ii, end = mod_paths.end();
for (ii = mod_paths.begin(); ii != end; ++ii) {
total_len += ii->length() + 1;
for (auto &path : mod_paths) {
total_len += path.length() + 1;
}
char *new_modlist = new char[total_len + 1];
memset(new_modlist, 0, total_len + 1);
end = mod_paths.end();
for (ii = mod_paths.begin(); ii != end; ++ii) {
strcat_s(new_modlist, total_len + 1, ii->c_str());
strcat_s(new_modlist, total_len + 1, ","); // replace later with NUL
for (auto &path : mod_paths) {
strcat_s(new_modlist, total_len + 1, path.c_str());
strcat_s(new_modlist, total_len + 1, ",");
}
// remove trailing comma
new_modlist[total_len-1] = '\0';
// make the rest of the modlist manipulation unaware that anything happened here
delete [] *modlist;
*modlist = new_modlist;
@@ -1544,6 +1590,12 @@ bool SetCmdlineParams()
{
//getcwd(FreeSpace_Directory, 256); // set the directory to our fs2 root
// DO THIS BEFORE get_flags, as portable_mode can change the value of pref_path printed in the json
if (portable_mode.found())
{
Cmdline_portable_mode = true;
}
// DO THIS FIRST to avoid unrecognized flag warnings when just getting flag file
if ( get_flags_arg.found() ) {
write_flags();
@@ -1724,14 +1776,14 @@ bool SetCmdlineParams()
if(window_arg.found()) {
// We need to set both values since we don't know if we are going to use the new config system
//options::OptionsManager::instance()->setOverride("Graphics.WindowMode", "0");
Cmdline_window = 1;
Cmdline_window = true;
}
if ( fullscreen_window_arg.found( ) )
{
//options::OptionsManager::instance()->setOverride("Graphics.WindowMode", "1");
Cmdline_fullscreen_window = 1;
Cmdline_window = 0; /* Make sure no-one sets both */
Cmdline_fullscreen_window = true;
Cmdline_window = false; /* Make sure no-one sets both */
}
if(render_res_arg.found() || deprecated_res_arg.found()){
@@ -1799,7 +1851,7 @@ bool SetCmdlineParams()
if(mod_arg.found() ) {
Cmdline_mod = mod_arg.str();
// strip off blank space it it's there
// strip off blank space if it's there
if ( Cmdline_mod[strlen(Cmdline_mod)-1] == ' ' ) {
Cmdline_mod[strlen(Cmdline_mod)-1] = '\0';
}
@@ -1826,6 +1878,14 @@ bool SetCmdlineParams()
Cmdline_mod = modlist;
}
if(campaign_arg.found()) {
Cmdline_campaign = campaign_arg.str();
// strip off blank space if it's there
if ( Cmdline_campaign[strlen(Cmdline_campaign)-1] == ' ' ) {
Cmdline_campaign[strlen(Cmdline_campaign)-1] = '\0';
}
}
if (fps_arg.found())
{
@@ -1842,10 +1902,6 @@ bool SetCmdlineParams()
Cmdline_show_pos = 1;
}
if ( nomotiondebris_arg.found() ) {
Motion_debris_enabled = false;
}
if( mipmap_arg.found() ) {
Cmdline_mipmap = 1;
}
@@ -1859,7 +1915,7 @@ bool SetCmdlineParams()
if (val > 0.1) {
VIEWER_ZOOM_DEFAULT = val;
} else {
VIEWER_ZOOM_DEFAULT = 0.75f;
VIEWER_ZOOM_DEFAULT = DEFAULT_FOV;
}
}
@@ -1878,6 +1934,25 @@ bool SetCmdlineParams()
if (fov_arg.found() || fov_cockpit_arg.found()) {
Warning(LOCATION, "FoV Command line settings found. VR-Mode will override these with the HMD's native FoV...");
}
// enable other settings to allow VR to work more seamlessly
mprintf(("VR-Mode enabled, so forcing on the following settings: capture_mouse, window_res 1000x1000, window, no_vsync \n"));
// ensure ingame resolution is set to sensible values in VR mode,
// which will exceed the resolution otherwise shown and is not dependent on the monitor resolution
Cmdline_capture_mouse = true;
Cmdline_window_res.emplace(static_cast<uint16_t>(1000), static_cast<uint16_t>(1000));
Cmdline_fullscreen_window = false;
Cmdline_window = true; /* Make sure no-one sets both */
removeWindowModeOption();
// Turn off VSync, since we definitely don't want to be capped by the main monitor
// the OpenXR runtime should have a buffered wait which will behave, effectively,
// as a VSync to VR goggle driver
Gr_enable_vsync = false;
removeVSyncOption();
openxr_prepare();
}
@@ -1886,28 +1961,16 @@ bool SetCmdlineParams()
Cmdline_orb_radar = 1;
}
if ( use_3dwarp.found() ) {
Fireball_use_3d_warp = true;
}
if ( use_warp_flash.found() ) {
Fireball_warp_flash = true;
}
if ( allow_autpilot_interrupt.found() ) {
Cmdline_autopilot_interruptable = 0;
}
if ( no_screenshake.found() ) {
Cmdline_no_screenshake = 1;
}
if ( deadzone.found() ) {
Cmdline_deadzone = deadzone.get_int();
}
if ( stretch_menu.found() ) {
Cmdline_stretch_menu = 1;
Cmdline_stretch_menu = true;
}
if ( capture_mouse.found() ) {
@@ -2014,6 +2077,9 @@ bool SetCmdlineParams()
if (output_script_json_arg.found() )
Output_scripting_json = true;
if (output_script_luastub_arg.found())
Output_scripting_luastub = true;
if (output_sexp_arg.found() ) {
Cmdline_output_sexp_info = true;
}
@@ -2061,11 +2127,6 @@ bool SetCmdlineParams()
Cmdline_noshadercache = true;
}
if (portable_mode.found())
{
Cmdline_portable_mode = true;
}
if (lang_arg.found())
{
Cmdline_lang = lang_arg.str();
@@ -2074,6 +2135,10 @@ bool SetCmdlineParams()
if (no_bsp_align_arg.found()) {
Cmdline_no_bsp_align = true;
}
if (no_large_shaders.found()) {
Cmdline_no_large_shaders = true;
}
#ifdef WIN32
if (fix_registry.found()) {
@@ -2116,11 +2181,6 @@ bool SetCmdlineParams()
Cmdline_ati_color_swap = 1;
}
if ( enable_3d_shockwave_arg.found() )
{
Cmdline_enable_3d_shockwave = 1;
}
if ( softparticles_arg.found() )
{
Cmdline_softparticles = 1;
@@ -2141,16 +2201,6 @@ bool SetCmdlineParams()
Gr_post_processing_enabled = false;
}
if ( bloom_intensity_arg.found() )
{
Cmdline_bloom_intensity = bloom_intensity_arg.get_int();
}
if ( flightshaftsoff_arg.found() )
{
Cmdline_force_lightshaft_off = true;
}
if( reparse_mainhall_arg.found() )
{
Cmdline_reparse_mainhall = 1;
@@ -2216,6 +2266,11 @@ bool SetCmdlineParams()
{
Cmdline_no_unfocus_pause = true;
}
if (retail_time_compression_range_arg.found())
{
Cmdline_retail_time_compression_range = true;
}
if (benchmark_mode_arg.found())
{
+13 -13
View File
@@ -12,7 +12,7 @@
#ifndef FS_CMDLINE_HEADER_FILE
#define FS_CMDLINE_HEADER_FILE
#include <tl/optional.hpp>
#include <optional>
int parse_cmdline(int argc, char *argv[]);
@@ -34,7 +34,6 @@ extern int Cmdline_cd_check;
extern int Cmdline_closed_game;
extern int Cmdline_freespace_no_music;
extern int Cmdline_freespace_no_sound;
extern int Cmdline_gimme_all_medals;
extern int Cmdline_mouse_coords;
extern int Cmdline_multi_log;
extern int Cmdline_multi_stream_chat_to_file;
@@ -44,10 +43,10 @@ extern int Cmdline_spew_pof_info;
extern int Cmdline_start_netgame;
extern int Cmdline_timeout;
extern int Cmdline_use_last_pilot;
extern int Cmdline_window;
extern int Cmdline_fullscreen_window;
extern bool Cmdline_window;
extern bool Cmdline_fullscreen_window;
extern char *Cmdline_res;
extern tl::optional<std::pair<uint16_t, uint16_t>>Cmdline_window_res;
extern std::optional<std::pair<uint16_t, uint16_t>>Cmdline_window_res;
extern char *Cmdline_center_res;
@@ -63,10 +62,7 @@ extern int Cmdline_noscalevid; // disables fit-to-window for movies - taylor
extern int Cmdline_spec;
extern int Cmdline_normal;
extern int Cmdline_height;
extern int Cmdline_enable_3d_shockwave;
extern int Cmdline_softparticles;
extern int Cmdline_bloom_intensity;
extern bool Cmdline_force_lightshaft_off;
extern int Cmdline_no_deferred_lighting;
extern bool Cmdline_deferred_lighting_cockpit;
extern int Cmdline_emissive;
@@ -75,7 +71,7 @@ extern int Cmdline_msaa_enabled;
// Game Speed related
extern int Cmdline_NoFPSCap;
extern int Cmdline_no_vsync;
extern bool Cmdline_no_vsync;
// HUD related
extern int Cmdline_ballistic_gauge;
@@ -84,12 +80,9 @@ extern int Cmdline_orb_radar;
extern int Cmdline_rearm_timer;
// Gameplay related
extern int Cmdline_ship_choice_3d;
extern int Cmdline_weapon_choice_3d;
extern int Cmdline_autopilot_interruptable;
extern int Cmdline_stretch_menu;
extern bool Cmdline_stretch_menu;
extern bool Cmdline_capture_mouse;
extern int Cmdline_no_screenshake;
extern int Cmdline_deadzone;
extern bool Cmdline_enable_vr;
@@ -99,6 +92,7 @@ extern int Cmdline_no_enhanced_sound;
// MOD related
extern char *Cmdline_mod; // DTP for mod support
extern char *Cmdline_campaign; // for campaign support
// Multiplayer/Network related
extern char *Cmdline_almission; // DTP for autoload mission (for multi only)
extern int Cmdline_ingamejoin;
@@ -130,6 +124,7 @@ extern bool Cmdline_noshadercache;
extern bool Cmdline_prefer_ipv4;
extern bool Cmdline_prefer_ipv6;
extern bool Cmdline_dump_packet_type;
extern bool Cmdline_no_large_shaders;
#ifdef WIN32
extern bool Cmdline_alternate_registry_path;
#endif
@@ -149,6 +144,7 @@ extern int Cmdline_verify_vps;
extern int Cmdline_reparse_mainhall;
extern bool Cmdline_profile_write_file;
extern bool Cmdline_no_unfocus_pause;
extern bool Cmdline_retail_time_compression_range;
extern bool Cmdline_benchmark_mode;
extern const char *Cmdline_pilot;
extern bool Cmdline_noninteractive;
@@ -167,5 +163,9 @@ extern bool Cmdline_vulkan;
enum class WeaponSpewType { NONE = 0, STANDARD, ALL };
extern WeaponSpewType Cmdline_spew_weapon_stats;
extern void removeVSyncOption();
extern void removeWindowModeOption();
extern void removeResolutionOption();
extern void removeResolutionVROption();
#endif
+49 -24
View File
@@ -141,6 +141,9 @@ SCP_vector<cc_line> Cc_lines;
// Backups for use when user closes the config menu without saving
SCP_vector<CCI> Control_config_backup;
// The current preset that the user is working on and will likely want to save to
static SCP_string Current_preset_name;
// Undo system
Undo_system Undo_controls;
@@ -923,8 +926,8 @@ bool control_config_do_reset(bool cycle, bool API_Access)
// first, determine how many bindings need to be changed
for (size_t e = 0; e < Control_config.size(); ++e) {
auto item = Control_config[e];
auto default_item = default_bindings[e];
const auto& item = Control_config[e];
const auto& default_item = default_bindings[e];
if (item.disabled) {
// skip
@@ -1291,11 +1294,11 @@ bool control_config_accept(bool API_Access)
char* cstr; // Must be a char *, because popup_input may return nullptr and std::string don't like it
retry:;
SCP_string default_string = (Current_preset_name.empty()) ? Player->callsign : Current_preset_name;
cstr = popup_input(flags,
"Confirm new custom preset name.\n\nThe name must not be empty.\n\n Press [Enter] to accept, [Esc] to "
"abort to config menu.",
XSTR( "Confirm new custom preset name.\n\nThe name must not be empty or a default preset.\n\n Press [Enter] to accept, [Esc] to abort to config menu.", 1867),
32 - 6,
Player->callsign);
default_string.c_str());
if (cstr == nullptr) {
// Abort
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
@@ -1316,14 +1319,13 @@ bool control_config_accept(bool API_Access)
});
if (it != Control_config_presets.end()) {
popup(flags, 1, POPUP_OK, "You may not overwrite a default preset. Please choose another name.");
popup(flags | PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, "You may not overwrite a default preset. Please choose another name.");
goto retry;
}
// Check if a preset file with name already exists. If so, prompt the user
CFILE* fp = cfopen((str + ".json").c_str(),
"r",
CFILE_NORMAL,
CF_TYPE_PLAYER_BINDS,
false,
CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
@@ -1331,11 +1333,11 @@ bool control_config_accept(bool API_Access)
cfclose(fp);
int n = popup(flags,
2,
POPUP_OK,
POPUP_CANCEL,
POPUP_OK,
"'%s'\n Already exists!\n Press OK to overwrite existing preset, or CANCEL to input another name",
str.c_str());
if ((n == 1) || (n == -1)) {
if ((n == 0) || (n == -1)) {
// If Cancel button was pressed, or popup dismissed:
// retry
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
@@ -1345,7 +1347,7 @@ bool control_config_accept(bool API_Access)
// Pack the current bindings into a preset, then save the file
CC_preset preset;
preset.name = str;
preset.name = std::move(str);
std::copy(Control_config.begin(), Control_config.end(), std::back_inserter(preset.bindings));
Control_config_presets.push_back(preset);
save_preset_file(preset, true);
@@ -1354,11 +1356,19 @@ bool control_config_accept(bool API_Access)
// consistant ordering
Control_config_presets.resize(1);
load_preset_files();
// finally, save the new preset so that changes will get saved to this preset
Current_preset_name = preset.name;
} else {
return false;
}
}
// adds scripting hook for 'On Control Config Menu Closed' --wookieejedi
if (scripting::hooks::OnControlConfigMenuClosed->isActive()) {
scripting::hooks::OnControlConfigMenuClosed->run(scripting::hook_param_list(scripting::hook_param("OptionsAccepted", 'b', true)));
}
if (!API_Access) {
gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
gamesnd_play_iface(InterfaceSounds::COMMIT_PRESSED);
@@ -1374,8 +1384,8 @@ void control_config_cancel_exit(bool API_Access)
// Check if any changes were made
if (!API_Access && (control_config_get_current_preset() == Control_config_presets.end())) {
// Changes were made, prompt the user first.
int flags = PF_TITLE_WHITE;
int choice = popup(flags, 2, POPUP_NO, POPUP_YES, "You have unsaved changes.\n\n\n Do you wish to continue without saving?");
int flags = PF_TITLE_WHITE | PF_USE_NEGATIVE_ICON | PF_USE_AFFIRMATIVE_ICON;
int choice = popup(flags, 2, POPUP_NO, POPUP_YES, XSTR( "You have unsaved changes.\n\n\n Do you wish to continue without saving?", 1866));
switch (choice) {
case -1: // Aborted
@@ -1396,6 +1406,11 @@ void control_config_cancel_exit(bool API_Access)
// Restore all bindings with the backup
std::move(Control_config_backup.begin(), Control_config_backup.end(), Control_config.begin());
// adds scripting hook for 'On Control Config Menu Closed' --wookieejedi
if (scripting::hooks::OnControlConfigMenuClosed->isActive()) {
scripting::hooks::OnControlConfigMenuClosed->run(scripting::hook_param_list(scripting::hook_param("OptionsAccepted", 'b', false)));
}
if (!API_Access) {
gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
}
@@ -1537,9 +1552,11 @@ void control_config_init(bool API_Access)
// Init preset cycling system
auto preset_it = control_config_get_current_preset();
if (preset_it == Control_config_presets.end()) {
Current_preset_name.clear();
Defaults_cycle_pos = 0;
} else {
Current_preset_name = preset_it->name;
Defaults_cycle_pos = static_cast<unsigned int>(std::distance(Control_config_presets.begin(), preset_it));
}
@@ -1651,6 +1668,9 @@ void control_config_close(bool API_Access)
Cc_lines.clear();
Conflicts.clear();
Undo_controls.clear();
// Clear this, just to be tidy
Current_preset_name.clear();
}
SCP_vector<CC_preset>::iterator control_config_get_current_preset(bool invert_agnostic) {
@@ -1746,7 +1766,7 @@ bool control_config_delete_preset(CC_preset preset) {
return delete_preset_file(preset);
}
bool control_config_create_new_preset(SCP_string newName)
bool control_config_create_new_preset(const SCP_string& newName, bool overwrite)
{
// Check if a hardcoded preset with name already exists. If so, complain to user and force retry
@@ -1759,13 +1779,14 @@ bool control_config_create_new_preset(SCP_string newName)
}
// Check if a preset file with name already exists.
if ((cf_exists_full((newName + ".json").c_str(), CF_TYPE_PLAYER_BINDS)) != 0) {
if (!overwrite && ((cf_exists_full((newName + ".json").c_str(), CF_TYPE_PLAYER_BINDS)) != 0)) {
return false;
}
// Pack the current bindings into a preset, then save the file
CC_preset preset;
preset.name = newName;
preset.type = Preset_t::pst;
std::copy(Control_config.begin(), Control_config.end(), std::back_inserter(preset.bindings));
// Done with the file
@@ -1794,7 +1815,7 @@ bool control_config_create_new_preset(SCP_string newName)
return false; //should be unreachable, but just in case
}
bool control_config_clone_preset(CC_preset preset, SCP_string newName) {
bool control_config_clone_preset(const CC_preset& preset, const SCP_string& newName, bool overwrite) {
// Check if a hardcoded preset with name already exists. If so, complain to user and force retry
auto it = std::find_if(Control_config_presets.begin(), Control_config_presets.end(), [newName](CC_preset& p) {
@@ -1806,7 +1827,7 @@ bool control_config_clone_preset(CC_preset preset, SCP_string newName) {
}
// Check if a preset file with name already exists.
if ((cf_exists_full((newName + ".json").c_str(), CF_TYPE_PLAYER_BINDS)) != 0) {
if (!overwrite && ((cf_exists_full((newName + ".json").c_str(), CF_TYPE_PLAYER_BINDS)) != 0)) {
return false;
}
@@ -1896,7 +1917,7 @@ int control_config_draw_list(int select_tease_line) {
char buf[256]; // c_str buffer
int font_height = gr_get_font_height();
for (line = Scroll_offset; cc_line_query_visible(line); ++line) {
for (line = Scroll_offset; cc_line_query_visible(line) && (line - Scroll_offset < LIST_BUTTONS_MAX); ++line) {
z = Cc_lines[line].cc_index;
// screen coordinate y = list box origin y + (this item's relative y - topmost item's relative y)
@@ -2091,7 +2112,7 @@ int control_config_bind_key_on_frame(int ctrl, selItem item, bool API_Access)
}
if ((ctrl == BANK_WHEN_PRESSED || ctrl == GLIDE_WHEN_PRESSED) && (Last_key >= 0) && (k <= 0) &&
!keyd_pressed[Last_key]) {
!key_is_pressed(Last_key)) {
// If the selected cc_item is BANK_WHEN_PRESSED or GLIDE_WHEN_PRESSED, and
// If the polled key is a modifier, and
// k was consumed, and
@@ -2123,9 +2144,12 @@ int control_config_bind_key_on_frame(int ctrl, selItem item, bool API_Access)
if (!done && (j < JOY_TOTAL_BUTTONS)) {
// Bind the joy button
Assert(!Control_config[ctrl].is_axis());
control_config_bind(ctrl, CC_bind(static_cast<CID>(joy), j), item, API_Access);
strcpy_s(bound_string, Joy_button_text[j]);
CC_bind joy_bind(static_cast<CID>(joy), j);
control_config_bind(ctrl, joy_bind, item, API_Access);
strcpy_s(bound_string, joy_bind.textify().c_str());
done = true;
}
@@ -2159,9 +2183,10 @@ int control_config_bind_key_on_frame(int ctrl, selItem item, bool API_Access)
if (mouse_down(mouse_bind)) {
Assert(!Control_config[ctrl].is_axis());
control_config_bind(ctrl, mouse_bind, item, API_Access);
strcpy_s(bound_string, Joy_button_text[i]);
strcpy_s(bound_string, mouse_bind.textify().c_str());
done = true;
break;
@@ -2820,12 +2845,12 @@ int check_control_used(int id, int key)
// check what current modifiers are pressed
mask = 0;
if (keyd_pressed[KEY_LSHIFT] || key_down_count(KEY_LSHIFT) || keyd_pressed[KEY_RSHIFT] || key_down_count(KEY_RSHIFT)) {
if (key_is_pressed(KEY_LSHIFT, true) || key_is_pressed(KEY_RSHIFT, true)) {
// Any shift key is pressed, add KEY_SHIFTED mask
mask |= KEY_SHIFTED;
}
if (keyd_pressed[KEY_LALT] || key_down_count(KEY_LALT) || keyd_pressed[KEY_RALT] || key_down_count(KEY_RALT)) {
if (key_is_pressed(KEY_LALT, true) || key_is_pressed(KEY_RALT, true)) {
// Any alt key is pressed, add KEY_ALTED to the mask
mask |= KEY_ALTED;
}
@@ -2841,7 +2866,7 @@ int check_control_used(int id, int key)
z &= KEY_MASK;
if (keyd_pressed[z] || key_down_count(z)) {
if (key_is_pressed(z, true)) {
// Key combo is pressed, control activated
control_used(id);
return 1;
+21 -7
View File
@@ -36,8 +36,10 @@ enum Joy_axis_index : short {
JOY_RX_AXIS,
JOY_RY_AXIS,
JOY_RZ_AXIS,
JOY_U_AXIS,
JOY_V_AXIS,
JOY_NUM_AXES // Number of axes a joystick may have. Must be last enum in Joy_axis_index.
JOY_NUM_AXES //!< Max number of joy axes that FSO can handle. Must be last enum in Joy_axis_index.
};
// Aliases for mouse axes. Really should unify this...
@@ -297,6 +299,8 @@ enum IoActionId : int {
TOGGLE_HUD_SHADOWS,
CYCLE_PRIMARY_WEAPON_PATTERN,
/*!
* This must always be below the last defined item
*/
@@ -557,7 +561,7 @@ class CC_preset {
public:
SCP_vector<CCB> bindings;
SCP_string name;
Preset_t type;
Preset_t type = Preset_t::hardcode;
public:
CC_preset() = default;
@@ -683,7 +687,6 @@ extern SCP_vector<conflict> Conflicts; //!< Stores conflict data for the keybind
extern SCP_vector<CCI> Control_config; //!< Stores the keyboard configuration
extern SCP_vector<CC_preset> Control_config_presets; // tabled control presets; pointers to config_item arrays
extern const char **Joy_button_text; // String table of button labels. XSTR'd on init.
extern bool Generate_controlconfig_table;
@@ -842,7 +845,7 @@ bool control_config_delete_preset(CC_preset preset);
* @returns TRUE if successful
* @returns FALSE if the preset already exists with that name
*/
bool control_config_clone_preset(CC_preset preset, SCP_string name);
bool control_config_clone_preset(const CC_preset& preset, const SCP_string& name, bool overwrite);
/*!
* @brief Saves a preset with the current controls
@@ -850,7 +853,7 @@ bool control_config_clone_preset(CC_preset preset, SCP_string name);
* @returns TRUE if successful
* @returns FALSE if the preset already exists with that name
*/
bool control_config_create_new_preset(SCP_string name);
bool control_config_create_new_preset(const SCP_string& name, bool overwrite);
/*!
* Returns the IoActionId (index within Control_config[]) of a control bound to the given key
@@ -908,7 +911,18 @@ const char *textify_scancode(int code);
*/
const char *textify_scancode_universal(int code);
/*!
/**
* @brief Creates a button label based on btn index and locale settings.
*
* @param[in] btn The btn to textify
*
* @return The text representation of the btn
*
* @note Not thread safe. Has an internal buffer for the return value which is overwritten on each call.
*/
const char* textify_button(int btn);
/*!
* @brief Checks how long a control has been active
*
* @param[in] id The IoActionId of the control to check
@@ -947,7 +961,7 @@ int check_control(int id, int key = -1);
void control_get_axes_readings(int *axis_v, float frame_time);
/**
* @brief Markes the given control (by IoActionId) as used
* @brief Marks the given control (by IoActionId) as used
*
* @details Updates the ::used timestamp, triggers a script hook, and marks ::continous_ongoing as true
*/
+109 -107
View File
@@ -48,12 +48,13 @@ int Joy_dead_zone_size = 10;
auto DeadZoneOption = options::OptionBuilder<int>("Input.JoystickDeadZone",
std::pair<const char*, int>{"Deadzone", 1377},
std::pair<const char*, int>{"The deadzone used for all joysticks", 1744})
.category("Input")
.category(std::make_pair("Input", 1827))
.range(0, 45)
.level(options::ExpertLevel::Beginner)
.default_val(10)
.bind_to(&Joy_dead_zone_size)
.importance(1)
.flags({options::OptionFlags::RetailBuiltinOption})
.finish();
int Joy_sensitivity = 9;
@@ -61,12 +62,13 @@ int Joy_sensitivity = 9;
auto SensitivityOption = options::OptionBuilder<int>("Input.JoystickSensitivity",
std::pair<const char*, int>{"Sensitivity", 1745},
std::pair<const char*, int>{"The sensitivity used for all joysticks", 1746})
.category("Input")
.category(std::make_pair("Input", 1827))
.range(0, 9)
.level(options::ExpertLevel::Beginner)
.default_val(9)
.bind_to(&Joy_sensitivity)
.importance(2)
.flags({options::OptionFlags::RetailBuiltinOption})
.finish();
//! arrays which hold the key mappings. The array index represents a key-independent action.
@@ -176,6 +178,7 @@ void control_config_common_init_bindings() {
(CYCLE_NEXT_PRIMARY, KEY_PERIOD, -1, WEAPON_TAB, 1, "Cycle Primary Weapon Forward", CC_TYPE_TRIGGER)
(CYCLE_PREV_PRIMARY, KEY_COMMA, -1, WEAPON_TAB, 1, "Cycle Primary Weapon Backward", CC_TYPE_TRIGGER)
(CYCLE_PRIMARY_WEAPON_SEQUENCE, KEY_O, -1, WEAPON_TAB, 1776, "Cycle Primary Weapon Firing Rate", CC_TYPE_TRIGGER)
(CYCLE_PRIMARY_WEAPON_PATTERN, KEY_ALTED | KEY_O, -1, WEAPON_TAB, 1859, "Cycle Primary Weapon Firing Pattern", CC_TYPE_TRIGGER)
(CYCLE_SECONDARY, KEY_DIVIDE, -1, WEAPON_TAB, 1, "Cycle Secondary Weapon Forward", CC_TYPE_TRIGGER)
(CYCLE_NUM_MISSLES, KEY_SHIFTED | KEY_DIVIDE, -1, WEAPON_TAB, 1, "Cycle Secondary Weapon Firing Rate", CC_TYPE_TRIGGER)
(LAUNCH_COUNTERMEASURE, KEY_X, 3, WEAPON_TAB, 1, "Launch Countermeasure", CC_TYPE_TRIGGER)
@@ -207,10 +210,10 @@ void control_config_common_init_bindings() {
(VIEW_DIST_INCREASE, KEY_PADPLUS, -1, COMPUTER_TAB, 1, "Increase View Distance", CC_TYPE_CONTINUOUS)
(VIEW_DIST_DECREASE, KEY_PADMINUS, -1, COMPUTER_TAB, 1, "Decrease View Distance", CC_TYPE_CONTINUOUS)
(VIEW_CENTER, KEY_PAD5, -1, COMPUTER_TAB, 1, "Center View", CC_TYPE_CONTINUOUS)
(PADLOCK_UP, -1, 33, COMPUTER_TAB, 1, "View Up", CC_TYPE_CONTINUOUS)
(PADLOCK_DOWN, -1, 32, COMPUTER_TAB, 1, "View Rear", CC_TYPE_CONTINUOUS)
(PADLOCK_LEFT, -1, 34, COMPUTER_TAB, 1, "View Left", CC_TYPE_CONTINUOUS)
(PADLOCK_RIGHT, -1, 35, COMPUTER_TAB, 1, "View Right", CC_TYPE_CONTINUOUS)
(PADLOCK_UP, -1, iHAT_UP, COMPUTER_TAB, 1, "View Up", CC_TYPE_CONTINUOUS)
(PADLOCK_DOWN, -1, iHAT_DOWN, COMPUTER_TAB, 1, "View Rear", CC_TYPE_CONTINUOUS)
(PADLOCK_LEFT, -1, iHAT_LEFT, COMPUTER_TAB, 1, "View Left", CC_TYPE_CONTINUOUS)
(PADLOCK_RIGHT, -1, iHAT_RIGHT, COMPUTER_TAB, 1, "View Right", CC_TYPE_CONTINUOUS)
(VIEW_TOPDOWN, -1, -1, COMPUTER_TAB, 1777, "Top-Down View", CC_TYPE_TRIGGER)
(VIEW_TRACK_TARGET, -1, -1, COMPUTER_TAB, 1778, "Target Padlock View", CC_TYPE_TRIGGER)
@@ -429,6 +432,7 @@ SCP_unordered_map<SCP_string, IoActionId> old_text = {
{"Cycle Nav Points", NAV_CYCLE},
{"Toggle Gliding", TOGGLE_GLIDING},
{"Cycle Primary Weapon Firing Rate", CYCLE_PRIMARY_WEAPON_SEQUENCE},
{"Cycle Primary Weapon Firing Pattern", CYCLE_PRIMARY_WEAPON_PATTERN},
{"Custom Control 1", CUSTOM_CONTROL_1},
{"Custom Control 2", CUSTOM_CONTROL_2},
{"Custom Control 3", CUSTOM_CONTROL_3},
@@ -436,67 +440,38 @@ SCP_unordered_map<SCP_string, IoActionId> old_text = {
{"Custom Control 5", CUSTOM_CONTROL_5},
};
const char* Joy_button_text_german_u[] = {
"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",
"Knopf 19", "Knopf 20", "Knopf 21", "Knopf 22", "Knopf 23", "Knopf 24",
"Knopf 25", "Knopf 26", "Knopf 27", "Knopf 28", "Knopf 29", "Knopf 30",
"Knopf 31", "Knopf 32", "Hut Hinten", "Hut Vorne", "Hut Links", "Hut Rechts"
// Localization strings for hat positions. Back[0], Forward[1], Left[2], Right[3]
// This ordering is used to follow the same logic as hatBtnToEnum in joy-sdl.cpp
const char* Joy_hat_text_german_u[JOY_NUM_HAT_POS] = {
"Hut Hinten", "Hut Vorne", "Hut Links", "Hut Rechts"
};
const char* Joy_button_text_french_u[] = {
"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",
"Bouton 19", "Bouton 20", "Bouton 21", "Bouton 22", "Bouton 23", "Bouton 24",
"Bouton 25", "Bouton 26", "Bouton 27", "Bouton 28", "Bouton 29", "Bouton 30",
"Bouton 31", "Bouton 32", ("Chapeau Arri\xc3\xa8""re"), "Chapeau Avant", "Chapeau Gauche", "Chapeau Droite"
const char* Joy_hat_text_french_u[JOY_NUM_HAT_POS] = {
("Chapeau Arri\xc3\xa8""re"), "Chapeau Avant", "Chapeau Gauche", "Chapeau Droite"
};
const char* Joy_button_text_polish_u[] = {
"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",
"Przyc.19", "Przyc.20", "Przyc.21", "Przyc.22", "Przyc.23", "Przyc.24",
"Przyc.25", "Przyc.26", "Przyc.27", "Przyc.28", "Przyc.29", "Przyc.30",
"Przyc.31", "Przyc.32", "Hat Ty\xc5\x82", ("Hat Prz\xc3\xb3""d"), "Hat Lewo", "Hat Prawo"
const char* Joy_hat_text_polish_u[JOY_NUM_HAT_POS] = {
"Hat Ty\xc5\x82", ("Hat Prz\xc3\xb3""d"), "Hat Lewo", "Hat Prawo"
};
const char* Joy_button_text_english_u[] = {
"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",
"Button 19", "Button 20", "Button 21", "Button 22", "Button 23", "Button 24",
"Button 25", "Button 26", "Button 27", "Button 28", "Button 29", "Button 30",
"Button 31", "Button 32", "Hat Back", "Hat Forward", "Hat Left", "Hat Right"
const char* Joy_hat_text_english_u[JOY_NUM_HAT_POS] = {
"Hat Back", "Hat Forward", "Hat Left", "Hat Right"
};
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",
"Knopf 19", "Knopf 20", "Knopf 21", "Knopf 22", "Knopf 23", "Knopf 24",
"Knopf 25", "Knopf 26", "Knopf 27", "Knopf 28", "Knopf 29", "Knopf 30",
"Knopf 31", "Knopf 32", "Hut Hinten", "Hut Vorne", "Hut Links", "Hut Rechts"
const char* Joy_hat_text_german[JOY_NUM_HAT_POS] = {
"Hut Hinten", "Hut Vorne", "Hut Links", "Hut Rechts"
};
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",
"Bouton 19", "Bouton 20", "Bouton 21", "Bouton 22", "Bouton 23", "Bouton 24",
"Bouton 25", "Bouton 26", "Bouton 27", "Bouton 28", "Bouton 29", "Bouton 30",
"Bouton 31", "Bouton 32", "Chapeau Arri\x8Are", "Chapeau Avant", "Chapeau Gauche", "Chapeau Droite"
const char* Joy_hat_text_french[JOY_NUM_HAT_POS] = {
"Chapeau Arri\x8Are", "Chapeau Avant", "Chapeau Gauche", "Chapeau Droite"
};
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",
"Przyc.19", "Przyc.20", "Przyc.21", "Przyc.22", "Przyc.23", "Przyc.24",
"Przyc.25", "Przyc.26", "Przyc.27", "Przyc.28", "Przyc.29", "Przyc.30",
"Przyc.31", "Przyc.32", "Hat Ty\xB3", "Hat Prz\xF3\x64", "Hat Lewo", "Hat Prawo"
const char* Joy_hat_text_polish[JOY_NUM_HAT_POS] = {
"Hat Ty\xB3", "Hat Prz\xF3\x64", "Hat Lewo", "Hat Prawo"
};
const char* Joy_hat_text_english[JOY_NUM_HAT_POS] = {
"Hat Back", "Hat Forward", "Hat Left", "Hat Right"
};
//English scancodes are still needed eclusively for the scripting API, as we need to give generic and stable scan code names to the API that are neither translated nor localized to keyboard layout.
@@ -542,17 +517,6 @@ const char *Scan_code_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",
"Button 19", "Button 20", "Button 21", "Button 22", "Button 23", "Button 24",
"Button 25", "Button 26", "Button 27", "Button 28", "Button 29", "Button 30",
"Button 31", "Button 32", "Hat Back", "Hat Forward", "Hat Left", "Hat Right"
};
const char **Joy_button_text = Joy_button_text_english;
bool Generate_controlconfig_table = false;
int sections_read = 0; // Number of sections read within the controlconfigdefaults.tbl
@@ -721,7 +685,69 @@ const char *textify_scancode_universal(int code)
return text;
}
//XSTR:ON
const char* textify_button(int btn) {
static char text[BTN_MSG_LEN];
if ((btn < 0) || (btn >= JOY_TOTAL_BUTTONS))
return "None";
text[0] = '\0';
if (btn < JOY_NUM_BUTTONS) {
// Is a button.
if (Lcl_gr) {
sprintf(text, "Knopf %i", btn);
} else if (Lcl_fr) {
sprintf(text, "Bouton %i", btn);
} else if (Lcl_pl) {
sprintf(text, "Przyc.%i", btn);
} else {
sprintf(text, "Button %i", btn);
}
} else {
//is Hat
btn -= JOY_NUM_BUTTONS;
Assertion(btn <= JOY_NUM_HAT_POS, "Invalid btn value '%i' after hat position translation.", btn);
if (Unicode_text_mode) {
// use unicode character maps
if (Lcl_gr) {
strcpy_s(text, Joy_hat_text_german_u[btn]);
} else if (Lcl_fr) {
strcpy_s(text, Joy_hat_text_french_u[btn]);
} else if (Lcl_pl) {
strcpy_s(text, Joy_hat_text_polish_u[btn]);
} else {
strcpy_s(text, Joy_hat_text_english_u[btn]);
}
} else {
// use ascii character maps
if (Lcl_gr) {
strcpy_s(text, Joy_hat_text_german[btn]);
} else if (Lcl_fr) {
strcpy_s(text, Joy_hat_text_french[btn]);
} else if (Lcl_pl) {
strcpy_s(text, Joy_hat_text_polish[btn]);
} else {
strcpy_s(text, Joy_hat_text_english[btn]);
}
}
}
return text;
}
//XSTR:ON
void control_config_common_load_overrides();
@@ -754,36 +780,6 @@ void control_config_common_init()
// load player presets
load_preset_files();
// Init control label localization
if (Unicode_text_mode) {
if (Lcl_gr) {
Joy_button_text = Joy_button_text_german_u;
}
else if (Lcl_fr) {
Joy_button_text = Joy_button_text_french_u;
}
else if (Lcl_pl) {
Joy_button_text = Joy_button_text_polish_u;
}
else {
Joy_button_text = Joy_button_text_english_u;
}
}
else {
if (Lcl_gr) {
Joy_button_text = Joy_button_text_german;
}
else if (Lcl_fr) {
Joy_button_text = Joy_button_text_french;
}
else if (Lcl_pl) {
Joy_button_text = Joy_button_text_polish;
}
else {
Joy_button_text = Joy_button_text_english;
}
}
// Old XSTR indices have been put beside their corresponding label in case we use them again
Axis_text[0] = vm_strdup(XSTR("X Axis", 1647)); // XSTR 1021 - "Joystick/Mouse X Axis"
Axis_text[1] = vm_strdup(XSTR("Y Axis", 1648)); // XSTR 1022 - "Joystick/Mouse Y Axis"
@@ -791,6 +787,8 @@ void control_config_common_init()
Axis_text[3] = vm_strdup(XSTR("rX Axis", 1650)); // XSTR 1024 - "Joystick rX Axis"
Axis_text[4] = vm_strdup(XSTR("rY Axis", 1651)); // XSTR 1025 - "Joystick rY Axis"
Axis_text[5] = vm_strdup(XSTR("rZ Axis", 1652)); // XSTR 1026 - "Joystick rZ Axis"
Axis_text[6] = vm_strdup(XSTR("U Axis", 1860));
Axis_text[7] = vm_strdup(XSTR("V Axis", 1861));
Mouse_button_text[0] = vm_strdup(XSTR("Left Button", 1027));
Mouse_button_text[1] = vm_strdup(XSTR("Right Button", 1028));
@@ -1152,6 +1150,7 @@ void LoadEnumsIntoActionMap() {
ADD_ENUM_TO_ACTION_MAP(TOGGLE_GLIDING)
ADD_ENUM_TO_ACTION_MAP(CYCLE_PRIMARY_WEAPON_SEQUENCE)
ADD_ENUM_TO_ACTION_MAP(CYCLE_PRIMARY_WEAPON_PATTERN)
ADD_ENUM_TO_ACTION_MAP(CUSTOM_CONTROL_1)
ADD_ENUM_TO_ACTION_MAP(CUSTOM_CONTROL_2)
@@ -1204,6 +1203,8 @@ void LoadEnumsIntoAxisMap() {
mAxisNameToVal["RX_AXIS"] = JOY_RX_AXIS;
mAxisNameToVal["RY_AXIS"] = JOY_RY_AXIS;
mAxisNameToVal["RZ_AXIS"] = JOY_RZ_AXIS;
mAxisNameToVal["U_AXIS"] = JOY_U_AXIS;
mAxisNameToVal["V_AXIS"] = JOY_V_AXIS;
}
void LoadEnumsIntoHatMap() {
@@ -1955,7 +1956,7 @@ int control_config_common_write_tbl(bool overwrite = false, bool all = false) {
return 1;
}
CFILE* cfile = cfopen("controlconfigdefaults.tbl", "w", CFILE_NORMAL, CF_TYPE_TABLES);
CFILE* cfile = cfopen("controlconfigdefaults.tbl", "w", CF_TYPE_TABLES);
if (cfile == nullptr) {
// Could not open. Bail.
return 1;
@@ -2648,22 +2649,21 @@ SCP_string CC_bind::textify() const {
SCP_string prefix;
SCP_string retval;
// TODO: XSTR the Mouse/Joy prefix
switch (cid) {
case CID_MOUSE:
prefix = "Mouse ";
prefix = XSTR("Mouse ", 1868);
break;
case CID_JOY0:
prefix = "Joy-0 ";
prefix = XSTR("Joy-0 ", 1869);
break;
case CID_JOY1:
prefix = "Joy-1 ";
prefix = XSTR("Joy-1 ", 1870);
break;
case CID_JOY2:
prefix = "Joy-2 ";
prefix = XSTR("Joy-2 ", 1871);
break;
case CID_JOY3:
prefix = "Joy-3 ";
prefix = XSTR("Joy-3 ", 1872);
break;
case CID_NONE:
case CID_KEYBOARD:
@@ -2675,7 +2675,7 @@ SCP_string CC_bind::textify() const {
if (flags & CCF_AXIS) {
// Is Axis
if (cid == CID_NONE) {
retval = "None";
retval = XSTR("None", 1873);
} else {
Assert((btn >= 0) && (btn < NUM_AXIS_TEXT));
retval = SCP_string(Axis_text[btn]);
@@ -2698,12 +2698,12 @@ SCP_string CC_bind::textify() const {
case CID_JOY2:
case CID_JOY3:
Assert((btn >= 0) && (btn < JOY_TOTAL_BUTTONS));
retval = SCP_string(Joy_button_text[btn]);
retval = SCP_string(textify_button(btn));
break;
case CID_NONE:
default:
retval = "None";
retval = XSTR("None", 1873);
break;
}
}
@@ -2782,10 +2782,12 @@ bool CCB::operator!=(const CCB& A) const {
}
bool CCB::has_first_conflict(const CCB& A) const {
// coverity[copy_paste_error:FALSE]
return !first.empty() && (first.conflicts_with(A.first) || first.conflicts_with(A.second));
}
bool CCB::has_second_conflict(const CCB& A) const {
// coverity[copy_paste_error:FALSE]
return !second.empty() && (second.conflicts_with(A.first) || second.conflicts_with(A.second));
}
+11 -5
View File
@@ -1,7 +1,9 @@
#include "controlconfig/controlsconfig.h"
#include "controlconfig/presets.h"
#include "gamesequence/gamesequence.h"
#include "libs/jansson.h"
#include "parse/parselo.h"
#include "popup/popup.h"
#include <jansson.h>
@@ -43,7 +45,7 @@ void load_preset_files(SCP_string clone) {
std::unique_ptr<PresetFileHandler> handler = nullptr;
for (const auto &file : filelist) {
CFILE* fp = cfopen((file + ".json").c_str(), "r", CFILE_NORMAL, CF_TYPE_PLAYER_BINDS, false,
CFILE* fp = cfopen((file + ".json").c_str(), "r", CF_TYPE_PLAYER_BINDS, false,
CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
if (!fp) {
@@ -133,8 +135,12 @@ void load_preset_files(SCP_string clone) {
Control_config_presets.push_back(preset);
} else if ((it->name != preset.name) || (it->type != Preset_t::pst)) {
// Complain and ignore if the preset names or the type differs
Warning(LOCATION, "PST => Preset '%s' is a duplicate of an existing preset, ignoring", preset.name.c_str());
if (gameseq_get_state() == GS_STATE_CONTROL_CONFIG) {
popup(PF_TITLE_WHITE | PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, "Preset '%s' is a duplicate of an existing preset, ignoring", preset.name.c_str());
} else {
// Complain and ignore if the preset names or the type differs
Warning(LOCATION, "PST => Preset '%s' is a duplicate of an existing preset, ignoring", preset.name.c_str());
}
} // else, silent ignore
}
@@ -184,7 +190,7 @@ bool save_preset_file(CC_preset preset, bool overwrite) {
std::unique_ptr<PresetFileHandler> handler = nullptr;
// Check if there's a file already
CFILE* fp = cfopen(filename.c_str(), "r", CFILE_NORMAL, CF_TYPE_PLAYER_BINDS, false,
CFILE* fp = cfopen(filename.c_str(), "r", CF_TYPE_PLAYER_BINDS, false,
CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
if ((fp != nullptr) && !overwrite) {
@@ -193,7 +199,7 @@ bool save_preset_file(CC_preset preset, bool overwrite) {
}
// Try opening file for write
fp = cfopen(filename.c_str(), "w", CFILE_NORMAL, CF_TYPE_PLAYER_BINDS, false,
fp = cfopen(filename.c_str(), "w", CF_TYPE_PLAYER_BINDS, false,
CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
if (!fp) {
+20 -13
View File
@@ -25,6 +25,8 @@
extern int Cmdline_nomovies;
bool Movie_active = false;
const char* Cutscene_bitmap_name[GR_NUM_RESOLUTIONS] = {
"ViewFootage",
@@ -60,6 +62,18 @@ static cutscene_info *get_cutscene_pointer(char *cutscene_filename)
return NULL;
}
int get_cutscene_index_by_name(const char* name)
{
for (int i = 0; i < static_cast<int>(Cutscenes.size()); i++) {
if (!stricmp(name, Cutscenes[i].name)) {
return i;
}
}
// Didn't find anything.
return -1;
}
static void cutscene_info_init(cutscene_info *csni)
{
csni->filename[0] = '\0';
@@ -340,32 +354,25 @@ static const char* Text_lines[MAX_TEXT_LINES];
void cutscenes_screen_play()
{
char name[MAX_FILENAME_LEN]; // *full_name
int which_cutscene;
Assert((Selected_line >= 0) && (Selected_line < (int) Cutscene_list.size()));
which_cutscene = Cutscene_list[Selected_line];
strcpy_s(name, Cutscenes[which_cutscene].filename);
// full_name = cf_add_ext(name, NOX(".mve"));
Assertion(SCP_vector_inbounds(Cutscene_list, Selected_line), "Selected line %d is out of range!", Selected_line);
int which_cutscene = Cutscene_list[Selected_line];
main_hall_stop_music(true);
main_hall_stop_ambient();
auto rval = movie::play(name);
auto rval = movie::play(Cutscenes[which_cutscene].filename, true);
main_hall_start_music();
if (!rval)
{
char str[256];
SCP_string str;
if (Cmdline_nomovies)
strcpy_s(str, XSTR("Movies are currently disabled.", 1574));
str = XSTR("Movies are currently disabled.", 1574);
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.c_str());
}
}
void cutscenes_screen_scroll_line_up()
+4
View File
@@ -37,6 +37,8 @@ typedef struct cutscene_info
extern SCP_vector<cutscene_info> Cutscenes;
extern bool Movie_active;
// initializa table data
void cutscene_init();
@@ -48,4 +50,6 @@ void cutscenes_screen_do_frame();
void cutscene_mark_viewable(const char* filename);
int get_cutscene_index_by_name(const char* name);
#endif
+1 -1
View File
@@ -6,7 +6,7 @@ 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 OUT_NUM_CHANNELS = av_popcount64(OUT_CH_LAYOUT);
const int DEFAULT_SRC_NUM_SAMPLES = 1024;
+5 -1
View File
@@ -69,7 +69,11 @@ CodecContextParameters getCodecParameters(AVStream* stream) {
paras.height = stream->codecpar->height;
paras.pixel_format = (AVPixelFormat)stream->codecpar->format;
paras.channel_layout = stream->codecpar->channel_layout;
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(59, 36, 255)
paras.channel_layout = stream->codecpar->ch_layout.u.mask;
#else
paras.channel_layout = stream->codecpar->channel_layout;
#endif
paras.sample_rate = stream->codecpar->sample_rate;
paras.audio_format = (AVSampleFormat)stream->codecpar->format;
+1 -1
View File
@@ -122,7 +122,7 @@ void SubtitleDecoder::pushSubtitleFrame(AVPacket* packet, AVSubtitle* subtitle)
}
SubtitleFramePtr frame(new SubtitleFrame());
frame->text = processed_text;
frame->text = std::move(processed_text);
frame->displayStartTime = start_time;
frame->displayEndTime = end_time;
+36 -8
View File
@@ -30,6 +30,7 @@
#include "io/key.h"
#include "mod_table/mod_table.h"
#include "network/multi.h"
#include "scripting/global_hooks.h"
extern int Game_mode;
extern int Is_standalone;
@@ -45,6 +46,7 @@ struct PlaybackState {
vec2d posBottomRight;
int subtitle_font = -1;
color subtitle_color = Color_bright_white;
};
void processEvents()
@@ -102,7 +104,7 @@ void displayVideo(Player* player, PlaybackState* state) {
auto subtitle = player->getCurrentSubtitle();
if (!subtitle.empty() && state->subtitle_font >= 0) {
gr_set_color_fast(&Color_bright_white);
gr_set_color_fast(&state->subtitle_color);
font::set_font(state->subtitle_font);
int width;
@@ -179,7 +181,20 @@ void initialize_player_state(Player* player, PlaybackState* state) {
if (state->subtitle_font < 0) {
Warning(LOCATION, "Failed to load subtitle font '%s'! Subtitles will be disabled.", Movie_subtitle_font.c_str());
}
if ((Movie_subtitle_rgba[0] >= 0 && Movie_subtitle_rgba[0] <= 255) &&
(Movie_subtitle_rgba[1] >= 0 && Movie_subtitle_rgba[1] <= 255) &&
(Movie_subtitle_rgba[2] >= 0 && Movie_subtitle_rgba[2] <= 255) &&
(Movie_subtitle_rgba[3] >= 0 && Movie_subtitle_rgba[3] <= 255))
{
gr_init_alphacolor(&state->subtitle_color,
Movie_subtitle_rgba[0],
Movie_subtitle_rgba[1],
Movie_subtitle_rgba[2],
Movie_subtitle_rgba[3]);
}
}
else if (font::FontManager::numberOfFonts() > 0) {
state->subtitle_font = 0; // if not explicitly specified, default to the first available font
@@ -258,12 +273,22 @@ void movie_display_loop(Player* player, PlaybackState* state) {
namespace movie {
// Play one movie
bool play(const char* name) {
bool play(const char* filename, bool via_tech_room = false)
{
if (scripting::hooks::OnMovieAboutToPlay->isActive())
{
auto paramList = scripting::hook_param_list(scripting::hook_param("Filename", 's', filename), scripting::hook_param("ViaTechRoom", 'b', via_tech_room));
bool skip = scripting::hooks::OnMovieAboutToPlay->isOverride(paramList);
scripting::hooks::OnMovieAboutToPlay->run(paramList);
if (skip)
return false;
}
// 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
if (Game_mode & GM_CAMPAIGN_MODE) {
cutscene_mark_viewable(name);
cutscene_mark_viewable(filename);
}
if (Cmdline_nomovies || Is_standalone) {
@@ -278,6 +303,7 @@ bool play(const char* name) {
// clear the screen and hide the mouse cursor
io::mouse::CursorManager::get()->pushStatus();
io::mouse::CursorManager::get()->showCursor(false);
Movie_active = true;
gr_reset_clip();
gr_set_color(255, 255, 255);
gr_set_clear_color(0, 0, 0);
@@ -291,7 +317,7 @@ bool play(const char* name) {
// clear third buffer (may not be one, but that's ok)
gr_clear();
auto player = cutscene::Player::newPlayer(name);
auto player = cutscene::Player::newPlayer(filename);
if (player) {
PlaybackState state;
initialize_player_state(player.get(), &state);
@@ -301,18 +327,20 @@ bool play(const char* name) {
player->stopPlayback();
} else {
// uh-oh, movie is invalid... Abory, Retry, Fail?
mprintf(("MOVIE ERROR: Found invalid movie! (%s)\n", name));
mprintf(("MOVIE ERROR: Found invalid movie! (%s)\n", filename));
}
Movie_active = false;
// show the mouse cursor again
io::mouse::CursorManager::get()->popStatus();
return true;
}
void play_two(const char* name1, const char* name2) {
if (play(name1)) {
play(name2);
void play_two(const char* filename1, const char* filename2) {
if (play(filename1)) {
play(filename2);
}
}
}
+2 -2
View File
@@ -14,9 +14,9 @@
namespace movie {
bool play(const char* name);
bool play(const char* filename, bool via_tech_room = false);
void play_two(const char* name1, const char* name2);
void play_two(const char* filename1, const char* filename2);
}
File diff suppressed because it is too large. Load diff
+334 -179
View File
@@ -3,6 +3,17 @@
#include "cfile/cfile.h"
#include "osapi/osregistry.h"
#ifdef WITH_OPENGL
#include <glad/glad.h>
#else
static constexpr int GLAD_GL_EXT_texture_compression_s3tc = 0;
static constexpr int GLAD_GL_ARB_texture_compression_bptc = 0;
#endif
#define BCDEC_IMPLEMENTATION 1
PUSH_SUPPRESS_WARNINGS
#include "ddsutils/bcdec.h"
POP_SUPPRESS_WARNINGS
/* Currently supported formats:
* DXT1a (compressed)
@@ -12,12 +23,9 @@
* uncompressed 1555 (16-bit, 1-bit being alpha)
* uncompressed 8888 (32-bit)
* uncompressed 888 (24-bit, no alpha)
* paletted 8-bit (256 colors)
* uncompressed R8 (8-bit, Red channel as luminance)
*/
int Texture_compression_available = 0;
int Use_compressed_textures = 0;
// power of two check, to verify that a given DDS will always be usable since
// some may not be power-of-2
@@ -26,39 +34,219 @@ static inline int is_power_of_two(int w, int h)
return ( (w && !(w & (w-1))) && (h && !(h & (h-1))) );
}
// This function is used to verify that the file format specified in the DX10 Header
// is supported by the OpenGL extensions
bool dds_read_dx10_header(CFILE* dds_file, DDS_HEADER_DXT10* header)
static bool valid_dx10_format(const DDS_HEADER_DXT10 &header)
{
header->dxgiFormat = static_cast<DXGI_FORMAT>(cfread_uint(dds_file));
header->resourceDimension = static_cast<D3D10_RESOURCE_DIMENSION>(cfread_uint(dds_file));
header->miscFlag = cfread_uint(dds_file);
header->arraySize = cfread_uint(dds_file);
header->miscFlags2 = cfread_uint(dds_file);
switch (header.dxgiFormat) {
case DXGI_FORMAT::DXGI_FORMAT_BC7_TYPELESS:
case DXGI_FORMAT::DXGI_FORMAT_BC7_UNORM:
case DXGI_FORMAT::DXGI_FORMAT_BC7_UNORM_SRGB:
return true;
switch (header->dxgiFormat) {
case DXGI_FORMAT::DXGI_FORMAT_BC7_TYPELESS:
case DXGI_FORMAT::DXGI_FORMAT_BC7_UNORM:
case DXGI_FORMAT::DXGI_FORMAT_BC7_UNORM_SRGB:
return true;
default:
return false;
default:
return false;
}
}
int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *height, int *bpp, int *compression_type, int *levels, size_t *size, ubyte *palette)
static bool conversion_needed(const DDS_HEADER &dds_header)
{
if ((dds_header.ddspf.dwFlags & DDPF_FOURCC) != DDPF_FOURCC) {
return false;
}
switch (dds_header.ddspf.dwFourCC) {
case FOURCC_DXT1:
case FOURCC_DXT3:
case FOURCC_DXT5:
return !GLAD_GL_EXT_texture_compression_s3tc;
case FOURCC_DX10:
// anything other than BC7 will end up invalid
return !GLAD_GL_ARB_texture_compression_bptc;
default:
break;
}
// anything not specifically listed should end up invalid
return false;
}
// Memory usage for uncompressed textures is quite high. Some MVP assets can
// require well over a GB of VRAM for a single ship after conversion. To help
// alleviate this we need to resize those textures where possible. At 1024x1024
// the memory requirement is reduced to about 36 MB per ship with a full set
// of textures.
//
// NOTE: modifies header!!
//
// returns: number of mipmap levels to skip
static uint conversion_resize(DDS_HEADER &dds_header)
{
const size_t MAX_SIZE = 1024;
uint width, height, depth, offset = 0;
if (dds_header.dwMipMapCount <= 1) {
return 0;
}
width = dds_header.dwWidth;
height = dds_header.dwHeight;
depth = dds_header.dwDepth;
// drop levels until we get to an appropriate size, but make sure we have
// at least 1 mipmap level remaining at the end (in case there's not a full chain)
while (((width > MAX_SIZE) || (height > MAX_SIZE)) && (offset < dds_header.dwMipMapCount-1)) {
width >>= 1;
height >>= 1;
depth >>= 1;
++offset;
}
// no change needed
if ( !offset ) {
return offset;
}
// update header with new values
dds_header.dwWidth = std::max(1U, width);
dds_header.dwHeight = std::max(1U, height);
dds_header.dwDepth = std::max(1U, depth);
return offset;
}
static int _dds_read_header(CFILE *ddsfile, DDS_HEADER &dds_header, DDS_HEADER_DXT10 *dds_header_dx10 = nullptr)
{
DDS_HEADER_DXT10 dx10_header;
// read the code
int code = cfread_int(ddsfile);
// check it
if (code != DDS_FILECODE) {
return DDS_ERROR_BAD_HEADER;
}
// read header variables
dds_header.dwSize = cfread_uint(ddsfile);
dds_header.dwFlags = cfread_uint(ddsfile);
dds_header.dwHeight = cfread_uint(ddsfile);
dds_header.dwWidth = cfread_uint(ddsfile);
dds_header.dwPitchOrLinearSize = cfread_uint(ddsfile);
dds_header.dwDepth = cfread_uint(ddsfile);
dds_header.dwMipMapCount = cfread_uint(ddsfile);
// skip over the crap we don't care about
cfseek(ddsfile, 11*4, CF_SEEK_CUR);
dds_header.ddspf.dwSize = cfread_uint(ddsfile);
dds_header.ddspf.dwFlags = cfread_uint(ddsfile);
dds_header.ddspf.dwFourCC = cfread_uint(ddsfile);
dds_header.ddspf.dwRGBBitCount = cfread_uint(ddsfile);
dds_header.ddspf.dwRBitMask = cfread_uint(ddsfile);
dds_header.ddspf.dwGBitMask = cfread_uint(ddsfile);
dds_header.ddspf.dwBBitMask = cfread_uint(ddsfile);
dds_header.ddspf.dwABitMask = cfread_uint(ddsfile);
dds_header.dwCaps = cfread_uint(ddsfile);
dds_header.dwCaps2 = cfread_uint(ddsfile);
// Unused but need them checked for later
dds_header.dwCaps3 = cfread_uint(ddsfile);
dds_header.dwCaps4 = cfread_uint(ddsfile);
dds_header.dwReserved2 = cfread_uint(ddsfile);
if (dds_header.ddspf.dwFourCC == FOURCC_DX10) {
dx10_header.dxgiFormat = static_cast<DXGI_FORMAT>(cfread_uint(ddsfile));
dx10_header.resourceDimension = static_cast<D3D10_RESOURCE_DIMENSION>(cfread_uint(ddsfile));
dx10_header.miscFlag = cfread_uint(ddsfile);
dx10_header.arraySize = cfread_uint(ddsfile);
dx10_header.miscFlags2 = cfread_uint(ddsfile);
if (dds_header_dx10) {
memcpy(dds_header_dx10, &dx10_header, sizeof(DDS_HEADER_DXT10));
}
}
// sanitize values
dds_header.dwDepth = std::max(1U, dds_header.dwDepth);
dds_header.dwMipMapCount = std::max(1U, dds_header.dwMipMapCount);
#ifndef NDEBUG
if (dds_header.dwDepth > 1) {
Assertion(dds_header.dwFlags & DDSD_DEPTH, "ERROR: Volume texture missing proper flags!!");
}
#endif
// set pitch manually (per MS docs)
dds_header.dwFlags &= ~DDSD_LINEARSIZE;
dds_header.dwFlags |= DDSD_PITCH;
if (dds_header.ddspf.dwFlags & DDPF_FOURCC) {
int block_size = (dds_header.ddspf.dwFourCC == FOURCC_DXT1) ? 8 : 16;
dds_header.dwPitchOrLinearSize = std::max(1U, (dds_header.dwWidth+3)/4) * block_size;
} else {
// this isn't technically correct, but it's only wrong for formats we don't support
dds_header.dwPitchOrLinearSize = (dds_header.dwWidth * dds_header.ddspf.dwRGBBitCount + 7) / 8;
}
return DDS_ERROR_NONE;
}
static size_t compute_dds_size(const DDS_HEADER &dds_header)
{
uint d_width, d_height, d_depth;
size_t d_size = 0;
for (uint i = 0; i < dds_header.dwMipMapCount; i++) {
d_width = std::max(1U, dds_header.dwWidth >> i);
d_height = std::max(1U, dds_header.dwHeight >> i);
d_depth = std::max(1U, dds_header.dwDepth >> i);
if (dds_header.ddspf.dwFlags & DDPF_FOURCC) {
// size of data block (4x4)
d_size += ((d_width + 3) / 4) * ((d_height + 3) / 4) * d_depth * ((dds_header.ddspf.dwFourCC == FOURCC_DXT1) ? 8 : 16);
} else {
d_size += d_width * d_height * d_depth * (dds_header.ddspf.dwRGBBitCount / 8);
}
}
// assumes valid cubemap (should be checked elsewhere)
if (dds_header.dwCaps2 & DDSCAPS2_CUBEMAP) {
// the previously computed size is just per face, mult by 6 for full size
d_size *= 6;
}
Assertion(d_size > 0, "ERROR: DDS size computed to 0!!");
return d_size;
}
static int get_bit_count(const DDS_HEADER &dds_header)
{
if (dds_header.ddspf.dwFlags & DDPF_RGB) {
return dds_header.ddspf.dwRGBBitCount;
} else if (dds_header.ddspf.dwFlags & DDPF_FOURCC) {
if (dds_header.ddspf.dwFourCC == FOURCC_DXT1) {
return 24;
} else {
return 32;
}
}
return 0;
}
int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *height, int *bpp, int *compression_type, int *levels, size_t *size)
{
DDS_HEADER dds_header;
DDS_HEADER_DXT10 dds_header_dx10;
int code = 0;
CFILE *ddsfile;
char real_name[MAX_FILENAME_LEN];
int retval = DDS_ERROR_NONE;
int ct = DDS_UNCOMPRESSED;
int bits = 0;
int i, is_cubemap = 0;
uint32_t d_width = 0, d_height = 0, d_depth = 0;
size_t d_size = 0;
int is_cubemap = 0;
if (img_cfp == NULL) {
@@ -81,113 +269,36 @@ int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *heigh
ddsfile = img_cfp;
}
// read the code
code = cfread_int(ddsfile);
retval = _dds_read_header(ddsfile, dds_header, &dds_header_dx10);
// check it
if (code != DDS_FILECODE) {
retval = DDS_ERROR_BAD_HEADER;
if (retval != DDS_ERROR_NONE) {
goto Done;
}
// read header variables
dds_header.dwSize = cfread_uint(ddsfile);
dds_header.dwFlags = cfread_uint(ddsfile);
dds_header.dwHeight = cfread_uint(ddsfile);
dds_header.dwWidth = cfread_uint(ddsfile);
dds_header.dwPitchOrLinearSize = cfread_uint(ddsfile);
dds_header.dwDepth = cfread_uint(ddsfile);
dds_header.dwMipMapCount = cfread_uint(ddsfile);
// check for valid cubemap (we require all 6 faces)
if (dds_header.dwCaps2 & DDSCAPS2_CUBEMAP) {
if ( !(dds_header.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) ) {
retval = DDS_ERROR_CUBEMAP_FACES;
ct = DDS_DXT_INVALID;
goto Done;
}
// skip over the crap we don't care about
for (i = 0; i < 11; i++)
cfread_uint(ddsfile);
// it's a valid cubemap, probably
is_cubemap = 1;
}
dds_header.ddspf.dwSize = cfread_uint(ddsfile);
dds_header.ddspf.dwFlags = cfread_uint(ddsfile);
dds_header.ddspf.dwFourCC = cfread_uint(ddsfile);
dds_header.ddspf.dwRGBBitCount = cfread_uint(ddsfile);
dds_header.ddspf.dwRBitMask = cfread_uint(ddsfile);
dds_header.ddspf.dwGBitMask = cfread_uint(ddsfile);
dds_header.ddspf.dwBBitMask = cfread_uint(ddsfile);
dds_header.ddspf.dwABitMask = cfread_uint(ddsfile);
dds_header.dwCaps = cfread_uint(ddsfile);
dds_header.dwCaps2 = cfread_uint(ddsfile);
// Unused but need them checked for later
dds_header.dwCaps3 = cfread_uint(ddsfile);
dds_header.dwCaps4 = cfread_uint(ddsfile);
dds_header.dwReserved2 = cfread_uint(ddsfile);
// sanity
if (dds_header.dwDepth == 0)
dds_header.dwDepth = 1;
if (dds_header.dwMipMapCount < 1)
dds_header.dwMipMapCount = 1;
d_width = dds_header.dwWidth;
d_height = dds_header.dwHeight;
d_depth = dds_header.dwDepth;
// calculate the type and size of the data
// determine and verify the type of data for internal use
if (dds_header.ddspf.dwFlags & DDPF_FOURCC) {
// did I mention lately that I hate Microsoft?
// this is here to fix the situation where Microsoft doesn't follow their own docs
if ( !(dds_header.dwFlags & (DDSD_LINEARSIZE | DDSD_PITCH) ) || dds_header.dwPitchOrLinearSize <= 0 ) {
// calculate the block size, mult by 8 for DXT1, 16 for DXT3 & 5
d_size = ((dds_header.dwWidth + 3)/4) * ((dds_header.dwHeight + 3)/4) * ((dds_header.dwDepth + 3)/4) * ((dds_header.ddspf.dwFourCC == FOURCC_DXT1) ? 8 : 16);
} else {
d_size = dds_header.dwPitchOrLinearSize;
}
// if we have mipmaps then compute them into the final size too
for (i = 1; i < (int)dds_header.dwMipMapCount; i++) {
// reduce size by half for the next pass
d_width /= 2;
d_height /= 2;
if (d_width <= 0)
d_width = 1;
if (d_height <= 0)
d_height = 1;
// size of data block (4x4)
d_size += ((d_width + 3) / 4) * ((d_height + 3) / 4) * ((dds_header.ddspf.dwFourCC == FOURCC_DXT1) ? 8 : 16);
}
if ( dds_header.dwCaps2 & DDSCAPS2_CUBEMAP ) {
if ( !(dds_header.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) ) {
retval = DDS_ERROR_CUBEMAP_FACES;
ct = DDS_DXT_INVALID;
goto Done;
}
// it's a valid cubemap, probably
is_cubemap = 1;
// the previously computed size is just per face, mult by 6 for full size
d_size *= 6;
}
Assert( d_size > 0 );
*size = d_size;
switch (dds_header.ddspf.dwFourCC) {
case FOURCC_DXT1:
bits = 24;
ct = (is_cubemap) ? DDS_CUBEMAP_DXT1 : DDS_DXT1;
break;
case FOURCC_DXT3:
bits = 32;
ct = (is_cubemap) ? DDS_CUBEMAP_DXT3 : DDS_DXT3;
break;
case FOURCC_DXT5:
bits = 32;
ct = (is_cubemap) ? DDS_CUBEMAP_DXT5 : DDS_DXT5;
break;
@@ -200,9 +311,8 @@ int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *heigh
break;
case FOURCC_DX10:
if (dds_read_dx10_header(ddsfile, &dds_header_dx10)) {
if (valid_dx10_format(dds_header_dx10)) {
// Currently only BC7 is supported
bits = 32;
ct = DDS_BC7;
} else {
retval = DDS_ERROR_UNSUPPORTED;
@@ -218,46 +328,7 @@ int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *heigh
goto Done;
break;
}
} else if ( dds_header.ddspf.dwFlags & (DDPF_RGB | DDPF_PALETTEINDEXED8) ) {
d_size += d_width * d_height * d_depth * (dds_header.ddspf.dwRGBBitCount / 8);
// calculate full data size for all mipmap levels
for (i = 1; i < (int)dds_header.dwMipMapCount; i++) {
d_width /= 2;
d_height /= 2;
d_depth /= 2;
if (d_width < 1)
d_width = 1;
if (d_height < 1)
d_height = 1;
if (d_depth < 1)
d_depth = 1;
d_size += d_width * d_height * d_depth * (dds_header.ddspf.dwRGBBitCount / 8);
}
Assert( d_size > 0 );
if ( dds_header.dwCaps2 & DDSCAPS2_CUBEMAP ) {
if ( !(dds_header.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) ) {
retval = DDS_ERROR_CUBEMAP_FACES;
ct = DDS_DXT_INVALID;
goto Done;
}
// it's a valid cubemap, probably
is_cubemap = 1;
// the previously computed size is just per face, mult by 6 for full size
d_size *= 6;
}
*size = d_size;
bits = dds_header.ddspf.dwRGBBitCount;
} else if (dds_header.ddspf.dwFlags & DDPF_RGB) {
ct = (is_cubemap) ? DDS_CUBEMAP_UNCOMPRESSED : DDS_UNCOMPRESSED;
} else {
// it's not a readable format
@@ -265,21 +336,33 @@ int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *heigh
goto Done;
}
// maybe do conversion if format not supported
if (conversion_needed(dds_header)) {
// switch to uncompressed format and reset vars
dds_header.ddspf.dwFlags &= ~DDPF_FOURCC;
dds_header.ddspf.dwFlags |= DDPF_RGB;
dds_header.ddspf.dwRGBBitCount = 32;
// NOTE: modifies header and returns offset for mipmap count
dds_header.dwMipMapCount -= conversion_resize(dds_header);
dds_header.dwMipMapCount = std::max(1U, dds_header.dwMipMapCount);
ct = (is_cubemap) ? DDS_CUBEMAP_UNCOMPRESSED : DDS_UNCOMPRESSED;
}
// we don't support compressed, non-power-of-2 images
if ( (ct != DDS_UNCOMPRESSED) && (!is_power_of_two(dds_header.dwWidth, dds_header.dwHeight)) ) {
retval = DDS_ERROR_NON_POWER_OF_2;
goto Done;
}
// make sure that the video card can handle compressed textures before using them
if ( !Use_compressed_textures && (ct != DDS_UNCOMPRESSED) && (ct != DDS_DXT_INVALID) ) {
retval = DDS_ERROR_NO_COMPRESSION;
goto Done;
}
// stuff important info
if (size)
*size = compute_dds_size(dds_header);
if (bpp)
*bpp = bits;
*bpp = get_bit_count(dds_header);
if (compression_type)
*compression_type = ct;
@@ -293,12 +376,6 @@ int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *heigh
if (levels)
*levels = dds_header.dwMipMapCount;
if (palette && (bits == 8)) {
cfseek(ddsfile, (ct == DDS_BC7) ? DX10_OFFSET : DDS_OFFSET, CF_SEEK_SET);
cfread(palette, 1, 1024, ddsfile);
}
Done:
if (img_cfp == NULL) {
// close file and return
@@ -313,11 +390,10 @@ Done:
int dds_read_bitmap(const char *filename, ubyte *data, ubyte *bpp, int cf_type)
{
int retval;
int w,h,ct,lvl;
size_t size = 0;
int bits = 0;
CFILE *cfp;
char real_name[MAX_FILENAME_LEN];
DDS_HEADER dds_header;
// this better not happen.. ever
Assert(filename != NULL);
@@ -329,28 +405,107 @@ int dds_read_bitmap(const char *filename, ubyte *data, ubyte *bpp, int cf_type)
strcat_s(real_name, ".dds");
// open it up and go to the data section
cfp = cfopen(real_name, "rb", CFILE_NORMAL, cf_type);
cfp = cfopen(real_name, "rb", cf_type);
// just in case
if (cfp == NULL)
if (cfp == nullptr)
return DDS_ERROR_INVALID_FILENAME;
// read the header -- if its at this stage, it should be legal.
retval = dds_read_header(real_name, cfp, &w, &h, &bits, &ct, &lvl, &size);
retval = _dds_read_header(cfp, dds_header);
Assert(retval == DDS_ERROR_NONE);
// this really shouldn't be needed but better safe than sorry
if (retval != DDS_ERROR_NONE) {
cfclose(cfp);
return retval;
}
cfseek(cfp, (ct == DDS_BC7) ? DX10_OFFSET : DDS_OFFSET, CF_SEEK_SET);
cfseek(cfp, (dds_header.ddspf.dwFourCC == FOURCC_DX10) ? DX10_OFFSET : DDS_OFFSET, CF_SEEK_SET);
size = compute_dds_size(dds_header);
// read in the data
cfread(data, 1, (int)size, cfp);
if ( !conversion_needed(dds_header) ) {
cfread(data, 1, (int)size, cfp);
} else {
// Compression format not supported, convert to BGRA
ubyte *comp_data = (ubyte*)vm_malloc(size);
cfread(comp_data, 1, (int)size, cfp);
ubyte *src = comp_data;
ubyte *dst = data;
uint d_width, d_height, d_depth;
size_t data_offset = 0;
// NOTE: this alters the width, height, and depth values in the header,
// so we have to jump through some hoops to get the proper values
const uint mipmap_offset = conversion_resize(dds_header);
const int num_faces = (dds_header.dwCaps2 & DDSCAPS2_CUBEMAP) ? 6 : 1;
const bool has_depth = (dds_header.dwFlags & DDSD_DEPTH) == DDSD_DEPTH;
for (int f = 0; f < num_faces; ++f) {
// if we resized then skip over all of that data (altering values to match pre-resize)
for (uint x = 0; x < mipmap_offset; ++x) {
d_width = std::max(1U, dds_header.dwWidth << (mipmap_offset - x));
d_height = std::max(1U, dds_header.dwHeight << (mipmap_offset - x));
d_depth = has_depth ? std::max(1U, dds_header.dwDepth << (mipmap_offset - x)) : 1U;
src += (d_width * d_height * d_depth);
}
for (uint m = mipmap_offset; m < dds_header.dwMipMapCount; ++m) {
// width/height/depth at post-resize mipmap sizes, so compensate here
d_width = std::max(1U, dds_header.dwWidth >> (m - mipmap_offset));
d_height = std::max(1U, dds_header.dwHeight >> (m - mipmap_offset));
d_depth = std::max(1U, dds_header.dwDepth >> (m - mipmap_offset));
for (uint d = 0; d < d_depth; ++d) {
for (uint i = 0; i < d_height; i += 4) {
for (uint j = 0; j < d_width; j += 4) {
dst = data + data_offset + ((i * d_width + j) * 4);
if (dds_header.ddspf.dwFourCC == FOURCC_DX10) {
bcdec_bc7(src, dst, d_width * 4);
src += BCDEC_BC7_BLOCK_SIZE;
} else if (dds_header.ddspf.dwFourCC == FOURCC_DXT5) {
bcdec_bc3(src, dst, d_width * 4);
src += BCDEC_BC3_BLOCK_SIZE;
} else if (dds_header.ddspf.dwFourCC == FOURCC_DXT1) {
bcdec_bc1(src, dst, d_width * 4);
src += BCDEC_BC1_BLOCK_SIZE;
} else if (dds_header.ddspf.dwFourCC == FOURCC_DXT3) {
bcdec_bc2(src, dst, d_width * 4);
src += BCDEC_BC2_BLOCK_SIZE;
}
}
}
}
// we need it in bgra, XOR to the rescue
for (size_t x = data_offset; x < (data_offset + (d_width * d_height * d_depth * 4)); x += 4) {
data[x] ^= data[x+2], data[x+2] ^= data[x], data[x] ^= data[x+2];
}
// bump data offset to next layer
data_offset += (d_width * d_height * d_depth * 4);
}
}
vm_free(comp_data);
comp_data = nullptr;
// switch to uncompressed format and reset vars (needed below to get correct bit count)
dds_header.ddspf.dwFlags &= ~DDPF_FOURCC;
dds_header.ddspf.dwFlags |= DDPF_RGB;
dds_header.ddspf.dwRGBBitCount = 32;
}
if (bpp)
*bpp = (ubyte)bits;
*bpp = (ubyte)get_bit_count(dds_header);
// we look done here
cfclose(cfp);
@@ -403,7 +558,7 @@ void dds_save_image(int width, int height, int bpp, int num_mipmaps, ubyte *data
strcat_s(real_filename, ".dds");
}
CFILE *image = cfopen( real_filename, "wb", CFILE_NORMAL, CF_TYPE_CACHE );
CFILE *image = cfopen( real_filename, "wb", CF_TYPE_CACHE );
if (image == NULL) {
mprintf(("Unable to open DDS image for saving!!\n"));
+2 -4
View File
@@ -59,6 +59,7 @@
#define DDSD_HEIGHT 0x00000002
#define DDSD_CAPS 0x00000001
#define DDSD_MIPMAPCOUNT 0x00020000
#define DDSD_DEPTH 0x00800000
#define DDSCAPS_COMPLEX 0x00000008
#define DDSCAPS_PRIMARYSURFACE 0x00000200
@@ -278,7 +279,7 @@ typedef struct {
//reads a dds header
//returns one of the error values
//'compression_type' comes back as one of the DDS_DXTC* defines
int dds_read_header(const char *filename, CFILE *img_cfp = NULL, int *width = 0, int *height = 0, int *bpp = 0, int *compression_type = 0, int *levels = 0, size_t *size = 0, ubyte *palette = NULL);
int dds_read_header(const char *filename, CFILE *img_cfp = NULL, int *width = 0, int *height = 0, int *bpp = 0, int *compression_type = 0, int *levels = 0, size_t *size = 0);
//reads bitmap
//size of the data it stored in size
@@ -290,7 +291,4 @@ void dds_save_image(int width, int height, int bpp, int num_mipmaps, ubyte *data
//returns a string from a DDS error code
const char *dds_error_string(int code);
extern int Texture_compression_available;
extern int Use_compressed_textures;
#endif //__DDS_H
+55 -34
View File
@@ -22,7 +22,8 @@
#include "object/objcollide.h"
#include "object/objectsnd.h"
#include "particle/particle.h"
#include "radar/radar.h"
#include "particle/ParticleEffect.h"
#include "particle/volumes/LegacyAACuboidVolume.h"
#include "radar/radarsetup.h"
#include "render/3d.h"
#include "scripting/global_hooks.h"
@@ -54,6 +55,8 @@ int Debris_model = -1;
int Debris_vaporize_model = -1;
int Debris_num_submodels = 0;
particle::ParticleEffectHandle Debris_hit_particle;
#define DEBRIS_INDEX(dp) (int)(dp-Debris.data())
@@ -112,6 +115,27 @@ void debris_init()
Debris.reserve(SOFT_LIMIT_DEBRIS_PIECES);
Num_hull_pieces = 0;
Debris_hit_particle = particle::ParticleManager::get()->addEffect(particle::ParticleEffect(
"", //Name
::util::UniformFloatRange(10.f), //Particle num
particle::ParticleEffect::ShapeDirection::ALIGNED, //Particle direction
::util::UniformFloatRange(1.f), //Velocity Inherit
false, //Velocity Inherit absolute?
make_unique<particle::LegacyAACuboidVolume>(0.3f, 1.f, true), //Velocity volume
::util::UniformFloatRange(0.f, 10.f), //Velocity volume multiplier
particle::ParticleEffect::VelocityScaling::NONE, //Velocity directional scaling
std::nullopt, //Orientation-based velocity
std::nullopt, //Position-based velocity
nullptr, //Position volume
particle::ParticleEffectHandle::invalid(), //Trail
1.f, //Chance
true, //Affected by detail
1.f, //Culling range multiplier
true, //Disregard Animation Length. Must be true for everything using particle::Anim_bitmap_X
::util::UniformFloatRange(0.25f, 0.75f), //Lifetime
::util::UniformFloatRange(0.2f, 0.4f), //Radius
particle::Anim_bitmap_id_fire)); //Bitmap
}
/**
@@ -121,14 +145,14 @@ void debris_page_in()
{
uint i;
Debris_model = model_load( NOX("debris01.pof"), 0, NULL );
Debris_model = model_load( NOX("debris01.pof") );
if (Debris_model >= 0) {
polymodel * pm;
pm = model_get(Debris_model);
Debris_num_submodels = pm->n_models;
}
Debris_vaporize_model = model_load( NOX("debris02.pof"), 0, NULL );
Debris_vaporize_model = model_load( NOX("debris02.pof") );
for (i=0; i<Species_info.size(); i++ )
{
@@ -376,7 +400,7 @@ MONITOR(NumHullDebris)
* @param exp_force Explosion force, used to assign velocity to pieces. 1.0f assigns velocity like before. 2.0f assigns twice as much to non-inherited part of velocity
* @param source_subsys The subsystem this debris came from, if any
*/
object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d *pos, vec3d *exp_center, bool hull_flag, float exp_force, ship_subsys* source_subsys)
object *debris_create(object *source_obj, int model_num, int submodel_num, const vec3d *pos, const vec3d *exp_center, bool hull_flag, float exp_force, const ship_subsys* source_subsys)
{
int parent_objnum;
object *obj;
@@ -401,7 +425,7 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
return obj;
}
object *debris_create_only(int parent_objnum, int parent_ship_class, int alt_type_index, int team, float hull_strength, int spark_timeout, int model_num, int submodel_num, vec3d *pos, matrix *orient, bool hull_flag, bool vaporize, int damage_type_idx)
object *debris_create_only(int parent_objnum, int parent_ship_class, int alt_type_index, int team, float hull_strength, int spark_timeout, int model_num, int submodel_num, const vec3d *pos, const matrix *orient, bool hull_flag, bool vaporize, int damage_type_idx)
{
int objnum;
object *obj;
@@ -449,7 +473,7 @@ object *debris_create_only(int parent_objnum, int parent_ship_class, int alt_typ
// non-hull debris has no relation to its parent orientation
vec3d rand;
vm_vec_rand_vec(&rand);
vm_vector_2_matrix(&orient_buf, &rand);
vm_vector_2_matrix_norm(&orient_buf, &rand);
orient = &orient_buf;
}
}
@@ -501,11 +525,11 @@ object *debris_create_only(int parent_objnum, int parent_ship_class, int alt_typ
}
else if (vaporize) {
db->model_num = Debris_vaporize_model;
db->submodel_num = Random::next(Debris_num_submodels);
db->submodel_num = (Debris_num_submodels <= 0 ? 0 : Random::next(Debris_num_submodels));
}
else {
db->model_num = Debris_model;
db->submodel_num = Random::next(Debris_num_submodels);
db->submodel_num = (Debris_num_submodels <= 0 ? 0 : Random::next(Debris_num_submodels));
}
}
else {
@@ -610,6 +634,11 @@ object *debris_create_only(int parent_objnum, int parent_ship_class, int alt_typ
db->model_instance_num = hull_flag ? model_create_instance(objnum, db->model_num) : -1;
// ensure that any texture replace on parent ship gets copied to debris --wookieejedi
int parent_model_instance_num;
if ((db->model_instance_num >= 0) && (parent_objnum >= 0) && ((parent_model_instance_num = object_get_model_instance_num(&Objects[parent_objnum])) >= 0))
model_get_instance(db->model_instance_num)->texture_replace = model_get_instance(parent_model_instance_num)->texture_replace;
// assign the network signature. The signature will be 0 for non-hull pieces, but since that
// is our invalid signature, it should be okay.
obj->net_signature = 0;
@@ -644,7 +673,7 @@ object *debris_create_only(int parent_objnum, int parent_ship_class, int alt_typ
if (spark_timeout >= 0) {
db->fire_timeout = _timestamp(spark_timeout);
} else if (parent_objnum >= 0) {
float t = 1000*Objects[parent_objnum].radius/3 + Random::next(fl2i(1000*3*Objects[parent_objnum].radius));
float t = 1000*Objects[parent_objnum].radius/3 + (fl2i(1000*3*Objects[parent_objnum].radius) == 0 ? 0 : Random::next(fl2i(1000*3*Objects[parent_objnum].radius)));
db->fire_timeout = _timestamp(fl2i(t)); // fireballs last from 5 - 30 seconds
} else {
db->fire_timeout = TIMESTAMP::immediate();
@@ -666,7 +695,7 @@ object *debris_create_only(int parent_objnum, int parent_ship_class, int alt_typ
return obj;
}
void debris_create_set_velocity(debris *db, ship *source_shipp, vec3d *exp_center, float exp_force, ship_subsys* source_subsys)
void debris_create_set_velocity(const debris *db, const ship *source_shipp, const vec3d *exp_center, float exp_force, const ship_subsys* source_subsys)
{
auto obj = &Objects[db->objnum];
auto source_obj = (source_shipp == nullptr) ? nullptr : &Objects[source_shipp->objnum];
@@ -776,30 +805,18 @@ void debris_hit(object *debris_obj, object * /*other_obj*/, vec3d *hitpos, float
debris *debris_p = &Debris[debris_obj->instance];
// Do a little particle spark shower to show we hit
{
particle::particle_emitter pe;
pe.pos = *hitpos; // Where the particles emit from
pe.vel = debris_obj->phys_info.vel; // Initial velocity of all the particles
if (Debris_hit_particle.isValid()){ // Where the particles emit from
vec3d tmp_norm;
vm_vec_sub( &tmp_norm, hitpos, &debris_obj->pos );
vm_vec_normalize_safe(&tmp_norm);
pe.normal = tmp_norm; // What normal the particle emit around
pe.normal_variance = 0.3f; // How close they stick to that normal 0=good, 1=360 degree
pe.min_rad = 0.20f; // Min radius
pe.max_rad = 0.40f; // Max radius
matrix orient;
vm_vector_2_matrix_norm(&orient, &tmp_norm);
// Sparks for first time at this spot
pe.num_low = 10; // Lowest number of particles to create
pe.num_high = 10; // Highest number of particles to create
pe.normal_variance = 0.3f; // How close they stick to that normal 0=good, 1=360 degree
pe.min_vel = 0.0f; // How fast the slowest particle can move
pe.max_vel = 10.0f; // How fast the fastest particle can move
pe.min_life = 0.25f; // How long the particles live
pe.max_life = 0.75f; // How long the particles live
particle::emit( &pe, particle::PARTICLE_FIRE, 0 );
auto source = particle::ParticleManager::get()->createSource(Debris_hit_particle);
auto host = std::make_unique<EffectHostVector>(*hitpos, orient, debris_obj->phys_info.vel);
host->setRadius(debris_obj->radius);
source->setHost(std::move(host));
source->finishCreation();
}
// multiplayer clients bail here
@@ -1105,7 +1122,7 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
/**
* Return the team field for a debris object
*/
int debris_get_team(object *objp)
int debris_get_team(const object *objp)
{
Assert( objp->type == OBJ_DEBRIS );
Assert( objp->instance >= 0 && objp->instance < (int)Debris.size() );
@@ -1197,6 +1214,9 @@ void debris_render(object * obj, model_draw_list *scene)
// render_info.set_flags(MR_NO_LIGHTING);
}
if (db->model_instance_num >= 0)
render_info.set_replacement_textures(model_get_instance(db->model_instance_num)->texture_replace);
submodel_render_queue( &render_info, scene, pm, pmi, db->submodel_num, &obj->orient, &obj->pos );
if (tbase != NULL && (swapped!=-1) && pm) {
@@ -1204,17 +1224,18 @@ void debris_render(object * obj, model_draw_list *scene)
}
}
bool debris_is_generic(debris *db)
bool debris_is_generic(const debris *db)
{
return db->model_num == Debris_model;
}
bool debris_is_vaporized(debris *db)
bool debris_is_vaporized(const debris *db)
{
return db->model_num == Debris_vaporize_model;
}
void create_generic_debris(object* ship_objp, vec3d* pos, float min_num_debris, float max_num_debris, float speed_mult, bool use_ship_debris) {
void create_generic_debris(object* ship_objp, const vec3d* pos, float min_num_debris, float max_num_debris, float speed_mult, bool use_ship_debris)
{
Assertion(ship_objp->type == OBJ_SHIP, "create_generic_debris called for a non-ship, only ships can spew debris!");
if (ship_objp->type != OBJ_SHIP)
return;
+7 -7
View File
@@ -71,29 +71,29 @@ void debris_delete( object * obj );
void debris_process_post( object * obj, float frame_time);
// Create debris, set velocity, and fire scripting hook
object *debris_create( object *source_obj, int model_num, int submodel_num, vec3d *pos, vec3d *exp_center, bool hull_flag, float exp_force, ship_subsys* source_subsys = nullptr );
object *debris_create(object *source_obj, int model_num, int submodel_num, const vec3d *pos, const vec3d *exp_center, bool hull_flag, float exp_force, const ship_subsys* source_subsys = nullptr);
// Create debris but don't do anything else
object *debris_create_only(int parent_objnum, int parent_ship_class, int alt_type_index, int team, float hull_strength, int spark_timeout, int model_num, int submodel_num, vec3d *pos, matrix *orient, bool hull_flag, bool vaporize, int damage_type_idx);
object *debris_create_only(int parent_objnum, int parent_ship_class, int alt_type_index, int team, float hull_strength, int spark_timeout, int model_num, int submodel_num, const vec3d *pos, const matrix *orient, bool hull_flag, bool vaporize, int damage_type_idx);
// Set velocity after debris creation
void debris_create_set_velocity(debris *db, ship *source_shipp, vec3d *exp_center, float exp_force, ship_subsys* source_subsys = nullptr);
void debris_create_set_velocity(const debris *db, const ship *source_shipp, const vec3d *exp_center, float exp_force, const ship_subsys* source_subsys = nullptr);
// Fire scripting hook after debris creation
void debris_create_fire_hook(object *obj, object *source_obj);
int debris_check_collision( object * obj, object * other_obj, vec3d * hitpos, collision_info_struct *debris_hit_info=NULL, vec3d* hitnormal = NULL );
void debris_hit( object * debris_obj, object * other_obj, vec3d * hitpos, float damage, vec3d* force );
int debris_get_team(object *objp);
void debris_add_to_hull_list(debris *db);
void debris_remove_from_hull_list(debris *db);
bool debris_is_generic(debris *db);
bool debris_is_vaporized(debris *db);
int debris_get_team(const object *objp);
bool debris_is_generic(const debris *db);
bool debris_is_vaporized(const debris *db);
// creates a burst of generic debris at hitpos from ship_objp, with a random number between min and max
// use_ship_debris is for whether the ship's generic debris should be used, or simply debris01.pof
void create_generic_debris(object* ship_objp, vec3d* hitpos, float min_num_debris, float max_num_debris, float speed_mult, bool use_ship_debris);
void create_generic_debris(object* ship_objp, const vec3d* hitpos, float min_num_debris, float max_num_debris, float speed_mult, bool use_ship_debris);
#endif // _DEBRIS_H
+16 -38
View File
@@ -26,28 +26,6 @@ DecalDefinition::~DecalDefinition() {
}
}
DecalDefinition::DecalDefinition(DecalDefinition&& other) noexcept {
*this = std::move(other); // Use operator implementation
}
DecalDefinition& DecalDefinition::operator=(DecalDefinition&& other) noexcept {
std::swap(_name, other._name);
std::swap(_diffuseFilename, other._diffuseFilename);
std::swap(_glowFilename, other._glowFilename);
std::swap(_normalMapFilename, other._normalMapFilename);
std::swap(_diffuseBitmap, other._diffuseBitmap);
std::swap(_glowBitmap, other._glowBitmap);
std::swap(_normalBitmap, other._normalBitmap);
std::swap(_loopDiffuse, other._loopDiffuse);
std::swap(_loopGlow, other._loopGlow);
std::swap(_loopNormal, other._loopNormal);
return *this;
}
void DecalDefinition::parse() {
if (optional_string("+Diffuse:")) {
stuff_string(_diffuseFilename, F_FILESPEC);
@@ -174,7 +152,7 @@ void parse_decals_table(const char* filename) {
SCP_string name;
stuff_string(name, F_NAME);
DecalDefinition def(name);
DecalDefinition def(std::move(name));
def.parse();
DecalDefinitions.push_back(std::move(def));
@@ -186,17 +164,17 @@ void parse_decals_table(const char* filename) {
return;
}
if (!gr_is_capable(CAPABILITY_DEFERRED_LIGHTING)) {
if (!gr_is_capable(gr_capability::CAPABILITY_DEFERRED_LIGHTING)) {
// We need deferred lighting
Decal_system_active = false;
mprintf(("Note: Decal system has been disabled due to lack of deferred lighting.\n"));
}
if (!gr_is_capable(CAPABILITY_NORMAL_MAP)) {
if (!gr_is_capable(gr_capability::CAPABILITY_NORMAL_MAP)) {
// We need normal mapping for the full feature range
Decal_system_active = false;
mprintf(("Note: Decal system has been disabled due to lack of normal mapping.\n"));
}
if (!gr_is_capable(CAPABILITY_SEPARATE_BLEND_FUNCTIONS)) {
if (!gr_is_capable(gr_capability::CAPABILITY_SEPARATE_BLEND_FUNCTIONS)) {
// We need separate blending functions for different color buffers
Decal_system_active = false;
mprintf(("Note: Decal system has been disabled due to lack of separate color buffer blend functions.\n"));
@@ -220,17 +198,17 @@ struct Decal {
vm_vec_make(&scale, 1.f, 1.f, 1.f);
}
bool isValid() {
if (!object.IsValid()) {
bool isValid() const {
if (!object.isValid()) {
return false;
}
if (object.objp->flags[Object::Object_Flags::Should_be_dead]) {
if (object.objp()->flags[Object::Object_Flags::Should_be_dead]) {
return false;
}
if (orig_obj_type != object.objp->type) {
if (orig_obj_type != object.objp()->type) {
mprintf(("Decal object type for object %d has changed from %s to %s. Please let m!m know about this\n",
OBJ_INDEX(object.objp), Object_type_names[orig_obj_type], Object_type_names[object.objp->type]));
object.objnum, Object_type_names[orig_obj_type], Object_type_names[object.objp()->type]));
return false;
}
@@ -241,12 +219,12 @@ struct Decal {
}
}
auto objp = object.objp;
auto objp = object.objp();
if (objp->type == OBJ_SHIP) {
auto shipp = &Ships[objp->instance];
auto model_instance = model_get_instance(shipp->model_instance_num);
Assertion(submodel >= 0 && submodel < model_get(object_get_model(objp))->n_models,
Assertion(submodel >= 0 && submodel < object_get_model(objp)->n_models,
"Invalid submodel number detected!");
auto smi = &model_instance->submodel[submodel];
@@ -339,7 +317,7 @@ void parseDecalReference(creation_info& dest_info, bool is_new_entry) {
}
if (required_string_if_new("+Radius:", is_new_entry)) {
dest_info.radius = util::parseUniformRange(0.0001f);
dest_info.radius = util::ParsedRandomFloatRange::parseRandomRange(0.0001f);
}
if (required_string_if_new("+Lifetime:", is_new_entry)) {
@@ -347,7 +325,7 @@ void parseDecalReference(creation_info& dest_info, bool is_new_entry) {
dest_info.lifetime = util::UniformFloatRange(-1.0f);
} else {
// Require at least a small lifetime so that the calculations don't have to deal with div-by-zero
dest_info.lifetime = util::parseUniformRange(0.0001f);
dest_info.lifetime = util::ParsedRandomFloatRange::parseRandomRange(0.0001f);
}
}
@@ -393,9 +371,9 @@ void initializeMission() {
}
matrix4 getDecalTransform(Decal& decal) {
Assertion(decal.object.objp->type == OBJ_SHIP, "Only ships are currently supported for decals!");
Assertion(decal.object.objp()->type == OBJ_SHIP, "Only ships are currently supported for decals!");
auto objp = decal.object.objp;
auto objp = decal.object.objp();
auto ship = &Ships[objp->instance];
auto pmi = model_get_instance(ship->model_instance_num);
auto pm = model_get(pmi->model_num);
@@ -501,7 +479,7 @@ void renderAll() {
draw_list.render();
}
void addDecal(creation_info& info, object* host, int submodel, const vec3d& local_pos, const matrix& local_orient) {
void addDecal(creation_info& info, const object* host, int submodel, const vec3d& local_pos, const matrix& local_orient) {
if (!Decal_system_active || !Decal_option_active) {
return;
}
+5 -5
View File
@@ -33,8 +33,8 @@ class DecalDefinition {
DecalDefinition& operator=(const DecalDefinition&) = delete;
// Move constructor and operator
DecalDefinition(DecalDefinition&& other) noexcept;
DecalDefinition& operator=(DecalDefinition&& other) noexcept;
DecalDefinition(DecalDefinition&& other) noexcept = default;
DecalDefinition& operator=(DecalDefinition&& other) noexcept = default;
void parse();
void loadBitmaps();
@@ -65,10 +65,10 @@ typedef int DecalReference;
*/
struct creation_info {
DecalReference definition_handle = -1;
util::UniformFloatRange radius = ::util::UniformFloatRange(-1.0f);
util::ParsedRandomFloatRange radius = ::util::UniformFloatRange(-1.0f);
float width = -1.0f;
float height = -1.0f;
util::UniformFloatRange lifetime = ::util::UniformFloatRange(-1.0f);
util::ParsedRandomFloatRange lifetime = ::util::UniformFloatRange(-1.0f);
bool random_rotation = false;
};
@@ -134,7 +134,7 @@ void renderAll();
* orientation should look along the direction
*/
void addDecal(creation_info& info,
object* host,
const object* host,
int submodel,
const vec3d& local_pos,
const matrix& local_orient);
+108 -76
View File
@@ -2,8 +2,9 @@
#include "shadows.sdr" //! #include "shadows.sdr"
#include "lighting.sdr" //! #include "lighting.sdr"
#include "gamma.sdr" //! #include "gamma.sdr"
#include "model_shader_flags.h"
#conditional_include +"LARGE_SHADER" "main_large.sdr"
#conditional_include -"LARGE_SHADER" "main_small.sdr"
#define MAX_LIGHTS 8
#define LT_DIRECTIONAL 0
@@ -96,32 +97,61 @@ layout (std140) uniform modelData {
};
in VertexOutput {
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_ENV
vec3 envReflect;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_ENV
mat3 tangentMatrix;
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_FOG
float fogDist;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_FOG
vec4 position;
vec3 normal;
vec4 texCoord;
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
vec4 shadowUV[4];
vec4 shadowPos;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
} vertIn;
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_DIFFUSE
uniform sampler2DArray sBasemap;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_DIFFUSE
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_GLOW
uniform sampler2DArray sGlowmap;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_GLOW
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_SPEC
uniform sampler2DArray sSpecmap;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_SPEC
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_ENV
uniform samplerCube sEnvmap;
uniform samplerCube sIrrmap;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_ENV
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_NORMAL
uniform sampler2DArray sNormalmap;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_NORMAL
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_AMBIENT
uniform sampler2DArray sAmbientmap;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_AMBIENT
uniform sampler2D sFramebuffer;
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_MISC
uniform sampler2DArray sMiscmap;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_MISC
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
uniform sampler2DArray shadow_map;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
out vec4 fragOut0;
#ifndef MODEL_SDR_FLAG_SHADOW_MAP
out vec4 fragOut1;
out vec4 fragOut2;
out vec4 fragOut3;
out vec4 fragOut4;
#endif
vec3 FresnelLazarovEnv(vec3 specColor, vec3 view, vec3 normal, float gloss)
{
@@ -182,13 +212,12 @@ vec3 CalculateLighting(vec3 normal, vec3 diffuseMaterial, vec3 specularMaterial,
void main()
{
#ifdef FLAG_SHADOW_MAP
#ifdef MODEL_SDR_FLAG_SHADOW_MAP
// need depth and depth squared for variance shadow maps
fragOut0 = vec4(vertIn.position.z, vertIn.position.z * vertIn.position.z * VARIANCE_SHADOW_SCALE_INV, 0.0, 1.0);
if (true) {
return;
}
#endif
return;
#else
vec3 eyeDir = vec3(normalize(-vertIn.position).xyz);
vec2 texCoord = vertIn.texCoord.xy;
@@ -203,13 +232,13 @@ void main()
vec3 unitNormal = normalize(vertIn.normal);
vec3 normal = unitNormal;
if (FLAG_ACTIVE(MODEL_SDR_FLAG_AMBIENT)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_AMBIENT
// red channel is ambient occlusion factor which only affects ambient lighting.
// green is cavity occlusion factor which only affects diffuse and specular lighting.
aoFactors = texture(sAmbientmap, vec3(texCoord, float(sAmbientmapIndex))).xy;
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_AMBIENT
if (FLAG_ACTIVE(MODEL_SDR_FLAG_NORMAL)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_NORMAL
// Normal map - convert from DXT5nm
vec2 normalSample;
normal.rg = normalSample = (texture(sNormalmap, vec3(texCoord, float(sNormalmapIndex))).ag * 2.0) - 1.0;
@@ -221,7 +250,7 @@ void main()
normal /= norm;
else
normal = unitNormal;
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_NORMAL
vec2 distort = vec2(0.0, 0.0);
@@ -229,26 +258,26 @@ void main()
distort = vec2(cos(vertIn.position.x*vertIn.position.w*0.005+anim_timer*20.0)*sin(vertIn.position.y*vertIn.position.w*0.005),sin(vertIn.position.x*vertIn.position.w*0.005+anim_timer*20.0)*cos(vertIn.position.y*vertIn.position.w*0.005))*0.03;
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_DIFFUSE)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_DIFFUSE
vec2 diffuseTexCoord = texCoord;
if (effect_num == 2) {
diffuseTexCoord = texCoord + distort*(1.0-anim_timer);
}
baseColor = texture(sBasemap, vec3(diffuseTexCoord, float(sBasemapIndex)));
if (FLAG_ACTIVE(MODEL_SDR_FLAG_HDR)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_HDR
baseColor.rgb = srgb_to_linear(baseColor.rgb);
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_HDR
if (FLAG_ACTIVE(MODEL_SDR_FLAG_ALPHA_MULT)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_ALPHA_MULT
baseColor.a *= alphaMult;
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_ALPHA_MULT
if ( blend_alpha == 0 && baseColor.a < 0.95 ) discard; // if alpha blending is not on, discard transparent pixels
// premultiply alpha if blend_alpha is 1. assume that our blend function is srcColor + (1-Alpha)*destColor.
// if blend_alpha is 2, assume blend func is additive and don't modify color
if(blend_alpha == 1) baseColor.rgb = baseColor.rgb * baseColor.a;
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_DIFFUSE
// Anti-glint "trick" based on Valve's "Advanced VR Rendering" talk at GDC2015:
// http://media.steampowered.com/apps/valve/2015/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf Page 43
@@ -261,21 +290,22 @@ void main()
// Now that we have a base color and min gloss value, compute the spec color
vec4 specColor = vec4(baseColor.rgb * SPEC_FACTOR_NO_SPEC_MAP, glossData);
if (FLAG_ACTIVE(MODEL_SDR_FLAG_SPEC)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_SPEC
specColor = texture(sSpecmap, vec3(texCoord, float(sSpecmapIndex)));
if (FLAG_ACTIVE(MODEL_SDR_FLAG_ALPHA_MULT)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_ALPHA_MULT
specColor *= alphaMult;
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_ALPHA_MULT
if(alphaGloss) glossData = specColor.a;
if(gammaSpec) {
specColor.rgb = max(specColor.rgb, vec3(0.03f)); // hardcoded minimum specular value. read John Hable's blog post titled 'Everything Is Shiny'.
fresnelFactor = 1.0;
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_HDR)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_HDR
specColor.rgb = srgb_to_linear(specColor.rgb);
}
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_HDR
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_SPEC
baseColor.rgb *= aoFactors.y;
specColor.rgb *= aoFactors.y;
@@ -283,8 +313,8 @@ void main()
vec4 teamMask = vec4(0.0);
vec3 team_color_glow = vec3(0.0);
if (FLAG_ACTIVE(MODEL_SDR_FLAG_MISC)) {
if (FLAG_ACTIVE(MODEL_SDR_FLAG_TEAMCOLOR)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_MISC
#prereplace IF_FLAG MODEL_SDR_FLAG_TEAMCOLOR
teamMask = texture(sMiscmap, vec3(texCoord, float(sMiscmapIndex)));
//For team colors applied to a diffuse or spec map, we assume that the base color of the diffuse
@@ -294,52 +324,52 @@ void main()
vec3 team_color = base_color * teamMask.x + stripe_color * teamMask.y + color_offset;
team_color_glow = (base_color * teamMask.b) + (stripe_color * teamMask.a);
if (FLAG_ACTIVE(MODEL_SDR_FLAG_HDR)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_HDR
baseColor.rgb = linear_to_srgb(baseColor.rgb);
specColor.rgb = linear_to_srgb(specColor.rgb);
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_HDR
baseColor.rgb += team_color;
baseColor.rgb = max(baseColor.rgb, vec3(0.0)); // We need to make sure that nothing here ever goes negative
specColor.rgb += team_color;
specColor.rgb = max(specColor.rgb, vec3(0.03));
if (FLAG_ACTIVE(MODEL_SDR_FLAG_HDR)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_HDR
baseColor.rgb = srgb_to_linear(baseColor.rgb);
specColor.rgb = srgb_to_linear(specColor.rgb);
}
}
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_HDR
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_TEAMCOLOR
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_MISC
// Lights aren't applied when we are rendering to the G-buffers since that gets handled later
if (FLAG_ACTIVE(MODEL_SDR_FLAG_DEFERRED)) {
if (FLAG_ACTIVE(MODEL_SDR_FLAG_LIGHT)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_DEFERRED
#prereplace IF_FLAG MODEL_SDR_FLAG_LIGHT
// Ambient lighting still needs to be done since that counts as an "emissive" color
vec3 lightAmbient = (emissionFactor + ambientFactor * ambientFactor) * aoFactors.x; // ambientFactor^2 due to legacy OpenGL compatibility behavior
emissiveColor.rgb += baseColor.rgb * lightAmbient;
} else {
if (FLAG_ACTIVE(MODEL_SDR_FLAG_SPEC)) {
#prereplace ELSE_FLAG //MODEL_SDR_FLAG_LIGHT
#prereplace IF_FLAG MODEL_SDR_FLAG_SPEC
baseColor.rgb += pow(1.0 - clamp(dot(eyeDir, normal), 0.0, 1.0), 5.0 * clamp(glossData, 0.01, 1.0)) * specColor.rgb;
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_SPEC
// If there is no lighting then we copy the color data so far into the
emissiveColor.rgb += baseColor.rgb;
}
} else {
if (FLAG_ACTIVE(MODEL_SDR_FLAG_LIGHT)) {
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_LIGHT
#prereplace ELSE_FLAG //MODEL_SDR_FLAG_DEFERRED
#prereplace IF_FLAG MODEL_SDR_FLAG_LIGHT
float shadow = 1.0;
if (FLAG_ACTIVE(MODEL_SDR_FLAG_SHADOWS)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_SHADOWS
shadow = getShadowValue(shadow_map, -vertIn.position.z, vertIn.shadowPos.z, vertIn.shadowUV, fardist, middist, neardist, veryneardist);
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_SHADOWS
baseColor.rgb = CalculateLighting(normal, baseColor.rgb, specColor.rgb, glossData, fresnelFactor, shadow, aoFactors.x);
} else {
if (FLAG_ACTIVE(MODEL_SDR_FLAG_SPEC)) {
#prereplace ELSE_FLAG //MODEL_SDR_FLAG_LIGHT
#prereplace IF_FLAG MODEL_SDR_FLAG_SPEC
baseColor.rgb += pow(1.0 - clamp(dot(eyeDir, normal), 0.0, 1.0), 5.0 * clamp(glossData, 0.01, 1.0)) * specColor.rgb;
}
}
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_SPEC
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_LIGHT
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_DEFERRED
if (FLAG_ACTIVE(MODEL_SDR_FLAG_ENV)) {
if (FLAG_ACTIVE(MODEL_SDR_FLAG_LIGHT)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_ENV
#prereplace IF_FLAG MODEL_SDR_FLAG_LIGHT
// Bit of a hack here, pretend we're doing blinn-phong shading and use a (modified version of) the derivation from
// Plausible Blinn-Phong Reflection of Standard Cube MIP-Maps - McGuire et al.
// to determine the mip bias.
@@ -383,48 +413,48 @@ void main()
vec3 diffEnvColor = srgb_to_linear(texture(sIrrmap, vec3(envMatrix * vec4(normal, 0.0))).rgb);
vec3 diffEnvLighting = kD * baseColor.rgb * diffEnvColor * aoFactors.x;
emissiveColor.rgb += (specEnvLighting + diffEnvLighting) * baseColor.a;
}
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_LIGHT
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_ENV
if (FLAG_ACTIVE(MODEL_SDR_FLAG_GLOW)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_GLOW
vec3 glowColor = texture(sGlowmap, vec3(texCoord, float(sGlowmapIndex))).rgb;
if (FLAG_ACTIVE(MODEL_SDR_FLAG_MISC)) {
if (FLAG_ACTIVE(MODEL_SDR_FLAG_TEAMCOLOR)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_MISC
#prereplace IF_FLAG MODEL_SDR_FLAG_TEAMCOLOR
float glowColorLuminance = dot(glowColor, vec3(0.299, 0.587, 0.114));
glowColor = team_glow_enabled ? mix(max(team_color_glow, vec3(0.0)), glowColor, clamp(glowColorLuminance - teamMask.b - teamMask.a, 0.0, 1.0)) : glowColor;
}
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_HDR)) {
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_TEAMCOLOR
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_MISC
#prereplace IF_FLAG MODEL_SDR_FLAG_HDR
glowColor = srgb_to_linear(glowColor) * GLOW_MAP_SRGB_MULTIPLIER;
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_HDR
emissiveColor.rgb += glowColor * GLOW_MAP_INTENSITY;
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_GLOW
if (FLAG_ACTIVE(MODEL_SDR_FLAG_ALPHA_MULT)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_ALPHA_MULT
//Since this is emissive, we need to premultiply it for intensity, and apply alpha to not replace existing emissive
emissiveColor *= alphaMult;
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_ALPHA_MULT
if (FLAG_ACTIVE(MODEL_SDR_FLAG_FOG)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_FOG
vec3 finalFogColor = fogColor.rgb;
if (FLAG_ACTIVE(MODEL_SDR_FLAG_HDR)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_HDR
finalFogColor = srgb_to_linear(finalFogColor);
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_DIFFUSE)) {
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_HDR
#prereplace IF_FLAG MODEL_SDR_FLAG_DIFFUSE
if(blend_alpha == 1) finalFogColor *= baseColor.a;
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_DIFFUSE
// This code will only be used by the forward renderer so we apply the fog effect to both the emissive and the base
// color.
baseColor.rgb = mix(emissiveColor.rgb + baseColor.rgb, finalFogColor, vertIn.fogDist);
emissiveColor.rgb = vec3(0.0); // Zero the emissive color since it has already been added by the previous line
specColor.rgb *= vertIn.fogDist;
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_FOG
if (FLAG_ACTIVE(MODEL_SDR_FLAG_DIFFUSE)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_DIFFUSE
if(desaturate == 1) {
baseColor.rgb = color.rgb * dot(vec3(1.0), baseColor.rgb) * 0.3333333;
}
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_DIFFUSE
if (effect_num == 0) {
float shinefactor = 1.0/(1.0 + pow(abs((fract(abs(texCoord.x))-anim_timer) * 1000.0), 2.0)) * 1000.0;
@@ -433,32 +463,34 @@ void main()
} else if (effect_num == 1) {
float shinefactor = 1.0/(1.0 + pow(abs(vertIn.position.y-anim_timer), 2.0));
emissiveColor.rgb += vec3(shinefactor);
if (!(FLAG_ACTIVE(MODEL_SDR_FLAG_LIGHT))) {
#prereplace IF_NOT_FLAG MODEL_SDR_FLAG_LIGHT
// ATI Wireframe fix *grumble*
baseColor.a = clamp((vertIn.position.y-anim_timer) * 10000.0,0.0,1.0);
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_LIGHT
} else if (effect_num == 2) {
vec2 screenPos = gl_FragCoord.xy * vec2(vpwidth,vpheight);
baseColor.a = baseColor.a;
float cloak_interp = (sin(vertIn.position.x*vertIn.position.w*0.005+anim_timer*20.0)*sin(vertIn.position.y*vertIn.position.w*0.005)*0.5)-0.5;
if (FLAG_ACTIVE(MODEL_SDR_FLAG_LIGHT)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_LIGHT
baseColor.rgb = mix(texture(sFramebuffer, screenPos + distort*anim_timer + anim_timer*0.1*normal.xy).rgb,baseColor.rgb,clamp(cloak_interp+anim_timer*2.0,0.0,1.0));
} else {
#prereplace ELSE_FLAG //MODEL_SDR_FLAG_LIGHT
baseColor.rgb = mix(texture(sFramebuffer, screenPos + distort*anim_timer + anim_timer*0.1*vertIn.normal.xy).rgb,baseColor.rgb,clamp(cloak_interp+anim_timer*2.0,0.0,1.0));
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_LIGHT
}
if (!(FLAG_ACTIVE(MODEL_SDR_FLAG_DEFERRED))) {
#prereplace IF_NOT_FLAG MODEL_SDR_FLAG_DEFERRED
// emissive colors won't be added later when we are using forward rendering so we need to do that here
baseColor.rgb += emissiveColor.rgb;
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_DEFERRED
fragOut0 = baseColor;
if (FLAG_ACTIVE(MODEL_SDR_FLAG_DEFERRED)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_DEFERRED
fragOut1 = vec4(vertIn.position.xyz, 1.0);
fragOut2 = vec4(normal, glossData);
fragOut3 = vec4(specColor.rgb, fresnelFactor);
fragOut4 = emissiveColor;
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_DEFERRED
#endif
}
+65 -36
View File
@@ -1,17 +1,18 @@
#extension GL_ARB_gpu_shader5: enable
#include "model_shader_flags.h"
#conditional_include +"LARGE_SHADER" "main_large.sdr"
#conditional_include -"LARGE_SHADER" "main_small.sdr"
#ifdef FLAG_THICK_OUTLINE
#ifdef MODEL_SDR_FLAG_THICK_OUTLINES
layout (triangles) in;
// For every triangle line we generate 2 triangles which can be done with 4 vertices so in total we will need 12 vertices
layout (triangle_strip, max_vertices = 12) out;
#elif defined(FLAG_SHADOW_MAP)
#elif defined(MODEL_SDR_FLAG_SHADOW_MAP)
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;
#endif
#ifdef FLAG_SHADOW_MAP
#ifdef MODEL_SDR_FLAG_SHADOW_MAP
#ifdef GL_ARB_gpu_shader5
layout(invocations = 4) in;
#endif
@@ -102,11 +103,17 @@ layout (std140) uniform modelData {
};
in VertexOutput {
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_ENV
vec3 envReflect;
mat3 tangentMatrix;
float fogDist;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_ENV
#ifdef FLAG_SHADOW_MAP
mat3 tangentMatrix;
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_FOG
float fogDist;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_FOG
#ifdef MODEL_SDR_FLAG_SHADOW_MAP
#if !defined(GL_ARB_gpu_shader5)
float instance;
#endif
@@ -116,22 +123,35 @@ in VertexOutput {
#endif
vec3 normal;
vec4 texCoord;
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
vec4 shadowUV[4];
vec4 shadowPos;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
} vertIn[];
out VertexOutput {
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_ENV
vec3 envReflect;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_ENV
mat3 tangentMatrix;
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_FOG
float fogDist;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_FOG
vec4 position;
vec3 normal;
vec4 texCoord;
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
vec4 shadowUV[4];
vec4 shadowPos;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
} vertOut;
#ifdef FLAG_SHADOW_MAP
#ifdef MODEL_SDR_FLAG_SHADOW_MAP
void main(void)
{
#ifdef GL_ARB_gpu_shader5
@@ -141,16 +161,17 @@ out VertexOutput {
#endif
for(int vert = 0; vert < gl_in.length(); vert++)
{
if (FLAG_ACTIVE(MODEL_SDR_FLAG_TRANSFORM)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_TRANSFORM
if (vertIn[vert].clipModel > 0.9) {
// If the model was clipped in the vertex shader then we do not apply the shadow projection matrix here
gl_Position = gl_in[vert].gl_Position;
} else {
gl_Position = shadow_proj_matrix[instanceID] * gl_in[vert].gl_Position;
}
} else {
#prereplace ELSE_FLAG //MODEL_SDR_FLAG_TRANSFORM
gl_Position = shadow_proj_matrix[instanceID] * gl_in[vert].gl_Position;
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_TRANSFORM
if(gl_Position.z < -1.0)
gl_Position.z = -1.0;
@@ -160,22 +181,26 @@ out VertexOutput {
gl_Layer = instanceID;
if (FLAG_ACTIVE(MODEL_SDR_FLAG_ENV)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_ENV
vertOut.envReflect = vertIn[vert].envReflect;
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_NORMAL)) {
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_ENV
#prereplace IF_FLAG MODEL_SDR_FLAG_NORMAL
vertOut.tangentMatrix = vertIn[vert].tangentMatrix;
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_FOG)) {
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_NORMAL
#prereplace IF_FLAG MODEL_SDR_FLAG_FOG
vertOut.fogDist = vertIn[vert].fogDist;
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_SHADOWS)) {
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_FOG
#prereplace IF_FLAG MODEL_SDR_FLAG_SHADOWS
vertOut.shadowUV[0] = vertIn[vert].shadowUV[0];
vertOut.shadowUV[1] = vertIn[vert].shadowUV[1];
vertOut.shadowUV[2] = vertIn[vert].shadowUV[2];
vertOut.shadowUV[3] = vertIn[vert].shadowUV[3];
vertOut.shadowPos = vertIn[vert].shadowPos;
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_SHADOWS
if (use_clip_plane) {
gl_ClipDistance[0] = gl_in[vert].gl_ClipDistance[0];
}
@@ -183,7 +208,7 @@ out VertexOutput {
}
EndPrimitive();
}
#elif defined(FLAG_THICK_OUTLINE)
#elif defined(MODEL_SDR_FLAG_THICK_OUTLINES)
const vec2 pixelOffsetDir[4] = vec2[](
vec2(0.0, 1.0),
vec2(1.0, 1.0),
@@ -214,22 +239,26 @@ out VertexOutput {
vertOut.normal = vertIn[vert].normal;
vertOut.texCoord = vertIn[vert].texCoord;
if (FLAG_ACTIVE(MODEL_SDR_FLAG_ENV)) {
vertOut.envReflect = vertIn[vert].envReflect;
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_NORMAL)) {
vertOut.tangentMatrix = vertIn[vert].tangentMatrix;
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_FOG)) {
vertOut.fogDist = vertIn[vert].fogDist;
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_SHADOWS)) {
vertOut.shadowUV[0] = vertIn[vert].shadowUV[0];
vertOut.shadowUV[1] = vertIn[vert].shadowUV[1];
vertOut.shadowUV[2] = vertIn[vert].shadowUV[2];
vertOut.shadowUV[3] = vertIn[vert].shadowUV[3];
vertOut.shadowPos = vertIn[vert].shadowPos;
}
#prereplace IF_FLAG MODEL_SDR_FLAG_ENV
vertOut.envReflect = vertIn[vert].envReflect;
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_ENV
#prereplace IF_FLAG MODEL_SDR_FLAG_NORMAL
vertOut.tangentMatrix = vertIn[vert].tangentMatrix;
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_NORMAL
#prereplace IF_FLAG MODEL_SDR_FLAG_FOG
vertOut.fogDist = vertIn[vert].fogDist;
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_FOG
#prereplace IF_FLAG MODEL_SDR_FLAG_SHADOWS
vertOut.shadowUV[0] = vertIn[vert].shadowUV[0];
vertOut.shadowUV[1] = vertIn[vert].shadowUV[1];
vertOut.shadowUV[2] = vertIn[vert].shadowUV[2];
vertOut.shadowUV[3] = vertIn[vert].shadowUV[3];
vertOut.shadowPos = vertIn[vert].shadowPos;
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_SHADOWS
if (use_clip_plane) {
gl_ClipDistance[0] = gl_in[vert].gl_ClipDistance[0];
}
+36 -17
View File
@@ -2,7 +2,9 @@
#extension GL_ARB_gpu_shader5: enable
#include "shadows.sdr"
#include "model_shader_flags.h"
#conditional_include +"LARGE_SHADER" "main_large.sdr"
#conditional_include -"LARGE_SHADER" "main_small.sdr"
in vec4 vertPosition;
in vec4 vertTexCoord;
@@ -95,13 +97,22 @@ layout (std140) uniform modelData {
int flags;
};
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_TRANSFORM
uniform samplerBuffer transform_tex;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_TRANSFORM
out VertexOutput {
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_ENV
vec3 envReflect;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_ENV
mat3 tangentMatrix;
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_FOG
float fogDist;
#ifdef FLAG_SHADOW_MAP
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_FOG
#ifdef MODEL_SDR_FLAG_SHADOW_MAP
#if !defined(GL_ARB_gpu_shader5)
float instance;
#endif
@@ -113,11 +124,15 @@ out VertexOutput {
#endif
vec3 normal;
vec4 texCoord;
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
vec4 shadowUV[4];
vec4 shadowPos;
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
} vertOut;
#define TEXELS_PER_MATRIX 4
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_TRANSFORM
void getModelTransform(inout mat4 transform, out bool invisible, int id, int matrix_offset)
{
transform[0] = texelFetch(transform_tex, (matrix_offset + id) * TEXELS_PER_MATRIX);
@@ -127,6 +142,7 @@ void getModelTransform(inout mat4 transform, out bool invisible, int id, int mat
invisible = transform[3].w >= 0.9;
transform[3].w = 1.0;
}
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_TRANSFORM
void main()
{
@@ -137,20 +153,21 @@ void main()
mat4 scale = mat4(1.0);
bool clipModel = false;
if (FLAG_ACTIVE(MODEL_SDR_FLAG_TRANSFORM)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_TRANSFORM
getModelTransform(orient, clipModel, int(vertModelID), buffer_matrix_offset);
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_TRANSFORM
texCoord = textureMatrix * vertTexCoord;
vec4 vertex = vertPosition;
if (FLAG_ACTIVE(MODEL_SDR_FLAG_THRUSTER)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_THRUSTER
if(vertex.z < -1.5) {
vertex.z *= thruster_scale;
}
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_THRUSTER
// Transform the normal into eye space and normalize the result.
normal = normalize(mat3(modelViewMatrix) * mat3(orient) * vertNormal);
position = modelViewMatrix * orient * vertex;
#ifdef FLAG_SHADOW_MAP
#ifdef MODEL_SDR_FLAG_SHADOW_MAP
gl_Position = position;
#if !defined(GL_ARB_gpu_shader5)
#ifdef APPLE
@@ -162,37 +179,39 @@ void main()
#else
gl_Position = projMatrix * position;
#endif
if (FLAG_ACTIVE(MODEL_SDR_FLAG_SHADOWS)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_SHADOWS
vec4 shadowPos = shadow_mv_matrix * modelMatrix * orient * vertPosition;
vertOut.shadowPos = shadow_mv_matrix * modelMatrix * orient * vertPosition;
vertOut.shadowUV[0] = transformToShadowMap(shadow_proj_matrix[0], 0, shadowPos);
vertOut.shadowUV[1] = transformToShadowMap(shadow_proj_matrix[1], 1, shadowPos);
vertOut.shadowUV[2] = transformToShadowMap(shadow_proj_matrix[2], 2, shadowPos);
vertOut.shadowUV[3] = transformToShadowMap(shadow_proj_matrix[3], 3, shadowPos);
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_SHADOWS
// Setup stuff for normal maps and envmaps
vec3 t = normalize(mat3(modelViewMatrix) * mat3(orient) * vertTangent.xyz);
vec3 b = cross(normal, t) * vertTangent.w;
vertOut.tangentMatrix = mat3(t, b, normal);
if (FLAG_ACTIVE(MODEL_SDR_FLAG_ENV)) {
#prereplace IF_FLAG MODEL_SDR_FLAG_ENV
// Environment mapping reflection vector.
vec3 envReflect = reflect(normalize(position.xyz), normal);
vertOut.envReflect = vec3(envMatrix * vec4(envReflect, 0.0));
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_FOG)) {
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_ENV
#prereplace IF_FLAG MODEL_SDR_FLAG_FOG
vertOut.fogDist = clamp((gl_Position.z - fogStart) * 0.75 * fogScale, 0.0, 1.0);
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_TRANSFORM)) {
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_FOG
#prereplace IF_FLAG MODEL_SDR_FLAG_TRANSFORM
if (clipModel) {
// Clip this model by moving all vertices outside the clip volume
gl_Position = vec4(vec3(-2.0), 1.0);
}
#ifdef FLAG_SHADOW_MAP
#ifdef MODEL_SDR_FLAG_SHADOW_MAP
vertOut.clipModel = clipModel ? 1.0 : 0.0;
#endif
}
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_TRANSFORM
if(use_clip_plane) {
gl_ClipDistance[0] = dot(clip_equation, modelMatrix * orient * vertex);
@@ -200,7 +219,7 @@ void main()
gl_ClipDistance[0] = 1.0;
}
#ifndef FLAG_SHADOW_MAP
#ifndef MODEL_SDR_FLAG_SHADOW_MAP
vertOut.position = position;
vertOut.normal = normal;
vertOut.texCoord = texCoord;
@@ -0,0 +1,9 @@
#predefine IF_FLAG if ((flags & %s) != 0) {
#predefine IF_NOT_FLAG if ((flags & %s) == 0) {
#predefine ELSE_FLAG } else { %s
#predefine ENDIF_FLAG } %s
#predefine IF_FLAG_COMPILED //if true %s
#predefine ENDIF_FLAG_COMPILED //endif true %s
#define MODEL_SDR_FLAG_MODE_GLSL 1
#include "model_shader_flags.h"
@@ -0,0 +1,6 @@
#predefine IF_FLAG #ifdef %s
#predefine IF_NOT_FLAG #ifndef %s
#predefine ELSE_FLAG #else //%s
#predefine ENDIF_FLAG #endif //%s
#predefine IF_FLAG_COMPILED #ifdef %s
#predefine ENDIF_FLAG_COMPILED #endif //%s
@@ -1,19 +1,35 @@
#define MODEL_SDR_FLAG_LIGHT (1 << 0)
#define MODEL_SDR_FLAG_DEFERRED (1 << 1)
#define MODEL_SDR_FLAG_HDR (1 << 2)
#define MODEL_SDR_FLAG_DIFFUSE (1 << 3)
#define MODEL_SDR_FLAG_GLOW (1 << 4)
#define MODEL_SDR_FLAG_SPEC (1 << 5)
#define MODEL_SDR_FLAG_ENV (1 << 6)
#define MODEL_SDR_FLAG_NORMAL (1 << 7)
#define MODEL_SDR_FLAG_AMBIENT (1 << 8)
#define MODEL_SDR_FLAG_MISC (1 << 9)
#define MODEL_SDR_FLAG_TEAMCOLOR (1 << 10)
#define MODEL_SDR_FLAG_FOG (1 << 11)
#define MODEL_SDR_FLAG_TRANSFORM (1 << 12)
#define MODEL_SDR_FLAG_SHADOWS (1 << 13)
#define MODEL_SDR_FLAG_THRUSTER (1 << 14)
#define MODEL_SDR_FLAG_ALPHA_MULT (1 << 15)
#ifdef MODEL_SDR_FLAG_MODE_CPP
#define SDR_FLAG(name, value, geoshader) constexpr int name = value;
#elif defined MODEL_SDR_FLAG_MODE_CPP_ARRAY
#define SDR_FLAG(name, value, geoshader) {SDR_TYPE_MODEL, geoshader, value, #name, {}, #name},
#elif defined MODEL_SDR_FLAG_MODE_GLSL
#define SDR_FLAG(name, value, geoshader) const int name = value;
#else
#error Make sure to properly define the usage mode for this file!
#endif
SDR_FLAG(MODEL_SDR_FLAG_LIGHT , (1 << 0) , false)
SDR_FLAG(MODEL_SDR_FLAG_DEFERRED , (1 << 1) , false)
SDR_FLAG(MODEL_SDR_FLAG_HDR , (1 << 2) , false)
SDR_FLAG(MODEL_SDR_FLAG_DIFFUSE , (1 << 3) , false)
SDR_FLAG(MODEL_SDR_FLAG_GLOW , (1 << 4) , false)
SDR_FLAG(MODEL_SDR_FLAG_SPEC , (1 << 5) , false)
SDR_FLAG(MODEL_SDR_FLAG_ENV , (1 << 6) , false)
SDR_FLAG(MODEL_SDR_FLAG_NORMAL , (1 << 7) , false)
SDR_FLAG(MODEL_SDR_FLAG_AMBIENT , (1 << 8) , false)
SDR_FLAG(MODEL_SDR_FLAG_MISC , (1 << 9) , false)
SDR_FLAG(MODEL_SDR_FLAG_TEAMCOLOR , (1 << 10), false)
SDR_FLAG(MODEL_SDR_FLAG_FOG , (1 << 11), false)
SDR_FLAG(MODEL_SDR_FLAG_TRANSFORM , (1 << 12), false)
SDR_FLAG(MODEL_SDR_FLAG_SHADOWS , (1 << 13), false)
SDR_FLAG(MODEL_SDR_FLAG_THRUSTER , (1 << 14), false)
SDR_FLAG(MODEL_SDR_FLAG_ALPHA_MULT , (1 << 15), false)
#define FLAG_ACTIVE(flag) (flags & flag) != 0
#ifndef MODEL_SDR_FLAG_MODE_GLSL
//The following ones are used ONLY as compile-time flags, but they still need to be defined here to ensure no conflict occurs
//But since these are checked with ifdefs even for the large shader, they must never be available in GLSL mode
SDR_FLAG(MODEL_SDR_FLAG_SHADOW_MAP , (1 << 16), true)
SDR_FLAG(MODEL_SDR_FLAG_THICK_OUTLINES, (1 << 17), true)
#endif
+3 -3
View File
@@ -5,7 +5,6 @@ out vec4 fragOut2;
out vec4 fragOut3;
out vec4 fragOut4;
out vec4 fragOut5;
out float gl_FragDepth;
uniform sampler2DMS texColor;
uniform sampler2DMS texPos;
@@ -175,7 +174,8 @@ void main()
for(int i = 0; i < samples; i++) {
vec4 localPos = texelFetch(texPos, texel, i);
//Calculate local weight from distance Voxel, but if the distance is 0 (i.e. no model at all), set weight to 1 to allow stuff like background emissive
float localWeight = max(step(-0.001, dist),
//However, if the median distance is 0, only deal with current texel if it's local distance is 0 as well
float localWeight = max(step(-0.001, dist) * step(-0.001, localPos.z),
smoothstep(dist + dist * texelWidthFactor * (voxelDepth + voxelDepthFalloff), dist + dist * texelWidthFactor * voxelDepth, localPos.z) *
smoothstep(dist - dist * texelWidthFactor * voxelDepth, dist + dist * texelWidthFactor * (voxelDepth + voxelDepthFalloff), localPos.z)
);
@@ -191,7 +191,7 @@ void main()
fragOut0 = color / weight;
fragOut1 = pos / weight;
fragOut2 = normalize(normal);
fragOut2 = vec4(normalize(normal.xyz), normal.a / weight);
fragOut3 = specular / weight;
fragOut4 = emissive / weight;
gl_FragDepth = depth / weight;
+12 -8
View File
@@ -21,9 +21,11 @@ layout (std140) uniform genericData {
vec3 globalLightDiffuse;
float stepsize;
vec3 nebPos;
float globalstepalpha;
float opacitydistance;
vec3 nebSize;
float alphalim;
vec3 nebulaColor;
float udfScale;
float emissiveSpreadFactor;
float emissiveIntensity;
float emissiveFalloff;
@@ -92,12 +94,14 @@ void main()
vec3 sidestep = 1.0 / vec3(textureSize(volume_tex, 0));
for(float stept = maxtMin; stept < mintMax; stept += stepsize) {
for(float stept = maxtMin; stept < mintMax;) {
//Step setup
vec3 position = camera + rayDirection * stept - nebPos;
vec3 sampleposition = position / nebSize + 0.5;
vec4 volume_sample = textureGrad(volume_tex, sampleposition, gradX, gradY);
float stepsize_current = min(max(stepsize, volume_sample.x * udfScale), mintMax - stept);
#ifdef DO_EDGE_SMOOTHING
//Average 3D texel with texels on corner, in an attempt to reduce jagged edges.
float stepcolor_alpha = volume_sample.a;
@@ -117,7 +121,7 @@ void main()
float stepcolor_alpha = volume_sample.a;
#endif
float stepalpha = globalstepalpha * stepcolor_alpha;
float stepalpha = -(pow(alphalim, 1.0 / (opacitydistance / stepsize_current)) - 1.0f) * stepcolor_alpha;
//All the following computations are just required if we have a stepcoloralpha that is non-zero.
if(stepcolor_alpha > 0.01)
{
@@ -127,10 +131,10 @@ void main()
//Diffuse
#ifdef NOISE
//Mix the actual nebula color with the noise color depending on the product of the noise channels multiplied with intensity, smooth-clamped from 0 to 1
vec3 stepcolor_neb = mix(volume_sample.rgb, noiseColor,
vec3 stepcolor_neb = mix(nebulaColor, noiseColor,
smoothstep(0, 1, (textureGrad(noise_volume_tex, position / noiseColorScale1, gradX, gradY).r + textureGrad(noise_volume_tex, position / noiseColorScale2, gradX, gradY).g) / 2.0 * noiseIntensity));
#else
vec3 stepcolor_neb = volume_sample.rgb;
vec3 stepcolor_neb = nebulaColor;
#endif
vec3 stepcolor_diffuse = stepcolor_neb * henyey_greenstein(dot(rayDirection, globalLightDirection));
float directionalLightStep = 4.0 / float(directionalLightSampleSteps);
@@ -145,17 +149,17 @@ void main()
stepcolor_diffuse *= beer_powder_norm * (1 - exp(-directionalLightDepth * 2.0)) * exp(-directionalLightDepth);
//Emissive
cumnebdist += stepcolor_alpha * stepsize;
cumnebdist += stepcolor_alpha * stepsize_current;
vec3 emissive_lod = textureLod(emissive, fragTexCoord.xy, clamp(cumnebdist * emissiveSpreadFactor, 0, float(textureQueryLevels(emissive) - 1))).rgb;
vec3 stepcolor_emissive = emissive_lod.rgb * pow(1 - globalstepalpha, (depth - stept) * emissiveFalloff) * emissiveIntensity;
vec3 stepcolor_emissive = emissive_lod.rgb * pow(alphalim, 1.0 / (opacitydistance / ((depth - stept) * emissiveFalloff + 0.01))) * emissiveIntensity;
//Step finish
vec3 stepcolor = clamp(stepcolor_diffuse + stepcolor_emissive, 0, 1);
float stepalpha = globalstepalpha * stepcolor_alpha;
cumcolor += stepalpha * cumOMAlpha * stepcolor;
}
cumOMAlpha *= 1.0 - stepalpha;
stept += stepsize_current;
if(cumOMAlpha < alphalim)
break;
@@ -0,0 +1,78 @@
-- A version of include for lua. Originally written by Nuke
local chunck_cache = {}
--- function to load and run lua files
-- takes string filename and boolean cacheonly
-- cfile will try to find filename in all accesible locations and load it only if it hasnt done so already
-- if cacheonly flag is set, code will be cached but not executed, good for inits. however it is ignored when calling an already cached chunk.
-- returns true on success or nil on failure to find/load file
local function execute_lua_file(filename, cacheonly)
--dont reload chunks from file if they have already been loaded. because faster == better
if (type(chunck_cache[filename]) == "table" and type(chunck_cache[filename][1]) == "function") then
if (not chunck_cache[filename][2] and not chunck_cache[filename][3]) then
chunck_cache[filename][2] = true
local val, err = pcall(chunck_cache[filename][1])
if (err) then
-- Add an boolean to indicate that this function has caused an error
chunck_cache[filename][3] = true
return false, string.format("Error while executing external lua file %q:\n%s", filename, err)
end
return true
else
return false
end
else
if (cf.fileExists(filename, "", true)) then
--open the file
local file = cf.openFile(filename, "r", "")
local fstring = file:read("*a") --load it all into a string
file:close()
if (fstring and type(fstring) == "string") then
--use the string as a code chunk and convert it to function
local func, error = loadstring(fstring, filename)
if (not func) then -- Compile error
return false, string.format("Error while processing file %q. Errormessage:\n%s", filename, error)
end
chunck_cache[filename] = {}
chunck_cache[filename][1] = func
chunck_cache[filename][2] = false
--maybe execute
if (not cacheonly) then
chunck_cache[filename][2] = true
local val, err = xpcall(chunck_cache[filename][1], function(err)
-- Add an boolean to indicate that this function has caused an error
chunck_cache[filename][3] = true
return string.format("Error while executing external lua file %q:\n%s\n\n%s", filename, err, debug.traceback())
end)
if (err) then
return false, err
end
end
return true
end
else
return false, string.format("Couldn't find external lua file %q!", filename)
end
end
end
function include(fileName)
if (fileName == nil) then
stackErrorf("Invalid argument for 'include'!")
else
if (not fileName:ends(".lua")) then
fileName = fileName .. ".lua"
end
local succ, err = execute_lua_file(fileName)
if (not succ and err) then
error(err)
end
end
end
@@ -0,0 +1,86 @@
-- Basic forwarders for common Lua methods
function error(str)
ba.error(str)
end
function warning(str)
ba.warning(str)
end
function print(str)
ba.print(str)
end
function println(str)
if (str) then
ba.print(str)
end
ba.print("\n")
end
function stackError(str, level)
if (level == nil) then
level = 2
else
level = level + 1
end
error(debug.traceback(tostring(str) .. "\n", level) .. "\n")
end
function warningf(str, ...)
warning(string.format(str, ...))
end
function errorf(str, ...)
error(string.format(str, ...))
end
function printf(str, ...)
print(string.format(str, ...))
end
function stackErrorf(str, ...)
stackError(string.format(str, ...), 2)
end
function string.starts(str, start)
return string.sub(str, 1, string.len(start)) == start
end
function string.ends(str, e)
return (e == '') or (string.sub(str, -string.len(e)) == e)
end
-- Global table that can hold variables that should not be able to be changed
Globals = {}
Globals.values = {}
local mt = {}
function mt.__newindex(t, index, value)
if (index == "values") then
stackErrorf("Cannot set value to index %q. Index is forbidden!", tostring(index))
elseif (rawget(t.values, index) ~= nil) then
stackErrorf("Cannot set value to index %q. Index already used!", tostring(index))
else
rawset(t.values, index, value)
end
end
function mt.__index(t, index)
if (index == "values") then
stackErrorf("Trying to access forbidden value %q!", index)
else
return rawget(t.values, index)
end
end
setmetatable(Globals, mt)
-- Initial Values
Globals.nullVec = ba.createVector(0, 0, 0)
Globals.zeroVec = Globals.nullVec
Globals.identityOrient = ba.createOrientationFromVectors(ba.createVector(0, 0, 1), ba.createVector(0, 1, 0), ba.createVector(1, 0, 0))
+26 -80
View File
@@ -8,9 +8,9 @@ $Fog:
+Start dist: 10.0
+Compl dist: 500.0
$AI:
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Turrets attack this: YES
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Skip Death Roll Percent Chance: 0.0
$Name: Sentry Gun
@@ -28,10 +28,10 @@ $Fog:
$AI:
+Accept Player Orders: NO
+Auto attacks: YES
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Guards attack this: YES
+Turrets attack this: YES
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Skip Death Roll Percent Chance: 0.0
$Name: Escape Pod
@@ -48,9 +48,9 @@ $Fog:
+Compl dist: 600.0
$AI:
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "play dead (persistent)" "stay near ship" )
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Turrets attack this: YES
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Skip Death Roll Percent Chance: 0.0
$Name: Cargo
@@ -87,37 +87,11 @@ $AI:
+Accept Player Orders: YES
+Player orders: ( "rearm me" "abort rearm" "depart" )
+Auto attacks: YES
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Guards attack this: YES
+Turrets attack this: YES
+Active docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Skip Death Roll Percent Chance: 0.0
;;WMC - Stealth ships always have another type, so this isn't used
$Name: Stealth
$Counts for Alone: YES
$Praise Destruction: YES
$On Hotkey List: YES
$Target as Threat: YES
$Show Attack Direction: YES
$Max Debris Speed: 200
$FF Multiplier: 1.0
$EMP Multiplier: 4.0
$Protected on cripple: YES
$Fog:
+Start dist: 10.0
+Compl dist: 500.0
$AI:
+Valid goals: ( "fly to ship" "attack ship" "waypoints" "waypoints once" "depart" "attack subsys" "attack wing" "guard ship" "disable ship" "disarm ship" "attack any" "attack ship class" "ignore ship" "ignore ship (new)" "guard wing" "evade ship" "stay still" "play dead" "play dead (persistent)" "stay near ship" "keep safe dist" )
+Accept Player Orders: YES
+Player Orders: ( "attack ship" "disable ship" "disarm ship" "guard ship" "ignore ship" "ignore ship (new)" "form on wing" "cover me" "attack any" "depart" "disable subsys" )
+Auto attacks: YES
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Guards attack this: YES
+Turrets attack this: YES
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Skip Death Roll Percent Chance: 0.0
$Name: Fighter
@@ -136,16 +110,16 @@ $Fog:
+Start dist: 10.0
+Compl dist: 500.0
$AI:
+Valid goals: ( "fly to ship" "attack ship" "waypoints" "waypoints once" "depart" "attack subsys" "attack wing" "guard ship" "disable ship" "disarm ship" "attack any" "attack ship class" "ignore ship" "ignore ship (new)" "guard wing" "evade ship" "stay still" "play dead" "play dead (persistent)" "stay near ship" "keep safe dist" "form on wing")
+Valid goals: ( "fly to ship" "attack ship" "waypoints" "waypoints once" "depart" "attack subsys" "attack wing" "guard ship" "disable ship" "disable ship (tactical)" "disarm ship" "disarm ship (tactical)" "attack any" "attack ship class" "ignore ship" "ignore ship (new)" "guard wing" "evade ship" "stay still" "play dead" "play dead (persistent)" "stay near ship" "keep safe dist" "form on wing")
+Accept Player Orders: YES
+Player Orders: ( "attack ship" "disable ship" "disarm ship" "guard ship" "ignore ship" "ignore ship (new)" "form on wing" "cover me" "attack any" "depart" "disable subsys" )
+Player Orders: ( "attack ship" "disable ship" "disable ship (tactical)" "disarm ship" "disarm ship (tactical)" "guard ship" "ignore ship" "ignore ship (new)" "form on wing" "cover me" "attack any" "attack ship class" "depart" "disable subsys" )
+Auto attacks: YES
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Guards attack this: YES
+Turrets attack this: YES
+Can Form Wing: YES
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Skip Death Roll Percent Chance: 0.0
$Name: Bomber
@@ -164,44 +138,16 @@ $Fog:
+Start dist: 10.0
+Compl dist: 500.0
$AI:
+Valid goals: ( "fly to ship" "attack ship" "waypoints" "waypoints once" "depart" "attack subsys" "attack wing" "guard ship" "disable ship" "disarm ship" "attack any" "attack ship class" "ignore ship" "ignore ship (new)" "guard wing" "evade ship" "stay still" "play dead" "play dead (persistent)" "stay near ship" "keep safe dist" "form on wing" )
+Valid goals: ( "fly to ship" "attack ship" "waypoints" "waypoints once" "depart" "attack subsys" "attack wing" "guard ship" "disable ship" "disable ship (tactical)" "disarm ship" "disarm ship (tactical)" "attack any" "attack ship class" "ignore ship" "ignore ship (new)" "guard wing" "evade ship" "stay still" "play dead" "play dead (persistent)" "stay near ship" "keep safe dist" "form on wing" )
+Accept Player Orders: YES
+Player Orders: ( "attack ship" "disable ship" "disarm ship" "guard ship" "ignore ship" "ignore ship (new)" "form on wing" "cover me" "attack any" "depart" "disable subsys" )
+Player Orders: ( "attack ship" "disable ship" "disable ship (tactical)" "disarm ship" "disarm ship (tactical)" "guard ship" "ignore ship" "ignore ship (new)" "form on wing" "cover me" "attack any" "attack ship class" "depart" "disable subsys" )
+Auto attacks: YES
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Guards attack this: YES
+Turrets attack this: YES
+Can Form Wing: YES
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Skip Death Roll Percent Chance: 0.0
;;WMC - This fighter/bomber type doesn't seem to be used anywhere, because no ship is set as both fighter and bomber
$Name: Fighter/bomber
$Counts for Alone: YES
$Praise Destruction: YES
$On Hotkey List: YES
$Target as Threat: YES
$Show Attack Direction: YES
$Warp Pushable: YES
$Max Debris Speed: 200
$FF Multiplier: 1.0
$EMP Multiplier: 4.0
$Protected on cripple: YES
$Fog:
+Start dist: 10.0
+Compl dist: 500.0
$AI:
+Valid goals: ( "fly to ship" "attack ship" "waypoints" "waypoints once" "depart" "attack subsys" "attack wing" "guard ship" "disable ship" "disarm ship" "attack any" "attack ship class" "ignore ship" "ignore ship (new)" "guard wing" "evade ship" "stay still" "play dead" "play dead (persistent)" "stay near ship" "keep safe dist" "form on wing" )
+Accept Player Orders: YES
+Player Orders: ( "attack ship" "disable ship" "disarm ship" "guard ship" "ignore ship" "ignore ship (new)" "form on wing" "cover me" "attack any" "depart" "disable subsys" )
+Auto attacks: YES
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Guards attack this: YES
+Turrets attack this: YES
+Can Form Wing: YES
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Skip Death Roll Percent Chance: 0.0
$Name: Transport
@@ -230,7 +176,7 @@ $AI:
+Turrets attack this: YES
+Can Form Wing: YES
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Skip Death Roll Percent Chance: 0.0
@@ -262,7 +208,7 @@ $AI:
+Can Form Wing: YES
+Active docks: ( "cargo" )
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Skip Death Roll Percent Chance: 0.0
@@ -292,7 +238,7 @@ $AI:
+Turrets attack this: YES
+Can Form Wing: YES
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Skip Death Roll Percent Chance: 0.0
@@ -322,7 +268,7 @@ $AI:
+Turrets attack this: YES
+Can Form Wing: YES
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Skip Death Roll Percent Chance: 0.0
@@ -352,7 +298,7 @@ $AI:
+Turrets attack this: YES
+Can Form Wing: YES
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Skip Death Roll Percent Chance: 0.0
@@ -382,7 +328,7 @@ $AI:
+Turrets attack this: YES
+Can Form Wing: YES
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Skip Death Roll Percent Chance: 0.0
@@ -412,7 +358,7 @@ $AI:
+Turrets attack this: YES
+Can Form Wing: YES
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Skip Death Roll Percent Chance: 0.0
@@ -440,7 +386,7 @@ $AI:
+Turrets attack this: YES
+Can Form Wing: YES
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Skip Death Roll Percent Chance: 0.0
@@ -466,7 +412,7 @@ $AI:
+Guards attack this: YES
+Turrets attack this: YES
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Skip Death Roll Percent Chance: 0.0
@@ -490,7 +436,7 @@ $AI:
+Guards attack this: YES
+Turrets attack this: YES
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Skip Death Roll Percent Chance: 0.0
+2 -13
View File
@@ -291,17 +291,6 @@ static const char *GetExceptionDescription(DWORD ExceptionCode)
return "Unknown exception type";
}
static char* GetFilePart(char *source)
{
char *result = strrchr(source, '\\');
if (result) {
result++;
} else {
result = source;
}
return result;
}
// --------------------
//
// External Functions
@@ -338,7 +327,7 @@ int __cdecl RecordExceptionInfo(PEXCEPTION_POINTERS data, const char *Message)
ModuleName[0] = 0;
}
char *FilePart = GetFilePart(ModuleName);
char *FilePart = util::get_file_part(ModuleName);
// Extract the file name portion and remove it's file extension. We'll
// use that name shortly.
@@ -371,7 +360,7 @@ int __cdecl RecordExceptionInfo(PEXCEPTION_POINTERS data, const char *Message)
// code address, which is the same as the ModuleHandle. This can be used
// to get the filename of the module that the crash happened in.
if (VirtualQuery((void*)Context->Eip, &MemInfo, sizeof(MemInfo)) && GetModuleFileName((HINSTANCE)MemInfo.AllocationBase, CrashModulePathName, sizeof(CrashModulePathName)) > 0) {
CrashModuleFileName = GetFilePart(CrashModulePathName);
CrashModuleFileName = util::get_file_part(CrashModulePathName);
}
// Print out the beginning of the error log in a Win95 error window
+248 -63
View File
@@ -37,26 +37,15 @@ constexpr int INTITIAL_FIREBALL_CONTAINTER_SIZE = 256;
SCP_vector<fireball> Fireballs;
SCP_vector<int> Unused_fireball_indices;
fireball_info Fireball_info[MAX_FIREBALL_TYPES];
int fireball_used[MAX_FIREBALL_TYPES];
int Num_fireball_types = 0;
SCP_vector<fireball_info> Fireball_info;
bool fireballs_inited = false;
bool fireballs_parsed = false;
bool Fireball_use_3d_warp = false;
static auto WarpOption __UNUSED = options::OptionBuilder<bool>("Graphics.3dWarp",
std::pair<const char*, int>{"3D Warp", 1770},
std::pair<const char*, int>{"Use a 3D model for warp effects", 1771})
.category("Graphics")
.default_val(true)
.level(options::ExpertLevel::Advanced)
.bind_to(&Fireball_use_3d_warp)
.importance(65)
.finish();
static float exp_to_line(float t, float start_value, float end_slope, float scale)
{
return -scale * expf(-start_value / scale * t) + end_slope * t + scale;
}
/**
* Play warp in sound for warp effect
@@ -120,7 +109,7 @@ void fireball_play_warphole_close_sound(fireball *fb)
static void fireball_generate_unique_id(char *unique_id, int buffer_len, int fireball_index)
{
Assert((fireball_index >= 0) && (fireball_index < MAX_FIREBALL_TYPES));
Assertion(SCP_vector_inbounds(Fireball_info, fireball_index), "fireball_index is out of bounds!");
switch (fireball_index)
{
@@ -164,7 +153,7 @@ static void fireball_generate_unique_id(char *unique_id, int buffer_len, int fir
*/
static void fireball_set_default_color(int idx)
{
Assert((idx >= 0) && (idx < MAX_FIREBALL_TYPES));
Assertion(SCP_vector_inbounds(Fireball_info, idx), "idx is out of bounds!");
switch (idx)
{
@@ -200,7 +189,7 @@ static void fireball_set_default_color(int idx)
static void fireball_set_default_warp_attributes(int idx)
{
Assert((idx >= 0) && (idx < MAX_FIREBALL_TYPES));
Assertion(SCP_vector_inbounds(Fireball_info, idx), "idx is out of bounds!");
switch (idx)
{
@@ -210,9 +199,6 @@ static void fireball_set_default_warp_attributes(int idx)
strcpy_s(Fireball_info[idx].warp_ball, "warpball01");
strcpy_s(Fireball_info[idx].warp_model, "warp.pof");
if (Fireball_use_3d_warp)
Fireball_info[idx].use_3d_warp = true;
break;
}
}
@@ -232,9 +218,9 @@ void fireball_info_clear(fireball_info *fb)
int fireball_info_lookup(const char *unique_id)
{
for (int i = 0; i < Num_fireball_types; ++i)
for (size_t i = 0; i < Fireball_info.size(); ++i)
if (!stricmp(Fireball_info[i].unique_id, unique_id))
return i;
return static_cast<int>(i);
return -1;
}
@@ -308,25 +294,19 @@ static void parse_fireball_tbl(const char *table_filename)
// we are creating a new entry, so set some defaults
else
{
// make sure we don't exceed the max
if (Num_fireball_types >= MAX_FIREBALL_TYPES)
{
error_display(0, "Too many fireball entries! Max is %d", MAX_FIREBALL_TYPES);
return;
}
fi = &Fireball_info[Num_fireball_types];
int new_fireball_index = static_cast<int>(Fireball_info.size());
Fireball_info.emplace_back();
fi = &Fireball_info.back();
fireball_info_clear(fi);
// If the table didn't specify a unique ID, generate one. This will be assigned a few lines later.
if (strlen(unique_id) == 0)
fireball_generate_unique_id(unique_id, NAME_LENGTH, Num_fireball_types);
fireball_generate_unique_id(unique_id, NAME_LENGTH, new_fireball_index);
// Set remaining fireball defaults
fireball_set_default_color(Num_fireball_types);
fireball_set_default_warp_attributes(Num_fireball_types);
fireball_set_default_color(new_fireball_index);
fireball_set_default_warp_attributes(new_fireball_index);
Num_fireball_types++;
first_time = true;
}
@@ -371,9 +351,17 @@ static void parse_fireball_tbl(const char *table_filename)
stuff_string(fi->warp_glow, F_NAME, NAME_LENGTH);
// check for custom warp ball
if (optional_string("$Warp ball:"))
if (optional_string("$Warp ball:")) {
stuff_string(fi->warp_ball, F_NAME, NAME_LENGTH);
// if we are explicitly specifying a ball, then we'll want to use it,
// rather than just having the default ball that might or might not be used
fi->warp_flash = true;
}
if (optional_string("$Force warp flash:"))
stuff_boolean(&fi->warp_flash);
// check for custom warp model
if (optional_string("$Warp model:"))
{
@@ -383,6 +371,114 @@ static void parse_fireball_tbl(const char *table_filename)
// rather than just having the default model that might or might not be used
fi->use_3d_warp = true;
}
if (optional_string("$Force 3D Warp:")) {
stuff_boolean(&fi->use_3d_warp);
}
if (optional_string("$Warp size ratio:")) {
stuff_float(&fi->warp_size_ratio);
} else if (first_time) {
if (fi->use_3d_warp) {
fi->warp_size_ratio = 1 / 25.0f;
} else {
fi->warp_size_ratio = 1.0f;
}
}
if (optional_string("$Flare size ratio:")) {
stuff_float(&fi->flare_size_ratio);
} else if (first_time) {
fi->flare_size_ratio = 1.0f;
}
if (optional_string("$Flicker magnitude:")) {
stuff_float(&fi->flicker_magnitude);
} else if (first_time) {
fi->flicker_magnitude = 0.10f;
}
if (optional_string("$Warp flare style:")) {
switch (optional_string_one_of(3, "classic", "enhanced", "cinematic")) {
case 0:
fi->warp_flare_style = warp_style::CLASSIC;
break;
case 1:
fi->warp_flare_style = warp_style::ENHANCED;
break;
case 2:
fi->warp_flare_style = warp_style::CINEMATIC;
break;
default:
error_display(0, "Invalid warp flare style. Must be classic, enhanced, or cinematic.");
}
// Set warp flare option
if (optional_string("+Flare size ratio:")) {
stuff_float(&fi->flare_size_ratio);
} else if (fi->warp_flare_style == warp_style::CLASSIC) {
fi->flare_size_ratio = 1.0f;
} else if (fi->warp_flare_style == warp_style::CINEMATIC) {
fi->flare_size_ratio = 5.3f;
}
} else if (first_time) {
fi->warp_flare_style = warp_style::CLASSIC;
}
if (optional_string("$Warp model style:")) {
switch (optional_string_one_of(2, "classic", "cinematic")) {
case 0:
fi->warp_model_style = warp_style::CLASSIC;
break;
case 1:
fi->warp_model_style = warp_style::CINEMATIC;
break;
default:
error_display(0, "Invalid warp model style. Must be classic or cinematic.");
}
} else if (first_time) {
fi->warp_model_style = warp_style::CLASSIC;
}
// Set warp_model_style options if cinematic style is chosen
if (fi->warp_model_style == warp_style::CINEMATIC) {
if (optional_string("+Warp size ratio:")) {
stuff_float(&fi->warp_size_ratio);
} else {
fi->warp_size_ratio = 1.6f;
}
// The first two values need to be implied multiples of PI
// for convenience. These shouldn't need to be faster than a full
// rotation per second, which is already ridiculous.
if (optional_string("+Rotation anim:")) {
stuff_float_list(fi->rot_anim, 3);
CLAMP(fi->rot_anim[0], 0.0f, 2.0f);
CLAMP(fi->rot_anim[1], 0.0f, 2.0f);
fi->rot_anim[2] = MAX(0.0f, fi->rot_anim[2]);
} else {
// PI / 2.75f, PI / 10.0f, 2.0f
fi->rot_anim[0] = 0.365f;
fi->rot_anim[1] = 0.083f;
fi->rot_anim[2] = 2.0f;
}
// Variable frame rate for faster propagation of ripples
if (optional_string("+Frame anim:")) {
stuff_float_list(fi->frame_anim, 3);
// A frame rate that is 4 times the normal speed is ridiculous
CLAMP(fi->frame_anim[0], 0.0f, 4.0f);
CLAMP(fi->frame_anim[1], 1.0f, 4.0f);
fi->frame_anim[2] = MAX(0.0f, fi->frame_anim[2]);
} else {
fi->frame_anim[0] = 1.0f;
fi->frame_anim[1] = 1.0f;
fi->frame_anim[2] = 3.0f;
}
}
}
required_string("#End");
@@ -399,9 +495,9 @@ void fireball_parse_tbl()
if (fireballs_parsed)
return;
// every newly parsed fireball_info will get cleared before being added
// must do this outside of parse_fireball_tbl because it's called twice
Num_fireball_types = 0;
// every newly parsed fireball_info will get cleared before being added;
// must clear the vector outside of parse_fireball_tbl because it's called more than once
Fireball_info.clear();
parse_fireball_tbl("fireball.tbl");
@@ -436,10 +532,11 @@ void fireball_parse_tbl()
void fireball_load_data()
{
int i, idx;
int i, n, idx;
fireball_info *fd;
for ( i = 0; i < Num_fireball_types; i++ ) {
n = static_cast<int>(Fireball_info.size());
for ( i = 0; i < n; i++ ) {
fd = &Fireball_info[i];
for(idx=0; idx<fd->lod_count; idx++){
@@ -548,7 +645,13 @@ void fireball_set_framenum(int num)
}
if ( fb->fireball_render_type == FIREBALL_WARP_EFFECT ) {
framenum = bm_get_anim_frame(fl->bitmap_id, fb->time_elapsed, 0.0f, true);
float new_time = fb->time_elapsed;
if (fd->warp_model_style == warp_style::CINEMATIC) {
float duration_ratio = 2.0f / fb->warp_open_duration;
new_time = exp_to_line(fb->time_elapsed, fd->frame_anim[0] * duration_ratio, fd->frame_anim[1], fd->frame_anim[2] * duration_ratio);
}
framenum = bm_get_anim_frame(fl->bitmap_id, new_time, 0.0f, true);
if ( fb->orient ) {
// warp out effect plays backwards
@@ -798,8 +901,7 @@ int fireball_create(vec3d *pos, int fireball_type, int render_type, int parent_o
object *obj;
fireball_info *fd;
fireball_lod *fl;
Assert( fireball_type > -1 );
Assert( fireball_type < Num_fireball_types );
Assertion(SCP_vector_inbounds(Fireball_info, fireball_type), "fireball_type is out of bounds!");
fd = &Fireball_info[fireball_type];
@@ -946,13 +1048,14 @@ void fireball_close()
void fireballs_page_in()
{
int i, idx;
int i, n, idx;
fireball_info *fd;
for ( i = 0; i < Num_fireball_types; i++ ) {
n = static_cast<int>(Fireball_info.size());
for ( i = 0; i < n; i++ ) {
fd = &Fireball_info[i];
if((i < NUM_DEFAULT_FIREBALLS) || fireball_used[i]) {
if ((i < NUM_DEFAULT_FIREBALLS) || fd->fireball_used) {
// if this is a Knossos ani, only load if Knossos_warp_ani_used is true
if ( (i == FIREBALL_KNOSSOS) && !Knossos_warp_ani_used)
continue;
@@ -973,7 +1076,7 @@ void fireballs_page_in()
// load the warp model, if we have one
if (strlen(fd->warp_model) > 0 && cf_exists_full(fd->warp_model, CF_TYPE_MODELS)) {
mprintf(("Loading warp model '%s'\n", fd->warp_model));
fd->warp_model_id = model_load(fd->warp_model, 0, nullptr, 0);
fd->warp_model_id = model_load(fd->warp_model, nullptr, ErrorType::WARNING);
} else {
fd->warp_model_id = -1;
}
@@ -984,8 +1087,8 @@ void fireball_get_color(int idx, float *red, float *green, float *blue)
{
Assert( red && blue && green );
if ( (idx < 0) || (idx >= Num_fireball_types) ) {
Int3();
if (!SCP_vector_inbounds(Fireball_info, idx)) {
UNREACHABLE("idx is out of bounds!");
*red = 1.0f;
*green = 1.0f;
@@ -1039,22 +1142,48 @@ int fireball_asteroid_explosion_type(asteroid_info *aip)
return index;
}
static float cutscene_wormhole(float t) {
float a = 25.0f * powf(t, 4.0f);
return a / (a + 1.0f);
}
float fireball_wormhole_intensity(fireball *fb)
{
float t = fb->time_elapsed;
float rad;
if ( t < fb->warp_open_duration ) {
rad = (float)pow(t / fb->warp_open_duration, 0.4f);
} else if ( t < fb->total_time - fb->warp_close_duration ) {
rad = 1.0f;
float rad = cutscene_wormhole(t / fb->warp_open_duration);
fireball_info* fi = &Fireball_info[fb->fireball_info_index];
if (fi->warp_model_style == warp_style::CINEMATIC) {
rad *= cutscene_wormhole((fb->total_time - t) / fb->warp_close_duration);
rad /= cutscene_wormhole(fb->total_time / (2.0f * fb->warp_open_duration));
rad /= cutscene_wormhole(fb->total_time / (2.0f * fb->warp_close_duration));
} else {
rad = (float)pow((fb->total_time - t) / fb->warp_close_duration, 0.4f);
if (t < fb->warp_open_duration) {
rad = (float)pow(t / fb->warp_open_duration, 0.4f);
} else if (t < fb->total_time - fb->warp_close_duration) {
rad = 1.0f;
} else {
rad = (float)pow((fb->total_time - t) / fb->warp_close_duration, 0.4f);
}
}
return rad;
}
extern void warpin_queue_render(model_draw_list *scene, object *obj, matrix *orient, vec3d *pos, int texture_bitmap_num, float radius, float life_percent, float max_radius, bool warp_3d, int warp_glow_bitmap, int warp_ball_bitmap, int warp_model_id);
return rad;
}
static float fireball_wormhole_flare_radius(fireball* fb) {
float t = fb->time_elapsed;
float d1 = fb->warp_open_duration;
float d2 = fb->warp_close_duration;
float rad = 2 * (1.0f - exp(-4.0f * powf(1.7f * t/d1, 3.0f))) - (1.0f - exp(-2.0f * powf(1.7f * t/d1, 3.0f)));
rad *= (1.0f - exp(-2.0f * (fb->total_time - t) / d2));
return rad;
}
extern void warpin_queue_render(model_draw_list *scene, object *obj, matrix *orient, vec3d *pos, int texture_bitmap_num, float radius, float life_percent, float flare_rad, float flicker_magnitude, float max_radius, bool warp_3d, int warp_glow_bitmap, int warp_ball_bitmap, int warp_model_id, bool warp_flash);
void fireball_render(object* obj, model_draw_list *scene)
{
@@ -1096,11 +1225,54 @@ void fireball_render(object* obj, model_draw_list *scene)
break;
case FIREBALL_WARP_EFFECT: {
fireball_info* fi = &Fireball_info[fb->fireball_info_index];
float percent_life = fb->time_elapsed / fb->total_time;
float rad = obj->radius * fireball_wormhole_intensity(fb);
float rad = obj->radius * fireball_wormhole_intensity(fb) * fi->warp_size_ratio;
fireball_info *fi = &Fireball_info[fb->fireball_info_index];
warpin_queue_render(scene, obj, &obj->orient, &obj->pos, fb->current_bitmap, rad, percent_life, obj->radius, fi->use_3d_warp || (fb->flags & FBF_WARP_3D) != 0, fi->warp_glow_bitmap, fi->warp_ball_bitmap, fi->warp_model_id);
float flare_rad = obj->radius * fi->flare_size_ratio;
matrix* warp_orientation;
matrix dest = ZERO_MATRIX;
// Flare animation selection
if (fi->warp_flare_style == warp_style::ENHANCED) {
flare_rad += powf((2.0f * percent_life) - 1.0f, 24.0f) * obj->radius * 1.5f * fi->flare_size_ratio;
} else if (fi->warp_flare_style == warp_style::CINEMATIC) {
flare_rad *= fireball_wormhole_flare_radius(fb);
} else {
flare_rad *= fireball_wormhole_intensity(fb);
}
if (fi->warp_model_style == warp_style::CINEMATIC) {
matrix m = ZERO_MATRIX;
float duration_ratio = 2.0f / fb->warp_open_duration;
float angle = exp_to_line(fb->time_elapsed, PI * fi->rot_anim[0] * duration_ratio,
PI * fi->rot_anim[1],
fi->rot_anim[2] * duration_ratio);
matrix* bank_angle = vm_angle_2_matrix(&m, angle, 1);
warp_orientation = vm_matrix_x_matrix(&dest, &obj->orient, bank_angle);
} else {
warp_orientation = &obj->orient;
}
warpin_queue_render(scene,
obj,
warp_orientation,
&obj->pos,
fb->current_bitmap,
rad,
percent_life,
flare_rad,
fi->flicker_magnitude,
obj->radius,
fi->use_3d_warp || (fb->flags & FBF_WARP_3D) != 0,
fi->warp_glow_bitmap,
fi->warp_ball_bitmap,
fi->warp_model_id,
fi->warp_flash);
}
break;
@@ -1120,3 +1292,16 @@ int fireball_get_count()
return count;
}
void stuff_fireball_index_list(SCP_vector<int> &list, const char *name)
{
stuff_int_list(list, RAW_INTEGER_TYPE);
list.erase(std::remove_if(list.begin(), list.end(), [&](int index) {
if (!SCP_vector_inbounds(Fireball_info, index)) {
Warning(LOCATION, "Fireball index %d for %s was out of bounds. Removing this index.", index, name);
return true;
}
return false;
}), list.end());
}
+25 -8
View File
@@ -33,14 +33,19 @@ class asteroid_info;
#define FIREBALL_EXPLOSION_LARGE1 4 // Used for the big explosion when a ship breaks into pieces
#define FIREBALL_EXPLOSION_LARGE2 5 // Used for the big explosion when a ship breaks into pieces
#define MAX_FIREBALL_TYPES 32 // The maximum number of fireballs that can be defined
#define NUM_DEFAULT_FIREBALLS 6
#define MAX_FIREBALL_LOD 4
#define FIREBALL_NUM_LARGE_EXPLOSIONS 2
extern int fireball_used[MAX_FIREBALL_TYPES];
// Gamma39er: Flare animation enum. Add new animation types here.
enum class warp_style
{
CLASSIC,
ENHANCED,
CINEMATIC
};
// all this moved here by Goober5000 because it makes more sense in the H file
typedef struct fireball_lod {
@@ -57,6 +62,20 @@ typedef struct fireball_info {
float exp_color[3]; // red, green, blue
bool use_3d_warp;
bool warp_flash;
bool fireball_used;
warp_style warp_flare_style;
warp_style warp_model_style;
// Customize how large the warp and it's flare are.
float warp_size_ratio;
float flare_size_ratio;
float flicker_magnitude;
// Cinematic Warp stuff
float rot_anim[3];
float frame_anim[3];
char warp_glow[NAME_LENGTH];
int warp_glow_bitmap;
@@ -66,8 +85,7 @@ typedef struct fireball_info {
int warp_model_id;
} fireball_info;
extern fireball_info Fireball_info[MAX_FIREBALL_TYPES];
extern int Num_fireball_types;
extern SCP_vector<fireball_info> Fireball_info;
// flag values for fireball struct flags member
#define FBF_WARP_CLOSE_SOUND_PLAYED (1<<0)
@@ -146,11 +164,10 @@ float fireball_wormhole_intensity( fireball *fb );
// Goober5000
extern bool Knossos_warp_ani_used;
extern bool Fireball_use_3d_warp;
extern bool Fireball_warp_flash;
// Cyborg - get a count of how many valid fireballs are in the mission.
int fireball_get_count();
// Goober5000 - stuffs fireballs and checks that indexes are in bounds
void stuff_fireball_index_list(SCP_vector<int> &list, const char *name);
#endif /* _FIREBALLS_H */
+5 -22
View File
@@ -22,18 +22,6 @@
#include "render/batching.h"
#include "ship/ship.h"
bool Fireball_warp_flash = false;
static auto WarpFlashOption __UNUSED = options::OptionBuilder<bool>("Graphics.WarpFlash",
std::pair<const char*, int>{"Warp Flash", 1768},
std::pair<const char*, int>{"Show flash upon warp open or close", 1769})
.category("Graphics")
.default_val(true)
.level(options::ExpertLevel::Advanced)
.bind_to_once(&Fireball_warp_flash)
.importance(65)
.finish();
void warpin_batch_draw_face( int texture, vertex *v1, vertex *v2, vertex *v3 )
{
vec3d norm;
@@ -54,7 +42,7 @@ void warpin_batch_draw_face( int texture, vertex *v1, vertex *v2, vertex *v3 )
batching_add_tri(texture, vertlist); // TODO render as emissive
}
void warpin_queue_render(model_draw_list *scene, object *obj, matrix *orient, vec3d *pos, int texture_bitmap_num, float radius, float life_percent, float max_radius, bool warp_3d, int warp_glow_bitmap, int warp_ball_bitmap, int warp_model_id)
void warpin_queue_render(model_draw_list *scene, object *obj, matrix *orient, vec3d *pos, int texture_bitmap_num, float radius, float life_percent, float flare_rad, float flicker_magnitude, float max_radius, bool warp_3d, int warp_glow_bitmap, int warp_ball_bitmap, int warp_model_id, bool warp_flash)
{
vec3d center;
vec3d vecs[5];
@@ -68,17 +56,12 @@ void warpin_queue_render(model_draw_list *scene, object *obj, matrix *orient, ve
verts[1] = verts[2] = verts[3] = verts[4] = verts[0];
if (warp_glow_bitmap >= 0) {
float r = flare_rad;
float r = radius;
// Add in noise
int noise_frame = fl2i(Missiontime/15.0f) % NOISE_NUM_FRAMES;
r *= (0.40f + Noise[noise_frame] * 0.30f);
// Bobboau's warp thingie, toggled by cmdline
if (Fireball_warp_flash) {
r += powf((2.0f * life_percent) - 1.0f, 24.0f) * max_radius * 1.5f;
}
r *= (0.40f + Noise[noise_frame] * flicker_magnitude);
vecs[4] = center;
verts[4].texture_position.u = 0.5f; verts[4].texture_position.v = 0.5f;
@@ -95,7 +78,7 @@ void warpin_queue_render(model_draw_list *scene, object *obj, matrix *orient, ve
if ( (warp_model_id >= 0) && (warp_3d) ) {
model_render_params render_info;
float scale = radius / 25.0f;
float scale = radius;
vec3d warp_scale;
@@ -159,7 +142,7 @@ void warpin_queue_render(model_draw_list *scene, object *obj, matrix *orient, ve
warpin_batch_draw_face( texture_bitmap_num, &verts[0], &verts[3], &verts[4] );
}
if (warp_ball_bitmap >= 0 && Fireball_warp_flash) {
if (warp_ball_bitmap >= 0 && warp_flash) {
flash_ball warp_ball(20, .1f,.25f, &orient->vec.fvec, pos, 4.0f, 0.5f);
float adg = (2.0f * life_percent) - 1.0f;
+1 -1
View File
@@ -499,7 +499,7 @@ void help_overlay_blit(int overlay_id, int resolution_index)
font::set_font(help_overlaylist[overlay_id].fontlist.at(resolution_index));
for (idx = 0; idx < textcount; idx++) {
gr_set_color_fast(&Color_black);
gr_get_string_size(&width, &height, help_overlaylist[overlay_id].textlist.at(0).at(idx).string, (int)strlen(help_overlaylist[overlay_id].textlist.at(0).at(idx).string));
gr_get_string_size(&width, &height, help_overlaylist[overlay_id].textlist.at(0).at(idx).string, 1.0f, strlen(help_overlaylist[overlay_id].textlist.at(0).at(idx).string));
gr_rect(help_overlaylist[overlay_id].textlist.at(resolution_index).at(idx).x_coord-2*HELP_PADDING, help_overlaylist[overlay_id].textlist.at(resolution_index).at(idx).y_coord-3*HELP_PADDING, width+4*HELP_PADDING, height+4*HELP_PADDING, GR_RESIZE_MENU);
gr_set_color_fast(&Color_bright_white);
gr_printf_menu(help_overlaylist[overlay_id].textlist.at(resolution_index).at(idx).x_coord, help_overlaylist[overlay_id].textlist.at(resolution_index).at(idx).y_coord,
+5
View File
@@ -130,6 +130,11 @@ void gameplay_help_init_control_line(int id, gameplay_help_section &thisHelp)
auto ci = &Control_config[id];
// do not draw if a mod has disabled this control --wookieejedi
if (ci->disabled) {
return;
}
buf[0] = 0;
strcpy_s(buf, ci->first.textify().c_str());
Loaded 100 of 1073 files, more files were not shown because too many files have changed in this diff. Show more