Compare commits

..
Author SHA1 Message Date
SirKnightly 9f5810732a Automated build commit 2019-08-28 18:04:20 -05:00
Cliff Gordon f4bfec5029 Merge pull request #2089 from asarium/build/fixTravisGitHubToken
Update Travis GitHub token
2019-08-28 12:45:13 -05:00
asarium c18f775962 Update Travis GitHub token
The token used by Travis was also out of date so here is a new one. This
is a token created by the SirKnightly user.
2019-08-28 18:14:49 +02:00
Goober5000 608dcb6b44 Merge pull request #2088 from asarium/build/fixAppveyorGitHubToken
Update GitHub token used for AppVeyor release building
2019-08-26 15:10:35 -04:00
asarium b4b23e266b Update GitHub token used for AppVeyor release building
For some reason the old token was removed from the AppVeyor GitHub
account which made the release build fail.
2019-08-26 17:58:12 +02:00
m!m 65e2aa88b3 Merge pull request #2059 from asarium/build/travisWindowsAlways
Do not allow failure for Windows Travis builds anymore
2019-08-24 13:11:29 +02:00
asarium fe0c6a629a Do not allow failure for Windows Travis builds anymore 2019-08-22 17:36:28 +02:00
MageKing17 730c62af81 Merge pull request #2085 from Goober5000/issue_2081_actual_fix
Issue 2081 actual fix
2019-08-19 23:52:40 -07:00
Goober5000 13d4ebaceb leave a 'node' variable pointing to the beginning of the sexp node list so that we can manipulate it later 2019-08-19 23:35:55 -04:00
Goober5000 ed6a780898 Revert "fix for issue #2081" 2019-08-19 23:19:30 -04:00
Goober5000 f0b9929cd3 Merge pull request #2083 from Goober5000/eval_nums_redo
fix for issue #2081
2019-08-19 18:13:45 -04:00
Goober5000 f315caad95 fix a bug, and use Error instead of Warning since this indicates a programming error 2019-08-19 16:29:49 -04:00
Goober5000 b5a47e651f fix for issue #2081
This re-implements the eval_nums function to use C varargs, instead of C++11 template parameter packs.  This is necessary because Visual Studio has a bug where template parameter packs corrupt heap memory somehow.
2019-08-19 16:19:53 -04:00
m!m d49299225c Merge pull request #2080 from tcrayford/de_fault_is_in_de_spelling
fix typo: defualt->default
2019-08-11 14:33:32 +02:00
Tom Crayford 3b0bb79d79 fix typo: defualt->default 2019-08-11 11:09:13 +01:00
Goober5000 daacdc0035 Merge pull request #2078 from FSCyborg/Fix-#1433-
Fix 1433 Take two
2019-08-10 22:41:03 -04:00
FSCyborg 39df9ef90e Fix 1433 Take two
Have FSO check for subspace and start the loop up again when subspace is being used.
2019-08-09 22:21:33 -04:00
Goober5000 fc080cccbd Merge pull request #2075 from FSCyborg/fix#1916
"Fix" 1916
2019-07-30 22:59:47 -04:00
FSCyborg 0c07ad9d71 "Fix" 1916
Adds a check to see if the subsystem is the same before restting aspect lock.

More of an enhancement to expected behavior than a bugfix.
2019-07-30 17:58:52 -04:00
Goober5000 7d329bbbc6 Merge pull request #2074 from FSCyborg/fix#1974
Fix#1974
2019-07-30 12:33:40 -04:00
m!m 17a449529f Merge pull request #2060 from Mithi83/bug/1987-lab-thrusters
fix bug #1987: thruster rendering in lab
2019-07-30 11:59:36 +02:00
FSCyborg 73f0addc42 Fix#1974
"Cloning" failure was actually being caused by the pilot verification function resetting all pilot info and then not loading controls from the file to replace them.

The Control_Config array would all be set to -1 and then would get written into the file the next time the player was saved, making it seem that the controls were not being copied.

The original and current code would reset controls to defaults when a pilot was created.  And it would just let the old controls remain in case of a clone. The above problem would occur just as you hit accept on the bottom of the baracks screen.
2019-07-29 21:25:50 -04:00
Goober5000 0ba1583d90 Merge pull request #2035 from Goober5000/patch_nan_handling
when evaluating numeric SEXPs, handle NaN properly
2019-07-28 01:03:11 -04:00
Goober5000 2436697f2c Merge pull request #2071 from FSCyborg/Fix#2067
Fix#2067
2019-07-27 22:51:24 -04:00
FSCyborg 0e10100aad Fix#2067
Original behavior in Fred was accidentally removed when upgrading the FSO mission parser to keep it from crashing FSO from a bad sexp.  But returning false is only necessary in FSO since in FRED, we can fix the error once we know about it.
2019-07-27 21:21:33 -04:00
Goober5000 60bcdefac0 remove unneeded header 2019-07-25 15:14:45 -04:00
Goober5000 5d8ac3cc11 bring up to date with another eval_num 2019-07-25 15:14:45 -04:00
Goober5000 e0bc2f188b help the compiler out a bit, per Gasbow's suggestion 2019-07-25 15:14:45 -04:00
Goober5000 d13bbdd534 move eval-num derivatives out of the header file 2019-07-25 15:14:45 -04:00
Goober5000 44b09d137f let's try a function pointer instead of std::function 2019-07-25 15:14:45 -04:00
Goober5000 4439edcb4d more complaints 2019-07-25 15:14:45 -04:00
Goober5000 a9ddeda40e edits and clang-tidy 2019-07-25 15:14:45 -04:00
Goober5000 d606e4d952 complaints and stuff 2019-07-25 15:14:44 -04:00
Goober5000 2fa8a0bd84 that const crept back in again 2019-07-25 15:14:44 -04:00
Goober5000 f9d178d46b additional small fixes 2019-07-25 15:14:44 -04:00
Goober5000 989235936e when evaluating numeric SEXPs, handle NaN properly
NaN should propagate through the SEXP tree, but not all SEXPs do this properly.  The problem was made worse after I introducted `eval_num()` which silently ignored NaN values.  This commit adds new boolean arguments to `eval_num()` to flag NaN results, and changes all calls of `eval_num()` to properly handle the new arguments.  Additionally, this adds `eval_nums()` and `eval_array()` functions to more smoothly handle cases where many numbers appear in a row.
2019-07-25 15:14:44 -04:00
Goober5000 6df9c73a4c Merge pull request #2063 from Goober5000/modify_set_object_position
Allow positioning sexps to work on ships yet to arrive
2019-07-25 14:13:38 -04:00
Goober5000 d794eb6e77 Merge pull request #2070 from FSCyborg/Coverity#1093387
Coverity 1093387
2019-07-20 20:31:01 -04:00
Goober5000 e5c06c9554 Merge pull request #2069 from FSCyborg/Cyborg-Coverity-Fixes
Coverity 1093370
2019-07-20 18:14:38 -04:00
FSCyborg bc00b79922 Coverity 1093387
We already verify that the variable will not be null in the previous code block.
2019-07-20 16:12:45 -04:00
Goober5000 e1e86667b3 Merge pull request #2068 from FSCyborg/Fix#1791
Fix#1791 ChangeIFF & Laser_Flag
2019-07-20 01:05:33 -04:00
FSCyborg 881f787ac8 Fix#1791 ChangeIFF & Laser_Flag
Extremely rare bug caused by use of multiple protect from weapon flags. One of the Ai-Turret functions was setting only one of the flags because "else if" was typed instead of "if".
2019-07-19 21:21:58 -04:00
FSCyborg 88d5bed064 Coverity 1093370
Copy paste error, I can think of no reason to compare Max y and Min z
2019-07-19 09:11:14 -04:00
m!m d9b1659efc Merge pull request #2064 from asarium/fix/scriptingDeprecation
Move deprecation of createParticle to the next version
2019-07-15 19:46:50 +02:00
Goober5000 f6408113f2 fix stuffing of vector pointer 2019-07-15 13:15:21 -04:00
asarium 6075c17255 Move deprecation of createParticle to the next version
This should fix a problem with the MVPs.
2019-07-15 17:54:41 +02:00
Goober5000 da9f71dac0 might as well do set-object-facing and set-object-facing-object as well 2019-07-14 23:26:18 -04:00
Goober5000 03f1344794 might as well do set-object-orientation too 2019-07-14 21:24:22 -04:00
Goober5000 59e9d7cb0c add missing break to case 2019-07-14 21:20:33 -04:00
Goober5000 910595880a Allow set-object-position to work on ships yet to arrive
This adds `set-object-position` functionality for ships and wingmen still on the arrival list.  Requested by JSRNerdo.
2019-07-13 14:24:06 -04:00
MageKing17 9f07e43455 Merge pull request #2020 from asarium/feature/scriptingDeprecation
Add deprecation feature for the scripting API
2019-07-11 15:08:45 -07:00
m!m 7b8c156980 Merge pull request #2022 from asarium/opengl/smaa
Add SMAA post processing step
2019-07-11 18:02:47 +02:00
Thomas Jansen f8c11ccd2e fix bug #1987: thruster rendering in lab
Lab_selected_index must remain unchanged until labviewer_change_model is
called. There the variable is used to determine if a new ship must be
created and updated afterwards.
2019-07-07 08:36:55 +02:00
Goober5000 7e36dc8afe Merge pull request #2058 from FSCyborg/master
Coverity 1093382
2019-07-05 12:25:53 -04:00
FSCyborg b1ad89a9fa Update chttpget.cpp 2019-07-04 10:14:07 -04:00
FSCyborg 4d9b1a7674 Update chttpget.cpp 2019-07-03 15:03:34 -04:00
FSCyborg 72f3871b7b Update chttpget.cpp 2019-07-03 10:14:24 -04:00
FSCyborg 7906ff460a Coverity 1093382
Coverity spotted this dead code.  Looks like the original coder forgot that they had checked for !p already or was a case of mindless copy-pasting code..

Because of
pcode = strchr(p,' ')+1;
it looks like it really is safe to remove.
2019-07-02 23:18:13 -04:00
asarium 1eb1923751 Add SMAA 2019-06-30 13:28:05 +02:00
asarium 6d1931bf99 Add function for drawing full screen using oversized triangles
This replaces the current instances where two triangles are used for
drawing a full screen quad.
2019-06-30 13:08:45 +02:00
asarium f75cb1edd3 Add deprecation feature for the scripting API
This allows to mark certain functions or virtvars to be declared as
"deprecated" starting with a specific engine version. What this means is
that a special message will be added to the documentation stating since
when the function is deprecated and can contain an optional message. The
actual enforcement of the deprecation depends on the target version of
the mod so that we can stay backwards compatible.

If the mod supports the version since when the function is deprecated,
it will not be added to the Lua state which means that it doesn't exist
for the calling script. If the targetted version is before the stated
version, the function will still be added to the Lua state.

As the first function to use this feature, I have deprecated
createParticle in the testing library and moved it to the graphics
library with a new name reflecting that it creates a persistent
particle. I also added the corresponding function for adding a
non-persistent particle.
2019-06-30 11:31:32 +02:00
Goober5000 48586bc857 Merge pull request #2055 from wookieejedi/fix_weapon_icon_override
Bug fix: adds missing conditional when using weapon icons and 3D weapon selection
2019-06-28 18:29:07 -04:00
Goober5000 3adb861640 Merge pull request #2057 from wookieejedi/fix_blownoff_bug
Fix blown_off bug for good
2019-06-28 18:17:34 -04:00
wookieejedi 7b1f407c22 Fix blown_off bug for good
Thanks for @SamuelCho for telling me what to put to fix this bug for good. This PR fixes #2046 (for good it seems!).
2019-06-28 15:33:29 -04:00
Goober5000 ed5b4b9b5a Merge pull request #2054 from Goober5000/itld_bugfix
properly indicate that player ships have departed at the end of a mission
2019-06-27 15:21:09 -04:00
niffiwan b63ddf08bb Merge pull request #2056 from SamuelCho/subsys_destroyed_fix
Make sure various model rendering/collision code reference submodel instances instead of the prototype data
2019-06-27 20:39:19 +10:00
SamuelCho 816d8e5415 Make sure various model rendering/collision code reference submodel instances instead of the prototype data. 2019-06-25 22:33:52 -07:00
Goober5000 e7e43e9466 Merge pull request #2044 from niffiwan/fix/capitalplus_vs_shields
Fix AI selection of capital+ weps vs shields
2019-06-25 22:19:49 -04:00
wookieejedi 48e630dfd1 Add () to fix travis error 2019-06-25 17:17:02 -04:00
wookieejedi 00f2ddc8da Bug fix: adds missing conditional when using custom icons and 3D weapon selection
Previously if the 3D_weapon flag was used it would always create a weapon icon and overrride any pre-existing icons the modder would specify. This PR fixes that by adding an extra set of conditionals, which specify if a weapon has an icon file name then it should be used, and if the weapon does not have an `$Anim:` but does have a model then that model should be used if the 3D_weapon flag is enabled.
2019-06-25 16:20:13 -04:00
Goober5000 c6d93275c2 address clang complaint 2019-06-24 13:03:38 -04:00
Goober5000 e2ce0bea9b tweak comment 2019-06-24 02:13:19 -04:00
Goober5000 a98fd2cb54 use the new 'mission_check_ship_yet_to_arrive' function when appropriate 2019-06-24 02:11:35 -04:00
Goober5000 5444e81fab add new function for properly evaluating ship arrivals 2019-06-24 01:28:07 -04:00
Goober5000 83276a355d if ship is departing to jump node, add that to the script hook 2019-06-23 16:05:36 -04:00
m!m 98606b37e4 Merge pull request #2053 from wookieejedi/arc_color-options
Adds Table Option to Modify Arc Colors
2019-06-23 09:17:00 +02:00
wookieejedi c4a7e9694f Fix error message vars 2019-06-22 20:50:29 -04:00
wookieejedi 2db1758ec2 Use stuff_int_list
Incorporate m!m feedback
2019-06-22 17:59:59 -04:00
wookieejedi cff070dc07 Update to using tuples and error checks
Incorporates m!m's feedback.
2019-06-22 16:07:55 -04:00
wookieejedi 7b3ad77f36 Adds Table Option to Modify Arc Colors
This PR adds a table entry that allows modders to specify the RGBI values for the damage and emp arc colors (which were previosuly hardcoded).

This option adds the table entry to `Game_settings.tbl` under `#Graphic Settings` with the lines:
```
$EMP Arc Color:
	+Primary Color Option 1: rgb
	+Primary Color Option 2: rgb
	+Secondary Color Option 1: rgb

$Damage Arc Color:
	+Primary Color Option 1: rgb
	+Primary Color Option 2: rgb
	+Secondary Color Option 1: rgb
```
2019-06-21 14:58:05 -04:00
Goober5000 d67e79a44b Merge pull request #2042 from Goober5000/nested_subsys_destruction
properly handle destruction/repair of subsystem tree
2019-06-06 01:48:03 -04:00
niffiwan 977190b358 Address review feedback
Make wip an actual pointer!
Rename some vars to better reflect their usage (vs previous copy-pasta)
2019-06-04 18:39:21 +10:00
m!m ba3237604e Merge pull request #2048 from wookieejedi/per_shipclass_help_threshold
Add per ship class options for when AI sends "Help Me" message
2019-05-29 18:44:46 +02:00
wookieejedi d55a6632ca and one more float to specify 2019-05-24 23:58:52 -04:00
wookieejedi 680cb580cd specify rest of floats 2019-05-24 23:49:19 -04:00
wookieejedi 2f74940f6a specify float 2019-05-24 23:00:55 -04:00
wookieejedi 72d876bd4b Switch to const and add error checks
Incorporatea ll of m!m's feedback.
2019-05-23 15:35:59 -04:00
wookieejedi e22398bec8 Add per ship class options for when AI sends "Help Me" message
This PR allows modders to set, on a per-ship class basis, the fields for what hull and shiled integrity the AI wingmen send the "Help" message at. One good use case is when ships have low hitpoints, thus now the modder can set AI can call for help sooner then at simply 30% hull.
2019-05-23 13:19:30 -04:00
Goober5000 11661db6ab oops -- get distance before setting it to 9999999 2019-05-17 14:31:16 -04:00
Goober5000 6164004df3 repair parent submodel if it needs repairing 2019-05-17 14:31:16 -04:00
Goober5000 505aa3cdd1 organize subsystem modification sexps to all call one function 2019-05-17 14:31:16 -04:00
Goober5000 cfeb8da3d3 don't reuse subsystems that are skipped 2019-05-17 14:31:15 -04:00
Goober5000 ec7945276a handle child subobjects being destroyed 2019-05-17 14:31:15 -04:00
Goober5000 2bf19afb94 make sure all instances of ship_recalc_subsys_strength happen after do_subobj_destroyed_stuff 2019-05-17 14:31:15 -04:00
Goober5000 34b38f63fa remove unneeded function 2019-05-17 14:31:15 -04:00
niffiwan 4c7470fbf2 Fix AI selection of capital+ weps vs shields
Current the AI always selects capital+ weapons vs big/huge ships. This
makes the AI take shields into accounts, and not use the weapon if
either the shields are still up, or the weapon isn't good vs shields.

I don't greatly like the magic number 1.33 to determine if a weapon is
good vs shields, I'm happy to take alternative suggestions. I have
checked DE, WoD & BP tables and I don't think this change will affect
any of them (picked them because their either use capital+ weapons or
have shielded capships)

There's one DE weapon that the AI won't select anymore while shields
are up; however its fluff says it's bad vs shields and suggests a
paired shield-breaker so think it should be OK.
2019-05-12 15:50:13 +10:00
85 changed files with 20450 additions and 2352 deletions

No files matched your search

