Compare commits

...
Author SHA1 Message Date
JohnAFernandez 05f2db381a Create temp_coverity_scan.yaml
Temporary coverity scan workflow until the scheduled one gets a review
2023-10-30 11:10:32 -04:00
John Fernandez 6038076bf0 Add current_cmeasure > -1 check
This is an actual edge case bug.  If no countermeasure was set, and then one was set, there might be a garbage timestamp set that would give an incorrect countermeasure delay on next use.
2023-10-30 10:56:45 -04:00
John Fernandez 40c8cbbb25 Add check for negative index
For coverity 1523515
2023-10-30 10:56:45 -04:00
John Fernandez bd7429c353 Get rid of Extraneous check
Coverity 1523341 is pointing out this check, but shipp->ship_info_index is checked earlier just before we set the shipp pointer on line 1243
2023-10-30 10:56:45 -04:00
John Fernandez faf130adb3 Add Assertion for Coverity 1093701 2023-10-30 10:56:45 -04:00
John Fernandez f7fef072df Feedback 2023-10-30 10:56:18 -04:00
John Fernandez 0da6a4a64c Coverity 1523287
Fall back to standard behavior if no allowed paths.

Missing bracket
2023-10-30 10:56:18 -04:00
John Fernandez f542fea96e coverity 1523419
Avoid dividing by zero when there is just one autoscale ai class
2023-10-30 10:56:18 -04:00
John Fernandez 742326e42e Coverity 1523548 Divide by zero
Make sure we only use autoscale delay if there is more than one autoscale ai class.
2023-10-30 10:56:18 -04:00
John Fernandez e25a6517fc Add a check for 0
To avoid division by zero (in dubious circumstances) explicitly check for zero.  For coverity 1523313
2023-10-30 10:56:18 -04:00
John Fernandez be0c78dc72 Add checks for options_multi_vox_plist_get
For coverity 1093612, this function *should* never return zero, but it is no catastrophic if it does.  Allowing it to return a negative value in some unknown edge case would allow it to clobber some other global data.

So now add a check for negative values and take no action if those negative values are reached.  Assert on debug.
2023-10-30 10:55:41 -04:00
John Fernandez ef681affbf Make sure we don't clobber other memory
If this index is negative one return early before we accidentally clobber other data.

Coverity 1523181
2023-10-30 10:55:41 -04:00
Goober5000 3a2ac5ab5f Merge pull request #5726 from Goober5000/persona_index_check
check for out-of-range persona
2023-10-30 00:01:03 -04:00
Goober5000 435676a67d Merge pull request #5730 from Goober5000/class_type_check
make sure class_type exists when used
2023-10-30 00:00:47 -04:00
Goober5000 4fbe3b7131 make sure class_type exists when used
A mission in Mantle caused an invalid vector access when checking whether to vaporize a ship whose ship type was -1.  Turns out having "no type" is actually allowed, so I audited all `class_type` accesses throughout the code for potential -1 accesses.  Most were properly checked but a few were not.  A few others needed to be tweaked.

(I suspect this is something that would be on the Coverity list if it isn't already.)
2023-10-29 15:17:22 -04:00
Goober5000 87a4ae1e41 check for out-of-range persona
For missions which use the Persona Index method, make sure the mod doesn't load a persona index that is out of range for the personas it knows about.
2023-10-28 21:23:25 -04:00
mjn-mixael c738941ccf Provide Lua a way to toggle the mainhall help overlay 2023-10-28 19:16:09 -04:00
John Fernandez 5c25bb9bcb Just use the already existing SCP_string
The destination strings in player_order are already SCP_strings, so no need to use manual allocation
2023-10-28 19:15:25 -04:00
John Fernandez e0bc6d0ed7 Fix memory leak in tga file writing
Yes.  I know, I know, we're not going to use this code anymore.  But just in case, I don't want this memory leak to have the possibility to exist in the future.
2023-10-28 19:15:25 -04:00
Mike Nelson ec706a6a87 Allow SCPUI saving current player data to file (#5718)
* Allow saving current player data to file

* return nil, dummy

* unused
2023-10-27 07:32:37 -04:00
John Fernandez 5d0127a764 Fix workflow by adding reference branch 2023-10-26 23:41:28 -04:00
Mike Nelson 91c15e6f48 Player general orders (#5638) 2023-10-26 19:22:44 -04:00
Asteroth a9fc7bab8a fix for particle culling (#5719) 2023-10-26 16:08:09 -04:00
Taylor Richards 042c85d213 revert workaround for the windows runner breakage (#5722) 2023-10-26 13:53:27 -04:00
Goober5000 bb3d59ecbe Merge pull request #5715 from Baezon/fix-hud-target-triangle
Bugfix HUD target direction triangle
2023-10-25 23:19:26 -04:00
Goober5000 d1c57391cf Merge pull request #5699 from Goober5000/handle_shuffled_parse_objects
handle parse objects that are out of order
2023-10-25 23:18:19 -04:00
Mike Nelson 5986b7143f Adds custom data for intel entries (#5660)
* adds custom data for intel entries

* update tests

* This one, too
2023-10-25 07:32:03 -04:00
wookieejedi 5d447951b4 Add Game Option to refresh selected weapon in loadout (#5713)
* Add Game Option to refresh selected weapon in loadout

This PR adds an option to always ensure the viewed weapon is one that can actually be on the selected ship when first clicking on the weapon loadout.

If you go to the loadout in the briefing and view the weapons on your ship, then go and change your ship class and go back to the weapon loadout screen, you will see that the weapon shown in the window on the right side is from your very first viewing before you changed your ship class. Displaying a weapon not allowed on a ship by default can be confusing to players, especially on mods like FotG where most ships have unique weapons.

The player can still of course click on a non-allowed weapon to view it, but with this PR the player will be initially shown a selected weapon that is allowed on the ship when opening the loadout editor.

Tested and works as expected.

* update order to be near weapon bools
2023-10-25 07:31:23 -04:00
Sébastien Noel f149c36b44 Fix a few typos (#5598) 2023-10-24 20:33:45 -04:00
Asteroth 34b6cf74ab whoops forgot the rval 2023-10-24 15:16:12 -04:00
Asteroth bc33f90e32 early return if z is 0 2023-10-24 14:32:56 -04:00
MageKing17 bb47531c55 Make lock_fov settable for aspect/javelin missiles. (#5493)
The code has always checked a per-weapon-class value called `lock_fov` when comparing the dot product of a ship to its target to see if it can lock on to it, however the weapon table hasn't ever included a way to set this value; it's always the default value of 0.85. This just adds "+Lock FOV:" entries to aspect/javelin homing missile parsing after "+Seeker Strength:", which will set `lock_fov` as long as the supplied input is between 0 and 360 degrees.
2023-10-24 07:26:54 -04:00
Asteroth aed90493ec make g3_project_vertex unconditionally project 2023-10-23 17:53:30 -04:00
John Fernandez d54c3e51e3 Apply Workaround to windows Build 2023-10-23 15:47:27 -04:00
Goober5000 a215bea0d0 unswap the net signatures 2023-10-23 15:29:06 -04:00
Goober5000 ec23f6bd0e Merge pull request #5709 from Goober5000/fix_loadout_crash
fix a crash in the apply-loadout-to-wing routine
2023-10-23 12:21:30 -04:00
John Fernandez d93d56e1c9 remove redundant setting of object_host 2023-10-23 10:24:13 -04:00
John Fernandez d2265325e9 check for nullptr to avoid nullptr dereference
For coverity 1093467
2023-10-23 10:24:13 -04:00
John Fernandez 2bb22a2153 Return to avoid nullptr dereference
For coverity 1093461.  If this is null, the function is done at this point.
2023-10-23 10:24:13 -04:00
John Fernandez 018c22eee1 Make sure Net_player is not null here
For coverity 1093460. Net_player should never be null here, but it is C++ after all.
2023-10-23 10:24:13 -04:00
John Fernandez 6ef60c67ca Make sure Multi_pxo_channels is not null
For coverity 1093458
2023-10-23 10:24:13 -04:00
John Fernandez 982e8d7f85 Add net_player nullptr check
Address coverity 1093457 by adding a nullptr check and Assertion.  This *should* never happen, but that's what asserts are for, right?
2023-10-23 10:24:13 -04:00
John Fernandez 8affd53cf6 Remove Unused Functions
These functions have not been called from what I can tell since the source code was released.  But they did happen to trigger a clang warning, so it's time to get rid of them.
2023-10-23 07:50:29 -04:00
Mike Nelson eeaf894b15 Message notes feature (#5541)
* Add stage notes feature for mission messages

* don't keep notes outside the mission editor

* use F_MULTITEXT and do lcl_replacements

* this should be multitext too
2023-10-23 07:38:33 -04:00
Goober5000 b546d897ae fix a crash in the apply-loadout-to-wing routine
If a wing has fewer than four ships, clicking the apply-to-all button will cause a vector subscript out of range error.  This fixes it.
2023-10-23 00:44:33 -04:00
John Fernandez d8aea4ad30 Add CMakePresets.json to gitignore 2023-10-22 22:54:24 -04:00
Goober5000 829692b7bd Merge pull request #5468 from Goober5000/5462_followup
additional cleanup from PR 5462
2023-10-22 17:10:42 -04:00
Goober5000 855935d4eb Merge pull request #5706 from Goober5000/fix_5705
fix change-soundtrack after <No Music>
2023-10-22 16:12:30 -04:00
Goober5000 f83efb54c0 fix change-soundtrack after <No Music>
The fix in #5578 assumed that a previously playing soundtrack would properly set the timestamp, but if no soundtrack was previously played at all, this wouldn't happen.  So if we deliberately don't play a soundtrack, be sure to set the timestamp as if `event_music_do_frame()` had been called.

Fixes #5705.
2023-10-22 15:31:02 -04:00
Mike Nelson 3ca26587eb add default player weapon flag (#5600) 2023-10-22 13:23:30 -04:00
John Fernandez 3e2bb36d4b Fix Redefined Macro Warning
Clarify
2023-10-22 00:37:18 -04:00
Goober5000 02bd62ff3c Merge pull request #5700 from Goober5000/special_to_supercap
change "special warp physics" to "supercap warp physics"
2023-10-21 17:34:20 -04:00
Goober5000 e1e0239914 also the dialog text 2023-10-21 16:40:31 -04:00
Goober5000 e621dbe997 Merge pull request #5464 from Goober5000/render_constify
add const where appropriate to the modelrender API
2023-10-21 15:57:24 -04:00
Goober5000 ea5c328c13 change "special warp physics" to "supercap warp physics"
Per discussion with @Baezon, this is a more precise term.
2023-10-21 15:51:16 -04:00
Goober5000 8c0bc25303 Merge pull request #5671 from Goober5000/subsystem_calculation_fix
add "Calculate subsystem hitpoints after parsing" option
2023-10-21 14:08:37 -04:00
Goober5000 6b0a3b7606 handle parse objects that are out of order
Occasionally, FRED can save a mission with a wing's ships out of order; this can happen if ships are deleted and FRED finds a free index in the middle of the ship list.  This can cause benign but confusing mismatches in the ship registry, the hotkey list, and other places -- and it's also possible some mismatches may not be so benign, e.g. in multiplayer.  Anyway, it's better for the ships to appear in the order the wing expects them, so this adds a routine to swap them around if necessary.
2023-10-21 13:40:09 -04:00
Mike Nelson 9afe76b5d2 force msaa in-game toggle to require restart (#5688) 2023-10-21 11:44:15 -04:00
Mike Nelson ad27664ebc Pause and Resume voices (#5636)
* pause and resume voices

* Use newer styling rather than the sound.cpp styling
2023-10-21 10:23:53 -04:00
Goober5000 2fe182a4b1 Merge pull request #5604 from Goober5000/drawString_tweak
small speedup to drawString
2023-10-21 01:28:23 -04:00
Goober5000 60c2718b91 add spacing 2023-10-20 23:26:46 -04:00
Tyler Blount 15d9b9b3db Merge pull request #5689 from MjnMixael/fix_lightshafts_optimization
Fix lightshafts and bloom in-game options
2023-10-20 15:09:03 -07:00
mjn-mixael d00003e199 Merge branch 'master' into fix_lightshafts_optimization 2023-10-20 16:11:34 -05:00
Tyler Blount 991d0ee2d6 Merge pull request #5696 from MjnMixael/deferred_lighting_ingame
Add deferred lighting as an in-game option
2023-10-20 14:09:33 -07:00
mjn-mixael 3eee74a31c remove unneeded header 2023-10-20 14:16:22 -05:00
mjn-mixael 941d5f7ec3 Move the option definition to a file that doesn't require glad.h for building and resolve xstr issue 2023-10-20 14:01:50 -05:00
Asteroth 0cde26dd6e make invalid model_subsystem model nums a hard error (#5591) 2023-10-20 14:40:48 -04:00
Mike Nelson 7804f7fff5 add feature to always display the damage gauge (#5518) 2023-10-20 14:40:27 -04:00
Asteroth 832cec27ad bugfix missile time determination (#5595) 2023-10-20 14:40:02 -04:00
Mike Nelson 31acb115c2 Add nebula-fade-poof SEXP (#5612)
* nebula-fade-poofs

* Move this up because order of operations is important.

* Add some documentation

* Respect time compression

* Fix sexp description

* Make sure faded poofs do not flicker

* optimize
2023-10-20 14:39:38 -04:00
Goober5000 f9591b3a92 Merge pull request #5664 from Goober5000/fix_cheat_status
fix incorrect setting of disabled/disarmed flags when cheating
2023-10-20 14:27:37 -04:00
mjn-mixael 21f92194f1 Add deferred lighting as an in-game option 2023-10-20 12:38:53 -05:00
wookieejedi c605451460 Fix glare shining through cockpits in freelook (#5690)
Fixes #3098. The `shipfx_eye_in_shadow` function did a collision check for cockpits, bit did not previously take into account of the viewpoint had a non-forward orientation (ie the player was using free look). This PR sets the collide check to take that into account with a 1 line fix. Tested with multiple FotG cockpits and fixes the issue.
2023-10-20 07:39:25 -04:00
Taylor Richards 2acdc65875 add workaround for broken windows workflow (#5693)
Temporary fix for broken windows workflow. Hopefully a more permanent
solution will be found soon and we can then remove this.

Reference: https://github.com/actions/runner-images/issues/8598
2023-10-19 17:39:04 -04:00
Goober5000 b7de2fd644 Merge pull request #5554 from Goober5000/set_armor_type_generic
enhance set-armor-type to work with generic subsystems
2023-10-19 14:09:50 -04:00
Tyler Blount a226a81d80 Merge pull request #5692 from JohnAFernandez/master
Revert one "Fix" and add comments
2023-10-19 09:25:36 -07:00
John Fernandez eb39532f7c Revert one "Fix" and add comments
Only one of these was an actual memory leak.

Add comments to clarify
2023-10-19 11:42:24 -04:00
JohnAFernandez 1478ace3e0 Avoid edge case divide by zero (#5683)
* Add a divide by zero check

For coverity 1107324.  Keeps framecount from dividing by zero in very rare circumstances.

* Add a clarifying comment

This marks isNaturalNumberFactor() so that we know it is the best way to get whether a number is a natural number.

Modulo division is slower and gives the same results.

* Spoiled by Rust
2023-10-19 07:57:12 -04:00
JohnAFernandez 7edc5bf842 Change underlying type to avoid endianness problem (#5680)
Before this change if the wrong endianness was used, the c style cast that was used here would lead to the argument being passed to getsockopt to lack the actual information.

Fixes coverity 1093482

(Directly cast to socklen_t)
2023-10-19 07:56:21 -04:00
JohnAFernandez b8dc7d643d Fix two small memory leaks (#5679)
Fixes 1093679 and 1093680 from coverity by freeing if an early return is reached.
2023-10-19 07:55:23 -04:00
Goober5000 883ed32796 ai-disable-ship-tactical and ai-disarm-ship-tactical (#5512)
Add "tactical" versions of disable and disarm goals which only perform the specific task without implying anything else.  The target ship is not protected and attack goals are not cleared from other ships.

There is also a new AI profiles flag to make this the default hud squad message command instead of the classic disable/disarm.
2023-10-19 07:50:49 -04:00
Mike Nelson f3dfc85c0f weapon ignores countermeasures flag (#5628) 2023-10-19 07:49:06 -04:00
mjn-mixael e32ea7b694 Merge branch 'master' into fix_lightshafts_optimization
# Conflicts:
#	code/graphics/post_processing.cpp
2023-10-18 23:09:43 -05:00
Tyler Blount 7ef70f6d4d Merge pull request #5627 from MjnMixael/new_controls_xstrs
Add built-in xstrs for SCP-added controls
2023-10-18 20:21:49 -07:00
Tyler Blount 1b1afbf8d7 Merge branch 'master' into new_controls_xstrs 2023-10-18 19:51:26 -07:00
Tyler Blount bfdf05469b Merge pull request #5622 from MjnMixael/scpui_options_localization
SCPUI Options Localization
2023-10-18 19:50:43 -07:00
mjn-mixael aee48373ab Make sure these post processing variables are not optimized out of non Debug builds 2023-10-18 15:07:21 -05:00
mjn-mixael a2f1638a99 adjust XSTR IDs 2023-10-18 13:55:46 -05:00
mjn-mixael 762cf4cb88 We'll get this right eventually 2023-10-18 13:45:55 -05:00
mjn-mixael 705287c8d4 "nothing" to see here 2023-10-18 13:26:05 -05:00
mjn-mixael e2aac31912 Merge branch 'master' into scpui_options_localization
# Conflicts:
#	code/camera/camera.cpp
2023-10-18 12:49:48 -05:00
Tyler Blount a9f5a11813 Merge pull request #5686 from MjnMixael/lua_add_scrollback
Lua add scrollback
2023-10-18 10:21:01 -07:00
mjn-mixael b8728ed828 get team rather than team index 2023-10-18 08:59:24 -05:00
mjn-mixael de1110650f Adjust XSTR IDs per feedback 2023-10-18 08:42:25 -05:00
BMagnu b3295e5a2d Fix near z planes for the cockpit rendering (#5654)
* Properly unify cockpit near planes

* Properly pass near plane to deferred shader
2023-10-18 08:08:22 -04:00
Tyler Blount a6c1b1b04a Merge pull request #5605 from naomimyselfandi/more-message-filters
More message filters
2023-10-18 00:36:24 -07:00
Goober5000 b5fdf52e8c Merge pull request #5428 from Goober5000/remove_key_save
remove hud_squadmsg_save_keys()
2023-10-18 03:25:09 -04:00
Goober5000 c43f5bdd58 Merge pull request #5516 from Goober5000/pof_version_fix
POF version fix
2023-10-18 03:24:55 -04:00
Tyler Blount dc7fc774b8 Merge pull request #5662 from MjnMixael/on_intro_hook
Intro about to play hook
2023-10-18 00:24:44 -07:00
Goober5000 dad16f76c4 Merge pull request #5574 from Goober5000/generateWeaponGroupId
add mn.generateWeaponGroupId()
2023-10-17 20:06:27 -04:00
Goober5000 d10c59f6cc Merge pull request #5629 from Goober5000/arrival_warp_distance
add support for predicting arrival warp distance
2023-10-17 20:06:17 -04:00
Goober5000 3bd2fc9a56 Merge pull request #5677 from Goober5000/fix_5529
rewrite primary weapon cycling
2023-10-17 20:06:10 -04:00
Goober5000 fabff58d09 Merge pull request #5684 from Goober5000/prevent_repeated_death
don't kill/self-destruct ship if it's already dying
2023-10-17 20:05:29 -04:00
Mike Nelson 2fd3bf091d add waytpoint as allowed lua sexp parameter type (#5631) 2023-10-17 19:28:40 -04:00
Mike Nelson b4442d3423 double the allowed cargo (#5626) 2023-10-17 19:27:43 -04:00
Mike Nelson cf4cae7264 add dkjson as a default lua file (#5534) 2023-10-17 19:26:39 -04:00
Mike Nelson ebea1b1240 remove new lines from default generated mission (#5519) 2023-10-17 19:25:06 -04:00
mjn-mixael 54341acb9b allow use of enums 2023-10-16 15:54:53 -05:00
mjn-mixael 07fd188064 lua method to add a message directly to the message log.
(cherry picked from commit 1caceeaa2b9ebe654a102e293146dc23b9f3c2ee)
2023-10-16 15:21:37 -05:00
BMagnu 0cbe06884b Allow to Capture Mouse in FSO window (#5678)
* Allow to capture mouse, and also make window present

* Fix Typo
2023-10-17 03:57:21 +09:00
Goober5000 c1d3e5a2ad Merge pull request #5597 from Goober5000/maneuver_despite_engines
add a maneuver-despite-engines flag
2023-10-16 14:40:05 -04:00
Naomi Coffman 2bcedc34cc Respond to PR feedback 2023-10-16 12:36:48 -04:00
Goober5000 16892c3e46 Merge pull request #5670 from Goober5000/fly_to_ship_upgrade
fix and upgrade ai-fly-to-ship
2023-10-16 04:26:23 -04:00
Goober5000 5c88b75b94 Merge pull request #5524 from Goober5000/splash_aspect_ratio
aspect-ratio-specific splash screens
2023-10-16 03:26:10 -04:00
Goober5000 987c705bc9 address feedback 2023-10-16 03:24:53 -04:00
Goober5000 b89cbbd530 fix and upgrade ai-fly-to-ship
The ai-fly-to-ship goal was added early in FSO's development but never worked right.  Until recently it could crash; and even aside from the crash the AI would try to reach the target's exact position, causing repeated collisions.  This folds ai-fly-to-ship into ai-stay-near-ship, since the behaviors are conceptually the same except for fly-to being satisfied as soon as the target is in range.

This also adds a new "escort" mode usable by both behaviors.  The default Volition behavior is to swoop toward the target in a long, graceful arc; the new mode generates a goal point and flies directly to that point.  These can be toggled via an optional sexp parameter.

There is also some minor cleanup and a new vec3d operator for convenience.

Needed for Scroll; depends on #5667.
2023-10-16 03:24:52 -04:00
Goober5000 d3383d9d87 Merge pull request #5667 from Goober5000/refactor_mission_goal_achievable
refactor ai_mission_goal_achievable
2023-10-16 03:23:43 -04:00
Goober5000 4f6d9c36a8 don't kill/self-destruct ship if it's already dying
If a ship is in the process of dying, it shouldn't be killed or self-destructed again.  This fixes a bug noticed by RedMageJoe during the Derelict playthrough.

(This situation is distinct from a ship being hit while in the middle of its death roll.  That shortens the death roll but does not try to kill the ship again.)
2023-10-16 00:36:10 -04:00
JohnAFernandez a36157f582 Merge pull request #5540 from MjnMixael/lua_mod_root
LUA get mod root
2023-10-15 23:16:40 -04:00
JohnAFernandez 3837455004 Merge pull request #5617 from MjnMixael/allow_no_subcategory
Allow Lua SEXPs to not specify a subcategory
2023-10-15 23:15:59 -04:00
JohnAFernandez 808f7a88c6 Merge pull request #5557 from MjnMixael/lua_launch_url
Lua method to launch arbitrary url
2023-10-15 23:15:08 -04:00
Goober5000 79702273d5 some tweaks and clarifications 2023-10-15 16:55:50 -04:00
BMagnu d06018bcad Bump version to 23.3 (#5681) 2023-10-15 19:23:34 +00:00
Goober5000 ac87cde80d supercap check should come from params 2023-10-15 14:16:51 -04:00
Goober5000 06d9e02c34 sync up tokens 2023-10-15 13:48:23 -04:00
Asteroth 40233ae05f use a constant for excess speed 2023-10-15 13:43:49 -04:00
Goober5000 57192065d6 change assert to assertion 2023-10-15 13:43:49 -04:00
Goober5000 d2031a476a some fixes 2023-10-15 13:43:49 -04:00
Asteroth c60ea2d4a7 move supercap warp time constant 2023-10-15 13:43:49 -04:00
Asteroth 6843d48358 add math for predicting warp in distance 2023-10-15 13:43:47 -04:00
Goober5000 066b251052 implement UI work for arrival warp distance 2023-10-15 13:42:27 -04:00
BMagnu 4596600627 Fix hiDPI (#5673) 2023-10-16 01:44:33 +09:00
BMagnu ea262f90c0 Make version parsing available (#5655)
* Make version parsing available

* Consolidate version parsing

* Recode version parsing and write test

* remove copy paste error
2023-10-16 01:44:25 +09:00
BMagnu 02e84f212a Fix HUD slewing (#5656)
* Fixup HUD for slewing

* Fix Training Message box

* Lead indicator slew

* Fix HUD Message Head

* Correctly render messages

* Fix HUD offset handling

* HUD offset never makes any sense

* Cleanup offset code

* Remove unused parameter

* Fix Talking Head in RTT mode
2023-10-16 01:44:17 +09:00
Goober5000 a1d92afebf Merge pull request #5659 from Goober5000/objecttypes_warp_range_factor
allow modification of warp audible range via objecttypes.tbl
2023-10-15 12:43:23 -04:00
Goober5000 a20f3ca030 Merge pull request #5561 from Goober5000/special_warp_physics
add "special warp physics" to custom warpin parameters
2023-10-15 12:42:22 -04:00
Goober5000 e132fcf74c Merge pull request #5585 from Goober5000/beam_api_stuff
additional beam-related features for Lua
2023-10-15 12:41:05 -04:00
Goober5000 7a4df25fc5 Merge pull request #5566 from Goober5000/allowed_in_campaign
add AllowedInCampaign virtvar
2023-10-14 17:01:50 -04:00
Mike Nelson 08dfcc8b74 lua access to Support Ship availability (#5570) 2023-10-15 05:40:12 +09:00
Mike Nelson 0def45b381 add death message as a dialog hv (#5542) 2023-10-15 05:40:05 +09:00
Goober5000 be6a2b9196 add gr.killAllParticles (#5481)
Some scripts under development will benefit from access to the `particle::kill_all()` function.
2023-10-15 05:39:53 +09:00
Mike Nelson f7413be1d8 preload subspace tunnel flag (#5532) 2023-10-15 05:39:42 +09:00
Mike Nelson 02233fc439 Set timer padding sexp (#5535)
* set timer padding sexp

* allow negative padding
2023-10-15 05:39:33 +09:00
BMagnu febd8cd2ad Allow an asymmetric FOV / Frustrum (#5657)
* Enable Asymmetric Projection FOV

* Properly apply asymmetric FOV to g3_rotate_ functions

* De-CPP14-ify

* cleanup

* Make GCC happy

* Fix Vertical Asymmetric FOV

* Fix printf
2023-10-15 05:39:24 +09:00
Goober5000 bf7125724d small updates 2023-10-12 18:07:11 -04:00
Goober5000 efce98db47 rewrite primary weapon cycling
Remove a whole bunch of ad-hoc code piled on top of the retail weapon cycling behavior, then replace it with a robust algorithm that takes all relevant attributes into account.

Fixes #5529.
2023-10-12 17:50:04 -04:00
Goober5000 45abdefc07 add "Calculate subsystem hitpoints after parsing" option
Subsystem hitpoints are calculated as a percentage of the ship's hull strength as they are parsed.  If a modular table modifies the ship's hull strength, the subsystems are not modified at the same time.  This can lead to unreasonably large or small subsystem hitpoint values, as recently seen in the 1.3.0 version of Cardinal Spear.

This PR adds an option to defer hitpoint calculation until after parsing so that the subsystem is a percentage of the correct hull strength.  Since this may affect the balance of existing mods, it is off by default unless the build targets 24.0 or later.

This also removes the long-unused `hull_percentage_of_hits` check and adds several log statements for significant options in game_settings.tbl.
2023-10-06 20:52:22 -04:00
Goober5000 73c612034b log the filename 2023-10-06 13:07:46 -04:00
Goober5000 1ae9aaab21 Merge pull request #5669 from Goober5000/additional_shipstatus_fixes
additional ShipStatus fixes
2023-10-06 01:13:45 -04:00
Goober5000 3a46ed66ba additional ShipStatus fixes
Update the Lua enums to be consistent with the new ShipStatus enums.

Separately, add an extra ship registry check in the event a ship doesn't exist in the ship registry.
2023-10-06 00:38:23 -04:00
Goober5000 f98806b034 refactor ai_mission_goal_achievable
Change `ai_mission_goal_achievable` to use the ship registry instead of looking up the target repeatedly.
2023-10-05 23:15:28 -04:00
Goober5000 1812efa209 Merge pull request #5666 from Goober5000/fix_briefing_popup
fix replacement textures in briefing popup
2023-10-05 23:07:28 -04:00
Goober5000 2966757e62 Merge pull request #5668 from Goober5000/better_message
tweak error message
2023-10-05 23:07:20 -04:00
Goober5000 bc3aad374e tweak error message
For better debugging.
2023-10-05 22:23:02 -04:00
Goober5000 dcfea6f141 modify and address feedback 2023-10-05 17:32:53 -04:00
Goober5000 c5d192524e Merge pull request #5665 from notimaginative/add_mac_to_forum_posts
add macOS builds back to forum release build posts
2023-10-05 02:24:10 -04:00
Goober5000 7a47cc0521 fix replacement textures in briefing popup
Use the same method for texture replacement in briefing popups that is already used in the tech room.

Also don't render shadows when the jump node is displayed, since it's not being lit anyway.
2023-10-05 00:59:57 -04:00
Taylor Richards a33cc0f6c4 add macOS builds back to forum release build posts 2023-10-05 00:22:55 -04:00
Goober5000 af4ec4facc Merge pull request #5663 from Goober5000/fix_5661
remove incorrect setting of ship status
2023-10-04 23:10:52 -04:00
Goober5000 d897643217 tweak messages per feedback 2023-10-04 22:25:29 -04:00
Goober5000 5688ba8637 fix incorrect setting of disabled/disarmed flags when cheating
Normally the disabled/disarmed flags are only set if the destroyed subsystem is actually an engine or turret.  This should be done for cheats as well, otherwise, for example, destroying any subsystem on a non-engined ship will cause it to become disabled.
2023-10-04 22:18:44 -04:00
Goober5000 6631975e45 some additional fixes 2023-10-04 21:15:30 -04:00
Goober5000 fa2b135bb1 remove incorrect setting of ship status
There is a bit of code in missionparse that sets the parse object because in-game joining needs it.  This is unrelated to ship status, so the status shouldn't be changed.  This fixes the bug and adds a comment to clarify the situation, as well as some warnings to help track down incorrect joining states.

Fixes #5661.  Follow-up to #5658 (where the regression was introduced) and #4836 (which fixed in-game joining).
2023-10-04 20:46:22 -04:00
mjn-mixael 1ce9d46822 Intro about to play hook 2023-10-04 11:16:48 -05:00
Tyler Blount 7f4d78f44a Merge pull request #5639 from Goober5000/red_alert_wing_status
add wing status to red-alert system
2023-10-03 18:11:30 -07:00
Tyler Blount 10f484a504 Merge pull request #5649 from Goober5000/fix_ship_status
fix ShipStatus states to correctly account for exploding ships
2023-10-03 18:11:25 -07:00
Tyler Blount f0c8c9ad74 Merge pull request #5658 from Goober5000/fix_barrel_roll
fix barrel roll crash in Star Fox: Event Horizon
2023-10-03 18:11:18 -07:00
Goober5000 79579eda94 fix barrel roll crash in Star Fox: Event Horizon
The Star Fox barrel roll effect is achieved using a script which spawns a new ship.  The script sets no-collide on this spawned ship, but it also tries to set the ship flag for all future ships -- and future ships require a parse object, which doesn't exist for a created ship.  This patches the FALLTHROUGH in the sexp code to account for that possibility.

Separately, there are other ways a parse object pointer could become null through unusual code states, so this adds an INVALID status and several additional checks to defend against this crash in other circumstances.
2023-10-03 14:00:22 -04:00
Goober5000 f7b9896294 allow modification of warp audible range via objecttypes.tbl
The retail warp range multiplier can yield ridiculous results, like an Elysium warp being audible over 9000 meters away.  So allow the multiplier to be set via ship type.
2023-10-03 12:50:05 -04:00
Goober5000 be8ec82649 Merge pull request #5642 from BMagnu/fix_null_shiphit
Fix null dereference when a subsystem is hit for damage by a null object
2023-10-02 20:20:56 -04:00
Goober5000 b72b7688f9 Merge pull request #5634 from Baezon/fix-ai-subsys-attack-subobj
Fix for improved subsys attack pathing
2023-10-02 20:20:32 -04:00
Birk Magnussen c2e01864d5 Incorporate feedback 2023-10-02 17:48:03 +02:00
Goober5000 7a4d4466fd Merge pull request #5651 from Goober5000/fly_to_ship_mode_fix
fix crash when a ship has the fly-to-ship goal
2023-10-02 11:14:05 -04:00
Goober5000 ec75cac4d9 fix crash when a ship has the fly-to-ship goal
Add the missing AI mode in the switch block.  Also remove some redundant `break`s.
2023-10-02 00:04:02 -04:00
Goober5000 b6c0e8b562 fix ShipStatus states to correctly account for exploding ships
Adds a `DEATH_ROLL` status to specifically cover the state after ships have been destroyed but before they exit.  I've also audited all code that interacts with the ship registry to use the correct state with this new state taken into consideration.

This fixes access to exploding ships that was broken when the ship registry framework was introduced.  In particular, the `when destroyed X beam-lock-all X` QoL feature now works again.
2023-10-01 18:10:55 -04:00
JohnAFernandez 8d0570846b Merge pull request #5647 from notimaginative/fix_mac_id10t_error
fix bad extraction command in mac distribution zip
2023-10-01 12:55:19 -04:00
Taylor Richards 93d0624b3e fix bad extraction command in mac distribution zip 2023-10-01 03:22:15 -04:00
Goober5000 563445466e Merge pull request #5646 from Goober5000/warning_message_tweaks
tweak some model warning messages
2023-09-30 22:32:40 -04:00
Goober5000 b7e9d4c9cb tweak some model warning messages
Per a thread in the TBP forum, elaborate on these model warnings a bit.

Two other small code tweaks as well.
2023-09-30 20:06:41 -04:00
Birk Magnussen 348fb5ffb4 Change to variables 2023-10-01 01:25:38 +02:00
Taylor Richards d754c2cb50 tweak directory copying for frameworks on macOS (#5641)
CMake's copy_directory functions follow symlinks recursively as opposed to
preserving them. For mac frameworks, which make use of symlinks for versioning,
this causes the files to be duplicated multiple times in the copied framework.
Using rsync instead, just for frameworks, will properly duplicate the framework
while still avoiding the "file exists" error from cp.
2023-09-30 08:51:35 -04:00
Taylor Richards b760c5dec8 tweak mac build packaging (#5640)
Use GNU tar instead of the default bsdtar. This works around some weird
corruption bug triggered by the combination of the GitHub runner-VM, the llvm
linker, and bsdtar.

Adjust intermediate filenames such that they don't get uploaded to
indiegames by mistake.

Unpack builds as a single step instead of two.
2023-09-30 08:51:01 -04:00
JohnAFernandez 9c9b06a1b1 Merge pull request #5635 from MjnMixael/fix_gameplay_help
Do not clear Help Text
2023-09-30 05:02:20 -04:00
Birk Magnussen 30da49be81 Fix null dereference when hit for damage by a null object 2023-09-30 09:55:47 +02:00
Goober5000 c2d0eafc36 add wing status to red-alert system
If consecutive red-alert missions have different numbers of ships in a wing, then calculating the number of waves will not be correct.  This necessitates the addition of wing status to the stored data for red-alert sequences.

Not only must wing data be stored in `Red_alert_wing_status`, but also in the CSG file.  This necessitates a version bump.  Fortunately, the current design of CSG files allows extra data to be added to a section without breaking old builds, since the CSG loader will just skip over the unrecognized data.

This also renames `red_alert_wingman_status` to `red_alert_ship_status` since it's not limited to wingmen, as well as fixing the omission of exited ships if they are in the player's wing but don't have the red-alert-carry flag.

Fixes #5637.  Follow-up to #4457 and #5609.
2023-09-28 21:14:11 -04:00
mjn-mixael e3c7f81412 do not clear this 2023-09-27 23:17:32 -05:00
Asteroth 2b155c7a30 separate variable 2023-09-27 16:40:29 -04:00
Goober5000 df69993a84 Merge pull request #5633 from Goober5000/tweak_weapon_detonation
fix weapon detonation
2023-09-27 15:30:44 -04:00
Asteroth 3fb5bf1f5f fix world pos getting of target subsys 2023-09-27 14:35:53 -04:00
Goober5000 6823e24350 fix weapon detonation
Add some extra logic implied by the `Begun_detonation` flag.  Missiles that are homing can have their targets, headings, speeds, and lifetimes changed for various reasons.  If a missile has begun detonation, particularly if it is in "detonation limbo" because it is flying across a bowl-shaped turret, we don't want to change any of that.  The "detonation limbo" weapon lifetime is only accurate if all of those values remain constant.

Follow up to #4006.
2023-09-27 13:30:37 -04:00
MageKing17 305a7f6630 Show both name and callsign in escort list.
In #5477, I made the escort list respect hidden names by copying the behavior from `message_queue_process()`, which already checked those flags; however, this resulted in some dramatic behavioral changes for mods using callsigns for escort ships, and while making the behavior optional was a possibility, feedback suggested everyone would rather it just behaved like the target box and displayed both. So I replaced the code with similar logic from hudtargetbox.cpp, except with the "replace hidden name with ship class" code taking priority.
2023-09-26 16:33:45 -07:00
mjn-mixael 14a98e1470 add built-in xstrs for these controls 2023-09-26 10:07:29 -05:00
Goober5000 4ba6191e0c Merge pull request #5623 from notimaginative/fix_macos_packaging
fix macOS build packaging issues
2023-09-25 17:14:44 -04:00
mjn-mixael cb5bf05424 update comments here 2023-09-25 15:58:11 -05:00
Tyler Blount b4f633767e Merge pull request #5616 from Goober5000/HomingSubsys_fix
some fixes for setting HomingSubsystem in script
2023-09-25 13:56:24 -07:00
Naomi Coffman 15db3b17bc Respond to PR feedback 2023-09-24 11:09:31 -04:00
mjn-mixael ba2c37a1fe xstr the boolean default on/off as well 2023-09-22 23:24:52 -05:00
mjn-mixael aa997dd9ed Fix some overlapping xstrs 2023-09-22 23:11:08 -05:00
Taylor Richards 6dbfba2c9f fix macOS build packaging issues
- handle double archiving of macOS builds so they'll work properly with Knossos
 - fix issue where only a single configuration was included in the package
   (Release or FastDebug, not both)
2023-09-22 22:14:15 -04:00
Taylor Richards 9748de5ec1 Merge pull request #5621 from notimaginative/use_static_libstdc++
use static libstdc++
2023-09-22 22:13:05 -04:00
mjn-mixael a0a523223c clean up options builders and use delayed xstr for localization 2023-09-22 19:15:42 -05:00
Taylor Richards 0765c7be95 try and fix clang build error 2023-09-22 16:17:23 -04:00
Taylor Richards 73f8e57961 statically link to libstdc++
Statically link to libstdc++ for CI/CD builds in an attempt
to avoid compatibility issues without relying on a crippled
docker build image.

Should properly fix #5571
2023-09-22 15:13:43 -04:00
Taylor Richards 743d8dd666 Revert "Revert "Update build image with curl and jq preinstalled""
This reverts commit f67814aaae.
2023-09-22 15:12:20 -04:00
mjn-mixael 8fbf22a055 allow lua sexps to not specify a subcategory 2023-09-21 10:12:17 -05:00
Goober5000 7b410b2116 some fixes for setting HomingSubsystem in script
1. Allow setting the homing subsystem if the homing object has already been set
2. Use the `weapon_set_tracking_info` function if setting both object and subsystem, as it handles several important homing things
2023-09-20 23:29:04 -04:00
Tyler Blount 8fed4437ee Merge pull request #5614 from MjnMixael/fix_setting_mission_stats
Fix setting mission stats
2023-09-20 10:57:05 -07:00
Tyler Blount ad25418f92 Merge pull request #5613 from MjnMixael/fix_get_shipclass_kills
Fix Lua API Error with Player Stats
2023-09-20 10:52:15 -07:00
mjn-mixael 5972457ad5 fix setting mission stats 2023-09-19 10:57:30 -05:00
mjn-mixael 35876bc17e fix api error 2023-09-18 23:15:56 -05:00
Goober5000 46fa212db6 Merge pull request #5610 from Goober5000/collide_and_no_collide_sync
sync setting and getting of collides and no_collide
2023-09-17 18:28:22 -04:00
Goober5000 d0d65cd30c Merge pull request #5609 from Goober5000/red_alert_followup
improve checks for red-alert status
2023-09-17 18:28:15 -04:00
Goober5000 cb0e9ce601 sync setting and getting of collides and no_collide
The `collides` and `no_collide` flags are equivalent, but opposite.  So when sexps or scripts get or set those flags, allow each to be used as an anti-synonym (not exactly an antonym) for the other.
2023-09-17 01:23:31 -04:00
Goober5000 13bc0362c8 improve checks for red-alert status
Two fixes for red alert missions:
1. Since any ship in the wing can be stored, not just the wing leader, the "prospective name" check should check for all possible names in each wave
2. If a wing wasn't actually stored, the red alert code should not reset the wing's wave number to 0

Follow-up to #4457.
2023-09-17 00:17:39 -04:00
Goober5000 5749b856df Merge pull request #5606 from Goober5000/revert_5547
Revert 5547 and 5580
2023-09-16 15:39:35 -04:00
Goober5000 f67814aaae Revert "Update build image with curl and jq preinstalled"
This reverts commit 0219e65b00.
2023-09-16 14:58:39 -04:00
Goober5000 24daea79f3 Revert "Change ubuntu-latest to ubuntu-20.04"
This reverts commit 45306da4fe.
2023-09-16 14:58:27 -04:00
Goober5000 0f013f920b Revert "modify per feedback"
This reverts commit 679c3606c5.
2023-09-16 14:58:17 -04:00
Naomi Coffman 0811c7037b Allow (easily) requiring an exact mood match 2023-09-16 13:47:00 -04:00
Naomi Coffman f13a5b3736 Allow specifying tiebreakers between builtin messages 2023-09-16 13:47:00 -04:00
Naomi Coffman 04a5778235 Allow filtering builtin messages by nearby ships 2023-09-16 13:47:00 -04:00
Goober5000 5a941c1d59 small speedup to drawString
Since `gr_string` can accept a length parameter, there's no need to copy each line before it is drawn.

Related to #5495 but not one of the two options mentioned.
2023-09-16 13:43:11 -04:00
Goober5000 d0c3c7db21 Merge pull request #5602 from Goober5000/sexp_fixes
fix crash in unusually formatted handwritten SEXP
2023-09-16 13:34:26 -04:00
Goober5000 be678c2f54 Merge pull request #5603 from Goober5000/fix_message_candidates
fix random selection of message candidates
2023-09-16 13:34:14 -04:00
Naomi Coffman 9586f21780 Add team filters to messages 2023-09-16 10:24:40 -04:00
Goober5000 ed5a5861f7 aspect-ratio-specific splash screens
Adds the ability to specify an aspect ratio, or a range of aspect ratios, to be used by splash screens.
2023-09-16 02:18:10 -04:00
Goober5000 16180306ad fix random selection of message candidates
The `Random::next(low, high)` function returns a value in [low, high].  This location should use the single-argument version, `Random::next(int modulus)`, which returns a value in [0, modulus-1].
2023-09-16 02:12:22 -04:00
Goober5000 865045a231 fix crash in unusually formatted handwritten SEXP
As reported by Colt, there was a crash in the in-mission jump sequence in Shepherds where the mission previously worked.  The proximate cause was a handwritten SEXP called via script that omitted whitespace before an opening parenthesis.  This was incorrectly recognized by the upgraded SEXP parser as an invalid SEXP.  Unfortunately, a separate bug in `get_line_num()` caused a crash when the parser tried to display a warning, because the function tried to calculate the line number of a SEXP that did not come from a parsed file.

This commit fixes the parser to recognize opening parentheses even when no whitespace precedes them, moves the output to the 'unexpected end of sexp' warnings will they will now be seen, and fixes `get_line_num()` to work when there is no parsed text.

Follow-up to #5520.
2023-09-15 15:12:44 -04:00
Tyler Blount 0b54c741a6 Merge pull request #5599 from MjnMixael/fix_scpui_reset_loadout
Actually reset the weapon pool with SCPUI
2023-09-14 15:26:32 -07:00
mjn-mixael baa34f1ffe Actually reset the weapon pool, dummy 2023-09-14 10:46:52 -05:00
Goober5000 89b33ebbc5 add a maneuver-despite-engines flag
This flag ignores engine status when determining whether and how a ship can maneuver.  Implements #5503.
2023-09-13 22:36:58 -04:00
Goober5000 53e6edf8bb documentation 2023-09-10 17:40:02 -04:00
Tyler Blount 0220ad0563 Merge pull request #5594 from MjnMixael/fix_campaign_saving_scpui
Save player after changing campaign in scpui
2023-09-10 13:55:59 -07:00
Tyler Blount 910521bdfe Merge pull request #4457 from JohnAFernandez/restore-red-alert-flags
Fix wing persistence and ensure checks for depleted wings are valid
2023-09-10 13:55:34 -07:00
Goober5000 7003e5caa2 get the wave count correct 2023-09-10 13:49:31 -04:00
mjn-mixael 8efe146300 save player after changing campaign in scpui 2023-09-09 23:01:59 -05:00
Asteroth a14fb35713 initialize trail info better (#5588) 2023-09-09 02:41:55 -04:00
Goober5000 2d0dc7798d unused variable 2023-09-09 00:41:44 -04:00
Goober5000 8242e3b94b small edits 2023-09-08 19:40:53 -04:00
Goober5000 16cb6b3f2f rewrite red-alert bashing routine 2023-09-08 19:13:58 -04:00
Goober5000 8c9be400a6 Merge branch 'master' into restore-red-alert-flags 2023-09-08 00:57:54 -04:00
Goober5000 7974a682ef Merge pull request #5581 from TRBlount/briefing_icon_scale_followup
Follow-up for briefing icon scaling
2023-09-07 23:12:11 -04:00
Goober5000 41af098d19 Merge pull request #5582 from TRBlount/starfield_timestamp_fix
Update starfield animation handling
2023-09-07 23:12:04 -04:00
Goober5000 4c95370f74 add parse object flag for starting wing, and move starting wing checks to post-processing 2023-09-07 20:56:54 -04:00
Goober5000 a6730a997c feedback 2023-09-07 19:15:56 -04:00
Goober5000 c5b84d9406 Merge pull request #5589 from Goober5000/beam_armor_fix
supply parameter for is_beam in all armor checks
2023-09-07 16:40:52 -04:00
Tyler Blount d2f5a12d5f Add parentheses to make order of operations more clear 2023-09-06 19:26:20 -07:00
Tyler Blount 6f6e839bbf Update starfield animation handling 2023-09-06 19:23:48 -07:00
Goober5000 065524fd4b Merge pull request #5586 from Goober5000/firepoint_followup
fix the logic for lighting up firing points
2023-09-06 18:22:27 -04:00
Goober5000 c84cb7ab64 supply parameter for is_beam in all armor checks
For certain calculations involving armor, the `GetDamage` function needs to know if the damage is being applied by a beam so it can apply the calculations with the proper frametime.  The parameter was not provided in all cases, so this fixes that.

Follow-up to #1609.
2023-09-06 18:17:37 -04:00
Goober5000 587ed4e41f convert magic number to constant 2023-09-06 12:13:36 -04:00
Goober5000 8b8daece46 additional beam-related features for Lua
1. Add a `vanish()` function for beam objects, to be consistent with other object types
2. Add a `BeamFree` virtvar, analogous to `TurretLocked`
3. Add timestamp variants of TurretLocked and BeamFree to be consistent with sexps
4. Add `BeamLife`, `BeamWarmup`, and `BeamWarmdown` virtvars so scripts can access table properties
5. Add "On Beam Death", "On Beam Warmup", and "On Beam Warmdown" hooks
6. Clarify some existing documentation and patch a couple things
2023-09-06 00:28:07 -04:00
John Fernandez d73d46feb2 Stupidest typo in history 2023-09-04 14:50:01 -04:00
Goober5000 a881b339cc fix the logic for lighting up firing points
The firing point gauge did not work as advertised; this fixes it.  Unselected weapons are dimmed, selected weapons are normal, and firing weapons are bright.
2023-09-04 14:25:06 -04:00
Tyler Blount 1f90be0a86 Merge pull request #5584 from Goober5000/firepoint_fix
fix crash in firepoint gauge
2023-09-04 11:06:42 -07:00
Goober5000 4ce02ce291 fix crash in firepoint gauge
The gauge assumes that all firepoints will always have weapons, but it's possible for a ship to have less than the maximum number of weapons.
2023-09-03 18:07:40 -04:00
John Fernandez 7d83ece711 And make sure we can call the constructor 2023-09-01 19:34:25 -04:00
John Fernandez 9ee1a6eb23 Add a constructor for red_alert_wing_status 2023-09-01 19:25:36 -04:00
John Fernandez f258554304 add bash wingman status
And function calls.
2023-09-01 19:02:19 -04:00
John Fernandez 994048eb24 Create Struct And functions for restoring wings
This needs to be separate from ships
2023-09-01 16:54:46 -04:00
Tyler Blount 0af3197a90 Follow-up for briefing icon scaling 2023-09-01 12:15:41 -07:00
Goober5000 e5824b41bb Merge pull request #5580 from Goober5000/ubuntu_version_tweak
Change ubuntu-latest to ubuntu-20.04
2023-09-01 12:41:25 -04:00
Goober5000 679c3606c5 modify per feedback 2023-08-31 17:30:08 -04:00
Mike Nelson acbab034cc wtf (#5579) 2023-08-30 23:03:48 -04:00
Goober5000 45306da4fe Change ubuntu-latest to ubuntu-20.04 2023-08-30 22:57:29 -04:00
Goober5000 f09c7b3ba5 Merge pull request #5577 from Goober5000/additional_music_checks
additional music checks
2023-08-30 13:11:28 -04:00
John Fernandez 964f495238 A theoretical fix for invalid checks
Replace `wingp->num_waves == 0` with valid `wingp->current_wave >= wingp->num_waves` and correct six year old copy paste error.
2023-08-29 01:25:33 -04:00
Goober5000 865f7e725c Merge pull request #5578 from Goober5000/soundtrack_start_fix
fix soundtrack timestamp when change-soundtrack is called immediately
2023-08-27 16:33:28 -04:00
Goober5000 6a550a6701 additional music checks
This adds several fixes to make the event and menu music more robust:
1. The game will now run with zero soundtracks.  All accesses into a potentially empty vector should now have checks.
2. Soundtracks and menu music are now checked for validity before being played (not just when importing a FSM mission).
3. The parsing validity checks and the in-game event music now check for skippable patterns using the same function.
4. Zero measures and zero samples-per-measure now cause the game to skip a pattern.  Negative values now trigger a warning.
5. Omitting some or all of the `$Name:` lines for a soundtrack will not cause an assert.

Fixes #5576.  Follow-up to #5572.
2023-08-25 19:22:03 -04:00
Goober5000 ad2531efcc fix soundtrack timestamp when change-soundtrack is called immediately
There is a built-in delay for the event music to start playing, but this delay gets stepped on if `change-soundtrack` is called when the mission first starts.  So don't set the delay unless it has already elapsed at least once before.
2023-08-25 19:20:21 -04:00
Goober5000 8af06b9e78 Merge pull request #5575 from Goober5000/obj_sound_fix
fix persistent sounds not clearing their tally
2023-08-25 19:08:06 -04:00
Goober5000 b6eef2e8f2 fix persistent sounds not clearing their tally
When a non-looping persistent sound expires, `obj_snd_stop()` actually does need to be called.  Even though the sound is no longer playing, the `Num_obj_sounds_playing` tally needs to be decremented, otherwise it will eventually exceed its limit and prevent any additional persistent sounds from playing.  And it turns out `obj_snd_stop()` returns gracefully for sounds that aren't playing.

Follow-up to #3510.  Fixes a bug that appears to have been around since retail.
2023-08-25 13:27:09 -04:00
Goober5000 344e231058 add mn.generateWeaponGroupId()
The `mn.createWeapon()` function takes an optional group ID for weapons that share lighting, but the internal `weapon_create_group_id()` function was never exposed to the API.  This adds that.
2023-08-25 02:39:40 -04:00
BMagnu 2feeb34629 Move light calculation out of vertex shader (#5573) 2023-08-25 05:46:02 +09:00
Goober5000 9d28ba568c Merge pull request #5572 from Goober5000/5567_followup
fix validity check for soundtracks
2023-08-23 22:28:53 -04:00
Goober5000 1b6ed75d73 filename is already truncated 2023-08-23 21:10:05 -04:00
Goober5000 4cf7ab3474 fix validity check for soundtracks
Since event music soundtracks use the exact file extension specified (see #5567), the validity check should also use the exact file extension specified.

Also, move the validity check to after parsing has completed because extensions may be overridden.
2023-08-23 20:39:26 -04:00
Goober5000 bd4b9cb0d7 Merge pull request #5568 from Goober5000/fix_campaign_crash
fix crash in campaign editor
2023-08-22 20:32:13 -04:00
Goober5000 926e10584c Merge pull request #5567 from Goober5000/event_music_extension_agnostic
handle extension mismatch in event music
2023-08-22 20:32:05 -04:00
Goober5000 defab61664 handle extension mismatch in event music
Currently, menu music will trim the extension and look for both OGG and WAV files, but event music will use the exact extension specified.  This is intended but could lead to unexpected results in mods, so display a warning for the modder.
2023-08-22 15:48:21 -04:00
Goober5000 7dc971a6f2 fix crash in campaign editor
The crash in #5514 appears to be caused by some of the graphics code not being in the expected state for the synchronization.  Looking at the code in `render_frame()`, a `gr_flip()` happens after one frame ends and before the next frame begins.  That implies that this `gr_flip()` should not be here, as it is in the middle of a frame.  For additional evidence, `gr_flip()` modifies the "uniform buffer manager" state, and that is part of the stack trace preceding the crash.  Removing this `gr_flip()` fixes the crash.

The strange thing is that this code *doesn't run at all* while the campaign editor is active.  I verified this by adding a MessageBox in place of `gr_flip()`; the MessageBox doesn't display until the campaign editor is exited.  And yet, FRED crashes with `gr_flip()` present and doesn't crash with it removed.  This calls for a new category of bug; I propose "spookybug", from spooky action-at-a-distance.

Fixes #5514.
2023-08-22 12:47:14 -04:00
Goober5000 e0a6ca9abd Merge pull request #5563 from Goober5000/movie_subtitle_font_tweak
fix $Movie subtitle font: for custom fonts
2023-08-21 16:42:11 -04:00
Goober5000 210a9a8309 add AllowedInCampaign virtvar
These can be used to set whether a ship or weapon is allowed in loadouts, without necessarily waiting for the mission to be accepted.
2023-08-21 16:32:56 -04:00
Goober5000 613fad21c9 fix $Movie subtitle font: for custom fonts
The default movie subtitle font is font01.vf, but mods with custom font tables might not use this font.  So this changes the handling slightly so that the movie player will use whatever the first available font is.

Follow-up to #1523.  Fixes a sometimes spurious warning in mod initialization.
2023-08-19 13:25:13 -04:00
Goober5000 91497d5056 Merge pull request #5560 from Goober5000/fred_help
improve launching of FRED help
2023-08-17 21:25:16 -04:00
Goober5000 6b3e50dade add "special warp physics" to custom warpin parameters
Supercaps use a physics flag on warpin that makes them slow down faster than they would under the normal physics code.  This adds that flag as an option for custom warp parameters.

Since flags are not yet parsed when warp parameters are parsed, the code needs to skip ahead and peek at the flags in the same way as the weapon override.
2023-08-16 19:07:30 -04:00
Goober5000 e796a4fe00 improve launching of FRED help
1. Fall back to the FREDzone help docs if the local files cannot be found
2. Tweak url_launch error message and add a return value

This consequently removes the ReleaseWarning which wasn't the friendliest or clearest way to tell the user about a missing help file.
2023-08-16 12:28:53 -04:00
Goober5000 03f01604d9 Merge pull request #5559 from Goober5000/fix_5515
assign weapon particle effects properly
2023-08-16 11:27:30 -04:00
Goober5000 1547526057 Merge pull request #5558 from Goober5000/streaminganim_extension
some streaming animation fixes
2023-08-16 11:27:21 -04:00
Goober5000 7602b88756 assign weapon particle effects properly
Since `std::unordered_map.insert` does nothing if a key already exists, use bracket notation.  Fixes #5515.
2023-08-15 23:16:07 -04:00
Goober5000 4812ff529d Merge pull request #5550 from Goober5000/modular_weapon_flags
fix flags in modular weapon entries being cleared
2023-08-15 17:41:26 -04:00
Goober5000 fe42c7bdff make alpha value work for streaming EFFs 2023-08-14 18:07:21 -04:00
Goober5000 f706d6c0a0 use the correct resize mode 2023-08-14 17:40:47 -04:00
Goober5000 16b9225533 remove extensions from streaming animations
Since other functions in the scripting API remove extensions before loading the files, and since the internal functions expect them to be removed, the streaming anim API should handle that too.
2023-08-14 16:41:20 -04:00
mjn-mixael 9a7500de36 lua method to launch arbitrary url 2023-08-13 09:27:30 -05:00
Goober5000 64d9b6fb74 Merge pull request #5548 from Goober5000/stay_near_ship_fixes
ai-stay-near-ship fixes
2023-08-13 09:27:52 -04:00
Goober5000 b40f5a15b2 Merge pull request #5553 from Goober5000/nightly_porphyrion_to_perses
nightly build updates
2023-08-10 00:07:24 -04:00
Goober5000 52a5c356cf Merge pull request #5551 from Goober5000/dock_goal_achievability
remove Int3()'s in ai_mission_goal_achievable
2023-08-09 23:51:56 -04:00
Goober5000 e71dba4207 enhance set-armor-type to work with generic subsystems 2023-08-09 18:21:19 -04:00
Goober5000 3b42ee42ca put the hull and shields at the top to be consistent with other sexps 2023-08-09 17:23:13 -04:00
Goober5000 b270c44ede use https for indiegames 2023-08-09 15:17:45 -04:00
Goober5000 6cf6f8a6fe update server 2023-08-09 15:14:43 -04:00
Goober5000 c273496c1e remove obsolete build files 2023-08-09 15:08:36 -04:00
Goober5000 8933aaff38 address feedback and add more chex 2023-08-09 15:01:41 -04:00
Goober5000 a3de0db735 remove Int3()'s in ai_mission_goal_achievable
As reported by Woutersmits, the GTT Nova did not dock with the GTD Hall in the first mission of Black Horizon.  Attempting to run a debug build caused a CTD.  Investigation showed that there was an invalid dockpoint triggering an Int3().  The dockpoint has been fixed, but to aid troubleshooting in the future, the Int3()'s in this function have been changed to more appropriate functions.
2023-08-09 04:11:47 -04:00
Goober5000 0dcb60f805 fix flags in modular weapon entries being cleared
When weapon flags are parsed in a modular table and override the previous set of flags, certain flags must be kept to preserve the behavior of the weapon.  The previous `preset_wi_flags` technique only worked if all such flags (homing, has-display-name, even whether the weapon turns) were set in the same modular table.  If a modular table overrode the flags but didn't specify those lines over again, mysterious and subtle bugs would occur.

This modifies the flag parsing to explicitly preserve all appropriate flags from the existing weapon entry, which fixes the bug.  It also allows all of the flags to be specified in one place, rather than scattering `preset_wi_flags` assignments throughout `parse_weapon`.  And this also adds quite a few flags to the flag list that were not handled at all under the previous design.

Finally this fixes a few incorrect assignments of default values to fields that should only happen the first time a weapon entry is parsed.
2023-08-09 01:49:35 -04:00
MageKing17 1bc7732b6e Merge pull request #5549 from MjnMixael/fix_sexp_descriptions
Correct a few sexp descriptions
2023-08-08 22:44:41 -07:00
mjn-mixael 2a64abfe92 correct a few sexp descriptions 2023-08-08 17:00:12 -05:00
Goober5000 d1e81be2aa ai-stay-near-ship fixes
Three fixes:
1. In commit fa0878b6b3 for PR #5338, the optional distance parameter was inadvertently changed to a bool.  This fixes the parameter.
2. The distance parameter was previously parsed using `atoi` which works for number literals, so change to `eval_num` to allow sexp return values.
3. Make `eval_num` consistent with `eval_sexp` in the sense that evaluating an empty list is valid and returns false or 0.

Also takes advantage of the fact that `is_sexp_true` works for empty lists to streamline optional arguments in `ai_add_goal_sub_sexp`.
2023-08-08 13:07:21 -04:00
Goober5000 e285641ac6 Merge pull request #5528 from Goober5000/detonate_on_expiration
'detonate on expiration' weapon flag
2023-08-07 22:18:58 -04:00
Goober5000 d3b1ad4328 remove vestigial debug variables 2023-08-07 16:59:02 -04:00
Tyler Blount 914f0e13e3 Merge pull request #5526 from Goober5000/hud_set_coords
add screen resolution scaling for hud-set-coords
2023-08-06 15:22:08 -07:00
m!m df68da3dd6 Merge pull request #5547 from asarium/image_curl_jq
Update build image with curl and jq preinstalled
2023-08-06 18:15:05 +02:00
asarium 0219e65b00 Update build image with curl and jq preinstalled
The install step in the CI pipeline is no longer needed after this
change and has been removed.
2023-08-06 17:09:42 +02:00
m!m cc171a6344 Merge pull request #5546 from asarium/fix_file_exists
Fix "File exists" error
2023-08-06 16:44:23 +02:00
asarium 7d066a1c45 Fix "File exists" error
Copying a file with cp on top of another one is not allowed by default
so switching the command to use the CMake provided one will fix the
issue and will also unify the commands for all platforms.

The directory support is necessary for Mac where the SDL library is
actually a directory.
2023-08-06 14:46:46 +02:00
Tyler Blount 6677fcabae Merge pull request #5513 from Goober5000/fred_campaign_path
fix a couple bugs in the campaign editor
2023-08-04 13:46:44 -07:00
Tyler Blount 171d36bf7f Merge pull request #5527 from Goober5000/fix_5507
add model filename back into debug log
2023-08-04 13:46:35 -07:00
Tyler Blount 9018ddf0d5 Merge pull request #5539 from MjnMixael/fix_bitmap_fps
Fix animated background bitmaps rendering with incorrect framerate
2023-08-04 13:46:28 -07:00
Tyler Blount d847236dd2 Merge pull request #5537 from MjnMixael/fix_loadout_ctd
Fix: Prevent loadout related CTD
2023-08-04 13:46:20 -07:00
mjn-mixael bb6b010487 lua get mod root 2023-08-02 12:04:33 -05:00
mjn-mixael 0ee3d099ab and not or dummy 2023-08-02 09:28:07 -05:00
mjn-mixael 9aa48579b0 also check upper range 2023-08-02 09:19:26 -05:00
mjn-mixael bb28d0b859 account for very low framerates 2023-08-02 09:17:01 -05:00
mjn-mixael 2ef3a935e4 Fix animated background bitmaps rendering with incorrect framerate 2023-08-02 08:23:52 -05:00
mjn-mixael 233fa38890 Prevent loadout related CTD 2023-08-01 16:16:30 -05:00
Goober5000 e91d6ed17b 'detonate on expiration' weapon flag
For mods which want primary weapons to 'detonate', setting the detonation range is not reliable because, due to rounding imprecision, either the range (which detonates) or the lifetime (which does not) may happen first.  So this adds a flag to always detonate a weapon when its lifetime expires.  Secondary weapons have this flag by default, but primary weapons can add this flag in the $Flags list.  Additionally, if the detonation range and the predicted range due to lifetime are equal, the flag is added automatically.

Resolves #5521.
2023-07-29 18:23:38 -04:00
Goober5000 f6c86464aa add model filename back into debug log
In #4702 this log line was changed to the 'Model' category, which made it hidden by default.  This was missed in review but should be restored as it is a fairly important line.

Fixes #5507.
2023-07-29 15:29:29 -04:00
Goober5000 dd0af0e07c add screen resolution scaling for hud-set-coords
The hud-set-coords SEXP has always used exact pixels, without regard for the current screen resolution.  This adds a similar scaling mechanism as is used for show-subtitle.

Fixes #5525.
2023-07-29 15:21:43 -04:00
Goober5000 24031db712 Merge pull request #5520 from Goober5000/variable_token_fixes
SEXP parsing cleanup and fixes
2023-07-29 14:18:44 -04:00
Goober5000 d82b02a54a Merge pull request #5517 from Goober5000/fix_fred_bugs
fix mission corruption in FRED
2023-07-29 14:15:10 -04:00
Goober5000 a21876127d comment 2023-07-28 19:54:42 -04:00
Goober5000 f64de84e7c address feedback 2023-07-28 17:08:22 -04:00
Goober5000 feadc0bd69 feedback 2023-07-28 16:45:44 -04:00
Goober5000 1252d794db Merge pull request #5509 from Baezon/fix-laser-single-segment-trails
Some more fixes for laser single segment trails
2023-07-27 23:12:49 -04:00
Goober5000 58fcbde152 Merge pull request #5511 from z64555/fillValues_more_error
Add more error checking in joy-sdl.cpp.
2023-07-27 23:12:24 -04:00
Goober5000 b3970798e1 variables will only be referenced in nodes, not generators like for-counter 2023-07-27 16:14:06 -04:00
Goober5000 da34e25bc3 handle things properly on parse error 2023-07-27 16:07:15 -04:00
Goober5000 7fc75c0d6c more robust handling of Mp, especially after error 2023-07-27 15:04:38 -04:00
Goober5000 859978fd84 upgrade container parsing as well; and check for malformed variable tokens 2023-07-27 03:38:17 -04:00
Goober5000 7781d9fcda fix sexp variables in argument lists 2023-07-27 02:19:54 -04:00
Asteroth 03e876f65b no shadow 2023-07-27 00:58:10 -04:00
Goober5000 9480869e0a make variable parsing more robust; don't assume that an @ is always followed by a valid variable name; fix length checks; soften non-fatal Errors to error_display(0) 2023-07-27 00:04:15 -04:00
Goober5000 481e82303c use tokens in sexp help 2023-07-26 14:55:31 -04:00
Goober5000 689ac56bc8 fix mission corruption in FRED
When using the mission importer, missions were being corrupted for very subtle reasons: due to some code reordering in prior commits, `raw_ptr` would be initialized to `Parse_text_raw` before `Parse_text_raw` itself was initialized.  This assignment was done in the `CFred_mission_save` constructor and the ordering dependency is not obvious.  Since this is a highly fragile situation and has the potential to affect any use of `parse_comments()` in FRED, it's better to explicitly assign `raw_ptr` when it is needed, and just initialize it to nullptr in the constructor.

This also sets the version number to the legacy version (0.10) when the mission is saved in the retail format.
2023-07-26 03:39:17 -04:00
Goober5000 c80f787d34 POF version fix
Modelread.cpp supports POF versions as low as 1900, but early model versions were not loaded properly because they relied on preprocessor directives rather than version checks.  This changes the POF loading to correctly check version numbers and chunk IDs.

Fixes crashes when attempting to load a FS1 model.
2023-07-26 00:00:17 -04:00
Goober5000 c5469982c8 fix a couple bugs in the campaign editor
1. When saving a campaign, the save directory should be the one that the campaign was just loaded from.  If prompting the user, this should be the default save directory.  This fixes a bug where campaigns were saved to %APPDATA% instead of where the FREDder might expect.  This has been a bug ever since the migration of the game files from FreeSpace2 to %APPDATA%.
2. When saving a campaign, save only the external mission flags, not the working flags that are maintained during gameplay but have no meaning in the saved file.
2023-07-25 01:49:10 -04:00
z64555 db64a212d6 Adds more error checking in joy-sdl.cpp.
* In fillValues(), Check the size values returned by SDL to assert they are non-negative.  If they are negative, abort vector resize and mprintf the SDL Error.
2023-07-24 19:01:08 -05:00
Asteroth 0a07b7e0ad some fixes for laser single segment trails 2023-07-24 18:37:03 -04:00
Tyler Blount 833d181700 Merge pull request #5504 from Baezon/fix-cmeasure-single-segment-trail
Fix for countermeasures with a single segment trail
2023-07-23 10:08:35 -07:00
Tyler Blount dfc716d91a Merge pull request #5501 from naomimyselfandi/zero-out-persona-bitfields
Explicitly zero out persona bitfields
2023-07-23 09:58:49 -07:00
Goober5000 8dd6a27418 Merge pull request #5475 from Goober5000/ai_autoscaling_check
prevent AI autoscaling for only a single autoscaled class
2023-07-22 21:46:25 -04:00
Asteroth 691ae8752e fix for countermeasures with a single segment trail 2023-07-20 23:42:35 -04:00
Asteroth 14b4fd3465 Fix weapon flags +override handling wrt spawn flag (#5488)
* fix wep flags +override wrt spawn

* Revert "fix wep flags +override wrt spawn"

This reverts commit 08a2bee1ca.

* parse +override ahead of time

* use string list instead

* hopefully fix whitespace???
2023-07-19 17:09:11 -04:00
Naomi Coffman fc6a1402c3 Explicitly zero out persona bitfields
Personae have a flag and a species bitfield. They're built up during parsing, but never explicitly zeroed out. This leads to ships occasionally getting an incorrect persona (especially common with support ships, which never have an explicit persona).

Additionally, this commit addresses an issue with the UES Aranyaka (and potentially other support ships belonging to species without a support persona). I'm honestly not sure why they were ever able to speak; however, with this change, they'll never be able to. As such, this commit introduces a "default support persona" to retain the desired behavior.
2023-07-19 15:04:18 -04:00
MageKing17 275f96d80c Remove Int3()s from message_translate_tokens().
In f350e06851, two Int3()s were added to `message_translate_tokens()`, to check for possible out-of-bounds errors. However, in c70fdc3a52, just a couple months later, the code being protected by those bounds checks were put into `else` branches, meaning the `Int3()`s became redundant. This wouldn't actually cause any problems unless somebody passed a string with two `$`s at least 40 characters apart to `message_translate_tokens()`. Cue #4876, which started calling `message_translate_tokens()` on debriefing stages and recommendations, which can contain color tags. This still wouldn't cause problems as long as the color tags are in pairs within close proximity (`translate_key()` would say "that's not the name of a scan code" and leave the text between the two tags alone), but as soon as two color tags are far enough apart to trip the bounds check conditional, the `Int3()` would be hit. This is still fine on Release builds, which ignore `Int3()`s, but triggers a breakpoint on debug builds, which depending on the user's system, can result in a CTD. Since, as far as I can tell, the `Int3()`s haven't actually been meaningful since 2006, I've just removed them (and inverted the conditionals), and testing by the affected user confirms that it no longer CTDs.
2023-07-18 13:34:26 -07:00
Goober5000 850d706df2 prevent AI autoscaling for only a single autoscaled class
When only one AI class performs autoscaling, the math formulas which use autoscaling will become meaningless (e.g. in `ai_maybe_launch_cmeasure()`) or will cause divide-by-zero errors (e.g. in `ai_manage_shield()`).  And autoscaling is not very useful outside of the specific ways that Volition used it.  So this adds some warnings and disables single-occurrence autoscaling.

Fixes #5474.
2023-07-18 01:05:18 -04:00
Goober5000 b06c8e72e1 Merge pull request #5499 from Goober5000/fireball_fix
fix Lua API access to Fireballs array
2023-07-18 00:34:53 -04:00
Asteroth b1fd9ffffb Improve performance of collision retiming (#5496)
* fast version of setting position and orientation

* preliminary stale collide time

* add global collision cache stale flag instead

* clean up

* more clean up

* no periods >.>

* bring back single object version

* rename and bring back stale object list

* use a set
2023-07-18 00:28:49 -04:00
Goober5000 e2c264cec4 fix Lua API access to Fireballs array
When fireballs were made dynamic in 609ed4ed94, the `MAX_FIREBALLS` #define lost any relationship to the fireball collection.  This removes it and also correctly specifies the size of the fireball collection.

This fixes a CTD when accessing items in `mn.Fireballs` via script.
2023-07-17 23:33:22 -04:00
Fabian Woltermann 3f889137d7 Merge pull request #5497 from The-E/fix/warn_for_invalid_trail_textures
Add a warning for cases when we couldn't load a trail bitmap
2023-07-17 23:53:48 +02:00
Fabian Woltermann 19f1e6b4ee remove bothersome warning 2023-07-17 23:07:37 +02:00
Goober5000 7e692ebca6 Merge pull request #5498 from Goober5000/5492_followup
add missing #includes to fix compilation
2023-07-17 16:17:03 -04:00
Goober5000 0067a57f8f add missing #includes to fix compilation
These #include lines are needed for the changes introduced in #5492.  Not sure why they weren't picked up by CI, or why they work in some compilers but not others.
2023-07-17 14:58:24 -04:00
Fabian Woltermann e028162dc2 update batching assertions 2023-07-17 18:54:12 +02:00
Fabian Woltermann 9b26439dd3 Add a warning for cases when we couldn't load a trail bitmap 2023-07-17 17:12:33 +02:00
Tyler Blount 1431270287 Merge pull request #5483 from Baezon/hud-gauge-load-safety
Improved hud gauge loading safety
2023-07-16 15:49:17 -07:00
Tyler Blount 06e74fa976 Merge pull request #5491 from MageKing17/bugfix/demo-missing-campaign
When playing the demo, don't try to reset if no campaign is active.
2023-07-16 15:47:59 -07:00
Tyler Blount 318fde51d7 Merge pull request #5492 from MageKing17/bugfix/voice-recognition-while-paused
Ignore voice recognition events while game is paused.
2023-07-16 15:47:51 -07:00
Goober5000 15daaf2633 additional cleanup from PR 5462
Some streamlining and constifying of the readyroom popup list and associated functions.

Followup to #5462.
2023-07-13 01:54:25 -04:00
MageKing17 d253302fc9 Also check popup_active() and popupdead_is_active(). 2023-07-12 16:07:17 -07:00
MageKing17 560eb31e4f Ignore voice recognition events while game is paused.
If you pause the game, say something into the microphone, then unpause, it can abruptly perform an action based on voice recognition; this is probably counter to player expectations. This adds a `gameseq_get_state() != GS_STATE_GAME_PAUSED` check to the existing conditional.
2023-07-12 15:09:36 -07:00
MageKing17 493df37287 When playing the demo, don't try to reset if no campaign is active.
If the "Campaign Room only available in full version" popup is shown, it tries to reset `Active_campaign_index`, except that if a pilot is loaded with a missing campaign file, `Active_campaign_index` is -1. This causes an out-of-bounds array access, so let's present an alternate popup in this case (either one to select whatever the first campaign file found is, or the generic `popup_game_feature_not_in_demo()` if no campaign files are found).
2023-07-12 14:53:40 -07:00
BMagnu 32298b89fd Properly deinit io lib LuaFunctions (#5485) 2023-07-11 07:03:52 +09:00
Asteroth d6ee515873 remove testing prints 2023-07-07 01:22:40 -04:00
Asteroth bc09f0672b better hud gauge load safety 2023-07-07 01:20:11 -04:00
Goober5000 859534a75c Merge pull request #5482 from Goober5000/ship_killer_name_fix
fix some bugs revealed by ships with long display names
2023-07-07 00:41:59 -04:00
Goober5000 5f8234d1cd fix some bugs revealed by ships with long display names
Several related fixes:
1. Copy the actual ship name, not the display name, to `killer_parent_name` for two reasons:
  1a. Since `killer_parent_name` is used to look up the ship, it must be the actual ship name, not the display name.
  1b. Copying the display name can cause a buffer overflow because display names can be longer than 31 characters.
2. The display name functionality is moved to the more appropriate location in `player_generate_death_message()`.
3. Remove `player_get_killer_weapon_name()` which only served as a proxy check for whether the weapon index was used or not.
4. Use `ship_registry_get()` rather than `ship_name_lookup()`.
5. Add comments to clarify the use of `killer_parent_name`.
2023-07-03 20:08:26 -04:00
Goober5000 03e0904398 Merge pull request #5477 from MageKing17/cleanup/ship-name-handling
Avoid displaying hidden ship names in the escort list.
2023-07-03 17:18:43 -04:00
Goober5000 99170a3a70 Merge pull request #5480 from Goober5000/dockpoint_checks
add some additional safety checks for dockpoint paths
2023-07-03 17:18:31 -04:00
Goober5000 9b72fb6592 add some additional safety checks for dockpoint paths
1. Check that a path index is in range
2. Check that a path's parent submodel is the same as the dockpoint's parent submodel
2023-07-03 12:35:34 -04:00
Goober5000 ed6adeb281 Merge pull request #5479 from Goober5000/fix_instructor_check
fix instructor check
2023-07-02 22:59:55 -04:00
Goober5000 7c13df5881 fix instructor check
Fix the instructor check for whether a ship should circle or not.  Follow-up to #5353.  Fixes #5478.
2023-07-02 22:13:54 -04:00
BMagnu c6a98ad228 Clear Thread-stuff more aggressively (#5476) 2023-07-03 04:38:15 +09:00
MageKing17 927567ffed Avoid displaying hidden ship names in the escort list.
Secondarily, display callsigns in the escort list, if one is given.
2023-07-02 11:26:52 -07:00
Tyler Blount 5ebf530a30 Merge pull request #5473 from MageKing17/bugfix/avoid-split-line-once-assertion
Remove `max_pixel_w > 0` assertion from `split_str_once()`.
2023-06-30 08:44:48 -07:00
MageKing17 b32b54a737 Remove max_pixel_w > 0 assertion from split_str_once().
In at least two instances, `split_str_once()` can be called with width values derived from mod-supplied values that can be 0 or less (specifically, two hud gauges: if `+Messages:` has a `Max Width:` that's too small, or `+Directives:` has a `Max Line Width:` of 0 or less). Since user-supplied code shouldn't be tripping assertions, I looked into adding security around the calling sites when I realized that the assertion wasn't actually protecting against anything; the function would run just fine with a negative pixel width, it would just break with every whitespace. Since both calling sites that could trip the assertion already treat getting `src` back as output as an "I can't split this" error condition, it's perfectly fine (and skips iterating through the string) to just `return src` if the maximum pixel width is 0 or less, so let's just do that instead. Technically this is a behavior change in Release code, but the result of the old code would've been to spam the message log with every individual word in every message (if `Max Width:` was too small), and for directives to seemingly-randomly split only after the first word (if `Max Line Width:` was 0 or less). Not splitting at all is at least as correct, saves some pointless processing, and *should* still be obviously wrong if there was supposed to be a reasonable width value.
2023-06-28 11:56:38 -07:00
Goober5000 447ed95878 Merge pull request #5469 from Goober5000/fix_5387
tweak filename length check for PNGs
2023-06-25 01:33:02 -04:00
Goober5000 1ddf247fd5 Merge pull request #5471 from Goober5000/fix_5470
fix Assertion in turret_swarm_set_up_info
2023-06-25 00:32:16 -04:00
Goober5000 7f05f775af fix Assertion in turret_swarm_set_up_info
It appears that `(turret->turret_enemy_objnum < 0)` is an expected and allowed condition, so just assert that the objnum does not exceed MAX_OBJECTS.

Fixes #5470.
2023-06-23 22:55:41 -04:00
Goober5000 6cfc54499d tweak filename length check for PNGs
This is a bit tricky because both animated and non-animated PNGs use the same extension.  So for PNGs we need to defer the filename length check until we know for sure that it is an animated image.

Fixes #5387.
2023-06-21 03:45:14 -04:00
Joshua Glatt 4fa5c0d3e7 Fix save on mission close' container (#5463) 2023-06-20 21:12:37 -07:00
Goober5000 8c237626a5 Merge pull request #5462 from Goober5000/fix_5459
allow getting of mission info even for files with long names
2023-06-20 18:10:09 -04:00
BMagnu 41312265d5 Decouple MSAA from deferred end (#5467) 2023-06-21 06:17:56 +09:00
Goober5000 ee42e767a5 add warning to save; and make loading/saving more robust 2023-06-19 16:17:01 -04:00
wookieejedi f6b445ed2e Fix crash that can occur due to invalid glow point bank (#5465)
PR adds extra validity check within `model_render_glowpoints` function. Other places in code that use `bank->submodel_parent` check for validity before looking up `pmi->submodel`, but this check was missing from this section (which caused a CTD in a mission restart due to `bank->submodel_parent` being -1).
2023-06-18 22:14:16 -04:00
Goober5000 17d36156cb add const where appropriate to the modelrender API
See title.  There were some cascade effects, but the changes are mostly contained to the model code.  The calls to `gr_render_model` and `g3_render_primitives` use `const_cast` because constifying that API would require a whole other PR.
2023-06-18 14:05:46 -04:00
Goober5000 126c2e27f7 allow getting of mission info even for files with long names
Issue #5459 notes that mission files that are too long will crash the FRED campaign editor, but this is an artificial restriction.  The only need for a string buffer here is to enforce the correct mission extension, so use a SCP_string for this, and add checks for whether string manipulation is in fact necessary.  (In most cases it isn't.)

Fixes #5459.
2023-06-17 01:05:59 -04:00
Tyler Blount f4aa5c079f Merge pull request #5461 from TRBlount/23_2_RC
Begin 23.2 Release Cycle
2023-06-16 19:10:13 -07:00
Tyler Blount 4f9e1360a5 Update changelog and release.mako for 23.2 2023-06-16 17:13:38 -07:00
Tyler Blount d839f9f3c9 Merge pull request #5444 from Goober5000/5401_followup
refinements of jump node features
2023-06-16 14:38:12 -07:00
Tyler Blount 9d10066da7 Merge pull request #5318 from Goober5000/per_species_warp
add per-species warp effects
2023-06-16 14:35:45 -07:00
Goober5000 d42f3f79ac Merge pull request #5457 from Goober5000/zero_sun_bank
fix angle conversions in FRED
2023-06-15 22:32:33 -04:00
Goober5000 32982351dc Merge pull request #5456 from Goober5000/kitsune_fix
handle special characters in additional places in FRED
2023-06-15 22:32:24 -04:00
Goober5000 bcb9e48586 fix angle conversions in FRED
In certain cases, angles would be rounded to 360, where the expected range is 0-359.  The range was guarded properly for skyboxes but not for bitmaps and suns.  This fixes that.  Additionally, since suns do not bank, the angle conversion now sets the bank to 0.

Fixes #5390.
2023-06-14 14:31:12 -04:00
wookieejedi df323423dd Update Some Newish CM Options to Floats (#5452) 2023-06-12 19:24:07 -04:00
Goober5000 26abf577cc handle special characters in additional places in FRED
Kitsune discovered that special characters, notably semicolons, were not properly handled in the Mission Specs editor.  This adds appropriate handling of special characters for fields in that editor, similar fields in the campaign editor, and the corresponding places in qtFRED.  This also makes error messages more descriptive for campaign load failures.
2023-06-11 16:34:50 -04:00
BMagnu 7c0827aaa2 Move bad check (#5455) 2023-06-10 23:13:26 +02:00
Asteroth 4845f6837d fix ai reposition oversight (#5454) 2023-06-08 20:13:46 -04:00
Shivansps 15e7fb16d1 Validate chunk size to avoid align crash and add align skip flag (#5450)
* validate chunk size to avoid align crash and add align skip flag

* change type from uint to int

* change mprintf output to a warning

* revert uint to int change and requested changes
2023-06-08 16:05:56 -04:00
Asteroth 60f3aa59d6 Make lasers less kinky (#5446)
* properly handle trapezoidal bitmaps

* clean up

* fixup single segment trails too

* fix
2023-06-07 19:59:07 -04:00
BMagnu 8562dde955 OpenGL Capability Handling (#5445)
* Init Particle shaders only if they're actually used

* set layout correctly

* Don't compile shadow shader if not needed

* Properly deal with capabilities

* Fix typo

* remove obsolete capability
2023-06-07 19:58:55 -04:00
Mike Nelson 85f915f352 Fix typo and copy/paste error (#5449) 2023-06-06 16:39:35 -04:00
Goober5000 23f6b39597 Merge pull request #5407 from z64555/fix/5405
Fix 5405
2023-06-05 21:45:01 -04:00
Goober5000 c7bc0a7263 Merge pull request #5443 from Goober5000/lighting_profiles_followup
some updates to the lighting profile code
2023-06-05 21:44:35 -04:00
Goober5000 3ae178e125 refinements of jump node features
1. Deprecate the old set-jumpnode-name sexp now that there is a set-jumpnode-display-name
2. Make the display name design consistent with ships and weapons; in particular add a `HasDisplayName()` function and automatically generate the display name for hash-truncated names
3. Keep the display name in sync when the name is changed in the FRED dialog
4. Fix the overriding of hash-truncated names with display names on the HUD
5. Fix the incorrect setting of the alphacolor flag when using FRED
6. Fix array out-of-bounds access when no object is selected

Follow-up to #5401.
2023-06-05 00:41:38 -04:00
Goober5000 e7cb174684 Merge pull request #5442 from Goober5000/retime_pairs_fix_and_update
some refinements for retiming of object collision pairs
2023-06-04 22:11:04 -04:00
Goober5000 aef5a022a8 Merge pull request #5440 from Goober5000/drop_shadows_option
add game_settings.tbl option to enable HUD drop shadows by default
2023-06-04 16:38:49 -04:00
Goober5000 fe77cbee3c Merge pull request #5441 from MjnMixael/default_cm_class
Lua access to default countermeasure class
2023-06-04 16:38:42 -04:00
Goober5000 ab5e016dbb some updates to the lighting profile code
1. Add const qualifier where appropriate to API methods
2. Change `TonemapperAlgorithm` from enum to enum class, for type safety and token scope
3. Update saving of lighting profile in FRED
4. Add saving of lighting profile in qtFRED
5. Add lighting profile (and asteroid) initialization to qtFRED
2023-06-04 16:09:51 -04:00
Goober5000 91e7bea55e Merge pull request #5439 from Goober5000/followup_stuff
Fixes for lab backgrounds and curve initialization
2023-06-04 16:09:23 -04:00
Goober5000 c72b8b0cf4 some refinements for retiming of object collision pairs
1. Add a function to retime *only* the collision pairs involving a specific object.  This is useful when only one object has moved, since only collisions involving that object are affected.
2. Use this function when objects are moved for autopilot, via sexp, and via script.

Previously collision pairs were not retimed when objects were moved via script, leading to bugs.  This fixes that.
2023-06-04 16:04:53 -04:00
mjn-mixael c07389ce6b invalid weapon 2023-06-04 09:22:01 -05:00
z64555 f07e3322e9 Use a std::runtime_error instead of std::exception, because messages in std::exceptions are not a cstdlib spec.
* Update doxy to reflect changes
2023-06-04 09:04:17 -05:00
Goober5000 8e242b4c40 Merge pull request #5433 from Goober5000/sexp_tree_search
Sexp tree searching and filtering
2023-06-03 23:33:19 -04:00
Asteroth 9bd3b00b49 add single segment trails (#5432) 2023-06-02 21:28:45 -04:00
Asteroth 46b886df2c add single segment trails (#5432) 2023-06-02 20:23:07 -04:00
Asteroth 87ad9d99c4 add single segment trails (#5432) 2023-06-02 20:22:40 -04:00
mjn-mixael 1a946beed1 lua access to default countermeasure class 2023-06-02 17:40:44 -05:00
Goober5000 720d938a3a address feedback 2023-06-02 16:26:25 -04:00
Goober5000 ab63301d22 Merge pull request #5401 from MjnMixael/translatable_jump_node
Enhance jump node handling
2023-06-01 22:43:08 -04:00
Goober5000 f1bed594f8 Merge pull request #5435 from MjnMixael/lua_is_player_allowed
Flags to see if a ship or weapon class is player allowed
2023-06-01 22:42:58 -04:00
Goober5000 8a44ff160f Merge pull request #5438 from MjnMixael/fix_default_lighting_profile
Default profile name needs to be added after reset()
2023-06-01 22:42:48 -04:00
Goober5000 ee74f86c5e use correct #Background bitmaps string, use correct string skipping, and do a little tidying 2023-06-01 15:58:39 -04:00
Goober5000 68d216d973 add curves_init and alphabetize #include list 2023-06-01 15:38:22 -04:00
Goober5000 d7d9f10208 add game_settings.tbl option to enable HUD drop shadows by default
As requested by a comment on #4543.
2023-06-01 15:23:41 -04:00
mjn-mixael cc567edaf7 default profile name needs to be added after reset() 2023-05-31 15:50:20 -05:00
mjn-mixael fd6b670a04 flags to see if a ship or weapon is player allowed 2023-05-31 11:37:59 -05:00
Goober5000 b24594acb8 Merge pull request #5418 from scp-fs2open/dependabot/pip/ci/post/requests-2.31.0
Bump requests from 2.26.0 to 2.31.0 in /ci/post
2023-05-30 22:56:52 -04:00
Goober5000 af84b91619 Merge pull request #5421 from BMagnu/modular_subsystem_set_data
Virtual POFs: Modify Subsystems
2023-05-30 22:56:34 -04:00
Goober5000 e28e681d08 Merge pull request #5426 from Baezon/all-poofs-default
All poofs on by default
2023-05-30 22:56:24 -04:00
Goober5000 b223665c3d Merge pull request #5434 from TheForce172/fix/qtFredload
Quick fix to qtfred loading on linux
2023-05-30 22:55:53 -04:00
The Force 303e482047 Quick fix to allow qtfred to compile on ubuntu 2023-05-30 23:53:26 +01:00
Goober5000 8fc28b01ea work with operator indexes to reduce back-and-forth between const and index 2023-05-30 15:41:24 -04:00
Goober5000 278355cac0 select text by default, and implement escape 2023-05-30 15:41:22 -04:00
Goober5000 9bd10e55c6 sort operators by cost when filtering, and use the same best-match strategy in sexp_match_closest_operator 2023-05-30 15:41:17 -04:00
Joshua Glatt a10c733122 allow using container data with ai-waypoints* SEXPs (#5429) 2023-05-29 15:24:18 -07:00
Goober5000 a06573b15e implement type-to-filter and enter-to-confirm 2023-05-29 00:31:27 -04:00
Goober5000 4ff90d3716 move some utilities to a better location, plus a slight refactor 2023-05-28 22:47:38 -04:00
Goober5000 01b96de318 fix handle mismatch 2023-05-28 22:42:23 -04:00
Goober5000 eb959cd0bf make the tooltip explain why an operator can't be selected 2023-05-28 22:42:23 -04:00
Goober5000 46dee9ff0c use selected operators, and prevent disabled operators from being confirmed 2023-05-28 22:42:23 -04:00
Goober5000 579ce220ab fix some sexp help text 2023-05-28 22:42:23 -04:00
Goober5000 09ae954d8e disable operators with incompatible return types 2023-05-28 22:42:23 -04:00
Goober5000 4c43f22a7a multiline tooltips work 2023-05-28 22:42:22 -04:00
Goober5000 9967ed5150 add a new MFC control for the operators 2023-05-28 22:42:22 -04:00
Goober5000 ff2ec6a2ab preliminary sexp operator popup 2023-05-28 22:42:22 -04:00
z64555 9b0846c897 Try const std::exception &e, as per Goober5000's suggestion. 2023-05-27 20:25:41 -05:00
Mike Nelson 2ed78ab1a8 Fix asteroid wrapping (#5419)
* refactor how asteroid wrapping is done and setup for allowing or disallowing range check

* allow fred to toggle enhanced spawn checking

* field naming adjustment

* some minor tweaks

* Add sexp compatibility

* We don't need to save the boolean, just the string.

* full qtFRED support
2023-05-27 15:03:49 -04:00
Goober5000 99450fa643 remove hud_squadmsg_save_keys()
Remove this function and associated items, since they are commented out and unused.
2023-05-27 13:39:47 -04:00
Goober5000 5373ceb650 Merge pull request #5425 from Goober5000/comm_menu_hook
add hooks for comm menu opening and closing
2023-05-27 12:07:52 -04:00
Goober5000 8e7a93698b Merge pull request #5424 from Goober5000/hud_gauge_qtfred_update
patch qtFRED's handling of hud gauges
2023-05-27 12:07:44 -04:00
Taylor Richards b3532e71cc add support for loose lz4 compressed files (#5411) 2023-05-26 22:43:13 -04:00
EatThePath bee289cfa9 Merge pull request #5423 from EatThePath/ltp/fix-reset-new-profiles
call reset() on new profiles to ensure properly set default values.
2023-05-26 21:46:10 -04:00
Asteroth 5bf35ef048 all poofs on by default 2023-05-26 17:44:58 -04:00
Asteroth 16e0e3d6c4 Use volume particles for poofs (#5412)
* allow volume particles for poofs

* fix
2023-05-26 16:23:06 -04:00
Goober5000 59a5d2642c add hooks for comm menu opening and closing
Implements #5420.
2023-05-26 12:51:34 -04:00
Goober5000 346bbb61a2 patch qtFRED's handling of hud gauges
There was a missing function call in qtFRED's initialization, which prevented custom HUD gauges from being loaded.  This adds that.  Additionally, this updates the deduplication code in `get_listing_opf_custom_hud_gauge` to match its counterpart in FRED.

Fixes #5422.
2023-05-26 11:34:11 -04:00
ETP 2ba173d208 call reset() on new profiles to ensure properly set default values. 2023-05-25 20:13:04 -04:00
Birk Magnussen f4b6a4af61 Property Append Mode proper 2023-05-25 20:55:22 +02:00
Birk Magnussen f8220ccd60 Property Append Mode 2023-05-25 20:54:04 +02:00
Birk Magnussen be29fc9eaa fix warning 2023-05-25 12:15:18 +02:00
Birk Magnussen 4d25b34c1b Add Subsystem data change 2023-05-25 12:12:55 +02:00
EatThePath b32e7b35f7 fix #5416 by loading correct table filenames and ensuring tonemapper is parsed into proper profile. (#5417)
Also fixes semi-spurious warnings about missing default profile by ensuring proper creation of the default profile even if no files are found.
2023-05-22 22:46:58 -04:00
dependabot[bot] b837c4fa7a Bump requests from 2.26.0 to 2.31.0 in /ci/post
Bumps [requests](https://github.com/psf/requests) from 2.26.0 to 2.31.0.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.26.0...v2.31.0)

---
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-05-23 02:42:44 +00:00
Goober5000 7443fed890 Merge pull request #5415 from Goober5000/iequals
add lcase_equal and lcase_lessthan
2023-05-21 21:19:12 -04:00
Asteroth d4beb69328 Add player damage inflicted factor (#5406)
* add player damage inflicted factor

* update default file
2023-05-21 08:17:31 -04:00
Goober5000 d6f3fc76f9 Merge pull request #5414 from Goober5000/fix_event_delay_status
fix evaluation of event status for some events
2023-05-20 18:53:58 -04:00
Goober5000 3e0c7f0721 add lcase_equal and lcase_lessthan
The `SCP_string_lcase_equal_to()()` and `SCP_string_lcase_less_than()()` functors are rather unwieldy to use in non-functor situations, so this adds conventional function equivalents.
2023-05-20 18:21:37 -04:00
Goober5000 d0409ee7be Merge pull request #5409 from Goober5000/fred_and_parse_cleanup
some cleanup and refactoring
2023-05-20 12:41:10 -04:00
Fabian Woltermann 04ad198bb1 Merge pull request #5380 from EatThePath/ltp/multiple-profiles
Ltp/multiple profiles
2023-05-20 10:27:21 +02:00
Fabian Woltermann ca66b41a9e Merge branch 'master' into ltp/multiple-profiles 2023-05-20 10:02:05 +02:00
Goober5000 38c04d0ab3 fix evaluation of event status for some events
Related to #5267, and again concerned with the original check for event delay:
```
if ( (fix) Mission_events[i].timestamp + delay >= Missiontime )
    return SEXP_FALSE;
```
For events that were never evaluated at all, their timestamp remained 0.  Thus the function did not return and the status of the event (which by definition was incomplete) was always checked.

After the timestamp refactoring, this comparison always returned SEXP_FALSE for these events.  The correct behavior is to bypass invalid timestamps so that the status of the event is always checked.

This fixes the behavior of `is-event-false-delay` in debriefings.
2023-05-19 23:11:35 -04:00
Goober5000 d784f18a52 Merge pull request #5410 from Goober5000/fix_qtfred_init
fix qtFRED initialization
2023-05-19 20:57:29 -04:00
Mike Nelson d87cd04aad Traitor overrides feature (#5404)
* Traitor overrides feature

* must code the way goober codes or else

* clarity is key when you're ocd

* even more clarity
2023-05-19 13:07:50 -04:00
ETP aec4977e6e cleaned up some dead commented code 2023-05-19 13:05:28 -04:00
Goober5000 c7ad3592a6 fix qtFRED initialization
The `stars_post_level_init()` change in #5403 exposed a bug where qtFRED would sometimes try to render the mission before all setup had been completed, causing a crash because `Show_iffs` was zero-length.  This was due to the mission being created in the middle of initialization, instead of after initialization was complete.  This fix moves `createNewMission()` to main.cpp, after initialization has finished, and in parallel with the command-line option to load a mission.
2023-05-19 00:37:13 -04:00
Goober5000 1fe528b86d Merge pull request #5403 from Goober5000/skybox_timestamp_fix
patch FRED handling of starfield setup
2023-05-18 18:33:24 -04:00
Goober5000 34663c68bd some cleanup and refactoring
Refactor and clean up some of the code, and add some fixes and utility functions.  This covers the non-X-Wing part of #5277.
2023-05-18 18:28:09 -04:00
Asteroth 29e77013ab init curves in fred (#5408) 2023-05-18 04:51:51 -04:00
z64555 3ec4480c13 We actually want to throw when the pointer is a nullptr, thank you. 2023-05-17 09:38:54 -05:00
z64555 562dd95da3 Replace Assertion within io::joystick::Joystick's constructor with a throw.
* Add try-catch block within enumerateJoysticks() to catch the exception thrown by the Joystick constructor and log the deviceid and the SDL error.
2023-05-17 08:49:47 -05:00
Goober5000 2b1cd53db9 Merge pull request #5397 from Goober5000/lua_is_player
add ship:isPlayer()
2023-05-14 22:05:21 -04:00
Goober5000 be8c3ebb2f patch FRED handling of starfield setup
1. Skybox initialization (and perhaps other aspects of mission initialization) requires the existence of a timestamp snapshot, so make sure a snapshot has been taken before FRED creates a mission.  Follow-up to #5343.
2. Move `stars_post_level_init()` to `Editor::createNewMission()` in qtFRED to be consistent with FRED's `create_new_mission()`.

Fixes a crash when the user tries to add a skybox when FRED first launches.
2023-05-14 15:35:18 -04:00
BMagnuandFabian Woltermann b0b05b35fd MSAA (#5400)
* Add MS buffers

* Implement basic MSAA with commandline

* Move MSAA init to deferred pipeline

* Fix shadows when MSAA is enabled

* Implement resolve shader

* Cleanup basic resolve shader

* Implement front-first depth-aware MSAA resolve

* Fix background resolve

* Allow setting MSAA level

* Ensure good MSAA level

* Code Median shader for different sample counts

* Cleanup

* Add MSAA options toggle

* Add MSAA sample count pre-parsing

* Add GL scope

Co-authored-by: Fabian Woltermann <[email protected]>

* Typo
2023-05-14 08:14:51 +00:00
ETP 7beb28b4f6 added lab interface for selecting lighting profiles. 2023-05-13 21:12:59 -04:00
ETP a094eb00c8 Trim out some future feature code. 2023-05-13 21:12:59 -04:00
ETP 6ccde7b01d maybe appease CI 2023-05-13 21:12:58 -04:00
ETP 62b70e74ca Rebasing lighting profile switchery 2023-05-13 21:12:58 -04:00
EatThePath 89ffbb5a34 Merge pull request #5347 from EatThePath/ltp/profile-code-reorg
lighting profile code reorg
2023-05-13 21:11:58 -04:00
mjn-mixael 4c7e9f6585 On second thought, this should still be Name and not DisplayName 2023-05-12 16:38:07 -05:00
mjn-mixael 78b957982b enhance jump node handling 2023-05-12 15:30:41 -05:00
Goober5000 8aa5a22f5d Merge pull request #5399 from BMagnu/modularpof_parent_subsystem
Fix modular pof handling of dock / path parent names
2023-05-12 14:19:16 -04:00
BMagnu 26cfc8d017 Make check case insensitive 2023-05-13 01:52:40 +09:00
Goober5000 5ed0a9161c Merge pull request #5398 from Goober5000/update_dock_flags
update type_flags when dock name changes
2023-05-12 11:39:36 -04:00
Birk Magnussen 6f8c8e802a fix modular pof handling of dock / path parent names 2023-05-12 10:26:13 +02:00
Goober5000 712a70444b update type_flags when dock name changes
The `type_flags` on a model's dockpoints are determined by the dockpoint name.  If the name changes, the flags should be updated accordingly.

This fixes a bug in Scroll where a dockpoint that was imported and renamed to start with the word "cargo" was not compatible with cargo docking as expected.
2023-05-12 04:08:38 -04:00
Goober5000 eaf57bddf3 add ship:isPlayer()
Add Lua functions to check whether a ship or parse object is a player ship.
2023-05-12 00:35:29 -04:00
wookieejedi 29f82cb5d7 Fix two undocking bugs for small ships (#5396) 2023-05-11 17:06:42 -04:00
Goober5000 7846e593a0 Merge pull request #5394 from BMagnu/fix_anim_crash_dead_ship
Add additional checks for Animation List handling of nonexistent polymodel instances
2023-05-08 23:19:40 -04:00
Birk Magnussen ff3be1a4e3 Add additional checks for animation list handling of nonexistent polymodel instances 2023-05-06 13:42:21 +02:00
Goober5000 25348edff2 Merge pull request #5391 from Goober5000/tweak_int_parsing
make number parsing a little more forgiving
2023-05-05 14:38:04 -04:00
Goober5000 0bdcd3c2f4 Merge pull request #5393 from MjnMixael/lua_enum_index_fix
Lua Enum Hotfix
2023-05-05 14:37:54 -04:00
mjn-mixael 13a990a98f this needs to be converted from base 1 2023-05-05 10:14:48 -05:00
Asteroth 18ba984f3e fix for weapons with lots of inherited velocity (#5392) 2023-05-05 07:58:37 -04:00
Fabian Woltermann 488db515ce Merge pull request #5388 from BMagnu/fix_shader_hdr
Fix HDR conversions in main shader
2023-05-05 13:54:20 +02:00
Mike Nelson 3f8e3360f9 Some additional splash screen features (#5379)
* some additional splash screen features

* Do this based on actual milliseconds

* splash screen is skipped in standalone

* os_poll()
2023-05-04 14:24:10 -04:00
Goober5000 61579f746c make number parsing a little more forgiving
In retail, number parsing picked up immediately at the character after the number parsed, so parsing `0.50` as an int would yield 0, and then the next available characters would be `.50`.  Even though parsing has been tightened up and made stricter, we can still "fail gracefully" by simulating the old behavior.  And when failing gracefully, the message can be a warning.
2023-05-03 22:44:55 -04:00
Asteroth 02a40ae905 Remove model octants (#5373)
* remove model octants

* actually remove the struct

* comments

* remove scratch comment

* initialize
2023-05-01 23:54:43 -04:00
Goober5000 04a9de69ea Merge pull request #5375 from Goober5000/4562_redux
Modernise CFLAGS on Mac/Linux
2023-05-01 23:25:20 -04:00
Goober5000 1457bb0c7f Merge pull request #5386 from MjnMixael/no_unicode_font_error
Warn instead of error for bitmap fonts in unicode
2023-05-01 23:25:01 -04:00
Goober5000 275c7ffe66 Merge pull request #5389 from Goober5000/5381_followup
clear caches for both nodes in rand_sexp
2023-05-01 23:23:41 -04:00
Goober5000 e120bb90b6 clear caches for both nodes in rand_sexp
Since `rand_sexp` also writes text into the sexp node for the seed value, its cache should be cleared too.  And since this is a pretty common operation, wrap it in a `clear_cache` function.

Follow-up to #5381.
2023-05-01 16:36:58 -04:00
Goober5000 10ce1ac625 sync toolchain-apple-clang.cmake flags with the ones in toolchain-clang.cmake 2023-05-01 14:54:08 -04:00
Birk Magnussen baada08eca Fix shader 2023-05-01 20:00:59 +02:00
Goober5000 996a2002e6 Merge pull request #5377 from Goober5000/remove_old_fred_components
remove some obsolete FRED components
2023-04-30 20:48:50 -04:00
wookieejedi 5a1ac87802 Update recent particle optimizations to fix edge case slowdowns (#5385)
#5328 added a very useful culling for particles created by specific particle effects (ie weapons, now beams), though in an effort to simplify the culling process, that PR removed the necessary culling of default smoke on ships. This PR restores the culling of default smoke while also keeping the new culling of particle specific effects. Tested and works as expected, including fixing the slowdowns caused by the aforementioned removal of smoke effect culls.
2023-04-30 15:15:37 -04:00
mjn-mixael 9e5894512c warn instead of error 2023-04-30 10:57:15 -05:00
MageKing17 e5301b7595 Fix the rand SEXP's use of cached values. (#5381)
The `rand` SEXP stores the result of its first call in the "low" node. Prior to PR #2402, this worked fine, but after that, the value is cached when first evaluated, meaning that subsequent calls to the `rand` SEXP will always return the lowest value in the range, not whatever number was rolled the first time.

This commit makes it so that writing the rolled value to the node's `text` attribute is immediately followed by deleting the no-longer cached value, so that the SEXP continues to work as intended.
2023-04-30 11:31:32 -04:00
MageKing17 ae91e4af1b Actually handle a missing Fade_anim properly. (#5382)
When I made FSO not crash with demo data in PR #1156, I avoided calling `brief_maybe_blit_scene_cut()` if `Fade_anim` didn't load, when I should've made it do what the icculus port does in demo mode: pretend the animation finished immediately.

With this commit, the first mission of the demo correctly advances past the first briefing stage.
2023-04-29 17:13:37 -07:00
Fabian Woltermann b77902309a Merge pull request #5384 from The-E/fix/division_by_zero_when_rendering_glowpoints
fix crash in glowpoint rendering
2023-04-29 19:32:32 +02:00
Fabian Woltermann 09a1485a7b this makes sure we do not run into a division by zero under certain circumstances. Also skips glowpoint rendering if the glowpoint is currently invisible 2023-04-29 18:04:39 +02:00
Asteroth 63df812d79 Add beam particles (#5330)
* add beam particles

* tweaks

* more tweaks

* fix warning

* dumb c++

* fix switch

* spelling
2023-04-29 08:45:31 -04:00
Goober5000 4dc6fd417f Merge pull request #5374 from Goober5000/required_for_mission_fred
Add FRED support for the "required weapon" feature
2023-04-27 14:41:11 -04:00
Goober5000 f15c5188c3 remove some obsolete FRED components
- remove FolderDlg which hasn't been needed since we dropped support for Visual Studio 6
    (see version history of MFC, https://mariusbancila.ro/blog/2015/08/12/version-history-of-vc-mfc-and-atl/)
- remove dialog1 which isn't used
2023-04-27 14:37:01 -04:00
Asteroth b8dacdd898 afterburning hard ignores wings (#5376) 2023-04-27 02:51:41 -04:00
Goober5000 b97430e5a0 move from setjmp to try/catch 2023-04-26 19:36:16 -04:00
Goober5000 64c27d8186 fix unused variable warnings 2023-04-26 19:36:16 -04:00
Asteroth d43cf1018d ensure pmi for this lookup (#5372) 2023-04-25 22:27:41 -04:00
Goober5000 e7048f6940 make CI happy 2023-04-25 13:25:08 -04:00
Goober5000 ef1933ec1b Modernise CFLAGS on Mac/Linux
Per GCC optimisation guide, which applies equally well to clang:
* -funroll-loops should not be used unless directed by profiling. The compiler will already unroll loops when it's a good idea.
* clang and gcc now have -Og optimisation levels designed to enable debugging with good performance.

(second attempt at PR #4562)
2023-04-25 13:22:18 -04:00
Goober5000 2a74c93313 link with team loudout dialog 2023-04-25 12:51:23 -04:00
Goober5000 143c52d252 add checkboxlistdlg 2023-04-25 12:18:00 -04:00
Goober5000 53ba2e792a modify loadout dialog 2023-04-25 12:18:00 -04:00
Goober5000 06df0a8a4d Merge pull request #5332 from Goober5000/xmt_ssm
improve XMT handling of ssm.tbl
2023-04-25 00:14:04 -04:00
Taylor Richards 28747bb1b7 warn when a critical file might be be shadowed (#5350) 2023-04-24 02:19:30 -04:00
wookieejedi f2987aa749 Fix max Z speed when using ETS and engine damage tracking (#5368)
* Fix max Z speed when using ETS and engine damage tracking

Follow up for #5137 and #5292. This engine strength check thus needs to be added to all instances where `max_vel.xyz.z` is updated, so a function was created and added in respective locations. Fixes #5367.

* cleanup and adding validity assertations

* cleanup outdated comments

* might as well make the cleanup look nice

* update to account for more edge cases

* cleanup
2023-04-23 22:01:05 -04:00
Fabian Woltermann 938eacdee9 Merge pull request #5370 from The-E/fix/crash_when_logging_ai_submode
Fix crash when logging ai submode
2023-04-23 20:08:47 +02:00
Fabian Woltermann 898c0c1945 fix a crash when attempting to log the ai being in certain submodes 2023-04-23 19:19:44 +02:00
Fabian Woltermann 6234c97f4f fix invalid access when choosing builtin messages (#5369) 2023-04-23 17:19:23 +00:00
Fabian Woltermann 8dd4a05cd1 fix invalid access when choosing builtin messages 2023-04-23 18:52:15 +02:00
BMagnu 6e561761d1 Cleanup Variable Names for Volumetrics (#5362)
* Rename opacityDistance

* Add oversight
2023-04-23 08:16:12 -04:00
Goober5000 b3f237b8c1 Merge pull request #5366 from Goober5000/fred_rc_fixes
some FRED cleanup
2023-04-22 12:14:37 -04:00
Goober5000 587d5af8ca some FRED cleanup
1. Disambiguate dialog IDs for the music player and the volumetric nebula dialogs
2. Fix compilation of qtFRED
3. Small refactor of Personas access to use STL functions where appropriate
2023-04-21 23:16:51 -04:00
Goober5000 0cc28cf8fc Merge pull request #5348 from MjnMixael/sync_color_handling
Deprecate old versions in favor of versions that use color objects
2023-04-21 21:49:08 -04:00
Goober5000 5c9b309293 Merge pull request #5361 from Goober5000/fred_orient_qol
FRED object editor QOL improvements
2023-04-21 21:48:38 -04:00
Mike Nelson c19f05a9d9 organize and map additional keys (#5354) 2023-04-21 21:05:54 -04:00
BMagnu ab4d1fb779 Skip anim if type is unknown (#5363) 2023-04-22 02:28:27 +09:00
BMagnu 13e1f28c4a FRED Dialog for Volumetrics (#5351)
* Add volumetrics dialog skeleton

* Implement first fields in dialog

* Add dialog to main window

* Fix Spinners

* Add all non-noise inputs

* Add Noise Fields

* Fix errors

* Add Tooltips

* Fix fred menu

* Init dialog
2023-04-22 01:06:58 +09:00
Goober5000 bce1e7c2d9 Merge pull request #5360 from Goober5000/improve_spawn_collision
improve spawn collision checking
2023-04-21 09:40:47 -04:00
Goober5000 2f654c496c FRED object editor QOL improvements
1. When the "object" radio button is selected, the "point to" check box will also be selected
2. When an object is selected from the object list, the "object" radio button and "point to" check box will also be selected

Fixes #5356.
2023-04-20 23:58:18 -04:00
Goober5000 1feef8ff2a improve spawn collision checking
Take into account the collision flag and collision groups when spawning a ship.  Should fix #5357.

Also clean up the code a bit, including setting a few `int`s to `bool`s and adding a missing axis case.
2023-04-20 22:31:34 -04:00
Asteroth fa0878b6b3 Add an Ai goal flag to afterburn hard (#5338)
* add afterburn hard flag

* return some ab locked checks

* this one too

* more tweaks
2023-04-20 19:42:35 -04:00
wookieejedi 21d1ffd3bd Fixes CTD with New Particle Lifetime Curve (#5358)
Turns out Velocity Lifetime Curve was never initialized.
2023-04-20 14:39:46 -04:00
Goober5000 237fea6cbf Merge pull request #5355 from Goober5000/enhanced_sexp_warnings
enhance some SEXP warnings
2023-04-20 11:29:42 -04:00
mjn-mixael 95649dafa1 cleanup 2023-04-20 09:37:33 -05:00
EatThePath 427873a345 remove int3 from the rest of the batching things (#5349) 2023-04-20 07:43:29 -04:00
Asteroth 4a53ff742d Add debris density (#5340)
* add debris density

* doc new param
2023-04-20 02:48:19 -04:00
Goober5000 581c834353 Merge pull request #5337 from Goober5000/various_tweaks
Various tweaks and polishing
2023-04-19 22:20:53 -04:00
Goober5000 58f3e8fb06 Merge pull request #5345 from MjnMixael/finalize_scpui_api
Finalize scpui api
2023-04-19 22:20:06 -04:00
Goober5000 d7a2bba630 enhance some SEXP warnings
These messages add the context of the actual SEXPs causing the warnings to be displayed.  Motivated by Admiral Nelson's mod debugging work.
2023-04-19 22:15:21 -04:00
Goober5000 0d6791ff1d Merge pull request #5353 from Goober5000/joe_fixes
Joe fixes
2023-04-19 22:14:33 -04:00
Asteroth 9be559622e dont overwrite a disallowed depart order (#5352) 2023-04-19 17:30:09 -04:00
Asteroth 31b23d8c50 Whackable debris and asteroids (#5291)
* whackable debris and asteroids

* fixes

* review tweaks

* some more review tweaks
2023-04-19 10:56:46 -04:00
Asteroth 56f010a231 Add arbitrary curves support (#5323)
* Add arbitrary curves support

* review tweaks

* pretty sure i dont need this anymore
2023-04-19 08:13:06 -04:00
Goober5000 f0322a12f2 remove unused variable 2023-04-18 20:50:17 -04:00
Goober5000 f62e437dbd properly handle wingmen that are destroyed before mission 2023-04-18 19:50:32 -04:00
Goober5000 41e338e8ab Joe fix: if the Instructor is known to a mission, it should govern training messages 2023-04-18 19:49:29 -04:00
Goober5000 6ce1f5276a Joe fix: if a ship can't find a dock path, the game shouldn't crash 2023-04-18 19:46:36 -04:00
mjn-mixael 623f887495 documentation 2023-04-18 09:18:36 -05:00
mjn-mixael 3f6eae0836 Update methods to optionally accept and return color objects 2023-04-18 08:37:30 -05:00
Asteroth 0bffa82422 fix wep glowpoints (#5344) 2023-04-18 08:04:16 -04:00
Goober5000 d203d2915f Merge pull request #5343 from Goober5000/synchronized_timestamps_take_2
synchronize simulation timestamps across the entire frame
2023-04-17 19:15:32 -04:00
EatThePath 64af9e520c Merge pull request #5154 from EatThePath/opt/less-batching-find
Optimizing the trail renderer by avoiding repeated batch_find calls
2023-04-17 16:15:59 -05:00
ETP 77c7aee8f4 Moved the configurable profile adjustments into their own file 2023-04-17 14:58:14 -05:00
mjn-mixael eafab41823 unify language and capitolization 2023-04-17 14:50:38 -05:00
BMagnu bbb7599512 Add proper time wrapping for animations (#5339) 2023-04-18 04:40:04 +09:00
BMagnu 522e1aa360 Restrict player order accept ship (#5341) 2023-04-18 04:39:56 +09:00
ETP 57f9455f6c moving lighting profiles into a namespace and arranging it as cleanup for future changes 2023-04-17 14:36:41 -05:00
ETP a8035fec36 Applied formatting to lighting profiles files 2023-04-17 14:06:21 -05:00
Goober5000 9b337b714b take a new snapshot when time compression is updated 2023-04-17 12:10:56 -04:00
mjn-mixael f5a08bb694 change api description to finalize 2023-04-17 08:53:52 -05:00
mjn-mixael da7d9f28b9 global to param 2023-04-17 08:53:26 -05:00
Asteroth 4bbc9f3eb3 Improve particle culling and performance (#5328)
* better particle culling

* remove range on emitters

* explicit cast

* bit more efficient
2023-04-17 08:03:41 -04:00
Asteroth 7c4b9272d5 Randomize particle rotation (#5335)
* randomize particle rotation

* spelling

* initialize it, dummy
2023-04-17 07:37:38 -04:00
Goober5000 051d85d05c fix time compression with snapshotted timestamps
Because time compression adjusts the raw timestamp to be 0, it must use the exact value, not the snapshotted value, or the mission time will be slightly off.  So this commit fixes that problem, as well as making sure that changes in time compression always occur at the start of a frame.
2023-04-16 22:19:57 -04:00
Goober5000 b487969e5f use constant 2023-04-16 14:27:59 -04:00
ngld 86a81bfb9c Merge pull request #5342 from ngld/pr/fix-nightly-upload 2023-04-16 19:39:15 +02:00
ngld d7c22b126c Mark the nightly upload step as succesful as long as at least one mirror got the file 2023-04-16 19:00:32 +02:00
Mike Nelson 108def6224 Scpui Hud Config API (#5302)
* initial API for hud config elements

* get rendering, highlighting, and selecting working

* Add a way to create color objects

* some cleanup and fixes

* go away we dont need you

* allow arbitrarily scaling the hud config draw

* last few config options and innitial preset handling

* vectorize hud presets and setup handling

* some last minute fixes

* iiiiiiiiiiiiiiiiiiiiiiint

* really

* documentation and address feedback

* completely revert this as well

* more documentation

* document all the things

* comment out unused parameter

* peach emoji retentive

* whatever

* return types

* color
2023-04-16 08:13:06 -04:00
BMagnu ff296f8f98 Add a Translation Moveable (#5313)
* Add Translation Moveable

* Update SEXP docs

* Update some strings
2023-04-16 20:56:44 +09:00
Goober5000 4106414858 timestamps need to be synced in FRED too 2023-04-15 22:36:22 -04:00
Goober5000 9c5b4dfb49 synchronize simulation timestamps across the entire frame
Prior to the timer upgrade, all simulation timestamps shared identical timer and timestamp values for the duration of the frame, since they were only updated within the `game_set_frametime` function.  Since the timer upgrade depends on the system clock, timestamps evaluated near the end of the frame will be very slightly later than timestamps evaluated near the beginning of the frame.  It is desirable to keep them all in sync.

This PR tweaks the timestamp system to take a snapshot at the beginning of the frame, then use that snapshot for the entire duration of the frame.  This only affects simulation timestamps; real-time timestamps still use the live timer.
2023-04-15 22:17:23 -04:00
Goober5000 1083f34ffc Merge pull request #5336 from Goober5000/rank_adjustment
tweak rank handling in Lua
2023-04-15 22:04:38 -04:00
Mike Nelson 3c30257816 Modular messages table (#5285)
* modular messages table

* clarify warning
2023-04-16 08:40:25 +09:00
BMagnu 023a7d3e68 "On Frame but actually Wait before you continue"-Executor (#5314)
* add 'syncronized async run'

* cleanup

* cleanup 2

* Properly free the screen

* Incorporate feedback
2023-04-16 08:39:49 +09:00
BMagnu f32b575f0c Allow 0-Asteroid setups (#5329)
* Allow 0-Asteroid setups

* Make mission brief error non fatal
2023-04-16 08:39:04 +09:00
Asteroth 1525f829b7 Flush empty cbrief voice filenames to "None" (#5333)
* make clearing cbrief voice easier

* qtfred too

* ani_filename too
2023-04-15 15:06:37 -04:00
Goober5000 a932dc94c0 Merge pull request #5307 from MjnMixael/explicit_no_wrap
Explicitely do not split lines when making the message log
2023-04-15 14:59:09 -04:00
Goober5000 55a92a32de a bit of encapsulation 2023-04-15 14:23:05 -04:00
Goober5000 0c8a6c6f97 small streamlining 2023-04-15 14:23:05 -04:00
Goober5000 5e3f8e4792 Merge pull request #5334 from Goober5000/check_whitespace_comma
check for whitespace between token and comma
2023-04-15 14:19:37 -04:00
Goober5000 7018a560b9 streamline type conversion 2023-04-15 00:06:33 -04:00
Goober5000 bcc964d0fa color tweaks 2023-04-15 00:06:33 -04:00
Goober5000 8fbe2c244a address feedback 2023-04-14 20:34:19 -04:00
Goober5000 c6a2dcdfa9 tweak rank handling in Lua
Follow-up to #5280:

1. Make the Rank virtvar actually return a rank object, to be consistent with other Lua API methods
2. Add a RankIndex virtvar to replicate the previous functionality
3. Make RankIndex return the expected 1-based index for Lua

This is a breaking change to the API, but since the original API is less than a month old, the impact should be small.
2023-04-14 19:17:46 -04:00
Goober5000 d28db605a9 avoid repeated commas 2023-04-14 11:51:03 -04:00
Goober5000 67428f506c grayspace makes more sense here 2023-04-14 10:56:11 -04:00
Goober5000 0ff15cfe16 check for whitespace between token and comma
When parsing a list of numbers, such as in the $uvec or $fvec of models, a bug was reported where whitespace before the comma caused the number parsing to fail.  This change checks for a comma after whitespace instead of checking for a comma as the very next character.
2023-04-14 02:51:01 -04:00
Goober5000 4ee4f51ee2 improve XMT handling of ssm.tbl
Extensible modular table handling for -ssm.tbm files was not very robust due to quite a few assumptions left over from straight .tbl parsing.  Ostensibly optional fields were required, non-overridden fields were reset to defaults, etc.  This improves XMT parsing and adds sensible defaults for SSM fields.
2023-04-14 01:12:09 -04:00
Goober5000 4da52ca23b Merge pull request #5325 from Goober5000/hotkey_followup
convert hotkey types to enum
2023-04-14 01:07:44 -04:00
Fabian Woltermann 1d52bc5876 make sure deferred_global_data follows the alignment rules (#5331) 2023-04-13 20:45:56 +00:00
Asteroth 689dca1f3f bugfix accidental swap (#5324) 2023-04-12 14:55:04 -04:00
Goober5000 bb53f7ee68 type safety revealed something 2023-04-12 10:55:38 -04:00
Goober5000 78d9562661 feedback and fix 2023-04-12 10:55:38 -04:00
Goober5000 b7d1270439 convert hotkey types to enum
Here's a suggested followup to #5249.  This converts the hotkey type to an enum for improved type safety.  It also adds the corresponding Lua enums and adjusts the Type virtvar to return them.
2023-04-12 10:55:36 -04:00
Goober5000 257ba70d70 Merge pull request #5326 from Goober5000/validity_checks
add validity checks
2023-04-12 10:52:39 -04:00
Goober5000 10e5875289 add validity checks
Many of the recent scripting API enhancements are missing validity functions and validity checks, so this adds them.  There are also some documentation fixes and a >= vs. > bugfix.
2023-04-12 00:14:20 -04:00
BMagnu 64de96f6ce Fix Subsystem serialization (#5319) 2023-04-12 00:31:54 +09:00
Asteroth ac9636733f ets fixes (#5317) 2023-04-11 06:31:04 +09:00
Asteroth a2df152323 Add fov values to .pof models (#5244)
* add model fov values

* initialize proper defaults

* set defaults directly
2023-04-11 06:30:17 +09:00
Goober5000 fbca88d36d add per-species warp effects
This allows warp parameters to be specified in species_defs.tbl, rather than requiring them to be specified for each ship in ships.tbl.  Since this introduces a cyclic dependency between species_defs.tbl and sounds.tbl, the parsing of sounds.tbl is broken into two stages.

Implements request from #5283.
2023-04-10 17:24:38 -04:00
Mike Nelson e01a5359ac Scpui API for Control Config (#5305)
* read access to controls

* Early draft of checking keypresses in scpui

* detangle some code and prepare it for API usage

* API access to the core methods required

* move these checks into the UI methods

* comment

* fix bugs

* be smarter

* Need this stuff, too

* some more presets work

* unify func naming scheme

* cleanup and clarifications

* get detect keypress working

* allow searching and creating new presets based on current controls

* address feedback

* return nil if no preset is matched

* use the builtin methods which do the same thing, but slightly cleaner

* typo
2023-04-07 12:02:13 -04:00
BMagnu e2b205ffaa Modular POF Features 2 (#5209)
* Add weapon bank copy

* Add Path / Dock point copying

* cleanup

* Fix dock points

* Fix copy paste error

* Incorporate feedback

* Incorporate feedback 2

* delete copy assignment
2023-04-07 08:12:20 +09:00
Goober5000 1388866ddd Merge pull request #5315 from Goober5000/fix_qtfred_compilation
fix qtfred compilation
2023-04-06 11:04:31 -04:00
Goober5000 7e9e8bcb62 additional fixes 2023-04-05 21:14:45 -04:00
Goober5000 deded57112 fix qtfred compilation
Fix various compilation warnings and errors.
2023-04-05 20:56:53 -04:00
BMagnu 599a1893c3 Add +Use Ship as Template (#5311)
* Implement +Use Ship as Template

* Update Warning Message
2023-04-06 07:10:30 +09:00
Goober5000 dbff592f94 Merge pull request #5312 from Goober5000/chase_view_toggle
make 'player starts in chase view' a toggle
2023-04-05 13:00:23 -04:00
Goober5000 9c00070154 revert view on escape 2023-04-05 00:04:58 -04:00
Asteroth 203b738f79 Add $CockpitLaunchSnd (#5300)
* add cockpit launch snd

* whoops

* another whoopsie
2023-04-04 23:40:15 -04:00
Goober5000 b016163bf3 make 'player starts in chase view' a toggle
Per request of #5226.  This PR also makes the variable names more consistent.
2023-04-04 23:34:03 -04:00
Fabian Woltermann 884d47611f Merge pull request #5310 from The-E/fix/5309_div_by_zero_in_glowpoint_rendering
fix rare division-by-zero caused by unchecked data
2023-04-03 18:56:30 +02:00
Fabian Woltermann a786e2d541 fix rare division-by-zero caused by unchecked data 2023-04-03 18:16:44 +02:00
Goober5000 dc2370393e Merge pull request #5251 from Goober5000/move_self_destruct_log
move self-destruct mission logging to ship_hit_kill
2023-04-03 10:28:50 -04:00
Mike Nelson 0dd4daf2eb modular traitor + cleanup (#5188) 2023-04-03 14:12:57 +02:00
naomimyselfandi 949141c611 Message filter follow up (#5304)
* Fix intra-persona message borrowing logic

Closes #5299.

* Always assign personae for Support

Disabling the Auto_assign_personas flag had the side-effect of prohibiting support ships from ever speaking. Since a mod that wants this behavior (for whatever reason) can just not have a support persona, this commit makes an exception for them.

* Make Protect Target and Cover Me adaptive like Engage Enemy is

* Respect the allow subsitution flag
2023-04-03 08:11:46 -04:00
Fabian Woltermann 14689265ce Merge pull request #5308 from TRBlount/fix/vulkan_build
Prevent build error when Vulkan SDK isn't installed
2023-04-03 09:23:53 +02:00
Tyler Blount 837ac8d08e Also force if the option is set, but Vulkan could not be found 2023-04-02 19:56:50 -07:00
Tyler Blount 6cac2af8e4 Default to OFF for FSO_BUILD_WITH_VULKAN 2023-04-02 18:47:41 -07:00
mjn-mixael 80004f2996 explicitely do not split lines 2023-04-02 19:43:53 -05:00
Asteroth e3cd5c819f removal of current_max_speed (#5292) 2023-04-01 16:13:08 -04:00
Asteroth 39273db918 $beaminfo implies beam flag (#5297) 2023-04-01 16:12:32 -04:00
Asteroth cd36ce336f small fix for type5 fighter beams (#5298) 2023-04-01 16:11:54 -04:00
Goober5000 dcdade36a3 Merge pull request #5293 from Goober5000/5290_followup
additional constraint on Command arrival messages
2023-03-30 22:05:52 -04:00
naomimyselfandi cbbd197cd3 Add "no-first-wave-message" wing flag (#5288)
* Add "no-first-wave-message" wing flag

For when you want custom dialogue for the first wave, and automatic announcements for the rest.

* Fix FRED macro name
2023-03-30 21:17:03 -04:00
Goober5000 5d4cd31a79 fix IFF logic for teams that attack themselves (#5294)
If a team explicitly attacks itself, then the same-team checks should not apply.  Fixes a bug reported by SilverAngelX on Discord.
2023-03-30 21:16:45 -04:00
Asteroth 835285248e No overlapping turret sounds (#5295)
* prevent overlapping turret sounds

* whitespace

* fixes
2023-03-30 21:16:32 -04:00
Goober5000 682cffa610 additional constraint on Command arrival messages
Command should not be considered if the mission explicitly prevents Command from sending builtin messages.

Follow-up to #5290.
2023-03-29 00:31:03 -04:00
EatThePath 4753d0f761 Merge pull request #5290 from naomimyselfandi/configurable-command-arrival-message-chance
Dehardcode Command arrival message chance
2023-03-28 22:41:49 -05:00
Mike Nelson 85bcfd56e8 force expand wings instead of toggle for scpui (#5286) 2023-03-28 07:40:03 -04:00
Mike Nelson af88697348 Parse and save asteroids by name (#5134)
* parse and save asteroids by name

* typo

* update version
2023-03-28 07:38:14 -04:00
ETP 633f138afe Remove Int3() from new versions of batching_add_ for modernization 2023-03-27 23:46:54 -05:00
David Gibson d7ebb8f062 Optimizing the trail renderer building code path moderately by avoiding repeated batch_find calls 2023-03-27 23:01:05 -05:00
BMagnu 272d6261c4 Generic Lua Multiplayer RPC (#4835)
* Add automatic lua obj serialization function dispatch

* Implement fundamental and object de/serialization

* Proper default case for package deserialization

* Add No Multi func

* Add Serialization part

* Fix max encoding size for userdata

* Implement exception handling

* Start Implementing lua RPC

* Prepare waitAsync for RPC

* Add packet order enforcing and forwarding

* Add RPC registry

* Make RPCs callable

* Add waitRPC

* Add serializers

* Fix GCC error

* Explicitly specify lua_net_exception

* Fix Warnings

* Replace Seriliaze fundamental with cross-platform data types

* Appease Clang

* Prevent serialization CTD on invalid objects

* Actually use the temporaries assigned

* Fix OSWPT shadow

* Fix table deserialize order

* Incorporate Feedback

* Fix Warnigs

* ix WArnings 2

* Add sanity checks for OSWPT wing serialization

* Multi Bump

* Forgot we have american-style dates there
2023-03-28 03:07:03 +09:00
wookieejedi 2a492e00c2 Revert "synchronize simulation timestamps across the entire frame" (#5287)
* Revert "synchronize simulation timestamps across the entire frame"

* try a proper fix instead of revert

* make sure nothing is reverted

* and back to full revert
2023-03-27 09:59:23 -04:00
Fabian Woltermann c816a65c63 Merge pull request #5289 from EatThePath/restore-envmap-hotkey-export
restored the keyboard hotkey for envmap export.
2023-03-26 21:48:44 +02:00
Mike Nelson 8d762d3fbe fredTunes, Fredify, Fred Music, or whatever. It's a music player. (#5101)
* initial semi-working version

* better implementation of play and add stop and music.tbl viewer

* let the music window lose focus

* some cleanup

* add autoplay, next, previous

* use graphics

* Better dialog layout and allow ignoring files from the player list

* Make betterer

* a touch more cleanup

* revert this change

* missing bracket from merge conflict resolution

* address feedback
2023-03-25 13:52:11 -04:00
Naomi Coffman fec9603a09 Fix brainfart 2023-03-25 13:51:17 -04:00
Naomi Coffman 78cb768546 Dehardcode Command arrival message chance
Historically, there's been a hardcoded 25% chance for Command to announce an enemy wing arrival. This is problematic for mods without Command, like BTA.
2023-03-25 13:27:16 -04:00
David Gibson de057e421e restored the keyboard hotkey for envmap export. 2023-03-25 11:57:41 -05:00
Fabian Woltermann 9308318199 Merge pull request #5253 from naomimyselfandi/more-flexible-dynamic-messages
More flexible dynamic messages
2023-03-24 10:50:39 +01:00
Fabian Woltermann 17b34508e9 Merge pull request #5280 from MjnMixael/medals_access
Scpui API for medals access
2023-03-24 10:49:45 +01:00
Fabian Woltermann bcf0ab1957 Merge pull request #5256 from MjnMixael/texture_filtering_option
Expose texture filtering as a built-in option
2023-03-24 10:48:44 +01:00
Fabian Woltermann 18a679052b Merge pull request #5282 from qazwsxal/fix/gamma_stopgap
FIX: Incorrect gamma calculations in shaders.
2023-03-23 22:05:19 +01:00
Adam Leach d516ab3c23 Stopgap patch to make envmaps work again. 2023-03-23 19:33:41 +00:00
mjn-mixael dceea0d7a5 don't need this 2023-03-23 13:17:51 -05:00
mjn-mixael 1fdf8b1756 access to array sizes 2023-03-23 12:52:11 -05:00
mjn-mixael d76c733d66 nothing to see here 2023-03-23 12:23:03 -05:00
mjn-mixael c92d383b69 scpui api for medals access 2023-03-23 11:19:46 -05:00
Fabian Woltermann 7c6e27e83d Merge pull request #5279 from Baezon/clip-planes
Add clip planes to game_settings.tbl
2023-03-23 14:12:40 +01:00
Fabian Woltermann f2eca9ca3f Merge pull request #5249 from MjnMixael/scpui_hotkeys
Scpui hotkeys
2023-03-23 14:11:13 +01:00
Asteroth 31e891df0d rename and betterchecking 2023-03-23 05:04:02 -04:00
Fabian Woltermann 98f1777040 Merge pull request #5252 from MjnMixael/capitalize_icon_names
these should be capitalized
2023-03-23 10:01:15 +01:00
Asteroth af41dbae37 add clip planes to game_settings 2023-03-22 19:48:05 -04:00
mjn-mixael 242c7184b8 Merge branch 'master' into scpui_hotkeys
# Conflicts:
#	code/scripting/api/libs/ui.cpp
2023-03-22 09:14:21 -05:00
Fabian Woltermann 2f28dc2f1e Merge pull request #5239 from MjnMixael/scpui_game_help
SCPUI methods for the Game Help UI
2023-03-22 15:11:11 +01:00
mjn-mixael 88166d58bc Merge branch 'master' into scpui_hotkeys
# Conflicts:
#	code/scripting/api/libs/ui.cpp
#	code/source_groups.cmake
2023-03-22 08:33:11 -05:00
mjn-mixael 51c55550f0 Merge branch 'master' into scpui_game_help
# Conflicts:
#	code/scripting/api/libs/ui.cpp
2023-03-22 08:25:33 -05:00
BMagnu 9caa9c4c7c Expose some Nebula settings to Lua (#5268)
* Add more nebula options

* rename vars due to windows api defines
2023-03-22 12:42:18 +01:00
Mike Nelson fbf0db09a7 Scpui Mission Log (#5242)
* SCPUI access to scrollback items (mission event log and message log)

* copy paste error

* check the objective flags instead of the action flags now

* rename actions -> segments
2023-03-21 20:03:35 -04:00
Asteroth 6afb160ebd add some parameters for corkscrew start angle (#5275) 2023-03-21 20:03:20 -04:00
Naomi Coffman 6752a7f196 Fix bad merge 2023-03-20 11:30:05 -04:00
Naomi Coffman 2cb9b94f61 Merge branch 'master' into more-flexible-dynamic-messages 2023-03-20 11:07:36 -04:00
Goober5000 6f7c949e16 Merge pull request #5267 from Goober5000/event_timestamp_check_fix
fix an edge case in is-event-true-delay and related sexps
2023-03-20 11:04:32 -04:00
Goober5000 5b411f4041 Merge pull request #5266 from Goober5000/timestamp_snapshot
synchronize simulation timestamps across the entire frame
2023-03-20 11:04:14 -04:00
Naomi Coffman 91acdfbc23 Ensure variable is initialized 2023-03-20 10:58:46 -04:00
Mike Nelson 29ea809790 toggle auto-assigning personas (#5125) 2023-03-19 21:50:26 -04:00
Goober5000 7540c79993 add comment 2023-03-19 00:01:20 -04:00
Goober5000 eed50619ca fix an edge case in is-event-true-delay and related sexps
Originally the check for event delay was this:
```
if ( (fix) Mission_events[i].timestamp + delay >= Missiontime )
    return SEXP_FALSE;
```
This returns false even when the mission time is equal to the timestamp.  Therefore the timestamp check needs to use >, not >=.

Thanks to Durandal and ShivanSpS for helping to track this down.
2023-03-17 15:00:06 -04:00
Goober5000 685f641696 synchronize simulation timestamps across the entire frame
Prior to the timer upgrade, all simulation timestamps shared identical timer and timestamp values for the duration of the frame, since they were only updated within the `game_set_frametime` function.  Since the timer upgrade depends on the system clock, timestamps evaluated near the end of the frame will be very slightly later than timestamps evaluated near the beginning of the frame.  It is desirable to keep them all in sync.

This PR tweaks the timestamp system to take a snapshot at the beginning of the frame, then use that snapshot for the entire duration of the frame.  This only affects simulation timestamps; real-time timestamps still use the live timer.
2023-03-17 14:14:55 -04:00
Asteroth 32cfb59a9e fix a bug in mission log with subsys names (#5261) 2023-03-16 22:43:15 -04:00
Goober5000 75a14625cf Merge pull request #3392 from the-maddin/qt-campaign-editor
QtFRED campaign editor
2023-03-15 15:15:48 -04:00
Goober5000 56869f10a5 Merge pull request #5259 from MjnMixael/qtfred_warning_fix
Use qtfred style warning instead of fred style
2023-03-15 15:15:22 -04:00
Goober5000 482d4a19a8 Merge branch 'master' into qtfred_warning_fix 2023-03-15 14:18:11 -04:00
Goober5000 2baf97b07a Merge pull request #5257 from DMJC/master
Fixes for Missionsave.cpp and BriefingEditorDialog.ui
2023-03-15 14:13:33 -04:00
mjn-mixael 27d9e412cb use qtfred style warning instead of fred 2023-03-15 08:02:32 -05:00
James Carthew 6e51c7cc05 Fixed missionsave.cpp - removed deprecated MB_OK MessageBox command. 2023-03-15 22:16:05 +10:30
James Carthew 638745cb16 Fixed compilation error in BriefingEditorDialog.ui 2023-03-15 22:15:01 +10:30
mjn-mixael 900abcf680 expose texture filtering as a built-in option 2023-03-14 11:00:55 -05:00
Mike Nelson b74937d74f always test goober-suggested code for errors (#5254) 2023-03-13 16:38:55 -04:00
Naomi Coffman 2c42f425dc Remove some hardcoded send chances
I missed these earlier. Oh well. They're gone now.
2023-03-11 20:51:32 -05:00
Naomi Coffman fd82ff70f1 Merge all friendly arrival messages into one type 2023-03-11 19:14:14 -05:00
Naomi Coffman 1b5b902bdd Remove unused parameters
These were always 0, and now they're gone.
2023-03-11 18:11:56 -05:00
Naomi Coffman 730eddc73a Localize message type parsing 2023-03-11 17:57:03 -05:00
Naomi Coffman 39b24a5789 Add subject filters to most messages 2023-03-11 17:39:49 -05:00
Naomi Coffman 43bd4d95fa Support sender filters 2023-03-11 17:39:49 -05:00
Naomi Coffman 7a5c145436 Parse message filters
They're not used yet, but they do get parsed.
2023-03-11 11:39:06 -05:00
Naomi Coffman 95f5839b5f Disenlongate method names 2023-03-11 11:39:06 -05:00
Naomi Coffman 8d1171ae88 Add message types for every standard player order
This commit also changes a couple confusing message type names.
2023-03-11 11:39:06 -05:00
Naomi Coffman 11987590af Overhaul builtin message matching logic
The logic used to select builtin messages was complex and hard to follow. This commit replaces it with logic that, while not identical, is both similar and more flexible. Additionally, the old logic had a major limitation when it came to downgrading messages: If a message type was defined for *any* persona, then it couldn't be downgraded for *any* persona. The new logic removes this limitation, and makes downgrade paths easier to define as well.
2023-03-11 09:34:01 -05:00
Naomi Coffman 629857adfb Always use the tabled occurrence chance
Some message types had hard-coded occurrence chances. These have been removed, and the default occurrence chance for the corresponding type modified to compensate.
2023-03-11 09:33:55 -05:00
Naomi Coffman 29c644c10c Store message priority and timing with the type 2023-03-11 08:27:46 -05:00
mjn-mixael 2bb705eca0 these should be capitalized 2023-03-10 10:39:46 -06:00
Mike Nelson b1033732f1 fixup error checking in regards to sexps using dynamic parameters (#5245)
* fixup error checking in regards to sexps using dynamic parameters

* anal retentive

* add more nonsense to make other nonsense work

* check these better

* dammit github

This reverts commit 542707c1c2.

* do this again but not in GitHub

* more nonsense to handle nonsense

* Revert "more nonsense to handle nonsense"

This reverts commit 6bc8b6e775.

* this is the song that never ends
2023-03-10 03:05:53 -05:00
Goober5000 39d5fc36f7 Merge pull request #5250 from Goober5000/tweak_techroom_modelnum
fix Techroom_modelnum references
2023-03-10 00:06:53 -05:00
Goober5000 ede86efa99 move self-destruct mission logging to ship_hit_kill
This moves `LOG_SELF_DESTRUCTED` to the same place that `LOG_SHIP_DESTROYED` is recorded.  This allows self-destruction to be correctly recorded when a ship is self-destructed via script, as well as when it is auto-repaired with a negative hull multiplier, or when ships are killed off in in-game joining.
2023-03-09 23:47:19 -05:00
Goober5000 8b63f9528d fix Techroom_modelnum references
These should be >=, not >
2023-03-09 22:19:35 -05:00
mjn-mixael 08471e8749 cleanup includes 2023-03-09 16:41:18 -06:00
mjn-mixael 465190b154 fix some issues based on testing 2023-03-09 16:38:31 -06:00
mjn-mixael 3c498e65ec get hotkeys by line 2023-03-09 15:56:30 -06:00
mjn-mixael aa91e93aa6 copy/paste 2023-03-09 14:36:27 -06:00
mjn-mixael 3e24e21e4d add a dumb 2023-03-09 10:25:36 -06:00
mjn-mixael 6d142428c3 remove a dumb 2023-03-09 10:14:04 -06:00
mjn-mixael 92f140c080 add functions 2023-03-09 10:03:37 -06:00
mjn-mixael 03555ebce4 some cleanup and prep 2023-03-09 09:56:39 -06:00
Goober5000 0d3922d483 Merge pull request #5247 from Goober5000/fix_submodel_iteration
fix submodel sanity check
2023-03-08 19:51:37 -05:00
Goober5000 0f88965aed fix submodel sanity check
If a submodel doesn't have a parent, set `parent_sm` to nullptr instead of a random value.
2023-03-08 19:09:29 -05:00
Goober5000 a65813b292 Merge pull request #5234 from Goober5000/new_hud_gauges
add missing HUD gauges
2023-03-08 15:30:50 -05:00
Goober5000 8236a87d25 Merge pull request #5243 from Goober5000/add_ship_flags
add some ship flags to the alter-ship-flag lists
2023-03-08 15:29:55 -05:00
mjn-mixael e105b57a26 read access to mission hotkeys for scpui 2023-03-08 14:23:33 -06:00
Asteroth 482034a383 Adjust movement sanity checks to account for more situations (#5240)
* adjust movement sanity checks

* traverse through children

* use `model_iterate_submodel_tree`
2023-03-08 15:18:57 -05:00
Goober5000 5e255dd8d1 add some ship flags to the alter-ship-flag lists
A few ship flags were missing from these lists.
2023-03-07 22:40:21 -05:00
mjn-mixael 55a89dc13d clarify documentation 2023-03-07 13:27:00 -06:00
Fabian Woltermann 7205808e76 Merge pull request #5149 from MjnMixael/refactor_scrollback_msg
Refactor Msg_scrollback_lines
2023-03-07 18:11:06 +01:00
Goober5000 0b2c356fe8 Merge pull request #5241 from MjnMixael/fix_subsy_node_check
Check the op const, not the op dummy
2023-03-07 10:37:08 -05:00
JohnAFernandez 199fca289c Merge pull request #5223 from Baezon/shudder-multipliers
Add shudder multipliers
2023-03-07 10:29:12 -05:00
mjn-mixael c1260fc533 Check the op const, not the op dummy 2023-03-07 08:10:50 -06:00
niffiwan f9c9474b0c Merge pull request #5235 from niffiwan/fix/chucked-asteroids-speed
use large asteroids speed when chucking asteroids
2023-03-07 20:41:04 +10:00
niffiwan 625a77bdb1 Merge pull request #5238 from Baezon/remove-vestigal-attach-thrusters
Remove `Attach_thrusters` submodel flag
2023-03-07 20:40:29 +10:00
mjn-mixael 1d9fa9719c some cleanup 2023-03-06 18:26:19 -06:00
mjn-mixael bc2218a87b use a table 2023-03-06 18:22:33 -06:00
mjn-mixael b2e56dc408 Initial setup of lua access to help sections 2023-03-06 17:33:09 -06:00
mjn-mixael 8cd8e9b0ff address feedback 2023-03-06 09:45:55 -06:00
Fabian Woltermann 2392a6cc7d Merge pull request #5231 from BMagnu/volumetric_nebulae
Localized Volumetric Nebulae
2023-03-06 16:38:14 +01:00
Fabian Woltermann c8fd2af450 Merge pull request #5090 from MjnMixael/scpui_closeup_icons
SCPUI methods required for handling closeup briefing icon stuff
2023-03-06 16:36:44 +01:00
Mike Nelson 46d1386690 Enhance Dynamic SEXPs with parent parameters (#5033)
* Add ability for a Lua sexp parameter to require a 'parent' parameter

* Add dockpoint as a return type

* variable conflicts

* var name

* qtfred

* address feedback
2023-03-06 22:27:06 +09:00
BMagnu 7b288deb62 Add missing return statements 2023-03-06 14:26:29 +01:00
BMagnu 5be591a345 Separate parsing from initialization and remove RAII 2023-03-06 14:16:03 +01:00
niffiwan 5cc0404efc use input asteroids speed
In case anyone wants to change the type of asteroids chucked at ships in
future
2023-03-06 21:48:03 +10:00
Asteroth ece792d35b remove vestigal flag 2023-03-06 02:17:52 -05:00
BMagnu 7893f0e3c5 Remove superfluous comment 2023-03-06 00:15:59 +09:00
BMagnuandFabian Woltermann c2a61c7d86 Update volumetric fog uniform buffer
Co-authored-by: Fabian Woltermann <[email protected]>
2023-03-06 00:14:58 +09:00
Fabian Woltermann a918212fe6 Merge pull request #5237 from BMagnu/opengl_debug_access
Add new OpenGL Debug Mode to cmake
2023-03-05 15:42:15 +01:00
Birk Magnussen e561b9e915 Add new OpenGL Debug Mode to cmake 2023-03-05 14:56:53 +01:00
Fabian Woltermann 9d41b1bb1e Merge pull request #5236 from qazwsxal/gr_debug_groups
Enable debug scope on release builds
2023-03-05 14:21:17 +01:00
Birk Magnussen b3502ba413 Add GR debug scopes 2023-03-05 13:13:51 +01:00
Birk Magnussen 3917890981 Don't render volumetrics when fog is disabled 2023-03-05 13:03:01 +01:00
Adam Leach a150dc8255 Enable debug scope on release builds 2023-03-05 11:33:45 +00:00
niffiwan aa4c3840f4 use large asteroids speed when chucking asteroids
Chucked asteroids are always large. Therefore use their speed, not the
speed of the 1st parsed/small asteroid. Should not affect retail because
it uses the same speed for all three asteroids
2023-03-05 21:14:02 +10:00
niffiwan 65f96cbf42 Merge pull request #5233 from Baezon/fix-thruster-flicker
Small fix for thruster flicker
2023-03-05 21:06:30 +10:00
Mike Nelson e664849346 Use subsystem names instead of model names (#5217)
* use subsystem names instead of model names

* address feedback
2023-03-05 19:02:35 +09:00
Mike Nelson c7a5f87b1b Document options files (#5177)
* Some documentation

* top level descriptions
2023-03-05 19:01:45 +09:00
Goober5000 b265124459 add missing HUD gauges
Looks like the last time this list was updated was in commit 2cded90031, and other gauges have been added since then.  So let's update the list.
2023-03-05 01:36:09 -05:00
Asteroth 89f10a5495 small fix for thruster flicker 2023-03-05 00:55:14 -05:00
Birk Magnussen 2f4bea8b21 Fix claaaaang 2023-03-05 00:41:44 +01:00
Birk Magnussen 473f907a40 Fix more warnings 2023-03-05 00:28:34 +01:00
Birk Magnussen 8af5d4cf93 Tidy up more after lib 2023-03-05 00:06:06 +01:00
Birk Magnussen 58fd88a113 Tidy up after lib's warnings 2023-03-05 00:00:05 +01:00
Birk Magnussen b50456c244 Fix GCC Warns 2 2023-03-04 23:57:00 +01:00
Birk Magnussen 97fde4d149 Fix GCC Warns 2023-03-04 23:48:06 +01:00
Birk Magnussen 5b06f84771 Correct depth for FoV abberation 2023-03-04 23:24:34 +01:00
Birk Magnussen e194e84c27 Add FRED round trip support 2023-03-04 22:30:29 +01:00
Goober5000 e103eaeb45 add some XSTR entries (#5229)
Add XSTR entries for "or", "None", and "Nothing".

Note that there is already an XSTR entry for "none", but it does not have the right capitalization.

Note that "None" is localized in `textify_scancode` but not `textify_scancode_universal`.

This makes "Nothing" cargo use appropriate localization.

Fixes #5227.
2023-03-04 08:57:29 -06:00
Goober5000 8153e32351 Merge pull request #5224 from Baezon/ai-movement-flags
Update some movement flags to work for AI too
2023-03-03 23:29:20 -05:00
Goober5000 fd66eb7550 Merge pull request #5230 from Baezon/fix-damage-scaling-bug
Fix damage scaling oversight
2023-03-03 23:29:01 -05:00
Asteroth 02805be745 fix damage scaling oversight 2023-03-03 21:32:07 -05:00
Goober5000 f8f61e8b62 Merge pull request #5104 from Goober5000/persona_species
Persona species enhancements
2023-03-03 18:25:53 -05:00
BMagnu cfba7ec067 optimize Shader performance 2023-03-03 09:10:14 +01:00
Birk Magnussen 5e285e42bc Set proper texture address mide 2023-03-02 21:17:56 +01:00
Birk Magnussen 975b31dc91 Fix nebula alpha 2023-03-02 21:04:41 +01:00
MjnMixael 7a24e0e4c6 Refactor gameplay help (#5119)
* refactor gameplay help

* OCD

* some read better than others

* typo
2023-03-02 22:10:08 +09:00
MjnMixael 259828316d Use weapon tech model if no anim (#5075)
* initial working version

* cleanup and generalize variable names
2023-03-02 22:09:13 +09:00
BMagnu 3a3d2c4438 Tidy up shader code 2023-03-02 13:54:11 +01:00
BMagnu 4af5bf405f Make volumetrics obey nebula quality settings 2023-03-02 13:38:53 +01:00
BMagnu 7827cb4835 Add Noise intnsity lab integration 2023-03-02 13:01:10 +01:00
BMagnu db8292be03 Add noise color intensity 2023-03-02 12:54:00 +01:00
BMagnu 1b1a8983ee Properly check for uploaded textures 2023-03-02 12:39:14 +01:00
BMagnu 5e9dd9aef5 Calculate alpha for things rendered after the nebula 2023-03-02 12:35:35 +01:00
BMagnu c342a22507 handle 3d array access using define 2023-03-02 11:42:07 +01:00
Asteroth 15b1ed8822 fix name (#5225) 2023-03-02 10:23:49 +00:00
Asteroth a0e94eca92 update some movement flags to work for AI too 2023-03-01 21:11:23 -05:00
Asteroth 6720115b95 fix retail star look by applying gamma correction (#5222) 2023-03-01 20:19:00 -05:00
Asteroth c3d6d72941 add for engine wash too 2023-02-28 20:13:08 -05:00
Asteroth 0428fa221f add shudder multipliers 2023-02-28 20:08:26 -05:00
Birk Magnussen 7f83dd8ddb Fix volume map generation 2023-02-28 21:51:34 +01:00
Birk Magnussen dd1641fd15 Fix coordinates 2023-02-28 21:11:07 +01:00
Birk Magnussen 53b1dc690a Enter values from empirical testing 2023-02-28 20:27:11 +01:00
Birk Magnussen 5392a0d9fe Fix lab volumetrics 2023-02-28 20:24:46 +01:00
BMagnu 2f0e2f591f Adjust alpha of neb-affected effects 2023-02-28 14:17:49 +01:00
BMagnu cc1e26dd25 Fix skip_to_start_of_string_one_of 2023-02-27 16:56:08 +01:00
BMagnu 14b37add71 ImGui integration for neb settings 2023-02-27 16:49:39 +01:00
BMagnu e1f071036f Lab parse volumetric nebula 2023-02-27 15:55:03 +01:00
BMagnu 6b0f49cf3b Begin Lab integration 2023-02-27 09:37:11 +01:00
wookieejedi 9d57ca14de Add line of sight as optional AI override (#5220)
Many values in `ai.tbl` can be inserted as overrides for their equivalent `Ai_profiles.tbl` values. (They are all optional and if not set for an AI class, the values in AI Profiles will be used.)

This is particularly useful for making very specific AI classes that still follow the main AI profiles table with easy to change values.

This PR adds `$firing requires exact los:` as an optional override to set in `ai.tbl`. This particular override is very useful, since it can be set to off by default in the `ai_profiles.tbl` for performance, but then set to on for some select AI classes within `ai.tbl`, and those AI classes can be easily changed on the fly in a mission.
2023-02-26 21:43:40 -05:00
Birk Magnussen 2298c3fb31 Properly unload volume textures 2023-02-25 00:13:59 +01:00
Birk Magnussen 8f697dd03a Fix Noise, Fix Scale, Fix Pos 2023-02-24 23:50:50 +01:00
Goober5000 6eeeb788dc Merge pull request #5218 from Goober5000/5210_5157_followup
5210 and 5157 followup
2023-02-24 17:22:42 -05:00
BMagnu a60512cfa4 Add parsing for nebula settings 2023-02-24 14:51:18 +01:00
BMagnu 2fd24ecf29 Begin integration into mission 2023-02-24 14:16:38 +01:00
BMagnu 9cdbf4b5ed Load configurable noise 2023-02-24 11:59:21 +01:00
m!m d2e57becd3 Merge pull request #5219 from asarium/codeowners_update
Remove myself from code owners
2023-02-24 11:40:00 +01:00
asarium 305fa3c6eb Remove myself from code owners
I have not been able to keep up with code reviews for quite some time so
I should not be a default one.

Also fixed a copy issue which was missing an option to properly handle
already existing files.
2023-02-24 11:17:53 +01:00
Goober5000 7a2caea6ea here too 2023-02-23 23:02:30 -05:00
Goober5000 0fc8fcfad3 localization tweaks
1) follow-up to 5210: Avoid a memory leak caused by duplicating text, assigning it to a SCP_string, and then leaving the buffer in limbo
2) also keep the text as const char * since it's probably best to be consistent and keep the three types the same
3) be more scrupulous about checking for the existence of map entries, since the [] operator is create-if-not-found
2023-02-23 22:32:28 -05:00
Goober5000 dbe731782a prevent memory leaks in the mission log by using unique_ptr (since message_log_remove_segs no longer exists to free the strings) 2023-02-23 21:06:49 -05:00
Goober5000 6bc6b0f1e2 use SCP_string optimizations here 2023-02-23 20:35:48 -05:00
Birk Magnussen 6eee49a868 Optimize smoothing mode of volumetrics shader 2023-02-23 20:55:26 +01:00
Birk Magnussen b6f0e8e4e8 Build noise lib in release 2023-02-23 20:55:08 +01:00
BMagnu 1a5c39154d Very basic volumetric noise setup 2023-02-23 15:33:06 +01:00
Fabian Woltermann b373ad2df4 Merge pull request #5036 from MjnMixael/lua_access_to_enums
allow scripts to read LuaEnums and add LuaEnums
2023-02-23 14:46:48 +01:00
Fabian Woltermann 39c5336847 Merge pull request #5210 from MjnMixael/mapify_builtin_strings
Mapify builtin strings
2023-02-23 14:38:32 +01:00
Fabian Woltermann 9cfc6f4b07 Merge pull request #5157 from MjnMixael/refactor_scrollback_log
Refactor mission log scrollback
2023-02-23 14:35:15 +01:00
Fabian Woltermann 9190d90536 Merge pull request #5158 from MjnMixael/lua_goals_virtvars
Add virtvars for goal satisfaction and score
2023-02-23 14:33:54 +01:00
Fabian Woltermann 50fee8eb8a Merge pull request #5211 from Baezon/increase-snd-update
Increase sound update rate
2023-02-23 14:33:03 +01:00
Fabian Woltermann 7f44bd1969 Merge pull request #5213 from MjnMixael/check_dup_enum_items
Check duplicate enum items
2023-02-23 14:32:48 +01:00
BMagnu 03e3bdb40a cleanup noise 2023-02-23 12:33:33 +01:00
BMagnu c127b2b982 Make Edge smoothing toggleable 2023-02-23 11:06:50 +01:00
BMagnu 15d078aad2 Add edge smoothing and fix size ordering 2023-02-23 10:47:27 +01:00
Birk Magnussen 92fc993597 Remove UB due to Non uniform control flow 2023-02-23 00:48:53 +01:00
Birk Magnussen 88dd1f843b Disable noise 2023-02-23 00:14:26 +01:00
Birk Magnussen 084085a53f Make noise loadable 2023-02-22 23:19:45 +01:00
BMagnu eb81b50c55 Actually load noise volume texture 2023-02-22 16:50:19 +01:00
BMagnu 6e91356f47 Properly pass volumetric pso/size 2023-02-22 16:48:39 +01:00
BMagnu 9dbf5df152 Add Noise sampling to volumetric shader 2023-02-22 16:11:33 +01:00
BMagnu c2c02470d1 Add noise generation 2023-02-22 14:52:55 +01:00
BMagnu e78fbfb9be Add worley noise 2023-02-22 14:09:21 +01:00
BMagnu 756f0a9732 Incorporate new COLLIDE_ALL for nebula rendering 2023-02-22 12:26:54 +01:00
BMagnu 68ad0c826b Merge branch 'master' into volumetric_nebulae 2023-02-22 09:31:41 +01:00
Goober5000 f02ff33311 Merge pull request #5204 from Goober5000/enhance_sexp_comments
Enhance sexp comments
2023-02-21 21:40:25 -05:00
Goober5000 98268b139c Merge pull request #5214 from Goober5000/mc_info_init_update
add initializers to mc_info
2023-02-21 21:40:12 -05:00
Goober5000 5b175673ed add initializers to mc_info
This initializes `mc_info` to the correct values when it is constructed, removing the need for `mc_info_init`.

This PR also fixes a group of incorrectly inverted assignments in beam.cpp.
2023-02-21 19:09:10 -05:00
Asteroth 1dc4a210b7 Add collision flag for colliding with all polies (#5212)
* add collision flag for colliding with all polies

* copy paste error
2023-02-22 04:45:18 +09:00
mjn-mixael eaed502d62 break the loops 2023-02-21 12:25:49 -06:00
mjn-mixael 267921b443 skip the outer loop, not the inner loop 2023-02-21 11:51:07 -06:00
mjn-mixael 439f59e1f2 check for duplicates here, too 2023-02-21 09:12:54 -06:00
mjn-mixael ce8724a653 disallow enum duplicates 2023-02-21 09:10:48 -06:00
mjn-mixael ed78597635 check for duplicate enum items 2023-02-21 08:39:47 -06:00
mjn-mixael af41185acb Merge branch 'master' into lua_access_to_enums 2023-02-21 08:00:02 -06:00
MjnMixael 61247bf3e2 sexps to check turret weapons (#5072) 2023-02-21 18:11:21 +09:00
MjnMixael c83b4b5838 is-ship-emp-active sexp (#5071)
* is-ship-emp-active sexp

* remove these

* remove counting

* unused variable declarations
2023-02-21 18:11:00 +09:00
MjnMixael f6ffe4e399 add pre-parse enums support (#5011)
* add pre-parse enums support

* Skip to the next defined enum if one already exists by this name.

* do this as string instead of char array
2023-02-21 18:10:52 +09:00
Asteroth 18b48214a2 Fix some issues with damage application (#5084)
* fix some issues with damage application

* typo

* turn off flag for new versions

* update versions to apply to post 23.0 nightlies
2023-02-21 18:10:44 +09:00
Asteroth ddc5c7ac8b increase sound update rate 2023-02-21 01:17:09 -05:00
Goober5000 9d0629f657 Merge pull request #5196 from MjnMixael/flag_sexp_descriptions
Flag sexp descriptions
2023-02-20 23:26:29 -05:00
mjn-mixael 7d0743d5ed SCP_string 2023-02-20 18:01:08 -06:00
mjn-mixael 9e24469928 emplace 2023-02-20 17:28:21 -06:00
mjn-mixael 4483d5051b remote the last of the old array and actually copy the data into the map 2023-02-20 17:06:01 -06:00
the-maddin 4e9309a154 Comment branch types 2023-02-20 21:15:08 +01:00
the-maddin 439c22b528 Merge branch 'master' into qt-campaign-editor 2023-02-20 21:07:01 +01:00
Fabian Woltermann e3be23ac7f disable the fog pass when rendering cockpits (#5208) 2023-02-20 23:17:47 +09:00
MjnMixael 39c71d3a7b Flag to apply hud shudder to chase view (#5145)
* flag to apply hud shudder to chase view

* not not
2023-02-20 23:13:24 +09:00
MjnMixael b2fe7a94ae Remove nebula bitmap limit (#5128)
* Remove nebula bitmap limit

* FRED bounds check and qtFRED

* remove length checks
2023-02-20 23:13:10 +09:00
Asteroth b7353b2027 Add turret-fired-since SEXP (#5061)
* add turret-fired-since

* update to new timestamp system

* unused variables
2023-02-20 22:10:49 +09:00
BMagnu bef3f33f6a Always to sample buffer assign 2023-02-20 11:04:55 +01:00
BMagnu d0f051847c reduce 3d texture build from O(n^3) to O(n^2) 2023-02-20 11:00:41 +01:00
Fabian Woltermann 153d3effaa Merge pull request #5160 from The-E/feature/vulkan
make the vulkan support buildable again
2023-02-20 10:54:11 +01:00
Fabian Woltermann 96f0c66722 shut down the imgui SDL backend regardless of graphics API selected 2023-02-20 10:27:31 +01:00
Goober5000 bdea153270 Merge pull request #5163 from MjnMixael/lua_update_discord
Lua update discord
2023-02-19 18:40:18 -05:00
mjn-mixael 13e28a3102 const the header, dummy 2023-02-19 14:58:17 -06:00
Goober5000 b089dabadc Merge pull request #5207 from MageKing17/bugfix/negative-check-inversion
Fix negative child check inversion.
2023-02-19 15:54:48 -05:00
Goober5000 a20dd3bea9 Merge pull request #5174 from MjnMixael/get_audiostream_duration
get audiostream duration in float seconds
2023-02-19 15:46:30 -05:00
mjn-mixael 5dc8b04dab boom chikka const const 2023-02-19 14:32:48 -06:00
mjn-mixael 00995f5516 typos 2023-02-19 14:29:00 -06:00
MageKing17 8846e043fb Fix negative child check inversion.
In PR #5202, a bunch of `Assert(child >= 0);` statements were replaced with `if (child < 0) return nullptr;`, except the first one kept the assertion's condition (inverting the logic). This fixes this accidental inversion.
2023-02-19 12:26:37 -08:00
Goober5000 89c6d330f8 Merge pull request #5159 from MjnMixael/credits_no_splitting
Prevent line splitting if building credits for SCPUI
2023-02-19 15:10:14 -05:00
Goober5000 42db9f2e7b Merge pull request #5169 from MjnMixael/countermeasure_cargo_size
Feature for countermeasures to respect cargo size
2023-02-19 15:06:17 -05:00
Goober5000 35f4dab373 Update code/sound/audiostr.h
Update documentation
2023-02-19 14:44:41 -05:00
mjn-mixael 2ed504eb82 clarified descriptions 2023-02-19 10:48:48 -06:00
MjnMixael 5074a939ed Merge branch 'master' into lua_update_discord 2023-02-19 10:39:11 -06:00
Fabian Woltermann ec4222b412 Merge pull request #5190 from MjnMixael/lua_os_focus
Lua method to check if the game has focus
2023-02-19 17:22:27 +01:00
Fabian Woltermann 901dfe310b Merge pull request #5186 from MjnMixael/on_warp_complete_hook
On warp complete hook
2023-02-19 17:21:58 +01:00
Fabian Woltermann 5f6f4c11b2 Merge pull request #5191 from MjnMixael/unlimited_power
Unlimited Power
2023-02-19 17:21:07 +01:00
Fabian Woltermann 2de1441bf1 Merge pull request #5192 from MjnMixael/cutscene_custom_data
Cutscene custom data
2023-02-19 17:20:48 +01:00
Fabian Woltermann e1de3b6ac4 Merge pull request #5202 from Goober5000/deblongify_fred
deblongify fred
2023-02-19 17:20:02 +01:00
Fabian Woltermann 6960fe58c8 Merge pull request #5203 from Baezon/no-bsp-tree-optimization
Remove previous bsp tree skipping optimization
2023-02-19 17:19:46 +01:00
Fabian Woltermann 4b6a791b02 pin vulkan version to 1.3.204.0 2023-02-19 15:43:17 +01:00
Fabian Woltermann 801b693e63 make sure the WITH_VULKAN compile time flag is still set 2023-02-19 15:43:17 +01:00
Fabian Woltermann 0ab3a85289 cleanup 2023-02-19 15:43:17 +01:00
Fabian Woltermann faf8fb2ecc don't build vulkan on macos for now either 2023-02-19 15:43:17 +01:00
Fabian Woltermann 0fbc422ca0 remove vulkan references from the lab 2023-02-19 15:43:17 +01:00
Fabian Woltermann c835481e6d x86 builds don't get vulkan 2023-02-19 15:43:17 +01:00
Fabian Woltermann 4deaecece9 more compile fixes 2023-02-19 15:43:17 +01:00
Fabian Woltermann 1387c46b67 fix the rest of the pipelines 2023-02-19 15:43:17 +01:00
Fabian Woltermann acd4486fc1 remove unfinished imgui init 2023-02-19 15:43:17 +01:00
Fabian Woltermann b7343690de move vulkan sdk install to similar place in macos pipeline 2023-02-19 15:43:17 +01:00
Fabian Woltermann 7d39df9871 fix missing fall-through in case statement 2023-02-19 15:43:17 +01:00
Fabian Woltermann 4ab8d35b8b add curl to the gha container 2023-02-19 15:43:16 +01:00
Fabian Woltermann 3e7e3bfb4d more cleanup 2023-02-19 15:43:16 +01:00
Fabian Woltermann 42a16b4c7d fix minor issues breaking compilation in CI 2023-02-19 15:43:16 +01:00
Fabian Woltermann 7ea7953cd7 wip 2023-02-19 15:43:16 +01:00
Fabian Woltermann 0bb898ae2e download the vulkan sdk in the pipeline 2023-02-19 15:43:16 +01:00
Fabian Woltermann c6831d8b30 instead of shipping our own copy of vulkan-hpp, use the one in the official SDK 2023-02-19 15:43:16 +01:00
Asteroth 68aec1edef Merge remote-tracking branch 'upstream/master' into no-bsp-tree-optimization 2023-02-19 04:07:07 -05:00
Fabian Woltermann 072fee459b Merge pull request #5199 from Baezon/refactor-submodel-rand-points
Add `GetVertex()` and `NumVertices()` script functions and clean up random submodel point retrieval a bit
2023-02-19 08:58:03 +01:00
Goober5000 d85d854646 make multiline work in text editor 2023-02-18 16:17:32 -05:00
Goober5000 23c5355bc7 make multiline comments display properly without length restriction 2023-02-18 15:45:28 -05:00
Asteroth eba379330e update naming and remove unused function 2023-02-18 15:31:06 -05:00
Asteroth f75f08f7ba remove previous optimization 2023-02-18 15:15:41 -05:00
Goober5000 0357df1e7d add comment 2023-02-18 15:01:44 -05:00
Asteroth 7a5c6df202 update docs and prints 2023-02-18 14:58:00 -05:00
Goober5000 628ac80f2c prevent fred from crashing on a node that shouldn't be there 2023-02-18 14:55:18 -05:00
Goober5000 ea58a760ff prevent the BLONG by capturing keypresses 2023-02-18 14:09:44 -05:00
Fabian Woltermann 5e79d94bad Merge pull request #5201 from The-E/fix/deprecated_github_actions
Fix github CI deprecation warnings
2023-02-18 19:48:23 +01:00
Goober5000 2f4059b7fd Merge pull request #5198 from Goober5000/fix_mission_version
mission version numbers should be major.minor
2023-02-18 13:46:18 -05:00
Fabian Woltermann b030148c21 Merge pull request #5019 from Goober5000/query_referenced_update
more #define updates
2023-02-18 18:45:22 +01:00
MjnMixael 754c351498 per bank autoaim (#5074)
adds per-bank autoaim feature
2023-02-18 18:43:03 +01:00
Fabian Woltermann f45a6fb58c removes soon to be deprecated github CI commands. For details see https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/ 2023-02-18 18:30:08 +01:00
Asteroth 6e25fbb50f unused variable 2023-02-17 23:55:22 -05:00
Asteroth db5a37c178 add num vertices script func 2023-02-17 23:23:24 -05:00
Asteroth b68e424213 refactor getting random vertices and script func 2023-02-17 23:03:57 -05:00
Goober5000 af428ca6b9 other feedback 2023-02-17 21:59:57 -05:00
Goober5000 731b5d53c5 change case 2023-02-17 21:50:42 -05:00
Birk Magnussen 3042846e62 Fix model-based volume generation 2023-02-18 00:17:44 +01:00
Goober5000 8d27682126 mission version numbers should be major.minor
Since older builds of FRED parse the mission version as a float, the version can contain a maximum of one decimal point.  These changes allow FRED and FSO to disregard the build number when loading, saving, or comparing versions.

There is also a small fix to qtfred's saving of the author field.
2023-02-17 12:32:54 -05:00
mjn-mixael 9f20cb1921 descriptions 2023-02-17 10:03:54 -06:00
BMagnu 8b75bbbb0d Add model read for 3d texture sample 2023-02-17 15:09:21 +01:00
BMagnu 9220b48592 Fix Typo and test oversampling 2023-02-17 13:26:18 +01:00
BMagnu f7f2b5f025 Encapsulate 3d texture render in volumetrics class 2023-02-17 11:59:13 +01:00
BMagnu 2531a31b1e tidyup parameters 2023-02-17 10:42:23 +01:00
Goober5000 8d406c2167 Merge pull request #5069 from MjnMixael/popup_shortcut_var
Pass shortcut key character to Lua as a hook variable
2023-02-16 22:32:44 -05:00
Goober5000 0813a7f416 Merge pull request #5195 from MjnMixael/fix_qtfred_building
missed items required to build qtfred
2023-02-16 22:31:45 -05:00
Goober5000 9a1badf444 Merge pull request #5193 from MjnMixael/object_death_documentation
Match documentation description to actual hook names.
2023-02-16 22:30:28 -05:00
MjnMixael 5df51711fe add ability to disable grid rendering for each stage (#5053)
* add ability to disable grid rendingering for each stage

* revert these
2023-02-16 22:22:32 -05:00
MjnMixael 7ec27f147f Allow for arbitrary briefing icon scaling (#5047)
* allow for arbitrary briefing icon scaling

* only apply valid scale values
2023-02-16 22:22:16 -05:00
mjn-mixael e972cdc2cf explicit size_t 2023-02-16 21:10:07 -06:00
mjn-mixael f220075bbe missed items required to build qtfred 2023-02-16 20:45:01 -06:00
mjn-mixael 730c84308e qtFRED support 2023-02-16 20:36:04 -06:00
mjn-mixael badde3ad96 Let FRED display flag descriptions 2023-02-16 17:12:47 -06:00
BMagnu 1371dc3a08 Add attribution before I forget 2023-02-16 16:11:09 +01:00
mjn-mixael 0c5342b875 Match documentation to actual hook names. 2023-02-16 09:05:30 -06:00
BMagnu 4c3024e5fc Add Beer-Powder absorption for diffuse lighting 2023-02-16 16:03:47 +01:00
mjn-mixael bbb7539fb6 cutscene custom data 2023-02-16 08:50:03 -06:00
BMagnu a9a110e8fa Add Heyney Greenstein Scattering 2023-02-16 14:58:19 +01:00
BMagnu a71dbbab6a Tidy up shader and prepare for diffuse lighting 2023-02-16 13:29:43 +01:00
BMagnu 3e8be9c8a3 Fix emissive blur 2023-02-16 12:30:56 +01:00
mjn-mixael b2270e4714 OPF_BOLT_TYPE is the senate 2023-02-15 18:24:37 -06:00
mjn-mixael 5410b3ef46 sssssssnake case 2023-02-15 16:54:17 -06:00
mjn-mixael 5344b45c47 scripting documentation 2023-02-15 16:48:11 -06:00
mjn-mixael 2bdf6c21f2 i pity the bool 2023-02-15 16:44:41 -06:00
mjn-mixael 5b2bd80609 cleanup os_foreground() 2023-02-15 16:42:03 -06:00
mjn-mixael 8063fc3863 Unlimited Power 2023-02-15 16:34:15 -06:00
Birk Magnussen 9ac262579d Document Emissive Attempts 2023-02-15 20:39:16 +01:00
mjn-mixael 4924f56613 lua method to check if the game has focus 2023-02-15 10:01:59 -06:00
BMagnu dbc2cb1c27 prepare volumetric shader for multi-influence color 2023-02-15 15:51:14 +01:00
Fabian Woltermann 076ad7770b remove main shader compile-time flags (#5055) 2023-02-15 15:20:11 +01:00
BMagnu 3c942fc409 Proper step calculation based on nebula parameters 2023-02-15 15:09:37 +01:00
BMagnu 5f48e55990 Proper alpha-considering ray marching 2023-02-15 14:26:48 +01:00
MjnMixael aaee1e5a32 enhance handling of motion debris (#5022)
* enhance handling of motion debris

* dunno what i was thinking here

* address feedback

* require all four bitmaps to be defined in new parsing method

* address feedback
2023-02-15 17:13:48 +09:00
MjnMixael ce274209c1 adds hudgage and event to the valid types of a Lua Sexp parameter (#5018) 2023-02-15 17:13:38 +09:00
MjnMixael 7be49e67d1 modular autopilot table (#4978)
* modular autopilot table

* clarical comment
2023-02-15 17:13:29 +09:00
BMagnu 8731ad1448 Add option to deprecate hooks (#5184)
* Add hook deprecation to calls

* Deprecate hooks properly

* Change OnSplashScreen hook callig

* Check for deprecated hooks at script time

* include hooks directly

* Check deprecation for lua added hooks

* Write deprecation notice to docs

* rescope Target_version

* fix typo
2023-02-15 17:12:25 +09:00
Birk Magnussen a5f634885b Get volumetric ray marching working 2023-02-15 01:14:34 +01:00
Goober5000 fe4d93393b Merge pull request #5122 from Goober5000/parse_object_colgroup
make collision_group_id accessible to parse objects
2023-02-14 18:45:06 -05:00
Birk Magnussen 9de6beb4c2 First working raycast 2023-02-14 21:03:18 +01:00
BMagnu 4485efe484 Add FRED SpaceMouse support (#4984)
* Add hidapi lib

* Add Spacemouse Interface

* Integrate HID API

* Implement basic 3dconnexion hid protocol

* FRED Spacemouse integration

* QtFRED support

* Fix assertion

* More devices

* Increase polling

* Wireless resetting

* QtFRED polling frequency

* Add nonlinear scalings

* Linux Build Options for HIDAPI

* Linux Build Options for HIDAPI 2

* Fix GCC

* Resolve Type Aliasing

* Fix out-of-focus control

* rename searchSpaceMouse
2023-02-15 03:00:08 +09:00
mjn-mixael 12a0a8642e override then normal hook 2023-02-14 09:56:22 -06:00
mjn-mixael e246616fac on warp complete hook 2023-02-14 09:43:35 -06:00
BMagnu d3701166af Properly clear new composite buffer 2023-02-14 16:41:57 +01:00
BMagnu e1db2ca59a Hooks into deferred draw code 2023-02-14 15:39:05 +01:00
BMagnu 063a567fe4 Being volumetrics calculations 2023-02-14 15:22:23 +01:00
BMagnu c32c655350 Keep Emissive texture intact during deferred render step 2023-02-14 15:21:00 +01:00
BMagnu 91d274cd6d Add 3D-Texture support 2023-02-14 14:36:28 +01:00
MjnMixael 08742f36e8 enable commandline language setting (#5013) 2023-02-14 17:28:09 +09:00
MjnMixael 24571d099e modular ai classes table (#4945)
* modular ai classes table

* bool instead of int

* merge these
2023-02-14 17:27:16 +09:00
MjnMixael f29c48965e fictionviewer localization (#5012)
* fictionviewer localization

* Move this to it's own method

* C_str
2023-02-14 17:26:36 +09:00
MjnMixael fbb209ef6b Modular rank table (#4854)
* vectorize ranks

* Add modular table parsing

* int

* comments

* prevent field overwriting if tbm is used

* address feedback

* off by one
2023-02-14 17:25:52 +09:00
Goober5000 7cc9f72cac Merge pull request #5077 from MjnMixael/gameplay_profiles_alias
Allow gameplay_profiles.tbl to be an alias of ai_profiles.tbl
2023-02-13 21:45:21 -05:00
Goober5000 6f7f9c2f48 Merge pull request #5120 from MjnMixael/scpui_pause_screen
funcs and virtvars for SCPUI pause screen
2023-02-13 21:45:12 -05:00
Goober5000 d398ce25fb Merge pull request #5117 from MjnMixael/pause_weapon_sounds
Expose pausing weapon sounds
2023-02-13 21:39:39 -05:00
Goober5000 3c59687d75 Merge pull request #5185 from MjnMixael/splash_screens_range
Keep splash screen rand choice in range
2023-02-13 21:13:19 -05:00
mjn-mixael ef3af0e254 Keep this in range 2023-02-13 14:56:27 -06:00
MjnMixael 40807000ad Merge branch 'master' into countermeasure_cargo_size 2023-02-12 23:18:02 -06:00
Goober5000 de5a422fc0 Merge pull request #5146 from MjnMixael/on_asteroid_created
On asteroid created hook
2023-02-12 21:25:32 -05:00
Goober5000 4b86f32b21 Merge pull request #5183 from Goober5000/thruster_flag_rename
rename thruster flags
2023-02-12 20:52:48 -05:00
Goober5000 09b6552908 rename thruster flags
`Roll_` and `Bank_` are synonyms, and the `Roll_` thruster flags should be `Yaw_` anyway, so rename them and rename their table strings.  This still checks the old table strings for compatibility.
2023-02-12 19:42:26 -05:00
Goober5000 de3e158b73 Merge pull request #5182 from Baezon/fix-thruster-sounds
Fix thruster sounds and add flag for player thruster sounds
2023-02-12 19:36:38 -05:00
Goober5000 a0c0766146 Merge pull request #5181 from Goober5000/build_fix
build compatibility fix
2023-02-12 19:24:12 -05:00
Asteroth 05790db5e7 clean up 2023-02-12 18:47:02 -05:00
Asteroth d28833e92a fix thruster sounds and add flag 2023-02-12 15:55:23 -05:00
Goober5000 60e5ba9541 Merge pull request #5139 from MjnMixael/has_armor_sexp
has-armor-type sexp
2023-02-12 15:40:53 -05:00
Goober5000 705d4a519f Merge pull request #5175 from MjnMixael/unlimit_cheats
Remove message requirement for custom cheats
2023-02-12 15:39:38 -05:00
Goober5000 950fbf1a13 Merge pull request #5178 from MjnMixael/lua_free_models
Lua method to free all loaded models
2023-02-12 15:39:27 -05:00
Goober5000 dd0b099d9b Merge pull request #5176 from MjnMixael/disable_old_debug_cmnds
Remove some old debug key checks in mainhall
2023-02-12 15:39:19 -05:00
Goober5000 ca6f25f5af Merge pull request #5085 from Goober5000/play_dead_ets
prevent ship from managing ETS if it is playing dead
2023-02-12 13:34:21 -05:00
MjnMixael 09215672a1 override to set glowpoint bank to default off (#5091) 2023-02-12 09:54:23 -05:00
MjnMixael 1076493ceb choose random splash image (#5054)
* choose random splash image

* address feedback
2023-02-12 09:52:57 -05:00
Goober5000 28a1e2a3d4 build compatibility fix
Follow-up to #5138.  Tweak the function header to be more compatible with different build environments; some don't like the `= ""` for some reason.
2023-02-11 22:18:38 -05:00
MjnMixaelandGoober5000 280d8c8c8a increase mission author name length limit (#5162)
* increase mission author name length limit

* use string_copy

---------

Co-authored-by: Goober5000 <[email protected]>
2023-02-12 08:29:18 +09:00
MjnMixael 58e7d50b1c Add to description 2023-02-11 16:19:24 -06:00
Goober5000 1c4db98bc5 Merge pull request #5180 from Goober5000/update_version_23.1.x
bump version to 23.1.x
2023-02-11 16:53:33 -05:00
Goober5000 214c6e3d5c bump version to 23.1.x 2023-02-11 16:28:59 -05:00
Goober5000 eaa063ba65 Merge pull request #5152 from Goober5000/mission_versioning
add versioning support to missions
2023-02-11 16:19:33 -05:00
mjn-mixael 002ab4885e gate float divisions behind mod flag 2023-02-11 14:48:55 -06:00
Goober5000 58175aa386 Merge pull request #5179 from Goober5000/model_sanity_checks
add some sanity checks for submodel indexes
2023-02-11 15:41:24 -05:00
Goober5000 0e70c4918a Merge pull request #5079 from MjnMixael/visible_node_comments
Make sexp node comments more visible at a glance
2023-02-11 15:37:27 -05:00
Goober5000 0d75790a6a Merge pull request #5138 from MjnMixael/force_emp_sexp
hud-force-emp-effect sexp
2023-02-11 15:36:48 -05:00
Goober5000 85e11ecd6d Merge pull request #5096 from MjnMixael/opf_turret_type
Implement opf_turret_type
2023-02-11 15:36:35 -05:00
Goober5000 3651239a6b Merge pull request #5010 from Goober5000/more_category_updates
more category updates
2023-02-11 15:33:28 -05:00
mjn-mixael 041a390660 no team, dummy 2023-02-11 14:26:39 -06:00
Goober5000 6bc1bff0ab add some sanity checks for submodel indexes
Add some checks during model load for submodel indexes that could be out of range due to a corrupt model.
2023-02-11 00:32:24 -05:00
mjn-mixael de1215f64e unused 2023-02-10 21:40:10 -06:00
mjn-mixael d101227721 lua method to free all loaded models 2023-02-10 20:57:23 -06:00
mjn-mixael 13b7f626a9 appease etp 2023-02-10 09:30:38 -06:00
mjn-mixael 0e375e2e0d remove some old debug key checks in mainhall 2023-02-10 09:00:38 -06:00
mjn-mixael a360245857 remove message requirement for custom cheats 2023-02-09 15:08:30 -06:00
mjn-mixael d0e26adc20 appease goober 2023-02-07 16:08:32 -06:00
mjn-mixael 289266d959 get audiostream duration in milliseconds 2023-02-07 13:18:53 -06:00
mjn-mixael 4f36c6a781 feature for countermeasures to respect cargo size 2023-02-03 10:15:32 -06:00
mjn-mixael 4a8991703f missed comma 2023-02-01 12:17:58 -06:00
mjn-mixael 34232bd5d8 const char instead of SCP_string 2023-02-01 12:03:44 -06:00
mjn-mixael 7eca7febcb expose setting discord presence 2023-02-01 11:52:41 -06:00
mjn-mixael 0ad91aaf3d prevent line splitting if building credits for SCPUI 2023-01-31 16:19:40 -06:00
mjn-mixael e83609b121 properly force fit the actions 2023-01-30 14:22:57 -06:00
mjn-mixael 1d93e9bff6 variable collision 2023-01-30 14:01:24 -06:00
mjn-mixael a568f514a3 add virtvars for goal satisfaction and score 2023-01-30 13:59:31 -06:00
mjn-mixael ed8a511fe9 refactor mission log scrollback 2023-01-30 13:37:02 -06:00
Goober5000 3c723c9ea9 add versioning support to missions
This finally enables the `$Version:` field in FreeSpace missions, which has been present ever since the beginning of FS1's development but has never been used for its intended purpose.  This field now stores the version of FSO that is required to run the mission.  If the version of the engine is not sufficient to run the version of the mission, then a) the mission is hidden from the mission listing, or b) a friendly notification is displayed if the mission is loaded anyway (for example, through a campaign).  Furthermore, FRED will notify the user if the mission's version is migrated from any version other than the legacy 0.10.

It will be the responsibility of coders who modify the mission format to also update the `MISSION_VERSION` constant with the appropriate major/minor/build/revision of the format change.
2023-01-28 18:01:51 -05:00
mjn-mixael e9be428cd1 refactor Msg_scrollback_lines 2023-01-27 16:36:03 -06:00
mjn-mixael 8360bae5af on asteroid created hook 2023-01-26 11:24:33 -06:00
mjn-mixael 6162c475a0 float 2023-01-26 08:34:34 -06:00
mjn-mixael 9419f24184 warning 2023-01-26 08:30:26 -06:00
mjn-mixael 236b648b11 address feedback 2023-01-25 08:43:11 -06:00
mjn-mixael 414c630d04 address feedback 2023-01-25 08:31:36 -06:00
mjn-mixael d7bbecfa16 has-armor-type sexp 2023-01-24 11:20:25 -06:00
mjn-mixael d2e1e2b5de hud-force-emp-effect sexp 2023-01-23 21:50:36 -06:00
Goober5000 11f2635abd add parse object collision group to sexps 2023-01-21 18:53:40 -05:00
Goober5000 df8268368a make collision_group_id accessible to parse objects
Add collision groups to parse objects so they can be set before arrival via script.
2023-01-21 18:10:51 -05:00
mjn-mixael 6b097be0a6 use me daddy 2023-01-16 14:15:56 -06:00
mjn-mixael 9980c3f5c5 funcs and virtvars for SCPUI pause screen 2023-01-16 14:02:01 -06:00
mjn-mixael bd1a288cd9 expose pausing weapon sounds 2023-01-15 21:02:50 -06:00
Goober5000 eca7db0315 allow personas to be used by more than one species 2023-01-12 12:47:12 -05:00
Goober5000 be4d7acb6a change substitute_missing_messages to an actual flag, and add a no automatic assignment flag 2023-01-12 00:49:21 -05:00
Goober5000 02e5cc4353 remove PERSONA_FLAG_VASUDAN, since it is no longer assigned, and fix the -Vas suffix on the personas, which has apparently been broken since the species upgrade 2023-01-11 23:55:28 -05:00
mjn-mixael 481c0a490b address feedback 2023-01-11 08:14:29 -06:00
mjn-mixael 2a5b930941 implement opf_turret_type for turret-protect-ship and turret-unprotect-ship 2023-01-09 11:13:37 -06:00
mjn-mixael 2881482182 fix rendering of jump nodes 2023-01-07 11:11:02 -06:00
mjn-mixael 661732a45b only load the model in the retail ui 2023-01-07 02:23:36 -06:00
mjn-mixael 856997326b some cleanup 2023-01-07 01:49:58 -06:00
mjn-mixael d52c2da8b5 take a break youve earned it 2023-01-07 01:48:39 -06:00
mjn-mixael c6a1639a82 scpui methods required for handling closeup briefing icon stuff 2023-01-07 01:48:39 -06:00
Goober5000 a0181e715d prevent ship from managing ETS if it is playing dead
This was the bug found recently that was thought to be related to #2157.  It turns out that ships will manage ETS even if they are playing dead, which caused a ship to accelerate during a ship-maneuver as it directed more power to engines.  So this PR adds a "$ships playing dead don't manage ETS:" flag to control this behavior.  Tested and works.

This also capitalizes two flags that did not have an initial capital letter.
2023-01-06 03:04:11 -05:00
mjn-mixael dbbd6b7705 Make sexp node comments more visible at a glance 2023-01-04 16:08:10 -06:00
mjn-mixael ae135b4922 mission profiles instead of gameplay profiles 2023-01-04 13:48:16 -06:00
mjn-mixael 9c167b279d throw in -gmp.tbm as optional match to -aip.tbm 2023-01-03 21:25:59 -06:00
mjn-mixael 1884e4c4d1 allow gameplay_profiles.tbl to be an alias of ai_profiles.tbl 2023-01-03 21:21:37 -06:00
mjn-mixael 8cf7796809 Pass shortcut key character to Lua as a hook variable 2023-01-01 18:04:05 -06:00
mjn-mixael 3b3a45d2d8 fix documentation 2022-12-20 16:07:52 -06:00
mjn-mixael 9f1c00c581 allow scripts to read LuaEnums and add LuaEnums 2022-12-20 15:53:40 -06:00
Goober5000 87a051a933 Merge branch 'master' into more_category_updates 2022-12-18 01:31:47 -05:00
Goober5000 7022ba191a ci stuff 2022-12-16 23:03:27 -05:00
Goober5000 8d672bddb3 change SEXP_SRC_* to enum class 2022-12-16 22:10:22 -05:00
Goober5000 dc281a56f8 change SEXP_MODE_* to enum class 2022-12-16 19:45:05 -05:00
Goober5000 7b0a8eff9e change REF_TYPE_* to enum class 2022-12-16 19:41:45 -05:00
Goober5000 d722f50f8b more category updates
1. Allow categories, not just subcategories, to be added by scripted SEXPs.
2. Allow subcategories in different categories to have the same name.
2022-12-13 21:16:26 -05:00
the-maddin ddeb40aa61 checks fix 2022-06-25 00:19:11 +02:00
the-maddin db68e30862 fix qvector error 2022-06-13 23:02:48 +02:00
the-maddin a1fc0907cf unified warning message handling 2022-06-13 01:00:04 +02:00
the-maddin 2c5f52a28d Integrated error checking
numbered to reflect campaigntreewnd.cpp
2022-06-12 02:04:12 +02:00
the-maddin 3d5ae71fc6 Merge remote-tracking branch 'refs/remotes/upstream/master' into qt-campaign-editor 2022-06-04 23:46:34 +02:00
the-maddin 5d0fadba19 doxy 2022-06-04 23:46:16 +02:00
the-maddin 2eb6410de8 Merge branch 'master' into qt-campaign-editor 2022-05-22 22:36:23 +02:00
the-maddin 401a26623a changes z64555 v1.4 2022-05-22 15:17:31 +02:00
the-maddin 9336d7264f changes z64555 v1.3 2022-05-22 14:17:15 +02:00
the-maddin ec3ad17fa2 changes z64555 v1.2 2022-05-09 01:35:15 +02:00
the-maddin d9a9cb5f9d changes z64555 v1.1 2022-05-09 01:34:47 +02:00
the-maddin 0a7ff1bc1a changes jg18 v3 2022-04-29 01:28:37 +02:00
the-maddin e5f80a160a incorporate feedback 2022-04-21 00:32:36 +02:00
the-maddin e3a153ef5b Clarify abbreviations 2022-04-11 23:36:39 +02:00
the-maddin ccf86293ce incorporate feedback 2022-03-29 00:59:59 +02:00
the-maddin f142780b95 clang 2022-03-25 00:55:49 +01:00
the-maddin 48f99e36b0 Merge branch 'master' into qt-campaign-editor 2022-03-25 00:22:45 +01:00
the-maddin 8bf51ff858 fix CheckedDataListModel pointer issue
(cherry picked from commit 3d4c03ede65657c38d5271cd70caa2e0eedef6bf)
2022-03-25 00:15:18 +01:00
the-maddin 84cb7fddba Export campaign model to Campaign struct
(cherry picked from commit 00ca3070063ba9859d316ac5e5da27aa67084561)
2022-03-25 00:15:15 +01:00
the-maddin 566d15dfec Add first mission selection, always keep valid
(cherry picked from commit 961a58a9b6bc261b6d11bf37a90bd457f602edc0)
2022-03-25 00:15:12 +01:00
the-maddin 0d82ca5be2 clang stuff
(cherry picked from commit 3ca042cc115372043527b94156faeb69b542aac7)
2022-03-25 00:15:06 +01:00
the-maddin 4857f320ad Saving part 2: Campaign Specs to Campaign
Move model Campaign Steps to engine campaign
struct

(cherry picked from commit 796eae1a8e003ba9b704692d460f909c20f49970)
2022-03-25 00:15:02 +01:00
the-maddin 636f6933be Ensure correct flags and loop state
(cherry picked from commit 68583f28cffa37a284b236173c29f11bf8ede1c5)
2022-03-25 00:14:58 +01:00
the-maddin a8483c5a8a Saving part 1: Output Campaign to file
Output a Campaign with ordered cmissions to a file,
like it is read.
This version does not depend on any FRED model/
implementation.

(cherry picked from commit c8aa141295de9f45813bc2bb762f3f2290ebad6d)
2022-03-25 00:14:53 +01:00
the-maddin 5eb4c35572 clang msvc
(cherry picked from commit 6faa6d41d87fdca6c9acc24b080451cd3fbfce59)
2021-09-28 22:46:30 +02:00
the-maddin 15752d1729 Integrate branch buttons into context menu
(cherry picked from commit fb986ea29efd7e9612d76e0722733d33a2f95aa3)
2021-09-28 20:23:13 +02:00
the-maddin 413842c84a Branch moving & branch UI misc
(cherry picked from commit 9ecb5b734de149ad85e2ad3c4409a20714b4f96a)
2021-09-28 20:23:13 +02:00
the-maddin e41bde6dad Fix branch sexptree popup menu part 3
(cherry picked from commit 4cd06c05b56518ac92ca0d63203437a7fa38de6c)
2021-09-28 20:23:13 +02:00
the-maddin e37ca8fd8e Model data access fix
(cherry picked from commit
effea261ecb607c09422ec9973522b02821bee6e)
2021-09-28 20:23:13 +02:00
the-maddin e2099271c6 Fix branch sexptree popup menu part 2
(cherry picked from commit 53d5d25c3a21876b3246af3eeff91ded7c37b678)
2021-09-28 20:23:13 +02:00
the-maddin 19817f4cda reorder model impl and lazy init some constants
(cherry picked from commit f2b2385a27b52a2088421c203560309e38444fcd)
2021-09-28 20:23:13 +02:00
the-maddin c41e5c9d7f Always replace corrupted model after load attempt
(cherry picked from commit ed8be26f81e80b72e147ea54b54b7440606e302c)
2021-09-28 20:23:13 +02:00
the-maddin b08109c2fe Fix branch sexptree popup menu part 1
(cherry picked from commit 17319ea5deb48e4ac27af804033dabc5907e781f)
2021-09-28 20:23:13 +02:00
the-maddin 30b484b276 Use AssociatedPlainTextDocument
(cherry picked from commit 5abb00e4382840e04474905f1477121173bd986a)
2021-09-28 20:23:13 +02:00
the-maddin 2989034394 Dialog cleanup
(cherry picked from commit 024be9d0e6d3c447c6b2bc972be4dddc9b31bfc2)
2021-09-28 20:23:13 +02:00
the-maddin eec2ce1713 Model structure and TextEdit cleanup
(cherry picked from commit 306de2da527128583841f0cb73363fb5ca222b16)
2021-09-28 20:23:13 +02:00
the-maddin 439f633364 Add branches & conditions in model
(cherry picked from commit 730bf0d9d5ff55b1b0e99c73c79ce12e5af67d48)
2021-09-28 20:23:13 +02:00
the-maddin 458d2f5e12 custom mission selection & linking context menu
(cherry picked from commit 31d2b9d0e02c803fa06b369772d754da70187c3c)
2021-09-28 20:23:13 +02:00
the-maddin 2f361340fc Parse eligible & campaign missions for event names
(cherry picked from commit 62a6ae9f6fc8cb7955b7804aeb951564c5bd3bd0)
2021-09-28 20:23:13 +02:00
the-maddin 41d65630f8 validate and use current branch index
(cherry picked from commit 072796d1f76325ec5e9be38c899951420d3ea781)
2021-09-28 20:23:13 +02:00
the-maddin 5e57094f8e Merge branch 'master' into qt-campaign-editor 2021-09-19 14:27:07 +02:00
the-maddin ae9b604f44 Merge branch 'master' into qt-campaign-editor 2021-06-29 23:31:08 +02:00
the-maddin 8db39a6c61 WIP note
(cherry picked from commit fdd2b54af8c4a9ca7f1370dfba09f277a78edc3c)
2021-06-29 23:27:58 +02:00
the-maddin ec84c7183e comboBox tweak
(cherry picked from commit cf0232f33f20b27ffa03ff2ee4ed6590822f149c)
2021-06-29 23:27:54 +02:00
the-maddin 16a5b1ccc7 Improve mission list robustness 2021-06-29 01:14:11 +02:00
the-maddin 856726d000 pick pulled model changes 2021-06-29 01:14:07 +02:00
the-maddin dd2c5a22a4 Comboboxes for loop brief & anim
also cmbBox cleanup
2021-06-29 01:12:35 +02:00
the-maddin b97129da86 Cleanup mission list loading, drop mission object 2021-06-29 01:10:56 +02:00
the-maddin a7badba0d8 cleanup 2021-06-29 01:10:52 +02:00
the-maddin 93a1f3e6b4 Use finer UI update control instead of modelChanged 2021-06-29 01:10:29 +02:00
the-maddin b19399021d load and display loop data 2021-06-29 01:08:38 +02:00
the-maddin c95fe1c9d1 clang
(cherry picked from commit 488dcdb1cc762d51826409df6d239fbad978a1e6)
2021-06-20 12:54:51 +02:00
the-maddin f405496791 Clang-tidy fixes 2021-06-20 01:21:32 +02:00
the-maddin 33b63e5b6c Implement FRED-Mission button 2021-06-20 00:56:10 +02:00
the-maddin b64bd789b6 Some more clang fixes 2021-06-20 00:56:10 +02:00
the-maddin 9011319e2f Use new CheckedDataListModel 2021-06-20 00:56:10 +02:00
the-maddin 3fd825b1de SaveAs shortcut 2021-06-20 00:56:10 +02:00
the-maddin b21d380240 Handle branch tree selection 2021-06-20 00:56:10 +02:00
the-maddin c2e8ba9fa6 Use campaign branch sexp_tree and load formulas 2021-06-20 00:56:10 +02:00
the-maddin 61fb9c5dd1 CMission Data: use combo boxes where possible 2021-06-20 00:56:10 +02:00
the-maddin f7ecb85df6 CampaignMissionData: load cmission, display
editable cmission data

Also make CheckedDataList construction translator
callbacks explicitly const.
2021-06-20 00:56:10 +02:00
the-maddin 144ae46ccc model initialisation cleanup 2021-06-20 00:56:10 +02:00
the-maddin 1a81682472 Show player number of multi campaigns
according to first mission.
2021-06-20 00:56:10 +02:00
the-maddin 3349c99a0a Clean up data entry widget signalling 2021-06-20 00:56:10 +02:00
the-maddin 6e2723a313 Update widgets on mission selection change 2021-06-20 00:56:10 +02:00
the-maddin 9241c49f32 Warn before dropping unloadable missionDropped
because it won't be shown for re-selection after
next load of campaign
2021-06-20 00:56:10 +02:00
the-maddin 80fc7a5cbf gcc11: add missing include
(cherry picked from commit 9959cdad5535abf56a156f1924d260a64e688d57)
2021-06-20 00:56:10 +02:00
the-maddin ca982fa1ae Immutable campaignType, file load & menu changes
Since the campaign type determines the compatible
missions, changing it would require invalidating
the mission list. So I'm restricting it to being
set on campaign creation.
2021-06-20 00:56:10 +02:00
the-maddin 20fc9d629c Create available mission list
Unlike FRED, I'm using a checked list of all
missions, not a simple list of the unused ones.
I'm showing uneditable / packaged missions
in yellow, missing / unloadable missions in red.
Also keeping missions loaded.
2021-06-20 00:56:10 +02:00
the-maddin 881f47670c Use CheckedDataListModel improvements
Make necessary changes and improvements
in model usage.
2021-06-20 00:56:10 +02:00
the-maddin 54a64cb91e Deal with windows filenames in CFile
(cherry picked from commit 0ed5a18fd9883166bbef8360ae9f2cfed3ae7f69)
2021-06-20 00:56:10 +02:00
the-maddin 232eb2a099 Allow full-length paths for campaign files
so qtfred can load them fro outside the cfile tree.
2021-06-20 00:56:10 +02:00
the-maddin fc65df048f Register initial... lists changes 2021-05-06 00:48:37 +02:00
the-maddin f2cfac14b3 Fix compile issue, correct reload behaviour 2021-05-06 00:37:10 +02:00
the-maddin 5cbe64c793 Implement initial ships/weapons lists, intialize
model by loading campaign file
2021-05-06 00:03:15 +02:00
the-maddin e2b9a5a1a2 Initial campaign loading & trivial uiUpdate
functionality
2021-05-06 00:03:08 +02:00
the-maddin da83c3aa41 Tie campaignmodel to campaign file, use QStrings in
model

String conversion should happen on load/save, not
every UI update/cahnge
2021-05-06 00:02:58 +02:00
the-maddin 30237c8988 initial updateUI, explicit model modification
flagging
2021-05-06 00:02:56 +02:00
the-maddin ca23d30c99 File ops UI logic, cleanup 2021-05-06 00:02:43 +02:00
the-maddin 53e30ba771 Connect some more signals/slots 2021-05-06 00:00:46 +02:00
the-maddin c4f84ea9f5 alternative layout 2021-05-05 23:58:50 +02:00
the-maddin 7acd4c6491 sync changes to model (initial) 2021-05-05 23:58:50 +02:00
the-maddin 04c136f59e add model with initial functionality 2021-05-05 23:58:50 +02:00
the-maddin 3768473270 Add more slots 2021-05-05 23:58:50 +02:00
the-maddin 52427a7ec3 Add initial CampaignEditorDialog
ui with most basic functionality
2021-05-05 23:58:50 +02:00
690 changed files with 53614 additions and 95321 deletions

No files matched your search

-8
View File
@@ -1,14 +1,6 @@
cmake/ @asarium
ci/ @asarium @z64555
code/executor/ @asarium
code/scpui/ @asarium
code/scripting/ @asarium
code/controlconfig/ @z64555
code/model/modelanimation*.* @bmagnu
+42 -12
View File
@@ -15,7 +15,7 @@ jobs:
configuration: [FastDebug, Release]
name: Linux
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/linux_build:sha-8a6bbbe
container: ghcr.io/scp-fs2open/linux_build:sha-3d30dc5
steps:
# - name: Cache Qt
# id: cache-qt-lin
@@ -31,11 +31,16 @@ jobs:
# cached: ${{ steps.cache-qt-lin.outputs.cache-hit }}
# setup-python: 'false'
# aqtversion: ==1.1.3
- uses: actions/checkout@v1
name: Checkout
with:
submodules: true
- 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
env:
CONFIGURATION: ${{ matrix.configuration }}
@@ -133,7 +138,12 @@ jobs:
# arch: win64_msvc2017_64
# cached: ${{ steps.cache-qt-win.outputs.cache-hit }}
# aqtversion: ==0.8
- 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
env:
CONFIGURATION: ${{ matrix.configuration }}
@@ -144,11 +154,19 @@ jobs:
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DFSO_USE_SPEECH="ON" \
-DFSO_USE_VOICEREC="ON" -DMSVC_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_BUILD_QTFRED=OFF -DFSO_BUILD_TESTS=ON \
-DFSO_INSTALL_DEBUG_FILES="ON" -A "$ARCHITECTURE" \
-G "Visual Studio 16 2019" -T "v142" ..
if [ "$ARCHITECTURE" = "Win32" ]; then
cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DFSO_USE_SPEECH="ON" \
-DFSO_USE_VOICEREC="ON" -DMSVC_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_BUILD_QTFRED=OFF -DFSO_BUILD_TESTS=ON \
-DFSO_INSTALL_DEBUG_FILES="ON" -DFSO_BUILD_WITH_VULKAN="OFF" -A "$ARCHITECTURE" \
-G "Visual Studio 16 2019" -T "v142" ..
else
cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DFSO_USE_SPEECH="ON" \
-DFSO_USE_VOICEREC="ON" -DMSVC_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_BUILD_QTFRED=OFF -DFSO_BUILD_TESTS=ON \
-DFSO_INSTALL_DEBUG_FILES="ON" -A "$ARCHITECTURE" \
-G "Visual Studio 16 2019" -T "v142" ..
fi
- name: Compile
working-directory: ./build
env:
@@ -235,12 +253,17 @@ jobs:
# setup-python: 'false'
# aqtversion: ==1.1.3
# py7zrversion: '==0.19.*'
- uses: actions/checkout@v1
name: Checkout
with:
submodules: true
fetch-depth: 0
- 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: Set up test version
shell: bash
run: |
@@ -264,13 +287,15 @@ jobs:
XDG_RUNTIME_DIR: /root
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
- name: Package build result
working-directory: ./build
run: cd bin && tar -cvzf macos-build.tar *.app
working-directory: ./build/bin
# Use GNU tar here (part of runner image) to avoid weird corruption bug with bsdtar
# Ref: https://github.com/actions/runner-images/issues/2619
run: gtar -cvzf macos-build-${{ matrix.configuration }}.tgz *.app
- name: Upload build result
uses: actions/upload-artifact@v2
with:
name: mac-${{ matrix.configuration }}
path: ${{ github.workspace }}/build/bin/macos-build.tar
path: ${{ github.workspace }}/build/bin/macos-build-${{ matrix.configuration }}.tgz
mac_zip:
name: Build Mac distribution zip
needs: build_mac
@@ -293,6 +318,11 @@ jobs:
with:
name: mac-FastDebug
path: builds
- name: Unpack builds
working-directory: ./builds
run: |
tar -xvzf macos-build-Release.tgz
tar -xvzf macos-build-FastDebug.tgz
- name: Create Distribution package
working-directory: ./builds
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Mac
+47 -13
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-8a6bbbe
container: ghcr.io/scp-fs2open/linux_build:sha-3d30dc5
steps:
# - name: Cache Qt
# id: cache-qt-lin
@@ -87,12 +87,18 @@ jobs:
# cached: ${{ steps.cache-qt-lin.outputs.cache-hit }}
# setup-python: 'false'
# aqtversion: ==1.1.3
- uses: actions/checkout@v1
# checks-out your repository under $GITHUB_WORKSPACE, so your workflow can access it.
name: Checkout
with:
submodules: true # `true` to checkout submodules, `recursive` to recursively checkout submodules
ref: '${{ github.ref }}'
- name: Prepare Vulkan SDK
uses: humbletim/[email protected]
with:
vulkan-query-version: 1.3.204.0
vulkan-components: Vulkan-Headers, Vulkan-Loader
vulkan-use-cache: true
- name: Configure CMake
env:
CONFIGURATION: ${{ matrix.configuration }}
@@ -140,6 +146,7 @@ jobs:
with:
submodules: true
fetch-depth: '0' # value 0 to fetch all history and tags for all branches
ref: '${{ github.ref }}'
- name: Download Release builds
# Grab the release builds
uses: actions/download-artifact@v2
@@ -186,6 +193,7 @@ jobs:
name: Checkout
with:
submodules: true
ref: '${{ github.ref }}'
# - name: Cache Qt
# # Cache Qt
# id: cache-qt-win
@@ -213,7 +221,12 @@ jobs:
# arch: win64_msvc2017_64
# cached: ${{ steps.cache-qt-win.outputs.cache-hit }}
# aqtversion: ==0.8
- 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
env:
CONFIGURATION: ${{ matrix.configuration }}
@@ -224,11 +237,19 @@ jobs:
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DFSO_USE_SPEECH="ON" \
-DFSO_USE_VOICEREC="ON" -DMSVC_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_BUILD_QTFRED=OFF -DFSO_BUILD_TESTS=ON \
-DFSO_INSTALL_DEBUG_FILES="ON" -A "$ARCHITECTURE" \
-G "Visual Studio 16 2019" -T "v142" ..
if [ "$ARCHITECTURE" = "Win32" ]; then
cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DFSO_USE_SPEECH="ON" \
-DFSO_USE_VOICEREC="ON" -DMSVC_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_BUILD_QTFRED=OFF -DFSO_BUILD_TESTS=ON \
-DFSO_INSTALL_DEBUG_FILES="ON" -DFSO_BUILD_WITH_VULKAN="OFF" -A "$ARCHITECTURE" \
-G "Visual Studio 16 2019" -T "v142" ..
else
cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DFSO_USE_SPEECH="ON" \
-DFSO_USE_VOICEREC="ON" -DMSVC_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_BUILD_QTFRED=OFF -DFSO_BUILD_TESTS=ON \
-DFSO_INSTALL_DEBUG_FILES="ON" -A "$ARCHITECTURE" \
-G "Visual Studio 16 2019" -T "v142" ..
fi
- name: Compile
working-directory: ./build
env:
@@ -267,7 +288,7 @@ jobs:
with:
submodules: true
fetch-depth: '0'
ref: '${{ github.ref }}'
- name: Download Release builds
uses: actions/download-artifact@v2
with:
@@ -334,12 +355,18 @@ jobs:
# cached: ${{ steps.cache-qt-mac.outputs.cache-hit }}
# setup-python: 'false'
# aqtversion: ==1.1.3
- uses: actions/checkout@v1
name: Checkout
with:
submodules: true
fetch-depth: 0
ref: '${{ github.ref }}'
- 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
env:
CONFIGURATION: ${{ matrix.configuration }}
@@ -357,13 +384,15 @@ jobs:
XDG_RUNTIME_DIR: /root
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
- name: Package build result
working-directory: ./build
run: cd bin && tar -cvzf macos-build.tar *.app
working-directory: ./build/bin
# Use GNU tar here (part of runner image) to avoid weird corruption bug with bsdtar
# Ref: https://github.com/actions/runner-images/issues/2619
run: gtar -cvzf macos-build-${{ matrix.configuration }}.tgz *.app
- name: Upload build result
uses: actions/upload-artifact@v2
with:
name: mac-${{ matrix.configuration }}
path: ${{ github.workspace }}/build/bin/macos-build.tar
path: ${{ github.workspace }}/build/bin/macos-build-${{ matrix.configuration }}.tgz
mac_zip:
name: Build Mac distribution zip
needs: build_mac
@@ -386,6 +415,11 @@ jobs:
with:
name: mac-FastDebug
path: builds
- name: Unpack builds
working-directory: ./builds
run: |
tar -xvzf macos-build-Release.tgz
tar -xvzf macos-build-FastDebug.tgz
- name: Create Distribution package
id: generate_package
working-directory: ./builds
+6
View File
@@ -24,6 +24,12 @@ jobs:
name: Checkout
with:
submodules: true
- 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: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
+42 -12
View File
@@ -15,7 +15,7 @@ jobs:
configuration: [FastDebug, Release]
name: Linux
runs-on: ubuntu-latest
container: ghcr.io/scp-fs2open/linux_build:sha-8a6bbbe
container: ghcr.io/scp-fs2open/linux_build:sha-3d30dc5
steps:
# - name: Cache Qt
# id: cache-qt-lin
@@ -31,7 +31,6 @@ jobs:
# cached: ${{ steps.cache-qt-lin.outputs.cache-hit }}
# setup-python: 'false'
# aqtversion: ==1.1.3
- uses: actions/checkout@v1
name: Checkout
with:
@@ -42,6 +41,12 @@ jobs:
[[ "${{ github.ref }}" =~ ^refs\/heads\/test\/(.*)$ ]]
# Override the revision string so that the builds are named correctly
echo "set(FSO_VERSION_REVISION_STR ${BASH_REMATCH[1]})" > "version_override.cmake"
- 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
env:
CONFIGURATION: ${{ matrix.configuration }}
@@ -146,7 +151,12 @@ jobs:
# arch: win64_msvc2017_64
# cached: ${{ steps.cache-qt-win.outputs.cache-hit }}
# aqtversion: ==0.8
- 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
env:
CONFIGURATION: ${{ matrix.configuration }}
@@ -157,11 +167,19 @@ jobs:
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DFSO_USE_SPEECH="ON" \
-DFSO_USE_VOICEREC="ON" -DMSVC_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_BUILD_QTFRED=OFF -DFSO_BUILD_TESTS=ON \
-DFSO_INSTALL_DEBUG_FILES="ON" -A "$ARCHITECTURE" \
-G "Visual Studio 16 2019" -T "v142" ..
if [ "$ARCHITECTURE" = "Win32" ]; then
cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DFSO_USE_SPEECH="ON" \
-DFSO_USE_VOICEREC="ON" -DMSVC_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_BUILD_QTFRED=OFF -DFSO_BUILD_TESTS=ON \
-DFSO_INSTALL_DEBUG_FILES="ON" -DFSO_BUILD_WITH_VULKAN="OFF" -A "$ARCHITECTURE" \
-G "Visual Studio 16 2019" -T "v142" ..
else
cmake -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DFSO_USE_SPEECH="ON" \
-DFSO_USE_VOICEREC="ON" -DMSVC_SIMD_INSTRUCTIONS="$SIMD" \
-DFSO_BUILD_QTFRED=OFF -DFSO_BUILD_TESTS=ON \
-DFSO_INSTALL_DEBUG_FILES="ON" -A "$ARCHITECTURE" \
-G "Visual Studio 16 2019" -T "v142" ..
fi
- name: Compile
working-directory: ./build
env:
@@ -249,12 +267,17 @@ jobs:
# setup-python: 'false'
# aqtversion: ==1.1.3
# py7zrversion: '==0.19.*'
- uses: actions/checkout@v1
name: Checkout
with:
submodules: true
fetch-depth: 0
- 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: Set up test version
shell: bash
run: |
@@ -277,13 +300,15 @@ jobs:
XDG_RUNTIME_DIR: /root
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
- name: Package build result
working-directory: ./build
run: cd bin && tar -cvzf macos-build.tar *.app
working-directory: ./build/bin
# Use GNU tar here (part of runner image) to avoid weird corruption bug with bsdtar
# Ref: https://github.com/actions/runner-images/issues/2619
run: gtar -cvzf macos-build-${{ matrix.configuration }}.tgz *.app
- name: Upload build result
uses: actions/upload-artifact@v2
with:
name: mac-${{ matrix.configuration }}
path: ${{ github.workspace }}/build/bin/macos-build.tar
path: ${{ github.workspace }}/build/bin/macos-build-${{ matrix.configuration }}.tgz
mac_zip:
name: Build Mac distribution zip
needs: build_mac
@@ -306,6 +331,11 @@ jobs:
with:
name: mac-FastDebug
path: builds
- name: Unpack builds
working-directory: ./builds
run: |
tar -xvzf macos-build-Release.tgz
tar -xvzf macos-build-FastDebug.tgz
- name: Create Distribution package
working-directory: ./builds
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Mac
+1 -1
View File
@@ -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-8a6bbbe
container: ghcr.io/scp-fs2open/linux_build:sha-3d30dc5
steps:
# - name: Cache Qt
# id: cache-qt-lin
+81
View File
@@ -0,0 +1,81 @@
name: Weekly Coverity Scan for Freespace Open
# adapted from code by "albert-github" on the doxygen repository
# many thanks for figuring this out first so it could be less painful for us!
# This mode is for testing
on: [push, pull_request]
# In production, push on a specific schedule
#on:
# schedule:
# - cron: "1 0 * * 5" # Run once per a week on Friday morning (midnight UTC, 4 AM EST), to avoid Coverity's submission limits
env:
QT_VERSION: 5.12.9
coverity_email: [email protected]
coverity_token: ${{ secrets.COVERITY_TOKEN }}
jobs:
build:
name: Build FSO With Coverity Wrapper
runs-on: ${{ matrix.config.os }}
strategy:
fail-fast: false
matrix:
config:
- { name: "GCC on ubuntu", os: ubuntu-latest, build_type: "Release" }
steps:
- name: Install Dependencies
run: |
sudo apt-get install ninja-build
sudo apt install cmake libsdl2-dev g++
sudo apt-get install libopenal-dev
sudo apt-get install -y libudev-dev
sudo apt-get install doxygen
sudo apt install graphviz
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive # `true` to checkout submodules, `recursive` to recursively checkout submodules
# pipe results of wget to a log file because it's very verbose and rarely fails
- name: Install Coverity
run: |
wget -o wgetlog.txt -q https://scan.coverity.com/download/cxx/linux64 --post-data "token=${{ env.coverity_token }}&project=scp-fs2open/fs2open.github.com" -O coverity_tool.tgz
mkdir cov-scan
tar ax -f coverity_tool.tgz --strip-components=1 -C cov-scan
- name: Setup Environment
run: |
echo "$(pwd)/cov-scan/bin" >> $GITHUB_PATH
echo "NPROC=$(getconf _NPROCESSORS_ONLN)" >> $GITHUB_ENV
- name: Prepare Vulkan SDK
uses: humbletim/[email protected]
with:
vulkan-query-version: 1.3.204.0
vulkan-components: Vulkan-Headers, Vulkan-Loader
vulkan-use-cache: true
- name: Configure CMake for FSO
env:
CONFIGURATION: Release
compiler: gcc-5
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
- name: Build FSO with Coverity Wrapper
working-directory: ./build
env:
CONFIGURATION: Release
run: cov-build --dir cov-int ninja -k 20 all
- name: Compress Results
working-directory: ./build
run: tar zcf cov-scan.tgz cov-int
#Comment this out when testing to keep from running into upload limits
- name: Upload to Coverity
run: |
cd build
curl --form token=${{ env.coverity_token }} --form email=${{ env.coverity_email }} --form [email protected] --form version="$(git rev-parse HEAD)" --form description="Automatic GHA scan" 'https://scan.coverity.com/builds?project=scp-fs2open/fs2open.github.com'
+36 -12
View File
@@ -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-8a6bbbe
container: ghcr.io/scp-fs2open/linux_build:sha-3d30dc5
steps:
# - name: Cache Qt
# id: cache-qt-lin
@@ -38,7 +38,6 @@ jobs:
# cached: ${{ steps.cache-qt-lin.outputs.cache-hit }}
# setup-python: 'false'
# aqtversion: ==1.1.3
- uses: actions/checkout@v1
name: Checkout
with:
@@ -48,7 +47,12 @@ jobs:
uses: hendrikmuhs/ccache-action@v1
with:
key: ${{ runner.os }}-${{ matrix.configuration }}-${{ matrix.compiler }}
- 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
env:
CONFIGURATION: ${{ matrix.configuration }}
@@ -113,7 +117,12 @@ jobs:
# arch: win64_msvc2017_64
# cached: ${{ steps.cache-qt-win.outputs.cache-hit }}
# aqtversion: ==0.8
- 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
env:
CONFIGURATION: ${{ matrix.configuration }}
@@ -125,12 +134,23 @@ jobs:
cd build
if [ "$COMPILER" = "MinGW" ]; then
cmake -DFSO_USE_SPEECH="OFF" -DFSO_FATAL_WARNINGS="ON" -DFSO_USE_VOICEREC="OFF" -DFSO_BUILD_TESTS="ON" \
-DFSO_BUILD_FRED2="OFF" -DCMAKE_BUILD_TYPE=$CONFIGURATION -G "Ninja" ..
if [ "$ARCHITECTURE" = "Win32" ]; then
cmake -DFSO_USE_SPEECH="OFF" -DFSO_FATAL_WARNINGS="ON" -DFSO_USE_VOICEREC="OFF" -DFSO_BUILD_TESTS="ON" \
-DFSO_BUILD_FRED2="OFF" -DFSO_BUILD_WITH_VULKAN="OFF" -DCMAKE_BUILD_TYPE=$CONFIGURATION -G "Ninja" ..
else
cmake -DFSO_USE_SPEECH="OFF" -DFSO_FATAL_WARNINGS="ON" -DFSO_USE_VOICEREC="OFF" -DFSO_BUILD_TESTS="ON" \
-DFSO_BUILD_FRED2="OFF" -DCMAKE_BUILD_TYPE=$CONFIGURATION -G "Ninja" ..
fi
else
cmake -DFSO_USE_SPEECH="ON" -DFSO_FATAL_WARNINGS="ON" -DFSO_USE_VOICEREC="OFF" -DFSO_BUILD_TESTS="ON" \
-DMSVC_SIMD_INSTRUCTIONS=SSE2 -DFSO_BUILD_FRED2="ON" -G "Visual Studio 16 2019" \
-DFSO_BUILD_QTFRED=OFF -T "v142" -A "$ARCHITECTURE" ..
if [ "$ARCHITECTURE" = "Win32" ]; then
cmake -DFSO_USE_SPEECH="ON" -DFSO_FATAL_WARNINGS="ON" -DFSO_USE_VOICEREC="OFF" -DFSO_BUILD_TESTS="ON" \
-DMSVC_SIMD_INSTRUCTIONS=SSE2 -DFSO_BUILD_FRED2="ON" -DFSO_BUILD_WITH_VULKAN="OFF" -G "Visual Studio 16 2019" \
-DFSO_BUILD_QTFRED=OFF -T "v142" -A "$ARCHITECTURE" ..
else
cmake -DFSO_USE_SPEECH="ON" -DFSO_FATAL_WARNINGS="ON" -DFSO_USE_VOICEREC="OFF" -DFSO_BUILD_TESTS="ON" \
-DMSVC_SIMD_INSTRUCTIONS=SSE2 -DFSO_BUILD_FRED2="ON" -G "Visual Studio 16 2019" \
-DFSO_BUILD_QTFRED=OFF -T "v142" -A "$ARCHITECTURE" ..
fi
fi
- name: Compile
working-directory: ./build
@@ -182,7 +202,6 @@ jobs:
# setup-python: 'false'
# aqtversion: ==1.1.3
# py7zrversion: '==0.19.*'
- uses: actions/checkout@v1
name: Checkout
with:
@@ -192,7 +211,12 @@ jobs:
uses: hendrikmuhs/ccache-action@v1
with:
key: ${{ runner.os }}-${{ matrix.configuration }}-${{ matrix.compiler }}
- 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
env:
CONFIGURATION: ${{ matrix.configuration }}
@@ -217,4 +241,4 @@ jobs:
if: startsWith(matrix.compiler, 'clang-')
uses: asarium/clang-tidy-action@v1
with:
fixesFile: clang-fixes.yaml
fixesFile: clang-fixes.yaml
+1
View File
@@ -250,6 +250,7 @@ documentation/doxygen/*
projects/*
/.vs
CMakeSettings.json
CMakePresets.json
# Weird files created by Linux
.fuse_hidden*
-175
View File
@@ -1,175 +0,0 @@
language: bash
sudo: required
dist: xenial
cache:
directories:
- $HOME/cmake-3.8
- $HOME/.ccache
- $HOME/curl_cache
addons:
apt:
packages: &global_deps
- ninja-build
- libopenal-dev
- libreadline6-dev
- libpng12-dev
- libjpeg62-dev
- liblua5.1-0-dev
- libjansson-dev
- libsdl2-dev
- libfreetype6-dev
- qt57base
coverity_scan:
project:
name: "scp-fs2open/fs2open.github.com"
notification_email: [email protected]
build_command: "ci/travis/script.sh"
# must match TRAVIS_BRANCH check below
branch_pattern: coverity_scan
env:
global:
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
# via the "travis encrypt" command using the project repo's public key
# also note that fork's don't get access to secure keys
# you have to test using a branch in the main repo
- secure: "C3wF967ZeliwwP1vC12EMIBOaC568n26Z/cPnwzn317ve59DWH3YSfPZVgvt08GzmaXITGGsJvPB+qxfGoKvQzYE4O1B73q81RpUe5pB3IhF+ThQ91VfQZIRJR5xEGJaLINUlHTTZGX5jxlkVO9wAcauVj/s3b8sQ3dvUZauPvk="
# These declarations set INDIEGAMES_USER and INDIEGAMES_PASSWORD for uploading nightly builds to the indiegames server
- secure: "lUuRu8XIi8MKNf1ebOfyC4iVEpPyASojJIDWXRo2bNqEF4ILAljXdkVeXeN6H5yKCHD52cxCNTtyePIG/o3p3QEuGSVud9bDS3D7LaQicLETGGrsw3l07U49gF2OKHXGopg0MzBbZUU9QmhoFTAe8t6PV9NDuEayYCheqvTqjZg="
- secure: "E/DHLYcPK/hBUqxBYYlUqp5sjgvIqY5A0qRHyQ4bmjsB+WB/Xx71bGCSiF7hk6lTxar1ZI1i5RAXXh9AIvNVaYAIdEOlCP+q3gvwCYuc5naZEKmkxlUCf0oEL4O9Fye93A/3VkFHuBdC1TGPYYf69m4W5r4367wWO9dPRIdWpJA="
# These declarations set DATACORDER_USER and DATACORDER_PASSWORD
- secure: "dpBH/dDN3bmU/NFlh+2v9isNx9wX0ocoRy+W+kBXRH32sosUGp26REhMqgVRpBNP5oxPBU8ic5bEogxAYWCB+0xUygBbkxAwyMPgoA34s0OXdTCY/ofw14ni8qqV2Ffy7fQJbP/jkMURyiMHx3kBTxNv3YjxKJqLnOuOMlQLpT8="
- secure: "tLMRBD1Ufp5iKNwlqPDVbbuczgusaXNoBJyAnPATpJq2YwlkW4j3PqP9rW5vd85+52xam2EOP20w9PoBR5J6FLdiXRu4Lf7yCEhSHFAgowVqQj8QcJpPlyXr90bM4emFGrGqpdxVwxyQ5AFhKwLuEZKsI14GYLN+UMEwpNCMing="
deploy:
- provider: releases
api_key:
secure: "q619+eQTe7lv8UVphK4OIzU8Jw84KBbVkuprN2sWIubRcV3IbZr2+WahJoUMt+nyhiy3YjDYtstO2ZgkxupwnZgwGUBVIiD1c4SPuyy+HTjNMOtiVsEUHT2hf+xPAemWpTlK5HcwhMmHAOh6rt6dEj57QOg0gcmGiwD/tCbEriA="
skip_cleanup: true
file_glob: true
file: "/tmp/builds/*"
on:
condition: '"$RELEASE_BUILD" == true'
tags: true
- provider: script
script: bash ci/travis/ftp_deploy.sh
on:
condition: '"$NIGHTLY_BUILD" == true'
tags: true
- provider: script
skip_cleanup: true
script: bash ci/travis/ftp_deploy.sh
on:
condition: $TEST_BUILD = true
all_branches: true
matrix:
include:
# note that gcc Debug MUST be 1st for Coverity
- os: linux
env: CONFIGURATION="Debug" CC=gcc-5 CXX=g++-5
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:beineri/opt-qt571-xenial'
packages:
- *global_deps
- g++-5
- os: linux
env: CONFIGURATION="Debug" CC=gcc-9 CXX=g++-9
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:beineri/opt-qt571-xenial'
packages:
- g++-9
- *global_deps
- os: linux
env: CONFIGURATION="Debug" CC=clang-9 CXX=clang++-9 CMAKE_OPTIONS="-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:beineri/opt-qt571-xenial'
packages:
- *global_deps
- g++-9
script:
- ./ci/travis/script.sh
- ./ci/travis/clang_tidy.sh
- os: osx
env: CONFIGURATION="Debug"
- os: windows
env: CONFIGURATION="Debug" CMAKE_TOOLSET=v141 CMAKE_GENERATOR="Visual Studio 15 2017"
- os: windows
env: CONFIGURATION="Debug" CMAKE_TOOLSET="" CMAKE_GENERATOR="Ninja"
- os: linux
env: CONFIGURATION="Release" CC=gcc-5 CXX=g++-5
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:beineri/opt-qt571-xenial'
packages:
- *global_deps
- g++-5
- os: linux
env: CONFIGURATION="Release" CC=gcc-9 CXX=g++-9
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:beineri/opt-qt571-xenial'
packages:
- g++-9
- *global_deps
- os: linux
env: CONFIGURATION="Release" CC=clang-9 CXX=clang++-9 CMAKE_OPTIONS="-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:beineri/opt-qt571-xenial'
packages:
- *global_deps
- g++-9
script:
- ./ci/travis/script.sh
- ./ci/travis/clang_tidy.sh
- os: osx
env: CONFIGURATION="Release"
- os: windows
env: CONFIGURATION="Release" CMAKE_TOOLSET=v141 CMAKE_GENERATOR="Visual Studio 15 2017"
- os: windows
env: CONFIGURATION="Release" CMAKE_TOOLSET="" CMAKE_GENERATOR="Ninja"
# There is a GCC compiler bug with MinGW that causes compilation failures on Windows at the moment
allow_failures:
- os: windows
env: CONFIGURATION="Debug" CMAKE_TOOLSET="" CMAKE_GENERATOR="Ninja"
- os: windows
env: CONFIGURATION="Release" CMAKE_TOOLSET="" CMAKE_GENERATOR="Ninja"
fast_finish: true
before_install:
# ugly hack; if running a coverity scan abort all except the 1st build
# see note re gcc compiler above needing to be 1st
# also note that branch_pattern & the TRAVIS_BRANCH check must match
# unfortunately COVERITY_SCAN_BRANCH isn't defined until later in the
# build process
- if ([[ "${TRAVIS_JOB_NUMBER##*.}" != "1" ]] && [[ "${TRAVIS_BRANCH}" == "coverity_scan" ]]); then false ; fi
- source "./ci/travis/check_release.sh"
- "./ci/travis/before_install.sh"
install:
- if [ "$TRAVIS_OS_NAME" = "windows" ]; then export PATH="/c/Program Files/CMake/bin":$PATH; fi
- "./ci/travis/install.sh"
- export PATH=$HOME/cmake-3.6/bin:$PATH
before_script:
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then QT_ENV_SCRIPT=$(find /opt -name 'qt*-env.sh'); source $QT_ENV_SCRIPT; fi
- "./ci/travis/before_script.sh"
script:
- if [ "$BUILD_DEPLOYMENT" = true ] ; then ./ci/travis/release.sh ; else ./ci/travis/script.sh ; fi
+3 -1
View File
@@ -137,8 +137,9 @@ option(FSO_RELEASE_LOGGING "Enable logging output for release builds" OFF)
OPTION(FSO_BUILD_WITH_FFMPEG "Enable the usage of FFmpeg for sound and custscenes" ON)
OPTION(FSO_BUILD_WITH_OPENGL "Enable compilation of the OpenGL renderer" ON)
OPTION(FSO_BUILD_WITH_OPENGL_DEBUG "Enables debug option for OpenGL" OFF)
OPTION(FSO_BUILD_WITH_VULKAN "Enable compilation of the Vulkan renderer" ON)
OPTION(FSO_BUILD_WITH_VULKAN "Enable compilation of the Vulkan renderer" OFF)
MARK_AS_ADVANCED(FORCE FSO_CMAKE_DEBUG)
MARK_AS_ADVANCED(FORCE FSO_BUILD_INCLUDED_LIBS)
@@ -151,6 +152,7 @@ mark_as_advanced(FORCE ENABLE_COTIRE)
mark_as_advanced(FORCE FSO_RELEASE_LOGGING)
mark_as_advanced(FORCE FSO_BUILD_WITH_FFMPEG)
mark_as_advanced(FORCE FSO_BUILD_WITH_OPENGL)
mark_as_advanced(FORCE FSO_BUILD_WITH_OPENGL_DEBUG)
mark_as_advanced(FORCE FSO_BUILD_WITH_VULKAN)
# Include cotire file from https://github.com/sakra/cotire/
+179
View File
@@ -3,6 +3,185 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [23.2.0] - 2023-06-16
### Changes
<details><summary> <b>Big Feature: MSAA</b> </summary>
> The return of a long forgotten feature, with optimizations and improvements
> Noticeable reduction to artifacts caused by subpixel geometry and glinting.
</details>
<details><summary> <b>Big Feature: SCPUI</b> </summary>
> A modernized approach to defining menus in FS
> Tired of having your Menus in FSO be at a resolution of potato? Use SCPUI to have them rendered from Fake-HTML to the actual screensize as opposed to a prebuilt graphics!
> Tired of being limited to whatever people in the SCP hardcoded in for buttons? Use SCPUI to define buttons and all other manner of shenanigans as Lua-code just as you like.
> Tired of needing to replace a bajillion interface graphics to reskin FSO? Use SCPUI, and especially Mjn's existing collection of Lua, CSS, Fake-HTML and images, and you only need to replace about 250 graphics.
</details>
<details><summary> <b>Big Feature: Localized Volumetric Nebulae</b> </summary>
> Allows specifying a POF as the "hull" of a nebula, which will be rendered using ray marching
> Further details can be found on the [GitHub Pull Request](https://github.com/scp-fs2open/fs2open.github.com/pull/5231)
> Note: As this is a new feature, many improvements and optimizations remain to be made
> Adapted from Andrew Schneider's 2015 SIGGRAPH talk "The real-time volumetric cloudscapes of Horizon: Zero Dawn"
</details>
<details><summary>Game: </summary>
- Per bank autoaim
</details>
<details><summary>Animation: </summary>
- Fix CTD on bad legacy animation data
- Add proper time wrapping for Animations
- Actually handle a mssing `Fade_anim` properly
</details>
<details><summary>Controls: </summary>
- Organize and map additional keys to librocket
- Catch when SDL fails to open a joystick that is enumerated by the OS
</details>
<details><summary>FRED: </summary>
- Add SpaceMouse support
- Add pre-parse enums support
- Add music player to FRED
- Enhanced SEXP comments
- FRED Dialog for Volumetrics
- QoL improvements to Object Editor
- Add FRED support for the "required weapon" feature
- SEXP Tree search and filter
</details>
<details><summary>QtFRED: </summary>
- Campaign Editor
- Add SpaceMouse support
- Make 'player starts in chase view' a toggle
</details>
<details><summary>Graphics: </summary>
- "The other great shader flag removal effort"
- Enhance handling of motion debris
- Expose texture filtering as a built-in option
- Improved particle culling and performance
- Optimized trail renderer
- Beam Particles
- Multiple lighting profiles
- Use volume particles for poofs
- Optimize for simple trails
- Kink shamed the laser bitmaps
</details>
<details><summary>HUD: </summary>
- Flag to apply HUD shudder to chase view
- Add missing HUD gauges
- Explicitly do not split lines when making the message log
</details>
<details><summary>Localization: </summary>
- Add some XSTR entries
</details>
<details><summary>Modding: </summary>
- Mapify built-in strings
- Allow `gameplay_profiles.tbl` to be an alias of `ai_profiles.tbl`
- Modular rank table
- Toggle auto-assigning personas
- Add some parameters for corkscrew starting angle
- Add clip planes to `game_settings.tbl`
- Add `+Use ship` as a Template
- Modular messages table
- Add arbitrary curves support
- Traitor overrides
- Add support for loose lz4 compressed files
- Add per-species warp effects
</details>
<details><summary>Models: </summary>
- Fix submodel sanity check
- Fix techroom modelnum references
- Adjust movement sanity checks to account for more situations
- Modular POF Features 2
- Add fov values to .pof models
- Add a Translation Moveable
- Remove model octants
- Fix glowpoints on animated submodels
- Update type_flags when dock name changes
- Add additional checks for Animation List handling of nonexistent polymodel instances
- Virtual POFs: Modify Subsystems
- Validate chunk size to avoid alignment crash and add align skip flag
</details>
<details><summary>Multiplayer: </summary>
- Generic Lua Multiplayer RPC
</details>
<details><summary>Performance: </summary>
- Increase sound update rate
- Add `line of sight` as an optional AI override
</details>
<details><summary>SEXPs: </summary>
- `turret-fired-since`, returns `true` if the specified turret has fired in the last `N` milliseconds
- `is-ship-emp-active`, returns `true` if the specified ship or list of ships is currently under an EMP effect
- `turret-has-primary` and `turret-has-secondary`, returns `true` if the specified turret contains the specified weapon
- `has-armor-type`, returns `true` if the specified ship or subsystem has the specified armor type
- `OPF_ANY_HUD_GAUGE` and `OPF_EVENT_NAME`, new Lua SEXP parameters
- Enhance Dynamic SEXPs with parent parameters
- Add "afterburn hard" AI goal flag
</details>
<details><summary>Scripting: </summary>
- Add option to deprecate hooks
- Get audiostream duration in float seconds
- Lua method to check if the game has focus
- `On warp complete` hook
- Allow Lua to set the Discord presence to custom strings
- Add virtvars for goal satisfaction and score
- Allow scripts to read and add LuaEnums
- Funcs and virtvars for SCPUI pause screen
- Expose pausing weapon sounds
- Make collision_group_id accessible to parse objects
- Pass shortcut key character to Lua as a hook variable
- Lua method to free all loaded models
- `On Asteroid Created` hook
- SCPUI methods required for handling closeup briefing icons
- Expose some Nebula settings to Lua
- SCPUI mission log
- SCPUI APIsfor the Game Help UI, medals access, and control config
- Force expand wings instead of toggle for SCPUI
- Add misc. validity checks
- Convert hotkey types to enum
- Finalize SCPUI API
- Blocking `On Frame` executor
- SCPUI Hud Config API
- Configurable restriction for ships that accept Lua player orders
- Add `ship::isPlayer()`
- Lua access to default countermeasures class
- Flag to check if a ship or weapon class is player allowed
- Add hooks for comm menu opening/closing
</details>
<details><summary>Technical: </summary>
- Improve CFLAGS handling
</details>
## [22.2.0] - 2022-08-06
```
-2
View File
@@ -1,7 +1,5 @@
FreeSpace2 *S*ource *C*ode *P*roject
==
[![Travis-CI Build Status](https://travis-ci.org/scp-fs2open/fs2open.github.com.svg?branch=master)](https://travis-ci.org/scp-fs2open/fs2open.github.com)
[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/scp-fs2open/fs2open.github.com?branch=master&svg=true)](https://ci.appveyor.com/project/SirKnightly/fs2open-github-com/branch/master)
[![Coverity](https://img.shields.io/coverity/scan/870.svg)](https://scan.coverity.com/projects/870)
Building
-62
View File
@@ -1,62 +0,0 @@
version: 1.0.0.{build}
image: Visual Studio 2015
configuration:
- Debug
- Release
clone_depth: 10
environment:
matrix:
- BuildID: 0
CMAKE_GENERATOR: Visual Studio 14 2015
PlatformToolset: v140
QT_DIR: C:\Qt\5.9\msvc2015
- BuildID: 1
CMAKE_GENERATOR: Visual Studio 14 2015 Win64
PlatformToolset: v140
QT_DIR: C:\Qt\5.9\msvc2015_64
before_build:
- git submodule update --init --recursive
build_script:
- ps: . $Env:APPVEYOR_BUILD_FOLDER/ci/appveyor/build.ps1
test_script:
- ps: . $Env:APPVEYOR_BUILD_FOLDER/ci/appveyor/test.ps1
deploy:
- provider: GitHub
auth_token:
secure: h55Scpy+3vmo1Yb7WlSIGA4d9DRnsbzUYc2LYsQdByQHZHbqrqjBpicH0D2FFLEO
on:
ReleaseBuild: true # deploy on release push only
- provider: FTP
protocol: sftp
host: scp.indiegames.us
username:
secure: SFivQZfatqWHXK1ijYK3GQ==
password:
secure: q6Zk/412o1ri+NEya1dl1Q==
folder: public_html/builds/nightly/$(VersionName)
on:
NightlyBuild: true # deploy on nightly push only
- provider: FTP
protocol: sftp
host: porphyrion.feralhosting.com
username:
secure: 36+bVD8eJgI0BVbi7TZ4zQ==
password:
secure: CrzmDVca8AGG08iWPA1gOD4Ge06+wJ3rcBagBGclwYQ=
folder: www/datacorder.porphyrion.feralhosting.com/public_html/builds/nightly/$(VersionName)
on:
NightlyBuild: true # deploy on nightly push only
- provider: FTP
protocol: sftp
host: porphyrion.feralhosting.com
username:
secure: 36+bVD8eJgI0BVbi7TZ4zQ==
password:
secure: CrzmDVca8AGG08iWPA1gOD4Ge06+wJ3rcBagBGclwYQ=
folder: www/datacorder.porphyrion.feralhosting.com/public_html/builds/test/$(VersionName)
on:
TestBuild: true # deploy on test build push only
-164
View File
@@ -1,164 +0,0 @@
class BuildConfig {
[string]$Generator
[string]$PackageType
[string]$Toolset
[string]$SimdType
[string]$QtDir
[Bool]$SourcePackage
}
$NightlyConfigurations = @(
# [BuildConfig]@{
# Generator="Visual Studio 14 2015 Win64";
# PackageType="Win64";
# Toolset="v140";
# SimdType="SSE2";
# QtDir="C:\Qt\5.9\msvc2015_64";
# SourcePackage=$false;
# },
# [BuildConfig]@{
# Generator="Visual Studio 14 2015";
# PackageType="Win32";
# Toolset="v140";
# SimdType="SSE2";
# QtDir="C:\Qt\5.9\msvc2015";
# SourcePackage=$false;
# }
)
$ReleaseConfigurations = @(
# [BuildConfig]@{
# Generator="Visual Studio 14 2015";
# PackageType="Win32";
# Toolset="v140";
# SimdType="SSE2";
# QtDir="C:\Qt\5.9\msvc2015";
# SourcePackage=$true;
# }
# [BuildConfig]@{
# Generator="Visual Studio 14 2015";
# PackageType="Win32-AVX";
# Toolset="v140";
# SimdType="AVX";
# QtDir="C:\Qt\5.9\msvc2015";
# SourcePackage=$false;
# }
# [BuildConfig]@{
# Generator="Visual Studio 14 2015 Win64";
# PackageType="Win64";
# Toolset="v140";
# SimdType="SSE2";
# QtDir="C:\Qt\5.9\msvc2015_64";
# SourcePackage=$false;
# }
# [BuildConfig]@{
# Generator="Visual Studio 14 2015 Win64";
# PackageType="Win64-AVX";
# Toolset="v140";
# SimdType="AVX";
# QtDir="C:\Qt\5.9\msvc2015_64";
# SourcePackage=$false;
# }
)
$BuildConfigurations = $null
# Default values
$ReleaseBuild = $false
$NightlyBuild = $false
$TestBuild = $false
# Set to true to test either the release or the nightly part of this script
$ReleaseTest = $false
$NightlyTest = $false
$TestBuildTest = $false
if ($ReleaseTest -Or ([System.Convert]::ToBoolean($env:APPVEYOR_REPO_TAG) -And ("$env:APPVEYOR_REPO_TAG_NAME" -match "^release_(.*)"))) {
# Tag matches
$ReleaseBuild = $true
$PackageName = "fs2_open_$($matches[1])"
$BuildConfigurations = $ReleaseConfigurations
}
if ($NightlyTest -Or ([System.Convert]::ToBoolean($env:APPVEYOR_REPO_TAG) -And ("$env:APPVEYOR_REPO_TAG_NAME" -match "^nightly_(.*)"))) {
# Tag matches
$NightlyBuild = $true
$PackageName = "nightly_$($matches[1])"
Set-AppveyorBuildVariable 'VersionName' "$($matches[1])"
$BuildConfigurations = $NightlyConfigurations
}
if ($TestBuildTest -Or ([System.Convert]::ToInt32($env:APPVEYOR_PULL_REQUEST_NUMBER) -le 0 -And ("$env:APPVEYOR_REPO_BRANCH" -match "^test\/(.*)"))) {
# Tag matches
$TestBuild = $true
$PackageName = "test_$($matches[1])"
Set-AppveyorBuildVariable 'VersionName' "$($matches[1])"
$BuildConfigurations = $NightlyConfigurations
# Override the revision string so that the builds are named correctly
[System.IO.File]::WriteAllLines("$env:APPVEYOR_BUILD_FOLDER/version_override.cmake", "set(FSO_VERSION_REVISION_STR $env:VersionName)")
}
# Multiply by 2 so that we can add 0 or 1 for debug or release Configs
$buildID = [convert]::ToInt32($env:BuildID) * 2
if ($Env:Configuration -eq "Release") {
$buildID = $buildID + 1
}
$DeployBuild = $false
if ($ReleaseBuild -Or $NightlyBuild -Or $TestBuild) {
$DeployBuild = $true
}
Set-AppveyorBuildVariable 'ReleaseBuild' "$ReleaseBuild"
Set-AppveyorBuildVariable 'NightlyBuild' "$NightlyBuild"
Set-AppveyorBuildVariable 'TestBuild' "$TestBuild"
New-Item build -type directory
Set-Location -Path build
if ($DeployBuild) {
# Release build
if ($buildID -ge $BuildConfigurations.Length) {
# Not needed
exit 0
}
$buildConfig = $BuildConfigurations[$buildID]
if ($buildConfig.SourcePackage -eq $True) {
7z a -xr'!.git' "$($PackageName)-source-Win.zip" "$env:APPVEYOR_BUILD_FOLDER"
Push-AppveyorArtifact "$($PackageName)-source-Win.zip"
}
cmake -DCMAKE_INSTALL_PREFIX="$env:APPVEYOR_BUILD_FOLDER/../install" -DFSO_USE_SPEECH="ON" `
-DFSO_USE_VOICEREC="ON" -DMSVC_SIMD_INSTRUCTIONS="$($buildConfig.SimdType)" `
-DQT5_INSTALL_ROOT="$($buildConfig.QtDir)" -DFSO_BUILD_QTFRED=OFF `
-DFSO_INSTALL_DEBUG_FILES="ON" `
-G "$($buildConfig.Generator)" -T "$($buildConfig.Toolset)" ..
$Configs = @("Release", "FastDebug")
foreach ($config in $Configs) {
cmake --build . --config "$config" --target INSTALL -- /verbosity:minimal
if (! ($?)) {
Add-AppveyorMessage "A release build failed!"
exit 1
}
}
7z a -xr'!*.pdb' "$($PackageName)-builds-$($buildConfig.PackageType).zip" "$env:APPVEYOR_BUILD_FOLDER/../install/*"
Push-AppveyorArtifact "$($PackageName)-builds-$($buildConfig.PackageType).zip"
7z a "$($PackageName)-debug-$($buildConfig.PackageType).7z" "$env:APPVEYOR_BUILD_FOLDER/../install/*.pdb"
Push-AppveyorArtifact "$($PackageName)-debug-$($buildConfig.PackageType).7z"
} else {
cmake -DFSO_USE_SPEECH="ON" -DFSO_FATAL_WARNINGS="ON" -DFSO_USE_VOICEREC="ON" -DFSO_BUILD_TESTS="ON" -DMSVC_SIMD_INSTRUCTIONS=SSE2 `
-DFSO_BUILD_QTFRED=OFF -DQT5_INSTALL_ROOT="$env:QT_DIR" -DFSO_BUILD_FRED2="ON" `
-G "$Env:CMAKE_GENERATOR" -T "$Env:PlatformToolset" ..
cmake --build . --config "$Env:CONFIGURATION" -- /verbosity:minimal
if (! ($?)) {
exit 1
}
}
-13
View File
@@ -1,13 +0,0 @@
if ([System.Convert]::ToBoolean($env:ReleaseBuild) -Or [System.Convert]::ToBoolean($env:NightlyBuild) -Or [System.Convert]::ToBoolean($env:TestBuild)) {
# Skip tests for deployment
exit 0
} else {
write "Running unit tests..."
# Run unit tests
&"$pwd\bin\$Env:CONFIGURATION\unittests.exe" --gtest_shuffle 2>&1
if (! ($?)) {
exit 1
}
}
+5 -2
View File
@@ -18,10 +18,11 @@ LD_LIBRARY_PATH=$Qt5_DIR/lib:$LD_LIBRARY_PATH
if [ "$RUNNER_OS" = "macOS" ]; then
CXXFLAGS="-mtune=generic -pipe -Wno-unknown-pragmas"
CFLAGS="-mtune=generic -pipe -Wno-unknown-pragmas"
PLATFORM_CMAKE_OPTIONS=""
# TODO: Vulkan support is disabled on MacOS due to issues with the test suite not linking correctly
PLATFORM_CMAKE_OPTIONS="-DFSO_BUILD_WITH_VULKAN=OFF"
export CMAKE_OSX_ARCHITECTURES="$ARCHITECTURE"
else
CXXFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
CXXFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas -static-libstdc++"
CFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
PLATFORM_CMAKE_OPTIONS="-DFSO_BUILD_APPIMAGE=ON"
fi
@@ -29,6 +30,8 @@ fi
CMAKE_OPTIONS="$JOB_CMAKE_OPTIONS"
if [[ "$COMPILER" =~ ^clang.*$ ]]; then
CMAKE_OPTIONS="$CMAKE_OPTIONS -DCLANG_USE_LIBCXX=ON"
# force clang to silently allow -static-libstdc++ flag
CXXFLAGS="$CXXFLAGS -Qunused-arguments"
fi
mkdir build
+13 -13
View File
@@ -10,27 +10,27 @@ source $HERE/dist_functions.sh
if [ "$OS" = "Linux" ]; then
tar -cvzf "$(get_package_name)-builds-Linux.tar.gz" *
echo "::set-output name=package_path::$(pwd)/$(get_package_name)-builds-Linux.tar.gz"
echo "::set-output name=package_name::$(get_package_name)-builds-Linux.tar.gz"
echo "::set-output name=package_mime::$(file -b --mime-type "$(pwd)/$(get_package_name)-builds-Linux.tar.gz")"
echo "package_path=$(pwd)/$(get_package_name)-builds-Linux.tar.gz" >> $GITHUB_OUTPUT
echo "package_name=$(get_package_name)-builds-Linux.tar.gz" >> $GITHUB_OUTPUT
echo "package_mime=$(file -b --mime-type "$(pwd)/$(get_package_name)-builds-Linux.tar.gz")" >> $GITHUB_OUTPUT
elif [ "$OS" = "Windows" ]; then
7z a -xr'!*.pdb' "$(get_package_name)-builds-$ARCH-$SIMD.zip" "*"
echo "::set-output name=package_path::$(pwd)/$(get_package_name)-builds-$ARCH-$SIMD.zip"
echo "::set-output name=package_name::$(get_package_name)-builds-$ARCH-$SIMD.zip"
echo "::set-output name=package_mime::$(file -b --mime-type "$(pwd)/$(get_package_name)-builds-$ARCH-$SIMD.zip")"
echo "package_path=$(pwd)/$(get_package_name)-builds-$ARCH-$SIMD.zip" >> $GITHUB_OUTPUT
echo "package_name=$(get_package_name)-builds-$ARCH-$SIMD.zip" >> $GITHUB_OUTPUT
echo "package_mime=$(file -b --mime-type "$(pwd)/$(get_package_name)-builds-$ARCH-$SIMD.zip")" >> $GITHUB_OUTPUT
7z a "$(get_package_name)-debug-$ARCH-$SIMD.7z" "*.pdb"
echo "::set-output name=debug_path::$(pwd)/$(get_package_name)-debug-$ARCH-$SIMD.7z"
echo "::set-output name=debug_name::$(get_package_name)-debug-$ARCH-$SIMD.7z"
echo "::set-output name=debug_mime::$(file -b --mime-type "$(pwd)/$(get_package_name)-debug-$ARCH-$SIMD.7z")"
echo "debug_path=$(pwd)/$(get_package_name)-debug-$ARCH-$SIMD.7z" >> $GITHUB_OUTPUT
echo "debug_name=$(get_package_name)-debug-$ARCH-$SIMD.7z" >> $GITHUB_OUTPUT
echo "debug_mime=$(file -b --mime-type "$(pwd)/$(get_package_name)-debug-$ARCH-$SIMD.7z")" >> $GITHUB_OUTPUT
elif [ "$OS" = "Mac" ]; then
tar -cvzf "$(get_package_name)-builds-Mac.tar.gz" *
tar -cvzf "$(get_package_name)-builds-Mac.tar.gz" *.app
echo "::set-output name=package_path::$(pwd)/$(get_package_name)-builds-Mac.tar.gz"
echo "::set-output name=package_name::$(get_package_name)-builds-Mac.tar.gz"
echo "::set-output name=package_mime::$(file -b --mime-type "$(pwd)/$(get_package_name)-builds-Mac.tar.gz")"
echo "package_path=$(pwd)/$(get_package_name)-builds-Mac.tar.gz" >> $GITHUB_OUTPUT
echo "package_name=$(get_package_name)-builds-Mac.tar.gz" >> $GITHUB_OUTPUT
echo "package_mime=$(file -b --mime-type "$(pwd)/$(get_package_name)-builds-Mac.tar.gz")" >> $GITHUB_OUTPUT
else
echo "Invalid OS: $OS"
fi
+13 -3
View File
@@ -10,11 +10,21 @@ HERE=$(dirname "$SCRIPT")
source $HERE/dist_functions.sh
if [ "$UPLOAD_TYPE" = "nightly" ]; then
SSHPASS=$INDIEGAMES_SSHPASS upload_files_to_sftp "$INDIEGAMES_USER@scp.indiegames.us" "public_html/builds/nightly"
any_success=false
if SSHPASS=$INDIEGAMES_SSHPASS upload_files_to_sftp "$INDIEGAMES_USER@scp.indiegames.us" "public_html/builds/nightly"; then
any_success=true
fi
SSHPASS=$DATACORDER_SSHPASS upload_files_to_sftp "$DATACORDER_USER@porphyrion.feralhosting.com" "www/datacorder.porphyrion.feralhosting.com/public_html/builds/nightly"
if SSHPASS=$DATACORDER_SSHPASS upload_files_to_sftp "$DATACORDER_USER@perses.feralhosting.com" "www/datacorder.perses.feralhosting.com/public_html/builds/nightly"; then
any_success=true
fi
if [ "$any_success" = "false" ]; then
echo "All uploads failed"
exit 1
fi
elif [ "$UPLOAD_TYPE" = "test" ]; then
SSHPASS=$DATACORDER_SSHPASS upload_files_to_sftp "$DATACORDER_USER@porphyrion.feralhosting.com" "www/datacorder.porphyrion.feralhosting.com/public_html/builds/test"
SSHPASS=$DATACORDER_SSHPASS upload_files_to_sftp "$DATACORDER_USER@perses.feralhosting.com" "www/datacorder.perses.feralhosting.com/public_html/builds/test"
else
echo "Unknown upload type $UPLOAD_TYPE"
exit 1
+7 -3
View File
@@ -19,7 +19,7 @@
# HLP_API:
# HLP_KEY:
# LINUX_RESULT: bool, if the linux builds were sucessfully uploaded
# LINUX_RESULT: bool, if the linux builds were successfully uploaded
# WINDOWS_RESULT: bool, if the windows builds were successfully uploaded
import sys
@@ -137,8 +137,8 @@ def main():
"pass": os.environ["INDIEGAMES_SSHPASS"],
"path": "public_html/builds/{type}/{version}/",
"mirrors": (
"https://porphyrion.feralhosting.com/datacorder/builds/{type}/{version}/{file}",
"http://scp.indiegames.us/builds/{type}/{version}/{file}",
"https://perses.feralhosting.com/datacorder/builds/{type}/{version}/{file}",
"https://scp.indiegames.us/builds/{type}/{version}/{file}",
),
},
"nebula": {
@@ -260,6 +260,10 @@ def main():
if "Linux" not in groups.keys():
print("ERROR: No Linux builds were detected!")
sys.exit(1)
if "Mac" not in groups.keys():
print("ERROR: No Mac builds were detected!")
sys.exit(1)
# z64: What dose this do???
# print(installer.render_installer_config(version, groups, config))
+14 -7
View File
@@ -9,7 +9,7 @@ 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.
[size=5pt]Previous [url=https://www.hard-light.net/forums/index.php?topic=98360.0]22.2.0 Release Thread[/url][/size]
[size=5pt]Previous [url=https://www.hard-light.net/forums/index.php?topic=98682.0]23.0.0 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.
@@ -18,11 +18,11 @@ Launchers, if you don't have one already:
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)
[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=http://scp.indiegames.us/builds/Launcher55g.zip]Mirror[/url]) ([url=https://www.mediafire.com/?wdvzn7hhhzh418m]Mirror[/url]) Not compatible with Windows 8+, use wxLauncher above
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
OS X: Soulstorm's [url=https://www.hard-light.net/forums/index.php/topic,51391.0.html]OS X Launcher 3.0[/url]
Linux: [url=https://www.hard-light.net/forums/index.php/topic,53206.0.html]YAL[/url] or [url=https://www.hard-light.net/wiki/index.php/Fs2_open_on_Linux/Graphics_Settings]by hand[/url] or whatever you can figure out.[/hidden]
[img]http://scp.indiegames.us/img/windows-icon.png[/img] [color=green][size=12pt]Windows (32/64-bit)[/size][/color]
[img]https://scp.indiegames.us/img/windows-icon.png[/img] [color=green][size=12pt]Windows (32/64-bit)[/size][/color]
[size=8pt]Compiled using GitHub Actions on Windows Server 2019 (10.0.17763), Visual Studio Enterprise 2019[/size]
[b]64-bit:[/b] ${build(groups["Win64"].mainFile)}
@@ -44,7 +44,7 @@ Linux: [url=https://www.hard-light.net/forums/index.php/topic,53206.0.html]YAL[
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!
[/hidden]
[img]http://scp.indiegames.us/img/linux-icon.png[/img] [color=green][size=12pt]Linux 64-bit[/size][/color]
[img]https://scp.indiegames.us/img/linux-icon.png[/img] [color=green][size=12pt]Linux 64-bit[/size][/color]
[size=8pt]Compiled with Ubuntu 16.04 LTS 64-bit, GCC 5[/size]
${build(groups["Linux"].mainFile)}
@@ -52,14 +52,21 @@ These builds use a mechanism called [url=https://appimage.org/]AppImage[/url] wh
Alternatively, if there is a package in your software repository then you should use that. If you are the maintainer of such a package for a distribution then let us know and we will include that here.
[img]http://scp.indiegames.us/img/mac-icon.png[/img] [color=green][size=12pt]OS X[/size][/color]
[b][color=red]Not available[/color][/b] We recently lost access to our Mac CI environment which we usually used for compiling these builds so for the time being, there will be no builds for this OS.
[img]https://scp.indiegames.us/img/mac-icon.png[/img] [color=green][size=12pt]macOS[/size][/color]
[size=8pt]macOS 10.9+, 64-bit (Intel)[/size]
${build(groups["Mac"].mainFile)}
These builds are not signed and so by default will fail to launch. To run them simply right-click on the app, click open, then click open again on the security confirmation dialog. You should only have to do this once for each app.
If running the game through Knossos or Knossos.NET this step should not be necessary.
[size=8pt][color=red][b]NOTE:[/b][/color] macOS builds currently have limited support and may exhibit issues not present on other platforms.[/size]
[hidden=TrackIR Users]
[size=12pt]Important!![/size]
An external DLL is required for FSO to use TrackIR functions. The following DLL is simply unpacked in to your main FreeSpace2 root dir.
TrackIR is only supported on Windows.
[url=https://www.mediafire.com/download.php?4zw024zrh44etse]TrackIR SCP DLL[/url] ([url=http://scp.fsmods.net/builds/scptrackir.zip]Mirror[/url]) ([url=http://scp.indiegames.us/builds/scptrackir.zip]Mirror[/url])[/hidden]
[url=https://www.mediafire.com/download.php?4zw024zrh44etse]TrackIR SCP DLL[/url] ([url=http://scp.fsmods.net/builds/scptrackir.zip]Mirror[/url]) ([url=https://scp.indiegames.us/builds/scptrackir.zip]Mirror[/url])[/hidden]
Known issues:
[list]
+1 -1
View File
@@ -1,3 +1,3 @@
Mako==1.2.2
requests==2.26.0
requests==2.31.0
semantic-version==2.8.5
-8
View File
@@ -1,8 +0,0 @@
#!/usr/bin/env sh
set -ex
if [ "$NIGHTLY_BUILD" = true ]; then
echo "Generating bintray config..."
sed -e "s/\$VERSION_NAME/$VERSION_NAME/" ci/bintray.template.json > ci/bintray.json
fi
-20
View File
@@ -1,20 +0,0 @@
#!/usr/bin/env sh
set -ex
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
export DEBIAN_FRONTEND=noninteractive
sudo add-apt-repository -y "ppa:msulikowski/valgrind" # For fixing a bug with valgrind 3.11 which does not recognize the rdrand instruction
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -
sudo add-apt-repository -y 'deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main'
sudo apt-get -yq update
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
# Nothing to do here
:
elif [ "$TRAVIS_OS_NAME" = "windows" ]; then
# Nothing to do here
:
fi
-50
View File
@@ -1,50 +0,0 @@
#!/usr/bin/env bash
set -ex
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
mkdir -p /tmp/builds
if [ "$RELEASE_BUILD" = true ]; then
# Package the source code in release builds
PARENT_DIR="$(basename "$PWD")"
(cd .. && tar -czvf /tmp/builds/$PACKAGE_NAME-source-Unix.tar.gz --exclude-vcs "$PARENT_DIR")
fi
fi
mkdir -p build
cd build
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
CXXFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
CFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
export CXXFLAGS
export CFLAGS
CMAKE="cmake -G Ninja -DFSO_FATAL_WARNINGS=ON $CMAKE_OPTIONS"
if [ "$BUILD_DEPLOYMENT" = true ]; then
for config in $BUILD_CONFIGS
do
mkdir -p $config
cd $config
eval $CMAKE -DFSO_INSTALL_DEBUG_FILES=ON -DCMAKE_BUILD_TYPE=$config -DCMAKE_INSTALL_PREFIX="/tmp/release/$config" \
-DFSO_BUILD_APPIMAGE=ON -DFSO_BUILD_INCLUDED_LIBS=ON -DFFMPEG_USE_PRECOMPILED=ON -DFSO_BUILD_QTFRED=OFF ../..
cd ..
done
else
eval $CMAKE -DCMAKE_BUILD_TYPE=$CONFIGURATION -DFSO_BUILD_TESTS=ON -DFSO_BUILD_INCLUDED_LIBS=ON -DFSO_BUILD_QTFRED=OFF ..
fi
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
if [ "$BUILD_DEPLOYMENT" = true ]; then
cmake -G "Xcode" -DFSO_FATAL_WARNINGS=ON -DFSO_INSTALL_DEBUG_FILES=ON -DCMAKE_INSTALL_PREFIX="/tmp/release" ..
else
cmake -G "Xcode" $CMAKE_OPTIONS ..
fi
elif [ "$TRAVIS_OS_NAME" = "windows" ]; then
if [ "$CMAKE_GENERATOR" = "Ninja" ]; then
cmake -DFSO_USE_SPEECH="OFF" -DFSO_FATAL_WARNINGS="ON" -DFSO_USE_VOICEREC="OFF" -DFSO_BUILD_TESTS="ON" \
-DFSO_BUILD_FRED2="OFF" -G "$CMAKE_GENERATOR" ..
else
cmake -DFSO_USE_SPEECH="ON" -DFSO_FATAL_WARNINGS="ON" -DFSO_USE_VOICEREC="OFF" -DFSO_BUILD_TESTS="ON" \
-DMSVC_SIMD_INSTRUCTIONS=SSE2 -DFSO_BUILD_FRED2="ON" -G "$CMAKE_GENERATOR" -T "$CMAKE_TOOLSET" ..
fi
fi
-74
View File
@@ -1,74 +0,0 @@
#!/usr/bin/env sh
RELEASE_BUILD=false
NIGHTLY_BUILD=false
TEST_BUILD=false
BUILD_DEPLOYMENT=false
BUILD_CONFIGS="Release FastDebug"
VERSION_NAME=""
PACKAGE_NAME=""
RELEASE_PATTERN="^release_(.*)$"
NIGHTLY_PATTERN="^nightly_(.*)$"
TEST_BUILD_PATTERN="^test\/(.*)$"
# These are for testing
NIGHTLY_TEST=false
RELEASE_TEST=false
TEST_BUILD_TEST=false
if [ "$RELEASE_TEST" = true ] || [[ "$TRAVIS_TAG" =~ $RELEASE_PATTERN ]]; then
echo "This is a release tag!";
RELEASE_BUILD=true;
PACKAGE_NAME="fs2_open_${BASH_REMATCH[1]}";
fi
if [ "$NIGHTLY_TEST" = true ] || [[ "$TRAVIS_TAG" =~ $NIGHTLY_PATTERN ]]; then
echo "This is a nightly tag!";
NIGHTLY_BUILD=true;
VERSION_NAME="${BASH_REMATCH[1]}";
PACKAGE_NAME="nightly_${BASH_REMATCH[1]}";
fi
if [ "$TEST_BUILD_TEST" = true ] || [[ "$TRAVIS_PULL_REQUEST" == "false" && "$TRAVIS_BRANCH" =~ $TEST_BUILD_PATTERN ]]; then
echo "This is a test build branch!";
TEST_BUILD=true;
if [ "$TEST_BUILD_TEST" = true ]; then
VERSION_NAME="test";
PACKAGE_NAME="test_test";
else
VERSION_NAME="${BASH_REMATCH[1]}";
PACKAGE_NAME="test_${BASH_REMATCH[1]}";
fi
# Override the revision string so that the builds are named correctly
echo "set(FSO_VERSION_REVISION_STR $VERSION_NAME)" > "$TRAVIS_BUILD_DIR/version_override.cmake"
fi
if ([ "$RELEASE_BUILD" = true ] || [ "$NIGHTLY_BUILD" = true ] || [ "$TEST_BUILD" = true ]); then
BUILD_DEPLOYMENT=true;
fi
if [ "$BUILD_DEPLOYMENT" = true ]; then
if ([ "$TRAVIS_OS_NAME" = "linux" ] && (! [[ "$CC" =~ ^gcc-5.*$ ]])); then
echo "Skipping non-release compiler";
exit 0;
fi
if ([[ "$CONFIGURATION" == "Debug" ]]); then
echo "Skipping non-release configuration";
exit 0;
fi
if [ "$TRAVIS_OS_NAME" = "windows" ]; then
echo "Skipping non-release platform"
exit 0
fi
fi
export RELEASE_BUILD
export NIGHTLY_BUILD
export TEST_BUILD
export BUILD_DEPLOYMENT
export BUILD_CONFIGS
export VERSION_NAME
export PACKAGE_NAME
-89
View File
@@ -1,89 +0,0 @@
#!/usr/bin/env bash
set -e
set -u
if [[ ! "$(curl -V)" == *"sftp"* ]]; then
# Before
echo "Before:"
curl -V
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
if [ -f ~/curl_cache/curl*.deb ]; then
cd ~/curl_cache
sudo dpkg -i libcurl3*.deb
sudo dpkg -i curl*.deb
else
# Since the Travis CI people are not capable of enabling SSH/SCP support for their libcurl we need to build that manually...
# These commands are based on the tutorial from here: http://zeroset.mnim.org/2013/03/14/sftp-support-for-curl-in-ubuntu-12-10-quantal-quetzal-and-later/
mkdir /tmp/curl
cd /tmp/curl
sudo apt-get update
sudo apt-get install build-essential debhelper libssh2-1-dev libgnutls-dev libidn11-dev libkrb5-dev libldap2-dev libnss3-dev librtmp-dev libtool openssh-server quilt
apt-get source curl
sudo apt-get build-dep curl
cd curl-*
export DEB_BUILD_OPTIONS="nocheck"
sudo dpkg-buildpackage -uc -us -j"$(grep -c ^processor /proc/cpuinfo)"
cd ..
dpkg -l | grep curl
ls -al
if [ ! -d ~/curl_cache ]; then
mkdir ~/curl_cache
fi
cp libcurl3*.deb curl*.deb ~/curl_cache
sudo dpkg -i libcurl3*.deb
sudo dpkg -i curl*.deb
fi
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
brew install libssh2
if [ -d ~/curl_cache/curl ]; then
cd ~/curl_cache/curl
sudo make install
else
mkdir /tmp/curl
cd /tmp/curl
curl -LO "https://curl.haxx.se/download/curl-7.64.0.tar.bz2"
tar -xjf curl-7.64.0.tar.bz2
cd curl-7.64.0
./configure --disable-debug --disable-dependency-tracking --disable-silent-rules --with-libssh2 --with-darwinssl --without-ca-bundle --without-ca-path
make -j"$(sysctl hw.logicalcpu | cut -d " " -f 2)"
if [ ! -d ~/curl_cache ]; then
mkdir ~/curl_cache
fi
cp -a . ~/curl_cache/curl
sudo make install
fi
export PATH=/usr/local/bin:$PATH
fi
# After
echo "After:"
curl -V
fi
cd /tmp/builds
for file in *; do
if [ "$TEST_BUILD" = true ]; then
# Upload to datacorder
curl -k "sftp://porphyrion.feralhosting.com/www/datacorder.porphyrion.feralhosting.com/public_html/builds/test/$VERSION_NAME/" --user "$DATACORDER_USER:$DATACORDER_PASSWORD" -T "$file" --ftp-create-dirs
else
# Upload to indiegames
curl -k "sftp://scp.indiegames.us/~/public_html/builds/nightly/$VERSION_NAME/" --user "$INDIEGAMES_USER:$INDIEGAMES_PASSWORD" -T "$file" --ftp-create-dirs
# Upload to datacorder
curl -k "sftp://porphyrion.feralhosting.com/~/www/datacorder.porphyrion.feralhosting.com/public_html/builds/nightly/$VERSION_NAME/" --user "$DATACORDER_USER:$DATACORDER_PASSWORD" -T "$file" --ftp-create-dirs
fi
done
-47
View File
@@ -1,47 +0,0 @@
#!/usr/bin/env bash
set -ex
FILENAME=
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
export DEBIAN_FRONTEND=noninteractive
if [ ! -d "$HOME/cmake-3.8/bin" ]; then
# If the cache does not currently contain CMake then download and install it
mkdir -p $HOME/cmake-3.8/
wget -O /tmp/cmake.tar.gz --no-check-certificate https://cmake.org/files/v3.8/cmake-3.8.2-Linux-x86_64.tar.gz
tar -xzf /tmp/cmake.tar.gz -C $HOME/cmake-3.8/ --strip-components=1
fi
export PATH=$HOME/cmake-3.8/bin:$PATH
cd $HOME
if [ "${BUILD_DEPLOYMENT}" = true ]; then
wget -O appimagetool -c "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage" # (64-bit)
chmod a+x ./appimagetool
wget -O linuxdeployqt -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage" # (64-bit)
chmod a+x ./linuxdeployqt
fi
sudo apt-get -yq install valgrind
if [[ "$CC" = "clang-9" ]]; then
sudo apt-get -yq install clang-9 clang-tidy-9
fi
if [[ "$CC" = "clang-4.0" ]]; then
# Fix a header bug present in ubuntu...
sudo ln -s /usr/include/libcxxabi/__cxxabi_config.h /usr/include/c++/v1/__cxxabi_config.h
fi
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
gem install xcpretty
brew update
brew outdated cmake || brew upgrade cmake
elif [ "$TRAVIS_OS_NAME" = "windows" ]; then
choco install mingw ninja
fi
cmake --version
-68
View File
@@ -1,68 +0,0 @@
#!/usr/bin/env sh
set -ex
mkdir -p /tmp/builds
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
cd build
for config in $BUILD_CONFIGS
do
cd "$config"
# Compile all targets
ninja all
# Install Freespace2 targets
cmake -DCMAKE_INSTALL_PREFIX=/tmp/release/$config/fso -DCOMPONENT=Unspecified -P cmake_install.cmake
cmake -DCMAKE_INSTALL_PREFIX=/tmp/release/$config/fso -DCOMPONENT=Freespace2 -P cmake_install.cmake
# We need to be a bit creative for determining the AppImage name since we don't want to hard-code the name
FILENAME="$(find /tmp/release/$config/fso/bin -name 'fs2_open_*' -type f -printf "%f\n").AppImage"
$HOME/appimagetool -n /tmp/release/$config/fso "/tmp/release/$config/fso/$FILENAME"
: <<'END'
# Install qtFRED targets
cmake -DCMAKE_INSTALL_PREFIX=/tmp/release/$config/qtfred/usr -DCOMPONENT=Unspecified -P cmake_install.cmake
cmake -DCMAKE_INSTALL_PREFIX=/tmp/release/$config/qtfred/usr -DCOMPONENT=qtFRED -P cmake_install.cmake
PREV="$(pwd)"
cd /tmp/release/$config/qtfred
unset QTDIR; unset QT_PLUGIN_PATH; unset LD_LIBRARY_PATH
$HOME/linuxdeployqt usr/qtfred.desktop -bundle-non-qt-libs
# Move our AppRun script to the right location
mv usr/AppRun AppRun
echo "Embed newer libstdc++ for distros that don't come with it (ubuntu 14.04)";
mkdir -p usr/optional/; mkdir -p usr/optional/libstdc++/;
cp /usr/lib/x86_64-linux-gnu/libstdc++.so.6 ./usr/optional/libstdc++/;
$HOME/appimagetool -n . "$(find /tmp/release/$config/qtfred/usr/bin -name 'qtfred_*' -type f -printf "%f\n").AppImage"
cd "$PREV"
END
cd ..
done
cp `find /tmp/release -name '*.AppImage' -print` /tmp/release
(cd /tmp/release && tar -cvzf /tmp/builds/$PACKAGE_NAME-builds-Linux.tar.gz *.AppImage)
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
cd build
for config in $BUILD_CONFIGS
do
cmake --build . --config "$config" --target install | tee build.log \
| xcpretty
XCODE_RET=${PIPESTATUS[0]}
if [ "$XCODE_RET" -ne "0" ]; then
tar -cvzf build.log.tar.gz build.log
curl --upload-file build.log.tar.gz "https://transfer.sh/build.log.tar.gz"
exit $XCODE_RET
fi
done
ls -al /tmp/release
(cd /tmp/release && tar -cvzf /tmp/builds/$PACKAGE_NAME-builds-MacOSX.tar.gz *)
fi
-30
View File
@@ -1,30 +0,0 @@
#!/usr/bin/env sh
set -e
cd build
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
ninja -k 20 all
if [ "$CONFIGURATION" = "Debug" ]; then
valgrind --leak-check=full --error-exitcode=1 --gen-suppressions=all \
--suppressions="$TRAVIS_BUILD_DIR/ci/travis/valgrind.supp" ./bin/unittests --gtest_shuffle
else
./bin/unittests --gtest_shuffle
fi
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
cmake --build . --config "$CONFIGURATION" | tee build.log | xcpretty
XCODE_RET=${PIPESTATUS[0]}
if [ "$XCODE_RET" -ne "0" ]; then
tar -cvzf build.log.tar.gz build.log
curl --upload-file build.log.tar.gz "https://keep.sh"
exit $XCODE_RET
fi
elif [ "$TRAVIS_OS_NAME" = "windows" ]; then
if [ "$CMAKE_GENERATOR" = "Ninja" ]; then
cmake --build . --config "$CONFIGURATION"
else
cmake --build . --config "$CONFIGURATION" -- /verbosity:minimal
fi
fi
+3 -3
View File
@@ -4,7 +4,7 @@ MESSAGE(STATUS "Doing configuration specific to Apple Clang...")
# TODO: Actually add Mac specific flags here...
# Suppress specific warning
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -funroll-loops -fsigned-char -Wno-unknown-pragmas")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fsigned-char -Wno-unknown-pragmas")
# Omit "conversion from string literal to 'char *' is deprecated" warnings.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-write-strings")
@@ -13,6 +13,6 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated -Wno-char-subscripts")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcolor-diagnostics")
set(CMAKE_CXX_FLAGS_RELEASE "-Wno-unused-variable")
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -Wno-unused-variable -Wno-unused-parameter")
set(CMAKE_CXX_FLAGS_DEBUG "-Wextra -Wshadow -Wno-unused-parameter")
set(CMAKE_CXX_FLAGS_DEBUG "-Og -g -Wshadow")
+3 -3
View File
@@ -33,7 +33,7 @@ set(COMPILER_FLAGS "")
_enable_extra_compiler_warnings_flags()
set(COMPILER_FLAGS "${COMPILER_FLAGS} ${_flags}")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -funroll-loops -fsigned-char -Wno-unknown-pragmas")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -fsigned-char -Wno-unknown-pragmas")
# Omit "argument unused during compilation" when clang is used with ccache.
if(${CMAKE_CXX_COMPILER} MATCHES "ccache")
@@ -85,7 +85,7 @@ endif()
set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable -Wno-unused-parameter")
set(COMPILER_FLAGS_DEBUG "-O0 -g -Wshadow")
set(COMPILER_FLAGS_DEBUG "-Og -g -Wshadow")
# Always use the base flags and add our compiler flags at the bacl
set(CMAKE_CXX_FLAGS "${CXX_BASE_FLAGS} ${COMPILER_FLAGS}")
@@ -120,7 +120,7 @@ if (FSO_FATAL_WARNINGS)
target_compile_options(compiler INTERFACE "-Werror")
endif()
# Always define this to make sure that the fixed width format macros are available
# Always define this to make sure that the fixed-width format macros are available
target_compile_definitions(compiler INTERFACE __STDC_FORMAT_MACROS)
if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR MINGW)
+3 -3
View File
@@ -45,7 +45,7 @@ endif()
_enable_extra_compiler_warnings_flags()
set(COMPILER_FLAGS "${COMPILER_FLAGS} ${_flags}")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -funroll-loops -fsigned-char -Wno-unknown-pragmas")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -fsigned-char -Wno-unknown-pragmas")
if (NOT GCC_INCREMENTAL_LINKING)
# Place each function and data in its own section so the linker can
@@ -115,7 +115,7 @@ endif()
set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable -Wno-unused-but-set-variable -Wno-array-bounds -Wno-empty-body -Wno-clobbered -Wno-unused-parameter")
set(COMPILER_FLAGS_DEBUG "-O0 -g -Wshadow")
set(COMPILER_FLAGS_DEBUG "-Og -g -Wshadow")
# Always use the base flags and add our compiler flags at the back
set(CMAKE_CXX_FLAGS "${CXX_BASE_FLAGS} ${COMPILER_FLAGS}")
@@ -165,7 +165,7 @@ if (FSO_FATAL_WARNINGS)
target_compile_options(compiler INTERFACE "-Werror")
endif()
# Always define this to make sure that the fixed width format macros are available
# Always define this to make sure that the fixed-width format macros are available
target_compile_definitions(compiler INTERFACE __STDC_FORMAT_MACROS=1)
if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR MINGW)
+30 -17
View File
@@ -67,30 +67,43 @@ ENDIF(EXISTS \"${CMAKE_CURRENT_BINARY_DIR}/${TARGET}/${FILE}\")
ENDFUNCTION(EP_CHECK_FILE_EXISTS)
MACRO(COPY_FILE_TO_TARGET _target _file)
if(UNIX)
ADD_CUSTOM_COMMAND(
TARGET ${_target} POST_BUILD
COMMAND cp -a "${_file}" "$<TARGET_FILE_DIR:${_target}>/${LIBRAY_DESTINATION}/"
COMMENT "copying '${_file}'..."
)
if (IS_DIRECTORY "${_file}")
get_filename_component(_dirName "${_file}" NAME)
if (PLATFORM_MAC AND ("${_file}" MATCHES ".framework$"))
# This is stupid, but it preserves symlinks, unlike copy_directory_if_different.
# Otherwise we end up creating duplicate files in the copied framework.
ADD_CUSTOM_COMMAND(
TARGET ${_target} POST_BUILD
COMMAND rsync -rlq "${_file}" "$<TARGET_FILE_DIR:${_target}>/${LIBRAY_DESTINATION}"
COMMENT "copying '${_file}'..."
VERBATIM
)
else()
ADD_CUSTOM_COMMAND(
TARGET ${_target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different "${_file}" "$<TARGET_FILE_DIR:${_target}>/${LIBRAY_DESTINATION}/${_dirName}"
COMMENT "copying '${_file}'..."
VERBATIM
)
endif()
else()
ADD_CUSTOM_COMMAND(
TARGET ${_target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_file}" "$<TARGET_FILE_DIR:${_target}>/${LIBRAY_DESTINATION}/"
COMMENT "copying '${_file}'..."
TARGET ${_target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_file}" "$<TARGET_FILE_DIR:${_target}>/${LIBRAY_DESTINATION}/"
COMMENT "copying '${_file}'..."
VERBATIM
)
endif()
endmacro(COPY_FILE_TO_TARGET)
MACRO(COPY_FILES_TO_TARGET _target)
if(UNIX)
ADD_CUSTOM_COMMAND(
TARGET ${_target} POST_BUILD
COMMAND mkdir -p "$<TARGET_FILE_DIR:${_target}>/${LIBRAY_DESTINATION}/"
COMMENT "Creating '$<TARGET_FILE_DIR:${_target}>/${LIBRAY_DESTINATION}/'..."
)
endif()
ADD_CUSTOM_COMMAND(
TARGET ${_target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory "$<TARGET_FILE_DIR:${_target}>/${LIBRAY_DESTINATION}/"
COMMENT "Creating '$<TARGET_FILE_DIR:${_target}>/${LIBRAY_DESTINATION}/'..."
VERBATIM
)
FOREACH(file IN LISTS TARGET_COPY_FILES)
COPY_FILE_TO_TARGET("${_target}" "${file}")
ENDFOREACH(file)
+1 -1
View File
@@ -6,7 +6,7 @@ if (EXISTS "${PROJECT_SOURCE_DIR}/version_override.cmake")
include("${PROJECT_SOURCE_DIR}/version_override.cmake")
endif()
set_if_not_defined(FSO_VERSION_MAJOR 22)
set_if_not_defined(FSO_VERSION_MAJOR 23)
set_if_not_defined(FSO_VERSION_MINOR 3)
set_if_not_defined(FSO_VERSION_BUILD 0)
+17 -5
View File
@@ -20,6 +20,9 @@ TARGET_INCLUDE_DIRECTORIES(code PUBLIC ${GENERATED_SOURCE_DIR}/code)
if (FSO_BUILD_WITH_OPENGL)
target_link_libraries(code PUBLIC OpenGL)
if(FSO_BUILD_WITH_OPENGL_DEBUG)
add_definitions(-DFS_OPENGL_DEBUG)
endif()
endif()
TARGET_LINK_LIBRARIES(code PUBLIC openal)
@@ -47,10 +50,6 @@ target_link_libraries(code PUBLIC libRocket)
target_link_libraries(code PUBLIC pcp)
if (FSO_BUILD_WITH_VULKAN)
target_link_libraries(code PUBLIC vulkan-hpp)
endif()
target_link_libraries(code PUBLIC parsers)
target_link_libraries(code PUBLIC mdns)
@@ -70,6 +69,10 @@ target_link_libraries(code PUBLIC any)
target_link_libraries(code PUBLIC optional)
target_link_libraries(code PUBLIC anl)
target_link_libraries(code PUBLIC hidapi::hidapi)
target_link_libraries(code PUBLIC imgui)
# Headers for standalone "gui" on UNIX
@@ -94,7 +97,16 @@ if (FSO_BUILD_WITH_OPENGL)
target_compile_definitions(code PUBLIC WITH_OPENGL)
endif()
if (FSO_BUILD_WITH_VULKAN)
target_compile_definitions(code PUBLIC WITH_VULKAN)
find_package(Vulkan REQUIRED)
if (Vulkan_FOUND)
target_compile_definitions(code PUBLIC WITH_VULKAN)
target_link_libraries(code PRIVATE Vulkan::Vulkan)
target_compile_definitions(code PUBLIC WITH_VULKAN VULKAN_HPP_DISPATCH_LOADER_DYNAMIC=1 VK_NO_PROTOTYPES)
else()
message(WARNING "FSO_BUILD_WITH_VULKAN was set, but the package was unable to be found. Forcing OFF.")
set(FSO_BUILD_WITH_VULKAN OFF CACHE BOOL "Enable compilation of the Vulkan renderer" FORCE)
endif()
endif()
include(shaders.cmake)
+17 -18
View File
@@ -34,7 +34,13 @@ typedef struct ai_flag_name {
char flag_name[TOKEN_LENGTH];
} ai_flag_name;
typedef struct ai_flag_description {
AI::AI_Flags flag;
SCP_string flag_desc;
} ai_flag_description;
extern ai_flag_name Ai_flag_names[];
extern ai_flag_description Ai_flag_descriptions[];
extern const int Num_ai_flag_names;
// dock_orient_and_approach() modes.
@@ -50,12 +56,6 @@ extern const int Num_ai_flag_names;
#define AIDO_DOCK_NOW 2 // Immediately move into dock position. For ships that start mission docked.
#define AIDO_UNDOCK 3 // Set goal of undocking with object.
// Submodes for seeking safety.
#define AISS_1 41 // Pick a spot to fly to.
#define AISS_2 42 // Flying to spot.
#define AISS_3 43 // Gotten near spot, fly about there.
#define AISS_1a 44 // Pick a new nearby spot because we are endangered, then go to AISS_2
// Flags to ai_turn_towards_vector().
#define AITTV_FAST (1<<0) // Turn fast, not slowed down based on skill level.
#define AITTV_VIA_SEXP (1<<1) // Goober5000 - via sexp
@@ -87,7 +87,7 @@ extern const int Num_ai_flag_names;
#define AIM_BAY_DEPART 18 // Departing to a fighter bay, following path to do so
#define AIM_SENTRYGUN 19 // AI mode for sentry guns only (floating turrets)
#define AIM_WARP_OUT 20 // Commence warp out sequence. Point in legal direction. Then call John's code.
#define AIM_FLY_TO_SHIP 21 // [Kazan] Fly to a ship, doesn't matter if it's hostile or friendly -- for Autopilot usage
#define AIM_FLY_TO_SHIP 21 // Rendezvous with a ship. Like stay-near, but non-perpetual.
#define AIM_LUA 22 // Generic Lua-based AI mode
#define MAX_AI_BEHAVIORS 23 // Number of AIM_xxxx types
@@ -180,6 +180,12 @@ typedef struct ai_class {
#define AIS_UNDOCK_3 33
#define AIS_UNDOCK_4 34
// Submodes for seeking safety.
#define AISS_1 41 // Pick a spot to fly to.
#define AISS_2 42 // Flying to spot.
#define AISS_3 43 // Gotten near spot, fly about there.
#define AISS_1a 44 // Pick a new nearby spot because we are endangered, then go to AISS_2. (Not implemented.)
// Submodes for Guard behavior
#define AIS_GUARD_PATROL 101
#define AIS_GUARD_ATTACK 102
@@ -234,7 +240,6 @@ typedef struct ai_info {
flagset<AI::AI_Flags> ai_flags; // Special flags for AI behavior.
int shipnum; // Ship using this slot, -1 means none.
int behavior; // AI behavior; vestigial field from early development of FS1
int mode;
int previous_mode;
int mode_time; // timestamp at which current mode elapses.
@@ -302,6 +307,7 @@ typedef struct ai_info {
fix submode_start_time; // time at which we entered the current submode
int submode_parm0; // parameter specific to current submode
int submode_parm1; // SUSHI: Another optional parameter
float submode_float0; // Goober5000: a float parameter
fix next_predict_pos_time; // Next time to predict position.
int next_dynamic_path_check_time; //ETP: Time of next path check in ai_new_maybe_reposition_attack_subsys
@@ -367,11 +373,6 @@ typedef struct ai_info {
float ai_turret_max_aim_update_delay;
flagset<AI::Profile_Flags> ai_profile_flags; //Holds AI_Profiles flags (possibly overriden by AI class) that actually apply to AI
union {
float stay_near_distance; // Distance to stay within for AIM_STAY_NEAR mode.
};
ship_subsys* targeted_subsys; // Targeted subobject on current target. NULL if none;
ship_subsys* last_subsys_target; // last known subsystem target
int targeted_subsys_parent; // Parent objnum of subobject, not necessarily targeted
@@ -559,7 +560,7 @@ extern void ai_attack_wing(object *attacker, int wingnum);
extern void ai_deathroll_start(object *ship_obj);
extern int set_target_objnum(ai_info *aip, int objnum);
extern void ai_form_on_wing(object *objp, object *goal_objp);
extern void ai_do_stay_near(object *objp, object *other_obj, float dist);
extern void ai_do_stay_near(object *objp, object *other_obj, float dist, int additional_data);
extern ship_subsys *set_targeted_subsys(ai_info *aip, ship_subsys *new_subsys, int parent_objnum);
extern void ai_rearm_repair( object *objp, int docker_index, object *goal_objp, int dockee_index );
extern void ai_add_rearm_goal( object *requester_objp, object *support_objp );
@@ -588,6 +589,8 @@ extern int ai_fire_primary_weapon(object *objp); //changed to return weather it
extern int ai_fire_secondary_weapon(object *objp);
extern float ai_get_weapon_dist(ship_weapon *swp);
extern void turn_towards_point(object *objp, vec3d *point, vec3d *slide_vec, float bank_override, matrix* target_orient = nullptr, int flags = 0);
extern bool ai_willing_to_afterburn_hard(ai_info* aip);
extern void ai_afterburn_hard(object* objp, ai_info* aip);
extern int ai_maybe_fire_afterburner(object *objp, ai_info *aip);
extern void set_predicted_enemy_pos(vec3d *predicted_enemy_pos, object *pobjp, vec3d *enemy_pos, vec3d *enemy_vel, ai_info *aip);
@@ -617,10 +620,6 @@ int get_nearest_objnum(int objnum, int enemy_team_mask, int enemy_wing, float ra
// moved to header file by Goober5000
void ai_announce_ship_dying(object *dying_objp);
// added by kazan
void ai_start_fly_to_ship(object *objp, int shipnum);
void ai_fly_to_ship();
//Moved declaration here for player ship -WMC
void ai_process_subobjects(int objnum);
+11 -4
View File
@@ -45,7 +45,8 @@ namespace AI {
Purge, // purge this goal next time we process
Goals_purged, // this goal has already caused other goals to get purged
Depart_sound_played,// Goober5000 - replacement for AL's hack ;)
Target_own_team,
Target_own_team, // this attack goal is allowed to target friendlies
Afterburn_hard, // afterburn as hard as possible to the goal
NUM_VALUES
};
@@ -121,7 +122,7 @@ namespace AI {
Smart_shield_management,
Smart_subsystem_targeting_for_turrets,
Strict_turret_tagged_only_targeting,
Support_dont_add_primaries, //Prevents support ship from equipping new primary as requested in http://scp.indiegames.us/mantis/view.php?id=3198
Support_dont_add_primaries, //Prevents support ship from equipping new primary as requested in https://scp.indiegames.us/mantis/view.php?id=3198
Turrets_ignore_target_radius,
Use_actual_primary_range,
Use_subsystem_path_point_radii,
@@ -130,8 +131,9 @@ namespace AI {
Use_only_single_fov_for_turrets,
No_turning_directional_bias,
Use_axial_turnrate_differences,
all_nonshielded_ships_can_manage_ets,
fightercraft_nonshielded_ships_can_manage_ets,
All_nonshielded_ships_can_manage_ets,
Fightercraft_nonshielded_ships_can_manage_ets,
Ships_playing_dead_dont_manage_ets,
Better_collision_avoidance,
Require_exact_los,
Improved_missile_avoidance,
@@ -150,6 +152,11 @@ namespace AI {
Fixed_removing_play_dead_order,
Disable_bay_emerge_timeout,
Adjusted_AI_class_autoscale,
Carry_shield_difficulty_scaling_bug,
Whackable_debris,
Whackable_asteroids,
Dynamic_goals_afterburn_hard,
Hudsquadmsg_tactical_disarm_disable,
NUM_VALUES
};
+43 -7
View File
@@ -223,6 +223,9 @@ void parse_ai_profiles_tbl(const char *filename)
if (optional_string("$Player Subsys Damage Factor:") || optional_string("$AI Damage Reduction to Player Subsys:"))
parse_float_list(profile->subsys_damage_scale, NUM_SKILL_LEVELS);
if (optional_string("$Player Damage Inflicted Factor:"))
parse_float_list(profile->player_damage_inflicted_scale, NUM_SKILL_LEVELS);
// represented in fractions of F1_0
if (optional_string("$Predict Position Delay:"))
{
@@ -546,16 +549,20 @@ void parse_ai_profiles_tbl(const char *filename)
mprintf(("Warning: \"$ships with no shields can manage ETS\" flag is deprecated in favor of \"$any ship with no shields can manage ETS\"\n"));
bool temp;
stuff_boolean(&temp);
profile->flags.set(AI::Profile_Flags::all_nonshielded_ships_can_manage_ets, temp);
profile->flags.set(AI::Profile_Flags::All_nonshielded_ships_can_manage_ets, temp);
}
set_flag(profile, "$no directional bias for missile and ship turning:", AI::Profile_Flags::No_turning_directional_bias);
// ----------
set_flag(profile, "$no directional bias for missile and ship turning:", AI::Profile_Flags::No_turning_directional_bias);
set_flag(profile, "$respect ship axial turnrate differences:", AI::Profile_Flags::Use_axial_turnrate_differences);
set_flag(profile, "$any ship with no shields can manage ETS:", AI::Profile_Flags::all_nonshielded_ships_can_manage_ets);
set_flag(profile, "$any ship with no shields can manage ETS:", AI::Profile_Flags::All_nonshielded_ships_can_manage_ets);
set_flag(profile, "$fighters/bombers with no shields can manage ETS:", AI::Profile_Flags::fightercraft_nonshielded_ships_can_manage_ets);
set_flag(profile, "$fighters/bombers with no shields can manage ETS:", AI::Profile_Flags::Fightercraft_nonshielded_ships_can_manage_ets);
set_flag(profile, "$ships playing dead don't manage ETS:", AI::Profile_Flags::Ships_playing_dead_dont_manage_ets);
set_flag(profile, "$better combat collision avoidance for fightercraft:", AI::Profile_Flags::Better_collision_avoidance);
@@ -610,6 +617,15 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$use adjusted AI class autoscale:", AI::Profile_Flags::Adjusted_AI_class_autoscale);
set_flag(profile, "$carry shield difficulty scaling bug:", AI::Profile_Flags::Carry_shield_difficulty_scaling_bug);
set_flag(profile, "$debris affected by physics whacks:", AI::Profile_Flags::Whackable_debris);
set_flag(profile, "$asteroids affected by physics whacks:", AI::Profile_Flags::Whackable_asteroids);
set_flag(profile, "$dynamic goals afterburn hard:", AI::Profile_Flags::Dynamic_goals_afterburn_hard);
set_flag(profile, "$hud squad messages use tactical disarm/disable:", AI::Profile_Flags::Hudsquadmsg_tactical_disarm_disable);
// if we've been through once already and are at the same place, force a move
if (saved_Mp && (saved_Mp == Mp))
@@ -652,12 +668,21 @@ void ai_profiles_init()
// init retail entry first
parse_ai_profiles_tbl(NULL);
// Allow mission_profiles.tbl to be a alias of ai_profiles.tbl, but only load one or the other.
// mission_profiles.tbl would be newer so assume intended, but print to the log to be sure - Mjn
char filename[MAX_FILENAME_LEN] = "ai_profiles.tbl";
if (cf_exists_full("mission_profiles.tbl", CF_TYPE_TABLES)) {
mprintf(("mission_profiles.tbl was found! Using that instead of ai_profiles.tbl...\n"));
strcpy_s(filename, "mission_profiles.tbl");
}
// now parse the supplied table (if any)
if (cf_exists_full("ai_profiles.tbl", CF_TYPE_TABLES))
parse_ai_profiles_tbl("ai_profiles.tbl");
if (cf_exists_full(filename, CF_TYPE_TABLES))
parse_ai_profiles_tbl(filename);
// parse any modular tables
parse_modular_table("*-aip.tbm", parse_ai_profiles_tbl);
parse_modular_table("*-msp.tbm", parse_ai_profiles_tbl);
// set default if specified
temp = ai_profile_lookup(Default_profile_name);
@@ -711,6 +736,7 @@ void ai_profile_t::reset()
shield_energy_scale[i] = 0;
afterburner_recharge_scale[i] = 0;
player_damage_scale[i] = 0;
player_damage_inflicted_scale[i] = 0;
subsys_damage_scale[i] = 0;
beam_friendly_damage_cap[i] = 0;
@@ -760,7 +786,7 @@ void ai_profile_t::reset()
flags.set(AI::Profile_Flags::Fix_ai_path_order_bug);
flags.set(AI::Profile_Flags::Aspect_invulnerability_fix);
flags.set(AI::Profile_Flags::Use_actual_primary_range);
flags.set(AI::Profile_Flags::fightercraft_nonshielded_ships_can_manage_ets);
flags.set(AI::Profile_Flags::Fightercraft_nonshielded_ships_can_manage_ets);
}
// this flag has been enabled ever since 3.7.2
if (mod_supports_version(3, 7, 2)) {
@@ -770,6 +796,10 @@ void ai_profile_t::reset()
if (mod_supports_version(3, 6, 10)) {
flags.set(AI::Profile_Flags::Reset_last_hit_target_time_for_player_hits);
}
// backwards compatible flag for a bug accidentally introduced during this time
if (mod_supports_version(3, 6, 14) && !mod_supports_version(23, 1, 0)) {
flags.set(AI::Profile_Flags::Carry_shield_difficulty_scaling_bug);
}
if (mod_supports_version(21, 4, 0)) {
flags.set(AI::Profile_Flags::Fixed_ship_weapon_collision);
}
@@ -783,4 +813,10 @@ void ai_profile_t::reset()
flags.set(AI::Profile_Flags::No_continuous_turn_on_attack);
flags.set(AI::Profile_Flags::Fixed_removing_play_dead_order);
}
if (mod_supports_version(23, 2, 0)) {
flags.set(AI::Profile_Flags::Ships_playing_dead_dont_manage_ets);
}
if (mod_supports_version(23, 4, 0)) {
flags.set(AI::Profile_Flags::Hudsquadmsg_tactical_disarm_disable);
}
}
+1
View File
@@ -53,6 +53,7 @@ public:
float shield_energy_scale[NUM_SKILL_LEVELS]; // shield energy available
float afterburner_recharge_scale[NUM_SKILL_LEVELS]; // speed of afterburner recharge
float player_damage_scale[NUM_SKILL_LEVELS]; // damage applied to the player
float player_damage_inflicted_scale[NUM_SKILL_LEVELS]; // damage applied by the player
float subsys_damage_scale[NUM_SKILL_LEVELS]; // damage applied to a player subsystem
float beam_friendly_damage_cap[NUM_SKILL_LEVELS]; // damage cap values for friendly beam fire
+51 -60
View File
@@ -67,7 +67,6 @@ int ai_big_maybe_follow_subsys_path(int do_dot_check=1);
void ai_big_strafe_position();
static int ai_big_strafe_maybe_retreat(const vec3d *target_pos);
extern int model_which_octant_distant_many( vec3d *pnt, int model_num,matrix *model_orient, vec3d * model_pos, polymodel **pm, int *octs);
extern void compute_desired_rvec(vec3d *rvec, vec3d *goal_pos, vec3d *cur_pos);
extern void big_ship_collide_recover_start(object *objp, object *big_objp, vec3d *collision_normal);
@@ -83,10 +82,9 @@ void ai_bpap(object *objp, vec3d *attacker_objp_pos, vec3d *attacker_objp_fvec,
vec3d result_point, best_point;
vec3d rel_point;
int num_tries;
model_octant *octp;
polymodel *pm;
int i, q, octs[4];
int i;
ship_info *sip = &Ship_info[Ships[objp->instance].ship_info_index];
polymodel* pm = model_get(sip->model_num);
model_subsystem *tp = NULL;
if (ss != NULL)
tp = ss->system_info;
@@ -94,63 +92,53 @@ void ai_bpap(object *objp, vec3d *attacker_objp_pos, vec3d *attacker_objp_fvec,
best_point = objp->pos;
nearest_dist = weapon_travel_dist;
model_which_octant_distant_many(attacker_objp_pos, sip->model_num, &objp->orient, &objp->pos, &pm, octs);
// attempt anywhere from 16 to 4 times, more if we're closer
num_tries = (int) (vm_vec_dist(&objp->pos, attacker_objp_pos)/objp->radius);
if (num_tries >= 4)
num_tries = 1;
else
num_tries = 4 - num_tries;
num_tries = (4 - num_tries) * 4;
// Index #0 is best one.
if ( pm->octants[octs[0]].verts ) {
*local_attack_point = *pm->octants[octs[0]].verts[0]; // Set just in case it doesn't get set below.
} else {
vm_vec_zero(local_attack_point);
}
vm_vec_zero(local_attack_point);
for (q=0; q<4; q++) {
octp = &pm->octants[octs[q]];
if (octp->nverts > 0) {
auto collision_tree = model_get_bsp_collision_tree(pm->submodel[pm->detail[0]].collision_tree_index);
if (num_tries > octp->nverts)
num_tries = octp->nverts;
if (!collision_tree->poly_centers.empty()) {
int num_polies = (int)collision_tree->poly_centers.size();
if (num_tries > octp->nverts)
num_tries = octp->nverts;
if (num_tries > num_polies)
num_tries = num_polies;
for (i=0; i<num_tries; i++) {
int index;
float dist, dot;
vec3d v2p;
for (i=0; i<num_tries; i++) {
int index;
float dist, dot;
vec3d v2p;
index = (int) (frand() * (octp->nverts));
index = (int) (frand() * num_polies);
rel_point = *octp->verts[index];
vm_vec_unrotate(&result_point, &rel_point, &objp->orient);
vm_vec_add2(&result_point, &objp->pos);
rel_point = collision_tree->poly_centers[index];
vm_vec_unrotate(&result_point, &rel_point, &objp->orient);
vm_vec_add2(&result_point, &objp->pos);
dist = vm_vec_normalized_dir(&v2p, &result_point, attacker_objp_pos);
bool in_fov = false;
dist = vm_vec_normalized_dir(&v2p, &result_point, attacker_objp_pos);
bool in_fov = false;
dot = vm_vec_dot(&v2p, attacker_objp_fvec);
if (tp == NULL) {
if (dot > fov)
in_fov = true;
} else {
in_fov = turret_fov_test(ss, attacker_objp_fvec, &v2p);
}
dot = vm_vec_dot(&v2p, attacker_objp_fvec);
if (tp == NULL) {
if (dot > fov)
in_fov = true;
} else {
in_fov = turret_fov_test(ss, attacker_objp_fvec, &v2p);
}
if (in_fov) {
if (dist < nearest_dist) {
nearest_dist = dist;
best_point = result_point;
*local_attack_point = rel_point;
Assert( !vm_is_vec_nan(local_attack_point) );
if (dot > (1.0f + fov)/2.0f) // If this point is quite good, quit searching for a better one.
goto done_1;
}
if (in_fov) {
if (dist < nearest_dist) {
nearest_dist = dist;
best_point = result_point;
*local_attack_point = rel_point;
Assert( !vm_is_vec_nan(local_attack_point) );
if (dot > (1.0f + fov)/2.0f) // If this point is quite good, quit searching for a better one.
goto done_1;
}
}
}
@@ -174,8 +162,6 @@ done_1:
}
mc_info mc;
mc_info_init(&mc);
mc.model_instance_num = Ships[objp->instance].model_instance_num;
mc.model_num = sip->model_num;
mc.orient = &objp->orient;
@@ -549,11 +535,11 @@ bool ai_new_maybe_reposition_attack_subsys() {
// get world pos of eye (stored in geye)
ep = &(pm->view_positions[Ships[Pl_objp->instance].current_viewpoint]);
model_local_to_global_point(&geye, &ep->pnt, pm->id, 0, &Pl_objp->orient, &Pl_objp->pos);
model_local_to_global_point(&geye, &ep->pnt, pm, 0, &Pl_objp->orient, &Pl_objp->pos);
// get world pos of subsystem
vm_vec_unrotate(&gsubpos, &aip->targeted_subsys->system_info->pnt, &En_objp->orient);
vm_vec_add2(&gsubpos, &En_objp->pos);
polymodel* tgt_pm = model_get(Ship_info[Ships[target_objp->instance].ship_info_index].model_num);
model_local_to_global_point(&gsubpos, &vmd_zero_vector, tgt_pm, aip->targeted_subsys->system_info->subobj_num, &En_objp->orient, &En_objp->pos);
// you're in sight! shoot it!
if (ship_subsystem_in_sight(En_objp, aip->targeted_subsys, &geye, &gsubpos, 0))
@@ -618,6 +604,7 @@ bool ai_new_maybe_reposition_attack_subsys() {
else
good_pos = &world_goal_pos;
aip->next_dynamic_path_check_time = timestamp( AI_DYNAMIC_PATH_RECHECK_DELAY );
aip->last_dynamic_path_goal = *good_pos;
}
else{ //Not enough time has passed till recheck.
@@ -631,15 +618,17 @@ bool ai_new_maybe_reposition_attack_subsys() {
accelerate_ship(aip, subsys_distance > 200.0f ? 1.0f : subsys_distance / 200.0f);
if (!(Ships[Pl_objp->instance].flags[Ship::Ship_Flags::Afterburner_locked])) {
if (subsys_distance > 300.0f) {
if (ai_willing_to_afterburn_hard(aip) && subsys_distance > 1000.0f)
ai_afterburn_hard(Pl_objp, aip);
else if (subsys_distance > 300.0f) {
if (ai_maybe_fire_afterburner(Pl_objp, aip)) {
afterburners_start(Pl_objp);
aip->afterburner_stop_time = Missiontime + 2 * F1_0;
}
}
else
afterburners_stop(Pl_objp);
}
} else
afterburners_stop(Pl_objp);
return true;
}
@@ -759,7 +748,7 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
if (ai_new_maybe_reposition_attack_subsys())
return;
} else if ( ai_big_maybe_follow_subsys_path() ) {
if ((Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) && !(aip->ai_flags[AI::AI_Flags::Kamikaze])) {
if ((Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) && !(aip->ai_flags[AI::AI_Flags::Kamikaze]) && !ai_willing_to_afterburn_hard(aip)) {
afterburners_stop(Pl_objp);
}
return;
@@ -851,7 +840,9 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
} else {
accelerate_ship(aip, accel);
if ((aip->ai_flags[AI::AI_Flags::Free_afterburner_use] || aip->ai_profile_flags[AI::Profile_Flags::Free_afterburner_use]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (accel > 0.95f)) {
if (ai_willing_to_afterburn_hard(aip) && accel > 0.99f && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked])) {
ai_afterburn_hard(Pl_objp, aip);
} else if ((aip->ai_flags[AI::AI_Flags::Free_afterburner_use] || aip->ai_profile_flags[AI::Profile_Flags::Free_afterburner_use]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (accel > 0.95f)) {
if (ai_maybe_fire_afterburner(Pl_objp, aip)) {
afterburners_start(Pl_objp);
aip->afterburner_stop_time = Missiontime + 3*F1_0;
@@ -923,13 +914,13 @@ static void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy)
}
if (tswp->num_secondary_banks > 0) {
if (!(En_objp->flags[Object::Object_Flags::Protected]) || (aip->goals[0].ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP))) {
if (!(En_objp->flags[Object::Object_Flags::Protected]) || (aip->goals[0].ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISABLE_SHIP_TACTICAL | AI_GOAL_DISARM_SHIP | AI_GOAL_DISARM_SHIP_TACTICAL))) {
bool valid_secondary = ai_choose_secondary_weapon(Pl_objp, aip, En_objp);
int current_bank = tswp->current_secondary_bank;
if (current_bank > -1 && valid_secondary) {
weapon_info *swip = &Weapon_info[tswp->secondary_bank_weapons[current_bank]];
if(!(En_objp->flags[Object::Object_Flags::Protected]) || ((aip->goals[0].ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP)) && swip->wi_flags[Weapon::Info_Flags::Puncture] )) { //override lockdown on protected ships when using anti subsystem weapons - Valathil
if(!(En_objp->flags[Object::Object_Flags::Protected]) || ((aip->goals[0].ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISABLE_SHIP_TACTICAL | AI_GOAL_DISARM_SHIP | AI_GOAL_DISARM_SHIP_TACTICAL)) && swip->wi_flags[Weapon::Info_Flags::Puncture] )) { //override lockdown on protected ships when using anti subsystem weapons - Valathil
// If ship is protected and very low on hits, don't fire missiles.
if (!(En_objp->flags[Object::Object_Flags::Protected]) || (En_objp->hull_strength > 10*swip->damage)) {
if (aip->ai_flags[AI::AI_Flags::Unload_secondaries]) {
+348 -258
View File
File diff suppressed because it is too large. Load diff
+208 -147
View File
@@ -13,6 +13,7 @@
#include "ai/aigoals.h"
#include "ai/ailua.h"
#include "globalincs/linklist.h"
#include "globalincs/utility.h"
#include "mission/missionlog.h"
#include "mission/missionparse.h"
#include "network/multi.h"
@@ -50,6 +51,8 @@ struct ship_registry_entry;
// Goober5000 - okay, this seems really stupid. If any ship in the mission is assigned a goal
// in PURGE_GOALS_ALL_SHIPS, *every* other ship will have certain goals purged. So I added
// PURGE_GOALS_ONE_SHIP for goals which should only purge other goals in the one ship.
// Goober5000 - note that the new disable and disarm goals (AI_GOAL_DISABLE_SHIP_TACTICAL and
// AI_GOAL_DISARM_SHIP_TACTICAL) do not purge ANY goals, not even the ones in the one ship
#define PURGE_GOALS_ALL_SHIPS (AI_GOAL_IGNORE | AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP)
#define PURGE_GOALS_ONE_SHIP (AI_GOAL_IGNORE_NEW)
@@ -74,7 +77,9 @@ ai_goal_list Ai_goal_names[] =
{ "Attack wing", AI_GOAL_CHASE_WING, 0 },
{ "Guard ship", AI_GOAL_GUARD, 0 },
{ "Disable ship", AI_GOAL_DISABLE_SHIP, 0 },
{ "Disable ship (tactical)",AI_GOAL_DISABLE_SHIP_TACTICAL, 0 },
{ "Disarm ship", AI_GOAL_DISARM_SHIP, 0 },
{ "Disarm ship (tactical)", AI_GOAL_DISARM_SHIP_TACTICAL, 0 },
{ "Attack any", AI_GOAL_CHASE_ANY, 0 },
{ "Ignore ship", AI_GOAL_IGNORE, 0 },
{ "Ignore ship (new)", AI_GOAL_IGNORE_NEW, 0 },
@@ -119,8 +124,10 @@ const char *Ai_goal_text(int goal, int submode)
case AI_GOAL_GUARD_WING:
return XSTR( "guard ", 480);
case AI_GOAL_DISABLE_SHIP:
case AI_GOAL_DISABLE_SHIP_TACTICAL:
return XSTR( "disable ", 481);
case AI_GOAL_DISARM_SHIP:
case AI_GOAL_DISARM_SHIP_TACTICAL:
return XSTR( "disarm ", 482);
case AI_GOAL_EVADE_SHIP:
return XSTR( "evade ", 483);
@@ -527,11 +534,12 @@ void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list, ai_info *ai
// ignore goals should get rid of any kind of attack goal
case AI_GOAL_IGNORE:
case AI_GOAL_IGNORE_NEW:
if ( purge_ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP | AI_GOAL_CHASE | AI_GOAL_CHASE_WING | AI_GOAL_CHASE_SHIP_CLASS | AI_GOAL_DESTROY_SUBSYSTEM) )
if ( purge_ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISABLE_SHIP_TACTICAL | AI_GOAL_DISARM_SHIP | AI_GOAL_DISARM_SHIP_TACTICAL | AI_GOAL_CHASE | AI_GOAL_CHASE_WING | AI_GOAL_CHASE_SHIP_CLASS | AI_GOAL_DESTROY_SUBSYSTEM) )
purge_goal->flags.set(AI::Goal_Flags::Purge);
break;
// disarm/disable goals should remove attacks from certain ships types
// (but not tactical disarm/disable)
case AI_GOAL_DISARM_SHIP:
case AI_GOAL_DISABLE_SHIP:
if ( purge_ai_mode & (AI_GOAL_CHASE | AI_GOAL_CHASE_WING | AI_GOAL_CHASE_SHIP_CLASS) ) {
@@ -548,12 +556,17 @@ void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list, ai_info *ai
}
// grab the ship type of the ship that is being disarmed/disabled
ship_type_info *crippled_ships_type = &Ship_types[Ship_info[Ships[ship_index].ship_info_index].class_type];
int crippled_ship_type = Ship_info[Ships[ship_index].ship_info_index].class_type;
// work through all the ship types which to see if the class matching our ai ship must ignore the ship
if (ai_ship_type < 0 || crippled_ship_type < 0)
break;
ship_type_info *crippled_ship_type_info = &Ship_types[crippled_ship_type];
// work through all the ship types to see if the class matching our ai ship must ignore the ship
// being disarmed/disabled
for ( j=0 ; j < (int)crippled_ships_type->ai_cripple_ignores.size(); j++) {
if (crippled_ships_type->ai_cripple_ignores[j] == ai_ship_type) {
for ( j=0 ; j < (int)crippled_ship_type_info->ai_cripple_ignores.size(); j++) {
if (crippled_ship_type_info->ai_cripple_ignores[j] == ai_ship_type) {
purge_goal->flags.set(AI::Goal_Flags::Purge);
}
}
@@ -904,7 +917,7 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, char
int ref_type;
ref_type = Sexp_nodes[CDR(node)].subtype;
if (ref_type == SEXP_ATOM_STRING) { // referenced by name
if (ref_type == SEXP_ATOM_STRING || ref_type == SEXP_ATOM_CONTAINER_DATA) { // referenced by name
// save the waypoint path name -- the list will get resolved when the goal is checked
// for achievability.
aigp->target_name = ai_get_goal_target_name(CTEXT(CDR(node)), &aigp->target_name_index); // waypoint path name;
@@ -930,14 +943,16 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, char
break;
case OP_AI_DISABLE_SHIP:
aigp->ai_mode = AI_GOAL_DISABLE_SHIP;
case OP_AI_DISABLE_SHIP_TACTICAL:
aigp->ai_mode = (op == OP_AI_DISABLE_SHIP) ? AI_GOAL_DISABLE_SHIP : AI_GOAL_DISABLE_SHIP_TACTICAL;
aigp->target_name = ai_get_goal_target_name( CTEXT(CDR(node)), &aigp->target_name_index );
aigp->ai_submode = -SUBSYSTEM_ENGINE;
aigp->priority = atoi( CTEXT(CDR(CDR(node))) );
break;
case OP_AI_DISARM_SHIP:
aigp->ai_mode = AI_GOAL_DISARM_SHIP;
case OP_AI_DISARM_SHIP_TACTICAL:
aigp->ai_mode = (op == OP_AI_DISARM_SHIP) ? AI_GOAL_DISARM_SHIP : AI_GOAL_DISARM_SHIP_TACTICAL;
aigp->target_name = ai_get_goal_target_name( CTEXT(CDR(node)), &aigp->target_name_index );
aigp->ai_submode = -SUBSYSTEM_TURRET;
aigp->priority = atoi( CTEXT(CDR(CDR(node))) );
@@ -975,7 +990,7 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, char
// this goal needs some extra setup
// if this doesn't work, the goal will be immediately removed
auto ship_entry = ship_registry_get(aigp->target_name);
if (ship_entry->status == ShipStatus::PRESENT)
if (ship_entry && ship_entry->shipp)
{
auto target_aip = &Ai_info[ship_entry->shipp->ai_index];
target_aip->ai_flags.set(AI::AI_Flags::Awaiting_repair);
@@ -1021,15 +1036,32 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, char
aigp->ai_mode = AI_GOAL_KEEP_SAFE_DISTANCE;
break;
case OP_AI_FLY_TO_SHIP:
case OP_AI_STAY_NEAR_SHIP:
{
bool is_nan, is_nan_forever;
aigp->target_name = ai_get_goal_target_name( CTEXT(CDR(node)), &aigp->target_name_index );
aigp->priority = atoi( CTEXT(CDDR(node)) );
// distance from ship
if ( CDDDR(node) < 0 )
aigp->float_data = 300.0f;
else
aigp->float_data = i2fl(atoi( CTEXT(CDDDR(node)) ));
aigp->ai_mode = AI_GOAL_STAY_NEAR_SHIP;
aigp->float_data = i2fl(eval_num(CDDDR(node), is_nan, is_nan_forever));
// (the CDDDDR argument is whether to afterburn, and is handled at the end of the function, so don't handle it here)
// whether to "escort" the ship
if ( CDDDDDR(node) >= 0 )
aigp->int_data = is_sexp_true(CDDDDDR(node)) ? 1 : 0;
if (op == OP_AI_FLY_TO_SHIP)
aigp->ai_mode = AI_GOAL_FLY_TO_SHIP;
else
aigp->ai_mode = AI_GOAL_STAY_NEAR_SHIP;
break;
}
case OP_AI_FORM_ON_WING:
aigp->priority = 99;
@@ -1045,7 +1077,6 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, char
case OP_AI_EVADE_SHIP:
case OP_AI_IGNORE:
case OP_AI_IGNORE_NEW:
case OP_AI_FLY_TO_SHIP:
aigp->target_name = ai_get_goal_target_name( CTEXT(CDR(node)), &aigp->target_name_index );
aigp->priority = atoi( CTEXT(CDR(CDR(node))) );
@@ -1072,14 +1103,10 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, char
aigp->ai_mode = AI_GOAL_CHASE_WING;
} else if (op == OP_AI_CHASE_SHIP_CLASS) {
aigp->ai_mode = AI_GOAL_CHASE_SHIP_CLASS;
} else if ( op == OP_AI_STAY_NEAR_SHIP ) {
aigp->ai_mode = AI_GOAL_STAY_NEAR_SHIP;
} else if ( op == OP_AI_IGNORE ) {
aigp->ai_mode = AI_GOAL_IGNORE;
} else if ( op == OP_AI_IGNORE_NEW ) {
aigp->ai_mode = AI_GOAL_IGNORE_NEW;
} else if ( op == OP_AI_FLY_TO_SHIP ) {
aigp->ai_mode = AI_GOAL_FLY_TO_SHIP;
} else
UNREACHABLE("Coding error: unhandled AI goal in ai_add_goal_sub_sexp!");
@@ -1116,15 +1143,45 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, char
}
// Goober5000 - we now have an extra optional chase argument to allow chasing our own team
if ( op == OP_AI_CHASE || op == OP_AI_CHASE_WING || op == OP_AI_CHASE_SHIP_CLASS || op == OP_AI_DISABLE_SHIP || op == OP_AI_DISARM_SHIP ) {
if ((CDDDR(node) != -1) && is_sexp_true(CDDDR(node)))
if ( op == OP_AI_CHASE || op == OP_AI_CHASE_WING || op == OP_AI_CHASE_SHIP_CLASS
|| op == OP_AI_DISABLE_SHIP || op == OP_AI_DISABLE_SHIP_TACTICAL || op == OP_AI_DISARM_SHIP || op == OP_AI_DISARM_SHIP_TACTICAL ) {
if (is_sexp_true(CDDDR(node)))
aigp->flags.set(AI::Goal_Flags::Target_own_team);
}
if ( op == OP_AI_DESTROY_SUBSYS ) {
if ((CDDDDR(node) != -1) && is_sexp_true(CDDDDR(node)))
if (is_sexp_true(CDDDDR(node)))
aigp->flags.set(AI::Goal_Flags::Target_own_team);
}
// maybe get the afterburn hard flag
if (op == OP_AI_CHASE_ANY) {
if (is_sexp_true(CDDR(node)))
aigp->flags.set(AI::Goal_Flags::Afterburn_hard);
}
if (op == OP_AI_GUARD ||
op == OP_AI_GUARD_WING ||
op == OP_AI_WAYPOINTS ||
op == OP_AI_WAYPOINTS_ONCE) {
if (is_sexp_true(CDDDR(node)))
aigp->flags.set(AI::Goal_Flags::Afterburn_hard);
}
if (op == OP_AI_CHASE ||
op == OP_AI_CHASE_WING ||
op == OP_AI_CHASE_SHIP_CLASS ||
op == OP_AI_DISABLE_SHIP ||
op == OP_AI_DISABLE_SHIP_TACTICAL ||
op == OP_AI_DISARM_SHIP ||
op == OP_AI_DISARM_SHIP_TACTICAL ||
op == OP_AI_STAY_NEAR_SHIP ||
op == OP_AI_FLY_TO_SHIP) {
if (is_sexp_true(CDDDDR(node)))
aigp->flags.set(AI::Goal_Flags::Afterburn_hard);
}
if (op == OP_AI_DESTROY_SUBSYS || op == OP_AI_DOCK) {
if (is_sexp_true(CDDDDDR(node)))
aigp->flags.set(AI::Goal_Flags::Afterburn_hard);
}
// Goober5000 - since none of the goals act on the actor,
// don't assign the goal if the actor's goal target is itself
if (aigp->target_name != NULL && !strcmp(aigp->target_name, actor_name))
@@ -1191,11 +1248,13 @@ int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp )
priority = ( CDR( CDR( CDR(node) ) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( CDR( node ) ) ) ) ) : -1;
break;
case OP_AI_DISABLE_SHIP:
goalmode = AI_GOAL_DISABLE_SHIP;
case OP_AI_DISABLE_SHIP_TACTICAL:
goalmode = (op == OP_AI_DISABLE_SHIP) ? AI_GOAL_DISABLE_SHIP : AI_GOAL_DISABLE_SHIP_TACTICAL;
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
break;
case OP_AI_DISARM_SHIP:
goalmode = AI_GOAL_DISABLE_SHIP;
case OP_AI_DISARM_SHIP_TACTICAL:
goalmode = (op == OP_AI_DISARM_SHIP) ? AI_GOAL_DISARM_SHIP : AI_GOAL_DISARM_SHIP_TACTICAL;
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
break;
case OP_AI_WARP_OUT:
@@ -1225,11 +1284,8 @@ int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp )
priority = ( CDR(node) >= 0 ) ? atoi( CTEXT( CDR( node ) ) ) : -1;
break;
case OP_AI_PLAY_DEAD:
goalmode = AI_GOAL_PLAY_DEAD;
priority = ( CDR(node) >= 0 ) ? atoi( CTEXT( CDR( node ) ) ) : -1;
break;
case OP_AI_PLAY_DEAD_PERSISTENT:
goalmode = AI_GOAL_PLAY_DEAD_PERSISTENT;
goalmode = (op == OP_AI_PLAY_DEAD) ? AI_GOAL_PLAY_DEAD : AI_GOAL_PLAY_DEAD_PERSISTENT;
priority = ( CDR(node) >= 0 ) ? atoi( CTEXT( CDR( node ) ) ) : -1;
break;
case OP_AI_KEEP_SAFE_DISTANCE:
@@ -1271,12 +1327,9 @@ int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp )
goalmode = AI_GOAL_STAY_NEAR_SHIP;
break;
case OP_AI_IGNORE:
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
goalmode = AI_GOAL_IGNORE;
break;
case OP_AI_IGNORE_NEW:
priority = ( CDR( CDR(node) ) >= 0 ) ? atoi( CTEXT( CDR( CDR( node ) ) ) ) : -1;
goalmode = AI_GOAL_IGNORE_NEW;
goalmode = (op == OP_AI_IGNORE) ? AI_GOAL_IGNORE : AI_GOAL_IGNORE_NEW;
break;
case OP_AI_FORM_ON_WING:
priority = 99;
@@ -1498,13 +1551,11 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
{
int status;
ai_achievability return_val;
ai_info *aip;
int index = -1, sindex = -1;
int modelnum = -1;
auto objp = &Objects[objnum];
Assert( objp->instance != -1 );
aip = &Ai_info[Ships[objp->instance].ai_index];
auto shipp = &Ships[objp->instance];
auto aip = &Ai_info[shipp->ai_index];
// these orders are always achievable.
if ( (aigp->ai_mode == AI_GOAL_KEEP_SAFE_DISTANCE)
@@ -1515,11 +1566,11 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
if (aigp->ai_mode == AI_GOAL_LUA)
return ai_lua_is_achievable(aigp, objnum);
auto target_ship_entry = aigp->target_name == nullptr ? nullptr : ship_registry_get(aigp->target_name);
// warp (depart) only achievable if there's somewhere to depart to
if (aigp->ai_mode == AI_GOAL_WARP)
{
ship *shipp = &Ships[objp->instance];
// always valid if has working subspace drive, not disabled, and not limited by subsystem strength
if ( ship_can_warp_full_check(shipp) )
return ai_achievability::ACHIEVABLE;
@@ -1538,9 +1589,7 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// if the wing target is valid then be sure to set the override bit so that it always
// gets executed next
if ( aigp->ai_mode == AI_GOAL_FORM_ON_WING ) {
sindex = ship_name_lookup( aigp->target_name );
if (sindex < 0)
if (!target_ship_entry || !target_ship_entry->shipp)
return ai_achievability::NOT_ACHIEVABLE;
aigp->flags.set(AI::Goal_Flags::Goal_override);
@@ -1597,11 +1646,10 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// shipnum could be -1 depending on if the ship hasn't arrived or died. only look for subsystem
// destroyed when shipnum is valid
sindex = ship_name_lookup( aigp->target_name );
// can't determine the status of this goal if ship not valid
// or we haven't found a valid subsystem index yet
if ( (sindex == -1) || (aigp->flags[AI::Goal_Flags::Subsys_needs_fixup]) ) {
if ( !target_ship_entry || !target_ship_entry->shipp || (aigp->flags[AI::Goal_Flags::Subsys_needs_fixup]) ) {
status = 0;
break;
}
@@ -1610,46 +1658,46 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// as 0 so we can continue. (The subsystem name must be turned into an index into the ship's subsystems
// for this goal to be valid).
Assert ( aigp->ai_submode >= 0 );
ssp = ship_get_indexed_subsys( &Ships[sindex], aigp->ai_submode );
ssp = ship_get_indexed_subsys( target_ship_entry->shipp, aigp->ai_submode );
if (ssp != NULL) {
// see MWA 3/20/97 comment above - instead of checking the mission log, check the current hits
status = (ssp->current_hits <= 0.0f) ? 1 : 0;
} else {
// not supposed to ever happen, but could if there is a mismatch between the table and model subsystems
nprintf(("AI", "Couldn't find subsystem %d for ship %s\n", aigp->ai_submode, Ships[sindex].ship_name));
nprintf(("AI", "Couldn't find subsystem %d for ship %s\n", aigp->ai_submode, target_ship_entry->shipp->ship_name));
status = 0;
}
break;
}
case AI_GOAL_DISABLE_SHIP:
case AI_GOAL_DISABLE_SHIP_TACTICAL:
{
// shipnum could be -1 depending on if the ship hasn't arrived or died. only look for subsystem
// destroyed when shipnum is valid
sindex = ship_name_lookup(aigp->target_name);
// can't determine the status of this goal if ship not valid
if (sindex < 0) {
if (!target_ship_entry || !target_ship_entry->shipp) {
status = 0;
} else {
// see MWA 3/20/97 comment above - instead of checking the mission log, check the current hits
status = (Ships[sindex].subsys_info[SUBSYSTEM_ENGINE].aggregate_current_hits <= 0.0f) ? 1 : 0;
status = (target_ship_entry->shipp->subsys_info[SUBSYSTEM_ENGINE].aggregate_current_hits <= 0.0f) ? 1 : 0;
}
break;
}
case AI_GOAL_DISARM_SHIP:
case AI_GOAL_DISARM_SHIP_TACTICAL:
{
// shipnum could be -1 depending on if the ship hasn't arrived or died. only look for subsystem
// destroyed when shipnum is valid
sindex = ship_name_lookup(aigp->target_name);
// can't determine the status of this goal if ship not valid
if (sindex < 0) {
if (!target_ship_entry || !target_ship_entry->shipp) {
status = 0;
} else {
// see MWA 3/20/97 comment above - instead of checking the mission log, check the current hits
status = (Ships[sindex].subsys_info[SUBSYSTEM_TURRET].aggregate_current_hits <= 0.0f) ? 1 : 0;
status = (target_ship_entry->shipp->subsys_info[SUBSYSTEM_TURRET].aggregate_current_hits <= 0.0f) ? 1 : 0;
}
break;
}
@@ -1668,22 +1716,23 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// MWA -- 4/22/98. Check for the ship actually being in the mission before
// checking departure and destroyed. In multiplayer, since ships can respawn,
// they get log entries for being destroyed even though they have respawned.
sindex = ship_name_lookup( aigp->target_name );
if ( sindex < 0 ) {
status = mission_log_get_time( LOG_SHIP_DEPARTED, aigp->target_name, NULL, NULL);
if ( !status ) {
status = mission_log_get_time( LOG_SHIP_DESTROYED, aigp->target_name, NULL, NULL);
if ( !status ) {
status = mission_log_get_time( LOG_SELF_DESTRUCTED, aigp->target_name, NULL, NULL);
}
}
if ( status )
return_val = ai_achievability::NOT_ACHIEVABLE;
// Goober5000 - update this to use ship registry status with similar logic
if (target_ship_entry && target_ship_entry->status == ShipStatus::EXITED) {
status = 1;
return_val = ai_achievability::NOT_ACHIEVABLE;
} else {
status = 0;
}
// fly-to-ship can potentially be determined
if (aigp->ai_mode == AI_GOAL_FLY_TO_SHIP && target_ship_entry && target_ship_entry->objp) {
auto dist = vm_vec_dist(&target_ship_entry->objp->pos, &objp->pos);
if (dist < aigp->float_data) {
return_val = ai_achievability::SATISFIED;
status = 1;
}
}
break;
}
@@ -1721,7 +1770,7 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
}
default:
Int3();
UNREACHABLE("Unhandled AI goal %d", aigp->ai_mode);
status = 0;
break;
}
@@ -1736,12 +1785,12 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// the if statement.
if ( (aigp->ai_mode == AI_GOAL_CHASE_WING) || (aigp->ai_mode == AI_GOAL_GUARD_WING) )
{
sindex = wing_name_lookup( aigp->target_name );
int wingnum = wing_name_lookup( aigp->target_name );
if (sindex < 0)
if (wingnum < 0)
return ai_achievability::NOT_KNOWN;
wing *wingp = &Wings[sindex];
wing *wingp = &Wings[wingnum];
if ( wingp->flags[Ship::Wing_Flags::Gone] )
return ai_achievability::NOT_ACHIEVABLE;
@@ -1758,24 +1807,22 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
}
else
{
auto ship_entry = ship_registry_get(aigp->target_name);
if (!ship_entry)
if (!target_ship_entry)
{
status = SHIP_STATUS_UNKNOWN;
}
// goal ship is currently in mission
else if (ship_entry->status == ShipStatus::PRESENT)
else if (target_ship_entry->status == ShipStatus::PRESENT || target_ship_entry->status == ShipStatus::DEATH_ROLL)
{
status = SHIP_STATUS_ARRIVED;
}
// goal ship is still on the arrival list
else if (ship_entry->status == ShipStatus::NOT_YET_PRESENT)
else if (target_ship_entry->status == ShipStatus::NOT_YET_PRESENT)
{
status = SHIP_STATUS_NOT_ARRIVED;
}
// goal ship has left the area
else if (ship_entry->status == ShipStatus::EXITED)
else if (target_ship_entry->status == ShipStatus::EXITED)
{
status = SHIP_STATUS_GONE;
}
@@ -1786,16 +1833,21 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
if (status == SHIP_STATUS_UNKNOWN)
{
mprintf(("Potentially incorrect behaviour in AI goal for ship %s: Ship %s could not be found among currently active, departed, or yet-to-arrive ships.\nPlease check the mission file.\n", Ships[objp->instance].ship_name, aigp->target_name));
mprintf(("Potentially incorrect behaviour in AI goal for ship %s: Ship %s could not be found among currently active, departed, or yet-to-arrive ships.\nPlease check the mission file.\n", shipp->ship_name, aigp->target_name));
}
}
// Goober5000 - before doing anything else, check if this is a disarm goal for an arrived ship...
if ((status == SHIP_STATUS_ARRIVED) && (aigp->ai_mode == AI_GOAL_DISARM_SHIP))
if ((status == SHIP_STATUS_ARRIVED) && (aigp->ai_mode == AI_GOAL_DISARM_SHIP || aigp->ai_mode == AI_GOAL_DISARM_SHIP_TACTICAL))
{
// if the ship has no turrets, we can't disarm it!
if (Ships[ship_name_lookup(aigp->target_name)].subsys_info[SUBSYSTEM_TURRET].type_count == 0)
return ai_achievability::NOT_ACHIEVABLE;
if (target_ship_entry && target_ship_entry->shipp) {
// if the ship has no turrets, we can't disarm it!
if (target_ship_entry->shipp->subsys_info[SUBSYSTEM_TURRET].type_count == 0)
return ai_achievability::NOT_ACHIEVABLE;
} else {
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
return ai_achievability::NOT_ACHIEVABLE; // force this goal to be invalid
}
}
// if the goal is an ignore/disable/disarm goal, then
@@ -1817,37 +1869,36 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// this goal will get removed.
if ( (aigp->ai_mode == AI_GOAL_DOCK) && (status == SHIP_STATUS_ARRIVED) ) {
if (!(aigp->flags[AI::Goal_Flags::Docker_index_valid])) {
modelnum = Ship_info[Ships[objp->instance].ship_info_index].model_num;
int modelnum = Ship_info[shipp->ship_info_index].model_num;
Assert( modelnum >= 0 );
index = model_find_dock_name_index(modelnum, aigp->docker.name);
aigp->docker.index = index;
aigp->docker.index = model_find_dock_name_index(modelnum, aigp->docker.name);
aigp->flags.set(AI::Goal_Flags::Docker_index_valid);
}
if (!(aigp->flags[AI::Goal_Flags::Dockee_index_valid])) {
sindex = ship_name_lookup(aigp->target_name);
if ( sindex != -1 ) {
modelnum = Ship_info[Ships[sindex].ship_info_index].model_num;
index = model_find_dock_name_index(modelnum, aigp->dockee.name);
aigp->dockee.index = index;
if (target_ship_entry && target_ship_entry->shipp) {
int modelnum = Ship_info[target_ship_entry->shipp->ship_info_index].model_num;
aigp->dockee.index = model_find_dock_name_index(modelnum, aigp->dockee.name);
aigp->flags.set(AI::Goal_Flags::Dockee_index_valid);
} else
aigp->dockee.index = -1; // this will force code into if statement below making goal not achievable.
}
if ( (aigp->dockee.index == -1) || (aigp->docker.index == -1) ) {
Int3(); // for now, allender wants to know about these things!!!!
Warning(LOCATION, "Cannot determine docking information for %s!", shipp->ship_name); // for now, allender wants to know about these things!!!!
return ai_achievability::NOT_ACHIEVABLE;
}
// if ship is disabled, don't know if it can dock or not
if ( Ships[objp->instance].flags[Ship::Ship_Flags::Disabled] )
if ( shipp->flags[Ship::Ship_Flags::Disabled] )
return ai_achievability::NOT_KNOWN;
// we must also determine if we're prevented from docking for any reason
sindex = ship_name_lookup(aigp->target_name);
Assert( sindex >= 0 );
object *goal_objp = &Objects[Ships[sindex].objnum];
if (!target_ship_entry || !target_ship_entry->shipp) {
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
return ai_achievability::NOT_ACHIEVABLE; // force this goal to be invalid
}
auto goal_objp = target_ship_entry->objp;
// if the ship that I am supposed to dock with is docked with something else, then I need to put my goal on hold
// [MK, 4/23/98: With Mark, we believe this fixes the problem of Comet refusing to warp out after docking with Omega.
@@ -1896,9 +1947,14 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// might happen too, so err on the safe side. (Yay for emergent paragraph justification!)
if ((aip->mode == AIM_DOCK) && (aip->submode >= AIS_UNDOCK_0))
{
// only put it on hold if it's someone other than the guy we're undocking from right now!!
if (aip->goal_objnum != Ships[ship_name_lookup(aigp->target_name)].objnum)
return ai_achievability::NOT_KNOWN;
if ( target_ship_entry && target_ship_entry->shipp ) {
// only put it on hold if it's someone other than the guy we're undocking from right now!!
if (aip->goal_objnum != target_ship_entry->shipp->objnum)
return ai_achievability::NOT_KNOWN;
} else {
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
return ai_achievability::NOT_ACHIEVABLE; // force this goal to be invalid
}
}
} else if ( (aigp->ai_mode == AI_GOAL_DESTROY_SUBSYSTEM) && (status == SHIP_STATUS_ARRIVED) ) {
@@ -1906,23 +1962,21 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// have fixed up the subsystem name (of the subsystem to destroy) into an index into
// the ship's subsystem list
if ( aigp->flags[AI::Goal_Flags::Subsys_needs_fixup] ) {
sindex = ship_name_lookup( aigp->target_name );
if ( sindex != -1 ) {
aigp->ai_submode = ship_find_subsys( &Ships[sindex], aigp->docker.name );
if ( target_ship_entry && target_ship_entry->shipp ) {
aigp->ai_submode = ship_find_subsys( target_ship_entry->shipp, aigp->docker.name );
aigp->flags.remove(AI::Goal_Flags::Subsys_needs_fixup);
} else {
Int3();
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
return ai_achievability::NOT_ACHIEVABLE; // force this goal to be invalid
}
}
} else if ( ((aigp->ai_mode == AI_GOAL_IGNORE) || (aigp->ai_mode == AI_GOAL_IGNORE_NEW)) && (status == SHIP_STATUS_ARRIVED) ) {
object *ignored;
// for ignoring a ship, call the ai_ignore object function, then declare the goal satisfied
sindex = ship_name_lookup( aigp->target_name );
Assert( sindex != -1 ); // should be true because of above status
ignored = &Objects[Ships[sindex].objnum];
if (!target_ship_entry || !target_ship_entry->shipp) {
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
return ai_achievability::NOT_ACHIEVABLE; // force this goal to be invalid
}
auto ignored = target_ship_entry->objp;
ai_ignore_object(objp, ignored, (aigp->ai_mode == AI_GOAL_IGNORE_NEW));
@@ -1938,7 +1992,9 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
case AI_GOAL_GUARD:
case AI_GOAL_GUARD_WING:
case AI_GOAL_DISABLE_SHIP:
case AI_GOAL_DISABLE_SHIP_TACTICAL:
case AI_GOAL_DISARM_SHIP:
case AI_GOAL_DISARM_SHIP_TACTICAL:
case AI_GOAL_DESTROY_SUBSYSTEM:
case AI_GOAL_IGNORE:
case AI_GOAL_IGNORE_NEW:
@@ -1955,7 +2011,7 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
else if ( status == SHIP_STATUS_UNKNOWN )
return ai_achievability::NOT_KNOWN;
Int3(); // get allender -- bad logic
UNREACHABLE("Invalid status variable %d for ship %s; get Allender or a SCP member", status, shipp->ship_name); // get allender -- bad logic
break;
}
@@ -1967,31 +2023,29 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// short circuit a couple of cases. Ship not arrived shouldn't happen. Ship gone means
// we mark the goal as not achievable.
if ( status == SHIP_STATUS_NOT_ARRIVED ) {
Int3(); // get Allender. this shouldn't happen!!!
UNREACHABLE("Ship %s cannot rearm a target %s that hasn't arrived; get Allender or a SCP member", shipp->ship_name, aigp->target_name); // get Allender. this shouldn't happen!!!
return ai_achievability::NOT_ACHIEVABLE;
}
if ( status == SHIP_STATUS_GONE )
return ai_achievability::NOT_ACHIEVABLE;
sindex = ship_name_lookup( aigp->target_name );
if ( sindex < 0 ) {
Int3();
if ( !target_ship_entry || !target_ship_entry->shipp ) {
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
return ai_achievability::NOT_ACHIEVABLE;
}
// if desitnation currently being repaired, then goal is stil active
if ( Ai_info[Ships[sindex].ai_index].ai_flags[AI::AI_Flags::Being_repaired] )
// if destination currently being repaired, then goal is still active
if ( Ai_info[target_ship_entry->shipp->ai_index].ai_flags[AI::AI_Flags::Being_repaired] )
return ai_achievability::ACHIEVABLE;
// if the destination ship is dying or departing (but not completed yet), the mark goal as
// not achievable.
if ( Ships[sindex].is_dying_or_departing())
if ( target_ship_entry->shipp->is_dying_or_departing())
return ai_achievability::NOT_ACHIEVABLE;
// if the destination object is no longer awaiting repair, then remove the item
if ( !(Ai_info[Ships[sindex].ai_index].ai_flags[AI::AI_Flags::Awaiting_repair]) )
if ( !(Ai_info[target_ship_entry->shipp->ai_index].ai_flags[AI::AI_Flags::Awaiting_repair]) )
return ai_achievability::NOT_ACHIEVABLE;
// not repairing anything means that he can do this goal!!!
@@ -2006,14 +2060,14 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// if he is repairing something, he can satisfy his repair goal (his goal_objnum)
// return GOAL_NOT_KNOWN which is kind of a hack which puts the goal on hold until it can be
// satisfied.
if ( aip->goal_objnum != Ships[sindex].objnum )
if ( aip->goal_objnum != target_ship_entry->shipp->objnum )
return ai_achievability::NOT_KNOWN;
return ai_achievability::ACHIEVABLE;
}
default:
Int3(); // invalid case in switch:
UNREACHABLE("Unhandled AI goal %d", aigp->ai_mode); // invalid case in switch:
}
return ai_achievability::NOT_KNOWN;
@@ -2124,11 +2178,11 @@ void validate_mission_goals(int objnum, ai_info *aip)
if ( (aip->goals[0].ai_mode != AI_GOAL_NONE) && (aip->goals[0].flags[AI::Goal_Flags::Goal_on_hold]) )
aip->mode = AIM_NONE;
// if the active goal is a rearm/repair goal, the put all other valid goals (which are not repair goals)
// on hold
if ( (aip->goals[0].ai_mode == AI_GOAL_REARM_REPAIR) && object_is_docked(&Objects[objnum]) ) {
// if the active goal is a rearm/repair or undock goal,
// then put all other valid goals (which are not rearm/repair or undock goals) on hold
if ( (aip->goals[0].ai_mode == AI_GOAL_REARM_REPAIR || aip->goals[0].ai_mode == AI_GOAL_UNDOCK) && object_is_docked(&Objects[objnum]) ) {
for ( i = 1; i < MAX_AI_GOALS; i++ ) {
if ( (aip->goals[i].ai_mode == AI_GOAL_NONE) || (aip->goals[i].ai_mode == AI_GOAL_REARM_REPAIR) )
if ( aip->goals[i].ai_mode == AI_GOAL_NONE || aip->goals[i].ai_mode == AI_GOAL_REARM_REPAIR || aip->goals[i].ai_mode == AI_GOAL_UNDOCK )
continue;
aip->goals[i].flags.set(AI::Goal_Flags::Goal_on_hold);
}
@@ -2287,12 +2341,6 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
break;
}
case AI_GOAL_FLY_TO_SHIP:
shipnum = ship_name_lookup( current_goal->target_name );
Assert (shipnum != -1 ); // shouldn't get here if this is false!!!!
ai_start_fly_to_ship(objp, shipnum);
break;
case AI_GOAL_DOCK: {
shipnum = ship_name_lookup( current_goal->target_name );
Assert (shipnum != -1 ); // shouldn't get here if this is false!!!!
@@ -2367,22 +2415,27 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
break;
// when destroying a subsystem, we can destroy a specific instance of a subsystem
// or all instances of a type of subsystem (i.e. a specific engine or all engines).
// the ai_submode value is > 0 for a specific instance of subsystem and < 0 for all
// instances of a specific type
// when destroying a subsystem, we can destroy a specific instance of a subsystem
// or all instances of a type of subsystem (i.e. a specific engine or all engines).
// the ai_submode value is > 0 for a specific instance of subsystem and < 0 for all
// instances of a specific type
case AI_GOAL_DESTROY_SUBSYSTEM:
case AI_GOAL_DISABLE_SHIP:
case AI_GOAL_DISARM_SHIP: {
case AI_GOAL_DISABLE_SHIP_TACTICAL:
case AI_GOAL_DISARM_SHIP:
case AI_GOAL_DISARM_SHIP_TACTICAL: {
shipnum = ship_name_lookup( current_goal->target_name );
Assert( shipnum >= 0 );
other_obj = &Objects[Ships[shipnum].objnum];
ai_attack_object( objp, other_obj);
ai_set_attack_subsystem( objp, current_goal->ai_submode ); // submode stored the subsystem type
if (current_goal->ai_mode != AI_GOAL_DESTROY_SUBSYSTEM) {
// don't protect-ship for tactical goals
if (current_goal->ai_mode != AI_GOAL_DESTROY_SUBSYSTEM && current_goal->ai_mode != AI_GOAL_DISABLE_SHIP_TACTICAL && current_goal->ai_mode != AI_GOAL_DISARM_SHIP_TACTICAL) {
if (aip->target_objnum != -1) {
int class_type = Ship_info[Ships[shipnum].ship_info_index].class_type;
// Only protect if _not_ a capital ship. We don't want the Lucifer accidentally getting protected.
if (Ship_types[Ship_info[Ships[shipnum].ship_info_index].class_type].flags[Ship::Type_Info_Flags::AI_protected_on_cripple])
if (class_type >= 0 && Ship_types[class_type].flags[Ship::Type_Info_Flags::AI_protected_on_cripple])
Objects[aip->target_objnum].flags.set(Object::Object_Flags::Protected);
}
} else // Just in case this ship had been protected, unprotect it.
@@ -2460,14 +2513,17 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
// labels for support ship commands
case AI_GOAL_STAY_NEAR_SHIP: {
case AI_GOAL_STAY_NEAR_SHIP:
case AI_GOAL_FLY_TO_SHIP:
{
shipnum = ship_name_lookup( current_goal->target_name );
Assert( shipnum >= 0 );
other_obj = &Objects[Ships[shipnum].objnum];
float dist = current_goal->float_data; // How far away to stay from ship. Should be set in SEXP?
ai_do_stay_near(objp, other_obj, dist);
int additional_data = current_goal->int_data; // Whether to target a particular point as if escorting
ai_do_stay_near(objp, other_obj, dist, additional_data);
break;
}
}
case AI_GOAL_KEEP_SAFE_DISTANCE:
// todo MK: hook to keep support ship at a safe distance
@@ -2496,7 +2552,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
ai_formation_object_recalculate_slotnums(old_form_objnum);
}
void ai_update_goal_references(ai_goal *goals, int type, const char *old_name, const char *new_name)
void ai_update_goal_references(ai_goal *goals, sexp_ref_type type, const char *old_name, const char *new_name)
{
int i, mode, flag, dummy;
@@ -2506,8 +2562,8 @@ void ai_update_goal_references(ai_goal *goals, int type, const char *old_name, c
flag = 0;
switch (type)
{
case REF_TYPE_SHIP:
case REF_TYPE_PLAYER:
case sexp_ref_type::SHIP:
case sexp_ref_type::PLAYER:
switch (mode)
{
case AI_GOAL_CHASE:
@@ -2515,7 +2571,9 @@ void ai_update_goal_references(ai_goal *goals, int type, const char *old_name, c
case AI_GOAL_DESTROY_SUBSYSTEM:
case AI_GOAL_GUARD:
case AI_GOAL_DISABLE_SHIP:
case AI_GOAL_DISABLE_SHIP_TACTICAL:
case AI_GOAL_DISARM_SHIP:
case AI_GOAL_DISARM_SHIP_TACTICAL:
case AI_GOAL_IGNORE:
case AI_GOAL_IGNORE_NEW:
case AI_GOAL_EVADE_SHIP:
@@ -2524,7 +2582,7 @@ void ai_update_goal_references(ai_goal *goals, int type, const char *old_name, c
}
break;
case REF_TYPE_WING:
case sexp_ref_type::WING:
switch (mode)
{
case AI_GOAL_CHASE_WING:
@@ -2533,7 +2591,7 @@ void ai_update_goal_references(ai_goal *goals, int type, const char *old_name, c
}
break;
case REF_TYPE_WAYPOINT:
case sexp_ref_type::WAYPOINT:
switch (mode)
{
case AI_GOAL_WAYPOINTS:
@@ -2542,7 +2600,7 @@ void ai_update_goal_references(ai_goal *goals, int type, const char *old_name, c
}
break;
case REF_TYPE_PATH:
case sexp_ref_type::WAYPOINT_PATH:
switch (mode)
{
case AI_GOAL_WAYPOINTS:
@@ -2553,7 +2611,7 @@ void ai_update_goal_references(ai_goal *goals, int type, const char *old_name, c
break;
default:
Warning(LOCATION, "unhandled FRED reference type %d in ai_update_goal_references", type);
Warning(LOCATION, "unhandled FRED reference type %d in ai_update_goal_references", static_cast<int>(type));
break;
}
@@ -2570,7 +2628,7 @@ void ai_update_goal_references(ai_goal *goals, int type, const char *old_name, c
}
}
int query_referenced_in_ai_goals(ai_goal *goals, int type, const char *name)
bool query_referenced_in_ai_goals(ai_goal *goals, sexp_ref_type type, const char *name)
{
int i, mode, flag;
@@ -2580,7 +2638,8 @@ int query_referenced_in_ai_goals(ai_goal *goals, int type, const char *name)
flag = 0;
switch (type)
{
case REF_TYPE_SHIP:
case sexp_ref_type::SHIP:
case sexp_ref_type::PLAYER:
switch (mode)
{
case AI_GOAL_CHASE:
@@ -2588,7 +2647,9 @@ int query_referenced_in_ai_goals(ai_goal *goals, int type, const char *name)
case AI_GOAL_DESTROY_SUBSYSTEM:
case AI_GOAL_GUARD:
case AI_GOAL_DISABLE_SHIP:
case AI_GOAL_DISABLE_SHIP_TACTICAL:
case AI_GOAL_DISARM_SHIP:
case AI_GOAL_DISARM_SHIP_TACTICAL:
case AI_GOAL_IGNORE:
case AI_GOAL_IGNORE_NEW:
case AI_GOAL_EVADE_SHIP:
@@ -2597,7 +2658,7 @@ int query_referenced_in_ai_goals(ai_goal *goals, int type, const char *name)
}
break;
case REF_TYPE_WING:
case sexp_ref_type::WING:
switch (mode)
{
case AI_GOAL_CHASE_WING:
@@ -2606,7 +2667,7 @@ int query_referenced_in_ai_goals(ai_goal *goals, int type, const char *name)
}
break;
case REF_TYPE_WAYPOINT:
case sexp_ref_type::WAYPOINT:
switch (mode)
{
case AI_GOAL_WAYPOINTS:
@@ -2615,7 +2676,7 @@ int query_referenced_in_ai_goals(ai_goal *goals, int type, const char *name)
}
break;
case REF_TYPE_PATH:
case sexp_ref_type::WAYPOINT_PATH:
switch (mode)
{
case AI_GOAL_WAYPOINTS:
@@ -2628,11 +2689,11 @@ int query_referenced_in_ai_goals(ai_goal *goals, int type, const char *name)
if (flag) // is this a valid goal to parse for this conversion?
{
if (!stricmp(goals[i].target_name, name))
return 1;
return true;
}
}
return 0;
return false;
}
char *ai_add_dock_name(const char *str)
+7 -5
View File
@@ -73,15 +73,17 @@ struct ai_info;
#define AI_GOAL_FLY_TO_SHIP (1<<23) // 0x00800000
#define AI_GOAL_IGNORE_NEW (1<<24) // 0x01000000
#define AI_GOAL_CHASE_SHIP_CLASS (1<<25) // 0x02000000
#define AI_GOAL_PLAY_DEAD_PERSISTENT (1<<26) // 0x03000000
#define AI_GOAL_LUA (1<<27) // 0x04000000
#define AI_GOAL_PLAY_DEAD_PERSISTENT (1<<26) // 0x04000000
#define AI_GOAL_LUA (1<<27) // 0x08000000
#define AI_GOAL_DISARM_SHIP_TACTICAL (1<<28) // 0x10000000
#define AI_GOAL_DISABLE_SHIP_TACTICAL (1<<29) // 0x20000000
// now the masks for ship types
// Goober5000: added AI_GOAL_STAY_NEAR_SHIP and AI_GOAL_KEEP_SAFE_DISTANCE as valid for fighters
//WMC - Don't need these anymore. Whee!
/*
#define AI_GOAL_ACCEPT_FIGHTER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_CHASE | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_WARP | AI_GOAL_DESTROY_SUBSYSTEM | AI_GOAL_CHASE_WING | AI_GOAL_GUARD | AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP | AI_GOAL_CHASE_ANY | AI_GOAL_IGNORE | AI_GOAL_IGNORE_NEW | AI_GOAL_GUARD_WING | AI_GOAL_EVADE_SHIP | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_PLAY_DEAD_PERSISTENT | AI_GOAL_STAY_NEAR_SHIP | AI_GOAL_KEEP_SAFE_DISTANCE )
#define AI_GOAL_ACCEPT_FIGHTER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_CHASE | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_WARP | AI_GOAL_DESTROY_SUBSYSTEM | AI_GOAL_CHASE_WING | AI_GOAL_GUARD | AI_GOAL_DISABLE_SHIP | AI_GOAL_DISABLE_SHIP_TACTICAL | AI_GOAL_DISARM_SHIP | AI_GOAL_DISARM_SHIP_TACTICAL | AI_GOAL_CHASE_ANY | AI_GOAL_IGNORE | AI_GOAL_IGNORE_NEW | AI_GOAL_GUARD_WING | AI_GOAL_EVADE_SHIP | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_PLAY_DEAD_PERSISTENT | AI_GOAL_STAY_NEAR_SHIP | AI_GOAL_KEEP_SAFE_DISTANCE )
#define AI_GOAL_ACCEPT_BOMBER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_FIGHTER | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_STEALTH ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_FIGHTER | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_TRANSPORT ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_CHASE | AI_GOAL_CHASE_WING | AI_GOAL_DOCK | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_WARP | AI_GOAL_UNDOCK | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_PLAY_DEAD_PERSISTENT | AI_GOAL_STAY_NEAR_SHIP )
@@ -187,8 +189,8 @@ extern void ai_copy_mission_wing_goal( ai_goal *aigp, ai_info *aip );
extern void ai_mission_goal_complete( ai_info *aip );
extern void ai_mission_wing_goal_complete( int wingnum, ai_goal *remove_goalp );
extern void ai_update_goal_references(ai_goal *goals, int type, const char *old_name, const char *new_name);
extern int query_referenced_in_ai_goals(ai_goal *goals, int type, const char *name);
extern void ai_update_goal_references(ai_goal *goals, sexp_ref_type type, const char *old_name, const char *new_name);
extern bool query_referenced_in_ai_goals(ai_goal *goals, sexp_ref_type type, const char *name);
extern char *ai_add_dock_name(const char *str);
extern int ai_query_goal_valid( int ship, int ai_goal_type );
+180 -5
View File
@@ -18,9 +18,9 @@ void ai_lua_add_mode(int sexp_op, const ai_mode_lua& mode) {
}
bool ai_lua_add_order(int sexp_op, player_order_lua order) {
Player_orders.emplace_back(vm_strdup(order.parseText.c_str()), vm_strdup(order.displayText.c_str()), -1, sexp_op);
Player_orders.emplace_back(order.parseText, order.displayText, -1, sexp_op);
Player_orders.back().localize();
Lua_player_orders.emplace(sexp_op, std::move(order));
return true;
@@ -48,6 +48,134 @@ const player_order_lua* ai_lua_find_player_order(int sexp_op) {
return &aiLuaOrder->second;
}
int ai_lua_get_num_general_orders() {
int count = 0;
for (const auto& order : Lua_player_orders) {
if (order.second.generalOrder) {
count++;
}
}
return count;
}
SCP_vector<SCP_string> ai_lua_get_general_order_categories(bool enabled_only)
{
SCP_vector<SCP_string> list;
for (const auto& order : Lua_player_orders) {
const SCP_string &cat = order.second.category;
// If it's not a general order then move on
if (!order.second.generalOrder) {
continue;
}
// If the order is not enabled then move on
if (enabled_only && !order.second.cur_enabled) {
continue;
}
Assertion((cat.length() > 0), "Lua general orders category name must be longer than 0 characters!");
for (size_t i = 0; i <= list.size(); i++) {
// reached the end of the list, so add it
if (i == list.size()) {
list.push_back(cat);
break;
}
// if it's already in the list then don't add it
if (cat == list[i]) {
break;
}
}
}
return list;
}
SCP_vector<SCP_string> ai_lua_get_general_orders(bool onlyEnabled, bool onlyValid, const SCP_string& category)
{
SCP_vector<SCP_string> list;
for (auto order : Lua_player_orders) {
if (order.second.generalOrder) {
bool add = false;
// Only enabled orders
if (onlyEnabled && order.second.cur_enabled) {
add = true;
// Only valid orders
} else if (onlyValid && order.second.cur_valid) {
add = true;
// Only orders that match the category requested
} else if ((!category.empty()) && (order.second.category == category)) {
add = true;
// All general orders
} else {
add = true;
}
if (add) {
list.push_back(order.second.parseText);
}
}
}
return list;
}
int ai_lua_find_general_order_id(const SCP_string& name) {
for (const auto& order : Lua_player_orders) {
if (order.second.parseText == name) {
return order.first;
}
}
return -1;
}
void ai_lua_enable_general_order(int sexp_op, bool enable) {
auto aiLuaOrder = Lua_player_orders.find(sexp_op);
if (aiLuaOrder == Lua_player_orders.end())
return;
else
aiLuaOrder->second.cur_enabled = enable;
}
void ai_lua_validate_general_order(int sexp_op, bool validity)
{
auto aiLuaOrder = Lua_player_orders.find(sexp_op);
if (aiLuaOrder == Lua_player_orders.end())
return;
else
aiLuaOrder->second.cur_valid = validity;
}
void ai_lua_reset_general_orders() {
for (auto order : Lua_player_orders) {
ai_lua_enable_general_order(order.first, false);
ai_lua_validate_general_order(order.first, false);
}
}
bool ai_lua_is_general_order(int sexp_op) {
auto aiLuaOrder = Lua_player_orders.find(sexp_op);
if (aiLuaOrder == Lua_player_orders.end())
return false;
return aiLuaOrder->second.generalOrder;
}
void run_ai_lua_action(const luacpp::LuaFunction& action, const ai_mode_lua& lua_ai, ai_info* aip) {
if (!action.isValid()) {
Error(LOCATION,
@@ -56,7 +184,11 @@ void run_ai_lua_action(const luacpp::LuaFunction& action, const ai_mode_lua& lua
}
luacpp::LuaValueList luaParameters;
luaParameters.push_back(luacpp::LuaValue::createValue(action.getLuaState(), scripting::api::l_AI_Helper.Set(object_h(&Objects[Ships[aip->shipnum].objnum]))));
if (aip->shipnum >= 0){
luaParameters.push_back(luacpp::LuaValue::createValue(action.getLuaState(), scripting::api::l_AI_Helper.Set(object_h(&Objects[Ships[aip->shipnum].objnum]))));
} else {
luaParameters.push_back(luacpp::LuaValue::createValue(action.getLuaState(), scripting::api::l_AI_Helper.Set(object_h())));
}
if (lua_ai.needsTarget) {
luaParameters.push_back(luacpp::LuaValue::createValue(action.getLuaState(), scripting::api::l_OSWPT.Set(aip->lua_ai_target.target)));
}
@@ -67,8 +199,13 @@ void run_ai_lua_action(const luacpp::LuaFunction& action, const ai_mode_lua& lua
auto retVals = action.call(Script_system.GetLuaSession(), luaParameters);
if (!retVals.empty() && retVals[0].getValueType() == luacpp::ValueType::BOOLEAN) {
if (retVals[0].getValue<bool>())
ai_mission_goal_complete(aip);
if (retVals[0].getValue<bool>()) {
// If we don't have a ship then it's a general order and we have nothing else to do
if (aip->shipnum >= 0) {
ai_mission_goal_complete(aip);
}
}
}
}
@@ -103,6 +240,26 @@ void ai_lua_start(ai_goal* aigp, object* objp){
run_ai_lua_action(action, lua_ai, aip);
}
// For sending general orders that don't run on a ship.
// Essentially just runs arbitrary lua script when the command is called
void ai_lua_start_general(int lua_sexp_id, int target_objnum)
{
//Create a dummy aip to pass the target data
ai_info aip;
aip.shipnum = -1;
if (target_objnum >= 0) {
aip.lua_ai_target = {object_ship_wing_point_team(&Ships[Objects[target_objnum].instance]), {}};
}
const auto& lua_ai = ai_lua_find_mode(lua_sexp_id);
const auto& lua_ai_sexp = lua_ai->sexp;
const auto& action = lua_ai_sexp.getActionEnter();
run_ai_lua_action(action, *lua_ai, &aip);
}
bool ai_lua_is_valid_target_intrinsic(int sexp_op, int target_objnum, ship* self) {
ship* target = &Ships[Objects[target_objnum].instance];
@@ -186,6 +343,24 @@ bool ai_lua_is_valid_target(int sexp_op, int target_objnum, ship* self, size_t o
return ai_lua_is_valid_target_lua(mode, target_objnum, self);
}
bool ai_lua_is_valid_ship(int sexp_op, bool isWing, ship* self)
{
const player_order_lua& order = *ai_lua_find_player_order(sexp_op);
switch (order.shipRestrictions) {
case player_order_lua::ship_restrictions::ANY:
return true;
case player_order_lua::ship_restrictions::WING:
return isWing;
case player_order_lua::ship_restrictions::IN_PLAYER_WING:
return self->wingnum != -1 && Ships[Player_obj->instance].wingnum == self->wingnum;
case player_order_lua::ship_restrictions::PLAYER_WING:
return isWing && self->wingnum != -1 && Ships[Player_obj->instance].wingnum == self->wingnum;
}
return false;
}
ai_achievability ai_lua_is_achievable(const ai_goal* aigp, int objnum){
const auto& lua_ai = Lua_ai_modes.at(aigp->ai_submode);
+15
View File
@@ -19,7 +19,12 @@ struct player_order_lua {
int ai_message = MESSAGE_YESSIR;
SCP_string parseText = "";
SCP_string displayText = "";
bool generalOrder = false;
SCP_string category = "";
bool cur_enabled = false;
bool cur_valid = false;
enum class target_restrictions : int { TARGET_ALLIES, TARGET_ALL, TARGET_OWN, TARGET_ENEMIES, TARGET_SAME_WING, TARGET_PLAYER_WING, TARGET_ALL_CAPS, TARGET_ALLIED_CAPS, TARGET_ENEMY_CAPS, TARGET_NOT_SELF } targetRestrictions = target_restrictions::TARGET_ALL;
enum class ship_restrictions : int { ANY, WING, IN_PLAYER_WING, PLAYER_WING } shipRestrictions = ship_restrictions::ANY;
};
@@ -28,7 +33,17 @@ bool ai_lua_add_order(int sexp_op, player_order_lua order);
bool ai_lua_has_mode(int sexp_op);
const ai_mode_lua* ai_lua_find_mode(int sexp_op);
const player_order_lua* ai_lua_find_player_order(int sexp_op);
SCP_vector<SCP_string> ai_lua_get_general_order_categories(bool enabled_only = true);
int ai_lua_get_num_general_orders();
SCP_vector<SCP_string> ai_lua_get_general_orders(bool onlyEnabled = false, bool onlyValid = false, const SCP_string& category = "");
int ai_lua_find_general_order_id(const SCP_string& name);
void ai_lua_enable_general_order(int sexp_op, bool enable);
void ai_lua_validate_general_order(int sexp_op, bool validity);
void ai_lua_reset_general_orders();
bool ai_lua_is_general_order(int sexp_op);
void ai_lua(ai_info* aip);
void ai_lua_start(ai_goal* aigp, object* objp);
void ai_lua_start_general(int lua_sexp_id, int target_objnum);
bool ai_lua_is_valid_target(int sexp_op, int target_objnum, ship* self, size_t order);
bool ai_lua_is_valid_ship(int sexp_op, bool isWing, ship* self);
ai_achievability ai_lua_is_achievable(const ai_goal* aigp, int objnum);
+25 -6
View File
@@ -58,11 +58,19 @@ const char *Turret_target_order_names[NUM_TURRET_ORDER_TYPES] = {
#define EEOF_BIG_ONLY (1<<0) // turret fires only at big and huge ships
#define EEOF_SMALL_ONLY (1<<1) // turret fires only at small ships
#define EEOF_TAGGED_ONLY (1<<2) // turret fires only at tagged ships
#define EEOF_BEAM (1<<3) // turret is a beam
#define EEOF_FLAK (1<<4) // turret is flak
#define EEOF_LASER (1<<5) // turret is a laser
#define EEOF_MISSILE (1<<6) // turret is a missile
const char* Turret_valid_types[NUM_TURRET_TYPES] = {
"Beam",
"Flak",
"Laser",
"Missile",
};
typedef struct eval_enemy_obj_struct {
int turret_parent_objnum; // parent of turret
float weapon_travel_dist; // max targeting range of turret weapon
@@ -1096,7 +1104,7 @@ int find_turret_enemy(ship_subsys *turret_subsys, int objnum, vec3d *tpos, vec3d
ai_info *aip = &Ai_info[Ships[Objects[objnum].instance].ai_index];
sip = &Ship_info[Ships[Objects[objnum].instance].ship_info_index];
if ((Ship_types[sip->class_type].flags[Ship::Type_Info_Flags::Turret_tgt_ship_tgt]) && (aip->target_objnum != -1)) {
if ((sip->class_type >= 0) && (Ship_types[sip->class_type].flags[Ship::Type_Info_Flags::Turret_tgt_ship_tgt]) && (aip->target_objnum != -1)) {
int target_objnum = aip->target_objnum;
if (Objects[target_objnum].signature == aip->target_signature) {
@@ -1763,7 +1771,7 @@ 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 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)
{
matrix turret_orient;
int weapon_objnum;
@@ -1887,6 +1895,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
parent_ship->last_fired_turret = turret;
turret->last_fired_weapon_info_index = turret_weapon_class;
turret->turret_last_fired = _timestamp();
if (scripting::hooks::OnTurretFired->isActive()) {
scripting::hooks::OnTurretFired->run(scripting::hooks::WeaponUsedConditions{ parent_ship , turret_enemy_objp, SCP_vector<int>{ turret_weapon_class }, true },
@@ -2029,6 +2038,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
parent_ship->last_fired_turret = turret;
turret->last_fired_weapon_info_index = wp->weapon_info_index;
turret->turret_last_fired = _timestamp();
wp->target_num = turret->turret_enemy_objnum;
// AL 1-6-97: Store pointer to turret subsystem
@@ -2078,7 +2088,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
}
}
if ( wip->launch_snd.isValid() ) {
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 );
@@ -2155,6 +2165,7 @@ void turret_swarm_fire_from_turret(turret_swarm_info *tsi)
Ships[Objects[tsi->parent_objnum].instance].last_fired_turret = tsi->turret;
tsi->turret->last_fired_weapon_info_index = tsi->weapon_class;
tsi->turret->turret_last_fired = _timestamp();
if (scripting::hooks::OnTurretFired->isActive()) {
scripting::hooks::OnTurretFired->run(scripting::hooks::WeaponUsedConditions{
@@ -2617,6 +2628,8 @@ void ai_turret_execute_behavior(ship *shipp, ship_subsys *ss)
number_of_firings = num_valid;
}
auto sound_played = gamesnd_id();
for (int i = 0; i < number_of_firings; ++i)
{
int valid_index;
@@ -2626,6 +2639,13 @@ void ai_turret_execute_behavior(ship *shipp, ship_subsys *ss)
valid_index = i;
auto wip = get_turret_weapon_wip(&ss->weapons, valid_weapons[valid_index]);
bool play_sound = false;
if (sound_played != wip->launch_snd) {
sound_played = wip->launch_snd;
play_sound = true;
}
// Forces the firing turret to retain the firingpoints of their weapons:
// if the turret has multiple banks, the first bank will only fire from the first firepoint,
// the second bank only from the second firepoint, and so on.
@@ -2728,7 +2748,6 @@ void ai_turret_execute_behavior(ship *shipp, ship_subsys *ss)
vm_vec_scale_add(&end, &gpos, &gvec, model_get_radius(model_num));
mc_info hull_check;
mc_info_init(&hull_check);
hull_check.model_instance_num = shipp->model_instance_num;
hull_check.model_num = model_num;
hull_check.orient = &objp->orient;
@@ -2781,7 +2800,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);
turret_fire_weapon(valid_weapons[valid_index], ss, parent_objnum, &gpos, &shoot_vector, &predicted_enemy_pos, 100.0f, play_sound);
}
else
{
@@ -2889,7 +2908,7 @@ bool turret_adv_fov_test(ship_subsys *ss, vec3d *gvec, vec3d *v2e, float size_mo
bool turret_fov_test(ship_subsys *ss, vec3d *gvec, vec3d *v2e, float size_mod)
{
bool in_fov = false;
if (ss->system_info->flags[Model::Subsystem_Flags::Turret_base_restricted_fov])
if (ss->system_info->turret_base_fov > -1.0f)
in_fov = turret_adv_fov_test(ss, gvec, v2e, size_mod);
else
in_fov = turret_std_fov_test(ss, gvec, v2e, size_mod);
+1 -1
View File
@@ -670,7 +670,7 @@ void anim_read_header(anim *ptr, CFILE *fp)
* @param file_mapped Whether to use memory-mapped file or not.
*
* @details Memory-mapped files will page in the animation from disk as it is needed, but performance is not as good.
* @return Pointer to anim that is loaded if sucess, NULL if failure.
* @return Pointer to anim that is loaded if success, NULL if failure.
*/
anim *anim_load(const char *real_filename, int cf_dir_type, int file_mapped)
{
+166 -94
View File
@@ -265,7 +265,7 @@ static void inner_bound_pos_fixup(asteroid_field *asfieldp, vec3d *pos)
/**
* Create a single asteroid
*/
object *asteroid_create(asteroid_field *asfieldp, int asteroid_type, int asteroid_subtype)
object *asteroid_create(asteroid_field *asfieldp, int asteroid_type, int asteroid_subtype, bool check_visibility)
{
int n, objnum;
matrix orient;
@@ -356,6 +356,13 @@ object *asteroid_create(asteroid_field *asfieldp, int asteroid_type, int asteroi
angs.h = static_randf( rand_base++ ) * PI2;
}
// If the generated asteroid position is within the player view then abort
// I'm unsure how Eyepoint is handled for multiplayer, so this may need to move up into the SP
// only section - Mjn
if (check_visibility && asteroid_is_within_view(&pos, -1.0f, true)) {
return nullptr;
}
vm_angles_2_matrix(&orient, &angs);
flagset<Object::Object_Flags> asteroid_default_flagset;
asteroid_default_flagset += Object::Object_Flags::Renders;
@@ -437,6 +444,12 @@ object *asteroid_create(asteroid_field *asfieldp, int asteroid_type, int asteroi
// ensure vel is valid
Assert( !vm_is_vec_nan(&objp->phys_info.vel) );
if (scripting::hooks::OnAsteroidCreated->isActive()) {
scripting::hooks::OnAsteroidCreated->run(
scripting::hook_param_list(
scripting::hook_param("Asteroid", 'o', objp)));
}
return objp;
}
@@ -691,11 +704,29 @@ void asteroid_create_asteroid_field(int num_asteroids, int field_type, int aster
Asteroid_field.num_initial_asteroids = num_asteroids;
if (field_type == 0) {
Asteroid_field.field_type = FT_PASSIVE;
} else {
Asteroid_field.field_type = FT_ACTIVE;
switch (field_type) {
case 0:
Asteroid_field.field_type = FT_PASSIVE;
Asteroid_field.enhanced_visibility_checks = false;
break;
case 1:
Asteroid_field.field_type = FT_ACTIVE;
Asteroid_field.enhanced_visibility_checks = false;
break;
case 2:
Asteroid_field.field_type = FT_PASSIVE;
Asteroid_field.enhanced_visibility_checks = true;
break;
case 3:
Asteroid_field.field_type = FT_ACTIVE;
Asteroid_field.enhanced_visibility_checks = true;
break;
default: //Any other number will just give default behavior
Asteroid_field.field_type = FT_PASSIVE;
Asteroid_field.enhanced_visibility_checks = false;
break;
}
vm_vec_rand_vec_quick(&Asteroid_field.vel);
vm_vec_scale(&Asteroid_field.vel, (float)asteroid_speed);
Asteroid_field.speed = (float)asteroid_speed;
@@ -746,7 +777,7 @@ void asteroid_create_asteroid_field(int num_asteroids, int field_type, int aster
}
// will replace any existing asteroid or debris field with a debris field
void asteroid_create_debris_field(int num_asteroids, int asteroid_speed, int debris1, int debris2, int debris3, vec3d o_min, vec3d o_max)
void asteroid_create_debris_field(int num_asteroids, int asteroid_speed, int debris1, int debris2, int debris3, vec3d o_min, vec3d o_max, bool enhanced)
{
remove_all_asteroids();
@@ -754,6 +785,8 @@ void asteroid_create_debris_field(int num_asteroids, int asteroid_speed, int deb
Asteroid_field.field_type = FT_PASSIVE;
Asteroid_field.enhanced_visibility_checks = enhanced;
vm_vec_rand_vec_quick(&Asteroid_field.vel);
vm_vec_scale(&Asteroid_field.vel, (float)asteroid_speed);
Asteroid_field.speed = (float)asteroid_speed;
@@ -883,37 +916,37 @@ static int asteroid_should_wrap(object *objp, asteroid_field *asfieldp)
}
/**
* Wrap an asteroid from one end of the asteroid field to the other
* Generates a potential new position for an asteroid that might wrap
* from one end of the asteroid field to the other
*/
static void asteroid_wrap_pos(object *objp, asteroid_field *asfieldp)
static void asteroid_wrap_pos(vec3d *pos, asteroid_field *asfieldp)
{
if (objp->pos.xyz.x < asfieldp->min_bound.xyz.x) {
objp->pos.xyz.x = asfieldp->max_bound.xyz.x + (objp->pos.xyz.x - asfieldp->min_bound.xyz.x);
if (pos->xyz.x < asfieldp->min_bound.xyz.x) {
pos->xyz.x = asfieldp->max_bound.xyz.x + (pos->xyz.x - asfieldp->min_bound.xyz.x);
}
if (objp->pos.xyz.y < asfieldp->min_bound.xyz.y) {
objp->pos.xyz.y = asfieldp->max_bound.xyz.y + (objp->pos.xyz.y - asfieldp->min_bound.xyz.y);
}
if (objp->pos.xyz.z < asfieldp->min_bound.xyz.z) {
objp->pos.xyz.z = asfieldp->max_bound.xyz.z + (objp->pos.xyz.z - asfieldp->min_bound.xyz.z);
if (pos->xyz.y < asfieldp->min_bound.xyz.y) {
pos->xyz.y = asfieldp->max_bound.xyz.y + (pos->xyz.y - asfieldp->min_bound.xyz.y);
}
if (objp->pos.xyz.x > asfieldp->max_bound.xyz.x) {
objp->pos.xyz.x = asfieldp->min_bound.xyz.x + (objp->pos.xyz.x - asfieldp->max_bound.xyz.x);
if (pos->xyz.z < asfieldp->min_bound.xyz.z) {
pos->xyz.z = asfieldp->max_bound.xyz.z + (pos->xyz.z - asfieldp->min_bound.xyz.z);
}
if (objp->pos.xyz.y > asfieldp->max_bound.xyz.y) {
objp->pos.xyz.y = asfieldp->min_bound.xyz.y + (objp->pos.xyz.y - asfieldp->max_bound.xyz.y);
if (pos->xyz.x > asfieldp->max_bound.xyz.x) {
pos->xyz.x = asfieldp->min_bound.xyz.x + (pos->xyz.x - asfieldp->max_bound.xyz.x);
}
if (objp->pos.xyz.z > asfieldp->max_bound.xyz.z) {
objp->pos.xyz.z = asfieldp->min_bound.xyz.z + (objp->pos.xyz.z - asfieldp->max_bound.xyz.z);
if (pos->xyz.y > asfieldp->max_bound.xyz.y) {
pos->xyz.y = asfieldp->min_bound.xyz.y + (pos->xyz.y - asfieldp->max_bound.xyz.y);
}
if (pos->xyz.z > asfieldp->max_bound.xyz.z) {
pos->xyz.z = asfieldp->min_bound.xyz.z + (pos->xyz.z - asfieldp->max_bound.xyz.z);
}
// wrap on inner bound, check all 3 axes as needed, use of rand ok for multiplayer with send_asteroid_throw()
inner_bound_pos_fixup(asfieldp, &objp->pos);
inner_bound_pos_fixup(asfieldp, pos);
}
@@ -960,7 +993,8 @@ static void asteroid_aim_at_target(object *objp, object *asteroid_objp, float de
vm_vec_add2(&rand_vec, &objp->orient.vec.rvec);
vm_vec_normalize(&rand_vec);
speed = Asteroid_info[0].max_speed * (frand()/2.0f + 0.5f);
auto asp = &Asteroids[asteroid_objp->instance];
speed = Asteroid_info[asp->asteroid_type].max_speed * (frand()/2.0f + 0.5f);
vm_vec_copy_scale(&asteroid_objp->phys_info.vel, &rand_vec, -speed);
asteroid_objp->phys_info.desired_vel = asteroid_objp->phys_info.vel;
@@ -983,6 +1017,32 @@ static void sanitize_asteroid_targets_list() {
}
}
/**
* Checks if an asteroid will be within the player's view
*
**/
bool asteroid_is_within_view(vec3d *pos, float range, bool range_override)
{
vec3d vec_to_asteroid;
// Distance and view cone for the position in relation to the player
float dist = vm_vec_normalized_dir(&vec_to_asteroid, pos, &Eye_position);
float dot = vm_vec_dot(&Eye_matrix.vec.fvec, &vec_to_asteroid);
// if asteroid is within view or far enough away then wrap
if (dot > cos(g3_get_hfov(Proj_fov))) {
if (range_override) {
return true;
} else {
if (dist < range) {
return true;
}
}
}
return false;
}
/**
* Call once per frame to maybe throw some asteroids at one or more ships.
*
@@ -1023,7 +1083,7 @@ static void maybe_throw_asteroid()
if (subtype < 0)
return;
object *objp = asteroid_create(&Asteroid_field, ASTEROID_TYPE_LARGE, subtype);
object *objp = asteroid_create(&Asteroid_field, ASTEROID_TYPE_LARGE, subtype, Asteroid_field.enhanced_visibility_checks);
if (objp != nullptr) {
asteroid_aim_at_target(target_objp, objp, ASTEROID_MIN_COLLIDE_TIME + frand() * 20.0f);
@@ -1074,7 +1134,7 @@ void asteroid_delete( object * obj )
}
/**
* See if we should reposition the asteroid.
* See if we should reposition the asteroid.
* Only reposition if oustide the bounding volume and the player isn't looking towards the asteroid.
*/
static void asteroid_maybe_reposition(object *objp, asteroid_field *asfieldp)
@@ -1084,61 +1144,74 @@ static void asteroid_maybe_reposition(object *objp, asteroid_field *asfieldp)
return;
}
if ( asteroid_should_wrap(objp, asfieldp) ) {
vec3d vec_to_asteroid, old_asteroid_pos, old_vel;
float dot, dist;
if (asteroid_should_wrap(objp, asfieldp)) {
old_asteroid_pos = objp->pos;
old_vel = objp->phys_info.vel;
// Generate a possible new position if we do end up wrapping, but don't move the asteroid yet
vec3d new_pos = objp->pos;
asteroid_wrap_pos(&new_pos, asfieldp);
// don't wrap asteroid if it is a target of some ship
if ( !asteroid_is_targeted(objp) ) {
bool wrap = false;
bool reverse = false;
// only wrap if player won't see asteroid disappear/reverse direction
dist = vm_vec_normalized_dir(&vec_to_asteroid, &objp->pos, &Eye_position);
dot = vm_vec_dot(&Eye_matrix.vec.fvec, &vec_to_asteroid);
if ( (dot < 0.7f) || (dist > asfieldp->bound_rad) ) {
if (Num_asteroids > MAX_ASTEROIDS-10) {
objp->flags.set(Object::Object_Flags::Should_be_dead);
} else {
// check to ensure player won't see asteroid appear either
asteroid_wrap_pos(objp, asfieldp);
asteroid* astp = &Asteroids[objp->instance];
// If asteroid is targeted then we cannot wrap because they player would see it and say "SHENANIGANS!"
// So we bail
if (asteroid_is_targeted(objp)) {
return;
}
if (asfieldp->field_type == FT_ACTIVE) {
// this doesnt count as a thrown asteroid anymore
for (asteroid_target& target : Asteroid_targets)
if (target.objnum == astp->target_objnum)
target.incoming_asteroids--;
// if asteroid is not within view...
if (!asteroid_is_within_view(&objp->pos, asfieldp->bound_rad, asfieldp->enhanced_visibility_checks)) {
astp->target_objnum = -1;
}
// if asteroid new position is within view then reverse velocity, otherwise wrap
if (asteroid_is_within_view(&new_pos, (asfieldp->bound_rad * 1.3f), asfieldp->enhanced_visibility_checks)) {
dist = vm_vec_normalized_dir(&vec_to_asteroid, &objp->pos, &Eye_position);
dot = vm_vec_dot(&Eye_matrix.vec.fvec, &vec_to_asteroid);
//probably don't reverse direction if there's gravity involved
if (IS_VEC_NULL(&The_mission.gravity)) {
if ((dot > 0.7f) && (dist < (asfieldp->bound_rad * 1.3f))) {
// player would see asteroid pop out other side, so reverse velocity instead of wrapping
objp->pos = old_asteroid_pos;
vm_vec_copy_scale(&objp->phys_info.vel, &old_vel, -1.0f);
objp->phys_info.desired_vel = objp->phys_info.vel;
Asteroids[objp->instance].target_objnum = -1;
}
}
// update last pos (after vel is known)
vm_vec_scale_add(&objp->last_pos, &objp->pos, &objp->phys_info.vel, -flFrametime);
asteroid_update_collide(objp);
if (asfieldp->field_type == FT_ACTIVE) {
if (MULTIPLAYER_MASTER)
send_asteroid_throw(objp);
}
// if the mission has gravity, then we can't reverse. So make sure gravity is null
if (IS_VEC_NULL(&The_mission.gravity)) {
reverse = true;
}
} else {
wrap = true;
}
}
// we can wrap, but we have too many asteroids, so destroy this one instead
if (wrap && (Num_asteroids > MAX_ASTEROIDS - 10)) {
objp->flags.set(Object::Object_Flags::Should_be_dead);
return;
}
// Reverse instead of wrap!
if (reverse) {
vm_vec_copy_scale(&objp->phys_info.vel, &objp->phys_info.vel, -1.0f);
objp->phys_info.desired_vel = objp->phys_info.vel;
Asteroids[objp->instance].target_objnum = -1;
return;
}
// We can wrap, so wrap!
if (wrap) {
objp->pos = new_pos;
asteroid *astp = &Asteroids[objp->instance];
if (asfieldp->field_type == FT_ACTIVE) {
// this doesnt count as a thrown asteroid anymore
for (asteroid_target &target : Asteroid_targets)
if (target.objnum == astp->target_objnum)
target.incoming_asteroids--;
astp->target_objnum = -1;
}
// update last pos (after vel is known)
vm_vec_scale_add(&objp->last_pos, &objp->pos, &objp->phys_info.vel, -flFrametime);
asteroid_update_collide(objp);
if (asfieldp->field_type == FT_ACTIVE) {
if (MULTIPLAYER_MASTER)
send_asteroid_throw(objp);
}
}
}
@@ -1166,7 +1239,6 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
}
mc_info mc;
mc_info_init(&mc);
int num, asteroid_subtype;
Assert( pasteroid->type == OBJ_ASTEROID );
@@ -1601,7 +1673,7 @@ static void asteroid_do_area_effect(object *asteroid_objp)
continue;
ship_apply_global_damage(ship_objp, asteroid_objp, &asteroid_objp->pos, damage, asip->damage_type_idx);
weapon_area_apply_blast(NULL, ship_objp, &asteroid_objp->pos, blast, 0);
weapon_area_apply_blast(nullptr, ship_objp, &asteroid_objp->pos, blast, false);
} // end for
}
@@ -1613,7 +1685,7 @@ static void asteroid_do_area_effect(object *asteroid_objp)
* @param hitpos world position asteroid was hit, can be NULL if hit by area effect
* @param damage amount of damage to apply to asteroid
*/
void asteroid_hit( object * pasteroid_obj, object * other_obj, vec3d * hitpos, float damage )
void asteroid_hit( object * pasteroid_obj, object * other_obj, vec3d * hitpos, float damage, vec3d* force )
{
float explosion_life;
asteroid *asp;
@@ -1625,7 +1697,13 @@ void asteroid_hit( object * pasteroid_obj, object * other_obj, vec3d * hitpos, f
}
if ( MULTIPLAYER_MASTER ){
send_asteroid_hit( pasteroid_obj, other_obj, hitpos, damage );
send_asteroid_hit( pasteroid_obj, other_obj, hitpos, damage, force );
}
if (hitpos && force && The_mission.ai_profile->flags[AI::Profile_Flags::Whackable_asteroids]) {
vec3d rel_hit_pos = *hitpos - pasteroid_obj->pos;
physics_calculate_and_apply_whack(force, &rel_hit_pos, &pasteroid_obj->phys_info, &pasteroid_obj->orient, &pasteroid_obj->phys_info.I_body_inv);
pasteroid_obj->phys_info.desired_vel = pasteroid_obj->phys_info.vel;
}
pasteroid_obj->hull_strength -= damage;
@@ -1885,7 +1963,6 @@ static void asteroid_test_collide(object *pasteroid_obj, object *pship_obj, mc_i
static int asteroid_will_collide(object *pasteroid_obj, object *escort_objp)
{
mc_info mc;
mc_info_init(&mc);
asteroid_test_collide(pasteroid_obj, escort_objp, &mc);
@@ -2015,7 +2092,6 @@ float asteroid_time_to_impact(object *asteroid_objp)
float time=-1.0f, total_dist, speed;
asteroid *asp;
mc_info mc;
mc_info_init(&mc);
asp = &Asteroids[asteroid_objp->instance];
@@ -2037,17 +2113,6 @@ float asteroid_time_to_impact(object *asteroid_objp)
return time;
}
int get_asteroid_position(const char* name)
{
for (int i = 0; i < (int)Asteroid_info.size(); i++) {
if (!stricmp(name, Asteroid_info[i].name)) {
return i;
}
}
return -1;
}
static SCP_string setup_display_name(SCP_string name)
{
@@ -2118,7 +2183,7 @@ static void asteroid_parse_section()
asteroid_t.name);
}
} else {
// Don't create poof if it has +nocreate and is in a modular table.
// Don't create asteroid if it has +nocreate and is in a modular table.
if (!create_if_not_found && Parsing_modular_table) {
if (!skip_to_start_of_string_either("$Name:", "#end")) {
error_display(1, "Missing [#end] or [$Name] after asteroid %s", asteroid_t.name);
@@ -2349,7 +2414,7 @@ static void asteroid_parse_tbl(const char* filename)
}
// Gets the index of an asteroid by name from Asteroid_info
static int get_asteroid_index(const char* asteroid_name)
int get_asteroid_index(const char* asteroid_name)
{
for (int i = 0; i < (int)Asteroid_info.size(); i++) {
if (!stricmp(asteroid_name, Asteroid_info[i].name)) {
@@ -2461,6 +2526,10 @@ void asteroid_init()
// parse any modular tables
parse_modular_table("*-ast.tbm", asteroid_parse_tbl);
//No asteroids defined. Bail!
if (asteroid_list.empty())
return;
// now verify the asteroids were found and put them in the correct order
verify_asteroid_list();
@@ -2616,6 +2685,9 @@ void asteroid_target_closest_danger()
void asteroid_page_in()
{
if (Asteroid_info.empty())
return;
if (Asteroid_field.num_initial_asteroids > 0 ) {
int i, j, k;
+8 -3
View File
@@ -143,6 +143,7 @@ typedef struct asteroid_field {
debris_genre_t debris_genre; // type of debris (ship or asteroid) [generic type]
int field_debris_type[MAX_ACTIVE_DEBRIS_TYPES]; // one of the debris type defines above
int num_used_field_debris_types; // how many of the above are used
bool enhanced_visibility_checks; // if true then range checks are overridden for spawning and wrapping asteroids in the field
SCP_vector<SCP_string> target_names; // default retail behavior is to just throw at the first big ship in the field
} asteroid_field;
@@ -158,24 +159,28 @@ extern vec3d Asteroid_icon_closeup_position; // closeup position for asteroid f
extern float Asteroid_icon_closeup_zoom; // zoom position for asteroid field briefing icon rendering
void asteroid_init();
bool asteroid_is_within_view(vec3d *pos, float range, bool range_override = false);
void asteroid_level_init();
void asteroid_level_close();
void asteroid_create_all();
void asteroid_create_asteroid_field(int num_asteroids, int field_type, int asteroid_speed, bool brown, bool blue, bool orange, vec3d o_min, vec3d o_max, bool inner_box, vec3d i_min, vec3d i_max, SCP_vector<SCP_string> targets);
void asteroid_create_debris_field(int num_asteroids, int asteroid_speed, int debris1, int debris2, int debris3, vec3d o_min, vec3d o_max);
void asteroid_create_debris_field(int num_asteroids, int asteroid_speed, int debris1, int debris2, int debris3, vec3d o_min, vec3d o_max, bool enhanced);
void asteroid_render(object* obj, model_draw_list* scene);
void asteroid_delete( object *asteroid_objp );
void asteroid_process_pre( object *asteroid_objp );
void asteroid_process_post( object *asteroid_objp);
int asteroid_check_collision( object *asteroid_objp, object * other_obj, vec3d * hitpos, collision_info_struct *asteroid_hit_info=NULL, vec3d* hitnormal=NULL );
void asteroid_hit( object *pasteroid_objp, object *other_objp, vec3d *hitpos, float damage );
void asteroid_hit( object *pasteroid_objp, object *other_objp, vec3d *hitpos, float damage, vec3d* force );
int asteroid_count();
int asteroid_collide_objnum(object *asteroid_objp);
float asteroid_time_to_impact(object *asteroid_objp);
void asteroid_show_brackets();
void asteroid_target_closest_danger();
void asteroid_add_target(object* objp);
int get_asteroid_position(const char* name);
int get_asteroid_index(const char* asteroid_name);
// need to extern for keycontrol debug commands
object *asteroid_create(asteroid_field *asfieldp, int asteroid_type, int asteroid_subtype, bool check_visibility = false);
// need to extern for multiplayer
void asteroid_sub_create(object *parent_objp, int asteroid_type, vec3d *relvec);
+38 -24
View File
@@ -1011,7 +1011,7 @@ void nav_warp(bool prewarp=false)
vm_vec_scale(&velocity, (float)Ai_info[Ships[Autopilot_flight_leader->instance].ai_index].waypoint_speed_cap);
// Find all ships that are supposed to autopilot with the player and move them
// to the cinimatic location or the final destination
// to the cinematic location or the final destination
for (int i = 0; i < MAX_SHIPS; i++)
{
if (Ships[i].objnum != -1
@@ -1020,11 +1020,12 @@ void nav_warp(bool prewarp=false)
{
vm_vec_add(&Objects[Ships[i].objnum].pos, &Objects[Ships[i].objnum].pos, &targetPos);
Objects[Ships[i].objnum].phys_info.vel = velocity;
// retime collision pairs
if (Objects[Ships[i].objnum].flags[Object::Object_Flags::Collides])
obj_collide_obj_cache_stale(&Objects[Ships[i].objnum]);
}
}
// retime all collision pairs
obj_collide_retime_cached_pairs();
}
// ********************************************************************************************
@@ -1183,6 +1184,10 @@ void send_autopilot_msgID(int msgid)
if (msgid < 0 || msgid >= NP_NUM_MESSAGES)
return;
// bail out if message is not set
if (NavMsgs[msgid].message[0] == '\0')
return;
send_autopilot_msg(NavMsgs[msgid].message, NavMsgs[msgid].filename);
}
// ********************************************************************************************
@@ -1222,6 +1227,15 @@ void NavSystem_Init()
for (int i = 0; i < MAX_NAVPOINTS; i++)
Navs[i].clear();
//Initialize all these as empty strings so we can detect and bail out later -Mjn
for (int i = 0; i < NP_NUM_MESSAGES; i++)
NavMsgs[i].message[0] = '\0';
//Set defaults here before parsing
NavLinkDistance = 1000;
AutopilotMinEnemyDistance = 5000;
AutopilotMinAsteroidDistance = 1000;
LockWeaponsDuringAutopilot = false;
AutoPilotEngaged = false;
CurrentNav = -1;
audio_handle = -1;
@@ -1229,10 +1243,9 @@ void NavSystem_Init()
UseCutsceneBars = true;
// defaults... can be tabled or bound to mission later
if (cf_exists_full("autopilot.tbl", CF_TYPE_TABLES))
parse_autopilot_table("autopilot.tbl");
else
parse_autopilot_table(NULL);
parse_autopilot_table("autopilot.tbl");
parse_modular_table("*-aplt.tbm", parse_autopilot_table);
}
// ********************************************************************************************
@@ -1243,10 +1256,16 @@ void parse_autopilot_table(const char *filename)
try
{
if (filename == NULL)
read_file_text_from_default(defaults_get_file("autopilot.tbl"));
else
if (!Parsing_modular_table) {
// if table doesn't exist, use the default table
if (cf_exists_full(filename, CF_TYPE_TABLES))
read_file_text(filename, CF_TYPE_TABLES);
else
read_file_text_from_default(defaults_get_file("autopilot.tbl"));
} else {
read_file_text(filename, CF_TYPE_TABLES);
}
reset_parse();
@@ -1254,23 +1273,17 @@ void parse_autopilot_table(const char *filename)
required_string("#Autopilot");
// autopilot link distance
required_string("$Link Distance:");
stuff_int(&NavLinkDistance);
if (optional_string("$Link Distance:"))
stuff_int(&NavLinkDistance);
if (optional_string("$Interrupt autopilot if enemy within distance:"))
stuff_int(&AutopilotMinEnemyDistance);
else
AutopilotMinEnemyDistance = 5000;
if (optional_string("$Interrupt autopilot if asteroid within distance:"))
stuff_int(&AutopilotMinAsteroidDistance);
else
AutopilotMinAsteroidDistance = 1000;
if (optional_string("$Lock Weapons During Autopilot:"))
stuff_boolean(&LockWeaponsDuringAutopilot);
else
LockWeaponsDuringAutopilot = false;
// optional no cutscene bars
if (optional_string("+No_Cutscene_Bars"))
@@ -1285,13 +1298,14 @@ void parse_autopilot_table(const char *filename)
"$Support Present:", "$Support Working:" };
for (int i = 0; i < NP_NUM_MESSAGES; i++)
{
required_string(msg_tags[i]);
if (optional_string(msg_tags[i])) {
required_string("+Msg:");
stuff_string(NavMsgs[i].message, F_MESSAGE, 256);
required_string("+Msg:");
stuff_string(NavMsgs[i].message, F_MESSAGE, 256);
required_string("+Snd File:");
stuff_string(NavMsgs[i].filename, F_NAME, 256);
required_string("+Snd File:");
stuff_string(NavMsgs[i].filename, F_NAME, 256);
}
}
+1 -1
View File
@@ -100,7 +100,7 @@ void bm_lock_apng( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort fla
void bm_lock_jpg( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags );
void bm_lock_pcx( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags );
void bm_lock_tga( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags );
void bm_lock_user( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags );
void bm_lock_user( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags, bool convert = true );
const size_t BM_BLOCK_SIZE = 4096;
+100 -10
View File
@@ -585,6 +585,59 @@ int bm_create(int bpp, int w, int h, void *data, int flags) {
return n;
}
int bm_create_3d(int bpp, int w, int h, int d, void* data) {
Assert((bpp == 16) || (bpp == 24) || (bpp == 32));
Assertion(bm_inited, "bmpman must be initialized before this function can be called!");
int n = find_block_of(1);
// Out of bitmap slots
if (n == -1)
return -1;
// make sure that we have valid data
if (data == nullptr) {
UNREACHABLE("No valid data received for 3D Bitmap creation!");
return -1;
}
auto entry = bm_get_entry(n);
memset(entry, 0, sizeof(bitmap_entry));
sprintf_safe(entry->filename, "TMP%dx%dx%d+%d", w, h, d, bpp);
entry->type = BM_TYPE_3D;
entry->comp_type = BM_TYPE_NONE;
entry->bm.w = (short)w;
entry->bm.h = (short)h;
entry->bm.d = (short)d;
entry->bm.rowsize = (short)w;
entry->bm.bpp = (ubyte)bpp;
entry->bm.true_bpp = (ubyte)bpp;
entry->bm.flags = (ubyte)BMP_TEX_XPARENT;
entry->bm.data = 0;
entry->bm.palette = nullptr;
entry->info.user.bpp = (ubyte)bpp;
entry->info.user.data = data;
entry->info.user.flags = (ubyte)BMP_TEX_XPARENT;
entry->signature = Bm_next_signature++;
entry->handle = n;
entry->mem_taken = (w * h * d * (bpp >> 3));
entry->load_count++;
bm_update_memory_used(n, (int)entry->mem_taken);
gr_bm_create(bm_get_slot(n));
return n;
}
void bm_convert_format(bitmap *bmp, ushort flags) {
int idx;
@@ -628,7 +681,7 @@ void bm_free_data(bitmap_slot* bs, bool release)
// Don't free up memory for user defined bitmaps, since
// BmpMan isn't the one in charge of allocating/deallocing them.
if (be->type==BM_TYPE_USER) {
if (be->type == BM_TYPE_USER || be->type == BM_TYPE_3D) {
#ifdef BMPMAN_NDEBUG
if ( be->data_size != 0 )
bm_texture_ram -= be->data_size;
@@ -684,7 +737,7 @@ void bm_free_data_fast(int handle)
// Don't free up memory for user defined bitmaps, since
// BmpMan isn't the one in charge of allocating/deallocing them.
if (be->type == BM_TYPE_USER) {
if (be->type == BM_TYPE_USER || be->type == BM_TYPE_3D) {
#ifdef BMPMAN_NDEBUG
if ( be->data_size != 0 )
bm_texture_ram -= be->data_size;
@@ -892,6 +945,27 @@ int bm_get_info(int handle, int *w, int * h, ushort* flags, int *nframes, int *f
}
}
int bm_get_depth(int handle, int* depth) {
bitmap* bmp;
if (!bm_inited) return -1;
auto entry = bm_get_entry(handle);
Assertion(entry->handle == handle, "Invalid bitmap handle %d passed to bm_get_info().\nThis might be due to an invalid animation somewhere else.\n", handle); // INVALID BITMAP HANDLE!
if (entry->type != BM_TYPE_3D) {
*depth = 0;
return -1;
}
bmp = &(entry->bm);
*depth = bmp->d;
return handle;
}
int bm_get_num_mipmaps(int num) {
auto entry = bm_get_entry(num);
@@ -1407,6 +1481,10 @@ static int bm_load_image_data(int handle, int bpp, ushort flags, bool nodebug)
bm_lock_user(handle, bs, bmp, true_bpp, flags);
break;
case BM_TYPE_3D:
bm_lock_user(handle, bs, bmp, true_bpp, flags, false);
break;
default:
Warning(LOCATION, "Unsupported type in bm_lock -- %d\n", c_type);
return -1;
@@ -1517,10 +1595,13 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke
// MAX_FILENAME_LEN-10 == 5 character frame designator plus '.' plus 3 letter ext plus NULL terminator
// we only check for -5 here since the filename should already have the extension on it, and it must have passed the previous check
if (strlen(filename) > MAX_FILENAME_LEN - 5) {
Warning(LOCATION, "Passed filename, '%s', is too long to support an extension and frames!!\n\nMaximum length for an ANI/EFF/APNG, minus the extension, is %i characters.\n", filename, MAX_FILENAME_LEN - 10);
if (img_cfp != nullptr)
cfclose(img_cfp);
return -1;
// Don't check PNGs yet, because a PNG could be a regular non-animated image
if (type != BM_TYPE_PNG) {
Warning(LOCATION, "Passed filename, '%s', is too long to support an extension and frames!!\n\nMaximum length for an ANI/EFF/APNG, minus the extension, is %i characters.\n", filename, MAX_FILENAME_LEN - 10);
if (img_cfp != nullptr)
cfclose(img_cfp);
return -1;
}
}
// it's an effect file, any readable image type with eff being txt
@@ -1604,6 +1685,14 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke
return -1;
}
}
// Now do the same filename length check that was deferred for PNGs above
if (strlen(filename) > MAX_FILENAME_LEN - 5) {
Warning(LOCATION, "Passed filename, '%s', is too long to support an extension and frames!!\n\nMaximum length for an ANI/EFF/APNG, minus the extension, is %i characters.\n", filename, MAX_FILENAME_LEN - 10);
if (img_cfp != nullptr)
cfclose(img_cfp);
return -1;
}
}
else {
Warning(LOCATION, "Unsupported image type: %i", type);
@@ -2388,7 +2477,7 @@ void bm_lock_tga(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags
bm_convert_format(bmp, flags);
}
void bm_lock_user(int /*handle*/, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags) {
void bm_lock_user(int /*handle*/, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags, bool convert) {
auto be = &bs->entry;
// Unload any existing data
@@ -2428,7 +2517,8 @@ void bm_lock_user(int /*handle*/, bitmap_slot *bs, bitmap *bmp, int bpp, ushort
break;
}
bm_convert_format(bmp, flags);
if (convert)
bm_convert_format(bmp, flags);
}
int bm_make_render_target(int width, int height, int flags) {
@@ -2512,7 +2602,7 @@ void *bm_malloc(int n, size_t size) {
void bm_page_in_aabitmap(int handle, int nframes) {
int i;
if (handle == -1)
if (handle < 0)
return;
Assert(bm_get_entry(handle)->handle == handle);
@@ -3131,7 +3221,7 @@ int bm_unload_fast(int handle, int clear_render_targets) {
return -1; // Already been released
}
if (be->type == BM_TYPE_USER) {
if (be->type == BM_TYPE_USER || be->type == BM_TYPE_3D) {
return -1;
}
+27 -1
View File
@@ -79,7 +79,9 @@ enum BM_TYPE
BM_TYPE_CUBEMAP_DDS, //!< generic DDS cubemap (uncompressed cubemap surface)
BM_TYPE_CUBEMAP_DXT1, //!< 24-bit cubemap (compressed cubemap surface)
BM_TYPE_CUBEMAP_DXT3, //!< 32-bit cubemap (compressed cubemap surface)
BM_TYPE_CUBEMAP_DXT5 //!< 32-bit cubemap (compressed cubemap surface)
BM_TYPE_CUBEMAP_DXT5, //!< 32-bit cubemap (compressed cubemap surface)
BM_TYPE_3D //!< 3D in-memory
};
/**
@@ -90,6 +92,7 @@ struct bitmap
{
short w; //!< Width, in number of pixels
short h; //!< Height, in number of pixels
short d; //!< Depth, in number of pixels
short rowsize; //!< What you need to add to go to next row
int bpp; //!< Requested bitdepth of each pixel. ( 7, 8, 15, 16, 24, 32)
int true_bpp; //!< The image's actual bitdepth
@@ -217,6 +220,19 @@ int bm_load_duplicate(const char *filename);
*/
int bm_create(int bpp, int w, int h, void *data = NULL, int flags = 0);
/**
* Loads a 3D bitmap which exists somewhere in the RAM.
*
* @param bpp The bitdepth of the bitmap
* @param w The width of the bitmap
* @param h The height of the bitmap
* @param d The depth of the bitmap
* @param[in] data The bitmap's data glob
*
* @note The used RAM cannot be freed until bm_release is called on the created bitmap
*/
int bm_create_3d(int bpp, int w, int h, int d, void* data = nullptr);
/**
* @brief Unloads a bitmap's data, but not the bitmap info
*
@@ -373,6 +389,16 @@ int bm_is_valid(int handle);
*/
int bm_get_info(int handle, int *w = nullptr, int * h = nullptr, ushort* flags = nullptr, int *nframes = nullptr, int *fps = nullptr);
/**
* @brief Gets 3D info on the bitmap indexed by handle.
*
* @param[out] depth If non-null, gets the depth
*
* @returns The handle on success
* @returns -1 on failure
*/
int bm_get_depth(int handle, int* depth);
/**
* @brief Gets the filename of the bitmap indexed by handle
*
+53 -21
View File
@@ -14,8 +14,8 @@
#include "ship/ship.h" //compute_slew_matrix
//*************************IMPORTANT GLOBALS*************************
float VIEWER_ZOOM_DEFAULT = 0.75f; // Default viewer zoom, 0.625 as per multi-lateral agreement on 3/24/97
float COCKPIT_ZOOM_DEFAULT = 0.75f;
fov_t VIEWER_ZOOM_DEFAULT = 0.75f; // Default viewer zoom, 0.625 as per multi-lateral agreement on 3/24/97
fov_t COCKPIT_ZOOM_DEFAULT = 0.75f;
float Sexp_fov = 0.0f;
warp_camera Warp_camera;
@@ -27,6 +27,33 @@ SCP_vector<camera*> Cameras;
camid Current_camera;
camid Main_camera;
asymmetric_fov operator* (const asymmetric_fov& left, const float& right) {
return asymmetric_fov{ left.left * right, left.right * right, left.up * right, left.down * right };
}
asymmetric_fov operator+ (const asymmetric_fov& left, const float& right) {
float ar = (left.up - left.down) / (left.right - left.left);
return asymmetric_fov{ left.left - right * 0.5f, left.right + right * 0.5f, left.up + right * 0.5f * ar, left.down - right * 0.5f * ar };
}
asymmetric_fov operator- (const asymmetric_fov& left, const float& right) {
float ar = (left.up - left.down) / (left.right - left.left);
return asymmetric_fov{ left.left + right * 0.5f, left.right - right * 0.5f, left.up - right * 0.5f * ar, left.down + right * 0.5f * ar };
}
#define APPLY_TO_FOV_T(op, name) \
struct apply_##name##_to_fov { \
float r; \
template<typename T> \
fov_t operator()(const T& l) { \
return fov_t(l op r); \
} \
}; \
fov_t operator op (const fov_t& zoom, const float& scale) { \
return mpark::visit(apply_##name##_to_fov{scale}, zoom); \
}
APPLY_TO_FOV_T(*, mul)
APPLY_TO_FOV_T(+, add)
APPLY_TO_FOV_T(-, sub)
static SCP_string fov_display(float val)
{
auto degrees = fl_degrees(val);
@@ -34,15 +61,20 @@ static SCP_string fov_display(float val)
sprintf(out, u8"%.1f\u00B0", degrees);
return out;
}
auto FovOption = options::OptionBuilder<float>("Graphics.FOV", "Field Of View", "The vertical field of view.")
.category("Graphics")
.range(0.436332f, 1.5708f)
.bind_to(&VIEWER_ZOOM_DEFAULT)
.display(fov_display)
.default_val(0.75f)
.level(options::ExpertLevel::Advanced)
.importance(60)
.finish();
auto FovOption = options::OptionBuilder<float>("Graphics.FOV",
std::pair<const char*, int>{"Field Of View", 1703},
std::pair<const char*, int>{"The vertical field of view", 1704})
.category("Graphics")
.range(0.436332f, 1.5708f)
.change_listener([](const float& val, bool) {
VIEWER_ZOOM_DEFAULT = val;
return true;
})
.display(fov_display)
.default_val(0.75f)
.level(options::ExpertLevel::Advanced)
.importance(60)
.finish();
//*************************CLASS: camera*************************
//This is where the camera class begins! :D
@@ -85,7 +117,7 @@ void camera::reset()
func_custom_orientation = NULL;
fov.clear();
fov.set(VIEWER_ZOOM_DEFAULT);
fov.set(g3_get_hfov(VIEWER_ZOOM_DEFAULT));
pos_x.clear();
pos_y.clear();
@@ -104,7 +136,7 @@ void camera::set_name(const char *in_name)
strncpy(name, in_name, NAME_LENGTH-1);
}
void camera::set_fov(float in_fov, float in_fov_time, float in_fov_acceleration_time, float in_fov_deceleration_time)
void camera::set_fov(fov_t in_fov, float in_fov_time, float in_fov_acceleration_time, float in_fov_deceleration_time)
{
if(in_fov_time == 0.0f && in_fov_acceleration_time == 0.0f && in_fov_deceleration_time == 0.0f)
{
@@ -114,26 +146,23 @@ void camera::set_fov(float in_fov, float in_fov_time, float in_fov_acceleration_
}
flags &= ~CAM_STATIONARY_FOV;
if(in_fov <= 0.0f)
if(g3_get_hfov(in_fov) <= 0.0f)
{
fov.setVD(in_fov_time, in_fov_acceleration_time, 0.0f);
}
fov.setAVD(in_fov, in_fov_time, in_fov_acceleration_time, in_fov_deceleration_time, 0.0f);
fov.setAVD(g3_get_hfov(in_fov), in_fov_time, in_fov_acceleration_time, in_fov_deceleration_time, 0.0f);
}
void camera::set_object_host(object *objp, int n_object_host_submodel)
{
if(objp == NULL)
object_host = object_h();
object_host = object_h(objp);
object_host_submodel = n_object_host_submodel;
set_custom_position_function(NULL);
set_custom_orientation_function(NULL);
if(n_object_host_submodel > 0)
{
if(objp->type == OBJ_SHIP)
if(objp != nullptr && objp->type == OBJ_SHIP)
{
ship_subsys* ssp = GET_FIRST(&Ships[objp->instance].subsys_list);
while ( ssp != END_OF_LIST( &Ships[objp->instance].subsys_list ) )
@@ -319,11 +348,14 @@ int camera::get_object_target_submodel()
return object_target_submodel;
}
float camera::get_fov()
fov_t camera::get_fov()
{
if(!(flags & CAM_STATIONARY_FOV))
{
fov.get(&c_fov, NULL);
float fov_now;
fov.get(&fov_now, nullptr);
return fov_now;
//TODO enable moving asymmetric fov
}
return c_fov;
+18 -5
View File
@@ -10,6 +10,8 @@
#include <string>
#include <mpark/variant.hpp>
#define CAM_STATIONARY_FOV (1<<0)
#define CAM_STATIONARY_ORI (1<<1)
#define CAM_STATIONARY_POS (1<<2)
@@ -18,6 +20,17 @@
#define EXTERN_CAM_BBOX_CONSTANT_PADDING 5.0f
#define EXTERN_CAM_BBOX_MULTIPLIER_PADDING 1.5f
struct asymmetric_fov {
float left, right, up, down;
friend asymmetric_fov operator* (const asymmetric_fov&, const float&);
friend asymmetric_fov operator+ (const asymmetric_fov&, const float&);
friend asymmetric_fov operator- (const asymmetric_fov&, const float&);
};
using fov_t = mpark::variant<float, asymmetric_fov>;
fov_t operator* (const fov_t&, const float&);
fov_t operator+ (const fov_t&, const float&);
fov_t operator- (const fov_t&, const float&);
class camera
{
protected:
@@ -41,7 +54,7 @@ protected:
avd_movement ori[9];
//Cache stuff
float c_fov;
fov_t c_fov;
vec3d c_pos;
matrix c_ori;
public:
@@ -59,7 +72,7 @@ public:
void set_custom_position_function(void (*n_func_custom_position)(camera *cam, vec3d *pos));
void set_custom_orientation_function(void (*n_func_custom_orientation)(camera *cam, matrix *ori));
void set_fov(float in_fov, float in_fov_time = 0.0f, float in_fov_acceleration_time = 0.0f, float in_deceleration_time = 0.0f);
void set_fov(fov_t in_fov, float in_fov_time = 0.0f, float in_fov_acceleration_time = 0.0f, float in_deceleration_time = 0.0f);
void set_position(vec3d *in_position = NULL, float in_translation_time = 0.0f, float in_translation_acceleration_time = 0.0f, float in_translation_deceleration_time = 0.0f, float in_end_velocity = 0.0f);
@@ -74,7 +87,7 @@ public:
int get_object_host_submodel();
object *get_object_target();
int get_object_target_submodel();
float get_fov();
fov_t get_fov();
void get_info(vec3d *position, matrix *orientation, bool apply_camera_orientation = true);
//Is
@@ -155,8 +168,8 @@ public:
//Some global stuff
extern SCP_vector<subtitle> Subtitles;
extern float VIEWER_ZOOM_DEFAULT;
extern float COCKPIT_ZOOM_DEFAULT;
extern fov_t VIEWER_ZOOM_DEFAULT;
extern fov_t COCKPIT_ZOOM_DEFAULT;
extern float Sexp_fov;
//Helpful functions
+1 -1
View File
@@ -438,7 +438,7 @@ int cfile_flush_dir(int dir_type)
// filename = name of filename or filepath to process
// ext = extension to add. Must start with the period
// Returns: new filename or filepath with extension.
char *cf_add_ext(const char *filename, const char *ext)
const char *cf_add_ext(const char *filename, const char *ext)
{
static char path[MAX_PATH_LEN];
+1 -1
View File
@@ -171,7 +171,7 @@ int cfile_init(const char *exe_dir, const char *cdrom_dir=NULL);
void cfile_close();
// add an extension to a filename if it doesn't already have it
char *cf_add_ext(const char *filename, const char *ext);
const char *cf_add_ext(const char *filename, const char *ext);
// return filename of a CFILE you called cfopen() successfully on.
const char *cf_get_filename(const CFILE *cfile);
+43 -8
View File
@@ -775,9 +775,10 @@ int is_ext_in_list( const char *ext_list, const char *ext )
// Run a basic test for indexed files that may be shadowed
#ifndef NDEBUG
#define ENABLE_SHADOW_CHECK 1
SCP_vector<SCP_string> critical_shadowed;
#endif
static void check_file_shadows(const int root_index __UNUSED, const int pathtype __UNUSED, const SCP_string &name __UNUSED, const SCP_string sub_path __UNUSED)
static void check_file_shadows(const int root_index __UNUSED, const int pathtype __UNUSED, const SCP_string &name __UNUSED, const SCP_string &sub_path __UNUSED, const char *real_name = nullptr)
{
#if ENABLE_SHADOW_CHECK
if ( !cf_should_scan_subdirs(pathtype) ) {
@@ -786,11 +787,12 @@ static void check_file_shadows(const int root_index __UNUSED, const int pathtype
SCP_string curfile, newfile;
const bool critical = ((pathtype == CF_TYPE_TABLES) || (pathtype == CF_TYPE_MISSIONS));
const auto root = cf_get_root(root_index);
newfile = root->path + ((root->roottype == CF_ROOTTYPE_PACK) ? "::" : "");
newfile += cf_get_root_pathtype(root, pathtype) + DIR_SEPARATOR_CHAR;
newfile += sub_path + name;
newfile += sub_path + (real_name ? real_name : name);
for (uint i = 0; i < Num_files; ++i) {
const auto f = cf_get_file(i);
@@ -815,14 +817,23 @@ static void check_file_shadows(const int root_index __UNUSED, const int pathtype
continue;
}
curfile = r->path + ((r->roottype == CF_ROOTTYPE_PACK) ? "::" : "");
curfile += cf_get_root_pathtype(r, pathtype) + DIR_SEPARATOR_CHAR;
curfile += f->sub_path + f->name_ext;
if (r->roottype == CF_ROOTTYPE_PATH) {
curfile = f->real_name;
} else {
curfile = r->path + ((r->roottype == CF_ROOTTYPE_PACK) ? "::" : "");
curfile += cf_get_root_pathtype(r, pathtype) + DIR_SEPARATOR_CHAR;
curfile += f->sub_path + f->name_ext;
}
// this log message occurs in the middle of an existing line, hence the extra new lines
mprintf(("\nWARNING! A file being indexed may be shadowed by an existing file!\n New:\n %s\n Existing:\n %s\n",
mprintf(("\nWARNING! A %sfile being indexed may be shadowed by an existing file!\n New:\n %s\n Existing:\n %s\n",
critical ? "critical " : "",
newfile.c_str(), curfile.c_str()));
if (critical) {
critical_shadowed.push_back(name);
}
break;
}
#endif
@@ -886,12 +897,18 @@ void cf_search_root_path(int root_index)
for (auto &file : files) {
auto ext_idx = file.name.rfind('.');
auto orig_name = file.name;
if ( ext_idx != SCP_string::npos && SCP_string_lcase_equal_to()(file.name.substr(ext_idx), SCP_string(".lz41")) ) {
file.name = file.name.erase(ext_idx, file.name.length());
ext_idx = file.name.rfind('.');
}
if ( ext_idx == SCP_string::npos || !is_ext_in_list(Pathtypes[i].extensions, file.name.substr(ext_idx+1).c_str()) ) {
continue;
}
check_file_shadows(root_index, i, file.name, file.sub_path);
check_file_shadows(root_index, i, file.name, file.sub_path, orig_name.c_str());
cf_file *cfile = cf_create_file();
@@ -901,7 +918,7 @@ void cf_search_root_path(int root_index)
cfile->write_time = file.m_time;
cfile->size = static_cast<int>(file.size);
cfile->pack_offset = 0;
cfile->real_name = search_path + DIR_SEPARATOR_STR + file.sub_path + file.name;
cfile->real_name = search_path + DIR_SEPARATOR_STR + file.sub_path + orig_name;
cfile->sub_path = file.sub_path;
++num_files;
@@ -1143,6 +1160,24 @@ void cf_build_file_list()
}
}
#ifndef NDEBUG
// if some special/critical files might be shadowed then make sure the user knows about it
if ( !critical_shadowed.empty() && !running_unittests ) {
SCP_string shadowed;
const auto count = critical_shadowed.size();
// only report a few of the files so that the warning dialog doesn't get freakishly large
for (size_t j = 0; (j < 5) && (j < count); ++j) {
shadowed += critical_shadowed[j] + '\n';
}
Warning(LOCATION, "Some critical files might be shadowed! Please check the debug log for details.\n\n"
"%lu file(s) detected, including:\n%s", count, shadowed.c_str());
}
critical_shadowed.clear();
critical_shadowed.shrink_to_fit();
#endif
}
+8 -3
View File
@@ -16,7 +16,11 @@ bool CustomCheat::canUseCheat() {
void CustomCheat::runCheat() {
if (!canUseCheat()) return;
HUD_printf("%s", cheatMsg.c_str());
//Only try to send the message if we actually have one to send and are in a mission
if (!cheatMsg.empty() && (Game_mode & GM_IN_MISSION))
HUD_printf("%s", cheatMsg.c_str());
scripting::hooks::OnCheat->run(scripting::hook_param_list(scripting::hook_param("Cheat", 's', cheatCode)));
CheatUsed = cheatCode;
}
@@ -108,8 +112,9 @@ void parse_cheat_table(const char* filename) {
code = code.substr(0, CHEAT_BUFFER_LEN);
}
required_string("+Message:");
stuff_string(msg, F_MESSAGE);
if (optional_string("+Message:")) {
stuff_string(msg, F_MESSAGE);
}
if (optional_string("+RequireCheats:")) {
stuff_boolean(&requireCheats);
+47 -8
View File
@@ -188,6 +188,7 @@ Flag exe_params[] =
//flag launcher text FSO on_flags off_flags category reference URL
{ "-window", "Run in window", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-window", },
{ "-fullscreen_window", "Run in fullscreen window", false, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fullscreen_window", },
{ "-capture_mouse", "Capture the mouse within the window", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-capture_mouse", },
{ "-stretch_menu", "Stretch interface to fill screen", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-stretch_menu", },
{ "-noscalevid", "Disable scale-to-window for movies", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noscalevid", },
{ "-nomotiondebris", "Disable motion debris", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nomotiondebris",},
@@ -235,6 +236,7 @@ Flag exe_params[] =
{ "-prefer_ipv4", "Prefer IPv4 DNS lookups", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-prefer_ipv4", },
{ "-prefer_ipv6", "Prefer IPv6 DNS lookups", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-prefer_ipv6", },
{ "-log_multi_packet", "Log multi packet types ", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-log_multi_packet",},
{ "-no_bsp_align", "Disable pof BSP data alignment", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_bsp_align", },
#ifdef WIN32
{ "-fix_registry", "Use a different registry path", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fix_registry", },
#endif
@@ -273,6 +275,7 @@ Flag exe_params[] =
{ "-slow_frames_ok", "Don't adjust timestamps for slow frames", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-slow_frames_ok", },
{ "-imgui_debug", "Show imgui debug/demo window in the lab", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-imgui_debug", },
{ "-luadev", "Make lua errors non-fatal", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-luadev", },
{"-vulkan", "Use vulkan render backend", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-vulkan", },
};
// clang-format on
@@ -329,7 +332,6 @@ int Cmdline_use_last_pilot = 0;
// Graphics related
cmdline_parm fov_arg("-fov", "Vertical field-of-view factor", AT_FLOAT); // Cmdline_fov -- comand line FOV -Bobboau
cmdline_parm fov_cockpit_arg("-fov_cockpit", "Vertical field-of-view factor for Cockpits", AT_FLOAT);
cmdline_parm clip_dist_arg("-clipdist", "Changes the distance from the viewpoint for the near-clipping plane", AT_FLOAT); // Cmdline_clip_dist
cmdline_parm ambient_power_arg("-ambient", "Multiplies the brightness of all ambient light", AT_FLOAT);
cmdline_parm light_power_arg("-light", "Multiplies the brightness of all light", AT_FLOAT);
cmdline_parm emissive_power_arg("-emissive", "Multiplies the brightness of all ambient light", AT_FLOAT);
@@ -351,6 +353,7 @@ cmdline_parm deprecated_fxaa_arg("-fxaa", nullptr, AT_NONE);
cmdline_parm deprecated_fxaa_preset_arg("-fxaa_preset", "FXAA quality (0-2), requires post-processing and -fxaa", AT_INT);
cmdline_parm deprecated_smaa_arg("-smaa", nullptr, AT_NONE);
cmdline_parm deprecated_smaa_preset_arg("-smaa_preset", "SMAA quality (0-3), requires post-processing and -smaa", AT_INT);
cmdline_parm msaa_enabled_arg("-msaa", nullptr, AT_INT);
cmdline_parm fb_explosions_arg("-fb_explosions", NULL, AT_NONE);
cmdline_parm fb_thrusters_arg("-fb_thrusters", NULL, AT_NONE);
cmdline_parm flightshaftsoff_arg("-nolightshafts", NULL, AT_NONE);
@@ -360,7 +363,6 @@ cmdline_parm no_deferred_lighting_arg("-no_deferred", NULL, AT_NONE); // Cmdline
cmdline_parm deferred_lighting_cockpit_arg("-deferred_cockpit", nullptr, AT_NONE);
cmdline_parm anisotropy_level_arg("-anisotropic_filter", NULL, AT_INT);
float Cmdline_clip_dist = Default_min_draw_distance;
float Cmdline_ambient_power = 1.0f;
float Cmdline_emissive_power = 0.0f;
float Cmdline_light_power = 1.0f;
@@ -379,6 +381,7 @@ bool Cmdline_force_lightshaft_off = false;
int Cmdline_no_deferred_lighting = 0;
bool Cmdline_deferred_lighting_cockpit = false;
int Cmdline_aniso_level = 0;
int Cmdline_msaa_enabled = 0;
// Game Speed related
cmdline_parm no_fpscap("-no_fps_capping", "Don't limit frames-per-second", AT_NONE); // Cmdline_NoFPSCap
@@ -404,6 +407,7 @@ cmdline_parm use_3dwarp("-3dwarp", nullptr, AT_NONE); // Is now Fireball_use_3
cmdline_parm use_warp_flash("-warp_flash", nullptr, AT_NONE); // Cmdline_warp_flash
cmdline_parm allow_autpilot_interrupt("-no_ap_interrupt", nullptr, AT_NONE);
cmdline_parm stretch_menu("-stretch_menu", nullptr, AT_NONE); // Cmdline_stretch_menu
cmdline_parm capture_mouse("-capture_mouse", nullptr, AT_NONE); // Cmdline_capture_mouse
cmdline_parm no_screenshake("-no_screenshake", nullptr, AT_NONE); // Cmdline_no_screenshake
cmdline_parm deadzone("-deadzone",
"Sets the joystick deadzone. Integer value from 0 to 100 as a percentage of the joystick's range (100% would make the stick do nothing). Disables deadzone slider in the in-game Options menu.", AT_INT); //Cmdline_deadzone
@@ -412,6 +416,7 @@ int Cmdline_ship_choice_3d = 0;
int Cmdline_weapon_choice_3d = 0;
int Cmdline_autopilot_interruptable = 1;
int Cmdline_stretch_menu = 0;
bool Cmdline_capture_mouse = false;
int Cmdline_no_screenshake = 0;
int Cmdline_deadzone = -1;
@@ -442,8 +447,10 @@ char *Cmdline_gateway_ip = nullptr;
// Launcher related options
cmdline_parm portable_mode("-portable_mode", NULL, AT_NONE);
cmdline_parm joy_info("-joy_info", "Outputs SDL joystick info", AT_NONE);
cmdline_parm lang_arg("-language", "Language name as defined in strings.tbl", AT_STRING);
bool Cmdline_portable_mode = false;
SCP_string Cmdline_lang;
// Troubleshooting
cmdline_parm loadallweapons_arg("-loadallweps", NULL, AT_NONE); // Cmdline_load_all_weapons
@@ -464,6 +471,7 @@ cmdline_parm noshadercache_arg("-noshadercache", NULL, AT_NONE);
cmdline_parm prefer_ipv4_arg("-prefer_ipv4", nullptr, AT_NONE);
cmdline_parm prefer_ipv6_arg("-prefer_ipv6", nullptr, AT_NONE);
cmdline_parm log_multi_packet_arg("-log_multi_packet", nullptr, AT_NONE);
cmdline_parm no_bsp_align_arg("-no_bsp_align", nullptr, AT_NONE);
#ifdef WIN32
cmdline_parm fix_registry("-fix_registry", NULL, AT_NONE);
#endif
@@ -485,6 +493,7 @@ bool Cmdline_noshadercache = false;
bool Cmdline_prefer_ipv4 = false;
bool Cmdline_prefer_ipv6 = false;
bool Cmdline_dump_packet_type = false;
bool Cmdline_no_bsp_align = false;
#ifdef WIN32
bool Cmdline_alternate_registry_path = false;
#endif
@@ -525,6 +534,7 @@ cmdline_parm fixed_seed_rand("-seed", nullptr, AT_INT); // Cmdline_rng_seed,Cmdl
cmdline_parm luadev_arg("-luadev", "Make lua errors non-fatal", AT_NONE); // Cmdline_lua_devmode
cmdline_parm override_arg("-override_data", "Enable override directory", AT_NONE); // Cmdline_override_data
cmdline_parm imgui_debug_arg("-imgui_debug", nullptr, AT_NONE);
cmdline_parm vulkan("-vulkan", nullptr, AT_NONE);
char *Cmdline_start_mission = NULL;
int Cmdline_dis_collisions = 0;
@@ -560,6 +570,7 @@ bool Cmdline_slow_frames_ok = false;
bool Cmdline_lua_devmode = false;
bool Cmdline_override_data = false;
bool Cmdline_show_imgui_debug = false;
bool Cmdline_vulkan = false;
// Other
cmdline_parm get_flags_arg(GET_FLAGS_STRING, "Output the launcher flags file", AT_STRING);
@@ -827,7 +838,7 @@ void os_validate_parms(int argc, char *argv[])
// if we got a -help, --help, -h, or -? then show the help text, otherwise show unknown option
if (!stricmp(token, "-help") || !stricmp(token, "--help") || !stricmp(token, "-h") || !stricmp(token, "-?")) {
printf("FreeSpace 2 Open, version %s\n", FS_VERSION_FULL);
printf("Website: http://scp.indiegames.us\n");
printf("Website: https://scp.indiegames.us\n");
printf("Github (bug reporting): https://github.com/scp-fs2open/fs2open.github.com/issues\n\n");
printf("Usage: fs2_open [options]\n");
@@ -1638,7 +1649,7 @@ bool SetCmdlineParams()
// be sure that this string fits in our limits
if ( strlen(Cmdline_game_password) >= MAX_PASSWD_LEN ) {
ReleaseWarning(LOCATION, "Multi game password is longer than max of %d charaters and will be trimmed to fit!", MAX_PASSWD_LEN-1);
ReleaseWarning(LOCATION, "Multi game password is longer than max of %d characters and will be trimmed to fit!", MAX_PASSWD_LEN-1);
Cmdline_game_password[MAX_PASSWD_LEN-1] = '\0';
}
}
@@ -1835,10 +1846,6 @@ bool SetCmdlineParams()
}
}
if( clip_dist_arg.found() ) {
Min_draw_distance = Cmdline_clip_dist = clip_dist_arg.get_float();
}
if (orb_radar.found())
{
Cmdline_orb_radar = 1;
@@ -1867,6 +1874,10 @@ bool SetCmdlineParams()
if ( stretch_menu.found() ) {
Cmdline_stretch_menu = 1;
}
if ( capture_mouse.found() ) {
Cmdline_capture_mouse = true;
}
// new lighting lines
if ( ambient_power_arg.found() )
Cmdline_ambient_power = ambient_power_arg.get_float();
@@ -1933,6 +1944,21 @@ bool SetCmdlineParams()
}
}
if (msaa_enabled_arg.found()) {
Cmdline_msaa_enabled = msaa_enabled_arg.get_int();
switch (Cmdline_msaa_enabled) {
case 0:
case 4:
case 8:
case 16:
break;
default:
Warning(LOCATION, "Requested illegal MSAA sample count %d. Allowed are: 0, 4, 8, 16. Setting to 0.", Cmdline_msaa_enabled);
Cmdline_msaa_enabled = 0;
break;
}
}
if ( glow_arg.found() )
Cmdline_glow = 0;
@@ -2000,6 +2026,15 @@ bool SetCmdlineParams()
{
Cmdline_portable_mode = true;
}
if (lang_arg.found())
{
Cmdline_lang = lang_arg.str();
}
if (no_bsp_align_arg.found()) {
Cmdline_no_bsp_align = true;
}
#ifdef WIN32
if (fix_registry.found()) {
@@ -2200,6 +2235,10 @@ bool SetCmdlineParams()
Cmdline_show_video_info = true;
}
if (vulkan.found()) {
Cmdline_vulkan = true;
}
//Deprecated flags - CommanderDJ
if (deprecated_no_emissive_arg.found()) {
Cmdline_emissive = 0;
+4 -1
View File
@@ -52,7 +52,6 @@ extern char *Cmdline_center_res;
// FSO OPTIONS -------------------------------------------------
// Graphics related
extern float Cmdline_clip_dist;
extern float Cmdline_ambient_power;
extern float Cmdline_emissive_power;
extern float Cmdline_light_power;
@@ -70,6 +69,7 @@ extern int Cmdline_no_deferred_lighting;
extern bool Cmdline_deferred_lighting_cockpit;
extern int Cmdline_emissive;
extern int Cmdline_aniso_level;
extern int Cmdline_msaa_enabled;
// Game Speed related
extern int Cmdline_NoFPSCap;
@@ -86,6 +86,7 @@ extern int Cmdline_ship_choice_3d;
extern int Cmdline_weapon_choice_3d;
extern int Cmdline_autopilot_interruptable;
extern int Cmdline_stretch_menu;
extern bool Cmdline_capture_mouse;
extern int Cmdline_no_screenshake;
extern int Cmdline_deadzone;
@@ -104,6 +105,7 @@ extern char *Cmdline_gateway_ip;
// Launcher related options
extern bool Cmdline_portable_mode;
extern SCP_string Cmdline_lang;
// Troubleshooting
extern int Cmdline_load_all_weapons;
@@ -156,6 +158,7 @@ extern bool Cmdline_slow_frames_ok;
extern bool Cmdline_lua_devmode;
extern bool Cmdline_override_data;
extern bool Cmdline_show_imgui_debug;
extern bool Cmdline_vulkan;
enum class WeaponSpewType { NONE = 0, STANDARD, ALL };
extern WeaponSpewType Cmdline_spew_weapon_stats;
+8
View File
@@ -51,6 +51,14 @@ void cmeasure_set_ship_launch_vel(object *objp, object *parent_objp, int arand)
objp->phys_info.max_vel.xyz.z = -25.0f;
vm_vec_copy_scale(&objp->phys_info.desired_vel, &objp->orient.vec.fvec, objp->phys_info.max_vel.xyz.z );
// if this cmeasure has a single segment trail, let the trail know since we just changed the velocity
// yeah this is hacky but that's what this function gets for CHANGING the velocity on objects with a ""CONSTANT VELOCITY""
weapon* wp = &Weapons[objp->instance];
if (wp->trail_ptr && wp->trail_ptr->single_segment) {
wp->trail_ptr->vel[0] = objp->phys_info.vel;
wp->trail_ptr->vel[1] = objp->phys_info.vel;
}
}
/**
File diff suppressed because it is too large. Load diff
+120 -3
View File
@@ -433,6 +433,26 @@ private:
short btn = -1; //!< The button, key combo, or axis that's bound.
};
/**
* @struct cc_line
* @brief Defines an interactable line to display control names and their bindings
*/
struct cc_line {
const char* label;
int cc_index; // index into Control_config of item
int y; // Y coordinate of line
int kx, kw, jx, jw; // x start and width of keyboard and joystick bound text
};
/**
* @struct conflict
* @brief Defines an conflict between bindings
*/
struct conflict {
int first = -1; // index of other control in conflict with this one
int second = -1; // index of other control in conflict with this one
};
/*!
* A pair of bindings.
* @note Please don't set the bindings directly, use ::take() instead.
@@ -641,6 +661,15 @@ private:
SCP_vector<CCI>& ControlConfig;
};
enum class selItem : int {
selItem_REND, // Must be first to allow cycling
None,
Primary,
Secondary,
selItem_END // Must be last to allow cycling
};
extern int Failed_key_index;
@@ -649,6 +678,9 @@ extern int Joy_sensitivity;
extern int Control_config_overlay_id;
extern SCP_vector<cc_line> Cc_lines; //!< Stores the keyboard details for the UI
extern SCP_vector<conflict> Conflicts; //!< Stores conflict data for the keybinds
extern SCP_vector<CCI> Control_config; //!< Stores the keyboard configuration
extern SCP_vector<CC_preset> Control_config_presets; // tabled control presets; pointers to config_item arrays
extern const char **Joy_button_text; // String table of button labels. XSTR'd on init.
@@ -689,7 +721,7 @@ void control_config_common_close();
/*!
* @brief init config menu
*/
void control_config_init();
void control_config_init(bool API_Access = false);
/*!
* @brief do a frame of the config menu
@@ -699,12 +731,73 @@ void control_config_do_frame(float frametime);
/*!
* @brief close config menu
*/
void control_config_close();
void control_config_close(bool API_Access = false);
/*!
* @brief setup for binding a control
*/
void control_config_do_bind(bool API_Access = false);
/*!
* @brief setup for searching a control
*/
void control_config_do_search(bool API_Access = false);
/**
* @brief Unbinds the selected control
*/
bool control_config_remove_binding(int ctrl, selItem item, bool API_Access = false);
/**
* @brief Clears all conflicting control bindings, except the selected control
*/
bool control_config_clear_other(int ctrl, bool API_Access = false);
/**
* @brief Unbinds ALL controls
* TODO: unbind axes and reset inversion
*/
bool control_config_clear_all(bool API_Access = false);
/**
* @brief Reverts all bindings to their preset. If already default, cycle to the next presets.
*/
bool control_config_do_reset(bool cycle = true, bool API_Access = false);
/**
* @brief Toggles a modifier on or off for a control binding
*/
bool control_config_toggle_modifier(int bit, int ctrl, bool API_Access = false);
/**
* @brief Toggles inversion for the selected axis control
*/
bool control_config_toggle_invert(int ctrl, selItem item, bool API_Access = false);
/*!
* @brief Performs a single undo opration, reverting the most recent change to bindings, if any
*/
void control_config_do_undo(bool API_Access = false);
/*!
*@brief Runs every frame to check for input and binds the input if appropriate
*/
int control_config_bind_key_on_frame(int ctrl, selItem item, bool API_Access = false);
/*!
*@brief Runs every frame to check for input. Returns the index of the item the key is bound to or -1 if nothing.
*/
int control_config_search_key_on_frame(bool API_Access = false);
/*!
* Does a cursory conflict check, then accepts changes to the bindings, if any, and request the menu to close.
*/
bool control_config_accept(bool API_Access = false);
/*!
* @brief Cancel configuration of controls, revert any changes, return to previous menu/game state
*/
void control_config_cancel_exit();
void control_config_cancel_exit(bool API_Access = false);
/*!
* @brief Copies all bindings within preset into Control_config
@@ -735,6 +828,30 @@ bool control_config_use_preset_by_name(const SCP_string &name);
SCP_vector<CC_preset>::iterator control_config_get_current_preset(bool invert_agnostic = false);
/*!
* @brief Deletes the preset
*
* @returns TRUE if successful
* @returns FALSE if the preset is default or currently selected
*/
bool control_config_delete_preset(CC_preset preset);
/*!
* @brief Clones a preset
*
* @returns TRUE if successful
* @returns FALSE if the preset already exists with that name
*/
bool control_config_clone_preset(CC_preset preset, SCP_string name);
/*!
* @brief Saves a preset with the current controls
*
* @returns TRUE if successful
* @returns FALSE if the preset already exists with that name
*/
bool control_config_create_new_preset(SCP_string name);
/*!
* Returns the IoActionId (index within Control_config[]) of a control bound to the given key
*
+35 -29
View File
@@ -45,27 +45,29 @@ int Failed_key_index;
// Joystick configuration
int Joy_dead_zone_size = 10;
auto DeadZoneOption =
options::OptionBuilder<int>("Input.JoystickDeadZone", "Deadzone", "The deadzone of the selected joystick.")
.category("Input")
.range(0, 45)
.level(options::ExpertLevel::Beginner)
.default_val(10)
.bind_to(&Joy_dead_zone_size)
.importance(1)
.finish();
auto DeadZoneOption = options::OptionBuilder<int>("Input.JoystickDeadZone",
std::pair<const char*, int>{"Deadzone", 1377},
std::pair<const char*, int>{"The deadzone used for all joysticks", 1744})
.category("Input")
.range(0, 45)
.level(options::ExpertLevel::Beginner)
.default_val(10)
.bind_to(&Joy_dead_zone_size)
.importance(1)
.finish();
int Joy_sensitivity = 9;
auto SensitivityOption =
options::OptionBuilder<int>("Input.JoystickSensitivity", "Sensitivity", "The sentitivity of the selected joystick.")
.category("Input")
.range(0, 9)
.level(options::ExpertLevel::Beginner)
.default_val(9)
.bind_to(&Joy_sensitivity)
.importance(2)
.finish();
auto SensitivityOption = options::OptionBuilder<int>("Input.JoystickSensitivity",
std::pair<const char*, int>{"Sensitivity", 1745},
std::pair<const char*, int>{"The sensitivity used for all joysticks", 1746})
.category("Input")
.range(0, 9)
.level(options::ExpertLevel::Beginner)
.default_val(9)
.bind_to(&Joy_sensitivity)
.importance(2)
.finish();
//! arrays which hold the key mappings. The array index represents a key-independent action.
//! please use SPACES for aligning the fields of this array
@@ -158,8 +160,8 @@ void control_config_common_init_bindings() {
// flight controls (flight modes)
(BANK_WHEN_PRESSED, -1, -1, SHIP_TAB, 1, "Bank When Pressed", CC_TYPE_CONTINUOUS)
(AFTERBURNER, KEY_TAB, 5, SHIP_TAB, 1, "Afterburner", CC_TYPE_CONTINUOUS)
(GLIDE_WHEN_PRESSED, -1, -1, SHIP_TAB, 0, "Glide When Pressed", CC_TYPE_CONTINUOUS)
(TOGGLE_GLIDING, KEY_ALTED | KEY_G, -1, SHIP_TAB, 0, "Toggle Gliding", CC_TYPE_TRIGGER)
(GLIDE_WHEN_PRESSED, -1, -1, SHIP_TAB, 1774, "Glide When Pressed", CC_TYPE_CONTINUOUS)
(TOGGLE_GLIDING, KEY_ALTED | KEY_G, -1, SHIP_TAB, 1775, "Toggle Gliding", CC_TYPE_TRIGGER)
// flight controls (axes)
(JOY_HEADING_AXIS, JOY_X_AXIS, MOUSE_X_AXIS, SHIP_TAB, 1016, "Turn (Yaw) Axis", CC_TYPE_AXIS_REL)
@@ -173,7 +175,7 @@ void control_config_common_init_bindings() {
(FIRE_SECONDARY, KEY_SPACEBAR, 1, WEAPON_TAB, 1, "Fire Secondary Weapon", CC_TYPE_CONTINUOUS)
(CYCLE_NEXT_PRIMARY, KEY_PERIOD, -1, WEAPON_TAB, 1, "Cycle Primary Weapon Forward", CC_TYPE_TRIGGER)
(CYCLE_PREV_PRIMARY, KEY_COMMA, -1, WEAPON_TAB, 1, "Cycle Primary Weapon Backward", CC_TYPE_TRIGGER)
(CYCLE_PRIMARY_WEAPON_SEQUENCE, KEY_O, -1, WEAPON_TAB, 0, "Cycle Primary Weapon Firing Rate", CC_TYPE_TRIGGER)
(CYCLE_PRIMARY_WEAPON_SEQUENCE, KEY_O, -1, WEAPON_TAB, 1776, "Cycle Primary Weapon Firing Rate", CC_TYPE_TRIGGER)
(CYCLE_SECONDARY, KEY_DIVIDE, -1, WEAPON_TAB, 1, "Cycle Secondary Weapon Forward", CC_TYPE_TRIGGER)
(CYCLE_NUM_MISSLES, KEY_SHIFTED | KEY_DIVIDE, -1, WEAPON_TAB, 1, "Cycle Secondary Weapon Firing Rate", CC_TYPE_TRIGGER)
(LAUNCH_COUNTERMEASURE, KEY_X, 3, WEAPON_TAB, 1, "Launch Countermeasure", CC_TYPE_TRIGGER)
@@ -209,8 +211,8 @@ void control_config_common_init_bindings() {
(PADLOCK_DOWN, -1, 32, COMPUTER_TAB, 1, "View Rear", CC_TYPE_CONTINUOUS)
(PADLOCK_LEFT, -1, 34, COMPUTER_TAB, 1, "View Left", CC_TYPE_CONTINUOUS)
(PADLOCK_RIGHT, -1, 35, COMPUTER_TAB, 1, "View Right", CC_TYPE_CONTINUOUS)
(VIEW_TOPDOWN, -1, -1, COMPUTER_TAB, 0, "Top-Down View", CC_TYPE_TRIGGER)
(VIEW_TRACK_TARGET, -1, -1, COMPUTER_TAB, 0, "Target Padlock View", CC_TYPE_TRIGGER)
(VIEW_TOPDOWN, -1, -1, COMPUTER_TAB, 1777, "Top-Down View", CC_TYPE_TRIGGER)
(VIEW_TRACK_TARGET, -1, -1, COMPUTER_TAB, 1778, "Target Padlock View", CC_TYPE_TRIGGER)
(RADAR_RANGE_CYCLE, KEY_RAPOSTRO, -1, COMPUTER_TAB, 1, "Cycle Radar Range", CC_TYPE_TRIGGER)
(SQUADMSG_MENU, KEY_C, -1, COMPUTER_TAB, 1, "Communications Menu", CC_TYPE_TRIGGER)
@@ -235,8 +237,8 @@ void control_config_common_init_bindings() {
// Navigation and Autopilot
(SHOW_NAVMAP, -1, -1, NO_TAB, 1, "Show Nav Map", CC_TYPE_TRIGGER, true)
(AUTO_PILOT_TOGGLE, KEY_ALTED | KEY_A, -1, COMPUTER_TAB, 0, "Toggle Auto Pilot", CC_TYPE_TRIGGER)
(NAV_CYCLE, KEY_ALTED | KEY_N, -1, COMPUTER_TAB, 0, "Cycle Nav Points", CC_TYPE_TRIGGER)
(AUTO_PILOT_TOGGLE, KEY_ALTED | KEY_A, -1, COMPUTER_TAB, 1779, "Toggle Auto Pilot", CC_TYPE_TRIGGER)
(NAV_CYCLE, KEY_ALTED | KEY_N, -1, COMPUTER_TAB, 1780, "Cycle Nav Points", CC_TYPE_TRIGGER)
// Escort
(ADD_REMOVE_ESCORT, KEY_ALTED | KEY_E, -1, COMPUTER_TAB, 1, "Add or Remove Escort", CC_TYPE_TRIGGER)
@@ -258,7 +260,7 @@ void control_config_common_init_bindings() {
// HUD
(TOGGLE_HUD, KEY_SHIFTED | KEY_O, -1, COMPUTER_TAB, 1, "Toggle HUD", CC_TYPE_TRIGGER)
(TOGGLE_HUD_CONTRAST, KEY_L, -1, COMPUTER_TAB, 1, "Toggle High HUD Contrast", CC_TYPE_TRIGGER)
(TOGGLE_HUD_SHADOWS, KEY_ALTED | KEY_L, -1, COMPUTER_TAB, 0, "Toggle HUD Drop Shadows", CC_TYPE_TRIGGER)
(TOGGLE_HUD_SHADOWS, KEY_ALTED | KEY_L, -1, COMPUTER_TAB, 1781, "Toggle HUD Drop Shadows", CC_TYPE_TRIGGER)
(HUD_TARGETBOX_TOGGLE_WIREFRAME, KEY_ALTED | KEY_SHIFTED | KEY_Q, -1, COMPUTER_TAB, 1, "Toggle HUD Wireframe Target View", CC_TYPE_TRIGGER)
// Custom Controls
@@ -643,7 +645,9 @@ const char *translate_key(char *key)
if (!first.empty() && !second.empty()) {
strcpy_s(text, first.textify().c_str());
strcat_s(text, " or ");
strcat_s(text, " ");
strcat_s(text, XSTR("or", 1672));
strcat_s(text, " ");
strcat_s(text, second.textify().c_str());
} else if (!first.empty()) {
@@ -653,7 +657,7 @@ const char *translate_key(char *key)
strcpy_s(text, second.textify().c_str());
} else {
strcpy_s(text, "None");
strcpy_s(text, XSTR("None", 1673));
}
return text;
@@ -664,7 +668,7 @@ const char *textify_scancode(int code)
static char text[BTN_MSG_LEN];
if (code < 0)
return "None";
return XSTR("None", 1673);
int keycode = code & KEY_MASK;
@@ -797,6 +801,8 @@ void control_config_common_init()
Mouse_button_text[6] = vm_strdup(XSTR("Wheel Down", 1656));
Mouse_button_text[7] = vm_strdup(XSTR("Wheel Left", 1657));
Mouse_button_text[8] = vm_strdup(XSTR("Wheel Right", 1658));
Script_system.OnStateDestroy.add([](lua_State*) -> void { Lua_hooks.clear(); });
}
/*
+28 -2
View File
@@ -35,7 +35,7 @@ Section lookupSectionValue(const char* name) {
return Section::Invalid;
}
void load_preset_files() {
void load_preset_files(SCP_string clone) {
SCP_vector<SCP_string> filelist;
cf_get_file_list(filelist, CF_TYPE_PLAYER_BINDS, NOX("*.json"), CF_SORT_NAME, nullptr,
CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
@@ -128,7 +128,8 @@ void load_preset_files() {
// Done with the file
auto it = preset_find_duplicate(preset);
if (it == Control_config_presets.end()) {
// If we just cloned the file, then allow the duplicate. Just this once.
if ((clone == preset.name) || (it == Control_config_presets.end())) {
Control_config_presets.push_back(preset);
} else if ((it->name != preset.name) || (it->type != Preset_t::pst)) {
@@ -147,6 +148,31 @@ bool preset_file_exists(SCP_string name) {
return cf_exists(name.c_str(), CF_TYPE_PLAYER_BINDS) != 0;
}
bool delete_preset_file(CC_preset preset) {
// can't remove the default preset!
if (preset.name == "default") {
return false;
}
auto it = control_config_get_current_preset();
// can't remove the currently loaded preset either!
if (preset.name == it->name) {
return false;
}
SCP_string filename = preset.name + ".json";
cf_delete(filename.c_str(), CF_TYPE_PLAYER_BINDS, CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
// Reload the presets from file.
Control_config_presets.resize(1);
load_preset_files();
return true;
}
bool save_preset_file(CC_preset preset, bool overwrite) {
// Must have a name
if (preset.name.empty()) {
+13 -1
View File
@@ -209,12 +209,24 @@ private:
*/
bool save_preset_file(CC_preset preset, bool overwrite);
/**
* @brief Deletes the given preset to file.
* @param[in] preset The preset to delete
*
* @returns True if successful, or
* @returns False Preset is default, or
* @returns False Preset file is the currently selected preset
*/
bool delete_preset_file(CC_preset preset);
/**
* @brief Loads in all preset .json files from 'players/presets'
* @details If a preset file is unique, it is loaded into the game and available for use by the player. However, if
* a preset is a duplicate of another preset, it is ignored, and the player is warned of it
*
* @param[in] clone Used to check if we just cloned a particular preset and allows just that clone in without warning
*/
void load_preset_files();
void load_preset_files(SCP_string clone = "");
/**
* @brief Checks if the given preset is a duplicate within Control_config_presets vector
+1 -1
View File
@@ -108,7 +108,7 @@ class Decoder {
* @note A implementation should initialize the datastructures required for decoding here.
*
* @param fileName The name of the file that should be opened
* @return @c true if the initialization was successfull, @c false otherwise
* @return @c true if the initialization was successful, @c false otherwise
*/
virtual bool initialize(const SCP_string& fileName, const PlaybackProperties& properties) = 0;
+3
View File
@@ -175,6 +175,9 @@ void parse_cutscene_table(const char* filename)
if (flag)
csnp->flags.set(Cutscene::Cutscene_Flags::Never_viewable);
}
if (optional_string("$Custom data:")) {
parse_string_map(csnp->custom_data, "$end_custom_data", "+Val:");
}
}
+1
View File
@@ -32,6 +32,7 @@ typedef struct cutscene_info
char name[NAME_LENGTH];
char* description;
flagset<Cutscene::Cutscene_Flags> flags;
SCP_map<SCP_string, SCP_string> custom_data;
} cutscene_info;
extern SCP_vector<cutscene_info> Cutscenes;
+8 -3
View File
@@ -174,10 +174,15 @@ void determine_display_positions(Player* player, PlaybackState* state) {
void initialize_player_state(Player* player, PlaybackState* state) {
determine_display_positions(player, state);
state->subtitle_font = font::FontManager::getFontIndex(Movie_subtitle_font);
if (!Movie_subtitle_font.empty()) {
state->subtitle_font = font::FontManager::getFontIndex(Movie_subtitle_font);
if (state->subtitle_font < 0) {
Warning(LOCATION, "Failed to load subtitle font '%s'! Subtitles will be disabled.", Movie_subtitle_font.c_str());
if (state->subtitle_font < 0) {
Warning(LOCATION, "Failed to load subtitle font '%s'! Subtitles will be disabled.", Movie_subtitle_font.c_str());
}
}
else if (font::FontManager::numberOfFonts() > 0) {
state->subtitle_font = 0; // if not explicitly specified, default to the first available font
}
}
+21 -19
View File
@@ -251,10 +251,10 @@ void debris_process_post(object * obj, float frame_time)
int n, n_arcs = Random::next(1, 3); // Create 1-3 sparks
vec3d v1, v2, v3, v4;
submodel_get_two_random_points_better(db->model_num, db->submodel_num, &v1, &v2);
submodel_get_two_random_points_better(db->model_num, db->submodel_num, &v3, &v4);
vec3d v1 = submodel_get_random_point(db->model_num, db->submodel_num);
vec3d v2 = submodel_get_random_point(db->model_num, db->submodel_num);
vec3d v3 = submodel_get_random_point(db->model_num, db->submodel_num);
vec3d v4 = submodel_get_random_point(db->model_num, db->submodel_num);
n = 0;
@@ -327,11 +327,7 @@ void debris_process_post(object * obj, float frame_time)
// Maybe move a vertex.... 20% of the time maybe?
int mr = Random::next();
if ( mr < Random::MAX_VALUE/5 ) {
vec3d v1, v2;
submodel_get_two_random_points_better(db->model_num, db->submodel_num, &v1, &v2);
db->arc_pts[i][mr % 2] = v1;
db->arc_pts[i][mr % 2] = submodel_get_random_point(db->model_num, db->submodel_num);
}
}
}
@@ -363,7 +359,7 @@ int debris_find_oldest()
}
#define DEBRIS_ROTVEL_SCALE 5.0f
void calc_debris_physics_properties( physics_info *pi, vec3d *min, vec3d *max );
void calc_debris_physics_properties( physics_info *pi, vec3d *min, vec3d *max, float density );
MONITOR(NumSmallDebris)
MONITOR(NumHullDebris)
@@ -378,8 +374,9 @@ MONITOR(NumHullDebris)
* @param exp_center Explosion center in global coordinates
* @param hull_flag Whether this debris is a chunk of a ship's hull (as opposed to shrapnel)
* @param exp_force Explosion force, used to assign velocity to pieces. 1.0f assigns velocity like before. 2.0f assigns twice as much to non-inherited part of velocity
* @param source_subsys The subsystem this debris came from, if any
*/
object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d *pos, vec3d *exp_center, bool hull_flag, float exp_force)
object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d *pos, vec3d *exp_center, bool hull_flag, float exp_force, ship_subsys* source_subsys)
{
int parent_objnum;
object *obj;
@@ -397,7 +394,7 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
obj = debris_create_only(parent_objnum, shipp->ship_info_index, shipp->alt_type_index, shipp->team, -1.0f, -1, model_num, submodel_num, pos, nullptr, hull_flag, vaporize, shipp->debris_damage_type_idx);
if (obj != nullptr)
{
debris_create_set_velocity(&Debris[obj->instance], shipp, exp_center, exp_force);
debris_create_set_velocity(&Debris[obj->instance], shipp, exp_center, exp_force, source_subsys);
debris_create_fire_hook(obj, source_obj);
}
@@ -669,7 +666,7 @@ object *debris_create_only(int parent_objnum, int parent_ship_class, int alt_typ
return obj;
}
void debris_create_set_velocity(debris *db, ship *source_shipp, vec3d *exp_center, float exp_force)
void debris_create_set_velocity(debris *db, ship *source_shipp, vec3d *exp_center, float exp_force, ship_subsys* source_subsys)
{
auto obj = &Objects[db->objnum];
auto source_obj = (source_shipp == nullptr) ? nullptr : &Objects[source_shipp->objnum];
@@ -690,7 +687,8 @@ void debris_create_set_velocity(debris *db, ship *source_shipp, vec3d *exp_cente
vec3d *min, *max;
min = &pm->submodel[db->submodel_num].min;
max = &pm->submodel[db->submodel_num].max;
calc_debris_physics_properties( &obj->phys_info, min, max );
float density = source_subsys != nullptr ? source_subsys->system_info->density : Ship_info[source_shipp->ship_info_index].debris_density;
calc_debris_physics_properties( &obj->phys_info, min, max, density);
}
else {
scale = exp_force * i2fl(Random::next(10, 29)); // for radial_vel away from blast center (non-hull)
@@ -773,7 +771,7 @@ void debris_create_fire_hook(object *obj, object *source_obj)
* Alas, poor debris_obj got whacked. Fortunately, we know who did it, where and how hard, so we
* can do something about it.
*/
void debris_hit(object *debris_obj, object * /*other_obj*/, vec3d *hitpos, float damage)
void debris_hit(object *debris_obj, object * /*other_obj*/, vec3d *hitpos, float damage, vec3d* force)
{
debris *debris_p = &Debris[debris_obj->instance];
@@ -813,6 +811,11 @@ void debris_hit(object *debris_obj, object * /*other_obj*/, vec3d *hitpos, float
damage = 0.0f;
}
if (hitpos && force && The_mission.ai_profile->flags[AI::Profile_Flags::Whackable_debris]) {
vec3d rel_hit_pos = *hitpos - debris_obj->pos;
physics_calculate_and_apply_whack(force, &rel_hit_pos, &debris_obj->phys_info, &debris_obj->orient, &debris_obj->phys_info.I_body_inv);
}
debris_obj->hull_strength -= damage;
if (debris_obj->hull_strength < 0.0f) {
@@ -833,7 +836,6 @@ void debris_hit(object *debris_obj, object * /*other_obj*/, vec3d *hitpos, float
int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, collision_info_struct *debris_hit_info, vec3d* hitNormal)
{
mc_info mc;
mc_info_init(&mc);
Assert( pdebris->type == OBJ_DEBRIS );
@@ -873,7 +875,7 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
weapon *wp = &Weapons[other_obj->instance];
wp->collisionInfo = new mc_info; // The weapon will free this memory later
memcpy(wp->collisionInfo, &mc, sizeof(mc_info));
*wp->collisionInfo = mc;
return mc.num_hits;
}
@@ -1115,7 +1117,7 @@ int debris_get_team(object *objp)
/**
* Fills in debris physics properties when created, specifically mass and moment of inertia
*/
void calc_debris_physics_properties( physics_info *pi, vec3d *mins, vec3d *maxs )
void calc_debris_physics_properties( physics_info *pi, vec3d *mins, vec3d *maxs, float density )
{
float dx, dy, dz, mass;
dx = maxs->xyz.x - mins->xyz.x;
@@ -1124,7 +1126,7 @@ void calc_debris_physics_properties( physics_info *pi, vec3d *mins, vec3d *maxs
// John, with new bspgen, just set pi->mass = mass
mass = 0.12f * dx * dy * dz;
pi->mass = (float) pow(mass, 0.6666667f) * 4.65f;
pi->mass = (float) pow(mass, 0.6666667f) * 4.65f * density;
pi->I_body_inv.vec.rvec.xyz.x = 12.0f / (pi->mass * (dy*dy + dz*dz));
pi->I_body_inv.vec.rvec.xyz.y = 0.0f;
+3 -3
View File
@@ -71,19 +71,19 @@ void debris_delete( object * obj );
void debris_process_post( object * obj, float frame_time);
// Create debris, set velocity, and fire scripting hook
object *debris_create( object *source_obj, int model_num, int submodel_num, vec3d *pos, vec3d *exp_center, bool hull_flag, float exp_force );
object *debris_create( object *source_obj, int model_num, int submodel_num, vec3d *pos, vec3d *exp_center, bool hull_flag, float exp_force, ship_subsys* source_subsys = nullptr );
// Create debris but don't do anything else
object *debris_create_only(int parent_objnum, int parent_ship_class, int alt_type_index, int team, float hull_strength, int spark_timeout, int model_num, int submodel_num, vec3d *pos, matrix *orient, bool hull_flag, bool vaporize, int damage_type_idx);
// Set velocity after debris creation
void debris_create_set_velocity(debris *db, ship *source_shipp, vec3d *exp_center, float exp_force);
void debris_create_set_velocity(debris *db, ship *source_shipp, vec3d *exp_center, float exp_force, ship_subsys* source_subsys = nullptr);
// Fire scripting hook after debris creation
void debris_create_fire_hook(object *obj, object *source_obj);
int debris_check_collision( object * obj, object * other_obj, vec3d * hitpos, collision_info_struct *debris_hit_info=NULL, vec3d* hitnormal = NULL );
void debris_hit( object * debris_obj, object * other_obj, vec3d * hitpos, float damage );
void debris_hit( object * debris_obj, object * other_obj, vec3d * hitpos, float damage, vec3d* force );
int debris_get_team(object *objp);
void debris_add_to_hull_list(debris *db);
+4 -1
View File
@@ -72,7 +72,10 @@ $Player Damage Factor: 0.25, 0.5, 0.65, 0.85, 1
;; factor applied to subsystem damage suffered by the player
;; (in addition to Player Damage Factor)
$Player Subsys Damage Factor: 0.2, 0.4, 0.6, 0.8, 1
$Player Subsys Damage Factor: 0.2, 0.4, 0.6, 0.8, 1
;; factor applied to damage inflicted by the player
$Player Damage Inflicted Factor: 1, 1, 1, 1, 1
;; measure of time (in F1_0 units) after which the AI will recalculate
;; the position of its target
+1 -1
View File
@@ -119,7 +119,7 @@
* half-rate linear filtering on GCN.
*
* If SMAA is applied to 64-bit color buffers, switching to point filtering
* when accesing them will increase the performance. Search for
* when accessing them will increase the performance. Search for
* 'SMAASamplePoint' to see which textures may benefit from point
* filtering, and where (which is basically the color input in the edge
* detection and resolve passes).
+2 -1
View File
@@ -15,7 +15,8 @@ layout (std140) uniform genericData {
void main()
{
vec4 baseColor = texture(baseMap, fragTexCoord.xyz);
float y = fragTexCoord.y / fragTexCoord.w;
vec4 baseColor = texture(baseMap, vec3(fragTexCoord.x, y, fragTexCoord.z));
baseColor.rgb = srgb_to_linear(baseColor.rgb);
vec4 blendColor = vec4(srgb_to_linear(fragColor.rgb), fragColor.a);
+1 -1
View File
@@ -17,7 +17,7 @@ layout (std140) uniform genericData {
void main()
{
fragTexCoord = vec4(vertTexCoord.xyz, 0.0);
fragColor = vertColor * color;
gl_Position = projMatrix * modelViewMatrix * vertPosition;
fragTexCoord = vertTexCoord;
}
+9
View File
@@ -0,0 +1,9 @@
in vec4 fragTexCoord;
out vec4 fragOut0;
uniform sampler2D tex;
void main()
{
fragOut0 = texture(tex, fragTexCoord.xy);
}
@@ -3,6 +3,7 @@ out vec4 fragOut1;
out vec4 fragOut2;
out vec4 fragOut3;
out vec4 fragOut4;
out vec4 fragOut5;
void main()
{
fragOut0 = vec4(0.0, 0.0, 0.0, 1.0); // color
@@ -10,4 +11,5 @@ void main()
fragOut2 = vec4(0.0, 0.0, 0.0, 1.0); // normal
fragOut3 = vec4(0.0, 0.0, 0.0, 0.0); // specular
fragOut4 = vec4(0.0, 0.0, 0.0, 1.0); // emissive
fragOut5 = vec4(0.0, 0.0, 0.0, 1.0); // composite
}
+27 -21
View File
@@ -3,8 +3,6 @@
#include "shadows.sdr" //! #include "shadows.sdr"
in vec3 beamVec;
in vec3 lightPosition;
out vec4 fragOut0;
uniform sampler2D ColorBuffer;
@@ -26,6 +24,13 @@ layout (std140) uniform globalDeferredData {
float invScreenWidth;
float invScreenHeight;
float nearPlane;
};
layout (std140) uniform matrixData {
mat4 modelViewMatrix;
mat4 projMatrix;
};
layout (std140) uniform lightData {
@@ -63,23 +68,24 @@ vec3 ExpandLightSize(in vec3 lightDir, in vec3 reflectDir) {
vec3 centerToRay = max(dot(lightDir, reflectDir),sourceRadius) * reflectDir - lightDir;
return lightDir + centerToRay * clamp(sourceRadius/length(centerToRay), 0.0, 1.0);
}
void GetLightInfo(vec3 position, in float alpha, in vec3 reflectDir, out vec3 lightDir, out float attenuation, out float area_normalisation)
void GetLightInfo(vec3 position, in float alpha, in vec3 reflectDir, out vec3 lightDirOut, out float attenuation, out float area_normalisation)
{
if (lightType == LT_DIRECTIONAL) {
lightDir = normalize(lightPosition);
lightDirOut = normalize(lightDir);
attenuation = 1.0;
area_normalisation = 1.0;
} else {
vec3 lightPosition = modelViewMatrix[3].xyz;
// Positional light source
if (lightType == LT_POINT) {
lightDir = lightPosition - position.xyz;
float dist = length(lightDir);
lightDirOut = lightPosition - position.xyz;
float dist = length(lightDirOut);
// this chunk is unneccessary if sourceRadius= 0.0, but let's avoid a branch.
// given a sphere of radius sourceRadius centered at lightDir,
// move lightDir towards the ray defined by reflectDir
lightDir = ExpandLightSize(lightDir, reflectDir);
dist = length(lightDir);
// this chunk is unnecessary if sourceRadius= 0.0, but let's avoid a branch.
// given a sphere of radius sourceRadius centered at lightDirOut,
// move lightDirOut towards the ray defined by reflectDir
lightDirOut = ExpandLightSize(lightDirOut, reflectDir);
dist = length(lightDirOut);
// Energy conservation term
float alpha_adjust = clamp(alpha + (sourceRadius/(2*dist)), 0.0, 1.0);
area_normalisation = alpha/alpha_adjust;
@@ -93,7 +99,7 @@ void GetLightInfo(vec3 position, in float alpha, in vec3 reflectDir, out vec3 li
attenuation = 1.0 - clamp(sqrt(dist / lightRadius), 0.0, 1.0);
}
else if (lightType == LT_TUBE) { // Tube light
vec3 beamVec = vec3(modelViewMatrix * vec4(0.0, 0.0, -scale.z, 0.0));
vec3 beamDir = normalize(beamVec);
//The actual 'lighting element' is shorter than the light volume cylinder
//To compensate the light is moved forward along the beam one radius and the length shortened
@@ -113,15 +119,15 @@ void GetLightInfo(vec3 position, in float alpha, in vec3 reflectDir, out vec3 li
vec3 r = d - a_t * dot(d, a_t) - c * dot(d,c);
float neardist = dot(r, r)/dot(b_t, r);
// Move along the beam by the distance we calculated
lightDir = sourceDir - beamDir * clamp(neardist, 0.0, beamLength);
lightDirOut = sourceDir - beamDir * clamp(neardist, 0.0, beamLength);
// Somebody with a symbolic expression simplifier or a wrinklier brain than me
// should figure out how to optimise these calcs - qaz
// this chunk is unneccessary if sourceRadius = 0.0, but let's avoid a branch.
// this chunk is unnecessary if sourceRadius = 0.0, but let's avoid a branch.
// Same principle as in LT_POINT, treat chosen location as a spherelight.
lightDir = ExpandLightSize(lightDir, reflectDir);
float dist = length(lightDir);
lightDirOut = ExpandLightSize(lightDirOut, reflectDir);
float dist = length(lightDirOut);
// Energy conservation term
float alpha_adjust = min(alpha + (sourceRadius/(2*dist)), 1.0);
area_normalisation = alpha/alpha_adjust;
@@ -134,9 +140,9 @@ void GetLightInfo(vec3 position, in float alpha, in vec3 reflectDir, out vec3 li
attenuation = 1.0 - clamp(sqrt(dist / lightRadius), 0.0, 1.0);
}
else if (lightType == LT_CONE) {
lightDir = lightPosition - position.xyz;
float coneDot = dot(normalize(-lightDir), coneDir);
float dist = length(lightDir);
lightDirOut = lightPosition - position.xyz;
float coneDot = dot(normalize(-lightDirOut), coneDir);
float dist = length(lightDirOut);
attenuation = 1.0 - clamp(sqrt(dist / lightRadius), 0.0, 1.0);
area_normalisation = 1.0;
@@ -155,7 +161,7 @@ void GetLightInfo(vec3 position, in float alpha, in vec3 reflectDir, out vec3 li
}
}
attenuation *= attenuation;
lightDir = normalize(lightDir);
lightDirOut = normalize(lightDirOut);
}
}
@@ -164,7 +170,7 @@ void main()
vec2 screenPos = gl_FragCoord.xy * vec2(invScreenWidth, invScreenHeight);
vec3 position = texture(PositionBuffer, screenPos).xyz;
if(abs(dot(position, position)) < 0.1)
if(abs(dot(position, position)) < nearPlane * nearPlane)
discard;
vec3 diffColor = texture(ColorBuffer, screenPos).rgb;
@@ -27,17 +27,11 @@ layout (std140) uniform lightData {
float sourceRadius;
};
out vec3 lightPosition;
out vec3 beamVec;
void main()
{
if (lightType == LT_DIRECTIONAL) {
gl_Position = vec4(vertPosition.xyz, 1.0);
lightPosition = lightDir;
} else {
gl_Position = projMatrix * modelViewMatrix * vec4(vertPosition.xyz * scale, 1.0);
lightPosition = modelViewMatrix[3].xyz;
if(lightType == LT_TUBE)
beamVec = vec3(modelViewMatrix * vec4(0.0, 0.0, -scale.z, 0.0));
}
}
+1 -1
View File
@@ -11,7 +11,7 @@ in vec4 fragTexCoord;
out vec4 fragOut0;
// Iteratively optimised points to give low discrepancy distribution on arbritrary hemisphere.
// Iteratively optimised points to give low discrepancy distribution on arbitrary hemisphere.
const vec3 points[128] = vec3[128](
vec3(-0.2268, 0.6185, 0.7523),
vec3( 0.9958, -0.0871, -0.0277),
+2 -2
View File
@@ -33,7 +33,7 @@ vec3 ComputeGGX(vec3 specColor, vec3 diffColor, vec3 light, vec3 normal, vec3 ha
// NOTE - we're intentionally using UE4's reflectance model as modellers are using tools designed for common engines.
// Cook-Torrance BRDF Model (Specular Reflection) = Distibution * Fresnel * Geometry / (4*dotNV*dotNL)
// Cook-Torrance BRDF Model (Specular Reflection) = Distribution * Fresnel * Geometry / (4*dotNV*dotNL)
// Distribution Term - Trowbridge-Reitz GGX
@@ -49,7 +49,7 @@ vec3 ComputeGGX(vec3 specColor, vec3 diffColor, vec3 light, vec3 normal, vec3 ha
// Smith's method:
// Microsurfaces block light rays coming in from the light
// AND block light rays reflecting to the camera.
// Hence, model both seperately and multiply.
// Hence, model both separately and multiply.
float g1vNL = GeometrySchlickGGX(dotNL, k);
float g1vNV = GeometrySchlickGGX(dotNV, k);
float geometry = g1vNL * g1vNV;
+253 -272
View File
@@ -2,12 +2,14 @@
#include "shadows.sdr" //! #include "shadows.sdr"
#include "lighting.sdr" //! #include "lighting.sdr"
#include "gamma.sdr" //! #include "gamma.sdr"
#include "model_shader_flags.h"
#define MAX_LIGHTS 8
#define LT_DIRECTIONAL 0
#define LT_POINT 1
#define LT_TUBE 2
#define LT_TUBE 2
struct model_light {
vec4 position;
@@ -54,21 +56,14 @@ layout (std140) uniform modelData {
int blend_alpha;
vec3 emissionFactor;
bool overrideDiffuse_;
vec3 diffuseClr_;
bool overrideGlow_;
vec3 glowClr_;
bool overrideSpec_;
vec3 specClr_;
bool alphaGloss;
bool gammaSpec;
bool envGloss;
bool alpha_spec_;
int effect_num;
int sBasemapIndex;
vec4 fogColor;
@@ -88,8 +83,6 @@ layout (std140) uniform modelData {
float middist;
float fardist;
vec2 normalAlphaMinMax_;
int sBasemapIndex;
int sGlowmapIndex;
int sSpecmapIndex;
@@ -98,58 +91,31 @@ layout (std140) uniform modelData {
int sMiscmapIndex;
float alphaMult;
int flags;
};
in VertexOutput {
#ifdef FLAG_ENV_MAP
vec3 envReflect;
#endif
mat3 tangentMatrix;
#ifdef FLAG_FOG
mat3 tangentMatrix;
float fogDist;
#endif
vec4 position;
vec3 normal;
vec4 texCoord;
#ifdef FLAG_SHADOWS
vec4 shadowUV[4];
vec4 shadowPos;
#endif
} vertIn;
#ifdef FLAG_DIFFUSE_MAP
uniform sampler2DArray sBasemap;
#endif
#ifdef FLAG_GLOW_MAP
uniform sampler2DArray sGlowmap;
#endif
#ifdef FLAG_SPEC_MAP
uniform sampler2DArray sSpecmap;
#endif
#ifdef FLAG_ENV_MAP
uniform samplerCube sEnvmap;
uniform samplerCube sIrrmap;
#endif
#ifdef FLAG_NORMAL_MAP
uniform sampler2DArray sNormalmap;
#endif
#ifdef FLAG_AMBIENT_MAP
uniform sampler2DArray sAmbientmap;
#endif
#ifdef FLAG_ANIMATED
uniform sampler2D sFramebuffer;
#endif
#ifdef FLAG_TEAMCOLOR
vec4 teamMask;
#endif
#ifdef FLAG_MISC_MAP
uniform sampler2DArray sMiscmap;
#endif
#ifdef FLAG_SHADOWS
uniform sampler2DArray shadow_map;
#endif
out vec4 fragOut0;
out vec4 fragOut1;
@@ -216,81 +182,73 @@ vec3 CalculateLighting(vec3 normal, vec3 diffuseMaterial, vec3 specularMaterial,
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
#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
vec3 eyeDir = vec3(normalize(-vertIn.position).xyz);
vec2 texCoord = vertIn.texCoord.xy;
// setup our baseline values for base, emissive, fresnel, gloss, AO and normal
// default specular value is set below, as it depends on the diffuse color
vec4 baseColor = color;
vec4 specColor = vec4(0.0, 0.0, 0.0, 1.0);
vec4 emissiveColor = vec4(0.0, 0.0, 0.0, 1.0);
float fresnelFactor = 0.0;
float glossData = defaultGloss;
vec2 aoFactors = vec2(1.0, 1.0);
#ifdef FLAG_AMBIENT_MAP
// red channel is ambient occlusion factor which only affects ambient lighting.
// green is cavity occlusion factor which only affects diffuse and specular lighting.
aoFactors = texture(sAmbientmap, vec3(texCoord, float(sAmbientmapIndex))).xy;
#endif
vec3 unitNormal = normalize(vertIn.normal);
vec3 normal = unitNormal;
#ifdef FLAG_NORMAL_MAP
// Normal map - convert from DXT5nm
vec2 normalSample;
normal.rg = normalSample = (texture(sNormalmap, vec3(texCoord, float(sNormalmapIndex))).ag * 2.0) - 1.0;
normal.b = clamp(sqrt(1.0 - dot(normal.rg, normal.rg)), 0.0001, 1.0);
normal = vertIn.tangentMatrix * normal;
float norm = length(normal);
// prevent breaking of normal maps
if (norm > 0.0)
normal /= norm;
else
normal = unitNormal;
#endif
#ifdef FLAG_ANIMATED
vec2 distort = vec2(cos(vertIn.position.x*vertIn.position.w*0.005+anim_timer*20.0)*sin(vertIn.position.y*vertIn.position.w*0.005),sin(vertIn.position.x*vertIn.position.w*0.005+anim_timer*20.0)*cos(vertIn.position.y*vertIn.position.w*0.005))*0.03;
#endif
if (FLAG_ACTIVE(MODEL_SDR_FLAG_AMBIENT)) {
// red channel is ambient occlusion factor which only affects ambient lighting.
// green is cavity occlusion factor which only affects diffuse and specular lighting.
aoFactors = texture(sAmbientmap, vec3(texCoord, float(sAmbientmapIndex))).xy;
}
#ifdef FLAG_DIFFUSE_MAP
vec2 diffuseTexCoord = texCoord;
#ifdef FLAG_ANIMATED
if (effect_num == 2) {
diffuseTexCoord = texCoord + distort*(1.0-anim_timer);
}
#endif
baseColor = texture(sBasemap, vec3(diffuseTexCoord, float(sBasemapIndex)));
if (FLAG_ACTIVE(MODEL_SDR_FLAG_NORMAL)) {
// Normal map - convert from DXT5nm
vec2 normalSample;
normal.rg = normalSample = (texture(sNormalmap, vec3(texCoord, float(sNormalmapIndex))).ag * 2.0) - 1.0;
normal.b = clamp(sqrt(1.0 - dot(normal.rg, normal.rg)), 0.0001, 1.0);
normal = vertIn.tangentMatrix * normal;
float norm = length(normal);
// prevent breaking of normal maps
if (norm > 0.0)
normal /= norm;
else
normal = unitNormal;
}
#ifdef FLAG_ALPHA_MULT
baseColor.a *= alphaMult;
#endif
vec2 distort = vec2(0.0, 0.0);
if ( blend_alpha == 0 && baseColor.a < 0.95 ) discard; // if alpha blending is not on, discard transparent pixels
// premultiply alpha if blend_alpha is 1. assume that our blend function is srcColor + (1-Alpha)*destColor.
// if blend_alpha is 2, assume blend func is additive and don't modify color
if(blend_alpha == 1) baseColor.rgb = baseColor.rgb * baseColor.a;
#endif
specColor = vec4(baseColor.rgb * SPEC_FACTOR_NO_SPEC_MAP, glossData);
#ifdef FLAG_HDR
baseColor.rgb = srgb_to_linear(baseColor.rgb);
#endif
#ifdef FLAG_SPEC_MAP
specColor = texture(sSpecmap, vec3(texCoord, float(sSpecmapIndex)));
if(alphaGloss) glossData = specColor.a;
if(gammaSpec) {
specColor.rgb = max(specColor.rgb, vec3(0.03f)); // hardcoded minimum specular value. read John Hable's blog post titled 'Everything Is Shiny'.
fresnelFactor = 1.0;
if (effect_num >= 0) {
distort = vec2(cos(vertIn.position.x*vertIn.position.w*0.005+anim_timer*20.0)*sin(vertIn.position.y*vertIn.position.w*0.005),sin(vertIn.position.x*vertIn.position.w*0.005+anim_timer*20.0)*cos(vertIn.position.y*vertIn.position.w*0.005))*0.03;
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_DIFFUSE)) {
vec2 diffuseTexCoord = texCoord;
if (effect_num == 2) {
diffuseTexCoord = texCoord + distort*(1.0-anim_timer);
}
baseColor = texture(sBasemap, vec3(diffuseTexCoord, float(sBasemapIndex)));
if (FLAG_ACTIVE(MODEL_SDR_FLAG_HDR)) {
baseColor.rgb = srgb_to_linear(baseColor.rgb);
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_ALPHA_MULT)) {
baseColor.a *= alphaMult;
}
if ( blend_alpha == 0 && baseColor.a < 0.95 ) discard; // if alpha blending is not on, discard transparent pixels
// premultiply alpha if blend_alpha is 1. assume that our blend function is srcColor + (1-Alpha)*destColor.
// if blend_alpha is 2, assume blend func is additive and don't modify color
if(blend_alpha == 1) baseColor.rgb = baseColor.rgb * baseColor.a;
}
#ifdef FLAG_HDR
specColor.rgb = srgb_to_linear(specColor.rgb);
#endif
#endif
baseColor.rgb *= aoFactors.y;
specColor.rgb *= aoFactors.y;
// Anti-glint "trick" based on Valve's "Advanced VR Rendering" talk at GDC2015:
// http://media.steampowered.com/apps/valve/2015/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf Page 43
@@ -300,176 +258,199 @@ void main()
float glossGeo = 1.0f - pow(clamp(max(dot(normDx,normDx), dot(normDy,normDy)),0.0,1.0),0.33);
glossData = min(glossData, glossGeo);
#ifdef FLAG_MISC_MAP
#ifdef FLAG_TEAMCOLOR
teamMask = texture(sMiscmap, vec3(texCoord, float(sMiscmapIndex)));
//For team colors applied to a diffuse or spec map, we assume that the base color of the diffuse
//at this point is vec3(0.5). To get accurate results, we subtract 0.5 from the team colors
vec3 color_offset = vec3(-0.5) * (teamMask.x + teamMask.y);
vec3 team_color = base_color * teamMask.x + stripe_color * teamMask.y + color_offset;
vec3 team_color_glow = (base_color * teamMask.b) + (stripe_color * teamMask.a);
#ifdef FLAG_HDR
baseColor.rgb = linear_to_srgb(baseColor.rgb);
specColor.rgb = linear_to_srgb(specColor.rgb);
#endif
baseColor.rgb += team_color;
baseColor.rgb = max(baseColor.rgb, vec3(0.0)); // We need to make sure that nothing here ever goes negative
specColor.rgb += team_color;
specColor.rgb = max(specColor.rgb, vec3(0.03));
#ifdef FLAG_HDR
baseColor.rgb = srgb_to_linear(baseColor.rgb);
specColor.rgb = srgb_to_linear(specColor.rgb);
#endif
#endif
#endif
// Now that we have a base color and min gloss value, compute the spec color
vec4 specColor = vec4(baseColor.rgb * SPEC_FACTOR_NO_SPEC_MAP, glossData);
if (FLAG_ACTIVE(MODEL_SDR_FLAG_SPEC)) {
specColor = texture(sSpecmap, vec3(texCoord, float(sSpecmapIndex)));
if(alphaGloss) glossData = specColor.a;
if(gammaSpec) {
specColor.rgb = max(specColor.rgb, vec3(0.03f)); // hardcoded minimum specular value. read John Hable's blog post titled 'Everything Is Shiny'.
fresnelFactor = 1.0;
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_HDR)) {
specColor.rgb = srgb_to_linear(specColor.rgb);
}
}
baseColor.rgb *= aoFactors.y;
specColor.rgb *= aoFactors.y;
vec4 teamMask = vec4(0.0);
vec3 team_color_glow = vec3(0.0);
if (FLAG_ACTIVE(MODEL_SDR_FLAG_MISC)) {
if (FLAG_ACTIVE(MODEL_SDR_FLAG_TEAMCOLOR)) {
teamMask = texture(sMiscmap, vec3(texCoord, float(sMiscmapIndex)));
//For team colors applied to a diffuse or spec map, we assume that the base color of the diffuse
//at this point is vec3(0.5). To get accurate results, we subtract 0.5 from the team colors
vec3 color_offset = vec3(-0.5) * (teamMask.x + teamMask.y);
vec3 team_color = base_color * teamMask.x + stripe_color * teamMask.y + color_offset;
team_color_glow = (base_color * teamMask.b) + (stripe_color * teamMask.a);
if (FLAG_ACTIVE(MODEL_SDR_FLAG_HDR)) {
baseColor.rgb = linear_to_srgb(baseColor.rgb);
specColor.rgb = linear_to_srgb(specColor.rgb);
}
baseColor.rgb += team_color;
baseColor.rgb = max(baseColor.rgb, vec3(0.0)); // We need to make sure that nothing here ever goes negative
specColor.rgb += team_color;
specColor.rgb = max(specColor.rgb, vec3(0.03));
if (FLAG_ACTIVE(MODEL_SDR_FLAG_HDR)) {
baseColor.rgb = srgb_to_linear(baseColor.rgb);
specColor.rgb = srgb_to_linear(specColor.rgb);
}
}
}
// Lights aren't applied when we are rendering to the G-buffers since that gets handled later
#ifdef FLAG_DEFERRED
#ifdef FLAG_LIGHT
// Ambient lighting still needs to be done since that counts as an "emissive" color
vec3 lightAmbient = (emissionFactor + ambientFactor * ambientFactor) * aoFactors.x; // ambientFactor^2 due to legacy OpenGL compatibility behavior
emissiveColor.rgb += baseColor.rgb * lightAmbient;
#else
#ifdef FLAG_SPEC_MAP
baseColor.rgb += pow(1.0 - clamp(dot(eyeDir, normal), 0.0, 1.0), 5.0 * clamp(glossData, 0.01, 1.0)) * specColor.rgb;
#endif
// If there is no lighting then we copy the color data so far into the
emissiveColor.rgb += baseColor.rgb;
#endif
#else
#ifdef FLAG_LIGHT
float shadow = 1.0;
#ifdef FLAG_SHADOWS
shadow = getShadowValue(shadow_map, -vertIn.position.z, vertIn.shadowPos.z, vertIn.shadowUV, fardist, middist, neardist, veryneardist);
#endif
baseColor.rgb = CalculateLighting(normal, baseColor.rgb, specColor.rgb, glossData, fresnelFactor, shadow, aoFactors.x);
#else
#ifdef FLAG_SPEC_MAP
baseColor.rgb += pow(1.0 - clamp(dot(eyeDir, normal), 0.0, 1.0), 5.0 * clamp(glossData, 0.01, 1.0)) * specColor.rgb;
#endif
#endif
#endif
#ifdef FLAG_ENV_MAP
#ifdef FLAG_LIGHT
// Bit of a hack here, pretend we're doing blinn-phong shading and use a (modified version of) the derivation from
// Plausible Blinn-Phong Reflection of Standard Cube MIP-Maps - McGuire et al.
// to determine the mip bias.
// We use the specular term listed at http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html
// 1/(pi*alpha^2) * NdotM^((2/alpha^2)-2)
// so let s = (2/alpha^2 - 2)
// 1/2 log(s + 1) = 1/2 log(2/alpha^2 -1)
const float ENV_REZ = 512; // Ideally this would be #define'd and shader recompiled with envmap rez changes
const float REZ_BIAS = log2(ENV_REZ * sqrt(3));
float roughness = clamp(1.0f - glossData, 0.0f, 1.0f);
float alpha = roughness * roughness;
float alphaSqr = alpha * alpha;
float rough_bias = 0.5 * log2(2/alphaSqr - 1);
float mip_bias = REZ_BIAS - rough_bias;
// Sample light, using mip bias to blur it.
vec3 light_dir = reflect(-eyeDir, normal);
vec3 env_light_dir = vec3(envMatrix * vec4(light_dir, 0.0));
vec4 specEnvColour = srgb_to_linear(textureLod(sEnvmap, env_light_dir, mip_bias));
vec3 halfVec = normal;
// Lots of hacks here to get things to look right. We aren't loading a BRDF split-sum integral texture
// or properly calculating IBL levels.
// Fresnel calculation as with standard lights.
vec3 fresnel = mix(specColor.rgb, FresnelSchlick(halfVec, eyeDir, specColor.rgb), specColor.a);
// Pseudo-IBL, so use k_IBL
float k = alpha * alpha/ 2.0f;
float NdotL = max(dot(light_dir, normal),0);
float g1vNL = GeometrySchlickGGX(NdotL, k);
vec3 specEnvLighting = specEnvColour.rgb * fresnel * g1vNL;
vec3 kD = vec3(1.0)-fresnel;
kD *= (vec3(1.0) - specColor.rgb);
vec3 diffEnvColor = srgb_to_linear(texture(sIrrmap, vec3(envMatrix * vec4(normal, 0.0))).rgb);
vec3 diffEnvLighting = kD * baseColor.rgb * diffEnvColor * aoFactors.x;
emissiveColor.rgb += (specEnvLighting + diffEnvLighting) * baseColor.a;
#endif
#endif
#ifdef FLAG_GLOW_MAP
vec3 glowColor = texture(sGlowmap, vec3(texCoord, float(sGlowmapIndex))).rgb;
#ifdef FLAG_MISC_MAP
#ifdef FLAG_TEAMCOLOR
float glowColorLuminance = dot(glowColor, vec3(0.299, 0.587, 0.114));
glowColor = team_glow_enabled ? mix(max(team_color_glow, vec3(0.0)), glowColor, clamp(glowColorLuminance - teamMask.b - teamMask.a, 0.0, 1.0)) : glowColor;
#endif
#endif
#ifdef FLAG_HDR
glowColor = srgb_to_linear(glowColor) * GLOW_MAP_SRGB_MULTIPLIER;
#endif
emissiveColor.rgb += glowColor * GLOW_MAP_INTENSITY;
#endif
#ifdef FLAG_FOG
vec3 finalFogColor = fogColor.rgb;
#ifdef FLAG_HDR
finalFogColor = srgb_to_linear(finalFogColor);
#endif
#ifdef FLAG_DIFFUSE_MAP
if(blend_alpha == 1) finalFogColor *= baseColor.a;
#endif
// This code will only be used by the forward renderer so we apply the fog effect to both the emissive and the base
// color.
baseColor.rgb = mix(emissiveColor.rgb + baseColor.rgb, finalFogColor, vertIn.fogDist);
emissiveColor.rgb = vec3(0.0); // Zero the emissive color since it has already been added by the previous line
specColor.rgb *= vertIn.fogDist;
#endif
#ifdef FLAG_DIFFUSE_MAP
if(desaturate == 1) {
baseColor.rgb = color.rgb * dot(vec3(1.0), baseColor.rgb) * 0.3333333;
if (FLAG_ACTIVE(MODEL_SDR_FLAG_DEFERRED)) {
if (FLAG_ACTIVE(MODEL_SDR_FLAG_LIGHT)) {
// Ambient lighting still needs to be done since that counts as an "emissive" color
vec3 lightAmbient = (emissionFactor + ambientFactor * ambientFactor) * aoFactors.x; // ambientFactor^2 due to legacy OpenGL compatibility behavior
emissiveColor.rgb += baseColor.rgb * lightAmbient;
} else {
if (FLAG_ACTIVE(MODEL_SDR_FLAG_SPEC)) {
baseColor.rgb += pow(1.0 - clamp(dot(eyeDir, normal), 0.0, 1.0), 5.0 * clamp(glossData, 0.01, 1.0)) * specColor.rgb;
}
// If there is no lighting then we copy the color data so far into the
emissiveColor.rgb += baseColor.rgb;
}
} else {
if (FLAG_ACTIVE(MODEL_SDR_FLAG_LIGHT)) {
float shadow = 1.0;
if (FLAG_ACTIVE(MODEL_SDR_FLAG_SHADOWS)) {
shadow = getShadowValue(shadow_map, -vertIn.position.z, vertIn.shadowPos.z, vertIn.shadowUV, fardist, middist, neardist, veryneardist);
}
baseColor.rgb = CalculateLighting(normal, baseColor.rgb, specColor.rgb, glossData, fresnelFactor, shadow, aoFactors.x);
} else {
if (FLAG_ACTIVE(MODEL_SDR_FLAG_SPEC)) {
baseColor.rgb += pow(1.0 - clamp(dot(eyeDir, normal), 0.0, 1.0), 5.0 * clamp(glossData, 0.01, 1.0)) * specColor.rgb;
}
}
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_ENV)) {
if (FLAG_ACTIVE(MODEL_SDR_FLAG_LIGHT)) {
// Bit of a hack here, pretend we're doing blinn-phong shading and use a (modified version of) the derivation from
// Plausible Blinn-Phong Reflection of Standard Cube MIP-Maps - McGuire et al.
// to determine the mip bias.
// We use the specular term listed at http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html
// 1/(pi*alpha^2) * NdotM^((2/alpha^2)-2)
// so let s = (2/alpha^2 - 2)
// 1/2 log(s + 1) = 1/2 log(2/alpha^2 -1)
const float ENV_REZ = 512; // Ideally this would be #define'd and shader recompiled with envmap rez changes
const float REZ_BIAS = log2(ENV_REZ * sqrt(3));
float roughness = clamp(1.0f - glossData, 0.0f, 1.0f);
float alpha = roughness * roughness;
float alphaSqr = alpha * alpha;
float rough_bias = 0.5 * log2(2/alphaSqr - 1);
float mip_bias = REZ_BIAS - rough_bias;
// Sample light, using mip bias to blur it.
vec3 light_dir = reflect(-eyeDir, normal);
vec3 env_light_dir = vec3(envMatrix * vec4(light_dir, 0.0));
vec4 specEnvColour = srgb_to_linear(textureLod(sEnvmap, env_light_dir, mip_bias));
vec3 halfVec = normal;
// Lots of hacks here to get things to look right. We aren't loading a BRDF split-sum integral texture
// or properly calculating IBL levels.
// Fresnel calculation as with standard lights.
vec3 fresnel = mix(specColor.rgb, FresnelSchlick(halfVec, eyeDir, specColor.rgb), specColor.a);
// Pseudo-IBL, so use k_IBL
float k = alpha * alpha/ 2.0f;
float NdotL = max(dot(light_dir, normal),0);
float g1vNL = GeometrySchlickGGX(NdotL, k);
vec3 specEnvLighting = specEnvColour.rgb * fresnel * g1vNL;
vec3 kD = vec3(1.0)-fresnel;
kD *= (vec3(1.0) - specColor.rgb);
vec3 diffEnvColor = srgb_to_linear(texture(sIrrmap, vec3(envMatrix * vec4(normal, 0.0))).rgb);
vec3 diffEnvLighting = kD * baseColor.rgb * diffEnvColor * aoFactors.x;
emissiveColor.rgb += (specEnvLighting + diffEnvLighting) * baseColor.a;
}
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_GLOW)) {
vec3 glowColor = texture(sGlowmap, vec3(texCoord, float(sGlowmapIndex))).rgb;
if (FLAG_ACTIVE(MODEL_SDR_FLAG_MISC)) {
if (FLAG_ACTIVE(MODEL_SDR_FLAG_TEAMCOLOR)) {
float glowColorLuminance = dot(glowColor, vec3(0.299, 0.587, 0.114));
glowColor = team_glow_enabled ? mix(max(team_color_glow, vec3(0.0)), glowColor, clamp(glowColorLuminance - teamMask.b - teamMask.a, 0.0, 1.0)) : glowColor;
}
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_HDR)) {
glowColor = srgb_to_linear(glowColor) * GLOW_MAP_SRGB_MULTIPLIER;
}
emissiveColor.rgb += glowColor * GLOW_MAP_INTENSITY;
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_FOG)) {
vec3 finalFogColor = fogColor.rgb;
if (FLAG_ACTIVE(MODEL_SDR_FLAG_HDR)) {
finalFogColor = srgb_to_linear(finalFogColor);
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_DIFFUSE)) {
if(blend_alpha == 1) finalFogColor *= baseColor.a;
}
// This code will only be used by the forward renderer so we apply the fog effect to both the emissive and the base
// color.
baseColor.rgb = mix(emissiveColor.rgb + baseColor.rgb, finalFogColor, vertIn.fogDist);
emissiveColor.rgb = vec3(0.0); // Zero the emissive color since it has already been added by the previous line
specColor.rgb *= vertIn.fogDist;
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_DIFFUSE)) {
if(desaturate == 1) {
baseColor.rgb = color.rgb * dot(vec3(1.0), baseColor.rgb) * 0.3333333;
}
}
if (effect_num == 0) {
float shinefactor = 1.0/(1.0 + pow(abs((fract(abs(texCoord.x))-anim_timer) * 1000.0), 2.0)) * 1000.0;
emissiveColor.rgb += vec3(shinefactor);
baseColor.a = baseColor.a * clamp(shinefactor * (fract(abs(texCoord.x))-anim_timer) * -10000.0,0.0,1.0);
} else if (effect_num == 1) {
float shinefactor = 1.0/(1.0 + pow(abs(vertIn.position.y-anim_timer), 2.0));
emissiveColor.rgb += vec3(shinefactor);
if (!(FLAG_ACTIVE(MODEL_SDR_FLAG_LIGHT))) {
// ATI Wireframe fix *grumble*
baseColor.a = clamp((vertIn.position.y-anim_timer) * 10000.0,0.0,1.0);
}
} else if (effect_num == 2) {
vec2 screenPos = gl_FragCoord.xy * vec2(vpwidth,vpheight);
baseColor.a = baseColor.a;
float cloak_interp = (sin(vertIn.position.x*vertIn.position.w*0.005+anim_timer*20.0)*sin(vertIn.position.y*vertIn.position.w*0.005)*0.5)-0.5;
if (FLAG_ACTIVE(MODEL_SDR_FLAG_LIGHT)) {
baseColor.rgb = mix(texture(sFramebuffer, screenPos + distort*anim_timer + anim_timer*0.1*normal.xy).rgb,baseColor.rgb,clamp(cloak_interp+anim_timer*2.0,0.0,1.0));
} else {
baseColor.rgb = mix(texture(sFramebuffer, screenPos + distort*anim_timer + anim_timer*0.1*vertIn.normal.xy).rgb,baseColor.rgb,clamp(cloak_interp+anim_timer*2.0,0.0,1.0));
}
}
if (!(FLAG_ACTIVE(MODEL_SDR_FLAG_DEFERRED))) {
// emissive colors won't be added later when we are using forward rendering so we need to do that here
baseColor.rgb += emissiveColor.rgb;
}
#endif
#ifdef FLAG_ANIMATED
if (effect_num == 0) {
float shinefactor = 1.0/(1.0 + pow(abs((fract(abs(texCoord.x))-anim_timer) * 1000.0), 2.0)) * 1000.0;
emissiveColor.rgb += vec3(shinefactor);
baseColor.a = baseColor.a * clamp(shinefactor * (fract(abs(texCoord.x))-anim_timer) * -10000.0,0.0,1.0);
}
if (effect_num == 1) {
float shinefactor = 1.0/(1.0 + pow(abs(vertIn.position.y-anim_timer), 2.0));
emissiveColor.rgb += vec3(shinefactor);
#ifndef FLAG_LIGHT
// ATI Wireframe fix *grumble*
baseColor.a = clamp((vertIn.position.y-anim_timer) * 10000.0,0.0,1.0);
#endif
}
if (effect_num == 2) {
vec2 screenPos = gl_FragCoord.xy * vec2(vpwidth,vpheight);
baseColor.a = baseColor.a;
float cloak_interp = (sin(vertIn.position.x*vertIn.position.w*0.005+anim_timer*20.0)*sin(vertIn.position.y*vertIn.position.w*0.005)*0.5)-0.5;
#ifdef FLAG_LIGHT
baseColor.rgb = mix(texture(sFramebuffer, screenPos + distort*anim_timer + anim_timer*0.1*normal.xy).rgb,baseColor.rgb,clamp(cloak_interp+anim_timer*2.0,0.0,1.0));
#else
baseColor.rgb = mix(texture(sFramebuffer, screenPos + distort*anim_timer + anim_timer*0.1*vertIn.normal.xy).rgb,baseColor.rgb,clamp(cloak_interp+anim_timer*2.0,0.0,1.0));
#endif
}
#endif
#ifndef FLAG_DEFERRED
// emissive colors won't be added later when we are using forward rendering so we need to do that here
baseColor.rgb += emissiveColor.rgb;
#endif
fragOut0 = baseColor;
#ifdef FLAG_DEFERRED
fragOut1 = vec4(vertIn.position.xyz, 1.0);
fragOut2 = vec4(normal, glossData);
fragOut3 = vec4(specColor.rgb, fresnelFactor);
fragOut4 = emissiveColor;
#endif
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_DEFERRED)) {
fragOut1 = vec4(vertIn.position.xyz, 1.0);
fragOut2 = vec4(normal, glossData);
fragOut3 = vec4(specColor.rgb, fresnelFactor);
fragOut4 = emissiveColor;
}
}
+106 -128
View File
@@ -1,10 +1,12 @@
#extension GL_ARB_gpu_shader5: enable
#include "model_shader_flags.h"
#ifdef FLAG_THICK_OUTLINE
layout (triangles) in;
// For every triangle line we generate 2 triangles which can be done with 4 vertices so in total we will need 12 vertices
layout (triangle_strip, max_vertices = 12) out;
#else
#elif defined(FLAG_SHADOW_MAP)
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;
#endif
@@ -61,21 +63,13 @@ layout (std140) uniform modelData {
int blend_alpha;
vec3 emissionFactor;
bool overrideDiffuse_;
vec3 diffuseClr_;
bool overrideGlow_;
vec3 glowClr_;
bool overrideSpec_;
vec3 specClr_;
bool alphaGloss;
bool gammaSpec;
bool envGloss;
bool alpha_spec_;
int effect_num;
int sBasemapIndex;
vec4 fogColor;
@@ -95,8 +89,6 @@ layout (std140) uniform modelData {
float middist;
float fardist;
vec2 normalAlphaMinMax_;
int sBasemapIndex;
int sGlowmapIndex;
int sSpecmapIndex;
@@ -105,160 +97,146 @@ layout (std140) uniform modelData {
int sMiscmapIndex;
float alphaMult;
int flags;
};
in VertexOutput {
#ifdef FLAG_ENV_MAP
vec3 envReflect;
#endif
mat3 tangentMatrix;
#ifdef FLAG_FOG
mat3 tangentMatrix;
float fogDist;
#endif
#ifdef FLAG_SHADOW_MAP
#if !defined(GL_ARB_gpu_shader5)
float instance;
#endif
#ifdef FLAG_TRANSFORM
float clipModel;
#endif
#else
vec4 position;
#endif
vec3 normal;
vec4 texCoord;
#ifdef FLAG_SHADOWS
vec4 shadowUV[4];
vec4 shadowPos;
#endif
} vertIn[];
out VertexOutput {
#ifdef FLAG_ENV_MAP
vec3 envReflect;
#endif
mat3 tangentMatrix;
#ifdef FLAG_FOG
mat3 tangentMatrix;
float fogDist;
#endif
vec4 position;
vec3 normal;
vec4 texCoord;
#ifdef FLAG_SHADOWS
vec4 shadowUV[4];
vec4 shadowPos;
#endif
} vertOut;
#ifdef FLAG_SHADOW_MAP
void main(void)
{
#ifdef GL_ARB_gpu_shader5
int instanceID = gl_InvocationID;
#else
int instanceID = int(vertIn[0].instance);
#endif
for(int vert = 0; vert < gl_in.length(); vert++)
void main(void)
{
#ifdef FLAG_TRANSFORM
if (vertIn[vert].clipModel > 0.9) {
// If the model was clipped in the vertex shader then we do not apply the shadow projection matrix here
gl_Position = gl_in[vert].gl_Position;
} else {
gl_Position = shadow_proj_matrix[instanceID] * gl_in[vert].gl_Position;
}
#else
gl_Position = shadow_proj_matrix[instanceID] * gl_in[vert].gl_Position;
#endif
if(gl_Position.z < -1.0)
#ifdef GL_ARB_gpu_shader5
int instanceID = gl_InvocationID;
#else
int instanceID = int(vertIn[0].instance);
#endif
for(int vert = 0; vert < gl_in.length(); vert++)
{
if (FLAG_ACTIVE(MODEL_SDR_FLAG_TRANSFORM)) {
if (vertIn[vert].clipModel > 0.9) {
// If the model was clipped in the vertex shader then we do not apply the shadow projection matrix here
gl_Position = gl_in[vert].gl_Position;
} else {
gl_Position = shadow_proj_matrix[instanceID] * gl_in[vert].gl_Position;
}
} else {
gl_Position = shadow_proj_matrix[instanceID] * gl_in[vert].gl_Position;
}
if(gl_Position.z < -1.0)
gl_Position.z = -1.0;
vertOut.position = gl_in[vert].gl_Position;
vertOut.normal = vertIn[vert].normal;
vertOut.texCoord = vertIn[vert].texCoord;
gl_Layer = instanceID;
#ifdef FLAG_ENV_MAP
vertOut.envReflect = vertIn[vert].envReflect;
#endif
#ifdef FLAG_NORMAL_MAP
vertOut.tangentMatrix = vertIn[vert].tangentMatrix;
#endif
#ifdef FLAG_FOG
vertOut.fogDist = vertIn[vert].fogDist;
#endif
#ifdef FLAG_SHADOWS
vertOut.shadowUV[0] = vertIn[vert].shadowUV[0];
vertOut.shadowUV[1] = vertIn[vert].shadowUV[1];
vertOut.shadowUV[2] = vertIn[vert].shadowUV[2];
vertOut.shadowUV[3] = vertIn[vert].shadowUV[3];
vertOut.shadowPos = vertIn[vert].shadowPos;
#endif
#if defined(FLAG_CLIP)
gl_ClipDistance[0] = gl_in[vert].gl_ClipDistance[0];
#endif
EmitVertex();
}
EndPrimitive();
}
#elif defined(FLAG_THICK_OUTLINE)
const vec2 pixelOffsetDir[4] = vec2[](
vec2(0.0, 1.0),
vec2(1.0, 1.0),
vec2(1.0, -1.0),
vec2(0.0, -1.0)
);
void main(void)
{
for(int vert = 0; vert < gl_in.length(); vert++)
{
int nextVert = (vert + 1) % gl_in.length();
vec4 clip = gl_in[vert].gl_Position;
vec4 diff = gl_in[nextVert].gl_Position - clip; // vector from vert to the next vertex in the list
vec2 normal = normalize(vec2(diff.y, -diff.x)); // Computing the normal of a 2D vector is actually rather simple...
for (int lineVert = 0; lineVert < 4; ++lineVert)
{
// This is the pixel offset along the normal axis
vec2 yOffPixel = pixelOffsetDir[lineVert].y * normal * (outlineWidth / 2.0);
// This is the offset of the vertex along the vector between this vertex and the next one in the triangle
vec2 xOff = pixelOffsetDir[lineVert].x * diff.xy;
// This is the final offset in clip space
vec2 finalOffset = xOff + yOffPixel * vec2(vpwidth, vpheight) * clip.w;
gl_Position = vec4(clip.xyz + vec3(finalOffset, 0.0), clip.w);
vertOut.position = vertIn[vert].position;
vertOut.position = gl_in[vert].gl_Position;
vertOut.normal = vertIn[vert].normal;
vertOut.texCoord = vertIn[vert].texCoord;
#ifdef FLAG_ENV_MAP
vertOut.envReflect = vertIn[vert].envReflect;
#endif
#ifdef FLAG_NORMAL_MAP
vertOut.tangentMatrix = vertIn[vert].tangentMatrix;
#endif
#ifdef FLAG_FOG
vertOut.fogDist = vertIn[vert].fogDist;
#endif
#ifdef FLAG_SHADOWS
vertOut.shadowUV[0] = vertIn[vert].shadowUV[0];
vertOut.shadowUV[1] = vertIn[vert].shadowUV[1];
vertOut.shadowUV[2] = vertIn[vert].shadowUV[2];
vertOut.shadowUV[3] = vertIn[vert].shadowUV[3];
vertOut.shadowPos = vertIn[vert].shadowPos;
#endif
#if defined(FLAG_CLIP)
gl_ClipDistance[0] = gl_in[vert].gl_ClipDistance[0];
#endif
gl_Layer = instanceID;
if (FLAG_ACTIVE(MODEL_SDR_FLAG_ENV)) {
vertOut.envReflect = vertIn[vert].envReflect;
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_NORMAL)) {
vertOut.tangentMatrix = vertIn[vert].tangentMatrix;
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_FOG)) {
vertOut.fogDist = vertIn[vert].fogDist;
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_SHADOWS)) {
vertOut.shadowUV[0] = vertIn[vert].shadowUV[0];
vertOut.shadowUV[1] = vertIn[vert].shadowUV[1];
vertOut.shadowUV[2] = vertIn[vert].shadowUV[2];
vertOut.shadowUV[3] = vertIn[vert].shadowUV[3];
vertOut.shadowPos = vertIn[vert].shadowPos;
}
if (use_clip_plane) {
gl_ClipDistance[0] = gl_in[vert].gl_ClipDistance[0];
}
EmitVertex();
}
EndPrimitive();
}
}
#elif defined(FLAG_THICK_OUTLINE)
const vec2 pixelOffsetDir[4] = vec2[](
vec2(0.0, 1.0),
vec2(1.0, 1.0),
vec2(1.0, -1.0),
vec2(0.0, -1.0)
);
void main(void)
{
for(int vert = 0; vert < gl_in.length(); vert++)
{
int nextVert = (vert + 1) % gl_in.length();
vec4 clip = gl_in[vert].gl_Position;
vec4 diff = gl_in[nextVert].gl_Position - clip; // vector from vert to the next vertex in the list
vec2 normal = normalize(vec2(diff.y, -diff.x)); // Computing the normal of a 2D vector is actually rather simple...
for (int lineVert = 0; lineVert < 4; ++lineVert)
{
// This is the pixel offset along the normal axis
vec2 yOffPixel = pixelOffsetDir[lineVert].y * normal * (outlineWidth / 2.0);
// This is the offset of the vertex along the vector between this vertex and the next one in the triangle
vec2 xOff = pixelOffsetDir[lineVert].x * diff.xy;
// This is the final offset in clip space
vec2 finalOffset = xOff + yOffPixel * vec2(vpwidth, vpheight) * clip.w;
gl_Position = vec4(clip.xyz + vec3(finalOffset, 0.0), clip.w);
vertOut.position = vertIn[vert].position;
vertOut.normal = vertIn[vert].normal;
vertOut.texCoord = vertIn[vert].texCoord;
if (FLAG_ACTIVE(MODEL_SDR_FLAG_ENV)) {
vertOut.envReflect = vertIn[vert].envReflect;
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_NORMAL)) {
vertOut.tangentMatrix = vertIn[vert].tangentMatrix;
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_FOG)) {
vertOut.fogDist = vertIn[vert].fogDist;
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_SHADOWS)) {
vertOut.shadowUV[0] = vertIn[vert].shadowUV[0];
vertOut.shadowUV[1] = vertIn[vert].shadowUV[1];
vertOut.shadowUV[2] = vertIn[vert].shadowUV[2];
vertOut.shadowUV[3] = vertIn[vert].shadowUV[3];
vertOut.shadowPos = vertIn[vert].shadowPos;
}
if (use_clip_plane) {
gl_ClipDistance[0] = gl_in[vert].gl_ClipDistance[0];
}
EmitVertex();
}
EndPrimitive();
}
}
#endif
+68 -85
View File
@@ -2,6 +2,7 @@
#extension GL_ARB_gpu_shader5: enable
#include "shadows.sdr"
#include "model_shader_flags.h"
in vec4 vertPosition;
in vec4 vertTexCoord;
@@ -56,21 +57,13 @@ layout (std140) uniform modelData {
int blend_alpha;
vec3 emissionFactor;
bool overrideDiffuse_;
vec3 diffuseClr_;
bool overrideGlow_;
vec3 glowClr_;
bool overrideSpec_;
vec3 specClr_;
bool alphaGloss;
bool gammaSpec;
bool envGloss;
bool alpha_spec_;
int effect_num;
int sBasemapIndex;
vec4 fogColor;
@@ -90,8 +83,6 @@ layout (std140) uniform modelData {
float middist;
float fardist;
vec2 normalAlphaMinMax_;
int sBasemapIndex;
int sGlowmapIndex;
int sSpecmapIndex;
@@ -100,41 +91,32 @@ layout (std140) uniform modelData {
int sMiscmapIndex;
float alphaMult;
int flags;
};
#ifdef FLAG_TRANSFORM
uniform samplerBuffer transform_tex;
#endif
out VertexOutput {
#ifdef FLAG_ENV_MAP
vec3 envReflect;
#endif
mat3 tangentMatrix;
#ifdef FLAG_FOG
mat3 tangentMatrix;
float fogDist;
#endif
#ifdef FLAG_SHADOW_MAP
#if !defined(GL_ARB_gpu_shader5)
float instance;
#endif
#ifdef FLAG_TRANSFORM
// This flag is needed to let the geometry shader know that it doesn't need to apply the
// shadow projection to gl_Position
float clipModel;
#endif
#else
vec4 position;
#endif
vec3 normal;
vec4 texCoord;
#ifdef FLAG_SHADOWS
vec4 shadowUV[4];
vec4 shadowPos;
#endif
} vertOut;
#ifdef FLAG_TRANSFORM
#define TEXELS_PER_MATRIX 4
void getModelTransform(inout mat4 transform, out bool invisible, int id, int matrix_offset)
{
@@ -145,7 +127,7 @@ void getModelTransform(inout mat4 transform, out bool invisible, int id, int mat
invisible = transform[3].w >= 0.9;
transform[3].w = 1.0;
}
#endif
void main()
{
vec4 position;
@@ -153,76 +135,77 @@ void main()
vec4 texCoord;
mat4 orient = mat4(1.0);
mat4 scale = mat4(1.0);
#ifdef FLAG_TRANSFORM
bool clipModel;
getModelTransform(orient, clipModel, int(vertModelID), buffer_matrix_offset);
#endif
bool clipModel = false;
if (FLAG_ACTIVE(MODEL_SDR_FLAG_TRANSFORM)) {
getModelTransform(orient, clipModel, int(vertModelID), buffer_matrix_offset);
}
texCoord = textureMatrix * vertTexCoord;
vec4 vertex = vertPosition;
#ifdef FLAG_THRUSTER
if(vertex.z < -1.5) {
vertex.z *= thruster_scale;
if (FLAG_ACTIVE(MODEL_SDR_FLAG_THRUSTER)) {
if(vertex.z < -1.5) {
vertex.z *= thruster_scale;
}
}
#endif
// Transform the normal into eye space and normalize the result.
// Transform the normal into eye space and normalize the result.
normal = normalize(mat3(modelViewMatrix) * mat3(orient) * vertNormal);
position = modelViewMatrix * orient * vertex;
#ifdef FLAG_SHADOW_MAP
gl_Position = position;
#if !defined(GL_ARB_gpu_shader5)
#ifdef APPLE
vertOut.instance = float(gl_InstanceIDARB);
#else
vertOut.instance = float(gl_InstanceID);
#endif
#endif
#else
gl_Position = projMatrix * position;
#endif
#ifdef FLAG_SHADOWS
vec4 shadowPos = shadow_mv_matrix * modelMatrix * orient * vertPosition;
vertOut.shadowPos = shadow_mv_matrix * modelMatrix * orient * vertPosition;
vertOut.shadowUV[0] = transformToShadowMap(shadow_proj_matrix[0], 0, shadowPos);
vertOut.shadowUV[1] = transformToShadowMap(shadow_proj_matrix[1], 1, shadowPos);
vertOut.shadowUV[2] = transformToShadowMap(shadow_proj_matrix[2], 2, shadowPos);
vertOut.shadowUV[3] = transformToShadowMap(shadow_proj_matrix[3], 3, shadowPos);
#endif
// Setup stuff for normal maps and envmaps
vec3 t = normalize(mat3(modelViewMatrix) * mat3(orient) * vertTangent.xyz);
vec3 b = cross(normal, t) * vertTangent.w;
vertOut.tangentMatrix = mat3(t, b, normal);
#ifdef FLAG_ENV_MAP
// Environment mapping reflection vector.
vec3 envReflect = reflect(normalize(position.xyz), normal);
vertOut.envReflect = vec3(envMatrix * vec4(envReflect, 0.0));
#endif
#ifdef FLAG_FOG
vertOut.fogDist = clamp((gl_Position.z - fogStart) * 0.75 * fogScale, 0.0, 1.0);
#endif
#ifdef FLAG_TRANSFORM
if (clipModel) {
// Clip this model by moving all vertices outside the clip volume
gl_Position = vec4(vec3(-2.0), 1.0);
#ifdef FLAG_SHADOW_MAP
gl_Position = position;
#if !defined(GL_ARB_gpu_shader5)
#ifdef APPLE
vertOut.instance = float(gl_InstanceIDARB);
#else
vertOut.instance = float(gl_InstanceID);
#endif
#endif
#else
gl_Position = projMatrix * position;
#endif
if (FLAG_ACTIVE(MODEL_SDR_FLAG_SHADOWS)) {
vec4 shadowPos = shadow_mv_matrix * modelMatrix * orient * vertPosition;
vertOut.shadowPos = shadow_mv_matrix * modelMatrix * orient * vertPosition;
vertOut.shadowUV[0] = transformToShadowMap(shadow_proj_matrix[0], 0, shadowPos);
vertOut.shadowUV[1] = transformToShadowMap(shadow_proj_matrix[1], 1, shadowPos);
vertOut.shadowUV[2] = transformToShadowMap(shadow_proj_matrix[2], 2, shadowPos);
vertOut.shadowUV[3] = transformToShadowMap(shadow_proj_matrix[3], 3, shadowPos);
}
#ifdef FLAG_SHADOW_MAP
vertOut.clipModel = clipModel ? 1.0 : 0.0;
#endif
#endif
#ifdef FLAG_CLIP
// Setup stuff for normal maps and envmaps
vec3 t = normalize(mat3(modelViewMatrix) * mat3(orient) * vertTangent.xyz);
vec3 b = cross(normal, t) * vertTangent.w;
vertOut.tangentMatrix = mat3(t, b, normal);
if (FLAG_ACTIVE(MODEL_SDR_FLAG_ENV)) {
// Environment mapping reflection vector.
vec3 envReflect = reflect(normalize(position.xyz), normal);
vertOut.envReflect = vec3(envMatrix * vec4(envReflect, 0.0));
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_FOG)) {
vertOut.fogDist = clamp((gl_Position.z - fogStart) * 0.75 * fogScale, 0.0, 1.0);
}
if (FLAG_ACTIVE(MODEL_SDR_FLAG_TRANSFORM)) {
if (clipModel) {
// Clip this model by moving all vertices outside the clip volume
gl_Position = vec4(vec3(-2.0), 1.0);
}
#ifdef FLAG_SHADOW_MAP
vertOut.clipModel = clipModel ? 1.0 : 0.0;
#endif
}
if(use_clip_plane) {
gl_ClipDistance[0] = dot(clip_equation, modelMatrix * orient * vertex);
} else {
gl_ClipDistance[0] = 1.0;
}
#endif
#ifndef FLAG_SHADOW_MAP
vertOut.position = position;
vertOut.normal = normal;
vertOut.texCoord = texCoord;
#else
vertOut.normal = normal;
vertOut.texCoord = texCoord;
#endif
#ifndef FLAG_SHADOW_MAP
vertOut.position = position;
vertOut.normal = normal;
vertOut.texCoord = texCoord;
#else
vertOut.normal = normal;
vertOut.texCoord = texCoord;
#endif
}
@@ -0,0 +1,19 @@
#define MODEL_SDR_FLAG_LIGHT (1 << 0)
#define MODEL_SDR_FLAG_DEFERRED (1 << 1)
#define MODEL_SDR_FLAG_HDR (1 << 2)
#define MODEL_SDR_FLAG_DIFFUSE (1 << 3)
#define MODEL_SDR_FLAG_GLOW (1 << 4)
#define MODEL_SDR_FLAG_SPEC (1 << 5)
#define MODEL_SDR_FLAG_ENV (1 << 6)
#define MODEL_SDR_FLAG_NORMAL (1 << 7)
#define MODEL_SDR_FLAG_AMBIENT (1 << 8)
#define MODEL_SDR_FLAG_MISC (1 << 9)
#define MODEL_SDR_FLAG_TEAMCOLOR (1 << 10)
#define MODEL_SDR_FLAG_FOG (1 << 11)
#define MODEL_SDR_FLAG_TRANSFORM (1 << 12)
#define MODEL_SDR_FLAG_SHADOWS (1 << 13)
#define MODEL_SDR_FLAG_THRUSTER (1 << 14)
#define MODEL_SDR_FLAG_ALPHA_MULT (1 << 15)
#define FLAG_ACTIVE(flag) (flags & flag) != 0
+198
View File
@@ -0,0 +1,198 @@
in vec4 fragTexCoord;
out vec4 fragOut0;
out vec4 fragOut1;
out vec4 fragOut2;
out vec4 fragOut3;
out vec4 fragOut4;
out vec4 fragOut5;
out float gl_FragDepth;
uniform sampler2DMS texColor;
uniform sampler2DMS texPos;
uniform sampler2DMS texNormal;
uniform sampler2DMS texSpecular;
uniform sampler2DMS texEmissive;
uniform sampler2DMS texDepth;
layout (std140) uniform genericData {
int samples;
float fov;
};
const float voxelDepth = 2.5f;
const float voxelDepthFalloff = 2.5f;
#define SORT(a, b) if (a > b) { float t = dists[a]; dists[a] = dists[b]; dists[b] = t; }
//The following sorting networks for median calculation are NOT complete. Calculations that don't affect the
//median entry are removed, and thus, while the median element is correct, the rest of the array is NOT fully sorted
#ifdef SAMPLES_4
float getMedianDist(ivec2 texel) {
float dists[4];
for(int i = 0; i < 4; i++) {
dists[i] = texelFetch(texPos, texel, i).z;
}
SORT(0, 2)
SORT(1, 3)
SORT(0, 1)
SORT(2, 3)
SORT(1, 2)
return dists[1];
}
#else
#ifdef SAMPLES_8
float getMedianDist(ivec2 texel) {
float dists[8];
for(int i = 0; i < 8; i++) {
dists[i] = texelFetch(texPos, texel, i).z;
}
SORT(0, 4)
SORT(1, 5)
SORT(2, 6)
SORT(3, 7)
SORT(0, 2)
SORT(1, 3)
SORT(4, 6)
SORT(5, 7)
SORT(2, 4)
SORT(3, 5)
SORT(0, 1)
SORT(2, 3)
SORT(4, 5)
SORT(6, 7)
SORT(1, 4)
SORT(3, 6)
SORT(3, 4)
return dists[3];
}
#else
#ifdef SAMPLES_16
float getMedianDist(ivec2 texel) {
float dists[16];
for(int i = 0; i < 16; i++) {
dists[i] = texelFetch(texPos, texel, i).z;
}
SORT(0, 1)
SORT(2, 3)
SORT(4, 5)
SORT(6, 7)
SORT(8, 9)
SORT(10, 11)
SORT(12, 13)
SORT(14, 15)
SORT(0, 2)
SORT(4, 6)
SORT(8, 10)
SORT(12, 14)
SORT(1, 3)
SORT(5, 7)
SORT(9, 11)
SORT(13, 15)
SORT(0, 4)
SORT(1, 5)
SORT(2, 6)
SORT(3, 7)
SORT(8, 12)
SORT(9, 13)
SORT(10, 14)
SORT(11, 15)
SORT(0, 8)
SORT(1, 9)
SORT(2, 10)
SORT(3, 11)
SORT(4, 12)
SORT(5, 13)
SORT(6, 14)
SORT(7, 15)
SORT(5, 10)
SORT(6, 9)
SORT(3, 12)
SORT(13, 14)
SORT(7, 11)
SORT(1, 2)
SORT(4, 8)
SORT(7, 13)
SORT(2, 8)
SORT(5, 6)
SORT(9, 10)
SORT(3, 8)
SORT(6, 8)
SORT(3, 5)
SORT(7, 9)
SORT(5, 6)
SORT(7, 8)
SORT(6, 7)
return dists[7];
}
#else
//Fallback, do front first
float getMedianDist(ivec2 texel) {
float minDist = -1000000;
for(int i = 0; i < samples; i++) {
minDist = max(minDist, texelFetch(texPos, texel, i).z);
}
return minDist;
}
#endif //SAMPLES_16
#endif //SAMPLES_8
#endif //SAMPLES_4
void main()
{
vec2 texSize = textureSize(texColor);
ivec2 texel = ivec2(texSize * fragTexCoord.xy);
float texelWidthFactor = tan(fov / texSize.y);
float dist = getMedianDist(texel);
float weight = 0.0f;
vec4 color = vec4(0);
vec4 pos = vec4(0);
vec4 normal = vec4(0);
vec4 specular = vec4(0);
vec4 emissive = vec4(0);
float depth = 0;
for(int i = 0; i < samples; i++) {
vec4 localPos = texelFetch(texPos, texel, i);
//Calculate local weight from distance Voxel, but if the distance is 0 (i.e. no model at all), set weight to 1 to allow stuff like background emissive
float localWeight = max(step(-0.001, dist),
smoothstep(dist + dist * texelWidthFactor * (voxelDepth + voxelDepthFalloff), dist + dist * texelWidthFactor * voxelDepth, localPos.z) *
smoothstep(dist - dist * texelWidthFactor * voxelDepth, dist + dist * texelWidthFactor * (voxelDepth + voxelDepthFalloff), localPos.z)
);
pos += localPos * localWeight;
color += texelFetch(texColor, texel, i) * localWeight;
normal += texelFetch(texNormal, texel, i) * localWeight;
specular += texelFetch(texSpecular, texel, i) * localWeight;
emissive += texelFetch(texEmissive, texel, i) * localWeight;
depth += texelFetch(texDepth, texel, i).x * localWeight;
weight += localWeight;
}
fragOut0 = color / weight;
fragOut1 = pos / weight;
fragOut2 = normalize(normal);
fragOut3 = specular / weight;
fragOut4 = emissive / weight;
gl_FragDepth = depth / weight;
}
@@ -0,0 +1,167 @@
in vec4 fragTexCoord;
out vec4 fragOut0;
layout (binding = 0) uniform sampler2D composite;
layout (binding = 1) uniform sampler2D emissive;
layout (binding = 2) uniform sampler2D depth;
layout (binding = 3) uniform sampler3D volume_tex;
#ifdef NOISE
layout (binding = 4) uniform sampler3D noise_volume_tex;
#endif
layout (std140) uniform genericData {
mat4 p_inv;
mat4 v_inv;
vec3 camera;
float zNear;
vec3 globalLightDirection;
float zFar;
vec3 globalLightDiffuse;
float stepsize;
vec3 nebPos;
float globalstepalpha;
vec3 nebSize;
float alphalim;
float emissiveSpreadFactor;
float emissiveIntensity;
float emissiveFalloff;
float henyeyGreensteinCoeff;
vec3 noiseColor;
int directionalLightSampleSteps;
float directionalLightStepSize;
float noiseColorScale1;
float noiseColorScale2;
float noiseIntensity;
float aspect;
float fov;
};
const float sqrt4pi_inv = inversesqrt(4.0 * 3.14159);
const float beer_powder_norm = 3.0/2.0 * sqrt(3.0);
//This HG implementation assumes that the scatter vectors between which is theta both point away from the point of scatter
float henyey_greenstein(float cosTheta) {
float radicant = 1.0 + henyeyGreensteinCoeff * henyeyGreensteinCoeff + 2.0 * henyeyGreensteinCoeff * cosTheta;
return sqrt4pi_inv * (1.0 - henyeyGreensteinCoeff * henyeyGreensteinCoeff) / pow(radicant, 3.0 / 2.0);
}
/*
Base idea of sampling volumetrics from multiple LOD 3D-Textures with cloud models / noise as well as the shading for the diffuse
part of the volumetrics is adapted from Andrew Schneider's 2015 SIGGRAPH talk "The real-time volumetric cloudscapes of Horizon: Zero Dawn".
*/
void main()
{
vec4 eyeDirection = p_inv * vec4(fragTexCoord.xy * 2.0 - 1.0, -1, 1);
eyeDirection.w = 0;
vec3 rayDirection = normalize((v_inv * eyeDirection).xyz);
vec4 color_in = texture(composite, fragTexCoord.xy);
vec3 lCorner = nebPos - nebSize * 0.5;
vec3 rCorner = nebPos + nebSize * 0.5;
vec3 t1 = (lCorner - camera) / rayDirection;
vec3 t2 = (rCorner - camera) / rayDirection;
vec3 tMin = min(t1, t2);
vec3 tMax = max(t1, t2);
vec2 fragcoordAngle = (fragTexCoord.xy - 0.5) * fov;
fragcoordAngle.x *= aspect;
float depth = (2.0 * zNear * zFar / (zFar + zNear - (2 * texture(depth, fragTexCoord.xy).x - 1) * (zFar - zNear))) * sqrt(1.0 + tan(fragcoordAngle.x) * tan(fragcoordAngle.x) + tan(fragcoordAngle.y) * tan(fragcoordAngle.y));
//The t at which the ray enters the nebula cube
float maxtMin = max(0,max(tMin.x, max(tMin.y, tMin.z)));
//The t at which the ray leaves the nebula cube
float mintMax = min(depth, min(tMax.x, min(tMax.y, tMax.z)));
//The cumulative one minus alpha value of the nebula. Corresponds to the multiplier of the current step when additively drawing to a fragment for which the steps closer to the camera are already drawn.
float cumOMAlpha = 1;
//The cumulative distance already travelled through the nebula.
float cumnebdist = 0;
//The color of the current fragment
vec3 cumcolor = vec3(0, 0, 0);
//While not perfectly accurate, it's sufficient to assume all gradients for the 3d texture lookups are identical
vec3 initialPos = (camera + rayDirection * maxtMin) / nebSize + 0.5;
vec3 gradX = dFdx(initialPos);
vec3 gradY = dFdy(initialPos);
vec3 sidestep = 1.0 / vec3(textureSize(volume_tex, 0));
for(float stept = maxtMin; stept < mintMax; stept += stepsize) {
//Step setup
vec3 position = camera + rayDirection * stept - nebPos;
vec3 sampleposition = position / nebSize + 0.5;
vec4 volume_sample = textureGrad(volume_tex, sampleposition, gradX, gradY);
#ifdef DO_EDGE_SMOOTHING
//Average 3D texel with texels on corner, in an attempt to reduce jagged edges.
float stepcolor_alpha = volume_sample.a;
if(cumOMAlpha > 0.8) {
//Draw additional samples only if we currently encounter an edge
stepcolor_alpha = stepcolor_alpha / 2.0 + (
textureGrad(volume_tex, sampleposition + vec3(sidestep.x, sidestep.y, sidestep.z), gradX, gradY).a +
textureGrad(volume_tex, sampleposition + vec3(sidestep.x, sidestep.y, -sidestep.z), gradX, gradY).a +
textureGrad(volume_tex, sampleposition + vec3(sidestep.x, -sidestep.y, sidestep.z), gradX, gradY).a +
textureGrad(volume_tex, sampleposition + vec3(sidestep.x, -sidestep.y, -sidestep.z), gradX, gradY).a +
textureGrad(volume_tex, sampleposition + vec3(-sidestep.x, sidestep.y, sidestep.z), gradX, gradY).a +
textureGrad(volume_tex, sampleposition + vec3(-sidestep.x, sidestep.y, -sidestep.z), gradX, gradY).a +
textureGrad(volume_tex, sampleposition + vec3(-sidestep.x, -sidestep.y, sidestep.z), gradX, gradY).a +
textureGrad(volume_tex, sampleposition + vec3(-sidestep.x, -sidestep.y, -sidestep.z), gradX, gradY).a) / 16.0;
}
#else
float stepcolor_alpha = volume_sample.a;
#endif
float stepalpha = globalstepalpha * stepcolor_alpha;
//All the following computations are just required if we have a stepcoloralpha that is non-zero.
if(stepcolor_alpha > 0.01)
{
//Noise - Technically, we need to do edge noise here but I'm not very happy with how it turned out. The cloud needs to be "eroded" by the noise as per the SIGGRAPH talk, but it's unclear as to how that can be achieved.
//So for now, don't do edge noise. noise_volume_tex.ba are still reserved for noise data for edge erosion.
//Diffuse
#ifdef NOISE
//Mix the actual nebula color with the noise color depending on the product of the noise channels multiplied with intensity, smooth-clamped from 0 to 1
vec3 stepcolor_neb = mix(volume_sample.rgb, noiseColor,
smoothstep(0, 1, (textureGrad(noise_volume_tex, position / noiseColorScale1, gradX, gradY).r + textureGrad(noise_volume_tex, position / noiseColorScale2, gradX, gradY).g) / 2.0 * noiseIntensity));
#else
vec3 stepcolor_neb = volume_sample.rgb;
#endif
vec3 stepcolor_diffuse = stepcolor_neb * henyey_greenstein(dot(rayDirection, globalLightDirection));
float directionalLightStep = 4.0 / float(directionalLightSampleSteps);
float directionalLightDepth = 0.1;
//From the current position in the volumetric cloud, sample towards the sun to test whether or not the current part of the nebula is bright or not
for(int dlstep = 1; dlstep <= directionalLightSampleSteps; dlstep++){
//TODO Sample these in a cone towards the sun, not just a line. Also add the high-distance sample for concave nebulae
vec3 dlsteppos = (position - globalLightDirection * (dlstep * directionalLightStepSize)) / nebSize + 0.5;
float dlstepalpha = textureGrad(volume_tex, dlsteppos, gradX, gradY).a * step(0, dlsteppos.x) * step(dlsteppos.x, 1) * step(0, dlsteppos.y) * step(dlsteppos.y, 1) * step(0, dlsteppos.z) * step(dlsteppos.z, 1);
directionalLightDepth += dlstepalpha * directionalLightStep;
}
stepcolor_diffuse *= beer_powder_norm * (1 - exp(-directionalLightDepth * 2.0)) * exp(-directionalLightDepth);
//Emissive
cumnebdist += stepcolor_alpha * stepsize;
vec3 emissive_lod = textureLod(emissive, fragTexCoord.xy, clamp(cumnebdist * emissiveSpreadFactor, 0, float(textureQueryLevels(emissive) - 1))).rgb;
vec3 stepcolor_emissive = emissive_lod.rgb * pow(1 - globalstepalpha, (depth - stept) * emissiveFalloff) * emissiveIntensity;
//Step finish
vec3 stepcolor = clamp(stepcolor_diffuse + stepcolor_emissive, 0, 1);
float stepalpha = globalstepalpha * stepcolor_alpha;
cumcolor += stepalpha * cumOMAlpha * stepcolor;
}
cumOMAlpha *= 1.0 - stepalpha;
if(cumOMAlpha < alphalim)
break;
}
cumcolor += cumOMAlpha * color_in.rgb;
fragOut0 = vec4(cumcolor, 1);
}
+714
View File
@@ -0,0 +1,714 @@
-- Module options:
local always_try_using_lpeg = true
local register_global_module_table = false
local global_module_name = 'json'
--[==[
David Kolf's JSON module for Lua 5.1/5.2
Version 2.5
For the documentation see the corresponding readme.txt or visit
<http://dkolf.de/src/dkjson-lua.fsl/>.
You can contact the author by sending an e-mail to 'david' at the
domain 'dkolf.de'.
Copyright (C) 2010-2014 David Heiko Kolf
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]==]
-- global dependencies:
local pairs, type, tostring, tonumber, getmetatable, setmetatable, rawset =
pairs, type, tostring, tonumber, getmetatable, setmetatable, rawset
local error, require, pcall, select = error, require, pcall, select
local floor, huge = math.floor, math.huge
local strrep, gsub, strsub, strbyte, strchar, strfind, strlen, strformat =
string.rep, string.gsub, string.sub, string.byte, string.char,
string.find, string.len, string.format
local strmatch = string.match
local concat = table.concat
local json = { version = "dkjson 2.5" }
if register_global_module_table then
_G[global_module_name] = json
end
local _ENV = nil -- blocking globals in Lua 5.2
pcall (function()
-- Enable access to blocked metatables.
-- Don't worry, this module doesn't change anything in them.
local debmeta = require "debug".getmetatable
if debmeta then getmetatable = debmeta end
end)
json.null = setmetatable ({}, {
__tojson = function () return "null" end
})
local function isarray (tbl)
local max, n, arraylen = 0, 0, 0
for k,v in pairs (tbl) do
if k == 'n' and type(v) == 'number' then
arraylen = v
if v > max then
max = v
end
else
if type(k) ~= 'number' or k < 1 or floor(k) ~= k then
return false
end
if k > max then
max = k
end
n = n + 1
end
end
if max > 10 and max > arraylen and max > n * 2 then
return false -- don't create an array with too many holes
end
return true, max
end
local escapecodes = {
["\""] = "\\\"", ["\\"] = "\\\\", ["\b"] = "\\b", ["\f"] = "\\f",
["\n"] = "\\n", ["\r"] = "\\r", ["\t"] = "\\t"
}
local function escapeutf8 (uchar)
local value = escapecodes[uchar]
if value then
return value
end
local a, b, c, d = strbyte (uchar, 1, 4)
a, b, c, d = a or 0, b or 0, c or 0, d or 0
if a <= 0x7f then
value = a
elseif 0xc0 <= a and a <= 0xdf and b >= 0x80 then
value = (a - 0xc0) * 0x40 + b - 0x80
elseif 0xe0 <= a and a <= 0xef and b >= 0x80 and c >= 0x80 then
value = ((a - 0xe0) * 0x40 + b - 0x80) * 0x40 + c - 0x80
elseif 0xf0 <= a and a <= 0xf7 and b >= 0x80 and c >= 0x80 and d >= 0x80 then
value = (((a - 0xf0) * 0x40 + b - 0x80) * 0x40 + c - 0x80) * 0x40 + d - 0x80
else
return ""
end
if value <= 0xffff then
return strformat ("\\u%.4x", value)
elseif value <= 0x10ffff then
-- encode as UTF-16 surrogate pair
value = value - 0x10000
local highsur, lowsur = 0xD800 + floor (value/0x400), 0xDC00 + (value % 0x400)
return strformat ("\\u%.4x\\u%.4x", highsur, lowsur)
else
return ""
end
end
local function fsub (str, pattern, repl)
-- gsub always builds a new string in a buffer, even when no match
-- exists. First using find should be more efficient when most strings
-- don't contain the pattern.
if strfind (str, pattern) then
return gsub (str, pattern, repl)
else
return str
end
end
local function quotestring (value)
-- based on the regexp "escapable" in https://github.com/douglascrockford/JSON-js
value = fsub (value, "[%z\1-\31\"\\\127]", escapeutf8)
if strfind (value, "[\194\216\220\225\226\239]") then
value = fsub (value, "\194[\128-\159\173]", escapeutf8)
value = fsub (value, "\216[\128-\132]", escapeutf8)
value = fsub (value, "\220\143", escapeutf8)
value = fsub (value, "\225\158[\180\181]", escapeutf8)
value = fsub (value, "\226\128[\140-\143\168-\175]", escapeutf8)
value = fsub (value, "\226\129[\160-\175]", escapeutf8)
value = fsub (value, "\239\187\191", escapeutf8)
value = fsub (value, "\239\191[\176-\191]", escapeutf8)
end
return "\"" .. value .. "\""
end
json.quotestring = quotestring
local function replace(str, o, n)
local i, j = strfind (str, o, 1, true)
if i then
return strsub(str, 1, i-1) .. n .. strsub(str, j+1, -1)
else
return str
end
end
-- locale independent num2str and str2num functions
local decpoint, numfilter
local function updatedecpoint ()
decpoint = strmatch(tostring(0.5), "([^05+])")
-- build a filter that can be used to remove group separators
numfilter = "[^0-9%-%+eE" .. gsub(decpoint, "[%^%$%(%)%%%.%[%]%*%+%-%?]", "%%%0") .. "]+"
end
updatedecpoint()
local function num2str (num)
return replace(fsub(tostring(num), numfilter, ""), decpoint, ".")
end
local function str2num (str)
local num = tonumber(replace(str, ".", decpoint))
if not num then
updatedecpoint()
num = tonumber(replace(str, ".", decpoint))
end
return num
end
local function addnewline2 (level, buffer, buflen)
buffer[buflen+1] = "\n"
buffer[buflen+2] = strrep (" ", level)
buflen = buflen + 2
return buflen
end
function json.addnewline (state)
if state.indent then
state.bufferlen = addnewline2 (state.level or 0,
state.buffer, state.bufferlen or #(state.buffer))
end
end
local encode2 -- forward declaration
local function addpair (key, value, prev, indent, level, buffer, buflen, tables, globalorder, state)
local kt = type (key)
if kt ~= 'string' and kt ~= 'number' then
return nil, "type '" .. kt .. "' is not supported as a key by JSON."
end
if prev then
buflen = buflen + 1
buffer[buflen] = ","
end
if indent then
buflen = addnewline2 (level, buffer, buflen)
end
buffer[buflen+1] = quotestring (key)
buffer[buflen+2] = ":"
return encode2 (value, indent, level, buffer, buflen + 2, tables, globalorder, state)
end
local function appendcustom(res, buffer, state)
local buflen = state.bufferlen
if type (res) == 'string' then
buflen = buflen + 1
buffer[buflen] = res
end
return buflen
end
local function exception(reason, value, state, buffer, buflen, defaultmessage)
defaultmessage = defaultmessage or reason
local handler = state.exception
if not handler then
return nil, defaultmessage
else
state.bufferlen = buflen
local ret, msg = handler (reason, value, state, defaultmessage)
if not ret then return nil, msg or defaultmessage end
return appendcustom(ret, buffer, state)
end
end
function json.encodeexception(reason, value, state, defaultmessage)
return quotestring("<" .. defaultmessage .. ">")
end
encode2 = function (value, indent, level, buffer, buflen, tables, globalorder, state)
local valtype = type (value)
local valmeta = getmetatable (value)
valmeta = type (valmeta) == 'table' and valmeta -- only tables
local valtojson = valmeta and valmeta.__tojson
if valtojson then
if tables[value] then
return exception('reference cycle', value, state, buffer, buflen)
end
tables[value] = true
state.bufferlen = buflen
local ret, msg = valtojson (value, state)
if not ret then return exception('custom encoder failed', value, state, buffer, buflen, msg) end
tables[value] = nil
buflen = appendcustom(ret, buffer, state)
elseif value == nil then
buflen = buflen + 1
buffer[buflen] = "null"
elseif valtype == 'number' then
local s
if value ~= value or value >= huge or -value >= huge then
-- This is the behaviour of the original JSON implementation.
s = "null"
else
s = num2str (value)
end
buflen = buflen + 1
buffer[buflen] = s
elseif valtype == 'boolean' then
buflen = buflen + 1
buffer[buflen] = value and "true" or "false"
elseif valtype == 'string' then
buflen = buflen + 1
buffer[buflen] = quotestring (value)
elseif valtype == 'table' then
if tables[value] then
return exception('reference cycle', value, state, buffer, buflen)
end
tables[value] = true
level = level + 1
local isa, n = isarray (value)
if n == 0 and valmeta and valmeta.__jsontype == 'object' then
isa = false
end
local msg
if isa then -- JSON array
buflen = buflen + 1
buffer[buflen] = "["
for i = 1, n do
buflen, msg = encode2 (value[i], indent, level, buffer, buflen, tables, globalorder, state)
if not buflen then return nil, msg end
if i < n then
buflen = buflen + 1
buffer[buflen] = ","
end
end
buflen = buflen + 1
buffer[buflen] = "]"
else -- JSON object
local prev = false
buflen = buflen + 1
buffer[buflen] = "{"
local order = valmeta and valmeta.__jsonorder or globalorder
if order then
local used = {}
n = #order
for i = 1, n do
local k = order[i]
local v = value[k]
if v then
used[k] = true
buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state)
prev = true -- add a seperator before the next element
end
end
for k,v in pairs (value) do
if not used[k] then
buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state)
if not buflen then return nil, msg end
prev = true -- add a seperator before the next element
end
end
else -- unordered
for k,v in pairs (value) do
buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state)
if not buflen then return nil, msg end
prev = true -- add a seperator before the next element
end
end
if indent then
buflen = addnewline2 (level - 1, buffer, buflen)
end
buflen = buflen + 1
buffer[buflen] = "}"
end
tables[value] = nil
else
return exception ('unsupported type', value, state, buffer, buflen,
"type '" .. valtype .. "' is not supported by JSON.")
end
return buflen
end
function json.encode (value, state)
state = state or {}
local oldbuffer = state.buffer
local buffer = oldbuffer or {}
state.buffer = buffer
updatedecpoint()
local ret, msg = encode2 (value, state.indent, state.level or 0,
buffer, state.bufferlen or 0, state.tables or {}, state.keyorder, state)
if not ret then
error (msg, 2)
elseif oldbuffer == buffer then
state.bufferlen = ret
return true
else
state.bufferlen = nil
state.buffer = nil
return concat (buffer)
end
end
local function loc (str, where)
local line, pos, linepos = 1, 1, 0
while true do
pos = strfind (str, "\n", pos, true)
if pos and pos < where then
line = line + 1
linepos = pos
pos = pos + 1
else
break
end
end
return "line " .. line .. ", column " .. (where - linepos)
end
local function unterminated (str, what, where)
return nil, strlen (str) + 1, "unterminated " .. what .. " at " .. loc (str, where)
end
local function scanwhite (str, pos)
while true do
pos = strfind (str, "%S", pos)
if not pos then return nil end
local sub2 = strsub (str, pos, pos + 1)
if sub2 == "\239\187" and strsub (str, pos + 2, pos + 2) == "\191" then
-- UTF-8 Byte Order Mark
pos = pos + 3
elseif sub2 == "//" then
pos = strfind (str, "[\n\r]", pos + 2)
if not pos then return nil end
elseif sub2 == "/*" then
pos = strfind (str, "*/", pos + 2)
if not pos then return nil end
pos = pos + 2
else
return pos
end
end
end
local escapechars = {
["\""] = "\"", ["\\"] = "\\", ["/"] = "/", ["b"] = "\b", ["f"] = "\f",
["n"] = "\n", ["r"] = "\r", ["t"] = "\t"
}
local function unichar (value)
if value < 0 then
return nil
elseif value <= 0x007f then
return strchar (value)
elseif value <= 0x07ff then
return strchar (0xc0 + floor(value/0x40),
0x80 + (floor(value) % 0x40))
elseif value <= 0xffff then
return strchar (0xe0 + floor(value/0x1000),
0x80 + (floor(value/0x40) % 0x40),
0x80 + (floor(value) % 0x40))
elseif value <= 0x10ffff then
return strchar (0xf0 + floor(value/0x40000),
0x80 + (floor(value/0x1000) % 0x40),
0x80 + (floor(value/0x40) % 0x40),
0x80 + (floor(value) % 0x40))
else
return nil
end
end
local function scanstring (str, pos)
local lastpos = pos + 1
local buffer, n = {}, 0
while true do
local nextpos = strfind (str, "[\"\\]", lastpos)
if not nextpos then
return unterminated (str, "string", pos)
end
if nextpos > lastpos then
n = n + 1
buffer[n] = strsub (str, lastpos, nextpos - 1)
end
if strsub (str, nextpos, nextpos) == "\"" then
lastpos = nextpos + 1
break
else
local escchar = strsub (str, nextpos + 1, nextpos + 1)
local value
if escchar == "u" then
value = tonumber (strsub (str, nextpos + 2, nextpos + 5), 16)
if value then
local value2
if 0xD800 <= value and value <= 0xDBff then
-- we have the high surrogate of UTF-16. Check if there is a
-- low surrogate escaped nearby to combine them.
if strsub (str, nextpos + 6, nextpos + 7) == "\\u" then
value2 = tonumber (strsub (str, nextpos + 8, nextpos + 11), 16)
if value2 and 0xDC00 <= value2 and value2 <= 0xDFFF then
value = (value - 0xD800) * 0x400 + (value2 - 0xDC00) + 0x10000
else
value2 = nil -- in case it was out of range for a low surrogate
end
end
end
value = value and unichar (value)
if value then
if value2 then
lastpos = nextpos + 12
else
lastpos = nextpos + 6
end
end
end
end
if not value then
value = escapechars[escchar] or escchar
lastpos = nextpos + 2
end
n = n + 1
buffer[n] = value
end
end
if n == 1 then
return buffer[1], lastpos
elseif n > 1 then
return concat (buffer), lastpos
else
return "", lastpos
end
end
local scanvalue -- forward declaration
local function scantable (what, closechar, str, startpos, nullval, objectmeta, arraymeta)
local len = strlen (str)
local tbl, n = {}, 0
local pos = startpos + 1
if what == 'object' then
setmetatable (tbl, objectmeta)
else
setmetatable (tbl, arraymeta)
end
while true do
pos = scanwhite (str, pos)
if not pos then return unterminated (str, what, startpos) end
local char = strsub (str, pos, pos)
if char == closechar then
return tbl, pos + 1
end
local val1, err
val1, pos, err = scanvalue (str, pos, nullval, objectmeta, arraymeta)
if err then return nil, pos, err end
pos = scanwhite (str, pos)
if not pos then return unterminated (str, what, startpos) end
char = strsub (str, pos, pos)
if char == ":" then
if val1 == nil then
return nil, pos, "cannot use nil as table index (at " .. loc (str, pos) .. ")"
end
pos = scanwhite (str, pos + 1)
if not pos then return unterminated (str, what, startpos) end
local val2
val2, pos, err = scanvalue (str, pos, nullval, objectmeta, arraymeta)
if err then return nil, pos, err end
tbl[val1] = val2
pos = scanwhite (str, pos)
if not pos then return unterminated (str, what, startpos) end
char = strsub (str, pos, pos)
else
n = n + 1
tbl[n] = val1
end
if char == "," then
pos = pos + 1
end
end
end
scanvalue = function (str, pos, nullval, objectmeta, arraymeta)
pos = pos or 1
pos = scanwhite (str, pos)
if not pos then
return nil, strlen (str) + 1, "no valid JSON value (reached the end)"
end
local char = strsub (str, pos, pos)
if char == "{" then
return scantable ('object', "}", str, pos, nullval, objectmeta, arraymeta)
elseif char == "[" then
return scantable ('array', "]", str, pos, nullval, objectmeta, arraymeta)
elseif char == "\"" then
return scanstring (str, pos)
else
local pstart, pend = strfind (str, "^%-?[%d%.]+[eE]?[%+%-]?%d*", pos)
if pstart then
local number = str2num (strsub (str, pstart, pend))
if number then
return number, pend + 1
end
end
pstart, pend = strfind (str, "^%a%w*", pos)
if pstart then
local name = strsub (str, pstart, pend)
if name == "true" then
return true, pend + 1
elseif name == "false" then
return false, pend + 1
elseif name == "null" then
return nullval, pend + 1
end
end
return nil, pos, "no valid JSON value at " .. loc (str, pos)
end
end
local function optionalmetatables(...)
if select("#", ...) > 0 then
return ...
else
return {__jsontype = 'object'}, {__jsontype = 'array'}
end
end
function json.decode (str, pos, nullval, ...)
local objectmeta, arraymeta = optionalmetatables(...)
return scanvalue (str, pos, nullval, objectmeta, arraymeta)
end
function json.use_lpeg ()
local g = require ("lpeg")
if g.version() == "0.11" then
error "due to a bug in LPeg 0.11, it cannot be used for JSON matching"
end
local pegmatch = g.match
local P, S, R = g.P, g.S, g.R
local function ErrorCall (str, pos, msg, state)
if not state.msg then
state.msg = msg .. " at " .. loc (str, pos)
state.pos = pos
end
return false
end
local function Err (msg)
return g.Cmt (g.Cc (msg) * g.Carg (2), ErrorCall)
end
local SingleLineComment = P"//" * (1 - S"\n\r")^0
local MultiLineComment = P"/*" * (1 - P"*/")^0 * P"*/"
local Space = (S" \n\r\t" + P"\239\187\191" + SingleLineComment + MultiLineComment)^0
local PlainChar = 1 - S"\"\\\n\r"
local EscapeSequence = (P"\\" * g.C (S"\"\\/bfnrt" + Err "unsupported escape sequence")) / escapechars
local HexDigit = R("09", "af", "AF")
local function UTF16Surrogate (match, pos, high, low)
high, low = tonumber (high, 16), tonumber (low, 16)
if 0xD800 <= high and high <= 0xDBff and 0xDC00 <= low and low <= 0xDFFF then
return true, unichar ((high - 0xD800) * 0x400 + (low - 0xDC00) + 0x10000)
else
return false
end
end
local function UTF16BMP (hex)
return unichar (tonumber (hex, 16))
end
local U16Sequence = (P"\\u" * g.C (HexDigit * HexDigit * HexDigit * HexDigit))
local UnicodeEscape = g.Cmt (U16Sequence * U16Sequence, UTF16Surrogate) + U16Sequence/UTF16BMP
local Char = UnicodeEscape + EscapeSequence + PlainChar
local String = P"\"" * g.Cs (Char ^ 0) * (P"\"" + Err "unterminated string")
local Integer = P"-"^(-1) * (P"0" + (R"19" * R"09"^0))
local Fractal = P"." * R"09"^0
local Exponent = (S"eE") * (S"+-")^(-1) * R"09"^1
local Number = (Integer * Fractal^(-1) * Exponent^(-1))/str2num
local Constant = P"true" * g.Cc (true) + P"false" * g.Cc (false) + P"null" * g.Carg (1)
local SimpleValue = Number + String + Constant
local ArrayContent, ObjectContent
-- The functions parsearray and parseobject parse only a single value/pair
-- at a time and store them directly to avoid hitting the LPeg limits.
local function parsearray (str, pos, nullval, state)
local obj, cont
local npos
local t, nt = {}, 0
repeat
obj, cont, npos = pegmatch (ArrayContent, str, pos, nullval, state)
if not npos then break end
pos = npos
nt = nt + 1
t[nt] = obj
until cont == 'last'
return pos, setmetatable (t, state.arraymeta)
end
local function parseobject (str, pos, nullval, state)
local obj, key, cont
local npos
local t = {}
repeat
key, obj, cont, npos = pegmatch (ObjectContent, str, pos, nullval, state)
if not npos then break end
pos = npos
t[key] = obj
until cont == 'last'
return pos, setmetatable (t, state.objectmeta)
end
local Array = P"[" * g.Cmt (g.Carg(1) * g.Carg(2), parsearray) * Space * (P"]" + Err "']' expected")
local Object = P"{" * g.Cmt (g.Carg(1) * g.Carg(2), parseobject) * Space * (P"}" + Err "'}' expected")
local Value = Space * (Array + Object + SimpleValue)
local ExpectedValue = Value + Space * Err "value expected"
ArrayContent = Value * Space * (P"," * g.Cc'cont' + g.Cc'last') * g.Cp()
local Pair = g.Cg (Space * String * Space * (P":" + Err "colon expected") * ExpectedValue)
ObjectContent = Pair * Space * (P"," * g.Cc'cont' + g.Cc'last') * g.Cp()
local DecodeValue = ExpectedValue * g.Cp ()
function json.decode (str, pos, nullval, ...)
local state = {}
state.objectmeta, state.arraymeta = optionalmetatables(...)
local obj, retpos = pegmatch (DecodeValue, str, pos, nullval, state)
if state.msg then
return nil, state.pos, state.msg
else
return obj, retpos
end
end
-- use this function only once:
json.use_lpeg = function () return json end
json.using_lpeg = true
return json -- so you can get the module using json = require "dkjson".use_lpeg()
end
if always_try_using_lpeg then
pcall (json.use_lpeg)
end
return json
+29 -4
View File
@@ -1,5 +1,5 @@
#Ship types
#Ship types
$Name: Navbuoy
$Max Debris Speed: 200
$FF Multiplier: 1.0
@@ -12,6 +12,7 @@ $AI:
+Turrets attack this: YES
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Vaporize Percent Chance: 0.0
$Name: Sentry Gun
$Counts for Alone: YES
$On Hotkey List: YES
@@ -32,6 +33,7 @@ $AI:
+Turrets attack this: YES
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Vaporize Percent Chance: 0.0
$Name: Escape Pod
$Praise Destruction: YES
$On Hotkey List: YES
@@ -50,6 +52,7 @@ $AI:
+Turrets attack this: YES
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Vaporize Percent Chance: 0.0
$Name: Cargo
$Scannable: YES
$Max Debris Speed: 200
@@ -63,6 +66,7 @@ $Fog:
$AI:
+Passive docks: ( "cargo" )
$Vaporize Percent Chance: 0.0
$Name: Support
$Counts for Alone: YES
$Praise Destruction: YES
@@ -89,6 +93,7 @@ $AI:
+Active docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Vaporize Percent Chance: 0.0
;;WMC - Stealth ships always have another type, so this isn't used
$Name: Stealth
$Counts for Alone: YES
@@ -114,6 +119,7 @@ $AI:
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Vaporize Percent Chance: 0.0
$Name: Fighter
$Counts for Alone: YES
$Praise Destruction: YES
@@ -141,6 +147,7 @@ $AI:
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Vaporize Percent Chance: 0.0
$Name: Bomber
$Counts for Alone: YES
$Praise Destruction: YES
@@ -168,7 +175,8 @@ $AI:
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Vaporize Percent Chance: 0.0
;;WMC - This fighter/bomber type doesn't seem to be used anywhere, because no ship is set as both fighter and bomber
;;WMC - This fighter/bomber type doesn't seem to be used anywhere, because no ship is set as both fighter and bomber
$Name: Fighter/bomber
$Counts for Alone: YES
$Praise Destruction: YES
@@ -195,6 +203,7 @@ $AI:
+Passive docks: ( "support" )
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
$Vaporize Percent Chance: 0.0
$Name: Transport
$Counts for Alone: YES
$Praise Destruction: YES
@@ -204,6 +213,7 @@ $Show Attack Direction: YES
$Max Debris Speed: 150
$FF Multiplier: 1.0
$EMP Multiplier: 2.0
$Warp Sound Range Multiplier: 6.0
$Beams Easily Hit: YES
$Protected on cripple: YES
$Fog:
@@ -223,6 +233,7 @@ $AI:
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Vaporize Percent Chance: 0.0
$Name: Freighter
$Counts for Alone: YES
$Praise Destruction: YES
@@ -233,6 +244,7 @@ $Scannable: YES
$Max Debris Speed: 150
$FF Multiplier: 1.0
$EMP Multiplier: 1.75
$Warp Sound Range Multiplier: 6.0
$Beams Easily Hit: YES
$Protected on cripple: YES
$Fog:
@@ -253,6 +265,7 @@ $AI:
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Vaporize Percent Chance: 0.0
$Name: AWACS
$Counts for Alone: YES
$Praise Destruction: YES
@@ -262,6 +275,7 @@ $Show Attack Direction: YES
$Max Debris Speed: 150
$FF Multiplier: 1.0
$EMP Multiplier: 0.8
$Warp Sound Range Multiplier: 6.0
$Beams Easily Hit: YES
$Protected on cripple: YES
$Fog:
@@ -281,6 +295,7 @@ $AI:
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Vaporize Percent Chance: 0.0
$Name: Gas Miner
$Counts for Alone: YES
$Praise Destruction: YES
@@ -290,6 +305,7 @@ $Show Attack Direction: YES
$Max Debris Speed: 150
$FF Multiplier: 1.0
$EMP Multiplier: 1.0
$Warp Sound Range Multiplier: 6.0
$Beams Easily Hit: YES
$Protected on cripple: YES
$Fog:
@@ -309,6 +325,7 @@ $AI:
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Vaporize Percent Chance: 0.0
$Name: Cruiser
$Counts for Alone: YES
$Praise Destruction: YES
@@ -318,6 +335,7 @@ $Show Attack Direction: YES
$Max Debris Speed: 150
$FF Multiplier: 1.0
$EMP Multiplier: 0.9
$Warp Sound Range Multiplier: 6.0
$Beams Easily Hit: YES
$Protected on cripple: YES
$Fog:
@@ -337,6 +355,7 @@ $AI:
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Vaporize Percent Chance: 0.0
$Name: Corvette
$Counts for Alone: YES
$Praise Destruction: YES
@@ -346,6 +365,7 @@ $Show Attack Direction: YES
$Max Debris Speed: 150
$FF Multiplier: 1.0
$EMP Multiplier: 0.3333
$Warp Sound Range Multiplier: 6.0
$Beams Easily Hit: YES
$Protected on cripple: YES
$Fog:
@@ -365,6 +385,7 @@ $AI:
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Vaporize Percent Chance: 0.0
$Name: Capital
$Counts for Alone: YES
$Praise Destruction: YES
@@ -394,6 +415,7 @@ $AI:
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Vaporize Percent Chance: 0.0
$Name: Super Cap
$Counts for Alone: YES
$Praise Destruction: YES
@@ -421,6 +443,7 @@ $AI:
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Vaporize Percent Chance: 0.0
$Name: Drydock
$Counts for Alone: YES
$Praise Destruction: YES
@@ -446,6 +469,7 @@ $AI:
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Vaporize Percent Chance: 0.0
$Name: Knossos Device
$Counts for Alone: YES
$Praise Destruction: YES
@@ -469,4 +493,5 @@ $AI:
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
$Vaporize Percent Chance: 0.0
#End
#End
+1 -1
View File
@@ -311,7 +311,7 @@ static char* GetFilePart(char *source)
SCP_string safe_string;
// Entry point into the main exception handling routine. This routine is put into an except()
// statment at the beginning of a thread and is called anytime that there is a program exception
// statement at the beginning of a thread and is called anytime that there is a program exception
// The data is stored in a file called ErrorLog.txt in the data directory.
//
// data: pointer to the exception data
+38 -31
View File
@@ -48,44 +48,51 @@ bool fireballs_parsed = false;
bool Fireball_use_3d_warp = false;
static auto WarpOption = options::OptionBuilder<bool>("Graphics.3dWarp", "3D Warp", "Use a 3D model for warp effects")
.category("Graphics")
.default_val(true)
.level(options::ExpertLevel::Advanced)
.bind_to(&Fireball_use_3d_warp)
.importance(65)
.finish();
static auto WarpOption __UNUSED = options::OptionBuilder<bool>("Graphics.3dWarp",
std::pair<const char*, int>{"3D Warp", 1770},
std::pair<const char*, int>{"Use a 3D model for warp effects", 1771})
.category("Graphics")
.default_val(true)
.level(options::ExpertLevel::Advanced)
.bind_to(&Fireball_use_3d_warp)
.importance(65)
.finish();
/**
* Play warp in sound for warp effect
*/
void fireball_play_warphole_open_sound(int ship_class, fireball *fb)
{
gamesnd_id sound_index;
float range_multiplier = 1.0f;
object *fireball_objp;
Assert((fb != NULL) && (fb->objnum >= 0));
if((fb == NULL) || (fb->objnum < 0)){
return;
}
fireball_objp = &Objects[fb->objnum];
auto fireball_objp = &Objects[fb->objnum];
auto sound_index = gamesnd_id(GameSounds::WARP_IN);
sound_index = gamesnd_id(GameSounds::WARP_IN);
if(fb->warp_open_sound_index.isValid()) {
if (fb->warp_open_sound_index.isValid()) {
sound_index = fb->warp_open_sound_index;
} else if ((ship_class >= 0) && (ship_class < ship_info_size())) {
if ( Ship_info[ship_class].is_huge_ship() ) {
sound_index = gamesnd_id(GameSounds::CAPITAL_WARP_IN);
fb->flags |= FBF_WARP_CAPITAL_SIZE;
} else if ( Ship_info[ship_class].is_big_ship() ) {
range_multiplier = 6.0f;
fb->flags |= FBF_WARP_CRUISER_SIZE;
}
}
snd_play_3d(gamesnd_get_game_sound(sound_index), &fireball_objp->pos, &Eye_position, fireball_objp->radius, NULL, 0, 1.0f, SND_PRIORITY_DOUBLE_INSTANCE, NULL, range_multiplier); // play warp sound effect
if (ship_class >= 0 && ship_class < ship_info_size()) {
if (Ship_info[ship_class].is_huge_ship()) {
fb->flags |= FBF_WARP_CAPITAL_SIZE;
} else if (Ship_info[ship_class].is_big_ship()) {
fb->flags |= FBF_WARP_CRUISER_SIZE;
}
// originally 6.0 for SIF_BIG_SHIP and 1.0 for everything else
if (Ship_info[ship_class].class_type >= 0)
fb->warp_sound_range_multiplier = Ship_types[Ship_info[ship_class].class_type].warp_sound_range_multiplier;
else
fb->warp_sound_range_multiplier = 1.0f;
}
snd_play_3d(gamesnd_get_game_sound(sound_index), &fireball_objp->pos, &Eye_position, fireball_objp->radius, NULL, 0, 1.0f, SND_PRIORITY_DOUBLE_INSTANCE, NULL, fb->warp_sound_range_multiplier); // play warp sound effect
}
/**
@@ -93,15 +100,14 @@ void fireball_play_warphole_open_sound(int ship_class, fireball *fb)
*/
void fireball_play_warphole_close_sound(fireball *fb)
{
gamesnd_id sound_index;
Assert((fb != NULL) && (fb->objnum >= 0));
if((fb == NULL) || (fb->objnum < 0)){
return;
}
auto fireball_objp = &Objects[fb->objnum];
auto sound_index = gamesnd_id(GameSounds::WARP_OUT);
object *fireball_objp;
fireball_objp = &Objects[fb->objnum];
sound_index = gamesnd_id(GameSounds::WARP_OUT);
if ( fb->warp_close_sound_index.isValid() ) {
if (fb->warp_close_sound_index.isValid()) {
sound_index = fb->warp_close_sound_index;
} else if ( fb->flags & FBF_WARP_CAPITAL_SIZE ) {
sound_index = gamesnd_id(GameSounds::CAPITAL_WARP_OUT);
@@ -109,7 +115,7 @@ void fireball_play_warphole_close_sound(fireball *fb)
return;
}
snd_play_3d(gamesnd_get_game_sound(sound_index), &fireball_objp->pos, &Eye_position, fireball_objp->radius); // play warp sound effect
snd_play_3d(gamesnd_get_game_sound(sound_index), &fireball_objp->pos, &Eye_position, fireball_objp->radius, NULL, 0, 1.0F, SND_PRIORITY_SINGLE_INSTANCE, NULL, fb->warp_sound_range_multiplier); // play warp sound effect
}
static void fireball_generate_unique_id(char *unique_id, int buffer_len, int fireball_index)
@@ -845,6 +851,7 @@ int fireball_create(vec3d *pos, int fireball_type, int render_type, int parent_o
new_fireball->warp_close_sound_index = warp_close_sound;
new_fireball->warp_open_duration = (warp_open_duration < 0.0f) ? WARPHOLE_GROW_TIME : warp_open_duration;
new_fireball->warp_close_duration = (warp_close_duration < 0.0f) ? WARPHOLE_GROW_TIME : warp_close_duration;
new_fireball->warp_sound_range_multiplier = 1.0f;
matrix orient;
if(orient_override != NULL){
@@ -1069,8 +1076,8 @@ void fireball_render(object* obj, model_draw_list *scene)
float alpha = 1.0f;
if (The_mission.flags[Mission::Mission_Flags::Fullneb] && Neb_affects_fireballs)
alpha *= neb2_get_fog_visibility(&obj->pos,
if (Neb_affects_fireballs)
nebula_handle_alpha(alpha, &obj->pos,
Neb2_fog_visibility_fireball_const + (obj->radius * Neb2_fog_visibility_fireball_scaled_factor));
g3_transfer_vertex(&p, &obj->pos);
+3 -2
View File
@@ -40,8 +40,6 @@ class asteroid_info;
#define FIREBALL_NUM_LARGE_EXPLOSIONS 2
#define MAX_FIREBALLS 200
extern int fireball_used[MAX_FIREBALL_TYPES];
// all this moved here by Goober5000 because it makes more sense in the H file
@@ -94,6 +92,9 @@ typedef struct fireball {
gamesnd_id warp_close_sound_index;
float warp_open_duration;
float warp_close_duration;
// the sound multiplier is based on the ship class, but we lose that while the warp is closing
float warp_sound_range_multiplier;
} fireball;
// end move
+11 -8
View File
@@ -24,13 +24,15 @@
bool Fireball_warp_flash = false;
static auto WarpFlashOption = options::OptionBuilder<bool>("Graphics.WarpFlash", "Warp Flash", "Show flash upon warp open or close")
.category("Graphics")
.default_val(true)
.level(options::ExpertLevel::Advanced)
.bind_to_once(&Fireball_warp_flash)
.importance(65)
.finish();
static auto WarpFlashOption __UNUSED = options::OptionBuilder<bool>("Graphics.WarpFlash",
std::pair<const char*, int>{"Warp Flash", 1768},
std::pair<const char*, int>{"Show flash upon warp open or close", 1769})
.category("Graphics")
.default_val(true)
.level(options::ExpertLevel::Advanced)
.bind_to_once(&Fireball_warp_flash)
.importance(65)
.finish();
void warpin_batch_draw_face( int texture, vertex *v1, vertex *v2, vertex *v3 )
{
@@ -83,7 +85,8 @@ void warpin_queue_render(model_draw_list *scene, object *obj, matrix *orient, ve
g3_transfer_vertex( &verts[4], &vecs[4] );
float alpha = (The_mission.flags[Mission::Mission_Flags::Fullneb]) ? neb2_get_fog_visibility(&obj->pos, 1.0f) : 1.0f;
float alpha = 1.0f;
nebula_handle_alpha(alpha, &obj->pos, 1.0f);
//batch_add_bitmap(warp_glow_bitmap, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT, &verts[4], 0, r, alpha);
batching_add_bitmap(warp_glow_bitmap, &verts[4], 0, r, alpha);
+347 -476
View File
@@ -11,10 +11,12 @@
#include "controlconfig/controlsconfig.h"
#include "freespace.h"
#include "gamehelp/gameplayhelp.h"
#include "gamesequence/gamesequence.h"
#include "gamesnd/gamesnd.h"
#include "globalincs/alphacolors.h"
#include "io/key.h"
#include "mission/missionmessage.h"
#include "missionui/missionscreencommon.h"
#include "sound/audiostr.h"
#include "ui/ui.h"
@@ -22,33 +24,44 @@
// text positioning constats
// text positioning constants
#define TITLE_Y 35
#define Y_START 70
#define X_OFFSET_1 70
// pixel offset for description of key from where key binding starts
#define KEY_DESCRIPTION_OFFSET 193
// increased this from 193 to 250 to account for allowing multiple keys -Mjn
#define KEY_DESCRIPTION_OFFSET 250
// different gameplay help pages
enum : int {
// The first 9 are the basic retail pages
GP_HELP_BASIC_KEYS,
GP_HELP_MOVEMENT_KEYS,
GP_HELP_COMMON_TARGET_KEYS,
GP_HELP_ADVANCED_TARGET_KEYS,
GP_HELP_MESSAGING,
GP_HELP_WEAPON_KEYS,
GP_HELP_THROTTLE_AND_ETS_KEYS,
GP_HELP_VIEW_KEYS,
GP_HELP_MISC_KEYS,
// Plus one for multi only
GP_HELP_MULTI_KEYS,
// Any others defined here will have unique sections within the vector
// but will need special handling to display in the retail UI
GP_HELP_FUNCTION_KEYS,
First_available_section
};
#define GP_FIRST_SCREEN 0 // keep up to date
#define GP_HELP_BASIC_KEYS 0
#define GP_HELP_MOVEMENT_KEYS 1
#define GP_HELP_COMMON_TARGET_KEYS 2
#define GP_HELP_ADVANCED_TARGET_KEYS 3
#define GP_HELP_MESSAGING 4
#define GP_HELP_WEAPON_KEYS 5
#define GP_HELP_THROTTLE_AND_ETS_KEYS 6
#define GP_HELP_VIEW_KEYS 7
#define GP_HELP_MISC_KEYS 8
#define GP_HELP_MULTI_KEYS 9
#define GP_LAST_SCREEN_SINGLE 8 // keep up to date
#define GP_LAST_SCREEN_MULTI 9 // keep up to date
// set this to GP_LAST_SCREEN_SINGLE or GP_LAST_SCREEN_MULTI based upon what game mode we're in
int Gp_last_screen;
static int Gp_last_screen;
#define NUM_BUTTONS 3
#define PREVIOUS_PAGE_BUTTON 0
@@ -109,10 +122,11 @@ static int Gameplay_help_inited = 0;
static int Current_help_page;
SCP_vector<gameplay_help_section> Help_text;
void gameplay_help_blit_control_line(int x, int y, int id)
void gameplay_help_init_control_line(int id, gameplay_help_section &thisHelp)
{
char buf[256];
char buf[256];
auto ci = &Control_config[id];
@@ -121,38 +135,55 @@ void gameplay_help_blit_control_line(int x, int y, int id)
strcpy_s(buf, ci->first.textify().c_str());
if (!ci->second.empty()) {
strcat_s(buf, XSTR( ", ", 129));
strcat_s(buf, XSTR(", ", 129));
strcat_s(buf, ci->second.textify().c_str());
}
if (ci->empty()) {
strcpy_s(buf, XSTR( "no binding", 130));
strcpy_s(buf, XSTR("no binding", 130));
}
gr_string(x,y,buf,GR_RESIZE_MENU);
// gr_string(x+KEY_DESCRIPTION_OFFSET,y,ci->text,GR_RESIZE_MENU);
gr_string(x+KEY_DESCRIPTION_OFFSET, y, XSTR(ci->text.c_str(), CONTROL_CONFIG_XSTR + id), GR_RESIZE_MENU);
thisHelp.key.push_back(buf);
thisHelp.text.push_back(XSTR(ci->text.c_str(), CONTROL_CONFIG_XSTR + id));
}
void gameplay_help_blit_control_line_raw(int x, int y, const char *control_text, const char *control_description)
void gameplay_help_init_control_line_raw(const char* control_text, const char* control_description, gameplay_help_section &thisHelp)
{
gr_string(x,y,control_text,GR_RESIZE_MENU);
gr_string(x+KEY_DESCRIPTION_OFFSET,y,control_description,GR_RESIZE_MENU);
thisHelp.key.push_back(control_text);
thisHelp.text.push_back(control_description);
}
// displays the given help key and text at the specified
// x and y coordinates
void gameplay_help_blit_help_text(int x, int y, const SCP_string *control_text, const SCP_string *control_description)
{
gr_string(x, y, control_text->c_str(), GR_RESIZE_MENU);
gr_string(x + KEY_DESCRIPTION_OFFSET, y, control_description->c_str(), GR_RESIZE_MENU);
}
// displays a help section header at the specified y coordinate and an x coordinate
// calculated from the header string's length
void gameplay_help_blit_header_text(int y_offset, const SCP_string *header)
{
gr_set_color_fast(&Color_bright);
int w;
gr_get_string_size(&w, nullptr, header->c_str());
gr_printf_menu((gr_screen.clip_width - w) / 2, y_offset, "%s", header->c_str());
gr_set_color_fast(&Color_normal);
}
// game_play_help_set_title() will display the title for the help screen and
// set the font for the rest of the screen
void gameplay_help_set_title(const char *title)
void gameplay_help_set_title(const SCP_string *title)
{
int sy=TITLE_Y;
char buf[128];
gr_set_color_fast(&Color_bright);
int w;
gr_get_string_size(&w, NULL, title);
gr_get_string_size(&w, nullptr, title->c_str());
gr_printf_menu((gr_screen.clip_width_unscaled - w) / 2,sy,"%s", title);
gr_printf_menu((gr_screen.clip_width_unscaled - w) / 2,sy,"%s", title->c_str());
sprintf(buf, XSTR("Page %d of %d", 132), Current_help_page + 1, Gp_last_screen + 1);
gr_get_string_size(&w, NULL, buf);
@@ -160,6 +191,253 @@ void gameplay_help_set_title(const char *title)
gr_set_color_fast(&Color_normal);
}
// Inits all the gameplay help text and returns it
// in a nice organized vector of help sections
SCP_vector<gameplay_help_section> gameplay_help_init_text()
{
SCP_vector<gameplay_help_section> complete_help_text;
for (int i = 0; i < First_available_section; i++) {
gameplay_help_section thisHelp;
switch (i) {
case GP_HELP_BASIC_KEYS:
thisHelp.title = XSTR("Basic Keys", 133);
thisHelp.header = "";
gameplay_help_init_control_line(END_MISSION, thisHelp);
gameplay_help_init_control_line(FIRE_PRIMARY, thisHelp);
gameplay_help_init_control_line(MAX_THROTTLE, thisHelp);
gameplay_help_init_control_line(ZERO_THROTTLE, thisHelp);
gameplay_help_init_control_line(TARGET_NEXT, thisHelp);
gameplay_help_init_control_line(TARGET_PREV, thisHelp);
gameplay_help_init_control_line(TOGGLE_AUTO_TARGETING, thisHelp);
break;
case GP_HELP_MOVEMENT_KEYS:
thisHelp.title = XSTR("Movement Keys", 147);
thisHelp.header = "";
gameplay_help_init_control_line(FORWARD_THRUST, thisHelp);
gameplay_help_init_control_line(MAX_THROTTLE, thisHelp);
gameplay_help_init_control_line(ONE_THIRD_THROTTLE, thisHelp);
gameplay_help_init_control_line(TWO_THIRDS_THROTTLE, thisHelp);
gameplay_help_init_control_line(MINUS_5_PERCENT_THROTTLE, thisHelp);
gameplay_help_init_control_line(PLUS_5_PERCENT_THROTTLE, thisHelp);
gameplay_help_init_control_line(ZERO_THROTTLE, thisHelp);
gameplay_help_init_control_line(AFTERBURNER, thisHelp);
gameplay_help_init_control_line(REVERSE_THRUST, thisHelp);
gameplay_help_init_control_line(PITCH_FORWARD, thisHelp);
gameplay_help_init_control_line(PITCH_BACK, thisHelp);
gameplay_help_init_control_line(YAW_LEFT, thisHelp);
gameplay_help_init_control_line(YAW_RIGHT, thisHelp);
gameplay_help_init_control_line(BANK_LEFT, thisHelp);
gameplay_help_init_control_line(BANK_RIGHT, thisHelp);
gameplay_help_init_control_line(BANK_WHEN_PRESSED, thisHelp);
break;
case GP_HELP_COMMON_TARGET_KEYS:
thisHelp.title = XSTR("Basic Targeting Keys", 148);
thisHelp.header = "";
gameplay_help_init_control_line(TARGET_NEXT, thisHelp);
gameplay_help_init_control_line(TARGET_PREV, thisHelp);
gameplay_help_init_control_line(TOGGLE_AUTO_TARGETING, thisHelp);
gameplay_help_init_control_line(TARGET_SHIP_IN_RETICLE, thisHelp);
gameplay_help_init_control_line(TARGET_NEXT_CLOSEST_HOSTILE, thisHelp);
gameplay_help_init_control_line(TARGET_PREV_CLOSEST_HOSTILE, thisHelp);
gameplay_help_init_control_line(TARGET_NEXT_CLOSEST_FRIENDLY, thisHelp);
gameplay_help_init_control_line(TARGET_PREV_CLOSEST_FRIENDLY, thisHelp);
gameplay_help_init_control_line(TARGET_NEXT_SUBOBJECT, thisHelp);
gameplay_help_init_control_line(TARGET_PREV_SUBOBJECT, thisHelp);
gameplay_help_init_control_line(TARGET_SUBOBJECT_IN_RETICLE, thisHelp);
gameplay_help_init_control_line(MATCH_TARGET_SPEED, thisHelp);
gameplay_help_init_control_line(TOGGLE_AUTO_MATCH_TARGET_SPEED, thisHelp);
break;
case GP_HELP_ADVANCED_TARGET_KEYS:
thisHelp.title = XSTR("Advanced Targeting Keys", 149);
thisHelp.header = "";
gameplay_help_init_control_line(TARGET_CLOSEST_SHIP_ATTACKING_SELF, thisHelp);
gameplay_help_init_control_line(TARGET_CLOSEST_SHIP_ATTACKING_TARGET, thisHelp);
gameplay_help_init_control_line(TARGET_LAST_TRANMISSION_SENDER, thisHelp);
gameplay_help_init_control_line(TARGET_TARGETS_TARGET, thisHelp);
gameplay_help_init_control_line(TARGET_NEXT_ESCORT_SHIP, thisHelp);
gameplay_help_init_control_line(TARGET_CLOSEST_REPAIR_SHIP, thisHelp);
gameplay_help_init_control_line(TARGET_NEXT_UNINSPECTED_CARGO, thisHelp);
gameplay_help_init_control_line(TARGET_PREV_UNINSPECTED_CARGO, thisHelp);
gameplay_help_init_control_line(TARGET_NEWEST_SHIP, thisHelp);
gameplay_help_init_control_line(TARGET_NEXT_BOMB, thisHelp);
gameplay_help_init_control_line(TARGET_PREV_BOMB, thisHelp);
gameplay_help_init_control_line(STOP_TARGETING_SHIP, thisHelp);
gameplay_help_init_control_line(TARGET_NEXT_LIVE_TURRET, thisHelp);
gameplay_help_init_control_line(TARGET_PREV_LIVE_TURRET, thisHelp);
gameplay_help_init_control_line(STOP_TARGETING_SUBSYSTEM, thisHelp);
gameplay_help_init_control_line_raw(XSTR("F5...F12", 143), XSTR("Select target assigned to that hotkey", 150), thisHelp);
gameplay_help_init_control_line_raw(XSTR("Shift-F5...F12", 151), XSTR("Add/remove target from that hotkey", 152), thisHelp);
gameplay_help_init_control_line_raw(XSTR("Alt-Shift-F5...F12", 153), XSTR("Clear that hotkey", 154), thisHelp);
break;
case GP_HELP_MESSAGING:
thisHelp.title = XSTR("Messaging Keys", 155);
thisHelp.header = "";
gameplay_help_init_control_line(SQUADMSG_MENU, thisHelp);
gameplay_help_init_control_line(REARM_MESSAGE, thisHelp);
gameplay_help_init_control_line(ATTACK_MESSAGE, thisHelp);
gameplay_help_init_control_line(DISARM_MESSAGE, thisHelp);
gameplay_help_init_control_line(DISABLE_MESSAGE, thisHelp);
gameplay_help_init_control_line(CAPTURE_MESSAGE, thisHelp);
gameplay_help_init_control_line(ENGAGE_MESSAGE, thisHelp);
gameplay_help_init_control_line(FORM_MESSAGE, thisHelp);
gameplay_help_init_control_line(IGNORE_MESSAGE, thisHelp);
gameplay_help_init_control_line(PROTECT_MESSAGE, thisHelp);
gameplay_help_init_control_line(COVER_MESSAGE, thisHelp);
gameplay_help_init_control_line(WARP_MESSAGE, thisHelp);
gameplay_help_init_control_line_raw(XSTR("F5...F12", 143),
XSTR("send specified order to these target(s)", 156),
thisHelp);
break;
case GP_HELP_WEAPON_KEYS:
thisHelp.title = XSTR("Weapon Keys", 157);
thisHelp.header = "";
gameplay_help_init_control_line(FIRE_PRIMARY, thisHelp);
gameplay_help_init_control_line(FIRE_SECONDARY, thisHelp);
gameplay_help_init_control_line(CYCLE_NEXT_PRIMARY, thisHelp);
gameplay_help_init_control_line(CYCLE_PREV_PRIMARY, thisHelp);
gameplay_help_init_control_line(CYCLE_SECONDARY, thisHelp);
gameplay_help_init_control_line(CYCLE_NUM_MISSLES, thisHelp);
gameplay_help_init_control_line(LAUNCH_COUNTERMEASURE, thisHelp);
break;
case GP_HELP_THROTTLE_AND_ETS_KEYS:
thisHelp.title = XSTR("Energy Management Keys", 158);
thisHelp.header = "";
gameplay_help_init_control_line(SHIELD_EQUALIZE, thisHelp);
gameplay_help_init_control_line(SHIELD_XFER_TOP, thisHelp);
gameplay_help_init_control_line(SHIELD_XFER_BOTTOM, thisHelp);
gameplay_help_init_control_line(SHIELD_XFER_LEFT, thisHelp);
gameplay_help_init_control_line(SHIELD_XFER_RIGHT, thisHelp);
gameplay_help_init_control_line(INCREASE_WEAPON, thisHelp);
gameplay_help_init_control_line(DECREASE_WEAPON, thisHelp);
gameplay_help_init_control_line(INCREASE_SHIELD, thisHelp);
gameplay_help_init_control_line(DECREASE_SHIELD, thisHelp);
gameplay_help_init_control_line(INCREASE_ENGINE, thisHelp);
gameplay_help_init_control_line(DECREASE_ENGINE, thisHelp);
gameplay_help_init_control_line(ETS_EQUALIZE, thisHelp);
/*
gameplay_help_init_control_line(XFER_LASER, thisHelp);
gameplay_help_init_control_line(XFER_SHIELD, thisHelp);
*/
break;
case GP_HELP_MISC_KEYS:
thisHelp.title = XSTR("Miscellaneous Keys", 159);
thisHelp.header = "";
// ending mission
gameplay_help_init_control_line(END_MISSION, thisHelp);
gameplay_help_init_control_line_raw(XSTR("ESC", 160), XSTR("invoke abort mission popup", 161), thisHelp);
// time compression
gameplay_help_init_control_line(TIME_SPEED_UP, thisHelp);
gameplay_help_init_control_line(TIME_SLOW_DOWN, thisHelp);
// radar keys
gameplay_help_init_control_line(RADAR_RANGE_CYCLE, thisHelp);
// escort view keys
gameplay_help_init_control_line(ADD_REMOVE_ESCORT, thisHelp);
gameplay_help_init_control_line(ESCORT_CLEAR, thisHelp);
// Pause, Print Screenshot
gameplay_help_init_control_line_raw(XSTR("Pause", 162), XSTR("pause game", 163), thisHelp);
gameplay_help_init_control_line_raw(XSTR("Print Scrn", 164), XSTR("take screen shot", 165), thisHelp);
break;
case GP_HELP_VIEW_KEYS:
thisHelp.title = XSTR("View Keys", 166);
thisHelp.header = "";
gameplay_help_init_control_line(PADLOCK_UP, thisHelp);
gameplay_help_init_control_line(PADLOCK_DOWN, thisHelp);
gameplay_help_init_control_line(PADLOCK_LEFT, thisHelp);
gameplay_help_init_control_line(PADLOCK_RIGHT, thisHelp);
gameplay_help_init_control_line(VIEW_CHASE, thisHelp);
gameplay_help_init_control_line(VIEW_EXTERNAL, thisHelp);
gameplay_help_init_control_line(VIEW_EXTERNAL_TOGGLE_CAMERA_LOCK, thisHelp);
gameplay_help_init_control_line(VIEW_SLEW, thisHelp);
gameplay_help_init_control_line(VIEW_DIST_INCREASE, thisHelp);
gameplay_help_init_control_line(VIEW_DIST_DECREASE, thisHelp);
gameplay_help_init_control_line(VIEW_CENTER, thisHelp);
gameplay_help_init_control_line(VIEW_OTHER_SHIP, thisHelp);
break;
case GP_HELP_MULTI_KEYS:
thisHelp.title = XSTR("Multiplayer Keys", 167);
thisHelp.header = XSTR("Ingame messaging keys (tap for text, hold for voice)", 168);
gameplay_help_init_control_line(MULTI_MESSAGE_ALL, thisHelp);
gameplay_help_init_control_line(MULTI_MESSAGE_FRIENDLY, thisHelp);
gameplay_help_init_control_line(MULTI_MESSAGE_HOSTILE, thisHelp);
gameplay_help_init_control_line(MULTI_MESSAGE_TARGET, thisHelp);
break;
case GP_HELP_FUNCTION_KEYS:
thisHelp.title = XSTR("Function Keys", 134);
thisHelp.header = "";
gameplay_help_init_control_line_raw(XSTR("F1", 135), XSTR("context-sensitive help", 136), thisHelp);
gameplay_help_init_control_line_raw(XSTR("F2", 137),
XSTR("options screen (available anywhere in game)", 138),
thisHelp);
gameplay_help_init_control_line_raw(XSTR("F3", 139), XSTR("hotkey assignment", 140), thisHelp);
gameplay_help_init_control_line_raw(XSTR("F4", 141), XSTR("HUD message scroll-back", 142), thisHelp);
gameplay_help_init_control_line_raw(XSTR("F5...F12", 143), XSTR("hotkeys", 144), thisHelp);
gameplay_help_init_control_line_raw(XSTR("Shift-Esc", 145),
XSTR("quit FreeSpace 2 immediately", 146),
thisHelp);
break;
default:
continue;
}
complete_help_text.push_back(thisHelp);
}
return complete_help_text;
}
// called once when the gameplay help state is entered
void gameplay_help_init()
{
@@ -170,6 +448,10 @@ void gameplay_help_init()
return;
}
// init all the help text
Help_text.clear(); //Make sure the array is empty before we start.
Help_text = gameplay_help_init_text();
common_set_interface_palette("InterfacePalette"); // set the interface palette
Ui_window.create(0, 0, gr_screen.max_w_unscaled, gr_screen.max_h_unscaled, 0);
Ui_window.set_mask_bmap(Game_help_mask_filename[gr_screen.res]);
@@ -204,7 +486,7 @@ void gameplay_help_init()
Background_bitmap = bm_load(Game_help_filename[gr_screen.res]);
Current_help_page = GP_HELP_BASIC_KEYS;
Current_help_page = GP_FIRST_SCREEN;
Gameplay_help_inited = 1;
}
@@ -235,6 +517,7 @@ void gameplay_help_leave()
// unpause all game sounds
weapon_unpause_sounds();
audiostream_unpause_all();
message_resume_all();
gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
game_flush();
@@ -297,456 +580,43 @@ void gameplay_help_draw_text()
separation = gr_get_font_height() + 3;
switch ( Current_help_page ) {
gameplay_help_section thisHelp = Help_text[Current_help_page];
case GP_HELP_BASIC_KEYS:
{
gameplay_help_set_title(XSTR("Basic Keys", 133));
x_offset = X_OFFSET_1;
y_offset = Y_START;
gameplay_help_set_title(&thisHelp.title);
x_offset = X_OFFSET_1;
y_offset = Y_START;
// if we have a header then display it
if (thisHelp.header.length() > 0) {
gameplay_help_blit_header_text(y_offset, &thisHelp.header);
y_offset += separation;
}
// blit help text for each key
for (int i = 0; i < (int)thisHelp.key.size(); i++) {
y_offset += separation;
gameplay_help_blit_help_text(x_offset, y_offset, &thisHelp.key[i], &thisHelp.text[i]);
}
// Special handling of function keys to display on the same page as the basic keys
if (Current_help_page == GP_HELP_BASIC_KEYS) {
y_offset += separation;
y_offset += separation;
thisHelp = Help_text[GP_HELP_FUNCTION_KEYS];
gameplay_help_blit_header_text(y_offset, &thisHelp.title);
y_offset += separation;
y_offset += separation;
// blit help text for each key
for (int i = 0; i < (int)thisHelp.key.size(); i++) {
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset, END_MISSION);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset, FIRE_PRIMARY);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset, MAX_THROTTLE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset, ZERO_THROTTLE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset, TARGET_NEXT);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset, TARGET_PREV);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset, TOGGLE_AUTO_TARGETING);
y_offset += separation;
y_offset += separation;
gr_set_color_fast(&Color_bright);
int w;
gr_get_string_size(&w, NULL, XSTR("Function Keys", 134));
gr_printf_menu((gr_screen.clip_width - w) / 2, y_offset, "%s", XSTR("Function Keys", 134));
gr_set_color_fast(&Color_normal);
y_offset += separation;
y_offset += separation;
gameplay_help_blit_control_line_raw(x_offset, y_offset, XSTR("F1", 135), XSTR("context-sensitive help", 136));
y_offset += separation;
gameplay_help_blit_control_line_raw(x_offset, y_offset, XSTR("F2", 137), XSTR("options screen (available anywhere in game)", 138));
y_offset += separation;
gameplay_help_blit_control_line_raw(x_offset, y_offset, XSTR("F3", 139), XSTR("hotkey assignment", 140));
y_offset += separation;
gameplay_help_blit_control_line_raw(x_offset, y_offset, XSTR("F4", 141), XSTR("HUD message scroll-back", 142));
y_offset += separation;
gameplay_help_blit_control_line_raw(x_offset, y_offset, XSTR("F5...F12", 143), XSTR("hotkeys", 144));
y_offset += separation;
gameplay_help_blit_control_line_raw(x_offset, y_offset, XSTR("Shift-Esc", 145), XSTR("quit FreeSpace 2 immediately", 146));
break;
gameplay_help_blit_help_text(x_offset, y_offset, &thisHelp.key[i], &thisHelp.text[i]);
}
case GP_HELP_MOVEMENT_KEYS:
gameplay_help_set_title(XSTR( "Movement Keys", 147));
x_offset=X_OFFSET_1;
y_offset=Y_START;
gameplay_help_blit_control_line(x_offset, y_offset,FORWARD_THRUST);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,MAX_THROTTLE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,ONE_THIRD_THROTTLE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,TWO_THIRDS_THROTTLE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,MINUS_5_PERCENT_THROTTLE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,PLUS_5_PERCENT_THROTTLE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,ZERO_THROTTLE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,AFTERBURNER);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,REVERSE_THRUST);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,PITCH_FORWARD);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,PITCH_BACK);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,YAW_LEFT);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,YAW_RIGHT);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,BANK_LEFT);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,BANK_RIGHT);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,BANK_WHEN_PRESSED);
break;
case GP_HELP_COMMON_TARGET_KEYS:
gameplay_help_set_title(XSTR( "Basic Targeting Keys", 148));
x_offset=X_OFFSET_1;
y_offset=Y_START;
gameplay_help_blit_control_line(x_offset, y_offset,TARGET_NEXT);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,TARGET_PREV);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,TOGGLE_AUTO_TARGETING);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,TARGET_SHIP_IN_RETICLE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,TARGET_NEXT_CLOSEST_HOSTILE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,TARGET_PREV_CLOSEST_HOSTILE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,TARGET_NEXT_CLOSEST_FRIENDLY);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,TARGET_PREV_CLOSEST_FRIENDLY);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,TARGET_NEXT_SUBOBJECT);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,TARGET_PREV_SUBOBJECT);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,TARGET_SUBOBJECT_IN_RETICLE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,MATCH_TARGET_SPEED);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,TOGGLE_AUTO_MATCH_TARGET_SPEED);
break;
case GP_HELP_ADVANCED_TARGET_KEYS:
gameplay_help_set_title(XSTR( "Advanced Targeting Keys", 149));
x_offset=X_OFFSET_1;
y_offset=Y_START;
gameplay_help_blit_control_line(x_offset, y_offset,TARGET_CLOSEST_SHIP_ATTACKING_SELF);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,TARGET_CLOSEST_SHIP_ATTACKING_TARGET);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,TARGET_LAST_TRANMISSION_SENDER);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,TARGET_TARGETS_TARGET);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,TARGET_NEXT_ESCORT_SHIP);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,TARGET_CLOSEST_REPAIR_SHIP);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,TARGET_NEXT_UNINSPECTED_CARGO);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,TARGET_PREV_UNINSPECTED_CARGO);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,TARGET_NEWEST_SHIP);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,TARGET_NEXT_BOMB);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,TARGET_PREV_BOMB);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,STOP_TARGETING_SHIP);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,TARGET_NEXT_LIVE_TURRET);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,TARGET_PREV_LIVE_TURRET);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,STOP_TARGETING_SUBSYSTEM);
y_offset += separation;
gameplay_help_blit_control_line_raw(x_offset, y_offset, XSTR( "F5...F12", 143), XSTR( "Select target assigned to that hotkey", 150));
y_offset += separation;
gameplay_help_blit_control_line_raw(x_offset, y_offset, XSTR( "Shift-F5...F12", 151), XSTR( "Add/remove target from that hotkey", 152));
y_offset += separation;
gameplay_help_blit_control_line_raw(x_offset, y_offset, XSTR( "Alt-Shift-F5...F12", 153), XSTR( "Clear that hotkey", 154));
break;
case GP_HELP_MESSAGING:
gameplay_help_set_title(XSTR( "Messaging Keys", 155));
x_offset=X_OFFSET_1;
y_offset=Y_START;
gameplay_help_blit_control_line(x_offset, y_offset,SQUADMSG_MENU);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,REARM_MESSAGE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,ATTACK_MESSAGE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,DISARM_MESSAGE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,DISABLE_MESSAGE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,CAPTURE_MESSAGE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,ENGAGE_MESSAGE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,FORM_MESSAGE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,IGNORE_MESSAGE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,PROTECT_MESSAGE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,COVER_MESSAGE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,WARP_MESSAGE);
y_offset += separation;
gameplay_help_blit_control_line_raw(x_offset, y_offset, XSTR( "F5...F12", 143), XSTR( "send specified order to these target(s)", 156));
break;
case GP_HELP_WEAPON_KEYS:
gameplay_help_set_title(XSTR( "Weapon Keys", 157));
x_offset=X_OFFSET_1;
y_offset=Y_START;
gameplay_help_blit_control_line(x_offset, y_offset,FIRE_PRIMARY);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,FIRE_SECONDARY);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,CYCLE_NEXT_PRIMARY);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,CYCLE_PREV_PRIMARY);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,CYCLE_SECONDARY);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,CYCLE_NUM_MISSLES);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,LAUNCH_COUNTERMEASURE);
break;
case GP_HELP_THROTTLE_AND_ETS_KEYS:
gameplay_help_set_title(XSTR( "Energy Management Keys", 158));
x_offset=X_OFFSET_1;
y_offset=Y_START;
gameplay_help_blit_control_line(x_offset, y_offset,SHIELD_EQUALIZE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,SHIELD_XFER_TOP);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,SHIELD_XFER_BOTTOM);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,SHIELD_XFER_LEFT);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,SHIELD_XFER_RIGHT);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,INCREASE_WEAPON);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,DECREASE_WEAPON);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,INCREASE_SHIELD);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,DECREASE_SHIELD);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,INCREASE_ENGINE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,DECREASE_ENGINE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,ETS_EQUALIZE);
/*
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,XFER_LASER);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,XFER_SHIELD);
*/
break;
case GP_HELP_MISC_KEYS:
gameplay_help_set_title(XSTR( "Miscellaneous Keys", 159));
x_offset=X_OFFSET_1;
y_offset=Y_START;
// ending mission
//
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,END_MISSION);
y_offset += separation;
gameplay_help_blit_control_line_raw(x_offset,y_offset, XSTR( "ESC", 160), XSTR( "invoke abort mission popup", 161));
// time compression
//
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,TIME_SPEED_UP);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,TIME_SLOW_DOWN);
// radar keys
//
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,RADAR_RANGE_CYCLE);
// escort view keys
//
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,ADD_REMOVE_ESCORT);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,ESCORT_CLEAR);
// Pause, Print Screenshot
y_offset += separation;
gameplay_help_blit_control_line_raw(x_offset,y_offset, XSTR( "Pause", 162), XSTR( "pause game", 163));
y_offset += separation;
gameplay_help_blit_control_line_raw(x_offset,y_offset, XSTR( "Print Scrn", 164), XSTR( "take screen shot", 165));
break;
case GP_HELP_VIEW_KEYS:
gameplay_help_set_title(XSTR( "View Keys", 166));
x_offset=X_OFFSET_1;
y_offset=Y_START;
gameplay_help_blit_control_line(x_offset, y_offset,PADLOCK_UP);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,PADLOCK_DOWN);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,PADLOCK_LEFT);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,PADLOCK_RIGHT);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,VIEW_CHASE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,VIEW_EXTERNAL);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,VIEW_EXTERNAL_TOGGLE_CAMERA_LOCK);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,VIEW_SLEW);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,VIEW_DIST_INCREASE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,VIEW_DIST_DECREASE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,VIEW_CENTER);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset,VIEW_OTHER_SHIP);
break;
case GP_HELP_MULTI_KEYS:
{
gameplay_help_set_title(XSTR("Multiplayer Keys", 167));
x_offset = X_OFFSET_1;
y_offset = Y_START;
// ingame messaging
gr_set_color_fast(&Color_bright);
int w;
gr_get_string_size(&w, NULL, XSTR("Ingame messaging keys (tap for text, hold for voice)", 168));
gr_printf_menu((gr_screen.clip_width - w) / 2, y_offset, "%s", XSTR("Ingame messaging keys (tap for text, hold for voice)", 168));
gr_set_color_fast(&Color_normal);
y_offset += separation;
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset, MULTI_MESSAGE_ALL);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset, MULTI_MESSAGE_FRIENDLY);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset, MULTI_MESSAGE_HOSTILE);
y_offset += separation;
gameplay_help_blit_control_line(x_offset, y_offset, MULTI_MESSAGE_TARGET);
break;
}
} // end switch
}
}
// gameplay_help_do_frame() is the function that displays help when acutally playing the game
@@ -763,6 +633,7 @@ void gameplay_help_do_frame(float /*frametime*/)
// make sure game sounds are paused
weapon_pause_sounds();
audiostream_pause_all();
message_pause_all();
k = Ui_window.process() & ~KEY_DEBUGGED;
gameplay_help_process_key(k);
+11
View File
@@ -12,6 +12,17 @@
#ifndef __GAMEPLAY_HELP_H__
#define __GAMEPLAY_HELP_H__
struct gameplay_help_section {
SCP_string title;
SCP_string header;
SCP_vector<SCP_string> key;
SCP_vector<SCP_string> text;
};
extern SCP_vector<gameplay_help_section> Help_text;
SCP_vector<gameplay_help_section> gameplay_help_init_text();
void gameplay_help_init();
void gameplay_help_do_frame(float frametime);
+94 -44
View File
@@ -45,13 +45,15 @@ static bool music_volume_change_listener(float new_val, bool /*initial*/)
return true;
}
static auto MusicVolumeOption = options::OptionBuilder<float>("Audio.Music", "Music", "Volume used for playing music")
.category("Audio")
.default_val(Default_music_volume)
.range(0.0f, 1.0f)
.change_listener(music_volume_change_listener)
.importance(1)
.finish();
static auto MusicVolumeOption __UNUSED = options::OptionBuilder<float>("Audio.Music",
std::pair<const char*, int>{"Music", 1371},
std::pair<const char*, int>{"Volume used for playing music", 1760})
.category("Audio")
.default_val(Default_music_volume)
.range(0.0f, 1.0f)
.change_listener(music_volume_change_listener)
.importance(1)
.finish();
typedef struct tagSNDPATTERN {
int default_next_pattern; // Needed so the next_pattern member can be reset
@@ -257,6 +259,19 @@ SCP_vector<menu_music> Spooled_music;
int Mission_music[NUM_SCORES];
bool event_music_pattern_is_skippable(const SOUNDTRACK_PATTERN_INFO &pattern)
{
// check for blank or "none"
if (pattern.fname[0] == '\0' || !strnicmp(pattern.fname, NOX("none.wav"), 4))
return true;
// no content means this pattern isn't intended to play
if (pattern.num_measures == 0 || pattern.samples_per_measure == 0)
return true;
return false;
}
// -------------------------------------------------------------------------------------------------
// event_music_init()
//
@@ -289,6 +304,51 @@ void event_music_init()
// look for any modular tables
parse_modular_table(NOX("*-mus.tbm"), event_music_parse_musictbl);
// now that we've parsed everything, check the validity
for (auto &soundtrack : Soundtracks)
{
bool all_patterns_valid = true;
// Goober5000 - set the valid flag according to whether we can load all our patterns
// (since someone may be running an enhanced music.tbl without warble_fs1 installed)
for (int i = 0; i < soundtrack.num_patterns; i++)
{
auto filename = soundtrack.patterns[i].fname;
// some patterns aren't played for various legitimate reasons
if (event_music_pattern_is_skippable(soundtrack.patterns[i]))
continue;
// check for negative numbers (zero is allowed)
if (soundtrack.patterns[i].num_measures < 0 || soundtrack.patterns[i].samples_per_measure < 0)
{
Warning(LOCATION, "Soundtrack file %s has a negative 'num_measures' or 'samples_per_measure'; this is not allowed", soundtrack.patterns[i].fname);
all_patterns_valid = false;
break;
}
// check for file with exact extension
// (since event music specifies samples and measures, the audio format is important; so we don't want to assume any format will work)
if (!cf_exists_full(filename, CF_TYPE_MUSIC))
{
#ifndef NDEBUG
// see if the file exists with a different extension
auto res = cf_find_file_location_ext(filename, NUM_AUDIO_EXT, audio_ext_list, CF_TYPE_MUSIC);
if (res.found)
Warning(LOCATION, "Soundtrack file %s was not found with its specified extension, but another file %s exists in the modpack. Please update the extension and adjust audio specifications if necessary.", filename, res.name_ext.c_str());
#endif
Warning(LOCATION, "One or more files in '%s' could not be loaded. The soundtrack will not be used.", soundtrack.name);
all_patterns_valid = false;
break;
}
}
if (all_patterns_valid)
soundtrack.flags |= EMF_VALID;
}
Event_music_inited = TRUE;
Event_music_begun = FALSE;
@@ -410,7 +470,7 @@ void event_music_do_frame()
// start off the music delayed
if ( timestamp_elapsed(Pattern_timer_id) ) {
Pattern_timer_id = TIMESTAMP::invalid();
Pattern_timer_id = TIMESTAMP::never();
Event_music_begun = TRUE;
if ( Current_pattern != -1 && Patterns[Current_pattern].handle >= 0) {
//WMC - removed in favor of if
@@ -544,14 +604,14 @@ void event_music_level_start(int force_soundtrack)
if (force_soundtrack != -1)
Current_soundtrack_num = force_soundtrack;
// Check that soundtrack index is in range, except that < 0 means no soundtrack
if (Current_soundtrack_num < 0)
{
Pattern_timer_id = TIMESTAMP::never(); // update the timestamp as if a soundtrack did start
return;
}
Assert(Current_soundtrack_num >= 0 && Current_soundtrack_num < (int)Soundtracks.size());
if (Current_soundtrack_num < 0 || Current_soundtrack_num > (int)Soundtracks.size())
Assert(Current_soundtrack_num < (int)Soundtracks.size());
if (Current_soundtrack_num >= (int)Soundtracks.size())
return;
strack = &Soundtracks[Current_soundtrack_num];
@@ -564,7 +624,7 @@ void event_music_level_start(int force_soundtrack)
// tracks because their patterns weren't -1
for (i = 0; i < MAX_PATTERNS; i++)
{
if (!strnicmp(strack->patterns[i].fname, NOX("none.wav"), 4))
if (event_music_pattern_is_skippable(strack->patterns[i]))
{
Patterns[i].handle = -1;
continue;
@@ -644,7 +704,9 @@ void event_music_first_pattern()
// if we really are initializing the level
if (Missiontime == 0) {
Pattern_timer_id = TIMESTAMP::invalid(); // don't let this start quite yet; see event_music_set_start_delay()
} else {
}
// don't step on a timestamp in progress; only set it if it has elapsed at least once already
else if (Pattern_timer_id.isNever()) {
Pattern_timer_id = TIMESTAMP::immediate(); // start immediately
}
@@ -1166,9 +1228,6 @@ void parse_soundtrack()
int i, strack_idx = -1;
bool nocreate = false;
//Start parsing soundtrack
//required_string("#Soundtrack Start");
//Get the name, and do we have this track already?
required_string("$SoundTrack Name:");
stuff_string(namebuf, F_NAME, NAME_LENGTH);
@@ -1284,23 +1343,6 @@ void parse_soundtrack()
//We're done here.
required_string("#SoundTrack End");
// Goober5000 - set the valid flag according to whether we can load all our patterns
// (since someone may be running an enhanced music.tbl without warble_fs1 installed)
for (i = 0; i < Soundtracks[strack_idx].num_patterns; i++)
{
// check for "none"
if (!strlen(Soundtracks[strack_idx].patterns[i].fname) || !strnicmp(Soundtracks[strack_idx].patterns[i].fname, "none", 4))
continue;
// check for file
if (!cf_exists_full_ext(Soundtracks[strack_idx].patterns[i].fname, CF_TYPE_MUSIC, NUM_AUDIO_EXT, audio_ext_list))
return;
}
// made it here okay, so it's valid
Soundtracks[strack_idx].flags |= EMF_VALID;
}
void parse_menumusic()
@@ -1579,7 +1621,7 @@ int hostile_ships_present()
// NOTE: callers to this function are advised to allocate a 256 byte buffer
void event_music_get_info(char *outbuf)
{
if ( Event_music_enabled == FALSE || Event_music_level_inited == FALSE || Current_pattern == -1 ) {
if ( Event_music_enabled == FALSE || Event_music_level_inited == FALSE || Current_soundtrack_num < 0 || Current_pattern < 0 ) {
strcpy(outbuf,XSTR( "Event music is not playing", 213));
}
else {
@@ -1598,7 +1640,7 @@ int event_music_next_soundtrack(int delta)
{
int new_soundtrack;
if ( Event_music_enabled == FALSE || Event_music_level_inited == FALSE ) {
if ( Event_music_enabled == FALSE || Event_music_level_inited == FALSE || Soundtracks.empty() ) {
return -1;
}
@@ -1631,7 +1673,7 @@ void event_sexp_change_soundtrack(const char *name)
}
event_music_level_close();
Current_soundtrack_num = -1;
Current_soundtrack_num = -1;
event_music_level_start(new_soundtrack);
}
@@ -1642,7 +1684,7 @@ void event_sexp_change_soundtrack(const char *name)
// NOTE: callers to this function are advised to allocate a NAME_LENGTH buffer
void event_music_get_soundtrack_name(char *outbuf)
{
if ( Event_music_enabled == FALSE || Event_music_level_inited == FALSE ) {
if ( Event_music_enabled == FALSE || Event_music_level_inited == FALSE || Current_soundtrack_num < 0 ) {
strcpy(outbuf, XSTR( "Event music is not playing", 213));
}
else {
@@ -1653,11 +1695,15 @@ void event_music_get_soundtrack_name(char *outbuf)
// set the current soundtrack based on name
void event_music_set_soundtrack(const char *name)
{
Current_soundtrack_num = event_music_get_soundtrack_index(name);
int index = event_music_get_soundtrack_index(name);
if ( Current_soundtrack_num == -1 ) {
if (index >= 0 && Soundtracks[index].flags & EMF_VALID)
Current_soundtrack_num = index;
else
Current_soundtrack_num = -1;
if (Current_soundtrack_num == -1)
mprintf(("Current soundtrack set to -1 in event_music_set_soundtrack\n"));
}
}
int event_music_get_soundtrack_index(const char *name)
@@ -1674,7 +1720,7 @@ int event_music_get_soundtrack_index(const char *name)
int event_music_get_spooled_music_index(const char *name)
{
// find the correct index for the event music
// find the correct index for the spooled music
for ( int i = 0; i < (int)Spooled_music.size(); i++ ) {
if ( !stricmp(name, Spooled_music[i].name) ) {
return i;
@@ -1694,8 +1740,12 @@ void event_music_set_score(int score_index, const char *name)
{
Assert(score_index < NUM_SCORES);
// find the correct index for the event music
Mission_music[score_index] = event_music_get_spooled_music_index(name);
int index = event_music_get_spooled_music_index(name);
if (index >= 0 && Spooled_music[index].flags & SMF_VALID)
Mission_music[score_index] = index;
else
Mission_music[score_index] = -1;
}
// reset what sort of music is to be used for this mission
+6 -5
View File
@@ -74,15 +74,16 @@ extern SCP_vector<menu_music> Spooled_music;
// event music soundtrack storage
typedef struct tagSOUNDTRACK_PATTERN_INFO {
char fname[MAX_FILENAME_LEN];
float num_measures;
int samples_per_measure;
} SOUNDTRACK_PATTERN_INFO;
typedef struct tagSOUNDTRACK_INFO {
int flags;
int num_patterns;
char name[NAME_LENGTH];
struct {
char fname[MAX_FILENAME_LEN];
float num_measures;
int samples_per_measure;
} patterns[MAX_PATTERNS];
SOUNDTRACK_PATTERN_INFO patterns[MAX_PATTERNS];
} SOUNDTRACK_INFO;
// Goober5000 - event music flags
Loaded 100 of 690 files, more files were not shown because too many files have changed in this diff. Show more