Compare commits

...
Author SHA1 Message Date
JohnAFernandez db5a90c955 Ok, that wasn't it. Try reloading UTC time
And getting rid of the workflow dispatch
2024-05-27 14:56:04 -04:00
JohnAFernandez 95f26ef625 account for 0 index 2024-05-27 14:50:13 -04:00
JohnAFernandez bc7654392a POSIX cron syntax 2024-05-27 14:45:55 -04:00
JohnAFernandez 760b035a3a Try again 2024-05-27 14:43:30 -04:00
JohnAFernandez ce2fd88c24 Try this cron expression for testing 2024-05-27 14:40:32 -04:00
JohnAFernandez 3d6c02ffe2 Temporary workflow dispatch 2024-05-27 14:32:08 -04:00
JohnAFernandez 2aae150981 Hopefully Fix coverity scanning 2024-05-27 14:28:03 -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
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
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 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
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 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
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
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
345 changed files with 7145 additions and 4498 deletions

No files matched your search

+14 -2
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-1ff82e8
steps:
- uses: actions/checkout@v1
name: Checkout
@@ -24,7 +24,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
@@ -269,6 +269,18 @@ 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
+14 -2
View File
@@ -44,7 +44,7 @@ jobs:
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
container: ghcr.io/scp-fs2open/linux_build:sha-1ff82e8
steps:
- uses: actions/checkout@v1
# checks-out your repository under $GITHUB_WORKSPACE, so your workflow can access it.
@@ -55,7 +55,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
@@ -339,6 +339,18 @@ 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
-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 }}
+14 -2
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-1ff82e8
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
@@ -282,6 +282,18 @@ 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
+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-1ff82e8
steps:
- uses: actions/checkout@v1
name: Checkout
+2 -2
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
@@ -22,7 +22,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-1ff82e8
steps:
- uses: actions/checkout@v1
name: Checkout
+14 -27
View File
@@ -2,14 +2,17 @@ name: Weekly Coverity Scan for Freespace Open
# adapted from code by "albert-github" on the doxygen repository
# many thanks for figuring this out first so it could be less painful for us!
# This mode is for testing
# keep this from running on everyone's fork
# if: github.ref == 'refs/heads/master'
#This mode is for testing
#on: [push, pull_request]
# In production, push on a specific schedule
on:
schedule:
- cron: "1 0 * * 5" # Run once per a week on Friday morning (midnight UTC, 4 AM EST), to avoid Coverity's submission limits
- cron: "57 18 * * *" # Run once per a week on Friday morning (4 AM EST), to avoid Coverity's submission limits
env:
QT_VERSION: 5.12.12
coverity_email: [email protected]
@@ -18,26 +21,17 @@ env:
jobs:
build:
name: Build FSO With Coverity Wrapper
runs-on: ${{ matrix.config.os }}
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/linux_build:sha-1ff82e8
strategy:
fail-fast: false
matrix:
config:
- { name: "GCC on ubuntu", os: ubuntu-latest, build_type: "Release" }
steps:
- name: Install Dependencies
run: |
sudo apt-get install ninja-build
sudo apt install cmake libsdl2-dev g++
sudo apt-get install libopenal-dev
sudo apt-get install -y libudev-dev
sudo apt-get install doxygen
sudo apt install graphviz
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v1
with:
submodules: recursive # `true` to checkout submodules, `recursive` to recursively checkout submodules
submodules: true # `true` to checkout submodules, `recursive` to recursively checkout submodules
# pipe results of wget to a log file because it's very verbose and rarely fails
- name: Install Coverity
@@ -51,17 +45,10 @@ jobs:
echo "$(pwd)/cov-scan/bin" >> $GITHUB_PATH
echo "NPROC=$(getconf _NPROCESSORS_ONLN)" >> $GITHUB_ENV
- name: Prepare Vulkan SDK
uses: humbletim/[email protected]
with:
vulkan-query-version: 1.3.204.0
vulkan-components: Vulkan-Headers, Vulkan-Loader
vulkan-use-cache: true
- name: Configure CMake for FSO
env:
CONFIGURATION: Release
compiler: gcc-5
CONFIGURATION: FastDebug
COMPILER: gcc-9
ENABLE_QTFRED: OFF
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
+3 -3
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
+5 -5
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,7 +41,7 @@ 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]
+2 -2
View File
@@ -6,8 +6,8 @@ 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_MINOR 3)
set_if_not_defined(FSO_VERSION_MAJOR 24)
set_if_not_defined(FSO_VERSION_MINOR 1)
set_if_not_defined(FSO_VERSION_BUILD 0)
# A numeric revision e.g. the CI build number
+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;
}
+2 -2
View File
@@ -597,8 +597,8 @@ 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 );
+2
View File
@@ -157,7 +157,9 @@ namespace AI {
Whackable_debris,
Whackable_asteroids,
Dynamic_goals_afterburn_hard,
Player_orders_afterburn_hard,
Hudsquadmsg_tactical_disarm_disable,
Align_to_target_when_guarding_still,
NUM_VALUES
};
+4
View File
@@ -625,8 +625,12 @@ 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 we've been through once already and are at the same place, force a move
if (saved_Mp && (saved_Mp == Mp))
{
+6 -6
View File
@@ -76,7 +76,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 +193,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 +213,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 +411,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 +541,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
@@ -1034,7 +1034,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) {
+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()
+41 -36
View File
@@ -1021,7 +1021,7 @@ void ai_level_init()
/**
* Check if object is a stealth ship
*/
bool is_object_stealth_ship(object* objp)
bool is_object_stealth_ship(const object *objp)
{
if (objp->type == OBJ_SHIP) {
if (Ships[objp->instance].flags[Ship::Ship_Flags::Stealth]) {
@@ -1109,7 +1109,7 @@ float get_skill_stealth_dot_scaler()
return 1.0f;
}
int ai_is_stealth_visible(object *viewer_objp, object *stealth_objp)
int ai_is_stealth_visible(const object *viewer_objp, const object *stealth_objp)
{
ship *shipp;
vec3d vec_to_stealth;
@@ -1905,7 +1905,7 @@ int Player_attacking_enabled = 1;
/**
* Determine whether an object is targetable within a nebula
*/
int object_is_targetable(object *target, ship *viewer)
bool object_is_targetable(const object *target, const ship *viewer)
{
// if target is ship, check if visible by team
if (target->type == OBJ_SHIP)
@@ -2413,7 +2413,7 @@ int find_nearby_threat(int objnum, int enemy_team_mask, float range, int *count)
/**
* Number of live turrets with target_objnum
*/
int num_turrets_attacking(object *turret_parent, int target_objnum)
int num_turrets_attacking(const object *turret_parent, int target_objnum)
{
ship_subsys *ss;
ship *shipp;
@@ -3515,6 +3515,7 @@ void ai_start_waypoints(object *objp, waypoint_list *wp_list, int wp_flags, int
aip->wp_index = start_index;
aip->wp_flags = wp_flags;
aip->mode = AIM_WAYPOINTS;
aip->submode_parm0 = start_index; // keep track of the start index because we need it for Fix_ai_path_order_bug
Assert(aip->active_goal != AI_ACTIVE_GOAL_DYNAMIC);
}
@@ -3636,7 +3637,7 @@ int Debug_k = 0;
*
* Return this value. Return value of 0.0f means no collision is possible.
*/
float compute_collision_time(vec3d *targpos, vec3d *targvel, vec3d *attackpos, float weapon_speed)
float compute_collision_time(const vec3d *targpos, const vec3d *targvel, const vec3d *attackpos, float weapon_speed)
{
vec3d vec_to_target;
float pos_dot_vel;
@@ -6305,7 +6306,7 @@ int ai_fire_primary_weapon(object *objp)
// threshold => max distance from pos to be considered "near"
//
// exit: number of ships within threshold units 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)
{
ship_obj *so;
object *ship_objp;
@@ -6476,7 +6477,7 @@ bool ai_select_secondary_weapon(object *objp, ship_weapon *swp, flagset<Weapon::
/**
* @return number of objects homing on object *target_objp
*/
int compute_num_homing_objects(object *target_objp)
int compute_num_homing_objects(const object *target_objp)
{
int count = 0;
@@ -6558,7 +6559,7 @@ float compute_incoming_payload(object *target_objp)
// OR: secondary los flag is set but no line of sight is availabe
// Note: If player is attacking a ship, that ship is allowed to fire at player. Otherwise, we get in a situation in which
// player is attacking a large ship, but that large ship is not defending itself with missiles.
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)
{
int num_homers = 0;
@@ -6574,8 +6575,8 @@ int check_ok_to_fire(int objnum, int target_objnum, weapon_info *wip, int second
if (The_mission.ai_profile->flags[AI::Profile_Flags::Require_exact_los] || wip->wi_flags[Weapon::Info_Flags::Require_exact_los]) {
//Check if th AI has Line of Sight and is allowed to fire
if (!check_los(objnum, target_objnum, 10.0f, -1, secondary_bank, turret)) {
return 0;
if (!check_los(objnum, target_objnum, 10.0f, -1, secondary_bank, firing_pos_global)) {
return false;
}
}
@@ -6589,14 +6590,14 @@ int check_ok_to_fire(int objnum, int target_objnum, weapon_info *wip, int second
// At Easy, 2/7...at Expert, 5/7
int t = ((Missiontime /(65536*10)) ^ target_objnum ^ 0x01) % (NUM_SKILL_LEVELS+2);
if (t > Ai_info[Ships[tobjp->instance].ai_index].ai_chance_to_use_missiles_on_plr) {
return 0;
return false;
}
}
int swarmers = 0;
if (wip->wi_flags[Weapon::Info_Flags::Swarm])
swarmers = 2; // Note, always want to be able to fire swarmers if no currently incident homers.
if (The_mission.ai_profile->max_allowed_player_homers[Game_skill_level] < num_homers + swarmers) {
return 0;
return false;
}
} else if (num_homers > 3) {
float incoming_payload;
@@ -6604,22 +6605,22 @@ int check_ok_to_fire(int objnum, int target_objnum, weapon_info *wip, int second
incoming_payload = compute_incoming_payload(&Objects[target_objnum]);
if (incoming_payload > tobjp->hull_strength) {
return 0;
return false;
}
}
}
}
return 1;
return true;
}
// --------------------------------------------------------------------------
// Returns true if *aip has a line of sight to its current target.
// threshold defines the minimum radius for an object to be considered relevant for LoS
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) {
//Do both checks over an XOR-Check for more detailed messages
int sources = (primary_bank != -1 ? 1 : 0) + (secondary_bank != -1 ? 1 : 0) + (turret != nullptr ? 1 : 0);
int sources = (primary_bank != -1 ? 1 : 0) + (secondary_bank != -1 ? 1 : 0) + (firing_pos_global != nullptr ? 1 : 0);
Assertion(sources >= 1, "Cannot check line of sight from a model with neither a primar bank, nor secondary bank nor a turret set as a source.");
Assertion(sources <= 1, "Cannot check line of sight from a model with more than one source set.");
@@ -6627,10 +6628,8 @@ bool check_los(int objnum, int target_objnum, float threshold, int primary_bank,
object* firing_ship = &Objects[objnum];
if (turret != nullptr) {
vec3d turret_fvec;
//It doesn't like not having an fvec output vector, so give it a dummy vector
ship_get_global_turret_gun_info(firing_ship, turret, &start, &turret_fvec, 1, nullptr);
if (firing_pos_global != nullptr) {
start = *firing_pos_global;
} else {
bool is_primary = secondary_bank == -1;
ship *shipp = &Ships[firing_ship->instance];
@@ -6942,7 +6941,7 @@ float ai_get_weapon_dist(ship_weapon *swp)
return MIN((Weapon_info[weapon_num].max_speed * Weapon_info[weapon_num].lifetime), Weapon_info[weapon_num].weapon_range);
}
float ai_get_weapon_speed(ship_weapon *swp)
float ai_get_weapon_speed(const ship_weapon *swp)
{
int bank_num, weapon_num;
@@ -6986,7 +6985,7 @@ weapon_info* ai_get_weapon(ship_weapon *swp)
// Also, stuff globals G_predicted_pos, G_collision_time and G_fire_pos.
// *pobjp object firing the weapon
// *eobjp object being fired upon
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)
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)
{
ship *shipp = &Ships[pobjp->instance];
float range_time;
@@ -10243,7 +10242,7 @@ void guard_object_was_hit(object *guard_objp, object *hitter_objp)
}
// don't attack if you can't see him
if ( awacs_get_level(hitter_objp, &Ships[aip->shipnum], 1) < 1 ) {
if ( awacs_get_level(hitter_objp, &Ships[aip->shipnum], true) < 1.0f ) {
// if he's a stealth and visible, but not targetable, ok to attack.
if ( is_object_stealth_ship(hitter_objp) ) {
if ( ai_is_stealth_visible(guard_objp, hitter_objp) != STEALTH_IN_FRUSTUM ) {
@@ -10893,14 +10892,14 @@ void ai_guard()
// Goal point is in front.
// If close to goal point, don't change direction, just change speed.
if (dist_to_goal_point > Pl_objp->radius + 10.0f) {
turn_towards_point(Pl_objp, &goal_point, NULL, 0.0f);
turn_towards_point(Pl_objp, &goal_point, nullptr, 0.0f);
}
set_accel_for_target_speed(Pl_objp, guard_objp->phys_info.speed + (dist_to_goal_point-40.0f)/20.0f);
}
} else {
if (dot_to_goal_point > 0.8f) {
turn_towards_point(Pl_objp, &goal_point, NULL, 0.0f);
turn_towards_point(Pl_objp, &goal_point, nullptr, 0.0f);
set_accel_for_target_speed(Pl_objp, guard_objp->phys_info.speed + dist_to_goal_point*0.1f);
} else {
set_accel_for_target_speed(Pl_objp, guard_objp->phys_info.speed - dist_to_goal_point*0.1f - 1.0f);
@@ -10909,10 +10908,14 @@ void ai_guard()
// consider guard object STILL
} else if (guard_objp->radius < 50.0f) {
if (dist_to_goal_point > 15.0f) {
turn_towards_point(Pl_objp, &goal_point, NULL, 0.0f);
turn_towards_point(Pl_objp, &goal_point, nullptr, 0.0f);
set_accel_for_target_speed(Pl_objp, (dist_to_goal_point-10.0f)/2.0f);
} else if (Pl_objp->phys_info.speed < 1.0f) {
turn_away_from_point(Pl_objp, &guard_objp->pos, 0.0f);
if (aip->ai_profile_flags[AI::Profile_Flags::Align_to_target_when_guarding_still]) {
turn_towards_point(Pl_objp, &guard_objp->pos, nullptr, 0.0f, &guard_objp->orient);
} else {
turn_away_from_point(Pl_objp, &guard_objp->pos, 0.0f);
}
}
// It's a big ship
} else if (dist_to_guardobj > MAX_GUARD_DIST + Pl_objp->radius + guard_objp->radius) {
@@ -12612,7 +12615,12 @@ int ai_formation()
if (aip->mode == AIM_WAYPOINTS) {
if (The_mission.ai_profile->flags[AI::Profile_Flags::Fix_ai_path_order_bug]){
// skip if wing leader has no waypoint order or a different waypoint list
if ((laip->mode != AIM_WAYPOINTS) || !(aip->wp_list == laip->wp_list)){
// ...or if it's a different start index or direction
if ( (laip->mode != AIM_WAYPOINTS)
|| (laip->wp_list != aip->wp_list)
|| (laip->submode_parm0 != aip->submode_parm0)
|| ((laip->wp_flags & WPF_BACKTRACK) != (aip->wp_flags & WPF_BACKTRACK))
) {
return 1;
}
}
@@ -13900,10 +13908,7 @@ int ai_acquire_depart_path(object *pl_objp, int parent_objnum, int allowed_path_
*/
void ai_bay_depart()
{
ai_info *aip;
int anchor_shipnum;
aip = &Ai_info[Ships[Pl_objp->instance].ai_index];
auto aip = &Ai_info[Ships[Pl_objp->instance].ai_index];
// if no path to follow, leave this mode
if ( aip->path_start < 0 ) {
@@ -13912,8 +13917,8 @@ void ai_bay_depart()
}
// check if parent ship valid; if not, abort depart
anchor_shipnum = ship_name_lookup(Parse_names[Ships[Pl_objp->instance].departure_anchor]);
if (anchor_shipnum < 0 || !ship_useful_for_departure(anchor_shipnum, Ships[Pl_objp->instance].departure_path_mask))
auto anchor_ship_entry = ship_registry_get(Parse_names[Ships[Pl_objp->instance].departure_anchor]);
if (!anchor_ship_entry || !ship_useful_for_departure(anchor_ship_entry->shipnum, Ships[Pl_objp->instance].departure_path_mask))
{
mprintf(("Aborting bay departure!\n"));
aip->mode = AIM_NONE;
@@ -13924,7 +13929,7 @@ void ai_bay_depart()
ai_manage_bay_doors(Pl_objp, aip, false);
if ( Ships[anchor_shipnum].bay_doors_status != MA_POS_READY )
if ( anchor_ship_entry->shipp()->bay_doors_status != MA_POS_READY )
return;
// follow the path to the final point
@@ -15812,7 +15817,7 @@ void maybe_set_dynamic_chase(ai_info *aip, int hitter_objnum)
}
// only set as target if can be targeted.
if (awacs_get_level(&Objects[hitter_objnum], &Ships[aip->shipnum], 1) < 1) {
if (awacs_get_level(&Objects[hitter_objnum], &Ships[aip->shipnum], true) < 1.0f) {
return;
}
+3
View File
@@ -751,6 +751,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
+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;
}
+146 -195
View File
@@ -118,7 +118,7 @@ void turret_instance_find_world_orient(matrix* out_mat, int model_instance_num,
* @param tpos Turret initial position
* @param dist Distance from turret to center point of object
*
* @return 1 if objp is in fov of the specified turret. Otherwise return 0.
* @return true if objp is in fov of the specified turret. Otherwise return false.
*/
bool object_in_turret_fov(const object *objp, const ship_subsys *ss, const vec3d *tvec, const vec3d *tpos, float dist)
{
@@ -175,9 +175,9 @@ bool object_in_turret_fov(const object *objp, const ship_subsys *ss, const vec3d
* @param bomb_objp Bomb specified
* @param ship_objp Ship specified
*
* @return 1 if bomb_objp is headed towards ship_objp
* @return true if bomb_objp is headed towards ship_objp
*/
int bomb_headed_towards_ship(object *bomb_objp, object *ship_objp)
bool bomb_headed_towards_ship(const object *bomb_objp, const object *ship_objp)
{
float dot;
vec3d bomb_to_ship_vector;
@@ -185,11 +185,7 @@ int bomb_headed_towards_ship(object *bomb_objp, object *ship_objp)
vm_vec_normalized_dir(&bomb_to_ship_vector, &ship_objp->pos, &bomb_objp->pos);
dot = vm_vec_dot(&bomb_objp->orient.vec.fvec, &bomb_to_ship_vector);
if ( dot > 0 ) {
return 1;
}
return 0;
return ( dot > 0 );
}
// Set active weapon for turret
@@ -201,7 +197,7 @@ int bomb_headed_towards_ship(object *bomb_objp, object *ship_objp)
* @note All non-negative return values are expressed in what I like to call "widx"s.
* @return -1 if unable to find a weapon for the target at all.
*/
int turret_select_best_weapon(ship_subsys *turret, object * /*target*/)
int turret_select_best_weapon(const ship_subsys *turret, const object * /*target*/)
{
//TODO: Fill this out with extraodinary gun-picking algorithms
if(turret->weapons.num_primary_banks > 0)
@@ -335,7 +331,7 @@ bool turret_weapon_has_subtype(const ship_weapon *swp, int subtype)
*
* @return a pointer to the Weapon_info for weapon_num
*/
weapon_info *get_turret_weapon_wip(ship_weapon *swp, int weapon_num)
const weapon_info *get_turret_weapon_wip(const ship_weapon *swp, int weapon_num)
{
Assert(weapon_num < MAX_SHIP_WEAPONS);
Assert(weapon_num >= 0);
@@ -352,7 +348,7 @@ weapon_info *get_turret_weapon_wip(ship_weapon *swp, int weapon_num)
return &Weapon_info[wi_index];
}
int get_turret_weapon_next_fire_stamp(ship_weapon *swp, int weapon_num)
int get_turret_weapon_next_fire_stamp(const ship_weapon *swp, int weapon_num)
{
Assert(weapon_num < MAX_SHIP_WEAPONS);
Assert(weapon_num >= 0);
@@ -379,7 +375,7 @@ void set_turret_weapon_next_fire_stamp(ship_weapon *swp, int weapon_num, int del
*
* @todo This function is kinda slow
*/
float longest_turret_weapon_range(ship_weapon *swp)
float longest_turret_weapon_range(const ship_weapon *swp)
{
float longest_range_so_far = 0.0f;
float weapon_range;
@@ -770,10 +766,10 @@ void evaluate_obj_as_target(object *objp, eval_enemy_obj_struct *eeo)
* @param laser_flag
* @param missile_flag
*/
int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subsys, int enemy_team_mask, vec3d *tpos, vec3d *tvec, int current_enemy, bool big_only_flag, bool small_only_flag, bool tagged_only_flag, bool beam_flag, bool flak_flag, bool laser_flag, bool missile_flag)
int get_nearest_turret_objnum(int turret_parent_objnum, const ship_subsys *turret_subsys, int enemy_team_mask, const vec3d *tpos, const vec3d *tvec, int current_enemy, bool big_only_flag, bool small_only_flag, bool tagged_only_flag, bool beam_flag, bool flak_flag, bool laser_flag, bool missile_flag)
{
eval_enemy_obj_struct eeo;
ship_weapon *swp = &turret_subsys->weapons;
auto swp = &turret_subsys->weapons;
// list of stuff to go thru
ship_obj *so;
@@ -1067,7 +1063,7 @@ DCF_BOOL(use_parent_target, Use_parent_target)
* @param tvec Forward vector of turret (world coords)
* @param current_enemy Objnum of current turret target
*/
int find_turret_enemy(ship_subsys *turret_subsys, int objnum, vec3d *tpos, vec3d *tvec, int current_enemy)
int find_turret_enemy(const ship_subsys *turret_subsys, int objnum, const vec3d *tpos, const vec3d *tvec, int current_enemy)
{
int enemy_team_mask, enemy_objnum;
ship_info *sip;
@@ -1188,8 +1184,6 @@ void ship_get_global_turret_info(const object *objp, const model_subsystem *tp,
model_instance_local_to_global_dir(gvec, &tp->turret_norm, model_instance_num, tp->subobj_num, &objp->orient, true);
}
void turret_ai_update_aim(ai_info *aip, object *En_Objp, ship_subsys *ss);
/**
* Given an object and a turret on that object, return the actual firing point of the gun and its normal.
*
@@ -1200,86 +1194,44 @@ void turret_ai_update_aim(ai_info *aip, object *En_Objp, ship_subsys *ss);
* @param objp Pointer to object
* @param ssp Pointer to turret subsystem
* @param gpos Absolute position of gun firing point
* @param avg_origin Use virtual gun pos corresponding to the average of the firing points
* @param gvec Vector from *gpos to *targetp
* @param use_angles Use current angles
* @param targetp Pointer to target object
* @param targetp Absolute position of target object
*/
void ship_get_global_turret_gun_info(object *objp, ship_subsys *ssp, vec3d *gpos, vec3d *gvec, int use_angles, vec3d *targetp)
void ship_get_global_turret_gun_info(const object *objp, const ship_subsys *ssp, vec3d *gpos, bool avg_origin, vec3d *gvec, bool use_angles, const vec3d *targetp)
{
vec3d * gun_pos;
vec3d *gun_pos;
model_subsystem *tp = ssp->system_info;
polymodel_instance *pmi = model_get_instance(Ships[objp->instance].model_instance_num);
polymodel *pm = model_get(pmi->model_num);
gun_pos = &tp->turret_firing_point[ssp->turret_next_fire_pos % tp->turret_num_firing_points];
vec3d avg_gun_pos;
if (avg_origin) {
vm_vec_avg_n(&avg_gun_pos, tp->turret_num_firing_points, tp->turret_firing_point);
gun_pos = &avg_gun_pos;
} else {
gun_pos = &tp->turret_firing_point[ssp->turret_next_fire_pos % tp->turret_num_firing_points];
}
model_instance_local_to_global_point(gpos, gun_pos, pm, pmi, tp->turret_gun_sobj, &objp->orient, &objp->pos);
// we might not need to calculate this
if (!gvec)
return;
if (use_angles) {
model_instance_local_to_global_dir(gvec, &tp->turret_norm, pm, pmi, tp->turret_gun_sobj, &objp->orient);
} else if (tp->flags[Model::Subsystem_Flags::Share_fire_direction]) {
vec3d avg, tmp_pos, tmp_target, enemy_point, turret_norm;
vm_vec_avg_n(&avg, tp->turret_num_firing_points, tp->turret_firing_point);
model_instance_local_to_global_point(&tmp_pos, &avg, pm, pmi, tp->turret_gun_sobj, &objp->orient, &objp->pos);
if (targetp == nullptr) {
ship* shipp = &Ships[Objects[ssp->parent_objnum].instance];
Assertion(ssp->turret_enemy_objnum >= 0, "The turret enemy object number %d for %s on ship name %s is invalid.", ssp->turret_enemy_objnum, ssp->sub_name, shipp->ship_name);
object *lep = &Objects[ssp->turret_enemy_objnum];
int best_weapon_tidx = turret_select_best_weapon(ssp, lep);
//This turret doesn't have any good weapons
if (best_weapon_tidx < 0)
return;
weapon_info *wip = get_turret_weapon_wip(&ssp->weapons, best_weapon_tidx);
float weapon_system_strength = ship_get_subsystem_strength(shipp, SUBSYSTEM_WEAPONS);
turret_ai_update_aim(&Ai_info[shipp->ai_index], &Objects[ssp->turret_enemy_objnum], ssp);
if ((ssp->targeted_subsys != nullptr) && !(ssp->flags[Ship::Subsystem_Flags::No_SS_targeting])) {
vm_vec_unrotate(&enemy_point, &ssp->targeted_subsys->system_info->pnt, &Objects[ssp->turret_enemy_objnum].orient);
vm_vec_add2(&enemy_point, &ssp->last_aim_enemy_pos);
} else {
if ((lep->type == OBJ_SHIP) && (Ship_info[Ships[lep->instance].ship_info_index].is_big_or_huge())) {
// the turret norm here is from the perspective of the base submodel, not the gun submodel
model_instance_local_to_global_dir(&turret_norm, &tp->turret_norm, pm, pmi, pm->submodel[tp->subobj_num].parent, &objp->orient);
ai_big_pick_attack_point_turret(lep, ssp, &tmp_pos, &turret_norm, &enemy_point, MIN(wip->max_speed * wip->lifetime, wip->weapon_range), tp->turret_fov);
}
else {
enemy_point = ssp->last_aim_enemy_pos;
}
}
vec3d target_moving_direction = ssp->last_aim_enemy_vel;
//Try to guess where the enemy will be, and store that spot in predicted_enemy_pos
if (The_mission.ai_profile->flags[AI::Profile_Flags::Use_additive_weapon_velocity]) {
vm_vec_scale_sub2(&target_moving_direction, &objp->phys_info.vel, wip->vel_inherit_amount);
}
set_predicted_enemy_pos_turret(&tmp_target, &tmp_pos, objp, &enemy_point, &target_moving_direction, wip->max_speed, ssp->turret_time_enemy_in_range * (weapon_system_strength + 1.0f) / 2.0f);
} else {
tmp_target = *targetp;
}
vm_vec_normalized_dir(gvec, &tmp_target, &tmp_pos);
} else {
//vector gun_pos2;
//vm_vec_add(&gun_pos2, gpos, gun_pos);
Assertion(targetp != nullptr, "The targetp parameter must not be null here!");
vm_vec_normalized_dir(gvec, targetp, gpos);
}
// per firingpoint based changes go here for turrets
}
/**
* Update turret aiming data based on max turret aim update delay
*/
void turret_ai_update_aim(ai_info *aip, object *En_Objp, ship_subsys *ss)
void turret_ai_update_aim(const ai_info *aip, const object *En_Objp, ship_subsys *ss)
{
if (Missiontime >= ss->next_aim_pos_time)
{
@@ -1294,26 +1246,15 @@ void turret_ai_update_aim(ai_info *aip, object *En_Objp, ship_subsys *ss)
}
}
/**
* Rotate a turret towards an enemy.
*
* Some obscure model thing only John Slagel knows about.
* Sets predicted enemy position.
* Sets predicted enemy position. Previously done at the beginning of aifft_rotate_turret.
* If the turret (*ss) has a subsystem targeted, the subsystem is used as the predicted point.
*
* @return TRUE if caller should use angles in subsequent rotations.
*/
int aifft_rotate_turret(object *objp, ship *shipp, ship_subsys *ss, object *lep, vec3d *predicted_enemy_pos, vec3d *gvec)
void aifft_update_predicted_enemy_pos(const object *objp, const ship *shipp, ship_subsys *ss, const vec3d *global_gun_pos, const vec3d *global_gun_vec, const object *lep, vec3d *predicted_enemy_pos)
{
int ret_val __UNUSED = 0; // to be used in future, see comment @ end of function
auto pmi = model_get_instance(shipp->model_instance_num);
auto pm = model_get(pmi->model_num);
if (ss->turret_enemy_objnum != -1) {
model_subsystem *tp = ss->system_info;
vec3d gun_pos, gun_vec, target_vel;
//float weapon_speed;
vec3d target_vel;
float weapon_system_strength;
//HACK HACK HACK -WMC
//This should use the best weapon variable
@@ -1322,15 +1263,13 @@ int aifft_rotate_turret(object *objp, ship *shipp, ship_subsys *ss, object *lep,
//This turret doesn't have any good weapons
if (best_weapon_tidx < 0)
return 0;
return;
weapon_info *wip = get_turret_weapon_wip(&ss->weapons, best_weapon_tidx);
auto wip = get_turret_weapon_wip(&ss->weapons, best_weapon_tidx);
// weapon_system_strength scales time enemy in range in 0..1. So, the lower this is, the worse the aiming will be.
weapon_system_strength = ship_get_subsystem_strength(shipp, SUBSYSTEM_WEAPONS);
ship_get_global_turret_info(objp, tp, &gun_pos, &gun_vec);
//Update "known" position and velocity of target. Only matters if max_aim_update_delay is set.
turret_ai_update_aim(&Ai_info[shipp->ai_index], &Objects[ss->turret_enemy_objnum], ss);
@@ -1344,7 +1283,7 @@ int aifft_rotate_turret(object *objp, ship *shipp, ship_subsys *ss, object *lep,
}
} else {
if ((lep->type == OBJ_SHIP) && (Ship_info[Ships[lep->instance].ship_info_index].is_big_or_huge())) {
ai_big_pick_attack_point_turret(lep, ss, &gun_pos, &gun_vec, &enemy_point, tp->turret_fov, MIN(wip->max_speed * wip->lifetime, wip->weapon_range));
ai_big_pick_attack_point_turret(lep, ss, global_gun_pos, global_gun_vec, &enemy_point, tp->turret_fov, MIN(wip->max_speed * wip->lifetime, wip->weapon_range));
} else {
enemy_point = ss->last_aim_enemy_pos;
}
@@ -1357,25 +1296,13 @@ int aifft_rotate_turret(object *objp, ship *shipp, ship_subsys *ss, object *lep,
vm_vec_scale_sub2(&target_vel, &objp->phys_info.vel, wip->vel_inherit_amount);
}
if (tp->flags[Model::Subsystem_Flags::Turret_distant_firepoint] || Always_use_distant_firepoints) {
//The firing point of this turret is so far away from the its center that we should consider this for firing calculations
//This will do the enemy position prediction based on their relative position and speed to the firing point, not the turret center.
vec3d temp;
ship_get_global_turret_gun_info(objp, ss, &gun_pos, &temp, 1, nullptr);
}
if (IS_VEC_NULL(&The_mission.gravity) || wip->gravity_const == 0.0f)
set_predicted_enemy_pos_turret(predicted_enemy_pos, &gun_pos, objp, &enemy_point, &target_vel, wip->max_speed, ss->turret_time_enemy_in_range * (weapon_system_strength + 1.0f)/2.0f);
set_predicted_enemy_pos_turret(predicted_enemy_pos, global_gun_pos, objp, &enemy_point, &target_vel, wip->max_speed, ss->turret_time_enemy_in_range * (weapon_system_strength + 1.0f)/2.0f);
else {
vec3d shoot_vec;
vec3d gravity_vec = The_mission.gravity * wip->gravity_const;
if (physics_lead_ballistic_trajectory(&gun_pos, &enemy_point, &target_vel, wip->max_speed, &gravity_vec, &shoot_vec)) {
*predicted_enemy_pos = gun_pos + shoot_vec * 1000.0f;
} else {
if ((ss->system_info->flags[Model::Subsystem_Flags::Turret_reset_idle]) && (timestamp_elapsed(ss->rotation_timestamp))) {
ret_val = model_rotate_gun(objp, pm, pmi, ss, predicted_enemy_pos, true);
}
return ret_val;
if (physics_lead_ballistic_trajectory(global_gun_pos, &enemy_point, &target_vel, wip->max_speed, &gravity_vec, &shoot_vec)) {
*predicted_enemy_pos = *global_gun_pos + shoot_vec * 1000.0f;
}
}
@@ -1387,36 +1314,54 @@ int aifft_rotate_turret(object *objp, ship *shipp, ship_subsys *ss, object *lep,
// Add to predicted_enemy_pos value in .45 to 1.5x radius of enemy ship, so will often miss, but not by a huge amount.
vm_vec_scale_add2(predicted_enemy_pos, &rand_vec, (1.0f - weapon_system_strength)*1.5f * lep->radius);
}
}
}
/**
* Rotate a turret towards an enemy.
*
* Some obscure model thing only John Slagel knows about.
*
* @return TRUE if caller should use angles in subsequent rotations.
*/
bool aifft_rotate_turret(const object *objp, const ship *shipp, ship_subsys *ss, const vec3d *global_gun_pos, const vec3d *global_gun_vec, const vec3d *predicted_enemy_pos)
{
bool ret_val __UNUSED = false; // to be used in future, see comment @ end of function
auto pmi = model_get_instance(shipp->model_instance_num);
auto pm = model_get(pmi->model_num);
if (ss->turret_enemy_objnum != -1) {
model_subsystem *tp = ss->system_info;
//Get the normalized dir between the turret and the predicted enemy position.
//If the dot product is smaller than or equal to the turret's FOV, try and point the gun at it.
vec3d v2e;
vm_vec_normalized_dir(&v2e, predicted_enemy_pos, &gun_pos);
vm_vec_normalized_dir(&v2e, predicted_enemy_pos, global_gun_pos);
bool in_fov;
in_fov = turret_fov_test(ss, gvec, &v2e);
in_fov = turret_fov_test(ss, global_gun_vec, &v2e);
if (in_fov) {
ret_val = model_rotate_gun(objp, pm, pmi, ss, predicted_enemy_pos);
} else if ((tp->flags[Model::Subsystem_Flags::Turret_reset_idle]) &&(timestamp_elapsed(ss->rotation_timestamp))) {
ret_val = model_rotate_gun(objp, pm, pmi, ss, predicted_enemy_pos, true);
ret_val = model_rotate_gun(objp, pm, pmi, ss, nullptr);
}
} else if ((ss->system_info->flags[Model::Subsystem_Flags::Turret_reset_idle]) && (timestamp_elapsed(ss->rotation_timestamp))) {
ret_val = model_rotate_gun(objp, pm, pmi, ss, predicted_enemy_pos, true);
ret_val = model_rotate_gun(objp, pm, pmi, ss, nullptr);
}
// by default "ret_val" should be set to 1 for multi-part turrets, and 0 for single-part turrets
// but we need to keep retail behavior by default, which means always returning 0 unless a special
// by default "ret_val" should be set to true for multi-part turrets, and false for single-part turrets
// but we need to keep retail behavior by default, which means always returning false unless a special
// flag is used. the "ret_val" stuff is here is needed/wanted at a later date however.
//return ret_val;
// return 0 by default (to preserve retail behavior) but allow for a per-subsystem option
// return false by default (to preserve retail behavior) but allow for a per-subsystem option
// for using the turret normals for firing
if (ss->system_info->flags[Model::Subsystem_Flags::Fire_on_normal])
return 1;
return true;
return 0;
return false;
}
/**
@@ -1424,7 +1369,7 @@ int aifft_rotate_turret(object *objp, ship *shipp, ship_subsys *ss, object *lep,
*
* @return Dot product of vector from point abs_gunposp to *enemy_subsysp, if hittable
*/
float aifft_compute_turret_dot(object *objp, object *enemy_objp, vec3d *abs_gunposp, ship_subsys *turret_subsysp, ship_subsys *enemy_subsysp)
float aifft_compute_turret_dot(const object *objp, const object *enemy_objp, const vec3d *abs_gunposp, const ship_subsys *turret_subsysp, const ship_subsys *enemy_subsysp)
{
float dot_out;
vec3d subobj_pos, vector_out;
@@ -1432,7 +1377,7 @@ float aifft_compute_turret_dot(object *objp, object *enemy_objp, vec3d *abs_gunp
vm_vec_unrotate(&subobj_pos, &enemy_subsysp->system_info->pnt, &enemy_objp->orient);
vm_vec_add2(&subobj_pos, &enemy_objp->pos);
if (ship_subsystem_in_sight(enemy_objp, enemy_subsysp, abs_gunposp, &subobj_pos, 1, &dot_out, &vector_out)) {
if (ship_subsystem_in_sight(enemy_objp, enemy_subsysp, abs_gunposp, &subobj_pos, true, &dot_out, &vector_out)) {
vec3d turret_norm;
model_instance_local_to_global_dir(&turret_norm, &turret_subsysp->system_info->turret_norm, Ships[objp->instance].model_instance_num, turret_subsysp->system_info->subobj_num, &objp->orient, true);
@@ -1486,7 +1431,7 @@ DCF(mf, "Adjusts the maximum number of tries an AI may do when trying to pick a
*
* @return Dot product from turret to subsystem in *dot_out
*/
ship_subsys *aifft_find_turret_subsys(object *objp, ship_subsys *ssp, object *enemy_objp, float *dot_out)
ship_subsys *aifft_find_turret_subsys(const object *objp, const ship_subsys *ssp, const vec3d *global_gun_pos, const object *enemy_objp, float *dot_out)
{
ship *eshipp, *shipp;
ship_info *esip;
@@ -1503,10 +1448,6 @@ ship_subsys *aifft_find_turret_subsys(object *objp, ship_subsys *ssp, object *en
float best_dot = 0.0f;
*dot_out = best_dot;
// Compute absolute gun position.
vec3d abs_gun_pos;
ship_get_global_turret_info(objp, ssp->system_info, &abs_gun_pos, nullptr);
// Only pick a turret to attack on large ships.
if (!esip->is_big_or_huge())
return best_subsysp;
@@ -1572,7 +1513,7 @@ ship_subsys *aifft_find_turret_subsys(object *objp, ship_subsys *ssp, object *en
}
for(idx=offset; idx<aifft_list_size; idx+=stride){
dot = aifft_compute_turret_dot(objp, enemy_objp, &abs_gun_pos, ssp, aifft_list[idx]);
dot = aifft_compute_turret_dot(objp, enemy_objp, global_gun_pos, ssp, aifft_list[idx]);
if ((dot - dot_fov_modifier)* aifft_rank[idx] > best_dot) {
best_dot = (dot - dot_fov_modifier)*aifft_rank[idx];
@@ -1587,34 +1528,17 @@ ship_subsys *aifft_find_turret_subsys(object *objp, ship_subsys *ssp, object *en
}
/**
* @return !0 if the specified target should scan for a new target, otherwise return 0
* @return true if the specified target should scan for a new target, otherwise return false
*/
int turret_should_pick_new_target(ship_subsys *turret)
bool turret_should_pick_new_target(ship_subsys *turret)
{
// int target_type;
if ( timestamp_elapsed(turret->turret_next_enemy_check_stamp) ) {
return 1;
}
/*
if ( turret->turret_enemy_objnum == -1 ) {
return 1;
}
target_type = Objects[turret->turret_enemy_objnum].type;
if ( (target_type != OBJ_SHIP) && (target_type != OBJ_ASTEROID) ) {
return 1;
}
*/
return 0;
return timestamp_elapsed(turret->turret_next_enemy_check_stamp);
}
/**
* Set the next fire timestamp for a turret, based on weapon type and ai class
*/
void turret_set_next_fire_timestamp(int weapon_num, weapon_info *wip, ship_subsys *turret, ai_info *aip)
void turret_set_next_fire_timestamp(int weapon_num, const weapon_info *wip, ship_subsys *turret, const ai_info *aip)
{
Assert(weapon_num < MAX_SHIP_WEAPONS);
float wait = 1000.0f;
@@ -1727,13 +1651,13 @@ void turret_set_next_fire_timestamp(int weapon_num, weapon_info *wip, ship_subsy
/**
* Decide if a turret should launch an aspect seeking missile
*/
int turret_should_fire_aspect(ship_subsys *turret, weapon_info *wip, bool in_sight)
bool turret_should_fire_aspect(const ship_subsys *turret, const weapon_info *wip, bool in_sight)
{
if ( in_sight && (turret->turret_time_enemy_in_range >= MIN(wip->min_lock_time,AICODE_TURRET_MAX_TIME_IN_RANGE)) ) {
return 1;
return true;
}
return 0;
return false;
}
/**
@@ -1755,9 +1679,9 @@ void turret_update_enemy_in_range(ship_subsys *turret, float seconds)
/**
* Fire a weapon from a turret
*/
bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum, vec3d *turret_pos, vec3d *firing_vec, vec3d *predicted_pos = nullptr, float flak_range_override = 100.0f, bool play_sound = true)
bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum, const vec3d *orig_firing_pos, const vec3d *orig_firing_vec, const vec3d *predicted_pos = nullptr, float flak_range_override = 100.0f, bool play_sound = true)
{
matrix turret_orient;
matrix firing_orient;
int weapon_objnum;
ai_info *parent_aip;
ship *parent_ship;
@@ -1819,16 +1743,21 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
}
#endif
if (check_ok_to_fire(parent_objnum, turret->turret_enemy_objnum, wip, -1, turret)) {
if (check_ok_to_fire(parent_objnum, turret->turret_enemy_objnum, wip, -1, orig_firing_pos)) {
auto turret_enemy_objp = (turret->turret_enemy_objnum >= 0) ? &Objects[turret->turret_enemy_objnum] : nullptr;
ship_weapon* swp = &turret->weapons;
turret->turret_last_fire_direction = *firing_vec;
turret->turret_last_fire_direction = *orig_firing_vec;
if (turret->turret_inaccuracy > 0.0f)
vm_vec_random_cone(firing_vec, firing_vec, turret->turret_inaccuracy);
const vec3d *firing_vec = orig_firing_vec;
vec3d firing_vec_buf;
vm_vector_2_matrix(&turret_orient, firing_vec, nullptr, nullptr);
if (turret->turret_inaccuracy > 0.0f) {
vm_vec_random_cone(&firing_vec_buf, firing_vec, turret->turret_inaccuracy);
firing_vec = &firing_vec_buf;
}
vm_vector_2_matrix(&firing_orient, firing_vec, nullptr, nullptr);
// grab and set some burst data before turret_set_next_fire_timestamp wipes it
int old_burst_seed = swp->burst_seed[weapon_num];
@@ -2007,11 +1936,15 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
}
}
}
vec3d firing_pos_buf;
const vec3d *firing_pos = &firing_pos_buf;
// zookeeper - Firepoints should cycle normally between shots,
// so we need to get the position info separately for each shot
ship_get_global_turret_gun_info(&Objects[parent_objnum], turret, turret_pos, firing_vec, 1, nullptr);
ship_get_global_turret_gun_info(&Objects[parent_objnum], turret, &firing_pos_buf, false, nullptr, true, nullptr);
weapon_objnum = weapon_create( turret_pos, &turret_orient, turret_weapon_class, parent_objnum, -1, 1, 0,0.0f, turret);
weapon_objnum = weapon_create(firing_pos, &firing_orient, turret_weapon_class, parent_objnum, -1, 1, 0, 0.0f, turret);
weapon_set_tracking_info(weapon_objnum, parent_objnum, turret->turret_enemy_objnum, 1, turret->targeted_subsys);
//nprintf(("AI", "Turret_time_enemy_in_range = %7.3f\n", ss->turret_time_enemy_in_range));
@@ -2043,7 +1976,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
if(predicted_pos != NULL)
{
// pick a firing range so that it detonates properly
flak_pick_range(objp, turret_pos, predicted_pos, ship_get_subsystem_strength(parent_ship, SUBSYSTEM_WEAPONS));
flak_pick_range(objp, firing_pos, predicted_pos, ship_get_subsystem_strength(parent_ship, SUBSYSTEM_WEAPONS));
// determine what that range was
flak_range = flak_get_range(objp);
@@ -2056,7 +1989,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
// do mflash if the weapon has it
if (wip->muzzle_flash >= 0) {
mflash_create(turret_pos, firing_vec, &Objects[parent_ship->objnum].phys_info, wip->muzzle_flash);
mflash_create(firing_pos, firing_vec, &Objects[parent_ship->objnum].phys_info, wip->muzzle_flash);
}
// in multiplayer (and the master), then send a turret fired packet.
@@ -2075,7 +2008,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
if ( play_sound && wip->launch_snd.isValid() ) {
// Don't play turret firing sound if turret sits on player ship... it gets annoying.
if ( parent_objnum != OBJ_INDEX(Player_obj) || (turret->flags[Ship::Subsystem_Flags::Play_sound_for_player]) ) {
snd_play_3d( gamesnd_get_game_sound(wip->launch_snd), turret_pos, &View_position );
snd_play_3d( gamesnd_get_game_sound(wip->launch_snd), firing_pos, &View_position );
}
}
}
@@ -2107,7 +2040,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
void turret_swarm_fire_from_turret(turret_swarm_info *tsi)
{
int weapon_objnum;
matrix turret_orient;
matrix firing_orient;
vec3d turret_pos, turret_fvec;
// parent not alive, quick out.
@@ -2120,7 +2053,7 @@ void turret_swarm_fire_from_turret(turret_swarm_info *tsi)
tsi->turret->turret_next_fire_pos = tsi->weapon_num;
// change firing point
ship_get_global_turret_gun_info(&Objects[tsi->parent_objnum], tsi->turret, &turret_pos, &turret_fvec, 1, NULL);
ship_get_global_turret_gun_info(&Objects[tsi->parent_objnum], tsi->turret, &turret_pos, false, &turret_fvec, true, nullptr);
tsi->turret->turret_next_fire_pos++;
//check if this really is a swarm. If not, how the hell did it get here?
@@ -2135,11 +2068,11 @@ void turret_swarm_fire_from_turret(turret_swarm_info *tsi)
turret_fvec = tsi->turret->turret_last_fire_direction;
}
// make turret_orient from turret_fvec -- turret->turret_last_fire_direction
vm_vector_2_matrix(&turret_orient, &turret_fvec, NULL, NULL);
// make firing_orient from turret_fvec -- turret->turret_last_fire_direction
vm_vector_2_matrix(&firing_orient, &turret_fvec, NULL, NULL);
// create weapon and homing info
weapon_objnum = weapon_create(&turret_pos, &turret_orient, tsi->weapon_class, tsi->parent_objnum, -1, 1, 0, 0.0f, tsi->turret);
weapon_objnum = weapon_create(&turret_pos, &firing_orient, tsi->weapon_class, tsi->parent_objnum, -1, 1, 0, 0.0f, tsi->turret);
weapon_set_tracking_info(weapon_objnum, tsi->parent_objnum, tsi->target_objnum, 1, tsi->target_subsys);
// do other cool stuff if weapon is created.
@@ -2198,7 +2131,7 @@ int Num_turrets_fired = 0;
* all turret movement and resetting when idle
*/
extern int Nebula_sec_range;
void ai_turret_execute_behavior(ship *shipp, ship_subsys *ss)
void ai_turret_execute_behavior(const ship *shipp, ship_subsys *ss)
{
float weapon_firing_range;
float weapon_min_range; // *Weapon minimum firing range -Et1
@@ -2282,12 +2215,21 @@ void ai_turret_execute_behavior(ship *shipp, ship_subsys *ss)
objp = &Objects[shipp->objnum];
Assert(objp->type == OBJ_SHIP);
// Use the turret info for all guns, not one gun in particular.
vec3d gvec, gpos;
ship_get_global_turret_info(objp, tp, &gpos, &gvec);
vec3d global_gun_pos, global_gun_vec;
if (tp->flags[Model::Subsystem_Flags::Turret_distant_firepoint] || Always_use_distant_firepoints) {
//The firing point of this turret is so far away from the its center that we should consider this for firing calculations
//This will do the enemy position prediction based on their relative position and speed to the firing point, not the turret center.
ship_get_global_turret_gun_info(objp, ss, &global_gun_pos, false, &global_gun_vec, true, nullptr);
} else {
// Use the turret info for all guns, not one gun in particular.
ship_get_global_turret_info(objp, tp, &global_gun_pos, &global_gun_vec);
}
// Update predicted enemy position. This used to be done in aifft_rotate_turret
aifft_update_predicted_enemy_pos(objp, shipp, ss, &global_gun_pos, &global_gun_vec, lep, &predicted_enemy_pos);
// Rotate the turret even if time hasn't elapsed, since it needs to turn to face its target.
int use_angles = aifft_rotate_turret(objp, shipp, ss, lep, &predicted_enemy_pos, &gvec);
bool use_angles = aifft_rotate_turret(objp, shipp, ss, &global_gun_pos, &global_gun_vec, &predicted_enemy_pos);
// Multiplayer clients are now able to try to track their targets and also reset to their idle positions.
// But everything after this point is turret firing, so we need to bail here.
@@ -2311,18 +2253,20 @@ void ai_turret_execute_behavior(ship *shipp, ship_subsys *ss)
float dist_to_enemy = 0.0f;
if (lep) {
if (The_mission.ai_profile->flags[AI::Profile_Flags::Turrets_ignore_target_radius])
dist_to_enemy = MAX(0, vm_vec_normalized_dir(&v2e, &predicted_enemy_pos, &gpos));
dist_to_enemy = MAX(0, vm_vec_normalized_dir(&v2e, &predicted_enemy_pos, &global_gun_pos));
else
dist_to_enemy = MAX(0, vm_vec_normalized_dir(&v2e, &predicted_enemy_pos, &gpos) - lep->radius);
dist_to_enemy = MAX(0, vm_vec_normalized_dir(&v2e, &predicted_enemy_pos, &global_gun_pos) - lep->radius);
}
// count the number of enemies, in case we have a spawning weapon
int num_ships_nearby = num_nearby_fighters(iff_get_attackee_mask(obj_team(objp)), &gpos, 1500.0f);
int num_ships_nearby = num_nearby_fighters(iff_get_attackee_mask(obj_team(objp)), &global_gun_pos, 1500.0f);
// some flags considering there may be different weapon types on this turret
bool we_did_non_spawning_logic = false;
bool tentative_return = false;
float turret_barrel_length = -1.0f;
//WMC - go through all valid weapons. Fire spawns if there are any.
int valid_weapons[MAX_SHIP_WEAPONS];
int num_valid = 0;
@@ -2354,7 +2298,7 @@ void ai_turret_execute_behavior(ship *shipp, ship_subsys *ss)
if ( (wip->wi_flags[Weapon::Info_Flags::Spawn]) && !(wip->wi_flags[Weapon::Info_Flags::Smart_spawn]) )
{
if (( num_ships_nearby >= 3 ) || ((num_ships_nearby >= 2) && (frand() < 0.1f))) {
turret_fire_weapon(i, ss, parent_objnum, &gpos, &ss->turret_last_fire_direction);
turret_fire_weapon(i, ss, parent_objnum, &global_gun_pos, &ss->turret_last_fire_direction);
} else {
// Regardless of firing rate, don't check whether should fire for awhile.
if (tp->flags[Model::Subsystem_Flags::Use_multiple_guns])
@@ -2402,10 +2346,16 @@ void ai_turret_execute_behavior(ship *shipp, ship_subsys *ss)
// If the barrel of this turret is long, we shouldn't try to fire if the enemy is under the gun.
// Note that this isn't the same thing as min_range, which is unrelated to barrel length.
if (tp->flags[Model::Subsystem_Flags::Turret_distant_firepoint] || Always_use_distant_firepoints) {
vec3d fpoint, fvec;
ship_get_global_turret_gun_info(objp, ss, &fpoint, &fvec, use_angles, &predicted_enemy_pos);
auto barrel_length = vm_vec_dist(&fpoint, &gpos);
if (dist_to_enemy < barrel_length) continue;
if (turret_barrel_length < 0.0f) {
if (tp->turret_gun_sobj >= 0) {
auto pm = model_get(tp->model_num);
auto submodel = &pm->submodel[tp->turret_gun_sobj];
turret_barrel_length = 2 * submodel->rad;
} else {
turret_barrel_length = 0.0f;
}
}
if (dist_to_enemy < turret_barrel_length) continue;
}
// Don't try to fire beyond weapon_limit_range (or within min range)
@@ -2523,7 +2473,7 @@ void ai_turret_execute_behavior(ship *shipp, ship_subsys *ss)
// Maybe pick a new enemy, unless targeting has been taken over by scripting
if ( turret_should_pick_new_target(ss) && !ss->scripting_target_override && !(ss->flags[Ship::Subsystem_Flags::Forced_target])) {
Num_find_turret_enemy++;
int objnum = find_turret_enemy(ss, parent_objnum, &gpos, &gvec, ss->turret_enemy_objnum);
int objnum = find_turret_enemy(ss, parent_objnum, &global_gun_pos, &global_gun_vec, ss->turret_enemy_objnum);
if (objnum >= 0) {
if (ss->turret_enemy_objnum == -1) {
@@ -2545,7 +2495,7 @@ void ai_turret_execute_behavior(ship *shipp, ship_subsys *ss)
float dot = 1.0f;
lep = &Objects[ss->turret_enemy_objnum];
if (( lep->type == OBJ_SHIP ) && !(ss->flags[Ship::Subsystem_Flags::No_SS_targeting])) {
ss->targeted_subsys = aifft_find_turret_subsys(objp, ss, lep, &dot);
ss->targeted_subsys = aifft_find_turret_subsys(objp, ss, &global_gun_pos, lep, &dot);
}
// recheck in 2-3 seconds
ss->turret_next_enemy_check_stamp = timestamp((int)((MAX(dot, 0.5f) * The_mission.ai_profile->turret_target_recheck_time) + (The_mission.ai_profile->turret_target_recheck_time / 2.0f)));
@@ -2586,14 +2536,15 @@ void ai_turret_execute_behavior(ship *shipp, ship_subsys *ss)
return;
}
if ( lep == nullptr ){
return;
}
//This can't happen. See above code
//if ( lep == nullptr ){
// return;
//}
//This can't happen. See above code
//Assert(ss->turret_enemy_objnum != -1);
bool in_fov = turret_fov_test(ss, &gvec, &v2e);
bool in_fov = turret_fov_test(ss, &global_gun_vec, &v2e);
bool something_was_ok_to_fire = false;
// the only reason predicted_enemy_pos might be zero, while everything else is valid is if
@@ -2648,13 +2599,13 @@ void ai_turret_execute_behavior(ship *shipp, ship_subsys *ss)
// We're ready to fire... now get down to specifics, like where is the
// actual gun point and normal, not just the one for whole turret.
ship_get_global_turret_gun_info(objp, ss, &gpos, &gvec, use_angles, &predicted_enemy_pos);
ship_get_global_turret_gun_info(objp, ss, &global_gun_pos, false, &global_gun_vec, use_angles, &predicted_enemy_pos);
// Fire in the direction the turret is facing, not right at the target regardless of turret dir.
// [Yet this retail comment precedes the calculation of vector-to-enemy...]
vm_vec_sub(&v2e, &predicted_enemy_pos, &gpos);
vm_vec_sub(&v2e, &predicted_enemy_pos, &global_gun_pos);
dist_to_enemy = vm_vec_normalize(&v2e);
float dot = vm_vec_dot(&v2e, &gvec);
float dot = vm_vec_dot(&v2e, &global_gun_vec);
// (flak jitter moved to after we obtain shoot_vector below)
@@ -2719,7 +2670,7 @@ void ai_turret_execute_behavior(ship *shipp, ship_subsys *ss)
// Check if turret should fire and enemy's engines are
// in line of sight
if (turret_should_fire_aspect(ss, wip, in_sight) &&
ship_get_closest_subsys_in_sight(&Ships[lep->signature], SUBSYSTEM_ENGINE, &gpos))
ship_get_closest_subsys_in_sight(&Ships[lep->signature], SUBSYSTEM_ENGINE, &global_gun_pos))
{
ok_to_fire = true;
}
@@ -2729,14 +2680,14 @@ void ai_turret_execute_behavior(ship *shipp, ship_subsys *ss)
if ( ok_to_fire && (tp->flags[Model::Subsystem_Flags::Turret_hull_check]) ) {
int model_num = Ship_info[shipp->ship_info_index].model_num;
vec3d end;
vm_vec_scale_add(&end, &gpos, &gvec, model_get_radius(model_num));
vm_vec_scale_add(&end, &global_gun_pos, &global_gun_vec, model_get_radius(model_num));
mc_info hull_check;
hull_check.model_instance_num = shipp->model_instance_num;
hull_check.model_num = model_num;
hull_check.orient = &objp->orient;
hull_check.pos = &objp->pos;
hull_check.p0 = &gpos;
hull_check.p0 = &global_gun_pos;
hull_check.p1 = &end;
hull_check.flags = MC_CHECK_MODEL | MC_CHECK_RAY;
@@ -2776,7 +2727,7 @@ void ai_turret_execute_behavior(ship *shipp, ship_subsys *ss)
// (Despite the retail comment above, retail actually fired toward the enemy; v2e = vector-to-enemy)
vec3d shoot_vector = v2e;
if (tp->flags[Model::Subsystem_Flags::Fire_on_normal])
shoot_vector = gvec;
shoot_vector = global_gun_vec;
// if the weapon is a flak gun, add some jitter to its aim so it fires in a "cone"
// to make a cool visual effect and make them less lethal
@@ -2784,7 +2735,7 @@ void ai_turret_execute_behavior(ship *shipp, ship_subsys *ss)
flak_jitter_aim(&shoot_vector, dist_to_enemy, ship_get_subsystem_strength(shipp, SUBSYSTEM_WEAPONS), wip);
}
turret_fire_weapon(valid_weapons[valid_index], ss, parent_objnum, &gpos, &shoot_vector, &predicted_enemy_pos, 100.0f, play_sound);
turret_fire_weapon(valid_weapons[valid_index], ss, parent_objnum, &global_gun_pos, &shoot_vector, &predicted_enemy_pos, 100.0f, play_sound);
}
else
{
+6
View File
@@ -1049,6 +1049,7 @@ bool asteroid_is_within_view(vec3d *pos, float range, bool range_override)
*/
static void maybe_throw_asteroid()
{
Assertion(Asteroid_field.num_used_field_debris_types > 0, "maybe_throw_asteroid() called while num_used_field_debris_types was 0; this should never happen, get a coder!");
for (asteroid_target& target : Asteroid_targets) {
if (!timestamp_elapsed(target.throw_stamp))
@@ -2584,6 +2585,11 @@ void asteroid_frame()
return;
}
// If no asteroid types are defined for the field, abort.
if (Asteroid_field.num_used_field_debris_types <= 0) {
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();
+57 -17
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;
@@ -54,6 +54,9 @@ 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 constexpr float fov_default = DEFAULT_FOV;
static SCP_string fov_display(float val)
{
auto degrees = fl_degrees(val);
@@ -64,18 +67,55 @@ static SCP_string fov_display(float val)
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_val(fov_default)
.level(options::ExpertLevel::Advanced)
.importance(60)
.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*************************
//This is where the camera class begins! :D
camera::camera(const char *in_name, int in_signature)
@@ -301,7 +341,7 @@ void camera::set_rotation_facing(vec3d *in_target, float in_rotation_time, float
// 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;
@@ -324,7 +364,7 @@ void camera::do_frame(float /*in_frametime*/)
object *camera::get_object_host()
{
if(object_host.IsValid())
if(object_host.isValid())
return object_host.objp;
else
return NULL;
@@ -337,7 +377,7 @@ int camera::get_object_host_submodel()
object *camera::get_object_target()
{
if(object_target.IsValid())
if(object_target.isValid())
return object_target.objp;
else
return NULL;
@@ -373,7 +413,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,7 +422,7 @@ 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);
@@ -444,9 +484,9 @@ 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);
@@ -481,7 +521,7 @@ void camera::get_info(vec3d *position, matrix *orientation, bool apply_camera_or
vm_vector_2_matrix(&c_ori, &targetvec, NULL, NULL);
target_set = true;
}
else if(object_host.IsValid())
else if(object_host.isValid())
{
if(eyep)
{
@@ -754,7 +794,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], static_cast<size_t>(text_line_lens[i]));
if(w > tw)
tw = w;
@@ -1011,7 +1051,7 @@ int camid::getSignature()
return sig;
}
bool camid::isValid()
bool camid::isValid() const
{
if(idx >= Cameras.size())
return false;
@@ -1203,7 +1243,7 @@ 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 +1251,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,7 +1264,7 @@ 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);
}
+2
View File
@@ -20,6 +20,8 @@
#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&);
+17 -17
View File
@@ -91,12 +91,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;
@@ -330,17 +328,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 +360,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
+103 -62
View File
@@ -40,6 +40,7 @@
#ifdef SCP_UNIX
#include "osapi/osapi.h"
#include <dirent.h>
#include <sys/stat.h>
#endif
#include <cstring>
@@ -1208,93 +1209,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;
@@ -1799,7 +1840,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';
}
@@ -1859,7 +1900,7 @@ bool SetCmdlineParams()
if (val > 0.1) {
VIEWER_ZOOM_DEFAULT = val;
} else {
VIEWER_ZOOM_DEFAULT = 0.75f;
VIEWER_ZOOM_DEFAULT = DEFAULT_FOV;
}
}
+2 -2
View File
@@ -923,8 +923,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
+1 -1
View File
@@ -947,7 +947,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
*/
+4 -2
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.
+14
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';
+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
+3
View File
@@ -278,6 +278,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);
@@ -304,6 +305,8 @@ bool play(const char* name) {
mprintf(("MOVIE ERROR: Found invalid movie! (%s)\n", name));
}
Movie_active = false;
// show the mouse cursor again
io::mouse::CursorManager::get()->popStatus();
+3 -3
View File
@@ -501,11 +501,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 {
@@ -644,7 +644,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();
+2 -2
View File
@@ -220,8 +220,8 @@ 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]) {
+7 -4
View File
@@ -118,10 +118,13 @@ uniform sampler2DArray sMiscmap;
uniform sampler2DArray shadow_map;
out vec4 fragOut0;
#ifndef 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)
{
@@ -185,10 +188,9 @@ void main()
#ifdef FLAG_SHADOW_MAP
// need depth and depth squared for variance shadow maps
fragOut0 = vec4(vertIn.position.z, vertIn.position.z * vertIn.position.z * VARIANCE_SHADOW_SCALE_INV, 0.0, 1.0);
if (true) {
return;
}
#endif
return;
#else
vec3 eyeDir = vec3(normalize(-vertIn.position).xyz);
vec2 texCoord = vertIn.texCoord.xy;
@@ -461,4 +463,5 @@ void main()
fragOut3 = vec4(specColor.rgb, fresnelFactor);
fragOut4 = emissiveColor;
}
#endif
}
-1
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;
+2 -2
View File
@@ -51,7 +51,7 @@ 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")
.category(std::make_pair("Graphics", 1825))
.default_val(true)
.level(options::ExpertLevel::Advanced)
.bind_to(&Fireball_use_3d_warp)
@@ -1052,7 +1052,7 @@ float fireball_wormhole_intensity(fireball *fb)
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);
+1 -1
View File
@@ -27,7 +27,7 @@ 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")
.category(std::make_pair("Graphics", 1825))
.default_val(true)
.level(options::ExpertLevel::Advanced)
.bind_to_once(&Fireball_warp_flash)
+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, 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,
+4 -2
View File
@@ -114,7 +114,8 @@ const char *GS_event_text[] =
"GS_EVENT_PXO_HELP",
"GS_EVENT_FICTION_VIEWER", // 65
"GS_EVENT_SCRIPTING",
"GS_EVENT_SCRIPTING_MISSION"
"GS_EVENT_SCRIPTING_MISSION",
"GS_EVENT_INGAME_OPTIONS"
};
//XSTR:ON
@@ -178,7 +179,8 @@ const char *GS_state_text[] =
"GS_STATE_START_GAME",
"GS_STATE_FICTION_VIEWER",
"GS_STATE_SCRIPTING",
"GS_STATE_SCRIPTING_MISSION"
"GS_STATE_SCRIPTING_MISSION",
"GS_STATE_INGAME_OPTIONS"
};
//XSTR:ON
+2
View File
@@ -90,6 +90,7 @@ enum GS_EVENT {
GS_EVENT_FICTION_VIEWER,
GS_EVENT_SCRIPTING,
GS_EVENT_SCRIPTING_MISSION,
GS_EVENT_INGAME_OPTIONS,
GS_NUM_EVENTS // Last one++
};
@@ -161,6 +162,7 @@ enum GS_STATE {
GS_STATE_FICTION_VIEWER,
GS_STATE_SCRIPTING,
GS_STATE_SCRIPTING_MISSION,
GS_STATE_INGAME_OPTIONS,
GS_NUM_STATES // Last one++
};
+2 -1
View File
@@ -48,11 +48,12 @@ static bool music_volume_change_listener(float new_val, bool /*initial*/)
static auto MusicVolumeOption __UNUSED = options::OptionBuilder<float>("Audio.Music",
std::pair<const char*, int>{"Music", 1371},
std::pair<const char*, int>{"Volume used for playing music", 1760})
.category("Audio")
.category(std::make_pair("Audio", 1826))
.default_val(Default_music_volume)
.range(0.0f, 1.0f)
.change_listener(music_volume_change_listener)
.importance(1)
.flags({options::OptionFlags::RetailBuiltinOption})
.finish();
typedef struct tagSNDPATTERN {
+1 -1
View File
@@ -319,7 +319,7 @@ enum class InterfaceSounds {
MIN_INTERFACE_SOUNDS =70 //!< MIN_INTERFACE_SOUNDS
};
// These two id types are defined as sublcasses so that type safe implicit conversions are possible from the predefined
// These two id types are defined as subclasses so that type safe implicit conversions are possible from the predefined
// sound enum values
struct gamesnd_id_tag{};
+1
View File
@@ -72,6 +72,7 @@
#define MAX_POLYGON_MODELS 300
// object.h
//If this value exceeds 2^16-1, this will break collision pair caching as is. Proceed with caution.
#define MAX_OBJECTS 5000 //Increased from 3500 to 5000 in 2022
// from weapon.h (and beam.h)
+2 -2
View File
@@ -442,7 +442,7 @@ public:
class camera *getCamera();
size_t getIndex();
int getSignature();
bool isValid();
bool isValid() const;
};
#include "globalincs/vmallocator.h"
@@ -453,7 +453,7 @@ public:
// - is not "none"
// - is not "<none>"
inline bool VALID_FNAME(const char* x) {
return strlen((x)) && stricmp((x), "none") != 0 && stricmp((x), "<none>") != 0;
return (x[0] != '\0') && stricmp(x, "none") != 0 && stricmp(x, "<none>") != 0;
}
/**
* @brief Checks if the specified string may be a valid file name
+12 -6
View File
@@ -248,45 +248,48 @@ const auto ModelDetailOption __UNUSED = options::OptionBuilder<int>("Graphics.De
std::pair<const char*, int>{"Model Detail", 1739},
std::pair<const char*, int>{"Detail level of models", 1740})
.importance(8)
.category("Graphics")
.category(std::make_pair("Graphics", 1825))
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.change_listener([](int val, bool) {
Detail.detail_distance = val;
return true;
})
.flags({options::OptionFlags::RetailBuiltinOption})
.finish();
const auto TexturesOption __UNUSED = options::OptionBuilder<int>("Graphics.Texture",
std::pair<const char*, int>{"3D Hardware Textures", 1362},
std::pair<const char*, int>{"Level of detail of textures", 1720})
.importance(6)
.category("Graphics")
.category(std::make_pair("Graphics", 1825))
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.change_listener([](int val, bool) {
Detail.hardware_textures = val;
return true;
})
.flags({options::OptionFlags::RetailBuiltinOption})
.finish();
const auto ParticlesOption __UNUSED = options::OptionBuilder<int>("Graphics.Particles",
std::pair<const char*, int>{"Particles", 1363},
std::pair<const char*, int>{"Level of detail for particles", 1717})
.importance(5)
.category("Graphics")
.category(std::make_pair("Graphics", 1825))
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.change_listener([](int val, bool) {
Detail.num_particles = val;
return true;
})
.flags({options::OptionFlags::RetailBuiltinOption})
.finish();
const auto SmallDebrisOption __UNUSED = options::OptionBuilder<int>("Graphics.SmallDebris",
std::pair<const char*, int>{"Impact Effects", 1364},
std::pair<const char*, int>{"Level of detail of impact effects", 1743})
.category("Graphics")
.category(std::make_pair("Graphics", 1825))
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.importance(4)
@@ -294,32 +297,35 @@ const auto SmallDebrisOption __UNUSED = options::OptionBuilder<int>("Graphics.Sm
Detail.num_small_debris = val;
return true;
})
.flags({options::OptionFlags::RetailBuiltinOption})
.finish();
const auto ShieldEffectsOption __UNUSED = options::OptionBuilder<int>("Graphics.ShieldEffects",
std::pair<const char*, int>{"Shield Hit Effects", 1718},
std::pair<const char*, int>{"Level of detail of shield impacts", 1719})
.importance(3)
.category("Graphics")
.category(std::make_pair("Graphics", 1825))
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.change_listener([](int val, bool) {
Detail.shield_effects = val;
return true;
})
.flags({options::OptionFlags::RetailBuiltinOption})
.finish();
const auto StarsOption __UNUSED = options::OptionBuilder<int>("Graphics.Stars",
std::pair<const char*, int>{"Stars", 1366},
std::pair<const char*, int>{"Number of stars in the mission", 1698})
.importance(2)
.category("Graphics")
.category(std::make_pair("Graphics", 1825))
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.change_listener([](int val, bool) {
Detail.num_stars = val;
return true;
})
.flags({options::OptionFlags::RetailBuiltinOption})
.finish();
// Call this with:
+3 -3
View File
@@ -21,17 +21,17 @@ template <typename T>
using SCP_vector = std::vector<T, std::allocator<T>>;
template <typename T>
bool SCP_vector_contains(SCP_vector<T>& vector, T item) {
bool SCP_vector_contains(const SCP_vector<T>& vector, const T& item) {
return std::find(vector.begin(), vector.end(), item) != vector.end();
}
template <typename T>
inline bool SCP_vector_inbounds(SCP_vector<T>& vector, int idx) {
inline bool SCP_vector_inbounds(const SCP_vector<T>& vector, int idx) {
return ((idx >= 0) && (idx < static_cast<int>(vector.size())));
}
template <typename T>
inline bool SCP_vector_inbounds(SCP_vector<T>& vector, size_t idx) {
inline bool SCP_vector_inbounds(const SCP_vector<T>& vector, size_t idx) {
return idx < vector.size();
}
+42 -26
View File
@@ -116,11 +116,12 @@ static bool gamma_change_listener(float new_val, bool initial)
static auto GammaOption __UNUSED = options::OptionBuilder<float>("Graphics.Gamma",
std::pair<const char*, int>{"Brightness", 1375},
std::pair<const char*, int>{"The brightness value used for the game window", 1738})
.category("Graphics")
.category(std::make_pair("Graphics", 1825))
.default_val(1.0f)
.enumerator(gamma_value_enumerator)
.display(gamma_display)
.change_listener(gamma_change_listener)
.flags({options::OptionFlags::RetailBuiltinOption})
.finish();
@@ -134,7 +135,7 @@ const auto LightingOption __UNUSED = options::OptionBuilder<int>("Graphics.Light
std::pair<const char*, int>{"Lighting", 1367},
std::pair<const char*, int>{"Level of detail of the lighting", 1715})
.importance(1)
.category("Graphics")
.category(std::make_pair("Graphics", 1825))
.values(DetailLevelValues)
.default_val(MAX_DETAIL_LEVEL)
.change_listener([](int val, bool initial) {
@@ -144,6 +145,7 @@ const auto LightingOption __UNUSED = options::OptionBuilder<int>("Graphics.Light
}
return true;
})
.flags({options::OptionFlags::RetailBuiltinOption})
.finish();
os::ViewportState Gr_configured_window_state = os::ViewportState::Windowed;
@@ -169,7 +171,7 @@ static bool mode_change_func(os::ViewportState state, bool initial)
static auto WindowModeOption __UNUSED = options::OptionBuilder<os::ViewportState>("Graphics.WindowMode",
std::pair<const char*, int>{"Window Mode", 1772},
std::pair<const char*, int>{"Controls how the game window is created", 1773})
.category("Graphics")
.category(std::make_pair("Graphics", 1825))
.level(options::ExpertLevel::Beginner)
.values({{os::ViewportState::Fullscreen, {"Fullscreen", 1679}},
{os::ViewportState::Borderless, {"Borderless", 1675}},
@@ -260,7 +262,7 @@ static bool videodisplay_change(int display, bool initial)
static auto VideoDisplayOption = options::OptionBuilder<int>("Graphics.Display",
std::pair<const char*, int>{"Primary display", 1741},
std::pair<const char*, int>{"The display used for rendering", 1742})
.category("Graphics")
.category(std::make_pair("Graphics", 1825))
.level(options::ExpertLevel::Beginner)
.deserializer(videodisplay_deserializer)
.serializer(videodisplay_serializer)
@@ -370,7 +372,7 @@ static bool resolution_change(const ResolutionInfo& /*info*/, bool initial)
static auto ResolutionOption = options::OptionBuilder<ResolutionInfo>("Graphics.Resolution",
std::pair<const char*, int>{"Resolution", 1748},
std::pair<const char*, int>{"The rendering resolution", 1749})
.category("Graphics")
.category(std::make_pair("Graphics", 1825))
.level(options::ExpertLevel::Beginner)
.deserializer(resolution_deserializer)
.serializer(resolution_serializer)
@@ -386,7 +388,7 @@ bool Gr_enable_soft_particles = false;
static auto SoftParticlesOption __UNUSED = options::OptionBuilder<bool>("Graphics.SoftParticles",
std::pair<const char*, int>{"Soft Particles", 1761},
std::pair<const char*, int>{"Enable or disable soft particle rendering", 1762})
.category("Graphics")
.category(std::make_pair("Graphics", 1825))
.level(options::ExpertLevel::Advanced)
.default_val(true)
.bind_to_once(&Gr_enable_soft_particles)
@@ -398,13 +400,13 @@ flagset<FramebufferEffects> Gr_framebuffer_effects;
static auto FramebufferEffectsOption __UNUSED = options::OptionBuilder<flagset<FramebufferEffects>>("Graphics.FramebufferEffects",
std::pair<const char*, int>{"Framebuffer effects", 1732},
std::pair<const char*, int>{"Controls which framebuffer effects will be applied to the scene", 1733})
.category("Graphics")
.category(std::make_pair("Graphics", 1825))
.level(options::ExpertLevel::Advanced)
.values({{{}, {"None", 211}},
{{FramebufferEffects::Shockwaves}, {"Shockwaves", 1688}},
{{FramebufferEffects::Thrusters}, {"Thrusters", 1689}},
{{FramebufferEffects::Shockwaves, FramebufferEffects::Thrusters}, {"All", 1690}}})
.default_val({FramebufferEffects::Shockwaves, FramebufferEffects::Thrusters})
.default_val({})
.bind_to_once(&Gr_framebuffer_effects)
.importance(77)
.finish();
@@ -415,7 +417,7 @@ AntiAliasMode Gr_aa_mode_last_frame = AntiAliasMode::None;
static auto AAOption __UNUSED = options::OptionBuilder<AntiAliasMode>("Graphics.AAMode",
std::pair<const char*, int>{"Anti Aliasing", 1752},
std::pair<const char*, int>{"Controls the anti aliasing mode of the engine.", 1753})
.category("Graphics")
.category(std::make_pair("Graphics", 1825))
.level(options::ExpertLevel::Advanced)
.values({{AntiAliasMode::None, {"None", 211}},
{AntiAliasMode::FXAA_Low, {"FXAA Low", 1681}},
@@ -434,7 +436,7 @@ extern int Cmdline_msaa_enabled;
static auto MSAAOption __UNUSED = options::OptionBuilder<int>("Graphics.MSAASamples",
std::pair<const char*, int>{"Multisample Anti Aliasing", 1758},
std::pair<const char*, int>{"Controls whether multisample anti asliasing is enabled, and with how many samples", 1759})
.category("Graphics")
.category(std::make_pair("Graphics", 1825))
.level(options::ExpertLevel::Advanced)
.values({{0, {"Off", 1693}},
{4, {"4 Samples", 1694}},
@@ -458,9 +460,9 @@ bool Gr_post_processing_enabled = true;
static auto PostProcessOption __UNUSED = options::OptionBuilder<bool>("Graphics.PostProcessing",
std::pair<const char*, int>{"Post processing", 1726},
std::pair<const char*, int>{"Controls whether post processing is enabled in the engine.", 1727})
.category("Graphics")
.category(std::make_pair("Graphics", 1825))
.level(options::ExpertLevel::Advanced)
.default_val(false)
.default_val(true)
.bind_to_once(&Gr_post_processing_enabled)
.importance(69)
.finish();
@@ -470,7 +472,7 @@ bool Gr_enable_vsync = true;
static auto VSyncOption __UNUSED = options::OptionBuilder<bool>("Graphics.VSync",
std::pair<const char*, int>{"Vertical Sync", 1766},
std::pair<const char*, int>{"Controls how the engine does vertical synchronization", 1767})
.category("Graphics")
.category(std::make_pair("Graphics", 1825))
.level(options::ExpertLevel::Advanced)
.default_val(true)
.bind_to_once(&Gr_enable_vsync)
@@ -1754,17 +1756,6 @@ bool gr_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, int d_mode,
return true;
}
void gr_force_windowed()
{
if ( !Gr_inited ) {
return;
}
if ( Os_debugger_running ) {
os_sleep(1000);
}
}
int gr_activated = 0;
void gr_activate(int active)
{
@@ -1779,7 +1770,7 @@ void gr_activate(int active)
}
if (active) {
if (Cmdline_fullscreen_window || Cmdline_window) {
if (gr_is_viewport_window()) {
os::getMainViewport()->restore();
} else {
os::getMainViewport()->setState(os::ViewportState::Fullscreen);
@@ -1789,7 +1780,7 @@ void gr_activate(int active)
}
if (active) {
if (!Cmdline_fullscreen_window && !Cmdline_window) {
if (!gr_is_viewport_window()) {
gr_set_gamma(Gr_gamma);
}
}
@@ -2968,3 +2959,28 @@ void gr_get_post_process_effect_names(SCP_vector<SCP_string>& names)
names.push_back(eff.name);
}
}
bool gr_is_viewport_window()
{
if (Fred_running) {
return true;
}
if (Using_in_game_options) {
switch (Gr_configured_window_state)
{
case os::ViewportState::Windowed:
case os::ViewportState::Borderless:
return true;
break;
default:
break;
}
} else {
if (Cmdline_window || Cmdline_fullscreen_window) {
return true;
}
}
return false;
}
+3 -1
View File
@@ -1002,7 +1002,7 @@ extern void gr_printf_menu_zoomed( int x, int y, const char * format, SCP_FORMAT
extern void gr_printf_no_resize( int x, int y, const char * format, SCP_FORMAT_STRING ... ) SCP_FORMAT_STRING_ARGS(3, 4);
// Returns the size of the string in pixels in w and h
extern void gr_get_string_size( int *w, int *h, const char * text, int len = 9999 );
extern void gr_get_string_size( int *w, int *h, const char * text, size_t len = std::string::npos );
// Returns the height of the current font
extern int gr_get_font_height();
@@ -1428,6 +1428,8 @@ void gr_set_gamma(float gamma);
void gr_get_post_process_effect_names(SCP_vector<SCP_string> &names);
bool gr_is_viewport_window();
// Include this last to make the 2D rendering function available everywhere
#include "graphics/render.h"
+2 -2
View File
@@ -339,8 +339,8 @@ void gr_set_ambient_light(int red, int green, int blue) {
gr_light_ambient[3] = 1.0f;
}
void gr_get_ambient_light(vec3d* light_vector) {
auto abv = ltp::current()->ambient_light_brightness;
auto over = ltp::current()->overall_brightness;
const auto& abv = ltp::current()->ambient_light_brightness;
const auto& over = ltp::current()->overall_brightness;
light_vector->xyz.x = over.handle(abv.handle(gr_light_ambient[0]));
light_vector->xyz.y = over.handle(abv.handle(gr_light_ambient[1]));
light_vector->xyz.z = over.handle(abv.handle(gr_light_ambient[2]));
+5 -5
View File
@@ -85,7 +85,7 @@ void gr_start_instance_matrix(const vec3d *offset, const matrix *rotation)
gr_model_matrix_stack.push(offset, rotation);
auto model_matrix = gr_model_matrix_stack.get_transform();
const auto& model_matrix = gr_model_matrix_stack.get_transform();
vm_matrix4_x_matrix4(&gr_model_view_matrix, &gr_view_matrix, &model_matrix);
modelview_matrix_depth++;
@@ -109,7 +109,7 @@ void gr_end_instance_matrix()
gr_model_matrix_stack.pop();
auto model_matrix = gr_model_matrix_stack.get_transform();
const auto& model_matrix = gr_model_matrix_stack.get_transform();
vm_matrix4_x_matrix4(&gr_model_view_matrix, &gr_view_matrix, &model_matrix);
modelview_matrix_depth--;
@@ -280,7 +280,7 @@ void gr_end_2d_matrix()
gr_view_matrix = gr_last_view_matrix;
auto model_matrix = gr_model_matrix_stack.get_transform();
const auto& model_matrix = gr_model_matrix_stack.get_transform();
vm_matrix4_x_matrix4(&gr_model_view_matrix, &gr_view_matrix, &model_matrix);
htl_2d_matrix_set = false;
@@ -302,7 +302,7 @@ void gr_push_scale_matrix(const vec3d *scale_factor)
gr_model_matrix_stack.push(NULL, NULL, scale_factor);
auto model_matrix = gr_model_matrix_stack.get_transform();
const auto& model_matrix = gr_model_matrix_stack.get_transform();
vm_matrix4_x_matrix4(&gr_model_view_matrix, &gr_view_matrix, &model_matrix);
matrix_uniform_up_to_date = false;
@@ -315,7 +315,7 @@ void gr_pop_scale_matrix()
gr_model_matrix_stack.pop();
auto model_matrix = gr_model_matrix_stack.get_transform();
const auto& model_matrix = gr_model_matrix_stack.get_transform();
vm_matrix4_x_matrix4(&gr_model_view_matrix, &gr_view_matrix, &model_matrix);
modelview_matrix_depth--;
+1 -1
View File
@@ -346,7 +346,7 @@ void gr_opengl_deferred_lighting_finish()
auto light_data = prepare_light_uniforms(l, light_uniform_aligner);
if (l.type == Light_Type::Cone) {
light_data->dualCone = l.dual_cone ? 1.0f : 0.0f;
light_data->dualCone = (l.flags & LF_DUAL_CONE) ? 1.0f : 0.0f;
light_data->coneAngle = l.cone_angle;
light_data->coneInnerAngle = l.cone_inner_angle;
light_data->coneDir = l.vec2;
+6 -6
View File
@@ -124,10 +124,10 @@ bool gr_opengl_openxr_create_session() {
};
XrSessionCreateInfo sessionCreateInfo {
sessionCreateInfo.type = XR_TYPE_SESSION_CREATE_INFO,
sessionCreateInfo.next = &graphicsBinding,
sessionCreateInfo.createFlags = 0,
sessionCreateInfo.systemId = xr_system
XR_TYPE_SESSION_CREATE_INFO,
&graphicsBinding,
0,
xr_system
};
XrResult sessionInit = xrCreateSession(xr_instance, &sessionCreateInfo, &xr_session);
@@ -249,9 +249,9 @@ bool gr_opengl_openxr_flip() {
xrAcquireSwapchainImage(swapchain, &acquireImageInfo, &activeIndex);
XrSwapchainImageWaitInfo waitImageInfo{
waitImageInfo.type = XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO,
XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO,
nullptr,
waitImageInfo.timeout = std::numeric_limits<int64_t>::max()
std::numeric_limits<int64_t>::max()
};
xrWaitSwapchainImage(swapchain, &waitImageInfo);
@@ -431,7 +431,6 @@ extern GLuint Cockpit_depth_texture;
extern GLuint Scene_position_texture;
extern GLuint Scene_normal_texture;
extern GLuint Scene_specular_texture;
extern bool stars_sun_has_glare(int index);
extern float Sun_spot;
void opengl_post_lightshafts()
{
@@ -452,7 +451,7 @@ void opengl_post_lightshafts()
light_get_global_dir(&light_dir, idx);
vm_vec_rotate(&local_light_dir, &light_dir, &Eye_matrix);
if ( !stars_sun_has_glare(idx) ) {
if ( !light_has_glare(idx) ) {
continue;
}
@@ -851,8 +850,8 @@ void opengl_post_shader_header(SCP_stringstream& sflags, shader_type shader_t, i
}
} else if (shader_t == SDR_TYPE_POST_PROCESS_LIGHTSHAFTS) {
char temp[64];
const auto ls_params = graphics::Post_processing_manager->getLightshaftParams();
sprintf(temp, "#define SAMPLE_NUM %d\n", ls_params.samplenum);
const auto& ls_params = graphics::Post_processing_manager->getLightshaftParams();
snprintf(temp, 64, "#define SAMPLE_NUM %d\n", ls_params.samplenum);
sflags << temp;
} else if (shader_t == SDR_TYPE_POST_PROCESS_FXAA) {
set_fxaa_defines(sflags);
+2 -2
View File
@@ -55,7 +55,7 @@ static auto TextureFilteringOption __UNUSED = options::OptionBuilder<int>("Graph
std::pair<const char*, int>{"Texture Filtering", 1763},
std::pair<const char*, int>{"Texture filtering option", 1764})
.importance(1)
.category("Graphics")
.category(std::make_pair("Graphics", 1825))
.values(TextureFilteringValues)
.default_val(0)
.bind_to_once(&GL_mipmap_filter)
@@ -107,7 +107,7 @@ static auto AnisotropyOption = options::OptionBuilder<float>("Graphics.Anisotrop
std::pair<const char*, int>{"Anistropic filtering", 1736},
std::pair<const char*, int>{"Controls the amount of anistropic filtering of the textures", 1737})
.enumerator(anisotropic_value_enumerator)
.category("Graphics")
.category(std::make_pair("Graphics", 1825))
.display(anisotropic_display)
.default_func(anisotropic_default)
.level(options::ExpertLevel::Advanced)
+3 -2
View File
@@ -43,7 +43,7 @@ bool Post_processing_enable_lightshafts = true;
static auto LightshaftsOption __UNUSED = options::OptionBuilder<bool>("Graphics.Lightshafts",
std::pair<const char*, int>{"Lightshafts", 1724},
std::pair<const char*, int>{"Enables or disables lightshafts (requires post-processing)", 1725})
.category("Graphics")
.category(std::make_pair("Graphics", 1825))
.default_val(true)
.level(options::ExpertLevel::Advanced)
.bind_to(&Post_processing_enable_lightshafts)
@@ -55,12 +55,13 @@ int Post_processing_bloom_intensity = 25; // using default value of Cmdline_bloo
static auto BloomIntensityOption __UNUSED = options::OptionBuilder<int>("Graphics.BloomIntensity",
std::pair<const char*, int>{"Bloom intensity", 1701},
std::pair<const char*, int>{"Sets the bloom intensity (requires post-processing)", 1702})
.category("Graphics")
.category(std::make_pair("Graphics", 1825))
.range(0, 200)
.level(options::ExpertLevel::Advanced)
.default_val(25)
.bind_to(&Post_processing_bloom_intensity)
.importance(55)
.flags({options::OptionFlags::RangeTypeInteger})
.finish();
} // namespace
+3 -3
View File
@@ -779,7 +779,7 @@ void endDrawing(graphics::paths::PathRenderer* path) {
}
}
void gr_string(float sx, float sy, const char* s, int resize_mode, int in_length) {
void gr_string(float sx, float sy, const char* s, int resize_mode, size_t in_length) {
if (gr_screen.mode == GR_STUB) {
return;
}
@@ -797,10 +797,10 @@ void gr_string(float sx, float sy, const char* s, int resize_mode, int in_length
}
size_t length;
if (in_length < 0) {
if (in_length == std::string::npos) {
length = strlen(s);
} else {
length = (size_t) in_length;
length = in_length;
}
FSFont* currentFont = FontManager::getCurrentFont();
+2 -2
View File
@@ -60,7 +60,7 @@ void gr_bitmap_ex(int x, int y, int w, int h, int sx, int sy, int resize_mode =
* @param resize_mode The mode for translating the screen positions
* @param length The number of bytes in the string to render. -1 will render the whole string.
*/
void gr_string(float x, float y, const char* string, int resize_mode = GR_RESIZE_FULL, int length = -1);
void gr_string(float x, float y, const char* string, int resize_mode = GR_RESIZE_FULL, size_t length = std::string::npos);
/**
* @brief Renders the specified string to the screen using the current font and color
* @param x The x-coordinate
@@ -69,7 +69,7 @@ void gr_string(float x, float y, const char* string, int resize_mode = GR_RESIZE
* @param resize_mode The mode for translating the screen positions
* @param length The number of bytes in the string to render. -1 will render the whole string.
*/
inline void gr_string(int x, int y, const char* string, int resize_mode = GR_RESIZE_FULL, int length = -1)
inline void gr_string(int x, int y, const char* string, int resize_mode = GR_RESIZE_FULL, size_t length = std::string::npos)
{
gr_string(i2fl(x), i2fl(y), string, resize_mode, length);
}
+1 -1
View File
@@ -44,7 +44,7 @@ auto ShadowQualityOption = options::OptionBuilder<ShadowQuality>("Graphics.Shado
{ShadowQuality::Ultra, {"Ultra", 1721}}})
.change_listener([](ShadowQuality val, bool initial) {if (initial) {Shadow_quality = val;}return initial;})
.level(options::ExpertLevel::Advanced)
.category("Graphics")
.category(std::make_pair("Graphics", 1825))
.default_val(ShadowQuality::Disabled)
.importance(80)
.finish();
+2 -2
View File
@@ -669,7 +669,7 @@ int gr_get_dynamic_font_lines(int number_default_lines) {
return fl2i((number_default_lines * 10) / (gr_get_font_height() + 1));
}
void gr_get_string_size(int *w1, int *h1, const char *text, int len)
void gr_get_string_size(int *w1, int *h1, const char *text, size_t len)
{
if (!FontManager::isReady())
{
@@ -685,7 +685,7 @@ void gr_get_string_size(int *w1, int *h1, const char *text, int len)
float w = 0.0f;
float h = 0.0f;
FontManager::getCurrentFont()->getStringSize(text, static_cast<size_t>(len), -1, &w, &h);
FontManager::getCurrentFont()->getStringSize(text, len, -1, &w, &h);
if (w1)
{
+52 -46
View File
@@ -81,7 +81,7 @@ int HUD_color_blue = 0;
int HUD_color_alpha = HUD_COLOR_ALPHA_DEFAULT; // 1 -> HUD_COLOR_ALPHA_USER_MAX
int HUD_draw = 1;
int HUD_contrast = 0; // high or lo contrast (for nebula, etc)
bool HUD_high_contrast = false; // high or low contrast (for nebula, etc)
bool HUD_shadows = false;
// Goober5000
@@ -363,7 +363,7 @@ void HudGauge::initPosition(int x, int y)
position[1] = y;
}
void HudGauge::getPosition(int *x, int *y)
void HudGauge::getPosition(int *x, int *y) const
{
*x = position[0];
*y = position[1];
@@ -390,7 +390,7 @@ void HudGauge::initFont(int input_font_num)
}
}
int HudGauge::getFont()
int HudGauge::getFont() const
{
return font_num;
}
@@ -404,7 +404,7 @@ void HudGauge::initOriginAndOffset(float originX, float originY, int offsetX, in
tabled_offset[1] = offsetY;
}
void HudGauge::getOriginAndOffset(float *originX, float *originY, int *offsetX, int *offsetY)
void HudGauge::getOriginAndOffset(float *originX, float *originY, int *offsetX, int *offsetY) const
{
*originX = tabled_origin[0];
*originY = tabled_origin[1];
@@ -420,19 +420,24 @@ void HudGauge::initCoords(bool use_coords, int coordsX, int coordsY)
tabled_coords[1] = coordsY;
}
void HudGauge::getCoords(bool *use_coords, int *coordsX, int *coordsY)
void HudGauge::getCoords(bool *use_coords, int *coordsX, int *coordsY) const
{
*use_coords = tabled_use_coords;
*coordsX = tabled_coords[0];
*coordsY = tabled_coords[1];
}
const char* HudGauge::getCustomGaugeName()
void HudGauge::initHiRes(const char* fname)
{
hi_res = (strncmp(fname, "2_", 2) == 0);
}
const char* HudGauge::getCustomGaugeName() const
{
return custom_name;
}
const char* HudGauge::getCustomGaugeText()
const char* HudGauge::getCustomGaugeText() const
{
return custom_text.c_str();
}
@@ -483,17 +488,17 @@ void HudGauge::setGaugeColor(int bright_index)
if(bright_index != HUD_C_NONE){
switch(bright_index){
case HUD_C_DIM:
alpha = HUD_contrast ? HUD_NEW_ALPHA_DIM_HI : HUD_NEW_ALPHA_DIM;
alpha = HUD_high_contrast ? HUD_NEW_ALPHA_DIM_HI : HUD_NEW_ALPHA_DIM;
gr_init_alphacolor(&gauge_color, gauge_color.red, gauge_color.green, gauge_color.blue, alpha);
break;
case HUD_C_NORMAL:
alpha = HUD_contrast ? HUD_NEW_ALPHA_NORMAL_HI : HUD_NEW_ALPHA_NORMAL;
alpha = HUD_high_contrast ? HUD_NEW_ALPHA_NORMAL_HI : HUD_NEW_ALPHA_NORMAL;
gr_init_alphacolor(&gauge_color, gauge_color.red, gauge_color.green, gauge_color.blue, alpha);
break;
case HUD_C_BRIGHT:
alpha = HUD_contrast ? HUD_NEW_ALPHA_BRIGHT_HI : HUD_NEW_ALPHA_BRIGHT;
alpha = HUD_high_contrast ? HUD_NEW_ALPHA_BRIGHT_HI : HUD_NEW_ALPHA_BRIGHT;
gr_init_alphacolor(&gauge_color, gauge_color.red, gauge_color.green, gauge_color.blue, alpha);
break;
@@ -523,15 +528,15 @@ void HudGauge::setGaugeColor(int bright_index)
} else {
switch(maybeFlashSexp()) {
case 0:
alpha = HUD_contrast ? HUD_NEW_ALPHA_DIM_HI : HUD_NEW_ALPHA_DIM;
alpha = HUD_high_contrast ? HUD_NEW_ALPHA_DIM_HI : HUD_NEW_ALPHA_DIM;
gr_init_alphacolor(&gauge_color, gauge_color.red, gauge_color.green, gauge_color.blue, alpha);
break;
case 1:
alpha = HUD_contrast ? HUD_NEW_ALPHA_BRIGHT_HI : HUD_NEW_ALPHA_BRIGHT;
alpha = HUD_high_contrast ? HUD_NEW_ALPHA_BRIGHT_HI : HUD_NEW_ALPHA_BRIGHT;
gr_init_alphacolor(&gauge_color, gauge_color.red, gauge_color.green, gauge_color.blue, alpha);
break;
default:
alpha = HUD_contrast ? HUD_NEW_ALPHA_NORMAL_HI : HUD_NEW_ALPHA_NORMAL;
alpha = HUD_high_contrast ? HUD_NEW_ALPHA_NORMAL_HI : HUD_NEW_ALPHA_NORMAL;
gr_init_alphacolor(&gauge_color, gauge_color.red, gauge_color.green, gauge_color.blue, alpha);
}
}
@@ -539,33 +544,37 @@ void HudGauge::setGaugeColor(int bright_index)
gr_set_color_fast(&gauge_color);
}
bool HudGauge::isCustom()
bool HudGauge::isCustom() const
{
return custom_gauge;
}
int HudGauge::getBaseWidth()
bool HudGauge::isHiRes() const
{
return hi_res;
}
int HudGauge::getBaseWidth() const
{
return base_w;
}
int HudGauge::getBaseHeight()
int HudGauge::getBaseHeight() const
{
return base_h;
}
float HudGauge::getAspectQuotient()
float HudGauge::getAspectQuotient() const
{
return aspect_quotient;
}
int HudGauge::getConfigType()
int HudGauge::getConfigType() const
{
//return gauge_type;
return gauge_config;
}
int HudGauge::getObjectType()
int HudGauge::getObjectType() const
{
return gauge_object;
}
@@ -588,7 +597,7 @@ void HudGauge::updateColor(int r, int g, int b, int a)
gr_init_alphacolor(&gauge_color, r, g, b, a);
}
const color& HudGauge::getColor()
const color& HudGauge::getColor() const
{
return gauge_color;
}
@@ -613,12 +622,12 @@ void HudGauge::initCockpit_view_choice(int cockpit_view_choice)
render_for_cockpit_toggle = cockpit_view_choice;
}
bool HudGauge::isOffbyDefault()
bool HudGauge::isOffbyDefault() const
{
return off_by_default;
}
bool HudGauge::isActive()
bool HudGauge::isActive() const
{
return active && !sexp_override;
}
@@ -643,7 +652,7 @@ void HudGauge::startPopUp(int time)
popup_timer = timestamp(time);
}
int HudGauge::popUpActive()
int HudGauge::popUpActive() const
{
//Assert(gauge_index >=0 && gauge_index < NUM_HUD_GAUGES);
if ( !pop_up ) {
@@ -673,7 +682,7 @@ void HudGauge::startFlashSexp()
flash_status = false;
}
bool HudGauge::flashExpiredSexp()
bool HudGauge::flashExpiredSexp() const
{
if(timestamp_elapsed(flash_duration)) {
return true;
@@ -1147,7 +1156,7 @@ void HudGauge::initialize()
sexp_lock_color = false;
}
bool HudGauge::canRender()
bool HudGauge::canRender() const
{
if (sexp_override) {
return false;
@@ -1293,12 +1302,12 @@ void HUD_init()
last_percent_throttle = 0.0f;
// default to high contrast in the nebula
HUD_contrast = 0;
HUD_high_contrast = false;
HUD_draw = 1;
HUD_disable_except_messages = 0;
if(The_mission.flags[Mission::Mission_Flags::Fullneb]){
HUD_contrast = 1;
HUD_high_contrast = true;
}
// reset to infinite
@@ -1697,7 +1706,7 @@ void hud_render_preprocess(float frametime)
if ( hud_disabled() ) {
// if the hud is disabled, we still need to make sure that the indicators are properly handled
hud_do_lock_indicators(flFrametime);
hud_do_lock_indicators(frametime);
return;
}
@@ -1823,15 +1832,15 @@ void hud_maybe_display_supernova()
/**
* @brief Undertakes main HUD render.
*/
void hud_render_all()
void hud_render_all(float frametime)
{
int i;
hud_render_gauges();
hud_render_gauges(-1, frametime);
// start rendering cockpit dependent gauges if possible
for ( i = 0; i < (int)Player_displays.size(); ++i ) {
hud_render_gauges(i);
hud_render_gauges(i, frametime);
}
hud_clear_msg_buffer();
@@ -1840,7 +1849,7 @@ void hud_render_all()
font::set_font(font::FONT1);
}
void hud_render_gauges(int cockpit_display_num)
void hud_render_gauges(int cockpit_display_num, float frametime)
{
size_t j, num_gauges;
ship_info* sip = &Ship_info[Player_ship->ship_info_index];
@@ -1866,9 +1875,6 @@ void hud_render_gauges(int cockpit_display_num)
}
}
//Since we render things twice in VR mode, frametime needs to be halved for HUD, as the HUD uses the frametime to advance ANI's and crucially, the missile lock...
float frametime = openxr_enabled() ? flFrametime * 0.5f : flFrametime;
// Check if this ship has its own HUD gauges.
if ( sip->hud_enabled ) {
num_gauges = sip->hud_gauges.size();
@@ -3313,17 +3319,17 @@ void hud_set_gauge_color(int gauge_index, int bright_index)
if(bright_index != HUD_C_NONE){
switch(bright_index){
case HUD_C_DIM:
alpha = HUD_contrast ? HUD_NEW_ALPHA_DIM_HI : HUD_NEW_ALPHA_DIM;
alpha = HUD_high_contrast ? HUD_NEW_ALPHA_DIM_HI : HUD_NEW_ALPHA_DIM;
gr_init_alphacolor(use_color, use_color->red, use_color->green, use_color->blue, alpha);
break;
case HUD_C_NORMAL:
alpha = HUD_contrast ? HUD_NEW_ALPHA_NORMAL_HI : HUD_NEW_ALPHA_NORMAL;
alpha = HUD_high_contrast ? HUD_NEW_ALPHA_NORMAL_HI : HUD_NEW_ALPHA_NORMAL;
gr_init_alphacolor(use_color, use_color->red, use_color->green, use_color->blue, alpha);
break;
case HUD_C_BRIGHT:
alpha = HUD_contrast ? HUD_NEW_ALPHA_BRIGHT_HI : HUD_NEW_ALPHA_BRIGHT;
alpha = HUD_high_contrast ? HUD_NEW_ALPHA_BRIGHT_HI : HUD_NEW_ALPHA_BRIGHT;
gr_init_alphacolor(use_color, use_color->red, use_color->green, use_color->blue, alpha);
break;
@@ -3353,15 +3359,15 @@ void hud_set_gauge_color(int gauge_index, int bright_index)
} else {
switch(flash_status) {
case 0:
alpha = HUD_contrast ? HUD_NEW_ALPHA_DIM_HI : HUD_NEW_ALPHA_DIM;
alpha = HUD_high_contrast ? HUD_NEW_ALPHA_DIM_HI : HUD_NEW_ALPHA_DIM;
gr_init_alphacolor(use_color, use_color->red, use_color->green, use_color->blue, alpha);
break;
case 1:
alpha = HUD_contrast ? HUD_NEW_ALPHA_BRIGHT_HI : HUD_NEW_ALPHA_BRIGHT;
alpha = HUD_high_contrast ? HUD_NEW_ALPHA_BRIGHT_HI : HUD_NEW_ALPHA_BRIGHT;
gr_init_alphacolor(use_color, use_color->red, use_color->green, use_color->blue, alpha);
break;
default:
alpha = HUD_contrast ? HUD_NEW_ALPHA_NORMAL_HI : HUD_NEW_ALPHA_NORMAL;
alpha = HUD_high_contrast ? HUD_NEW_ALPHA_NORMAL_HI : HUD_NEW_ALPHA_NORMAL;
gr_init_alphacolor(use_color, use_color->red, use_color->green, use_color->blue, alpha);
break;
}
@@ -3864,12 +3870,12 @@ void hud_save_restore_camera_data(int save)
void hud_toggle_contrast()
{
HUD_contrast = !HUD_contrast;
HUD_high_contrast = !HUD_high_contrast;
}
void hud_set_contrast(int high)
void hud_set_contrast(bool high)
{
HUD_contrast = high;
HUD_high_contrast = high;
}
void hud_toggle_shadows()
@@ -3988,7 +3994,7 @@ HudGauge(HUD_OBJECT_MULTI_MSG, HUD_MESSAGE_LINES, false, true, 0, 255, 255, 255)
{
}
bool HudGaugeMultiMsg::canRender()
bool HudGaugeMultiMsg::canRender() const
{
return true;
}
+26 -23
View File
@@ -69,7 +69,7 @@ enum class HudAlignment
};
extern int HUD_draw;
extern int HUD_contrast;
extern bool HUD_high_contrast;
extern bool HUD_shadows;
#define HUD_NUM_COLOR_LEVELS 16
@@ -119,8 +119,8 @@ void hud_close();
void hud_level_close();
void hud_update_frame(float frametime); // updates hud systems not dependant on rendering
void hud_render_preprocess(float frametime); // renders 3d dependant gauges
void hud_render_all();
void hud_render_gauges(int cockpit_display_num = -1);
void hud_render_all(float frametime);
void hud_render_gauges(int cockpit_display_num, float frametime);
void hud_stop_looped_engine_sounds();
// set the offset values for this render frame
@@ -203,7 +203,7 @@ int hud_disabled_except_messages();
// contrast stuff
void hud_toggle_contrast();
void hud_set_contrast(int high);
void hud_set_contrast(bool high);
void hud_toggle_shadows();
class HudGauge
@@ -223,6 +223,7 @@ protected:
bool tabled_use_coords;
int tabled_coords[2];
float aspect_quotient;
bool hi_res;
bool lock_color;
bool sexp_lock_color;
@@ -271,28 +272,30 @@ public:
void initFont(int input_font_num);
void initOriginAndOffset(float originX, float originY, int offsetX, int offsetY);
void initCoords(bool use_coords, int coordsX, int coordsY);
void initHiRes(const char* fname);
virtual void initSlew(bool slew);
void initCockpitTarget(const char* display_name, int _target_x, int _target_y, int _target_w, int _target_h, int _canvas_w, int _canvas_h);
void initRenderStatus(bool render);
bool isCustom();
int getBaseWidth();
int getBaseHeight();
float getAspectQuotient();
bool isCustom() const;
bool isHiRes() const;
int getBaseWidth() const;
int getBaseHeight() const;
float getAspectQuotient() const;
int getConfigType();
int getObjectType();
void getPosition(int *x, int *y);
bool isOffbyDefault();
bool isActive();
int getConfigType() const;
int getObjectType() const;
void getPosition(int *x, int *y) const;
bool isOffbyDefault() const;
bool isActive() const;
int getFont();
void getOriginAndOffset(float *originX, float *originY, int *offsetX, int *offsetY);
void getCoords(bool* use_coords, int* coordsX, int* coordsY);
int getFont() const;
void getOriginAndOffset(float *originX, float *originY, int *offsetX, int *offsetY) const;
void getCoords(bool* use_coords, int* coordsX, int* coordsY) const;
void updateColor(int r, int g, int b, int a = 255);
const color& getColor();
const color& getColor() const;
void lockConfigColor(bool lock);
void sexpLockConfigColor(bool lock);
void updateActive(bool show);
@@ -305,21 +308,21 @@ public:
// For flashing gauges in training missions
void startFlashSexp();
int maybeFlashSexp();
bool flashExpiredSexp();
bool flashExpiredSexp() const;
void resetTimers();
// For updating custom gauges
const char* getCustomGaugeName();
const char* getCustomGaugeName() const;
void updateCustomGaugeText(const char* txt);
void updateCustomGaugeText(const SCP_string& txt);
const char* getCustomGaugeText();
const char* getCustomGaugeText() const;
void startPopUp(int time=4000);
int popUpActive();
int popUpActive() const;
virtual void preprocess();
virtual void render(float frametime);
virtual bool canRender();
virtual bool canRender() const;
virtual void pageIn();
virtual void initialize();
virtual void onFrame(float frametime);
@@ -549,7 +552,7 @@ class HudGaugeMultiMsg: public HudGauge
protected:
public:
HudGaugeMultiMsg();
bool canRender() override;
bool canRender() const override;
void render(float frametime) override;
};
+2 -2
View File
@@ -327,8 +327,8 @@ void ssm_create(object *target, vec3d *start, size_t ssm_index, ssm_firing_info
// Init the ssm data
count = Ssm_info[ssm_index].count;
if (Ssm_info[ssm_index].max_count != -1) {
count += Random::next(count, Ssm_info[ssm_index].max_count);
if (Ssm_info[ssm_index].max_count != -1 && (Ssm_info[ssm_index].max_count - count) > 0) {
count = Random::next(count, Ssm_info[ssm_index].max_count);
}
// override in multiplayer
+2 -2
View File
@@ -288,7 +288,7 @@ int draw_subsys_brackets(graphics::line_draw_list* draw_list, ship_subsys* subsy
}
// determine if subsystem is on far or near side of the ship
int in_sight = ship_subsystem_in_sight(targetp, subsys, &View_position, &subobj_pos, 0);
bool in_sight = ship_subsystem_in_sight(targetp, subsys, &View_position, &subobj_pos, false);
if (draw)
{
@@ -761,7 +761,7 @@ void HudGaugeBrackets::renderBoundingBracketsSubobject()
}
// determine if subsystem is on far or near side of the ship
Player->subsys_in_view = ship_subsystem_in_sight(targetp, subsys, &View_position, &subobj_pos, 0);
Player->subsys_in_view = ship_subsystem_in_sight(targetp, subsys, &View_position, &subobj_pos, false) ? 1 : 0;
// AL 29-3-98: If subsystem is destroyed, draw gray brackets
// Goober5000: this will now execute for fighterbays if the bay has been given a
+1 -3
View File
@@ -1323,10 +1323,8 @@ void hud_config_button_do(int n)
break;
}
if (HC_current_file >= (int)HC_preset_filenames.size()) {
if ((++HC_current_file) >= static_cast<int> (HC_preset_filenames.size())) {
HC_current_file = 0;
} else {
HC_current_file++;
}
// load em up
+4 -4
View File
@@ -506,7 +506,7 @@ int hud_lock_on_subsys_ok()
vm_vec_add2(&subobj_pos, &target_objp->pos);
if ( Player->subsys_in_view < 0 ) {
in_sight = ship_subsystem_in_sight(target_objp, subsys, &View_position, &subobj_pos);
in_sight = ship_subsystem_in_sight(target_objp, subsys, &View_position, &subobj_pos) ? 1 : 0;
} else {
in_sight = Player->subsys_in_view;
}
@@ -640,7 +640,7 @@ void hud_do_lock_indicator(float frametime)
vec3d subobj_pos;
vm_vec_unrotate(&subobj_pos, &Player->locking_subsys->system_info->pnt, &tobjp->orient);
vm_vec_add2(&subobj_pos, &tobjp->pos);
int target_subsys_in_sight = ship_subsystem_in_sight(tobjp, Player->locking_subsys, &Player_obj->pos, &subobj_pos);
bool target_subsys_in_sight = ship_subsystem_in_sight(tobjp, Player->locking_subsys, &Player_obj->pos, &subobj_pos);
if (!target_subsys_in_sight || Player->locking_subsys->system_info->type != SUBSYSTEM_ENGINE) {
Player->locking_subsys =
@@ -1059,7 +1059,7 @@ void hud_lock_determine_lock_target(lock_info *lock_slot, weapon_info *wip)
vm_vec_unrotate(&subobj_pos, &Player->locking_subsys->system_info->pnt, &lock_slot->obj->orient);
vm_vec_add2(&subobj_pos, &lock_slot->obj->pos);
int target_subsys_in_sight = ship_subsystem_in_sight(lock_slot->obj, Player_ai->targeted_subsys, &Player_obj->pos, &subobj_pos);
bool target_subsys_in_sight = ship_subsystem_in_sight(lock_slot->obj, Player_ai->targeted_subsys, &Player_obj->pos, &subobj_pos);
if ( !target_subsys_in_sight || Player->locking_subsys->system_info->type != SUBSYSTEM_ENGINE ) {
lock_slot->subsys = ship_get_closest_subsys_in_sight(&Ships[lock_slot->obj->instance], SUBSYSTEM_ENGINE, &Player_obj->pos);
@@ -1110,7 +1110,7 @@ void hud_lock_determine_lock_target(lock_info *lock_slot, weapon_info *wip)
vm_vec_unrotate(&subobj_pos, &Player_ai->targeted_subsys->system_info->pnt, &lock_slot->obj->orient);
vm_vec_add2(&subobj_pos, &lock_slot->obj->pos);
int target_subsys_in_sight = ship_subsystem_in_sight(lock_slot->obj, Player_ai->targeted_subsys, &Player_obj->pos, &subobj_pos);
bool target_subsys_in_sight = ship_subsystem_in_sight(lock_slot->obj, Player_ai->targeted_subsys, &Player_obj->pos, &subobj_pos);
if ( !target_subsys_in_sight || Player_ai->targeted_subsys->system_info->type != SUBSYSTEM_ENGINE ) {
lock_slot->subsys = ship_get_closest_subsys_in_sight(&Ships[lock_slot->obj->instance], SUBSYSTEM_ENGINE, &Player_obj->pos);
+4 -4
View File
@@ -305,7 +305,7 @@ void HudGaugeMessages::processMessageBuffer()
ptr = strstr(msg, NOX(": "));
if ( ptr ) {
int sw;
gr_get_string_size(&sw, nullptr, msg, (int)(ptr + 2 - msg));
gr_get_string_size(&sw, nullptr, msg, (ptr + 2 - msg));
offset = sw;
}
@@ -641,7 +641,7 @@ void hud_add_msg_to_scrollback(const char *text, int source, int t)
// determine the length of the sender's name for underlining
if (ptr) {
gr_get_string_size(&w, nullptr, buf, (int)(ptr - buf));
gr_get_string_size(&w, nullptr, buf, (ptr - buf));
}
// create the new node for the vector
@@ -843,7 +843,7 @@ void hud_initialize_scrollback_lines()
int width = 0;
int height = 0;
gr_get_string_size(&width, &height, node_msg.text.c_str(), (int)node_msg.text.length());
gr_get_string_size(&width, &height, node_msg.text.c_str(), node_msg.text.length());
int max_width = Hud_mission_log_list2_coords[gr_screen.res][2];
if (width > max_width) {
@@ -1264,7 +1264,7 @@ void HudGaugeTalkingHead::pageIn()
bm_page_in_aabitmap( Head_frame.first_frame, Head_frame.num_frames );
}
bool HudGaugeTalkingHead::canRender()
bool HudGaugeTalkingHead::canRender() const
{
if (sexp_override) {
return false;
+1 -1
View File
@@ -137,7 +137,7 @@ public:
void pageIn() override;
void render(float frametime) override;
void initialize() override;
bool canRender() override;
bool canRender() const override;
};
class HudGaugeFixedMessages: public HudGauge
+37 -1
View File
@@ -1611,6 +1611,7 @@ void load_gauge_lag(gauge_settings* settings)
}
hud_gauge->initBitmaps(fname);
hud_gauge->initHiRes(fname);
gauge_assign_common(settings, std::move(hud_gauge));
}
@@ -1666,6 +1667,7 @@ void load_gauge_mini_shields(gauge_settings* settings)
hud_gauge->init2DigitOffsets(Mini_2digit_offsets[0], Mini_2digit_offsets[1]);
hud_gauge->init3DigitOffsets(Mini_3digit_offsets[0], Mini_3digit_offsets[1]);
hud_gauge->initBitmaps(fname);
hud_gauge->initHiRes(fname);
gauge_assign_common(settings, std::move(hud_gauge));
}
@@ -1762,6 +1764,7 @@ void load_gauge_weapon_energy(gauge_settings* settings)
}
hud_gauge->initBitmaps(fname);
hud_gauge->initHiRes(fname);
hud_gauge->initEnergyHeight(Wenergy_h);
hud_gauge->initTextOffsets(Wenergy_text_offsets[0], Wenergy_text_offsets[1]);
hud_gauge->initAlignments(text_alignment, weapon_alignment);
@@ -1915,6 +1918,7 @@ void load_gauge_escort_view(gauge_settings* settings)
}
hud_gauge->initBitmaps(fname_top, fname_middle, fname_bottom);
hud_gauge->initHiRes(fname_top);
hud_gauge->initEntryHeight(entry_h);
hud_gauge->initEntryStaggerWidth(entry_stagger_w);
hud_gauge->initBottomBgOffset(bottom_bg_offset);
@@ -1976,6 +1980,7 @@ void load_gauge_afterburner(gauge_settings* settings)
hud_gauge->initEnergyHeight(energy_h);
hud_gauge->initBitmaps(fname);
hud_gauge->initHiRes(fname);
gauge_assign_common(settings, std::move(hud_gauge));
}
@@ -2018,6 +2023,7 @@ void load_gauge_mission_time(gauge_settings* settings)
hud_gauge->initTextOffsets(time_text_offsets[0], time_text_offsets[1]);
hud_gauge->initValueOffsets(time_val_offsets[0], time_val_offsets[1]);
hud_gauge->initBitmaps(fname);
hud_gauge->initHiRes(fname);
gauge_assign_common(settings, std::move(hud_gauge));
}
@@ -2111,6 +2117,7 @@ void load_gauge_threat_indicator(gauge_settings* settings)
}
hud_gauge->initBitmaps(fname_arc, fname_laser, fname_lock);
hud_gauge->initHiRes(fname_arc);
hud_gauge->initLaserWarnOffsets(Laser_warn_offsets[0], Laser_warn_offsets[1]);
hud_gauge->initLockWarnOffsets(Lock_warn_offsets[0], Lock_warn_offsets[1]);
@@ -2178,6 +2185,7 @@ void load_gauge_center_reticle(gauge_settings* settings)
stuff_int(&autoaim_frame);
hud_gauge->initBitmaps(fname);
hud_gauge->initHiRes(fname);
hud_gauge->initFirepointDisplay(firepoints, scaleX, scaleY, size);
hud_gauge->setAutoaimFrame(autoaim_frame);
@@ -2351,6 +2359,7 @@ void load_gauge_throttle(gauge_settings* settings)
hud_gauge->initGlideOffsets(glide_offset[0], glide_offset[1], custom_glide);
hud_gauge->initMatchSpeedOffsets(match_speed_offset[0], match_speed_offset[1], custom_match);
hud_gauge->initBitmaps(fname);
hud_gauge->initHiRes(fname);
hud_gauge->showBackground(show_background);
gauge_assign_common(settings, std::move(hud_gauge));
@@ -2435,6 +2444,7 @@ void load_gauge_ets_retail(gauge_settings* settings)
hud_gauge->initBottomOffsets(bottom_offsets[0], bottom_offsets[1]);
hud_gauge->initBarHeight(bar_h);
hud_gauge->initBitmaps(fname);
hud_gauge->initHiRes(fname);
hud_gauge->initGaugePositions(gauge_positions);
gauge_assign_common(settings, std::move(hud_gauge));
@@ -2502,6 +2512,7 @@ void load_gauge_ets_weapons(gauge_settings* settings)
hud_gauge->initBottomOffsets(bottom_offsets[0], bottom_offsets[1]);
hud_gauge->initBarHeight(bar_h);
hud_gauge->initBitmaps(fname);
hud_gauge->initHiRes(fname);
gauge_assign_common(settings, std::move(hud_gauge));
}
@@ -2565,6 +2576,7 @@ void load_gauge_ets_shields(gauge_settings* settings)
hud_gauge->initBarHeight(bar_h);
hud_gauge->initBitmaps(fname);
hud_gauge->initHiRes(fname);
hud_gauge->initBottomOffsets(bottom_offsets[0], bottom_offsets[1]);
hud_gauge->initLetter(letter);
hud_gauge->initLetterOffsets(letter_offsets[0], letter_offsets[1]);
@@ -2633,6 +2645,7 @@ void load_gauge_ets_engines(gauge_settings* settings)
hud_gauge->initBarHeight(bar_h);
hud_gauge->initBitmaps(fname);
hud_gauge->initHiRes(fname);
hud_gauge->initBottomOffsets(bottom_offsets[0], bottom_offsets[1]);
hud_gauge->initLetter(letter);
hud_gauge->initLetterOffsets(letter_offsets[0], letter_offsets[1]);
@@ -2708,6 +2721,7 @@ void load_gauge_extra_target_data(gauge_settings* settings)
}
hud_gauge->initBitmaps(fname);
hud_gauge->initHiRes(fname);
hud_gauge->initBracketOffsets(bracket_offsets[0], bracket_offsets[1]);
hud_gauge->initDockOffsets(dock_offsets[0], dock_offsets[1]);
hud_gauge->initDockMaxWidth(dock_max_w);
@@ -2830,6 +2844,7 @@ void load_gauge_radar_std(gauge_settings* settings)
// Only load this if the user hasn't specified a preference
if (Cmdline_orb_radar == 0) {
hud_gauge->initBitmaps(fname);
hud_gauge->initHiRes(fname);
hud_gauge->initBlipRadius(Radar_blip_radius_normal, Radar_blip_radius_target);
hud_gauge->initCenterOffsets(Radar_center_offsets[0], Radar_center_offsets[1]);
hud_gauge->initDistanceInfinityOffsets(Radar_dist_offsets[2][0], Radar_dist_offsets[2][1]);
@@ -2926,6 +2941,7 @@ void load_gauge_radar_orb(gauge_settings* settings)
//only load this if the user actually wants to use the orb radar.
if (Cmdline_orb_radar == 1) {
hud_gauge->initBitmaps(fname);
hud_gauge->initHiRes(fname);
hud_gauge->initBlipRadius(Radar_blip_radius_normal, Radar_blip_radius_target);
hud_gauge->initCenterOffsets(Radar_center_offsets[0], Radar_center_offsets[1]);
hud_gauge->initDistanceInfinityOffsets(Radar_dist_offsets[2][0], Radar_dist_offsets[2][1]);
@@ -3126,6 +3142,7 @@ void load_gauge_radar_dradis(gauge_settings* settings)
hud_gauge->initRadius(Radar_radius[0], Radar_radius[1]);
hud_gauge->initBitmaps(xy_fname, xz_yz_fname, sweep_fname, target_fname, unknown_fname);
hud_gauge->initHiRes(xy_fname);
hud_gauge->initCockpitTarget(display_name, display_offset[0], display_offset[1], display_size[0], display_size[1], canvas_size[0], canvas_size[1]);
hud_gauge->initSound(loop_snd, loop_snd_volume, arrival_beep_snd, departure_beep_snd, stealth_arrival_snd, stealth_departure_snd, arrival_beep_delay, departure_beep_delay);
hud_gauge->initChase_view_only(settings->chase_view_only);
@@ -3345,6 +3362,7 @@ void load_gauge_target_monitor(gauge_settings* settings)
hud_gauge->initGaugeWirecolor(wirecolor);
hud_gauge->initGaugeWirecolorOverride(wirecoloroverride);
hud_gauge->initBitmaps(fname_monitor, fname_monitor_mask, fname_integrity, fname_static);
hud_gauge->initHiRes(fname_monitor);
gauge_assign_common(settings, std::move(hud_gauge));
}
@@ -3429,6 +3447,7 @@ void load_gauge_squad_message(gauge_settings* settings)
}
hud_gauge->initBitmaps(fname_top, fname_middle, fname_bottom);
hud_gauge->initHiRes(fname_top);
hud_gauge->initHeaderOffsets(Header_offsets[0], Header_offsets[1]);
hud_gauge->initItemStartOffsets(Item_start_offsets[0], Item_start_offsets[1]);
hud_gauge->initMiddleFrameStartOffsetY(Middle_frame_start_offset_y);
@@ -3501,6 +3520,7 @@ void load_gauge_objective_notify(gauge_settings* settings)
}
hud_gauge->initBitmaps(fname);
hud_gauge->initHiRes(fname);
hud_gauge->initObjTextOffsetY(Objective_text_offset_y);
hud_gauge->initObjValueOffsetY(Objective_text_val_offset_y);
hud_gauge->initSubspaceTextOffsetY(Subspace_text_offset_y);
@@ -3769,6 +3789,7 @@ void load_gauge_directives(gauge_settings* settings)
}
hud_gauge->initBitmaps(fname_top, fname_middle, fname_bottom);
hud_gauge->initHiRes(fname_top);
hud_gauge->initMiddleFrameOffsetY(middle_frame_offset_y);
hud_gauge->initTextHeight(text_h);
hud_gauge->initBottomBgOffset(bottom_bg_offset);
@@ -3827,6 +3848,7 @@ void load_gauge_talking_head(gauge_settings* settings)
hud_gauge->initAnimOffsets(Anim_offsets[0], Anim_offsets[1]);
hud_gauge->initAnimSizes(Anim_size[0], Anim_size[1]);
hud_gauge->initBitmaps(fname);
hud_gauge->initHiRes(fname);
hud_gauge->initHeaderOffsets(Header_offsets[0], Header_offsets[1]);
gauge_assign_common(settings, std::move(hud_gauge));
@@ -3866,6 +3888,7 @@ void load_gauge_countermeasures(gauge_settings* settings)
}
hud_gauge->initBitmaps(fname);
hud_gauge->initHiRes(fname);
hud_gauge->initCountTextOffsets(cm_text_offset[0], cm_text_offset[1]);
hud_gauge->initCountValueOffsets(cm_text_val_offset[0], cm_text_val_offset[1]);
@@ -3924,6 +3947,7 @@ void load_gauge_auto_target(gauge_settings* settings)
hud_gauge->initAutoTextOffsets(auto_text_offset[0], auto_text_offset[1]);
hud_gauge->initBitmaps(fname);
hud_gauge->initHiRes(fname);
hud_gauge->initTargetTextOffsets(target_text_offset[0], target_text_offset[1]);
hud_gauge->initOnColor(on_color[0], on_color[1], on_color[2], on_color[3]);
hud_gauge->initOffColor(off_color[0], off_color[1], off_color[2], off_color[3]);
@@ -3982,6 +4006,7 @@ void load_gauge_auto_speed(gauge_settings* settings)
hud_gauge->initAutoTextOffsets(auto_text_offset[0], auto_text_offset[1]);
hud_gauge->initBitmaps(fname);
hud_gauge->initHiRes(fname);
hud_gauge->initSpeedTextOffsets(speed_text_offset[0], speed_text_offset[1]);
hud_gauge->initOnColor(on_color[0], on_color[1], on_color[2], on_color[3]);
hud_gauge->initOffColor(off_color[0], off_color[1], off_color[2], off_color[3]);
@@ -4121,6 +4146,7 @@ void load_gauge_wingman_status(gauge_settings* settings)
}
hud_gauge->initBitmaps(fname_left, fname_middle, fname_right, fname_dots);
hud_gauge->initHiRes(fname_left);
hud_gauge->initHeaderOffsets(header_offsets[0], header_offsets[1]);
hud_gauge->initFixedHeaderPosition(fixed_header_position);
hud_gauge->initLeftFrameEndX(left_frame_end_x);
@@ -4218,6 +4244,7 @@ void load_gauge_damage(gauge_settings* settings)
}
hud_gauge->initBitmaps(fname_top, fname_middle, fname_bottom);
hud_gauge->initHiRes(fname_top);
hud_gauge->initHullIntegOffsets(hull_integ_offsets[0], hull_integ_offsets[1]);
hud_gauge->initHullIntegValueOffsetX(hull_integ_val_offset_x);
hud_gauge->initLineHeight(line_h);
@@ -4285,6 +4312,7 @@ void load_gauge_support(gauge_settings* settings)
}
hud_gauge->initBitmaps(fname);
hud_gauge->initHiRes(fname);
hud_gauge->initHeaderOffsets(header_offsets[0], header_offsets[1]);
hud_gauge->initTextDockOffsetX(text_dock_offset_x);
hud_gauge->initTextDockValueOffsetX(text_dock_val_offset_x);
@@ -4504,6 +4532,7 @@ void load_gauge_weapon_linking(gauge_settings* settings)
hud_gauge->init2SecondaryOffsets(Weapon_link_offsets[LINK_TWO_SECONDARY][0], Weapon_link_offsets[LINK_TWO_SECONDARY][1]);
hud_gauge->init3SecondaryOffsets(Weapon_link_offsets[LINK_THREE_SECONDARY][0], Weapon_link_offsets[LINK_THREE_SECONDARY][1]);
hud_gauge->initBitmaps(fname_arc, fname_primary_link_1, fname_primary_link_2, fname_secondary_link_1, fname_secondary_link_2, fname_secondary_link_3);
hud_gauge->initHiRes(fname_arc);
gauge_assign_common(settings, std::move(hud_gauge));
}
@@ -4688,10 +4717,11 @@ void load_gauge_lock(gauge_settings* settings)
stuff_boolean(&loop_locked_anim);
}
if(optional_string("Blink Locked Animation:")) {
stuff_boolean(&loop_locked_anim);
stuff_boolean(&blink_locked_anim);
}
hud_gauge->initBitmaps(fname_lock, fname_spin);
hud_gauge->initHiRes(fname_lock);
hud_gauge->initLoopLockedAnim(loop_locked_anim);
hud_gauge->initBlinkLockedAnim(blink_locked_anim);
hud_gauge->initGaugeHalfSize(Lock_gauge_half_w, Lock_gauge_half_h);
@@ -4766,6 +4796,7 @@ void load_gauge_brackets(gauge_settings* settings)
}
hud_gauge->initBitmaps(fname);
hud_gauge->initHiRes(fname);
hud_gauge->initMinSubTargetBoxSizes(min_subtarget_box[0], min_subtarget_box[1]);
hud_gauge->initMinTargetBoxSizes(min_target_box[0], min_target_box[1]);
@@ -4957,6 +4988,7 @@ void load_gauge_lead(gauge_settings* settings)
hud_gauge->initHalfSize(Lead_indicator_half[0], Lead_indicator_half[1]);
hud_gauge->initBitmaps(fname);
hud_gauge->initHiRes(fname);
gauge_assign_common(settings, std::move(hud_gauge));
}
@@ -5015,6 +5047,7 @@ void load_gauge_lead_sight(gauge_settings* settings)
}
hud_gauge->initBitmaps(fname);
hud_gauge->initHiRes(fname);
gauge_assign_common(settings, std::move(hud_gauge));
}
@@ -5059,6 +5092,7 @@ void load_gauge_kills(gauge_settings* settings)
}
hud_gauge->initBitmaps(fname);
hud_gauge->initHiRes(fname);
hud_gauge->initTextOffsets(text_offsets[0], text_offsets[1]);
hud_gauge->initTextValueOffsets(text_value_offsets[0], text_value_offsets[1]);
@@ -5299,6 +5333,7 @@ void load_gauge_primary_weapons(gauge_settings* settings)
}
hud_gauge->initBitmaps(fname_first, fname_entry, fname_last);
hud_gauge->initHiRes(fname_first);
hud_gauge->initHeaderOffsets(header_offsets[0], header_offsets[1]);
hud_gauge->initHeaderText(header_text);
hud_gauge->initBgFirstHeight(first_bg_h);
@@ -5413,6 +5448,7 @@ void load_gauge_secondary_weapons(gauge_settings* settings)
}
hud_gauge->initBitmaps(fname_first, fname_entry, fname_last);
hud_gauge->initHiRes(fname_first);
hud_gauge->initHeaderOffsets(header_offsets[0], header_offsets[1]);
hud_gauge->initHeaderText(header_text);
hud_gauge->initBgFirstHeight(first_bg_h);
+1 -1
View File
@@ -2635,7 +2635,7 @@ bool HudGaugeSquadMessage::maybeFlashPageScroll(bool flash_fast)
return draw_bright;
}
bool HudGaugeSquadMessage::canRender()
bool HudGaugeSquadMessage::canRender() const
{
if(hud_disabled_except_messages() && !message_gauge) {
return false;
+1 -1
View File
@@ -213,7 +213,7 @@ public:
void initPgDnOffsets(int x, int y);
void render(float frametime) override;
bool canRender() override;
bool canRender() const override;
void pageIn() override;
void initialize() override;
void startFlashPageScroll(int duration = 1400);
+22 -10
View File
@@ -470,7 +470,7 @@ int hud_target_invalid_awacs(object *objp)
}
// check for invalid status
if((Player_ship != NULL) && (awacs_get_level(objp, Player_ship) < 1.0f)){
if((Player_ship != nullptr) && (awacs_get_level(objp, Player_ship) < 1.0f)){
return 1;
}
@@ -872,7 +872,7 @@ void hud_target_hotkey_select( int k )
// a simple walk of the list to get the count
for ( hitem = GET_FIRST(plist); hitem != END_OF_LIST(plist); hitem = GET_NEXT(hitem) ){
if (awacs_get_level(hitem->objp, Player_ship, 1) > 1) {
if (awacs_get_level(hitem->objp, Player_ship, true) > 1.0f) {
visible_count++;
}
}
@@ -894,7 +894,7 @@ void hud_target_hotkey_select( int k )
first_target = NULL;
for ( hitem = GET_FIRST(plist); hitem != END_OF_LIST(plist); hitem = GET_NEXT(hitem) ) {
if (awacs_get_level(hitem->objp, Player_ship, 1) > 1) {
if (awacs_get_level(hitem->objp, Player_ship, true) > 1.0f) {
// get the first valid target
if (first_target == NULL) {
first_target = hitem;
@@ -939,7 +939,7 @@ void hud_target_hotkey_select( int k )
// next is before current target, so search from start of list
for ( hitem = GET_FIRST(plist); hitem != END_OF_LIST(plist); hitem = GET_NEXT(hitem) ) {
if (awacs_get_level(hitem->objp, Player_ship, 1) > 1) {
if (awacs_get_level(hitem->objp, Player_ship, true) > 1.0f) {
target = hitem;
break;
}
@@ -1830,7 +1830,7 @@ void hud_target_live_turret(int next_flag, int auto_advance, int only_player_tar
distance = vm_vec_normalized_dir(&vec_to_subsys, &gsubpos, &View_position);
// check if facing and in view
int facing = ship_subsystem_in_sight(objp, A, &View_position, &gsubpos, 0);
bool facing = ship_subsystem_in_sight(objp, A, &View_position, &gsubpos, false);
if (!auto_advance && get_closest_turret && !only_player_target) {
// if within 3 degrees and not previous subsys, use subsys in front
@@ -2334,7 +2334,7 @@ void hud_update_closest_turret()
}
// check if facing and in view
int facing = ship_subsystem_in_sight(objp, ss, &View_position, &gsubpos, 0);
bool facing = ship_subsystem_in_sight(objp, ss, &View_position, &gsubpos, false);
if (facing) {
new_distance *= 0.5f;
@@ -2627,12 +2627,24 @@ void hud_target_in_reticle_old()
target_obj = hud_reticle_pick_target();
if ( target_obj != NULL ) {
int oldTargetNum = Player_ai->target_objnum;
set_target_objnum( Player_ai, OBJ_INDEX(target_obj) );
hud_shield_hit_reset(target_obj);
if ( target_obj->type == OBJ_SHIP ) {
hud_maybe_set_sorted_turret_subsys(&Ships[target_obj->instance]);
hud_restore_subsystem_target(&Ships[target_obj->instance]);
ship* shipp = &Ships[target_obj->instance];
// if the player is attempting to target the same ship under their reticule again
// then lets select the nearest subsystem for them.
if (Automatically_select_subsystem_under_reticle_when_targeting_same_ship &&
Ship_info[shipp->ship_info_index].is_big_or_huge() &&
oldTargetNum == Player_ai->target_objnum) {
hud_target_subsystem_in_reticle();
}
else {
hud_maybe_set_sorted_turret_subsys(shipp);
hud_restore_subsystem_target(shipp);
}
}
}
else {
@@ -3426,7 +3438,7 @@ void hud_show_selection_set()
// Goober5000 - don't draw indicators for non-visible ships, per Mantis #1972
// (the only way we could get here is if the hotkey set contained a mix of visible
// and invisible ships)
if (awacs_get_level(targetp, Player_ship, 1) < 1) {
if (awacs_get_level(targetp, Player_ship, true) < 1.0f) {
continue;
}
@@ -3590,7 +3602,7 @@ void hud_show_hostile_triangle()
}
// check if ship is stealthy
if (awacs_get_level(&Objects[sp->objnum], Player_ship, 1) < 1) {
if (awacs_get_level(&Objects[sp->objnum], Player_ship, true) < 1.0f) {
continue;
}
+1 -1
View File
@@ -1906,7 +1906,7 @@ int hud_targetbox_subsystem_in_view(object *target_objp, int *sx, int *sy)
// is it subsystem in view
if ( Player->subsys_in_view == -1 ) {
rval = ship_subsystem_in_sight(target_objp, subsys, &View_position, &subobj_pos, 0);
rval = ship_subsystem_in_sight(target_objp, subsys, &View_position, &subobj_pos, false) ? 1 : 0;
} else {
rval = Player->subsys_in_view;
}
+16 -10
View File
@@ -24,6 +24,10 @@ int radar_iff_color[5][2][4];
int iff_bright_delta;
int *iff_color_brightness = &iff_bright_delta;
int IFF_COLOR_SELECTION = 0;
int IFF_COLOR_MESSAGE = 1;
int IFF_COLOR_TAGGED = 2;
// global only to file
SCP_vector <std::pair<color, color>> Iff_colors; // AL 1-2-97: Create two IFF colors, regular and bright
@@ -249,28 +253,28 @@ void parse_iff_table(const char* filename)
if ((optional_string("$Selection Color:")) || (optional_string("$Selection Colour:")))
{
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
iff_init_color(rgb[0], rgb[1], rgb[2]);
IFF_COLOR_SELECTION = iff_init_color(rgb[0], rgb[1], rgb[2]);
}
else
iff_init_color(0xff, 0xff, 0xff);
else if (!Parsing_modular_table)
IFF_COLOR_SELECTION = iff_init_color(0xff, 0xff, 0xff);
// Marks the ship currently saying something
if ((optional_string("$Message Color:")) || (optional_string("$Message Colour:")))
{
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
iff_init_color(rgb[0], rgb[1], rgb[2]);
IFF_COLOR_MESSAGE = iff_init_color(rgb[0], rgb[1], rgb[2]);
}
else
iff_init_color(0x7f, 0x7f, 0x7f);
else if (!Parsing_modular_table)
IFF_COLOR_MESSAGE = iff_init_color(0x7f, 0x7f, 0x7f);
// Marks the tagged ships
if ((optional_string("$Tagged Color:")) || (optional_string("$Tagged Colour:")))
{
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
iff_init_color(rgb[0], rgb[1], rgb[2]);
IFF_COLOR_TAGGED = iff_init_color(rgb[0], rgb[1], rgb[2]);
}
else
iff_init_color(0xff, 0xff, 0x00);
else if (!Parsing_modular_table)
IFF_COLOR_TAGGED = iff_init_color(0xff, 0xff, 0x00);
// init radar blips colour table
int a_bright, a_dim;
@@ -579,7 +583,9 @@ int iff_lookup(const char *iff_name)
*/
int iff_get_attackee_mask(int attacker_team)
{
Assert(attacker_team >= 0 && attacker_team < (int)Iff_info.size());
Assertion(SCP_vector_inbounds(Iff_info, attacker_team), "Attempted to get the attackee mask of an attacker team that is out of bounds");
if (!SCP_vector_inbounds(Iff_info, attacker_team))
return 0;
// All teams attack all other teams.
if (Mission_all_attack)
+4 -3
View File
@@ -17,9 +17,10 @@
class object;
// Goober5000 - new IFF color system
#define IFF_COLOR_SELECTION 0
#define IFF_COLOR_MESSAGE 1
#define IFF_COLOR_TAGGED 2
// Now variables so that modular tables can actually affect them. -MageKing17
extern int IFF_COLOR_SELECTION;
extern int IFF_COLOR_MESSAGE;
extern int IFF_COLOR_TAGGED;
enum IFF_hotkey_team { Default = -1, None = 0, Friendly, Hostile };
+4 -4
View File
@@ -241,7 +241,7 @@ SCP_vector<Joystick*> joystick_enumerator()
auto JoystickOption = options::OptionBuilder<Joystick*>("Input.Joystick",
std::pair<const char*, int>{"Joystick 0", 1705},
std::pair<const char*, int>{"The current joystick 0", 1706})
.category("Input") // Category this option shows up in the scripting heirachy
.category(std::make_pair("Input", 1827)) // Category this option shows up in the scripting heirachy
.deserializer(joystick_deserialize) // callback for json to C++
.serializer(joystick_serializer) // callback for C++ to json
.display(joystick_display) // callback for constructing the display label
@@ -255,7 +255,7 @@ auto JoystickOption = options::OptionBuilder<Joystick*>("Input.Joystick",
auto JoystickOption1 = options::OptionBuilder<Joystick*>("Input.Joystick1",
std::pair<const char*, int>{"Joystick 1", 1707},
std::pair<const char*, int>{"The current joystick 1", 1708})
.category("Input")
.category(std::make_pair("Input", 1827))
.deserializer(joystick_deserialize)
.serializer(joystick_serializer)
.display(joystick_display)
@@ -269,7 +269,7 @@ auto JoystickOption1 = options::OptionBuilder<Joystick*>("Input.Joystick1",
auto JoystickOption2 = options::OptionBuilder<Joystick*>("Input.Joystick2",
std::pair<const char*, int>{"Joystick 2", 1709},
std::pair<const char*, int>{"The current joystick 2", 1710})
.category("Input")
.category(std::make_pair("Input", 1827))
.deserializer(joystick_deserialize)
.serializer(joystick_serializer)
.display(joystick_display)
@@ -283,7 +283,7 @@ auto JoystickOption2 = options::OptionBuilder<Joystick*>("Input.Joystick2",
auto JoystickOption3 = options::OptionBuilder<Joystick*>("Input.Joystick3",
std::pair<const char*, int>{"Joystick 3", 1711},
std::pair<const char*, int>{"The current joystick 3", 1712})
.category("Input")
.category(std::make_pair("Input", 1827))
.deserializer(joystick_deserialize)
.serializer(joystick_serializer)
.display(joystick_display)
+3 -3
View File
@@ -49,7 +49,7 @@ static haptic_effect_t pExplode;
static auto ForceFeedbackOption = options::OptionBuilder<bool>("Input.ForceFeedback",
std::pair<const char*, int>{"Force Feedback", 1728},
std::pair<const char*, int>{"Enable or disable force feedback", 1729})
.category("Input")
.category(std::make_pair("Input", 1827))
.level(options::ExpertLevel::Beginner)
.default_val(false)
.finish();
@@ -57,7 +57,7 @@ static auto ForceFeedbackOption = options::OptionBuilder<bool>("Input.ForceFeedb
static auto HitEffectOption = options::OptionBuilder<bool>("Input.HitEffect",
std::pair<const char*, int>{"Directional Hit", 1730},
std::pair<const char*, int>{"Enable or disable the directional hit effect", 1731})
.category("Input")
.category(std::make_pair("Input", 1827))
.level(options::ExpertLevel::Beginner)
.default_val(false)
.finish();
@@ -65,7 +65,7 @@ static auto HitEffectOption = options::OptionBuilder<bool>("Input.HitEffect",
static auto ForceFeedbackStrength = options::OptionBuilder<float>("Input.FFStrength",
std::pair<const char*, int>{"Force Feedback Strength", 1756},
std::pair<const char*, int>{"The realtive strength of Force Feedback effects", 1757})
.category("Input")
.category(std::make_pair("Input", 1827))
.level(options::ExpertLevel::Beginner)
.range(0, 100)
.default_val(100)
+5 -3
View File
@@ -59,12 +59,13 @@ int Mouse_sensitivity = 4;
static auto MouseSensitivityOption __UNUSED = options::OptionBuilder<int>("Input.MouseSensitivity",
std::pair<const char*, int>{"Sensitivity", 1374},
std::pair<const char*, int>{"The sensitivity of the mouse input", 1747})
.category("Input")
.category(std::make_pair("Input", 1827))
.range(0, 9)
.level(options::ExpertLevel::Beginner)
.default_val(4)
.bind_to(&Mouse_sensitivity)
.importance(0)
.flags({options::OptionFlags::RetailBuiltinOption})
.finish();
bool Use_mouse_to_fly = false;
@@ -72,14 +73,15 @@ bool Use_mouse_to_fly = false;
static SCP_string mouse_mode_display(bool mode) { return mode ? XSTR("Joy-0", 1699) : XSTR("Mouse", 1774); }
static auto UseMouseOption __UNUSED = options::OptionBuilder<bool>("Input.UseMouse",
std::pair<const char*, int>{"Mouse", 1376},
std::pair<const char*, int>{"Mouse", 1373},
std::pair<const char*, int>{"Whether or not to use the mouse for flying", 1765})
.category("Input")
.category(std::make_pair("Input", 1827))
.display(mouse_mode_display)
.level(options::ExpertLevel::Beginner)
.default_val(false)
.bind_to(&Use_mouse_to_fly)
.importance(1)
.flags({options::OptionFlags::RetailBuiltinOption})
.finish();
const std::shared_ptr<scripting::Hook<>> OnMouseWheelHook = scripting::Hook<>::Factory(
+1 -1
View File
@@ -160,7 +160,7 @@ namespace ltp = lighting_profiles;
using namespace ltp;
bool graphics_options_changed()
{
auto stored_settings = getLabManager()->graphicsSettings;
const auto& stored_settings = getLabManager()->graphicsSettings;
if (stored_settings.ambient_factor != ltp::lab_get_ambient())
return true;
+10 -6
View File
@@ -1,14 +1,15 @@
#include "lab/renderer/lab_renderer.h"
#include "freespace.h"
#include "globalincs/vmallocator.h"
#include "lab/labv2_internal.h"
#include "graphics/2d.h"
#include "graphics/light.h"
#include "lab/labv2_internal.h"
#include "lab/renderer/lab_renderer.h"
#include "lighting/lighting_profiles.h"
#include "math/bitarray.h"
#include "nebula/neb.h"
#include "parse/parselo.h"
#include "starfield/starfield.h"
#include "starfield/nebula.h"
#include "nebula/neb.h"
#include "freespace.h"
#include "missionui/missionscreencommon.h"
#include "tracing/tracing.h"
@@ -347,7 +348,7 @@ void LabRenderer::useBackground(const SCP_string& mission_name) {
(ambient_light_level >> 16) & 0xff);
strcpy_s(Neb2_texture_name, "");
Neb2_poof_flags = 0;
clear_all_bits(Neb2_poof_flags.get(), Poof_info.size());
bool nebula = false;
if (optional_string("+Neb2:")) {
nebula = true;
@@ -364,8 +365,11 @@ void LabRenderer::useBackground(const SCP_string& mission_name) {
}
if (nebula){
// Obsolete and only for backwards compatibility
if (optional_string("+Neb2Flags:")) {
stuff_int(&Neb2_poof_flags);
int temp;
stuff_int(&temp);
bit_array_set_from_int(Neb2_poof_flags.get(), Poof_info.size(), temp);
}
// Get poofs by name
if (optional_string("+Neb2 Poofs List:")) {
+44 -10
View File
@@ -107,7 +107,7 @@ static bool DeferredLightingEnabled = true;
static auto DeferredLightingOption = options::OptionBuilder<bool>("Graphics.DeferredLighting",
std::pair<const char*, int>{"Deferred Lighting", 1782},
std::pair<const char*, int>{"Enables or disables deferred lighting", 1783})
.category("Graphics")
.category(std::make_pair("Graphics", 1825))
.default_val(true)
.level(options::ExpertLevel::Advanced)
.bind_to_once(&DeferredLightingEnabled)
@@ -176,13 +176,13 @@ static void light_rotate(light * l)
}
}
void light_add_directional(const vec3d* dir, const hdr_color* new_color, const float source_radius)
void light_add_directional(const vec3d* dir, int sun_index, bool no_glare, const hdr_color* new_color, const float source_radius)
{
Assert(new_color!= nullptr);
light_add_directional(dir, new_color->i(), new_color->r(), new_color->g(), new_color->b(), source_radius);
light_add_directional(dir, sun_index, no_glare, new_color->i(), new_color->r(), new_color->g(), new_color->b(), source_radius);
}
namespace ltp=lighting_profiles;
void light_add_directional(const vec3d *dir, float intensity, float r, float g, float b, const float source_radius)
void light_add_directional(const vec3d *dir, int sun_index, bool no_glare, float intensity, float r, float g, float b, const float source_radius)
{
if (Lighting_off) return;
@@ -191,6 +191,8 @@ void light_add_directional(const vec3d *dir, float intensity, float r, float g,
light l;
l.type = Light_Type::Directional;
l.flags = no_glare ? (LF_DEFAULT | LF_NO_GLARE) : LF_DEFAULT;
l.sun_index = sun_index;
vm_vec_copy_scale( &l.vec, dir, -1.0f );
@@ -233,6 +235,8 @@ void light_add_point(const vec3d *pos, float r1, float r2, float intensity, floa
Num_lights++;
l.type = Light_Type::Point;
l.flags = LF_DEFAULT;
l.sun_index = -1;
l.vec = *pos;
l.r = r;
l.g = g;
@@ -272,6 +276,8 @@ void light_add_tube(const vec3d *p0, const vec3d *p1, float r1, float r2, float
Num_lights++;
l.type = Light_Type::Tube;
l.flags = LF_DEFAULT;
l.sun_index = -1;
l.vec = *p0;
l.vec2 = *p1;
l.r = r;
@@ -317,19 +323,46 @@ int light_get_global_count()
* @param pos Position
* @param n Light source
*
* Returns 0 if there is no global light.
* Returns false if there is no global light.
*/
int light_get_global_dir(vec3d *pos, int n)
bool light_get_global_dir(vec3d *pos, int n)
{
if ( (n < 0) || (n >= (int)Static_light.size()) ) {
return 0;
if (!SCP_vector_inbounds(Static_light, n)) {
return false;
}
if (pos) {
*pos = Static_light[n].vec;
vm_vec_scale( pos, -1.0f );
}
return 1;
return true;
}
bool light_has_glare(int n)
{
if (!SCP_vector_inbounds(Static_light, n)) {
return false;
}
return (Static_light[n].flags & LF_NO_GLARE) == 0;
}
int light_get_sun_index(int n)
{
if (!SCP_vector_inbounds(Static_light, n)) {
return -1;
}
return Static_light[n].sun_index;
}
int light_find_for_sun(int sun_index)
{
for (size_t n = 0; n < Static_light.size(); ++n)
if (Static_light[n].sun_index == sun_index)
return static_cast<int>(n);
return -1;
}
void light_apply_rgb( ubyte *param_r, ubyte *param_g, ubyte *param_b, const vec3d *pos, const vec3d *norm, float static_light_level )
@@ -478,11 +511,12 @@ void light_add_cone(const vec3d *pos, const vec3d *dir, float angle, float inner
Num_lights++;
l.type = Light_Type::Cone;
l.flags = dual_cone ? (LF_DEFAULT | LF_DUAL_CONE) : LF_DEFAULT;
l.sun_index = -1;
l.vec = *pos;
l.vec2= *dir;
l.cone_angle = angle;
l.cone_inner_angle = inner_angle;
l.dual_cone = dual_cone;
l.r = r;
l.g = g;
l.b = b;
+15 -5
View File
@@ -47,11 +47,16 @@ typedef struct light {
float r,g,b; // The color components of the light
float cone_angle; // angle for cone lights
float cone_inner_angle; // the inner angle for calculating falloff
bool dual_cone; // should the cone be shining in both directions?
int flags; // see below
int sun_index; // if this light corresponds to a sun
float source_radius; // The actual size of the object or volume emitting the light
int instance;
} light;
#define LF_DUAL_CONE (1<<0) // should the cone be shining in both directions?
#define LF_NO_GLARE (1<<1) // for example, a sun with $NoGlare
#define LF_DEFAULT 0 // no flags by default
extern SCP_vector<light> Static_light;
struct light_indexing_info
@@ -91,8 +96,8 @@ extern void light_reset();
//Intensity in lighting inputs multiplies the base colors.
extern void light_add_directional(const vec3d *dir, const hdr_color *new_color, const float source_radius = 0.0f );
extern void light_add_directional(const vec3d *dir, float intensity, float r, float g, float b, const float source_radius = 0.0f);
extern void light_add_directional(const vec3d *dir, int sun_index, bool no_glare, const hdr_color *new_color, const float source_radius = 0.0f );
extern void light_add_directional(const vec3d *dir, int sun_index, bool no_glare, float intensity, float r, float g, float b, const float source_radius = 0.0f);
extern void light_add_point(const vec3d * pos, float r1, float r2, const hdr_color *new_color, const float source_radius = 0.0f);
extern void light_add_point(const vec3d * pos, float r1, float r2, float intensity, float r, float g, float b, const float source_radius = 0.0f);
extern void light_add_tube(const vec3d *p0, const vec3d *p1, float r1, float r2, const hdr_color *new_color, const float source_radius = 0.0f);
@@ -110,8 +115,13 @@ void light_apply_rgb( ubyte *param_r, ubyte *param_g, ubyte *param_b, const vec3
extern int light_get_global_count();
// Fills direction of global light source N in pos.
// Returns 0 if there is no global light.
extern int light_get_global_dir(vec3d *pos, int n);
// Returns false if there is no global light.
extern bool light_get_global_dir(vec3d *pos, int n);
extern bool light_has_glare(int n);
extern int light_get_sun_index(int n);
extern int light_find_for_sun(int sun_index);
bool light_compare_by_type(const light &a, const light &b);
+2 -2
View File
@@ -64,7 +64,7 @@ bool *Lcl_unexpected_tstring_check = nullptr;
// NOTE: with map storage of XSTR strings, the indexes no longer need to be contiguous,
// but internal strings should still increment XSTR_SIZE to avoid collisions.
// retail XSTR_SIZE = 1570
// #define XSTR_SIZE 1816 // This is the next available ID
// #define XSTR_SIZE 1842 // This is the next available ID
// struct to allow for strings.tbl-determined x offset
@@ -152,7 +152,7 @@ auto LanguageOption = options::OptionBuilder<int>("Game.Language",
return false; //This makes it so that changing the language requires a game restart
})
.flags({options::OptionFlags::ForceMultiValueSelection})
.category("Game")
.category(std::make_pair("Game", 1824))
.default_val(0)
.finish();
+51 -1
View File
@@ -42,8 +42,58 @@
#define toggle_bit(array, bitnum) (((ubyte *) array)[(bitnum) >> 3] ^= (1 << ((bitnum) & 7)))
// calculate number of bytes from number of bits
// calculates number of bytes from number of bits
#define calculate_num_bytes(num_bits) ((num_bits >> 3) + 1)
// zeroes out all bits in the bit array
#define clear_all_bits(array, num_bits) memset(array, 0, calculate_num_bytes(num_bits))
// tests whether any bit in this bit array is nonzero
template <class N_TYPE>
bool any_bits_set(void *array, N_TYPE num_bits)
{
auto bytes = static_cast<ubyte*>(array);
N_TYPE num_bytes = calculate_num_bytes(num_bits);
for (N_TYPE i = 0; i < num_bytes; ++i)
if (bytes[i] != 0)
return true;
return false;
}
// copies a bit array into an int so that they contain equivalent values, up to the capacity of the int type
template <class N_TYPE>
int bit_array_as_int(void *array, N_TYPE num_bits)
{
int rval = 0;
auto bytes = static_cast<ubyte*>(array);
N_TYPE num_bytes = calculate_num_bytes(num_bits);
for (N_TYPE i = 0; i < num_bytes && i < sizeof(int); ++i)
{
rval = rval << 3;
rval |= bytes[i];
}
return rval;
}
// copies an int into a bit array so that they contain equivalent values; any bits in the bit array higher than the capacity of an int are zeroed out
template <class N_TYPE>
void bit_array_set_from_int(void *array, N_TYPE num_bits, int input)
{
auto bytes = static_cast<ubyte*>(array);
N_TYPE num_bytes = calculate_num_bytes(num_bits);
for (N_TYPE i = 0; i < num_bytes; ++i)
{
if (i < sizeof(int))
{
bytes[i] = input & 255;
input = input >> 3;
}
else
bytes[i] = 0;
}
}
#endif // _BIT_ARRAY_H
+1 -1
View File
@@ -4,7 +4,7 @@
SCP_vector<Curve> Curves;
int curve_get_by_name(SCP_string& in_name) {
int curve_get_by_name(const SCP_string& in_name) {
for (int i = 0; i < (int)Curves.size(); i++) {
if (lcase_equal(Curves[i].name, in_name))
return i;
+1 -1
View File
@@ -43,6 +43,6 @@ public :
extern SCP_vector<Curve> Curves;
extern int curve_get_by_name(SCP_string& in_name);
extern int curve_get_by_name(const SCP_string& in_name);
extern void curves_init();
+2 -2
View File
@@ -22,13 +22,13 @@
*/
float fl_roundoff(float x, int multiple)
{
float half = (float) multiple / 2.0f;
float half = multiple / 2.0f;
if (x < 0)
half = -half;
x += half;
return (float) (((int) x / multiple) * multiple);
return i2fl((fl2i(x) / multiple) * multiple);
}
/**
+8 -56
View File
@@ -30,67 +30,19 @@ inline bool fl_is_nan(float fl) {
#define fl_sqrt(fl) sqrtf(fl)
#define fl_isqrt(fl) (1.0f/sqrtf(fl))
#define fl_abs(fl) fabsf(fl)
#define i2fl(i) ((float)(i))
#define fl2i(fl) ((int)(fl))
#define fl2ir(fl) ((int)(fl + ((fl < 0.0f) ? -0.5f : 0.5f)))
#define flceil(fl) (int)ceil(fl)
#define flfloor(fl) (int)floor(fl)
#define f2fl(fx) ((float)(fx)/65536.0f)
#define f2d(fx) (((double)(fx))/65536.0)
#define fl2f(fl) (int)((fl)*65536.0f)
#define i2fl(i) (static_cast<float>(i))
#define fl2i(fl) (static_cast<int>(fl))
#define fl2ir(fl) (static_cast<int>(fl + (((fl) < 0.0f) ? -0.5f : 0.5f)))
#define f2fl(fx) (static_cast<float>(fx)/65536.0f)
#define f2d(fx) (static_cast<double>(fx)/65536.0)
#define fl2f(fl) (static_cast<int>((fl)*65536.0f))
#define fl_tan(fl) tanf(fl)
// convert a measurement in degrees to radians
#define fl_radians(fl) ((float)((fl) * (PI / 180.0f)))
#define fl_radians(fl) (static_cast<float>((fl) * (PI / 180.0f)))
// convert a measurement in radians to degrees
#define fl_degrees(fl) ((float)((fl) * (180.0f / PI)))
// use this instead of:
// for: (int)floor(x+0.5f) use fl_round_2048(x)
// (int)ceil(x-0.5f) use fl_round_2048(x)
// (int)floor(x-0.5f) use fl_round_2048(x-1.0f)
// (int)floor(x) use fl_round_2048(x-0.5f)
// for values in the range -2048 to 2048
// use this instead of:
// for: (int)floor(x+0.5f) use fl_round_2048(x)
// (int)ceil(x-0.5f) use fl_round_2048(x)
// (int)floor(x-0.5f) use fl_round_2048(x-1.0f)
// (int)floor(x) use fl_round_2048(x-0.5f)
// for values in the range -2048 to 2048
/*
extern const float *p_fl_magic;
inline int fl_round_2048( float x )
{
double tmp_quad;
tmp_quad = x + *p_fl_magic;
return *((int *)&tmp_quad);
}
inline float fl_sqrt( float x)
{
float retval;
_asm fld x
_asm fsqrt
_asm fstp retval
return retval;
}
float fl_isqrt( float x )
{
float retval;
_asm fld x
_asm fsqrt
_asm fstp retval
return 1.0f / retval;
}
*/
#define fl_degrees(fl) (static_cast<float>((fl) * (180.0f / PI)))
// sees if a floating point number is within a certain threshold (by default, epsilon) of zero
inline bool fl_near_zero(float a, float e = std::numeric_limits<float>::epsilon())
+6
View File
@@ -1070,6 +1070,9 @@ void barracks_button_pressed(int n)
} else {
gamesnd_play_iface(InterfaceSounds::SCROLL);
// we now have a new pilot, so try to load its current campaign, falling back if necessary
mission_load_up_campaign(true);
if (Campaign_file_missing) {
popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, XSTR( "The currently active campaign cannot be found. Please select another...", 1600));
gameseq_post_event(GS_EVENT_CAMPAIGN_ROOM);
@@ -1081,6 +1084,9 @@ void barracks_button_pressed(int n)
if (Num_pilots && !barracks_pilot_accepted()) {
gamesnd_play_iface(InterfaceSounds::COMMIT_PRESSED);
// we now have a new pilot, so try to load its current campaign, falling back if necessary
mission_load_up_campaign(true);
if (Campaign_file_missing) {
popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, XSTR( "The currently active campaign cannot be found. Please select another...", 1600));
gameseq_post_event(GS_EVENT_CAMPAIGN_ROOM);
+3 -3
View File
@@ -639,7 +639,7 @@ void credits_init()
for (iter = Credit_text_parts.begin(); iter != Credit_text_parts.end(); ++iter)
{
gr_get_string_size(NULL, &temp_h, iter->c_str(), (int)iter->length());
gr_get_string_size(NULL, &temp_h, iter->c_str(), iter->length());
h = h + temp_h;
}
@@ -855,12 +855,12 @@ void credits_do_frame(float /*frametime*/)
length = std::numeric_limits<size_t>::max();
}
gr_get_string_size(&width, &height, iter->c_str() + currentPos, static_cast<int>(length));
gr_get_string_size(&width, &height, iter->c_str() + currentPos, length);
// Check if the text part is actually visible
if (Credit_position + y_offset + height > 0.0f)
{
float x = static_cast<float>((gr_screen.clip_width_unscaled - width) / 2);
gr_string(x, Credit_position + y_offset, iter->c_str() + currentPos, GR_RESIZE_MENU, static_cast<int>(length));
gr_string(x, Credit_position + y_offset, iter->c_str() + currentPos, GR_RESIZE_MENU, length);
}
y_offset += height;
+20 -14
View File
@@ -309,6 +309,8 @@ static int F1_text_done = 0;
int Main_hall_help_stamp = -1;
void main_hall_process_help_stuff();
bool Main_hall_use_defaults = true;
// ----------------------------------------------------------------------------
// VOICE RECORDING STUFF
@@ -906,8 +908,7 @@ void main_hall_do(float frametime)
Game_mode = GM_NORMAL;
// see if we have a missing campaign and force the player to select a new campaign if so
if (!(Player->flags & PLAYER_FLAGS_IS_MULTI) && Campaign_file_missing &&
!Campaign_room_no_campaigns) {
if (!(Player->flags & PLAYER_FLAGS_IS_MULTI) && Campaign_file_missing && !Campaign_room_no_campaigns) {
int rc = popup(0,
3,
XSTR("Go to Campaign Room", 1607),
@@ -933,7 +934,6 @@ void main_hall_do(float frametime)
break;
}
} else {
gameseq_post_event(GS_EVENT_NEW_CAMPAIGN);
gamesnd_play_iface(InterfaceSounds::IFACE_MOUSE_CLICK);
}
@@ -2158,18 +2158,20 @@ void region_info_init(main_hall_defines &m)
m.regions.clear();
}
main_hall_region defaults[] = {
main_hall_region(0, 0, XSTR( "Exit FreeSpace 2", 353), EXIT_REGION, ""),
main_hall_region(1, 'B', XSTR( "Barracks - Manage your FreeSpace 2 pilots", 354), BARRACKS_REGION, ""),
main_hall_region(2, 'R', XSTR( "Ready room - Start or continue a campaign", 355), START_REGION, ""),
main_hall_region(3, 'T', XSTR( "Tech room - View specifications of FreeSpace 2 ships and weaponry", 356), TECH_ROOM_REGION, ""),
main_hall_region(4, 0, XSTR( "Options - Change your FreeSpace 2 options", 357), OPTIONS_REGION, ""),
main_hall_region(5, 'C', XSTR( "Campaign Room - View all available campaigns", 358), CAMPAIGN_ROOM_REGION, ""),
main_hall_region(6, 'G', "Quick start", QUICK_START_REGION, "")
};
if (Main_hall_use_defaults) {
main_hall_region defaults[] = {
main_hall_region(0, 0, XSTR( "Exit FreeSpace 2", 353), EXIT_REGION, ""),
main_hall_region(1, 'B', XSTR( "Barracks - Manage your FreeSpace 2 pilots", 354), BARRACKS_REGION, ""),
main_hall_region(2, 'R', XSTR( "Ready room - Start or continue a campaign", 355), START_REGION, ""),
main_hall_region(3, 'T', XSTR( "Tech room - View specifications of FreeSpace 2 ships and weaponry", 356), TECH_ROOM_REGION, ""),
main_hall_region(4, 0, XSTR( "Options - Change your FreeSpace 2 options", 357), OPTIONS_REGION, ""),
main_hall_region(5, 'C', XSTR( "Campaign Room - View all available campaigns", 358), CAMPAIGN_ROOM_REGION, ""),
main_hall_region(6, 'G', "Quick start", QUICK_START_REGION, "")
};
for (int idx = 0; idx < 7; idx++) {
m.regions.push_back(defaults[idx]);
for (int idx = 0; idx < 7; idx++) {
m.regions.push_back(defaults[idx]);
}
}
// XSTR( "Multiplayer - Start or join a multiplayer game", 359)
@@ -2216,6 +2218,10 @@ void parse_main_hall_table(const char* filename)
reset_parse();
if (optional_string("$Base mainhalls on retail defaults:")) {
stuff_boolean(&Main_hall_use_defaults);
}
if (optional_string("$Num Resolutions:")) {
stuff_int(&num_resolutions);
}
-258
View File
@@ -1,258 +0,0 @@
/*
* Copyright (C) Volition, Inc. 1999. All rights reserved.
*
* All source code herein is the property of Volition, Inc. You may not sell
* or otherwise commercially exploit the source or things you created based on the
* source.
*
*/
#include "freespace.h"
#include "gamesequence/gamesequence.h"
#include "gamesnd/gamesnd.h"
#include "io/key.h"
#include "menuui/mainhallmenu.h"
#include "menuui/mainhalltemp.h"
#include "mission/missioncampaign.h"
#include "mission/missionload.h"
#include "playerman/player.h"
#include "ui/ui.h"
// ------------------------------------------------------------------------------------------------------------------------
// TEMP MAIN HALL DEFINES/VARS
//
#define MHT_NUM_BUTTONS 6
const char *Mht_bitmap_fname[GR_NUM_RESOLUTIONS] = {
"mht_background", // GR_640
"2_mht_background" // GR_1024
};
const char *Mht_bitmap_mask_fname[GR_NUM_RESOLUTIONS] = {
"mht_mask", // GR_640
"2_mht_mask" // GR_1024
};
// button defs
#define MHT_READY_ROOM 0
#define MHT_CAMPAIGN_ROOM 1
#define MHT_OPTIONS 2
#define MHT_TECH_ROOM 3
#define MHT_BARRACKS 4
#define MHT_EXIT 5
UI_WINDOW Mht_window; // the window object for the join screen
int Mht_bitmap; // the background bitmap
ui_button_info Mht_buttons[GR_NUM_RESOLUTIONS][MHT_NUM_BUTTONS] = {
{ // GR_640
ui_button_info( "MHT_00", 15, 194, -1, -1, 2 ), // ready room
ui_button_info( "MHT_01", 15, 222, -1, -1, 5 ), // campaigns
ui_button_info( "MHT_02", 14, 251, -1, -1, 4 ), // options
ui_button_info( "MHT_03", 14, 280, -1, -1, 3 ), // tech room
ui_button_info( "MHT_04", 14, 309, -1, -1, 1 ), // barracks
ui_button_info( "MHT_05", 16, 339, -1, -1, 0 ), // exit
},
{ // GR_1024
ui_button_info( "2_MHT_00", 25, 312, -1, -1, 2 ), // ready room
ui_button_info( "2_MHT_01", 25, 357, -1, -1, 5 ), // campaigns
ui_button_info( "2_MHT_02", 24, 403, -1, -1, 4 ), // options
ui_button_info( "2_MHT_03", 24, 450, -1, -1, 3 ), // tech room
ui_button_info( "2_MHT_04", 25, 497, -1, -1, 1 ), // barracks
ui_button_info( "2_MHT_05", 27, 544, -1, -1, 0 ), // exit
}
};
// ------------------------------------------------------------------------------------------------------------------------
// TEMP MAIN HALL FUNCTIONS
//
void mht_check_buttons();
void mht_button_pressed(int n);
void mht_exit_game();
void mht_init()
{
int idx;
// create the interface window
Mht_window.create(0, 0, gr_screen.max_w_unscaled,gr_screen.max_h_unscaled, 0);
Mht_window.set_mask_bmap(Mht_bitmap_mask_fname[gr_screen.res]);
// load the background bitmap
Mht_bitmap = bm_load(Mht_bitmap_fname[gr_screen.res]);
if(Mht_bitmap < 0){
// we failed to load the bitmap - this is very bad
Int3();
}
// create the interface buttons
for(idx=0; idx<MHT_NUM_BUTTONS; idx++){
// create the object
Mht_buttons[gr_screen.res][idx].button.create(&Mht_window, "", Mht_buttons[gr_screen.res][idx].x, Mht_buttons[gr_screen.res][idx].y, 1, 1, 0, 1);
// set the sound to play when highlighted
Mht_buttons[gr_screen.res][idx].button.set_highlight_action(common_play_highlight_sound);
// set the ani for the button
Mht_buttons[gr_screen.res][idx].button.set_bmaps(Mht_buttons[gr_screen.res][idx].filename);
// set the hotspot
Mht_buttons[gr_screen.res][idx].button.link_hotspot(Mht_buttons[gr_screen.res][idx].hotspot);
}
// remove any multiplayer flags from the game mode
Game_mode &= ~(GM_MULTIPLAYER);
// initialize the music
main_hall_start_music();
// set the game_mode based on the type of player
Assert( Player != NULL );
if ( Player->flags & PLAYER_FLAGS_IS_MULTI ){
Game_mode = GM_MULTIPLAYER;
} else {
Game_mode = GM_NORMAL;
}
}
void mht_do()
{
int k = Mht_window.process();
// need to ensure ambient is playing, since it may be stopped by a playing movie
main_hall_start_ambient();
// process any keypresses
switch(k){
case KEY_ESC :
mht_exit_game();
break;
case KEY_B:
gameseq_post_event( GS_EVENT_BARRACKS_MENU );
break;
case KEY_G:
if(Player->flags & PLAYER_FLAGS_IS_MULTI){
break;
}
if (Num_recent_missions > 0) {
strcpy_s( Game_current_mission_filename, Recent_missions[0] );
} else {
mission_load_up_campaign();
strcpy_s( Game_current_mission_filename, Campaign.missions[0].name );
}
Campaign.current_mission = -1;
gameseq_post_event(GS_EVENT_START_GAME_QUICK);
break;
case KEY_L:
gameseq_post_event( GS_EVENT_LOAD_MISSION_MENU );
break;
case KEY_F2:
gameseq_post_event(GS_EVENT_OPTIONS_MENU);
break;
case KEY_M:
if (Player->flags & PLAYER_FLAGS_IS_MULTI){
main_hall_do_multi_ready();
}
break;
}
// process button presses
mht_check_buttons();
// draw the background, etc
gr_reset_clip();
GR_MAYBE_CLEAR_RES(Mht_bitmap);
if(Mht_bitmap != -1){
gr_set_bitmap(Mht_bitmap);
gr_bitmap(0,0,GR_RESIZE_MENU);
}
Mht_window.draw();
// flip the buffer
gr_flip();
}
void mht_close()
{
// unload any bitmaps
if(!bm_unload(Mht_bitmap)){
nprintf(("General","WARNING : could not unload background bitmap %s\n", Mht_bitmap_fname[gr_screen.res]));
}
// destroy the UI_WINDOW
Mht_window.destroy();
}
void mht_check_buttons()
{
int idx;
for(idx=0; idx<MHT_NUM_BUTTONS; idx++){
// we only really need to check for one button pressed at a time, so we can break after
// finding one.
if(Mht_buttons[gr_screen.res][idx].button.pressed()){
mht_button_pressed(idx);
break;
}
}
}
void mht_button_pressed(int n)
{
switch(n){
case MHT_READY_ROOM:
if (Player->flags & PLAYER_FLAGS_IS_MULTI){
main_hall_do_multi_ready();
} else {
gameseq_post_event(GS_EVENT_NEW_CAMPAIGN);
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
}
break;
case MHT_CAMPAIGN_ROOM:
gameseq_post_event(GS_EVENT_CAMPAIGN_ROOM);
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
break;
case MHT_OPTIONS:
gameseq_post_event(GS_EVENT_OPTIONS_MENU);
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
break;
case MHT_TECH_ROOM:
gameseq_post_event( GS_EVENT_TECH_MENU );
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
break;
case MHT_BARRACKS:
gameseq_post_event( GS_EVENT_BARRACKS_MENU );
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
break;
case MHT_EXIT:
mht_exit_game();
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
break;
}
}
void mht_exit_game()
{
// stop music first
main_hall_stop_music(true);
main_hall_stop_ambient();
gameseq_post_event(GS_EVENT_QUIT_GAME);
}
-33
View File
@@ -1,33 +0,0 @@
/*
* Copyright (C) Volition, Inc. 1999. All rights reserved.
*
* All source code herein is the property of Volition, Inc. You may not sell
* or otherwise commercially exploit the source or things you created based on the
* source.
*
*/
#ifndef __TEMP_MAIN_HALL_MENU_HEADER_FILE
#define __TEMP_MAIN_HALL_MENU_HEADER_FILE
// ------------------------------------------------------------------------------------------------------------------------
// TEMP MAIN HALL DEFINES/VARS
//
// ------------------------------------------------------------------------------------------------------------------------
// TEMP MAIN HALL FUNCTIONS
//
// initialize the temporary main hall
void mht_init();
// do a frame for the main hall
void mht_do();
// close the temporary main hall
void mht_close();
#endif
+138 -1
View File
@@ -29,6 +29,8 @@
#include "missionui/missionscreencommon.h"
#include "nebula/neb.h"
#include "network/multi.h"
#include "options/OptionsManager.h"
#include "options/Option.h"
#include "osapi/osregistry.h"
#include "pilotfile/pilotfile.h"
#include "popup/popup.h"
@@ -284,6 +286,17 @@ int Options_skills_text_coords[GR_NUM_RESOLUTIONS][4] = {
}
};
int Options_scp_string_coords[GR_NUM_RESOLUTIONS][2] = {
{
265, 18 // GR_640
},
{
465, 25 // GR_1024
}
};
std::pair<SCP_string, int> Options_scp_string_text = {"Press F3 to access additional options", 1831};
// ---------------------------------------------------------------------------------------------------------
// DETAIL LEVEL OPTIONS definitions BEGIN
@@ -666,6 +679,11 @@ void options_cancel_exit()
Detail = Detail_original;
}
// We have to discard in game options here
if (Using_in_game_options) {
options::OptionsManager::instance()->discardChanges();
}
gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
}
@@ -690,6 +708,68 @@ void options_change_gamma(float delta)
sprintf(tmp_gamma_string, NOX("%.2f"), gamma);
os_config_write_string( NULL, NOX("GammaD3D"), tmp_gamma_string );
if (Using_in_game_options) {
const options::OptionBase* thisOpt = options::OptionsManager::instance()->getOptionByKey("Graphics.Gamma");
if (thisOpt != nullptr) {
auto val = thisOpt->getCurrentValueDescription();
SCP_string newVal = std::to_string(gamma); // OptionsManager stores values as serialized strings
thisOpt->setValueDescription({val.display, newVal.c_str()});
}
}
}
void options_set_ingame_binary_option(SCP_string key, bool value)
{
if (!Using_in_game_options) {
return;
}
const options::OptionBase* thisOpt = options::OptionsManager::instance()->getOptionByKey(key);
if (thisOpt != nullptr) {
auto val = thisOpt->getCurrentValueDescription();
SCP_string newVal = value ? "true" : "false"; // OptionsManager stores values as serialized strings
thisOpt->setValueDescription({val.display, newVal.c_str()});
}
}
void options_set_ingame_multi_option(SCP_string key, int value)
{
if (!Using_in_game_options) {
return;
}
const options::OptionBase* thisOpt = options::OptionsManager::instance()->getOptionByKey(key);
if (thisOpt != nullptr) {
auto values = thisOpt->getValidValues();
thisOpt->setValueDescription(values[value]);
}
}
void options_set_ingame_range_option(SCP_string key, int value)
{
if (!Using_in_game_options) {
return;
}
const options::OptionBase* thisOpt = options::OptionsManager::instance()->getOptionByKey(key);
if (thisOpt != nullptr) {
SCP_string newVal = std::to_string(value); // OptionsManager stores values as serialized strings
thisOpt->setValueDescription({newVal.c_str(), newVal.c_str()});
}
}
void options_set_ingame_range_option(SCP_string key, float value)
{
if (!Using_in_game_options) {
return;
}
const options::OptionBase* thisOpt = options::OptionsManager::instance()->getOptionByKey(key);
if (thisOpt != nullptr) {
SCP_string newVal = std::to_string(value); // OptionsManager stores values as serialized strings
thisOpt->setValueDescription({newVal.c_str(), newVal.c_str()});
}
}
void options_button_pressed(int n)
@@ -740,6 +820,7 @@ void options_button_pressed(int n)
// BEGIN - detail level tab buttons
// Target View Rendering is currently not handled by in-game options, assumes "On"
case HUD_TARGETVIEW_RENDER_ON:
Detail.targetview_model = 1;
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
@@ -750,6 +831,7 @@ void options_button_pressed(int n)
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
break;
// Planets is currently not handled by in-game options, assumes "On"
case PLANETS_ON:
Detail.planets_suns = 1;
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
@@ -760,6 +842,7 @@ void options_button_pressed(int n)
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
break;
// Weapon extras is currently not handled by in-game options, assumes "On"
case WEAPON_EXTRAS_ON:
Detail.weapon_extras = 1;
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
@@ -798,29 +881,35 @@ void options_button_pressed(int n)
case GAMMA_DOWN:
options_change_gamma(-0.05f);
// Gamma in-game change is handled in the above method
break;
case GAMMA_UP:
options_change_gamma(0.05f);
// Gamma in-game change is handled in the above method
break;
case BRIEF_VOICE_ON:
Briefing_voice_enabled = true;
options_set_ingame_binary_option("Audio.BriefingVoice", true);
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
break;
case BRIEF_VOICE_OFF:
Briefing_voice_enabled = false;
options_set_ingame_binary_option("Audio.BriefingVoice", false);
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
break;
case MOUSE_ON:
Use_mouse_to_fly = 1;
options_set_ingame_binary_option("Input.UseMouse", true);
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
break;
case MOUSE_OFF:
Use_mouse_to_fly = 0;
options_set_ingame_binary_option("Input.UseMouse", false);
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
break;
}
@@ -832,6 +921,7 @@ void options_sliders_update()
if (Options_sliders[gr_screen.res][OPT_SOUND_VOLUME_SLIDER].slider.pos != Sound_volume_int) {
Sound_volume_int = Options_sliders[gr_screen.res][OPT_SOUND_VOLUME_SLIDER].slider.pos;
snd_set_effects_volume((float) (Sound_volume_int) / 9.0f);
options_set_ingame_range_option("Audio.Effects", Master_sound_volume); // Volume options save the global float, not the range slider position
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
}
@@ -839,7 +929,7 @@ void options_sliders_update()
if (Options_sliders[gr_screen.res][OPT_MUSIC_VOLUME_SLIDER].slider.pos != Music_volume_int) {
Music_volume_int = Options_sliders[gr_screen.res][OPT_MUSIC_VOLUME_SLIDER].slider.pos;
event_music_set_volume((float) (Music_volume_int) / 9.0f);
options_set_ingame_range_option("Audio.Music", Master_event_music_volume); // Volume options save the global float, not the range slider position
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
}
@@ -847,30 +937,48 @@ void options_sliders_update()
if (Options_sliders[gr_screen.res][OPT_VOICE_VOLUME_SLIDER].slider.pos != Voice_volume_int) {
Voice_volume_int = Options_sliders[gr_screen.res][OPT_VOICE_VOLUME_SLIDER].slider.pos;
snd_set_voice_volume((float) (Voice_volume_int) / 9.0f);
options_set_ingame_range_option("Audio.Voice", Master_voice_volume); // Volume options save the global float, not the range slider position
options_play_voice_clip();
}
if (Mouse_sensitivity != Options_sliders[gr_screen.res][OPT_MOUSE_SENS_SLIDER].slider.pos) {
Mouse_sensitivity = Options_sliders[gr_screen.res][OPT_MOUSE_SENS_SLIDER].slider.pos;
options_set_ingame_range_option("Input.MouseSensitivity", Mouse_sensitivity);
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
}
if (Joy_sensitivity != Options_sliders[gr_screen.res][OPT_JOY_SENS_SLIDER].slider.pos) {
Joy_sensitivity = Options_sliders[gr_screen.res][OPT_JOY_SENS_SLIDER].slider.pos;
options_set_ingame_range_option("Input.JoystickSensitivity", Joy_sensitivity);
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
}
if (Joy_dead_zone_size != Options_sliders[gr_screen.res][OPT_JOY_DEADZONE_SLIDER].slider.pos * 5) {
Joy_dead_zone_size = Options_sliders[gr_screen.res][OPT_JOY_DEADZONE_SLIDER].slider.pos * 5;
options_set_ingame_range_option("Input.JoystickDeadZone", Joy_dead_zone_size);
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
}
if (Game_skill_level != Options_sliders[gr_screen.res][OPT_SKILL_SLIDER].slider.pos) {
Game_skill_level = Options_sliders[gr_screen.res][OPT_SKILL_SLIDER].slider.pos;
options_set_ingame_range_option("Game.SkillLevel", Game_skill_level);
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
}
}
void options_detail_sliders_in_game_update()
{
// Save in-game options settings
options_set_ingame_multi_option("Graphics.Detail", Detail.detail_distance);
options_set_ingame_multi_option("Graphics.NebulaDetail", Detail.nebula_detail);
options_set_ingame_multi_option("Graphics.Texture", Detail.hardware_textures);
options_set_ingame_multi_option("Graphics.Particles", Detail.num_particles);
options_set_ingame_multi_option("Graphics.SmallDebris", Detail.num_small_debris);
options_set_ingame_multi_option("Graphics.ShieldEffects", Detail.shield_effects);
options_set_ingame_multi_option("Graphics.Stars", Detail.num_stars);
options_set_ingame_multi_option("Graphics.Lighting", Detail.lighting);
}
void options_accept()
{
// apply the selected multiplayer options
@@ -883,6 +991,15 @@ void options_accept()
}
}
// We have to save in game options here
if (Using_in_game_options) {
// detail sliders are updated every frame but it's silly to run OptionsManager every frame, too
// so just set them on Accept and then persist.
options_detail_sliders_in_game_update();
options::OptionsManager::instance()->persistChanges();
}
// If music is zero volume, disable
if ( Master_event_music_volume <= 0.0f ) {
// event_music_disable();
@@ -1178,6 +1295,17 @@ void options_menu_do_frame(float /*frametime*/)
case KEY_ENTER:
break;
case KEY_F3: // SCP ingame options
if (Using_in_game_options) {
// Going into F3 Options needs to either discard or save the changes made here.
// There's an argument to be made for both but I feel like saving is the better choice - Mjn
options::OptionsManager::instance()->persistChanges();
gamesnd_play_iface(InterfaceSounds::IFACE_MOUSE_CLICK);
gameseq_post_event(GS_EVENT_INGAME_OPTIONS);
}
break;
}
for (i=0; i<NUM_BUTTONS; i++) {
@@ -1275,6 +1403,15 @@ void options_menu_do_frame(float /*frametime*/)
if(Tab == MULTIPLAYER_TAB){
options_multi_vox_process_waveform();
}
// maybe blit the SCP Options string
if (Using_in_game_options) {
gr_set_color_fast(&Color_bright_blue);
gr_string(Options_scp_string_coords[gr_screen.res][OPTIONS_X_COORD],
Options_scp_string_coords[gr_screen.res][OPTIONS_Y_COORD],
XSTR(Options_scp_string_text.first.c_str(), Options_scp_string_text.second),
GR_RESIZE_MENU);
}
gr_flip();
}
+3
View File
@@ -39,6 +39,9 @@ void options_menu_init();
void options_menu_close();
void options_menu_do_frame(float frametime);
// For optionsmenumulti.cpp
void options_set_ingame_binary_option(SCP_string key, bool value);
// kill the options menu
void options_cancel_exit();
+8
View File
@@ -1005,8 +1005,10 @@ void options_multi_protocol_button_pressed(int n)
if(!Om_local_broadcast){
Om_local_broadcast = 1;
options_set_ingame_binary_option("Multi.LocalBroadcast", true);
} else {
Om_local_broadcast = 0;
options_set_ingame_binary_option("Multi.LocalBroadcast", false);
}
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
@@ -1048,10 +1050,12 @@ void options_multi_protocol_button_pressed(int n)
Om_tracker_login.enable();
Om_tracker_passwd.enable();
Om_tracker_squad_name.enable();
options_set_ingame_binary_option("Multi.TogglePXO", true);
} else {
Om_tracker_login.disable();
Om_tracker_passwd.disable();
Om_tracker_squad_name.disable();
options_set_ingame_binary_option("Multi.TogglePXO", false);
}
// play a sound
@@ -1539,6 +1543,7 @@ void options_multi_gen_button_pressed(int n)
if(!Om_gen_xfer_multidata){
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
Om_gen_xfer_multidata = 1;
options_set_ingame_binary_option("Multi.TransferMissions", true);
} else {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
@@ -1549,6 +1554,7 @@ void options_multi_gen_button_pressed(int n)
if(Om_gen_xfer_multidata){
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
Om_gen_xfer_multidata = 0;
options_set_ingame_binary_option("Multi.TransferMissions", false);
} else {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
@@ -1559,6 +1565,7 @@ void options_multi_gen_button_pressed(int n)
if(!Om_gen_flush_cache){
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
Om_gen_flush_cache = 1;
options_set_ingame_binary_option("Multi.FlushCache", true);
} else {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
@@ -1569,6 +1576,7 @@ void options_multi_gen_button_pressed(int n)
if(Om_gen_flush_cache){
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
Om_gen_flush_cache = 0;
options_set_ingame_binary_option("Multi.FlushCache", false);
} else {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
+8 -2
View File
@@ -917,7 +917,11 @@ int sim_room_button_pressed(int n)
case CAMPAIGN_TAB:
if ( !strlen(Campaign.filename) ) {
popup( PF_USE_AFFIRMATIVE_ICON | PF_NO_NETWORKING, 1, POPUP_OK, XSTR( "The currently active campaign cannot be found, unable to switch to campaign mode!", 1612));
if (Campaign_load_failure == CAMPAIGN_ERROR_MISSING) {
popup(PF_USE_AFFIRMATIVE_ICON | PF_NO_NETWORKING, 1, POPUP_OK, XSTR("The currently active campaign cannot be found. Unable to switch to campaign mode.", 1612));
} else {
popup(PF_USE_AFFIRMATIVE_ICON | PF_NO_NETWORKING, 1, POPUP_OK, XSTR("The currently active campaign cannot be loaded. Unable to switch to campaign mode.", 1816));
}
break;
}
@@ -1050,7 +1054,9 @@ void sim_room_init()
Campaign.filename[0] = 0;
Campaign.num_missions = 0;
mission_campaign_load_failure_popup();
// don't display the popup in the sim room - first because there is already logic to prevent listing campaign missions,
// second because there's not much the player can do about it in the sim room, and third because displaying the popup
// clears the error code
}
Num_campaign_missions = 0;
+2 -2
View File
@@ -335,7 +335,7 @@ void techroom_select_new_entry()
if (Techroom_model_instance >= 0) {
model_delete_instance(Techroom_model_instance);
}
Techroom_model_instance = model_create_instance(-1, Techroom_modelnum);
Techroom_model_instance = model_create_instance(model_objnum_special::OBJNUM_NONE, Techroom_modelnum);
model_set_up_techroom_instance(sip, Techroom_model_instance);
@@ -396,7 +396,7 @@ void techroom_select_new_entry()
if (Techroom_model_instance >= 0) {
model_delete_instance(Techroom_model_instance);
}
Techroom_model_instance = model_create_instance(-1, Techroom_modelnum);
Techroom_model_instance = model_create_instance(model_objnum_special::OBJNUM_NONE, Techroom_modelnum);
// If this ends up being needed for weapon models, a weapon version
// of this method will need to be created. Should only be necessary
+2 -1
View File
@@ -130,11 +130,12 @@ bool Briefing_voice_enabled = true; // flag which turn on/off voice playback of
static auto BriefingVoiceOption __UNUSED = options::OptionBuilder<bool>("Audio.BriefingVoice",
std::pair<const char*, int>{"Briefing voice", 1368},
std::pair<const char*, int>{"Enable or disable voice playback in the briefing", 1716})
.category("Audio")
.category(std::make_pair("Audio", 1826))
.level(options::ExpertLevel::Beginner)
.default_val(true)
.bind_to(&Briefing_voice_enabled)
.importance(4)
.flags({options::OptionFlags::RetailBuiltinOption})
.finish();
// --------------------------------------------------------------------------------------
+32 -21
View File
@@ -60,7 +60,7 @@ char *Campaign_names[MAX_CAMPAIGNS] = { NULL };
char *Campaign_file_names[MAX_CAMPAIGNS] = { NULL };
char *Campaign_descs[MAX_CAMPAIGNS] = { NULL };
int Num_campaigns;
int Campaign_file_missing;
bool Campaign_file_missing = false;
int Campaign_load_failure = 0;
int Campaign_names_inited = 0;
SCP_vector<SCP_string> Ignored_campaigns;
@@ -428,7 +428,7 @@ int mission_campaign_load(const char* filename, const char* full_path, player* p
char name[NAME_LENGTH], type[NAME_LENGTH], temp[NAME_LENGTH];
if (campaign_is_ignored(filename)) {
Campaign_file_missing = 1;
Campaign_file_missing = true;
Campaign_load_failure = CAMPAIGN_ERROR_IGNORED;
return CAMPAIGN_ERROR_IGNORED;
}
@@ -634,19 +634,25 @@ int mission_campaign_load(const char* filename, const char* full_path, player* p
if ((Game_mode & GM_MULTIPLAYER) && Campaign.num_missions > UINT8_MAX)
throw parse::ParseException("Number of campaign missions is too high and breaks multi!");
}
catch (const parse::ParseException& e)
catch (const parse::FileOpenException& foe)
{
mprintf(("Error parsing '%s'\r\nError message = %s.\r\n", filename, e.what()));
mprintf(("Error opening '%s'\r\nError message = %s.\r\n", filename, foe.what()));
Campaign.filename[0] = 0;
Campaign.num_missions = 0;
if (!Fred_running && !(Game_mode & GM_MULTIPLAYER)) {
Campaign_file_missing = 1;
Campaign_load_failure = CAMPAIGN_ERROR_MISSING;
return CAMPAIGN_ERROR_MISSING;
}
Campaign_file_missing = true;
Campaign_load_failure = CAMPAIGN_ERROR_MISSING;
return CAMPAIGN_ERROR_MISSING;
}
catch (const parse::ParseException& pe)
{
mprintf(("Error parsing '%s'\r\nError message = %s.\r\n", filename, pe.what()));
Campaign.filename[0] = 0;
Campaign.num_missions = 0;
Campaign_file_missing = true;
Campaign_load_failure = CAMPAIGN_ERROR_CORRUPT;
return CAMPAIGN_ERROR_CORRUPT;
}
@@ -681,7 +687,7 @@ int mission_campaign_load(const char* filename, const char* full_path, player* p
}
// all is good here, move along
Campaign_file_missing = 0;
Campaign_file_missing = false;
return 0;
}
@@ -721,7 +727,7 @@ void mission_campaign_init()
{
mission_campaign_clear();
Campaign_file_missing = 0;
Campaign_file_missing = false;
player_loadout_init();
}
@@ -1539,26 +1545,31 @@ bool campaign_is_ignored(const char *filename)
return false;
}
static bool campaign_reportable_error(int val)
{
return val != 0 && val != CAMPAIGN_ERROR_MISSING && val != CAMPAIGN_ERROR_IGNORED;
}
// returns 0: loaded, !0: error
int mission_load_up_campaign( player *pl )
int mission_load_up_campaign(bool fall_back_from_current)
{
int rc = -1, idx;
if ( pl == NULL )
pl = Player;
auto pl = Player;
// find best campaign to use:
// 1) last used
// 2) builtin
// 3) anything else
// Note that in each step we only fall back when the error is benign, e.g. ignored or missing;
// if there's some other real error with the campaign file, we report it.
// Also note that if we *have* a current campaign, we shouldn't fall back *at all*, lest we repeatedly
// reset what the current campaign is, *unless* we are starting a brand new session or loading a new pilot.
// last used...
if ( strlen(pl->current_campaign) ) {
if (!campaign_is_ignored(pl->current_campaign)) {
return mission_campaign_load(pl->current_campaign, nullptr, pl);
}
else {
Campaign_file_missing = 1;
rc = mission_campaign_load(pl->current_campaign, nullptr, pl);
if (rc == 0 || !fall_back_from_current || campaign_reportable_error(rc)) {
return rc;
}
}
@@ -1566,7 +1577,7 @@ int mission_load_up_campaign( player *pl )
rc = mission_campaign_load(Default_campaign_file_name, nullptr, pl);
// everything else...
if (rc < 0) {
if (rc < 0 && !campaign_reportable_error(rc)) {
// no descriptions, no sorting
mission_campaign_build_list(false, false);
Loaded 100 of 345 files, more files were not shown because too many files have changed in this diff. Show more