+1 -11
View File
@@ -43,7 +43,7 @@ env:
deploy:
- provider: releases
api_key:
secure: "Wdt4Ccefo7a0ZDjEJQJgpghh7n72FtNJuKSAPUvoz4gtEX6Ct9J8yJI1t9V3jE3CTbbLJ21/Q6eZRDfT7UfNJe5DdepoJsP9DeFhKMWqQCq+AChqQWlm0KeZAffJoJreL8vXYhnRYcLT9ceZHEH6AqwN9TPV+xJziGPISAkYNZ8="
secure: "q619+eQTe7lv8UVphK4OIzU8Jw84KBbVkuprN2sWIubRcV3IbZr2+WahJoUMt+nyhiy3YjDYtstO2ZgkxupwnZgwGUBVIiD1c4SPuyy+HTjNMOtiVsEUHT2hf+xPAemWpTlK5HcwhMmHAOh6rt6dEj57QOg0gcmGiwD/tCbEriA="
skip_cleanup: true
file_glob: true
file: "/tmp/builds/*"
@@ -150,16 +150,6 @@ matrix:
env: CONFIGURATION="Release" CMAKE_TOOLSET=v141_xp CMAKE_GENERATOR="Visual Studio 15 2017"
- os: windows
env: CONFIGURATION="Release" CMAKE_TOOLSET="" CMAKE_GENERATOR="Ninja"
# As long as Windows is still experimental on Travis CI, allow failures
allow_failures:
- os: windows
env: CONFIGURATION="Debug" CMAKE_TOOLSET=v141_xp CMAKE_GENERATOR="Visual Studio 15 2017"
- os: windows
env: CONFIGURATION="Debug" CMAKE_TOOLSET="" CMAKE_GENERATOR="Ninja"
- os: windows
env: CONFIGURATION="Release" CMAKE_TOOLSET=v141_xp CMAKE_GENERATOR="Visual Studio 15 2017"
- os: windows
env: CONFIGURATION="Release" CMAKE_TOOLSET="" CMAKE_GENERATOR="Ninja"
fast_finish: true
before_install:
+1 -1
View File
@@ -24,7 +24,7 @@ test_script:
deploy:
- provider: GitHub
auth_token:
secure: 3kV4efHXwRnfXzmJPRAOs8D7+MhwXUXYeayI/P5y114L09kJa6b6L70beXdW7yYr
secure: h55Scpy+3vmo1Yb7WlSIGA4d9DRnsbzUYc2LYsQdByQHZHbqrqjBpicH0D2FFLEO
on:
ReleaseBuild: true # deploy on release push only
+10 -10
View File
@@ -10,8 +10,8 @@ include(CheckSymbolExists)
include(CheckCXXSymbolExists)
include(CheckTypeSize)
CHECK_INCLUDE_FILE("execinfo.h" HAVE_EXECINFO_H)
CHECK_INCLUDE_FILE_CXX("cxxabi.h" HAVE_CXXAPI_H)
CHECK_INCLUDE_FILE("execinfo.h" SCP_HAVE_EXECINFO_H)
CHECK_INCLUDE_FILE_CXX("cxxabi.h" SCP_HAVE_CXXAPI_H)
CHECK_TYPE_SIZE("max_align_t" MAX_ALIGN_T)
@@ -31,18 +31,18 @@ CHECK_TYPE_SIZE("U'b'" UNICODE_CHAR_LITERAL LANGUAGE CXX)
set(CMAKE_REQUIRED_FLAGS)
CHECK_FUNCTION_EXISTS(strcasecmp HAVE_STRCASECMP)
CHECK_FUNCTION_EXISTS(strncasecmp HAVE_STRNCASECMP)
CHECK_FUNCTION_EXISTS(strcasecmp SCP_HAVE_STRCASECMP)
CHECK_FUNCTION_EXISTS(strncasecmp SCP_HAVE_STRNCASECMP)
CHECK_FUNCTION_EXISTS(_stricmp HAVE__STRICMP)
CHECK_FUNCTION_EXISTS(_strnicmp HAVE__STRNICMP)
CHECK_FUNCTION_EXISTS(_stricmp SCP_HAVE__STRICMP)
CHECK_FUNCTION_EXISTS(_strnicmp SCP_HAVE__STRNICMP)
CHECK_FUNCTION_EXISTS(strlwr HAVE_STRLWR)
CHECK_FUNCTION_EXISTS(strlwr SCP_HAVE_STRLWR)
CHECK_INCLUDE_FILE("strings.h" HAVE_STRINGS_H)
CHECK_INCLUDE_FILE("strings.h" SCP_HAVE_STRINGS_H)
check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF)
check_symbol_exists(_snprintf "stdio.h" HAVE__SNPRINTF)
check_symbol_exists(snprintf "stdio.h" SCP_HAVE_SNPRINTF)
check_symbol_exists(_snprintf "stdio.h" SCP_HAVE__SNPRINTF)
set(PLATFORM_CHECK_HEADER "${GENERATED_SOURCE_DIR}/platformChecks.h")
CONFIGURE_FILE(${CMAKE_CURRENT_LIST_DIR}/platformChecks.h.in "${PLATFORM_CHECK_HEADER}")
+14 -14
View File
@@ -3,29 +3,29 @@
#define __PLATFORM_CHECKS_H__
#pragma once
#cmakedefine HAVE_EXECINFO_H
#cmakedefine HAVE_CXXAPI_H
#cmakedefine HAVE_MAX_ALIGN_T
#cmakedefine HAVE_STD_MAX_ALIGN_T
#cmakedefine SCP_HAVE_EXECINFO_H
#cmakedefine SCP_HAVE_CXXAPI_H
#cmakedefine SCP_HAVE_MAX_ALIGN_T
#cmakedefine SCP_HAVE_STD_MAX_ALIGN_T
#cmakedefine HAVE_STD_IS_TRIVIALLY_COPYABLE
#cmakedefine HAVE_STD_IS_TRIVIALLY_COPYABLE_ARRAY
#cmakedefine SCP_HAVE_STD_IS_TRIVIALLY_COPYABLE
#cmakedefine SCP_HAVE_STD_IS_TRIVIALLY_COPYABLE_ARRAY
#cmakedefine01 IS_64BIT
#cmakedefine01 HAVE_STRCASECMP
#cmakedefine01 HAVE_STRNCASECMP
#cmakedefine01 HAVE__STRICMP
#cmakedefine01 HAVE__STRNICMP
#cmakedefine01 SCP_HAVE_STRCASECMP
#cmakedefine01 SCP_HAVE_STRNCASECMP
#cmakedefine01 SCP_HAVE__STRICMP
#cmakedefine01 SCP_HAVE__STRNICMP
#cmakedefine01 HAVE_STRLWR
#cmakedefine01 SCP_HAVE_STRLWR
#cmakedefine01 HAVE_STRINGS_H
#cmakedefine01 SCP_HAVE_STRINGS_H
#cmakedefine01 HAVE_CHAR32_T
#cmakedefine01 HAVE_UNICODE_CHAR_LITERAL
#cmakedefine01 HAVE_SNPRINTF
#cmakedefine01 HAVE__SNPRINTF
#cmakedefine01 SCP_HAVE_SNPRINTF
#cmakedefine01 SCP_HAVE__SNPRINTF
#endif // __PLATFORM_CHECKS_H__
+64 -64
View File
@@ -1314,7 +1314,9 @@ ship_subsys *set_targeted_subsys(ai_info *aip, ship_subsys *new_subsys, int pare
}
if ( aip == Player_ai ) {
hud_lock_reset(0.5f);
if (aip->last_subsys_target != aip->targeted_subsys) {
hud_lock_reset(0.5f);
}
}
} else {
@@ -5318,9 +5320,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, Weapon::Info_Flag
{
if (swp->current_primary_bank >= 0)
{
int bank_index;
bank_index = swp->current_primary_bank;
int bank_index = swp->current_primary_bank;
if (Weapon_info[swp->primary_bank_weapons[bank_index]].wi_flags[Weapon::Info_Flags::Puncture])
{
@@ -5329,11 +5329,9 @@ int ai_select_primary_weapon(object *objp, object *other_objp, Weapon::Info_Flag
}
for (int i=0; i<swp->num_primary_banks; i++)
{
int weapon_info_index;
int weapon_info_index = swp->primary_bank_weapons[i];
weapon_info_index = swp->primary_bank_weapons[i];
if (weapon_info_index > -1)
if (weapon_info_index >= 0)
{
if (Weapon_info[weapon_info_index].wi_flags[Weapon::Info_Flags::Puncture])
{
@@ -5344,44 +5342,51 @@ int ai_select_primary_weapon(object *objp, object *other_objp, Weapon::Info_Flag
}
}
if ( (other_objp->type == OBJ_SHIP) && (Ship_info[Ships[other_objp->instance].ship_info_index].is_big_or_huge() ) )
auto other_is_ship = (other_objp->type == OBJ_SHIP);
float enemy_remaining_shield = get_shield_pct(other_objp);
if ( other_is_ship && (Ship_info[Ships[other_objp->instance].ship_info_index].is_big_or_huge() ) )
{
//Check if we have a capital+ weapon on board
for (int i = 0; i < swp->num_primary_banks; i++)
{
if (swp->primary_bank_weapons[i] > -1) // Make sure there is a weapon in the bank
if (swp->primary_bank_weapons[i] >= 0) // Make sure there is a weapon in the bank
{
if (Weapon_info[swp->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Capital_plus])
auto wip = &Weapon_info[swp->primary_bank_weapons[i]];
if (wip->wi_flags[Weapon::Info_Flags::Capital_plus])
{
swp->current_primary_bank = i;
nprintf(("AI", "%i: Ship %s selecting weapon %s (capital+) vs target %s\n", Framecount, Ships[objp->instance].ship_name, Weapon_info[swp->primary_bank_weapons[i]].name, Ships[other_objp->instance].ship_name));
return i;
// handle shielded big/huge ships (non FS-verse)
// only pick capital+ if the target has no shields; or the weapon is an ok shield-breaker anyway
if (enemy_remaining_shield <= 0.05f || (wip->shield_factor * 1.33f > wip->armor_factor))
{
swp->current_primary_bank = i;
nprintf(("AI", "%i: Ship %s selecting weapon %s (capital+) vs target %s\n", Framecount, Ships[objp->instance].ship_name, wip->name, Ships[other_objp->instance].ship_name));
return i;
}
}
}
}
}
float enemy_remaining_shield = get_shield_pct(other_objp);
// Is the target shielded by say only 5%?
if (enemy_remaining_shield <= 0.05f)
{
// Then it is safe to start using a heavy hull damage weapon such as the maxim
int i;
float i_hullfactor_prev = 0; // Previous weapon bank hull factor (this is the safe way to do it)
int i_hullfactor_prev_bank = -1; // Bank which gave us this hull factor
// Find the weapon with the highest hull * damage / fire delay factor
for (i = 0; i < swp->num_primary_banks; i++)
for (int i = 0; i < swp->num_primary_banks; i++)
{
if (swp->primary_bank_weapons[i] > -1) // Make sure there is a weapon in the bank
if (swp->primary_bank_weapons[i] >= 0) // Make sure there is a weapon in the bank
{
if ((((Weapon_info[swp->primary_bank_weapons[i]].armor_factor) * (Weapon_info[swp->primary_bank_weapons[i]].damage)) / Weapon_info[swp->primary_bank_weapons[i]].fire_wait) > i_hullfactor_prev)
auto wip = &Weapon_info[swp->primary_bank_weapons[i]];
if ((((wip->armor_factor) * (wip->damage)) / wip->fire_wait) > i_hullfactor_prev)
{
if ( !(Weapon_info[swp->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Capital_plus]) )
if ( !(wip->wi_flags[Weapon::Info_Flags::Capital_plus]) )
{
// This weapon is the new candidate
i_hullfactor_prev = ( ((Weapon_info[swp->primary_bank_weapons[i]].armor_factor) * (Weapon_info[swp->primary_bank_weapons[i]].damage)) / Weapon_info[swp->primary_bank_weapons[i]].fire_wait );
i_hullfactor_prev = ( ((wip->armor_factor) * (wip->damage)) / wip->fire_wait );
i_hullfactor_prev_bank = i;
}
}
@@ -5392,7 +5397,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, Weapon::Info_Flag
i_hullfactor_prev_bank = 0; // Just switch to the first one
}
swp->current_primary_bank = i_hullfactor_prev_bank; // Select the best weapon
nprintf(("AI", "%i: Ship %s selecting weapon %s (no shields) vs target %s\n", Framecount, Ships[objp->instance].ship_name, Weapon_info[swp->primary_bank_weapons[i_hullfactor_prev_bank]].name, (other_objp->type == OBJ_SHIP ? Ships[other_objp->instance].ship_name : "non-ship") ));
nprintf(("AI", "%i: Ship %s selecting weapon %s (no shields) vs target %s\n", Framecount, shipp->ship_name, Weapon_info[swp->primary_bank_weapons[i_hullfactor_prev_bank]].name, (other_is_ship ? Ships[other_objp->instance].ship_name : "non-ship") ));
return i_hullfactor_prev_bank; // Return
}
@@ -5401,28 +5406,23 @@ int ai_select_primary_weapon(object *objp, object *other_objp, Weapon::Info_Flag
{
if (swp->current_primary_bank >= 0)
{
int bank_index;
auto wip = &Weapon_info[swp->primary_bank_weapons[swp->current_primary_bank]];
bank_index = swp->current_primary_bank;
if ((Weapon_info[swp->primary_bank_weapons[bank_index]].wi_flags[Weapon::Info_Flags::Pierce_shields]) && !(Weapon_info[swp->primary_bank_weapons[bank_index]].wi_flags[Weapon::Info_Flags::Capital_plus]))
if ((wip->wi_flags[Weapon::Info_Flags::Pierce_shields]) && !(wip->wi_flags[Weapon::Info_Flags::Capital_plus]))
{
nprintf(("AI", "%i: Ship %s selecting weapon %s (>10%% shields)\n", Framecount, Ships[objp->instance].ship_name, Weapon_info[swp->primary_bank_weapons[bank_index]].name));
nprintf(("AI", "%i: Ship %s selecting weapon %s (>10%% shields)\n", Framecount, shipp->ship_name, wip->name));
return swp->current_primary_bank;
}
}
for (int i=0; i<swp->num_primary_banks; i++)
{
int weapon_info_index;
weapon_info_index = swp->primary_bank_weapons[i];
if (weapon_info_index > -1)
if (swp->primary_bank_weapons[i] >= 0)
{
if ((Weapon_info[weapon_info_index].wi_flags[Weapon::Info_Flags::Pierce_shields]) && !(Weapon_info[swp->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Capital_plus]))
auto wip = &Weapon_info[swp->primary_bank_weapons[i]];
if ((wip->wi_flags[Weapon::Info_Flags::Pierce_shields]) && !(wip->wi_flags[Weapon::Info_Flags::Capital_plus]))
{
swp->current_primary_bank = i;
nprintf(("AI", "%i: Ship %s selecting weapon %s (>10%% shields)\n", Framecount, Ships[objp->instance].ship_name, Weapon_info[swp->primary_bank_weapons[i]].name));
nprintf(("AI", "%i: Ship %s selecting weapon %s (>10%% shields)\n", Framecount, shipp->ship_name, wip->name));
return i;
}
}
@@ -5432,63 +5432,63 @@ int ai_select_primary_weapon(object *objp, object *other_objp, Weapon::Info_Flag
// Is the target shielded by less then 50%?
if (enemy_remaining_shield <= 0.50f)
{
// Should be using best balanced shield gun
int i;
float i_hullfactor_prev = 0; // Previous weapon bank hull factor (this is the safe way to do it)
int i_hullfactor_prev_bank = -1; // Bank which gave us this hull factor
// Should be using best balanced shield/hull gun
float i_balancedfactor_prev = 0; // Previous weapon bank "balanced" factor (this is the safe way to do it)
int i_balancedfactor_prev_bank = -1; // Bank which gave us this "balanced" factor
// Find the weapon with the highest average hull and shield * damage / fire delay factor
for (i = 0; i < swp->num_primary_banks; i++)
for (int i = 0; i < swp->num_primary_banks; i++)
{
if (swp->primary_bank_weapons[i] > -1) // Make sure there is a weapon in the bank
if (swp->primary_bank_weapons[i] >= 0) // Make sure there is a weapon in the bank
{
if ((((Weapon_info[swp->primary_bank_weapons[i]].armor_factor + Weapon_info[swp->primary_bank_weapons[i]].shield_factor) * Weapon_info[swp->primary_bank_weapons[i]].damage) / Weapon_info[swp->primary_bank_weapons[i]].fire_wait) > i_hullfactor_prev)
auto wip = &Weapon_info[swp->primary_bank_weapons[i]];
if ((((wip->armor_factor + wip->shield_factor) * wip->damage) / wip->fire_wait) > i_balancedfactor_prev)
{
if ( !(Weapon_info[swp->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Capital_plus]) )
if ( !(wip->wi_flags[Weapon::Info_Flags::Capital_plus]) )
{
// This weapon is the new candidate
i_hullfactor_prev = ((((Weapon_info[swp->primary_bank_weapons[i]].armor_factor + Weapon_info[swp->primary_bank_weapons[i]].shield_factor) * Weapon_info[swp->primary_bank_weapons[i]].damage) / Weapon_info[swp->primary_bank_weapons[i]].fire_wait));
i_hullfactor_prev_bank = i;
i_balancedfactor_prev = ((((wip->armor_factor + wip->shield_factor) * wip->damage) / wip->fire_wait));
i_balancedfactor_prev_bank = i;
}
}
}
}
if (i_hullfactor_prev_bank == -1) // In the unlikely instance we don't find at least 1 candidate weapon
if (i_balancedfactor_prev_bank == -1) // In the unlikely instance we don't find at least 1 candidate weapon
{
i_hullfactor_prev_bank = 0; // Just switch to the first one
i_balancedfactor_prev_bank = 0; // Just switch to the first one
}
swp->current_primary_bank = i_hullfactor_prev_bank; // Select the best weapon
nprintf(("AI", "%i: Ship %s selecting weapon %s (<50%% shields)\n", Framecount, Ships[objp->instance].ship_name, Weapon_info[swp->primary_bank_weapons[i_hullfactor_prev_bank]].name));
return i_hullfactor_prev_bank; // Return
swp->current_primary_bank = i_balancedfactor_prev_bank; // Select the best weapon
nprintf(("AI", "%i: Ship %s selecting weapon %s (<50%% shields)\n", Framecount, shipp->ship_name, Weapon_info[swp->primary_bank_weapons[i_balancedfactor_prev_bank]].name));
return i_balancedfactor_prev_bank; // Return
}
else
{
// Should be using best shield destroying gun
int i;
float i_hullfactor_prev = 0; // Previous weapon bank hull factor (this is the safe way to do it)
int i_hullfactor_prev_bank = -1; // Bank which gave us this hull factor
float i_shieldfactor_prev = 0; // Previous weapon bank shield factor (this is the safe way to do it)
int i_shieldfactor_prev_bank = -1; // Bank which gave us this shield factor
// Find the weapon with the highest average hull and shield * damage / fire delay factor
for (i = 0; i < swp->num_primary_banks; i++)
for (int i = 0; i < swp->num_primary_banks; i++)
{
if (swp->primary_bank_weapons[i] > -1) // Make sure there is a weapon in the bank
if (swp->primary_bank_weapons[i] >= 0) // Make sure there is a weapon in the bank
{
if ((((Weapon_info[swp->primary_bank_weapons[i]].shield_factor) * Weapon_info[swp->primary_bank_weapons[i]].damage) / Weapon_info[swp->primary_bank_weapons[i]].fire_wait) > i_hullfactor_prev)
auto wip = &Weapon_info[swp->primary_bank_weapons[i]];
if ((((wip->shield_factor) * wip->damage) / wip->fire_wait) > i_shieldfactor_prev)
{
if ( !(Weapon_info[swp->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Capital_plus]) )
if ( !(wip->wi_flags[Weapon::Info_Flags::Capital_plus]) )
{
// This weapon is the new candidate
i_hullfactor_prev = ( ((Weapon_info[swp->primary_bank_weapons[i]].shield_factor) * (Weapon_info[swp->primary_bank_weapons[i]].damage)) / Weapon_info[swp->primary_bank_weapons[i]].fire_wait );
i_hullfactor_prev_bank = i;
i_shieldfactor_prev = ( ((wip->shield_factor) * (wip->damage)) / wip->fire_wait );
i_shieldfactor_prev_bank = i;
}
}
}
}
if (i_hullfactor_prev_bank == -1) // In the unlikely instance we don't find at least 1 candidate weapon
if (i_shieldfactor_prev_bank == -1) // In the unlikely instance we don't find at least 1 candidate weapon
{
i_hullfactor_prev_bank = 0; // Just switch to the first one
i_shieldfactor_prev_bank = 0; // Just switch to the first one
}
swp->current_primary_bank = i_hullfactor_prev_bank; // Select the best weapon
nprintf(("AI", "%i: Ship %s selecting weapon %s (>50%% shields)\n", Framecount, Ships[objp->instance].ship_name, Weapon_info[swp->primary_bank_weapons[i_hullfactor_prev_bank]].name));
return i_hullfactor_prev_bank; // Return
swp->current_primary_bank = i_shieldfactor_prev_bank; // Select the best weapon
nprintf(("AI", "%i: Ship %s selecting weapon %s (>50%% shields)\n", Framecount, shipp->ship_name, Weapon_info[swp->primary_bank_weapons[i_shieldfactor_prev_bank]].name));
return i_shieldfactor_prev_bank; // Return
}
}
+1 -1
View File
@@ -1626,7 +1626,7 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
status = SHIP_STATUS_ARRIVED;
}
// goal ship is still on the arrival list
else if ( mission_parse_get_arrival_ship(aigp->target_name) )
else if ( mission_check_ship_yet_to_arrive(aigp->target_name) )
{
status = SHIP_STATUS_NOT_ARRIVED;
}
+3 -3
View File
@@ -856,11 +856,11 @@ int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subs
// flags for weapon types
if (beam_flag)
eeo.eeo_flags |= EEOF_BEAM;
else if (flak_flag)
if (flak_flag)
eeo.eeo_flags |= EEOF_FLAK;
else if (laser_flag)
if (laser_flag)
eeo.eeo_flags |= EEOF_LASER;
else if (missile_flag)
if (missile_flag)
eeo.eeo_flags |= EEOF_MISSILE;
eeo.enemy_team_mask = enemy_team_mask;
+68 -2
View File
@@ -38,6 +38,9 @@
#include <limits>
char Cfile_root_dir[CFILE_ROOT_DIRECTORY_LEN] = "";
char Cfile_user_dir[CFILE_ROOT_DIRECTORY_LEN] = "";
// During cfile_init, verify that Pathtypes[n].index == n for each item
// Each path must have a valid parent that can be tracable all the way back to the root
// so that we can create directories when we need to.
@@ -100,6 +103,8 @@ static char Cfile_stack[CFILE_STACK_MAX][CFILE_ROOT_DIRECTORY_LEN];
std::array<CFILE, MAX_CFILE_BLOCKS> Cfile_block_list;
static const char *Cfile_cdrom_dir = NULL;
//
// Function prototypes for internally-called functions
//
@@ -142,15 +147,47 @@ void cfile_close()
#define MIN_NUM_PATH_COMPONENTS 3 /* Drive + directory + file */
#endif
/**
* @brief Determine if the given path is in the root directory
*
* @param exe_path Path to executable
*
* @return true if root directory, false if not
*/
static bool cfile_in_root_dir(const char *exe_path)
{
int new_token;
int token_count = 0;
const char *p = exe_path;
Assert(exe_path != NULL);
do {
new_token = 0;
while (*p == DIR_SEPARATOR_CHAR) {
p++;
}
while ((*p != '\0') && (*p != DIR_SEPARATOR_CHAR)) {
new_token = 1;
p++;
}
token_count += new_token;
} while (*p != '\0');
return (token_count < MIN_NUM_PATH_COMPONENTS);
}
/**
* @brief Initialize the cfile system. Called once at application start.
*
* @param exe_dir Path to a file (not a directory)
* @param cdrom_dir Path to a CD drive mount point (may be NULL)
*
* @return 0 On success
* @return 1 On error
*/
int cfile_init(const SCP_vector<cfile::ModRoot>& modRoots)
int cfile_init(const char *exe_dir, const char *cdrom_dir)
{
// initialize encryption
encrypt_init();
@@ -159,8 +196,36 @@ int cfile_init(const SCP_vector<cfile::ModRoot>& modRoots)
return 0;
}
char buf[CFILE_ROOT_DIRECTORY_LEN];
strncpy(buf, exe_dir, CFILE_ROOT_DIRECTORY_LEN - 1);
buf[CFILE_ROOT_DIRECTORY_LEN - 1] = '\0';
// are we in a root directory?
if(cfile_in_root_dir(buf)){
os::dialogs::Message(os::dialogs::MESSAGEBOX_ERROR, "FreeSpace2/Fred2 cannot be run from a drive root directory!");
return 1;
}
// This needs to be set here because cf_build_secondary_filelist assumes it to be true
cfile_inited = 1;
/*
* Determine the executable's directory. Note that DIR_SEPARATOR_CHAR
* is guaranteed to be found in the string else cfile_in_root_dir()
* would have failed.
*/
char *p;
p = strrchr(buf, DIR_SEPARATOR_CHAR);
*p = '\0';
cfile_chdir(buf);
// set root directory
strcpy_s(Cfile_root_dir, buf);
strcpy_s(Cfile_user_dir, os_get_config_path().c_str());
// Initialize the block list with proper data
Cfile_block_list.fill({});
@@ -168,7 +233,8 @@ int cfile_init(const SCP_vector<cfile::ModRoot>& modRoots)
// 32 bit CRC table init
cf_chksum_long_init();
cf_build_secondary_filelist(modRoots);
Cfile_cdrom_dir = cdrom_dir;
cf_build_secondary_filelist(Cfile_cdrom_dir);
return 0;
}
+3 -14
View File
@@ -165,22 +165,11 @@ extern const char *Get_file_list_child;
// cfile directory. valid after cfile_init() returns successfully
#define CFILE_ROOT_DIRECTORY_LEN 256
namespace cfile {
enum class ModRootType { Unknown, Folder, Package };
enum class LocationType { Unknown, SecondaryMod, PrimaryMod, GameRoot };
struct ModRoot {
ModRootType type = ModRootType::Unknown;
SCP_string path;
LocationType location_type = LocationType::Unknown;
bool user_location = false;
};
} // namespace cfile
extern char Cfile_root_dir[CFILE_ROOT_DIRECTORY_LEN];
extern char Cfile_user_dir[CFILE_ROOT_DIRECTORY_LEN];
//================= LOW-LEVEL FUNCTIONS ==================
int cfile_init(const SCP_vector<cfile::ModRoot>& modRoots);
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
-266
View File
@@ -1,266 +0,0 @@
#define _CFILE_INTERNAL
#include "cfilemod.h"
#include "cfile.h"
#include "cmdline/cmdline.h"
#include "osapi/osapi.h"
#include "cfilesystem.h"
#ifdef SCP_UNIX
#include <glob.h>
#include <sys/types.h>
#include <dirent.h>
#include <fnmatch.h>
#include <sys/stat.h>
#include <unistd.h>
#include <libgen.h>
#endif
namespace cfile {
namespace {
typedef struct cf_root_sort {
SCP_string path;
int cf_type;
} cf_root_sort;
// packfile sort function
bool cf_packfile_sort_func(const cf_root_sort& r1, const cf_root_sort& r2) {
// if the 2 directory types are the same, do a string compare
if (r1.cf_type == r2.cf_type) {
return (stricmp(r1.path.c_str(), r2.path.c_str()) < 0);
}
// otherwise return them in order of CF_TYPE_* precedence
return (r1.cf_type < r2.cf_type);
}
// Go through a root and look for pack files
void build_pack_list(SCP_vector<ModRoot>& mod_roots,
const SCP_string& search_path,
LocationType location_type,
bool user_location) {
char filespec[MAX_PATH_LEN];
// allocate a temporary array of temporary roots so we can easily sort them
SCP_vector<cf_root_sort> temp_roots_sort;
// now just setup all the root info
for (int i = CF_TYPE_ROOT; i < CF_MAX_PATH_TYPES; i++) {
strcpy_s(filespec, search_path.c_str());
if (strlen(Pathtypes[i].path)) {
strcat_s(filespec, Pathtypes[i].path);
if (filespec[strlen(filespec) - 1] != DIR_SEPARATOR_CHAR)
strcat_s(filespec, DIR_SEPARATOR_STR);
}
#if defined _WIN32
strcat_s( filespec, "*.vp" );
intptr_t find_handle;
_finddata_t find;
find_handle = _findfirst( filespec, &find );
if (find_handle != -1) {
do {
// add the new item
if (!(find.attrib & _A_SUBDIR)) {
// get a temp pointer
rptr_sort = &temp_roots_sort[root_index++];
// fill in all the proper info
strcpy_s(rptr_sort->path, root->path);
if(strlen(Pathtypes[i].path)) {
strcat_s(rptr_sort->path, Pathtypes[i].path );
strcat_s(rptr_sort->path, DIR_SEPARATOR_STR);
}
strcat_s(rptr_sort->path, find.name );
rptr_sort->roottype = CF_ROOTTYPE_PACK;
rptr_sort->cf_type = i;
}
} while (!_findnext(find_handle, &find));
_findclose( find_handle );
}
#elif defined SCP_UNIX
strcat_s(filespec, "*.[vV][pP]");
glob_t globinfo;
memset(&globinfo, 0, sizeof(globinfo));
int status = glob(filespec, 0, NULL, &globinfo);
if (status == 0) {
for (uint j = 0; j < globinfo.gl_pathc; j++) {
// Determine if this is a regular file
struct stat statbuf;
memset(&statbuf, 0, sizeof(statbuf));
stat(globinfo.gl_pathv[j], &statbuf);
if (S_ISREG(statbuf.st_mode)) {
cf_root_sort sort;
// fill in all the proper info
sort.path = globinfo.gl_pathv[j];
sort.cf_type = i;
temp_roots_sort.push_back(sort);
}
}
globfree(&globinfo);
}
#endif
}
// sort the roots
std::sort(temp_roots_sort.begin(), temp_roots_sort.end(), cf_packfile_sort_func);
// now insert them all into the real root list properly
for (const auto& pack_root : temp_roots_sort) {
ModRoot root;
root.type = ModRootType::Package;
root.path = pack_root.path;
root.user_location = user_location;
root.location_type = location_type;
mod_roots.push_back(root);
}
}
char normalize_directory_separator(char in) {
if (in == '/') {
return DIR_SEPARATOR_CHAR;
}
return in;
}
void
add_mod_roots(SCP_vector<ModRoot>& mod_roots, const char* mod_cmdline, const SCP_string& rootDirectory, bool user_location) {
if (mod_cmdline) {
bool primary = true;
for (const char* cur_pos = mod_cmdline; strlen(cur_pos) != 0; cur_pos += (strlen(cur_pos) + 1)) {
SCP_stringstream ss;
ss << rootDirectory;
if (rootDirectory.back() != DIR_SEPARATOR_CHAR) {
ss << DIR_SEPARATOR_CHAR;
}
ss << cur_pos << DIR_SEPARATOR_STR;
SCP_string rootPath = ss.str();
// normalize the path to the native path format
std::transform(rootPath.begin(), rootPath.end(), rootPath.begin(), normalize_directory_separator);
ModRoot root;
root.type = ModRootType::Folder;
root.path = rootPath;
root.user_location = user_location;
if (primary) {
root.location_type = LocationType::PrimaryMod;
} else {
root.location_type = LocationType::SecondaryMod;
}
mod_roots.push_back(root);
build_pack_list(mod_roots, rootPath, root.location_type, user_location);
primary = false;
}
}
}
}
SCP_vector<ModRoot> getModRootsFromModCmdline(const SCP_string& content_root, const char* mod_cmdline) {
SCP_vector<ModRoot> mod_roots;
if (os_is_legacy_mode()) {
// =========================================================================
#ifdef WIN32
// Nothing to do here, Windows uses the current directory as the base
#else
add_mod_roots(mod_roots, mod_cmdline, os_get_legacy_user_dir(), true);
ModRoot root;
root.type = ModRootType::Folder;
root.path = os_get_legacy_user_dir();
root.user_location = true;
root.location_type = LocationType::GameRoot;
// do we already have a slash? as in the case of a root directory install
if (root.path.back() != DIR_SEPARATOR_CHAR) {
root.path += DIR_SEPARATOR_STR; // put trailing backslash on for easier path construction
}
mod_roots.push_back(root);
// Next, check any VP files under the current directory.
build_pack_list(mod_roots, root.path, root.location_type, root.user_location);
#endif
// =========================================================================
} else if (!Cmdline_portable_mode) {
// =========================================================================
// now look for mods under the users HOME directory to use before system ones
add_mod_roots(mod_roots, mod_cmdline, os_get_config_path(), true);
// =========================================================================
// =========================================================================
// set users HOME directory as default for loading and saving files
ModRoot root;
root.type = ModRootType::Folder;
root.path = os_get_config_path();
root.user_location = true;
root.location_type = LocationType::GameRoot;
// do we already have a slash? as in the case of a root directory install
if (root.path.back() != DIR_SEPARATOR_CHAR) {
root.path += DIR_SEPARATOR_STR; // put trailing backslash on for easier path construction
}
mod_roots.push_back(root);
// Next, check any VP files under the current directory.
build_pack_list(mod_roots, root.path, root.location_type, root.user_location);
// =========================================================================
}
add_mod_roots(mod_roots, mod_cmdline, content_root, false);
ModRoot root;
root.type = ModRootType::Folder;
root.path = content_root;
root.user_location = false;
root.location_type = LocationType::GameRoot;
// do we already have a slash? as in the case of a root directory install
if (root.path.back() != DIR_SEPARATOR_CHAR) {
root.path += DIR_SEPARATOR_STR; // put trailing backslash on for easier path construction
}
mod_roots.push_back(root);
//======================================================
// Next, check any VP files under the current directory.
build_pack_list(mod_roots, root.path, root.location_type, root.user_location);
return mod_roots;
}
}
-10
View File
@@ -1,10 +0,0 @@
#pragma once
#include "globalincs/pstypes.h"
#include "cfile/cfile.h"
namespace cfile {
SCP_vector<ModRoot> getModRootsFromModCmdline(const SCP_string& content_root, const char* mod_cmdline);
}
+360 -94
View File
@@ -160,113 +160,379 @@ cf_root *cf_create_root()
return &Root_blocks[block]->roots[offset];
}
static bool has_mod_location(const SCP_vector<cfile::ModRoot>& modRoots)
// return the # of packfiles which exist
int cf_get_packfile_count(cf_root *root)
{
for (const auto& root : modRoots)
SCP_string filespec;
int i;
int packfile_count;
// count up how many packfiles we're gonna have
packfile_count = 0;
for (i=CF_TYPE_ROOT; i<CF_MAX_PATH_TYPES; i++ )
{
if (root.location_type == cfile::LocationType::PrimaryMod)
filespec = root->path;
if(strlen(Pathtypes[i].path))
{
return true;
}
}
return false;
}
void cf_build_root_list(const SCP_vector<cfile::ModRoot>& modRoots)
{
Num_roots = 0;
Num_path_roots = 0;
auto has_mod = has_mod_location(modRoots);
mprintf(("CFile root configuration:\n"));
// Go through the roots specified and convert them to the internal data structure
for (const auto& root : modRoots)
{
if (root.path.size() >= CF_MAX_PATHNAME_LENGTH - 1)
{
Error(LOCATION, "Mod root path '%s' is longer than the maximum %d!", root.path.c_str(), CF_MAX_PATHNAME_LENGTH - 1);
return;
}
auto cfile_root = cf_create_root();
memset(cfile_root, 0, sizeof(*cfile_root));
strcpy_s(cfile_root->path, root.path.c_str());
if (root.user_location)
{
cfile_root->location_flags |= CF_LOCATION_ROOT_USER;
} else {
cfile_root->location_flags |= CF_LOCATION_ROOT_GAME;
}
if (root.location_type == cfile::LocationType::SecondaryMod)
{
cfile_root->location_flags |= CF_LOCATION_TYPE_SECONDARY_MODS;
} else if (root.location_type == cfile::LocationType::PrimaryMod)
{
cfile_root->location_flags |= CF_LOCATION_TYPE_PRIMARY_MOD;
} else if (root.location_type == cfile::LocationType::GameRoot)
{
cfile_root->location_flags |= CF_LOCATION_TYPE_ROOT;
if (!has_mod)
filespec += Pathtypes[ i ].path;
if ( filespec[ filespec.length( ) - 1 ] != DIR_SEPARATOR_CHAR )
{
// If we do not have a mod then game roots are also primary mods
cfile_root->location_flags |= CF_LOCATION_TYPE_PRIMARY_MOD;
}
} else {
UNREACHABLE("Unknown root location type!");
}
switch (root.type)
{
case cfile::ModRootType::Folder:
cfile_root->roottype = CF_ROOTTYPE_PATH;
break;
case cfile::ModRootType::Package:
cfile_root->roottype = CF_ROOTTYPE_PACK;
break;
default:
UNREACHABLE("Unknown root type!");
break;
}
if (root.type == cfile::ModRootType::Folder)
{
size_t path_len = strlen(cfile_root->path);
// do we already have a slash? as in the case of a root directory install
if ( (path_len < (CF_MAX_PATHNAME_LENGTH-1)) && (cfile_root->path[path_len-1] != DIR_SEPARATOR_CHAR) ) {
strcat_s(cfile_root->path, DIR_SEPARATOR_STR); // put trailing backslash on for easier path construction
filespec += DIR_SEPARATOR_STR;
}
}
#ifndef NDEBUG
switch (root.type)
{
case cfile::ModRootType::Folder:
mprintf((" Found root folder '%s'\n", root.path.c_str()));
break;
case cfile::ModRootType::Package: {
uint chksum = 0;
cf_chksum_pack(root.path.c_str(), &chksum);
mprintf((" Found root pack '%s' with a checksum of 0x%08x\n", root.path.c_str(), chksum));
break;
}
default:
UNREACHABLE("Unknown root type!");
break;
#if defined _WIN32
filespec += "*.vp";
intptr_t find_handle;
_finddata_t find;
find_handle = _findfirst( filespec.c_str( ), &find );
if (find_handle != -1) {
do {
if (!(find.attrib & _A_SUBDIR)) {
packfile_count++;
}
} while (!_findnext(find_handle, &find));
_findclose( find_handle );
}
#elif defined SCP_UNIX
filespec += "*.[vV][pP]";
glob_t globinfo;
memset(&globinfo, 0, sizeof(globinfo));
int status = glob(filespec.c_str( ), 0, NULL, &globinfo);
if (status == 0) {
for (unsigned int j = 0; j < globinfo.gl_pathc; j++) {
// Determine if this is a regular file
struct stat statbuf;
memset(&statbuf, 0, sizeof(statbuf));
stat(globinfo.gl_pathv[j], &statbuf);
if (S_ISREG(statbuf.st_mode)) {
packfile_count++;
}
}
globfree(&globinfo);
}
#endif
}
return packfile_count;
}
// packfile sort function
bool cf_packfile_sort_func(const cf_root_sort &r1, const cf_root_sort &r2)
{
// if the 2 directory types are the same, do a string compare
if (r1.cf_type == r2.cf_type) {
return (stricmp(r1.path, r2.path) < 0);
}
// otherwise return them in order of CF_TYPE_* precedence
return (r1.cf_type < r2.cf_type);
}
// Go through a root and look for pack files
void cf_build_pack_list( cf_root *root )
{
char filespec[MAX_PATH_LEN];
int i;
cf_root_sort *temp_roots_sort, *rptr_sort;
int temp_root_count, root_index;
// determine how many packfiles there are
temp_root_count = cf_get_packfile_count(root);
if (temp_root_count <= 0)
return;
// allocate a temporary array of temporary roots so we can easily sort them
temp_roots_sort = (cf_root_sort*)vm_malloc(sizeof(cf_root_sort) * temp_root_count);
if (temp_roots_sort == NULL) {
Int3();
return;
}
// now just setup all the root info
root_index = 0;
for (i = CF_TYPE_ROOT; i < CF_MAX_PATH_TYPES; i++) {
strcpy_s( filespec, root->path );
if ( strlen(Pathtypes[i].path) ) {
strcat_s( filespec, Pathtypes[i].path );
if ( filespec[strlen(filespec)-1] != DIR_SEPARATOR_CHAR )
strcat_s( filespec, DIR_SEPARATOR_STR );
}
#if defined _WIN32
strcat_s( filespec, "*.vp" );
intptr_t find_handle;
_finddata_t find;
find_handle = _findfirst( filespec, &find );
if (find_handle != -1) {
do {
// add the new item
if (!(find.attrib & _A_SUBDIR)) {
Assert(root_index < temp_root_count);
// get a temp pointer
rptr_sort = &temp_roots_sort[root_index++];
// fill in all the proper info
strcpy_s(rptr_sort->path, root->path);
if(strlen(Pathtypes[i].path)) {
strcat_s(rptr_sort->path, Pathtypes[i].path );
strcat_s(rptr_sort->path, DIR_SEPARATOR_STR);
}
strcat_s(rptr_sort->path, find.name );
rptr_sort->roottype = CF_ROOTTYPE_PACK;
rptr_sort->cf_type = i;
}
} while (!_findnext(find_handle, &find));
_findclose( find_handle );
}
#elif defined SCP_UNIX
strcat_s( filespec, "*.[vV][pP]" );
glob_t globinfo;
memset(&globinfo, 0, sizeof(globinfo));
int status = glob(filespec, 0, NULL, &globinfo);
if (status == 0) {
for (uint j = 0; j < globinfo.gl_pathc; j++) {
// Determine if this is a regular file
struct stat statbuf;
memset(&statbuf, 0, sizeof(statbuf));
stat(globinfo.gl_pathv[j], &statbuf);
if ( S_ISREG(statbuf.st_mode) ) {
Assert(root_index < temp_root_count);
// get a temp pointer
rptr_sort = &temp_roots_sort[root_index++];
// fill in all the proper info
strcpy_s(rptr_sort->path, globinfo.gl_pathv[j] );
rptr_sort->roottype = CF_ROOTTYPE_PACK;
rptr_sort->cf_type = i;
}
}
globfree(&globinfo);
}
#endif
}
// these should always be the same
Assert(root_index == temp_root_count);
// sort the roots
std::sort(temp_roots_sort, temp_roots_sort + temp_root_count, cf_packfile_sort_func);
// now insert them all into the real root list properly
for (i = 0; i < temp_root_count; i++) {
auto new_root = cf_create_root();
new_root->location_flags = root->location_flags;
strcpy_s( new_root->path, root->path );
#ifndef NDEBUG
uint chksum = 0;
cf_chksum_pack(temp_roots_sort[i].path, &chksum);
mprintf(("Found root pack '%s' with a checksum of 0x%08x\n", temp_roots_sort[i].path, chksum));
#endif
// mwa -- 4/2/98 put in the next 2 lines because the path name needs to be there
// to find the files.
strcpy_s(new_root->path, temp_roots_sort[i].path);
new_root->roottype = CF_ROOTTYPE_PACK;
}
// free up the temp list
vm_free(temp_roots_sort);
}
static char normalize_directory_separator(char in)
{
if (in == '/')
{
return DIR_SEPARATOR_CHAR;
}
return in;
}
static void cf_add_mod_roots(const char* rootDirectory, uint32_t basic_location)
{
if (Cmdline_mod)
{
bool primary = true;
for (const char* cur_pos=Cmdline_mod; strlen(cur_pos) != 0; cur_pos+= (strlen(cur_pos)+1))
{
SCP_stringstream ss;
ss << rootDirectory;
if (rootDirectory[strlen(rootDirectory) - 1] != DIR_SEPARATOR_CHAR)
{
ss << DIR_SEPARATOR_CHAR;
}
ss << cur_pos << DIR_SEPARATOR_STR;
SCP_string rootPath = ss.str();
if (rootPath.size() + 1 >= CF_MAX_PATHNAME_LENGTH) {
Error(LOCATION, "The length of mod directory path '%s' exceeds the maximum of %d!\n", rootPath.c_str(), CF_MAX_PATHNAME_LENGTH);
}
// normalize the path to the native path format
std::transform(rootPath.begin(), rootPath.end(), rootPath.begin(), normalize_directory_separator);
cf_root* root = cf_create_root();
strncpy(root->path, rootPath.c_str(), CF_MAX_PATHNAME_LENGTH-1);
if (primary) {
root->location_flags = basic_location | CF_LOCATION_TYPE_PRIMARY_MOD;
} else {
root->location_flags = basic_location | CF_LOCATION_TYPE_SECONDARY_MODS;
}
root->roottype = CF_ROOTTYPE_PATH;
cf_build_pack_list(root);
primary = false;
}
}
}
void cf_build_root_list(const char *cdrom_dir)
{
Num_roots = 0;
Num_path_roots = 0;
cf_root *root = nullptr;
if (os_is_legacy_mode())
{
// =========================================================================
#ifdef WIN32
// Nothing to do here, Windows uses the current directory as the base
#else
cf_add_mod_roots(os_get_legacy_user_dir(), CF_LOCATION_ROOT_USER);
root = cf_create_root();
strncpy(root->path, os_get_legacy_user_dir(), CF_MAX_PATHNAME_LENGTH - 1);
root->location_flags |= CF_LOCATION_ROOT_USER | CF_LOCATION_TYPE_ROOT;
if (Cmdline_mod == nullptr || strlen(Cmdline_mod) <= 0) {
// If there are no mods then the root is the primary mod
root->location_flags |= CF_LOCATION_TYPE_PRIMARY_MOD;
}
// do we already have a slash? as in the case of a root directory install
if ((strlen(root->path) < (CF_MAX_PATHNAME_LENGTH - 1)) && (root->path[strlen(root->path) - 1] != DIR_SEPARATOR_CHAR)) {
strcat_s(root->path, DIR_SEPARATOR_STR); // put trailing backslash on for easier path construction
}
root->roottype = CF_ROOTTYPE_PATH;
// Next, check any VP files under the current directory.
cf_build_pack_list(root);
#endif
// =========================================================================
}
else if (!Cmdline_portable_mode)
{
// =========================================================================
// now look for mods under the users HOME directory to use before system ones
cf_add_mod_roots(Cfile_user_dir, CF_LOCATION_ROOT_USER);
// =========================================================================
// =========================================================================
// set users HOME directory as default for loading and saving files
root = cf_create_root();
strcpy_s(root->path, Cfile_user_dir);
root->location_flags |= CF_LOCATION_ROOT_USER | CF_LOCATION_TYPE_ROOT;
if (Cmdline_mod == nullptr || strlen(Cmdline_mod) <= 0) {
// If there are no mods then the root is the primary mod
root->location_flags |= CF_LOCATION_TYPE_PRIMARY_MOD;
}
// do we already have a slash? as in the case of a root directory install
if ((strlen(root->path) < (CF_MAX_PATHNAME_LENGTH - 1)) && (root->path[strlen(root->path) - 1] != DIR_SEPARATOR_CHAR)) {
strcat_s(root->path, DIR_SEPARATOR_STR); // put trailing backslash on for easier path construction
}
root->roottype = CF_ROOTTYPE_PATH;
// Next, check any VP files under the current directory.
cf_build_pack_list(root);
// =========================================================================
}
char working_directory[CF_MAX_PATHNAME_LENGTH];
if ( !_getcwd(working_directory, CF_MAX_PATHNAME_LENGTH ) ) {
Error(LOCATION, "Can't get current working directory -- %d", errno );
}
cf_add_mod_roots(working_directory, CF_LOCATION_ROOT_GAME);
root = cf_create_root();
root->location_flags |= CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT;
if (Cmdline_mod == nullptr || strlen(Cmdline_mod) <= 0) {
// If there are no mods then the root is the primary mod
root->location_flags |= CF_LOCATION_TYPE_PRIMARY_MOD;
}
strcpy_s(root->path, working_directory);
size_t path_len = strlen(root->path);
// do we already have a slash? as in the case of a root directory install
if ( (path_len < (CF_MAX_PATHNAME_LENGTH-1)) && (root->path[path_len-1] != DIR_SEPARATOR_CHAR) ) {
strcat_s(root->path, DIR_SEPARATOR_STR); // put trailing backslash on for easier path construction
}
root->roottype = CF_ROOTTYPE_PATH;
//======================================================
// Next, check any VP files under the current directory.
cf_build_pack_list(root);
//======================================================
// Check the real CD if one...
if ( cdrom_dir && (strlen(cdrom_dir) < CF_MAX_PATHNAME_LENGTH) ) {
root = cf_create_root();
strcpy_s( root->path, cdrom_dir );
root->roottype = CF_ROOTTYPE_PATH;
//======================================================
// Next, check any VP files in the CD-ROM directory.
cf_build_pack_list(root);
}
// The final root is the in-memory root
auto root = cf_create_root();
root = cf_create_root();
root->location_flags = CF_LOCATION_ROOT_MEMORY | CF_LOCATION_TYPE_ROOT;
memset(root->path, 0, sizeof(root->path));
root->roottype = CF_ROOTTYPE_MEMORY;
}
// Given a lower case list of file extensions
@@ -657,7 +923,7 @@ void cf_build_file_list()
}
void cf_build_secondary_filelist(const SCP_vector<cfile::ModRoot>& modRoots)
void cf_build_secondary_filelist(const char *cdrom_dir)
{
int i;
@@ -678,7 +944,7 @@ void cf_build_secondary_filelist(const SCP_vector<cfile::ModRoot>& modRoots)
mprintf(( "Building file index...\n" ));
// build the list of searchable roots
cf_build_root_list(modRoots);
cf_build_root_list(cdrom_dir);
// build the list of files themselves
cf_build_file_list();
+1 -1
View File
@@ -15,7 +15,7 @@
#include "cfile/cfile.h"
// Builds a list of all the files
void cf_build_secondary_filelist(const SCP_vector<cfile::ModRoot>& modRoots);
void cf_build_secondary_filelist( const char *cdrom_path );
void cf_free_secondary_filelist();
// Internal stuff
+205 -328
View File
@@ -34,9 +34,6 @@
#include <CoreFoundation/CoreFoundation.h>
#endif
#include "cfile/cfile.h"
#include "cfile/cfilemod.h"
#ifdef SCP_UNIX
#include "osapi/osapi.h"
#include <dirent.h>
@@ -74,36 +71,23 @@ enum class flag_output_type {
Json_V1,
};
enum class flag_input_type {
Flags,
Stdin_Json_V1,
};
// variables
class cmdline_parm {
public:
cmdline_parm *next = nullptr, *prev = nullptr;
const char* name; // name of parameter, must start with '-' char
const char* help; // help text for this parameter
const bool stacks; // whether this arg stacks with each use or is replaced by newest use (should only be used for
// strings!!)
SCP_string args; // string value for parameter arguments (empty if no arguments)
bool name_found; // true if parameter on command line, otherwise false
const int arg_type; // from enum cmdline_arg_type; used for help
cmdline_parm *next, *prev;
const char *name; // name of parameter, must start with '-' char
const char *help; // help text for this parameter
const bool stacks; // whether this arg stacks with each use or is replaced by newest use (should only be used for strings!!)
char *args; // string value for parameter arguments (NULL if no arguments)
int name_found; // true if parameter on command line, otherwise false
const int arg_type; // from enum cmdline_arg_type; used for help
cmdline_parm(const char* name, const char* help, const int arg_type, const bool stacks = false) noexcept;
cmdline_parm(const char *name, const char *help, const int arg_type, const bool stacks = false) noexcept;
~cmdline_parm() noexcept;
cmdline_parm(const cmdline_parm& other) = delete;
cmdline_parm& operator=(const cmdline_parm& other) = delete;
cmdline_parm(cmdline_parm&& other) = delete;
cmdline_parm& operator=(cmdline_parm&& other) = delete;
bool found();
int found();
int get_int();
float get_float();
SCP_string str();
char *str();
bool check_if_args_is_valid();
bool has_param();
};
@@ -168,6 +152,7 @@ typedef struct
} Flag;
// clang-format off
// Please group them by type, ie graphics, gameplay etc, maximum 20 different types
Flag exe_params[] =
{
@@ -183,6 +168,7 @@ Flag exe_params[] =
{ "-post_process", "Enable post processing", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-post_process" },
{ "-soft_particles", "Enable soft particles", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-soft_particles" },
{ "-fxaa", "Enable FXAA anti-aliasing", true, EASY_MEM_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fxaa" },
{ "-smaa", "Enable SMAA anti-aliasing", true, EASY_MEM_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-smaa" },
{ "-nolightshafts", "Disable lightshafts", true, EASY_DEFAULT, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-flightshaftsoff"},
{ "-fb_explosions", "Enable Framebuffer Shockwaves", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fb_explosions", },
{ "-fb_thrusters", "Enable Framebuffer Thrusters", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fb_thrusters", },
@@ -264,6 +250,7 @@ Flag exe_params[] =
{ "-profile_frame_time","Profile engine subsystems", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-profile_frame_timings", },
{ "-debug_window", "Enable the debug window", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-debug_window", },
};
// clang-format on
// forward declaration
const char * get_param_desc(const char *flag_name);
@@ -291,11 +278,11 @@ cmdline_parm mouse_coords("-coords", NULL, AT_NONE); // Cmdline_mouse_coords
cmdline_parm timeout("-timeout", "Multiplayer network timeout (secs)", AT_INT); // Cmdline_timeout
cmdline_parm bit32_arg("-32bit", "Deprecated", AT_NONE); // (only here for retail compatibility reasons, doesn't actually do anything)
SCP_string Cmdline_connect_addr;
SCP_string Cmdline_game_name;
SCP_string Cmdline_game_password;
SCP_string Cmdline_rank_above;
SCP_string Cmdline_rank_below;
char *Cmdline_connect_addr = NULL;
char *Cmdline_game_name = NULL;
char *Cmdline_game_password = NULL;
char *Cmdline_rank_above = NULL;
char *Cmdline_rank_below = NULL;
int Cmdline_cd_check = 1;
int Cmdline_client_dodamage = 0;
int Cmdline_closed_game = 0;
@@ -338,6 +325,8 @@ cmdline_parm postprocess_arg("-post_process", NULL, AT_NONE);
cmdline_parm bloom_intensity_arg("-bloom_intensity", "Set bloom intensity, requires -post_process", AT_INT);
cmdline_parm fxaa_arg("-fxaa", NULL, AT_NONE);
cmdline_parm fxaa_preset_arg("-fxaa_preset", "FXAA quality (0-9), requires -post_process and -fxaa", AT_INT);
cmdline_parm smaa_arg("-smaa", nullptr, AT_NONE);
cmdline_parm smaa_preset_arg("-smaa_preset", "SMAA quality (0-9), requires -post_process and -smaa", 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);
@@ -408,7 +397,7 @@ int Cmdline_no_enhanced_sound = 0;
// MOD related
cmdline_parm mod_arg("-mod", "List of folders to overwrite/add-to the default data", AT_STRING, true); // Cmdline_mod -- DTP modsupport
SCP_vector<cfile::ModRoot> Cmdline_mod; // DTP for mod argument
char *Cmdline_mod = NULL; //DTP for mod argument
// Multiplayer/Network related
cmdline_parm almission_arg("-almission", "Autoload multiplayer mission", AT_STRING); // Cmdline_almission -- DTP for autoload Multi mission
@@ -418,19 +407,15 @@ cmdline_parm missioncrcspew_arg("-missioncrcs", NULL, AT_STRING); // Cmdline_sp
cmdline_parm tablecrcspew_arg("-tablecrcs", NULL, AT_STRING); // Cmdline_spew_table_crcs
cmdline_parm objupd_arg("-cap_object_update", "Multiplayer object update cap (0-3)", AT_INT);
SCP_string Cmdline_almission; // DTP for autoload multi mission.
char *Cmdline_almission = NULL; //DTP for autoload multi mission.
int Cmdline_ingamejoin = 0;
int Cmdline_mpnoreturn = 0;
SCP_string Cmdline_spew_mission_crcs;
SCP_string Cmdline_spew_table_crcs;
char *Cmdline_spew_mission_crcs = NULL;
char *Cmdline_spew_table_crcs = NULL;
int Cmdline_objupd = 3; // client object updates on LAN by default
// Launcher related options
cmdline_parm portable_mode("-portable_mode", NULL, AT_NONE);
cmdline_parm
stdin_flags("-stdin_flags",
"Tells FSO to read flags from stdin. Parameter is format if data supplied. Possible values: json_v1",
AT_STRING);
bool Cmdline_portable_mode = false;
@@ -462,7 +447,7 @@ int Cmdline_no_pbo = 0;
int Cmdline_ati_color_swap = 0;
int Cmdline_no_3d_sound = 0;
int Cmdline_drawelements = 0;
SCP_string Cmdline_keyboard_layout;
char* Cmdline_keyboard_layout = NULL;
bool Cmdline_gl_finish = false;
bool Cmdline_no_geo_sdr_effects = false;
bool Cmdline_set_cpu_affinity = false;
@@ -499,7 +484,8 @@ cmdline_parm show_video_info("-show_video_info", NULL, AT_NONE); //Cmdline_show_
cmdline_parm frame_profile_arg("-profile_frame_time", NULL, AT_NONE); //Cmdline_frame_profile
cmdline_parm debug_window_arg("-debug_window", NULL, AT_NONE); // Cmdline_debug_window
SCP_string Cmdline_start_mission;
char *Cmdline_start_mission = NULL;
int Cmdline_dis_collisions = 0;
int Cmdline_dis_weapons = 0;
bool Cmdline_output_sexp_info = false;
@@ -514,8 +500,8 @@ int Cmdline_show_stats = 0;
int Cmdline_save_render_targets = 0;
int Cmdline_window = 0;
int Cmdline_fullscreen_window = 0;
SCP_string Cmdline_res;
SCP_string Cmdline_center_res;
char *Cmdline_res = 0;
char *Cmdline_center_res = 0;
int Cmdline_verify_vps = 0;
int Cmdline_reparse_mainhall = 0;
bool Cmdline_profile_write_file = false;
@@ -566,8 +552,8 @@ void cmdline_debug_print_cmdline()
for (parmp = GET_FIRST(&Parm_list); parmp !=END_OF_LIST(&Parm_list); parmp = GET_NEXT(parmp) ) {
if ( parmp->name_found ) {
if (!parmp->args.empty()) {
mprintf(("\n %s %s", parmp->name, parmp->args.c_str()));
if ( parmp->args != NULL ) {
mprintf(("\n %s %s", parmp->name, parmp->args));
} else {
mprintf(("\n %s", parmp->name));
}
@@ -673,13 +659,14 @@ char *drop_extra_chars(char *str)
return str;
}
/*
* @brief Processes one argument for the given parameter
*
* @param param The parameter to check
* @param argc The argument count
* @param argv The argument values
* @param index The current index
* @param argc The argument values
* @param argc The current index
* @return @c true when an extra parameter was found, @c false otherwise
*/
bool parm_stuff_args(cmdline_parm *parm, int argc, char *argv[], int index)
@@ -696,17 +683,47 @@ bool parm_stuff_args(cmdline_parm *parm, int argc, char *argv[], int index)
}
else
{
if (parm->stacks) {
if (!parm->args.empty())
{
// Avoid adding the , at the start
parm->args += ",";
char* saved_args = NULL;
if (parm->args != NULL) {
if (parm->stacks) {
saved_args = parm->args;
}
parm->args += argv[index + 1];
else {
delete[] parm->args;
}
parm->args = NULL;
}
size_t argsize = strlen(argv[index + 1]);
size_t buffersize = argsize;
if (saved_args != NULL)
{
// Add one for the , separating args
buffersize += strlen(saved_args) + 1;
}
buffersize += 1; // Null-terminator
parm->args = new char[buffersize];
memset(parm->args, 0, buffersize);
if (saved_args != NULL)
{
// saved args go first, then new arg
strcpy_s(parm->args, buffersize, saved_args);
// add a separator too, so that we can tell the args apart
strcat_s(parm->args, buffersize, ",");
// now the new arg
strcat_s(parm->args, buffersize, argv[index + 1]);
delete[] saved_args;
}
else
{
parm->args = argv[index + 1];
strcpy_s(parm->args, buffersize, argv[index + 1]);
}
return true;
@@ -738,7 +755,7 @@ void os_parse_parms(int argc, char *argv[])
for (parmp = GET_FIRST(&Parm_list); parmp != END_OF_LIST(&Parm_list); parmp = GET_NEXT(parmp)) {
if (!stricmp(parmp->name, argv[i]))
{
parmp->name_found = true;
parmp->name_found = 1;
if (parm_stuff_args(parmp, argc, argv, i))
{
i++;
@@ -919,8 +936,11 @@ bool has_cmdline_only_flag(int argc, char *argv[])
static void reset_cmdline_parms()
{
for (cmdline_parm *parmp = GET_FIRST(&Parm_list); parmp != END_OF_LIST(&Parm_list); parmp = GET_NEXT(parmp)) {
parmp->args.clear();
parmp->name_found = false;
if (parmp->args != NULL) {
delete[] parmp->args;
parmp->args = NULL;
}
parmp->name_found = 0;
}
}
@@ -1016,14 +1036,11 @@ void os_init_cmdline(int argc, char *argv[])
* @param arg_type_ parameters arguement type (if any)
* @param stacks_ can the parameter be stacked
*/
cmdline_parm::cmdline_parm(const char* name_, const char* help_, const int arg_type_, const bool stacks_) noexcept
: name(name_), help(help_), stacks(stacks_), arg_type(arg_type_)
cmdline_parm::cmdline_parm(const char *name_, const char *help_, const int arg_type_, const bool stacks_) noexcept:
name(name_), help(help_), stacks(stacks_), arg_type(arg_type_)
{
if (stacks) {
Assertion(arg_type == AT_STRING, "Only string arguments can stack!");
}
name_found = false;
args = NULL;
name_found = 0;
if (Parm_list_inited == 0) {
Assertion(&Parm_list == this, "Coding error! 1st initialised cmdline_parm must be static Parm_list\n");
@@ -1042,12 +1059,20 @@ cmdline_parm::cmdline_parm(const char* name_, const char* help_, const int arg_t
// destructor - frees any allocated memory
cmdline_parm::~cmdline_parm() noexcept = default;
cmdline_parm::~cmdline_parm() noexcept
{
#ifndef FRED
if (args) {
delete [] args;
args = NULL;
}
#endif
}
// checks if the objects args variable is valid
// returns true if it is, shows an error box and returns false if not valid.
bool cmdline_parm::check_if_args_is_valid() {
if (args.empty()) {
if ( args == NULL ) {
Error(__FILE__, __LINE__,
"Command line flag passed that requires an argument, but the argument is missing!\r\n"
"The flag is '%s', make sure that you have an argument that follows it.\r\n"
@@ -1061,7 +1086,10 @@ bool cmdline_parm::check_if_args_is_valid() {
// returns - true if the parameter exists on the command line, otherwise false
bool cmdline_parm::found() { return name_found; }
int cmdline_parm::found()
{
return name_found;
}
// returns - the interger representation for the parameter argument
int cmdline_parm::get_int()
@@ -1069,12 +1097,22 @@ int cmdline_parm::get_int()
Assertion(arg_type == AT_INT, "Coding error! Cmdline arg (%s) called cmdline_parm::get_int() with invalid arg_type (%s)", name, cmdline_arg_types[arg_type]);
check_if_args_is_valid();
try {
return std::stoi(args);
} catch (const std::exception& e) {
Warning(LOCATION, "Failed to convert '%s' to a float for parameter '%s'!", args.c_str(), name);
return 0;
size_t offset = 0;
if (stacks) {
// first off, DON'T STACK NON-STRINGS!!
Int3();
// secondly, we still need to get it right for the user's sake...
char *moron = strstr(args, ",");
if ( moron && ((strlen(moron) + 1) < strlen(args)) ) {
// we get the last arg, since it's the newest one
offset = strlen(args) - strlen(moron) + 1;
}
}
return atoi(args+offset);
}
@@ -1084,24 +1122,36 @@ float cmdline_parm::get_float()
Assertion(arg_type == AT_FLOAT, "Coding error! Cmdline arg (%s) called cmdline_parm::get_float() with invalid arg_type (%s)", name, cmdline_arg_types[arg_type]);
check_if_args_is_valid();
try {
return std::stof(args);
} catch (const std::exception& e) {
Warning(LOCATION, "Failed to convert '%s' to a float for parameter '%s'!", args.c_str(), name);
return 0.0f;
size_t offset = 0;
if (stacks) {
// first off, DON'T STACK NON-STRINGS!!
Int3();
// secondly, we still need to get it right for the user's sake
char *moron = strstr(args, ",");
if ( moron && ((strlen(moron) + 1) < strlen(args)) ) {
// we get the last arg, since it's the newest one
offset = strlen(args) - strlen(moron) + 1;
}
}
return (float)atof(args+offset);
}
// returns - the string value for the parameter argument
SCP_string cmdline_parm::str()
char *cmdline_parm::str()
{
Assertion(arg_type == AT_STRING, "Coding error! Cmdline arg (%s) called cmdline_parm::str() with invalid arg_type (%s)", name, cmdline_arg_types[arg_type]);
check_if_args_is_valid();
return args;
}
bool cmdline_parm::has_param() { return !args.empty(); }
bool cmdline_parm::has_param() {
return args != nullptr;
}
#ifdef SCP_UNIX
// Return a vector with all filesystem names of "parent/dir" relative to parent.
@@ -1162,31 +1212,39 @@ static SCP_vector<SCP_string> unix_get_dir_names(const SCP_string& parent, const
}
// For case sensitive filesystems (e.g. Linux/BSD) perform case-insensitive dir matches.
static SCP_string handle_unix_modlist(const SCP_string& modlist)
static void handle_unix_modlist(char **modlist, size_t *len)
{
// search filesystem for given paths
SCP_vector<SCP_string> mod_paths;
SCP_stringstream iss(modlist);
SCP_string cur_mod;
while (std::getline(iss, cur_mod, ',')) {
for (char *cur_mod = strtok(*modlist, ","); cur_mod != NULL; cur_mod = strtok(NULL, ","))
{
SCP_vector<SCP_string> this_mod_paths = unix_get_dir_names(".", cur_mod);
// Ignore non-existing mods for unit tests
if (!running_unittests && this_mod_paths.empty()) {
ReleaseWarning(LOCATION, "Can't find mod '%s'. Ignoring.", cur_mod.c_str());
ReleaseWarning(LOCATION, "Can't find mod '%s'. Ignoring.", cur_mod);
}
mod_paths.insert(mod_paths.end(), this_mod_paths.begin(), this_mod_paths.end());
}
// create new string to replace modlist
SCP_string new_modlist;
for (const auto& path : mod_paths) {
new_modlist += path;
new_modlist += ","; // replace later with NUL
// create new char[] to replace modlist
size_t total_len = 0;
SCP_vector<SCP_string>::iterator ii, end = mod_paths.end();
for (ii = mod_paths.begin(); ii != end; ++ii) {
total_len += ii->length() + 1;
}
char *new_modlist = new char[total_len + 1];
memset(new_modlist, 0, total_len + 1);
end = mod_paths.end();
for (ii = mod_paths.begin(); ii != end; ++ii) {
strcat_s(new_modlist, total_len + 1, ii->c_str());
strcat_s(new_modlist, total_len + 1, ","); // replace later with NUL
}
// make the rest of the modlist manipulation unaware that anything happened here
return new_modlist;
delete [] *modlist;
*modlist = new_modlist;
*len = total_len;
}
#endif /* SCP_UNIX */
@@ -1244,7 +1302,6 @@ static json_t* json_get_v1() {
json_array_append_new(caps_array, json_string("No D3D"));
json_array_append_new(caps_array, json_string("New Sound"));
json_array_append_new(caps_array, json_string("SDL"));
json_array_append_new(caps_array, json_string("Stdin Flags: Json V1"));
json_object_set_new(root, "caps", caps_array);
}
@@ -1435,218 +1492,16 @@ static void write_flags() {
case flag_output_type::Binary:
write_flags_file();
break;
case flag_output_type::Json_V1: {
case flag_output_type::Json_V1:
json_t* root = json_get_v1();
json_dumpf(root, stdout, JSON_INDENT(4));
json_decref(root);
break;
}
}
}
static bool validate_version(json_t* rootEl)
{
const auto version_el = json_object_get(rootEl, "version");
if (version_el == nullptr) {
printf("Version element is missing!\n");
return false;
}
if (!json_is_number(version_el)) {
printf("Version value is not a number!\n");
return false;
}
if (json_integer_value(version_el) != 1) {
printf("Version value %" JSON_INTEGER_FORMAT " is not supported!\n", json_integer_value(version_el));
return false;
}
return true;
}
static cfile::ModRootType mapModRootType(const char* rootStr) {
if (!stricmp(rootStr, "folder")) {
return cfile::ModRootType::Folder;
} else if (!stricmp(rootStr, "package")) {
return cfile::ModRootType::Package;
} else {
return cfile::ModRootType::Unknown;
}
}
static cfile::LocationType mapLocationType(const char* rootStr) {
if (!stricmp(rootStr, "game_root")) {
return cfile::LocationType::GameRoot;
} else if (!stricmp(rootStr, "primary_mod")) {
return cfile::LocationType::PrimaryMod;
} else if (!stricmp(rootStr, "secondary_mod")) {
return cfile::LocationType::SecondaryMod;
} else {
return cfile::LocationType::Unknown;
}
}
static void stuff_mod_option(cmdline_parm* param, json_t* el)
{
if (!json_is_array(el))
{
printf("Value for option %s must be an array!", param->name);
return;
}
SCP_vector<cfile::ModRoot> roots;
size_t i;
json_t* modObj;
json_array_foreach(el, i, modObj)
{
const auto typeEl = json_object_get(modObj, "type");
const auto pathEl = json_object_get(modObj, "path");
const auto locationEl = json_object_get(modObj, "location_type");
if (typeEl == nullptr || pathEl == nullptr || locationEl == nullptr)
{
printf("A required mod root element is missing: Type %p, Path %p, Location %p", typeEl, pathEl, locationEl);
continue;
}
if (!json_is_string(typeEl) || !json_is_string(pathEl) || !json_is_string(locationEl))
{
printf("An element had a wrong type: Type %d, Path %d, Location %d", json_typeof(typeEl), json_typeof(pathEl), json_typeof(locationEl));
continue;
}
const auto userEl = json_object_get(modObj, "user");
if (userEl != nullptr && !json_is_boolean(userEl))
{
printf("User element type is not a boolean!");
continue;
}
cfile::ModRoot root;
root.type = mapModRootType(json_string_value(typeEl));
root.path = json_string_value(pathEl);
root.location_type = mapLocationType(json_string_value(locationEl));
root.user_location = userEl == nullptr ? false : json_boolean_value(userEl);
roots.push_back(root);
}
Cmdline_mod = roots;
}
static void stuff_json_option(cmdline_parm* param, json_t* el)
{
if (param == &mod_arg)
{
// The -mod parameter is handled specially since it is not a simple string
stuff_mod_option(param, el);
return;
}
switch (param->arg_type) {
case AT_NONE:
if (!json_is_boolean(el)) {
printf("Value for option %s must be a boolean!", param->name);
return;
}
param->name_found = json_is_true(el);
break;
case AT_INT:
if (!json_is_number(el)) {
printf("Value for option %s must be a number!", param->name);
return;
}
param->name_found = true;
param->args = std::to_string(json_integer_value(el));
break;
case AT_FLOAT:
if (!json_is_number(el)) {
printf("Value for option %s must be a number!", param->name);
return;
}
param->name_found = true;
param->args = std::to_string(json_real_value(el));
break;
case AT_STRING:
if (!json_is_string(el)) {
printf("Value for option %s must be a string!", param->name);
return;
}
param->name_found = true;
param->args.assign(json_string_value(el), json_string_length(el));
break;
default:
UNREACHABLE("Unknown arg type %d.", param->arg_type);
return;
}
}
static bool parse_json_flags(json_t* rootEl)
{
if (!json_is_object(rootEl)) {
printf("Root element must be an object!\n");
return false;
}
if (!validate_version(rootEl)) {
return false;
}
const auto flagsEl = json_object_get(rootEl, "flags");
if (flagsEl == nullptr) {
printf("Flags element is missing!\n");
return false;
}
if (!json_is_object(flagsEl)) {
printf("Flags element is not an object!\n");
return false;
}
const char* flagName;
json_t* flagValue;
json_object_foreach(flagsEl, flagName, flagValue)
{
for (auto parmp = GET_FIRST(&Parm_list); parmp != END_OF_LIST(&Parm_list); parmp = GET_NEXT(parmp)) {
if (!stricmp(parmp->name, flagName)) {
stuff_json_option(parmp, flagValue);
}
}
}
return true;
}
static bool SetCmdlineParams(flag_input_type inputType);
static bool SetCmdlineParamsFromStdin(const SCP_string& format)
{
if (format != "json_v1") {
// Invalid format!
printf("INPUT TYPE '%s' IS NOT SUPPORTED!\n", format.c_str());
return false;
}
json_error_t error;
json_t* flagsEl = json_loadf(stdin, JSON_DISABLE_EOF_CHECK, &error);
if (flagsEl == nullptr) {
printf("Failed to parse JSON: %s(%d:%d): %s\n", error.source, error.line, error.column, error.text);
return false;
}
if (!parse_json_flags(flagsEl)) {
return false;
}
return SetCmdlineParams(flag_input_type::Stdin_Json_V1);
}
static bool SetCmdlineParams(flag_input_type inputType)
bool SetCmdlineParams()
// Sets externed variables used for communication cmdline information
{
//getcwd(FreeSpace_Directory, 256); // set the directory to our fs2 root
@@ -1658,10 +1513,6 @@ static bool SetCmdlineParams(flag_input_type inputType)
return false;
}
if (inputType == flag_input_type::Flags && stdin_flags.found()) {
return SetCmdlineParamsFromStdin(stdin_flags.str());
}
if (no_fpscap.found())
{
Cmdline_NoFPSCap = 1;
@@ -1693,8 +1544,8 @@ static bool SetCmdlineParams(flag_input_type inputType)
Cmdline_spew_mission_crcs = missioncrcspew_arg.str();
// strip off blank space at end if it's there
if (Cmdline_spew_mission_crcs.back() == ' ') {
Cmdline_spew_mission_crcs.resize(Cmdline_spew_mission_crcs.size() - 1);
if ( Cmdline_spew_mission_crcs[strlen(Cmdline_spew_mission_crcs)-1] == ' ' ) {
Cmdline_spew_mission_crcs[strlen(Cmdline_spew_mission_crcs)-1] = '\0';
}
}
@@ -1702,8 +1553,8 @@ static bool SetCmdlineParams(flag_input_type inputType)
Cmdline_spew_table_crcs = tablecrcspew_arg.str();
// strip off blank space at end if it's there
if (Cmdline_spew_table_crcs.back() == ' ') {
Cmdline_spew_table_crcs.resize(Cmdline_spew_table_crcs.size() - 1);
if ( Cmdline_spew_table_crcs[strlen(Cmdline_spew_table_crcs)-1] == ' ' ) {
Cmdline_spew_table_crcs[strlen(Cmdline_spew_table_crcs)-1] = '\0';
}
}
@@ -1769,8 +1620,8 @@ static bool SetCmdlineParams(flag_input_type inputType)
Cmdline_game_name = gamename_arg.str();
// be sure that this string fits in our limits
if (Cmdline_game_name.size() > MAX_GAMENAME_LEN - 1) {
Cmdline_game_name.resize(MAX_GAMENAME_LEN - 1);
if ( strlen(Cmdline_game_name) > MAX_GAMENAME_LEN ) {
Cmdline_game_name[MAX_GAMENAME_LEN-1] = '\0';
}
}
@@ -1779,8 +1630,8 @@ static bool SetCmdlineParams(flag_input_type inputType)
Cmdline_game_password = gamepassword_arg.str();
// be sure that this string fits in our limits
if (Cmdline_game_password.size() > MAX_GAMENAME_LEN - 1) {
Cmdline_game_password.resize(MAX_GAMENAME_LEN - 1);
if ( strlen(Cmdline_game_name) > MAX_PASSWD_LEN ) {
Cmdline_game_name[MAX_PASSWD_LEN-1] = '\0';
}
}
@@ -1849,13 +1700,12 @@ static bool SetCmdlineParams(flag_input_type inputType)
int width = 0;
int height = 0;
if (sscanf(Cmdline_res.c_str(), "%dx%d", &width, &height) == 2) {
if ( sscanf(Cmdline_res, "%dx%d", &width, &height) == 2 ) {
SCP_string override;
sprintf(override, R"({"width":%d,"height":%d})", width, height);
sprintf(override, "{\"width\":%d,\"height\":%d}", width, height);
options::OptionsManager::instance()->setOverride("Graphics.Resolution", override);
} else {
mprintf(("Failed to parse -res parameter \"%s\". Must be in format \"<width>x<height>\".",
Cmdline_res.c_str()));
mprintf(("Failed to parse -res parameter \"%s\". Must be in format \"<width>x<height>\".", Cmdline_res));
}
}
if(center_res_arg.found()){
@@ -1888,32 +1738,35 @@ static bool SetCmdlineParams(flag_input_type inputType)
Cmdline_noparseerrors = 1;
}
// Legacy mod handling is handled here
if (inputType == flag_input_type::Flags && mod_arg.found()) {
auto modCmdline = mod_arg.str();
if(mod_arg.found() ) {
Cmdline_mod = mod_arg.str();
// strip off blank space it it's there
if (modCmdline.back() == ' ') {
modCmdline.resize(modCmdline.size() - 1);
if ( Cmdline_mod[strlen(Cmdline_mod)-1] == ' ' ) {
Cmdline_mod[strlen(Cmdline_mod)-1] = '\0';
}
// Ok - mod stacking support
size_t len = strlen(Cmdline_mod);
char *modlist = new char[len+2];
memset( modlist, 0, len + 2 );
strcpy_s(modlist, len+2, Cmdline_mod);
#ifdef SCP_UNIX
// handle case-insensitive searching
modCmdline = handle_unix_modlist(modCmdline);
handle_unix_modlist(&modlist, &len);
#endif
// null terminate each individual
for (auto& ch : modCmdline)
for (size_t i = 0; i < len; i++)
{
if (ch == ',')
ch = '\0';
if (modlist[i] == ',')
modlist[i] = '\0';
}
char whee[MAX_PATH_LEN];
memset(whee, 0, sizeof(whee));
_getcwd(whee, MAX_PATH_LEN-1);
Cmdline_mod = cfile::getModRootsFromModCmdline(whee, modCmdline.c_str());
//copy over - we don't have to delete[] Cmdline_mod because it's a pointer to an automatic global char*
Cmdline_mod = modlist;
}
@@ -2034,6 +1887,30 @@ static bool SetCmdlineParams(flag_input_type inputType)
Gr_aa_mode_last_frame = Gr_aa_mode;
}
if (smaa_arg.found()) {
Gr_aa_mode = AntiAliasMode::SMAA_Medium;
if (smaa_preset_arg.found()) {
switch (smaa_preset_arg.get_int()) {
case 0:
Gr_aa_mode = AntiAliasMode::SMAA_Low;
break;
case 1:
Gr_aa_mode = AntiAliasMode::SMAA_Medium;
break;
case 2:
Gr_aa_mode = AntiAliasMode::SMAA_High;
break;
case 3:
Gr_aa_mode = AntiAliasMode::SMAA_Ultra;
break;
default:
Gr_aa_mode = AntiAliasMode::SMAA_Ultra;
break;
}
}
}
if ( glow_arg.found() )
Cmdline_glow = 0;
@@ -2337,7 +2214,7 @@ int parse_cmdline(int argc, char *argv[])
// --------------- Kazan -------------
// If you're looking for the list of if (someparam.found()) { cmdline_someparam = something; } look above at this function
// I did this because of fred2_parse_cmdline()
return SetCmdlineParams(flag_input_type::Flags);
return SetCmdlineParams();
}
const char * get_param_desc(const char *flag_name)
+13 -18
View File
@@ -12,7 +12,6 @@
#ifndef FS_CMDLINE_HEADER_FILE
#define FS_CMDLINE_HEADER_FILE
#include "globalincs/pstypes.h"
int parse_cmdline(int argc, char *argv[]);
@@ -25,11 +24,11 @@ int parse_cmdline(int argc, char *argv[]);
// RETAIL OPTIONS ----------------------------------------------
extern SCP_string Cmdline_connect_addr;
extern SCP_string Cmdline_game_name;
extern SCP_string Cmdline_game_password;
extern SCP_string Cmdline_rank_above;
extern SCP_string Cmdline_rank_below;
extern char *Cmdline_connect_addr;
extern char *Cmdline_game_name;
extern char *Cmdline_game_password;
extern char *Cmdline_rank_above;
extern char *Cmdline_rank_below;
extern int Cmdline_cd_check;
extern int Cmdline_client_dodamage;
extern int Cmdline_closed_game;
@@ -47,8 +46,8 @@ extern int Cmdline_timeout;
extern int Cmdline_use_last_pilot;
extern int Cmdline_window;
extern int Cmdline_fullscreen_window;
extern SCP_string Cmdline_res;
extern SCP_string Cmdline_center_res;
extern char *Cmdline_res;
extern char *Cmdline_center_res;
// FSO OPTIONS -------------------------------------------------
@@ -97,18 +96,14 @@ extern int Cmdline_stretch_menu;
extern int Cmdline_voice_recognition;
extern int Cmdline_no_enhanced_sound;
namespace cfile {
struct ModRoot;
} // namespace cfile
// MOD related
extern SCP_vector<cfile::ModRoot> Cmdline_mod; // DTP for mod support
extern char *Cmdline_mod; // DTP for mod support
// Multiplayer/Network related
extern SCP_string Cmdline_almission; // DTP for autoload mission (for multi only)
extern char *Cmdline_almission; // DTP for autoload mission (for multi only)
extern int Cmdline_ingamejoin;
extern int Cmdline_mpnoreturn;
extern SCP_string Cmdline_spew_mission_crcs;
extern SCP_string Cmdline_spew_table_crcs;
extern char *Cmdline_spew_mission_crcs;
extern char *Cmdline_spew_table_crcs;
extern int Cmdline_objupd;
// Launcher related options
@@ -124,7 +119,7 @@ extern int Cmdline_mipmap;
extern int Cmdline_ati_color_swap;
extern int Cmdline_no_3d_sound;
extern int Cmdline_drawelements;
extern SCP_string Cmdline_keyboard_layout;
extern char* Cmdline_keyboard_layout;
extern bool Cmdline_gl_finish;
extern bool Cmdline_no_geo_sdr_effects;
extern bool Cmdline_set_cpu_affinity;
@@ -135,7 +130,7 @@ extern bool Cmdline_alternate_registry_path;
#endif
// Developer/Testing related
extern SCP_string Cmdline_start_mission;
extern char *Cmdline_start_mission;
extern int Cmdline_dis_collisions;
extern int Cmdline_dis_weapons;
extern bool Cmdline_output_sexp_info;
-48
View File
@@ -1,48 +0,0 @@
{
"version": 1,
"flags": {
"-bool_option": false,
"-number_option": 5.8,
"-string_option": "asdf",
"-mod": [
{
"type": "folder",
"path": "/home/fso/mediavps",
"user": true,
"location_type": "primary_mod"
},
{
"type": "folder",
"path": "/home/fso",
"user": true,
"location_type": "game_root"
},
{
"type": "folder",
"path": "/path/to/fso/mediavps",
"user": false,
"location_type": "primary_mod"
},
{
"type": "package",
"path": "/path/to/fso/mediavps/MVPS-Z.vp",
"location_type": "primary_mod"
},
{
"type": "package",
"path": "/path/to/fso/mediavps/MVPS-X.vp",
"location_type": "primary_mod"
},
{
"type": "folder",
"path": "/path/to/fso",
"location_type": "game_root"
},
{
"type": "package",
"path": "/path/to/fso/retail.vp",
"location_type": "game_root"
}
]
}
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,23 @@
uniform vec2 smaa_rt_metrics;
#define SMAA_RT_METRICS vec4(1.0 / smaa_rt_metrics, smaa_rt_metrics)
#define SMAA_INCLUDE_VS 0
#define SMAA_INCLUDE_PS 1
#include "SMAA.sdr"
in vec2 fragTexCoord;
in vec2 fragPixcoord;
in vec4 fragOffset[3];
out vec4 fragOut0;
uniform sampler2D edgesTex;
uniform sampler2D areaTex;
uniform sampler2D searchTex;
void main() {
fragOut0 = SMAABlendingWeightCalculationPS(fragTexCoord, fragPixcoord, fragOffset, edgesTex, areaTex, searchTex, vec4(0.0));
}
@@ -0,0 +1,22 @@
uniform vec2 smaa_rt_metrics;
#define SMAA_RT_METRICS vec4(1.0 / smaa_rt_metrics, smaa_rt_metrics)
#define SMAA_INCLUDE_VS 1
#define SMAA_INCLUDE_PS 0
#include "SMAA.sdr"
in vec4 vertPosition;
in vec2 vertTexCoord;
out vec2 fragTexCoord;
out vec2 fragPixcoord;
out vec4 fragOffset[3];
void main() {
gl_Position = vertPosition;
fragTexCoord = vertTexCoord;
SMAABlendingWeightCalculationVS(vertTexCoord, fragPixcoord, fragOffset);
}
@@ -0,0 +1,20 @@
uniform vec2 smaa_rt_metrics;
#define SMAA_RT_METRICS vec4(1.0 / smaa_rt_metrics, smaa_rt_metrics)
#define SMAA_INCLUDE_VS 0
#define SMAA_INCLUDE_PS 1
#include "SMAA.sdr"
in vec2 fragTexCoord;
in vec4 fragOffset[3];
out vec4 fragOut0;
uniform sampler2D colorTex;
void main() {
fragOut0 = vec4(SMAALumaEdgeDetectionPS(fragTexCoord, fragOffset, colorTex), 0.0, 1.0);
}
@@ -0,0 +1,21 @@
uniform vec2 smaa_rt_metrics;
#define SMAA_RT_METRICS vec4(1.0 / smaa_rt_metrics, smaa_rt_metrics)
#define SMAA_INCLUDE_VS 1
#define SMAA_INCLUDE_PS 0
#include "SMAA.sdr"
in vec4 vertPosition;
in vec2 vertTexCoord;
out vec2 fragTexCoord;
out vec4 fragOffset[3];
void main() {
gl_Position = vertPosition;
fragTexCoord = vertTexCoord;
SMAAEdgeDetectionVS(vertTexCoord, fragOffset);
}
@@ -0,0 +1,21 @@
uniform vec2 smaa_rt_metrics;
#define SMAA_RT_METRICS vec4(1.0 / smaa_rt_metrics, smaa_rt_metrics)
#define SMAA_INCLUDE_VS 0
#define SMAA_INCLUDE_PS 1
#include "SMAA.sdr"
in vec2 fragTexCoord;
in vec4 fragOffset;
out vec4 fragOut0;
uniform sampler2D colorTex;
uniform sampler2D blendTex;
void main() {
fragOut0 = SMAANeighborhoodBlendingPS(fragTexCoord, fragOffset, colorTex, blendTex);
}
@@ -0,0 +1,21 @@
uniform vec2 smaa_rt_metrics;
#define SMAA_RT_METRICS vec4(1.0 / smaa_rt_metrics, smaa_rt_metrics)
#define SMAA_INCLUDE_VS 1
#define SMAA_INCLUDE_PS 0
#include "SMAA.sdr"
in vec4 vertPosition;
in vec2 vertTexCoord;
out vec2 fragTexCoord;
out vec4 fragOffset;
void main() {
gl_Position = vertPosition;
fragTexCoord = vertTexCoord;
SMAANeighborhoodBlendingVS(vertTexCoord, fragOffset);
}
+2 -2
View File
@@ -1678,7 +1678,7 @@ void fs2netd_spew_table_checksums(const char *outfile)
char description[512] = { 0 };
char filename[65] = { 0 };
size_t offset = 0;
const char *p = nullptr;
char *p = NULL;
if ( Table_valid_status.empty() ) {
return;
@@ -1693,7 +1693,7 @@ void fs2netd_spew_table_checksums(const char *outfile)
return;
}
p = Cmdline_spew_table_crcs.c_str();
p = Cmdline_spew_table_crcs;
while (*p && (offset < sizeof(description))) {
if (*p == '"' && offset < sizeof(description)-1) {
+1 -1
View File
@@ -450,7 +450,7 @@ SCP_string dump_stacktrace();
// DEBUG compile time catch for dangerous uses of memset/memcpy/memmove
// This is disabled for VS2013 and lower since that doesn't support the necessary features
#if !defined(NDEBUG) && !defined(USING_THIRD_PARTY_LIBS) && (!defined(_MSC_VER) || _MSC_VER >= 1900)
#if SCP_COMPILER_CXX_AUTO_TYPE && SCP_COMPILER_CXX_STATIC_ASSERT && defined(HAVE_STD_IS_TRIVIALLY_COPYABLE)
#if SCP_COMPILER_CXX_AUTO_TYPE && SCP_COMPILER_CXX_STATIC_ASSERT && defined(SCP_HAVE_STD_IS_TRIVIALLY_COPYABLE)
// feature support seems to be: gcc clang msvc
// auto 4.4 2.9 2010
// std::is_trivial 4.5 ? 2012 (2010 only duplicates std::is_pod)
-1
View File
@@ -4,7 +4,6 @@
#pragma once
#include "scp_compiler_detection.h"
#include "platformChecks.h"
#define SCP_TOKEN_CONCAT1(x, y) x ## y
#define SCP_TOKEN_CONCAT(x, y) SCP_TOKEN_CONCAT1(x, y)
+1
View File
@@ -61,6 +61,7 @@ version get_executable_version() {
version::version(int major_in, int minor_in, int build_in, int revision_in) :
major(major_in), minor(minor_in), build(build_in), revision(revision_in) {
}
bool version::isValid() const { return major != 0 || minor != 0 || build != 0 || revision != 0; }
bool version::operator<(const version& v) const {
if (major < v.major) {
+2
View File
@@ -57,6 +57,8 @@ struct version {
version(int major, int minor, int build, int revision);
bool isValid() const;
bool operator<(const version& other) const;
bool operator==(const version& other) const;
bool operator!=(const version& other) const;
+12 -5
View File
@@ -304,7 +304,11 @@ static auto AAOption = options::OptionBuilder<AntiAliasMode>("Graphics.AAMode",
.values({{AntiAliasMode::None, "None"},
{AntiAliasMode::FXAA_Low, "FXAA Low"},
{AntiAliasMode::FXAA_Medium, "FXAA Medium"},
{AntiAliasMode::FXAA_High, "FXAA High"}})
{AntiAliasMode::FXAA_High, "FXAA High"},
{AntiAliasMode::SMAA_Low, "SMAA Low"},
{AntiAliasMode::SMAA_Medium, "SMAA Medium"},
{AntiAliasMode::SMAA_High, "SMAA High"},
{AntiAliasMode::SMAA_Ultra, "SMAA Ultra"}})
.default_val(AntiAliasMode::None)
.bind_to(&Gr_aa_mode)
.importance(79)
@@ -314,6 +318,9 @@ bool gr_is_fxaa_mode(AntiAliasMode mode)
{
return mode == AntiAliasMode::FXAA_Low || mode == AntiAliasMode::FXAA_Medium || mode == AntiAliasMode::FXAA_High;
}
bool gr_is_smaa_mode(AntiAliasMode mode) {
return mode == AntiAliasMode::SMAA_Low || mode == AntiAliasMode::SMAA_Medium || mode == AntiAliasMode::SMAA_High || mode == AntiAliasMode::SMAA_Ultra;
}
bool Gr_post_processing_enabled = false;
@@ -1248,11 +1255,11 @@ bool gr_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, int d_mode,
}
}
if (!Cmdline_res.empty()) {
if (Cmdline_res != nullptr) {
int tmp_width = 0;
int tmp_height = 0;
if ( sscanf(Cmdline_res.c_str(), "%dx%d", &tmp_width, &tmp_height) == 2 ) {
if ( sscanf(Cmdline_res, "%dx%d", &tmp_width, &tmp_height) == 2 ) {
width = tmp_width;
height = tmp_height;
}
@@ -1260,11 +1267,11 @@ bool gr_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, int d_mode,
Gr_enable_soft_particles = Cmdline_softparticles != 0;
}
if (!Cmdline_center_res.empty()) {
if (Cmdline_center_res != NULL) {
int tmp_center_width = 0;
int tmp_center_height = 0;
if ( (sscanf(Cmdline_center_res.c_str(), "%dx%d", &tmp_center_width, &tmp_center_height) == 2) && (tmp_center_width > 0) && (tmp_center_height > 0) ) {
if ( (sscanf(Cmdline_center_res, "%dx%d", &tmp_center_width, &tmp_center_height) == 2) && (tmp_center_width > 0) && (tmp_center_height > 0) ) {
center_aspect_ratio = (float)tmp_center_width / (float)tmp_center_height;
}
}
+13 -1
View File
@@ -47,14 +47,21 @@ extern flagset<FramebufferEffects> Gr_framebuffer_effects;
enum class AntiAliasMode {
None,
FXAA_Low,
FXAA_Medium,
FXAA_High
FXAA_High,
SMAA_Low,
SMAA_Medium,
SMAA_High,
SMAA_Ultra,
};
extern AntiAliasMode Gr_aa_mode;
extern AntiAliasMode Gr_aa_mode_last_frame;
bool gr_is_fxaa_mode(AntiAliasMode mode);
bool gr_is_smaa_mode(AntiAliasMode mode);
extern bool Gr_post_processing_enabled;
@@ -184,6 +191,11 @@ enum shader_type {
SDR_TYPE_DECAL,
SDR_TYPE_SCENE_FOG,
SDR_TYPE_ROCKET_UI,
SDR_TYPE_POST_PROCESS_SMAA_EDGE,
SDR_TYPE_POST_PROCESS_SMAA_BLENDING_WEIGHT,
SDR_TYPE_POST_PROCESS_SMAA_NEIGHBORHOOD_BLENDING,
NUM_SHADER_TYPES
};
File diff suppressed because it is too large. Load diff
+134
View File
@@ -0,0 +1,134 @@
/**
* Copyright (C) 2013 Jorge Jimenez ([email protected])
* Copyright (C) 2013 Jose I. Echevarria ([email protected])
* Copyright (C) 2013 Belen Masia ([email protected])
* Copyright (C) 2013 Fernando Navarro ([email protected])
* Copyright (C) 2013 Diego Gutierrez ([email protected])
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* 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. As clarification, there
* is no requirement that the copyright notice and permission be included in
* binary distributions 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.
*/
#ifndef SEARCHTEX_H
#define SEARCHTEX_H
#define SEARCHTEX_WIDTH 64
#define SEARCHTEX_HEIGHT 16
#define SEARCHTEX_PITCH SEARCHTEX_WIDTH
#define SEARCHTEX_SIZE (SEARCHTEX_HEIGHT * SEARCHTEX_PITCH)
// clang-format off
/**
* Stored in R8 format. Load it in the following format:
* - DX9: D3DFMT_L8
* - DX10: DXGI_FORMAT_R8_UNORM
*/
static const unsigned char searchTexBytes[] = {
0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x7f, 0x7f,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00,
0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0xfe, 0x7f, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xfe,
0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f,
0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x7f, 0x7f,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00,
0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0xfe, 0x7f, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xfe,
0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f,
0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f,
0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f,
0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f,
0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00,
0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f,
0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f,
0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f,
0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00,
0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
};
// clang-format on
#endif
+3 -3
View File
@@ -37,7 +37,7 @@ void opengl_clear_deferred_buffers()
opengl_shader_set_current( gr_opengl_maybe_create_shader(SDR_TYPE_DEFERRED_CLEAR, 0) );
opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f);
opengl_draw_full_screen_textured(0.0f, 0.0f, 1.0f, 1.0f);
opengl_shader_set_current();
@@ -263,7 +263,7 @@ void gr_opengl_deferred_lighting_finish()
uniformAligner.getOffset(element_index),
sizeof(graphics::deferred_light_data),
buffer->bufferHandle());
opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f);
opengl_draw_full_screen_textured(0.0f, 0.0f, 1.0f, 1.0f);
++element_index;
break;
case Light_Type::Cone:
@@ -335,7 +335,7 @@ void gr_opengl_deferred_lighting_finish()
Current_shader->program->Uniforms.setUniformf("zNear", Min_draw_distance);
Current_shader->program->Uniforms.setUniformf("zFar", Max_draw_distance);
opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f);
opengl_draw_full_screen_textured(0.0f, 0.0f, 1.0f, 1.0f);
} else {
// Transfer the resolved lighting back to the color texture
// TODO: Maybe this could be improved so that it doesn't require the copy back operation?
+23 -5
View File
@@ -534,7 +534,7 @@ void gr_opengl_scene_texture_end()
}
if ( Gr_post_processing_enabled && !PostProcessing_override ) {
gr_post_process_end();
gr_opengl_post_process_end();
} else {
GR_DEBUG_SCOPE("Draw scene texture");
TRACE_SCOPE(tracing::DrawSceneTexture);
@@ -551,7 +551,7 @@ void gr_opengl_scene_texture_end()
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
opengl_shader_set_passthrough(true);
opengl_shader_set_passthrough(true, High_dynamic_range);
GL_state.Array.BindArrayBuffer(0);
@@ -650,7 +650,7 @@ void gr_opengl_update_distortion()
GLboolean blend = GL_state.Blend(GL_FALSE);
GLboolean cull = GL_state.CullFace(GL_FALSE);
opengl_shader_set_passthrough(true);
opengl_shader_set_passthrough(true, High_dynamic_range);
GL_state.PushFramebufferState();
GL_state.BindFrameBuffer(Distortion_framebuffer);
@@ -695,7 +695,7 @@ void gr_opengl_update_distortion()
opengl_render_primitives_immediate(PRIM_TYPE_TRISTRIP, &vert_def, 4, vertices, sizeof(vertex) * 4);
opengl_shader_set_passthrough(false);
opengl_shader_set_passthrough(false, High_dynamic_range);
vertex distortion_verts[33];
@@ -864,7 +864,25 @@ void opengl_draw_textured_quad(GLfloat x1,
vert_def.add_vertex_component(vertex_format_data::POSITION2, sizeof(GLfloat) * 4, 0);
vert_def.add_vertex_component(vertex_format_data::TEX_COORD2, sizeof(GLfloat) * 4, sizeof(GLfloat) * 2);
opengl_render_primitives_immediate(PRIM_TYPE_TRISTRIP, &vert_def, 4, glVertices, sizeof(GLfloat) * 4 * 4);
opengl_render_primitives_immediate(PRIM_TYPE_TRISTRIP, &vert_def, 4, glVertices, sizeof(glVertices));
}
void opengl_draw_full_screen_textured(GLfloat u1, GLfloat v1, GLfloat u2, GLfloat v2)
{
GR_DEBUG_SCOPE("Draw full screen triangle");
GLfloat glVertices[3][4] = {
{-1.f, -1.f, u1, v1},
{3.f, -1.f, u2 * 2.f, v1},
{-1.f, 3.f, u1, v2 * 2.f},
};
vertex_layout vert_def;
vert_def.add_vertex_component(vertex_format_data::POSITION2, sizeof(GLfloat) * 4, 0);
vert_def.add_vertex_component(vertex_format_data::TEX_COORD2, sizeof(GLfloat) * 4, sizeof(GLfloat) * 2);
opengl_render_primitives_immediate(PRIM_TYPE_TRIS, &vert_def, 3, glVertices, sizeof(glVertices));
}
void gr_opengl_render_decals(decal_material* material_info,
+14
View File
@@ -64,6 +64,20 @@ void gr_opengl_render_rocket_primitives(interface_material* material_info, primi
void opengl_draw_textured_quad(GLfloat x1, GLfloat y1, GLfloat u1, GLfloat v1,
GLfloat x2, GLfloat y2, GLfloat u2, GLfloat v2 );
/**
* @brief Draw "something" so that the entire screen is covered and the corners use the UV values that are provided.
*
* @details This actually draws a a single oversized triangle that covers the screen in such a way so that the provided
* UV values are generated by the GPU in the corners of the screen. This is better than drawing two triangles since then
* the diagonal would be shaded differently for the two triangles causing visual differences.
*
* @param u1 The U value of the lower left corner.
* @param v1 The V value of the lower left corner.
* @param u2 The U value of the upper right corner.
* @param v2 The V value of the upper right corner.
*/
void opengl_draw_full_screen_textured(GLfloat u1, GLfloat v1, GLfloat u2, GLfloat v2);
inline GLenum opengl_primitive_type(primitive_type prim_type);
void gr_opengl_start_decal_pass();
+363 -61
View File
@@ -1,12 +1,17 @@
#include "cmdline/cmdline.h"
#include "gropenglpostprocessing.h"
#include "ShaderProgram.h"
#include "SmaaAreaTex.h"
#include "SmaaSearchTex.h"
#include "freespace.h"
#include "def_files/def_files.h"
#include "gropengl.h"
#include "gropengldraw.h"
#include "gropenglpostprocessing.h"
#include "gropenglshader.h"
#include "gropenglstate.h"
#include "cmdline/cmdline.h"
#include "def_files/def_files.h"
#include "io/timer.h"
#include "lighting/lighting.h"
#include "mod_table/mod_table.h"
@@ -14,8 +19,6 @@
#include "parse/parselo.h"
#include "ship/ship.h"
#include "tracing/tracing.h"
#include "ShaderProgram.h"
extern bool PostProcessing_override;
extern int opengl_check_framebuffer();
@@ -75,6 +78,18 @@ static GLuint Post_framebuffer_id[2] = { 0 };
static int Post_texture_width = 0;
static int Post_texture_height = 0;
static GLuint Smaa_edge_detection_fb = 0;
static GLuint Smaa_edges_tex = 0;
static GLuint Smaa_blending_weight_fb = 0;
static GLuint Smaa_blend_tex = 0;
static GLuint Smaa_neighborhood_blending_fb = 0;
static GLuint Smaa_output_tex = 0;
static GLuint Smaa_search_tex = 0;
static GLuint Smaa_area_tex = 0;
void opengl_post_pass_tonemap()
{
GR_DEBUG_SCOPE("Tonemapping");
@@ -89,7 +104,7 @@ void opengl_post_pass_tonemap()
GL_state.Texture.Enable(0, GL_TEXTURE_2D, Scene_color_texture);
opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, Scene_texture_u_scale, Scene_texture_u_scale);
opengl_draw_full_screen_textured(0.0f, 0.0f, Scene_texture_u_scale, Scene_texture_u_scale);
}
void opengl_post_pass_bloom()
@@ -124,7 +139,7 @@ void opengl_post_pass_bloom()
GL_state.Texture.Enable(0, GL_TEXTURE_2D, Scene_color_texture);
opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f);
opengl_draw_full_screen_textured(0.0f, 0.0f, 1.0f, 1.0f);
}
// ------ end bright pass ------
@@ -164,7 +179,7 @@ void opengl_post_pass_bloom()
glViewport(0, 0, bloom_width, bloom_height);
opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f);
opengl_draw_full_screen_textured(0.0f, 0.0f, 1.0f, 1.0f);
}
}
}
@@ -188,7 +203,7 @@ void opengl_post_pass_bloom()
glViewport(0, 0, gr_screen.max_w, gr_screen.max_h);
opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f);
opengl_draw_full_screen_textured(0.0f, 0.0f, 1.0f, 1.0f);
GL_state.SetAlphaBlendMode(ALPHA_BLEND_NONE);
}
@@ -263,7 +278,7 @@ void opengl_post_pass_fxaa() {
GL_state.Texture.Enable(0, GL_TEXTURE_2D, Scene_ldr_texture);
opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, Scene_texture_u_scale, Scene_texture_u_scale);
opengl_draw_full_screen_textured(0.0f, 0.0f, Scene_texture_u_scale, Scene_texture_u_scale);
// set and configure post shader ..
opengl_shader_set_current( gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_FXAA, 0) );
@@ -277,11 +292,124 @@ void opengl_post_pass_fxaa() {
GL_state.Texture.Enable(0, GL_TEXTURE_2D, Scene_luminance_texture);
opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, Scene_texture_u_scale, Scene_texture_u_scale);
opengl_draw_full_screen_textured(0.0f, 0.0f, Scene_texture_u_scale, Scene_texture_u_scale);
opengl_shader_set_current();
}
static void smaa_detect_edges()
{
GR_DEBUG_SCOPE("SMAA Detect Edges");
TRACE_SCOPE(tracing::SMAAEdgeDetection);
GL_state.BindFrameBuffer(Smaa_edge_detection_fb);
GLfloat clearValues[] = {0.0f, 0.0f, 0.0f, 1.0f};
glClearBufferfv(GL_COLOR, 0, clearValues);
// Do the edge detection step
opengl_shader_set_current(gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_SMAA_EDGE, 0));
// basic/default uniforms
Current_shader->program->Uniforms.setUniformi("colorTex", 0);
Current_shader->program->Uniforms.setUniform2f("smaa_rt_metrics", i2fl(Post_texture_width),
i2fl(Post_texture_height));
GL_state.Texture.Enable(0, GL_TEXTURE_2D, Scene_ldr_texture);
opengl_draw_full_screen_textured(0.0f, 0.0f, Scene_texture_u_scale, Scene_texture_u_scale);
}
static void smaa_calculate_blending_weights()
{
GR_DEBUG_SCOPE("SMAA Blending Weights calculation");
TRACE_SCOPE(tracing::SMAACalculateBlendingWeights);
GL_state.BindFrameBuffer(Smaa_blending_weight_fb);
GLfloat clearValues[] = {0.0f, 0.0f, 0.0f, 1.0f};
glClearBufferfv(GL_COLOR, 0, clearValues);
// Do the edge detection step
opengl_shader_set_current(gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_SMAA_BLENDING_WEIGHT, 0));
// basic/default uniforms
Current_shader->program->Uniforms.setUniformi("edgesTex", 0);
Current_shader->program->Uniforms.setUniformi("areaTex", 1);
Current_shader->program->Uniforms.setUniformi("searchTex", 2);
Current_shader->program->Uniforms.setUniform2f("smaa_rt_metrics", i2fl(Post_texture_width),
i2fl(Post_texture_height));
GL_state.Texture.Enable(0, GL_TEXTURE_2D, Smaa_edges_tex);
GL_state.Texture.Enable(1, GL_TEXTURE_2D, Smaa_area_tex);
GL_state.Texture.Enable(2, GL_TEXTURE_2D, Smaa_search_tex);
opengl_draw_full_screen_textured(0.0f, 0.0f, Scene_texture_u_scale, Scene_texture_u_scale);
}
static void smaa_neighborhood_blending()
{
GR_DEBUG_SCOPE("SMAA Neighborhood Blending");
TRACE_SCOPE(tracing::SMAANeighborhoodBlending);
GL_state.BindFrameBuffer(Smaa_neighborhood_blending_fb);
GLfloat clearValues[] = {0.0f, 0.0f, 0.0f, 1.0f};
glClearBufferfv(GL_COLOR, 0, clearValues);
// Do the edge detection step
opengl_shader_set_current(gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_SMAA_NEIGHBORHOOD_BLENDING, 0));
// basic/default uniforms
Current_shader->program->Uniforms.setUniformi("colorTex", 0);
Current_shader->program->Uniforms.setUniformi("blendTex", 1);
Current_shader->program->Uniforms.setUniform2f("smaa_rt_metrics", i2fl(Post_texture_width),
i2fl(Post_texture_height));
GL_state.Texture.Enable(0, GL_TEXTURE_2D, Scene_ldr_texture);
GL_state.Texture.Enable(1, GL_TEXTURE_2D, Smaa_blend_tex);
opengl_draw_full_screen_textured(0.0f, 0.0f, Scene_texture_u_scale, Scene_texture_u_scale);
}
void smaa_resolve()
{
GR_DEBUG_SCOPE("SMAA Resolve");
TRACE_SCOPE(tracing::SMAAResolve);
opengl_shader_set_passthrough(true, false);
GL_state.Texture.Enable(0, GL_TEXTURE_2D, Smaa_output_tex);
// Copy SMAA output back to the original framebuffer
if (GL_rendering_to_texture) {
opengl_draw_textured_quad(0.0f, 0.0f, 0.0f, 0.0f, (float)gr_screen.max_w, (float)gr_screen.max_h,
Scene_texture_u_scale, Scene_texture_v_scale);
} else {
opengl_draw_textured_quad(0.0f, 0.0f, 0.0f, Scene_texture_v_scale, (float)gr_screen.max_w,
(float)gr_screen.max_h, Scene_texture_u_scale, 0.0f);
}
}
void opengl_post_pass_smaa()
{
GR_DEBUG_SCOPE("SMAA");
TRACE_SCOPE(tracing::SMAA);
GL_state.PushFramebufferState();
GL_state.ColorMask(true, true, true, true);
smaa_detect_edges();
smaa_calculate_blending_weights();
smaa_neighborhood_blending();
GL_state.PopFramebufferState();
smaa_resolve();
}
extern GLuint Shadow_map_depth_texture;
extern GLuint Scene_depth_texture;
extern GLuint Cockpit_depth_texture;
@@ -332,7 +460,7 @@ void opengl_post_lightshafts()
GL_state.Blend(GL_TRUE);
GL_state.SetAlphaBlendMode(ALPHA_BLEND_ADDITIVE);
opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, Scene_texture_u_scale, Scene_texture_u_scale);
opengl_draw_full_screen_textured(0.0f, 0.0f, Scene_texture_u_scale, Scene_texture_u_scale);
GL_state.Blend(GL_FALSE);
break;
@@ -362,10 +490,14 @@ void gr_opengl_post_process_end()
// do tone mapping
opengl_post_pass_tonemap();
// Do FXAA
if (gr_is_fxaa_mode(Gr_aa_mode) && !fxaa_unavailable && !GL_rendering_to_texture) {
opengl_post_pass_fxaa();
}
// Do Post processing AA
if (!GL_rendering_to_texture) {
if (gr_is_smaa_mode(Gr_aa_mode)) {
opengl_post_pass_smaa();
} else if (gr_is_fxaa_mode(Gr_aa_mode) && !fxaa_unavailable) {
opengl_post_pass_fxaa();
}
}
// render lightshafts
opengl_post_lightshafts();
@@ -422,7 +554,7 @@ void gr_opengl_post_process_end()
GL_state.Texture.Enable(1, GL_TEXTURE_2D, Scene_depth_texture);
opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, Scene_texture_u_scale, Scene_texture_u_scale);
opengl_draw_full_screen_textured(0.0f, 0.0f, Scene_texture_u_scale, Scene_texture_u_scale);
//Shadow Map debug window
//#define SHADOW_DEBUG
@@ -705,9 +837,58 @@ static bool opengl_post_init_table()
}
}
void opengl_post_shader_header(SCP_stringstream &sflags, shader_type shader_t, int flags)
static void set_fxaa_defines(SCP_stringstream& sflags)
{
if ( shader_t == SDR_TYPE_POST_PROCESS_MAIN ) {
// Since we require OpenGL 3.2 we always have support for GLSL 130
sflags << "#define FXAA_GLSL_120 0\n";
sflags << "#define FXAA_GLSL_130 1\n";
if (GLSL_version >= 400) {
// The gather function became part of the standard with GLSL 4.00
sflags << "#define FXAA_GATHER4_ALPHA 1\n";
}
switch (Gr_aa_mode) {
case AntiAliasMode::None:
sflags << "#define FXAA_QUALITY_PRESET 10\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/6.0)\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/12.0)\n";
sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
break;
case AntiAliasMode::FXAA_Low:
sflags << "#define FXAA_QUALITY_PRESET 12\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/8.0)\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/16.0)\n";
sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
break;
case AntiAliasMode::FXAA_Medium:
sflags << "#define FXAA_QUALITY_PRESET 26\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/12.0)\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/24.0)\n";
sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
break;
case AntiAliasMode::FXAA_High:
sflags << "#define FXAA_QUALITY_PRESET 39\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/15.0)\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/32.0)\n";
sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
break;
default:
UNREACHABLE("Unhandled FXAA mode!");
}
}
void set_smaa_defines(SCP_stringstream& sflags)
{
// Define what GLSL version we use
if (GLSL_version >= 400) {
sflags << "#define SMAA_GLSL_4\n";
} else {
sflags << "#define SMAA_GLSL_3\n";
}
}
void opengl_post_shader_header(SCP_stringstream& sflags, shader_type shader_t, int flags)
{
if (shader_t == SDR_TYPE_POST_PROCESS_MAIN) {
for (size_t idx = 0; idx < Post_effects.size(); idx++) {
if (flags & (1 << idx)) {
sflags << "#define ";
@@ -715,46 +896,15 @@ void opengl_post_shader_header(SCP_stringstream &sflags, shader_type shader_t, i
sflags << "\n";
}
}
} else if ( shader_t == SDR_TYPE_POST_PROCESS_LIGHTSHAFTS ) {
} else if (shader_t == SDR_TYPE_POST_PROCESS_LIGHTSHAFTS) {
char temp[64];
sprintf(temp, "#define SAMPLE_NUM %d\n", ls_samplenum);
sflags << temp;
} else if ( shader_t == SDR_TYPE_POST_PROCESS_FXAA ) {
// Since we require OpenGL 3.2 we always have support for GLSL 130
sflags << "#define FXAA_GLSL_120 0\n";
sflags << "#define FXAA_GLSL_130 1\n";
if (GLSL_version >= 400) {
// The gather function became part of the standard with GLSL 4.00
sflags << "#define FXAA_GATHER4_ALPHA 1\n";
}
switch (Gr_aa_mode) {
case AntiAliasMode::None:
sflags << "#define FXAA_QUALITY_PRESET 10\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/6.0)\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/12.0)\n";
sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
break;
case AntiAliasMode::FXAA_Low:
sflags << "#define FXAA_QUALITY_PRESET 12\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/8.0)\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/16.0)\n";
sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
break;
case AntiAliasMode::FXAA_Medium:
sflags << "#define FXAA_QUALITY_PRESET 26\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/12.0)\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/24.0)\n";
sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
break;
case AntiAliasMode::FXAA_High:
sflags << "#define FXAA_QUALITY_PRESET 39\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/15.0)\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/32.0)\n";
sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
break;
}
} else if (shader_t == SDR_TYPE_POST_PROCESS_FXAA) {
set_fxaa_defines(sflags);
} else if (shader_t == SDR_TYPE_POST_PROCESS_SMAA_EDGE || shader_t == SDR_TYPE_POST_PROCESS_SMAA_BLENDING_WEIGHT ||
shader_t == SDR_TYPE_POST_PROCESS_SMAA_NEIGHBORHOOD_BLENDING) {
set_smaa_defines(sflags);
}
}
@@ -783,11 +933,17 @@ bool opengl_post_init_shaders()
Cmdline_bloom_intensity = 0;
}
if ( gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_FXAA, 0) < 0 ||
gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_FXAA_PREPASS, 0) < 0 ) {
Gr_aa_mode = AntiAliasMode::None;
fxaa_unavailable = true;
mprintf(("Error while compiling FXAA shaders. FXAA will be unavailable.\n"));
if (gr_is_fxaa_mode(Gr_aa_mode))
{
gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_FXAA, 0);
gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_FXAA_PREPASS, 0);
}
if (gr_is_smaa_mode(Gr_aa_mode)) {
// Precompile the SMAA shaders if enabled
gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_SMAA_EDGE, 0);
gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_SMAA_BLENDING_WEIGHT, 0);
gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_SMAA_NEIGHBORHOOD_BLENDING, 0);
}
return true;
@@ -825,6 +981,148 @@ void opengl_setup_bloom_textures()
GL_state.BindFrameBuffer(0);
}
void setup_smaa_edges_resources()
{
glGenTextures(1, &Smaa_edges_tex);
GL_state.Texture.SetActiveUnit(0);
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
GL_state.Texture.Enable(Smaa_edges_tex);
opengl_set_object_label(GL_TEXTURE, Smaa_edges_tex, "SMAA Edge detection texture");
if (GLAD_GL_ARB_texture_storage) {
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, Post_texture_width, Post_texture_height);
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Post_texture_width, Post_texture_height, 0, GL_BGRA, GL_UNSIGNED_BYTE,
nullptr);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glGenFramebuffers(1, &Smaa_edge_detection_fb);
GL_state.BindFrameBuffer(Smaa_edge_detection_fb);
opengl_set_object_label(GL_FRAMEBUFFER, Smaa_edge_detection_fb, "SMAA Edge detection framebuffer");
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, Smaa_edges_tex, 0);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
}
void setup_smaa_blending_weight_resources()
{
glGenTextures(1, &Smaa_blend_tex);
GL_state.Texture.SetActiveUnit(0);
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
GL_state.Texture.Enable(Smaa_blend_tex);
opengl_set_object_label(GL_TEXTURE, Smaa_blend_tex, "SMAA Blending weight calculation texture");
if (GLAD_GL_ARB_texture_storage) {
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, Post_texture_width, Post_texture_height);
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Post_texture_width, Post_texture_height, 0, GL_BGRA, GL_UNSIGNED_BYTE,
nullptr);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glGenFramebuffers(1, &Smaa_blending_weight_fb);
GL_state.BindFrameBuffer(Smaa_blending_weight_fb);
opengl_set_object_label(GL_FRAMEBUFFER, Smaa_blending_weight_fb, "SMAA Blending widght calculation framebuffer");
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, Smaa_blend_tex, 0);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
}
void setup_smaa_neighborhood_blending_resources()
{
glGenTextures(1, &Smaa_output_tex);
GL_state.Texture.SetActiveUnit(0);
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
GL_state.Texture.Enable(Smaa_output_tex);
opengl_set_object_label(GL_TEXTURE, Smaa_output_tex, "SMAA output texture");
if (GLAD_GL_ARB_texture_storage) {
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, Post_texture_width, Post_texture_height);
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Post_texture_width, Post_texture_height, 0, GL_BGRA, GL_UNSIGNED_BYTE,
nullptr);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glGenFramebuffers(1, &Smaa_neighborhood_blending_fb);
GL_state.BindFrameBuffer(Smaa_neighborhood_blending_fb);
opengl_set_object_label(GL_FRAMEBUFFER, Smaa_neighborhood_blending_fb, "SMAA neighborhood blending framebuffer");
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, Smaa_output_tex, 0);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
}
static GLuint load_smaa_texture(GLsizei width, GLsizei height, GLenum format, const uint8_t* pixels, const char* name)
{
GLuint tex;
glGenTextures(1, &tex);
GL_state.Texture.SetActiveUnit(0);
GL_state.Texture.SetTarget(GL_TEXTURE_2D);
GL_state.Texture.Enable(tex);
opengl_set_object_label(GL_TEXTURE, tex, name);
if (GLAD_GL_ARB_texture_storage) {
glTexStorage2D(GL_TEXTURE_2D, 1, format, width, height);
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(GL_TEXTURE_2D, 0, format, Post_texture_width, Post_texture_height, 0, GL_BGRA, GL_UNSIGNED_BYTE,
nullptr);
}
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format == GL_RG8 ? GL_RG : GL_RED, GL_UNSIGNED_BYTE, pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
return tex;
}
static void setup_smaa_resources()
{
GL_state.PushFramebufferState();
Smaa_area_tex = load_smaa_texture(AREATEX_WIDTH, AREATEX_HEIGHT, GL_RG8, areaTexBytes, "SMAA Area Texture");
Smaa_search_tex =
load_smaa_texture(SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT, GL_R8, searchTexBytes, "SMAA Search Texture");
setup_smaa_edges_resources();
setup_smaa_blending_weight_resources();
setup_smaa_neighborhood_blending_resources();
GL_state.PopFramebufferState();
}
// generate and test the framebuffer and textures that we are going to use
static bool opengl_post_init_framebuffer()
{
@@ -844,6 +1142,10 @@ static bool opengl_post_init_framebuffer()
opengl_setup_bloom_textures();
if (gr_is_smaa_mode(Gr_aa_mode)) {
setup_smaa_resources();
}
GL_state.BindFrameBuffer(0);
rval = true;
@@ -2,6 +2,9 @@
#ifndef _GROPENGLPOSTPROCESSING_H
#define _GROPENGLPOSTPROCESSING_H
#include "globalincs/pstypes.h"
#include "graphics/opengl/gropenglshader.h"
void opengl_post_process_init();
void opengl_post_process_shutdown();
+30 -5
View File
@@ -143,6 +143,15 @@ static opengl_shader_type_t GL_shader_types[] = {
{ SDR_TYPE_ROCKET_UI, "rocketui-v.sdr", "rocketui-f.sdr", nullptr,
{ opengl_vert_attrib::POSITION, opengl_vert_attrib::COLOR, opengl_vert_attrib::TEXCOORD }, "libRocket UI" },
{ SDR_TYPE_POST_PROCESS_SMAA_EDGE, "smaa-edge-v.sdr", "smaa-edge-f.sdr", nullptr,
{ opengl_vert_attrib::POSITION, opengl_vert_attrib::TEXCOORD }, "SMAA Edge detection" },
{ SDR_TYPE_POST_PROCESS_SMAA_BLENDING_WEIGHT, "smaa-blend-v.sdr", "smaa-blend-f.sdr", nullptr,
{ opengl_vert_attrib::POSITION, opengl_vert_attrib::TEXCOORD }, "SMAA Blending weight calculation" },
{ SDR_TYPE_POST_PROCESS_SMAA_NEIGHBORHOOD_BLENDING, "smaa-neighbour-v.sdr", "smaa-neighbour-f.sdr", nullptr,
{ opengl_vert_attrib::POSITION, opengl_vert_attrib::TEXCOORD }, "SMAA Neighborhood Blending" },
};
// clang-format on
@@ -370,11 +379,13 @@ static SCP_string opengl_shader_get_header(shader_type type_id, int flags, bool
sflags << "#define HAS_GEOMETRY_SHADER\n";
}
if (type_id == SDR_TYPE_POST_PROCESS_MAIN || type_id == SDR_TYPE_POST_PROCESS_LIGHTSHAFTS || type_id == SDR_TYPE_POST_PROCESS_FXAA) {
if (type_id == SDR_TYPE_POST_PROCESS_MAIN || type_id == SDR_TYPE_POST_PROCESS_LIGHTSHAFTS ||
type_id == SDR_TYPE_POST_PROCESS_FXAA || type_id == SDR_TYPE_POST_PROCESS_SMAA_EDGE ||
type_id == SDR_TYPE_POST_PROCESS_SMAA_BLENDING_WEIGHT ||
type_id == SDR_TYPE_POST_PROCESS_SMAA_NEIGHBORHOOD_BLENDING) {
// ignore looking for variants. main post process, lightshafts, and FXAA shaders need special headers to be hacked in
opengl_post_shader_header(sflags, type_id, flags);
}
else {
} else {
for (int i = 0; i < GL_num_shader_variants; ++i) {
opengl_shader_variant_t &variant = GL_shader_variants[i];
@@ -883,6 +894,20 @@ static void opengl_purge_shader_cache_type(const char* ext) {
SCP_string filter("*.");
filter += ext;
// Previously the cache files were stored in the mod directory. Since we have a better system now, those files
// should be cleaned out. This is only needed if we have a mod directory since otherwise we would delete the actual
// cache files
if (Cmdline_mod != nullptr && strlen(Cmdline_mod) > 0) {
SCP_vector<SCP_string> cache_files;
cf_get_file_list(cache_files, CF_TYPE_CACHE, filter.c_str(), CF_SORT_NONE, nullptr,
CF_LOCATION_TYPE_PRIMARY_MOD | CF_LOCATION_TYPE_SECONDARY_MODS);
for (auto& file : cache_files) {
cf_delete((file + "." + ext).c_str(), CF_TYPE_CACHE,
CF_LOCATION_TYPE_PRIMARY_MOD | CF_LOCATION_TYPE_SECONDARY_MODS);
}
}
SCP_vector<SCP_string> cache_files;
SCP_vector<file_list_info> file_info;
cf_get_file_list(cache_files, CF_TYPE_CACHE, filter.c_str(), CF_SORT_NONE, &file_info,
@@ -978,7 +1003,7 @@ GLint opengl_shader_get_attribute(opengl_vert_attrib::attrib_id attribute)
return Current_shader->program->getAttributeLocation(attribute);
}
void opengl_shader_set_passthrough(bool textured)
void opengl_shader_set_passthrough(bool textured, bool hdr)
{
opengl_shader_set_current(gr_opengl_maybe_create_shader(SDR_TYPE_PASSTHROUGH_RENDER, 0));
@@ -990,7 +1015,7 @@ void opengl_shader_set_passthrough(bool textured)
Current_shader->program->Uniforms.setUniformi("alphaTexture", 0);
Current_shader->program->Uniforms.setUniformi("srgb", High_dynamic_range ? 1 : 0);
Current_shader->program->Uniforms.setUniformi("srgb", hdr ? 1 : 0);
Current_shader->program->Uniforms.setUniformf("intensity", 1.0f);
Current_shader->program->Uniforms.setUniformf("alphaThreshold", GL_alpha_threshold);
+1 -1
View File
@@ -164,7 +164,7 @@ void opengl_shader_compile_deferred_light_clear_shader();
void opengl_shader_compile_passthrough_shader();
void opengl_shader_set_passthrough(bool textured = true);
void opengl_shader_set_passthrough(bool textured, bool hdr);
void opengl_shader_set_default_material(bool textured, bool alpha, vec4* clr, float color_scale, uint32_t array_index, const material::clip_plane& clip_plane);
-1
View File
@@ -199,7 +199,6 @@ void opengl_tcache_flush()
extern void opengl_kill_all_render_targets();
void opengl_tex_array_storage(GLenum target, GLint levels, GLenum format, GLint width, GLint height, GLint frames);
void opengl_tcache_shutdown()
{
opengl_kill_all_render_targets();
+1
View File
@@ -87,6 +87,7 @@ void gr_opengl_get_bitmap_from_texture(void* data_out, int bitmap_num);
size_t opengl_export_render_target( int slot, int width, int height, int alpha, int num_mipmaps, ubyte *image_data );
void opengl_set_texture_target(GLenum target = GL_TEXTURE_2D);
void opengl_set_texture_face(GLenum face = GL_TEXTURE_2D);
void opengl_tex_array_storage(GLenum target, GLint levels, GLenum format, GLint width, GLint height, GLint frames);
int gr_opengl_tcache_set(int bitmap_handle, int bitmap_type, float *u_scale, float *v_scale, uint32_t *array_index, int stage = 0);
int gr_opengl_preload(int bitmap_num, int is_aabitmap);
+3 -2
View File
@@ -223,14 +223,15 @@ void ChttpGet::WorkerThread()
if(strnicmp("HTTP/",p,5)==0)
{
char *pcode;
pcode = strchr(p,' ')+1;
if(!pcode)
pcode = strchr(p,' ');
if(pcode == nullptr)
{
m_State = HTTP_STATE_UNKNOWN_ERROR;
fclose(LOCALFILE);
return;
}
pcode++;
pcode[3] = '\0';
irsp = atoi(pcode);
+8
View File
@@ -1422,6 +1422,10 @@ void process_player_ship_keys(int k)
}
}
//Cyborg17 - Linking this function to restart sound if needed. This is to avoid having to
//check for subspace every frame.
extern void game_start_subspace_ambient_sound();
/**
* Handler for when player hits 'ESC' during the game
*/
@@ -1448,6 +1452,10 @@ void game_do_end_mission_popup()
break;
case 2:
// Cyborg17 - best place to check for this *one* looping sound.
if (Game_subspace_effect) {
game_start_subspace_ambient_sound();
}
gameseq_post_event(GS_EVENT_ENTER_GAME);
break;
-5
View File
@@ -128,11 +128,6 @@ int jpeg_read_header(const char *real_filename, CFILE *img_cfp, int *w, int *h,
jpeg_file = img_cfp;
}
Assert( jpeg_file != NULL );
if (jpeg_file == NULL)
return JPEG_ERROR_READING;
// set the basic/default error code
Jpeg_Set_Error(JPEG_ERROR_NONE);
-1
View File
@@ -1592,7 +1592,6 @@ void labviewer_change_ship_lod(Tree* caller)
void labviewer_change_ship(Tree* caller)
{
Lab_selected_index = caller->GetSelectedItem()->GetData();
Lab_last_selected_object = caller->GetSelectedItem();
labviewer_change_ship_lod(caller);
+33 -28
View File
@@ -4045,7 +4045,7 @@ int parse_wing_create_ships( wing *wingp, int num_to_create, int force, int spec
int num_remaining;
// see if ship is yet to arrive. If so, then return 0 so we can evaluate again later.
if (mission_parse_get_arrival_ship(name))
if (mission_check_ship_yet_to_arrive(name))
return 0;
// since this wing cannot arrive from this place, we need to mark the wing as destroyed and
@@ -5688,29 +5688,16 @@ bool parse_mission(mission *pm, int flags)
strcat_s(text, pm->name);
}
strcat_s(text, "\", and the current mod root is \"");
strcat_s(text, "\", and the current mod is \"");
// Try to find the first non-user, folder root and display that. Not ideal but better than nothing I guess...
// We go through all the specified mod roots and find the first non-user folder. If that does not exist then
// user folders will be considered next. If that also fails, a default value is used.
SCP_string modRoot = "<Unknown>";
for (const auto& consider_user : {false, true})
{
for (const auto& root : Cmdline_mod)
{
if (root.type != cfile::ModRootType::Folder)
{
continue;
}
if (root.user_location && !consider_user) {
continue;
}
modRoot = root.path;
if (Cmdline_mod == NULL || *Cmdline_mod == 0) {
strcat_s(text, "<retail default> ");
} else {
for (char *mod_token = Cmdline_mod; *mod_token != '\0'; mod_token += strlen(mod_token) + 1) {
strcat_s(text, mod_token);
strcat_s(text, " ");
}
}
strcat_s(text, modRoot.c_str());
strcpy(text + strlen(text) - 1, "\".)\n\n You can continue to load the mission, but it is quite likely that you will encounter a large number of mysterious errors. It is recommended that you either select a ");
strcat(text, (Game_mode & GM_CAMPAIGN_MODE) ? "campaign" : "mission");
@@ -5865,8 +5852,10 @@ bool post_process_mission()
sprintf(error_msg, "%s.\n\nIn sexpression: %s\n(Error appears to be: %s)", sexp_error_message(result), sexp_str.c_str(), Sexp_nodes[bad_node].text);
Warning(LOCATION, "%s", error_msg.c_str());
// syntax errors are unrecoverable, so abort
return false;
// syntax errors are recoverable in Fred but not FS
if (!Fred_running) {
return false;
}
}
}
}
@@ -6549,8 +6538,8 @@ p_object *mission_parse_get_arrival_ship(const char *name)
{
p_object *p_objp;
if (name == NULL)
return NULL;
if (name == nullptr)
return nullptr;
for (p_objp = GET_FIRST(&Ship_arrival_list); p_objp != END_OF_LIST(&Ship_arrival_list); p_objp = GET_NEXT(p_objp))
{
@@ -6560,7 +6549,7 @@ p_object *mission_parse_get_arrival_ship(const char *name)
}
}
return NULL;
return nullptr;
}
/**
@@ -6586,6 +6575,22 @@ p_object *mission_parse_get_arrival_ship(ushort net_signature)
return NULL;
}
/**
* Because player ships remain on the arrival list (see parse_wing_create_ships), testing for yet-to-arrive by merely
* checking the list will produce false positives for player ships. So this function also checks whether the object was created.
*/
bool mission_check_ship_yet_to_arrive(const char *name)
{
p_object *p_objp = mission_parse_get_arrival_ship(name);
if (p_objp == nullptr)
return false;
if (p_objp->created_object != nullptr)
return false;
return true;
}
/**
* Sets the arrival location of a parse object according to the arrival location of the object.
* @return objnum of anchor ship if there is one, -1 otherwise.
@@ -6805,7 +6810,7 @@ int mission_did_ship_arrive(p_object *objp)
shipnum = ship_name_lookup( name );
if ( shipnum == -1 ) {
// see if ship is yet to arrive. If so, then return -1 so we can evaluate again later.
if (mission_parse_get_arrival_ship(name))
if (mission_check_ship_yet_to_arrive(name))
return -1;
mission_parse_mark_non_arrival(objp); // Goober5000
@@ -7192,7 +7197,7 @@ int mission_do_departure(object *objp, bool goal_is_to_warp)
name = Parse_names[anchor];
// see if ship is yet to arrive. If so, then warp.
if (mission_parse_get_arrival_ship(name))
if (mission_check_ship_yet_to_arrive(name))
{
mprintf(("Anchor ship %s hasn't arrived yet! Trying to warp...\n", name));
goto try_to_warp;
+1
View File
@@ -482,6 +482,7 @@ extern char Neb2_texture_name[MAX_FILENAME_LEN];
bool parse_main(const char *mission_name, int flags = 0);
p_object *mission_parse_get_arrival_ship(ushort net_signature);
p_object *mission_parse_get_arrival_ship(const char *name);
bool mission_check_ship_yet_to_arrive(const char *name);
p_object *mission_parse_get_parse_object(ushort net_signature);
p_object *mission_parse_get_parse_object(const char *name);
int parse_create_object(p_object *objp);
+2 -2
View File
@@ -1265,7 +1265,7 @@ void wl_load_icons(int weapon_class)
icon = &Wl_icons[weapon_class];
if(!Cmdline_weapon_choice_3d || (wip->render_type == WRT_LASER && !strlen(wip->tech_model)))
if(!Cmdline_weapon_choice_3d || (wip->render_type == WRT_LASER && !strlen(wip->tech_model)) || strlen(Weapon_info[weapon_class].icon_filename) )
{
first_frame = bm_load_animation(Weapon_info[weapon_class].icon_filename, &num_frames, nullptr, nullptr, nullptr, false, CF_TYPE_INTERFACE);
@@ -1276,7 +1276,7 @@ void wl_load_icons(int weapon_class)
multi_send_anti_timeout_ping();
if ( first_frame == -1 && icon->model_index == -1)
if ( (first_frame == -1 && icon->model_index == -1) || (Cmdline_weapon_choice_3d && !strlen(wip->anim_filename)) )
{
if(strlen(wip->tech_model))
{
+78
View File
@@ -48,6 +48,12 @@ SCP_string Window_icon_path;
bool Disable_built_in_translations;
bool Weapon_shockwaves_respect_huge;
bool Using_in_game_options;
std::tuple<ubyte, ubyte, ubyte> Arc_color_damage_p1;
std::tuple<ubyte, ubyte, ubyte> Arc_color_damage_p2;
std::tuple<ubyte, ubyte, ubyte> Arc_color_damage_s1;
std::tuple<ubyte, ubyte, ubyte> Arc_color_emp_p1;
std::tuple<ubyte, ubyte, ubyte> Arc_color_emp_p2;
std::tuple<ubyte, ubyte, ubyte> Arc_color_emp_s1;
void parse_mod_table(const char *filename)
{
@@ -267,6 +273,72 @@ void parse_mod_table(const char *filename)
mprintf(("Game Settings Table: $BMPMAN Slot Limit is deprecated and should be removed. It is not needed anymore.\n"));
}
if (optional_string("$EMP Arc Color:")) {
if (optional_string("+Primary Color Option 1:")) {
int rgb[3];
stuff_int_list(rgb, 3);
if ((rgb[0] >= 0 && rgb[0] <= 255) && (rgb[1] >= 0 && rgb[1] <= 255) && (rgb[2] >= 0 && rgb[2] <= 255)) {
Arc_color_emp_p1 = std::make_tuple(static_cast<ubyte>(rgb[0]), static_cast<ubyte>(rgb[1]), static_cast<ubyte>(rgb[2]));
} else {
error_display(0, "$EMP Arc Color: +Primary Color Option 1 is %i, %i, %i. "
"One or more of these values is not within the range of 0-255. Assuming default color.", rgb[0], rgb[1], rgb[2]);
}
}
if (optional_string("+Primary Color Option 2:")) {
int rgb[3];
stuff_int_list(rgb, 3);
if ((rgb[0] >= 0 && rgb[0] <= 255) && (rgb[1] >= 0 && rgb[1] <= 255) && (rgb[2] >= 0 && rgb[2] <= 255)) {
Arc_color_emp_p2 = std::make_tuple(static_cast<ubyte>(rgb[0]), static_cast<ubyte>(rgb[1]), static_cast<ubyte>(rgb[2]));
} else {
error_display(0, "$EMP Arc Color: +Primary Color Option 2 is %i, %i, %i. "
"One or more of these values is not within the range of 0-255. Assuming default color.", rgb[0], rgb[1], rgb[2]);
}
}
if (optional_string("+Secondary Color Option 1:")) {
int rgb[3];
stuff_int_list(rgb, 3);
if ((rgb[0] >= 0 && rgb[0] <= 255) && (rgb[1] >= 0 && rgb[1] <= 255) && (rgb[2] >= 0 && rgb[2] <= 255)) {
Arc_color_emp_s1 = std::make_tuple(static_cast<ubyte>(rgb[0]), static_cast<ubyte>(rgb[1]), static_cast<ubyte>(rgb[2]));
} else {
error_display(0,"$EMP Arc Color: +Secondary Color Option 1 is %i, %i, %i. "
"One or more of these values is not within the range of 0-255. Assuming default color.", rgb[0], rgb[1], rgb[2]);
}
}
}
if (optional_string("$Damage Arc Color:")) {
if (optional_string("+Primary Color Option 1:")) {
int rgb[3];
stuff_int_list(rgb, 3);
if ((rgb[0] >= 0 && rgb[0] <= 255) && (rgb[1] >= 0 && rgb[1] <= 255) && (rgb[2] >= 0 && rgb[2] <= 255)) {
Arc_color_damage_p1 = std::make_tuple(static_cast<ubyte>(rgb[0]), static_cast<ubyte>(rgb[1]), static_cast<ubyte>(rgb[2]));
} else {
error_display(0, "Damage Arc Color: +Primary Color Option 1 is %i, %i, %i. "
"One or more of these values is not within the range of 0-255. Assuming default color.", rgb[0], rgb[1], rgb[2]);
}
}
if (optional_string("+Primary Color Option 2:")) {
int rgb[3];
stuff_int_list(rgb, 3);
if ((rgb[0] >= 0 && rgb[0] <= 255) && (rgb[1] >= 0 && rgb[1] <= 255) && (rgb[2] >= 0 && rgb[2] <= 255)) {
Arc_color_damage_p2 = std::make_tuple(static_cast<ubyte>(rgb[0]), static_cast<ubyte>(rgb[1]), static_cast<ubyte>(rgb[2]));
} else {
error_display(0, "$Damage Arc Color: +Primary Color Option 2 is %i, %i, %i. "
"One or more of these values is not within the range of 0-255. Assuming default color.", rgb[0], rgb[1], rgb[2]);
}
}
if (optional_string("+Secondary Color Option 1:")) {
int rgb[3];
stuff_int_list(rgb, 3);
if ((rgb[0] >= 0 && rgb[0] <= 255) && (rgb[1] >= 0 && rgb[1] <= 255) && (rgb[2] >= 0 && rgb[2] <= 255)) {
Arc_color_damage_s1 = std::make_tuple(static_cast<ubyte>(rgb[0]), static_cast<ubyte>(rgb[1]), static_cast<ubyte>(rgb[2]));
} else {
error_display(0, "$Damage Arc Color: +Secondary Color Option 1 is %i, %i, %i. "
"One or more of these values is not within the range of 0-255. Assuming default color.", rgb[0], rgb[1], rgb[2]);
}
}
}
optional_string("#NETWORK SETTINGS");
if (optional_string("$FS2NetD port:")) {
@@ -485,4 +557,10 @@ void mod_table_reset() {
Disable_built_in_translations = false;
Weapon_shockwaves_respect_huge = false;
Using_in_game_options = false;
Arc_color_damage_p1 = std::make_tuple(static_cast<ubyte>(64), static_cast<ubyte>(64), static_cast<ubyte>(225));
Arc_color_damage_p2 = std::make_tuple(static_cast<ubyte>(128), static_cast<ubyte>(128), static_cast<ubyte>(255));
Arc_color_damage_s1 = std::make_tuple(static_cast<ubyte>(200), static_cast<ubyte>(200), static_cast<ubyte>(255));
Arc_color_emp_p1 = std::make_tuple(static_cast<ubyte>(64), static_cast<ubyte>(64), static_cast<ubyte>(5));
Arc_color_emp_p2 = std::make_tuple(static_cast<ubyte>(128), static_cast<ubyte>(128), static_cast<ubyte>(10));
Arc_color_emp_s1 = std::make_tuple(static_cast<ubyte>(255), static_cast<ubyte>(255), static_cast<ubyte>(10));
}
+6
View File
@@ -39,6 +39,12 @@ extern SCP_string Window_icon_path;
extern bool Disable_built_in_translations;
extern bool Weapon_shockwaves_respect_huge;
extern bool Using_in_game_options;
extern std::tuple<ubyte, ubyte, ubyte> Arc_color_damage_p1;
extern std::tuple<ubyte, ubyte, ubyte> Arc_color_damage_p2;
extern std::tuple<ubyte, ubyte, ubyte> Arc_color_damage_s1;
extern std::tuple<ubyte, ubyte, ubyte> Arc_color_emp_p1;
extern std::tuple<ubyte, ubyte, ubyte> Arc_color_emp_p2;
extern std::tuple<ubyte, ubyte, ubyte> Arc_color_emp_s1;
void mod_table_init();
+8 -2
View File
@@ -1325,8 +1325,14 @@ int model_collide(mc_info *mc_info_obj)
// Check all the the highest detail model polygons and subobjects for intersections
// Don't check it or its children if it is destroyed
if (!Mc_pm->submodel[Mc_pm->detail[0]].blown_off) {
mc_check_subobj( Mc_pm->detail[0] );
if ( Mc_pmi ) {
if ( !Mc_pmi->submodel[Mc_pm->detail[0]].blown_off ) {
mc_check_subobj(Mc_pm->detail[0]);
}
} else {
if ( !Mc_pm->submodel[Mc_pm->detail[0]].blown_off ) {
mc_check_subobj(Mc_pm->detail[0]);
}
}
}
+3 -1
View File
@@ -4422,13 +4422,15 @@ void model_get_rotating_submodel_list(SCP_vector<int> *submodel_vector, object *
}
polymodel_instance *pmi = model_get_instance(model_instance_num);
submodel_instance *child_submodel_instance = &pmi->submodel[pm->detail[0]];
int i = child_submodel->first_child;
while ( i >= 0 ) {
child_submodel = &pm->submodel[i];
child_submodel_instance = &pmi->submodel[i];
// Don't check it or its children if it is destroyed or it is a replacement (non-moving)
if ( !child_submodel->blown_off && (child_submodel->i_replace == -1) && !child_submodel->no_collisions && !child_submodel->nocollide_this_only) {
if ( !child_submodel_instance->blown_off && (child_submodel->i_replace == -1) && !child_submodel->no_collisions && !child_submodel->nocollide_this_only) {
// Only look for submodels that rotate or intrinsic-rotate
if (child_submodel->movement_type == MOVEMENT_TYPE_ROT || child_submodel->movement_type == MOVEMENT_TYPE_INTRINSIC_ROTATE) {
+10 -15
View File
@@ -20,6 +20,7 @@
#include "graphics/uniforms.h"
#include "io/timer.h"
#include "math/staticrand.h"
#include "mod_table/mod_table.h"
#include "model/modelrender.h"
#include "nebula/neb.h"
#include "particle/particle.h"
@@ -831,13 +832,6 @@ void model_render_add_lightning( model_draw_list *scene, model_render_params* in
float width = 0.9f;
color primary, secondary;
const int AR = 64;
const int AG = 64;
const int AB = 5;
const int AR2 = 128;
const int AG2 = 128;
const int AB2 = 10;
Assert( sm->num_arcs > 0 );
if ( interp->get_model_flags() & MR_SHOW_OUTLINE_PRESET ) {
@@ -864,23 +858,23 @@ void model_render_add_lightning( model_draw_list *scene, model_render_params* in
// "normal", FreeSpace 1 style arcs
case MARC_TYPE_NORMAL:
if ( (rand()>>4) & 1 ) {
gr_init_color(&primary, 64, 64, 255);
gr_init_color(&primary, std::get<0>(Arc_color_damage_p1), std::get<1>(Arc_color_damage_p1), std::get<2>(Arc_color_damage_p1));
} else {
gr_init_color(&primary, 128, 128, 255);
gr_init_color(&primary, std::get<0>(Arc_color_damage_p2), std::get<1>(Arc_color_damage_p2), std::get<2>(Arc_color_damage_p2));
}
gr_init_color(&secondary, 200, 200, 255);
gr_init_color(&primary, std::get<0>(Arc_color_damage_s1), std::get<1>(Arc_color_damage_s1), std::get<2>(Arc_color_damage_s1));
break;
// "EMP" style arcs
case MARC_TYPE_EMP:
if ( (rand()>>4) & 1 ) {
gr_init_color(&primary, AR, AG, AB);
gr_init_color(&primary, std::get<0>(Arc_color_emp_p1), std::get<1>(Arc_color_emp_p1), std::get<2>(Arc_color_emp_p1));
} else {
gr_init_color(&primary, AR2, AG2, AB2);
gr_init_color(&primary, std::get<0>(Arc_color_emp_p2), std::get<1>(Arc_color_emp_p2), std::get<2>(Arc_color_emp_p2));
}
gr_init_color(&secondary, 255, 255, 10);
gr_init_color(&primary, std::get<0>(Arc_color_emp_s1), std::get<1>(Arc_color_emp_s1), std::get<2>(Arc_color_emp_s1));
break;
default:
@@ -2540,7 +2534,8 @@ void model_render_debug(int model_num, matrix *orient, vec3d * pos, uint flags,
gr_zbuffer_set(save_gr_zbuffering_mode);
}
void model_render_immediate(model_render_params *render_info, int model_num, matrix *orient, vec3d * pos, int render, bool sort)
void model_render_immediate(model_render_params* render_info, int model_num, matrix* orient, vec3d* pos, int render,
bool sort)
{
model_draw_list model_list;
@@ -2582,7 +2577,7 @@ void model_render_immediate(model_render_params *render_info, int model_num, mat
}
}
void model_render_queue(model_render_params *interp, model_draw_list *scene, int model_num, matrix *orient, vec3d *pos)
void model_render_queue(model_render_params* interp, model_draw_list* scene, int model_num, matrix* orient, vec3d* pos)
{
int i;
+4 -2
View File
@@ -296,8 +296,10 @@ public:
void reset();
};
void model_render_immediate(model_render_params *render_info, int model_num, matrix *orient, vec3d * pos, int render = MODEL_RENDER_ALL, bool sort = true);
void model_render_queue(model_render_params *render_info, model_draw_list* scene, int model_num, matrix *orient, vec3d *pos);
void model_render_immediate(model_render_params* render_info, int model_num, matrix* orient, vec3d* pos,
int render = MODEL_RENDER_ALL, bool sort = true);
void model_render_queue(model_render_params* render_info, model_draw_list* scene, int model_num, matrix* orient,
vec3d* pos);
void submodel_render_immediate(model_render_params *render_info, int model_num, int submodel_num, matrix *orient, vec3d * pos);
void submodel_render_queue(model_render_params *render_info, model_draw_list *scene, int model_num, int submodel_num, matrix *orient, vec3d * pos);
void model_render_buffers(model_draw_list* scene, model_material *rendering_material, model_render_params* interp, vertex_buffer *buffer, polymodel *pm, int mn, int detail_level, uint tmap_flags);
+2 -2
View File
@@ -1370,8 +1370,8 @@ void process_accept_player_data( ubyte *data, header *hinfo )
if ( stop == APD_END_DATA ) {
// if joining a game automatically, set the connect address to NULl so we don't try and
// do this next time we enter a game
if (!Cmdline_connect_addr.empty()) {
Cmdline_connect_addr.clear();
if (Cmdline_connect_addr != NULL) {
Cmdline_connect_addr = NULL;
}
// send my stats to the server if I'm not in observer mode
+26 -23
View File
@@ -945,7 +945,8 @@ void multi_join_game_init()
// if starting a network game, then go to the create game screen
if ( Cmdline_start_netgame ) {
multi_join_create_game();
} else if ( !Cmdline_connect_addr.empty() ) {
} else if ( Cmdline_connect_addr != NULL ) {
char *p;
short port_num;
int ip_addr;
@@ -955,11 +956,13 @@ void multi_join_game_init()
// create the address, looking out for port number at the end
port_num = DEFAULT_GAME_PORT;
const auto number_end = Cmdline_connect_addr.find(':');
if ( number_end != SCP_string::npos ) {
port_num = (short)atoi(Cmdline_connect_addr.substr(0, number_end).c_str());
p = strrchr(Cmdline_connect_addr, ':');
if ( p ) {
*p = '\0';
p++;
port_num = (short)atoi(p);
}
ip_addr = inet_addr(Cmdline_connect_addr.c_str());
ip_addr = inet_addr(Cmdline_connect_addr);
memcpy(Multi_autojoin_addr.addr, &ip_addr, 4);
Multi_autojoin_addr.port = port_num;
@@ -1003,7 +1006,7 @@ void multi_join_game_do_frame()
}
// when joining a network game, wait for the server query to come back, and then join the game
if ( !Cmdline_connect_addr.empty() ) {
if ( Cmdline_connect_addr != NULL ) {
int rval;
if ( !Multi_did_autojoin ) {
@@ -1011,7 +1014,7 @@ void multi_join_game_do_frame()
if ( rval == 0 ) {
// cancel was hit. Send the user back to the main hall
gameseq_post_event(GS_EVENT_MAIN_MENU);
Cmdline_connect_addr.clear(); // reset this value.
Cmdline_connect_addr = NULL; // reset this value.
}
// when we get here, we have the data -- join the game.
@@ -2267,7 +2270,7 @@ void multi_sg_select_rank_default();
// function which takes a rank name and returns the index. Useful for commandline options
// for above and below rank. We return the index of the rank in the Ranks[] array. If
// the rank isn't found, we return -1
int multi_start_game_rank_from_name( const char *rank ) {
int multi_start_game_rank_from_name( char *rank ) {
int i;
for ( i = 0; i <= MAX_FREESPACE2_RANK; i++ ) {
@@ -2352,8 +2355,8 @@ void multi_start_game_init()
// if starting a netgame, set the name of the game and any other options that are appropriate
if ( Cmdline_start_netgame ) {
if ( !Cmdline_game_name.empty() ) {
strcpy_s( Multi_sg_netgame->name, Cmdline_game_name.c_str() );
if ( Cmdline_game_name != NULL ) {
strcpy_s( Multi_sg_netgame->name, Cmdline_game_name );
Multi_sg_game_name.set_text(Multi_sg_netgame->name);
}
@@ -2363,21 +2366,21 @@ void multi_start_game_init()
Multi_sg_netgame->mode = NG_MODE_CLOSED;
} else if ( Cmdline_restricted_game ) {
Multi_sg_netgame->mode = NG_MODE_RESTRICTED;
} else if ( !Cmdline_game_password.empty() ) {
} else if ( Cmdline_game_password != NULL ) {
Multi_sg_netgame->mode = NG_MODE_PASSWORD;
strcpy_s(Multi_sg_netgame->passwd, Cmdline_game_password.c_str());
strcpy_s(Multi_sg_netgame->passwd, Cmdline_game_password);
Multi_sg_game_passwd.set_text(Multi_sg_netgame->passwd);
}
// deal with rank above and rank below
if ( (!Cmdline_rank_above.empty()) || (!Cmdline_rank_below.empty()) ) {
if ( (Cmdline_rank_above != NULL) || (Cmdline_rank_below != NULL) ) {
int rank;
const char *rank_str;
char *rank_str;
if ( !Cmdline_rank_above.empty() ) {
rank_str = Cmdline_rank_above.c_str();
if ( Cmdline_rank_above != NULL ) {
rank_str = Cmdline_rank_above;
} else {
rank_str = Cmdline_rank_below.c_str();
rank_str = Cmdline_rank_below;
}
// try and get the rank index from the name -- if found, then set the rank base
@@ -2388,7 +2391,7 @@ void multi_start_game_init()
Multi_sg_netgame->rank_base = Multi_sg_rank_select;
// now an arbitrary decision
if ( !Cmdline_rank_above.empty() ) {
if ( Cmdline_rank_above != NULL ) {
Multi_sg_netgame->mode = NG_MODE_RANK_ABOVE;
} else {
Multi_sg_netgame->mode = NG_MODE_RANK_BELOW;
@@ -3644,7 +3647,7 @@ void multi_create_game_do()
//DTP CHECK ALMISSION FLAG HERE AND SKIP THE BITMAP LOADING PROGRESS
//SINCE WE ALREADY HAVE A MISSION SELECTED IF THIS MISSION IS A VALID MULTIPLAYER MISSION
//IF NOT A VALID MULTIPLAYER MISSION CONTINUE LOADING, MAYBE CALL POPUP.
if ((!Cmdline_almission.empty()) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)) { //
if ((Cmdline_almission) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)) { //
multi_create_list_do(); //uhm here because off, hehe, my mind is failing right now
// DTP Var section for the is mission multi player Check.
@@ -3652,7 +3655,7 @@ void multi_create_game_do()
char mission_name[NAME_LENGTH+1];
int flags;
char *filename;
filename = cf_add_ext( Cmdline_almission.c_str(), FS_MISSION_FILE_EXT ); //DTP ADD EXTENSION needed next line
filename = cf_add_ext( Cmdline_almission, FS_MISSION_FILE_EXT ); //DTP ADD EXTENSION needed next line
flags = mission_parse_is_multi(filename, mission_name); //DTP flags will set if mission is multi
if (flags) { //only continue if mission is multiplayer mission
@@ -3660,7 +3663,7 @@ void multi_create_game_do()
ng = &Netgame;
char almissionname[256]; // needed, for the strncpy below
strncpy(almissionname, Cmdline_almission.c_str(), MAX_FILENAME_LEN); //DTP; copying name from cmd_almission line
strncpy(almissionname, Cmdline_almission,MAX_FILENAME_LEN); //DTP; copying name from cmd_almission line
Netgame.options.respawn = 99; //override anything //for debugging, i often forget this.
ng->respawn = Netgame.options.respawn;
@@ -3673,13 +3676,13 @@ void multi_create_game_do()
Multi_sync_mode = MULTI_SYNC_PRE_BRIEFING; //DTP must be set before a call to gameseq_post_event(GS_EVENT_MULTI_MISSION_SYNC) is done as it is below.
gameseq_post_event(GS_EVENT_MULTI_MISSION_SYNC);//DTP STart game
Cmdline_almission.clear(); // we don't want to autoload anymore do we, we will be able to quit. halleluja. Startgame has already been disabled, so no need to turn of "Cmdline_start_netgame"
Cmdline_almission = NULL; // we don't want to autoload anymore do we, we will be able to quit. halleluja. Startgame has already been disabled, so no need to turn of "Cmdline_start_netgame"
return; // we don't need to check or set regarding ships/weapons anything as we are already progressing into mission so return
}
else {
popup(PF_BODY_BIG | PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR(" Not a multi player-mission",9999)); //DTP startgame popup pilot error
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
Cmdline_almission.clear(); //DTP make sure this gets nullified.
Cmdline_almission = NULL; //DTP make sure this gets nullified.
}
}
+2 -2
View File
@@ -3263,7 +3263,7 @@ void multi_spew_pxo_checksums(int max_files, const char *outfile)
char filename[65] = { 0 };
char gametype[32] = { 0 };
size_t offset = 0;
const char *p = nullptr;
char *p = NULL;
// allocate filename space
file_names = (char**)vm_malloc(sizeof(char*) * max_files);
@@ -3285,7 +3285,7 @@ void multi_spew_pxo_checksums(int max_files, const char *outfile)
if (out == NULL)
goto Done;
p = Cmdline_spew_mission_crcs.c_str();
p = Cmdline_spew_mission_crcs;
while (*p && (offset < sizeof(description))) {
if (*p == '"') {
+3 -3
View File
@@ -1993,17 +1993,17 @@ unsigned int psnet_ras_status()
return INADDR_ANY;
}
pRasEnumConnections = (DWORD (__stdcall *)(LPRASCONN, LPDWORD, LPDWORD))GetProcAddress(ras_handle, "RasEnumConnectionsA");
pRasEnumConnections = (DWORD (__stdcall *)(LPRASCONN, LPDWORD, LPDWORD))(void*)GetProcAddress(ras_handle, "RasEnumConnectionsA");
if (!pRasEnumConnections) {
FreeLibrary( ras_handle );
return INADDR_ANY;
}
pRasGetConnectStatus = (DWORD (__stdcall *)(HRASCONN, LPRASCONNSTATUS))GetProcAddress(ras_handle, "RasGetConnectStatusA");
pRasGetConnectStatus = (DWORD (__stdcall *)(HRASCONN, LPRASCONNSTATUS))(void*)GetProcAddress(ras_handle, "RasGetConnectStatusA");
if (!pRasGetConnectStatus) {
FreeLibrary( ras_handle );
return INADDR_ANY;
}
pRasGetProjectionInfo = (DWORD (__stdcall *)(HRASCONN, RASPROJECTION, LPVOID, LPDWORD))GetProcAddress(ras_handle, "RasGetProjectionInfoA");
pRasGetProjectionInfo = (DWORD (__stdcall *)(HRASCONN, RASPROJECTION, LPVOID, LPDWORD))(void*)GetProcAddress(ras_handle, "RasGetProjectionInfoA");
if (!pRasGetProjectionInfo) {
FreeLibrary( ras_handle );
return INADDR_ANY;
+7 -7
View File
@@ -111,7 +111,7 @@ char title_str[512];
static HWND Multi_gen_dialog = NULL; // the dialog itself
// dialog proc for this dialog
BOOL CALLBACK std_gen_dialog_proc(HWND /*hwndDlg*/, UINT uMsg, WPARAM /*wParam*/, LPARAM /*lParam*/)
INT_PTR CALLBACK std_gen_dialog_proc(HWND /*hwndDlg*/, UINT uMsg, WPARAM /*wParam*/, LPARAM /*lParam*/)
{
switch(uMsg){
case WM_INITDIALOG:
@@ -483,7 +483,7 @@ int std_connect_lindex_to_npindex(int index)
}
// message handler for the connect tab
BOOL CALLBACK connect_proc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
INT_PTR CALLBACK connect_proc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
switch(uMsg){
// initialize the dialog
@@ -1016,7 +1016,7 @@ HTREEITEM std_multi_get_goal_item(char *goal_string,int type)
}
// message handler for the multiplayer tab
BOOL CALLBACK multi_proc(HWND hwndDlg,UINT uMsg,WPARAM /*wParam*/,LPARAM lParam)
INT_PTR CALLBACK multi_proc(HWND hwndDlg,UINT uMsg,WPARAM /*wParam*/,LPARAM lParam)
{
switch(uMsg){
// initialize the page
@@ -1271,7 +1271,7 @@ int std_pinfo_player_is_active(net_player *p)
}
// message handler for the player info tab
BOOL CALLBACK player_info_proc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
INT_PTR CALLBACK player_info_proc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
int player_num;
char callsign[40];
@@ -1453,7 +1453,7 @@ void std_gs_init_godstuff_controls()
}
// message handler for the godstuff tab
BOOL CALLBACK godstuff_proc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
INT_PTR CALLBACK godstuff_proc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
@@ -1607,7 +1607,7 @@ void std_debug_init_debug_controls(HWND hwndDlg)
}
// message handler for the godstuff tab
BOOL CALLBACK debug_proc(HWND hwndDlg,UINT uMsg,WPARAM /*wParam*/,LPARAM lParam)
INT_PTR CALLBACK debug_proc(HWND hwndDlg,UINT uMsg,WPARAM /*wParam*/,LPARAM lParam)
{
switch(uMsg){
// initialize the dialog
@@ -2343,7 +2343,7 @@ static void standalone_do_systray(int mode)
}
// just like the osapi version for the nonstandalone mode of FreeSpace
DWORD standalone_process(WORD /*lparam*/)
DWORD standalone_process(LPVOID /*lparam*/)
{
MSG msg;
+1 -1
View File
@@ -130,7 +130,7 @@ namespace
}
userSIDInitialized = true;
}
#if _MSC_VER >= 1400
#if !defined(_MSC_VER) || _MSC_VER >= 1400
if (userSIDValid)
{
if (needsWOW64())
+2004 -1131
View File
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -1170,7 +1170,7 @@ extern int get_sexp_main(void); // Returns start node
extern int run_sexp(const char* sexpression); // debug and lua sexps
extern int stuff_sexp_variable_list();
extern int eval_sexp(int cur_node, int referenced_node = -1);
extern int eval_num(int n);
extern int eval_num(int n, bool &is_nan, bool &is_nan_forever);
extern bool is_sexp_true(int cur_node, int referenced_node = -1);
extern int query_operator_return_type(int op);
extern int query_operator_argument_type(int op, int argnum);
+3 -2
View File
@@ -124,9 +124,10 @@ luacpp::LuaValue LuaSEXP::sexpToLua(int node, int argnum) const {
return LuaValue::createValue(_action.getLuaState(), value);
}
case OPF_NUMBER: {
auto res = eval_num(node);
bool is_nan, is_nan_forever;
auto res = eval_num(node, is_nan, is_nan_forever);
float value;
if (res == SEXP_NAN || res == SEXP_NAN_FOREVER) {
if (is_nan || is_nan_forever) {
value = std::numeric_limits<float>::quiet_NaN();
} else {
value = (float) res;
+1 -1
View File
@@ -850,7 +850,7 @@ void physics_apply_shock(vec3d *direction_vec, float pressure, physics_info *pi,
vm_vec_normalize_safe ( direction_vec );
area.xyz.x = (max->xyz.y - min->xyz.z) * (max->xyz.z - min->xyz.z);
area.xyz.x = (max->xyz.y - min->xyz.y) * (max->xyz.z - min->xyz.z);
area.xyz.y = (max->xyz.x - min->xyz.x) * (max->xyz.z - min->xyz.z);
area.xyz.z = (max->xyz.x - min->xyz.x) * (max->xyz.y - min->xyz.y);
+1 -1
View File
@@ -128,7 +128,7 @@ class pilotfile {
// --------------------------------------------------------------------
// PLR specific
// --------------------------------------------------------------------
void plr_reset_data();
void plr_reset_data(bool reset_all);
void plr_close();
void plr_read_flags();
+10 -4
View File
@@ -682,7 +682,7 @@ void pilotfile::plr_write_settings()
handler->endSectionWrite();
}
void pilotfile::plr_reset_data()
void pilotfile::plr_reset_data(bool reset_all)
{
// internals
m_have_flags = false;
@@ -691,7 +691,11 @@ void pilotfile::plr_reset_data()
m_data_invalid = false;
// set all the entries in the control config arrays to -1 (undefined)
control_config_clear();
// Cyborg17 - clear_all is false when we are just trying to verify the file, but true when we load the whole thing.
// Otherwise, we can end up getting rid of a pilot's controls by accident.
if (reset_all) {
control_config_clear();
}
// init stats
p->stats.init();
@@ -797,7 +801,8 @@ bool pilotfile::load_player(const char* callsign, player* _p, bool force_binary)
mprintf(("PLR => Loading '%s' with version %d...\n", filename.c_str(), version));
plr_reset_data();
//true resets everything, false sets up file verify.
plr_reset_data(true);
// the point of all this: read in the PLR contents
handler->beginSectionRead();
@@ -1016,7 +1021,8 @@ bool pilotfile::verify(const char *fname, int *rank, char *valid_language)
mprintf(("PLR => Verifying '%s' with version %d...\n", filename.c_str(), version));
plr_reset_data();
// true resets everything, false sets up file verify.
plr_reset_data(false);
bool have_flags = false;
bool have_info = false;
+42 -25
View File
@@ -2,14 +2,14 @@
//
#include "scripting/ade.h"
#include "ade_api.h"
#include "def_files/def_files.h"
#include "mod_table/mod_table.h"
#include "scripting/lua/LuaFunction.h"
#include "ship/ship.h"
#include "ade.h"
#include "ade_api.h"
#include "ade_args.h"
#include "def_files/def_files.h"
#include "globalincs/version.h"
#include "mod_table/mod_table.h"
#include "scripting/api/objs/asteroid.h"
#include "scripting/api/objs/beam.h"
#include "scripting/api/objs/debris.h"
@@ -17,6 +17,8 @@
#include "scripting/api/objs/ship.h"
#include "scripting/api/objs/waypoint.h"
#include "scripting/api/objs/weapon.h"
#include "scripting/lua/LuaFunction.h"
#include "ship/ship.h"
namespace {
using namespace scripting;
@@ -277,6 +279,12 @@ const ade_table_entry& ade_manager::getEntry(size_t idx) const {
ade_table_entry::ade_table_entry() { memset(Subentries, 0, sizeof(Subentries)); }
//Think of n_mtb_ldx as the parent metatable
int ade_table_entry::SetTable(lua_State* L, int p_amt_ldx, int p_mtb_ldx) {
if (DeprecationVersion.isValid() &&
mod_supports_version(DeprecationVersion.major, DeprecationVersion.minor, DeprecationVersion.build)) {
// The deprecation mechanism. Do not set this or any of its children if we are past the deprecation version
return 1;
}
uint i;
int cleanup_items = 0;
int mtb_ldx = INT_MAX;
@@ -626,12 +634,23 @@ void ade_table_entry::OutputMeta(FILE *fp)
fprintf(fp, "<dd>%s</dd>\n", Description);
}
//***Result: ReturnDescription
if(ReturnDescription != NULL) {
fprintf(fp, "<dd><b>Returns:</b> %s<br>&nbsp;</dd>\n", ReturnDescription);
} else {
fputs("<dd><b>Returns:</b> Nothing<br>&nbsp;</dd>\n", fp);
}
if (DeprecationVersion.isValid()) {
if (DeprecationMessage != nullptr) {
fprintf(fp, "<dd><b>Deprecated starting with version %d.%d.%d:</b> %s</dd>\n",
DeprecationVersion.major, DeprecationVersion.minor, DeprecationVersion.build,
DeprecationMessage);
} else {
fprintf(fp, "<dd><b>Deprecated starting with version %d.%d.%d.</b></dd>\n",
DeprecationVersion.major, DeprecationVersion.minor, DeprecationVersion.build);
}
}
//***Result: ReturnDescription
if (ReturnDescription != nullptr) {
fprintf(fp, "<dd><b>Returns:</b> %s<br>&nbsp;</dd>\n", ReturnDescription);
} else {
fputs("<dd><b>Returns:</b> Nothing<br>&nbsp;</dd>\n", fp);
}
}
break;
default:
@@ -723,13 +742,10 @@ const char *ade_lib::GetName() const
return getTableEntry(GetIdx()).GetName();
}
ade_func::ade_func(const char* name,
lua_CFunction func,
const ade_lib_handle& parent,
const char* args,
const char* desc,
const char* ret_type,
const char* ret_desc) {
ade_func::ade_func(const char* name, lua_CFunction func, const ade_lib_handle& parent, const char* args,
const char* desc, const char* ret_type, const char* ret_desc,
const gameversion::version& deprecation_version, const char* deprecation_message)
{
Assertion(strcmp(name, "__gc") != 0, "__gc is a reserved function name! An API function may not use it!");
ade_table_entry ate;
@@ -742,17 +758,16 @@ ade_func::ade_func(const char* name,
ate.Description = desc;
ate.ReturnType = ret_type;
ate.ReturnDescription = ret_desc;
ate.DeprecationVersion = deprecation_version;
ate.DeprecationMessage = deprecation_message;
LibIdx = ade_manager::getInstance()->getEntry(parent.GetIdx()).AddSubentry(ate);
}
ade_virtvar::ade_virtvar(const char* name,
lua_CFunction func,
const ade_lib_handle& parent,
const char* args,
const char* desc,
const char* ret_type,
const char* ret_desc) {
ade_virtvar::ade_virtvar(const char* name, lua_CFunction func, const ade_lib_handle& parent, const char* args,
const char* desc, const char* ret_type, const char* ret_desc,
const gameversion::version& deprecation_version, const char* deprecation_message)
{
Assertion(strcmp(name, "__gc") != 0, "__gc is a reserved function name! An API function may not use it!");
ade_table_entry ate;
@@ -765,6 +780,8 @@ ade_virtvar::ade_virtvar(const char* name,
ate.Description = desc;
ate.ReturnType = ret_type;
ate.ReturnDescription = ret_desc;
ate.DeprecationVersion = deprecation_version;
ate.DeprecationMessage = deprecation_message;
LibIdx = ade_manager::getInstance()->getEntry(parent.GetIdx()).AddSubentry(ate);
}
+3 -2
View File
@@ -5,8 +5,7 @@
#define FS2_OPEN_ADE_H
#include "globalincs/pstypes.h"
#include "platformChecks.h"
#include <utility>
#include "globalincs/version.h"
extern "C" {
#include <lauxlib.h>
@@ -123,6 +122,8 @@ class ade_table_entry {
const char* Description = nullptr;
const char* ReturnType = nullptr;
const char* ReturnDescription = nullptr;
gameversion::version DeprecationVersion;
const char* DeprecationMessage = nullptr;
//Subentries, of course
//WMC - I have HAD it with these motherfriendly vectors
+57 -6
View File
@@ -4,6 +4,7 @@
#ifndef FS2_OPEN_ADE_API_H_H
#define FS2_OPEN_ADE_API_H_H
#include "globalincs/version.h"
#include "scripting/ade.h"
#include "scripting/ade_args.h"
@@ -227,8 +228,9 @@ class ade_lib : public ade_lib_handle {
*/
class ade_func : public ade_lib_handle {
public:
ade_func(const char* name, lua_CFunction func, const ade_lib_handle& parent, const char* args = nullptr,
const char* desc = nullptr, const char* ret_type = nullptr, const char* ret_desc = nullptr);
ade_func(const char* name, lua_CFunction func, const ade_lib_handle& parent, const char* args, const char* desc,
const char* ret_type, const char* ret_desc, const gameversion::version& deprecation_version,
const char* deprecation_message);
};
/**
@@ -247,7 +249,31 @@ class ade_func : public ade_lib_handle {
*/
#define ADE_FUNC(name, parent, args, desc, ret_type, ret_desc) \
static int parent##_##name##_f(lua_State* L); \
::scripting::ade_func parent##_##name(#name, parent##_##name##_f, parent, args, desc, ret_type, ret_desc); \
::scripting::ade_func parent##_##name(#name, parent##_##name##_f, parent, args, desc, ret_type, ret_desc, \
::gameversion::version(), nullptr); \
static int parent##_##name##_f(lua_State* L)
/**
* @brief Declare a deprecated API function
*
* Immediately after this macro the function body should follow. This function is marked as deprecated and will be
* handled specially if the targetted engine version is higher than the specified version.
*
* @param name The name of the function, this may not be a string
* @param parent The library or object containing this function
* @param args Documentation for parameters of the function
* @param desc Description of what the function does
* @param ret_type The type of the returned value
* @param ret_desc Documentation for the returned value
* @param deprecate_version Version starting from which this function is deprecated.
* @param deprecated_msg Message for the deprecation notice. May be nullptr.
*
* @ingroup ade_api
*/
#define ADE_FUNC_DEPRECATED(name, parent, args, desc, ret_type, ret_desc, deprecate_version, deprecated_msg) \
static int parent##_##name##_f(lua_State* L); \
::scripting::ade_func parent##_##name(#name, parent##_##name##_f, parent, args, desc, ret_type, ret_desc, \
deprecate_version, deprecated_msg); \
static int parent##_##name##_f(lua_State* L)
/**
@@ -255,8 +281,9 @@ class ade_func : public ade_lib_handle {
*/
class ade_virtvar : public ade_lib_handle {
public:
ade_virtvar(const char* name, lua_CFunction func, const ade_lib_handle& parent, const char* args = nullptr,
const char* desc = nullptr, const char* ret_type = nullptr, const char* ret_desc = nullptr);
ade_virtvar(const char* name, lua_CFunction func, const ade_lib_handle& parent, const char* args, const char* desc,
const char* ret_type, const char* ret_desc, const gameversion::version& deprecation_version,
const char* deprecation_message);
};
/**
@@ -276,7 +303,31 @@ class ade_virtvar : public ade_lib_handle {
*/
#define ADE_VIRTVAR(name, parent, args, desc, ret_type, ret_desc) \
static int parent##_##name##_f(lua_State* L); \
::scripting::ade_virtvar parent##_##name(#name, parent##_##name##_f, parent, args, desc, ret_type, ret_desc); \
::scripting::ade_virtvar parent##_##name(#name, parent##_##name##_f, parent, args, desc, ret_type, ret_desc, \
::gameversion::version(), nullptr); \
static int parent##_##name##_f(lua_State* L)
/**
* @brief Declare a deprecated API variable
*
* Use this to handle forms of type vec.x and vec['x']. Basically an indexer for a specific variable. Format string
* should be "o*%", where * is indexing value, and % is the value to set to when LUA_SETTTING_VAR is set
*
* @param name The name of the variable, this may not be a string
* @param parent The library or object containing this field
* @param args Documentation for the type of the value that may be assigned
* @param desc Description of what the variable does
* @param ret_type The type of the returned value
* @param ret_desc Documentation for the returned value
* @param deprecate_version Version starting from which this function is deprecated.
* @param deprecated_msg Message for the deprecation notice. May be nullptr.
*
* @ingroup ade_api
*/
#define ADE_VIRTVAR_DEPRECATED(name, parent, args, desc, ret_type, ret_desc, deprecate_version, deprecated_msg) \
static int parent##_##name##_f(lua_State* L); \
::scripting::ade_virtvar parent##_##name(#name, parent##_##name##_f, parent, args, desc, ret_type, ret_desc, \
deprecate_version, deprecated_msg); \
static int parent##_##name##_f(lua_State* L)
/**
+138
View File
@@ -2,16 +2,19 @@
//
#include "graphics.h"
#include "scripting/api/objs/camera.h"
#include "scripting/api/objs/enums.h"
#include "scripting/api/objs/font.h"
#include "scripting/api/objs/model.h"
#include "scripting/api/objs/movie_player.h"
#include "scripting/api/objs/object.h"
#include "scripting/api/objs/particle.h"
#include "scripting/api/objs/streaminganim.h"
#include "scripting/api/objs/subsystem.h"
#include "scripting/api/objs/texture.h"
#include "scripting/api/objs/vecmath.h"
#include <asteroid/asteroid.h>
#include <camera/camera.h>
#include <debris/debris.h>
@@ -1588,5 +1591,140 @@ ADE_FUNC(openMovie, l_Graphics, "string name, boolean looping = false",
return ade_set_args(L, "o", l_MoviePlayer.Set(movie_player_h(std::move(player))));
}
ADE_FUNC(createPersistentParticle, l_Graphics,
"vector Position, vector Velocity, number Lifetime, number Radius, enumeration Type, [number Tracer "
"length=-1, boolean Reverse=false, texture Texture=Nil, object Attached Object=Nil]",
"Creates a persistent particle. Persistent variables are handled specially by the engine so that this "
"function can return a handle to the caller. Only use this if you absolutely need it. Use createParticle if "
"the returned handle is not required. Use PARTICLE_* enumerations for type."
"Reverse reverse animation, if one is specified"
"Attached object specifies object that Position will be (and always be) relative to.",
"particle", "Handle to the created particle")
{
particle::particle_info pi;
pi.type = particle::PARTICLE_DEBUG;
pi.optional_data = -1;
pi.attached_objnum = -1;
pi.attached_sig = -1;
pi.reverse = false;
// Need to consume tracer_length parameter but it isn't used anymore
float temp;
enum_h* type = nullptr;
bool rev = false;
object_h* objh = nullptr;
texture_h* texture = nullptr;
if (!ade_get_args(L, "ooffo|fboo", l_Vector.Get(&pi.pos), l_Vector.Get(&pi.vel), &pi.lifetime, &pi.rad,
l_Enum.GetPtr(&type), &temp, &rev, l_Texture.GetPtr(&texture), l_Object.GetPtr(&objh)))
return ADE_RETURN_NIL;
if (type != nullptr) {
switch (type->index) {
case LE_PARTICLE_DEBUG:
pi.type = particle::PARTICLE_DEBUG;
break;
case LE_PARTICLE_FIRE:
pi.type = particle::PARTICLE_FIRE;
break;
case LE_PARTICLE_SMOKE:
pi.type = particle::PARTICLE_SMOKE;
break;
case LE_PARTICLE_SMOKE2:
pi.type = particle::PARTICLE_SMOKE2;
break;
case LE_PARTICLE_BITMAP:
if (texture == nullptr || !texture->isValid()) {
LuaError(L, "Invalid texture specified for createParticle()!");
return ADE_RETURN_NIL;
} else {
pi.optional_data = texture->handle;
pi.type = particle::PARTICLE_BITMAP;
}
break;
}
}
if (rev)
pi.reverse = false;
if (objh != nullptr && objh->IsValid()) {
pi.attached_objnum = OBJ_INDEX(objh->objp);
pi.attached_sig = objh->objp->signature;
}
particle::WeakParticlePtr p = particle::createPersistent(&pi);
if (!p.expired())
return ade_set_args(L, "o", l_Particle.Set(particle_h(p)));
else
return ADE_RETURN_NIL;
}
ADE_FUNC(createParticle, l_Graphics,
"vector Position, vector Velocity, number Lifetime, number Radius, enumeration Type, [number Tracer "
"length=-1, boolean Reverse=false, texture Texture=Nil, object Attached Object=Nil]",
"Creates a non-persistent particle. Use PARTICLE_* enumerations for type."
"Reverse reverse animation, if one is specified"
"Attached object specifies object that Position will be (and always be) relative to.",
"boolean", "true if particle was created, false otherwise")
{
particle::particle_info pi;
pi.type = particle::PARTICLE_DEBUG;
pi.optional_data = -1;
pi.attached_objnum = -1;
pi.attached_sig = -1;
pi.reverse = false;
// Need to consume tracer_length parameter but it isn't used anymore
float temp;
enum_h* type = nullptr;
bool rev = false;
object_h* objh = nullptr;
texture_h* texture = nullptr;
if (!ade_get_args(L, "ooffo|fboo", l_Vector.Get(&pi.pos), l_Vector.Get(&pi.vel), &pi.lifetime, &pi.rad,
l_Enum.GetPtr(&type), &temp, &rev, l_Texture.GetPtr(&texture), l_Object.GetPtr(&objh)))
return ADE_RETURN_FALSE;
if (type != nullptr) {
switch (type->index) {
case LE_PARTICLE_DEBUG:
pi.type = particle::PARTICLE_DEBUG;
break;
case LE_PARTICLE_FIRE:
pi.type = particle::PARTICLE_FIRE;
break;
case LE_PARTICLE_SMOKE:
pi.type = particle::PARTICLE_SMOKE;
break;
case LE_PARTICLE_SMOKE2:
pi.type = particle::PARTICLE_SMOKE2;
break;
case LE_PARTICLE_BITMAP:
if (texture == nullptr || !texture->isValid()) {
LuaError(L, "Invalid texture specified for createParticle()!");
return ADE_RETURN_NIL;
} else {
pi.optional_data = texture->handle;
pi.type = particle::PARTICLE_BITMAP;
}
break;
}
}
if (rev)
pi.reverse = false;
if (objh != nullptr && objh->IsValid()) {
pi.attached_objnum = OBJ_INDEX(objh->objp);
pi.attached_sig = objh->objp->signature;
}
particle::create(&pi);
return ADE_RETURN_TRUE;
}
} // namespace api
} // namespace scripting
+8 -6
View File
@@ -56,12 +56,14 @@ ADE_FUNC(avdTest, l_Testing, NULL, "Test the AVD Physics code", NULL, NULL)
return ADE_RETURN_NIL;
}
ADE_FUNC(createParticle, l_Testing, "vector Position, vector Velocity, number Lifetime, number Radius, enumeration Type, [number Tracer length=-1, boolean Reverse=false, texture Texture=Nil, object Attached Object=Nil]",
"Creates a particle. Use PARTICLE_* enumerations for type."
"Reverse reverse animation, if one is specified"
"Attached object specifies object that Position will be (and always be) relative to.",
"particle",
"Handle to the created particle")
ADE_FUNC_DEPRECATED(createParticle, l_Testing,
"vector Position, vector Velocity, number Lifetime, number Radius, enumeration Type, [number "
"Tracer length=-1, boolean Reverse=false, texture Texture=Nil, object Attached Object=Nil]",
"Creates a particle. Use PARTICLE_* enumerations for type."
"Reverse reverse animation, if one is specified"
"Attached object specifies object that Position will be (and always be) relative to.",
"particle", "Handle to the created particle", gameversion::version(19, 0, 0, 0),
"Not available in the testing library anymore. Use gr.createPersistentParticle instead.")
{
particle::particle_info pi;
pi.type = particle::PARTICLE_DEBUG;
+52 -46
View File
@@ -757,6 +757,11 @@ static int lightningtype_match(char *p)
#define SHIP_MULTITEXT_LENGTH 4096
#define DEFAULT_DELTA_BANK_CONST 0.5f
const float DEFAULT_ASK_HELP_SHIELD_PERCENT = 0.1f; // percent shields at which ship will ask for help
const float DEFAULT_ASK_HELP_HULL_PERCENT = 0.3f; // percent hull at which ship will ask for help
const float AWACS_HELP_HULL_HI = 0.75f; // percent hull at which ship will ask for help
const float AWACS_HELP_HULL_LOW = 0.25f; // percent hull at which ship will ask for help
#define CHECK_THEN_COPY(attribute) \
do {\
if (other.attribute != NULL)\
@@ -965,6 +970,9 @@ void ship_info::clone(const ship_info& other)
scan_range_normal = other.scan_range_normal;
scan_range_capital = other.scan_range_capital;
ask_help_shield_percent = other.ask_help_shield_percent;
ask_help_hull_percent = other.ask_help_hull_percent;
memcpy(ct_info, other.ct_info, sizeof(trail_info) * MAX_SHIP_CONTRAILS);
ct_count = other.ct_count;
@@ -1244,6 +1252,9 @@ void ship_info::move(ship_info&& other)
scan_range_normal = other.scan_range_normal;
scan_range_capital = other.scan_range_capital;
ask_help_shield_percent = other.ask_help_shield_percent;
ask_help_hull_percent = other.ask_help_hull_percent;
std::swap(ct_info, other.ct_info);
ct_count = other.ct_count;
@@ -1625,6 +1636,9 @@ ship_info::ship_info()
scan_range_normal = CARGO_REVEAL_MIN_DIST;
scan_range_capital = CAP_CARGO_REVEAL_MIN_DIST;
ask_help_shield_percent = DEFAULT_ASK_HELP_SHIELD_PERCENT;
ask_help_hull_percent = DEFAULT_ASK_HELP_HULL_PERCENT;
memset(&ct_info, 0, sizeof(trail_info) * MAX_SHIP_CONTRAILS);
ct_count = 0;
@@ -3561,6 +3575,28 @@ static int parse_ship_values(ship_info* sip, const bool is_template, const bool
if(optional_string("$Scan range Capital:"))
stuff_float(&sip->scan_range_capital);
if (optional_string("$Ask Help Shield Percent:")) {
float help_shield_val;
stuff_float(&help_shield_val);
if (help_shield_val > 0.0f && help_shield_val <= 1.0f) {
sip->ask_help_shield_percent = help_shield_val;
} else {
error_display(0,"Ask Help Shield Percent for ship class %s is %f. This value is not within range of 0-1.0."
"Assuming default value of %f.", sip->name, help_shield_val, DEFAULT_ASK_HELP_SHIELD_PERCENT);
}
}
if (optional_string("$Ask Help Hull Percent:")) {
float help_hull_val;
stuff_float(&help_hull_val);
if (help_hull_val > 0.0f && help_hull_val <= 1.0f) {
sip->ask_help_shield_percent = help_hull_val;
} else {
error_display(0,"Ask Help Hull Percent for ship class %s is %f. This value is not within range of 0-1.0."
"Assuming default value of %f.", sip->name, help_hull_val, DEFAULT_ASK_HELP_HULL_PERCENT);
}
}
//Parse the engine sound
parse_game_sound("$EngineSnd:", &sip->engine_snd);
@@ -6827,8 +6863,8 @@ void ship_render_show_ship_cockpit(object *objp)
vec3d cockpit_eye_pos;
matrix dummy;
ship_get_eye(&cockpit_eye_pos, &dummy, objp, true, false); //Get cockpit eye position
ship_get_eye(&cockpit_eye_pos, &dummy, objp, true, false); // Get cockpit eye position
gr_end_view_matrix();
gr_end_proj_matrix();
gr_set_proj_matrix(Proj_fov, gr_screen.clip_aspect, 0.05f, Max_draw_distance);
@@ -6841,7 +6877,9 @@ void ship_render_show_ship_cockpit(object *objp)
render_info.set_object_number(OBJ_INDEX(objp));
render_info.set_detail_level_lock(0);
model_render_immediate(&render_info, Ship_info[Ships[objp->instance].ship_info_index].model_num, &objp->orient, &objp->pos); // Render ship model with fixed detail level 0 so its not switching LOD when moving away from origin
model_render_immediate(&render_info, Ship_info[Ships[objp->instance].ship_info_index].model_num, &objp->orient,
&objp->pos); // Render ship model with fixed detail level 0 so its not switching LOD when
// moving away from origin
Glowpoint_override = false;
gr_end_view_matrix();
@@ -7326,6 +7364,7 @@ void ship_cleanup(int shipnum, int cleanup_mode)
ship *shipp = &Ships[shipnum];
object *objp = &Objects[shipp->objnum];
char *jumpnode_name = nullptr;
// add the information to the exited ship list
switch (cleanup_mode) {
@@ -7366,14 +7405,14 @@ void ship_cleanup(int shipnum, int cleanup_mode)
// add mission log entry?
// (vanished ships and red-alert deleted ships have no log, and destroyed ships are logged in ship_hit_kill)
if ((cleanup_mode == SHIP_DEPARTED_WARP) || (cleanup_mode == SHIP_DEPARTED_BAY) || (cleanup_mode == SHIP_DEPARTED)) {\
if ((cleanup_mode == SHIP_DEPARTED_WARP) || (cleanup_mode == SHIP_DEPARTED_BAY) || (cleanup_mode == SHIP_DEPARTED)) {
// see if this ship departed within the radius of a jump node -- if so, put the node name into
// the secondary mission log field
CJumpNode *jnp = jumpnode_get_which_in(objp);
if(jnp==NULL)
mission_log_add_entry(LOG_SHIP_DEPARTED, shipp->ship_name, NULL, shipp->wingnum);
else
mission_log_add_entry(LOG_SHIP_DEPARTED, shipp->ship_name, jnp->GetName(), shipp->wingnum);
if (jnp != nullptr)
jumpnode_name = jnp->GetName();
mission_log_add_entry(LOG_SHIP_DEPARTED, shipp->ship_name, jumpnode_name, shipp->wingnum);
}
// run "On Ship Depart" conditional hook variable that accounts for all departure types
@@ -7384,8 +7423,9 @@ void ship_cleanup(int shipnum, int cleanup_mode)
const char* departmethod = get_departure_name(cleanup_mode);
Script_system.SetHookObject("Ship", objp);
Script_system.SetHookVar("Method", 's', departmethod);
Script_system.SetHookVar("JumpNode", 's', jumpnode_name);
Script_system.RunCondition(CHA_ONSHIPDEPART);
Script_system.RemHookVars(2, "Ship", "Method");
Script_system.RemHookVars(3, "Ship", "Method", "JumpNode");
}
#ifndef NDEBUG
@@ -12710,36 +12750,6 @@ int ship_type_name_lookup(const char *name)
return -1;
}
// checks the (arrival & departure) state of a ship. Return values:
// -1: has yet to arrive in mission
// 0: is currently in mission
// 1: has been destroyed, departed, or never existed
int ship_query_state(char *name)
{
int i;
// bogus
Assert(name != NULL);
if(name == NULL){
return -1;
}
for (i=0; i<MAX_SHIPS; i++){
if (Ships[i].objnum >= 0){
if ((Objects[Ships[i].objnum].type == OBJ_SHIP) || (Objects[Ships[i].objnum].type == OBJ_START)){
if (!stricmp(name, Ships[i].ship_name)){
return 0;
}
}
}
}
if (mission_parse_get_arrival_ship(name))
return -1;
return 1;
}
// Finds the world position of a subsystem.
// Return true/false for subsystem found/not found.
// Stuff vector *pos with absolute position.
@@ -15403,11 +15413,6 @@ void ship_maybe_praise_self(ship *deader_sp, ship *killer_sp)
Player->praise_self_count++;
}
#define ASK_HELP_SHIELD_PERCENT 0.1 // percent shields at which ship will ask for help
#define ASK_HELP_HULL_PERCENT 0.3 // percent hull at which ship will ask for help
#define AWACS_HELP_HULL_HI 0.75 // percent hull at which ship will ask for help
#define AWACS_HELP_HULL_LOW 0.25 // percent hull at which ship will ask for help
// -----------------------------------------------------------------------------
static void awacs_maybe_ask_for_help(ship *sp, int multi_team_filter)
{
@@ -15446,6 +15451,7 @@ void ship_maybe_ask_for_help(ship *sp)
{
object *objp;
int multi_team_filter = -1;
ship_info* sip = &Ship_info[sp->ship_info_index];
// First check if the player has reached the maximum number of ask_help's for a mission
if ((Builtin_messages[MESSAGE_HELP].max_count > -1) && (Player->ask_help_count >= Builtin_messages[MESSAGE_HELP].max_count))
@@ -15481,14 +15487,14 @@ void ship_maybe_ask_for_help(ship *sp)
return;
// first check if hull is at a critical level
if (objp->hull_strength < ASK_HELP_HULL_PERCENT * sp->ship_max_hull_strength)
if (objp->hull_strength < sip->ask_help_hull_percent * sp->ship_max_hull_strength)
goto play_ask_help;
// check if shields are near critical level
if (objp->flags[Object::Object_Flags::No_shields])
return; // no shields on ship, no don't check shield levels
if (shield_get_strength(objp) > (ASK_HELP_SHIELD_PERCENT * shield_get_max_strength(objp)))
if (shield_get_strength(objp) > (sip->ask_help_shield_percent * shield_get_max_strength(objp)))
return;
play_ask_help:
+3 -2
View File
@@ -1106,6 +1106,9 @@ public:
float scan_range_normal; // this ship can scan other normal/small ships at this range
float scan_range_capital; // this ship can scan other capital/large ships at this range
float ask_help_shield_percent;
float ask_help_hull_percent;
// contrail info
trail_info ct_info[MAX_SHIP_CONTRAILS];
int ct_count;
@@ -1522,8 +1525,6 @@ extern int ship_query_general_type(ship *shipp);
extern int ship_docking_valid(int docker, int dockee);
extern int get_quadrant(vec3d *hit_pnt, object *shipobjp = NULL); // Return quadrant num of given hit point.
extern int ship_query_state(char *name);
int ship_secondary_bank_has_ammo(int shipnum); // check if current secondary bank has ammo
int ship_engine_ok_to_warp(ship *sp); // check if ship has engine power to warp
+3 -23
View File
@@ -213,27 +213,6 @@ static void shipfx_subsystem_maybe_create_live_debris(object *ship_objp, ship *s
}
}
static void set_ship_submodel_as_blown_off(ship *shipp, const char *name)
{
int found = FALSE;
// go through list of ship subsystems and find name
ship_subsys *pss = NULL;
for (pss=GET_FIRST(&shipp->subsys_list); pss!=END_OF_LIST(&shipp->subsys_list); pss=GET_NEXT(pss)) {
if ( subsystem_stricmp(pss->system_info->subobj_name, name) == 0) {
found = TRUE;
break;
}
}
// set its blown off flag to TRUE
Assert(found);
if (found) {
pss->submodel_info_1.blown_off = 1;
}
}
/**
* Create debris for ship submodel which has live debris (at ship death)
* when ship submodel has not already been blown off (and hence liberated live debris)
@@ -284,8 +263,8 @@ static void shipfx_maybe_create_live_debris_at_ship_death( object *ship_objp )
shipfx_subsystem_maybe_create_live_debris(ship_objp, shipp, pss, &exp_center, 3.0f);
// now set subsystem as blown off, so we only get one copy
pm->submodel[parent].blown_off = 1;
set_ship_submodel_as_blown_off(&Ships[ship_objp->instance], pss->system_info->subobj_name);
pmi->submodel[parent].blown_off = true;
pss->submodel_info_1.blown_off = 1;
}
}
}
@@ -1683,6 +1662,7 @@ void shipfx_queue_render_ship_halves_and_debris(model_draw_list *scene, clip_shi
render_info.set_flags(render_flags);
render_info.set_clip_plane(model_clip_plane_pt, clip_plane_norm);
render_info.set_replacement_textures(shipp->ship_replacement_textures);
render_info.set_object_number(shipp->objnum);
model_render_queue(&render_info, scene, pm->id, &half_ship->orient, &orig_ship_world_center);
}
+31 -5
View File
@@ -108,10 +108,13 @@ static bool is_subsys_destroyed(ship *shipp, int submodel)
// do_subobj_destroyed_stuff is called when a subobject for a ship is killed. Separated out
// to separate function on 10/15/97 by MWA for easy multiplayer access. It does all of the
// cool things like blowing off the model (if applicable, writing the logs, etc)
// NOTE: if this function is used with ship_recalc_subsys_strength, it MUST be called first. If
// a child subsystem needs to be destroyed, the strength calculation needs to take it into account.
void do_subobj_destroyed_stuff( ship *ship_p, ship_subsys *subsys, vec3d* hitpos, bool no_explosion )
{
ship_info *sip;
object *ship_objp;
ship_subsys *ssp;
model_subsystem *psub;
vec3d g_subobj_pos;
int type, i, log_index;
@@ -123,6 +126,27 @@ void do_subobj_destroyed_stuff( ship *ship_p, ship_subsys *subsys, vec3d* hitpos
type = psub->type;
get_subsystem_world_pos(ship_objp, subsys, &g_subobj_pos);
// see if this subsystem is on a submodel
if (psub->subobj_num >= 0) {
polymodel *pm = model_get(sip->model_num);
// see if there are any subsystems which have this submodel as a parent
for (ssp = GET_FIRST(&ship_p->subsys_list); ssp != END_OF_LIST(&ship_p->subsys_list); ssp = GET_NEXT(ssp)) {
// is it another subsys which has a submodel?
if (ssp != subsys && ssp->system_info->subobj_num >= 0) {
// is this other submodel a child of the one being destroyed?
if (pm->submodel[ssp->system_info->subobj_num].parent == psub->subobj_num) {
// is it not yet destroyed? (this is a valid check because we already know there is a submodel)
if (!ssp->submodel_info_1.blown_off) {
// then destroy it first
ssp->current_hits = 0;
do_subobj_destroyed_stuff(ship_p, ssp, nullptr, no_explosion);
}
}
}
}
}
// create fireballs when subsys destroy for large ships.
object* objp = &Objects[ship_p->objnum];
@@ -192,10 +216,8 @@ void do_subobj_destroyed_stuff( ship *ship_p, ship_subsys *subsys, vec3d* hitpos
if ( ship_p->subsys_info[type].type_count == 1 ) {
ship_p->subsys_info[type].aggregate_current_hits = 0.0f;
} else {
float hits;
ship_subsys *ssp;
float hits = 0.0f;
hits = 0.0f;
for ( ssp=GET_FIRST(&ship_p->subsys_list); ssp != END_OF_LIST(&ship_p->subsys_list); ssp = GET_NEXT(ssp) ) {
// type matches?
if ( (ssp->system_info->type == type) && !(ssp->flags[Ship::Subsystem_Flags::No_aggregate]) ) {
@@ -652,10 +674,9 @@ float do_subobj_hit_stuff(object *ship_objp, object *other_obj, vec3d *hitpos, i
min_index = i;
}
}
Assert(min_index != -1);
}
Assert(min_index != -1);
float damage_to_apply = 0.0f;
subsystem = subsys_list[min_index].ptr;
range = subsys_list[min_index].range;
@@ -664,6 +685,11 @@ float do_subobj_hit_stuff(object *ship_objp, object *other_obj, vec3d *hitpos, i
Assert(range > 0.0f); // Goober5000 - avoid div-0 below
// Make sure this subsystem still has hitpoints. If it's a child of a parent that was destroyed, it will have been destroyed already.
if (subsystem->current_hits <= 0.0f) {
continue;
}
// only do this for the closest affected subsystem
if ( (j == 0) && (!(parent_armor_flags & SAF_IGNORE_SS_ARMOR))) {
if(subsystem->armor_type_idx > -1)
+11 -4
View File
@@ -62,8 +62,6 @@ add_file_folder("CFile"
cfile/cfilearchive.cpp
cfile/cfilearchive.h
cfile/cfilelist.cpp
cfile/cfilemod.cpp
cfile/cfilemod.h
cfile/cfilesystem.cpp
cfile/cfilesystem.h
)
@@ -199,11 +197,18 @@ add_file_folder("Default files\\\\data\\\\effects"
def_files/data/effects/shadowdebug-f.sdr
def_files/data/effects/shadowdebug-v.sdr
def_files/data/effects/shadows.sdr
def_files/data/effects/shield-impact-v.sdr
def_files/data/effects/shield-impact-f.sdr
def_files/data/effects/SMAA.sdr
def_files/data/effects/smaa-blend-v.sdr
def_files/data/effects/smaa-blend-f.sdr
def_files/data/effects/smaa-edge-v.sdr
def_files/data/effects/smaa-edge-f.sdr
def_files/data/effects/smaa-neighbour-v.sdr
def_files/data/effects/smaa-neighbour-f.sdr
def_files/data/effects/tonemapping-f.sdr
def_files/data/effects/video-f.sdr
def_files/data/effects/video-v.sdr
def_files/data/effects/shield-impact-v.sdr
def_files/data/effects/shield-impact-f.sdr
)
add_file_folder("Default files\\\\data\\\\maps"
@@ -408,6 +413,8 @@ add_file_folder("Graphics\\\\OpenGLGr\\\\OpenGL Headers"
graphics/opengl/gropengltexture.h
graphics/opengl/gropengltnl.h
graphics/opengl/ShaderProgram.h
graphics/opengl/SmaaAreaTex.h
graphics/opengl/SmaaSearchTex.h
)
# Graphics -> Paths
+5
View File
@@ -25,6 +25,11 @@ Category BloomBrightPass("Bloom bright pass", true);
Category BloomIterationStep("Bloom iteration step", true);
Category BloomCompositeStep("Bloom composite step", true);
Category FXAA("FXAA", true);
Category SMAA("SMAA", true);
Category SMAAEdgeDetection("SMAA Edge Detection", true);
Category SMAACalculateBlendingWeights("SMAA Calculate BLending Weights", true);
Category SMAANeighborhoodBlending("SMAA Neighborhood Blending", true);
Category SMAAResolve("SMAA Resolve", true);
Category Lightshafts("Lightshafts", true);
Category DrawPostEffects("Draw post effects", true);
+5
View File
@@ -37,6 +37,11 @@ extern Category BloomBrightPass;
extern Category BloomIterationStep;
extern Category BloomCompositeStep;
extern Category FXAA;
extern Category SMAA;
extern Category SMAAEdgeDetection;
extern Category SMAACalculateBlendingWeights;
extern Category SMAANeighborhoodBlending;
extern Category SMAAResolve;
extern Category Lightshafts;
extern Category DrawPostEffects;
+10 -10
View File
@@ -8,23 +8,23 @@
#include <utility>
#if HAVE_STRCASECMP || HAVE_STRNCASECMP
#if HAVE_STRINGS_H
#if SCP_HAVE_STRCASECMP || SCP_HAVE_STRNCASECMP
#if SCP_HAVE_STRINGS_H
#include <strings.h>
#else
#error strings.h is not available!
#endif
#endif
#if HAVE__STRICMP || HAVE__STRNICMP || HAVE_STRLWR
#if SCP_HAVE__STRICMP || SCP_HAVE__STRNICMP || SCP_HAVE_STRLWR
#include <string.h>
#endif
#if HAVE_STRCASECMP
#if SCP_HAVE_STRCASECMP
inline int stricmp(const char* s1, const char* s2) {
return strcasecmp(s1, s2);
}
#elif HAVE__STRICMP
#elif SCP_HAVE__STRICMP
inline int stricmp(const char* s1, const char* s2) {
return _stricmp(s1, s2);
}
@@ -32,11 +32,11 @@ inline int stricmp(const char* s1, const char* s2) {
#error No case insensitive string comparision available!
#endif
#if HAVE_STRNCASECMP
#if SCP_HAVE_STRNCASECMP
inline int strnicmp(const char* s1, const char* s2, size_t n) {
return strncasecmp(s1, s2, n);
}
#elif HAVE__STRNICMP
#elif SCP_HAVE__STRNICMP
inline int strnicmp(const char* s1, const char* s2, size_t n) {
return _strnicmp(s1, s2, n);
}
@@ -44,7 +44,7 @@ inline int strnicmp(const char* s1, const char* s2, size_t n) {
#error No case insensitive string comparision available!
#endif
#if !HAVE_STRLWR
#if !SCP_HAVE_STRLWR
inline void strlwr(char *s) {
if (s == NULL)
return;
@@ -56,8 +56,8 @@ inline void strlwr(char *s) {
}
#endif
#if !HAVE_SNPRINTF
#if HAVE__SNPRINTF
#if !SCP_HAVE_SNPRINTF
#if SCP_HAVE__SNPRINTF
#define snprintf _snprintf
#else
#error No support for snprintf detected!
+5 -5
View File
@@ -19,15 +19,15 @@
#include <CoreFoundation/CoreFoundation.h>
#endif
#if defined(HAVE_MALLOC_H)
#if defined(SCP_HAVE_MALLOC_H)
#include <malloc.h>
#endif
#ifdef HAVE_EXECINFO_H
#ifdef SCP_HAVE_EXECINFO_H
#include <execinfo.h>
#endif
#ifdef HAVE_CXXAPI_H
#ifdef SCP_HAVE_CXXAPI_H
#include <cxxabi.h>
#endif
@@ -49,7 +49,7 @@ int filelength(int fd)
SCP_string dump_stacktrace()
{
#ifdef HAVE_EXECINFO_H
#ifdef SCP_HAVE_EXECINFO_H
// The following is adapted from here: https://panthema.net/2008/0901-stacktrace-demangled/
const int ADDR_SIZE = 64;
void *addresses[ADDR_SIZE];
@@ -71,7 +71,7 @@ SCP_string dump_stacktrace()
// Demangle c++ function names to a more readable format using the ABI functions
// TODO: Maybe add configure time checks to check if the required features are available
SCP_stringstream stackstream;
#ifdef HAVE_CXXAPI_H
#ifdef SCP_HAVE_CXXAPI_H
size_t funcnamesize = 256;
char* funcname = reinterpret_cast<char*>(malloc(funcnamesize));
+24 -10
View File
@@ -35,7 +35,6 @@
#include "autopilot/autopilot.h"
#include "bmpman/bmpman.h"
#include "cfile/cfile.h"
#include "cfile/cfilemod.h"
#include "cmdline/cmdline.h"
#include "cmeasure/cmeasure.h"
#include "cutscene/cutscenes.h"
@@ -1685,6 +1684,7 @@ void game_init()
{
int s1 __UNUSED, e1 __UNUSED;
const char *ptr;
char whee[MAX_PATH_LEN];
Game_current_mission_filename[0] = 0;
@@ -1725,11 +1725,17 @@ void game_init()
cmdline_debug_print_cmdline();
#endif
memset(whee, 0, sizeof(whee));
_getcwd(whee, MAX_PATH_LEN-1);
strcat_s(whee, DIR_SEPARATOR_STR);
strcat_s(whee, EXE_FNAME);
//Initialize the libraries
s1 = timer_get_milliseconds();
// initialize before calling any cfopen stuff!!!
if ( cfile_init(Cmdline_mod) ) {
if ( cfile_init(whee, NULL) ) { // initialize before calling any cfopen stuff!!!
exit(1);
}
@@ -5680,17 +5686,17 @@ void game_enter_state( int old_state, int new_state )
// Main_hall_netgame_started = 1;
// main_hall_do_multi_ready();
//} DTP commented out to keep original source
if ( (Cmdline_start_netgame || (!Cmdline_connect_addr.empty())) && (!Main_hall_netgame_started) /*&& (Game_mode == GM_MULTIPLAYER)*/) { // DTP added "&& (game_mode == GM_multiplayer)" so that ppl don't get thrown into Multiplayer with a Singleplayer Pilot.
if ( (Cmdline_start_netgame || (Cmdline_connect_addr != NULL)) && (!Main_hall_netgame_started) /*&& (Game_mode == GM_MULTIPLAYER)*/) { // DTP added "&& (game_mode == GM_multiplayer)" so that ppl don't get thrown into Multiplayer with a Singleplayer Pilot.
Main_hall_netgame_started = 1;
main_hall_do_multi_ready();
}
if(!Cmdline_start_mission.empty()) {
strcpy_s(Game_current_mission_filename, Cmdline_start_mission.c_str());
if(Cmdline_start_mission) {
strcpy_s(Game_current_mission_filename, Cmdline_start_mission);
mprintf(( "Straight to mission '%s'\n", Game_current_mission_filename ));
gameseq_post_event(GS_EVENT_START_GAME);
// This stops the mission from loading again when you go back to the hall
Cmdline_start_mission.clear();
Cmdline_start_mission = NULL;
}
break;
@@ -6732,6 +6738,7 @@ int game_main(int argc, char *argv[])
tmp_mem = NULL;
#endif // _WIN32
if ( !parse_cmdline(argc, argv) ) {
return 1;
}
@@ -6750,10 +6757,10 @@ int game_main(int argc, char *argv[])
game_stop_time();
if (!Cmdline_spew_mission_crcs.empty()) {
if (Cmdline_spew_mission_crcs) {
multi_spew_pxo_checksums(1024, "mission_crcs.csv");
if (!Cmdline_spew_table_crcs.empty()) {
if (Cmdline_spew_table_crcs) {
fs2netd_spew_table_checksums("table_crcs.csv");
}
@@ -6761,7 +6768,7 @@ int game_main(int argc, char *argv[])
return 0;
}
if (!Cmdline_spew_table_crcs.empty()) {
if (Cmdline_spew_table_crcs) {
fs2netd_spew_table_checksums("table_crcs.csv");
game_shutdown();
return 0;
@@ -6958,6 +6965,13 @@ void game_shutdown(void)
cfile_close();
// although the comment in cmdline.cpp said this isn't needed,
// Valgrind disagrees (quite possibly incorrectly), but this is just cleaner
if (Cmdline_mod != NULL) {
delete[] Cmdline_mod;
Cmdline_mod = NULL;
}
lcl_xstr_close();
#if 0 // don't have an updater for fs2_open
+5 -1
View File
@@ -81,8 +81,12 @@ initialize(const std::string& cfilepath, int argc, char* argv[], Editor* editor,
cmdline_debug_print_cmdline();
#endif
// d'oh
// cfile needs a file path...
auto file_path = cfilepath + DIR_SEPARATOR_STR + "qtfred.exe";
listener(SubSystem::CFile);
if (cfile_init(cfilepath.c_str())) {
if (cfile_init(file_path.c_str())) {
return false;
}
+6
View File
@@ -24,6 +24,8 @@ class CFileInitTest : public test::FSTestFixture {
TEST_F(CFileInitTest, wrong_data_case) {
SCP_string cfile_dir(TEST_DATA_PATH);
cfile_dir += DIR_SEPARATOR_CHAR;
cfile_dir += "test"; // Cfile expects something after the path
ASSERT_FALSE(cfile_init(cfile_dir.c_str()));
@@ -32,6 +34,8 @@ TEST_F(CFileInitTest, wrong_data_case) {
TEST_F(CFileInitTest, right_data_case) {
SCP_string cfile_dir(TEST_DATA_PATH);
cfile_dir += DIR_SEPARATOR_CHAR;
cfile_dir += "test"; // Cfile expects something after the path
ASSERT_FALSE(cfile_init(cfile_dir.c_str()));
@@ -125,6 +129,8 @@ TEST(CFileStandalone, test_check_location_flags) {
TEST_F(CFileTest, test_get_path_type)
{
SCP_string cfile_dir(TEST_DATA_PATH);
cfile_dir += DIR_SEPARATOR_CHAR;
cfile_dir += "test"; // Cfile expects something after the path
ASSERT_FALSE(cfile_init(cfile_dir.c_str()));
+2
View File
@@ -33,6 +33,8 @@ void test::FSTestFixture::SetUp() {
if (_initFlags & INIT_CFILE) {
SCP_string cfile_dir(TEST_DATA_PATH);
cfile_dir += DIR_SEPARATOR_CHAR;
cfile_dir += "test"; // Cfile expects something after the path
if (cfile_init(cfile_dir.c_str())) {
FAIL() << "Cfile init failed!";
+5
View File
@@ -0,0 +1,5 @@
set(FSO_VERSION_MAJOR 19)
set(FSO_VERSION_MINOR 0)
set(FSO_VERSION_BUILD 0)
set(FSO_VERSION_REVISION 0)
set(FSO_VERSION_REVISION_STR RC1)