mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-08 17:48:46 -10:00
Compare commits
96
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f5810732a | ||
|
|
f4bfec5029 | ||
|
|
c18f775962 | ||
|
|
608dcb6b44 | ||
|
|
b4b23e266b | ||
|
|
65e2aa88b3 | ||
|
|
fe0c6a629a | ||
|
|
730c62af81 | ||
|
|
13d4ebaceb | ||
|
|
ed6a780898 | ||
|
|
f0b9929cd3 | ||
|
|
f315caad95 | ||
|
|
b5a47e651f | ||
|
|
d49299225c | ||
|
|
3b0bb79d79 | ||
|
|
daacdc0035 | ||
|
|
39df9ef90e | ||
|
|
fc080cccbd | ||
|
|
0c07ad9d71 | ||
|
|
7d329bbbc6 | ||
|
|
17a449529f | ||
|
|
73f0addc42 | ||
|
|
0ba1583d90 | ||
|
|
2436697f2c | ||
|
|
0e10100aad | ||
|
|
60bcdefac0 | ||
|
|
5d8ac3cc11 | ||
|
|
e0bc2f188b | ||
|
|
d13bbdd534 | ||
|
|
44b09d137f | ||
|
|
4439edcb4d | ||
|
|
a9ddeda40e | ||
|
|
d606e4d952 | ||
|
|
2fa8a0bd84 | ||
|
|
f9d178d46b | ||
|
|
989235936e | ||
|
|
6df9c73a4c | ||
|
|
d794eb6e77 | ||
|
|
e5c06c9554 | ||
|
|
bc00b79922 | ||
|
|
e1e86667b3 | ||
|
|
881f787ac8 | ||
|
|
88d5bed064 | ||
|
|
d9b1659efc | ||
|
|
f6408113f2 | ||
|
|
6075c17255 | ||
|
|
da9f71dac0 | ||
|
|
03f1344794 | ||
|
|
59e9d7cb0c | ||
|
|
910595880a | ||
|
|
9f07e43455 | ||
|
|
7b8c156980 | ||
|
|
f8c11ccd2e | ||
|
|
7e36dc8afe | ||
|
|
b1ad89a9fa | ||
|
|
4d9b1a7674 | ||
|
|
72f3871b7b | ||
|
|
7906ff460a | ||
|
|
1eb1923751 | ||
|
|
6d1931bf99 | ||
|
|
f75cb1edd3 | ||
|
|
48586bc857 | ||
|
|
3adb861640 | ||
|
|
7b1f407c22 | ||
|
|
ed5b4b9b5a | ||
|
|
b63ddf08bb | ||
|
|
816d8e5415 | ||
|
|
e7e43e9466 | ||
|
|
48e630dfd1 | ||
|
|
00f2ddc8da | ||
|
|
c6d93275c2 | ||
|
|
e2ce0bea9b | ||
|
|
a98fd2cb54 | ||
|
|
5444e81fab | ||
|
|
83276a355d | ||
|
|
98606b37e4 | ||
|
|
c4a7e9694f | ||
|
|
2db1758ec2 | ||
|
|
cff070dc07 | ||
|
|
7b3ad77f36 | ||
|
|
d67e79a44b | ||
|
|
977190b358 | ||
|
|
ba3237604e | ||
|
|
d55a6632ca | ||
|
|
680cb580cd | ||
|
|
2f74940f6a | ||
|
|
72d876bd4b | ||
|
|
e22398bec8 | ||
|
|
11661db6ab | ||
|
|
6164004df3 | ||
|
|
505aa3cdd1 | ||
|
|
cfeb8da3d3 | ||
|
|
ec7945276a | ||
|
|
2bf19afb94 | ||
|
|
34b38f63fa | ||
|
|
4c7470fbf2 |
No files matched your search
+1
-11
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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();
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
@@ -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?
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 == '"') {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace
|
||||
}
|
||||
userSIDInitialized = true;
|
||||
}
|
||||
#if _MSC_VER >= 1400
|
||||
#if !defined(_MSC_VER) || _MSC_VER >= 1400
|
||||
if (userSIDValid)
|
||||
{
|
||||
if (needsWOW64())
|
||||
|
||||
+2004
-1131
File diff suppressed because it is too large.
Load diff
+1
-1
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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> </dd>\n", ReturnDescription);
|
||||
} else {
|
||||
fputs("<dd><b>Returns:</b> Nothing<br> </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> </dd>\n", ReturnDescription);
|
||||
} else {
|
||||
fputs("<dd><b>Returns:</b> Nothing<br> </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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
@@ -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!
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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()));
|
||||
|
||||
|
||||
@@ -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!";
|
||||
|
||||
@@ -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)
|
||||
Reference in new issue
Block a user