mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-07 22:56:30 -10:00
Compare commits
101
Commits
json_export
...
fotg
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b53bde255 | ||
|
|
a4ac216d7a | ||
|
|
189275da56 | ||
|
|
4c7d80cba8 | ||
|
|
4a14e26256 | ||
|
|
0fc8e53f5f | ||
|
|
ba2a1c9e7d | ||
|
|
115a2979b1 | ||
|
|
e9b9797b6e | ||
|
|
da0ef89ac5 | ||
|
|
fe49ef63aa | ||
|
|
f51bc78126 | ||
|
|
711c7a7bf8 | ||
|
|
ca16b4710d | ||
|
|
471cf4c988 | ||
|
|
d734a36940 | ||
|
|
25079f5ed2 | ||
|
|
f0a0632d9d | ||
|
|
3528dffabd | ||
|
|
2aa569c1e7 | ||
|
|
584ec36f62 | ||
|
|
93c46bd1f9 | ||
|
|
b6cc62c435 | ||
|
|
00a288d53e | ||
|
|
4bfea90a17 | ||
|
|
aef3e3ac36 | ||
|
|
a7398d7f5c | ||
|
|
e2d740513a | ||
|
|
1a29b395ab | ||
|
|
b2e01d6173 | ||
|
|
bc17966b08 | ||
|
|
be9990f6a5 | ||
|
|
c5bddac8fb | ||
|
|
3de25b7e3a | ||
|
|
2768863c36 | ||
|
|
7b78df2363 | ||
|
|
d84736be1c | ||
|
|
1591237acf | ||
|
|
05b4635048 | ||
|
|
eef1041323 | ||
|
|
18058a45f7 | ||
|
|
fbb76863fd | ||
|
|
400fd0f9a8 | ||
|
|
b18337754d | ||
|
|
92a28b71cb | ||
|
|
0656175a72 | ||
|
|
dc820fdfc1 | ||
|
|
5042c44904 | ||
|
|
91000b4468 | ||
|
|
91614162f2 | ||
|
|
4b15ec4e75 | ||
|
|
e84a6e8d33 | ||
|
|
763601033b | ||
|
|
0ff8c8191f | ||
|
|
b0bb0ee3be | ||
|
|
31140ab533 | ||
|
|
e3d1428e35 | ||
|
|
1d332d693d | ||
|
|
36c656c389 | ||
|
|
43b8cf2221 | ||
|
|
ad91ba61b5 | ||
|
|
7dea7075e7 | ||
|
|
9ec10dd3e6 | ||
|
|
83b59fb76c | ||
|
|
418d53f169 | ||
|
|
d1444b45ac | ||
|
|
26553f1327 | ||
|
|
18ef1f77d4 | ||
|
|
9aed627ce7 | ||
|
|
f187522238 | ||
|
|
26adf935f7 | ||
|
|
d68baac787 | ||
|
|
c3d3f4d4dd | ||
|
|
cc037e3259 | ||
|
|
0c60515662 | ||
|
|
ec88fdbae1 | ||
|
|
83414b238d | ||
|
|
a233f62afb | ||
|
|
8ef442205c | ||
|
|
66bddb970c | ||
|
|
4ecc546e34 | ||
|
|
aaec401c8f | ||
|
|
6f1e33938c | ||
|
|
c4d1ed526c | ||
|
|
161e7498c4 | ||
|
|
e3311f36ac | ||
|
|
ed11f9a1c1 | ||
|
|
e0e3cffab6 | ||
|
|
b6d48faf4d | ||
|
|
73d6483df6 | ||
|
|
3952713eba | ||
|
|
617c530a3b | ||
|
|
8c0f95ced8 | ||
|
|
78f9c8f82c | ||
|
|
e3715cc420 | ||
|
|
366f4d5642 | ||
|
|
547d615552 | ||
|
|
4f074d94d1 | ||
|
|
a4ac843d5b | ||
|
|
359a98410a | ||
|
|
1acfc1c326 |
No files matched your search
@@ -0,0 +1,4 @@
|
||||
root = true
|
||||
|
||||
[*.{h,cpp}]
|
||||
indent_style = tab
|
||||
@@ -0,0 +1,18 @@
|
||||
[](https://scan.coverity.com/projects/870)
|
||||
|
||||
Welcome to Freespace Open!
|
||||
|
||||
In 2002 Volition released the source code for Freespace2. In the years since dedicated individuals have added countless new features to create a flexible and powerful space combat simulation engine. More info can be found on our [wiki](http://www.hard-light.net/wiki/index.php/Source_Code_Project)
|
||||
|
||||
People interested in contributing are encouraged to read [this thread](http://www.hard-light.net/forums/index.php?topic=82688.0)
|
||||
|
||||
The "projects" directory contains ready projects for:
|
||||
* Microsoft Visual C++ 6, 2005, 2008, 2010, 2011, 2013, 2015
|
||||
* Apple Xcode
|
||||
* Code::Blocks
|
||||
* Eclipse
|
||||
|
||||
|
||||
Review the commit logs to see what's new.
|
||||
|
||||
See the INSTALL file for instructions on how to build fs2_open, or open the relevant MSVC project
|
||||
+416
-404
@@ -69,445 +69,457 @@ int ai_path_type_match(char *p)
|
||||
|
||||
void parse_ai_profiles_tbl(const char *filename)
|
||||
{
|
||||
int i, rval;
|
||||
int i;
|
||||
char profile_name[NAME_LENGTH];
|
||||
ai_profile_t dummy_profile;
|
||||
char *saved_Mp = NULL;
|
||||
char buf[NAME_LENGTH];
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0)
|
||||
try
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", (filename) ? filename : "<default ai_profiles.tbl>", rval));
|
||||
return;
|
||||
}
|
||||
|
||||
if (filename == NULL)
|
||||
read_file_text_from_array(defaults_get_file("ai_profiles.tbl"));
|
||||
else
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
|
||||
reset_parse();
|
||||
|
||||
|
||||
// start parsing
|
||||
required_string("#AI Profiles");
|
||||
|
||||
// new default?
|
||||
if (optional_string("$Default Profile:"))
|
||||
stuff_string(Default_profile_name, F_NAME, NAME_LENGTH);
|
||||
|
||||
// begin reading data
|
||||
while (required_string_either("#End","$Profile Name:"))
|
||||
{
|
||||
ai_profile_t *profile = &dummy_profile;
|
||||
ai_profile_t *previous_profile = NULL;
|
||||
bool no_create = false;
|
||||
|
||||
// get the name
|
||||
required_string("$Profile Name:");
|
||||
stuff_string(profile_name, F_NAME, NAME_LENGTH);
|
||||
|
||||
// see if it exists
|
||||
for (i = 0; i < Num_ai_profiles; i++)
|
||||
{
|
||||
if (!stricmp(Ai_profiles[i].profile_name, profile_name))
|
||||
{
|
||||
previous_profile = &Ai_profiles[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// modular table stuff
|
||||
if (optional_string("+nocreate"))
|
||||
{
|
||||
no_create = true;
|
||||
|
||||
// use the previous one if possible,
|
||||
// otherwise continue to use the dummy one
|
||||
if (previous_profile != NULL)
|
||||
profile = previous_profile;
|
||||
}
|
||||
if (filename == NULL)
|
||||
read_file_text_from_array(defaults_get_file("ai_profiles.tbl"));
|
||||
else
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
|
||||
reset_parse();
|
||||
|
||||
|
||||
// start parsing
|
||||
required_string("#AI Profiles");
|
||||
|
||||
// new default?
|
||||
if (optional_string("$Default Profile:"))
|
||||
stuff_string(Default_profile_name, F_NAME, NAME_LENGTH);
|
||||
|
||||
// begin reading data
|
||||
while (required_string_either("#End", "$Profile Name:"))
|
||||
{
|
||||
// don't create multiple profiles with the same name
|
||||
if (previous_profile != NULL)
|
||||
ai_profile_t *profile = &dummy_profile;
|
||||
ai_profile_t *previous_profile = NULL;
|
||||
bool no_create = false;
|
||||
|
||||
// get the name
|
||||
required_string("$Profile Name:");
|
||||
stuff_string(profile_name, F_NAME, NAME_LENGTH);
|
||||
|
||||
// see if it exists
|
||||
for (i = 0; i < Num_ai_profiles; i++)
|
||||
{
|
||||
Warning(LOCATION, "An ai profile named '%s' already exists! The new one will not be created.\n", profile_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
// make sure we're under the limit
|
||||
if (Num_ai_profiles >= MAX_AI_PROFILES)
|
||||
if (!stricmp(Ai_profiles[i].profile_name, profile_name))
|
||||
{
|
||||
Warning(LOCATION, "Too many profiles in ai_profiles.tbl! Max is %d.\n", MAX_AI_PROFILES-1); // -1 because one is built-in
|
||||
skip_to_string("#End", NULL);
|
||||
previous_profile = &Ai_profiles[i];
|
||||
break;
|
||||
}
|
||||
|
||||
profile = &Ai_profiles[Num_ai_profiles];
|
||||
Num_ai_profiles++;
|
||||
}
|
||||
}
|
||||
|
||||
// initialize profile if we're not building from a previously parsed one
|
||||
if (!no_create)
|
||||
{
|
||||
// base profile, so zero it out
|
||||
if (profile == &Ai_profiles[0])
|
||||
// modular table stuff
|
||||
if (optional_string("+nocreate"))
|
||||
{
|
||||
memset(profile, 0, sizeof(ai_profile_t));
|
||||
no_create = true;
|
||||
|
||||
// use the previous one if possible,
|
||||
// otherwise continue to use the dummy one
|
||||
if (previous_profile != NULL)
|
||||
profile = previous_profile;
|
||||
}
|
||||
// brand new profile, so set it to the base defaults
|
||||
else
|
||||
{
|
||||
memcpy(profile, &Ai_profiles[0], sizeof(ai_profile_t));
|
||||
}
|
||||
}
|
||||
|
||||
// set the name
|
||||
strcpy_s(profile->profile_name, profile_name);
|
||||
|
||||
|
||||
// fill in any and all settings; they're all optional and can be in any order
|
||||
while (!check_for_string("$Profile Name:") && !check_for_string("#End"))
|
||||
{
|
||||
if (optional_string("$Player Afterburner Recharge Scale:"))
|
||||
parse_float_list(profile->afterburner_recharge_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Beam Friendly Fire Damage:"))
|
||||
parse_float_list(profile->beam_friendly_damage_cap, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Countermeasure Life Scale:"))
|
||||
parse_float_list(profile->cmeasure_life_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Countermeasure Firing Chance:"))
|
||||
parse_float_list(profile->cmeasure_fire_chance, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI In Range Time:"))
|
||||
parse_float_list(profile->in_range_time, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Always Links Ammo Weapons:"))
|
||||
parse_float_list(profile->link_ammo_levels_always, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Maybe Links Ammo Weapons:"))
|
||||
parse_float_list(profile->link_ammo_levels_maybe, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Primary Ammo Burst Multiplier:"))
|
||||
parse_float_list(profile->primary_ammo_burst_mult, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Always Links Energy Weapons:"))
|
||||
parse_float_list(profile->link_energy_levels_always, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Maybe Links Energy Weapons:"))
|
||||
parse_float_list(profile->link_energy_levels_maybe, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Missles Locked on Player:") || optional_string("$Max Missiles Locked on Player:"))
|
||||
parse_int_list(profile->max_allowed_player_homers, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Player Attackers:"))
|
||||
parse_int_list(profile->max_attackers, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Incoming Asteroids:"))
|
||||
parse_int_list(profile->max_incoming_asteroids, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Damage Factor:") || optional_string("$AI Damage Reduction to Player Hull:"))
|
||||
parse_float_list(profile->player_damage_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Subsys Damage Factor:") || optional_string("$AI Damage Reduction to Player Subsys:"))
|
||||
parse_float_list(profile->subsys_damage_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
// represented in fractions of F1_0
|
||||
if (optional_string("$Predict Position Delay:"))
|
||||
{
|
||||
int iLoop;
|
||||
float temp_list[NUM_SKILL_LEVELS];
|
||||
|
||||
parse_float_list(temp_list, NUM_SKILL_LEVELS);
|
||||
|
||||
for (iLoop = 0; iLoop < NUM_SKILL_LEVELS; iLoop++)
|
||||
profile->predict_position_delay[iLoop] = fl2f(temp_list[iLoop]);
|
||||
}
|
||||
|
||||
if (optional_string("$AI Shield Manage Delay:") || optional_string("$AI Shield Manage Delays:"))
|
||||
parse_float_list(profile->shield_manage_delay, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Friendly AI Fire Delay Scale:"))
|
||||
parse_float_list(profile->ship_fire_delay_scale_friendly, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Hostile AI Fire Delay Scale:"))
|
||||
parse_float_list(profile->ship_fire_delay_scale_hostile, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Friendly AI Secondary Fire Delay Scale:"))
|
||||
parse_float_list(profile->ship_fire_secondary_delay_scale_friendly, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Hostile AI Secondary Fire Delay Scale:"))
|
||||
parse_float_list(profile->ship_fire_secondary_delay_scale_hostile, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Turn Time Scale:"))
|
||||
parse_float_list(profile->turn_time_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Glide Attack Percent:")) {
|
||||
parse_float_list(profile->glide_attack_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->glide_attack_percent[i] < 0.0f || profile->glide_attack_percent[i] > 100.0f) {
|
||||
Warning(LOCATION, "$Glide Attack Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->glide_attack_percent[i]);
|
||||
profile->glide_attack_percent[i] = 0.0f;
|
||||
}
|
||||
profile->glide_attack_percent[i] /= 100.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Circle Strafe Percent:")) {
|
||||
parse_float_list(profile->circle_strafe_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->circle_strafe_percent[i] < 0.0f || profile->circle_strafe_percent[i] > 100.0f) {
|
||||
Warning(LOCATION, "$Circle Strafe Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->circle_strafe_percent[i]);
|
||||
profile->circle_strafe_percent[i] = 0.0f;
|
||||
}
|
||||
profile->circle_strafe_percent[i] /= 100.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Glide Strafe Percent:")) {
|
||||
parse_float_list(profile->glide_strafe_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->glide_strafe_percent[i] < 0.0f || profile->glide_strafe_percent[i] > 100.0f) {
|
||||
Warning(LOCATION, "$Glide Strafe Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->glide_strafe_percent[i]);
|
||||
profile->glide_strafe_percent[i] = 0.0f;
|
||||
}
|
||||
profile->glide_strafe_percent[i] /= 100.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Random Sidethrust Percent:")) {
|
||||
parse_float_list(profile->random_sidethrust_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->random_sidethrust_percent[i] < 0.0f || profile->random_sidethrust_percent[i] > 100.0f) {
|
||||
Warning(LOCATION, "$Random Sidethrust Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->random_sidethrust_percent[i]);
|
||||
profile->random_sidethrust_percent[i] = 0.0f;
|
||||
}
|
||||
profile->random_sidethrust_percent[i] /= 100.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Stalemate Time Threshold:"))
|
||||
parse_float_list(profile->stalemate_time_thresh, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Stalemate Distance Threshold:"))
|
||||
parse_float_list(profile->stalemate_dist_thresh, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Shield Recharge Scale:"))
|
||||
parse_float_list(profile->shield_energy_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Weapon Recharge Scale:"))
|
||||
parse_float_list(profile->weapon_energy_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Turret Target Ownage:"))
|
||||
parse_int_list(profile->max_turret_ownage_target, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Turret Player Ownage:"))
|
||||
parse_int_list(profile->max_turret_ownage_player, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Percentage Required For Kill Scale:"))
|
||||
parse_float_list(profile->kill_percentage_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Percentage Required For Assist Scale:"))
|
||||
parse_float_list(profile->assist_percentage_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Percentage Awarded For Capship Assist:"))
|
||||
parse_float_list(profile->assist_award_percentage_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Repair Penalty:"))
|
||||
parse_int_list(profile->repair_penalty, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Delay Before Allowing Bombs to Be Shot Down:"))
|
||||
parse_float_list(profile->delay_bomb_arm_timer, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Chance AI Has to Fire Missiles at Player:"))
|
||||
parse_int_list(profile->chance_to_use_missiles_on_plr, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Aim Update Delay:"))
|
||||
parse_float_list(profile->max_aim_update_delay, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Turret Max Aim Update Delay:"))
|
||||
parse_float_list(profile->turret_max_aim_update_delay, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Autoaim FOV:"))
|
||||
{
|
||||
float fov_list[NUM_SKILL_LEVELS];
|
||||
parse_float_list(fov_list, NUM_SKILL_LEVELS);
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++)
|
||||
// don't create multiple profiles with the same name
|
||||
if (previous_profile != NULL)
|
||||
{
|
||||
//Enforce range
|
||||
if (fov_list[i] < 0.0f || fov_list[i] >= 360.0f)
|
||||
Warning(LOCATION, "An ai profile named '%s' already exists! The new one will not be created.\n", profile_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
// make sure we're under the limit
|
||||
if (Num_ai_profiles >= MAX_AI_PROFILES)
|
||||
{
|
||||
Warning(LOCATION, "$Player Autoaim FOV should be >= 0 and < 360.0 (read %f). Setting to 0.", fov_list[i]);
|
||||
fov_list[i] = 0.0f;
|
||||
Warning(LOCATION, "Too many profiles in ai_profiles.tbl! Max is %d.\n", MAX_AI_PROFILES - 1); // -1 because one is built-in
|
||||
skip_to_string("#End", NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
//Convert units
|
||||
profile->player_autoaim_fov[i] = fov_list[i] * PI / 180.0f;
|
||||
profile = &Ai_profiles[Num_ai_profiles];
|
||||
Num_ai_profiles++;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Detail Distance Multiplier:"))
|
||||
parse_float_list(profile->detail_distance_mult, NUM_SKILL_LEVELS);
|
||||
|
||||
set_flag(profile, "$big ships can attack beam turrets on untargeted ships:", AIPF_BIG_SHIPS_CAN_ATTACK_BEAM_TURRETS_ON_UNTARGETED_SHIPS, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$smart primary weapon selection:", AIPF_SMART_PRIMARY_WEAPON_SELECTION, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$smart secondary weapon selection:", AIPF_SMART_SECONDARY_WEAPON_SELECTION, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$smart shield management:", AIPF_SMART_SHIELD_MANAGEMENT, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$smart afterburner management:", AIPF_SMART_AFTERBURNER_MANAGEMENT, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$allow rapid secondary dumbfire:", AIPF_ALLOW_RAPID_SECONDARY_DUMBFIRE, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$huge turret weapons ignore bombs:", AIPF_HUGE_TURRET_WEAPONS_IGNORE_BOMBS, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$don't insert random turret fire delay:", AIPF_DONT_INSERT_RANDOM_TURRET_FIRE_DELAY, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$hack improve non-homing swarm turret fire accuracy:", AIPF_HACK_IMPROVE_NON_HOMING_SWARM_TURRET_FIRE_ACCURACY, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$shockwaves damage small ship subsystems:", AIPF_SHOCKWAVES_DAMAGE_SMALL_SHIP_SUBSYSTEMS, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$navigation subsystem governs warpout capability:", AIPF_NAVIGATION_SUBSYS_GOVERNS_WARP, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$ignore lower bound for minimum speed of docked ship:", AIPF_NO_MIN_DOCK_SPEED_CAP, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$disable linked fire penalty:", AIPF_DISABLE_LINKED_FIRE_PENALTY, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$disable weapon damage scaling:", AIPF_DISABLE_WEAPON_DAMAGE_SCALING, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$use additive weapon velocity:", AIPF_USE_ADDITIVE_WEAPON_VELOCITY, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$use newtonian dampening:", AIPF_USE_NEWTONIAN_DAMPENING, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$include beams for kills and assists:", AIPF_INCLUDE_BEAMS_IN_STAT_CALCS, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$score kills based on damage caused:", AIPF_KILL_SCORING_SCALES_WITH_DAMAGE, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$score assists based on damage caused:", AIPF_ASSIST_SCORING_SCALES_WITH_DAMAGE, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$allow event and goal scoring in multiplayer:", AIPF_ALLOW_MULTI_EVENT_SCORING, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$fix linked primary weapon decision bug:", AIPF_FIX_LINKED_PRIMARY_BUG, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$prevent turrets targeting too distant bombs:", AIPF_PREVENT_TARGETING_BOMBS_BEYOND_RANGE, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$smart subsystem targeting for turrets:", AIPF_SMART_SUBSYSTEM_TARGETING_FOR_TURRETS, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$fix heat seekers homing on stealth ships bug:", AIPF_FIX_HEAT_SEEKER_STEALTH_BUG, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$multi allow empty primaries:", AIPF_MULTI_ALLOW_EMPTY_PRIMARIES, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$multi allow empty secondaries:", AIPF_MULTI_ALLOW_EMPTY_SECONDARIES, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$allow turrets target weapons freely:", AIPF_ALLOW_TURRETS_TARGET_WEAPONS_FREELY, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$use only single fov for turrets:", AIPF_USE_ONLY_SINGLE_FOV_FOR_TURRETS, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$allow vertical dodge:", AIPF_ALLOW_VERTICAL_DODGE, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$force beam turrets to use normal fov:", AIPF_FORCE_BEAM_TURRET_FOV, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$fix ai class bug:", AIPF_FIX_AI_CLASS_BUG, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$turrets ignore targets radius in range checks:", AIPF2_TURRETS_IGNORE_TARGET_RADIUS, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$no extra collision avoidance vs player:", AIPF2_NO_SPECIAL_PLAYER_AVOID, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$perform fewer checks for death screams:", AIPF2_PERFORM_FEWER_SCREAM_CHECKS, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$advanced turret fov edge checks:", AIPF2_ADVANCED_TURRET_FOV_EDGE_CHECKS, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$require turrets to have target in fov:", AIPF2_REQUIRE_TURRET_TO_HAVE_TARGET_IN_FOV, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$all ships manage shields:", AIPF2_ALL_SHIPS_MANAGE_SHIELDS, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$ai aims from ship center:", AIPF2_AI_AIMS_FROM_SHIP_CENTER, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$allow primary link at mission start:", AIPF2_ALLOW_PRIMARY_LINK_AT_START, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$allow beams to damage bombs:", AIPF2_BEAMS_DAMAGE_WEAPONS, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$disable weapon damage scaling for player:", AIPF2_PLAYER_WEAPON_SCALE_FIX, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$countermeasures affect aspect seekers:", AIPF2_ASPECT_LOCK_COUNTERMEASURE, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$ai guards specific ship in wing:", AIPF2_AI_GUARDS_SPECIFIC_SHIP_IN_WING, AIP_FLAG2);
|
||||
|
||||
profile->ai_path_mode = AI_PATH_MODE_NORMAL;
|
||||
if(optional_string("$ai path mode:"))
|
||||
// initialize profile if we're not building from a previously parsed one
|
||||
if (!no_create)
|
||||
{
|
||||
stuff_string(buf, F_NAME, NAME_LENGTH);
|
||||
int j = ai_path_type_match(buf);
|
||||
if(j >= 0) {
|
||||
profile->ai_path_mode = j;
|
||||
} else {
|
||||
Warning(LOCATION, "Invalid ai path mode '%s' specified", buf);
|
||||
// base profile, so zero it out
|
||||
if (profile == &Ai_profiles[0])
|
||||
{
|
||||
memset(profile, 0, sizeof(ai_profile_t));
|
||||
}
|
||||
// brand new profile, so set it to the base defaults
|
||||
else
|
||||
{
|
||||
memcpy(profile, &Ai_profiles[0], sizeof(ai_profile_t));
|
||||
}
|
||||
}
|
||||
|
||||
set_flag(profile, "$no warp camera:", AIPF2_NO_WARP_CAMERA, AIP_FLAG2);
|
||||
// set the name
|
||||
strcpy_s(profile->profile_name, profile_name);
|
||||
|
||||
set_flag(profile, "$fix ai path order bug:", AIPF2_FIX_AI_PATH_ORDER_BUG, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$strict turret-tagged-only targeting:", AIPF2_STRICT_TURRET_TAGGED_ONLY_TARGETING, AIP_FLAG2);
|
||||
|
||||
// ----------
|
||||
|
||||
// compatibility
|
||||
if (optional_string("$perform less checks for death screams:"))
|
||||
// fill in any and all settings; they're all optional and can be in any order
|
||||
while (!check_for_string("$Profile Name:") && !check_for_string("#End"))
|
||||
{
|
||||
mprintf(("Warning: \"$perform less checks for death screams\" flag is deprecated in favor of \"$perform fewer checks for death screams\"\n"));
|
||||
bool temp;
|
||||
stuff_boolean(&temp);
|
||||
if (temp)
|
||||
profile->flags2 |= AIPF2_PERFORM_FEWER_SCREAM_CHECKS;
|
||||
else
|
||||
profile->flags2 &= ~AIPF2_PERFORM_FEWER_SCREAM_CHECKS;
|
||||
if (optional_string("$Player Afterburner Recharge Scale:"))
|
||||
parse_float_list(profile->afterburner_recharge_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Beam Friendly Fire Damage:"))
|
||||
parse_float_list(profile->beam_friendly_damage_cap, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Countermeasure Life Scale:"))
|
||||
parse_float_list(profile->cmeasure_life_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Countermeasure Firing Chance:"))
|
||||
parse_float_list(profile->cmeasure_fire_chance, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI In Range Time:"))
|
||||
parse_float_list(profile->in_range_time, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Always Links Ammo Weapons:"))
|
||||
parse_float_list(profile->link_ammo_levels_always, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Maybe Links Ammo Weapons:"))
|
||||
parse_float_list(profile->link_ammo_levels_maybe, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Primary Ammo Burst Multiplier:"))
|
||||
parse_float_list(profile->primary_ammo_burst_mult, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Always Links Energy Weapons:"))
|
||||
parse_float_list(profile->link_energy_levels_always, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Maybe Links Energy Weapons:"))
|
||||
parse_float_list(profile->link_energy_levels_maybe, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Missles Locked on Player:") || optional_string("$Max Missiles Locked on Player:"))
|
||||
parse_int_list(profile->max_allowed_player_homers, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Player Attackers:"))
|
||||
parse_int_list(profile->max_attackers, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Incoming Asteroids:"))
|
||||
parse_int_list(profile->max_incoming_asteroids, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Damage Factor:") || optional_string("$AI Damage Reduction to Player Hull:"))
|
||||
parse_float_list(profile->player_damage_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Subsys Damage Factor:") || optional_string("$AI Damage Reduction to Player Subsys:"))
|
||||
parse_float_list(profile->subsys_damage_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
// represented in fractions of F1_0
|
||||
if (optional_string("$Predict Position Delay:"))
|
||||
{
|
||||
int iLoop;
|
||||
float temp_list[NUM_SKILL_LEVELS];
|
||||
|
||||
parse_float_list(temp_list, NUM_SKILL_LEVELS);
|
||||
|
||||
for (iLoop = 0; iLoop < NUM_SKILL_LEVELS; iLoop++)
|
||||
profile->predict_position_delay[iLoop] = fl2f(temp_list[iLoop]);
|
||||
}
|
||||
|
||||
if (optional_string("$AI Shield Manage Delay:") || optional_string("$AI Shield Manage Delays:"))
|
||||
parse_float_list(profile->shield_manage_delay, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Friendly AI Fire Delay Scale:"))
|
||||
parse_float_list(profile->ship_fire_delay_scale_friendly, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Hostile AI Fire Delay Scale:"))
|
||||
parse_float_list(profile->ship_fire_delay_scale_hostile, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Friendly AI Secondary Fire Delay Scale:"))
|
||||
parse_float_list(profile->ship_fire_secondary_delay_scale_friendly, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Hostile AI Secondary Fire Delay Scale:"))
|
||||
parse_float_list(profile->ship_fire_secondary_delay_scale_hostile, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Turn Time Scale:"))
|
||||
parse_float_list(profile->turn_time_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Glide Attack Percent:")) {
|
||||
parse_float_list(profile->glide_attack_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->glide_attack_percent[i] < 0.0f || profile->glide_attack_percent[i] > 100.0f) {
|
||||
Warning(LOCATION, "$Glide Attack Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->glide_attack_percent[i]);
|
||||
profile->glide_attack_percent[i] = 0.0f;
|
||||
}
|
||||
profile->glide_attack_percent[i] /= 100.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Circle Strafe Percent:")) {
|
||||
parse_float_list(profile->circle_strafe_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->circle_strafe_percent[i] < 0.0f || profile->circle_strafe_percent[i] > 100.0f) {
|
||||
Warning(LOCATION, "$Circle Strafe Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->circle_strafe_percent[i]);
|
||||
profile->circle_strafe_percent[i] = 0.0f;
|
||||
}
|
||||
profile->circle_strafe_percent[i] /= 100.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Glide Strafe Percent:")) {
|
||||
parse_float_list(profile->glide_strafe_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->glide_strafe_percent[i] < 0.0f || profile->glide_strafe_percent[i] > 100.0f) {
|
||||
Warning(LOCATION, "$Glide Strafe Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->glide_strafe_percent[i]);
|
||||
profile->glide_strafe_percent[i] = 0.0f;
|
||||
}
|
||||
profile->glide_strafe_percent[i] /= 100.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Random Sidethrust Percent:")) {
|
||||
parse_float_list(profile->random_sidethrust_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->random_sidethrust_percent[i] < 0.0f || profile->random_sidethrust_percent[i] > 100.0f) {
|
||||
Warning(LOCATION, "$Random Sidethrust Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->random_sidethrust_percent[i]);
|
||||
profile->random_sidethrust_percent[i] = 0.0f;
|
||||
}
|
||||
profile->random_sidethrust_percent[i] /= 100.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Stalemate Time Threshold:"))
|
||||
parse_float_list(profile->stalemate_time_thresh, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Stalemate Distance Threshold:"))
|
||||
parse_float_list(profile->stalemate_dist_thresh, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Shield Recharge Scale:"))
|
||||
parse_float_list(profile->shield_energy_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Weapon Recharge Scale:"))
|
||||
parse_float_list(profile->weapon_energy_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Turret Target Ownage:"))
|
||||
parse_int_list(profile->max_turret_ownage_target, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Turret Player Ownage:"))
|
||||
parse_int_list(profile->max_turret_ownage_player, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Percentage Required For Kill Scale:"))
|
||||
parse_float_list(profile->kill_percentage_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Percentage Required For Assist Scale:"))
|
||||
parse_float_list(profile->assist_percentage_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Percentage Awarded For Capship Assist:"))
|
||||
parse_float_list(profile->assist_award_percentage_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Repair Penalty:"))
|
||||
parse_int_list(profile->repair_penalty, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Delay Before Allowing Bombs to Be Shot Down:"))
|
||||
parse_float_list(profile->delay_bomb_arm_timer, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Chance AI Has to Fire Missiles at Player:"))
|
||||
parse_int_list(profile->chance_to_use_missiles_on_plr, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Aim Update Delay:"))
|
||||
parse_float_list(profile->max_aim_update_delay, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Turret Max Aim Update Delay:"))
|
||||
parse_float_list(profile->turret_max_aim_update_delay, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Autoaim FOV:"))
|
||||
{
|
||||
float fov_list[NUM_SKILL_LEVELS];
|
||||
parse_float_list(fov_list, NUM_SKILL_LEVELS);
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++)
|
||||
{
|
||||
//Enforce range
|
||||
if (fov_list[i] < 0.0f || fov_list[i] >= 360.0f)
|
||||
{
|
||||
Warning(LOCATION, "$Player Autoaim FOV should be >= 0 and < 360.0 (read %f). Setting to 0.", fov_list[i]);
|
||||
fov_list[i] = 0.0f;
|
||||
}
|
||||
|
||||
//Convert units
|
||||
profile->player_autoaim_fov[i] = fov_list[i] * PI / 180.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Detail Distance Multiplier:"))
|
||||
parse_float_list(profile->detail_distance_mult, NUM_SKILL_LEVELS);
|
||||
|
||||
set_flag(profile, "$big ships can attack beam turrets on untargeted ships:", AIPF_BIG_SHIPS_CAN_ATTACK_BEAM_TURRETS_ON_UNTARGETED_SHIPS, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$smart primary weapon selection:", AIPF_SMART_PRIMARY_WEAPON_SELECTION, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$smart secondary weapon selection:", AIPF_SMART_SECONDARY_WEAPON_SELECTION, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$smart shield management:", AIPF_SMART_SHIELD_MANAGEMENT, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$smart afterburner management:", AIPF_SMART_AFTERBURNER_MANAGEMENT, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$allow rapid secondary dumbfire:", AIPF_ALLOW_RAPID_SECONDARY_DUMBFIRE, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$huge turret weapons ignore bombs:", AIPF_HUGE_TURRET_WEAPONS_IGNORE_BOMBS, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$don't insert random turret fire delay:", AIPF_DONT_INSERT_RANDOM_TURRET_FIRE_DELAY, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$hack improve non-homing swarm turret fire accuracy:", AIPF_HACK_IMPROVE_NON_HOMING_SWARM_TURRET_FIRE_ACCURACY, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$shockwaves damage small ship subsystems:", AIPF_SHOCKWAVES_DAMAGE_SMALL_SHIP_SUBSYSTEMS, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$navigation subsystem governs warpout capability:", AIPF_NAVIGATION_SUBSYS_GOVERNS_WARP, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$ignore lower bound for minimum speed of docked ship:", AIPF_NO_MIN_DOCK_SPEED_CAP, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$disable linked fire penalty:", AIPF_DISABLE_LINKED_FIRE_PENALTY, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$disable weapon damage scaling:", AIPF_DISABLE_WEAPON_DAMAGE_SCALING, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$use additive weapon velocity:", AIPF_USE_ADDITIVE_WEAPON_VELOCITY, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$use newtonian dampening:", AIPF_USE_NEWTONIAN_DAMPENING, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$include beams for kills and assists:", AIPF_INCLUDE_BEAMS_IN_STAT_CALCS, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$score kills based on damage caused:", AIPF_KILL_SCORING_SCALES_WITH_DAMAGE, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$score assists based on damage caused:", AIPF_ASSIST_SCORING_SCALES_WITH_DAMAGE, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$allow event and goal scoring in multiplayer:", AIPF_ALLOW_MULTI_EVENT_SCORING, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$fix linked primary weapon decision bug:", AIPF_FIX_LINKED_PRIMARY_BUG, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$prevent turrets targeting too distant bombs:", AIPF_PREVENT_TARGETING_BOMBS_BEYOND_RANGE, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$smart subsystem targeting for turrets:", AIPF_SMART_SUBSYSTEM_TARGETING_FOR_TURRETS, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$fix heat seekers homing on stealth ships bug:", AIPF_FIX_HEAT_SEEKER_STEALTH_BUG, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$multi allow empty primaries:", AIPF_MULTI_ALLOW_EMPTY_PRIMARIES, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$multi allow empty secondaries:", AIPF_MULTI_ALLOW_EMPTY_SECONDARIES, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$allow turrets target weapons freely:", AIPF_ALLOW_TURRETS_TARGET_WEAPONS_FREELY, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$use only single fov for turrets:", AIPF_USE_ONLY_SINGLE_FOV_FOR_TURRETS, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$allow vertical dodge:", AIPF_ALLOW_VERTICAL_DODGE, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$force beam turrets to use normal fov:", AIPF_FORCE_BEAM_TURRET_FOV, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$fix ai class bug:", AIPF_FIX_AI_CLASS_BUG, AIP_FLAG);
|
||||
|
||||
set_flag(profile, "$turrets ignore targets radius in range checks:", AIPF2_TURRETS_IGNORE_TARGET_RADIUS, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$no extra collision avoidance vs player:", AIPF2_NO_SPECIAL_PLAYER_AVOID, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$perform fewer checks for death screams:", AIPF2_PERFORM_FEWER_SCREAM_CHECKS, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$advanced turret fov edge checks:", AIPF2_ADVANCED_TURRET_FOV_EDGE_CHECKS, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$require turrets to have target in fov:", AIPF2_REQUIRE_TURRET_TO_HAVE_TARGET_IN_FOV, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$all ships manage shields:", AIPF2_ALL_SHIPS_MANAGE_SHIELDS, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$ai aims from ship center:", AIPF2_AI_AIMS_FROM_SHIP_CENTER, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$allow primary link at mission start:", AIPF2_ALLOW_PRIMARY_LINK_AT_START, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$allow beams to damage bombs:", AIPF2_BEAMS_DAMAGE_WEAPONS, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$disable weapon damage scaling for player:", AIPF2_PLAYER_WEAPON_SCALE_FIX, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$countermeasures affect aspect seekers:", AIPF2_ASPECT_LOCK_COUNTERMEASURE, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$ai guards specific ship in wing:", AIPF2_AI_GUARDS_SPECIFIC_SHIP_IN_WING, AIP_FLAG2);
|
||||
|
||||
profile->ai_path_mode = AI_PATH_MODE_NORMAL;
|
||||
if (optional_string("$ai path mode:"))
|
||||
{
|
||||
stuff_string(buf, F_NAME, NAME_LENGTH);
|
||||
int j = ai_path_type_match(buf);
|
||||
if (j >= 0) {
|
||||
profile->ai_path_mode = j;
|
||||
}
|
||||
else {
|
||||
Warning(LOCATION, "Invalid ai path mode '%s' specified", buf);
|
||||
}
|
||||
}
|
||||
|
||||
set_flag(profile, "$no warp camera:", AIPF2_NO_WARP_CAMERA, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$fix ai path order bug:", AIPF2_FIX_AI_PATH_ORDER_BUG, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$strict turret-tagged-only targeting:", AIPF2_STRICT_TURRET_TAGGED_ONLY_TARGETING, AIP_FLAG2);
|
||||
|
||||
profile->bay_arrive_speed_mult = 1.0f;
|
||||
profile->bay_depart_speed_mult = 1.0f;
|
||||
if (optional_string("$bay arrive start speed multiplier:")) {
|
||||
stuff_float(&profile->bay_arrive_speed_mult);
|
||||
}
|
||||
if (optional_string("$bay depart end speed multiplier:")) {
|
||||
stuff_float(&profile->bay_depart_speed_mult);
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
// compatibility
|
||||
if (optional_string("$perform less checks for death screams:"))
|
||||
{
|
||||
mprintf(("Warning: \"$perform less checks for death screams\" flag is deprecated in favor of \"$perform fewer checks for death screams\"\n"));
|
||||
bool temp;
|
||||
stuff_boolean(&temp);
|
||||
if (temp)
|
||||
profile->flags2 |= AIPF2_PERFORM_FEWER_SCREAM_CHECKS;
|
||||
else
|
||||
profile->flags2 &= ~AIPF2_PERFORM_FEWER_SCREAM_CHECKS;
|
||||
}
|
||||
if (optional_string("$allow primary link delay:"))
|
||||
{
|
||||
mprintf(("Warning: \"$allow primary link delay\" flag is deprecated in favor of \"$allow primary link at mission start\"\n"));
|
||||
bool temp;
|
||||
stuff_boolean(&temp);
|
||||
if (temp)
|
||||
profile->flags2 &= ~AIPF2_ALLOW_PRIMARY_LINK_AT_START;
|
||||
else
|
||||
profile->flags2 |= AIPF2_ALLOW_PRIMARY_LINK_AT_START;
|
||||
}
|
||||
|
||||
|
||||
// if we've been through once already and are at the same place, force a move
|
||||
if (saved_Mp && (saved_Mp == Mp))
|
||||
{
|
||||
char tmp[60];
|
||||
memset(tmp, 0, 60);
|
||||
strncpy(tmp, Mp, 59);
|
||||
mprintf(("WARNING: Unrecognized parameter in ai_profiles: %s\n", tmp));
|
||||
|
||||
Mp++;
|
||||
}
|
||||
|
||||
// find next valid option
|
||||
skip_to_start_of_string_either("$", "#");
|
||||
saved_Mp = Mp;
|
||||
}
|
||||
if (optional_string("$allow primary link delay:"))
|
||||
{
|
||||
mprintf(("Warning: \"$allow primary link delay\" flag is deprecated in favor of \"$allow primary link at mission start\"\n"));
|
||||
bool temp;
|
||||
stuff_boolean(&temp);
|
||||
if (temp)
|
||||
profile->flags2 &= ~AIPF2_ALLOW_PRIMARY_LINK_AT_START;
|
||||
else
|
||||
profile->flags2 |= AIPF2_ALLOW_PRIMARY_LINK_AT_START;
|
||||
}
|
||||
|
||||
|
||||
// if we've been through once already and are at the same place, force a move
|
||||
if ( saved_Mp && (saved_Mp == Mp) )
|
||||
{
|
||||
char tmp[60];
|
||||
memset(tmp, 0, 60);
|
||||
strncpy(tmp, Mp, 59);
|
||||
mprintf(("WARNING: Unrecognized parameter in ai_profiles: %s\n", tmp));
|
||||
|
||||
Mp++;
|
||||
}
|
||||
|
||||
// find next valid option
|
||||
skip_to_start_of_string_either("$", "#");
|
||||
saved_Mp = Mp;
|
||||
}
|
||||
|
||||
required_string("#End");
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", (filename) ? filename : "<default ai_profiles.tbl>", e.what()));
|
||||
return;
|
||||
}
|
||||
|
||||
required_string("#End");
|
||||
|
||||
// add tbl/tbm to multiplayer validation list
|
||||
extern void fs2netd_add_table_validation(const char *tblname);
|
||||
|
||||
@@ -151,6 +151,11 @@ typedef struct ai_profile_t {
|
||||
|
||||
int ai_path_mode;
|
||||
|
||||
// Ships flying bay paths will gradually accelerate/decelerate instead of
|
||||
// flying the whole path at max speed
|
||||
float bay_arrive_speed_mult;
|
||||
float bay_depart_speed_mult;
|
||||
|
||||
} ai_profile_t;
|
||||
|
||||
|
||||
|
||||
+56
-9
@@ -826,13 +826,14 @@ LOCAL int ai_inited = 0;
|
||||
void ai_init()
|
||||
{
|
||||
if ( !ai_inited ) {
|
||||
// Do the first time initialization stuff here
|
||||
int rval;
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", "ai.tbl", rval));
|
||||
} else {
|
||||
parse_aitbl();
|
||||
// Do the first time initialization stuff here
|
||||
try
|
||||
{
|
||||
parse_aitbl();
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "ai.tbl", e.what()));
|
||||
}
|
||||
|
||||
ai_inited = 1;
|
||||
@@ -4010,11 +4011,57 @@ float ai_path_1()
|
||||
dot_to_next = vm_vec_dot_to_point(&nvel_vec, &Pl_objp->pos, &gnvp);
|
||||
|
||||
// This path mode respects the "cap-waypoint-speed" SEXP
|
||||
float max_allowed_speed = 0;
|
||||
float max_allowed_speed = 0.0f;
|
||||
if ( aip->waypoint_speed_cap > 0) {
|
||||
max_allowed_speed = (float) aip->waypoint_speed_cap;
|
||||
}
|
||||
|
||||
// Maybe gradually ramp up/down the speed of a ship flying a fighterbay path
|
||||
if (aip->mode == AIM_BAY_EMERGE || (aip->mode == AIM_BAY_DEPART && aip->path_cur != aip->path_start)) {
|
||||
SCP_string pathName(pm->paths[Path_points[aip->path_start].path_num].name);
|
||||
ship_info *gsip = &Ship_info[gshipp->ship_info_index];
|
||||
float speed_mult = 1.0f;
|
||||
|
||||
if (aip->mode == AIM_BAY_EMERGE) { // Arriving
|
||||
if (gsip->pathMetadata.find(pathName) != gsip->pathMetadata.end()) {
|
||||
speed_mult = gsip->pathMetadata[pathName].arrive_speed_mult;
|
||||
}
|
||||
|
||||
if (speed_mult == FLT_MIN) {
|
||||
speed_mult = The_mission.ai_profile->bay_arrive_speed_mult;
|
||||
}
|
||||
} else { // Departing
|
||||
if (gsip->pathMetadata.find(pathName) != gsip->pathMetadata.end()) {
|
||||
speed_mult = gsip->pathMetadata[pathName].depart_speed_mult;
|
||||
}
|
||||
|
||||
if (speed_mult == FLT_MIN) {
|
||||
speed_mult = The_mission.ai_profile->bay_depart_speed_mult;
|
||||
}
|
||||
}
|
||||
|
||||
if (speed_mult != 1.0f) {
|
||||
// We use the distance between the first and last point on the path here; it's not accurate
|
||||
// if the path is not straight, but should be good enough usually; can be changed if necessary.
|
||||
float total_path_length = vm_vec_dist_quick(&Path_points[aip->path_start].pos, &Path_points[aip->path_start + num_points - 1].pos);
|
||||
float dist_to_end;
|
||||
|
||||
if (aip->mode == AIM_BAY_EMERGE) { // Arriving
|
||||
dist_to_end = vm_vec_dist_quick(&Pl_objp->pos, &Path_points[aip->path_start].pos);
|
||||
} else { // Departing
|
||||
dist_to_end = vm_vec_dist_quick(&Pl_objp->pos, &Path_points[aip->path_start + num_points - 1].pos);
|
||||
}
|
||||
|
||||
// Calculate max speed, but respect the waypoint speed cap if it's lower
|
||||
float max_bay_speed = sip->max_speed * (speed_mult + (1.0f - speed_mult) * (dist_to_end / total_path_length));
|
||||
if (max_allowed_speed == 0.0f) {
|
||||
max_allowed_speed = max_bay_speed;
|
||||
} else {
|
||||
max_allowed_speed = MIN(max_allowed_speed, max_bay_speed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set_accel_for_docking(Pl_objp, aip, dot, dot_to_next, dist_to_next, dist_to_goal, sip, max_allowed_speed);
|
||||
aip->prev_dot_to_goal = dot;
|
||||
|
||||
@@ -7582,7 +7629,7 @@ void update_aspect_lock_information(ai_info *aip, vec3d *vec_to_enemy, float dis
|
||||
|
||||
wip = &Weapon_info[swp->secondary_bank_weapons[swp->current_secondary_bank]];
|
||||
|
||||
if (num_weapon_types && (wip->wi_flags & WIF_LOCKED_HOMING)) {
|
||||
if (num_weapon_types && (wip->wi_flags & WIF_LOCKED_HOMING) && !(shipp->flags2 & SF2_NO_SECONDARY_LOCKON)) {
|
||||
if (dist_to_enemy > 300.0f - MIN(enemy_radius, 100.0f))
|
||||
aip->ai_flags |= AIF_SEEK_LOCK;
|
||||
else
|
||||
|
||||
+3
-2
@@ -171,7 +171,7 @@ void ai_post_process_mission()
|
||||
// Goober5000 - MK originally iterated on only the first wing; now we iterate on only the player wing
|
||||
// because the player wing may not be first
|
||||
for ( i = 0; i < MAX_STARTING_WINGS; i++ ) {
|
||||
if ( Starting_wings[i] == Player_ship->wingnum ) {
|
||||
if (Starting_wings[i] >= 0 && Starting_wings[i] == Player_ship->wingnum) {
|
||||
wing *wingp;
|
||||
|
||||
wingp = &Wings[Starting_wings[i]];
|
||||
@@ -528,7 +528,7 @@ int ai_goal_find_dockpoint(int shipnum, int dock_type)
|
||||
}
|
||||
|
||||
// function to fix up dock point references for objects.
|
||||
// passed are the pointer to goal we are working with. aip if the ai_info pointer
|
||||
// passed are the pointer to goal we are working with. aip is the ai_info pointer
|
||||
// of the ship with the order. aigp is a pointer to the goal (of aip) of which we are
|
||||
// fixing up the docking points
|
||||
void ai_goal_fixup_dockpoints(ai_info *aip, ai_goal *aigp)
|
||||
@@ -537,6 +537,7 @@ void ai_goal_fixup_dockpoints(ai_info *aip, ai_goal *aigp)
|
||||
|
||||
Assert ( aip->shipnum != -1 );
|
||||
shipnum = ship_name_lookup( aigp->target_name );
|
||||
Assertion ( shipnum != -1, "Couldn't find ai goal's target_name (%s); get a coder!\n", aigp->target_name );
|
||||
docker_index = -1;
|
||||
dockee_index = -1;
|
||||
|
||||
|
||||
+124
-119
@@ -1887,143 +1887,148 @@ that is being protected.
|
||||
void asteroid_parse_tbl()
|
||||
{
|
||||
char impact_ani_file[MAX_FILENAME_LEN];
|
||||
int rval;
|
||||
|
||||
// How did we get here without having any species defined?
|
||||
Assertion(Species_info.size() > 0,
|
||||
"Cannot parse asteroids/debris if there "
|
||||
"are no species for them to belong to."
|
||||
);
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", "asteroid.tbl", rval));
|
||||
return;
|
||||
}
|
||||
|
||||
read_file_text("asteroid.tbl", CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
required_string("#Asteroid Types");
|
||||
|
||||
int tally = 0;
|
||||
int max_asteroids =
|
||||
NUM_DEBRIS_SIZES + Species_info.size() * NUM_DEBRIS_SIZES;
|
||||
|
||||
#ifndef NDEBUG
|
||||
SCP_vector<SCP_string> parsed_asteroids;
|
||||
#endif
|
||||
|
||||
// parse and tally each asteroid
|
||||
while (required_string_either("#End","$Name:"))
|
||||
|
||||
try
|
||||
{
|
||||
asteroid_info new_asteroid;
|
||||
read_file_text("asteroid.tbl", CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
asteroid_parse_section( &new_asteroid );
|
||||
required_string("#Asteroid Types");
|
||||
|
||||
int tally = 0;
|
||||
int max_asteroids =
|
||||
NUM_DEBRIS_SIZES + Species_info.size() * NUM_DEBRIS_SIZES;
|
||||
|
||||
int species = tally / NUM_DEBRIS_SIZES;
|
||||
if (tally >= max_asteroids)
|
||||
{
|
||||
#ifdef NDEBUG
|
||||
// Bump the warning count in release so they get something
|
||||
// even if the message never gets displayed.
|
||||
Warning(LOCATION, "Ignoring extra asteroid/debris");
|
||||
#else
|
||||
SCP_string msg("Ignoring extra asteroid/debris '");
|
||||
msg.append(new_asteroid.name);
|
||||
msg.append("'\n");
|
||||
Warning(LOCATION,msg.c_str());
|
||||
parsed_asteroids.push_back(msg);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
SCP_string msg;
|
||||
msg.append("Parsing asteroid: '");
|
||||
msg.append(new_asteroid.name);
|
||||
msg.append("' as a '");
|
||||
msg.append((species == 0)?"generic":Species_info[species-1].species_name);
|
||||
msg.append("'");
|
||||
switch(tally % NUM_DEBRIS_SIZES) {
|
||||
case ASTEROID_TYPE_SMALL:
|
||||
msg.append(" small\n");
|
||||
break;
|
||||
case ASTEROID_TYPE_MEDIUM:
|
||||
msg.append(" medium\n");
|
||||
break;
|
||||
case ASTEROID_TYPE_LARGE:
|
||||
msg.append(" large\n");
|
||||
break;
|
||||
default:
|
||||
Error(LOCATION, "Get a coder! Math has broken!\n"
|
||||
"Important numbers:\n"
|
||||
"\ttally: %d\n"
|
||||
"\tNUM_DEBRIS_SIZES: %d\n",
|
||||
tally, NUM_DEBRIS_SIZES
|
||||
);
|
||||
msg.append(" unknown\n");
|
||||
SCP_vector<SCP_string> parsed_asteroids;
|
||||
#endif
|
||||
|
||||
// parse and tally each asteroid
|
||||
while (required_string_either("#End", "$Name:"))
|
||||
{
|
||||
asteroid_info new_asteroid;
|
||||
|
||||
asteroid_parse_section(&new_asteroid);
|
||||
|
||||
int species = tally / NUM_DEBRIS_SIZES;
|
||||
if (tally >= max_asteroids)
|
||||
{
|
||||
#ifdef NDEBUG
|
||||
// Bump the warning count in release so they get something
|
||||
// even if the message never gets displayed.
|
||||
Warning(LOCATION, "Ignoring extra asteroid/debris");
|
||||
#else
|
||||
SCP_string msg("Ignoring extra asteroid/debris '");
|
||||
msg.append(new_asteroid.name);
|
||||
msg.append("'\n");
|
||||
Warning(LOCATION, msg.c_str());
|
||||
parsed_asteroids.push_back(msg);
|
||||
#endif
|
||||
}
|
||||
parsed_asteroids.push_back(msg);
|
||||
#endif
|
||||
Asteroid_info.push_back(new_asteroid);
|
||||
}
|
||||
tally++;
|
||||
}
|
||||
required_string("#End");
|
||||
|
||||
if (tally != max_asteroids)
|
||||
{
|
||||
else
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
for(SCP_vector<SCP_string>::iterator iter = parsed_asteroids.begin();
|
||||
iter != parsed_asteroids.end(); ++iter)
|
||||
{
|
||||
mprintf(("Asteroid.tbl as parsed:\n"));
|
||||
mprintf((iter->c_str()));
|
||||
SCP_string msg;
|
||||
msg.append("Parsing asteroid: '");
|
||||
msg.append(new_asteroid.name);
|
||||
msg.append("' as a '");
|
||||
msg.append((species == 0) ? "generic" : Species_info[species - 1].species_name);
|
||||
msg.append("'");
|
||||
switch (tally % NUM_DEBRIS_SIZES) {
|
||||
case ASTEROID_TYPE_SMALL:
|
||||
msg.append(" small\n");
|
||||
break;
|
||||
case ASTEROID_TYPE_MEDIUM:
|
||||
msg.append(" medium\n");
|
||||
break;
|
||||
case ASTEROID_TYPE_LARGE:
|
||||
msg.append(" large\n");
|
||||
break;
|
||||
default:
|
||||
Error(LOCATION, "Get a coder! Math has broken!\n"
|
||||
"Important numbers:\n"
|
||||
"\ttally: %d\n"
|
||||
"\tNUM_DEBRIS_SIZES: %d\n",
|
||||
tally, NUM_DEBRIS_SIZES
|
||||
);
|
||||
msg.append(" unknown\n");
|
||||
}
|
||||
parsed_asteroids.push_back(msg);
|
||||
#endif
|
||||
Asteroid_info.push_back(new_asteroid);
|
||||
}
|
||||
tally++;
|
||||
}
|
||||
required_string("#End");
|
||||
|
||||
if (tally != max_asteroids)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
for (SCP_vector<SCP_string>::iterator iter = parsed_asteroids.begin();
|
||||
iter != parsed_asteroids.end(); ++iter)
|
||||
{
|
||||
mprintf(("Asteroid.tbl as parsed:\n"));
|
||||
mprintf((iter->c_str()));
|
||||
}
|
||||
#endif
|
||||
Error(LOCATION,
|
||||
"Found %d asteroids/debris when %d expected\n\n"
|
||||
"<Number expected> = <Number of species> * %d + %d generic asteroids\n"
|
||||
"%d = %d*%d + %d\n\n"
|
||||
Error(LOCATION,
|
||||
"Found %d asteroids/debris when %d expected\n\n"
|
||||
"<Number expected> = <Number of species> * %d + %d generic asteroids\n"
|
||||
"%d = %d*%d + %d\n\n"
|
||||
#ifdef NDEBUG
|
||||
"Run a debug build to see a list of all parsed asteroids\n",
|
||||
"Run a debug build to see a list of all parsed asteroids\n",
|
||||
#else
|
||||
"See the debug.log for a listing of all parsed asteroids\n",
|
||||
"See the debug.log for a listing of all parsed asteroids\n",
|
||||
#endif
|
||||
tally, max_asteroids,
|
||||
NUM_DEBRIS_SIZES, NUM_DEBRIS_SIZES,
|
||||
max_asteroids, Species_info.size(), NUM_DEBRIS_SIZES, NUM_DEBRIS_SIZES
|
||||
);
|
||||
tally, max_asteroids,
|
||||
NUM_DEBRIS_SIZES, NUM_DEBRIS_SIZES,
|
||||
max_asteroids, Species_info.size(), NUM_DEBRIS_SIZES, NUM_DEBRIS_SIZES
|
||||
);
|
||||
}
|
||||
|
||||
Asteroid_impact_explosion_ani = -1;
|
||||
required_string("$Impact Explosion:");
|
||||
stuff_string(impact_ani_file, F_NAME, MAX_FILENAME_LEN);
|
||||
|
||||
if (VALID_FNAME(impact_ani_file)) {
|
||||
int num_frames;
|
||||
Asteroid_impact_explosion_ani = bm_load_animation(impact_ani_file, &num_frames, NULL, NULL, 1);
|
||||
}
|
||||
|
||||
required_string("$Impact Explosion Radius:");
|
||||
stuff_float(&Asteroid_impact_explosion_radius);
|
||||
|
||||
if (optional_string("$Briefing Icon Closeup Model:")) {
|
||||
stuff_string(Asteroid_icon_closeup_model, F_NAME, NAME_LENGTH);
|
||||
}
|
||||
else {
|
||||
strcpy_s(Asteroid_icon_closeup_model, Asteroid_info[ASTEROID_TYPE_LARGE].pof_files[0]); // magic file from retail
|
||||
}
|
||||
|
||||
if (optional_string("$Briefing Icon Closeup Position:")) {
|
||||
stuff_vec3d(&Asteroid_icon_closeup_position);
|
||||
}
|
||||
else {
|
||||
vm_vec_make(&Asteroid_icon_closeup_position, 0.0f, 0.0f, -334.0f); // magic numbers from retail
|
||||
}
|
||||
|
||||
if (optional_string("$Briefing Icon Closeup Zoom:")) {
|
||||
stuff_float(&Asteroid_icon_closeup_zoom);
|
||||
}
|
||||
else {
|
||||
Asteroid_icon_closeup_zoom = 0.5f; // magic number from retail
|
||||
}
|
||||
}
|
||||
|
||||
Asteroid_impact_explosion_ani = -1;
|
||||
required_string("$Impact Explosion:");
|
||||
stuff_string(impact_ani_file, F_NAME, MAX_FILENAME_LEN);
|
||||
|
||||
if ( VALID_FNAME(impact_ani_file) ) {
|
||||
int num_frames;
|
||||
Asteroid_impact_explosion_ani = bm_load_animation( impact_ani_file, &num_frames, NULL, NULL, 1);
|
||||
}
|
||||
|
||||
required_string("$Impact Explosion Radius:");
|
||||
stuff_float(&Asteroid_impact_explosion_radius);
|
||||
|
||||
if (optional_string("$Briefing Icon Closeup Model:")) {
|
||||
stuff_string(Asteroid_icon_closeup_model, F_NAME, NAME_LENGTH);
|
||||
} else {
|
||||
strcpy_s(Asteroid_icon_closeup_model, Asteroid_info[ASTEROID_TYPE_LARGE].pof_files[0]); // magic file from retail
|
||||
}
|
||||
|
||||
if (optional_string("$Briefing Icon Closeup Position:")) {
|
||||
stuff_vec3d(&Asteroid_icon_closeup_position);
|
||||
} else {
|
||||
vm_vec_make(&Asteroid_icon_closeup_position, 0.0f, 0.0f, -334.0f); // magic numbers from retail
|
||||
}
|
||||
|
||||
if (optional_string("$Briefing Icon Closeup Zoom:")) {
|
||||
stuff_float(&Asteroid_icon_closeup_zoom);
|
||||
} else {
|
||||
Asteroid_icon_closeup_zoom = 0.5f; // magic number from retail
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "asteroid.tbl", e.what()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1271,68 +1271,69 @@ void NavSystem_Init()
|
||||
|
||||
void parse_autopilot_table(char *filename)
|
||||
{
|
||||
int rval;
|
||||
SCP_vector<SCP_string> lines;
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0)
|
||||
try
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", (filename) ? filename : "<default autopilot.tbl>", rval));
|
||||
if (filename == NULL)
|
||||
read_file_text_from_array(defaults_get_file("autopilot.tbl"));
|
||||
else
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
|
||||
reset_parse();
|
||||
|
||||
|
||||
required_string("#Autopilot");
|
||||
|
||||
// autopilot link distance
|
||||
required_string("$Link Distance:");
|
||||
stuff_int(&NavLinkDistance);
|
||||
|
||||
if (optional_string("$Interrupt autopilot if enemy within distance:"))
|
||||
stuff_int(&AutopilotMinEnemyDistance);
|
||||
else
|
||||
AutopilotMinEnemyDistance = 5000;
|
||||
|
||||
if (optional_string("$Interrupt autopilot if asteroid within distance:"))
|
||||
stuff_int(&AutopilotMinAsteroidDistance);
|
||||
else
|
||||
AutopilotMinAsteroidDistance = 1000;
|
||||
|
||||
if (optional_string("$Lock Weapons During Autopilot:"))
|
||||
stuff_boolean(&LockWeaponsDuringAutopilot);
|
||||
else
|
||||
LockWeaponsDuringAutopilot = false;
|
||||
|
||||
// optional no cutscene bars
|
||||
if (optional_string("+No_Cutscene_Bars"))
|
||||
UseCutsceneBars = false;
|
||||
// optional no cutscene bars
|
||||
if (optional_string("+No_Autopilot_Interrupt"))
|
||||
Cmdline_autopilot_interruptable = 0;
|
||||
|
||||
// No Nav selected message
|
||||
char *msg_tags[] = { "$No Nav Selected:", "$Gliding:",
|
||||
"$Too Close:", "$Hostiles:", "$Linked:", "$Hazard:",
|
||||
"$Support Present:", "$Support Working:" };
|
||||
for (int i = 0; i < NP_NUM_MESSAGES; i++)
|
||||
{
|
||||
required_string(msg_tags[i]);
|
||||
|
||||
required_string("+Msg:");
|
||||
stuff_string(NavMsgs[i].message, F_MESSAGE, 256);
|
||||
|
||||
required_string("+Snd File:");
|
||||
stuff_string(NavMsgs[i].filename, F_NAME, 256);
|
||||
}
|
||||
|
||||
|
||||
required_string("#END");
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", (filename) ? filename : "<default autopilot.tbl>", e.what()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (filename == NULL)
|
||||
read_file_text_from_array(defaults_get_file("autopilot.tbl"));
|
||||
else
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
|
||||
reset_parse();
|
||||
|
||||
|
||||
required_string("#Autopilot");
|
||||
|
||||
// autopilot link distance
|
||||
required_string("$Link Distance:");
|
||||
stuff_int(&NavLinkDistance);
|
||||
|
||||
if (optional_string("$Interrupt autopilot if enemy within distance:"))
|
||||
stuff_int(&AutopilotMinEnemyDistance);
|
||||
else
|
||||
AutopilotMinEnemyDistance = 5000;
|
||||
|
||||
if (optional_string("$Interrupt autopilot if asteroid within distance:"))
|
||||
stuff_int(&AutopilotMinAsteroidDistance);
|
||||
else
|
||||
AutopilotMinAsteroidDistance = 1000;
|
||||
|
||||
if (optional_string("$Lock Weapons During Autopilot:"))
|
||||
stuff_boolean(&LockWeaponsDuringAutopilot);
|
||||
else
|
||||
LockWeaponsDuringAutopilot = false;
|
||||
|
||||
// optional no cutscene bars
|
||||
if (optional_string("+No_Cutscene_Bars"))
|
||||
UseCutsceneBars = false;
|
||||
// optional no cutscene bars
|
||||
if (optional_string("+No_Autopilot_Interrupt"))
|
||||
Cmdline_autopilot_interruptable = 0;
|
||||
|
||||
// No Nav selected message
|
||||
char *msg_tags[] = { "$No Nav Selected:", "$Gliding:",
|
||||
"$Too Close:", "$Hostiles:", "$Linked:", "$Hazard:",
|
||||
"$Support Present:", "$Support Working:" };
|
||||
for (int i = 0; i < NP_NUM_MESSAGES; i++)
|
||||
{
|
||||
required_string(msg_tags[i]);
|
||||
|
||||
required_string("+Msg:");
|
||||
stuff_string(NavMsgs[i].message, F_MESSAGE, 256);
|
||||
|
||||
required_string("+Snd File:");
|
||||
stuff_string(NavMsgs[i].filename, F_NAME, 256);
|
||||
}
|
||||
|
||||
|
||||
required_string("#END");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file bm_examples.cpp
|
||||
* This file contains example code for using bmpman.
|
||||
*/
|
||||
|
||||
#include "bmpman/bmpman.h"
|
||||
#include "graphics/2d.h"
|
||||
|
||||
void bm_create_example() {
|
||||
static int test_inited = 0;
|
||||
static int test_bmp;
|
||||
static uint test_bmp_data[128 * 64];
|
||||
|
||||
if (!test_inited) {
|
||||
test_inited = 1;
|
||||
// Create the new bitmap and fill in its data.
|
||||
// When you're done with it completely, call
|
||||
// bm_release to free up the bitmap handle
|
||||
test_bmp = bm_create(32, 128, 64, test_bmp_data);
|
||||
int i, j;
|
||||
for (i = 0; i < 64; i++) {
|
||||
for (j = 0; j < 64; j++) {
|
||||
uint r = i * 4;
|
||||
test_bmp_data[j + i * 128] = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// page out the data, so that the next bm_lock will convert the new data to
|
||||
// the correct bpp
|
||||
bm_unload(test_bmp);
|
||||
|
||||
// put in new data
|
||||
int x, y;
|
||||
gr_reset_clip();
|
||||
for (y = 0; y < 64; y++) {
|
||||
for (x = 0; x < 128; x++) {
|
||||
test_bmp_data[y * 128 + x] = 15;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the bitmap, the upper left corner is the origin (0, 0)
|
||||
gr_set_bitmap(test_bmp);
|
||||
gr_bitmap(0, 0);
|
||||
}
|
||||
+78
-81
@@ -1,121 +1,120 @@
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef __BM_INTERNAL_H__
|
||||
#define __BM_INTERNAL_H__
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file bm_internal.h
|
||||
* These are functions and types used by bmpman and a few others.
|
||||
*
|
||||
* @details It is a "protected" header that requires BMPMAN_INTERNAL to be defined before it can be included. This is to
|
||||
* provide a small measure of safety since this functions can cause problems if not used correctly
|
||||
*/
|
||||
|
||||
// extra check to make sure this stuff doesn't end up in normal files
|
||||
// don't use any of this unless BMPMAN_INTERNAL is defined
|
||||
#ifdef BMPMAN_INTERNAL
|
||||
#ifndef BMPMAN_INTERNAL
|
||||
#error The file header "bmpman/bm_internal.h" is protected. Make sure you know what you are doing!
|
||||
#endif
|
||||
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "bmpman/bmpman.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
|
||||
// Bitmap types
|
||||
enum BM_TYPE
|
||||
{
|
||||
BM_TYPE_NONE = 0, //!< No type
|
||||
BM_TYPE_USER, //!< in-memory
|
||||
BM_TYPE_PCX, //!< PCX
|
||||
BM_TYPE_TGA, //!< 16 or 32 bit targa
|
||||
BM_TYPE_DDS, //!< generic identifier for DDS
|
||||
BM_TYPE_PNG, //!< PNG
|
||||
BM_TYPE_JPG, //!< 32 bit jpeg
|
||||
BM_TYPE_ANI, //!< in-house ANI format
|
||||
BM_TYPE_EFF, //!< specifies any type of animated image, the EFF itself is just text
|
||||
|
||||
// no-type ( used in: bm_bitmaps[i].type )
|
||||
#define BM_TYPE_NONE 0
|
||||
// in-memory type ( used in: bm_bitmaps[i].type )
|
||||
#define BM_TYPE_USER 1
|
||||
// file-type types ( used in: bm_bitmaps[i].type )
|
||||
#define BM_TYPE_PCX 2
|
||||
#define BM_TYPE_TGA 3 // 16 or 32 bit targa
|
||||
#define BM_TYPE_DDS 4 // generic identifier for DDS
|
||||
#define BM_TYPE_PNG 5 // PNG
|
||||
#define BM_TYPE_JPG 6 // 32 bit jpeg
|
||||
#define BM_TYPE_ANI 7 // in-house ANI format
|
||||
#define BM_TYPE_EFF 8 // specifies any type of animated image, the EFF itself is just text
|
||||
// c-type types ( used in: bm_bitmaps[i].c_type )
|
||||
#define BM_TYPE_DXT1 9 // 24 bit with switchable alpha (compressed)
|
||||
#define BM_TYPE_DXT3 10 // 32 bit with 4 bit alpha (compressed)
|
||||
#define BM_TYPE_DXT5 11 // 32 bit with 8 bit alpha (compressed)
|
||||
#define BM_TYPE_CUBEMAP_DDS 12 // generic DDS cubemap (uncompressed cubemap surface)
|
||||
#define BM_TYPE_CUBEMAP_DXT1 13 // 24-bit cubemap (compressed cubemap surface)
|
||||
#define BM_TYPE_CUBEMAP_DXT3 14 // 32-bit cubemap (compressed cubemap surface)
|
||||
#define BM_TYPE_CUBEMAP_DXT5 15 // 32-bit cubemap (compressed cubemap surface)
|
||||
// special types ( used in: bm_bitmaps[i].type )
|
||||
#define BM_TYPE_RENDER_TARGET_STATIC 16 // 24/32 bit setup internally as a static render target
|
||||
#define BM_TYPE_RENDER_TARGET_DYNAMIC 17 // 24/32 bit setup internally as a dynamic render target
|
||||
// special types
|
||||
BM_TYPE_RENDER_TARGET_STATIC, //!< 24/32 bit setup internally as a static render target
|
||||
BM_TYPE_RENDER_TARGET_DYNAMIC, //!< 24/32 bit setup internally as a dynamic render target
|
||||
|
||||
// Compressed types (bitmap.c_type)
|
||||
BM_TYPE_DXT1, //!< 24 bit with switchable alpha
|
||||
BM_TYPE_DXT3, //!< 32 bit with 4 bit alpha
|
||||
BM_TYPE_DXT5, //!< 32 bit with 8 bit alpha
|
||||
BM_TYPE_CUBEMAP_DDS, //!< generic DDS cubemap (uncompressed cubemap surface)
|
||||
BM_TYPE_CUBEMAP_DXT1, //!< 24-bit cubemap (compressed cubemap surface)
|
||||
BM_TYPE_CUBEMAP_DXT3, //!< 32-bit cubemap (compressed cubemap surface)
|
||||
BM_TYPE_CUBEMAP_DXT5 //!< 32-bit cubemap (compressed cubemap surface)
|
||||
};
|
||||
|
||||
/// Moved from cpp file ///////////////////
|
||||
// Consider these 'protected' structures and functions that should only be used by special bitmap functions
|
||||
typedef union bm_extra_info {
|
||||
union bm_extra_info {
|
||||
struct {
|
||||
// Stuff needed for animations
|
||||
int first_frame; // used for animations -- points to index of first frame
|
||||
int num_frames; // used for animation -- number of frames in the animation
|
||||
int keyframe; // used for animation -- keyframe info
|
||||
ubyte fps; // used for animation -- frames per second
|
||||
int first_frame; //!< used for animations -- points to index of first frame
|
||||
int num_frames; //!< used for animations -- number of frames in the animation
|
||||
int keyframe; //!< used for animations -- keyframe info
|
||||
ubyte fps; //!< used for animations -- frames per second
|
||||
|
||||
struct {
|
||||
// stuff for static animations
|
||||
ubyte type; // type for individual images
|
||||
char filename[MAX_FILENAME_LEN]; // filename for individual images
|
||||
ubyte type; //!< type for individual images
|
||||
char filename[MAX_FILENAME_LEN]; //!< filename for individual images
|
||||
bool in_subdir; // Whether frames are in their own subdirectory
|
||||
} eff;
|
||||
} ani;
|
||||
|
||||
struct {
|
||||
// Stuff needed for user bitmaps
|
||||
void *data; // For user bitmaps, this is where the data comes from
|
||||
ubyte bpp; // For user bitmaps, this is what format the data is
|
||||
ubyte flags; // Flags passed to bm_create
|
||||
void* data; //!< For user bitmaps, this is where the data comes from
|
||||
ubyte bpp; //!< For user bitmaps, this is what format the data is
|
||||
ubyte flags; //!< For user bitmaps, Flags passed to bm_create
|
||||
} user;
|
||||
} bm_extra_info;
|
||||
};
|
||||
|
||||
|
||||
typedef struct bitmap_entry {
|
||||
struct bitmap_entry {
|
||||
// identification
|
||||
char filename[MAX_FILENAME_LEN]; // filename for this bitmap
|
||||
char filename[MAX_FILENAME_LEN]; //!< filename for this bitmap
|
||||
|
||||
uint signature; // a unique signature identifying the data
|
||||
uint palette_checksum; // checksum used to be sure bitmap is in current palette
|
||||
int handle; // Handle = id*MAX_BITMAPS + bitmapnum
|
||||
int last_used; // When this bitmap was last used
|
||||
uint signature; //!< a unique signature identifying the data
|
||||
uint palette_checksum; //!< checksum used to be sure bitmap is in current palette
|
||||
int handle; //!< Handle = id*MAX_BITMAPS + bitmapnum
|
||||
int last_used; //!< When this bitmap was last used
|
||||
|
||||
ubyte type; // PCX, USER, ANI, etc
|
||||
ubyte comp_type; // What sort of compressed type, BM_TYPE_NONE if not compressed
|
||||
signed char ref_count; // Number of locks on bitmap. Can't unload unless ref_count is 0.
|
||||
ubyte type; //!< PCX, USER, ANI, etc
|
||||
ubyte comp_type; //!< What sort of compressed type, BM_TYPE_NONE if not compressed
|
||||
signed char ref_count; //!< Number of locks on bitmap. Can't unload unless ref_count is 0.
|
||||
|
||||
int dir_type; // which directory this was loaded from (to skip other locations with same name)
|
||||
int dir_type; //!< which directory this was loaded from (to skip other locations with same name)
|
||||
|
||||
// compressed bitmap stuff (.dds) - RT please take a look at this and tell me if we really need it
|
||||
int mem_taken; // How much memory does this bitmap use? - UnknownPlayer
|
||||
int num_mipmaps; // number of mipmap levels, we need to read all of them
|
||||
int mem_taken; //!< How much memory does this bitmap use? - UnknownPlayer
|
||||
int num_mipmaps; //!< number of mipmap levels, we need to read all of them
|
||||
|
||||
// Stuff to keep track of usage
|
||||
ubyte preloaded; // If set, then this was loaded from the lst file
|
||||
int preload_count; // how many times this gets used in game, for unlocking
|
||||
ubyte used_flags; // What flags it was accessed thru
|
||||
int load_count;
|
||||
ubyte preloaded; //!< If set, then this was loaded from the lst file
|
||||
int preload_count; //!< how many times this gets used in game, for unlocking
|
||||
ubyte used_flags; //!< What flags it was accessed thru
|
||||
int load_count;
|
||||
|
||||
// Bitmap info
|
||||
bitmap bm;
|
||||
bitmap bm; //!< Bitmap info
|
||||
|
||||
// Data for animations and user bitmaps
|
||||
bm_extra_info info;
|
||||
bm_extra_info info; //!< Data for animations and user bitmaps
|
||||
|
||||
#ifdef BMPMAN_NDEBUG
|
||||
// bookeeping
|
||||
ubyte used_last_frame; // If set, then it was used last frame
|
||||
ubyte used_this_frame; // If set, then it was used this frame
|
||||
int data_size; // How much data this bitmap uses
|
||||
int used_count; // How many times it was accessed
|
||||
ubyte used_last_frame; // If set, then it was used last frame
|
||||
ubyte used_this_frame; // If set, then it was used this frame
|
||||
int data_size; // How much data this bitmap uses
|
||||
int used_count; // How many times it was accessed
|
||||
#endif
|
||||
} bitmap_entry;
|
||||
};
|
||||
|
||||
extern bitmap_entry bm_bitmaps[MAX_BITMAPS];
|
||||
|
||||
|
||||
// image specific lock functions
|
||||
void bm_lock_ani( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags );
|
||||
void bm_lock_dds( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags );
|
||||
@@ -126,6 +125,4 @@ void bm_lock_tga( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyt
|
||||
void bm_lock_user( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags );
|
||||
|
||||
|
||||
#endif // BMPMAN_INTERNAL
|
||||
|
||||
#endif // __BM_INTERNAL_H__
|
||||
+1865
-1971
File diff suppressed because it is too large.
Load diff
+555
-200
@@ -1,288 +1,643 @@
|
||||
#ifndef _BMPMAN_H
|
||||
#define _BMPMAN_H
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file bmpman.h
|
||||
* Header file for the bitmap manager (bmpman)
|
||||
*/
|
||||
|
||||
/**
|
||||
* @example bm_examples.cpp
|
||||
* @brief This containes examples of bmpman usage
|
||||
*/
|
||||
|
||||
#ifndef _BMPMAN_H
|
||||
#define _BMPMAN_H
|
||||
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "cfile/cfile.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define BMPMAN_NDEBUG
|
||||
#define BMPMAN_NDEBUG //!< Enables BMPMAN debugging code
|
||||
#endif
|
||||
|
||||
#define MAX_BITMAPS 4750 // How many bitmaps the game can handle
|
||||
// NOTE: MAX_BITMAPS shouldn't need to be bumped again. With the fixed bm_release() and it's
|
||||
// proper use even the largest missions should stay under this number. With the largest retail
|
||||
// missions and wasteful content we should still have about 20% of the slots free. If it still
|
||||
// goes over then it's something the artists need to fix. For instance the Terran Mara fighter,
|
||||
// with -spec and -glow and using the Shinepack, needs 117 bitmap slots alone. 111 of those is
|
||||
// just for the glowmaps. This number can be greatly reduced if the number of ani frames for
|
||||
// another LOD than LOD0 has fewer or no ani frames. A 37 frame glow ani for LOD2 is little
|
||||
// more than a waste of resources. Future reports of texture corruption should be initially
|
||||
// approached with content as the cause and not code. If anything we could/should reduce
|
||||
// MAX_BITMAPS in the future. Where it's at now should accomidate even the largest mods.
|
||||
// -- Taylor
|
||||
/**
|
||||
* @defgroup BMPMAN_CONSTANTS Macro constants used in/with bmpman.h
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief How many bitmaps the game can handle
|
||||
*
|
||||
* @attention MAX_BITMAPS shouldn't need to be bumped again. With the fixed bm_release() and it's proper use even the
|
||||
* largest missions should stay under this number. With the largest retail missions and wasteful content we should
|
||||
* still have about 20% of the slots free. If it still goes over then it's something the artists need to fix.
|
||||
* For instance the Terran Mara fighter, with -spec and -glow and using the Shinepack, needs 117 bitmap slots alone.
|
||||
* 111 of those is just for the glowmaps. This number can be greatly reduced if the number of ani frames for another
|
||||
* LOD than LOD0 has fewer or no ani frames. A 37 frame glow ani for LOD2 is little more than a waste of resources.
|
||||
* Future reports of texture corruption should be initially approached with content as the cause and not code.
|
||||
* If anything we could/should reduce MAX_BITMAPS in the future. Where it's at now should accomidate even the
|
||||
* largest mods. -- Taylor
|
||||
*/
|
||||
#define MAX_BITMAPS 4750
|
||||
|
||||
#define BMP_AABITMAP (1<<0) // antialiased bitmap
|
||||
#define BMP_TEX_XPARENT (1<<1) // transparent texture
|
||||
#define BMP_TEX_OTHER (1<<2) // so we can identify all "normal" textures
|
||||
#define BMP_TEX_DXT1 (1<<3) // dxt1 compressed 8r8g8b1a (24bit)
|
||||
#define BMP_TEX_DXT3 (1<<4) // dxt3 compressed 8r8g8b4a (32bit)
|
||||
#define BMP_TEX_DXT5 (1<<5) // dxt5 compressed 8r8g8b8a (32bit)
|
||||
#define BMP_TEX_CUBEMAP (1<<6) // a texture made for cubic environment map
|
||||
// Flag positions for bitmap.flags
|
||||
// ***** NOTE: bitmap.flags is an 8-bit value, no more BMP_TEX_* flags can be added unless the type is changed!! ******
|
||||
#define BMP_AABITMAP (1<<0) //!< antialiased bitmap
|
||||
#define BMP_TEX_XPARENT (1<<1) //!< transparent texture
|
||||
#define BMP_TEX_OTHER (1<<2) //!< so we can identify all "normal" textures
|
||||
#define BMP_TEX_DXT1 (1<<3) //!< dxt1 compressed 8r8g8b1a (24bit)
|
||||
#define BMP_TEX_DXT3 (1<<4) //!< dxt3 compressed 8r8g8b4a (32bit)
|
||||
#define BMP_TEX_DXT5 (1<<5) //!< dxt5 compressed 8r8g8b8a (32bit)
|
||||
#define BMP_TEX_CUBEMAP (1<<6) //!< a texture made for cubic environment map
|
||||
|
||||
//compressed texture types
|
||||
#define BMP_TEX_COMP ( BMP_TEX_DXT1 | BMP_TEX_DXT3 | BMP_TEX_DXT5 )
|
||||
// Combined flags
|
||||
#define BMP_TEX_COMP ( BMP_TEX_DXT1 | BMP_TEX_DXT3 | BMP_TEX_DXT5 ) //!< Compressed textures
|
||||
#define BMP_TEX_NONCOMP ( BMP_TEX_XPARENT | BMP_TEX_OTHER ) //!< Non-compressed textures
|
||||
#define BMP_TEX_ANY ( BMP_TEX_COMP | BMP_TEX_NONCOMP ) //!< Any texture
|
||||
|
||||
//non compressed textures
|
||||
#define BMP_TEX_NONCOMP ( BMP_TEX_XPARENT | BMP_TEX_OTHER )
|
||||
// Flag positions for bitmap.type
|
||||
#define BMP_FLAG_RENDER_TARGET_STATIC (1<<0) //!< Texture is a static type
|
||||
#define BMP_FLAG_RENDER_TARGET_DYNAMIC (1<<1) //!< Texture is a dynamic type (animation)
|
||||
#define BMP_FLAG_CUBEMAP (1<<2) //!< Texture is a cubemap
|
||||
|
||||
// any texture type
|
||||
#define BMP_TEX_ANY ( BMP_TEX_COMP | BMP_TEX_NONCOMP )
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#define BMP_FLAG_RENDER_TARGET_STATIC (1<<0)
|
||||
#define BMP_FLAG_RENDER_TARGET_DYNAMIC (1<<1)
|
||||
#define BMP_FLAG_CUBEMAP (1<<2)
|
||||
struct bitmap
|
||||
{
|
||||
short w; //!< Width, in number of pixels
|
||||
short h; //!< Height, in number of pixels
|
||||
short rowsize; //!< What you need to add to go to next row
|
||||
ubyte bpp; //!< Requested bitdepth of each pixel. ( 7, 8, 15, 16, 24, 32)
|
||||
ubyte true_bpp; //!< The image's actual bitdepth
|
||||
ubyte flags; //!< Various texture type flags. @see BMPMAN_CONSTANTS
|
||||
ptr_u data; //!< Pointer to data, or maybe offset into VRAM.
|
||||
ubyte *palette; /**< @brief Pointer to this bitmap's palette (if it has one).
|
||||
* @details If BMP_NO_PALETTE_MAP flag is cleared, this palette just points to the screen palette. (gr_palette)
|
||||
*/
|
||||
};
|
||||
|
||||
typedef struct bitmap {
|
||||
short w, h; // Width and height
|
||||
short rowsize; // What you need to add to go to next row
|
||||
ubyte bpp; // How many bits per pixel it is. (7,8,15,16,24,32) (what is requested)
|
||||
ubyte true_bpp; // How many bits per pixel the image actually is.
|
||||
ubyte flags; // See the BMP_???? defines for values (this isn't for the BMP_FLAG_* stuff)
|
||||
ptr_u data; // Pointer to data, or maybe offset into VRAM.
|
||||
ubyte *palette; // If bpp==8, this is pointer to palette. If the BMP_NO_PALETTE_MAP flag
|
||||
// is not set, this palette just points to the screen palette. (gr_palette)
|
||||
} bitmap;
|
||||
extern int bm_texture_ram; //!< how many bytes of textures are used.
|
||||
|
||||
extern int Bm_paging; //!< Bool type that indicates if BMPMAN is currently paging.
|
||||
|
||||
extern int Bm_paging;
|
||||
extern const ubyte bm_type_list[]; //!< List of valid bitmap types
|
||||
extern const char *bm_ext_list[]; //!< List of extensions for those types
|
||||
extern const int BM_NUM_TYPES; //!< Calculated number of bitmap types
|
||||
extern const ubyte bm_ani_type_list[]; //!< List of valid bitmap animation types
|
||||
extern const char *bm_ani_ext_list[]; //!< List of extensions for those types
|
||||
extern const int BM_ANI_NUM_TYPES; //!< Calculated number of bitmap animation types
|
||||
|
||||
extern int GLOWMAP; //!< References a map that is a fully lit version of its index -Bobboau
|
||||
extern int SPECMAP; //!< References a map that is for specular mapping -Bobboau
|
||||
extern int ENVMAP; //!< References a map that is for environment mapping -Bobboau
|
||||
extern int NORMMAP; //!< Normal mapping
|
||||
extern int HEIGHTMAP; //!< Height map for normal mapping
|
||||
extern int MISCMAP; //!< Utility map, to be utilized for various things shader authors can come up with
|
||||
|
||||
/**
|
||||
* @brief Initilizes the bitmap manager
|
||||
*/
|
||||
void bm_init();
|
||||
|
||||
/**
|
||||
* @brief Closes the bitmap manager, freeing any allocated memory used by bitmaps. Is called at program close.
|
||||
*/
|
||||
void bm_close();
|
||||
|
||||
int bm_get_cache_slot( int bitmap_id, int separate_ani_frames );
|
||||
/**
|
||||
* Gets the cache slot of the bitmap indexed by handle.
|
||||
*
|
||||
* @details if the bitmap is an ani, gets the first frame
|
||||
*
|
||||
* @returns The cache slot index of the bitmap if handle is valid
|
||||
*
|
||||
* @note If the handle is invalid, an Assert() fails
|
||||
*/
|
||||
int bm_get_cache_slot(int bitmap_id, int separate_ani_frames);
|
||||
|
||||
/**
|
||||
* @brief Gets the next available bitmap slot.
|
||||
*/
|
||||
int bm_get_next_handle();
|
||||
|
||||
void *bm_malloc(int n, int size);
|
||||
/**
|
||||
* @brief Allocates memory for the given handle.
|
||||
*
|
||||
* @returns A pointer to the allocated vm if successful,
|
||||
* @returns Null, if unsuccessful
|
||||
*
|
||||
* @note z64 - This function looks fishy. Not only is handle not used in release builds, but bm_bitmaps[handle].size
|
||||
* and bm_texture_size aren't modified unless this is a debug build
|
||||
*/
|
||||
void *bm_malloc(int handle, int size);
|
||||
|
||||
/**
|
||||
* @brief (DEBUG) Similar to bm_malloc, but only updates how much memory is used
|
||||
*
|
||||
* @note z64 - Also fishy (see bm_malloc)
|
||||
*/
|
||||
void bm_update_memory_used(int n, int size);
|
||||
|
||||
// how many bytes of textures are used.
|
||||
extern int bm_texture_ram;
|
||||
|
||||
// This loads a bitmap so we can draw with it later.
|
||||
// It returns a negative number if it couldn't load
|
||||
// the bitmap. On success, it returns the bitmap
|
||||
// number.
|
||||
/**
|
||||
* @brief Loads a bitmap so we can draw with it later.
|
||||
*
|
||||
* @param filename
|
||||
*
|
||||
* @returns The bitmap number if successful, else
|
||||
* @returns a negative value if not
|
||||
*/
|
||||
int bm_load(const char* filename);
|
||||
|
||||
/**
|
||||
* @brief Loads a bitmap so we can draw with it later. (Preferred version)
|
||||
*
|
||||
* @param filename
|
||||
*
|
||||
* @returns The bitmap number if successful, else
|
||||
* @returns a negative value if not
|
||||
*/
|
||||
int bm_load(const SCP_string& filename);
|
||||
|
||||
// special load function. basically allows you to load a bitmap which already exists (by filename).
|
||||
// this is useful because in some cases we need to have a bitmap which is locked in screen format
|
||||
// _and_ texture format, such as pilot pics and squad logos
|
||||
/**
|
||||
* @brief Reloads a bitmap as a duplicate.
|
||||
*
|
||||
* @details This function basically allows you to load a bitmap which already exists (by filename). This is useful
|
||||
* because in some cases we need to have a bitmap which is locked in screen format _and_ texture format, such as
|
||||
* the pilot pics and squad logos
|
||||
*
|
||||
* @param filename
|
||||
*
|
||||
* @returns The bitmap number if successful, else
|
||||
* @returns a negative value if not
|
||||
*/
|
||||
int bm_load_duplicate(const char *filename);
|
||||
|
||||
// Creates a bitmap that exists in RAM somewhere, instead
|
||||
// of coming from a disk file. You pass in a pointer to a
|
||||
// block of data. The data can be in the following formats:
|
||||
// 8 bpp (mapped into game palette)
|
||||
// 32 bpp
|
||||
// On success, it returns the bitmap number. You cannot
|
||||
// free that RAM until bm_release is called on that bitmap.
|
||||
// See example at bottom of this file
|
||||
int bm_create( int bpp, int w, int h, void *data = NULL, int flags = 0);
|
||||
/**
|
||||
* Loads a bitmap which exists somewhere in the RAM.
|
||||
*
|
||||
* @param bpp The bitdepth of the bitmap
|
||||
* @param w The width of the bitmap
|
||||
* @param h The height of the bitmap
|
||||
* @param[in] data The bitmap's data glob
|
||||
* @param flags
|
||||
*
|
||||
* @note The used RAM cannot be freed until bm_release is called on the created bitmap
|
||||
*/
|
||||
int bm_create(int bpp, int w, int h, void *data = NULL, int flags = 0);
|
||||
|
||||
// Frees up a bitmap's data, but bitmap number 'n' can
|
||||
// still be used, it will just have to be paged in next
|
||||
// time it is locked.
|
||||
int bm_unload( int n, int clear_render_targets = 0, bool nodebug = false);
|
||||
/**
|
||||
* @brief Unloads a bitmap's data, but not the bitmap info
|
||||
*
|
||||
* @details The bm number (n) may be reused once this function has been called on it. However, it will have to be paged
|
||||
* in the next time it is locked.
|
||||
|
||||
// like bm_unload() except that it's safe to use to free data without worrying about
|
||||
// load_count so it's safe to use in relation to bm_release() and in gr_*_texture functions
|
||||
int bm_unload_fast( int n, int clear_render_targets = 0 );
|
||||
* @param handle The index number of the bitmap to free
|
||||
* @param clear_render_targets If true, release a render target
|
||||
* @param nodebug If true, exclude certain debug messages
|
||||
*
|
||||
* @returns 0 if not successful,
|
||||
* @returns 1 if successful
|
||||
*/
|
||||
int bm_unload(int handle, int clear_render_targets = 0, bool nodebug = false);
|
||||
|
||||
// Frees up a bitmap's data, and it's slot, so bitmap
|
||||
// number 'n' cannot be used anymore, and bm_load or
|
||||
// bm_create might reuse the slot.
|
||||
int bm_release( int n, int clear_render_targets = 0 );
|
||||
/**
|
||||
* @brief Quickly unloads a bitmap's data, ignoring the load_count
|
||||
*
|
||||
* @details Similar to bm_unload(), except that it can be safely used to free data without worrying about load_count.
|
||||
* It's safe to use in relation to bm_release() and in gr_*_texture functions
|
||||
*
|
||||
* @param handle The bm number of the bitmap to free
|
||||
* @param clear_render_targets If true, release a render target
|
||||
*
|
||||
* @note bm_free_data_fast() is used here and NOT bm_free_data()
|
||||
*/
|
||||
int bm_unload_fast(int handle, int clear_render_targets = 0);
|
||||
|
||||
// This loads a bitmap sequence so we can draw with it later.
|
||||
// It returns a negative number if it couldn't load
|
||||
// the bitmap. On success, it returns the bitmap
|
||||
// number of the first frame and nframes is set.
|
||||
extern int bm_load_animation( const char *filename, int *nframes = NULL, int *fps = NULL, int *keyframe = NULL, int can_drop_frames = 0, int dir_type = CF_TYPE_ANY );
|
||||
/**
|
||||
* @brief Frees both a bitmap's data and it's associated slot.
|
||||
*
|
||||
* @details Once called, the bm number 'n' cannot be used until bm_load or bm_create is re-inits the slot.
|
||||
*
|
||||
* @param handle The index number of the bitmap to release
|
||||
* @param clear_render_targets If nonzero, also release render targets
|
||||
*
|
||||
* @returns 1 on success,
|
||||
* @returns 0 otherwise
|
||||
*
|
||||
* @note If the passed handle is that of an ANI, it frees EVERY frame. Be sure to only pass the handle of the first frame!
|
||||
*
|
||||
* @todo upgrade return type and clear_render_targets type to bools
|
||||
*/
|
||||
int bm_release(int handle, int clear_render_targets = 0);
|
||||
|
||||
//Loads either animation (bm_load_animation) or still image (bm_load)
|
||||
extern int bm_load_either(const char *filename, int *nframes = NULL, int *fps = NULL, int *keyframe = NULL, int can_drop_frames = 0, int dir_type = CF_TYPE_ANY);
|
||||
/**
|
||||
* @brief Loads a bitmap sequance so we can draw with it.
|
||||
*
|
||||
* @param[in] filename
|
||||
* @param[out] nframes If non-null, set to the number of frames the animation has
|
||||
* @param[out] fps If non-null, set to the fps of this animation
|
||||
* @param[out] keyframe if non null, set to the keyframe index of this animation
|
||||
* @param[in] can_drop_frames If set, allows dropped frames
|
||||
* @param[in] dir_type Directory type
|
||||
*
|
||||
* @returns The bm number of the first bitmap in the sequence if successful, or
|
||||
* @returns A negative value if unsuccessful
|
||||
*/
|
||||
int bm_load_animation(const char *filename, int *nframes = NULL, int *fps = NULL, int *keyframe = NULL, int can_drop_frames = 0, int dir_type = CF_TYPE_ANY);
|
||||
|
||||
// This locks down a bitmap and returns a pointer to a bitmap
|
||||
// that can be accessed until you call bm_unlock. Only lock
|
||||
// a bitmap when you need it! This will convert it into the
|
||||
// appropriate format also.
|
||||
extern bitmap * bm_lock( int bitmapnum, ubyte bpp, ubyte flags, bool nodebug = false);
|
||||
/**
|
||||
* @brief Loads either animation (bm_load_animation) or still image (bm_load)
|
||||
*
|
||||
* @param[in] filename
|
||||
* @param[out] nframes If non-null and loading was successful, set to the number of frames the animation has
|
||||
* @param[out] fps If non-null and loading was successful, set to the fps of this animation
|
||||
* @param[out] keyframe if non null and loading was successful, set to the keyframe index of this animation
|
||||
* @param[in] can_drop_frames
|
||||
* @param[in] dir_type
|
||||
*
|
||||
* @returns The bm number of the first bitmap in the sequence if successful, or
|
||||
* @returns A negative value if unsuccessful
|
||||
*/
|
||||
int bm_load_either(const char *filename, int *nframes = NULL, int *fps = NULL, int *keyframe = NULL, int can_drop_frames = 0, int dir_type = CF_TYPE_ANY);
|
||||
|
||||
// The signature is a field that gets filled in with
|
||||
// a unique signature for each bitmap. The signature for each bitmap
|
||||
// will also change when the bitmap's data changes.
|
||||
extern uint bm_get_signature( int bitmapnum);
|
||||
/**
|
||||
* @brief Locks down the bitmap indexed by bitmapnum.
|
||||
*
|
||||
* @details Also converts the bitmap to the appropriate format specified by bpp and flags. Only lock a bitmap when you
|
||||
* need it!
|
||||
*
|
||||
* @param bitmapnum The number indexing the desired bitmap
|
||||
* @param bpp The desired bpp of the bitmep
|
||||
* @param flags The desired bitmap format
|
||||
* @param nodebug
|
||||
|
||||
//gets the image type
|
||||
* @returns A pointer to the bitmap that's valid until bm_unlock is called if successful, or
|
||||
* @returns NULL if unsuccessful
|
||||
*/
|
||||
bitmap* bm_lock(int handle, ubyte bpp, ubyte flags, bool nodebug = false);
|
||||
|
||||
/**
|
||||
* @brief Returns a unique signiature for the bitmap indexed by handle
|
||||
*
|
||||
* @details A signature will change when the bitmap's data changes
|
||||
*/
|
||||
uint bm_get_signature(int handle);
|
||||
|
||||
/**
|
||||
* @brief Returns the image type of the given bitmap handle
|
||||
*/
|
||||
ubyte bm_get_type(int handle);
|
||||
|
||||
// Unlocks a bitmap
|
||||
extern void bm_unlock( int bitmapnum );
|
||||
/**
|
||||
* @brief Unlocks a bitmap
|
||||
*
|
||||
* @details Decrements the ref_count member of the bitmap_entry struct, A bitmap can only be unloaded when the
|
||||
* ref_count is 0
|
||||
*/
|
||||
void bm_unlock(int handle);
|
||||
|
||||
//WMC - Returns 0 if invalid, nonzero if valid
|
||||
extern int bm_is_valid(int handle);
|
||||
/**
|
||||
* @brief Checks if the bitmap indexed by handle is valid
|
||||
*
|
||||
* @details Some early known false or out of range handles (such as negative) are checked within
|
||||
* an initial routine pass, followed by a more thorough check routine to ensure the
|
||||
* series of bitmaps within the bm_bitmaps[] structure have not become invalid.
|
||||
*
|
||||
* @returns Nonzero if valid, else
|
||||
* @returns Zero otherwise
|
||||
*
|
||||
* @todo z64 - Returned value is essentially a bool type, need to check all caller functions to see if it can safely
|
||||
* be updated to reflect this
|
||||
*/
|
||||
int bm_is_valid(int handle);
|
||||
|
||||
// Gets info. w,h,or flags,nframes or fps can be NULL if you don't care.
|
||||
//WMC - Returns -1 on failure, handle or first frame handle on success.
|
||||
int bm_get_info( int bitmapnum, int *w=NULL, int * h=NULL, ubyte * flags=NULL, int *nframes=NULL, int *fps=NULL );
|
||||
/**
|
||||
* @brief Gets info on the bitmap indexed by handle.
|
||||
*
|
||||
* @param[out] w If non-null, gets the width
|
||||
* @param[out] h If non-null, gets the heigth
|
||||
* @param[out] flags If non-null, gets the flags
|
||||
* @param[out] nframs If non-null, gets the nframes
|
||||
* @param[out] fps If non-null, gets the fps
|
||||
*
|
||||
* @returns The handle on success, or
|
||||
* @returns The handle to the first frame on success, or
|
||||
* @returns -1 on failure
|
||||
*/
|
||||
int bm_get_info(int handle, int *w = NULL, int * h = NULL, ubyte * flags = NULL, int *nframes = NULL, int *fps = NULL);
|
||||
|
||||
// get filename
|
||||
extern void bm_get_filename(int bitmapnum, char *filename);
|
||||
/**
|
||||
* @brief Gets the filename of the bitmap indexed by handle
|
||||
*
|
||||
* @param[out] filename The filename of the bitmap, if successful. Is set to an empty string if unseccessful
|
||||
*
|
||||
* @todo z64 - maybe deprecate this in favor of an SCP_string version
|
||||
*/
|
||||
void bm_get_filename(int bitmapnum, char *filename);
|
||||
|
||||
// call to load all data for all bitmaps that have been requested to be loaded
|
||||
extern void bm_gfx_load_all();
|
||||
extern void bm_unload_all();
|
||||
/**
|
||||
* @brief Gets the filename of the bitmap indexed by handle, which must exist.
|
||||
*
|
||||
* @details If the bitmap does not exist (i.e. the handle is invalid), then an Assertion halts program execution.
|
||||
*
|
||||
* @returns A const char* to the filename of the bitmap
|
||||
*
|
||||
* @todo z64 - maybe deprecate this in favor of an SCP_string version.
|
||||
* @todo z64 - maybe combine this with the other bm_get_filename function like so:
|
||||
* void bm_get_filename(int handle, SCP_string *filename, bool must_exist = false);
|
||||
*/
|
||||
const char *bm_get_filename(int handle);
|
||||
|
||||
// call to get the palette for a bitmap
|
||||
void bm_get_palette(int n, ubyte *pal, char *name);
|
||||
/**
|
||||
* @brief Loads all data for all bitmaps that have been requested to be loaded
|
||||
*
|
||||
* @note This function is not defined.
|
||||
*/
|
||||
void bm_gfx_load_all();
|
||||
|
||||
// Hacked function to get a pixel from a bitmap.
|
||||
// Only works good in 8bpp mode.
|
||||
void bm_gfx_get_pixel( int bitmap, float u, float v, ubyte *r, ubyte *g, ubyte *b );
|
||||
/**
|
||||
* @brief Unloads all used bitmaps, should only ever be called by game_shutdown()
|
||||
*
|
||||
* @todo Maybe move this declaration into bmpman.cpp and then extern this function within game_shutdown() to
|
||||
* ensure it only ever gets called there.
|
||||
*/
|
||||
void bm_unload_all();
|
||||
|
||||
// Returns number of bytes of bitmaps locked this frame
|
||||
// ntotal = number of bytes of bitmaps locked this frame
|
||||
// nnew = number of bytes of bitmaps locked this frame that weren't locked last frame
|
||||
/**
|
||||
* @brief Gets the palette for a given bitmap indexed by handle, and optionally the filename
|
||||
*
|
||||
* @param[out] pal Is set to reference the bitmap's palette
|
||||
* @param[out] name (optional) Is set to the bitmap's filename
|
||||
*
|
||||
* @todo Maybe get rid of the optional filename and have the callers call bm_get_filename. Less efficient, however.
|
||||
*/
|
||||
void bm_get_palette(int handle, ubyte *pal, char *name);
|
||||
|
||||
/**
|
||||
* @brief Hack to get a pixel from a bitmap
|
||||
*
|
||||
* @details only works good in 8bpp mode
|
||||
*
|
||||
* @note This function is not defined.
|
||||
*/
|
||||
void bm_gfx_get_pixel(int bitmap, float u, float v, ubyte *r, ubyte *g, ubyte *b);
|
||||
|
||||
/**
|
||||
* @brief (DEBUG) Gets memory size, in bytes, of the locked bitmaps
|
||||
*
|
||||
* @details Both params are non-optional, and must be non-null. There's currently no safety checks on either.
|
||||
*
|
||||
* @param ntotal[out] Memory size, in bytes, of the locked bitmaps
|
||||
* @param nnew[out] Memory size, in bytes, of the bitmaps that were locked since the last frame
|
||||
*
|
||||
* @note This is a debug function, and is undefined within release builds
|
||||
*/
|
||||
void bm_get_frame_usage(int *ntotal, int *nnew);
|
||||
|
||||
// Reload a different image into an existing bmpman slot
|
||||
/**
|
||||
* @brief Reloads an existing bmpman slot with different bitmap
|
||||
*
|
||||
* @param[in] filename The filename of the image to load
|
||||
*
|
||||
* @returns The bitmap handle on success, or
|
||||
* @returns A negative value on failure
|
||||
*
|
||||
* @note This should only be used if you are certain the new picture is the same type, has same dimensions, etc.
|
||||
*/
|
||||
int bm_reload(int bitmap_handle, const char* filename);
|
||||
|
||||
/*
|
||||
* Example on using bm_create
|
||||
*
|
||||
{
|
||||
static int test_inited = 0;
|
||||
static int test_bmp;
|
||||
static uint test_bmp_data[128*64];
|
||||
|
||||
if ( !test_inited ) {
|
||||
test_inited = 1;
|
||||
// Create the new bitmap and fill in its data.
|
||||
// When you're done with it completely, call
|
||||
// bm_release to free up the bitmap handle
|
||||
test_bmp = bm_create( 32, 128, 64, test_bmp_data );
|
||||
int i,j;
|
||||
for (i=0; i<64; i++ ) {
|
||||
for (j=0; j<64; j++ ) {
|
||||
uint r=i*4;
|
||||
test_bmp_data[j+i*128] = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bm_unload(test_bmp); // this pages out the data, so that the
|
||||
// next bm_lock will convert the new data to the
|
||||
// correct bpp
|
||||
|
||||
// put in new data
|
||||
int x,y;
|
||||
gr_reset_clip();
|
||||
for (y=0; y<64; y++)
|
||||
for (x=0; x<128; x++ )
|
||||
test_bmp_data[y*128+x] = 15;
|
||||
|
||||
// Draw the bitmap to upper left corner
|
||||
gr_set_bitmap(test_bmp);
|
||||
gr_bitmap( 0,0 );
|
||||
}
|
||||
/**
|
||||
* @brief Stuffs Pathtypes with an additional path leading to a subdir of the same name as the given file (minus file extension)
|
||||
*/
|
||||
bool set_temp_subdir_pathtype(const char *filename);
|
||||
|
||||
|
||||
//============================================================================
|
||||
// Paging stuff
|
||||
//============================================================================
|
||||
|
||||
/**
|
||||
* @brief Tells bmpman to start keeping track of what bitmaps are used where
|
||||
*/
|
||||
void bm_page_in_start();
|
||||
|
||||
/**
|
||||
* @brief Tells bmpman to stop paging (?)
|
||||
*/
|
||||
void bm_page_in_stop();
|
||||
|
||||
// Paging code in a library should call these functions
|
||||
// in its page in function.
|
||||
|
||||
// Marks a texture as being used for this level
|
||||
// If num_frames is passed, assume this is an animation
|
||||
void bm_page_in_texture( int bitmapnum, int num_frames = 0 );
|
||||
/**
|
||||
* @brief Marks a texture as being used for this level
|
||||
*
|
||||
* @param[in] num_frames If specified, assumes this is an animated texture
|
||||
*/
|
||||
void bm_page_in_texture(int bitmapnum, int num_frames = 0);
|
||||
|
||||
// marks a texture as being a transparent textyre used for this level
|
||||
// Marks a texture as being used for this level
|
||||
// If num_frames is passed, assume this is an animation
|
||||
void bm_page_in_xparent_texture( int bitmapnum, int num_frames=1 );
|
||||
/**
|
||||
* @brief Marks a textures as being used for level and is transparant
|
||||
*
|
||||
* @param[in] num_frames If specified, assumes this is an animated texture
|
||||
*/
|
||||
void bm_page_in_xparent_texture(int bitmapnum, int num_frames = 1);
|
||||
|
||||
// Marks an aabitmap as being used for this level
|
||||
// If num_frames is passed, assume this is an animation
|
||||
void bm_page_in_aabitmap( int bitmapnum, int num_frames=1 );
|
||||
/**
|
||||
* @brief Marks a texture as being used for this level, and is anti-aliased
|
||||
*
|
||||
* @param[in] num_frames If specified, assumes this is an animated texture
|
||||
*/
|
||||
void bm_page_in_aabitmap(int bitmapnum, int num_frames = 1);
|
||||
|
||||
// unload a texture that was paged in
|
||||
int bm_page_out( int handle );
|
||||
/**
|
||||
* @brief Unloads the bitmap indexed by handle that was previously paged-in
|
||||
*
|
||||
* @returns 0 If the bitmap had already been released, or
|
||||
* @returns 0 If the handle is invalid, or
|
||||
* @returns 1 If successful
|
||||
*
|
||||
* @todo The return type should be a bool
|
||||
*/
|
||||
int bm_page_out(int handle);
|
||||
|
||||
//
|
||||
// Mode: 0 = High memory
|
||||
// 1 = Low memory ( every other frame of ani's)
|
||||
// 2 = Debug low memory ( only use first frame of each ani )
|
||||
void bm_set_low_mem( int mode );
|
||||
|
||||
const char *bm_get_filename(int handle);
|
||||
/**
|
||||
* @brief Sets BMPMAN's memory mode
|
||||
*
|
||||
* @details 0 = High memory;
|
||||
* 1 = Low memory (loads every other frame of ani's);
|
||||
* 2 = Debug low memory (only use first frame of each ani)
|
||||
*
|
||||
* @todo This should use an enum, or instead allow an arbitrary number to drop frames (like 1/2, 1/3, etc.)
|
||||
*/
|
||||
void bm_set_low_mem(int mode);
|
||||
|
||||
/**
|
||||
* @brief Sets bm_set_components and bm_get_components to reference screen format functions
|
||||
*/
|
||||
void BM_SELECT_SCREEN_FORMAT();
|
||||
|
||||
/**
|
||||
* @brief Sets bm_set_components and bm_get_components to reference texture format functions
|
||||
*/
|
||||
void BM_SELECT_TEX_FORMAT();
|
||||
|
||||
/**
|
||||
* @brief Sets bm_set_components and bm_get_components to reference texture format functions (with alpha)
|
||||
*/
|
||||
void BM_SELECT_ALPHA_TEX_FORMAT();
|
||||
|
||||
// set the rgba components of a pixel, any of the parameters can be NULL
|
||||
extern void (*bm_set_components)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
extern void (*bm_set_components_32)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
void bm_set_components_argb_d3d_16_screen(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
void bm_set_components_argb_d3d_32_screen(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
void bm_set_components_argb_d3d_16_tex(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
void bm_set_components_argb_d3d_32_tex(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
/**
|
||||
* @brief Functional pointer that references any of the bm_set_components functions.
|
||||
*
|
||||
* @details The bm_set_components functions packs the RGBA values into the ubyte array referenced by pixel, whose
|
||||
* format differs according to its bpp value and presence of an alpha channel. The RGBA values are scaled accordingly.
|
||||
*
|
||||
* @param[out] pixel The pixel to set
|
||||
* @param[in] r Red value (may not be NULL)
|
||||
* @param[in] g Green value (may not be NULL)
|
||||
* @param[in] b Blue value (may not be NULL)
|
||||
* @param[in] a Alpha value (currently ignored)
|
||||
*
|
||||
* @note z64 - These functions were made predating the introduction of C++ classes, and are basically the equivalent
|
||||
* of Pixel::set(ubyte *r, ubyte *b, ubyte *g). The original comment mentions that any of the rgba params may be
|
||||
* NULL, but this is by far _NOT_ the case, as a NULL value will cause undefined behavior (really really bad chroma
|
||||
* corruption)
|
||||
*
|
||||
* @note These functions assume the incoming bitdepth will always be >= to the outgoing bitdepth of the pixel. Should
|
||||
* the incoming bitdepth be lower, the outgoing values will appear darker than they should be
|
||||
*/
|
||||
extern void(*bm_set_components)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
|
||||
// get the rgba components of a pixel, any of the parameters can be NULL
|
||||
/**
|
||||
* @brief Functional pointer that references any of the bm_set_components_32 functions.
|
||||
*
|
||||
* @details The bm_set_components functions packs the RGBA values into the ubyte array referenced by pixel, whose
|
||||
* format differs according to its bpp value and presence of an alpha channel. The RGBA values are scaled accordingly.
|
||||
*
|
||||
* @see bm_set_components
|
||||
*/
|
||||
extern void(*bm_set_components_32)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
|
||||
/**
|
||||
* @brief Sets the 16bpp screen pixel to the specified RGBA value
|
||||
*
|
||||
* @see bm_set_components
|
||||
*/
|
||||
void bm_set_components_argb_16_screen(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
|
||||
/**
|
||||
* @brief Sets the 32bpp screen pixel to the specified RGBA value
|
||||
*
|
||||
* @see bm_set_components
|
||||
*/
|
||||
void bm_set_components_argb_32_screen(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
|
||||
/**
|
||||
* @brief Sets the 16bpp texture pixel to the specified RGBA value
|
||||
*
|
||||
* @see bm_set_components
|
||||
*/
|
||||
void bm_set_components_argb_16_tex(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
|
||||
/**
|
||||
* @brief Sets the 32bpp texture pixel to the specified RGBA value
|
||||
*
|
||||
* @see bm_set_components
|
||||
*/
|
||||
void bm_set_components_argb_32_tex(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
|
||||
/**
|
||||
* @brief Gets the RGBA components of a pixel according to the selected mode
|
||||
*
|
||||
* @see BM_SELECT_SCREEN_FORMAT() BM_SELECT_TEX_FORMAT() BM_SELECT_ALPHA_TEX_FORMAT()
|
||||
*/
|
||||
void bm_get_components(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
|
||||
extern int GLOWMAP; //this holds a reference to a map that is a fully lit version of its index -Bobboau
|
||||
extern int SPECMAP; //this holds a reference to a map that is for specular mapping -Bobboau
|
||||
extern int ENVMAP; //this holds a reference to a map that is for environment mapping -Bobboau
|
||||
extern int NORMMAP; // normal mapping
|
||||
extern int HEIGHTMAP; // height map for normal mapping
|
||||
extern int MISCMAP; // Utility map, to be utilized for various things shader authors can come up with
|
||||
/**
|
||||
* @brief Returns the compression type of the bitmap indexed by handle
|
||||
*/
|
||||
int bm_is_compressed(int handle);
|
||||
|
||||
int bm_is_compressed(int num);
|
||||
int bm_get_tcache_type(int num);
|
||||
int bm_get_size(int num);
|
||||
int bm_get_num_mipmaps(int num);
|
||||
/**
|
||||
* @brief Gets the correct TCACHE_TYPE for compressed graphics (uncompressed are assumed TCACHE_TYPE_NORMAL)
|
||||
*/
|
||||
int bm_get_tcache_type(int handle);
|
||||
|
||||
/**
|
||||
* @brief Gets the size, in bytes, taken up by the bitmap indexed by handle
|
||||
*
|
||||
* @todo retval should be a size_t
|
||||
*/
|
||||
int bm_get_size(int handle);
|
||||
|
||||
/**
|
||||
* @brief Gets the number of mipmaps of the indexed texture
|
||||
*/
|
||||
int bm_get_num_mipmaps(int handle);
|
||||
|
||||
/**
|
||||
* @brief Checks to see if the indexed bitmap has an alpha channel
|
||||
*
|
||||
* @note Currently just checks if the bitmap is 32bpp and is not a .PCX
|
||||
*
|
||||
* @todo retval should be a bool
|
||||
*/
|
||||
int bm_has_alpha_channel(int handle);
|
||||
|
||||
/**
|
||||
* @brief (DEBUG) Prints all loaded bitmaps to an outwindow
|
||||
*/
|
||||
void bm_print_bitmaps();
|
||||
|
||||
int bm_make_render_target( int width, int height, int flags );
|
||||
int bm_is_render_target(int bitmap_id);
|
||||
/**
|
||||
* @brief Creates a render target as close to the desired resolution as possible.
|
||||
*
|
||||
* @returns the handle of an avilable render target if successful, or
|
||||
* @returns -1 if not successful
|
||||
*
|
||||
* @note BM_FLAG_RENDER_TARGET_STATIC are drawn once/infrequently, while BM_FLAG_RENDER_TARGET_DYNAMIC are drawn roughly once every frame
|
||||
*/
|
||||
int bm_make_render_target(int width, int height, int flags);
|
||||
|
||||
/**
|
||||
* @brief Checks to see if the given bitmap indexed by handle is a render target
|
||||
*
|
||||
* @returns The render type (BM_TYPE) if it is a render target, or
|
||||
* @returns 0 if it is not
|
||||
*/
|
||||
int bm_is_render_target(int handle);
|
||||
|
||||
/**
|
||||
* @brief (GR function) Calls gr_bm_set_render target for the given bitmap indexed by handle
|
||||
*
|
||||
* @returns 1 if successful, or
|
||||
* @returns 0 if unsuccessful
|
||||
*
|
||||
* @todo retval should be a bool
|
||||
*/
|
||||
int bm_set_render_target(int handle, int face = -1);
|
||||
|
||||
int bm_load_and_parse_eff(const char *filename, int dir_type, int *nframes, int *nfps, int *key, ubyte *type);
|
||||
/**
|
||||
* @brief Loads and parses an .EFF
|
||||
*
|
||||
* @param[in] filename The filename of the .EFF
|
||||
* @param[in] dir_type
|
||||
* @param[out] nframes (optional) If given, is set to the number of frames this .EFF has
|
||||
* @param[out] nfps (optional) If given, is set to the fps of this .EFF
|
||||
* @param[out] key (optional) If given, is set to the keyframe index of this .EFF
|
||||
* @param[out] type (optional) If given, is set to the BM_TYPE of the .EFF
|
||||
* @param[out] in_subdir (optional) If given, is set to true if the frames of this .EFF are in a subdir
|
||||
*
|
||||
* @returns 0 If successful,
|
||||
* @returns -1 if not successful
|
||||
*
|
||||
* @todo retval should be a bool
|
||||
*/
|
||||
int bm_load_and_parse_eff(const char *filename, int dir_type, int *nframes, int *nfps, int *key, ubyte *type, bool *in_subdir);
|
||||
|
||||
#endif
|
||||
@@ -540,8 +540,15 @@ void warp_camera::get_info(vec3d *position, matrix *orientation)
|
||||
//*************************subtitle*************************
|
||||
|
||||
#define MAX_SUBTITLE_LINES 64
|
||||
subtitle::subtitle(int in_x_pos, int in_y_pos, const char* in_text, const char* in_imageanim, float in_display_time, float in_fade_time, const color *in_text_color, int in_text_fontnum, bool center_x, bool center_y, int in_width, int in_height, bool in_post_shaded)
|
||||
subtitle::subtitle(int in_x_pos, int in_y_pos, const char* in_text, const char* in_imageanim, float in_display_time,
|
||||
float in_fade_time, const color *in_text_color, int in_text_fontnum, bool center_x, bool center_y, int in_width,
|
||||
int in_height, bool in_post_shaded)
|
||||
:display_time(-1.0f), fade_time(-1.0f), text_fontnum(-1), time_displayed(-1.0f), time_displayed_end(-1.0f),
|
||||
post_shaded(false)
|
||||
{
|
||||
// Initialize color
|
||||
gr_init_color(&text_color, 0, 0, 0);
|
||||
|
||||
SCP_string text_buf;
|
||||
|
||||
// basic init, this always has to be done
|
||||
|
||||
@@ -86,6 +86,7 @@ cf_pathtype Pathtypes[CF_MAX_PATH_TYPES] = {
|
||||
{ CF_TYPE_INTEL_ANIMS, "data" DIR_SEPARATOR_STR "intelanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
|
||||
{ CF_TYPE_SCRIPTS, "data" DIR_SEPARATOR_STR "scripts", ".lua .lc", CF_TYPE_DATA },
|
||||
{ CF_TYPE_FICTION, "data" DIR_SEPARATOR_STR "fiction", ".txt", CF_TYPE_DATA },
|
||||
{ CF_TYPE_TEMP_SUBDIR_LOOKUP, "", ".eff", CF_TYPE_DATA },
|
||||
};
|
||||
|
||||
|
||||
@@ -501,7 +502,7 @@ int cf_exists(const char *filename, int dir_type)
|
||||
if ( (filename == NULL) || !strlen(filename) )
|
||||
return 0;
|
||||
|
||||
return (cf_find_file_location(filename, dir_type, 0, NULL, &offset, NULL) && !offset);
|
||||
return (cf_find_file_location(filename, dir_type, 0, NULL, NULL, &offset) && !offset);
|
||||
}
|
||||
|
||||
// Goober5000
|
||||
|
||||
+2
-1
@@ -78,8 +78,9 @@ typedef struct {
|
||||
#define CF_TYPE_INTEL_ANIMS 34
|
||||
#define CF_TYPE_SCRIPTS 35
|
||||
#define CF_TYPE_FICTION 36
|
||||
#define CF_TYPE_TEMP_SUBDIR_LOOKUP 37
|
||||
|
||||
#define CF_MAX_PATH_TYPES 37 // Can be as high as you'd like //DTP; yeah but beware alot of things uses CF_MAX_PATH_TYPES
|
||||
#define CF_MAX_PATH_TYPES 38 // Can be as high as you'd like //DTP; yeah but beware alot of things uses CF_MAX_PATH_TYPES
|
||||
|
||||
|
||||
// TRUE if type is specified and valid
|
||||
|
||||
@@ -901,6 +901,7 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
|
||||
case CF_TYPE_MULTI_CACHE:
|
||||
case CF_TYPE_MISSIONS:
|
||||
case CF_TYPE_CACHE:
|
||||
case CF_TYPE_TEMP_SUBDIR_LOOKUP:
|
||||
cfs_slow_search = 1;
|
||||
break;
|
||||
|
||||
|
||||
@@ -956,9 +956,9 @@ void control_config_reset_defaults(int presetnum)
|
||||
|
||||
// Reset keyboard defaults
|
||||
for (i=0; i<CCFG_MAX; i++) {
|
||||
// Note that key_default and joy_default are NOT overwritten here;
|
||||
// they should retain the values of the first preset because
|
||||
// for example the key-pressed SEXP works off the defaults of the first preset
|
||||
// Note that key_default, joy_default and text_default are NOT
|
||||
// overwritten here; they should retain the values of the first preset
|
||||
Control_config[i].text = preset[i].text;
|
||||
Control_config[i].key_id = preset[i].key_default;
|
||||
Control_config[i].joy_id = preset[i].joy_default;
|
||||
Control_config[i].tab = preset[i].tab;
|
||||
@@ -2107,6 +2107,45 @@ void control_config_do_frame(float frametime)
|
||||
List_buttons[i++].disable();
|
||||
}
|
||||
|
||||
// If multiple controls presets are provided, display which one is in use
|
||||
if (Control_config_presets.size() > 1) {
|
||||
SCP_string preset_str;
|
||||
int matching_preset = -1;
|
||||
|
||||
for (i=0; i<(int)Control_config_presets.size(); i++) {
|
||||
bool this_preset_matches = true;
|
||||
config_item *this_preset = Control_config_presets[i];
|
||||
|
||||
for (int j=0; j<CCFG_MAX; j++) {
|
||||
if (!Control_config[j].disabled && Control_config[j].key_id != this_preset[j].key_default) {
|
||||
this_preset_matches = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (this_preset_matches) {
|
||||
matching_preset = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (matching_preset >= 0) {
|
||||
sprintf(preset_str, "Controls: %s", Control_config_preset_names[matching_preset].c_str());
|
||||
} else {
|
||||
sprintf(preset_str, "Controls: custom");
|
||||
|
||||
}
|
||||
|
||||
gr_get_string_size(&w, NULL, preset_str.c_str());
|
||||
gr_set_color_fast(&Color_text_normal);
|
||||
|
||||
if (gr_screen.res == GR_640) {
|
||||
gr_string(16, (24 - font_height) / 2, preset_str.c_str(), GR_RESIZE_MENU);
|
||||
} else {
|
||||
gr_string(24, (40 - font_height) / 2, preset_str.c_str(), GR_RESIZE_MENU);
|
||||
}
|
||||
}
|
||||
|
||||
// blit help overlay if active
|
||||
help_overlay_maybe_blit(Control_config_overlay_id, gr_screen.res);
|
||||
|
||||
@@ -2207,11 +2246,11 @@ int check_control_used(int id, int key)
|
||||
|
||||
// check what current modifiers are pressed
|
||||
mask = 0;
|
||||
if (keyd_pressed[KEY_LSHIFT] || key_down_count(KEY_LSHIFT) || keyd_pressed[KEY_RSHIFT] || key_down_count(KEY_RSHIFT)) {
|
||||
if (keyd_pressed[KEY_LSHIFT] || keyd_pressed[KEY_RSHIFT]) {
|
||||
mask |= KEY_SHIFTED;
|
||||
}
|
||||
|
||||
if (keyd_pressed[KEY_LALT] || key_down_count(KEY_LALT) || keyd_pressed[KEY_RALT] || key_down_count(KEY_RALT)) {
|
||||
if (keyd_pressed[KEY_LALT] || keyd_pressed[KEY_RALT]) {
|
||||
mask |= KEY_ALTED;
|
||||
}
|
||||
|
||||
@@ -2226,7 +2265,7 @@ int check_control_used(int id, int key)
|
||||
|
||||
z &= KEY_MASK;
|
||||
|
||||
if (keyd_pressed[z] || key_down_count(z)) {
|
||||
if (keyd_pressed[z]) {
|
||||
control_used(id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -63,13 +63,14 @@ typedef struct config_item {
|
||||
short joy_default; //!< default joystick button bound to action
|
||||
char tab; //!< what tab (category) it belongs in
|
||||
bool hasXSTR; //!< whether we should translate this with an XSTR
|
||||
char *text; //!< describes the action in the config screen
|
||||
char *default_text; //!< default description of the action
|
||||
char type; //!< manner control should be checked in
|
||||
short key_id; //!< actual key bound to action
|
||||
short joy_id; //!< joystick button bound to action
|
||||
int used; //!< has control been used yet in mission? If so, this is the timestamp
|
||||
bool disabled; //!< whether this action should be available at all
|
||||
bool continuous_ongoing;//!< whether this action is a continuous one and is currently ongoing
|
||||
char *text; //!< overridable description of the action
|
||||
} config_item;
|
||||
|
||||
/*!
|
||||
@@ -292,6 +293,7 @@ extern int Control_config_overlay_id;
|
||||
|
||||
extern config_item Control_config[]; //!< Stores the keyboard configuration
|
||||
extern SCP_vector<config_item*> Control_config_presets; // tabled control presets; pointers to config_item arrays
|
||||
extern SCP_vector<SCP_string> Control_config_preset_names; // names for Control_config_presets (identical order of items)
|
||||
extern char **Scan_code_text;
|
||||
extern char **Joy_button_text;
|
||||
|
||||
|
||||
@@ -45,153 +45,153 @@ int Invert_axis_defaults[JOY_NUM_AXES] = { 0, 0, 0, 0, 0, 0 };
|
||||
//XSTR:OFF
|
||||
config_item Control_config[CCFG_MAX + 1] = {
|
||||
// targeting a ship
|
||||
{ KEY_T, -1, TARGET_TAB, true, "Target Next Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_T, -1, TARGET_TAB, true, "Target Previous Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_H, 2, TARGET_TAB, true, "Target Next Closest Hostile Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_H, -1, TARGET_TAB, true, "Target Previous Closest Hostile Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_H, -1, TARGET_TAB, true, "Toggle Auto Targeting", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_F, -1, TARGET_TAB, true, "Target Next Closest Friendly Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_F, -1, TARGET_TAB, true, "Target Previous Closest Friendly Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_Y, 4, TARGET_TAB, true, "Target Ship in Reticle", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_G, -1, TARGET_TAB, true, "Target Target's Nearest Attacker", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_Y, -1, TARGET_TAB, true, "Target Last Ship to Send Transmission", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_T, -1, TARGET_TAB, true, "Turn Off Targeting", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_T, -1, TARGET_TAB, true, "Target Next Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_T, -1, TARGET_TAB, true, "Target Previous Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_H, 2, TARGET_TAB, true, "Target Next Closest Hostile Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_H, -1, TARGET_TAB, true, "Target Previous Closest Hostile Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_ALTED | KEY_H, -1, TARGET_TAB, true, "Toggle Auto Targeting", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_F, -1, TARGET_TAB, true, "Target Next Closest Friendly Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_F, -1, TARGET_TAB, true, "Target Previous Closest Friendly Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_Y, 4, TARGET_TAB, true, "Target Ship in Reticle", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_G, -1, TARGET_TAB, true, "Target Target's Nearest Attacker", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_ALTED | KEY_Y, -1, TARGET_TAB, true, "Target Last Ship to Send Transmission", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_ALTED | KEY_T, -1, TARGET_TAB, true, "Turn Off Targeting", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
|
||||
// targeting a ship's subsystem
|
||||
{ KEY_V, -1, TARGET_TAB, true, "Target Subsystem in Reticle", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_S, -1, TARGET_TAB, true, "Target Next Subsystem", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_S, -1, TARGET_TAB, true, "Target Previous Subsystem", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_S, -1, TARGET_TAB, true, "Turn Off Targeting of Subsystems", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_V, -1, TARGET_TAB, true, "Target Subsystem in Reticle", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_S, -1, TARGET_TAB, true, "Target Next Subsystem", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_S, -1, TARGET_TAB, true, "Target Previous Subsystem", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_ALTED | KEY_S, -1, TARGET_TAB, true, "Turn Off Targeting of Subsystems", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
|
||||
// matching speed
|
||||
{ KEY_M, -1, COMPUTER_TAB, true, "Match Target Speed", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_M, -1, COMPUTER_TAB, true, "Toggle Auto Speed Matching", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_M, -1, COMPUTER_TAB, true, "Match Target Speed", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_ALTED | KEY_M, -1, COMPUTER_TAB, true, "Toggle Auto Speed Matching", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
|
||||
// weapons
|
||||
{ KEY_LCTRL, 0, WEAPON_TAB, true, "Fire Primary Weapon", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_SPACEBAR, 1, WEAPON_TAB, true, "Fire Secondary Weapon", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_PERIOD, -1, WEAPON_TAB, true, "Cycle Forward Primary Weapon", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_COMMA, -1, WEAPON_TAB, true, "Cycle Backward Primary Weapon", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_DIVIDE, -1, WEAPON_TAB, true, "Cycle Secondary Weapon Bank", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_DIVIDE, -1, WEAPON_TAB, true, "Cycle Secondary Weapon Firing Rate", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_X, 3, WEAPON_TAB, true, "Launch Countermeasure", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_LCTRL, 0, WEAPON_TAB, true, "Fire Primary Weapon", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SPACEBAR, 1, WEAPON_TAB, true, "Fire Secondary Weapon", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_PERIOD, -1, WEAPON_TAB, true, "Cycle Forward Primary Weapon", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_COMMA, -1, WEAPON_TAB, true, "Cycle Backward Primary Weapon", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_DIVIDE, -1, WEAPON_TAB, true, "Cycle Secondary Weapon Bank", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_DIVIDE, -1, WEAPON_TAB, true, "Cycle Secondary Weapon Firing Rate", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_X, 3, WEAPON_TAB, true, "Launch Countermeasure", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
|
||||
// controls
|
||||
{ KEY_A, -1, SHIP_TAB, true, "Forward Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_Z, -1, SHIP_TAB, true, "Reverse Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_PAD7, -1, SHIP_TAB, true, "Bank Left", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_PAD9, -1, SHIP_TAB, true, "Bank Right", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_PAD8, -1, SHIP_TAB, true, "Pitch Forward", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_PAD2, -1, SHIP_TAB, true, "Pitch Backward", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_PAD4, -1, SHIP_TAB, true, "Turn Left", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_PAD6, -1, SHIP_TAB, true, "Turn Right", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_A, -1, SHIP_TAB, true, "Forward Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_Z, -1, SHIP_TAB, true, "Reverse Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_PAD7, -1, SHIP_TAB, true, "Bank Left", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_PAD9, -1, SHIP_TAB, true, "Bank Right", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_PAD8, -1, SHIP_TAB, true, "Pitch Forward", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_PAD2, -1, SHIP_TAB, true, "Pitch Backward", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_PAD4, -1, SHIP_TAB, true, "Turn Left", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_PAD6, -1, SHIP_TAB, true, "Turn Right", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
|
||||
|
||||
// throttle controls
|
||||
{ KEY_BACKSP, -1, SHIP_TAB, true, "Set Throttle to Zero", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SLASH, -1, SHIP_TAB, true, "Set Throttle to Max", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_LBRACKET, -1, SHIP_TAB, true, "Set Throttle to One-Third", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_RBRACKET, -1, SHIP_TAB, true, "Set Throttle to Two-Thirds", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_EQUAL, -1, SHIP_TAB, true, "Increase Throttle 5 Percent", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_MINUS, -1, SHIP_TAB, true, "Decrease Throttle 5 Percent", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_BACKSP, -1, SHIP_TAB, true, "Set Throttle to Zero", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SLASH, -1, SHIP_TAB, true, "Set Throttle to Max", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_LBRACKET, -1, SHIP_TAB, true, "Set Throttle to One-Third", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_RBRACKET, -1, SHIP_TAB, true, "Set Throttle to Two-Thirds", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_EQUAL, -1, SHIP_TAB, true, "Increase Throttle 5 Percent", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_MINUS, -1, SHIP_TAB, true, "Decrease Throttle 5 Percent", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
|
||||
// squadmate messaging
|
||||
{ KEY_SHIFTED | KEY_A, -1, COMPUTER_TAB, true, "Attack My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_Z, -1, COMPUTER_TAB, true, "Disarm My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_D, -1, COMPUTER_TAB, true, "Disable My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_V, -1, COMPUTER_TAB, true, "Attack My Subsystem", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_X, -1, COMPUTER_TAB, true, "Capture My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_E, -1, COMPUTER_TAB, true, "Engage Enemy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_W, -1, COMPUTER_TAB, true, "Form on My Wing", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_I, -1, COMPUTER_TAB, true, "Ignore My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_P, -1, COMPUTER_TAB, true, "Protect My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_C, -1, COMPUTER_TAB, true, "Cover Me", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_J, -1, COMPUTER_TAB, true, "Return to Base", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_R, -1, COMPUTER_TAB, true, "Rearm Me", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_A, -1, COMPUTER_TAB, true, "Attack My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_Z, -1, COMPUTER_TAB, true, "Disarm My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_D, -1, COMPUTER_TAB, true, "Disable My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_V, -1, COMPUTER_TAB, true, "Attack My Subsystem", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_X, -1, COMPUTER_TAB, true, "Capture My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_E, -1, COMPUTER_TAB, true, "Engage Enemy", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_W, -1, COMPUTER_TAB, true, "Form on My Wing", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_I, -1, COMPUTER_TAB, true, "Ignore My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_P, -1, COMPUTER_TAB, true, "Protect My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_C, -1, COMPUTER_TAB, true, "Cover Me", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_J, -1, COMPUTER_TAB, true, "Return to Base", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_R, -1, COMPUTER_TAB, true, "Rearm Me", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
|
||||
{ KEY_R, 6, TARGET_TAB, true, "Target Closest Attacking Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_R, 6, TARGET_TAB, true, "Target Closest Attacking Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
|
||||
// Views
|
||||
{ KEY_PADMULTIPLY, -1, COMPUTER_TAB, true, "Chase View", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_PADPERIOD, -1, COMPUTER_TAB, true, "External View", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_PADENTER, -1, COMPUTER_TAB, true, "Toggle External Camera Lock", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_PAD0, -1, COMPUTER_TAB, true, "Free Look View", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false }, // Not in use anymore (Swifty)
|
||||
{ KEY_PADDIVIDE, -1, COMPUTER_TAB, true, "Current Target View", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_PADPLUS, -1, COMPUTER_TAB, true, "Increase View Distance", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_PADMINUS, -1, COMPUTER_TAB, true, "Decrease View Distance", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_PAD5, -1, COMPUTER_TAB, true, "Center View", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ -1, 33, COMPUTER_TAB, true, "View Up", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ -1, 32, COMPUTER_TAB, true, "View Rear", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ -1, 34, COMPUTER_TAB, true, "View Left", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ -1, 35, COMPUTER_TAB, true, "View Right", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_PADMULTIPLY, -1, COMPUTER_TAB, true, "Chase View", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_PADPERIOD, -1, COMPUTER_TAB, true, "External View", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_PADENTER, -1, COMPUTER_TAB, true, "Toggle External Camera Lock", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_PAD0, -1, COMPUTER_TAB, true, "Free Look View", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL }, // Not in use anymore (Swifty)
|
||||
{ KEY_PADDIVIDE, -1, COMPUTER_TAB, true, "Current Target View", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_PADPLUS, -1, COMPUTER_TAB, true, "Increase View Distance", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_PADMINUS, -1, COMPUTER_TAB, true, "Decrease View Distance", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_PAD5, -1, COMPUTER_TAB, true, "Center View", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
|
||||
{ -1, 33, COMPUTER_TAB, true, "View Up", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
|
||||
{ -1, 32, COMPUTER_TAB, true, "View Rear", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
|
||||
{ -1, 34, COMPUTER_TAB, true, "View Left", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
|
||||
{ -1, 35, COMPUTER_TAB, true, "View Right", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
|
||||
|
||||
{ KEY_RAPOSTRO, -1, COMPUTER_TAB, true, "Cycle Radar Range", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_C, -1, COMPUTER_TAB, true, "Communications Menu", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ -1, -1, -1, true, "Show Objectives", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_J, -1, COMPUTER_TAB, true, "Enter Subspace (End Mission)", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_J, -1, TARGET_TAB, true, "Target Target's Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_TAB, 5, SHIP_TAB, true, "Afterburner", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_RAPOSTRO, -1, COMPUTER_TAB, true, "Cycle Radar Range", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_C, -1, COMPUTER_TAB, true, "Communications Menu", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ -1, -1, -1, true, "Show Objectives", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_ALTED | KEY_J, -1, COMPUTER_TAB, true, "Enter Subspace (End Mission)", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_J, -1, TARGET_TAB, true, "Target Target's Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_TAB, 5, SHIP_TAB, true, "Afterburner", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
|
||||
|
||||
{ KEY_INSERT, -1, COMPUTER_TAB, true, "Increase Weapon Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_DELETE, -1, COMPUTER_TAB, true, "Decrease Weapon Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_HOME, -1, COMPUTER_TAB, true, "Increase Shield Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_END, -1, COMPUTER_TAB, true, "Decrease Shield Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_PAGEUP, -1, COMPUTER_TAB, true, "Increase Engine Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_PAGEDOWN, -1, COMPUTER_TAB, true, "Decrease Engine Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_D, -1, COMPUTER_TAB, true, "Equalize Energy Settings", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_INSERT, -1, COMPUTER_TAB, true, "Increase Weapon Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_DELETE, -1, COMPUTER_TAB, true, "Decrease Weapon Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_HOME, -1, COMPUTER_TAB, true, "Increase Shield Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_END, -1, COMPUTER_TAB, true, "Decrease Shield Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_PAGEUP, -1, COMPUTER_TAB, true, "Increase Engine Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_PAGEDOWN, -1, COMPUTER_TAB, true, "Decrease Engine Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_ALTED | KEY_D, -1, COMPUTER_TAB, true, "Equalize Energy Settings", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
|
||||
{ KEY_Q, 7, COMPUTER_TAB, true, "Equalize Shields", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_UP, -1, COMPUTER_TAB, true, "Augment Forward Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_DOWN, -1, COMPUTER_TAB, true, "Augment Rear Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_LEFT, -1, COMPUTER_TAB, true, "Augment Left Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_RIGHT, -1, COMPUTER_TAB, true, "Augment Right Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SCROLLOCK, -1, COMPUTER_TAB, true, "Transfer Energy Laser->Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_SCROLLOCK, -1, COMPUTER_TAB, true, "Transfer Energy Shield->Laser", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_Q, 7, COMPUTER_TAB, true, "Equalize Shields", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_UP, -1, COMPUTER_TAB, true, "Augment Forward Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_DOWN, -1, COMPUTER_TAB, true, "Augment Rear Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_LEFT, -1, COMPUTER_TAB, true, "Augment Left Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_RIGHT, -1, COMPUTER_TAB, true, "Augment Right Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SCROLLOCK, -1, COMPUTER_TAB, true, "Transfer Energy Laser->Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_SCROLLOCK, -1, COMPUTER_TAB, true, "Transfer Energy Shield->Laser", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
// { -1, -1, -1, true, "Show Damage Popup Window" },
|
||||
|
||||
{ -1, -1, SHIP_TAB, false, "Glide When Pressed", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ -1, -1, SHIP_TAB, false, "Glide When Pressed", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
|
||||
//Backslash -- this was a convenient place for Glide When Pressed, as Show Damage Popup isn't used
|
||||
{ -1, -1, SHIP_TAB, true, "Bank When Pressed", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ -1, -1, -1, true, "Show Nav Map", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_E, -1, COMPUTER_TAB, true, "Add or Remove Escort", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_SHIFTED | KEY_E, -1, COMPUTER_TAB, true, "Clear Escort List", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_E, -1, TARGET_TAB, true, "Target Next Escort Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_R, -1, TARGET_TAB, true, "Target Closest Repair Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ -1, -1, SHIP_TAB, true, "Bank When Pressed", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
|
||||
{ -1, -1, -1, true, "Show Nav Map", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_ALTED | KEY_E, -1, COMPUTER_TAB, true, "Add or Remove Escort", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_ALTED | KEY_SHIFTED | KEY_E, -1, COMPUTER_TAB, true, "Clear Escort List", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_E, -1, TARGET_TAB, true, "Target Next Escort Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_ALTED | KEY_R, -1, TARGET_TAB, true, "Target Closest Repair Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
|
||||
{ KEY_U, -1, TARGET_TAB, true, "Target Next Uninspected Cargo", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_U, -1, TARGET_TAB, true, "Target Previous Uninspected Cargo", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_N, -1, TARGET_TAB, true, "Target Newest Ship in Area", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_K, -1, TARGET_TAB, true, "Target Next Live Turret", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_K, -1, TARGET_TAB, true, "Target Previous Live Turret", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_U, -1, TARGET_TAB, true, "Target Next Uninspected Cargo", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_U, -1, TARGET_TAB, true, "Target Previous Uninspected Cargo", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_N, -1, TARGET_TAB, true, "Target Newest Ship in Area", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_K, -1, TARGET_TAB, true, "Target Next Live Turret", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_K, -1, TARGET_TAB, true, "Target Previous Live Turret", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
|
||||
{ KEY_B, -1, TARGET_TAB, true, "Target Next Hostile Bomb or Bomber", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_B, -1, TARGET_TAB, true, "Target Previous Hostile Bomb or Bomber", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_B, -1, TARGET_TAB, true, "Target Next Hostile Bomb or Bomber", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_B, -1, TARGET_TAB, true, "Target Previous Hostile Bomb or Bomber", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
|
||||
// multiplayer messaging keys
|
||||
{ KEY_1, -1, COMPUTER_TAB, true, "(Multiplayer) Message All", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_2, -1, COMPUTER_TAB, true, "(Multiplayer) Message Friendly", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_3, -1, COMPUTER_TAB, true, "(Multiplayer) Message Hostile", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_4, -1, COMPUTER_TAB, true, "(Multiplayer) Message Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_X, -1, COMPUTER_TAB, true, "(Multiplayer) Observer Zoom to Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_PERIOD, -1, COMPUTER_TAB, true, "Increase Time Compression", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_COMMA, -1, COMPUTER_TAB, true, "Decrease Time Compression", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_L, -1, COMPUTER_TAB, true, "Toggle High HUD Contrast", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_N, -1, COMPUTER_TAB, true, "(Multiplayer) Toggle Network Info", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_END, -1, COMPUTER_TAB, true, "(Multiplayer) Self Destruct", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_1, -1, COMPUTER_TAB, true, "(Multiplayer) Message All", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_2, -1, COMPUTER_TAB, true, "(Multiplayer) Message Friendly", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_3, -1, COMPUTER_TAB, true, "(Multiplayer) Message Hostile", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_4, -1, COMPUTER_TAB, true, "(Multiplayer) Message Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_ALTED | KEY_X, -1, COMPUTER_TAB, true, "(Multiplayer) Observer Zoom to Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_PERIOD, -1, COMPUTER_TAB, true, "Increase Time Compression", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_COMMA, -1, COMPUTER_TAB, true, "Decrease Time Compression", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_L, -1, COMPUTER_TAB, true, "Toggle High HUD Contrast", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_N, -1, COMPUTER_TAB, true, "(Multiplayer) Toggle Network Info", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_END, -1, COMPUTER_TAB, true, "(Multiplayer) Self Destruct", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
|
||||
// Misc
|
||||
{ KEY_SHIFTED | KEY_O, -1, COMPUTER_TAB, true, "Toggle HUD", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_3, -1, SHIP_TAB, true, "Right Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_1, -1, SHIP_TAB, true, "Left Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_PADPLUS, -1, SHIP_TAB, true, "Up Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_PADENTER, -1, SHIP_TAB, true, "Down Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_SHIFTED | KEY_Q, -1, COMPUTER_TAB, true, "Toggle HUD Wireframe Target View", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ -1, -1, COMPUTER_TAB, false, "Top-Down View", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ -1, -1, COMPUTER_TAB, false, "Target Padlock View", CC_TYPE_TRIGGER, -1, -1, 0, false, false }, // (Swifty) Toggle for VM_TRACK
|
||||
{ KEY_SHIFTED | KEY_O, -1, COMPUTER_TAB, true, "Toggle HUD", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_3, -1, SHIP_TAB, true, "Right Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_1, -1, SHIP_TAB, true, "Left Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_PADPLUS, -1, SHIP_TAB, true, "Up Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_SHIFTED | KEY_PADENTER, -1, SHIP_TAB, true, "Down Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_ALTED | KEY_SHIFTED | KEY_Q, -1, COMPUTER_TAB, true, "Toggle HUD Wireframe Target View", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ -1, -1, COMPUTER_TAB, false, "Top-Down View", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ -1, -1, COMPUTER_TAB, false, "Target Padlock View", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL }, // (Swifty) Toggle for VM_TRACK
|
||||
// Auto Navigation Systen
|
||||
{ KEY_ALTED | KEY_A, -1, COMPUTER_TAB, false, "Toggle Auto Pilot", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_N, -1, COMPUTER_TAB, false, "Cycle Nav Points", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_G, -1, SHIP_TAB, false, "Toggle Gliding", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_O, -1, WEAPON_TAB, false, "Cycle Primary Weapon Firing Rate", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_A, -1, COMPUTER_TAB, false, "Toggle Auto Pilot", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_ALTED | KEY_N, -1, COMPUTER_TAB, false, "Cycle Nav Points", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_ALTED | KEY_G, -1, SHIP_TAB, false, "Toggle Gliding", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ KEY_O, -1, WEAPON_TAB, false, "Cycle Primary Weapon Firing Rate", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
|
||||
{ -1, -1, -1, false, "", CC_TYPE_TRIGGER, -1, -1, 0, false, false }
|
||||
};
|
||||
|
||||
@@ -404,6 +404,7 @@ char **Scan_code_text = Scan_code_text_english;
|
||||
char **Joy_button_text = Joy_button_text_english;
|
||||
|
||||
SCP_vector<config_item*> Control_config_presets;
|
||||
SCP_vector<SCP_string> Control_config_preset_names;
|
||||
|
||||
void set_modifier_status()
|
||||
{
|
||||
@@ -591,6 +592,9 @@ void control_config_common_init()
|
||||
for (int i=0; i<CCFG_MAX; i++) {
|
||||
Control_config[i].disabled = false;
|
||||
Control_config[i].continuous_ongoing = false;
|
||||
|
||||
// init the overridable description with a copy of the default
|
||||
Control_config[i].text = strdup(Control_config[i].default_text);
|
||||
}
|
||||
|
||||
control_config_common_load_overrides();
|
||||
@@ -811,6 +815,14 @@ void control_config_common_load_overrides()
|
||||
std::copy(Control_config, Control_config + CCFG_MAX + 1, cfg_preset);
|
||||
Control_config_presets.push_back(cfg_preset);
|
||||
|
||||
SCP_string preset_name;
|
||||
if (optional_string("$Name:")) {
|
||||
stuff_string_line(preset_name);
|
||||
} else {
|
||||
preset_name = "<unnamed preset>";
|
||||
}
|
||||
Control_config_preset_names.push_back(preset_name);
|
||||
|
||||
while (required_string_either("#End","$Bind Name:")) {
|
||||
const int iBufferLength = 64;
|
||||
char szTempBuffer[iBufferLength];
|
||||
@@ -822,7 +834,7 @@ void control_config_common_load_overrides()
|
||||
for (size_t i = 0; i < cCntrlAryLength; ++i) {
|
||||
config_item& r_ccConfig = cfg_preset[i];
|
||||
|
||||
if (!strcmp(szTempBuffer, r_ccConfig.text)) {
|
||||
if (!strcmp(szTempBuffer, r_ccConfig.default_text)) {
|
||||
/**
|
||||
* short key_default;
|
||||
* short joy_default;
|
||||
@@ -833,6 +845,11 @@ void control_config_common_load_overrides()
|
||||
|
||||
int iTemp;
|
||||
|
||||
if (optional_string("$New Name:")) {
|
||||
stuff_string(szTempBuffer, F_NAME, iBufferLength);
|
||||
r_ccConfig.text = strdup(szTempBuffer);
|
||||
}
|
||||
|
||||
if (optional_string("$Key Default:")) {
|
||||
if (optional_string("NONE")) {
|
||||
r_ccConfig.key_default = (short)-1;
|
||||
|
||||
+52
-50
@@ -52,59 +52,61 @@ void cutscene_init()
|
||||
{
|
||||
atexit(cutscene_close);
|
||||
char buf[MULTITEXT_LENGTH];
|
||||
int rval;
|
||||
cutscene_info cutinfo;
|
||||
cutscene_info cutinfo;
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", "cutscenes.tbl", rval));
|
||||
try
|
||||
{
|
||||
read_file_text("cutscenes.tbl", CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
// parse in all the cutscenes
|
||||
Cutscenes.clear();
|
||||
skip_to_string("#Cutscenes");
|
||||
ignore_white_space();
|
||||
|
||||
bool isFirstCutscene = true;
|
||||
|
||||
while (required_string_either("#End", "$Filename:"))
|
||||
{
|
||||
required_string("$Filename:");
|
||||
stuff_string(cutinfo.filename, F_PATHNAME, MAX_FILENAME_LEN);
|
||||
|
||||
required_string("$Name:");
|
||||
stuff_string(cutinfo.name, F_NAME, NAME_LENGTH);
|
||||
|
||||
required_string("$Description:");
|
||||
stuff_string(buf, F_MULTITEXT, sizeof(buf));
|
||||
drop_white_space(buf);
|
||||
compact_multitext_string(buf);
|
||||
cutinfo.description = vm_strdup(buf);
|
||||
|
||||
if (optional_string("$cd:"))
|
||||
stuff_int(&cutinfo.cd);
|
||||
else
|
||||
cutinfo.cd = 0;
|
||||
|
||||
cutinfo.viewable = false;
|
||||
|
||||
if (isFirstCutscene) {
|
||||
isFirstCutscene = false;
|
||||
// The original code assumes the first movie is the intro, so always viewable
|
||||
cutinfo.viewable = true;
|
||||
}
|
||||
|
||||
if (optional_string("$Always Viewable:")) {
|
||||
stuff_boolean(&cutinfo.viewable);
|
||||
}
|
||||
|
||||
Cutscenes.push_back(cutinfo);
|
||||
}
|
||||
|
||||
required_string("#End");
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "cutscenes.tbl", e.what()));
|
||||
return;
|
||||
}
|
||||
|
||||
read_file_text("cutscenes.tbl", CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
// parse in all the cutscenes
|
||||
Cutscenes.clear();
|
||||
skip_to_string("#Cutscenes");
|
||||
ignore_white_space();
|
||||
|
||||
bool isFirstCutscene = true;
|
||||
|
||||
while ( required_string_either("#End", "$Filename:") )
|
||||
{
|
||||
required_string("$Filename:");
|
||||
stuff_string( cutinfo.filename, F_PATHNAME, MAX_FILENAME_LEN );
|
||||
|
||||
required_string("$Name:");
|
||||
stuff_string( cutinfo.name, F_NAME, NAME_LENGTH );
|
||||
|
||||
required_string("$Description:");
|
||||
stuff_string(buf, F_MULTITEXT, sizeof(buf));
|
||||
drop_white_space(buf);
|
||||
compact_multitext_string(buf);
|
||||
cutinfo.description = vm_strdup(buf);
|
||||
|
||||
if (optional_string("$cd:"))
|
||||
stuff_int( &cutinfo.cd );
|
||||
else
|
||||
cutinfo.cd = 0;
|
||||
|
||||
cutinfo.viewable = false;
|
||||
|
||||
if (isFirstCutscene) {
|
||||
isFirstCutscene = false;
|
||||
// The original code assumes the first movie is the intro, so always viewable
|
||||
cutinfo.viewable = true;
|
||||
}
|
||||
|
||||
if (optional_string("$Always Viewable:")) {
|
||||
stuff_boolean(&cutinfo.viewable);
|
||||
}
|
||||
|
||||
Cutscenes.push_back(cutinfo);
|
||||
}
|
||||
|
||||
required_string("#End");
|
||||
}
|
||||
|
||||
// function to return 0 based index of which CD a particular movie is on
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
|
||||
extern int Game_mode;
|
||||
|
||||
const char *movie_ext_list[] = { ".ogg", ".mve" };
|
||||
const int NUM_MOVIE_EXT = sizeof(movie_ext_list) / sizeof(char*);
|
||||
|
||||
|
||||
#define MOVIE_NONE -1
|
||||
#define MOVIE_OGG 0
|
||||
@@ -42,8 +45,6 @@ int movie_find(char *filename, char *out_name)
|
||||
char full_path[MAX_PATH];
|
||||
char tmp_name[MAX_PATH];
|
||||
int size, offset = 0;
|
||||
const int NUM_EXT = 2;
|
||||
const char *movie_ext[NUM_EXT] = { ".ogg", ".mve" };
|
||||
|
||||
if (out_name == NULL)
|
||||
return MOVIE_NONE;
|
||||
@@ -57,7 +58,7 @@ int movie_find(char *filename, char *out_name)
|
||||
char *p = strrchr(tmp_name, '.');
|
||||
if ( p ) *p = 0;
|
||||
|
||||
int rc = cf_find_file_location_ext(tmp_name, NUM_EXT, movie_ext, CF_TYPE_ANY, sizeof(full_path) - 1, full_path, &size, &offset, 0);
|
||||
int rc = cf_find_file_location_ext(tmp_name, NUM_MOVIE_EXT, movie_ext_list, CF_TYPE_ANY, sizeof(full_path) - 1, full_path, &size, &offset, 0);
|
||||
|
||||
if (rc == MOVIE_NONE)
|
||||
return MOVIE_NONE;
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
#ifndef _MOVIE_HEADER_FILE
|
||||
#define _MOVIE_HEADER_FILE
|
||||
|
||||
extern const char *movie_ext_list[];
|
||||
extern const int NUM_MOVIE_EXT;
|
||||
|
||||
bool movie_play(char *name);
|
||||
void movie_play_two(char *name1, char *name2);
|
||||
|
||||
|
||||
@@ -926,6 +926,10 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
|
||||
// reset flags to check MC_CHECK_MODEL | MC_CHECK_SPHERELINE and maybe MC_CHECK_INVISIBLE_FACES and MC_SUBMODEL_INSTANCE
|
||||
mc.flags = copy_flags | MC_SUBMODEL_INSTANCE;
|
||||
|
||||
if (Ship_info[Ships[ship_obj->instance].ship_info_index].collision_lod > -1) {
|
||||
mc.lod = Ship_info[Ships[ship_obj->instance].ship_info_index].collision_lod;
|
||||
}
|
||||
|
||||
// check each submodel in turn
|
||||
for (smv = submodel_vector.begin(); smv != submodel_vector.end(); ++smv) {
|
||||
// turn on submodel for collision test
|
||||
|
||||
@@ -9,10 +9,8 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/////////////////
|
||||
// Testing Goals
|
||||
// Breakpoints are set at places that need testing:
|
||||
// * the value of endptr strtol and strtoul needs to investigated, according to cplusplus.com, *endptr = end of the string that was successfully converted
|
||||
// TODO: Make a fast version of the parse_long, parse_ulong, etc. That just checks the first 1-3 characters. The fast version will be used in retail builds while the slow/safe version will be in debug's
|
||||
// @todo Make a fast version of the parse_long, parse_ulong, etc. That just checks the first 1-3 characters. The fast version will be used in retail builds while the slow/safe version will be in debug's
|
||||
// @todo Maybe make parser functions case-insensitive
|
||||
////////////////
|
||||
#include "debugconsole/consoleparse.h"
|
||||
|
||||
@@ -466,7 +464,7 @@ void dc_required_string(char *pstr)
|
||||
|
||||
dc_ignore_gray_space();
|
||||
|
||||
if (strnicmp(pstr, Cp, strlen(pstr))) {
|
||||
if (strncmp(pstr, Cp, strlen(pstr)) == 0) {
|
||||
str_found = pstr;
|
||||
}
|
||||
|
||||
@@ -492,10 +490,10 @@ int dc_required_string_either(char *str1, char *str2)
|
||||
|
||||
dc_ignore_gray_space();
|
||||
|
||||
if (strncmp(str1, Cp, strlen(str1) == 0)) {
|
||||
if (strncmp(str1, Cp, strlen(str1)) == 0) {
|
||||
str_found = str1;
|
||||
i = 0;
|
||||
} else if (strncmp(str2, Cp, strlen(str2) == 0)) {
|
||||
} else if (strncmp(str2, Cp, strlen(str2)) == 0) {
|
||||
str_found = str2;
|
||||
i = 1;
|
||||
}
|
||||
@@ -563,7 +561,7 @@ bool dc_optional_string(const char *pstr)
|
||||
{
|
||||
dc_ignore_gray_space();
|
||||
|
||||
if (strncmp(pstr, Cp, strlen(pstr) != 0)) {
|
||||
if (strncmp(pstr, Cp, strlen(pstr)) != 0) {
|
||||
return false;
|
||||
} // Else, optional string was found
|
||||
|
||||
|
||||
+82
-73
@@ -159,84 +159,93 @@ static void fireball_set_default_color(int idx)
|
||||
*/
|
||||
void parse_fireball_tbl(const char *filename)
|
||||
{
|
||||
int rval;
|
||||
lod_checker lod_check;
|
||||
color fb_color;
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", filename, rval));
|
||||
try
|
||||
{
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
required_string("#Start");
|
||||
|
||||
while (required_string_either("#End", "$Name:")) {
|
||||
memset(&lod_check, 0, sizeof(lod_checker));
|
||||
|
||||
// base filename
|
||||
required_string("$Name:");
|
||||
stuff_string(lod_check.filename, F_NAME, MAX_FILENAME_LEN);
|
||||
|
||||
lod_check.override = -1;
|
||||
|
||||
// these entries should only be in TBMs, and it has to include at least one
|
||||
if (Parsing_modular_table) {
|
||||
if (optional_string("+Explosion_Medium")) {
|
||||
lod_check.override = FIREBALL_EXPLOSION_MEDIUM;
|
||||
}
|
||||
else if (optional_string("+Warp_Effect")) {
|
||||
lod_check.override = FIREBALL_WARP;
|
||||
}
|
||||
else if (optional_string("+Knossos_Effect")) {
|
||||
lod_check.override = FIREBALL_KNOSSOS;
|
||||
}
|
||||
else if (optional_string("+Asteroid")) {
|
||||
lod_check.override = FIREBALL_ASTEROID;
|
||||
}
|
||||
else if (optional_string("+Explosion_Large1")) {
|
||||
lod_check.override = FIREBALL_EXPLOSION_LARGE1;
|
||||
}
|
||||
else if (optional_string("+Explosion_Large2")){
|
||||
lod_check.override = FIREBALL_EXPLOSION_LARGE2;
|
||||
}
|
||||
else {
|
||||
required_string("+Custom_Fireball");
|
||||
stuff_int(&lod_check.override);
|
||||
}
|
||||
}
|
||||
|
||||
lod_check.num_lods = 1;
|
||||
|
||||
// Do we have an LOD num
|
||||
if (optional_string("$LOD:")) {
|
||||
stuff_int(&lod_check.num_lods);
|
||||
}
|
||||
|
||||
if (lod_check.num_lods > MAX_FIREBALL_LOD) {
|
||||
lod_check.num_lods = MAX_FIREBALL_LOD;
|
||||
}
|
||||
|
||||
// check for particular lighting color
|
||||
if (optional_string("$Light color:")) {
|
||||
int r, g, b;
|
||||
|
||||
stuff_int(&r);
|
||||
stuff_int(&g);
|
||||
stuff_int(&b);
|
||||
|
||||
CLAMP(r, 0, 255);
|
||||
CLAMP(g, 0, 255);
|
||||
CLAMP(b, 0, 255);
|
||||
|
||||
gr_init_color(&fb_color, r, g, b);
|
||||
}
|
||||
else {
|
||||
// to keep things simple, we just use 0 alpha to indicate that a default value should be used
|
||||
memset(&fb_color, 0, sizeof(color));
|
||||
}
|
||||
|
||||
// we may use one filename for multiple entries so we'll have to handle dupes post parse
|
||||
LOD_checker.push_back(lod_check);
|
||||
LOD_color.push_back(fb_color);
|
||||
}
|
||||
|
||||
required_string("#End");
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", filename, e.what()));
|
||||
return;
|
||||
}
|
||||
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
required_string("#Start");
|
||||
|
||||
while (required_string_either("#End", "$Name:")) {
|
||||
memset( &lod_check, 0, sizeof(lod_checker) );
|
||||
|
||||
// base filename
|
||||
required_string("$Name:");
|
||||
stuff_string(lod_check.filename, F_NAME, MAX_FILENAME_LEN);
|
||||
|
||||
lod_check.override = -1;
|
||||
|
||||
// these entries should only be in TBMs, and it has to include at least one
|
||||
if ( Parsing_modular_table ) {
|
||||
if (optional_string("+Explosion_Medium")) {
|
||||
lod_check.override = FIREBALL_EXPLOSION_MEDIUM;
|
||||
} else if (optional_string("+Warp_Effect")) {
|
||||
lod_check.override = FIREBALL_WARP;
|
||||
} else if (optional_string("+Knossos_Effect")) {
|
||||
lod_check.override = FIREBALL_KNOSSOS;
|
||||
} else if (optional_string("+Asteroid")) {
|
||||
lod_check.override = FIREBALL_ASTEROID;
|
||||
} else if (optional_string("+Explosion_Large1")) {
|
||||
lod_check.override = FIREBALL_EXPLOSION_LARGE1;
|
||||
} else if (optional_string("+Explosion_Large2")){
|
||||
lod_check.override = FIREBALL_EXPLOSION_LARGE2;
|
||||
} else {
|
||||
required_string("+Custom_Fireball");
|
||||
stuff_int(&lod_check.override);
|
||||
}
|
||||
}
|
||||
|
||||
lod_check.num_lods = 1;
|
||||
|
||||
// Do we have an LOD num
|
||||
if (optional_string("$LOD:")) {
|
||||
stuff_int(&lod_check.num_lods);
|
||||
}
|
||||
|
||||
if (lod_check.num_lods > MAX_FIREBALL_LOD) {
|
||||
lod_check.num_lods = MAX_FIREBALL_LOD;
|
||||
}
|
||||
|
||||
// check for particular lighting color
|
||||
if ( optional_string("$Light color:") ) {
|
||||
int r, g, b;
|
||||
|
||||
stuff_int(&r);
|
||||
stuff_int(&g);
|
||||
stuff_int(&b);
|
||||
|
||||
CLAMP(r, 0, 255);
|
||||
CLAMP(g, 0, 255);
|
||||
CLAMP(b, 0, 255);
|
||||
|
||||
gr_init_color(&fb_color, r, g, b);
|
||||
} else {
|
||||
// to keep things simple, we just use 0 alpha to indicate that a default value should be used
|
||||
memset( &fb_color, 0, sizeof(color) );
|
||||
}
|
||||
|
||||
// we may use one filename for multiple entries so we'll have to handle dupes post parse
|
||||
LOD_checker.push_back(lod_check);
|
||||
LOD_color.push_back(fb_color);
|
||||
}
|
||||
|
||||
required_string("#End");
|
||||
}
|
||||
|
||||
void fireball_parse_tbl()
|
||||
|
||||
+49
-46
@@ -1267,7 +1267,7 @@ void bg_bitmap_dlg::OnImportBackground()
|
||||
{
|
||||
CFileDialog cfd(TRUE, ".fs2", NULL, 0, "FreeSpace2 Missions (*.fs2)|*.fs2||\0");
|
||||
char filename[256], error_str[1024];
|
||||
int rval, temp, count;
|
||||
int temp, count;
|
||||
char *saved_mp;
|
||||
|
||||
//warn on pressing the button
|
||||
@@ -1280,59 +1280,62 @@ void bg_bitmap_dlg::OnImportBackground()
|
||||
|
||||
strcpy_s(filename, cfd.GetPathName());
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("BGBITMAPDLG: Unable to parse '%s'! Error code = %i.\n", filename, rval));
|
||||
sprintf(error_str, "Could not parse file: %s", filename);
|
||||
|
||||
MessageBox((LPCTSTR) error_str, (LPCTSTR) "Unable to import mission background!", MB_ICONERROR | MB_OK);
|
||||
return;
|
||||
}
|
||||
|
||||
// parse in the new file
|
||||
read_file_text(filename);
|
||||
reset_parse();
|
||||
|
||||
if (!skip_to_start_of_string("#Background bitmaps"))
|
||||
return;
|
||||
|
||||
// skip beginning stuff
|
||||
required_string("#Background bitmaps");
|
||||
required_string("$Num stars:");
|
||||
stuff_int(&temp);
|
||||
required_string("$Ambient light level:");
|
||||
stuff_int(&temp);
|
||||
|
||||
saved_mp = Mp;
|
||||
|
||||
// see if we have more than one background in this mission
|
||||
count = 0;
|
||||
while(skip_to_string("$Bitmap List:"))
|
||||
count++;
|
||||
|
||||
Mp = saved_mp;
|
||||
|
||||
// pick one (if count is 0, it's retail with just one background)
|
||||
if (count > 0)
|
||||
try
|
||||
{
|
||||
int i, which = 0;
|
||||
// parse in the new file
|
||||
read_file_text(filename);
|
||||
reset_parse();
|
||||
|
||||
if (count > 1)
|
||||
if (!skip_to_start_of_string("#Background bitmaps"))
|
||||
return;
|
||||
|
||||
// skip beginning stuff
|
||||
required_string("#Background bitmaps");
|
||||
required_string("$Num stars:");
|
||||
stuff_int(&temp);
|
||||
required_string("$Ambient light level:");
|
||||
stuff_int(&temp);
|
||||
|
||||
saved_mp = Mp;
|
||||
|
||||
// see if we have more than one background in this mission
|
||||
count = 0;
|
||||
while (skip_to_string("$Bitmap List:"))
|
||||
count++;
|
||||
|
||||
Mp = saved_mp;
|
||||
|
||||
// pick one (if count is 0, it's retail with just one background)
|
||||
if (count > 0)
|
||||
{
|
||||
BackgroundChooser dlg(count);
|
||||
if (dlg.DoModal() == IDCANCEL)
|
||||
return;
|
||||
int i, which = 0;
|
||||
|
||||
which = dlg.GetChosenBackground();
|
||||
if (count > 1)
|
||||
{
|
||||
BackgroundChooser dlg(count);
|
||||
if (dlg.DoModal() == IDCANCEL)
|
||||
return;
|
||||
|
||||
which = dlg.GetChosenBackground();
|
||||
}
|
||||
|
||||
for (i = 0; i < which + 1; i++)
|
||||
skip_to_string("$Bitmap List:");
|
||||
}
|
||||
|
||||
for (i = 0; i < which + 1; i++)
|
||||
skip_to_string("$Bitmap List:");
|
||||
// now parse the background we've selected
|
||||
parse_one_background(&Backgrounds[get_active_background()]);
|
||||
|
||||
reinitialize_lists();
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("BGBITMAPDLG: Unable to parse '%s'! Error message = %s.\n", filename, e.what()));
|
||||
sprintf(error_str, "Could not parse file: %s\n\nError message: %s", filename, e.what());
|
||||
|
||||
// now parse the background we've selected
|
||||
parse_one_background(&Backgrounds[get_active_background()]);
|
||||
|
||||
reinitialize_lists();
|
||||
MessageBox((LPCTSTR)error_str, (LPCTSTR) "Unable to import mission background!", MB_ICONERROR | MB_OK);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void bg_bitmap_dlg::reinitialize_lists()
|
||||
|
||||
+6
-6
@@ -623,7 +623,7 @@ CAPTION "About FRED2"
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
ICON IDR_MAINFRAME,IDC_STATIC,10,17,20,20,SS_REALSIZEIMAGE
|
||||
LTEXT "FRED2_OPEN - FreeSpace Editor, Version 3.7.1 OpenGL",IDC_STATIC,39,8,184,10,SS_NOPREFIX
|
||||
LTEXT "FRED2_OPEN - FreeSpace Editor, Version 3.7.3 OpenGL",IDC_STATIC,39,8,184,10,SS_NOPREFIX
|
||||
LTEXT "Copyright © 1999 Volition, Inc. All Rights Reserved",IDC_STATIC,39,17,164,8
|
||||
DEFPUSHBUTTON "OK",IDOK,229,7,48,14,WS_GROUP
|
||||
LTEXT """Fred2 is the omega of all giant unwieldy pieces of code. Its big, its horrifying, and it just doesn't care. View it at your own risk."" - Dave Baranec",IDC_STATIC,39,62,238,20
|
||||
@@ -2121,12 +2121,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Volition Inc."
|
||||
VALUE "FileDescription", "Fred 2 Open"
|
||||
VALUE "FileVersion", "3.7.1.000000"
|
||||
VALUE "FileVersion", "3.7.3.000000"
|
||||
VALUE "InternalName", "Fred 2 Open"
|
||||
VALUE "LegalCopyright", "Copyright © 1998"
|
||||
VALUE "OriginalFilename", "fred2.exe"
|
||||
VALUE "ProductName", "Fred 2 Open"
|
||||
VALUE "ProductVersion", "3.7.1"
|
||||
VALUE "ProductVersion", "3.7.3"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
@@ -2696,12 +2696,12 @@ IDC_CURSOR2 CURSOR "res\\cursor2.cur"
|
||||
// String Table
|
||||
//
|
||||
|
||||
STRINGTABLE
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDR_MAINFRAME "FRED2_OPEN 3.7.1 - FreeSpace2 Mission Editor\nUntitled\nFRED2\nFreeSpace2 Missions (*.fs2)\n.fs2\nFreeSpace2Mission\nFreeSpace2 Mission"
|
||||
IDR_MAINFRAME "FRED2_OPEN 3.7.3 - FreeSpace2 Mission Editor\nUntitled\nFRED2\nFreeSpace2 Missions (*.fs2)\n.fs2\nFreeSpace2Mission\nFreeSpace2 Mission"
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
AFX_IDS_APP_TITLE "FRED2"
|
||||
AFX_IDS_IDLEMESSAGE "For Help, press F1"
|
||||
|
||||
@@ -1259,7 +1259,7 @@ void game_loading_callback_close()
|
||||
// Make sure bar shows all the way over.
|
||||
game_loading_callback(COUNT_ESTIMATE);
|
||||
|
||||
int real_count = game_busy_callback( NULL );
|
||||
int real_count __attribute__((__unused__)) = game_busy_callback( NULL );
|
||||
Mouse_hidden = 0;
|
||||
|
||||
Game_loading_callback_inited = 0;
|
||||
@@ -1423,7 +1423,7 @@ int game_start_mission()
|
||||
{
|
||||
mprintf(( "=================== STARTING LEVEL LOAD ==================\n" ));
|
||||
|
||||
int s1 = timer_get_milliseconds();
|
||||
int s1 __attribute__((__unused__)) = timer_get_milliseconds();
|
||||
|
||||
// clear post processing settings
|
||||
gr_post_process_set_defaults();
|
||||
@@ -1480,9 +1480,9 @@ int game_start_mission()
|
||||
|
||||
bm_print_bitmaps();
|
||||
|
||||
int e1 = timer_get_milliseconds();
|
||||
int e1 __attribute__((__unused__)) = timer_get_milliseconds();
|
||||
|
||||
printf("Level load took %f seconds.\n", (e1 - s1) / 1000.0f );
|
||||
mprintf(("Level load took %f seconds.\n", (e1 - s1) / 1000.0f ));
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -1739,7 +1739,7 @@ char full_path[1024];
|
||||
*/
|
||||
void game_init()
|
||||
{
|
||||
int s1, e1;
|
||||
int s1 __attribute__((__unused__)), e1 __attribute__((__unused__));
|
||||
const char *ptr;
|
||||
char whee[MAX_PATH_LEN];
|
||||
|
||||
|
||||
@@ -336,8 +336,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 3,7,1,000000
|
||||
PRODUCTVERSION 3,7,1,000000
|
||||
FILEVERSION 3,7,3,000000
|
||||
PRODUCTVERSION 3,7,3,000000
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -354,12 +354,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Volition Inc."
|
||||
VALUE "FileDescription", "FreeSpace 2 Open"
|
||||
VALUE "FileVersion", "3.7.1.000000"
|
||||
VALUE "FileVersion", "3.7.3.000000"
|
||||
VALUE "InternalName", "FreeSpace 2 Open"
|
||||
VALUE "LegalCopyright", "Copyright © 1998"
|
||||
VALUE "OriginalFilename", "fs2.exe"
|
||||
VALUE "ProductName", "FreeSpace 2 Open"
|
||||
VALUE "ProductVersion", "3.7.1"
|
||||
VALUE "ProductVersion", "3.7.3"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
+151
-145
@@ -323,7 +323,7 @@ void parse_helptbl(const char *filename)
|
||||
int overlay_id, currcount, vtxcount;
|
||||
char name[HELP_MAX_NAME_LENGTH];
|
||||
char buf[HELP_MAX_STRING_LENGTH + 1];
|
||||
int i, j, rval;
|
||||
int i, j;
|
||||
|
||||
SCP_vector<help_pline> pline_temp;
|
||||
help_pline pline_temp2;
|
||||
@@ -335,160 +335,166 @@ void parse_helptbl(const char *filename)
|
||||
help_left_bracket lbracket_temp2;
|
||||
vec3d vec3d_temp;
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", filename, rval));
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
// for each overlay...
|
||||
while (optional_string("$")) {
|
||||
|
||||
// for each overlay...
|
||||
while (optional_string("$")) {
|
||||
stuff_string(name, F_NAME, HELP_MAX_NAME_LENGTH);
|
||||
|
||||
stuff_string(name, F_NAME, HELP_MAX_NAME_LENGTH);
|
||||
overlay_id = help_overlay_get_index(name);
|
||||
|
||||
overlay_id = help_overlay_get_index(name);
|
||||
if (overlay_id < 0) {
|
||||
if (num_help_overlays >= MAX_HELP_OVERLAYS) {
|
||||
Warning(LOCATION, "Could not load help overlay after '%s' as maximum number of help overlays was reached (Max is %d)", help_overlaylist[overlay_id - 1].name, MAX_HELP_OVERLAYS);
|
||||
|
||||
if (overlay_id < 0) {
|
||||
if (num_help_overlays >= MAX_HELP_OVERLAYS) {
|
||||
Warning(LOCATION, "Could not load help overlay after '%s' as maximum number of help overlays was reached (Max is %d)", help_overlaylist[overlay_id - 1].name, MAX_HELP_OVERLAYS);
|
||||
|
||||
if (!skip_to_string("$end")) {
|
||||
Error(LOCATION, "Couldn't find $end. Help.tbl or -hlp.tbm is invalid.\n");
|
||||
}
|
||||
|
||||
continue;
|
||||
} else {
|
||||
overlay_id = num_help_overlays;
|
||||
strcpy_s(help_overlaylist[overlay_id].name, name);
|
||||
num_help_overlays++;
|
||||
}
|
||||
}
|
||||
|
||||
// clear out counters in the overlay struct
|
||||
help_overlaylist[overlay_id].plinecount = 0;
|
||||
help_overlaylist[overlay_id].textcount = 0;
|
||||
help_overlaylist[overlay_id].rbracketcount = 0;
|
||||
help_overlaylist[overlay_id].lbracketcount = 0;
|
||||
|
||||
help_overlaylist[overlay_id].fontlist.clear();
|
||||
help_overlaylist[overlay_id].plinelist.clear();
|
||||
help_overlaylist[overlay_id].textlist.clear();
|
||||
help_overlaylist[overlay_id].rbracketlist.clear();
|
||||
help_overlaylist[overlay_id].lbracketlist.clear();
|
||||
|
||||
if (optional_string("+resolutions")) {
|
||||
stuff_int(&help_overlaylist[overlay_id].num_resolutions);
|
||||
} else {
|
||||
help_overlaylist[overlay_id].num_resolutions = 2;
|
||||
}
|
||||
|
||||
if (help_overlaylist[overlay_id].num_resolutions < 1) {
|
||||
Error(LOCATION, "+resolutions in %s is %d. (Must be 1 or greater)", filename, help_overlaylist[overlay_id].num_resolutions);
|
||||
}
|
||||
|
||||
if (optional_string("+font")) {
|
||||
int font;
|
||||
for (i=0; i<help_overlaylist[overlay_id].num_resolutions; i++) {
|
||||
stuff_int(&font);
|
||||
help_overlaylist[overlay_id].fontlist.push_back(font);
|
||||
}
|
||||
} else {
|
||||
for (i=0; i<help_overlaylist[overlay_id].num_resolutions; i++) {
|
||||
help_overlaylist[overlay_id].fontlist.push_back(FONT1);
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<help_overlaylist[overlay_id].num_resolutions; i++) {
|
||||
help_overlaylist[overlay_id].plinelist.push_back(pline_temp);
|
||||
help_overlaylist[overlay_id].textlist.push_back(text_temp);
|
||||
help_overlaylist[overlay_id].rbracketlist.push_back(rbracket_temp);
|
||||
help_overlaylist[overlay_id].lbracketlist.push_back(lbracket_temp);
|
||||
}
|
||||
|
||||
int type;
|
||||
// read in all elements for this overlay
|
||||
while ((type = required_string_one_of(5, "+pline", "+text", "+right_bracket", "+left_bracket", "$end")) != 4) { // Doing it this way means an error lists "$end" at the end, which seems appropriate. -MageKing17
|
||||
|
||||
switch (type) {
|
||||
case 0: // +pline
|
||||
required_string("+pline");
|
||||
currcount = help_overlaylist[overlay_id].plinecount;
|
||||
int a, b; // temp vars to read in int before cast to float;
|
||||
|
||||
// read number of pline vertices
|
||||
stuff_int(&vtxcount);
|
||||
// get vertex coordinates for each resolution
|
||||
for (i = 0; i < help_overlaylist[overlay_id].num_resolutions; i++) {
|
||||
help_overlaylist[overlay_id].plinelist.at(i).push_back(pline_temp2);
|
||||
for (j = 0; j < vtxcount; j++) {
|
||||
help_overlaylist[overlay_id].plinelist.at(i).at(currcount).vtx.push_back(vec3d_temp);
|
||||
help_overlaylist[overlay_id].plinelist.at(i).at(currcount).vtxcount = vtxcount;
|
||||
stuff_int(&a);
|
||||
stuff_int(&b);
|
||||
help_overlaylist[overlay_id].plinelist.at(i).at(currcount).vtx.at(j).xyz.x = (float)a;
|
||||
help_overlaylist[overlay_id].plinelist.at(i).at(currcount).vtx.at(j).xyz.y = (float)b;
|
||||
help_overlaylist[overlay_id].plinelist.at(i).at(currcount).vtx.at(j).xyz.z = 0.0f;
|
||||
if (!skip_to_string("$end")) {
|
||||
Error(LOCATION, "Couldn't find $end. Help.tbl or -hlp.tbm is invalid.\n");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
help_overlaylist[overlay_id].plinecount++;
|
||||
break;
|
||||
case 1: // +text
|
||||
required_string("+text");
|
||||
currcount = help_overlaylist[overlay_id].textcount;
|
||||
|
||||
// get coordinates for each resolution
|
||||
for (i = 0; i < help_overlaylist[overlay_id].num_resolutions; i++) {
|
||||
help_overlaylist[overlay_id].textlist.at(i).push_back(text_temp2);
|
||||
stuff_int(&(help_overlaylist[overlay_id].textlist.at(i).at(currcount).x_coord));
|
||||
stuff_int(&(help_overlaylist[overlay_id].textlist.at(i).at(currcount).y_coord));
|
||||
else {
|
||||
overlay_id = num_help_overlays;
|
||||
strcpy_s(help_overlaylist[overlay_id].name, name);
|
||||
num_help_overlays++;
|
||||
}
|
||||
|
||||
// get string (always use the first resolution)
|
||||
stuff_string(buf, F_MESSAGE, sizeof(buf));
|
||||
help_overlaylist[overlay_id].textlist.at(0).at(currcount).string = vm_strdup(buf);
|
||||
|
||||
help_overlaylist[overlay_id].textcount++;
|
||||
break;
|
||||
case 2: // +right_bracket
|
||||
required_string("+right_bracket");
|
||||
currcount = help_overlaylist[overlay_id].rbracketcount;
|
||||
|
||||
// get coordinates for each resolution
|
||||
for (i = 0; i < help_overlaylist[overlay_id].num_resolutions; i++) {
|
||||
help_overlaylist[overlay_id].rbracketlist.at(i).push_back(rbracket_temp2);
|
||||
stuff_int(&(help_overlaylist[overlay_id].rbracketlist.at(i).at(currcount).x_coord));
|
||||
stuff_int(&(help_overlaylist[overlay_id].rbracketlist.at(i).at(currcount).y_coord));
|
||||
}
|
||||
|
||||
help_overlaylist[overlay_id].rbracketcount++;
|
||||
break;
|
||||
case 3: // +left_bracket
|
||||
required_string("+left_bracket");
|
||||
currcount = help_overlaylist[overlay_id].lbracketcount;
|
||||
|
||||
// get coordinates for each resolution
|
||||
for (i = 0; i < help_overlaylist[overlay_id].num_resolutions; i++) {
|
||||
help_overlaylist[overlay_id].lbracketlist.at(i).push_back(lbracket_temp2);
|
||||
stuff_int(&(help_overlaylist[overlay_id].lbracketlist.at(i).at(currcount).x_coord));
|
||||
stuff_int(&(help_overlaylist[overlay_id].lbracketlist.at(i).at(currcount).y_coord));
|
||||
}
|
||||
|
||||
help_overlaylist[overlay_id].lbracketcount++;
|
||||
break;
|
||||
case -1:
|
||||
// -noparseerrors is set
|
||||
break;
|
||||
case 4: // $end
|
||||
default:
|
||||
Assertion(false, "This should never happen.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// clear out counters in the overlay struct
|
||||
help_overlaylist[overlay_id].plinecount = 0;
|
||||
help_overlaylist[overlay_id].textcount = 0;
|
||||
help_overlaylist[overlay_id].rbracketcount = 0;
|
||||
help_overlaylist[overlay_id].lbracketcount = 0;
|
||||
|
||||
help_overlaylist[overlay_id].fontlist.clear();
|
||||
help_overlaylist[overlay_id].plinelist.clear();
|
||||
help_overlaylist[overlay_id].textlist.clear();
|
||||
help_overlaylist[overlay_id].rbracketlist.clear();
|
||||
help_overlaylist[overlay_id].lbracketlist.clear();
|
||||
|
||||
if (optional_string("+resolutions")) {
|
||||
stuff_int(&help_overlaylist[overlay_id].num_resolutions);
|
||||
}
|
||||
else {
|
||||
help_overlaylist[overlay_id].num_resolutions = 2;
|
||||
}
|
||||
|
||||
if (help_overlaylist[overlay_id].num_resolutions < 1) {
|
||||
Error(LOCATION, "+resolutions in %s is %d. (Must be 1 or greater)", filename, help_overlaylist[overlay_id].num_resolutions);
|
||||
}
|
||||
|
||||
if (optional_string("+font")) {
|
||||
int font;
|
||||
for (i = 0; i < help_overlaylist[overlay_id].num_resolutions; i++) {
|
||||
stuff_int(&font);
|
||||
help_overlaylist[overlay_id].fontlist.push_back(font);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < help_overlaylist[overlay_id].num_resolutions; i++) {
|
||||
help_overlaylist[overlay_id].fontlist.push_back(FONT1);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < help_overlaylist[overlay_id].num_resolutions; i++) {
|
||||
help_overlaylist[overlay_id].plinelist.push_back(pline_temp);
|
||||
help_overlaylist[overlay_id].textlist.push_back(text_temp);
|
||||
help_overlaylist[overlay_id].rbracketlist.push_back(rbracket_temp);
|
||||
help_overlaylist[overlay_id].lbracketlist.push_back(lbracket_temp);
|
||||
}
|
||||
|
||||
int type;
|
||||
// read in all elements for this overlay
|
||||
while ((type = required_string_one_of(5, "+pline", "+text", "+right_bracket", "+left_bracket", "$end")) != 4) { // Doing it this way means an error lists "$end" at the end, which seems appropriate. -MageKing17
|
||||
|
||||
switch (type) {
|
||||
case 0: // +pline
|
||||
required_string("+pline");
|
||||
currcount = help_overlaylist[overlay_id].plinecount;
|
||||
int a, b; // temp vars to read in int before cast to float;
|
||||
|
||||
// read number of pline vertices
|
||||
stuff_int(&vtxcount);
|
||||
// get vertex coordinates for each resolution
|
||||
for (i = 0; i < help_overlaylist[overlay_id].num_resolutions; i++) {
|
||||
help_overlaylist[overlay_id].plinelist.at(i).push_back(pline_temp2);
|
||||
for (j = 0; j < vtxcount; j++) {
|
||||
help_overlaylist[overlay_id].plinelist.at(i).at(currcount).vtx.push_back(vec3d_temp);
|
||||
help_overlaylist[overlay_id].plinelist.at(i).at(currcount).vtxcount = vtxcount;
|
||||
stuff_int(&a);
|
||||
stuff_int(&b);
|
||||
help_overlaylist[overlay_id].plinelist.at(i).at(currcount).vtx.at(j).xyz.x = (float)a;
|
||||
help_overlaylist[overlay_id].plinelist.at(i).at(currcount).vtx.at(j).xyz.y = (float)b;
|
||||
help_overlaylist[overlay_id].plinelist.at(i).at(currcount).vtx.at(j).xyz.z = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
help_overlaylist[overlay_id].plinecount++;
|
||||
break;
|
||||
case 1: // +text
|
||||
required_string("+text");
|
||||
currcount = help_overlaylist[overlay_id].textcount;
|
||||
|
||||
// get coordinates for each resolution
|
||||
for (i = 0; i < help_overlaylist[overlay_id].num_resolutions; i++) {
|
||||
help_overlaylist[overlay_id].textlist.at(i).push_back(text_temp2);
|
||||
stuff_int(&(help_overlaylist[overlay_id].textlist.at(i).at(currcount).x_coord));
|
||||
stuff_int(&(help_overlaylist[overlay_id].textlist.at(i).at(currcount).y_coord));
|
||||
}
|
||||
|
||||
// get string (always use the first resolution)
|
||||
stuff_string(buf, F_MESSAGE, sizeof(buf));
|
||||
help_overlaylist[overlay_id].textlist.at(0).at(currcount).string = vm_strdup(buf);
|
||||
|
||||
help_overlaylist[overlay_id].textcount++;
|
||||
break;
|
||||
case 2: // +right_bracket
|
||||
required_string("+right_bracket");
|
||||
currcount = help_overlaylist[overlay_id].rbracketcount;
|
||||
|
||||
// get coordinates for each resolution
|
||||
for (i = 0; i < help_overlaylist[overlay_id].num_resolutions; i++) {
|
||||
help_overlaylist[overlay_id].rbracketlist.at(i).push_back(rbracket_temp2);
|
||||
stuff_int(&(help_overlaylist[overlay_id].rbracketlist.at(i).at(currcount).x_coord));
|
||||
stuff_int(&(help_overlaylist[overlay_id].rbracketlist.at(i).at(currcount).y_coord));
|
||||
}
|
||||
|
||||
help_overlaylist[overlay_id].rbracketcount++;
|
||||
break;
|
||||
case 3: // +left_bracket
|
||||
required_string("+left_bracket");
|
||||
currcount = help_overlaylist[overlay_id].lbracketcount;
|
||||
|
||||
// get coordinates for each resolution
|
||||
for (i = 0; i < help_overlaylist[overlay_id].num_resolutions; i++) {
|
||||
help_overlaylist[overlay_id].lbracketlist.at(i).push_back(lbracket_temp2);
|
||||
stuff_int(&(help_overlaylist[overlay_id].lbracketlist.at(i).at(currcount).x_coord));
|
||||
stuff_int(&(help_overlaylist[overlay_id].lbracketlist.at(i).at(currcount).y_coord));
|
||||
}
|
||||
|
||||
help_overlaylist[overlay_id].lbracketcount++;
|
||||
break;
|
||||
case -1:
|
||||
// -noparseerrors is set
|
||||
break;
|
||||
case 4: // $end
|
||||
default:
|
||||
Assertion(false, "This should never happen.\n");
|
||||
break;
|
||||
}
|
||||
} // end while
|
||||
required_string("$end");
|
||||
} // end while
|
||||
required_string("$end");
|
||||
} // end while
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", filename, e.what()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+10
-13
@@ -28,15 +28,14 @@
|
||||
|
||||
#pragma optimize("", off)
|
||||
|
||||
#define DEFAULT_MASTER_EVENT_MUSIC_VOLUME 0.5f
|
||||
|
||||
#define HULL_VALUE_TO_PLAY_INTENSE_BATTLE_MUSIC 0.75f
|
||||
|
||||
////////////////////////////
|
||||
// Globals
|
||||
////////////////////////////
|
||||
int Event_Music_battle_started = 0;
|
||||
float Master_event_music_volume = DEFAULT_MASTER_EVENT_MUSIC_VOLUME; // range is 0->1
|
||||
float Default_music_volume = 0.5f; // range is 0->1
|
||||
float Master_event_music_volume = Default_music_volume;
|
||||
|
||||
typedef struct tagSNDPATTERN {
|
||||
int default_next_pattern; // Needed so the next_pattern member can be reset
|
||||
@@ -1360,10 +1359,8 @@ void parse_menumusic()
|
||||
|
||||
// Goober5000 - check for existence of file
|
||||
// taylor - check for all file types
|
||||
const int NUM_EXT = 2;
|
||||
const char *exts[NUM_EXT] = { ".ogg", ".wav" };
|
||||
|
||||
if ( cf_exists_full_ext(Spooled_music[idx].filename, CF_TYPE_MUSIC, NUM_EXT, exts) )
|
||||
// chief1983 - use type list defined in audiostr.h
|
||||
if ( cf_exists_full_ext(Spooled_music[idx].filename, CF_TYPE_MUSIC, NUM_AUDIO_EXT, audio_ext_list) )
|
||||
Spooled_music[idx].flags |= SMF_VALID;
|
||||
|
||||
if (!nocreate)
|
||||
@@ -1376,12 +1373,8 @@ void parse_menumusic()
|
||||
//
|
||||
void event_music_parse_musictbl(const char *filename)
|
||||
{
|
||||
int rval;
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", filename, rval));
|
||||
|
||||
} else {
|
||||
try
|
||||
{
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
@@ -1401,6 +1394,10 @@ void event_music_parse_musictbl(const char *filename)
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", filename, e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -41,7 +41,8 @@
|
||||
|
||||
extern int Event_Music_battle_started; // flag that will tell us if we've started a battle in the current mission
|
||||
extern int Event_music_enabled;
|
||||
extern float Master_event_music_volume; // range is 0->1
|
||||
extern float Default_music_volume; // range is 0->1
|
||||
extern float Master_event_music_volume; // range is 0->1
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
+74
-74
@@ -693,83 +693,83 @@ static SCP_vector<species_info> missingFlybySounds;
|
||||
|
||||
void parse_sound_table(const char* filename)
|
||||
{
|
||||
int rval;
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0)
|
||||
try
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", filename, rval));
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
// Parse the gameplay sounds section
|
||||
if (optional_string("#Game Sounds Start"))
|
||||
{
|
||||
while (!check_for_string("#Game Sounds End"))
|
||||
{
|
||||
game_snd tempSound;
|
||||
if (gamesnd_parse_line(&tempSound, "$Name:", &Snds))
|
||||
{
|
||||
Snds.push_back(game_snd(tempSound));
|
||||
}
|
||||
}
|
||||
|
||||
required_string("#Game Sounds End");
|
||||
}
|
||||
|
||||
// Parse the interface sounds section
|
||||
if (optional_string("#Interface Sounds Start"))
|
||||
{
|
||||
while (!check_for_string("#Interface Sounds End"))
|
||||
{
|
||||
game_snd tempSound;
|
||||
if (gamesnd_parse_line(&tempSound, "$Name:", &Snds_iface))
|
||||
{
|
||||
Snds_iface.push_back(game_snd(tempSound));
|
||||
Snds_iface_handle.push_back(-1);
|
||||
}
|
||||
}
|
||||
|
||||
required_string("#Interface Sounds End");
|
||||
}
|
||||
|
||||
// parse flyby sound section
|
||||
if (optional_string("#Flyby Sounds Start"))
|
||||
{
|
||||
char species_name_tag[NAME_LENGTH + 2];
|
||||
int sanity_check = 0;
|
||||
size_t i;
|
||||
|
||||
while (!check_for_string("#Flyby Sounds End") && (sanity_check <= (int)Species_info.size()))
|
||||
{
|
||||
for (i = 0; i < Species_info.size(); i++)
|
||||
{
|
||||
species_info *species = &Species_info[i];
|
||||
|
||||
sprintf(species_name_tag, "$%s:", species->species_name);
|
||||
|
||||
if (check_for_string(species_name_tag))
|
||||
{
|
||||
gamesnd_parse_line(&species->snd_flyby_fighter, species_name_tag);
|
||||
gamesnd_parse_line(&species->snd_flyby_bomber, species_name_tag);
|
||||
sanity_check--;
|
||||
}
|
||||
else
|
||||
{
|
||||
sanity_check++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
required_string("#Flyby Sounds End");
|
||||
}
|
||||
|
||||
if (optional_string("#Sound Environments Start"))
|
||||
{
|
||||
parse_sound_environments();
|
||||
}
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", filename, e.what()));
|
||||
return;
|
||||
}
|
||||
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
// Parse the gameplay sounds section
|
||||
if (optional_string("#Game Sounds Start"))
|
||||
{
|
||||
while (!check_for_string("#Game Sounds End"))
|
||||
{
|
||||
game_snd tempSound;
|
||||
if (gamesnd_parse_line(&tempSound, "$Name:", &Snds))
|
||||
{
|
||||
Snds.push_back(game_snd(tempSound));
|
||||
}
|
||||
}
|
||||
|
||||
required_string("#Game Sounds End");
|
||||
}
|
||||
|
||||
// Parse the interface sounds section
|
||||
if (optional_string("#Interface Sounds Start"))
|
||||
{
|
||||
while (!check_for_string("#Interface Sounds End"))
|
||||
{
|
||||
game_snd tempSound;
|
||||
if (gamesnd_parse_line( &tempSound, "$Name:", &Snds_iface))
|
||||
{
|
||||
Snds_iface.push_back(game_snd(tempSound));
|
||||
Snds_iface_handle.push_back(-1);
|
||||
}
|
||||
}
|
||||
|
||||
required_string("#Interface Sounds End");
|
||||
}
|
||||
|
||||
// parse flyby sound section
|
||||
if (optional_string("#Flyby Sounds Start"))
|
||||
{
|
||||
char species_name_tag[NAME_LENGTH + 2];
|
||||
int sanity_check = 0;
|
||||
size_t i;
|
||||
|
||||
while (!check_for_string("#Flyby Sounds End") && (sanity_check <= (int)Species_info.size()))
|
||||
{
|
||||
for (i = 0; i < Species_info.size(); i++)
|
||||
{
|
||||
species_info *species = &Species_info[i];
|
||||
|
||||
sprintf(species_name_tag, "$%s:", species->species_name);
|
||||
|
||||
if (check_for_string(species_name_tag))
|
||||
{
|
||||
gamesnd_parse_line(&species->snd_flyby_fighter, species_name_tag);
|
||||
gamesnd_parse_line(&species->snd_flyby_bomber, species_name_tag);
|
||||
sanity_check--;
|
||||
}
|
||||
else
|
||||
{
|
||||
sanity_check++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
required_string("#Flyby Sounds End");
|
||||
}
|
||||
|
||||
if (optional_string("#Sound Environments Start"))
|
||||
{
|
||||
parse_sound_environments();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+320
-308
@@ -273,71 +273,74 @@ void parse_colors(const char *filename)
|
||||
{
|
||||
Assertion(filename != NULL, "parse_colors() called on NULL; get a coder!\n");
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
|
||||
int err_code;
|
||||
if ((err_code = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %d.\n", filename, err_code));
|
||||
return;
|
||||
}
|
||||
|
||||
reset_parse();
|
||||
|
||||
// we search for the colors based on their order of definition above
|
||||
// if the color isn't found, we just use default values
|
||||
if (optional_string("#Start Colors"))
|
||||
|
||||
try
|
||||
{
|
||||
// vars for holding rgba values
|
||||
int rgba[4] = {0,0,0,0};
|
||||
int i, j;
|
||||
reset_parse();
|
||||
|
||||
char* color_names[TOTAL_COLORS] = {
|
||||
"$Blue:",
|
||||
"$Bright Blue:",
|
||||
"$Green:",
|
||||
"$Bright Green:",
|
||||
"$Black:",
|
||||
"$Grey:",
|
||||
"$Silver:",
|
||||
"$White:",
|
||||
"$Bright White:",
|
||||
"$Violet Gray:",
|
||||
"$Violet:",
|
||||
"$Dim Red:",
|
||||
"$Red:",
|
||||
"$Bright Red:",
|
||||
"$Pink:",
|
||||
"$Light Pink:",
|
||||
"$Yellow:",
|
||||
"$Bright Yellow:",
|
||||
"$UI Light Green:",
|
||||
"$UI Green:",
|
||||
"$UI Light Pink:",
|
||||
"$UI Pink:"
|
||||
};
|
||||
// we search for the colors based on their order of definition above
|
||||
// if the color isn't found, we just use default values
|
||||
if (optional_string("#Start Colors"))
|
||||
{
|
||||
// vars for holding rgba values
|
||||
int rgba[4] = { 0, 0, 0, 0 };
|
||||
int i, j;
|
||||
|
||||
// now for each color, check if it's corresponding string is there
|
||||
for (i = 0; i < TOTAL_COLORS; i++) {
|
||||
if (optional_string(color_names[i])) {
|
||||
// if so, get its rgba values and initialise it using them
|
||||
mprintf(("'%s' has been redefined.\n", color_names[i]));
|
||||
//if (check_for_string("(")) {
|
||||
char* color_names[TOTAL_COLORS] = {
|
||||
"$Blue:",
|
||||
"$Bright Blue:",
|
||||
"$Green:",
|
||||
"$Bright Green:",
|
||||
"$Black:",
|
||||
"$Grey:",
|
||||
"$Silver:",
|
||||
"$White:",
|
||||
"$Bright White:",
|
||||
"$Violet Gray:",
|
||||
"$Violet:",
|
||||
"$Dim Red:",
|
||||
"$Red:",
|
||||
"$Bright Red:",
|
||||
"$Pink:",
|
||||
"$Light Pink:",
|
||||
"$Yellow:",
|
||||
"$Bright Yellow:",
|
||||
"$UI Light Green:",
|
||||
"$UI Green:",
|
||||
"$UI Light Pink:",
|
||||
"$UI Pink:"
|
||||
};
|
||||
|
||||
// now for each color, check if it's corresponding string is there
|
||||
for (i = 0; i < TOTAL_COLORS; i++) {
|
||||
if (optional_string(color_names[i])) {
|
||||
// if so, get its rgba values and initialise it using them
|
||||
mprintf(("'%s' has been redefined.\n", color_names[i]));
|
||||
//if (check_for_string("(")) {
|
||||
stuff_int_list(rgba, 4, RAW_INTEGER_TYPE);
|
||||
for (j = 0; j < 4; j++) {
|
||||
if (rgba[j] < 0) {
|
||||
Warning(LOCATION, "RGBA value for '%s' in %s too low (%d), capping to 0.\n", color_names[i], filename, rgba[j]);
|
||||
rgba[j] = 0;
|
||||
} else if (rgba[j] > 255) {
|
||||
}
|
||||
else if (rgba[j] > 255) {
|
||||
Warning(LOCATION, "RGBA value for '%s' in %s too high (%d), capping to 255.\n", color_names[i], filename, rgba[j]);
|
||||
rgba[j] = 255;
|
||||
}
|
||||
}
|
||||
//} else {
|
||||
// stuff_hex_list(rgba, 4);
|
||||
//}
|
||||
gr_init_alphacolor(COLOR_LIST[i], rgba[0], rgba[1], rgba[2], rgba[3]);
|
||||
//} else {
|
||||
// stuff_hex_list(rgba, 4);
|
||||
//}
|
||||
gr_init_alphacolor(COLOR_LIST[i], rgba[0], rgba[1], rgba[2], rgba[3]);
|
||||
}
|
||||
}
|
||||
required_string("#End");
|
||||
}
|
||||
required_string("#End");
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", filename, e.what()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,281 +349,290 @@ void parse_everything_else(const char *filename)
|
||||
Assertion(filename != NULL, "parse_everything_else() called on NULL; get a coder!\n");
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
|
||||
int err_code;
|
||||
if ((err_code = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %d.\n", filename, err_code));
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
reset_parse();
|
||||
|
||||
reset_parse();
|
||||
int rgba[4] = { 0, 0, 0, 0 };
|
||||
|
||||
int rgba[4] = {0,0,0,0};
|
||||
// reusable temp vars
|
||||
int i, j;
|
||||
SCP_string temp;
|
||||
|
||||
// reusable temp vars
|
||||
int i, j;
|
||||
SCP_string temp;
|
||||
|
||||
if (optional_string("#Start Colors")) {
|
||||
// Skip this section; we already parsed it in every file.
|
||||
skip_to_string("#End", NULL);
|
||||
}
|
||||
|
||||
//Team coloring
|
||||
if (optional_string("#Team Colors")) {
|
||||
|
||||
while (required_string_either("#End", "$Team Name:")) {
|
||||
required_string("$Team Name:"); // required to move the parse pointer forward
|
||||
team_color temp_color;
|
||||
|
||||
char temp2[NAME_LENGTH];
|
||||
stuff_string(temp2, F_NAME, NAME_LENGTH);
|
||||
temp = temp2;
|
||||
|
||||
if (!stricmp(temp2, "none")) {
|
||||
Warning(LOCATION, "Team color in '%s' defined with a name of '%s'; this won't be usable due to 'None' being used for a lack of a team color by the engine.\n", filename, temp2);
|
||||
}
|
||||
|
||||
if (required_string("$Team Stripe Color:")) {
|
||||
int rgb[3];
|
||||
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
|
||||
for (i = 0; i < 3; i++) {
|
||||
CLAMP(rgb[i], 0, 255);
|
||||
}
|
||||
|
||||
temp_color.stripe.r = rgb[0] / 255.0f;
|
||||
temp_color.stripe.g = rgb[1] / 255.0f;
|
||||
temp_color.stripe.b = rgb[2] / 255.0f;
|
||||
}
|
||||
|
||||
if (required_string("$Team Base Color:")) {
|
||||
int rgb[3];
|
||||
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
|
||||
for (i = 0; i < 3; i++) {
|
||||
CLAMP(rgb[i], 0, 255);
|
||||
}
|
||||
|
||||
temp_color.base.r = rgb[0] / 255.0f;
|
||||
temp_color.base.g = rgb[1] / 255.0f;
|
||||
temp_color.base.b = rgb[2] / 255.0f;
|
||||
}
|
||||
|
||||
if (Team_Colors.find(temp) == Team_Colors.end()) { // Only push to the vector if the team isn't already defined.
|
||||
Team_Names.push_back(temp);
|
||||
}
|
||||
Team_Colors[temp] = temp_color;
|
||||
}
|
||||
required_string("#End");
|
||||
}
|
||||
|
||||
// Previously-hardcoded interface colors
|
||||
if (optional_string("#Interface Colors")) {
|
||||
char *color_names[INTERFACE_COLORS] = {
|
||||
"$Text Normal:",
|
||||
"$Text Subselected:",
|
||||
"$Text Selected:",
|
||||
"$Text Error:",
|
||||
"$Text Error Highlighted:",
|
||||
"$Text Active:",
|
||||
"$Text Active Highlighted:",
|
||||
"$Text Heading:",
|
||||
"$More Indicator:",
|
||||
"$Bright More Indicator:",
|
||||
"$Bright:",
|
||||
"$Normal:",
|
||||
"$Briefing Grid:",
|
||||
};
|
||||
|
||||
// now for each color, check if its corresponding string is there
|
||||
for (i = 0; i < INTERFACE_COLORS; i++) {
|
||||
if (optional_string(color_names[i])) {
|
||||
// if so, get its rgba values and initialise it using them
|
||||
mprintf(("'%s' has been redefined.\n", color_names[i]));
|
||||
if ( check_for_string("(") ) {
|
||||
// If we have a list of integers, use them.
|
||||
stuff_int_list(rgba, 4, RAW_INTEGER_TYPE);
|
||||
for (j = 0; j < 4; j++) {
|
||||
if (rgba[j] < 0)
|
||||
{
|
||||
Warning(LOCATION, "RGBA value for '%s' in %s too low (%d), capping to 0.\n", color_names[i], filename, rgba[j]);
|
||||
rgba[j] = 0;
|
||||
}
|
||||
else if (rgba[j] > 255)
|
||||
{
|
||||
Warning(LOCATION, "RGBA value for '%s' in %s too high (%d), capping to 255.\n", color_names[i], filename, rgba[j]);
|
||||
rgba[j] = 255;
|
||||
}
|
||||
}
|
||||
gr_init_alphacolor(interface_colors[i], rgba[0], rgba[1], rgba[2], rgba[3]);
|
||||
//} else if (check_for_string("#")) {
|
||||
// stuff_hex_list(rgba, 4);
|
||||
// gr_init_alphacolor(interface_colors[i], rgba[0], rgba[1], rgba[2], rgba[3]);
|
||||
} else {
|
||||
// We have a string; it should be the name of a color to use.
|
||||
stuff_string(temp, F_NAME);
|
||||
for (j = 0; j < TOTAL_COLORS; j++) {
|
||||
if ( !temp.compare(COLOR_NAMES[j]) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( j == TOTAL_COLORS ) {
|
||||
Warning(LOCATION, "Unknown color '%s' in %s, for definition of '%s'; using default ('%s').\n", temp.c_str(), filename, color_names[i], COLOR_NAMES[interface_defaults[i]]);
|
||||
} else {
|
||||
Assertion(j >= 0 && j < TOTAL_COLORS, "Attempting to copy nonexistant color (%d out of 0-%d)!\n", j, TOTAL_COLORS-1);
|
||||
memcpy(interface_colors[i], COLOR_LIST[j], sizeof(color));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
required_string("#End");
|
||||
}
|
||||
|
||||
// Text color tags; for briefings, command briefings, debriefings, and the fiction viewer
|
||||
if (optional_string("#Color Tags")) {
|
||||
while (required_string_either("$Tag:", "#End") < 1) {
|
||||
required_string("$Tag:");
|
||||
color temp_color;
|
||||
char tag;
|
||||
|
||||
stuff_string(temp, F_RAW);
|
||||
if (temp[0] == '$') {
|
||||
if (temp[1] == '\0') {
|
||||
Error(LOCATION, "%s - found a '$Tag:' entry with a solitary '$'.\n", filename);
|
||||
}
|
||||
tag = temp[1];
|
||||
if (temp[2] != '\0') {
|
||||
Warning(LOCATION, "%s - tag '$%c' has extra text in its definition.\n", filename, tag);
|
||||
}
|
||||
} else if (temp[0] == '\0') {
|
||||
Error(LOCATION, "%s - found a '$Tag:' entry with no tag.\n", filename);
|
||||
} else {
|
||||
tag = temp[0];
|
||||
if (temp[1] != '\0') {
|
||||
Warning(LOCATION, "%s - tag '$%c' has extra text in its definition.\n", filename, tag);
|
||||
}
|
||||
}
|
||||
|
||||
if (Tagged_Colors.find(tag) == Tagged_Colors.end()) { // Only push the tag to our list of tags if it's actually new, not just a redefinition.
|
||||
Color_Tags.push_back(tag);
|
||||
}
|
||||
|
||||
switch(required_string_one_of(4, "+Color:", "+Friendly", "+Hostile", "+Neutral")) {
|
||||
case 0: // +Color
|
||||
required_string("+Color:");
|
||||
|
||||
rgba[0] = rgba[1] = rgba[2] = 0;
|
||||
rgba[3] = 255; // Odds are pretty high you want it to have full alpha...
|
||||
|
||||
if ( check_for_string("(") ) {
|
||||
stuff_int_list(rgba, 4, RAW_INTEGER_TYPE);
|
||||
for (j = 0; j < 4; j++) {
|
||||
if (rgba[j] < 0)
|
||||
{
|
||||
Warning(LOCATION, "RGBA value for '$%c' in %s too low (%d), capping to 0.\n", tag, filename, rgba[j]);
|
||||
rgba[j] = 0;
|
||||
}
|
||||
else if (rgba[j] > 255)
|
||||
{
|
||||
Warning(LOCATION, "RGBA value for '$%c' in %s too high (%d), capping to 255.\n", tag, filename, rgba[j]);
|
||||
rgba[j] = 255;
|
||||
}
|
||||
}
|
||||
gr_init_alphacolor(&temp_color, rgba[0], rgba[1], rgba[2], rgba[3]);
|
||||
Custom_Colors[tag] = temp_color;
|
||||
Tagged_Colors[tag] = &Custom_Colors[tag];
|
||||
//} else if ( check_for_string ("#") ) {
|
||||
// stuff_hex_list(rgba, 4);
|
||||
// gr_init_alphacolor(&temp_color, rgba[0], rgba[1], rgba[2], rgba[3]);
|
||||
// Custom_Colors[tag] = temp_color;
|
||||
// Tagged_Colors[tag] = &Custom_Colors[tag];
|
||||
} else {
|
||||
// We have a string; it should be the name of a color to use.
|
||||
stuff_string(temp, F_NAME);
|
||||
for (j = 0; j < TOTAL_COLORS; j++) {
|
||||
if ( !temp.compare(COLOR_NAMES[j]) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( j == TOTAL_COLORS ) {
|
||||
Error(LOCATION, "Unknown color '%s' in %s, for definition of tag '$%c'.\n", temp.c_str(), filename, tag);
|
||||
}
|
||||
Tagged_Colors[tag] = COLOR_LIST[j];
|
||||
}
|
||||
break;
|
||||
case 1: // +Friendly
|
||||
required_string("+Friendly");
|
||||
Tagged_Colors[tag] = &Brief_color_green;
|
||||
break;
|
||||
case 2: // +Hostile
|
||||
required_string("+Hostile");
|
||||
Tagged_Colors[tag] = &Brief_color_red;
|
||||
break;
|
||||
case 3: // +Neutral
|
||||
required_string("+Neutral");
|
||||
Tagged_Colors[tag] = &Brief_color_legacy_neutral;
|
||||
break;
|
||||
case -1:
|
||||
// -noparseerrors is set
|
||||
if (Tagged_Colors.find(tag) == Tagged_Colors.end()) { // It was a new color, but since we haven't actually defined it...
|
||||
Color_Tags.pop_back();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Assertion(false, "MageKing17 made a coding error somewhere, and you should laugh at him (and report this error).\n");
|
||||
break;
|
||||
}
|
||||
if (optional_string("#Start Colors")) {
|
||||
// Skip this section; we already parsed it in every file.
|
||||
skip_to_string("#End", NULL);
|
||||
}
|
||||
|
||||
required_string("#End");
|
||||
}
|
||||
Assertion(Color_Tags.size() == Tagged_Colors.size(), "Color_Tags and Tagged_Colors size mismatch; get a coder!\n");
|
||||
//Team coloring
|
||||
if (optional_string("#Team Colors")) {
|
||||
|
||||
if (optional_string("#Default Text Colors")) {
|
||||
while (required_string_either("#End", "$Team Name:")) {
|
||||
required_string("$Team Name:"); // required to move the parse pointer forward
|
||||
team_color temp_color;
|
||||
|
||||
char* color_names[MAX_DEFAULT_TEXT_COLORS] = {
|
||||
"$Fiction Viewer:",
|
||||
"$Command Briefing:",
|
||||
"$Briefing:",
|
||||
"$Redalert Briefing:",
|
||||
"$Debriefing:",
|
||||
"$Recommendation:",
|
||||
"$Loop Briefing:",
|
||||
};
|
||||
char temp2[NAME_LENGTH];
|
||||
stuff_string(temp2, F_NAME, NAME_LENGTH);
|
||||
temp = temp2;
|
||||
|
||||
char *color_value[MAX_DEFAULT_TEXT_COLORS] = {
|
||||
&default_fiction_viewer_color,
|
||||
&default_command_briefing_color,
|
||||
&default_briefing_color,
|
||||
&default_redalert_briefing_color,
|
||||
&default_debriefing_color,
|
||||
&default_recommendation_color,
|
||||
&default_loop_briefing_color,
|
||||
};
|
||||
if (!stricmp(temp2, "none")) {
|
||||
Warning(LOCATION, "Team color in '%s' defined with a name of '%s'; this won't be usable due to 'None' being used for a lack of a team color by the engine.\n", filename, temp2);
|
||||
}
|
||||
|
||||
if (required_string("$Team Stripe Color:")) {
|
||||
int rgb[3];
|
||||
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
|
||||
for (i = 0; i < 3; i++) {
|
||||
CLAMP(rgb[i], 0, 255);
|
||||
}
|
||||
|
||||
temp_color.stripe.r = rgb[0] / 255.0f;
|
||||
temp_color.stripe.g = rgb[1] / 255.0f;
|
||||
temp_color.stripe.b = rgb[2] / 255.0f;
|
||||
}
|
||||
|
||||
if (required_string("$Team Base Color:")) {
|
||||
int rgb[3];
|
||||
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
|
||||
for (i = 0; i < 3; i++) {
|
||||
CLAMP(rgb[i], 0, 255);
|
||||
}
|
||||
|
||||
temp_color.base.r = rgb[0] / 255.0f;
|
||||
temp_color.base.g = rgb[1] / 255.0f;
|
||||
temp_color.base.b = rgb[2] / 255.0f;
|
||||
}
|
||||
|
||||
if (Team_Colors.find(temp) == Team_Colors.end()) { // Only push to the vector if the team isn't already defined.
|
||||
Team_Names.push_back(temp);
|
||||
}
|
||||
Team_Colors[temp] = temp_color;
|
||||
}
|
||||
required_string("#End");
|
||||
}
|
||||
|
||||
// Previously-hardcoded interface colors
|
||||
if (optional_string("#Interface Colors")) {
|
||||
char *color_names[INTERFACE_COLORS] = {
|
||||
"$Text Normal:",
|
||||
"$Text Subselected:",
|
||||
"$Text Selected:",
|
||||
"$Text Error:",
|
||||
"$Text Error Highlighted:",
|
||||
"$Text Active:",
|
||||
"$Text Active Highlighted:",
|
||||
"$Text Heading:",
|
||||
"$More Indicator:",
|
||||
"$Bright More Indicator:",
|
||||
"$Bright:",
|
||||
"$Normal:",
|
||||
"$Briefing Grid:",
|
||||
};
|
||||
|
||||
// now for each color, check if its corresponding string is there
|
||||
for (i = 0; i < INTERFACE_COLORS; i++) {
|
||||
if (optional_string(color_names[i])) {
|
||||
// if so, get its rgba values and initialise it using them
|
||||
mprintf(("'%s' has been redefined.\n", color_names[i]));
|
||||
if (check_for_string("(")) {
|
||||
// If we have a list of integers, use them.
|
||||
stuff_int_list(rgba, 4, RAW_INTEGER_TYPE);
|
||||
for (j = 0; j < 4; j++) {
|
||||
if (rgba[j] < 0)
|
||||
{
|
||||
Warning(LOCATION, "RGBA value for '%s' in %s too low (%d), capping to 0.\n", color_names[i], filename, rgba[j]);
|
||||
rgba[j] = 0;
|
||||
}
|
||||
else if (rgba[j] > 255)
|
||||
{
|
||||
Warning(LOCATION, "RGBA value for '%s' in %s too high (%d), capping to 255.\n", color_names[i], filename, rgba[j]);
|
||||
rgba[j] = 255;
|
||||
}
|
||||
}
|
||||
gr_init_alphacolor(interface_colors[i], rgba[0], rgba[1], rgba[2], rgba[3]);
|
||||
//} else if (check_for_string("#")) {
|
||||
// stuff_hex_list(rgba, 4);
|
||||
// gr_init_alphacolor(interface_colors[i], rgba[0], rgba[1], rgba[2], rgba[3]);
|
||||
}
|
||||
else {
|
||||
// We have a string; it should be the name of a color to use.
|
||||
stuff_string(temp, F_NAME);
|
||||
for (j = 0; j < TOTAL_COLORS; j++) {
|
||||
if (!temp.compare(COLOR_NAMES[j])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j == TOTAL_COLORS) {
|
||||
Warning(LOCATION, "Unknown color '%s' in %s, for definition of '%s'; using default ('%s').\n", temp.c_str(), filename, color_names[i], COLOR_NAMES[interface_defaults[i]]);
|
||||
}
|
||||
else {
|
||||
Assertion(j >= 0 && j < TOTAL_COLORS, "Attempting to copy nonexistant color (%d out of 0-%d)!\n", j, TOTAL_COLORS - 1);
|
||||
memcpy(interface_colors[i], COLOR_LIST[j], sizeof(color));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
required_string("#End");
|
||||
}
|
||||
|
||||
// Text color tags; for briefings, command briefings, debriefings, and the fiction viewer
|
||||
if (optional_string("#Color Tags")) {
|
||||
while (required_string_either("$Tag:", "#End") < 1) {
|
||||
required_string("$Tag:");
|
||||
color temp_color;
|
||||
char tag;
|
||||
|
||||
for (i = 0; i < MAX_DEFAULT_TEXT_COLORS; i++) {
|
||||
if ( optional_string(color_names[i]) ) {
|
||||
stuff_string(temp, F_RAW);
|
||||
if (temp[0] == '$') {
|
||||
if (temp[1] == '\0') {
|
||||
Error(LOCATION, "%s - default text color '%s' entry with a solitary '$'.\n", filename, color_names[i]);
|
||||
Error(LOCATION, "%s - found a '$Tag:' entry with a solitary '$'.\n", filename);
|
||||
}
|
||||
*color_value[i] = temp[1];
|
||||
tag = temp[1];
|
||||
if (temp[2] != '\0') {
|
||||
Warning(LOCATION, "%s - default text color '%s' has extra text after the tag '$%c'.\n", filename, color_names[i], *color_value[i]);
|
||||
}
|
||||
} else if (temp[0] == '\0') {
|
||||
Error(LOCATION, "%s - default text color '%s' entry with no tag.\n", filename, color_names[i]);
|
||||
} else {
|
||||
*color_value[i] = temp[0];
|
||||
if (temp[1] != '\0') {
|
||||
Warning(LOCATION, "%s - default text color '%s' has extra text after the tag '$%c'.\n", filename, color_names[i], *color_value[i]);
|
||||
Warning(LOCATION, "%s - tag '$%c' has extra text in its definition.\n", filename, tag);
|
||||
}
|
||||
}
|
||||
if (Tagged_Colors.find(*color_value[i]) == Tagged_Colors.end()) {
|
||||
// Just mprintf() this information instead of complaining with a Warning(); the tag might be defined in a later-loading TBM, and if it isn't, nothing too terrible will happen.
|
||||
mprintf(("%s - default text color '%s' set to non-existant tag '$%c'.\n", filename, color_names[i], *color_value[i]));
|
||||
else if (temp[0] == '\0') {
|
||||
Error(LOCATION, "%s - found a '$Tag:' entry with no tag.\n", filename);
|
||||
}
|
||||
else {
|
||||
tag = temp[0];
|
||||
if (temp[1] != '\0') {
|
||||
Warning(LOCATION, "%s - tag '$%c' has extra text in its definition.\n", filename, tag);
|
||||
}
|
||||
}
|
||||
|
||||
if (Tagged_Colors.find(tag) == Tagged_Colors.end()) { // Only push the tag to our list of tags if it's actually new, not just a redefinition.
|
||||
Color_Tags.push_back(tag);
|
||||
}
|
||||
|
||||
switch (required_string_one_of(4, "+Color:", "+Friendly", "+Hostile", "+Neutral")) {
|
||||
case 0: // +Color
|
||||
required_string("+Color:");
|
||||
|
||||
rgba[0] = rgba[1] = rgba[2] = 0;
|
||||
rgba[3] = 255; // Odds are pretty high you want it to have full alpha...
|
||||
|
||||
if (check_for_string("(")) {
|
||||
stuff_int_list(rgba, 4, RAW_INTEGER_TYPE);
|
||||
for (j = 0; j < 4; j++) {
|
||||
if (rgba[j] < 0)
|
||||
{
|
||||
Warning(LOCATION, "RGBA value for '$%c' in %s too low (%d), capping to 0.\n", tag, filename, rgba[j]);
|
||||
rgba[j] = 0;
|
||||
}
|
||||
else if (rgba[j] > 255)
|
||||
{
|
||||
Warning(LOCATION, "RGBA value for '$%c' in %s too high (%d), capping to 255.\n", tag, filename, rgba[j]);
|
||||
rgba[j] = 255;
|
||||
}
|
||||
}
|
||||
gr_init_alphacolor(&temp_color, rgba[0], rgba[1], rgba[2], rgba[3]);
|
||||
Custom_Colors[tag] = temp_color;
|
||||
Tagged_Colors[tag] = &Custom_Colors[tag];
|
||||
//} else if ( check_for_string ("#") ) {
|
||||
// stuff_hex_list(rgba, 4);
|
||||
// gr_init_alphacolor(&temp_color, rgba[0], rgba[1], rgba[2], rgba[3]);
|
||||
// Custom_Colors[tag] = temp_color;
|
||||
// Tagged_Colors[tag] = &Custom_Colors[tag];
|
||||
}
|
||||
else {
|
||||
// We have a string; it should be the name of a color to use.
|
||||
stuff_string(temp, F_NAME);
|
||||
for (j = 0; j < TOTAL_COLORS; j++) {
|
||||
if (!temp.compare(COLOR_NAMES[j])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j == TOTAL_COLORS) {
|
||||
Error(LOCATION, "Unknown color '%s' in %s, for definition of tag '$%c'.\n", temp.c_str(), filename, tag);
|
||||
}
|
||||
Tagged_Colors[tag] = COLOR_LIST[j];
|
||||
}
|
||||
break;
|
||||
case 1: // +Friendly
|
||||
required_string("+Friendly");
|
||||
Tagged_Colors[tag] = &Brief_color_green;
|
||||
break;
|
||||
case 2: // +Hostile
|
||||
required_string("+Hostile");
|
||||
Tagged_Colors[tag] = &Brief_color_red;
|
||||
break;
|
||||
case 3: // +Neutral
|
||||
required_string("+Neutral");
|
||||
Tagged_Colors[tag] = &Brief_color_legacy_neutral;
|
||||
break;
|
||||
case -1:
|
||||
// -noparseerrors is set
|
||||
if (Tagged_Colors.find(tag) == Tagged_Colors.end()) { // It was a new color, but since we haven't actually defined it...
|
||||
Color_Tags.pop_back();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Assertion(false, "MageKing17 made a coding error somewhere, and you should laugh at him (and report this error).\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
required_string("#End");
|
||||
}
|
||||
required_string("#End");
|
||||
Assertion(Color_Tags.size() == Tagged_Colors.size(), "Color_Tags and Tagged_Colors size mismatch; get a coder!\n");
|
||||
|
||||
if (optional_string("#Default Text Colors")) {
|
||||
|
||||
char* color_names[MAX_DEFAULT_TEXT_COLORS] = {
|
||||
"$Fiction Viewer:",
|
||||
"$Command Briefing:",
|
||||
"$Briefing:",
|
||||
"$Redalert Briefing:",
|
||||
"$Debriefing:",
|
||||
"$Recommendation:",
|
||||
"$Loop Briefing:",
|
||||
};
|
||||
|
||||
char *color_value[MAX_DEFAULT_TEXT_COLORS] = {
|
||||
&default_fiction_viewer_color,
|
||||
&default_command_briefing_color,
|
||||
&default_briefing_color,
|
||||
&default_redalert_briefing_color,
|
||||
&default_debriefing_color,
|
||||
&default_recommendation_color,
|
||||
&default_loop_briefing_color,
|
||||
};
|
||||
|
||||
for (i = 0; i < MAX_DEFAULT_TEXT_COLORS; i++) {
|
||||
if (optional_string(color_names[i])) {
|
||||
stuff_string(temp, F_RAW);
|
||||
if (temp[0] == '$') {
|
||||
if (temp[1] == '\0') {
|
||||
Error(LOCATION, "%s - default text color '%s' entry with a solitary '$'.\n", filename, color_names[i]);
|
||||
}
|
||||
*color_value[i] = temp[1];
|
||||
if (temp[2] != '\0') {
|
||||
Warning(LOCATION, "%s - default text color '%s' has extra text after the tag '$%c'.\n", filename, color_names[i], *color_value[i]);
|
||||
}
|
||||
}
|
||||
else if (temp[0] == '\0') {
|
||||
Error(LOCATION, "%s - default text color '%s' entry with no tag.\n", filename, color_names[i]);
|
||||
}
|
||||
else {
|
||||
*color_value[i] = temp[0];
|
||||
if (temp[1] != '\0') {
|
||||
Warning(LOCATION, "%s - default text color '%s' has extra text after the tag '$%c'.\n", filename, color_names[i], *color_value[i]);
|
||||
}
|
||||
}
|
||||
if (Tagged_Colors.find(*color_value[i]) == Tagged_Colors.end()) {
|
||||
// Just mprintf() this information instead of complaining with a Warning(); the tag might be defined in a later-loading TBM, and if it isn't, nothing too terrible will happen.
|
||||
mprintf(("%s - default text color '%s' set to non-existant tag '$%c'.\n", filename, color_names[i], *color_value[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
required_string("#End");
|
||||
}
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", filename, e.what()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,11 @@
|
||||
|
||||
|
||||
// throw
|
||||
#ifdef HAVE_CXX11
|
||||
void * operator new (size_t size)
|
||||
#else
|
||||
void * operator new (size_t size) throw (std::bad_alloc)
|
||||
#endif // CPP11_STD
|
||||
{
|
||||
void *p = vm_malloc_q(size);
|
||||
|
||||
@@ -19,7 +23,11 @@ void operator delete (void *p) throw()
|
||||
vm_free(p);
|
||||
}
|
||||
|
||||
#ifdef HAVE_CXX11
|
||||
void * operator new [] (size_t size)
|
||||
#else
|
||||
void * operator new [] (size_t size) throw (std::bad_alloc)
|
||||
#endif // CPP11_STD
|
||||
{
|
||||
void *p = vm_malloc_q(size);
|
||||
|
||||
|
||||
@@ -4,6 +4,25 @@
|
||||
|
||||
#include <new>
|
||||
|
||||
#ifdef HAVE_CXX11
|
||||
// throw
|
||||
extern void * operator new (size_t size);
|
||||
|
||||
extern void operator delete (void *p) throw();
|
||||
|
||||
extern void * operator new [] (size_t size);
|
||||
|
||||
extern void operator delete [] (void *p) throw();
|
||||
|
||||
// no-throw
|
||||
extern void * operator new (size_t size, const std::nothrow_t&) throw();
|
||||
|
||||
extern void operator delete (void *p, const std::nothrow_t&) throw();
|
||||
|
||||
extern void * operator new [] (size_t size, const std::nothrow_t&) throw();
|
||||
|
||||
extern void operator delete [] (void *p, const std::nothrow_t&) throw();
|
||||
#else
|
||||
// throw
|
||||
extern void * operator new (size_t size) throw (std::bad_alloc);
|
||||
|
||||
@@ -21,5 +40,6 @@ extern void operator delete (void *p, const std::nothrow_t&) throw();
|
||||
extern void * operator new [] (size_t size, const std::nothrow_t&) throw();
|
||||
|
||||
extern void operator delete [] (void *p, const std::nothrow_t&) throw();
|
||||
#endif
|
||||
|
||||
#endif // _FSMEMORY_H
|
||||
@@ -22,6 +22,7 @@
|
||||
#define IAM_64BIT 1
|
||||
#endif
|
||||
|
||||
|
||||
#include "windows_stub/config.h"
|
||||
|
||||
// value to represent an uninitialized state in any int or uint
|
||||
@@ -680,5 +681,113 @@ public:
|
||||
#include "globalincs/vmallocator.h"
|
||||
#include "globalincs/safe_strings.h"
|
||||
|
||||
// c++11 standard detection
|
||||
// for GCC with autotools, see AX_CXX_COMPILE_STDCXX_11 macro in configure.ac
|
||||
// this sets HAVE_CXX11 & -std=c++0x or -std=c++11 appropriately
|
||||
|
||||
// Use the visual studio version to detect C++11 support
|
||||
#if _MSC_VER >= 1600
|
||||
# define HAVE_CXX11
|
||||
#endif
|
||||
// clang doesn't seem to have a feature check for is_trivial
|
||||
// oh well, assume it'll be covered by one of the other two checks...
|
||||
// http://clang.llvm.org/docs/LanguageExtensions.html#feature_check
|
||||
#if defined(__clang__)
|
||||
#if __has_feature(cxx_static_assert)
|
||||
#if __has_feature(cxx_auto_type)
|
||||
#define HAVE_CXX11
|
||||
#endif // __has_feature(cxx_auto_type)
|
||||
#endif // __has_feature(cxx_static_assert)
|
||||
#endif // defined(__clang__)
|
||||
// TODO: sort out cmake/gcc
|
||||
|
||||
// DEBUG compile time catch for dangerous uses of memset/memcpy/memmove
|
||||
// would prefer std::is_trivially_copyable but it's not supported by gcc yet
|
||||
// ref: http://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html
|
||||
#ifndef NDEBUG
|
||||
#if defined(HAVE_CXX11)
|
||||
// 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)
|
||||
// static_assert 4.3 2.9 2010
|
||||
#include <type_traits>
|
||||
#include <cstring>
|
||||
|
||||
// MEMSET!
|
||||
const auto ptr_memset = std::memset;
|
||||
#define memset memset_if_trivial_else_error
|
||||
|
||||
template<typename T>
|
||||
void *memset_if_trivial_else_error(T *memset_data, int ch, size_t count)
|
||||
{
|
||||
static_assert(std::is_trivial<T>::value, "memset on non-trivial object");
|
||||
return ptr_memset(memset_data, ch, count);
|
||||
}
|
||||
|
||||
// assume memset on a void* is "safe"
|
||||
// only used in cutscene/mveplayer.cpp:mve_video_createbuf()
|
||||
inline void *memset_if_trivial_else_error(void *memset_data, int ch, size_t count)
|
||||
{
|
||||
return ptr_memset(memset_data, ch, count);
|
||||
}
|
||||
|
||||
// MEMCPY!
|
||||
const auto ptr_memcpy = std::memcpy;
|
||||
#define memcpy memcpy_if_trivial_else_error
|
||||
|
||||
template<typename T, typename U>
|
||||
void *memcpy_if_trivial_else_error(T *memcpy_dest, U *src, size_t count)
|
||||
{
|
||||
static_assert(std::is_trivial<T>::value, "memcpy on non-trivial object T");
|
||||
static_assert(std::is_trivial<U>::value, "memcpy on non-trivial object U");
|
||||
return ptr_memcpy(memcpy_dest, src, count);
|
||||
}
|
||||
|
||||
// assume memcpy with void* is "safe"
|
||||
// used in:
|
||||
// globalincs/systemvars.cpp:insertion_sort()
|
||||
// network/chat_api.cpp:AddChatCommandToQueue()
|
||||
// network/multi_obj.cpp:multi_oo_sort_func()
|
||||
// parse/lua.cpp:ade_get_args() && ade_set_args()
|
||||
//
|
||||
// probably should setup a static_assert on insertion_sort as well
|
||||
template<typename U>
|
||||
void *memcpy_if_trivial_else_error(void *memcpy_dest, U *memcpy_src, size_t count)
|
||||
{
|
||||
static_assert(std::is_trivial<U>::value, "memcpy on non-trivial object U");
|
||||
return ptr_memcpy(memcpy_dest, memcpy_src, count);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void *memcpy_if_trivial_else_error(T *memcpy_dest, void *memcpy_src, size_t count)
|
||||
{
|
||||
static_assert(std::is_trivial<T>::value, "memcpy on non-trivial object T");
|
||||
return ptr_memcpy(memcpy_dest, memcpy_src, count);
|
||||
}
|
||||
template<typename T>
|
||||
void *memcpy_if_trivial_else_error(T *memcpy_dest, const void *memcpy_src, size_t count)
|
||||
{
|
||||
static_assert(std::is_trivial<T>::value, "memcpy on non-trivial object T");
|
||||
return ptr_memcpy(memcpy_dest, memcpy_src, count);
|
||||
}
|
||||
|
||||
inline void *memcpy_if_trivial_else_error(void *memcpy_dest, void *memcpy_src, size_t count)
|
||||
{
|
||||
return ptr_memcpy(memcpy_dest, memcpy_src, count);
|
||||
}
|
||||
|
||||
// MEMMOVE!
|
||||
const auto ptr_memmove = std::memmove;
|
||||
#define memmove memmove_if_trivial_else_error
|
||||
|
||||
template<typename T, typename U>
|
||||
void *memmove_if_trivial_else_error(T *memmove_dest, U *memmove_src, size_t count)
|
||||
{
|
||||
static_assert(std::is_trivial<T>::value, "memmove on non-trivial object T");
|
||||
static_assert(std::is_trivial<U>::value, "memmove on non-trivial object U");
|
||||
return ptr_memmove(memmove_dest, memmove_src, count);
|
||||
}
|
||||
#endif // HAVE_CXX11
|
||||
#endif // NDEBUG
|
||||
|
||||
#endif // PS_TYPES_H
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
#define FS_VERSION_MAJOR 3 // major version
|
||||
#define FS_VERSION_MINOR 7 // increase by 1 for minor revs
|
||||
#define FS_VERSION_BUILD 1 // bugfix release
|
||||
#define FS_VERSION_BUILD 3 // bugfix release
|
||||
#define FS_VERSION_REVIS 000000 // SVN revision
|
||||
//#define FS_VERSION_IDENT NOX("custom") // special build release identifier, must be a string (don't define unless it's supposed to be used!!)
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "io/keycontrol.h" // m!m
|
||||
#include "debugconsole/console.h"
|
||||
#include "debugconsole/console.h"
|
||||
#include "popup/popup.h"
|
||||
|
||||
|
||||
#if defined(SCP_UNIX) && !defined(__APPLE__)
|
||||
@@ -83,7 +84,7 @@ int gr_alpha_test = 0;
|
||||
|
||||
// Default clipping distances
|
||||
const float Default_min_draw_distance = 1.0f;
|
||||
const float Default_max_draw_distance = 1e10;
|
||||
const float Default_max_draw_distance = 10000000.0f;
|
||||
float Min_draw_distance = Default_min_draw_distance;
|
||||
float Max_draw_distance = Default_max_draw_distance;
|
||||
|
||||
@@ -1771,7 +1772,7 @@ void gr_set_bitmap(int bitmap_num, int alphablend_mode, int bitblt_mode, float a
|
||||
void gr_flip()
|
||||
{
|
||||
// m!m avoid running CHA_ONFRAME when the "Quit mission" popup is shown. See mantis 2446 for reference
|
||||
if (!quit_mission_popup_shown)
|
||||
if (!quit_mission_popup_shown && !popup_active())
|
||||
{
|
||||
//WMC - Evaluate global hook if not override.
|
||||
Script_system.RunBytecode(Script_globalhook);
|
||||
|
||||
+97
-92
@@ -579,7 +579,7 @@ void gr_set_font(int fontnum)
|
||||
|
||||
void parse_fonts_tbl(char *only_parse_first_font, size_t only_parse_first_font_size)
|
||||
{
|
||||
int rval, i;
|
||||
int i;
|
||||
char *filename;
|
||||
|
||||
// choose file name
|
||||
@@ -591,99 +591,104 @@ void parse_fonts_tbl(char *only_parse_first_font, size_t only_parse_first_font_s
|
||||
filename = NULL;
|
||||
}
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", (filename) ? filename : NOX("<default fonts.tbl>"), rval));
|
||||
try
|
||||
{
|
||||
if (filename != NULL) {
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
}
|
||||
else {
|
||||
read_file_text_from_array(defaults_get_file("fonts.tbl"));
|
||||
}
|
||||
|
||||
reset_parse();
|
||||
|
||||
// start parsing
|
||||
required_string("#Fonts");
|
||||
|
||||
// read fonts
|
||||
while (required_string_either("#End", "$Font:")) {
|
||||
char font_filename[MAX_FILENAME_LEN];
|
||||
|
||||
// grab font
|
||||
required_string("$Font:");
|
||||
stuff_string(font_filename, F_NAME, MAX_FILENAME_LEN);
|
||||
|
||||
// if we only need the first font, copy it and bail
|
||||
if (only_parse_first_font != NULL) {
|
||||
strcpy_s(only_parse_first_font, only_parse_first_font_size, font_filename);
|
||||
return;
|
||||
}
|
||||
|
||||
// create font
|
||||
int font_id = gr_create_font(font_filename);
|
||||
if (font_id < 0) {
|
||||
Warning(LOCATION, "Could not create font from typeface '%s'!", font_filename);
|
||||
skip_to_start_of_string_either("#End", "$Font:");
|
||||
}
|
||||
else {
|
||||
// max allowed special char index; i.e. 7 special chars in retail fonts 1 & 3
|
||||
static const int MAX_SPECIAL_CHAR_IDX = UCHAR_MAX - 6;
|
||||
|
||||
// 'default' special char index for all languages using this font
|
||||
int default_special_char_index = 0;
|
||||
if (optional_string("+Default Special Character Index:")) {
|
||||
stuff_int(&default_special_char_index);
|
||||
|
||||
if (default_special_char_index < 0 || default_special_char_index >= MAX_SPECIAL_CHAR_IDX) {
|
||||
Error(LOCATION, "Default special character index (%d) for font (%s), must be 0 - %u", default_special_char_index, font_filename, MAX_SPECIAL_CHAR_IDX);
|
||||
}
|
||||
|
||||
for (i = 0; i < (int)Lcl_languages.size(); ++i) {
|
||||
Lcl_languages[i].special_char_indexes[font_id] = (ubyte)default_special_char_index;
|
||||
}
|
||||
}
|
||||
|
||||
while (optional_string("+Language:")) {
|
||||
char lang_name[LCL_LANG_NAME_LEN + 1];
|
||||
int special_char_index, lang_idx = -1;
|
||||
|
||||
stuff_string(lang_name, F_NAME, LCL_LANG_NAME_LEN + 1);
|
||||
|
||||
// find language and set the index, or if not found move to the next one
|
||||
for (i = 0; i < (int)Lcl_languages.size(); ++i) {
|
||||
if (!strcmp(Lcl_languages[i].lang_name, lang_name)) {
|
||||
lang_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lang_idx == -1) {
|
||||
Warning(LOCATION, "Ignoring invalid language (%s) specified by font (%s); not built-in or in strings.tbl", lang_name, font_filename);
|
||||
skip_to_start_of_string_either("+Language:", "$Font:", "#End");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (optional_string("+Special Character Index:")) {
|
||||
stuff_int(&special_char_index);
|
||||
|
||||
if (special_char_index < 0 || special_char_index >= MAX_SPECIAL_CHAR_IDX) {
|
||||
Error(LOCATION, "Special character index (%d) for font (%s), language (%s) is invalid, must be 0 - %u", special_char_index, font_filename, lang_name, MAX_SPECIAL_CHAR_IDX);
|
||||
}
|
||||
|
||||
Lcl_languages[lang_idx].special_char_indexes[font_id] = (ubyte)special_char_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// done parsing
|
||||
required_string("#End");
|
||||
|
||||
// double check
|
||||
if (Num_fonts < 3) {
|
||||
Error(LOCATION, "There must be at least three fonts in %s!", (filename) ? filename : NOX("<default fonts.tbl>"));
|
||||
}
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", (filename) ? filename : NOX("<default fonts.tbl>"), e.what()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (filename != NULL) {
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
} else {
|
||||
read_file_text_from_array(defaults_get_file("fonts.tbl"));
|
||||
}
|
||||
|
||||
reset_parse();
|
||||
|
||||
// start parsing
|
||||
required_string("#Fonts");
|
||||
|
||||
// read fonts
|
||||
while (required_string_either("#End","$Font:")) {
|
||||
char font_filename[MAX_FILENAME_LEN];
|
||||
|
||||
// grab font
|
||||
required_string("$Font:");
|
||||
stuff_string(font_filename, F_NAME, MAX_FILENAME_LEN);
|
||||
|
||||
// if we only need the first font, copy it and bail
|
||||
if (only_parse_first_font != NULL) {
|
||||
strcpy_s(only_parse_first_font, only_parse_first_font_size, font_filename);
|
||||
return;
|
||||
}
|
||||
|
||||
// create font
|
||||
int font_id = gr_create_font(font_filename);
|
||||
if (font_id < 0) {
|
||||
Warning(LOCATION, "Could not create font from typeface '%s'!", font_filename);
|
||||
skip_to_start_of_string_either("#End","$Font:");
|
||||
} else {
|
||||
// max allowed special char index; i.e. 7 special chars in retail fonts 1 & 3
|
||||
static const int MAX_SPECIAL_CHAR_IDX = UCHAR_MAX-6;
|
||||
|
||||
// 'default' special char index for all languages using this font
|
||||
int default_special_char_index = 0;
|
||||
if (optional_string("+Default Special Character Index:")) {
|
||||
stuff_int(&default_special_char_index);
|
||||
|
||||
if (default_special_char_index < 0 || default_special_char_index >= MAX_SPECIAL_CHAR_IDX) {
|
||||
Error(LOCATION, "Default special character index (%d) for font (%s), must be 0 - %u", default_special_char_index, font_filename, MAX_SPECIAL_CHAR_IDX);
|
||||
}
|
||||
|
||||
for (i = 0; i < (int)Lcl_languages.size(); ++i) {
|
||||
Lcl_languages[i].special_char_indexes[font_id] = (ubyte)default_special_char_index;
|
||||
}
|
||||
}
|
||||
|
||||
while (optional_string("+Language:")) {
|
||||
char lang_name[LCL_LANG_NAME_LEN + 1];
|
||||
int special_char_index, lang_idx = -1;
|
||||
|
||||
stuff_string(lang_name, F_NAME, LCL_LANG_NAME_LEN + 1);
|
||||
|
||||
// find language and set the index, or if not found move to the next one
|
||||
for (i = 0; i < (int)Lcl_languages.size(); ++i) {
|
||||
if (!strcmp(Lcl_languages[i].lang_name, lang_name)) {
|
||||
lang_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lang_idx == -1) {
|
||||
Warning(LOCATION, "Ignoring invalid language (%s) specified by font (%s); not built-in or in strings.tbl", lang_name, font_filename );
|
||||
skip_to_start_of_string_either("+Language:","$Font:","#End");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (optional_string("+Special Character Index:")) {
|
||||
stuff_int(&special_char_index);
|
||||
|
||||
if (special_char_index < 0 || special_char_index >= MAX_SPECIAL_CHAR_IDX) {
|
||||
Error(LOCATION, "Special character index (%d) for font (%s), language (%s) is invalid, must be 0 - %u", special_char_index, font_filename, lang_name, MAX_SPECIAL_CHAR_IDX);
|
||||
}
|
||||
|
||||
Lcl_languages[lang_idx].special_char_indexes[font_id] = (ubyte)special_char_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// done parsing
|
||||
required_string("#End");
|
||||
|
||||
// double check
|
||||
if (Num_fonts < 3) {
|
||||
Error(LOCATION, "There must be at least three fonts in %s!", (filename) ? filename : NOX("<default fonts.tbl>"));
|
||||
}
|
||||
}
|
||||
|
||||
void gr_stuff_first_font(char *first_font, size_t first_font_size )
|
||||
|
||||
@@ -20,6 +20,17 @@
|
||||
//we check background type to avoid messed up colours for ANI
|
||||
#define ANI_BPP_CHECK (ga->ani.bg_type == BM_TYPE_PCX) ? 16 : 32
|
||||
|
||||
// These two functions find if a bitmap or animation exists by filename, no extension needed.
|
||||
bool generic_bitmap_exists(const char *filename)
|
||||
{
|
||||
return cf_exists_full_ext(filename, CF_TYPE_ANY, BM_NUM_TYPES, bm_ext_list);
|
||||
}
|
||||
|
||||
bool generic_anim_exists(const char *filename)
|
||||
{
|
||||
return cf_exists_full_ext(filename, CF_TYPE_ANY, BM_ANI_NUM_TYPES, bm_ani_ext_list);
|
||||
}
|
||||
|
||||
// Goober5000
|
||||
int generic_anim_init_and_stream(generic_anim *anim, const char *anim_filename, ubyte bg_type, bool attempt_hi_res)
|
||||
{
|
||||
@@ -209,13 +220,19 @@ int generic_anim_stream(generic_anim *ga)
|
||||
ga->previous_frame = -1;
|
||||
}
|
||||
else {
|
||||
bool in_subdir;
|
||||
bpp = 32;
|
||||
if(ga->use_hud_color)
|
||||
bpp = 8;
|
||||
bm_load_and_parse_eff(ga->filename, CF_TYPE_ANY, &ga->num_frames, &anim_fps, &ga->keyframe, 0);
|
||||
bm_load_and_parse_eff(ga->filename, CF_TYPE_ANY, &ga->num_frames, &anim_fps, &ga->keyframe, 0, &in_subdir);
|
||||
char *p = strrchr( ga->filename, '.' );
|
||||
if ( p )
|
||||
*p = 0;
|
||||
|
||||
if (in_subdir) {
|
||||
set_temp_subdir_pathtype(ga->filename);
|
||||
}
|
||||
|
||||
char frame_name[32];
|
||||
snprintf(frame_name, 32, "%s_0000", ga->filename);
|
||||
ga->bitmap_id = bm_load(frame_name);
|
||||
|
||||
@@ -52,6 +52,8 @@ typedef struct generic_bitmap {
|
||||
int bitmap_id;
|
||||
} generic_bitmap;
|
||||
|
||||
bool generic_bitmap_exists(const char *filename);
|
||||
bool generic_anim_exists(const char *filename);
|
||||
int generic_anim_init_and_stream(generic_anim *anim, const char *anim_filename, ubyte bg_type, bool attempt_hi_res);
|
||||
void generic_anim_init(generic_anim *ga);
|
||||
void generic_anim_init(generic_anim *ga, const char *filename);
|
||||
|
||||
@@ -687,115 +687,118 @@ void gr_opengl_post_process_save_zbuffer()
|
||||
|
||||
static bool opengl_post_init_table()
|
||||
{
|
||||
int rval;
|
||||
bool warned = false;
|
||||
|
||||
if ( (rval = setjmp(parse_abort)) != 0 ) {
|
||||
mprintf(("Unable to parse 'post_processing.tbl'! Error code = %d.\n", rval));
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
if (cf_exists_full("post_processing.tbl", CF_TYPE_TABLES))
|
||||
read_file_text("post_processing.tbl", CF_TYPE_TABLES);
|
||||
else
|
||||
read_file_text_from_array(defaults_get_file("post_processing.tbl"));
|
||||
|
||||
if (cf_exists_full("post_processing.tbl", CF_TYPE_TABLES))
|
||||
read_file_text("post_processing.tbl", CF_TYPE_TABLES);
|
||||
else
|
||||
read_file_text_from_array(defaults_get_file("post_processing.tbl"));
|
||||
|
||||
reset_parse();
|
||||
reset_parse();
|
||||
|
||||
|
||||
if (optional_string("#Effects")) {
|
||||
while ( !required_string_3("$Name:", "#Ship Effects", "#End") ) {
|
||||
char tbuf[NAME_LENGTH+1] = { 0 };
|
||||
post_effect_t eff;
|
||||
if (optional_string("#Effects")) {
|
||||
while (!required_string_one_of(3, "$Name:", "#Ship Effects", "#End")) {
|
||||
char tbuf[NAME_LENGTH + 1] = { 0 };
|
||||
post_effect_t eff;
|
||||
|
||||
required_string("$Name:");
|
||||
stuff_string(tbuf, F_NAME, NAME_LENGTH);
|
||||
eff.name = tbuf;
|
||||
required_string("$Name:");
|
||||
stuff_string(tbuf, F_NAME, NAME_LENGTH);
|
||||
eff.name = tbuf;
|
||||
|
||||
required_string("$Uniform:");
|
||||
stuff_string(tbuf, F_NAME, NAME_LENGTH);
|
||||
eff.uniform_name = tbuf;
|
||||
required_string("$Uniform:");
|
||||
stuff_string(tbuf, F_NAME, NAME_LENGTH);
|
||||
eff.uniform_name = tbuf;
|
||||
|
||||
required_string("$Define:");
|
||||
stuff_string(tbuf, F_NAME, NAME_LENGTH);
|
||||
eff.define_name = tbuf;
|
||||
required_string("$Define:");
|
||||
stuff_string(tbuf, F_NAME, NAME_LENGTH);
|
||||
eff.define_name = tbuf;
|
||||
|
||||
required_string("$AlwaysOn:");
|
||||
stuff_boolean(&eff.always_on);
|
||||
required_string("$AlwaysOn:");
|
||||
stuff_boolean(&eff.always_on);
|
||||
|
||||
required_string("$Default:");
|
||||
stuff_float(&eff.default_intensity);
|
||||
eff.intensity = eff.default_intensity;
|
||||
required_string("$Default:");
|
||||
stuff_float(&eff.default_intensity);
|
||||
eff.intensity = eff.default_intensity;
|
||||
|
||||
required_string("$Div:");
|
||||
stuff_float(&eff.div);
|
||||
required_string("$Div:");
|
||||
stuff_float(&eff.div);
|
||||
|
||||
required_string("$Add:");
|
||||
stuff_float(&eff.add);
|
||||
required_string("$Add:");
|
||||
stuff_float(&eff.add);
|
||||
|
||||
// Post_effects index is used for flag checks, so we can't have more than 32
|
||||
if (Post_effects.size() < 32) {
|
||||
Post_effects.push_back( eff );
|
||||
} else if ( !warned ) {
|
||||
mprintf(("WARNING: post_processing.tbl can only have a max of 32 effects! Ignoring extra...\n"));
|
||||
warned = true;
|
||||
// Post_effects index is used for flag checks, so we can't have more than 32
|
||||
if (Post_effects.size() < 32) {
|
||||
Post_effects.push_back(eff);
|
||||
}
|
||||
else if (!warned) {
|
||||
mprintf(("WARNING: post_processing.tbl can only have a max of 32 effects! Ignoring extra...\n"));
|
||||
warned = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Built-in per-ship effects
|
||||
ship_effect se1;
|
||||
strcpy_s(se1.name, "FS1 Ship select");
|
||||
se1.shader_effect = 0;
|
||||
se1.disables_rendering = false;
|
||||
se1.invert_timer = false;
|
||||
Ship_effects.push_back(se1);
|
||||
//Built-in per-ship effects
|
||||
ship_effect se1;
|
||||
strcpy_s(se1.name, "FS1 Ship select");
|
||||
se1.shader_effect = 0;
|
||||
se1.disables_rendering = false;
|
||||
se1.invert_timer = false;
|
||||
Ship_effects.push_back(se1);
|
||||
|
||||
if (optional_string("#Ship Effects")) {
|
||||
while ( !required_string_3("$Name:", "#Light Shafts", "#End") ) {
|
||||
ship_effect se;
|
||||
char tbuf[NAME_LENGTH] = { 0 };
|
||||
if (optional_string("#Ship Effects")) {
|
||||
while (!required_string_one_of(3, "$Name:", "#Light Shafts", "#End")) {
|
||||
ship_effect se;
|
||||
char tbuf[NAME_LENGTH] = { 0 };
|
||||
|
||||
required_string("$Name:");
|
||||
stuff_string(tbuf, F_NAME, NAME_LENGTH);
|
||||
strcpy_s(se.name, tbuf);
|
||||
required_string("$Name:");
|
||||
stuff_string(tbuf, F_NAME, NAME_LENGTH);
|
||||
strcpy_s(se.name, tbuf);
|
||||
|
||||
required_string("$Shader Effect:");
|
||||
stuff_int(&se.shader_effect);
|
||||
required_string("$Shader Effect:");
|
||||
stuff_int(&se.shader_effect);
|
||||
|
||||
required_string("$Disables Rendering:");
|
||||
stuff_boolean(&se.disables_rendering);
|
||||
required_string("$Disables Rendering:");
|
||||
stuff_boolean(&se.disables_rendering);
|
||||
|
||||
required_string("$Invert timer:");
|
||||
stuff_boolean(&se.invert_timer);
|
||||
required_string("$Invert timer:");
|
||||
stuff_boolean(&se.invert_timer);
|
||||
|
||||
Ship_effects.push_back(se);
|
||||
Ship_effects.push_back(se);
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("#Light Shafts")) {
|
||||
required_string("$AlwaysOn:");
|
||||
stuff_boolean(&ls_on);
|
||||
required_string("$Density:");
|
||||
stuff_float(&ls_density);
|
||||
required_string("$Falloff:");
|
||||
stuff_float(&ls_falloff);
|
||||
required_string("$Weight:");
|
||||
stuff_float(&ls_weight);
|
||||
required_string("$Intensity:");
|
||||
stuff_float(&ls_intensity);
|
||||
required_string("$Sample Number:");
|
||||
stuff_int(&ls_samplenum);
|
||||
|
||||
ls_cpintensity = ls_weight;
|
||||
for (int i = 1; i < ls_samplenum; i++)
|
||||
ls_cpintensity += ls_weight * pow(ls_falloff, i);
|
||||
ls_cpintensity *= ls_intensity;
|
||||
}
|
||||
|
||||
required_string("#End");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (optional_string("#Light Shafts")) {
|
||||
required_string("$AlwaysOn:");
|
||||
stuff_boolean(&ls_on);
|
||||
required_string("$Density:");
|
||||
stuff_float(&ls_density);
|
||||
required_string("$Falloff:");
|
||||
stuff_float(&ls_falloff);
|
||||
required_string("$Weight:");
|
||||
stuff_float(&ls_weight);
|
||||
required_string("$Intensity:");
|
||||
stuff_float(&ls_intensity);
|
||||
required_string("$Sample Number:");
|
||||
stuff_int(&ls_samplenum);
|
||||
|
||||
ls_cpintensity = ls_weight;
|
||||
for(int i = 1; i < ls_samplenum; i++)
|
||||
ls_cpintensity += ls_weight * pow(ls_falloff, i);
|
||||
ls_cpintensity *= ls_intensity;
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("Unable to parse 'post_processing.tbl'! Error message = %s.\n", e.what()));
|
||||
return false;
|
||||
}
|
||||
|
||||
required_string("#End");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static char *opengl_post_load_shader(char *filename, int flags, int flags2)
|
||||
|
||||
@@ -192,6 +192,10 @@ int gr_opengl_create_stream_buffer()
|
||||
{
|
||||
opengl_vertex_buffer buffer;
|
||||
|
||||
if ( !Use_VBOs ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
vglGenBuffersARB(1, &buffer.vbo);
|
||||
|
||||
GL_vertex_buffers.push_back(buffer);
|
||||
|
||||
+1
-54
@@ -151,49 +151,6 @@ int Supernova_coords[GR_NUM_RESOLUTIONS][2] = {
|
||||
}
|
||||
};
|
||||
|
||||
// used to draw the kills gauge
|
||||
hud_frames Kills_gauge;
|
||||
int Kills_gauge_loaded = 0;
|
||||
int Kills_gauge_coords[GR_NUM_RESOLUTIONS][2] = {
|
||||
{ // GR_640
|
||||
497, 361
|
||||
},
|
||||
{ // GR_1024
|
||||
880, 624
|
||||
}
|
||||
};
|
||||
int Kills_text_coords[GR_NUM_RESOLUTIONS][2] = {
|
||||
{ // GR_640
|
||||
503, 365
|
||||
},
|
||||
{ // GR_1024
|
||||
886, 628
|
||||
}
|
||||
};
|
||||
|
||||
int Kills_text_val_coords_gr[GR_NUM_RESOLUTIONS][2] = {
|
||||
{ // GR_640
|
||||
615, 365
|
||||
},
|
||||
{ // GR_1024
|
||||
984, 628
|
||||
}
|
||||
};
|
||||
|
||||
int Kills_text_val_coords[GR_NUM_RESOLUTIONS][2] = {
|
||||
{ // GR_640
|
||||
571, 365
|
||||
},
|
||||
{ // GR_1024
|
||||
954, 628
|
||||
}
|
||||
};
|
||||
|
||||
char Kills_fname[GR_NUM_RESOLUTIONS][MAX_FILENAME_LEN] = {
|
||||
"kills1",
|
||||
"kills1"
|
||||
};
|
||||
|
||||
// used to draw the hud support view
|
||||
static int Hud_support_view_active;
|
||||
static int Hud_support_view_abort; // active when we need to display abort message
|
||||
@@ -237,7 +194,6 @@ int hud_subspace_notify_active();
|
||||
int hud_objective_notify_active();
|
||||
void hud_subspace_notify_abort();
|
||||
void hud_maybe_display_subspace_notify();
|
||||
void hud_init_kills_gauge();
|
||||
int hud_maybe_render_emp_icon();
|
||||
void hud_init_emp_icon();
|
||||
|
||||
@@ -1134,7 +1090,7 @@ bool HudGauge::canRender()
|
||||
}
|
||||
|
||||
if (gauge_config == HUD_ETS_GAUGE) {
|
||||
if (Ships[Player_obj->instance].flags2 & SF2_NO_ETS) {
|
||||
if (Ships[Player_obj->instance].flags2 & SF2_NO_ETS && !Show_disabled_ets_gauges) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1223,7 +1179,6 @@ void HUD_init()
|
||||
hud_init_wingman_status_gauge();
|
||||
hud_init_target_static();
|
||||
hud_init_text_flash_gauge();
|
||||
hud_init_kills_gauge();
|
||||
hud_stop_subspace_notify();
|
||||
hud_stop_objective_notify();
|
||||
hud_target_last_transmit_level_init();
|
||||
@@ -2571,14 +2526,6 @@ void HudGaugeLag::render(float frametime)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Obsolete initializer for the kills gauge. Now superseded by the new HUD code.
|
||||
*/
|
||||
void hud_init_kills_gauge()
|
||||
{
|
||||
Kills_gauge_loaded = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called at mission start to init data, and load support view bitmap if required
|
||||
*/
|
||||
|
||||
+59
-56
@@ -62,72 +62,75 @@ int ssm_info_lookup(char *name)
|
||||
// game init
|
||||
void ssm_init()
|
||||
{
|
||||
int rval;
|
||||
ssm_info bogus, *s;
|
||||
char weapon_name[NAME_LENGTH];
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", "ssm.tbl", rval));
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
read_file_text("ssm.tbl", CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
read_file_text("ssm.tbl", CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
// parse the table
|
||||
Ssm_info_count = 0;
|
||||
while (!optional_string("#end")){
|
||||
// another ssm definition
|
||||
if (optional_string("$SSM:")){
|
||||
// pointer to info struct
|
||||
if (Ssm_info_count >= MAX_SSM_TYPES){
|
||||
s = &bogus;
|
||||
}
|
||||
else {
|
||||
s = &Ssm_info[Ssm_info_count];
|
||||
}
|
||||
|
||||
// parse the table
|
||||
Ssm_info_count = 0;
|
||||
while(!optional_string("#end")){
|
||||
// another ssm definition
|
||||
if(optional_string("$SSM:")){
|
||||
// pointer to info struct
|
||||
if(Ssm_info_count >= MAX_SSM_TYPES){
|
||||
s = &bogus;
|
||||
} else {
|
||||
s = &Ssm_info[Ssm_info_count];
|
||||
}
|
||||
// name
|
||||
stuff_string(s->name, F_NAME, NAME_LENGTH);
|
||||
|
||||
// name
|
||||
stuff_string(s->name, F_NAME, NAME_LENGTH);
|
||||
// stuff data
|
||||
required_string("+Weapon:");
|
||||
stuff_string(weapon_name, F_NAME, NAME_LENGTH);
|
||||
required_string("+Count:");
|
||||
stuff_int(&s->count);
|
||||
required_string("+WarpRadius:");
|
||||
stuff_float(&s->warp_radius);
|
||||
required_string("+WarpTime:");
|
||||
stuff_float(&s->warp_time);
|
||||
// According to fireballs.cpp, "Warp lifetime must be at least 4 seconds!"
|
||||
if ((s->warp_time) < 4.0f) {
|
||||
// So let's warn them before they try to use it, shall we?
|
||||
Warning(LOCATION, "Expected a '+WarpTime:' value equal or greater than 4.0, found '%f' in weapon '%s'.\n Setting to 4.0, please check and set to a number 4.0 or greater!\n", s->warp_time, weapon_name);
|
||||
// And then make the Assert obsolete -- Zacam
|
||||
s->warp_time = 4.0f;
|
||||
}
|
||||
required_string("+Radius:");
|
||||
stuff_float(&s->radius);
|
||||
required_string("+Offset:");
|
||||
stuff_float(&s->offset);
|
||||
if (optional_string("+HUD Message:"))
|
||||
stuff_boolean(&s->send_message);
|
||||
else
|
||||
s->send_message = true;
|
||||
if (optional_string("+Custom Message:")) {
|
||||
stuff_string(s->message, F_NAME, NAME_LENGTH);
|
||||
s->use_custom_message = true;
|
||||
}
|
||||
parse_sound("+Alarm Sound:", &s->sound_index, s->name);
|
||||
|
||||
// stuff data
|
||||
required_string("+Weapon:");
|
||||
stuff_string(weapon_name, F_NAME, NAME_LENGTH);
|
||||
required_string("+Count:");
|
||||
stuff_int(&s->count);
|
||||
required_string("+WarpRadius:");
|
||||
stuff_float(&s->warp_radius);
|
||||
required_string("+WarpTime:");
|
||||
stuff_float(&s->warp_time);
|
||||
// According to fireballs.cpp, "Warp lifetime must be at least 4 seconds!"
|
||||
if ( (s->warp_time) < 4.0f) {
|
||||
// So let's warn them before they try to use it, shall we?
|
||||
Warning(LOCATION, "Expected a '+WarpTime:' value equal or greater than 4.0, found '%f' in weapon '%s'.\n Setting to 4.0, please check and set to a number 4.0 or greater!\n", s->warp_time, weapon_name);
|
||||
// And then make the Assert obsolete -- Zacam
|
||||
s->warp_time = 4.0f;
|
||||
}
|
||||
required_string("+Radius:");
|
||||
stuff_float(&s->radius);
|
||||
required_string("+Offset:");
|
||||
stuff_float(&s->offset);
|
||||
if (optional_string("+HUD Message:"))
|
||||
stuff_boolean(&s->send_message);
|
||||
else
|
||||
s->send_message = true;
|
||||
if (optional_string("+Custom Message:")) {
|
||||
stuff_string(s->message, F_NAME, NAME_LENGTH);
|
||||
s->use_custom_message = true;
|
||||
}
|
||||
parse_sound("+Alarm Sound:", &s->sound_index, s->name);
|
||||
|
||||
// see if we have a valid weapon
|
||||
s->weapon_info_index = -1;
|
||||
s->weapon_info_index = weapon_info_lookup(weapon_name);
|
||||
if(s->weapon_info_index >= 0){
|
||||
// valid
|
||||
Ssm_info_count++;
|
||||
// see if we have a valid weapon
|
||||
s->weapon_info_index = -1;
|
||||
s->weapon_info_index = weapon_info_lookup(weapon_name);
|
||||
if (s->weapon_info_index >= 0){
|
||||
// valid
|
||||
Ssm_info_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "ssm.tbl", e.what()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ssm_get_random_start_pos(vec3d *out, vec3d *start, matrix *orient, int ssm_index)
|
||||
|
||||
+26
-23
@@ -1641,40 +1641,43 @@ void hud_config_color_save(char *name)
|
||||
|
||||
void hud_config_color_load(char *name)
|
||||
{
|
||||
int idx, rval;
|
||||
int idx;
|
||||
char str[1024];
|
||||
char *fname;
|
||||
|
||||
fname = cf_add_ext(name, ".hcf");
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("HUDCONFIG: Unable to parse '%s'! Error code = %i.\n", fname, rval));
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
read_file_text(fname);
|
||||
reset_parse();
|
||||
|
||||
read_file_text(fname);
|
||||
reset_parse();
|
||||
// First, set all gauges to the current main color
|
||||
for (idx = 0; idx < NUM_HUD_GAUGES; idx++){
|
||||
gr_init_alphacolor(&HUD_config.clr[idx], HUD_color_red, HUD_color_green, HUD_color_blue, (HUD_color_alpha + 1) * 16);
|
||||
}
|
||||
|
||||
// First, set all gauges to the current main color
|
||||
for (idx=0; idx<NUM_HUD_GAUGES; idx++){
|
||||
gr_init_alphacolor(&HUD_config.clr[idx], HUD_color_red, HUD_color_green, HUD_color_blue, (HUD_color_alpha+1)*16);
|
||||
}
|
||||
// Now read in the color values for the gauges
|
||||
while (optional_string("+Gauge:")) {
|
||||
stuff_string(str, F_NAME, sizeof(str));
|
||||
|
||||
// Now read in the color values for the gauges
|
||||
while (optional_string("+Gauge:")) {
|
||||
stuff_string(str, F_NAME, sizeof(str));
|
||||
|
||||
for (idx=0; idx<NUM_HUD_GAUGES; idx++) {
|
||||
if (!stricmp(str, Hud_Gauge_Names[idx])) {
|
||||
required_string("+RGBA:");
|
||||
stuff_ubyte(&HUD_config.clr[idx].red);
|
||||
stuff_ubyte(&HUD_config.clr[idx].green);
|
||||
stuff_ubyte(&HUD_config.clr[idx].blue);
|
||||
stuff_ubyte(&HUD_config.clr[idx].alpha);
|
||||
break;
|
||||
for (idx = 0; idx < NUM_HUD_GAUGES; idx++) {
|
||||
if (!stricmp(str, Hud_Gauge_Names[idx])) {
|
||||
required_string("+RGBA:");
|
||||
stuff_ubyte(&HUD_config.clr[idx].red);
|
||||
stuff_ubyte(&HUD_config.clr[idx].green);
|
||||
stuff_ubyte(&HUD_config.clr[idx].blue);
|
||||
stuff_ubyte(&HUD_config.clr[idx].alpha);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("HUDCONFIG: Unable to parse '%s'! Error message = %s.\n", fname, e.what()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void hud_config_alpha_slider_up()
|
||||
|
||||
@@ -420,6 +420,10 @@ int hud_abort_lock()
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( Player_ship->flags2 & SF2_NO_SECONDARY_LOCKON ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// if we're on the same team and the team doesn't attack itself, then don't lock!
|
||||
if ((Player_ship->team == target_team) && (!iff_x_attacks_y(Player_ship->team, target_team)))
|
||||
{
|
||||
|
||||
+204
-183
@@ -46,6 +46,7 @@ int Hud_reticle_style = HUD_RETICLE_STYLE_FS2;
|
||||
|
||||
bool Hud_retail = true;
|
||||
bool Scale_retail_gauges = true;
|
||||
bool Show_disabled_ets_gauges = false;
|
||||
|
||||
int Hud_font = -1;
|
||||
|
||||
@@ -164,7 +165,7 @@ int parse_ship_start()
|
||||
|
||||
void parse_hud_gauges_tbl(const char *filename)
|
||||
{
|
||||
int i, rval;
|
||||
int i;
|
||||
char *saved_Mp = NULL;
|
||||
|
||||
int colors[3] = {255, 255, 255};
|
||||
@@ -174,110 +175,112 @@ void parse_hud_gauges_tbl(const char *filename)
|
||||
color *ship_clr_p = NULL;
|
||||
bool scale_gauge = true;
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", filename, rval));
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
if(optional_string("$Load Retail Configuration:")) {
|
||||
stuff_boolean(&Hud_retail);
|
||||
}
|
||||
|
||||
if ( optional_string("$Color:") ) {
|
||||
stuff_int_list(colors, 3);
|
||||
|
||||
check_color(colors);
|
||||
gr_init_alphacolor(&hud_color, colors[0], colors[1], colors[2], 255);
|
||||
hud_clr_p = &hud_color;
|
||||
}
|
||||
|
||||
if(optional_string("$Font:")) {
|
||||
stuff_int(&Hud_font);
|
||||
}
|
||||
|
||||
if(optional_string("$Max Directives:")) {
|
||||
stuff_int(&Max_directives);
|
||||
}
|
||||
|
||||
if(optional_string("$Max Escort Ships:")) {
|
||||
stuff_int(&Max_escort_ships);
|
||||
}
|
||||
|
||||
if(optional_string("$Length Unit Multiplier:")) {
|
||||
stuff_float(&Hud_unit_multiplier);
|
||||
|
||||
if (Hud_unit_multiplier <= 0.0f) {
|
||||
Warning(LOCATION, "\"$Length Unit Multiplier:\" value of \"%f\" is invalid! Resetting to default.", Hud_unit_multiplier);
|
||||
Hud_unit_multiplier = 1.0f;
|
||||
if (optional_string("$Load Retail Configuration:")) {
|
||||
stuff_boolean(&Hud_retail);
|
||||
}
|
||||
}
|
||||
|
||||
if(optional_string("$Speed Unit Multiplier:")) {
|
||||
stuff_float(&Hud_speed_multiplier);
|
||||
if (optional_string("$Color:")) {
|
||||
stuff_int_list(colors, 3);
|
||||
|
||||
if (Hud_speed_multiplier <= 0.0f) {
|
||||
Warning(LOCATION, "\"$Speed Unit Multiplier:\" value of \"%f\" is invalid! Resetting to default.", Hud_speed_multiplier);
|
||||
Hud_speed_multiplier = 1.0f;
|
||||
check_color(colors);
|
||||
gr_init_alphacolor(&hud_color, colors[0], colors[1], colors[2], 255);
|
||||
hud_clr_p = &hud_color;
|
||||
}
|
||||
} else {
|
||||
Hud_speed_multiplier = Hud_unit_multiplier;
|
||||
}
|
||||
|
||||
if (optional_string("$Wireframe Targetbox:")) {
|
||||
stuff_int(&Targetbox_wire);
|
||||
if ((Targetbox_wire < 0) || (Targetbox_wire > 3)) {
|
||||
Targetbox_wire = 0;
|
||||
if (optional_string("$Font:")) {
|
||||
stuff_int(&Hud_font);
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Targetbox Shader Effect:")) {
|
||||
stuff_int(&Targetbox_shader_effect);
|
||||
if (Targetbox_shader_effect < 0) {
|
||||
Targetbox_shader_effect = 0;
|
||||
if (optional_string("$Max Directives:")) {
|
||||
stuff_int(&Max_directives);
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Lock Wireframe Mode:")) {
|
||||
stuff_boolean(&Lock_targetbox_mode);
|
||||
}
|
||||
if (optional_string("$Max Escort Ships:")) {
|
||||
stuff_int(&Max_escort_ships);
|
||||
}
|
||||
|
||||
if (optional_string("$Scale Gauges:")) {
|
||||
stuff_boolean(&scale_gauge);
|
||||
Scale_retail_gauges = scale_gauge;
|
||||
}
|
||||
if (optional_string("$Length Unit Multiplier:")) {
|
||||
stuff_float(&Hud_unit_multiplier);
|
||||
|
||||
if(optional_string("$Reticle Style:")) {
|
||||
int temp = required_string_either("FS1", "FS2");
|
||||
if (Hud_unit_multiplier <= 0.0f) {
|
||||
Warning(LOCATION, "\"$Length Unit Multiplier:\" value of \"%f\" is invalid! Resetting to default.", Hud_unit_multiplier);
|
||||
Hud_unit_multiplier = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// using require_string_either won't advance the Mp pointer to the next token so force it instead
|
||||
skip_to_start_of_string("#Gauge Config");
|
||||
if (optional_string("$Speed Unit Multiplier:")) {
|
||||
stuff_float(&Hud_speed_multiplier);
|
||||
|
||||
if (temp < 0)
|
||||
Warning(LOCATION, "Undefined reticle style in hud_gauges.tbl!");
|
||||
else
|
||||
Hud_reticle_style = temp;
|
||||
}
|
||||
if (Hud_speed_multiplier <= 0.0f) {
|
||||
Warning(LOCATION, "\"$Speed Unit Multiplier:\" value of \"%f\" is invalid! Resetting to default.", Hud_speed_multiplier);
|
||||
Hud_speed_multiplier = 1.0f;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Hud_speed_multiplier = Hud_unit_multiplier;
|
||||
}
|
||||
|
||||
int base_res[2];
|
||||
int ship_idx = -1;
|
||||
int ship_font = -1;
|
||||
int gauge_type = -1;
|
||||
int use_font = -1;
|
||||
color *use_clr_p = NULL;
|
||||
SCP_vector<int> ship_classes;
|
||||
bool retail_config = false;
|
||||
int n_ships = 0;
|
||||
if (optional_string("$Wireframe Targetbox:")) {
|
||||
stuff_int(&Targetbox_wire);
|
||||
if ((Targetbox_wire < 0) || (Targetbox_wire > 3)) {
|
||||
Targetbox_wire = 0;
|
||||
}
|
||||
}
|
||||
|
||||
while(optional_string("#Gauge Config")) {
|
||||
ship_classes.clear();
|
||||
switch (optional_string_either("$Ship:", "$Ships:")) {
|
||||
if (optional_string("$Targetbox Shader Effect:")) {
|
||||
stuff_int(&Targetbox_shader_effect);
|
||||
if (Targetbox_shader_effect < 0) {
|
||||
Targetbox_shader_effect = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Lock Wireframe Mode:")) {
|
||||
stuff_boolean(&Lock_targetbox_mode);
|
||||
}
|
||||
|
||||
if (optional_string("$Scale Gauges:")) {
|
||||
stuff_boolean(&scale_gauge);
|
||||
Scale_retail_gauges = scale_gauge;
|
||||
}
|
||||
|
||||
if (optional_string("$Reticle Style:")) {
|
||||
int temp = required_string_either("FS1", "FS2");
|
||||
|
||||
// using require_string_either won't advance the Mp pointer to the next token so force it instead
|
||||
skip_to_start_of_string("#Gauge Config");
|
||||
|
||||
if (temp < 0)
|
||||
Warning(LOCATION, "Undefined reticle style in hud_gauges.tbl!");
|
||||
else
|
||||
Hud_reticle_style = temp;
|
||||
}
|
||||
|
||||
if (optional_string("$Show disabled ETS gauges:")) {
|
||||
stuff_boolean(&Show_disabled_ets_gauges);
|
||||
}
|
||||
|
||||
int base_res[2];
|
||||
int ship_idx = -1;
|
||||
int ship_font = -1;
|
||||
int gauge_type = -1;
|
||||
int use_font = -1;
|
||||
color *use_clr_p = NULL;
|
||||
SCP_vector<int> ship_classes;
|
||||
bool retail_config = false;
|
||||
int n_ships = 0;
|
||||
|
||||
while (optional_string("#Gauge Config")) {
|
||||
ship_classes.clear();
|
||||
switch (optional_string_either("$Ship:", "$Ships:")) {
|
||||
case 0:
|
||||
mprintf(("$Ship in hud_gauges.tbl and -hdg.tbms is deprecated. Use \"$Ships: (\"Some ship class\") instead.\n"));
|
||||
|
||||
if(!ships_inited) {
|
||||
if (!ships_inited) {
|
||||
// just in case ship info has not been initialized.
|
||||
skip_to_start_of_string("#Gauge Config");
|
||||
continue;
|
||||
@@ -287,15 +290,15 @@ void parse_hud_gauges_tbl(const char *filename)
|
||||
ship_idx = parse_ship_start();
|
||||
ship_classes.push_back(ship_idx);
|
||||
|
||||
if(ship_idx >= 0) {
|
||||
if (ship_idx >= 0) {
|
||||
Ship_info[ship_idx].hud_enabled = true;
|
||||
|
||||
// see if we need to load defaults for this configuration
|
||||
if(optional_string("$Load Retail Configuration:")) {
|
||||
if (optional_string("$Load Retail Configuration:")) {
|
||||
stuff_boolean(&Ship_info[ship_idx].hud_retail);
|
||||
}
|
||||
|
||||
if ( optional_string("$Color:") ) {
|
||||
if (optional_string("$Color:")) {
|
||||
stuff_int_list(colors, 3);
|
||||
|
||||
check_color(colors);
|
||||
@@ -303,10 +306,11 @@ void parse_hud_gauges_tbl(const char *filename)
|
||||
ship_clr_p = &ship_color;
|
||||
}
|
||||
|
||||
if(optional_string("$Font:")) {
|
||||
if (optional_string("$Font:")) {
|
||||
stuff_int(&ship_font);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// can't find ship class. move on.
|
||||
ship_classes.push_back(-1);
|
||||
skip_to_start_of_string("#Gauge Config");
|
||||
@@ -319,7 +323,7 @@ void parse_hud_gauges_tbl(const char *filename)
|
||||
|
||||
n_ships = stuff_int_list(shiparray, 256, SHIP_INFO_TYPE);
|
||||
|
||||
if(optional_string("$Load Retail Configuration:")) {
|
||||
if (optional_string("$Load Retail Configuration:")) {
|
||||
stuff_boolean(&retail_config);
|
||||
}
|
||||
|
||||
@@ -329,7 +333,7 @@ void parse_hud_gauges_tbl(const char *filename)
|
||||
Ship_info[shiparray[i]].hud_retail = retail_config;
|
||||
}
|
||||
|
||||
if ( optional_string("$Color:") ) {
|
||||
if (optional_string("$Color:")) {
|
||||
stuff_int_list(colors, 3);
|
||||
|
||||
check_color(colors);
|
||||
@@ -337,119 +341,131 @@ void parse_hud_gauges_tbl(const char *filename)
|
||||
ship_clr_p = &ship_color;
|
||||
}
|
||||
|
||||
if(optional_string("$Font:")) {
|
||||
if (optional_string("$Font:")) {
|
||||
stuff_int(&ship_font);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// No particular ship. -1 for default HUD configuration.
|
||||
ship_classes.push_back(-1);
|
||||
ship_font = -1;
|
||||
ship_clr_p = NULL;
|
||||
break;
|
||||
}
|
||||
// No particular ship. -1 for default HUD configuration.
|
||||
ship_classes.push_back(-1);
|
||||
ship_font = -1;
|
||||
ship_clr_p = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( ship_clr_p != NULL ) {
|
||||
use_clr_p = ship_clr_p;
|
||||
} else {
|
||||
use_clr_p = hud_clr_p;
|
||||
}
|
||||
if (ship_clr_p != NULL) {
|
||||
use_clr_p = ship_clr_p;
|
||||
}
|
||||
else {
|
||||
use_clr_p = hud_clr_p;
|
||||
}
|
||||
|
||||
if(ship_font >= 0) {
|
||||
use_font = ship_font;
|
||||
} else {
|
||||
use_font = Hud_font;
|
||||
}
|
||||
if (ship_font >= 0) {
|
||||
use_font = ship_font;
|
||||
}
|
||||
else {
|
||||
use_font = Hud_font;
|
||||
}
|
||||
|
||||
// Now start going through resolution info for this HUD layout
|
||||
required_string("$Base:");
|
||||
// Now start going through resolution info for this HUD layout
|
||||
required_string("$Base:");
|
||||
|
||||
// get the base width and height describing this HUD
|
||||
stuff_int_list(base_res, 2, RAW_INTEGER_TYPE);
|
||||
// get the base width and height describing this HUD
|
||||
stuff_int_list(base_res, 2, RAW_INTEGER_TYPE);
|
||||
|
||||
// gauge scaling for this base res?
|
||||
if (optional_string("$Scale Gauges:")) {
|
||||
stuff_boolean(&scale_gauge);
|
||||
}
|
||||
// gauge scaling for this base res?
|
||||
if (optional_string("$Scale Gauges:")) {
|
||||
stuff_boolean(&scale_gauge);
|
||||
}
|
||||
|
||||
// Pruning time. Let's see if the current resolution defined by the user matches the conditions set by this entry
|
||||
if(optional_string("$Required Aspect:")) {
|
||||
// filter aspect ratio.
|
||||
if(optional_string("Full Screen")) {
|
||||
if( (float)gr_screen.max_w / (float)gr_screen.max_h > 1.5) {
|
||||
skip_to_start_of_string("#Gauge Config");
|
||||
//skip_to_start_of_string_either("#Gauge Config", "#End");
|
||||
continue;
|
||||
// Pruning time. Let's see if the current resolution defined by the user matches the conditions set by this entry
|
||||
if (optional_string("$Required Aspect:")) {
|
||||
// filter aspect ratio.
|
||||
if (optional_string("Full Screen")) {
|
||||
if ((float)gr_screen.max_w / (float)gr_screen.max_h > 1.5) {
|
||||
skip_to_start_of_string("#Gauge Config");
|
||||
//skip_to_start_of_string_either("#Gauge Config", "#End");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else if(optional_string("Wide Screen")) {
|
||||
if( (float)gr_screen.max_w / (float)gr_screen.max_h <= 1.5) {
|
||||
skip_to_start_of_string("#Gauge Config");
|
||||
//skip_to_start_of_string_either("#Gauge Config", "#End");
|
||||
continue;
|
||||
else if (optional_string("Wide Screen")) {
|
||||
if ((float)gr_screen.max_w / (float)gr_screen.max_h <= 1.5) {
|
||||
skip_to_start_of_string("#Gauge Config");
|
||||
//skip_to_start_of_string_either("#Gauge Config", "#End");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check minimum resolution
|
||||
if(optional_string("$Min:")) {
|
||||
int min_res[2];
|
||||
stuff_int_list(min_res, 2, RAW_INTEGER_TYPE);
|
||||
|
||||
if(min_res[0] > gr_screen.max_w) {
|
||||
skip_to_start_of_string("#Gauge Config");
|
||||
continue;
|
||||
} else if (min_res[0] == gr_screen.max_w) {
|
||||
if(min_res[1] > gr_screen.max_h) {
|
||||
}
|
||||
|
||||
// check minimum resolution
|
||||
if (optional_string("$Min:")) {
|
||||
int min_res[2];
|
||||
stuff_int_list(min_res, 2, RAW_INTEGER_TYPE);
|
||||
|
||||
if (min_res[0] > gr_screen.max_w) {
|
||||
skip_to_start_of_string("#Gauge Config");
|
||||
continue;
|
||||
}
|
||||
else if (min_res[0] == gr_screen.max_w) {
|
||||
if (min_res[1] > gr_screen.max_h) {
|
||||
skip_to_start_of_string("#Gauge Config");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check maximum resolution
|
||||
if(optional_string("$Max:")) {
|
||||
int max_res[2];
|
||||
stuff_int_list(max_res, 2, RAW_INTEGER_TYPE);
|
||||
// check maximum resolution
|
||||
if (optional_string("$Max:")) {
|
||||
int max_res[2];
|
||||
stuff_int_list(max_res, 2, RAW_INTEGER_TYPE);
|
||||
|
||||
if(max_res[0] < gr_screen.max_w) {
|
||||
skip_to_start_of_string("#Gauge Config");
|
||||
continue;
|
||||
} else if (max_res[0] == gr_screen.max_w) {
|
||||
if(max_res[1] < gr_screen.max_h) {
|
||||
if (max_res[0] < gr_screen.max_w) {
|
||||
skip_to_start_of_string("#Gauge Config");
|
||||
continue;
|
||||
}
|
||||
else if (max_res[0] == gr_screen.max_w) {
|
||||
if (max_res[1] < gr_screen.max_h) {
|
||||
skip_to_start_of_string("#Gauge Config");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// let's start parsing for gauges.
|
||||
required_string("$Gauges:");
|
||||
|
||||
while (!check_for_string("$Gauges:") && !check_for_string("$End Gauges")) {
|
||||
// find out what type of gauge we're parsing.
|
||||
gauge_type = parse_gauge_type();
|
||||
|
||||
// then call the specific gauge load handler function for this gauge type.
|
||||
if (optional_string("default")) {
|
||||
// sending -1 base width and height will indicate GR_640 or GR_1024 to the handlers
|
||||
load_gauge(gauge_type, -1, -1, use_font, scale_gauge, &ship_classes, use_clr_p);
|
||||
}
|
||||
else {
|
||||
load_gauge(gauge_type, base_res[0], base_res[1], use_font, scale_gauge, &ship_classes, use_clr_p);
|
||||
}
|
||||
|
||||
if (saved_Mp && (saved_Mp == Mp)) {
|
||||
Mp++;
|
||||
}
|
||||
|
||||
skip_to_start_of_string_either("$", "+");
|
||||
// stolened from AI_profiles
|
||||
// if we've been through once already and are at the same place, force a move
|
||||
|
||||
saved_Mp = Mp;
|
||||
}
|
||||
|
||||
required_string("$End Gauges");
|
||||
required_string("#End");
|
||||
}
|
||||
|
||||
// let's start parsing for gauges.
|
||||
required_string("$Gauges:");
|
||||
|
||||
while (!check_for_string("$Gauges:") && !check_for_string("$End Gauges")) {
|
||||
// find out what type of gauge we're parsing.
|
||||
gauge_type = parse_gauge_type();
|
||||
|
||||
// then call the specific gauge load handler function for this gauge type.
|
||||
if(optional_string("default")) {
|
||||
// sending -1 base width and height will indicate GR_640 or GR_1024 to the handlers
|
||||
load_gauge(gauge_type, -1, -1, use_font, scale_gauge, &ship_classes, use_clr_p);
|
||||
} else {
|
||||
load_gauge(gauge_type, base_res[0], base_res[1], use_font, scale_gauge, &ship_classes, use_clr_p);
|
||||
}
|
||||
|
||||
if ( saved_Mp && (saved_Mp == Mp) ) {
|
||||
Mp++;
|
||||
}
|
||||
|
||||
skip_to_start_of_string_either("$", "+");
|
||||
// stolened from AI_profiles
|
||||
// if we've been through once already and are at the same place, force a move
|
||||
|
||||
saved_Mp = Mp;
|
||||
}
|
||||
|
||||
required_string("$End Gauges");
|
||||
required_string("#End");
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", filename, e.what()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2006,6 +2022,7 @@ void load_gauge_center_reticle(int base_w, int base_h, int hud_font, bool scale_
|
||||
int scaleX = 15;
|
||||
int scaleY = 10;
|
||||
int size = 5;
|
||||
int autoaim_frame = -1;
|
||||
|
||||
if(Hud_reticle_style == HUD_RETICLE_STYLE_FS1) {
|
||||
if(gr_screen.res == GR_640) {
|
||||
@@ -2055,8 +2072,12 @@ void load_gauge_center_reticle(int base_w, int base_h, int hud_font, bool scale_
|
||||
if (optional_string("Firepoint Y coordinate multiplier:"))
|
||||
stuff_int(&scaleY);
|
||||
|
||||
if(optional_string("Autoaim Frame:"))
|
||||
stuff_int(&autoaim_frame);
|
||||
|
||||
hud_gauge->initBitmaps(fname);
|
||||
hud_gauge->initFirepointDisplay(firepoints, scaleX, scaleY, size);
|
||||
hud_gauge->setAutoaimFrame(autoaim_frame);
|
||||
|
||||
if(ship_idx->at(0) >= 0) {
|
||||
for (SCP_vector<int>::iterator ship_index = ship_idx->begin(); ship_index != ship_idx->end(); ++ship_index) {
|
||||
|
||||
@@ -20,6 +20,7 @@ extern float Hud_speed_multiplier;
|
||||
#define HUD_RETICLE_STYLE_FS2 1
|
||||
|
||||
extern int Hud_reticle_style;
|
||||
extern bool Show_disabled_ets_gauges;
|
||||
|
||||
//Functions
|
||||
int hud_get_gauge_index(char* name);
|
||||
|
||||
+66
-12
@@ -20,6 +20,7 @@
|
||||
#include "weapon/emp.h"
|
||||
#include "localization/localize.h"
|
||||
#include "network/multi.h"
|
||||
#include "weapon/weapon.h"
|
||||
|
||||
#define NUM_RETICLE_ANIS 11 // keep up to date when modifying the number of reticle ani files
|
||||
|
||||
@@ -228,6 +229,7 @@ static int Threat_lock_frame; // frame offset of current lock flashing warnin
|
||||
HudGaugeReticle::HudGaugeReticle():
|
||||
HudGauge(HUD_OBJECT_CENTER_RETICLE, HUD_CENTER_RETICLE, true, false, (VM_EXTERNAL | VM_DEAD_VIEW | VM_WARP_CHASE | VM_PADLOCK_ANY | VM_TOPDOWN | VM_OTHER_SHIP), 255, 255, 255)
|
||||
{
|
||||
has_autoaim_lock = false;
|
||||
}
|
||||
|
||||
void HudGaugeReticle::initBitmaps(char *fname)
|
||||
@@ -247,9 +249,39 @@ void HudGaugeReticle::initFirepointDisplay(bool firepoint, int scaleX, int scale
|
||||
|
||||
void HudGaugeReticle::render(float frametime)
|
||||
{
|
||||
ship_info *sip = &Ship_info[Player_ship->ship_info_index];
|
||||
|
||||
if (autoaim_frame_offset > 0 || sip->autoaim_lock_snd > -1 || sip->autoaim_lost_snd > -1) {
|
||||
ship *shipp = &Ships[Objects[Player->objnum].instance];
|
||||
ship_weapon *swp = &shipp->weapons;
|
||||
ai_info *aip = &Ai_info[shipp->ai_index];
|
||||
|
||||
if (aip->target_objnum != -1) {
|
||||
bool autoaiming = false;
|
||||
|
||||
autoaiming = in_autoaim_fov(shipp, swp->current_primary_bank, &Objects[aip->target_objnum]);
|
||||
|
||||
if (autoaiming) {
|
||||
if (!has_autoaim_lock && sip->autoaim_lock_snd > -1) {
|
||||
snd_play( &Snds[sip->autoaim_lock_snd]);
|
||||
}
|
||||
has_autoaim_lock = true;
|
||||
}
|
||||
else {
|
||||
if (has_autoaim_lock && sip->autoaim_lost_snd > -1) {
|
||||
snd_play( &Snds[sip->autoaim_lost_snd]);
|
||||
}
|
||||
has_autoaim_lock = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setGaugeColor(HUD_C_BRIGHT);
|
||||
|
||||
renderBitmap(crosshair.first_frame, position[0], position[1]);
|
||||
if (has_autoaim_lock)
|
||||
renderBitmap(crosshair.first_frame + autoaim_frame_offset, position[0], position[1]);
|
||||
else
|
||||
renderBitmap(crosshair.first_frame, position[0], position[1]);
|
||||
|
||||
if (firepoint_display) {
|
||||
fp.clear();
|
||||
@@ -277,7 +309,7 @@ void HudGaugeReticle::render(float frametime)
|
||||
|
||||
void HudGaugeReticle::getFirepointStatus() {
|
||||
//First, get the player ship
|
||||
ship_info* pship;
|
||||
ship_info* sip;
|
||||
ship* shipp;
|
||||
polymodel* pm;
|
||||
|
||||
@@ -285,30 +317,45 @@ void HudGaugeReticle::getFirepointStatus() {
|
||||
|
||||
if (Objects[Player->objnum].type == OBJ_SHIP) {
|
||||
shipp = &Ships[Objects[Player->objnum].instance];
|
||||
pship = &Ship_info[shipp->ship_info_index];
|
||||
sip = &Ship_info[shipp->ship_info_index];
|
||||
|
||||
//Get the player eyepoint
|
||||
pm = model_get(pship->model_num);
|
||||
pm = model_get(sip->model_num);
|
||||
|
||||
if (pm->n_view_positions == 0) {
|
||||
mprintf(("Model %s does not have a defined eyepoint. Firepoint display could not be generated\n", pm->filename));
|
||||
} else {
|
||||
if (pm->n_guns > 0) {
|
||||
|
||||
if (pm->n_guns > 0) {
|
||||
eye eyepoint = pm->view_positions[shipp->current_viewpoint];
|
||||
vec2d ep = { eyepoint.pnt.xyz.x, eyepoint.pnt.xyz.y };
|
||||
|
||||
for (int i = 0; i < pm->n_guns; i++) {
|
||||
int isactive = 0;
|
||||
int bankactive = 0;
|
||||
ship_weapon *swp = &shipp->weapons;
|
||||
|
||||
if (!timestamp_elapsed(shipp->weapons.next_primary_fire_stamp[i]))
|
||||
isactive = 1;
|
||||
bankactive = 1;
|
||||
else if (timestamp_elapsed(shipp->weapons.primary_animation_done_time[i]))
|
||||
isactive = 1;
|
||||
bankactive = 1;
|
||||
else if (i == shipp->weapons.current_primary_bank || shipp->flags & SF_PRIMARY_LINKED)
|
||||
isactive = 2;
|
||||
bankactive = 2;
|
||||
|
||||
int num_slots = pm->gun_banks[i].num_slots;
|
||||
for (int j = 0; j < num_slots; j++) {
|
||||
int fpactive = bankactive;
|
||||
|
||||
if (sip->flags2 & SIF2_DYN_PRIMARY_LINKING) {
|
||||
// If this firepoint is not among the next shot(s) to be fired, dim it one step
|
||||
if ( !( (j >= (shipp->last_fired_point[i]+1) % num_slots) && (j <= (shipp->last_fired_point[i]+swp->primary_bank_slot_count[i]) % num_slots) ) ) {
|
||||
fpactive--;
|
||||
}
|
||||
} else if (Weapon_info[swp->primary_bank_weapons[i]].wi_flags2 & WIF2_CYCLE) {
|
||||
// If this firepoint is not the next one to be fired, dim it one step
|
||||
if (j != (shipp->last_fired_point[i]+1) % num_slots) {
|
||||
fpactive--;
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < pm->gun_banks[i].num_slots; j++) {
|
||||
vec3d fpfromeye;
|
||||
|
||||
matrix eye_orient, player_transpose;
|
||||
@@ -317,7 +364,7 @@ void HudGaugeReticle::getFirepointStatus() {
|
||||
vm_matrix_x_matrix(&eye_orient, &player_transpose, &Eye_matrix);
|
||||
vm_vec_rotate(&fpfromeye, &pm->gun_banks[i].pnt[j], &eye_orient);
|
||||
|
||||
firepoint tmp = { { fpfromeye.xyz.x - ep.x, ep.y - fpfromeye.xyz.y }, isactive };
|
||||
firepoint tmp = { { fpfromeye.xyz.x - ep.x, ep.y - fpfromeye.xyz.y }, fpactive };
|
||||
fp.push_back(tmp);
|
||||
}
|
||||
}
|
||||
@@ -326,6 +373,13 @@ void HudGaugeReticle::getFirepointStatus() {
|
||||
}
|
||||
}
|
||||
|
||||
void HudGaugeReticle::setAutoaimFrame(int framenum) {
|
||||
if (framenum < 0 || framenum > crosshair.num_frames - 1)
|
||||
autoaim_frame_offset = 0;
|
||||
else
|
||||
autoaim_frame_offset = framenum;
|
||||
}
|
||||
|
||||
void HudGaugeReticle::pageIn()
|
||||
{
|
||||
bm_page_in_aabitmap( crosshair.first_frame, crosshair.num_frames);
|
||||
|
||||
@@ -43,6 +43,8 @@ protected:
|
||||
int firepoint_size;
|
||||
int firepoint_scale_x;
|
||||
int firepoint_scale_y;
|
||||
int autoaim_frame_offset;
|
||||
bool has_autoaim_lock;
|
||||
public:
|
||||
HudGaugeReticle();
|
||||
void render(float frametime);
|
||||
@@ -50,6 +52,7 @@ public:
|
||||
void pageIn();
|
||||
void initFirepointDisplay(bool firepoint, int scaleX, int scaleY, int size);
|
||||
void getFirepointStatus();
|
||||
void setAutoaimFrame(int framenum);
|
||||
};
|
||||
|
||||
class HudGaugeThrottle: public HudGauge
|
||||
|
||||
@@ -545,6 +545,11 @@ void hud_shield_quadrant_hit(object *objp, int quadrant)
|
||||
shield_hit_info *shi;
|
||||
int num;
|
||||
|
||||
if (Game_mode & GM_STANDALONE_SERVER)
|
||||
return;
|
||||
|
||||
Assertion(objp != NULL, "hud_shield_quadrant_hit() called with a NULL objp; get a coder!\n");
|
||||
|
||||
if ( objp->type != OBJ_SHIP )
|
||||
return;
|
||||
|
||||
@@ -559,12 +564,16 @@ void hud_shield_quadrant_hit(object *objp, int quadrant)
|
||||
return;
|
||||
}
|
||||
|
||||
Assertion(shi->shield_hit_timers.size() > 0, "Shield hit info object for object '%s' has a size %d shield_hit_timers; get a coder!\n", Ships[objp->instance].ship_name, shi->shield_hit_timers.size());
|
||||
Assertion(shi->hull_hit_index < shi->shield_hit_timers.size(), "Shield hit info object for object '%s' has a hull_hit_index of %d (should be between 0 and %d); get a coder!\n", Ships[objp->instance].ship_name, shi->hull_hit_index, shi->shield_hit_timers.size() - 1);
|
||||
|
||||
if ( quadrant >= 0 ) {
|
||||
if ( !(Ship_info[Ships[objp->instance].ship_info_index].flags2 & SIF2_MODEL_POINT_SHIELDS) )
|
||||
num = Quadrant_xlate[quadrant];
|
||||
else
|
||||
num = quadrant;
|
||||
|
||||
Assertion(num < shi->hull_hit_index, "Shield hit info object for object '%s' hit on quadrant #%d, despite having a hull_hit_index of %d; get a coder!\n", Ships[objp->instance].ship_name, num, shi->hull_hit_index);
|
||||
shi->shield_hit_timers[num] = timestamp(SHIELD_HIT_DURATION_SHORT);
|
||||
} else {
|
||||
shi->shield_hit_timers[shi->hull_hit_index] = timestamp(SHIELD_HIT_DURATION_SHORT);
|
||||
|
||||
@@ -858,7 +858,7 @@ int hud_squadmsg_is_target_order_valid(int order, int find_order, ai_info *aip )
|
||||
}
|
||||
|
||||
// if we are messaging a ship, and that ship is our target, no target type orders are ever active
|
||||
if ( (Squad_msg_mode == SM_MODE_SHIP_COMMAND) && (target_objnum == Msg_instance) ){
|
||||
if ( (Squad_msg_mode == SM_MODE_SHIP_COMMAND) && (Objects[target_objnum].instance == Msg_instance) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1373,11 +1373,10 @@ int hud_squadmsg_send_wing_command( int wingnum, int command, int send_message,
|
||||
|
||||
target_shipname = NULL;
|
||||
target_team = -1;
|
||||
if ( ainfo->target_objnum != -1) {
|
||||
if ( Objects[ainfo->target_objnum].type == OBJ_SHIP ) {
|
||||
target_shipname = Ships[Objects[ainfo->target_objnum].instance].ship_name; // I think this is right
|
||||
target_team = Ships[Objects[ainfo->target_objnum].instance].team;
|
||||
}
|
||||
|
||||
if ( Objects[ainfo->target_objnum].type == OBJ_SHIP ) {
|
||||
target_shipname = Ships[Objects[ainfo->target_objnum].instance].ship_name; // I think this is right
|
||||
target_team = Ships[Objects[ainfo->target_objnum].instance].team;
|
||||
}
|
||||
|
||||
Assert ( ainfo->shipnum != -1 );
|
||||
|
||||
@@ -1095,7 +1095,7 @@ void hud_target_subobject_common(int next_flag)
|
||||
target_shipp = &Ships[Objects[Player_ai->target_objnum].instance];
|
||||
|
||||
if (!Player_ai->targeted_subsys) {
|
||||
start = GET_FIRST(&target_shipp->subsys_list);
|
||||
start = END_OF_LIST(&target_shipp->subsys_list);
|
||||
} else {
|
||||
start = Player_ai->targeted_subsys;
|
||||
}
|
||||
|
||||
+398
-397
@@ -128,406 +128,407 @@ void iff_init()
|
||||
int i, j, k;
|
||||
int string_idx;
|
||||
|
||||
int rval;
|
||||
if ((rval = setjmp(parse_abort)) != 0)
|
||||
try
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", "iff_defs.tbl", rval));
|
||||
// Goober5000 - if table doesn't exist, use the default table
|
||||
if (cf_exists_full("iff_defs.tbl", CF_TYPE_TABLES))
|
||||
read_file_text("iff_defs.tbl", CF_TYPE_TABLES);
|
||||
else
|
||||
read_file_text_from_array(defaults_get_file("iff_defs.tbl"));
|
||||
|
||||
reset_parse();
|
||||
|
||||
// parse the table --------------------------------------------------------
|
||||
|
||||
required_string("#IFFs");
|
||||
|
||||
// get the traitor
|
||||
required_string("$Traitor IFF:");
|
||||
stuff_string(traitor_name, F_NAME, NAME_LENGTH);
|
||||
|
||||
int rgb[3];
|
||||
|
||||
// check if alternate colours are wanted to be used for these
|
||||
// Marks various stuff... like asteroids
|
||||
if ((optional_string("$Selection Color:")) || (optional_string("$Selection Colour:")))
|
||||
{
|
||||
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
|
||||
iff_init_color(rgb[0], rgb[1], rgb[2]);
|
||||
}
|
||||
else
|
||||
iff_init_color(0xff, 0xff, 0xff);
|
||||
|
||||
// Marks the ship currently saying something
|
||||
if ((optional_string("$Message Color:")) || (optional_string("$Message Colour:")))
|
||||
{
|
||||
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
|
||||
iff_init_color(rgb[0], rgb[1], rgb[2]);
|
||||
}
|
||||
else
|
||||
iff_init_color(0x7f, 0x7f, 0x7f);
|
||||
|
||||
// Marks the tagged ships
|
||||
if ((optional_string("$Tagged Color:")) || (optional_string("$Tagged Colour:")))
|
||||
{
|
||||
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
|
||||
iff_init_color(rgb[0], rgb[1], rgb[2]);
|
||||
}
|
||||
else
|
||||
iff_init_color(0xff, 0xff, 0x00);
|
||||
|
||||
// init radar blips colour table
|
||||
int a_bright, a_dim;
|
||||
bool alternate_blip_color = false;
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
for (j = 0; j < 2; j++)
|
||||
{
|
||||
for (k = 0; k < 3; k++)
|
||||
{
|
||||
radar_iff_color[i][j][k] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if the bright/dim scaling is wanted to be changed
|
||||
if (optional_string("$Dimmed IFF brightness:"))
|
||||
{
|
||||
int dim_iff_brightness;
|
||||
stuff_int(&dim_iff_brightness);
|
||||
Assert(dim_iff_brightness >= 0 && dim_iff_brightness <= HUD_COLOR_ALPHA_MAX);
|
||||
*iff_color_brightness = dim_iff_brightness;
|
||||
}
|
||||
else
|
||||
*iff_color_brightness = 4;
|
||||
|
||||
// alternate = use same method as with ship blips
|
||||
// retail = use 1/2 intensities
|
||||
if (optional_string("$Use Alternate Blip Coloring:") || optional_string("$Use Alternate Blip Colouring:"))
|
||||
{
|
||||
stuff_boolean(&alternate_blip_color);
|
||||
}
|
||||
|
||||
// Parse blip colours, their order is hardcoded.
|
||||
if ((optional_string("$Missile Blip Color:")) || (optional_string("$Missile Blip Colour:")))
|
||||
{
|
||||
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
Assert(rgb[i] >= 0 && rgb[i] <= 255);
|
||||
radar_iff_color[0][1][i] = rgb[i];
|
||||
radar_iff_color[0][0][i] = rgb[i] / 2;
|
||||
}
|
||||
}
|
||||
|
||||
if ((optional_string("$Navbuoy Blip Color:")) || (optional_string("$Navbuoy Blip Colour:")))
|
||||
{
|
||||
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
Assert(rgb[i] >= 0 && rgb[i] <= 255);
|
||||
radar_iff_color[1][1][i] = rgb[i];
|
||||
radar_iff_color[1][0][i] = rgb[i] / 2;
|
||||
}
|
||||
}
|
||||
|
||||
if ((optional_string("$Warping Blip Color:")) || (optional_string("$Warping Blip Colour:")))
|
||||
{
|
||||
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
Assert(rgb[i] >= 0 && rgb[i] <= 255);
|
||||
radar_iff_color[2][1][i] = rgb[i];
|
||||
radar_iff_color[2][0][i] = rgb[i] / 2;
|
||||
}
|
||||
}
|
||||
|
||||
if ((optional_string("$Node Blip Color:")) || (optional_string("$Node Blip Colour:")))
|
||||
{
|
||||
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
Assert(rgb[i] >= 0 && rgb[i] <= 255);
|
||||
radar_iff_color[3][1][i] = rgb[i];
|
||||
radar_iff_color[3][0][i] = rgb[i] / 2;
|
||||
}
|
||||
}
|
||||
|
||||
if ((optional_string("$Tagged Blip Color:")) || (optional_string("$Tagged Blip Colour:")))
|
||||
{
|
||||
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
Assert(rgb[i] >= 0 && rgb[i] <= 255);
|
||||
radar_iff_color[4][1][i] = rgb[i];
|
||||
radar_iff_color[4][0][i] = rgb[i] / 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (alternate_blip_color == true)
|
||||
{
|
||||
a_bright = iff_get_alpha_value(true);
|
||||
a_dim = iff_get_alpha_value(false);
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
if (radar_iff_color[i][0][0] >= 0)
|
||||
{
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
radar_iff_color[i][0][j] = radar_iff_color[i][1][j];
|
||||
}
|
||||
|
||||
radar_iff_color[i][1][3] = a_bright;
|
||||
radar_iff_color[i][0][3] = a_dim;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
if (radar_iff_color[i][0][0] >= 0)
|
||||
{
|
||||
radar_iff_color[i][0][3] = 255;
|
||||
radar_iff_color[i][1][3] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Radar Target ID Flags:")) {
|
||||
parse_string_flag_list((int*)&radar_target_id_flags, rti_flags, Num_rti_flags);
|
||||
if (optional_string("+reset"))
|
||||
radar_target_id_flags = 0;
|
||||
}
|
||||
|
||||
// begin reading data
|
||||
Num_iffs = 0;
|
||||
while (required_string_either("#End", "$IFF Name:"))
|
||||
{
|
||||
iff_info *iff;
|
||||
int cur_iff;
|
||||
|
||||
// make sure we're under the limit
|
||||
if (Num_iffs >= MAX_IFFS)
|
||||
{
|
||||
Warning(LOCATION, "Too many iffs in iffs_defs.tbl! Max is %d.\n", MAX_IFFS);
|
||||
skip_to_start_of_string("#End", NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
// add new IFF
|
||||
iff = &Iff_info[Num_iffs];
|
||||
cur_iff = Num_iffs;
|
||||
Num_iffs++;
|
||||
|
||||
|
||||
// get required IFF info ----------------------------------------------
|
||||
|
||||
// get the iff name
|
||||
required_string("$IFF Name:");
|
||||
stuff_string(iff->iff_name, F_NAME, NAME_LENGTH);
|
||||
|
||||
// get the iff color
|
||||
if (check_for_string("$Colour:"))
|
||||
required_string("$Colour:");
|
||||
else
|
||||
required_string("$Color:");
|
||||
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
|
||||
iff->color_index = iff_init_color(rgb[0], rgb[1], rgb[2]);
|
||||
|
||||
|
||||
// get relationships between IFFs -------------------------------------
|
||||
|
||||
// get the list of iffs attacked
|
||||
if (optional_string("$Attacks:"))
|
||||
num_attack_names[cur_iff] = stuff_string_list(attack_names[cur_iff], MAX_IFFS);
|
||||
else
|
||||
num_attack_names[cur_iff] = 0;
|
||||
|
||||
// get the list of observed colors
|
||||
num_observed_colors[cur_iff] = 0;
|
||||
while (optional_string("+Sees"))
|
||||
{
|
||||
// get iff observed
|
||||
stuff_string_until(observed_color_table[cur_iff][num_observed_colors[cur_iff]].iff_name, "As:", NAME_LENGTH);
|
||||
required_string("As:");
|
||||
|
||||
// get color observed
|
||||
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
|
||||
observed_color_table[cur_iff][num_observed_colors[cur_iff]].color_index = iff_init_color(rgb[0], rgb[1], rgb[2]);
|
||||
|
||||
// increment
|
||||
num_observed_colors[cur_iff]++;
|
||||
}
|
||||
|
||||
|
||||
// get flags ----------------------------------------------------------
|
||||
|
||||
// get iff flags
|
||||
iff->flags = 0;
|
||||
if (optional_string("$Flags:"))
|
||||
{
|
||||
char flag_strings[MAX_IFF_FLAGS][NAME_LENGTH];
|
||||
|
||||
int num_strings = stuff_string_list(flag_strings, MAX_IFF_FLAGS);
|
||||
for (string_idx = 0; string_idx < num_strings; string_idx++)
|
||||
{
|
||||
if (!stricmp(NOX("support allowed"), flag_strings[string_idx]))
|
||||
iff->flags |= IFFF_SUPPORT_ALLOWED;
|
||||
else if (!stricmp(NOX("exempt from all teams at war"), flag_strings[string_idx]))
|
||||
iff->flags |= IFFF_EXEMPT_FROM_ALL_TEAMS_AT_WAR;
|
||||
else if (!stricmp(NOX("orders hidden"), flag_strings[string_idx]))
|
||||
iff->flags |= IFFF_ORDERS_HIDDEN;
|
||||
else if (!stricmp(NOX("orders shown"), flag_strings[string_idx]))
|
||||
iff->flags |= IFFF_ORDERS_SHOWN;
|
||||
else if (!stricmp(NOX("wing name hidden"), flag_strings[string_idx]))
|
||||
iff->flags |= IFFF_WING_NAME_HIDDEN;
|
||||
else
|
||||
Warning(LOCATION, "Bogus string in iff flags: %s\n", flag_strings[string_idx]);
|
||||
}
|
||||
}
|
||||
|
||||
// get default ship flags
|
||||
iff->default_parse_flags = 0;
|
||||
if (optional_string("$Default Ship Flags:"))
|
||||
{
|
||||
i = 0;
|
||||
j = 0;
|
||||
char flag_strings[MAX_PARSE_OBJECT_FLAGS][NAME_LENGTH];
|
||||
int num_strings = stuff_string_list(flag_strings, MAX_PARSE_OBJECT_FLAGS);
|
||||
for (i = 0; i < num_strings; i++)
|
||||
{
|
||||
for (j = 0; j < MAX_PARSE_OBJECT_FLAGS; j++)
|
||||
{
|
||||
if (!stricmp(flag_strings[i], Parse_object_flags[j]))
|
||||
{
|
||||
iff->default_parse_flags |= (1 << j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (j == MAX_PARSE_OBJECT_FLAGS)
|
||||
Warning(LOCATION, "Bogus string in iff default ship flags: %s\n", flag_strings[i]);
|
||||
}
|
||||
|
||||
// again
|
||||
iff->default_parse_flags2 = 0;
|
||||
if (optional_string("$Default Ship Flags2:"))
|
||||
{
|
||||
i = 0;
|
||||
j = 0;
|
||||
char flag_strings[MAX_PARSE_OBJECT_FLAGS_2][NAME_LENGTH];
|
||||
int num_strings = stuff_string_list(flag_strings, MAX_PARSE_OBJECT_FLAGS_2);
|
||||
for (i = 0; i < num_strings; i++)
|
||||
{
|
||||
for (j = 0; j < MAX_PARSE_OBJECT_FLAGS_2; j++)
|
||||
{
|
||||
if (!stricmp(flag_strings[i], Parse_object_flags_2[j]))
|
||||
{
|
||||
iff->default_parse_flags2 |= (1 << j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (j == MAX_PARSE_OBJECT_FLAGS_2)
|
||||
Warning(LOCATION, "Bogus string in iff default ship flags2: %s\n", flag_strings[i]);
|
||||
}
|
||||
|
||||
// this is cleared between each level but let's just set it here for thoroughness
|
||||
iff->ai_rearm_timestamp = timestamp(-1);
|
||||
}
|
||||
|
||||
required_string("#End");
|
||||
|
||||
|
||||
// now resolve the relationships ------------------------------------------
|
||||
|
||||
// first get the traitor
|
||||
Iff_traitor = iff_lookup(traitor_name);
|
||||
if (Iff_traitor < 0)
|
||||
{
|
||||
Iff_traitor = 0;
|
||||
Warning(LOCATION, "Traitor IFF %s not found in iff_defs.tbl! Defaulting to %s.\n", traitor_name, Iff_info[Iff_traitor].iff_name);
|
||||
}
|
||||
|
||||
// next get the attackees and colors
|
||||
for (int cur_iff = 0; cur_iff < Num_iffs; cur_iff++)
|
||||
{
|
||||
iff_info *iff = &Iff_info[cur_iff];
|
||||
|
||||
// clear the iffs to be attacked
|
||||
iff->attackee_bitmask = 0;
|
||||
iff->attackee_bitmask_all_teams_at_war = 0;
|
||||
|
||||
// clear the observed colors
|
||||
for (j = 0; j < MAX_IFFS; j++)
|
||||
iff->observed_color_index[j] = -1;
|
||||
|
||||
// resolve the list names
|
||||
for (int list_index = 0; list_index < MAX_IFFS; list_index++)
|
||||
{
|
||||
// are we within the number of attackees listed?
|
||||
if (list_index < num_attack_names[cur_iff])
|
||||
{
|
||||
// find out who
|
||||
int target_iff = iff_lookup(attack_names[cur_iff][list_index]);
|
||||
|
||||
// valid?
|
||||
if (target_iff >= 0)
|
||||
iff->attackee_bitmask |= iff_get_mask(target_iff);
|
||||
else
|
||||
Warning(LOCATION, "Attack target IFF %s not found for IFF %s in iff_defs.tbl!\n", attack_names[cur_iff][list_index], iff->iff_name);
|
||||
}
|
||||
|
||||
// are we within the number of colors listed?
|
||||
if (list_index < num_observed_colors[cur_iff])
|
||||
{
|
||||
// find out who
|
||||
int target_iff = iff_lookup(observed_color_table[cur_iff][list_index].iff_name);
|
||||
|
||||
// valid?
|
||||
if (target_iff >= 0)
|
||||
iff->observed_color_index[target_iff] = observed_color_table[cur_iff][list_index].color_index;
|
||||
else
|
||||
Warning(LOCATION, "Observed color IFF %s not found for IFF %s in iff_defs.tbl!\n", observed_color_table[cur_iff][list_index].iff_name, iff->iff_name);
|
||||
}
|
||||
}
|
||||
|
||||
// resolve the all teams at war relationships
|
||||
if (iff->flags & IFFF_EXEMPT_FROM_ALL_TEAMS_AT_WAR)
|
||||
{
|
||||
// exempt, so use standard attacks
|
||||
iff->attackee_bitmask_all_teams_at_war = iff->attackee_bitmask;
|
||||
}
|
||||
else
|
||||
{
|
||||
// nonexempt, so build bitmask of all other nonexempt teams
|
||||
for (int other_iff = 0; other_iff < Num_iffs; other_iff++)
|
||||
{
|
||||
// skip myself (unless I attack myself normally)
|
||||
if ((other_iff == cur_iff) && !iff_x_attacks_y(cur_iff, cur_iff))
|
||||
continue;
|
||||
|
||||
// skip anyone exempt
|
||||
if (Iff_info[other_iff].flags & IFFF_EXEMPT_FROM_ALL_TEAMS_AT_WAR)
|
||||
continue;
|
||||
|
||||
// add everyone else
|
||||
iff->attackee_bitmask_all_teams_at_war |= iff_get_mask(other_iff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add tbl/tbm to multiplayer validation list
|
||||
extern void fs2netd_add_table_validation(const char *tblname);
|
||||
fs2netd_add_table_validation("iff_defs.tbl");
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "iff_defs.tbl", e.what()));
|
||||
return;
|
||||
}
|
||||
|
||||
// Goober5000 - if table doesn't exist, use the default table
|
||||
if (cf_exists_full("iff_defs.tbl", CF_TYPE_TABLES))
|
||||
read_file_text("iff_defs.tbl", CF_TYPE_TABLES);
|
||||
else
|
||||
read_file_text_from_array(defaults_get_file("iff_defs.tbl"));
|
||||
|
||||
reset_parse();
|
||||
|
||||
// parse the table --------------------------------------------------------
|
||||
|
||||
required_string("#IFFs");
|
||||
|
||||
// get the traitor
|
||||
required_string("$Traitor IFF:");
|
||||
stuff_string(traitor_name, F_NAME, NAME_LENGTH);
|
||||
|
||||
int rgb[3];
|
||||
|
||||
// check if alternate colours are wanted to be used for these
|
||||
// Marks various stuff... like asteroids
|
||||
if ((optional_string("$Selection Color:")) || (optional_string("$Selection Colour:")))
|
||||
{
|
||||
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
|
||||
iff_init_color(rgb[0], rgb[1], rgb[2]);
|
||||
}
|
||||
else
|
||||
iff_init_color(0xff, 0xff, 0xff);
|
||||
|
||||
// Marks the ship currently saying something
|
||||
if ((optional_string("$Message Color:")) || (optional_string("$Message Colour:")))
|
||||
{
|
||||
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
|
||||
iff_init_color(rgb[0], rgb[1], rgb[2]);
|
||||
}
|
||||
else
|
||||
iff_init_color(0x7f, 0x7f, 0x7f);
|
||||
|
||||
// Marks the tagged ships
|
||||
if ((optional_string("$Tagged Color:")) || (optional_string("$Tagged Colour:")))
|
||||
{
|
||||
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
|
||||
iff_init_color(rgb[0], rgb[1], rgb[2]);
|
||||
}
|
||||
else
|
||||
iff_init_color(0xff, 0xff, 0x00);
|
||||
|
||||
// init radar blips colour table
|
||||
int a_bright,a_dim;
|
||||
bool alternate_blip_color = false;
|
||||
for (i=0;i<5;i++)
|
||||
{
|
||||
for (j=0;j<2;j++)
|
||||
{
|
||||
for (k=0;k<3;k++)
|
||||
{
|
||||
radar_iff_color[i][j][k] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if the bright/dim scaling is wanted to be changed
|
||||
if (optional_string("$Dimmed IFF brightness:"))
|
||||
{
|
||||
int dim_iff_brightness;
|
||||
stuff_int(&dim_iff_brightness);
|
||||
Assert(dim_iff_brightness >= 0 && dim_iff_brightness <= HUD_COLOR_ALPHA_MAX);
|
||||
*iff_color_brightness = dim_iff_brightness;
|
||||
}
|
||||
else
|
||||
*iff_color_brightness = 4;
|
||||
|
||||
// alternate = use same method as with ship blips
|
||||
// retail = use 1/2 intensities
|
||||
if (optional_string("$Use Alternate Blip Coloring:") || optional_string("$Use Alternate Blip Colouring:"))
|
||||
{
|
||||
stuff_boolean(&alternate_blip_color);
|
||||
}
|
||||
|
||||
// Parse blip colours, their order is hardcoded.
|
||||
if ((optional_string("$Missile Blip Color:")) || (optional_string("$Missile Blip Colour:")))
|
||||
{
|
||||
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
|
||||
for (i=0;i<3;i++)
|
||||
{
|
||||
Assert(rgb[i] >= 0 && rgb[i] <= 255);
|
||||
radar_iff_color[0][1][i] = rgb[i];
|
||||
radar_iff_color[0][0][i] = rgb[i]/2;
|
||||
}
|
||||
}
|
||||
|
||||
if ((optional_string("$Navbuoy Blip Color:")) || (optional_string("$Navbuoy Blip Colour:")))
|
||||
{
|
||||
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
|
||||
for (i=0;i<3;i++)
|
||||
{
|
||||
Assert(rgb[i] >= 0 && rgb[i] <= 255);
|
||||
radar_iff_color[1][1][i] = rgb[i];
|
||||
radar_iff_color[1][0][i] = rgb[i]/2;
|
||||
}
|
||||
}
|
||||
|
||||
if ((optional_string("$Warping Blip Color:")) || (optional_string("$Warping Blip Colour:")))
|
||||
{
|
||||
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
|
||||
for (i=0;i<3;i++)
|
||||
{
|
||||
Assert(rgb[i] >= 0 && rgb[i] <= 255);
|
||||
radar_iff_color[2][1][i] = rgb[i];
|
||||
radar_iff_color[2][0][i] = rgb[i]/2;
|
||||
}
|
||||
}
|
||||
|
||||
if ((optional_string("$Node Blip Color:")) || (optional_string("$Node Blip Colour:")))
|
||||
{
|
||||
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
|
||||
for (i=0;i<3;i++)
|
||||
{
|
||||
Assert(rgb[i] >= 0 && rgb[i] <= 255);
|
||||
radar_iff_color[3][1][i] = rgb[i];
|
||||
radar_iff_color[3][0][i] = rgb[i]/2;
|
||||
}
|
||||
}
|
||||
|
||||
if ((optional_string("$Tagged Blip Color:")) || (optional_string("$Tagged Blip Colour:")))
|
||||
{
|
||||
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
|
||||
for (i=0;i<3;i++)
|
||||
{
|
||||
Assert(rgb[i] >= 0 && rgb[i] <= 255);
|
||||
radar_iff_color[4][1][i] = rgb[i];
|
||||
radar_iff_color[4][0][i] = rgb[i]/2;
|
||||
}
|
||||
}
|
||||
|
||||
if (alternate_blip_color == true)
|
||||
{
|
||||
a_bright = iff_get_alpha_value(true);
|
||||
a_dim = iff_get_alpha_value(false);
|
||||
for (i=0;i<5;i++)
|
||||
{
|
||||
if (radar_iff_color[i][0][0] >= 0)
|
||||
{
|
||||
for (j=0;j<3;j++)
|
||||
{
|
||||
radar_iff_color[i][0][j] = radar_iff_color[i][1][j];
|
||||
}
|
||||
|
||||
radar_iff_color[i][1][3] = a_bright;
|
||||
radar_iff_color[i][0][3] = a_dim;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0;i<5;i++)
|
||||
{
|
||||
if (radar_iff_color[i][0][0] >= 0)
|
||||
{
|
||||
radar_iff_color[i][0][3] = 255;
|
||||
radar_iff_color[i][1][3] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Radar Target ID Flags:")) {
|
||||
parse_string_flag_list((int*)&radar_target_id_flags, rti_flags, Num_rti_flags);
|
||||
if (optional_string("+reset"))
|
||||
radar_target_id_flags = 0;
|
||||
}
|
||||
|
||||
// begin reading data
|
||||
Num_iffs = 0;
|
||||
while (required_string_either("#End", "$IFF Name:"))
|
||||
{
|
||||
iff_info *iff;
|
||||
int cur_iff;
|
||||
|
||||
// make sure we're under the limit
|
||||
if (Num_iffs >= MAX_IFFS)
|
||||
{
|
||||
Warning(LOCATION, "Too many iffs in iffs_defs.tbl! Max is %d.\n", MAX_IFFS);
|
||||
skip_to_start_of_string("#End", NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
// add new IFF
|
||||
iff = &Iff_info[Num_iffs];
|
||||
cur_iff = Num_iffs;
|
||||
Num_iffs++;
|
||||
|
||||
|
||||
// get required IFF info ----------------------------------------------
|
||||
|
||||
// get the iff name
|
||||
required_string("$IFF Name:");
|
||||
stuff_string(iff->iff_name, F_NAME, NAME_LENGTH);
|
||||
|
||||
// get the iff color
|
||||
if (check_for_string("$Colour:"))
|
||||
required_string("$Colour:");
|
||||
else
|
||||
required_string("$Color:");
|
||||
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
|
||||
iff->color_index = iff_init_color(rgb[0], rgb[1], rgb[2]);
|
||||
|
||||
|
||||
// get relationships between IFFs -------------------------------------
|
||||
|
||||
// get the list of iffs attacked
|
||||
if (optional_string("$Attacks:"))
|
||||
num_attack_names[cur_iff] = stuff_string_list(attack_names[cur_iff], MAX_IFFS);
|
||||
else
|
||||
num_attack_names[cur_iff] = 0;
|
||||
|
||||
// get the list of observed colors
|
||||
num_observed_colors[cur_iff] = 0;
|
||||
while (optional_string("+Sees"))
|
||||
{
|
||||
// get iff observed
|
||||
stuff_string_until(observed_color_table[cur_iff][num_observed_colors[cur_iff]].iff_name, "As:", NAME_LENGTH);
|
||||
required_string("As:");
|
||||
|
||||
// get color observed
|
||||
stuff_int_list(rgb, 3, RAW_INTEGER_TYPE);
|
||||
observed_color_table[cur_iff][num_observed_colors[cur_iff]].color_index = iff_init_color(rgb[0], rgb[1], rgb[2]);
|
||||
|
||||
// increment
|
||||
num_observed_colors[cur_iff]++;
|
||||
}
|
||||
|
||||
|
||||
// get flags ----------------------------------------------------------
|
||||
|
||||
// get iff flags
|
||||
iff->flags = 0;
|
||||
if (optional_string("$Flags:"))
|
||||
{
|
||||
char flag_strings[MAX_IFF_FLAGS][NAME_LENGTH];
|
||||
|
||||
int num_strings = stuff_string_list(flag_strings, MAX_IFF_FLAGS);
|
||||
for (string_idx = 0; string_idx < num_strings; string_idx++)
|
||||
{
|
||||
if (!stricmp(NOX("support allowed"), flag_strings[string_idx]))
|
||||
iff->flags |= IFFF_SUPPORT_ALLOWED;
|
||||
else if (!stricmp(NOX("exempt from all teams at war"), flag_strings[string_idx]))
|
||||
iff->flags |= IFFF_EXEMPT_FROM_ALL_TEAMS_AT_WAR;
|
||||
else if (!stricmp(NOX("orders hidden"), flag_strings[string_idx]))
|
||||
iff->flags |= IFFF_ORDERS_HIDDEN;
|
||||
else if (!stricmp(NOX("orders shown"), flag_strings[string_idx]))
|
||||
iff->flags |= IFFF_ORDERS_SHOWN;
|
||||
else if (!stricmp(NOX("wing name hidden"), flag_strings[string_idx]))
|
||||
iff->flags |= IFFF_WING_NAME_HIDDEN;
|
||||
else
|
||||
Warning(LOCATION, "Bogus string in iff flags: %s\n", flag_strings[string_idx]);
|
||||
}
|
||||
}
|
||||
|
||||
// get default ship flags
|
||||
iff->default_parse_flags = 0;
|
||||
if (optional_string("$Default Ship Flags:"))
|
||||
{
|
||||
i = 0;
|
||||
j = 0;
|
||||
char flag_strings[MAX_PARSE_OBJECT_FLAGS][NAME_LENGTH];
|
||||
int num_strings = stuff_string_list(flag_strings, MAX_PARSE_OBJECT_FLAGS);
|
||||
for (i = 0; i < num_strings; i++)
|
||||
{
|
||||
for (j = 0; j < MAX_PARSE_OBJECT_FLAGS; j++)
|
||||
{
|
||||
if (!stricmp(flag_strings[i], Parse_object_flags[j]))
|
||||
{
|
||||
iff->default_parse_flags |= (1 << j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (j == MAX_PARSE_OBJECT_FLAGS)
|
||||
Warning(LOCATION, "Bogus string in iff default ship flags: %s\n", flag_strings[i]);
|
||||
}
|
||||
|
||||
// again
|
||||
iff->default_parse_flags2 = 0;
|
||||
if (optional_string("$Default Ship Flags2:"))
|
||||
{
|
||||
i = 0;
|
||||
j = 0;
|
||||
char flag_strings[MAX_PARSE_OBJECT_FLAGS_2][NAME_LENGTH];
|
||||
int num_strings = stuff_string_list(flag_strings, MAX_PARSE_OBJECT_FLAGS_2);
|
||||
for (i = 0; i < num_strings; i++)
|
||||
{
|
||||
for (j = 0; j < MAX_PARSE_OBJECT_FLAGS_2; j++)
|
||||
{
|
||||
if (!stricmp(flag_strings[i], Parse_object_flags_2[j]))
|
||||
{
|
||||
iff->default_parse_flags2 |= (1 << j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (j == MAX_PARSE_OBJECT_FLAGS_2)
|
||||
Warning(LOCATION, "Bogus string in iff default ship flags2: %s\n", flag_strings[i]);
|
||||
}
|
||||
|
||||
// this is cleared between each level but let's just set it here for thoroughness
|
||||
iff->ai_rearm_timestamp = timestamp(-1);
|
||||
}
|
||||
|
||||
required_string("#End");
|
||||
|
||||
|
||||
// now resolve the relationships ------------------------------------------
|
||||
|
||||
// first get the traitor
|
||||
Iff_traitor = iff_lookup(traitor_name);
|
||||
if (Iff_traitor < 0)
|
||||
{
|
||||
Iff_traitor = 0;
|
||||
Warning(LOCATION, "Traitor IFF %s not found in iff_defs.tbl! Defaulting to %s.\n", traitor_name, Iff_info[Iff_traitor].iff_name);
|
||||
}
|
||||
|
||||
// next get the attackees and colors
|
||||
for (int cur_iff = 0; cur_iff < Num_iffs; cur_iff++)
|
||||
{
|
||||
iff_info *iff = &Iff_info[cur_iff];
|
||||
|
||||
// clear the iffs to be attacked
|
||||
iff->attackee_bitmask = 0;
|
||||
iff->attackee_bitmask_all_teams_at_war = 0;
|
||||
|
||||
// clear the observed colors
|
||||
for (j = 0; j < MAX_IFFS; j++)
|
||||
iff->observed_color_index[j] = -1;
|
||||
|
||||
// resolve the list names
|
||||
for (int list_index = 0; list_index < MAX_IFFS; list_index++)
|
||||
{
|
||||
// are we within the number of attackees listed?
|
||||
if (list_index < num_attack_names[cur_iff])
|
||||
{
|
||||
// find out who
|
||||
int target_iff = iff_lookup(attack_names[cur_iff][list_index]);
|
||||
|
||||
// valid?
|
||||
if (target_iff >= 0)
|
||||
iff->attackee_bitmask |= iff_get_mask(target_iff);
|
||||
else
|
||||
Warning(LOCATION, "Attack target IFF %s not found for IFF %s in iff_defs.tbl!\n", attack_names[cur_iff][list_index], iff->iff_name);
|
||||
}
|
||||
|
||||
// are we within the number of colors listed?
|
||||
if (list_index < num_observed_colors[cur_iff])
|
||||
{
|
||||
// find out who
|
||||
int target_iff = iff_lookup(observed_color_table[cur_iff][list_index].iff_name);
|
||||
|
||||
// valid?
|
||||
if (target_iff >= 0)
|
||||
iff->observed_color_index[target_iff] = observed_color_table[cur_iff][list_index].color_index;
|
||||
else
|
||||
Warning(LOCATION, "Observed color IFF %s not found for IFF %s in iff_defs.tbl!\n", observed_color_table[cur_iff][list_index].iff_name, iff->iff_name);
|
||||
}
|
||||
}
|
||||
|
||||
// resolve the all teams at war relationships
|
||||
if (iff->flags & IFFF_EXEMPT_FROM_ALL_TEAMS_AT_WAR)
|
||||
{
|
||||
// exempt, so use standard attacks
|
||||
iff->attackee_bitmask_all_teams_at_war = iff->attackee_bitmask;
|
||||
}
|
||||
else
|
||||
{
|
||||
// nonexempt, so build bitmask of all other nonexempt teams
|
||||
for (int other_iff = 0; other_iff < Num_iffs; other_iff++)
|
||||
{
|
||||
// skip myself (unless I attack myself normally)
|
||||
if ((other_iff == cur_iff) && !iff_x_attacks_y(cur_iff, cur_iff))
|
||||
continue;
|
||||
|
||||
// skip anyone exempt
|
||||
if (Iff_info[other_iff].flags & IFFF_EXEMPT_FROM_ALL_TEAMS_AT_WAR)
|
||||
continue;
|
||||
|
||||
// add everyone else
|
||||
iff->attackee_bitmask_all_teams_at_war |= iff_get_mask(other_iff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add tbl/tbm to multiplayer validation list
|
||||
extern void fs2netd_add_table_validation(const char *tblname);
|
||||
fs2netd_add_table_validation("iff_defs.tbl");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+11
-1
@@ -41,6 +41,7 @@
|
||||
#define LAB_FLAG_FULLY_LOAD (1<<5) // use create_ship() to test the ships
|
||||
#define LAB_FLAG_SHOW_WEAPONS (1<<6) // determines if external weapons models are displayed
|
||||
#define LAB_FLAG_INITIAL_ROTATION (1<<7) // initial rotation setting
|
||||
#define LAB_FLAG_DESTROYED_SUBSYSTEMS (1<<8) // render model as if all subsystems are destroyed
|
||||
|
||||
// modes
|
||||
#define LAB_MODE_NONE 0 // not showing anything
|
||||
@@ -684,7 +685,7 @@ void labviewer_add_model_thrusters(ship_info *sip)
|
||||
mst.distortion_bitmap = thruster_distortion_bitmap;
|
||||
|
||||
mst.use_ab = Lab_thrust_afterburn;
|
||||
mst.glow_noise = thruster_glow_noise;
|
||||
mst.glow_noise = thruster_glow_noise * sip->thruster_glow_noise_mult;
|
||||
mst.rotvel = &vmd_zero_vector;
|
||||
|
||||
if (Lab_mode == LAB_MODE_SHIP) {
|
||||
@@ -904,6 +905,13 @@ void labviewer_render_model(float frametime)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sip != NULL) {
|
||||
if (Lab_viewer_flags & LAB_FLAG_DESTROYED_SUBSYSTEMS) {
|
||||
model_show_damaged(Lab_model_num, 1);
|
||||
}
|
||||
}
|
||||
|
||||
opengl_shader_set_animated_effect(ANIMATED_SHADER_LOADOUTSELECT_FS1);
|
||||
opengl_shader_set_animated_timer(MIN((timer_get_milliseconds()-anim_timer_start)/1500.0f,2.0f));
|
||||
|
||||
@@ -1855,6 +1863,7 @@ void labviewer_make_render_options_window(Button *caller)
|
||||
ADD_RENDER_FLAG("Animated Shader", Lab_model_flags, MR_ANIMATED_SHADER);
|
||||
ADD_RENDER_FLAG("Show Ship Weapons", Lab_viewer_flags, LAB_FLAG_SHOW_WEAPONS);
|
||||
ADD_RENDER_FLAG("Initial Rotation", Lab_viewer_flags, LAB_FLAG_INITIAL_ROTATION);
|
||||
ADD_RENDER_FLAG("Show Destroyed Subsystems", Lab_viewer_flags, LAB_FLAG_DESTROYED_SUBSYSTEMS);
|
||||
|
||||
|
||||
// start tree
|
||||
@@ -2234,6 +2243,7 @@ void labviewer_make_weap_window(Button* caller)
|
||||
delete type_nodes[i];
|
||||
}
|
||||
}
|
||||
delete[] type_nodes;
|
||||
|
||||
Lab_mode = LAB_MODE_WEAPON;
|
||||
|
||||
|
||||
+22
-19
@@ -142,32 +142,35 @@ bool ScreenClassInfoEntry::Parse()
|
||||
|
||||
void GUISystem::ParseClassInfo(char* filename)
|
||||
{
|
||||
int rval;
|
||||
|
||||
if (ClassInfoParsed) {
|
||||
Warning(LOCATION, "Class info is being parsed twice");
|
||||
DestroyClassInfo();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
read_file_text(filename);
|
||||
reset_parse();
|
||||
ScreenClassInfo.Parse();
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("WMCGUI: Unable to parse '%s'! Error code = %i.\n", filename, rval));
|
||||
bool flag;
|
||||
do {
|
||||
ScreenClassInfoEntry* sciep = new ScreenClassInfoEntry;
|
||||
flag = sciep->Parse();
|
||||
if (flag) {
|
||||
list_append(&ScreenClassInfo, sciep);
|
||||
} else {
|
||||
delete sciep;
|
||||
}
|
||||
} while (flag);
|
||||
|
||||
ClassInfoParsed = true;
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("WMCGUI: Unable to parse '%s'! Error code = %s.\n", filename, e.what()));
|
||||
return;
|
||||
}
|
||||
|
||||
read_file_text(filename);
|
||||
reset_parse();
|
||||
ScreenClassInfo.Parse();
|
||||
|
||||
bool flag;
|
||||
do {
|
||||
ScreenClassInfoEntry* sciep = new ScreenClassInfoEntry;
|
||||
flag = sciep->Parse();
|
||||
if (flag) {
|
||||
list_append(&ScreenClassInfo, sciep);
|
||||
}
|
||||
} while(flag);
|
||||
|
||||
ClassInfoParsed = true;
|
||||
}
|
||||
|
||||
void ClassInfoEntry::Parse(char* tag, int in_type)
|
||||
|
||||
@@ -112,7 +112,6 @@ void lcl_init(int lang_init)
|
||||
char lang_string[128];
|
||||
const char *ret;
|
||||
int lang, idx, i;
|
||||
int rval;
|
||||
|
||||
// initialize encryption
|
||||
encrypt_init();
|
||||
@@ -121,12 +120,14 @@ void lcl_init(int lang_init)
|
||||
Lcl_languages.push_back(Lcl_builtin_languages[FS2_OPEN_DEFAULT_LANGUAGE]);
|
||||
|
||||
// check string.tbl to see which languages we support
|
||||
if ( (rval = setjmp(parse_abort)) != 0 ) {
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", "strings.tbl", rval));
|
||||
}
|
||||
else {
|
||||
try
|
||||
{
|
||||
parse_stringstbl_quick("strings.tbl");
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "strings.tbl", e.what()));
|
||||
}
|
||||
|
||||
parse_modular_table(NOX("*-lcl.tbm"), parse_stringstbl_quick);
|
||||
|
||||
@@ -407,7 +408,7 @@ void parse_tstringstbl(const char *filename)
|
||||
// initialize the xstr table
|
||||
void lcl_xstr_init()
|
||||
{
|
||||
int i, rval;
|
||||
int i;
|
||||
|
||||
|
||||
for (i = 0; i < XSTR_SIZE; i++)
|
||||
@@ -417,18 +418,26 @@ void lcl_xstr_init()
|
||||
Lcl_ext_str[i] = NULL;
|
||||
|
||||
|
||||
if ( (rval = setjmp(parse_abort)) != 0 )
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", "strings.tbl", rval));
|
||||
else
|
||||
try
|
||||
{
|
||||
parse_stringstbl("strings.tbl");
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "strings.tbl", e.what()));
|
||||
}
|
||||
|
||||
parse_modular_table(NOX("*-lcl.tbm"), parse_stringstbl);
|
||||
|
||||
|
||||
if ( (rval = setjmp(parse_abort)) != 0 )
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", "tstrings.tbl", rval));
|
||||
else
|
||||
try
|
||||
{
|
||||
parse_tstringstbl("tstrings.tbl");
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "tstrings.tbl", e.what()));
|
||||
}
|
||||
|
||||
parse_modular_table(NOX("*-tlc.tbm"), parse_tstringstbl);
|
||||
|
||||
@@ -1209,7 +1218,7 @@ void lcl_translate_brief_icon_name_gr(char *name)
|
||||
|
||||
} else if ((pos = strstr(name, "Transport")) != NULL) {
|
||||
pos += 9; // strlen of "transport"
|
||||
strcpy_s(buf, "Transportowiec");
|
||||
strcpy_s(buf, "Transporter");
|
||||
strcat_s(buf, pos);
|
||||
strcpy(name, buf);
|
||||
|
||||
@@ -1356,7 +1365,7 @@ char buf[128];
|
||||
|
||||
} else if ((pos = strstr(name, "Transport")) != NULL) {
|
||||
pos += 9; // strlen of "transport"
|
||||
strcpy_s(buf, "Transporter");
|
||||
strcpy_s(buf, "Transportowiec");
|
||||
strcat_s(buf, pos);
|
||||
strcpy(name, buf);
|
||||
|
||||
|
||||
@@ -225,7 +225,7 @@ vec3d *vm_vec_avg4(vec3d *dest,vec3d *src0,vec3d *src1,vec3d *src2,vec3d *src3)
|
||||
}
|
||||
|
||||
|
||||
//scales a vector in place. returns ptr to vector
|
||||
//scales a vector in place.
|
||||
#ifndef _INLINE_VECMAT
|
||||
void vm_vec_scale(vec3d *dest,float s)
|
||||
{
|
||||
@@ -236,7 +236,7 @@ void vm_vec_scale(vec3d *dest,float s)
|
||||
#endif
|
||||
|
||||
|
||||
//scales and copies a vector. returns ptr to dest
|
||||
//scales and copies a vector.
|
||||
#ifndef _INLINE_VECMAT
|
||||
void vm_vec_copy_scale(vec3d *dest,vec3d *src,float s)
|
||||
{
|
||||
@@ -288,7 +288,7 @@ void vm_vec_scale_sub2(vec3d *dest,vec3d *src,float k)
|
||||
}
|
||||
#endif
|
||||
|
||||
//scales a vector in place, taking n/d for scale. returns ptr to vector
|
||||
//scales a vector in place, taking n/d for scale.
|
||||
//dest *= n/d
|
||||
#ifndef _INLINE_VECMAT
|
||||
void vm_vec_scale2(vec3d *dest,float n,float d)
|
||||
|
||||
+126
-131
@@ -35,9 +35,9 @@
|
||||
char *fs2_open_credit_text =
|
||||
"SOURCE CODE PROJECT STAFF:\n"
|
||||
"\n"
|
||||
"Project Leaders:\n"
|
||||
"Project Leader:\n"
|
||||
"\n"
|
||||
"Cliff \"chief1983\" Gordon\n"
|
||||
"Fabian \"The E\" Woltermann\n"
|
||||
"\n"
|
||||
"Senior Advisors:\n"
|
||||
"\n"
|
||||
@@ -45,6 +45,7 @@ char *fs2_open_credit_text =
|
||||
"Michael \"Zacam\" LaFleur\n"
|
||||
"Taylor Richards\n"
|
||||
"Edward \"Inquisitor\" Gardner\n"
|
||||
"Cliff \"chief1983\" Gordon\n"
|
||||
"\n"
|
||||
"Programmers:\n"
|
||||
"\n"
|
||||
@@ -52,19 +53,13 @@ char *fs2_open_credit_text =
|
||||
"Derek \"Kazan\" Meek\n"
|
||||
"Nick \"phreak\" Iannetta\n"
|
||||
"Mike \"Bobboau\" Abegg\n"
|
||||
"Backslash\n"
|
||||
"Echelon9\n"
|
||||
"Flaming_Sword\n"
|
||||
"FUBAR\n"
|
||||
"Iss Mneur\n"
|
||||
"kkmic\n"
|
||||
"Shade\n"
|
||||
"Soulstorm\n"
|
||||
"Sushi\n"
|
||||
"Swifty\n"
|
||||
"Wanderer\n"
|
||||
"Fabian \"The E\" Woltermann\n"
|
||||
"CommanderDJ\n"
|
||||
"Backslash, Echelon9, Flaming_Sword\n"
|
||||
"FUBAR, Iss Mneur, kkmic\n"
|
||||
"Shade, Soulstorm, Sushi\n"
|
||||
"Swifty, Wanderer, CommanderDJ\n"
|
||||
"Valathil, MageKing17, Yarn\n"
|
||||
"m!m, z64555, zookeeper\n"
|
||||
"jg18, niffiwan\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"Readme Staff:\n"
|
||||
@@ -284,133 +279,133 @@ int credits_screen_button_pressed(int n)
|
||||
}
|
||||
|
||||
void credits_parse_table(const char* filename)
|
||||
{
|
||||
int rval;
|
||||
{
|
||||
try
|
||||
{
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", filename, rval));
|
||||
return;
|
||||
}
|
||||
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
// any metadata?
|
||||
if (optional_string("$Music:"))
|
||||
{
|
||||
stuff_string(Credits_music_name, F_NAME, NAME_LENGTH);
|
||||
}
|
||||
if (optional_string("$Number of Images:"))
|
||||
{
|
||||
int temp;
|
||||
stuff_int(&temp);
|
||||
if (temp > 0)
|
||||
Credits_num_images = temp;
|
||||
}
|
||||
if (optional_string("$Start Image Index:"))
|
||||
{
|
||||
stuff_int(&Credits_artwork_index);
|
||||
|
||||
// bounds check
|
||||
if (Credits_artwork_index < 0)
|
||||
// any metadata?
|
||||
if (optional_string("$Music:"))
|
||||
{
|
||||
Credits_artwork_index = 0;
|
||||
stuff_string(Credits_music_name, F_NAME, NAME_LENGTH);
|
||||
}
|
||||
else if (Credits_artwork_index >= Credits_num_images)
|
||||
if (optional_string("$Number of Images:"))
|
||||
{
|
||||
Credits_artwork_index = Credits_num_images - 1;
|
||||
int temp;
|
||||
stuff_int(&temp);
|
||||
if (temp > 0)
|
||||
Credits_num_images = temp;
|
||||
}
|
||||
}
|
||||
if (optional_string("$Text scroll rate:"))
|
||||
{
|
||||
stuff_float(&Credits_scroll_rate);
|
||||
if (Credits_scroll_rate < 0.01f)
|
||||
Credits_scroll_rate = 0.01f;
|
||||
}
|
||||
if (optional_string("$Artworks display time:"))
|
||||
{
|
||||
stuff_float(&Credits_artwork_display_time);
|
||||
if (Credits_artwork_display_time < 0.01f)
|
||||
Credits_artwork_display_time = 0.01f;
|
||||
}
|
||||
if (optional_string("$Artworks fade time:"))
|
||||
{
|
||||
stuff_float(&Credits_artwork_fade_time);
|
||||
if (Credits_artwork_fade_time < 0.01f)
|
||||
Credits_artwork_fade_time = 0.01f;
|
||||
}
|
||||
if (optional_string("$SCP Credits position:"))
|
||||
{
|
||||
char mode[NAME_LENGTH];
|
||||
|
||||
stuff_string(mode, F_NAME, NAME_LENGTH);
|
||||
|
||||
if (!stricmp(mode, "Start"))
|
||||
SCP_credits_position = START;
|
||||
else if (!stricmp(mode, "End"))
|
||||
SCP_credits_position = END;
|
||||
else
|
||||
Warning(LOCATION, "Unknown credits position mode \"%s\".", mode);
|
||||
}
|
||||
|
||||
ignore_white_space();
|
||||
|
||||
SCP_string credits_text;
|
||||
SCP_string line;
|
||||
|
||||
SCP_vector<int> charNum;
|
||||
SCP_vector<const char*> lines;
|
||||
int numLines = -1;
|
||||
|
||||
bool first_run = true;
|
||||
while(!check_for_string_raw("#end"))
|
||||
{
|
||||
// Read in a line of text
|
||||
stuff_string_line(line);
|
||||
|
||||
// This is a bit odd but it means if a total conversion uses different credits the
|
||||
// Volition credit won't happen
|
||||
// Also don't append the default credits anymore when there was already a parsed table
|
||||
if(first_run && !Credits_parsed && !line.compare(mod_check))
|
||||
if (optional_string("$Start Image Index:"))
|
||||
{
|
||||
credits_text.append(unmodified_credits);
|
||||
}
|
||||
stuff_int(&Credits_artwork_index);
|
||||
|
||||
first_run = false;
|
||||
|
||||
if (line.empty())
|
||||
{
|
||||
// If the line is empty then just append a newline, don't bother with splitting it first
|
||||
credits_text.append("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// split_str doesn't take care of this.
|
||||
charNum.clear();
|
||||
|
||||
// Split the string into multiple lines if it's too long
|
||||
numLines = split_str(line.c_str(), Credits_text_coords[gr_screen.res][2], charNum, lines, -1);
|
||||
|
||||
// Make sure that we have valid data
|
||||
Assertion(lines.size() == (size_t) numLines, "split_str reported %d lines but vector contains %d entries!", numLines, lines.size());
|
||||
|
||||
Assertion(lines.size() <= charNum.size(),
|
||||
"Something has gone wrong while splitting strings. Got %d lines but only %d chacter lengths.",
|
||||
lines.size(), charNum.size());
|
||||
|
||||
// Now add all splitted lines to the credit text and append a newline to the end
|
||||
for (int i = 0; i < numLines; i++)
|
||||
// bounds check
|
||||
if (Credits_artwork_index < 0)
|
||||
{
|
||||
credits_text.append(SCP_string(lines[i], charNum[i]));
|
||||
credits_text.append("\n");
|
||||
Credits_artwork_index = 0;
|
||||
}
|
||||
else if (Credits_artwork_index >= Credits_num_images)
|
||||
{
|
||||
Credits_artwork_index = Credits_num_images - 1;
|
||||
}
|
||||
}
|
||||
if (optional_string("$Text scroll rate:"))
|
||||
{
|
||||
stuff_float(&Credits_scroll_rate);
|
||||
if (Credits_scroll_rate < 0.01f)
|
||||
Credits_scroll_rate = 0.01f;
|
||||
}
|
||||
if (optional_string("$Artworks display time:"))
|
||||
{
|
||||
stuff_float(&Credits_artwork_display_time);
|
||||
if (Credits_artwork_display_time < 0.01f)
|
||||
Credits_artwork_display_time = 0.01f;
|
||||
}
|
||||
if (optional_string("$Artworks fade time:"))
|
||||
{
|
||||
stuff_float(&Credits_artwork_fade_time);
|
||||
if (Credits_artwork_fade_time < 0.01f)
|
||||
Credits_artwork_fade_time = 0.01f;
|
||||
}
|
||||
if (optional_string("$SCP Credits position:"))
|
||||
{
|
||||
char mode[NAME_LENGTH];
|
||||
|
||||
stuff_string(mode, F_NAME, NAME_LENGTH);
|
||||
|
||||
if (!stricmp(mode, "Start"))
|
||||
SCP_credits_position = START;
|
||||
else if (!stricmp(mode, "End"))
|
||||
SCP_credits_position = END;
|
||||
else
|
||||
Warning(LOCATION, "Unknown credits position mode \"%s\".", mode);
|
||||
}
|
||||
|
||||
ignore_white_space();
|
||||
|
||||
SCP_string credits_text;
|
||||
SCP_string line;
|
||||
|
||||
SCP_vector<int> charNum;
|
||||
SCP_vector<const char*> lines;
|
||||
int numLines = -1;
|
||||
|
||||
bool first_run = true;
|
||||
while (!check_for_string_raw("#end"))
|
||||
{
|
||||
// Read in a line of text
|
||||
stuff_string_line(line);
|
||||
|
||||
// This is a bit odd but it means if a total conversion uses different credits the
|
||||
// Volition credit won't happen
|
||||
// Also don't append the default credits anymore when there was already a parsed table
|
||||
if (first_run && !Credits_parsed && !line.compare(mod_check))
|
||||
{
|
||||
credits_text.append(unmodified_credits);
|
||||
}
|
||||
|
||||
first_run = false;
|
||||
|
||||
if (line.empty())
|
||||
{
|
||||
// If the line is empty then just append a newline, don't bother with splitting it first
|
||||
credits_text.append("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// split_str doesn't take care of this.
|
||||
charNum.clear();
|
||||
|
||||
// Split the string into multiple lines if it's too long
|
||||
numLines = split_str(line.c_str(), Credits_text_coords[gr_screen.res][2], charNum, lines, -1);
|
||||
|
||||
// Make sure that we have valid data
|
||||
Assertion(lines.size() == (size_t)numLines, "split_str reported %d lines but vector contains %d entries!", numLines, lines.size());
|
||||
|
||||
Assertion(lines.size() <= charNum.size(),
|
||||
"Something has gone wrong while splitting strings. Got %d lines but only %d chacter lengths.",
|
||||
lines.size(), charNum.size());
|
||||
|
||||
// Now add all splitted lines to the credit text and append a newline to the end
|
||||
for (int i = 0; i < numLines; i++)
|
||||
{
|
||||
credits_text.append(SCP_string(lines[i], charNum[i]));
|
||||
credits_text.append("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Credit_text_parts.push_back(credits_text);
|
||||
|
||||
Credits_parsed = true;
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", filename, e.what()));
|
||||
return;
|
||||
}
|
||||
|
||||
Credit_text_parts.push_back(credits_text);
|
||||
|
||||
Credits_parsed = true;
|
||||
}
|
||||
|
||||
void credits_parse()
|
||||
|
||||
+424
-406
@@ -59,7 +59,9 @@ extern void game_process_cheats(int k);
|
||||
|
||||
SCP_vector< SCP_vector<main_hall_defines> > Main_hall_defines;
|
||||
|
||||
main_hall_defines *Main_hall = NULL;
|
||||
static main_hall_defines *Main_hall = NULL;
|
||||
|
||||
static int Main_hall_music_index = -1;
|
||||
|
||||
int Vasudan_funny = 0;
|
||||
int Vasudan_funny_plate = -1;
|
||||
@@ -439,7 +441,7 @@ void main_hall_init(const SCP_string &main_hall_name)
|
||||
}
|
||||
|
||||
// if we're switching to a different mainhall we may need to change music
|
||||
if (main_hall_get_music_index(main_hall_get_index(main_hall_to_load)) != main_hall_get_music_index(main_hall_id())) {
|
||||
if (main_hall_get_music_index(main_hall_get_index(main_hall_to_load)) != Main_hall_music_index) {
|
||||
main_hall_stop_music(true);
|
||||
}
|
||||
|
||||
@@ -447,8 +449,8 @@ void main_hall_init(const SCP_string &main_hall_name)
|
||||
snazzy_menu_init();
|
||||
|
||||
// assign the proper main hall data
|
||||
Assert(main_hall_get_pointer(main_hall_to_load) != NULL);
|
||||
Main_hall = main_hall_get_pointer(main_hall_to_load);
|
||||
Assertion(Main_hall != NULL, "Failed to obtain pointer to main hall '%s'; get a coder!\n", main_hall_to_load.c_str());
|
||||
|
||||
// check if we have to change the ready room's description
|
||||
if(Main_hall->default_readyroom) {
|
||||
@@ -1138,7 +1140,6 @@ int main_hall_get_music_index(int main_hall_num)
|
||||
*/
|
||||
void main_hall_start_music()
|
||||
{
|
||||
int index;
|
||||
char *filename;
|
||||
|
||||
// start a looping ambient sound
|
||||
@@ -1155,13 +1156,13 @@ void main_hall_start_music()
|
||||
}
|
||||
|
||||
// get music
|
||||
index = main_hall_get_music_index(main_hall_id());
|
||||
if (index < 0) {
|
||||
Main_hall_music_index = main_hall_get_music_index(main_hall_id());
|
||||
if (Main_hall_music_index < 0) {
|
||||
nprintf(("Warning", "No music file exists to play music at the main menu!\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
filename = Spooled_music[index].filename;
|
||||
filename = Spooled_music[Main_hall_music_index].filename;
|
||||
Assert(filename != NULL);
|
||||
|
||||
// get handle
|
||||
@@ -2078,415 +2079,432 @@ void parse_main_hall_table(const char* filename)
|
||||
{
|
||||
SCP_vector<main_hall_defines> temp_vector;
|
||||
main_hall_defines *m, temp;
|
||||
int idx, s_idx, m_idx, rval;
|
||||
int idx, s_idx, m_idx;
|
||||
int num_resolutions = 2;
|
||||
unsigned int count;
|
||||
char temp_string[MAX_FILENAME_LEN];
|
||||
SCP_string temp_scp_string;
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", filename, rval));
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
reset_parse();
|
||||
|
||||
if (optional_string("$Num Resolutions:")) {
|
||||
stuff_int(&num_resolutions);
|
||||
}
|
||||
|
||||
if (num_resolutions < 1) {
|
||||
Error(LOCATION, "$Num Resolutions in %s is %d. (Must be 1 or greater)", filename, num_resolutions);
|
||||
}
|
||||
|
||||
// go for it
|
||||
count = Main_hall_defines.size();
|
||||
while (!optional_string("#end")) {
|
||||
Main_hall_defines.push_back(temp_vector);
|
||||
// read in all resolutions
|
||||
for (m_idx = 0; m_idx < num_resolutions; m_idx++) {
|
||||
Main_hall_defines.at(count).push_back(temp);
|
||||
m = &Main_hall_defines.at(count).at(m_idx);
|
||||
|
||||
// ready
|
||||
required_string("$Main Hall");
|
||||
|
||||
// Parse the entry name for the first resolution, checking for duplicates and erroring if necessary
|
||||
if (m_idx == 0) {
|
||||
if (optional_string("+Name:")) {
|
||||
stuff_string(temp_string, F_RAW, MAX_FILENAME_LEN);
|
||||
|
||||
// we can't have two mainhalls with the same name
|
||||
if (main_hall_get_pointer(temp_string) == NULL) {
|
||||
m->name = temp_string;
|
||||
} else {
|
||||
Error(LOCATION, "A mainhall with the name '%s' already exists. All mainhalls must have unique names.", temp_string);
|
||||
}
|
||||
} else {
|
||||
snprintf(temp_string, MAX_FILENAME_LEN, "%d", count);
|
||||
m->name = temp_string;
|
||||
}
|
||||
} else {
|
||||
if (optional_string("+Name:")) {
|
||||
stuff_string(temp_string, F_RAW, MAX_FILENAME_LEN);
|
||||
|
||||
/**
|
||||
* the reason that this is an error is that even if we were to change the names to match
|
||||
* it is very likely the user would get the wrong mainhall loaded since their campaign files
|
||||
* may still refer to the entry with the incorrect name
|
||||
*/
|
||||
if (strcmp(temp_string, Main_hall_defines.at(count).at(0).name.c_str()) != 0) {
|
||||
Error(LOCATION, "The mainhall '%s' has different names for different resolutions. All resolutions must have the same name. Either remove the hi-res entries' names entirely or set them to match the first resolution entry's name.", Main_hall_defines.at(0).at(count).name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
m->name = Main_hall_defines.at(count).at(0).name;
|
||||
}
|
||||
|
||||
// add cheats
|
||||
while (optional_string("+Cheat String:")) {
|
||||
stuff_string(temp_scp_string, F_RAW);
|
||||
m->cheat.push_back(temp_scp_string);
|
||||
|
||||
if(temp_scp_string.size() > MAIN_HALL_MAX_CHEAT_LEN) {
|
||||
// Since the value is longer than the cheat buffer it will never match.
|
||||
|
||||
Warning(LOCATION, "The value '%s' for '+Cheat String:' is too long! It can be at most %d characters long.", temp_scp_string.size(), MAIN_HALL_MAX_CHEAT_LEN);
|
||||
}
|
||||
|
||||
required_string("+Anim To Change:");
|
||||
stuff_string(temp_scp_string, F_NAME);
|
||||
m->cheat_anim_from.push_back(temp_scp_string);
|
||||
|
||||
required_string("+Anim To Change To:");
|
||||
stuff_string(temp_scp_string, F_NAME);
|
||||
m->cheat_anim_to.push_back(temp_scp_string);
|
||||
}
|
||||
|
||||
// minimum resolution
|
||||
if (optional_string("+Min Resolution:")) {
|
||||
stuff_int(&m->min_width);
|
||||
stuff_int(&m->min_height);
|
||||
} else if (m_idx == 0) {
|
||||
m->min_width = 0;
|
||||
m->min_height = 0;
|
||||
} else {
|
||||
m->min_width = GR_1024_THRESHOLD_WIDTH;
|
||||
m->min_height = GR_1024_THRESHOLD_HEIGHT;
|
||||
}
|
||||
|
||||
// minimum aspect ratio
|
||||
if (optional_string("+Min Aspect Ratio:")) {
|
||||
stuff_float(&m->min_aspect_ratio);
|
||||
} else {
|
||||
m->min_aspect_ratio = 0.0f;
|
||||
}
|
||||
|
||||
// bitmap and mask
|
||||
required_string("+Bitmap:");
|
||||
stuff_string(temp_string, F_NAME, MAX_FILENAME_LEN);
|
||||
m->bitmap = temp_string;
|
||||
|
||||
required_string("+Mask:");
|
||||
stuff_string(temp_string, F_NAME, MAX_FILENAME_LEN);
|
||||
m->mask = temp_string;
|
||||
|
||||
required_string("+Music:");
|
||||
stuff_string(temp_string, F_NAME, MAX_FILENAME_LEN);
|
||||
m->music_name = temp_string;
|
||||
|
||||
// Goober5000
|
||||
if (optional_string("+Substitute Music:")) {
|
||||
stuff_string(temp_string, F_NAME, MAX_FILENAME_LEN);
|
||||
m->substitute_music_name = temp_string;
|
||||
}
|
||||
|
||||
if (optional_string("+Help Overlay:")) {
|
||||
stuff_string(temp_string, F_NAME, MAX_FILENAME_LEN);
|
||||
m->help_overlay_name = temp_string;
|
||||
}
|
||||
|
||||
if (optional_string("+Help Overlay Resolution Index:")) {
|
||||
stuff_int(&m->help_overlay_resolution_index);
|
||||
} else {
|
||||
m->help_overlay_resolution_index = m_idx;
|
||||
}
|
||||
|
||||
// zoom area
|
||||
if (optional_string("+Zoom To:")) {
|
||||
stuff_int(&m->zoom_area_width);
|
||||
stuff_int(&m->zoom_area_height);
|
||||
} else {
|
||||
m->zoom_area_width = -1;
|
||||
m->zoom_area_height = -1;
|
||||
}
|
||||
|
||||
// intercom sounds
|
||||
required_string("+Num Intercom Sounds:");
|
||||
stuff_int(&m->num_random_intercom_sounds);
|
||||
|
||||
// initialise intercom sounds vectors
|
||||
intercom_sounds_init(*m);
|
||||
|
||||
for (idx = 0; idx < m->num_random_intercom_sounds; idx++) {
|
||||
// intercom delay
|
||||
required_string("+Intercom delay:");
|
||||
stuff_int(&m->intercom_delay.at(idx).at(0));
|
||||
stuff_int(&m->intercom_delay.at(idx).at(1));
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_random_intercom_sounds; idx++) {
|
||||
// intercom sound id
|
||||
parse_sound("+Intercom sound:", &m->intercom_sounds.at(idx), "+Intercom sound:", PARSE_SOUND_INTERFACE_SOUND);
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_random_intercom_sounds; idx++) {
|
||||
// intercom pan
|
||||
required_string("+Intercom pan:");
|
||||
stuff_float(&m->intercom_sound_pan.at(idx));
|
||||
}
|
||||
|
||||
// misc animations
|
||||
required_string("+Num Misc Animations:");
|
||||
stuff_int(&m->num_misc_animations);
|
||||
|
||||
// initialise the misc anim vectors
|
||||
misc_anim_init(*m);
|
||||
|
||||
for (idx = 0; idx < m->num_misc_animations; idx++) {
|
||||
// anim names
|
||||
required_string("+Misc anim:");
|
||||
stuff_string(temp_string, F_NAME, MAX_FILENAME_LEN);
|
||||
m->misc_anim_name.at(idx) = (SCP_string)temp_string;
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_misc_animations; idx++) {
|
||||
// anim groups, optionally
|
||||
if (optional_string("+Misc anim group:")) {
|
||||
stuff_int(&m->misc_anim_group.at(idx));
|
||||
} else {
|
||||
m->misc_anim_group.at(idx) = -1;
|
||||
}
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_misc_animations; idx++) {
|
||||
// anim delay
|
||||
required_string("+Misc anim delay:");
|
||||
stuff_int(&m->misc_anim_delay.at(idx).at(0));
|
||||
stuff_int(&m->misc_anim_delay.at(idx).at(1));
|
||||
stuff_int(&m->misc_anim_delay.at(idx).at(2));
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_misc_animations; idx++) {
|
||||
// anim coords
|
||||
required_string("+Misc anim coords:");
|
||||
stuff_int(&m->misc_anim_coords.at(idx).at(0));
|
||||
stuff_int(&m->misc_anim_coords.at(idx).at(1));
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_misc_animations; idx++) {
|
||||
// anim mode
|
||||
required_string("+Misc anim mode:");
|
||||
stuff_int(&m->misc_anim_modes.at(idx));
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_misc_animations; idx++) {
|
||||
// anim pan
|
||||
required_string("+Misc anim pan:");
|
||||
stuff_float(&m->misc_anim_sound_pan.at(idx));
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_misc_animations; idx++) {
|
||||
// anim sound id
|
||||
parse_sound_list("+Misc anim sounds:", m->misc_anim_special_sounds.at(idx), "+Misc anim sounds:", PARSE_SOUND_INTERFACE_SOUND);
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_misc_animations; idx++) {
|
||||
// anim sound triggers
|
||||
required_string("+Misc anim trigger:");
|
||||
int temp_int = 0;
|
||||
stuff_int(&temp_int);
|
||||
for (s_idx = 0; s_idx < temp_int; s_idx++) {
|
||||
m->misc_anim_special_trigger.at(idx).push_back(0);
|
||||
stuff_int(&m->misc_anim_special_trigger.at(idx).at(s_idx));
|
||||
}
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_misc_animations; idx++) {
|
||||
// anim sound handles - deprecated, but deal with it just in case
|
||||
if (optional_string("+Misc anim handles:")) {
|
||||
advance_to_eoln(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_misc_animations; idx++) {
|
||||
// anim sound flags - table flag deprecated, so ignore user input
|
||||
if (optional_string("+Misc anim flags:")) {
|
||||
advance_to_eoln(NULL);
|
||||
}
|
||||
|
||||
// we need one flag for each sound
|
||||
Assert(m->misc_anim_special_sounds.at(idx).size() < INT_MAX);
|
||||
for (s_idx = 0; s_idx < (int)m->misc_anim_special_sounds.at(idx).size(); s_idx++) {
|
||||
m->misc_anim_sound_flag.at(idx).push_back(0);
|
||||
}
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_misc_animations; idx++) {
|
||||
// render over doors - default to false
|
||||
|
||||
if (optional_string("+Misc anim over doors:")) {
|
||||
bool temp_b;
|
||||
stuff_boolean(&temp_b);
|
||||
m->misc_anim_over_doors.push_back(temp_b);
|
||||
} else {
|
||||
m->misc_anim_over_doors.push_back(0);
|
||||
}
|
||||
}
|
||||
|
||||
region_info_init(*m);
|
||||
|
||||
// door animations
|
||||
required_string("+Num Door Animations:");
|
||||
stuff_int(&m->num_door_animations);
|
||||
|
||||
// initialise the door anim vectors
|
||||
door_anim_init(*m);
|
||||
|
||||
for (idx = 0; idx < m->num_door_animations; idx++) {
|
||||
// door name
|
||||
required_string("+Door anim:");
|
||||
stuff_string(temp_string, F_NAME, MAX_FILENAME_LEN);
|
||||
m->door_anim_name.at(idx) = (SCP_string)temp_string;
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_door_animations; idx++) {
|
||||
// door coords
|
||||
required_string("+Door coords:");
|
||||
stuff_int(&m->door_anim_coords.at(idx).at(0));
|
||||
stuff_int(&m->door_anim_coords.at(idx).at(1));
|
||||
stuff_int(&m->door_anim_coords.at(idx).at(2));
|
||||
stuff_int(&m->door_anim_coords.at(idx).at(3));
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_door_animations; idx++) {
|
||||
// door open and close sounds
|
||||
parse_sound_list("+Door sounds:", m->door_sounds.at(idx), "+Door sounds:", (parse_sound_flags)(PARSE_SOUND_INTERFACE_SOUND | PARSE_SOUND_SCP_SOUND_LIST));
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_door_animations; idx++) {
|
||||
// door pan value
|
||||
required_string("+Door pan:");
|
||||
stuff_float(&m->door_sound_pan[idx]);
|
||||
}
|
||||
|
||||
int mask;
|
||||
for (idx = 0; optional_string("+Door mask value:"); idx++) {
|
||||
// door mask
|
||||
stuff_string(temp_string, F_RAW, MAX_FILENAME_LEN);
|
||||
|
||||
mask = (int) strtol(temp_string, NULL, 0);
|
||||
mask = 255 - mask;
|
||||
|
||||
if(idx >= (int) m->regions.size()) {
|
||||
m->regions.resize(idx + 1);
|
||||
}
|
||||
m->regions[idx].mask = mask;
|
||||
}
|
||||
|
||||
for (idx = 0; optional_string("+Door action:"); idx++) {
|
||||
// door action
|
||||
|
||||
if(idx >= (int) m->regions.size()) {
|
||||
m->regions.resize(idx + 1);
|
||||
}
|
||||
|
||||
if (optional_string("Script")) {
|
||||
m->regions[idx].action = SCRIPT_REGION;
|
||||
stuff_string(m->regions[idx].lua_action, F_RAW);
|
||||
} else {
|
||||
stuff_string(temp_scp_string, F_RAW);
|
||||
|
||||
int action = -1;
|
||||
for (int i = 0; Main_hall_region_map[i].name != NULL; i++) {
|
||||
if (temp_scp_string == Main_hall_region_map[i].name) {
|
||||
action = Main_hall_region_map[i].mask;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (action == -1) {
|
||||
SCP_string err_msg = "";
|
||||
for (int i = 0; Main_hall_region_map[i].name != NULL; i++) {
|
||||
if (i != 0) {
|
||||
err_msg += ", ";
|
||||
}
|
||||
err_msg += Main_hall_region_map[i].name;
|
||||
}
|
||||
|
||||
Error(LOCATION, "Unkown Door Region '%s'! Expected one of: %s", temp_scp_string.c_str(), err_msg.c_str());
|
||||
}
|
||||
|
||||
m->regions[idx].action = action;
|
||||
}
|
||||
}
|
||||
|
||||
for (idx = 0; optional_string("+Door key:"); idx++) {
|
||||
// door key
|
||||
stuff_string(temp_string, F_RAW, MAX_FILENAME_LEN);
|
||||
|
||||
if ((int) m->regions.size() <= idx) {
|
||||
m->regions.resize(idx + 1);
|
||||
}
|
||||
m->regions[idx].key = temp_string[0];
|
||||
}
|
||||
|
||||
for (idx = 0; optional_string("+Door description:"); idx++) {
|
||||
// region description (tooltip)
|
||||
stuff_string(temp_scp_string, F_MESSAGE);
|
||||
|
||||
if (temp_scp_string != "default") {
|
||||
if(idx >= (int) m->regions.size()) {
|
||||
m->regions.resize(idx + 1);
|
||||
}
|
||||
|
||||
m->regions[idx].description = temp_scp_string;
|
||||
|
||||
if (idx == 2) {
|
||||
m->default_readyroom = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// font for tooltips and other text
|
||||
if (optional_string("+Font:")) {
|
||||
stuff_int(&m->font);
|
||||
} else {
|
||||
m->font = FONT1;
|
||||
}
|
||||
|
||||
// tooltip padding
|
||||
if (optional_string("+Tooltip Padding:")) {
|
||||
stuff_int(&m->tooltip_padding);
|
||||
} else {
|
||||
m->tooltip_padding = -1; // we'll get the default value later
|
||||
}
|
||||
|
||||
// tooltip y location
|
||||
if (optional_string("+Tooltip Y:")) {
|
||||
stuff_int(&m->region_yval);
|
||||
} else {
|
||||
m->region_yval = -1;
|
||||
}
|
||||
if (optional_string("$Num Resolutions:")) {
|
||||
stuff_int(&num_resolutions);
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
if (num_resolutions < 1) {
|
||||
Error(LOCATION, "$Num Resolutions in %s is %d. (Must be 1 or greater)", filename, num_resolutions);
|
||||
}
|
||||
|
||||
// free up memory from parsing the mainhall tbl
|
||||
stop_parse();
|
||||
// go for it
|
||||
count = Main_hall_defines.size();
|
||||
while (!optional_string("#end")) {
|
||||
Main_hall_defines.push_back(temp_vector);
|
||||
// read in all resolutions
|
||||
for (m_idx = 0; m_idx < num_resolutions; m_idx++) {
|
||||
Main_hall_defines.at(count).push_back(temp);
|
||||
m = &Main_hall_defines.at(count).at(m_idx);
|
||||
|
||||
// ready
|
||||
required_string("$Main Hall");
|
||||
|
||||
// Parse the entry name for the first resolution, checking for duplicates and erroring if necessary
|
||||
if (m_idx == 0) {
|
||||
if (optional_string("+Name:")) {
|
||||
stuff_string(temp_string, F_RAW, MAX_FILENAME_LEN);
|
||||
|
||||
// we can't have two mainhalls with the same name
|
||||
if (main_hall_get_pointer(temp_string) == NULL) {
|
||||
m->name = temp_string;
|
||||
}
|
||||
else {
|
||||
Error(LOCATION, "A mainhall with the name '%s' already exists. All mainhalls must have unique names.", temp_string);
|
||||
}
|
||||
}
|
||||
else {
|
||||
snprintf(temp_string, MAX_FILENAME_LEN, "%d", count);
|
||||
m->name = temp_string;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (optional_string("+Name:")) {
|
||||
stuff_string(temp_string, F_RAW, MAX_FILENAME_LEN);
|
||||
|
||||
/**
|
||||
* the reason that this is an error is that even if we were to change the names to match
|
||||
* it is very likely the user would get the wrong mainhall loaded since their campaign files
|
||||
* may still refer to the entry with the incorrect name
|
||||
*/
|
||||
if (strcmp(temp_string, Main_hall_defines.at(count).at(0).name.c_str()) != 0) {
|
||||
Error(LOCATION, "The mainhall '%s' has different names for different resolutions. All resolutions must have the same name. Either remove the hi-res entries' names entirely or set them to match the first resolution entry's name.", Main_hall_defines.at(0).at(count).name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
m->name = Main_hall_defines.at(count).at(0).name;
|
||||
}
|
||||
|
||||
// add cheats
|
||||
while (optional_string("+Cheat String:")) {
|
||||
stuff_string(temp_scp_string, F_RAW);
|
||||
m->cheat.push_back(temp_scp_string);
|
||||
|
||||
if (temp_scp_string.size() > MAIN_HALL_MAX_CHEAT_LEN) {
|
||||
// Since the value is longer than the cheat buffer it will never match.
|
||||
|
||||
Warning(LOCATION, "The value '%s' for '+Cheat String:' is too long! It can be at most %d characters long.", temp_scp_string.size(), MAIN_HALL_MAX_CHEAT_LEN);
|
||||
}
|
||||
|
||||
required_string("+Anim To Change:");
|
||||
stuff_string(temp_scp_string, F_NAME);
|
||||
m->cheat_anim_from.push_back(temp_scp_string);
|
||||
|
||||
required_string("+Anim To Change To:");
|
||||
stuff_string(temp_scp_string, F_NAME);
|
||||
m->cheat_anim_to.push_back(temp_scp_string);
|
||||
}
|
||||
|
||||
// minimum resolution
|
||||
if (optional_string("+Min Resolution:")) {
|
||||
stuff_int(&m->min_width);
|
||||
stuff_int(&m->min_height);
|
||||
}
|
||||
else if (m_idx == 0) {
|
||||
m->min_width = 0;
|
||||
m->min_height = 0;
|
||||
}
|
||||
else {
|
||||
m->min_width = GR_1024_THRESHOLD_WIDTH;
|
||||
m->min_height = GR_1024_THRESHOLD_HEIGHT;
|
||||
}
|
||||
|
||||
// minimum aspect ratio
|
||||
if (optional_string("+Min Aspect Ratio:")) {
|
||||
stuff_float(&m->min_aspect_ratio);
|
||||
}
|
||||
else {
|
||||
m->min_aspect_ratio = 0.0f;
|
||||
}
|
||||
|
||||
// bitmap and mask
|
||||
required_string("+Bitmap:");
|
||||
stuff_string(temp_string, F_NAME, MAX_FILENAME_LEN);
|
||||
m->bitmap = temp_string;
|
||||
|
||||
required_string("+Mask:");
|
||||
stuff_string(temp_string, F_NAME, MAX_FILENAME_LEN);
|
||||
m->mask = temp_string;
|
||||
|
||||
required_string("+Music:");
|
||||
stuff_string(temp_string, F_NAME, MAX_FILENAME_LEN);
|
||||
m->music_name = temp_string;
|
||||
|
||||
// Goober5000
|
||||
if (optional_string("+Substitute Music:")) {
|
||||
stuff_string(temp_string, F_NAME, MAX_FILENAME_LEN);
|
||||
m->substitute_music_name = temp_string;
|
||||
}
|
||||
|
||||
if (optional_string("+Help Overlay:")) {
|
||||
stuff_string(temp_string, F_NAME, MAX_FILENAME_LEN);
|
||||
m->help_overlay_name = temp_string;
|
||||
}
|
||||
|
||||
if (optional_string("+Help Overlay Resolution Index:")) {
|
||||
stuff_int(&m->help_overlay_resolution_index);
|
||||
}
|
||||
else {
|
||||
m->help_overlay_resolution_index = m_idx;
|
||||
}
|
||||
|
||||
// zoom area
|
||||
if (optional_string("+Zoom To:")) {
|
||||
stuff_int(&m->zoom_area_width);
|
||||
stuff_int(&m->zoom_area_height);
|
||||
}
|
||||
else {
|
||||
m->zoom_area_width = -1;
|
||||
m->zoom_area_height = -1;
|
||||
}
|
||||
|
||||
// intercom sounds
|
||||
required_string("+Num Intercom Sounds:");
|
||||
stuff_int(&m->num_random_intercom_sounds);
|
||||
|
||||
// initialise intercom sounds vectors
|
||||
intercom_sounds_init(*m);
|
||||
|
||||
for (idx = 0; idx < m->num_random_intercom_sounds; idx++) {
|
||||
// intercom delay
|
||||
required_string("+Intercom delay:");
|
||||
stuff_int(&m->intercom_delay.at(idx).at(0));
|
||||
stuff_int(&m->intercom_delay.at(idx).at(1));
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_random_intercom_sounds; idx++) {
|
||||
// intercom sound id
|
||||
parse_sound("+Intercom sound:", &m->intercom_sounds.at(idx), "+Intercom sound:", PARSE_SOUND_INTERFACE_SOUND);
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_random_intercom_sounds; idx++) {
|
||||
// intercom pan
|
||||
required_string("+Intercom pan:");
|
||||
stuff_float(&m->intercom_sound_pan.at(idx));
|
||||
}
|
||||
|
||||
// misc animations
|
||||
required_string("+Num Misc Animations:");
|
||||
stuff_int(&m->num_misc_animations);
|
||||
|
||||
// initialise the misc anim vectors
|
||||
misc_anim_init(*m);
|
||||
|
||||
for (idx = 0; idx < m->num_misc_animations; idx++) {
|
||||
// anim names
|
||||
required_string("+Misc anim:");
|
||||
stuff_string(temp_string, F_NAME, MAX_FILENAME_LEN);
|
||||
m->misc_anim_name.at(idx) = (SCP_string)temp_string;
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_misc_animations; idx++) {
|
||||
// anim groups, optionally
|
||||
if (optional_string("+Misc anim group:")) {
|
||||
stuff_int(&m->misc_anim_group.at(idx));
|
||||
}
|
||||
else {
|
||||
m->misc_anim_group.at(idx) = -1;
|
||||
}
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_misc_animations; idx++) {
|
||||
// anim delay
|
||||
required_string("+Misc anim delay:");
|
||||
stuff_int(&m->misc_anim_delay.at(idx).at(0));
|
||||
stuff_int(&m->misc_anim_delay.at(idx).at(1));
|
||||
stuff_int(&m->misc_anim_delay.at(idx).at(2));
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_misc_animations; idx++) {
|
||||
// anim coords
|
||||
required_string("+Misc anim coords:");
|
||||
stuff_int(&m->misc_anim_coords.at(idx).at(0));
|
||||
stuff_int(&m->misc_anim_coords.at(idx).at(1));
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_misc_animations; idx++) {
|
||||
// anim mode
|
||||
required_string("+Misc anim mode:");
|
||||
stuff_int(&m->misc_anim_modes.at(idx));
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_misc_animations; idx++) {
|
||||
// anim pan
|
||||
required_string("+Misc anim pan:");
|
||||
stuff_float(&m->misc_anim_sound_pan.at(idx));
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_misc_animations; idx++) {
|
||||
// anim sound id
|
||||
parse_sound_list("+Misc anim sounds:", m->misc_anim_special_sounds.at(idx), "+Misc anim sounds:", PARSE_SOUND_INTERFACE_SOUND);
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_misc_animations; idx++) {
|
||||
// anim sound triggers
|
||||
required_string("+Misc anim trigger:");
|
||||
int temp_int = 0;
|
||||
stuff_int(&temp_int);
|
||||
for (s_idx = 0; s_idx < temp_int; s_idx++) {
|
||||
m->misc_anim_special_trigger.at(idx).push_back(0);
|
||||
stuff_int(&m->misc_anim_special_trigger.at(idx).at(s_idx));
|
||||
}
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_misc_animations; idx++) {
|
||||
// anim sound handles - deprecated, but deal with it just in case
|
||||
if (optional_string("+Misc anim handles:")) {
|
||||
advance_to_eoln(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_misc_animations; idx++) {
|
||||
// anim sound flags - table flag deprecated, so ignore user input
|
||||
if (optional_string("+Misc anim flags:")) {
|
||||
advance_to_eoln(NULL);
|
||||
}
|
||||
|
||||
// we need one flag for each sound
|
||||
Assert(m->misc_anim_special_sounds.at(idx).size() < INT_MAX);
|
||||
for (s_idx = 0; s_idx < (int)m->misc_anim_special_sounds.at(idx).size(); s_idx++) {
|
||||
m->misc_anim_sound_flag.at(idx).push_back(0);
|
||||
}
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_misc_animations; idx++) {
|
||||
// render over doors - default to false
|
||||
|
||||
if (optional_string("+Misc anim over doors:")) {
|
||||
bool temp_b;
|
||||
stuff_boolean(&temp_b);
|
||||
m->misc_anim_over_doors.push_back(temp_b);
|
||||
}
|
||||
else {
|
||||
m->misc_anim_over_doors.push_back(0);
|
||||
}
|
||||
}
|
||||
|
||||
region_info_init(*m);
|
||||
|
||||
// door animations
|
||||
required_string("+Num Door Animations:");
|
||||
stuff_int(&m->num_door_animations);
|
||||
|
||||
// initialise the door anim vectors
|
||||
door_anim_init(*m);
|
||||
|
||||
for (idx = 0; idx < m->num_door_animations; idx++) {
|
||||
// door name
|
||||
required_string("+Door anim:");
|
||||
stuff_string(temp_string, F_NAME, MAX_FILENAME_LEN);
|
||||
m->door_anim_name.at(idx) = (SCP_string)temp_string;
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_door_animations; idx++) {
|
||||
// door coords
|
||||
required_string("+Door coords:");
|
||||
stuff_int(&m->door_anim_coords.at(idx).at(0));
|
||||
stuff_int(&m->door_anim_coords.at(idx).at(1));
|
||||
stuff_int(&m->door_anim_coords.at(idx).at(2));
|
||||
stuff_int(&m->door_anim_coords.at(idx).at(3));
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_door_animations; idx++) {
|
||||
// door open and close sounds
|
||||
parse_sound_list("+Door sounds:", m->door_sounds.at(idx), "+Door sounds:", (parse_sound_flags)(PARSE_SOUND_INTERFACE_SOUND | PARSE_SOUND_SCP_SOUND_LIST));
|
||||
}
|
||||
|
||||
for (idx = 0; idx < m->num_door_animations; idx++) {
|
||||
// door pan value
|
||||
required_string("+Door pan:");
|
||||
stuff_float(&m->door_sound_pan[idx]);
|
||||
}
|
||||
|
||||
int mask;
|
||||
for (idx = 0; optional_string("+Door mask value:"); idx++) {
|
||||
// door mask
|
||||
stuff_string(temp_string, F_RAW, MAX_FILENAME_LEN);
|
||||
|
||||
mask = (int)strtol(temp_string, NULL, 0);
|
||||
mask = 255 - mask;
|
||||
|
||||
if (idx >= (int)m->regions.size()) {
|
||||
m->regions.resize(idx + 1);
|
||||
}
|
||||
m->regions[idx].mask = mask;
|
||||
}
|
||||
|
||||
for (idx = 0; optional_string("+Door action:"); idx++) {
|
||||
// door action
|
||||
|
||||
if (idx >= (int)m->regions.size()) {
|
||||
m->regions.resize(idx + 1);
|
||||
}
|
||||
|
||||
if (optional_string("Script")) {
|
||||
m->regions[idx].action = SCRIPT_REGION;
|
||||
stuff_string(m->regions[idx].lua_action, F_RAW);
|
||||
}
|
||||
else {
|
||||
stuff_string(temp_scp_string, F_RAW);
|
||||
|
||||
int action = -1;
|
||||
for (int i = 0; Main_hall_region_map[i].name != NULL; i++) {
|
||||
if (temp_scp_string == Main_hall_region_map[i].name) {
|
||||
action = Main_hall_region_map[i].mask;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (action == -1) {
|
||||
SCP_string err_msg = "";
|
||||
for (int i = 0; Main_hall_region_map[i].name != NULL; i++) {
|
||||
if (i != 0) {
|
||||
err_msg += ", ";
|
||||
}
|
||||
err_msg += Main_hall_region_map[i].name;
|
||||
}
|
||||
|
||||
Error(LOCATION, "Unkown Door Region '%s'! Expected one of: %s", temp_scp_string.c_str(), err_msg.c_str());
|
||||
}
|
||||
|
||||
m->regions[idx].action = action;
|
||||
}
|
||||
}
|
||||
|
||||
for (idx = 0; optional_string("+Door key:"); idx++) {
|
||||
// door key
|
||||
stuff_string(temp_string, F_RAW, MAX_FILENAME_LEN);
|
||||
|
||||
if ((int)m->regions.size() <= idx) {
|
||||
m->regions.resize(idx + 1);
|
||||
}
|
||||
m->regions[idx].key = temp_string[0];
|
||||
}
|
||||
|
||||
for (idx = 0; optional_string("+Door description:"); idx++) {
|
||||
// region description (tooltip)
|
||||
stuff_string(temp_scp_string, F_MESSAGE);
|
||||
|
||||
if (temp_scp_string != "default") {
|
||||
if (idx >= (int)m->regions.size()) {
|
||||
m->regions.resize(idx + 1);
|
||||
}
|
||||
|
||||
m->regions[idx].description = temp_scp_string;
|
||||
|
||||
if (idx == 2) {
|
||||
m->default_readyroom = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// font for tooltips and other text
|
||||
if (optional_string("+Font:")) {
|
||||
stuff_int(&m->font);
|
||||
}
|
||||
else {
|
||||
m->font = FONT1;
|
||||
}
|
||||
|
||||
// tooltip padding
|
||||
if (optional_string("+Tooltip Padding:")) {
|
||||
stuff_int(&m->tooltip_padding);
|
||||
}
|
||||
else {
|
||||
m->tooltip_padding = -1; // we'll get the default value later
|
||||
}
|
||||
|
||||
// tooltip y location
|
||||
if (optional_string("+Tooltip Y:")) {
|
||||
stuff_int(&m->region_yval);
|
||||
}
|
||||
else {
|
||||
m->region_yval = -1;
|
||||
}
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
// free up memory from parsing the mainhall tbl
|
||||
stop_parse();
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", filename, e.what()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+16
-15
@@ -1292,25 +1292,26 @@ int Player_tips_shown = 0;
|
||||
// tooltips
|
||||
void player_tips_init()
|
||||
{
|
||||
int rval;
|
||||
|
||||
Num_player_tips = 0;
|
||||
|
||||
try
|
||||
{
|
||||
read_file_text("tips.tbl", CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", "tips.tbl", rval));
|
||||
return;
|
||||
}
|
||||
while (!optional_string("#end")) {
|
||||
required_string("+Tip:");
|
||||
|
||||
read_file_text("tips.tbl", CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
while(!optional_string("#end")) {
|
||||
required_string("+Tip:");
|
||||
|
||||
if(Num_player_tips >= MAX_PLAYER_TIPS) {
|
||||
break;
|
||||
if (Num_player_tips >= MAX_PLAYER_TIPS) {
|
||||
break;
|
||||
}
|
||||
Player_tips[Num_player_tips++] = stuff_and_malloc_string(F_NAME, NULL);
|
||||
}
|
||||
Player_tips[Num_player_tips++] = stuff_and_malloc_string(F_NAME, NULL);
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "tips.tbl", e.what()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+41
-38
@@ -1026,51 +1026,54 @@ int techroom_load_ani(anim **animpp, char *name)
|
||||
|
||||
void techroom_intel_init()
|
||||
{
|
||||
int rval, temp;
|
||||
int temp;
|
||||
static int inited = 0;
|
||||
|
||||
if (inited)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
read_file_text("species.tbl", CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", "species.tbl", rval));
|
||||
Intel_info_size = 0;
|
||||
while (optional_string("$Entry:")) {
|
||||
Assert(Intel_info_size < MAX_INTEL_ENTRIES);
|
||||
if (Intel_info_size >= MAX_INTEL_ENTRIES) {
|
||||
mprintf(("TECHMENU: Too many intel entries!\n"));
|
||||
break;
|
||||
}
|
||||
|
||||
Intel_info[Intel_info_size].flags = IIF_DEFAULT_VALUE;
|
||||
|
||||
required_string("$Name:");
|
||||
stuff_string(Intel_info[Intel_info_size].name, F_NAME, NAME_LENGTH);
|
||||
|
||||
required_string("$Anim:");
|
||||
stuff_string(Intel_info[Intel_info_size].anim_filename, F_NAME, NAME_LENGTH);
|
||||
|
||||
required_string("$AlwaysInTechRoom:");
|
||||
stuff_int(&temp);
|
||||
if (temp) {
|
||||
// set default to align with what we read - Goober5000
|
||||
Intel_info[Intel_info_size].flags |= IIF_IN_TECH_DATABASE;
|
||||
Intel_info[Intel_info_size].flags |= IIF_DEFAULT_IN_TECH_DATABASE;
|
||||
}
|
||||
|
||||
required_string("$Description:");
|
||||
stuff_string(Intel_info[Intel_info_size].desc, F_MULTITEXT, TECH_INTEL_DESC_LEN);
|
||||
|
||||
Intel_info_size++;
|
||||
}
|
||||
|
||||
inited = 1;
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "species.tbl", e.what()));
|
||||
return;
|
||||
}
|
||||
|
||||
read_file_text("species.tbl", CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
Intel_info_size = 0;
|
||||
while (optional_string("$Entry:")) {
|
||||
Assert(Intel_info_size < MAX_INTEL_ENTRIES);
|
||||
if (Intel_info_size >= MAX_INTEL_ENTRIES) {
|
||||
mprintf(("TECHMENU: Too many intel entries!\n"));
|
||||
break;
|
||||
}
|
||||
|
||||
Intel_info[Intel_info_size].flags = IIF_DEFAULT_VALUE;
|
||||
|
||||
required_string("$Name:");
|
||||
stuff_string(Intel_info[Intel_info_size].name, F_NAME, NAME_LENGTH);
|
||||
|
||||
required_string("$Anim:");
|
||||
stuff_string(Intel_info[Intel_info_size].anim_filename, F_NAME, NAME_LENGTH);
|
||||
|
||||
required_string("$AlwaysInTechRoom:");
|
||||
stuff_int(&temp);
|
||||
if (temp) {
|
||||
// set default to align with what we read - Goober5000
|
||||
Intel_info[Intel_info_size].flags |= IIF_IN_TECH_DATABASE;
|
||||
Intel_info[Intel_info_size].flags |= IIF_DEFAULT_IN_TECH_DATABASE;
|
||||
}
|
||||
|
||||
required_string("$Description:");
|
||||
stuff_string(Intel_info[Intel_info_size].desc, F_MULTITEXT, TECH_INTEL_DESC_LEN);
|
||||
|
||||
Intel_info_size++;
|
||||
}
|
||||
|
||||
inited = 1;
|
||||
}
|
||||
|
||||
void techroom_init()
|
||||
|
||||
@@ -274,77 +274,78 @@ int brief_text_wipe_finished();
|
||||
//
|
||||
void brief_parse_icon_tbl()
|
||||
{
|
||||
int rval, icon;
|
||||
int icon;
|
||||
size_t species;
|
||||
char name[MAX_FILENAME_LEN];
|
||||
|
||||
Assert(!Species_info.empty());
|
||||
const size_t max_icons = Species_info.size() * MIN_BRIEF_ICONS;
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", "icons.tbl", rval));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
read_file_text("icons.tbl", CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
required_string("#Start");
|
||||
|
||||
Briefing_icon_info.clear();
|
||||
while (required_string_either("#End","$Name:"))
|
||||
try
|
||||
{
|
||||
if(Briefing_icon_info.size() >= max_icons) {
|
||||
Warning(LOCATION, "Too many icons in icons.tbl; only the first %d will be used", max_icons);
|
||||
skip_to_start_of_string("#End");
|
||||
break;
|
||||
}
|
||||
read_file_text("icons.tbl", CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
briefing_icon_info bii;
|
||||
required_string("#Start");
|
||||
|
||||
// parse regular frames
|
||||
required_string("$Name:");
|
||||
stuff_string(name, F_NAME, MAX_FILENAME_LEN);
|
||||
generic_anim_init(&bii.regular, name);
|
||||
|
||||
// parse fade frames
|
||||
required_string("$Name:");
|
||||
stuff_string(name, F_NAME, MAX_FILENAME_LEN);
|
||||
hud_anim_init(&bii.fade, 0, 0, name);
|
||||
|
||||
// parse highlighting frames
|
||||
required_string("$Name:");
|
||||
stuff_string(name, F_NAME, MAX_FILENAME_LEN);
|
||||
hud_anim_init(&bii.highlight, 0, 0, name);
|
||||
|
||||
// add it to the collection
|
||||
Briefing_icon_info.push_back(bii);
|
||||
}
|
||||
required_string("#End");
|
||||
|
||||
|
||||
// now assign the icons to their species
|
||||
const size_t num_species_covered = Briefing_icon_info.size() / MIN_BRIEF_ICONS;
|
||||
size_t bii_index = 0;
|
||||
for (icon = 0; icon < MIN_BRIEF_ICONS; icon++)
|
||||
{
|
||||
for (species = 0; species < num_species_covered; species++)
|
||||
Species_info[species].bii_index[icon] = bii_index++;
|
||||
}
|
||||
|
||||
// error check
|
||||
if (num_species_covered < Species_info.size())
|
||||
{
|
||||
SCP_string errormsg = "The following species are missing icon info in icons.tbl:\n";
|
||||
|
||||
for (species = num_species_covered; species < Species_info.size(); species++)
|
||||
Briefing_icon_info.clear();
|
||||
while (required_string_either("#End", "$Name:"))
|
||||
{
|
||||
errormsg += Species_info[species].species_name;
|
||||
errormsg += "\n";
|
||||
if (Briefing_icon_info.size() >= max_icons) {
|
||||
Warning(LOCATION, "Too many icons in icons.tbl; only the first %d will be used", max_icons);
|
||||
skip_to_start_of_string("#End");
|
||||
break;
|
||||
}
|
||||
|
||||
briefing_icon_info bii;
|
||||
|
||||
// parse regular frames
|
||||
required_string("$Name:");
|
||||
stuff_string(name, F_NAME, MAX_FILENAME_LEN);
|
||||
generic_anim_init(&bii.regular, name);
|
||||
|
||||
// parse fade frames
|
||||
required_string("$Name:");
|
||||
stuff_string(name, F_NAME, MAX_FILENAME_LEN);
|
||||
hud_anim_init(&bii.fade, 0, 0, name);
|
||||
|
||||
// parse highlighting frames
|
||||
required_string("$Name:");
|
||||
stuff_string(name, F_NAME, MAX_FILENAME_LEN);
|
||||
hud_anim_init(&bii.highlight, 0, 0, name);
|
||||
|
||||
// add it to the collection
|
||||
Briefing_icon_info.push_back(bii);
|
||||
}
|
||||
required_string("#End");
|
||||
|
||||
|
||||
// now assign the icons to their species
|
||||
const size_t num_species_covered = Briefing_icon_info.size() / MIN_BRIEF_ICONS;
|
||||
size_t bii_index = 0;
|
||||
for (icon = 0; icon < MIN_BRIEF_ICONS; icon++)
|
||||
{
|
||||
for (species = 0; species < num_species_covered; species++)
|
||||
Species_info[species].bii_index[icon] = bii_index++;
|
||||
}
|
||||
|
||||
Error(LOCATION, errormsg.c_str());
|
||||
// error check
|
||||
if (num_species_covered < Species_info.size())
|
||||
{
|
||||
SCP_string errormsg = "The following species are missing icon info in icons.tbl:\n";
|
||||
|
||||
for (species = num_species_covered; species < Species_info.size(); species++)
|
||||
{
|
||||
errormsg += Species_info[species].species_name;
|
||||
errormsg += "\n";
|
||||
}
|
||||
|
||||
Error(LOCATION, errormsg.c_str());
|
||||
}
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "icons.tbl", e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+211
-195
@@ -100,7 +100,7 @@ bool campaign_is_ignored(const char *filename);
|
||||
*/
|
||||
int mission_campaign_get_info(const char *filename, char *name, int *type, int *max_players, char **desc)
|
||||
{
|
||||
int rval, i, success = 0;
|
||||
int i, success = 0;
|
||||
char campaign_type[NAME_LENGTH], fname[MAX_FILENAME_LEN];
|
||||
|
||||
Assert( name != NULL );
|
||||
@@ -116,53 +116,57 @@ int mission_campaign_get_info(const char *filename, char *name, int *type, int *
|
||||
|
||||
*type = -1;
|
||||
do {
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("MISSIONCAMPAIGN: Unable to parse '%s'! Error code = %i.\n", fname, rval));
|
||||
break;
|
||||
}
|
||||
try
|
||||
{
|
||||
read_file_text(fname);
|
||||
reset_parse();
|
||||
|
||||
read_file_text(fname);
|
||||
reset_parse();
|
||||
required_string("$Name:");
|
||||
stuff_string(name, F_NAME, NAME_LENGTH);
|
||||
if (name == NULL) {
|
||||
nprintf(("Warning", "No name found for campaign file %s\n", filename));
|
||||
break;
|
||||
}
|
||||
|
||||
required_string("$Name:");
|
||||
stuff_string( name, F_NAME, NAME_LENGTH );
|
||||
if (name == NULL) {
|
||||
nprintf(("Warning", "No name found for campaign file %s\n", filename));
|
||||
break;
|
||||
}
|
||||
required_string("$Type:");
|
||||
stuff_string(campaign_type, F_NAME, NAME_LENGTH);
|
||||
|
||||
required_string("$Type:");
|
||||
stuff_string( campaign_type, F_NAME, NAME_LENGTH );
|
||||
for (i = 0; i < MAX_CAMPAIGN_TYPES; i++) {
|
||||
if (!stricmp(campaign_type, campaign_types[i])) {
|
||||
*type = i;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<MAX_CAMPAIGN_TYPES; i++) {
|
||||
if ( !stricmp(campaign_type, campaign_types[i]) ) {
|
||||
*type = i;
|
||||
if (name == NULL) {
|
||||
Warning(LOCATION, "Invalid campaign type \"%s\"\n", campaign_type);
|
||||
break;
|
||||
}
|
||||
|
||||
if (desc) {
|
||||
if (optional_string("+Description:")) {
|
||||
*desc = stuff_and_malloc_string(F_MULTITEXT, NULL);
|
||||
}
|
||||
else {
|
||||
*desc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// if this is a multiplayer campaign, get the max players
|
||||
if ((*type) != CAMPAIGN_TYPE_SINGLE) {
|
||||
skip_to_string("+Num Players:");
|
||||
stuff_int(max_players);
|
||||
}
|
||||
|
||||
// if we found a valid campaign type
|
||||
if ((*type) >= 0) {
|
||||
success = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (name == NULL) {
|
||||
Warning(LOCATION, "Invalid campaign type \"%s\"\n", campaign_type);
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("MISSIONCAMPAIGN: Unable to parse '%s'! Error message = %s.\n", fname, e.what()));
|
||||
break;
|
||||
}
|
||||
|
||||
if (desc) {
|
||||
if (optional_string("+Description:")) {
|
||||
*desc = stuff_and_malloc_string(F_MULTITEXT, NULL);
|
||||
} else {
|
||||
*desc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// if this is a multiplayer campaign, get the max players
|
||||
if ((*type) != CAMPAIGN_TYPE_SINGLE) {
|
||||
skip_to_string("+Num Players:");
|
||||
stuff_int(max_players);
|
||||
}
|
||||
|
||||
// if we found a valid campaign type
|
||||
if ((*type) >= 0) {
|
||||
success = 1;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
Assert(success);
|
||||
@@ -176,22 +180,14 @@ int mission_campaign_get_info(const char *filename, char *name, int *type, int *
|
||||
*/
|
||||
int mission_campaign_get_mission_list(const char *filename, char **list, int max)
|
||||
{
|
||||
int rval, i, num = 0;
|
||||
int i, num = 0;
|
||||
char name[MAX_FILENAME_LEN];
|
||||
|
||||
filename = cf_add_ext(filename, FS_CAMPAIGN_FILE_EXT);
|
||||
|
||||
// read the campaign file and get the list of mission filenames
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("MISSIONCAMPAIGN: Unable to parse '%s'! Error code = %i.\n", filename, rval));
|
||||
|
||||
// since we can't return count of allocated elements, free them instead
|
||||
for (i=0; i<num; i++)
|
||||
vm_free(list[i]);
|
||||
|
||||
num = -1;
|
||||
|
||||
} else {
|
||||
try
|
||||
{
|
||||
read_file_text(filename);
|
||||
reset_parse();
|
||||
|
||||
@@ -203,6 +199,16 @@ int mission_campaign_get_mission_list(const char *filename, char **list, int max
|
||||
Warning(LOCATION, "Maximum number of missions exceeded (%d)!", max);
|
||||
}
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("MISSIONCAMPAIGN: Unable to parse '%s'! Error message = %s.\n", filename, e.what()));
|
||||
|
||||
// since we can't return count of allocated elements, free them instead
|
||||
for (i = 0; i<num; i++)
|
||||
vm_free(list[i]);
|
||||
|
||||
num = -1;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
@@ -410,7 +416,7 @@ void mission_campaign_get_sw_info()
|
||||
*/
|
||||
int mission_campaign_load( char *filename, player *pl, int load_savefile, bool reset_stats )
|
||||
{
|
||||
int len, rval, i;
|
||||
int len, i;
|
||||
char name[NAME_LENGTH], type[NAME_LENGTH], temp[NAME_LENGTH];
|
||||
|
||||
if (campaign_is_ignored(filename)) {
|
||||
@@ -429,21 +435,8 @@ int mission_campaign_load( char *filename, player *pl, int load_savefile, bool r
|
||||
}
|
||||
|
||||
// read the mission file and get the list of mission filenames
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("Error parsing '%s'\r\nError code = %i.\r\n", filename, rval));
|
||||
|
||||
Campaign.filename[0] = 0;
|
||||
Campaign.num_missions = 0;
|
||||
|
||||
if ( !Fred_running && !(Game_mode & GM_MULTIPLAYER) ) {
|
||||
Campaign_file_missing = 1;
|
||||
Campaign_load_failure = CAMPAIGN_ERROR_MISSING;
|
||||
return CAMPAIGN_ERROR_MISSING;
|
||||
}
|
||||
|
||||
return CAMPAIGN_ERROR_CORRUPT;
|
||||
|
||||
} else {
|
||||
try
|
||||
{
|
||||
// be sure to remove all old malloced strings of Mission_names
|
||||
// we must also free any goal stuff that was from a previous campaign
|
||||
// this also frees sexpressions so the next call to init_sexp will be able to reclaim
|
||||
@@ -643,6 +636,21 @@ int mission_campaign_load( char *filename, player *pl, int load_savefile, bool r
|
||||
Campaign.num_missions++;
|
||||
}
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("Error parsing '%s'\r\nError message = %s.\r\n", filename, e.what()));
|
||||
|
||||
Campaign.filename[0] = 0;
|
||||
Campaign.num_missions = 0;
|
||||
|
||||
if (!Fred_running && !(Game_mode & GM_MULTIPLAYER)) {
|
||||
Campaign_file_missing = 1;
|
||||
Campaign_load_failure = CAMPAIGN_ERROR_MISSING;
|
||||
return CAMPAIGN_ERROR_MISSING;
|
||||
}
|
||||
|
||||
return CAMPAIGN_ERROR_CORRUPT;
|
||||
}
|
||||
|
||||
// set up the other variables for the campaign stuff. After initializing, we must try and load
|
||||
// the campaign save file for this player. Since all campaign loads go through this routine, I
|
||||
@@ -1406,14 +1414,9 @@ void mission_campaign_clear()
|
||||
*/
|
||||
int mission_campaign_get_filenames(char *filename, char dest[][NAME_LENGTH], int *num)
|
||||
{
|
||||
int rval;
|
||||
|
||||
// read the mission file and get the list of mission filenames
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("MISSIONCAMPAIGN: Unable to parse '%s'! Error code = %i.\n", filename, rval));
|
||||
return rval;
|
||||
|
||||
} else {
|
||||
try
|
||||
{
|
||||
Assert( strlen(filename) < MAX_FILENAME_LEN ); // make sure no overflow
|
||||
read_file_text(filename);
|
||||
reset_parse();
|
||||
@@ -1431,6 +1434,11 @@ int mission_campaign_get_filenames(char *filename, char dest[][NAME_LENGTH], int
|
||||
(*num)++;
|
||||
}
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("MISSIONCAMPAIGN: Unable to parse '%s'! Error message = %s.\n", filename, e.what()));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1443,110 +1451,115 @@ void read_mission_goal_list(int num)
|
||||
{
|
||||
char *filename, notes[NOTES_LENGTH], goals[MAX_GOALS][NAME_LENGTH];
|
||||
char events[MAX_MISSION_EVENTS][NAME_LENGTH];
|
||||
int i, z, rval, event_count, count = 0;
|
||||
int i, z, event_count, count = 0;
|
||||
|
||||
filename = Campaign.missions[num].name;
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("MISSIONCAMPAIGN: Unable to parse '%s'! Error code = %i.\n", filename, rval));
|
||||
try
|
||||
{
|
||||
read_file_text(filename);
|
||||
reset_parse();
|
||||
init_sexp();
|
||||
|
||||
// first, read the mission notes for this mission. Used in campaign editor
|
||||
if (skip_to_string("#Mission Info")) {
|
||||
if (skip_to_string("$Notes:")) {
|
||||
stuff_string(notes, F_NOTES, NOTES_LENGTH);
|
||||
if (Campaign.missions[num].notes){
|
||||
vm_free(Campaign.missions[num].notes);
|
||||
}
|
||||
|
||||
Campaign.missions[num].notes = (char *)vm_malloc(strlen(notes) + 1);
|
||||
strcpy(Campaign.missions[num].notes, notes);
|
||||
}
|
||||
}
|
||||
|
||||
event_count = 0;
|
||||
// skip to events section in the mission file. Events come before goals, so we process them first
|
||||
if (skip_to_string("#Events")) {
|
||||
while (1) {
|
||||
if (skip_to_string("$Formula:", "#Goals") != 1){
|
||||
break;
|
||||
}
|
||||
|
||||
z = skip_to_string("+Name:", "$Formula:");
|
||||
if (!z){
|
||||
break;
|
||||
}
|
||||
|
||||
if (z == 1){
|
||||
stuff_string(events[event_count], F_NAME, NAME_LENGTH);
|
||||
}
|
||||
else {
|
||||
sprintf(events[event_count], NOX("Event #%d"), event_count + 1);
|
||||
}
|
||||
|
||||
event_count++;
|
||||
if (event_count > MAX_MISSION_EVENTS) {
|
||||
Warning(LOCATION, "Maximum number of events exceeded (%d)!", MAX_MISSION_EVENTS);
|
||||
event_count = MAX_MISSION_EVENTS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
count = 0;
|
||||
if (skip_to_string("#Goals")) {
|
||||
while (1) {
|
||||
if (skip_to_string("$Type:", "#End") != 1){
|
||||
break;
|
||||
}
|
||||
|
||||
z = skip_to_string("+Name:", "$Type:");
|
||||
if (!z){
|
||||
break;
|
||||
}
|
||||
|
||||
if (z == 1){
|
||||
stuff_string(goals[count], F_NAME, NAME_LENGTH);
|
||||
}
|
||||
else {
|
||||
sprintf(goals[count], NOX("Goal #%d"), count + 1);
|
||||
}
|
||||
|
||||
count++;
|
||||
if (count > MAX_GOALS) {
|
||||
Warning(LOCATION, "Maximum number of goals exceeded (%d)!", MAX_GOALS);
|
||||
count = MAX_GOALS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Campaign.missions[num].num_goals = count;
|
||||
if (count) {
|
||||
Campaign.missions[num].goals = (mgoal *)vm_malloc(count * sizeof(mgoal));
|
||||
Assert(Campaign.missions[num].goals); // make sure we got the memory
|
||||
memset(Campaign.missions[num].goals, 0, count * sizeof(mgoal));
|
||||
|
||||
for (i = 0; i < count; i++){
|
||||
strcpy_s(Campaign.missions[num].goals[i].name, goals[i]);
|
||||
}
|
||||
}
|
||||
// copy the events
|
||||
Campaign.missions[num].num_events = event_count;
|
||||
if (event_count) {
|
||||
Campaign.missions[num].events = (mevent *)vm_malloc(event_count * sizeof(mevent));
|
||||
Assert(Campaign.missions[num].events);
|
||||
memset(Campaign.missions[num].events, 0, event_count * sizeof(mevent));
|
||||
|
||||
for (i = 0; i < event_count; i++){
|
||||
strcpy_s(Campaign.missions[num].events[i].name, events[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Goober5000 - variables do not need to be read here
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("MISSIONCAMPAIGN: Unable to parse '%s'! Error message = %s.\n", filename, e.what()));
|
||||
return;
|
||||
}
|
||||
|
||||
read_file_text(filename);
|
||||
reset_parse();
|
||||
init_sexp();
|
||||
|
||||
// first, read the mission notes for this mission. Used in campaign editor
|
||||
if (skip_to_string("#Mission Info")) {
|
||||
if (skip_to_string("$Notes:")) {
|
||||
stuff_string(notes, F_NOTES, NOTES_LENGTH);
|
||||
if (Campaign.missions[num].notes){
|
||||
vm_free(Campaign.missions[num].notes);
|
||||
}
|
||||
|
||||
Campaign.missions[num].notes = (char *) vm_malloc(strlen(notes) + 1);
|
||||
strcpy(Campaign.missions[num].notes, notes);
|
||||
}
|
||||
}
|
||||
|
||||
event_count = 0;
|
||||
// skip to events section in the mission file. Events come before goals, so we process them first
|
||||
if ( skip_to_string("#Events") ) {
|
||||
while (1) {
|
||||
if (skip_to_string("$Formula:", "#Goals") != 1){
|
||||
break;
|
||||
}
|
||||
|
||||
z = skip_to_string("+Name:", "$Formula:");
|
||||
if (!z){
|
||||
break;
|
||||
}
|
||||
|
||||
if (z == 1){
|
||||
stuff_string(events[event_count], F_NAME, NAME_LENGTH);
|
||||
} else {
|
||||
sprintf(events[event_count], NOX("Event #%d"), event_count + 1);
|
||||
}
|
||||
|
||||
event_count++;
|
||||
if (event_count > MAX_MISSION_EVENTS) {
|
||||
Warning(LOCATION, "Maximum number of events exceeded (%d)!", MAX_MISSION_EVENTS);
|
||||
event_count = MAX_MISSION_EVENTS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
count = 0;
|
||||
if (skip_to_string("#Goals")) {
|
||||
while (1) {
|
||||
if (skip_to_string("$Type:", "#End") != 1){
|
||||
break;
|
||||
}
|
||||
|
||||
z = skip_to_string("+Name:", "$Type:");
|
||||
if (!z){
|
||||
break;
|
||||
}
|
||||
|
||||
if (z == 1){
|
||||
stuff_string(goals[count], F_NAME, NAME_LENGTH);
|
||||
} else {
|
||||
sprintf(goals[count], NOX("Goal #%d"), count + 1);
|
||||
}
|
||||
|
||||
count++;
|
||||
if (count > MAX_GOALS) {
|
||||
Warning(LOCATION, "Maximum number of goals exceeded (%d)!", MAX_GOALS);
|
||||
count = MAX_GOALS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Campaign.missions[num].num_goals = count;
|
||||
if (count) {
|
||||
Campaign.missions[num].goals = (mgoal *) vm_malloc(count * sizeof(mgoal));
|
||||
Assert(Campaign.missions[num].goals); // make sure we got the memory
|
||||
memset(Campaign.missions[num].goals, 0, count * sizeof(mgoal));
|
||||
|
||||
for (i=0; i<count; i++){
|
||||
strcpy_s(Campaign.missions[num].goals[i].name, goals[i]);
|
||||
}
|
||||
}
|
||||
// copy the events
|
||||
Campaign.missions[num].num_events = event_count;
|
||||
if (event_count) {
|
||||
Campaign.missions[num].events = (mevent *)vm_malloc(event_count * sizeof(mevent));
|
||||
Assert ( Campaign.missions[num].events );
|
||||
memset(Campaign.missions[num].events, 0, event_count * sizeof(mevent));
|
||||
|
||||
for (i = 0; i < event_count; i++ ){
|
||||
strcpy_s(Campaign.missions[num].events[i].name, events[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Goober5000 - variables do not need to be read here
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1622,33 +1635,36 @@ void mission_campaign_maybe_play_movie(int type)
|
||||
*/
|
||||
int mission_campaign_parse_is_multi(char *filename, char *name)
|
||||
{
|
||||
int i, rval;
|
||||
int i;
|
||||
char temp[NAME_LENGTH];
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("MISSIONCAMPAIGN: Unable to parse '%s'! Error code = %i.\n", filename, rval));
|
||||
try
|
||||
{
|
||||
read_file_text(filename);
|
||||
reset_parse();
|
||||
|
||||
required_string("$Name:");
|
||||
stuff_string(temp, F_NAME, NAME_LENGTH);
|
||||
if (name)
|
||||
strcpy(name, temp);
|
||||
|
||||
required_string("$Type:");
|
||||
stuff_string(temp, F_NAME, NAME_LENGTH);
|
||||
|
||||
for (i = 0; i < MAX_CAMPAIGN_TYPES; i++) {
|
||||
if (!stricmp(temp, campaign_types[i])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
Error(LOCATION, "Unknown campaign type %s", temp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
read_file_text( filename );
|
||||
reset_parse();
|
||||
|
||||
required_string("$Name:");
|
||||
stuff_string( temp, F_NAME, NAME_LENGTH );
|
||||
if ( name )
|
||||
strcpy( name, temp );
|
||||
|
||||
required_string( "$Type:" );
|
||||
stuff_string( temp, F_NAME, NAME_LENGTH );
|
||||
|
||||
for (i = 0; i < MAX_CAMPAIGN_TYPES; i++ ) {
|
||||
if ( !stricmp(temp, campaign_types[i]) ) {
|
||||
return i;
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("MISSIONCAMPAIGN: Unable to parse '%s'! Error message = %s.\n", filename, e.what()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
Error(LOCATION, "Unknown campaign type %s", temp );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -561,7 +561,7 @@ void parse_msgtbl()
|
||||
|
||||
// now we can start parsing
|
||||
if (optional_string("#Message Frequencies")) {
|
||||
while (!required_string_3("$Name:", "#Personas", "#Moods" )) {
|
||||
while (!required_string_one_of(3, "$Name:", "#Personas", "#Moods" )) {
|
||||
message_frequency_parse();
|
||||
}
|
||||
}
|
||||
@@ -648,19 +648,22 @@ void parse_msgtbl()
|
||||
// this is called at the start of each level
|
||||
void messages_init()
|
||||
{
|
||||
int rval, i;
|
||||
int i;
|
||||
static int table_read = 0;
|
||||
|
||||
if ( !table_read ) {
|
||||
Default_command_persona = -1;
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", "messages.tbl", rval));
|
||||
|
||||
try
|
||||
{
|
||||
parse_msgtbl();
|
||||
table_read = 1;
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "messages.tbl", e.what()));
|
||||
return;
|
||||
}
|
||||
|
||||
parse_msgtbl();
|
||||
table_read = 1;
|
||||
}
|
||||
|
||||
Current_mission_mood = 0;
|
||||
@@ -1531,6 +1534,9 @@ void message_queue_process()
|
||||
|
||||
// Don't play death scream unless a small ship.
|
||||
if ( q->builtin_type == MESSAGE_WINGMAN_SCREAM ) {
|
||||
if (Message_shipnum < 0) {
|
||||
goto all_done;
|
||||
}
|
||||
if (!((Ship_info[Ships[Message_shipnum].ship_info_index].flags & SIF_SMALL_SHIP) || (Ships[Message_shipnum].flags2 & SF2_ALWAYS_DEATH_SCREAM)) ) {
|
||||
goto all_done;
|
||||
}
|
||||
@@ -1914,7 +1920,7 @@ void message_send_builtin_to_player( int type, ship *shipp, int priority, int ti
|
||||
char *who_from;
|
||||
int best_match = -1;
|
||||
|
||||
matching_builtin *current_builtin = new matching_builtin();
|
||||
matching_builtin current_builtin;
|
||||
SCP_vector <matching_builtin> matching_builtins;
|
||||
|
||||
|
||||
@@ -1976,52 +1982,52 @@ void message_send_builtin_to_player( int type, ship *shipp, int priority, int ti
|
||||
// check the type of message
|
||||
if ( !stricmp(Messages[i].name, name) ) {
|
||||
// condition 1: we have a type match
|
||||
current_builtin->message_index = i;
|
||||
current_builtin->type_of_match = BUILTIN_MATCHES_TYPE;
|
||||
current_builtin.message_index = i;
|
||||
current_builtin.type_of_match = BUILTIN_MATCHES_TYPE;
|
||||
|
||||
// check the species of this persona (if required)
|
||||
if ( (persona_species >= 0) && (Personas[Messages[i].persona_index].species == persona_species) ) {
|
||||
// condition 2: we have a type + species match
|
||||
current_builtin->type_of_match = BUILTIN_MATCHES_SPECIES;
|
||||
current_builtin.type_of_match = BUILTIN_MATCHES_SPECIES;
|
||||
}
|
||||
|
||||
// check the exact persona (if required)
|
||||
// NOTE: doesn't need to be nested under the species condition above
|
||||
if ( (persona_index >= 0) && (Messages[i].persona_index == persona_index) ) {
|
||||
// condition 3: type + species + persona index match
|
||||
current_builtin->type_of_match = BUILTIN_MATCHES_PERSONA_CHECK_MOOD;
|
||||
current_builtin.type_of_match = BUILTIN_MATCHES_PERSONA_CHECK_MOOD;
|
||||
}
|
||||
|
||||
// check if the personas mood suits this particular message, first check if it is excluded
|
||||
if (!Messages[i].excluded_moods.empty() && (current_builtin->type_of_match == BUILTIN_MATCHES_PERSONA_CHECK_MOOD)) {
|
||||
if (!Messages[i].excluded_moods.empty() && (current_builtin.type_of_match == BUILTIN_MATCHES_PERSONA_CHECK_MOOD)) {
|
||||
for (SCP_vector<int>::iterator iter = Messages[i].excluded_moods.begin(); iter != Messages[i].excluded_moods.end(); ++iter) {
|
||||
if (*iter == Current_mission_mood) {
|
||||
current_builtin->type_of_match = BUILTIN_MATCHES_PERSONA_EXCLUDED;
|
||||
current_builtin.type_of_match = BUILTIN_MATCHES_PERSONA_EXCLUDED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (current_builtin->type_of_match == BUILTIN_MATCHES_PERSONA_CHECK_MOOD) {
|
||||
if (current_builtin.type_of_match == BUILTIN_MATCHES_PERSONA_CHECK_MOOD) {
|
||||
if (Current_mission_mood == Messages[i].mood) {
|
||||
current_builtin->type_of_match = BUILTIN_MATCHES_PERSONA_MOOD;
|
||||
current_builtin.type_of_match = BUILTIN_MATCHES_PERSONA_MOOD;
|
||||
}
|
||||
else {
|
||||
current_builtin->type_of_match = BUILTIN_MATCHES_PERSONA;
|
||||
current_builtin.type_of_match = BUILTIN_MATCHES_PERSONA;
|
||||
}
|
||||
}
|
||||
|
||||
if (current_builtin->type_of_match == best_match) {
|
||||
if (current_builtin.type_of_match == best_match) {
|
||||
num_matching_builtins++;
|
||||
}
|
||||
// otherwise check to see if the this is the best kind of match we've found so far
|
||||
else if (current_builtin->type_of_match > best_match) {
|
||||
best_match = current_builtin->type_of_match;
|
||||
else if (current_builtin.type_of_match > best_match) {
|
||||
best_match = current_builtin.type_of_match;
|
||||
num_matching_builtins = 1;
|
||||
}
|
||||
|
||||
// add the match to our list
|
||||
matching_builtins.push_back(*current_builtin);
|
||||
matching_builtins.push_back(current_builtin);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1838,6 +1838,7 @@ int parse_create_object_sub(p_object *p_objp)
|
||||
|
||||
shipp->ship_max_shield_strength = p_objp->ship_max_shield_strength;
|
||||
shipp->ship_max_hull_strength = p_objp->ship_max_hull_strength;
|
||||
shipp->max_shield_recharge = p_objp->max_shield_recharge;
|
||||
|
||||
// Goober5000 - ugh, this is really stupid having to do this here; if the
|
||||
// ship creation code was better organized this wouldn't be necessary
|
||||
@@ -2250,7 +2251,7 @@ int parse_create_object_sub(p_object *p_objp)
|
||||
Objects[objnum].hull_strength = p_objp->initial_hull * shipp->ship_max_hull_strength / 100.0f;
|
||||
for (iLoop = 0; iLoop<Objects[objnum].n_quadrants; iLoop++)
|
||||
{
|
||||
Objects[objnum].shield_quadrant[iLoop] = (float) (p_objp->initial_shields * get_max_shield_quad(&Objects[objnum]) / 100.0f);
|
||||
Objects[objnum].shield_quadrant[iLoop] = (float) (shipp->max_shield_recharge * p_objp->initial_shields * get_max_shield_quad(&Objects[objnum]) / 100.0f);
|
||||
}
|
||||
|
||||
// initial velocities now do not apply to ships which warp in after mission starts
|
||||
@@ -3110,6 +3111,7 @@ int parse_object(mission *pm, int flag, p_object *p_objp)
|
||||
}
|
||||
|
||||
Assert(p_objp->ship_max_hull_strength > 0.0f); // Goober5000: div-0 check (not shield because we might not have one)
|
||||
p_objp->max_shield_recharge = Ship_info[p_objp->ship_class].max_shield_recharge;
|
||||
|
||||
|
||||
// if the kamikaze flag is set, we should have the next flag
|
||||
@@ -4603,8 +4605,9 @@ void resolve_path_masks(int anchor, int *path_mask)
|
||||
Assert(!(anchor & SPECIAL_ARRIVAL_ANCHOR_FLAG));
|
||||
parent_pobjp = mission_parse_get_parse_object(Parse_names[anchor]);
|
||||
|
||||
// load model for checking paths
|
||||
modelnum = model_load(Ship_info[parent_pobjp->ship_class].pof_file, 0, NULL);
|
||||
// Load the anchor ship model with subsystems and all; it'll need to be done for this mission anyway
|
||||
ship_info *sip = &Ship_info[parent_pobjp->ship_class];
|
||||
modelnum = model_load(sip->pof_file, sip->n_subsystems, &sip->subsystems[0]);
|
||||
|
||||
// resolve names to indexes
|
||||
*path_mask = 0;
|
||||
@@ -4617,9 +4620,6 @@ void resolve_path_masks(int anchor, int *path_mask)
|
||||
*path_mask |= (1 << bay_path);
|
||||
}
|
||||
|
||||
// unload model
|
||||
model_unload(modelnum);
|
||||
|
||||
// cache the result
|
||||
prp->cached_mask = *path_mask;
|
||||
}
|
||||
@@ -5832,39 +5832,38 @@ int get_mission_info(const char *filename, mission *mission_p, bool basic)
|
||||
if (p) *p = 0; // remove any extension
|
||||
strcat_s(real_fname, FS_MISSION_FILE_EXT); // append mission extension
|
||||
|
||||
int rval, filelength;
|
||||
int filelength;
|
||||
|
||||
// if mission_p is NULL, make it point to The_mission
|
||||
if ( mission_p == NULL )
|
||||
mission_p = &The_mission;
|
||||
|
||||
do {
|
||||
CFILE *ftemp = cfopen(real_fname, "rt");
|
||||
if (!ftemp) {
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
CFILE *ftemp = cfopen(real_fname, "rt");
|
||||
if (!ftemp) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 7/9/98 -- MWA -- check for 0 length file.
|
||||
filelength = cfilelength(ftemp);
|
||||
cfclose(ftemp);
|
||||
if (filelength == 0) {
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("MISSIONS: Unable to parse '%s'! Error code = %i.\n", real_fname, rval));
|
||||
break;
|
||||
}
|
||||
// 7/9/98 -- MWA -- check for 0 length file.
|
||||
filelength = cfilelength(ftemp);
|
||||
cfclose(ftemp);
|
||||
if (filelength == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
read_file_text(real_fname, CF_TYPE_MISSIONS);
|
||||
mission_p->Reset( );
|
||||
mission_p->Reset();
|
||||
parse_init(basic);
|
||||
parse_mission_info(mission_p, basic);
|
||||
} while (0);
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("MISSIONS: Unable to parse '%s'! Error message = %s.\n", real_fname, e.what()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return rval;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -5926,22 +5925,27 @@ int parse_main(const char *mission_name, int flags)
|
||||
cfclose(ftemp);
|
||||
}
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("MISSIONS: Unable to parse '%s'! Error code = %i.\n", mission_name, rval));
|
||||
try
|
||||
{
|
||||
// import?
|
||||
if (flags & MPF_IMPORT_FSM) {
|
||||
read_file_text(mission_name, CF_TYPE_ANY);
|
||||
convertFSMtoFS2();
|
||||
}
|
||||
else {
|
||||
read_file_text(mission_name, CF_TYPE_MISSIONS);
|
||||
}
|
||||
|
||||
The_mission.Reset();
|
||||
rval = parse_mission(&The_mission, flags);
|
||||
display_parse_diagnostics();
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("MISSIONS: Unable to parse '%s'! Error message = %s.\n", mission_name, e.what()));
|
||||
rval = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
// import?
|
||||
if (flags & MPF_IMPORT_FSM) {
|
||||
read_file_text(mission_name, CF_TYPE_ANY);
|
||||
convertFSMtoFS2();
|
||||
} else {
|
||||
read_file_text(mission_name, CF_TYPE_MISSIONS);
|
||||
}
|
||||
|
||||
The_mission.Reset( );
|
||||
rval = parse_mission(&The_mission, flags);
|
||||
display_parse_diagnostics();
|
||||
} while (0);
|
||||
|
||||
if (!Fred_running)
|
||||
@@ -6283,7 +6287,7 @@ void mission_parse_set_up_initial_docks()
|
||||
*/
|
||||
int mission_parse_is_multi(const char *filename, char *mission_name)
|
||||
{
|
||||
int rval, game_type;
|
||||
int game_type;
|
||||
int filelength;
|
||||
CFILE *ftemp;
|
||||
|
||||
@@ -6302,25 +6306,28 @@ int mission_parse_is_multi(const char *filename, char *mission_name)
|
||||
|
||||
game_type = 0;
|
||||
do {
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("MISSIONS: Unable to parse '%s'! Error code = %i.\n", filename, rval));
|
||||
try
|
||||
{
|
||||
read_file_text(filename, CF_TYPE_MISSIONS);
|
||||
reset_parse();
|
||||
|
||||
if (skip_to_string("$Name:") != 1) {
|
||||
nprintf(("Network", "Unable to process %s because we couldn't find $Name:", filename));
|
||||
break;
|
||||
}
|
||||
stuff_string(mission_name, F_NAME, NAME_LENGTH);
|
||||
|
||||
if (skip_to_string("+Game Type Flags:") != 1) {
|
||||
nprintf(("Network", "Unable to process %s because we couldn't find +Game Type Flags:\n", filename));
|
||||
break;
|
||||
}
|
||||
stuff_int(&game_type);
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("MISSIONS: Unable to parse '%s'! Error message = %s.\n", filename, e.what()));
|
||||
break;
|
||||
}
|
||||
|
||||
read_file_text(filename, CF_TYPE_MISSIONS);
|
||||
reset_parse();
|
||||
|
||||
if ( skip_to_string("$Name:") != 1 ) {
|
||||
nprintf(("Network", "Unable to process %s because we couldn't find $Name:", filename));
|
||||
break;
|
||||
}
|
||||
stuff_string( mission_name, F_NAME, NAME_LENGTH );
|
||||
|
||||
if ( skip_to_string("+Game Type Flags:") != 1 ) {
|
||||
nprintf(("Network", "Unable to process %s because we couldn't find +Game Type Flags:\n", filename));
|
||||
break;
|
||||
}
|
||||
stuff_int(&game_type);
|
||||
} while (0);
|
||||
|
||||
return (game_type & MISSION_TYPE_MULTI) ? game_type : 0;
|
||||
@@ -7555,6 +7562,7 @@ void mission_bring_in_support_ship( object *requester_objp )
|
||||
// set support ship hitpoints
|
||||
pobj->ship_max_hull_strength = Ship_info[i].max_hull_strength;
|
||||
pobj->ship_max_shield_strength = Ship_info[i].max_shield_strength;
|
||||
pobj->max_shield_recharge = Ship_info[i].max_shield_recharge;
|
||||
|
||||
pobj->team = requester_shipp->team;
|
||||
|
||||
|
||||
@@ -424,6 +424,8 @@ public:
|
||||
float ship_max_hull_strength; // Needed to deal with special hitpoints
|
||||
float ship_max_shield_strength;
|
||||
|
||||
float max_shield_recharge;
|
||||
|
||||
// Goober5000
|
||||
SCP_vector<texture_replace> replacement_textures;
|
||||
|
||||
|
||||
@@ -1058,49 +1058,51 @@ void debrief_traitor_init()
|
||||
if ( !inited ) {
|
||||
debriefing *debrief;
|
||||
debrief_stage *stagep;
|
||||
int rval;
|
||||
int stage_num;
|
||||
|
||||
try
|
||||
{
|
||||
read_file_text("traitor.tbl", CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", "traitor.tbl", rval));
|
||||
// simplied form of the debriefing stuff.
|
||||
debrief = &Traitor_debriefing;
|
||||
required_string("#Debriefing_info");
|
||||
|
||||
required_string("$Num stages:");
|
||||
stuff_int(&debrief->num_stages);
|
||||
Assert(debrief->num_stages == 1);
|
||||
|
||||
stage_num = 0;
|
||||
stagep = &debrief->stages[stage_num++];
|
||||
required_string("$Formula:");
|
||||
stagep->formula = get_sexp_main();
|
||||
required_string("$multi text");
|
||||
stuff_string(stagep->text, F_MULTITEXT, NULL);
|
||||
required_string("$Voice:");
|
||||
char traitor_voice_file[MAX_FILENAME_LEN];
|
||||
stuff_string(traitor_voice_file, F_FILESPEC, MAX_FILENAME_LEN);
|
||||
|
||||
// DKA 9/13/99 Only 1 traitor msg for FS2
|
||||
// if ( Player->main_hall ) {
|
||||
// strcpy_s(stagep->voice, NOX("3_"));
|
||||
// } else {
|
||||
// strcpy_s(stagep->voice, NOX("1_"));
|
||||
// }
|
||||
|
||||
// Goober5000
|
||||
debrief_choose_voice(stagep->voice, traitor_voice_file, debrief_find_persona_index(), 1);
|
||||
|
||||
required_string("$Recommendation text:");
|
||||
stuff_string(stagep->recommendation_text, F_MULTITEXT, NULL);
|
||||
|
||||
inited = 1;
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "traitor.tbl", e.what()));
|
||||
return;
|
||||
}
|
||||
|
||||
read_file_text("traitor.tbl", CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
// simplied form of the debriefing stuff.
|
||||
debrief = &Traitor_debriefing;
|
||||
required_string("#Debriefing_info");
|
||||
|
||||
required_string("$Num stages:");
|
||||
stuff_int(&debrief->num_stages);
|
||||
Assert(debrief->num_stages == 1);
|
||||
|
||||
stage_num = 0;
|
||||
stagep = &debrief->stages[stage_num++];
|
||||
required_string("$Formula:");
|
||||
stagep->formula = get_sexp_main();
|
||||
required_string("$multi text");
|
||||
stuff_string( stagep->text, F_MULTITEXT, NULL);
|
||||
required_string("$Voice:");
|
||||
char traitor_voice_file[MAX_FILENAME_LEN];
|
||||
stuff_string(traitor_voice_file, F_FILESPEC, MAX_FILENAME_LEN);
|
||||
|
||||
// DKA 9/13/99 Only 1 traitor msg for FS2
|
||||
// if ( Player->main_hall ) {
|
||||
// strcpy_s(stagep->voice, NOX("3_"));
|
||||
// } else {
|
||||
// strcpy_s(stagep->voice, NOX("1_"));
|
||||
// }
|
||||
|
||||
// Goober5000
|
||||
debrief_choose_voice(stagep->voice, traitor_voice_file, debrief_find_persona_index(), 1);
|
||||
|
||||
required_string("$Recommendation text:");
|
||||
stuff_string( stagep->recommendation_text, F_MULTITEXT, NULL);
|
||||
|
||||
inited = 1;
|
||||
}
|
||||
|
||||
// disable the accept button if in single player and I am a traitor
|
||||
|
||||
@@ -1513,6 +1513,11 @@ void draw_model_icon(int model_id, int flags, float closeup_zoom, int x, int y,
|
||||
//Assume it's a weapon
|
||||
rot_angles.h = -(PI_2);
|
||||
}
|
||||
else if(sip->model_icon_angles.p != 0.0f || sip->model_icon_angles.b != 0.0f || sip->model_icon_angles.h != 0.0f)
|
||||
{
|
||||
// If non-zero model_icon_angles exists, always use that
|
||||
rot_angles = sip->model_icon_angles;
|
||||
}
|
||||
else if(sip->flags & SIF_SMALL_SHIP)
|
||||
{
|
||||
rot_angles.p = -(PI_2);
|
||||
|
||||
+218
-211
@@ -36,240 +36,247 @@ bool Beams_use_damage_factors = false;
|
||||
|
||||
void parse_mod_table(const char *filename)
|
||||
{
|
||||
int rval;
|
||||
// SCP_vector<SCP_string> lines;
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0)
|
||||
try
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", (filename) ? filename : "<default game_settings.tbl>", rval));
|
||||
return;
|
||||
}
|
||||
if (filename == NULL)
|
||||
read_file_text_from_array(defaults_get_file("game_settings.tbl"));
|
||||
else
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
|
||||
if (filename == NULL)
|
||||
read_file_text_from_array(defaults_get_file("game_settings.tbl"));
|
||||
else
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
reset_parse();
|
||||
// start parsing
|
||||
optional_string("#CAMPAIGN SETTINGS");
|
||||
|
||||
// start parsing
|
||||
optional_string("#CAMPAIGN SETTINGS");
|
||||
|
||||
if (optional_string("$Default Campaign File Name:")) {
|
||||
char temp[MAX_FILENAME_LEN];
|
||||
stuff_string(temp, F_NAME, MAX_FILENAME_LEN);
|
||||
|
||||
// remove extension?
|
||||
if (drop_extension(temp)) {
|
||||
mprintf(("Game Settings Table: Removed extension on default campaign file name %s\n", temp));
|
||||
}
|
||||
|
||||
// check length
|
||||
int maxlen = (MAX_FILENAME_LEN - 4);
|
||||
int len = strlen(temp);
|
||||
if (len > maxlen) {
|
||||
Warning(LOCATION, "Token too long: [%s]. Length = %i. Max is %i.\n", temp, len, maxlen);
|
||||
temp[maxlen] = 0;
|
||||
}
|
||||
|
||||
strcpy_s(Default_campaign_file_name, temp);
|
||||
}
|
||||
|
||||
if (optional_string("#Ignored Campaign File Names")) {
|
||||
SCP_string campaign_name;
|
||||
|
||||
while (optional_string("$Campaign File Name:")) {
|
||||
stuff_string(campaign_name, F_NAME);
|
||||
if (optional_string("$Default Campaign File Name:")) {
|
||||
char temp[MAX_FILENAME_LEN];
|
||||
stuff_string(temp, F_NAME, MAX_FILENAME_LEN);
|
||||
|
||||
// remove extension?
|
||||
if (drop_extension(campaign_name)) {
|
||||
mprintf(("Game Settings Table: Removed extension on ignored campaign file name %s\n", campaign_name.c_str()));
|
||||
if (drop_extension(temp)) {
|
||||
mprintf(("Game Settings Table: Removed extension on default campaign file name %s\n", temp));
|
||||
}
|
||||
|
||||
Ignored_campaigns.push_back(campaign_name);
|
||||
// check length
|
||||
int maxlen = (MAX_FILENAME_LEN - 4);
|
||||
int len = strlen(temp);
|
||||
if (len > maxlen) {
|
||||
Warning(LOCATION, "Token too long: [%s]. Length = %i. Max is %i.\n", temp, len, maxlen);
|
||||
temp[maxlen] = 0;
|
||||
}
|
||||
|
||||
strcpy_s(Default_campaign_file_name, temp);
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Red-alert applies to delayed ships:")) {
|
||||
stuff_boolean(&Red_alert_applies_to_delayed_ships);
|
||||
if (Red_alert_applies_to_delayed_ships) {
|
||||
mprintf(("Game Settings Table: Red-alert stats will be loaded for ships that arrive later in missions\n"));
|
||||
} else {
|
||||
mprintf(("Game Settings Table: Red-alert stats will NOT be loaded for ships that arrive later in missions (this is retail behavior)\n"));
|
||||
if (optional_string("#Ignored Campaign File Names")) {
|
||||
SCP_string campaign_name;
|
||||
|
||||
while (optional_string("$Campaign File Name:")) {
|
||||
stuff_string(campaign_name, F_NAME);
|
||||
|
||||
// remove extension?
|
||||
if (drop_extension(campaign_name)) {
|
||||
mprintf(("Game Settings Table: Removed extension on ignored campaign file name %s\n", campaign_name.c_str()));
|
||||
}
|
||||
|
||||
Ignored_campaigns.push_back(campaign_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
optional_string("#HUD SETTINGS");
|
||||
|
||||
// how long should the game wait before displaying a directive?
|
||||
if (optional_string("$Directive Wait Time:")) {
|
||||
stuff_int(&Directive_wait_time);
|
||||
}
|
||||
|
||||
if (optional_string("$Cutscene camera displays HUD:")) {
|
||||
stuff_boolean(&Cutscene_camera_displays_hud);
|
||||
}
|
||||
// compatibility
|
||||
if (optional_string("$Cutscene camera disables HUD:")) {
|
||||
mprintf(("Game Settings Table: \"$$Cutscene camera disables HUD\" is deprecated in favor of \"$Cutscene camera displays HUD\"\n"));
|
||||
bool temp;
|
||||
stuff_boolean(&temp);
|
||||
Cutscene_camera_displays_hud = !temp;
|
||||
}
|
||||
|
||||
if (optional_string("$Full color head animations:")) {
|
||||
stuff_boolean(&Full_color_head_anis);
|
||||
}
|
||||
// compatibility
|
||||
if (optional_string("$Color head animations with hud colors:")) {
|
||||
mprintf(("Game Settings Table: \"$Color head animations with hud colors\" is deprecated in favor of \"$Full color head animations\"\n"));
|
||||
bool temp;
|
||||
stuff_boolean(&temp);
|
||||
Full_color_head_anis = !temp;
|
||||
}
|
||||
|
||||
optional_string("#SEXP SETTINGS");
|
||||
|
||||
if (optional_string("$Loop SEXPs Then Arguments:")) {
|
||||
stuff_boolean(&True_loop_argument_sexps);
|
||||
if (True_loop_argument_sexps) {
|
||||
mprintf(("Game Settings Table: Using Reversed Loops For SEXP Arguments\n"));
|
||||
} else {
|
||||
mprintf(("Game Settings Table: Using Standard Loops For SEXP Arguments\n"));
|
||||
if (optional_string("$Red-alert applies to delayed ships:")) {
|
||||
stuff_boolean(&Red_alert_applies_to_delayed_ships);
|
||||
if (Red_alert_applies_to_delayed_ships) {
|
||||
mprintf(("Game Settings Table: Red-alert stats will be loaded for ships that arrive later in missions\n"));
|
||||
}
|
||||
else {
|
||||
mprintf(("Game Settings Table: Red-alert stats will NOT be loaded for ships that arrive later in missions (this is retail behavior)\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Use Alternate Chaining Behavior:")) {
|
||||
stuff_boolean(&Alternate_chaining_behavior);
|
||||
if (Alternate_chaining_behavior) {
|
||||
mprintf(("Game Settings Table: Using alternate event chaining behavior\n"));
|
||||
} else {
|
||||
mprintf(("Game Settings Table: Using standard event chaining behavior\n"));
|
||||
optional_string("#HUD SETTINGS");
|
||||
|
||||
// how long should the game wait before displaying a directive?
|
||||
if (optional_string("$Directive Wait Time:")) {
|
||||
stuff_int(&Directive_wait_time);
|
||||
}
|
||||
}
|
||||
|
||||
optional_string("#GRAPHICS SETTINGS");
|
||||
|
||||
if (optional_string("$Enable External Shaders:")) {
|
||||
stuff_boolean(&Enable_external_shaders);
|
||||
if (Enable_external_shaders)
|
||||
mprintf(("Game Settings Table: External shaders are enabled\n"));
|
||||
else
|
||||
mprintf(("Game Settings Table: External shaders are DISABLED\n"));
|
||||
}
|
||||
|
||||
if (optional_string("$Default Detail Level:")) {
|
||||
int detail_level;
|
||||
|
||||
stuff_int(&detail_level);
|
||||
|
||||
mprintf(("Game Settings Table: Setting default detail level to %i of %i-%i\n", detail_level, 0, NUM_DEFAULT_DETAIL_LEVELS-1));
|
||||
|
||||
if (detail_level < 0 || detail_level > NUM_DEFAULT_DETAIL_LEVELS-1) {
|
||||
Warning(LOCATION, "Invalid detail level: %i, setting to %i\n", detail_level, Default_detail_level);
|
||||
} else {
|
||||
Default_detail_level = detail_level;
|
||||
if (optional_string("$Cutscene camera displays HUD:")) {
|
||||
stuff_boolean(&Cutscene_camera_displays_hud);
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Briefing Window FOV:")) {
|
||||
float fov;
|
||||
|
||||
stuff_float(&fov);
|
||||
|
||||
mprintf(("Game Settings Table: Setting briefing window FOV from %f to %f\n", Briefing_window_FOV, fov));
|
||||
|
||||
Briefing_window_FOV = fov;
|
||||
}
|
||||
|
||||
optional_string("#NETWORK SETTINGS");
|
||||
|
||||
if (optional_string("$FS2NetD port:")) {
|
||||
stuff_int(&FS2NetD_port);
|
||||
if (FS2NetD_port)
|
||||
mprintf(("Game Settings Table: FS2NetD connecting to port %i\n", FS2NetD_port));
|
||||
}
|
||||
|
||||
optional_string("#SOUND SETTINGS");
|
||||
|
||||
if (optional_string("$Default Sound Volume:")) {
|
||||
stuff_float(&Master_sound_volume);
|
||||
}
|
||||
|
||||
if (optional_string("$Default Music Volume:")) {
|
||||
stuff_float(&Master_event_music_volume);
|
||||
}
|
||||
|
||||
if (optional_string("$Default Voice Volume:")) {
|
||||
stuff_float(&Master_voice_volume);
|
||||
}
|
||||
|
||||
optional_string("#FRED SETTINGS");
|
||||
|
||||
if (optional_string("$Disable Hard Coded Message Head Ani Files:")) {
|
||||
stuff_boolean(&Disable_hc_message_ani);
|
||||
if (Disable_hc_message_ani) {
|
||||
mprintf(("Game Settings Table: FRED - Disabling Hard Coded Message Ani Files\n"));
|
||||
} else {
|
||||
mprintf(("Game Settings Table: FRED - Using Hard Coded Message Ani Files\n"));
|
||||
|
||||
// compatibility
|
||||
if (optional_string("$Cutscene camera disables HUD:")) {
|
||||
mprintf(("Game Settings Table: \"$$Cutscene camera disables HUD\" is deprecated in favor of \"$Cutscene camera displays HUD\"\n"));
|
||||
bool temp;
|
||||
stuff_boolean(&temp);
|
||||
Cutscene_camera_displays_hud = !temp;
|
||||
}
|
||||
}
|
||||
|
||||
optional_string("#OTHER SETTINGS");
|
||||
|
||||
if (optional_string("$Fixed Turret Collisions:")) {
|
||||
stuff_boolean(&Fixed_turret_collisions);
|
||||
}
|
||||
|
||||
if (optional_string("$Damage Impacted Subsystem First:")) {
|
||||
stuff_boolean(&Damage_impacted_subsystem_first);
|
||||
}
|
||||
|
||||
if (optional_string("$Default ship select effect:")) {
|
||||
char effect[NAME_LENGTH];
|
||||
stuff_string(effect, F_NAME, NAME_LENGTH);
|
||||
if (!stricmp(effect, "FS2"))
|
||||
Default_ship_select_effect = 2;
|
||||
else if (!stricmp(effect, "FS1"))
|
||||
Default_ship_select_effect = 1;
|
||||
else if (!stricmp(effect, "off"))
|
||||
Default_ship_select_effect = 0;
|
||||
}
|
||||
|
||||
if (optional_string("$Default weapon select effect:")) {
|
||||
char effect[NAME_LENGTH];
|
||||
stuff_string(effect, F_NAME, NAME_LENGTH);
|
||||
if (!stricmp(effect, "FS2"))
|
||||
Default_weapon_select_effect = 2;
|
||||
else if (!stricmp(effect, "FS1"))
|
||||
Default_weapon_select_effect = 1;
|
||||
else if (!stricmp(effect, "off"))
|
||||
Default_weapon_select_effect = 0;
|
||||
}
|
||||
|
||||
if (optional_string("$Weapons inherit parent collision group:")) {
|
||||
stuff_boolean(&Weapons_inherit_parent_collision_group);
|
||||
if (Weapons_inherit_parent_collision_group)
|
||||
mprintf(("Game Settings Table: Weapons inherit parent collision group\n"));
|
||||
}
|
||||
|
||||
if (optional_string("$Flight controls follow eyepoint orientation:")) {
|
||||
stuff_boolean(&Flight_controls_follow_eyepoint_orientation);
|
||||
if (Flight_controls_follow_eyepoint_orientation)
|
||||
mprintf(("Game Settings Table: Flight controls follow eyepoint orientation\n"));
|
||||
}
|
||||
|
||||
if (optional_string("$Beams Use Damage Factors:")) {
|
||||
stuff_boolean(&Beams_use_damage_factors);
|
||||
if (Beams_use_damage_factors) {
|
||||
mprintf(("Game Settings Table: Beams will use Damage Factors\n"));
|
||||
} else {
|
||||
mprintf(("Game Settings Table: Beams will ignore Damage Factors (retail behavior)\n"));
|
||||
if (optional_string("$Full color head animations:")) {
|
||||
stuff_boolean(&Full_color_head_anis);
|
||||
}
|
||||
// compatibility
|
||||
if (optional_string("$Color head animations with hud colors:")) {
|
||||
mprintf(("Game Settings Table: \"$Color head animations with hud colors\" is deprecated in favor of \"$Full color head animations\"\n"));
|
||||
bool temp;
|
||||
stuff_boolean(&temp);
|
||||
Full_color_head_anis = !temp;
|
||||
}
|
||||
}
|
||||
|
||||
required_string("#END");
|
||||
optional_string("#SEXP SETTINGS");
|
||||
|
||||
if (optional_string("$Loop SEXPs Then Arguments:")) {
|
||||
stuff_boolean(&True_loop_argument_sexps);
|
||||
if (True_loop_argument_sexps) {
|
||||
mprintf(("Game Settings Table: Using Reversed Loops For SEXP Arguments\n"));
|
||||
}
|
||||
else {
|
||||
mprintf(("Game Settings Table: Using Standard Loops For SEXP Arguments\n"));
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Use Alternate Chaining Behavior:")) {
|
||||
stuff_boolean(&Alternate_chaining_behavior);
|
||||
if (Alternate_chaining_behavior) {
|
||||
mprintf(("Game Settings Table: Using alternate event chaining behavior\n"));
|
||||
}
|
||||
else {
|
||||
mprintf(("Game Settings Table: Using standard event chaining behavior\n"));
|
||||
}
|
||||
}
|
||||
|
||||
optional_string("#GRAPHICS SETTINGS");
|
||||
|
||||
if (optional_string("$Enable External Shaders:")) {
|
||||
stuff_boolean(&Enable_external_shaders);
|
||||
if (Enable_external_shaders)
|
||||
mprintf(("Game Settings Table: External shaders are enabled\n"));
|
||||
else
|
||||
mprintf(("Game Settings Table: External shaders are DISABLED\n"));
|
||||
}
|
||||
|
||||
if (optional_string("$Default Detail Level:")) {
|
||||
int detail_level;
|
||||
|
||||
stuff_int(&detail_level);
|
||||
|
||||
mprintf(("Game Settings Table: Setting default detail level to %i of %i-%i\n", detail_level, 0, NUM_DEFAULT_DETAIL_LEVELS - 1));
|
||||
|
||||
if (detail_level < 0 || detail_level > NUM_DEFAULT_DETAIL_LEVELS - 1) {
|
||||
Warning(LOCATION, "Invalid detail level: %i, setting to %i\n", detail_level, Default_detail_level);
|
||||
}
|
||||
else {
|
||||
Default_detail_level = detail_level;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Briefing Window FOV:")) {
|
||||
float fov;
|
||||
|
||||
stuff_float(&fov);
|
||||
|
||||
mprintf(("Game Settings Table: Setting briefing window FOV from %f to %f\n", Briefing_window_FOV, fov));
|
||||
|
||||
Briefing_window_FOV = fov;
|
||||
}
|
||||
|
||||
optional_string("#NETWORK SETTINGS");
|
||||
|
||||
if (optional_string("$FS2NetD port:")) {
|
||||
stuff_int(&FS2NetD_port);
|
||||
if (FS2NetD_port)
|
||||
mprintf(("Game Settings Table: FS2NetD connecting to port %i\n", FS2NetD_port));
|
||||
}
|
||||
|
||||
optional_string("#SOUND SETTINGS");
|
||||
|
||||
if (optional_string("$Default Sound Volume:")) {
|
||||
stuff_float(&Master_sound_volume);
|
||||
}
|
||||
|
||||
if (optional_string("$Default Music Volume:")) {
|
||||
stuff_float(&Master_event_music_volume);
|
||||
}
|
||||
|
||||
if (optional_string("$Default Voice Volume:")) {
|
||||
stuff_float(&Master_voice_volume);
|
||||
}
|
||||
|
||||
optional_string("#FRED SETTINGS");
|
||||
|
||||
if (optional_string("$Disable Hard Coded Message Head Ani Files:")) {
|
||||
stuff_boolean(&Disable_hc_message_ani);
|
||||
if (Disable_hc_message_ani) {
|
||||
mprintf(("Game Settings Table: FRED - Disabling Hard Coded Message Ani Files\n"));
|
||||
}
|
||||
else {
|
||||
mprintf(("Game Settings Table: FRED - Using Hard Coded Message Ani Files\n"));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
optional_string("#OTHER SETTINGS");
|
||||
|
||||
if (optional_string("$Fixed Turret Collisions:")) {
|
||||
stuff_boolean(&Fixed_turret_collisions);
|
||||
}
|
||||
|
||||
if (optional_string("$Damage Impacted Subsystem First:")) {
|
||||
stuff_boolean(&Damage_impacted_subsystem_first);
|
||||
}
|
||||
|
||||
if (optional_string("$Default ship select effect:")) {
|
||||
char effect[NAME_LENGTH];
|
||||
stuff_string(effect, F_NAME, NAME_LENGTH);
|
||||
if (!stricmp(effect, "FS2"))
|
||||
Default_ship_select_effect = 2;
|
||||
else if (!stricmp(effect, "FS1"))
|
||||
Default_ship_select_effect = 1;
|
||||
else if (!stricmp(effect, "off"))
|
||||
Default_ship_select_effect = 0;
|
||||
}
|
||||
|
||||
if (optional_string("$Default weapon select effect:")) {
|
||||
char effect[NAME_LENGTH];
|
||||
stuff_string(effect, F_NAME, NAME_LENGTH);
|
||||
if (!stricmp(effect, "FS2"))
|
||||
Default_weapon_select_effect = 2;
|
||||
else if (!stricmp(effect, "FS1"))
|
||||
Default_weapon_select_effect = 1;
|
||||
else if (!stricmp(effect, "off"))
|
||||
Default_weapon_select_effect = 0;
|
||||
}
|
||||
|
||||
if (optional_string("$Weapons inherit parent collision group:")) {
|
||||
stuff_boolean(&Weapons_inherit_parent_collision_group);
|
||||
if (Weapons_inherit_parent_collision_group)
|
||||
mprintf(("Game Settings Table: Weapons inherit parent collision group\n"));
|
||||
}
|
||||
|
||||
if (optional_string("$Flight controls follow eyepoint orientation:")) {
|
||||
stuff_boolean(&Flight_controls_follow_eyepoint_orientation);
|
||||
if (Flight_controls_follow_eyepoint_orientation)
|
||||
mprintf(("Game Settings Table: Flight controls follow eyepoint orientation\n"));
|
||||
}
|
||||
|
||||
if (optional_string("$Beams Use Damage Factors:")) {
|
||||
stuff_boolean(&Beams_use_damage_factors);
|
||||
if (Beams_use_damage_factors) {
|
||||
mprintf(("Game Settings Table: Beams will use Damage Factors\n"));
|
||||
}
|
||||
else {
|
||||
mprintf(("Game Settings Table: Beams will ignore Damage Factors (retail behavior)\n"));
|
||||
}
|
||||
}
|
||||
|
||||
required_string("#END");
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", (filename) ? filename : "<default game_settings.tbl>", e.what()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void mod_table_init()
|
||||
|
||||
+2
-1
@@ -1022,7 +1022,8 @@ typedef struct mc_info {
|
||||
vec3d *p0; // The starting point of the ray (sphere) to check
|
||||
vec3d *p1; // The ending point of the ray (sphere) to check
|
||||
int flags; // Flags that the model_collide code looks at. See MC_??? defines
|
||||
float radius; // If MC_CHECK_THICK is set, checks a sphere moving with the radius.
|
||||
float radius; // If MC_CHECK_THICK is set, checks a sphere moving with the radius.
|
||||
int lod; // Which detail level of the submodel to check instead
|
||||
|
||||
// Return values
|
||||
int num_hits; // How many collisions were found
|
||||
|
||||
@@ -1130,7 +1130,22 @@ void mc_check_subobj( int mn )
|
||||
if ( Cmdline_old_collision_sys ) {
|
||||
model_collide_sub(sm->bsp_data);
|
||||
} else {
|
||||
model_collide_bsp(model_get_bsp_collision_tree(sm->collision_tree_index), 0);
|
||||
if (Mc->lod > 0 && sm->num_details > 0) {
|
||||
bsp_info *lod_sm = sm;
|
||||
|
||||
for (int i = Mc->lod - 1; i >= 0; i--) {
|
||||
if (sm->details[i] != -1) {
|
||||
lod_sm = &Mc_pm->submodel[sm->details[i]];
|
||||
|
||||
//mprintf(("Checking %s collision for %s using %s instead\n", Mc_pm->filename, sm->name, lod_sm->name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
model_collide_bsp(model_get_bsp_collision_tree(lod_sm->collision_tree_index), 0);
|
||||
} else {
|
||||
model_collide_bsp(model_get_bsp_collision_tree(sm->collision_tree_index), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+51
-31
@@ -83,7 +83,6 @@ static float Interp_box_scale = 1.0f; // this is used to scale both detail boxes
|
||||
static vec3d Interp_render_box_min = ZERO_VECTOR;
|
||||
static vec3d Interp_render_box_max = ZERO_VECTOR;
|
||||
static float Interp_render_sphere_radius = 0.0f;
|
||||
static vec3d Interp_render_sphere_offset = ZERO_VECTOR;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// lighting save stuff
|
||||
@@ -369,7 +368,6 @@ void interp_clear_instance()
|
||||
Interp_render_box_min = vmd_zero_vector;
|
||||
Interp_render_box_max = vmd_zero_vector;
|
||||
Interp_render_sphere_radius = 0.0f;
|
||||
Interp_render_sphere_offset = vmd_zero_vector;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2728,6 +2726,7 @@ void model_really_render(int model_num, matrix *orient, vec3d * pos, uint flags,
|
||||
uint save_gr_zbuffering_mode;
|
||||
int zbuf_mode;
|
||||
ship *shipp = NULL;
|
||||
ship_info *sip = NULL;
|
||||
object *objp = NULL;
|
||||
bool set_autocen = false;
|
||||
bool draw_thrusters = false;
|
||||
@@ -2742,6 +2741,7 @@ void model_really_render(int model_num, matrix *orient, vec3d * pos, uint flags,
|
||||
|
||||
if (objp->type == OBJ_SHIP) {
|
||||
shipp = &Ships[objp->instance];
|
||||
sip = &Ship_info[shipp->ship_info_index];
|
||||
|
||||
if (shipp->flags2 & SF2_GLOWMAPS_DISABLED)
|
||||
flags |= MR_NO_GLOWMAPS;
|
||||
@@ -2905,33 +2905,37 @@ void model_really_render(int model_num, matrix *orient, vec3d * pos, uint flags,
|
||||
}
|
||||
#endif
|
||||
|
||||
// scale the render box settings based on the "Model Detail" slider
|
||||
switch (Detail.detail_distance)
|
||||
{
|
||||
// 1st dot is 20%
|
||||
case 0:
|
||||
Interp_box_scale = 0.2f;
|
||||
break;
|
||||
if (shipp != NULL && (sip->flags2 & SIF2_LOCK_DETAIL_BOXES)) {
|
||||
Interp_box_scale = 1.0f;
|
||||
} else {
|
||||
// scale the render box settings based on the "Model Detail" slider
|
||||
switch (Detail.detail_distance)
|
||||
{
|
||||
// 1st dot is 20%
|
||||
case 0:
|
||||
Interp_box_scale = 0.2f;
|
||||
break;
|
||||
|
||||
// 2nd dot is 50%
|
||||
case 1:
|
||||
Interp_box_scale = 0.5f;
|
||||
break;
|
||||
// 2nd dot is 50%
|
||||
case 1:
|
||||
Interp_box_scale = 0.5f;
|
||||
break;
|
||||
|
||||
// 3rd dot is 80%
|
||||
case 2:
|
||||
Interp_box_scale = 0.8f;
|
||||
break;
|
||||
// 3rd dot is 80%
|
||||
case 2:
|
||||
Interp_box_scale = 0.8f;
|
||||
break;
|
||||
|
||||
// 4th dot is 100% (this is the default setting for "High" and "Very High" settings)
|
||||
case 3:
|
||||
Interp_box_scale = 1.0f;
|
||||
break;
|
||||
// 4th dot is 100% (this is the default setting for "High" and "Very High" settings)
|
||||
case 3:
|
||||
Interp_box_scale = 1.0f;
|
||||
break;
|
||||
|
||||
// 5th dot (max) is 120%
|
||||
case 4:
|
||||
Interp_box_scale = 1.2f;
|
||||
break;
|
||||
// 5th dot (max) is 120%
|
||||
case 4:
|
||||
Interp_box_scale = 1.2f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
vec3d auto_back = ZERO_VECTOR;
|
||||
@@ -4468,7 +4472,13 @@ void model_render_children_buffers(polymodel *pm, int mn, int detail_level)
|
||||
vm_vec_copy_scale(&Interp_render_box_min, &model->render_box_min, Interp_box_scale);
|
||||
vm_vec_copy_scale(&Interp_render_box_max, &model->render_box_max, Interp_box_scale);
|
||||
|
||||
if ( (-model->use_render_box + in_box(&Interp_render_box_min, &Interp_render_box_max, &model->offset)) )
|
||||
vec3d offset;
|
||||
if (model->use_render_box_offset)
|
||||
offset = model->render_box_offset;
|
||||
else
|
||||
model_find_submodel_offset(&offset, pm->id, mn);
|
||||
|
||||
if ( (-model->use_render_box + in_box(&Interp_render_box_min, &Interp_render_box_max, &offset)) )
|
||||
return;
|
||||
}
|
||||
if ( !(Interp_flags & MR_FULL_DETAIL) && model->use_render_sphere ) {
|
||||
@@ -4476,8 +4486,10 @@ void model_render_children_buffers(polymodel *pm, int mn, int detail_level)
|
||||
|
||||
// TODO: doesn't consider submodel rotations yet -zookeeper
|
||||
vec3d offset;
|
||||
model_find_submodel_offset(&offset, pm->id, mn);
|
||||
vm_vec_add2(&offset, &model->render_sphere_offset);
|
||||
if (model->use_render_sphere_offset)
|
||||
offset = model->render_sphere_offset;
|
||||
else
|
||||
model_find_submodel_offset(&offset, pm->id, mn);
|
||||
|
||||
if ( (-model->use_render_sphere + in_sphere(&offset, Interp_render_sphere_radius)) )
|
||||
return;
|
||||
@@ -4591,7 +4603,13 @@ void model_render_buffers(polymodel *pm, int mn, bool is_child)
|
||||
vm_vec_copy_scale(&Interp_render_box_min, &model->render_box_min, Interp_box_scale);
|
||||
vm_vec_copy_scale(&Interp_render_box_max, &model->render_box_max, Interp_box_scale);
|
||||
|
||||
if ( (-model->use_render_box + in_box(&Interp_render_box_min, &Interp_render_box_max, &model->offset)) )
|
||||
vec3d offset;
|
||||
if (model->use_render_box_offset)
|
||||
offset = model->render_box_offset;
|
||||
else
|
||||
model_find_submodel_offset(&offset, pm->id, mn);
|
||||
|
||||
if ( (-model->use_render_box + in_box(&Interp_render_box_min, &Interp_render_box_max, &offset)) )
|
||||
return;
|
||||
}
|
||||
if ( !is_child && !(Interp_flags & MR_FULL_DETAIL) && model->use_render_sphere ) {
|
||||
@@ -4599,8 +4617,10 @@ void model_render_buffers(polymodel *pm, int mn, bool is_child)
|
||||
|
||||
// TODO: doesn't consider submodel rotations yet -zookeeper
|
||||
vec3d offset;
|
||||
model_find_submodel_offset(&offset, pm->id, mn);
|
||||
vm_vec_add2(&offset, &model->render_sphere_offset);
|
||||
if (model->use_render_sphere_offset)
|
||||
offset = model->render_sphere_offset;
|
||||
else
|
||||
model_find_submodel_offset(&offset, pm->id, mn);
|
||||
|
||||
if ( (-model->use_render_sphere + in_sphere(&offset, Interp_render_sphere_radius)) )
|
||||
return;
|
||||
|
||||
@@ -1354,6 +1354,18 @@ int read_model_file(polymodel * pm, char *filename, int n_subsystems, model_subs
|
||||
while (*p == ' ') p++;
|
||||
pm->submodel[n].use_render_box = atoi(p);
|
||||
|
||||
if ( (p = strstr(props, "$box_offset:")) != NULL ) {
|
||||
p += 12;
|
||||
while (*p == ' ') p++;
|
||||
pm->submodel[n].render_box_offset.xyz.x = (float)strtod(p, (char **)NULL);
|
||||
while (*p != ',') p++;
|
||||
pm->submodel[n].render_box_offset.xyz.y = (float)strtod(++p, (char **)NULL);
|
||||
while (*p != ',') p++;
|
||||
pm->submodel[n].render_box_offset.xyz.z = (float)strtod(++p, (char **)NULL);
|
||||
|
||||
pm->submodel[n].use_render_box_offset = true;
|
||||
}
|
||||
|
||||
if ( (p = strstr(props, "$box_min:")) != NULL ) {
|
||||
p += 9;
|
||||
while (*p == ' ') p++;
|
||||
@@ -1400,6 +1412,8 @@ int read_model_file(polymodel * pm, char *filename, int n_subsystems, model_subs
|
||||
pm->submodel[n].render_sphere_offset.xyz.y = (float)strtod(++p, (char **)NULL);
|
||||
while (*p != ',') p++;
|
||||
pm->submodel[n].render_sphere_offset.xyz.z = (float)strtod(++p, (char **)NULL);
|
||||
|
||||
pm->submodel[n].use_render_sphere_offset = true;
|
||||
} else {
|
||||
pm->submodel[n].render_sphere_offset = vmd_zero_vector;
|
||||
}
|
||||
@@ -2639,6 +2653,12 @@ int model_load(char *filename, int n_subsystems, model_subsystem *subsystems, in
|
||||
}
|
||||
dl2 = tolower(sm2->name[first_diff]) - 'a';
|
||||
|
||||
// Handle LODs named "detail0/1/2/etc" too (as opposed to "detaila/b/c/etc")
|
||||
if (sm1->parent == -1 && sm2->parent == -1 && !sm1->is_damaged && !sm2->is_damaged && !sm1->is_live_debris && !sm2->is_live_debris) {
|
||||
dl2 = dl2 - dl1;
|
||||
dl1 = 0;
|
||||
}
|
||||
|
||||
if ( (dl1<0) || (dl2<0) || (dl1>=MAX_MODEL_DETAIL_LEVELS) || (dl2>=MAX_MODEL_DETAIL_LEVELS) ) continue; // invalid detail levels
|
||||
|
||||
if ( dl1 == 0 ) {
|
||||
@@ -2663,10 +2683,11 @@ int model_load(char *filename, int n_subsystems, model_subsystem *subsystems, in
|
||||
|
||||
if ( !Cmdline_old_collision_sys ) {
|
||||
for ( i = 0; i < pm->n_models; ++i ) {
|
||||
pm->submodel[i].collision_tree_index = model_create_bsp_collision_tree();
|
||||
bsp_collision_tree *tree = model_get_bsp_collision_tree(pm->submodel[i].collision_tree_index);
|
||||
|
||||
model_collide_parse_bsp(tree, pm->submodel[i].bsp_data, pm->version);
|
||||
if ( !(pm->submodel[i].nocollide_this_only || pm->submodel[i].no_collisions) ) {
|
||||
pm->submodel[i].collision_tree_index = model_create_bsp_collision_tree();
|
||||
bsp_collision_tree *tree = model_get_bsp_collision_tree(pm->submodel[i].collision_tree_index);
|
||||
model_collide_parse_bsp(tree, pm->submodel[i].bsp_data, pm->version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+42
-38
@@ -249,48 +249,52 @@ void neb2_regen();
|
||||
// initialize neb2 stuff at game startup
|
||||
void neb2_init()
|
||||
{
|
||||
int rval;
|
||||
char name[MAX_FILENAME_LEN];
|
||||
|
||||
if ( ( rval = setjmp(parse_abort) ) != 0 ) {
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", "nebula.tbl", rval));
|
||||
try
|
||||
{
|
||||
// read in the nebula.tbl
|
||||
read_file_text("nebula.tbl", CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
// background bitmaps
|
||||
Neb2_bitmap_count = 0;
|
||||
while (!optional_string("#end")) {
|
||||
// nebula
|
||||
required_string("+Nebula:");
|
||||
stuff_string(name, F_NAME, MAX_FILENAME_LEN);
|
||||
|
||||
if (Neb2_bitmap_count < MAX_NEB2_BITMAPS) {
|
||||
strcpy_s(Neb2_bitmap_filenames[Neb2_bitmap_count++], name);
|
||||
}
|
||||
else {
|
||||
WarningEx(LOCATION, "nebula.tbl\nExceeded maximum number of nebulas (%d)!\nSkipping %s.", MAX_NEB2_BITMAPS, name);
|
||||
}
|
||||
}
|
||||
|
||||
// poofs
|
||||
Neb2_poof_count = 0;
|
||||
while (!optional_string("#end")) {
|
||||
// nebula
|
||||
required_string("+Poof:");
|
||||
stuff_string(name, F_NAME, MAX_FILENAME_LEN);
|
||||
|
||||
if (Neb2_poof_count < MAX_NEB2_POOFS) {
|
||||
strcpy_s(Neb2_poof_filenames[Neb2_poof_count++], name);
|
||||
}
|
||||
else {
|
||||
WarningEx(LOCATION, "nebula.tbl\nExceeded maximum number of nebula poofs (%d)!\nSkipping %s.", MAX_NEB2_POOFS, name);
|
||||
}
|
||||
}
|
||||
|
||||
// should always have 6 neb poofs
|
||||
Assert(Neb2_poof_count == 6);
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "nebula.tbl", e.what()));
|
||||
return;
|
||||
}
|
||||
|
||||
// read in the nebula.tbl
|
||||
read_file_text("nebula.tbl", CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
// background bitmaps
|
||||
Neb2_bitmap_count = 0;
|
||||
while ( !optional_string("#end") ) {
|
||||
// nebula
|
||||
required_string("+Nebula:");
|
||||
stuff_string(name, F_NAME, MAX_FILENAME_LEN);
|
||||
|
||||
if ( Neb2_bitmap_count < MAX_NEB2_BITMAPS ) {
|
||||
strcpy_s(Neb2_bitmap_filenames[Neb2_bitmap_count++], name);
|
||||
} else {
|
||||
WarningEx(LOCATION, "nebula.tbl\nExceeded maximum number of nebulas (%d)!\nSkipping %s.", MAX_NEB2_BITMAPS, name);
|
||||
}
|
||||
}
|
||||
|
||||
// poofs
|
||||
Neb2_poof_count = 0;
|
||||
while ( !optional_string("#end") ) {
|
||||
// nebula
|
||||
required_string("+Poof:");
|
||||
stuff_string(name, F_NAME, MAX_FILENAME_LEN);
|
||||
|
||||
if ( Neb2_poof_count < MAX_NEB2_POOFS ) {
|
||||
strcpy_s(Neb2_poof_filenames[Neb2_poof_count++], name);
|
||||
} else {
|
||||
WarningEx(LOCATION, "nebula.tbl\nExceeded maximum number of nebula poofs (%d)!\nSkipping %s.", MAX_NEB2_POOFS, name);
|
||||
}
|
||||
}
|
||||
|
||||
// should always have 6 neb poofs
|
||||
Assert(Neb2_poof_count == 6);
|
||||
}
|
||||
|
||||
// set detail level
|
||||
|
||||
+116
-114
@@ -155,123 +155,125 @@ DCF(lightning_intensity, "Sets lightning intensity between 0.0 and 1.0 (Default
|
||||
void nebl_init()
|
||||
{
|
||||
char name[MAX_FILENAME_LEN];
|
||||
int rval;
|
||||
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", "lightning.tbl", rval));
|
||||
try
|
||||
{
|
||||
// parse the lightning table
|
||||
read_file_text("lightning.tbl", CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
// parse the individual lightning bolt types
|
||||
required_string("#Bolts begin");
|
||||
while (!optional_string("#Bolts end")){
|
||||
bolt_type new_bolt_type;
|
||||
|
||||
// bolt title
|
||||
required_string("$Bolt:");
|
||||
stuff_string(new_bolt_type.name, F_NAME, NAME_LENGTH);
|
||||
|
||||
// b_scale
|
||||
required_string("+b_scale:");
|
||||
stuff_float(&new_bolt_type.b_scale);
|
||||
|
||||
// b_shrink
|
||||
required_string("+b_shrink:");
|
||||
stuff_float(&new_bolt_type.b_shrink);
|
||||
|
||||
// b_poly_pct
|
||||
required_string("+b_poly_pct:");
|
||||
stuff_float(&new_bolt_type.b_poly_pct);
|
||||
|
||||
// child rand
|
||||
required_string("+b_rand:");
|
||||
stuff_float(&new_bolt_type.b_rand);
|
||||
|
||||
// z add
|
||||
required_string("+b_add:");
|
||||
stuff_float(&new_bolt_type.b_add);
|
||||
|
||||
// # strikes
|
||||
required_string("+b_strikes:");
|
||||
stuff_int(&new_bolt_type.num_strikes);
|
||||
|
||||
// lifetime
|
||||
required_string("+b_lifetime:");
|
||||
stuff_int(&new_bolt_type.lifetime);
|
||||
|
||||
// noise
|
||||
required_string("+b_noise:");
|
||||
stuff_float(&new_bolt_type.noise);
|
||||
|
||||
// emp effect
|
||||
required_string("+b_emp:");
|
||||
stuff_float(&new_bolt_type.emp_intensity);
|
||||
stuff_float(&new_bolt_type.emp_time);
|
||||
|
||||
// texture
|
||||
required_string("+b_texture:");
|
||||
stuff_string(name, F_NAME, sizeof(name));
|
||||
if (!Fred_running){
|
||||
new_bolt_type.texture = bm_load(name);
|
||||
}
|
||||
|
||||
// glow
|
||||
required_string("+b_glow:");
|
||||
stuff_string(name, F_NAME, sizeof(name));
|
||||
if (!Fred_running){
|
||||
new_bolt_type.glow = bm_load(name);
|
||||
}
|
||||
|
||||
// brightness
|
||||
required_string("+b_bright:");
|
||||
stuff_float(&new_bolt_type.b_bright);
|
||||
|
||||
Bolt_types.push_back(new_bolt_type);
|
||||
}
|
||||
|
||||
// parse lightning storm types
|
||||
required_string("#Storms begin");
|
||||
while (!optional_string("#Storms end")){
|
||||
storm_type new_storm_type;
|
||||
|
||||
// bolt title
|
||||
required_string("$Storm:");
|
||||
stuff_string(new_storm_type.name, F_NAME, NAME_LENGTH);
|
||||
|
||||
// bolt types
|
||||
while (optional_string("+bolt:")){
|
||||
if (new_storm_type.num_bolt_types < MAX_BOLT_TYPES_PER_STORM){
|
||||
stuff_string(name, F_NAME, sizeof(name));
|
||||
|
||||
new_storm_type.bolt_types[new_storm_type.num_bolt_types] = nebl_get_bolt_index(name);
|
||||
Assert(new_storm_type.bolt_types[new_storm_type.num_bolt_types] != (size_t)-1);
|
||||
|
||||
new_storm_type.num_bolt_types++;
|
||||
}
|
||||
}
|
||||
|
||||
// flavor
|
||||
required_string("+flavor:");
|
||||
stuff_float(&new_storm_type.flavor.xyz.x);
|
||||
stuff_float(&new_storm_type.flavor.xyz.y);
|
||||
stuff_float(&new_storm_type.flavor.xyz.z);
|
||||
|
||||
// frequencies
|
||||
required_string("+random_freq:");
|
||||
stuff_int(&new_storm_type.min);
|
||||
stuff_int(&new_storm_type.max);
|
||||
|
||||
// counts
|
||||
required_string("+random_count:");
|
||||
stuff_int(&new_storm_type.min_count);
|
||||
stuff_int(&new_storm_type.max_count);
|
||||
|
||||
Storm_types.push_back(new_storm_type);
|
||||
}
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "lightning.tbl", e.what()));
|
||||
return;
|
||||
}
|
||||
|
||||
// parse the lightning table
|
||||
read_file_text("lightning.tbl", CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
// parse the individual lightning bolt types
|
||||
required_string("#Bolts begin");
|
||||
while(!optional_string("#Bolts end")){
|
||||
bolt_type new_bolt_type;
|
||||
|
||||
// bolt title
|
||||
required_string("$Bolt:");
|
||||
stuff_string(new_bolt_type.name, F_NAME, NAME_LENGTH);
|
||||
|
||||
// b_scale
|
||||
required_string("+b_scale:");
|
||||
stuff_float(&new_bolt_type.b_scale);
|
||||
|
||||
// b_shrink
|
||||
required_string("+b_shrink:");
|
||||
stuff_float(&new_bolt_type.b_shrink);
|
||||
|
||||
// b_poly_pct
|
||||
required_string("+b_poly_pct:");
|
||||
stuff_float(&new_bolt_type.b_poly_pct);
|
||||
|
||||
// child rand
|
||||
required_string("+b_rand:");
|
||||
stuff_float(&new_bolt_type.b_rand);
|
||||
|
||||
// z add
|
||||
required_string("+b_add:");
|
||||
stuff_float(&new_bolt_type.b_add);
|
||||
|
||||
// # strikes
|
||||
required_string("+b_strikes:");
|
||||
stuff_int(&new_bolt_type.num_strikes);
|
||||
|
||||
// lifetime
|
||||
required_string("+b_lifetime:");
|
||||
stuff_int(&new_bolt_type.lifetime);
|
||||
|
||||
// noise
|
||||
required_string("+b_noise:");
|
||||
stuff_float(&new_bolt_type.noise);
|
||||
|
||||
// emp effect
|
||||
required_string("+b_emp:");
|
||||
stuff_float(&new_bolt_type.emp_intensity);
|
||||
stuff_float(&new_bolt_type.emp_time);
|
||||
|
||||
// texture
|
||||
required_string("+b_texture:");
|
||||
stuff_string(name, F_NAME, sizeof(name));
|
||||
if(!Fred_running){
|
||||
new_bolt_type.texture = bm_load(name);
|
||||
}
|
||||
|
||||
// glow
|
||||
required_string("+b_glow:");
|
||||
stuff_string(name, F_NAME, sizeof(name));
|
||||
if(!Fred_running){
|
||||
new_bolt_type.glow = bm_load(name);
|
||||
}
|
||||
|
||||
// brightness
|
||||
required_string("+b_bright:");
|
||||
stuff_float(&new_bolt_type.b_bright);
|
||||
|
||||
Bolt_types.push_back(new_bolt_type);
|
||||
}
|
||||
|
||||
// parse lightning storm types
|
||||
required_string("#Storms begin");
|
||||
while(!optional_string("#Storms end")){
|
||||
storm_type new_storm_type;
|
||||
|
||||
// bolt title
|
||||
required_string("$Storm:");
|
||||
stuff_string(new_storm_type.name, F_NAME, NAME_LENGTH);
|
||||
|
||||
// bolt types
|
||||
while(optional_string("+bolt:")){
|
||||
if(new_storm_type.num_bolt_types < MAX_BOLT_TYPES_PER_STORM){
|
||||
stuff_string(name, F_NAME, sizeof(name));
|
||||
|
||||
new_storm_type.bolt_types[new_storm_type.num_bolt_types] = nebl_get_bolt_index(name);
|
||||
Assert(new_storm_type.bolt_types[new_storm_type.num_bolt_types] != (size_t)-1);
|
||||
|
||||
new_storm_type.num_bolt_types++;
|
||||
}
|
||||
}
|
||||
|
||||
// flavor
|
||||
required_string("+flavor:");
|
||||
stuff_float(&new_storm_type.flavor.xyz.x);
|
||||
stuff_float(&new_storm_type.flavor.xyz.y);
|
||||
stuff_float(&new_storm_type.flavor.xyz.z);
|
||||
|
||||
// frequencies
|
||||
required_string("+random_freq:");
|
||||
stuff_int(&new_storm_type.min);
|
||||
stuff_int(&new_storm_type.max);
|
||||
|
||||
// counts
|
||||
required_string("+random_count:");
|
||||
stuff_int(&new_storm_type.min_count);
|
||||
stuff_int(&new_storm_type.max_count);
|
||||
|
||||
Storm_types.push_back(new_storm_type);
|
||||
}
|
||||
}
|
||||
|
||||
// initialize lightning before entering a level
|
||||
|
||||
@@ -585,6 +585,11 @@ void multi_options_process_packet(unsigned char *data, header *hinfo)
|
||||
// find out who is sending this data
|
||||
player_index = find_player_id(hinfo->id);
|
||||
|
||||
if (player_index < 0) {
|
||||
nprintf(("Network", "Received packet from unknown player!\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
// get the packet code
|
||||
GET_DATA(code);
|
||||
switch(code){
|
||||
|
||||
@@ -4511,7 +4511,8 @@ void multi_pxo_pinfo_build_vals()
|
||||
if (fs->stats.last_flown == 0) {
|
||||
strcpy_s(Multi_pxo_pinfo_vals[7], XSTR("No missions flown", 970) );
|
||||
} else {
|
||||
tm *tmr = gmtime( (time_t*)&fs->stats.last_flown );
|
||||
time_t tmp_lf = fs->stats.last_flown; // don't cast a pointer to a type that can be either 32 or 64bit
|
||||
tm *tmr = gmtime( &tmp_lf );
|
||||
|
||||
if (tmr != NULL)
|
||||
strftime(Multi_pxo_pinfo_vals[7], 30, "%m/%d/%y %H:%M", tmr);
|
||||
|
||||
@@ -1599,6 +1599,12 @@ void multi_create_standalone_object()
|
||||
|
||||
vm_vec_zero(&v);
|
||||
objnum = observer_create(&m,&v);
|
||||
|
||||
if (objnum < 0) {
|
||||
Error(LOCATION, "Failed to create standalone observer object! Please investigate!");
|
||||
return;
|
||||
}
|
||||
|
||||
Player_obj = &Objects[objnum];
|
||||
obj_set_flags(Player_obj, Player_obj->flags & (~OF_COLLIDES) );
|
||||
//obj_set_flags(Player_obj, Player_obj->flags | OF_SHOULD_BE_DEAD);
|
||||
|
||||
@@ -269,6 +269,10 @@ int ship_ship_check_collision(collision_info_struct *ship_ship_hit_info, vec3d *
|
||||
// reset flags to check MC_CHECK_MODEL | MC_CHECK_SPHERELINE and maybe MC_CHECK_INVISIBLE_FACES and MC_SUBMODEL_INSTANCE
|
||||
mc.flags = copy_flags | MC_SUBMODEL_INSTANCE;
|
||||
|
||||
if (heavy_sip->collision_lod > -1) {
|
||||
mc.lod = heavy_sip->collision_lod;
|
||||
}
|
||||
|
||||
// check each submodel in turn
|
||||
for (smv = submodel_vector.begin(); smv != submodel_vector.end(); ++smv) {
|
||||
// turn on submodel for collision test
|
||||
|
||||
@@ -168,6 +168,7 @@ int ship_weapon_check_collision(object *ship_objp, object *weapon_objp, float ti
|
||||
mc.pos = &ship_objp->pos;
|
||||
mc.p0 = &weapon_objp->last_pos;
|
||||
mc.p1 = &weapon_end_pos;
|
||||
mc.lod = sip->collision_lod;
|
||||
memcpy(&mc_shield, &mc, sizeof(mc_info));
|
||||
memcpy(&mc_hull, &mc, sizeof(mc_info));
|
||||
|
||||
@@ -200,15 +201,16 @@ int ship_weapon_check_collision(object *ship_objp, object *weapon_objp, float ti
|
||||
// The weapon is not allowed to impact the shield before it reaches this point
|
||||
vec3d shield_ignored_until = weapon_objp->last_pos;
|
||||
|
||||
float min_weapon_span = sip->auto_shield_spread_min_span;
|
||||
float weapon_flown_for = vm_vec_dist(&wp->start_pos, &weapon_objp->last_pos);
|
||||
|
||||
// If weapon hasn't yet flown a distance greater than the maximum ignore
|
||||
// range, then some part of the currently checked range needs to be
|
||||
// ignored
|
||||
if (weapon_flown_for < sip->auto_shield_spread) {
|
||||
if (weapon_flown_for < min_weapon_span) {
|
||||
vm_vec_sub(&shield_ignored_until, &weapon_end_pos, &wp->start_pos);
|
||||
vm_vec_normalize(&shield_ignored_until);
|
||||
vm_vec_scale(&shield_ignored_until, sip->auto_shield_spread);
|
||||
vm_vec_scale(&shield_ignored_until, min_weapon_span);
|
||||
vm_vec_add2(&shield_ignored_until, &wp->start_pos);
|
||||
}
|
||||
|
||||
@@ -243,7 +245,7 @@ int ship_weapon_check_collision(object *ship_objp, object *weapon_objp, float ti
|
||||
// If no collision with the model found in the ignore range, only
|
||||
// then do we check for sphereline collisions with the model during the
|
||||
// non-ignored range
|
||||
if (!shield_collision && weapon_flown_for + this_range > sip->auto_shield_spread) {
|
||||
if (!shield_collision && weapon_flown_for + this_range > min_weapon_span) {
|
||||
mc_shield.p0 = &shield_ignored_until;
|
||||
|
||||
mc_shield.p1 = &weapon_end_pos;
|
||||
@@ -251,16 +253,14 @@ int ship_weapon_check_collision(object *ship_objp, object *weapon_objp, float ti
|
||||
mc_shield.radius = sip->auto_shield_spread;
|
||||
|
||||
if (sip->auto_shield_spread_from_lod > -1) {
|
||||
pm = model_get(sip->model_num);
|
||||
mc_shield.submodel_num = pm->detail[sip->auto_shield_spread_from_lod];
|
||||
|
||||
mc_shield.flags = MC_CHECK_MODEL | MC_SUBMODEL_INSTANCE | MC_CHECK_SPHERELINE;
|
||||
} else {
|
||||
mc_shield.flags = MC_CHECK_MODEL | MC_CHECK_SPHERELINE;
|
||||
mc_shield.lod = sip->auto_shield_spread_from_lod;
|
||||
}
|
||||
|
||||
mc_shield.flags = MC_CHECK_MODEL | MC_CHECK_SPHERELINE;
|
||||
|
||||
shield_collision = model_collide(&mc_shield);
|
||||
|
||||
mc_shield.lod = sip->collision_lod;
|
||||
mc_shield.submodel_num = -1;
|
||||
|
||||
// Because we manipulated p0 and p1 above, hit_dist will be
|
||||
@@ -407,6 +407,12 @@ int ship_weapon_check_collision(object *ship_objp, object *weapon_objp, float ti
|
||||
bool weapon_override = Script_system.IsConditionOverride(CHA_COLLIDESHIP, weapon_objp);
|
||||
|
||||
if(!ship_override && !weapon_override) {
|
||||
if (shield_collision && quadrant_num >= 0) {
|
||||
if ((sip->shield_impact_explosion_anim > -1) && (wip->shield_impact_explosion_radius > 0)) {
|
||||
// do in weapons.cpp for most parts just because that is how rest of the functions are handled
|
||||
shield_impact_explosion(&mc.hit_point, ship_objp, wip->shield_impact_explosion_radius, sip->shield_impact_explosion_anim);
|
||||
}
|
||||
}
|
||||
ship_weapon_do_hit_stuff(ship_objp, weapon_objp, &mc.hit_point_world, &mc.hit_point, quadrant_num, mc.hit_submodel, mc.hit_normal);
|
||||
}
|
||||
|
||||
|
||||
@@ -49,10 +49,18 @@ void shield_add_strength(object *objp, float delta)
|
||||
if (delta == 0.0f)
|
||||
return;
|
||||
|
||||
|
||||
float shield_str = shield_get_strength(objp);
|
||||
float shield_recharge_limit = Ships[objp->instance].ship_max_shield_strength * Ships[objp->instance].max_shield_recharge;
|
||||
|
||||
if (shield_str >= shield_recharge_limit)
|
||||
return;
|
||||
|
||||
if (!(Ai_info[Ships[objp->instance].ai_index].ai_profile_flags & AIPF_SMART_SHIELD_MANAGEMENT)
|
||||
|| delta <= 0.0f) //SUSHI: We don't want smart shield management for negative delta
|
||||
{
|
||||
if ((delta > 0.0f) && ((shield_str + delta) > shield_recharge_limit))
|
||||
delta = shield_recharge_limit - shield_str;
|
||||
|
||||
for (int i = 0; i < objp->n_quadrants; i++)
|
||||
shield_add_quad(objp, i, delta / objp->n_quadrants);
|
||||
}
|
||||
@@ -81,7 +89,11 @@ void shield_add_strength(object *objp, float delta)
|
||||
// all quads are at full strength
|
||||
if (weakest >= section_max)
|
||||
break;
|
||||
|
||||
|
||||
// set the limit for the shield recharge
|
||||
if ((delta > 0.0f) && ((shield_str + delta) > shield_recharge_limit))
|
||||
delta = shield_recharge_limit - shield_str;
|
||||
|
||||
// throw all possible shield power at this quadrant
|
||||
// if there's any left over then apply it to the next weakest on the next pass
|
||||
float xfer_amount;
|
||||
|
||||
+24
-13
@@ -503,7 +503,7 @@ void obj_snd_do_frame()
|
||||
}
|
||||
|
||||
distance -= add_distance;
|
||||
if ( distance < 0 ) {
|
||||
if ( distance < 0.0f ) {
|
||||
distance = 0.0f;
|
||||
}
|
||||
|
||||
@@ -521,39 +521,48 @@ void obj_snd_do_frame()
|
||||
rot_vol_mult = 1.0f;
|
||||
alive_vol_mult = 1.0f;
|
||||
if ( objp->type == OBJ_SHIP ) {
|
||||
if ( !(Ship_info[Ships[objp->instance].ship_info_index].flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP)) ) {
|
||||
if ( objp->phys_info.max_vel.xyz.z <= 0 ) {
|
||||
ship_info *sip = &Ship_info[Ships[objp->instance].ship_info_index];
|
||||
if ( !(sip->flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP)) ) {
|
||||
if ( objp->phys_info.max_vel.xyz.z <= 0.0f ) {
|
||||
percent_max = 0.0f;
|
||||
}
|
||||
else
|
||||
percent_max = objp->phys_info.fspeed / objp->phys_info.max_vel.xyz.z;
|
||||
|
||||
if ( percent_max >= 0.5 )
|
||||
speed_vol_multiplier = 1.0f;
|
||||
else {
|
||||
speed_vol_multiplier = 0.5f + (percent_max); // linear interp: 0.5->1.0 when 0.0->0.5
|
||||
if ( sip->min_engine_vol == -1.0f) {
|
||||
// Retail behavior: volume ramps from 0.5 (when stationary) to 1.0 (when at half speed)
|
||||
if ( percent_max >= 0.5f ) {
|
||||
speed_vol_multiplier = 1.0f;
|
||||
} else {
|
||||
speed_vol_multiplier = 0.5f + (percent_max); // linear interp: 0.5->1.0 when 0.0->0.5
|
||||
}
|
||||
} else {
|
||||
// Volume ramps from min_engine_vol (when stationary) to 1.0 (when at full speed)
|
||||
speed_vol_multiplier = MAX(sip->min_engine_vol, percent_max);
|
||||
}
|
||||
}
|
||||
if (osp->ss != NULL)
|
||||
{
|
||||
if (osp->flags & OS_TURRET_BASE_ROTATION)
|
||||
{
|
||||
if (osp->ss->base_rotation_rate_pct > 0)
|
||||
if (osp->ss->base_rotation_rate_pct > 0.0f)
|
||||
rot_vol_mult = ((0.25f + (0.75f * osp->ss->base_rotation_rate_pct)) * osp->ss->system_info->turret_base_rotation_snd_mult);
|
||||
else
|
||||
rot_vol_mult = 0;
|
||||
rot_vol_mult = 0.0f;
|
||||
}
|
||||
if (osp->flags & OS_TURRET_GUN_ROTATION)
|
||||
{
|
||||
if (osp->ss->gun_rotation_rate_pct > 0)
|
||||
if (osp->ss->gun_rotation_rate_pct > 0.0f)
|
||||
rot_vol_mult = ((0.25f + (0.75f * osp->ss->gun_rotation_rate_pct)) * osp->ss->system_info->turret_gun_rotation_snd_mult);
|
||||
else
|
||||
rot_vol_mult = 0;
|
||||
rot_vol_mult = 0.0f;
|
||||
}
|
||||
if (osp->flags & OS_SUBSYS_ROTATION )
|
||||
{
|
||||
if (osp->ss->flags & SSF_ROTATES) {
|
||||
rot_vol_mult = 1.0;
|
||||
rot_vol_mult = 1.0f;
|
||||
} else {
|
||||
rot_vol_mult = 0.0f;
|
||||
}
|
||||
}
|
||||
if (osp->flags & OS_SUBSYS_ALIVE)
|
||||
@@ -568,6 +577,8 @@ void obj_snd_do_frame()
|
||||
{
|
||||
if (osp->ss->current_hits <= 0.0f) {
|
||||
alive_vol_mult = 1.0f;
|
||||
} else {
|
||||
alive_vol_mult = 0.0f;
|
||||
}
|
||||
}
|
||||
if (osp->flags & OS_SUBSYS_DAMAGED)
|
||||
@@ -591,7 +602,7 @@ void obj_snd_do_frame()
|
||||
new_vol = max_vol - (distance - Snds[osp->id].min) * max_vol / (Snds[osp->id].max - Snds[osp->id].min);
|
||||
}
|
||||
|
||||
if ( new_vol < 0.1 ) {
|
||||
if ( new_vol < 0.1f ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,8 @@ void outwnd_print(const char *id = NULL, const char *temp = NULL);
|
||||
bool outwnd_inited = false;
|
||||
ubyte Outwnd_no_filter_file = 0; // 0 = .cfg file found, 1 = not found and warning not printed yet, 2 = not found and warning printed
|
||||
|
||||
struct outwnd_filter_struct {
|
||||
class outwnd_filter_struct {
|
||||
public:
|
||||
char name[NAME_LENGTH];
|
||||
bool enabled;
|
||||
|
||||
@@ -75,22 +76,16 @@ void load_filter_info(void)
|
||||
if (!fp) {
|
||||
Outwnd_no_filter_file = 1;
|
||||
|
||||
memset( &new_filter, 0, sizeof(outwnd_filter_struct) );
|
||||
strcpy_s( new_filter.name, "error" );
|
||||
new_filter.enabled = true;
|
||||
|
||||
OutwndFilter.push_back( new_filter );
|
||||
|
||||
memset( &new_filter, 0, sizeof(outwnd_filter_struct) );
|
||||
strcpy_s( new_filter.name, "general" );
|
||||
new_filter.enabled = true;
|
||||
|
||||
OutwndFilter.push_back( new_filter );
|
||||
|
||||
memset( &new_filter, 0, sizeof(outwnd_filter_struct) );
|
||||
strcpy_s( new_filter.name, "warning" );
|
||||
new_filter.enabled = true;
|
||||
|
||||
OutwndFilter.push_back( new_filter );
|
||||
|
||||
return;
|
||||
@@ -99,7 +94,6 @@ void load_filter_info(void)
|
||||
Outwnd_no_filter_file = 0;
|
||||
|
||||
while ( fgets(inbuf, NAME_LENGTH+3, fp) ) {
|
||||
memset( &new_filter, 0, sizeof(outwnd_filter_struct) );
|
||||
|
||||
if (*inbuf == '+')
|
||||
new_filter.enabled = true;
|
||||
|
||||
+22
-98
@@ -64,28 +64,30 @@ int palman_is_nondarkening(int r,int g, int b)
|
||||
|
||||
void palman_load_pixels()
|
||||
{
|
||||
int rval;
|
||||
if ((rval = setjmp(parse_abort)) != 0) {
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", "pixels.tbl", rval));
|
||||
try
|
||||
{
|
||||
// open pixels.tbl
|
||||
read_file_text("pixels.tbl", CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
// parse pixels
|
||||
while (!optional_string("#END")){
|
||||
// nondarkening pixel
|
||||
if (required_string("+ND")){
|
||||
stuff_ubyte(&Palman_non_darkening_default[Palman_num_nondarkening_default][0]);
|
||||
stuff_ubyte(&Palman_non_darkening_default[Palman_num_nondarkening_default][1]);
|
||||
stuff_ubyte(&Palman_non_darkening_default[Palman_num_nondarkening_default++][2]);
|
||||
}
|
||||
}
|
||||
|
||||
// set this to be the active table
|
||||
palman_set_nondarkening(Palman_non_darkening_default, Palman_num_nondarkening_default);
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "pixels.tbl", e.what()));
|
||||
return;
|
||||
}
|
||||
|
||||
// open pixels.tbl
|
||||
read_file_text("pixels.tbl", CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
// parse pixels
|
||||
while(!optional_string("#END")){
|
||||
// nondarkening pixel
|
||||
if(required_string("+ND")){
|
||||
stuff_ubyte(&Palman_non_darkening_default[Palman_num_nondarkening_default][0]);
|
||||
stuff_ubyte(&Palman_non_darkening_default[Palman_num_nondarkening_default][1]);
|
||||
stuff_ubyte(&Palman_non_darkening_default[Palman_num_nondarkening_default++][2]);
|
||||
}
|
||||
}
|
||||
|
||||
// set this to be the active table
|
||||
palman_set_nondarkening(Palman_non_darkening_default, Palman_num_nondarkening_default);
|
||||
}
|
||||
|
||||
void palman_set_nondarkening(ubyte colors[MAX_NONDARK_COLORS][3], int size)
|
||||
@@ -526,84 +528,6 @@ void palette_update(const char *name_with_extension, int restrict_font_to_128)
|
||||
}
|
||||
}
|
||||
|
||||
ubyte *palette_get_fade_table()
|
||||
{
|
||||
int i,l;
|
||||
|
||||
if ( palman_screen_signature != gr_screen.signature ) {
|
||||
palman_screen_signature = gr_screen.signature;
|
||||
palette_fade_table_calculated = 0;
|
||||
}
|
||||
|
||||
|
||||
if ( !palette_fade_table_calculated ) {
|
||||
//mprintf(( "Creating fading table..." ));
|
||||
|
||||
for (i=0; i<256; i++ ) {
|
||||
int r, g, b;
|
||||
int ur, ug, ub;
|
||||
r = gr_palette[i*3+0];
|
||||
g = gr_palette[i*3+1];
|
||||
b = gr_palette[i*3+2];
|
||||
|
||||
if ( palman_is_nondarkening(r,g,b)) {
|
||||
// Make pure white not fade
|
||||
for (l=0; l<32; l++ ) {
|
||||
gr_fade_table[((l+1)*256)+i] = (unsigned char)i;
|
||||
}
|
||||
} else {
|
||||
for (l=0; l<32; l++ ) {
|
||||
|
||||
if ( l < 24 ) {
|
||||
float f = (float)pow(i2fl(l)/23.0f, 1.0f/Gr_gamma);
|
||||
ur = fl2i(i2fl(r)*f); if ( ur > 255 ) ur = 255;
|
||||
ug = fl2i(i2fl(g)*f); if ( ug > 255 ) ug = 255;
|
||||
ub = fl2i(i2fl(b)*f); if ( ub > 255 ) ub = 255;
|
||||
} else {
|
||||
int x,y;
|
||||
int gi, gr, gg, gb;
|
||||
|
||||
gi = (r+g+b)/3;
|
||||
|
||||
#ifdef RGB_LIGHTING
|
||||
gr = r;
|
||||
gg = g;
|
||||
gb = gi*2;
|
||||
#else
|
||||
gr = r*2;
|
||||
gg = g*2;
|
||||
gb = b*2;
|
||||
#endif
|
||||
|
||||
x = l-24; // x goes from 0 to 7
|
||||
y = 31-l; // y goes from 7 to 0
|
||||
|
||||
ur = ((gr*x)+(r*y))/7; if ( ur > 255 ) ur = 255;
|
||||
ug = ((gg*x)+(g*y))/7; if ( ug > 255 ) ug = 255;
|
||||
ub = ((gb*x)+(b*y))/7; if ( ub > 255 ) ub = 255;
|
||||
}
|
||||
gr_fade_table[((l+1)*256)+i] = (unsigned char)palette_find( ur, ug, ub );
|
||||
|
||||
}
|
||||
}
|
||||
gr_fade_table[ (0*256)+i ] = gr_fade_table[ (1*256)+i ];
|
||||
gr_fade_table[ (33*256)+i ] = gr_fade_table[ (32*256)+i ];
|
||||
}
|
||||
|
||||
// Mirror the fade table
|
||||
for (i=0; i<34; i++ ) {
|
||||
for ( l = 0; l < 256; l++ ) {
|
||||
gr_fade_table[ ((67-i)*256)+l ] = gr_fade_table[ (i*256)+l ];
|
||||
}
|
||||
}
|
||||
|
||||
// mprintf(( "done\n" ));
|
||||
palette_fade_table_calculated = 1;
|
||||
}
|
||||
|
||||
return &gr_fade_table[0];
|
||||
}
|
||||
|
||||
|
||||
ubyte *palette_get_blend_table(float alpha)
|
||||
{
|
||||
|
||||
@@ -24,7 +24,6 @@ extern void palette_flush();
|
||||
// Functions to query a palette
|
||||
extern uint palette_compute_checksum( ubyte *pal ); // computes checksum of palette
|
||||
extern ubyte *palette_get_blend_table(float alpha);
|
||||
extern ubyte *palette_get_fade_table();
|
||||
|
||||
extern uint palette_find( int r, int g, int b );
|
||||
|
||||
|
||||
@@ -15614,6 +15614,29 @@ ADE_FUNC(getStack, l_Testing, NULL, "Generates an ADE stackdump", "string", "Cur
|
||||
return ade_set_args(L, "s", buf);
|
||||
}
|
||||
|
||||
ADE_FUNC(setCurrentPlayerMulti, l_Testing, "boolean", "Sets whether current player is a multiplayer pilot or not.", "boolean", "True if successful, false if not.")
|
||||
{
|
||||
bool multi;
|
||||
|
||||
if(!ade_get_args(L, "b", &multi))
|
||||
return ADE_RETURN_NIL;
|
||||
|
||||
if(Player == NULL)
|
||||
return ade_set_error(L, "b", false);
|
||||
|
||||
if (multi) {
|
||||
Game_mode &= ~GM_NORMAL;
|
||||
Game_mode |= GM_MULTIPLAYER;
|
||||
Player->flags |= PLAYER_FLAGS_IS_MULTI;
|
||||
} else {
|
||||
Game_mode &= ~GM_MULTIPLAYER;
|
||||
Game_mode |= GM_NORMAL;
|
||||
Player->flags &= ~PLAYER_FLAGS_IS_MULTI;
|
||||
}
|
||||
|
||||
return ADE_RETURN_TRUE;
|
||||
}
|
||||
|
||||
ADE_FUNC(isCurrentPlayerMulti, l_Testing, NULL, "Returns whether current player is a multiplayer pilot or not.", "boolean", "Whether current player is a multiplayer pilot or not")
|
||||
{
|
||||
if(Player == NULL)
|
||||
|
||||
+47
-185
@@ -43,7 +43,6 @@ int Warning_count, Error_count;
|
||||
int Warning_count_save = 0, Error_count_save = 0;
|
||||
int fred_parse_flag = 0;
|
||||
int Token_found_flag;
|
||||
jmp_buf parse_abort;
|
||||
|
||||
char *Mission_text = NULL;
|
||||
char *Mission_text_raw = NULL;
|
||||
@@ -483,7 +482,7 @@ int required_string(char *pstr)
|
||||
if (count == RS_MAX_TRIES) {
|
||||
nprintf(("Error", "Error: Unable to find required token [%s]\n", pstr));
|
||||
Warning(LOCATION, "Error: Unable to find required token [%s]\n", pstr);
|
||||
longjmp(parse_abort, 1);
|
||||
throw parse::ParseException("Required string not found");
|
||||
}
|
||||
|
||||
Mp += strlen(pstr);
|
||||
@@ -691,79 +690,13 @@ int required_string_either(char *str1, char *str2)
|
||||
|
||||
if (count == RS_MAX_TRIES) {
|
||||
nprintf(("Error", "Error: Unable to find either required token [%s] or [%s]\n", str1, str2));
|
||||
Warning(LOCATION, "Error: Unable to find either required token [%s] or [%s]\n", str1, str2);
|
||||
longjmp(parse_abort, 2);
|
||||
Warning(LOCATION, "Error: Unable to find either required token [%s] or [%s]\n", str1, str2);
|
||||
throw parse::ParseException("Required string not found");
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Return 0 or 1 for str1 match, str2 match. Return -1 if neither matches.
|
||||
// Does not update Mp if token found. If not found, advances, trying to
|
||||
// find the string. Doesn't advance past the found string.
|
||||
int required_string_3(char *str1, char *str2, char *str3)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
ignore_white_space();
|
||||
|
||||
while (count < RS_MAX_TRIES) {
|
||||
if (strnicmp(str1, Mp, strlen(str1)) == 0) {
|
||||
// Mp += strlen(str1);
|
||||
diag_printf("Found required string [%s]\n", token_found = str1);
|
||||
return 0;
|
||||
} else if (strnicmp(str2, Mp, strlen(str2)) == 0) {
|
||||
// Mp += strlen(str2);
|
||||
diag_printf("Found required string [%s]\n", token_found = str2);
|
||||
return 1;
|
||||
} else if (strnicmp(str3, Mp, strlen(str3)) == 0) {
|
||||
diag_printf("Found required string [%s]\n", token_found = str3);
|
||||
return 2;
|
||||
}
|
||||
|
||||
error_display(1, "Required token = [%s], [%s] or [%s], found [%.32s].\n", str1, str2, str3, next_tokens());
|
||||
|
||||
advance_to_eoln(NULL);
|
||||
ignore_white_space();
|
||||
count++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int required_string_4(char *str1, char *str2, char *str3, char *str4)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
ignore_white_space();
|
||||
|
||||
while (count < RS_MAX_TRIES) {
|
||||
if (strnicmp(str1, Mp, strlen(str1)) == 0) {
|
||||
// Mp += strlen(str1);
|
||||
diag_printf("Found required string [%s]\n", token_found = str1);
|
||||
return 0;
|
||||
} else if (strnicmp(str2, Mp, strlen(str2)) == 0) {
|
||||
// Mp += strlen(str2);
|
||||
diag_printf("Found required string [%s]\n", token_found = str2);
|
||||
return 1;
|
||||
} else if (strnicmp(str3, Mp, strlen(str3)) == 0) {
|
||||
diag_printf("Found required string [%s]\n", token_found = str3);
|
||||
return 2;
|
||||
} else if (strnicmp(str4, Mp, strlen(str4)) == 0) {
|
||||
diag_printf("Found required string [%s]\n", token_found = str4);
|
||||
return 3;
|
||||
}
|
||||
|
||||
error_display(1, "Required token = [%s], [%s], [%s], or [%s], found [%.32s].\n", str1, str2, str3, str4, next_tokens());
|
||||
|
||||
advance_to_eoln(NULL);
|
||||
ignore_white_space();
|
||||
count++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Generic version of old required_string_3 and required_string_4; written by ngld, with some tweaks by MageKing17
|
||||
int required_string_one_of(int arg_count, ...)
|
||||
{
|
||||
@@ -953,8 +886,8 @@ char* alloc_text_until(char* instr, char* endstr)
|
||||
|
||||
if(foundstr == NULL)
|
||||
{
|
||||
Error(LOCATION, "Missing [%s] in file");
|
||||
longjmp(parse_abort, 3);
|
||||
Error(LOCATION, "Missing [%s] in file", endstr);
|
||||
throw parse::ParseException("End string not found");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -988,8 +921,8 @@ void copy_text_until(char *outstr, char *instr, char *endstr, int max_chars)
|
||||
foundstr = stristr(instr, endstr);
|
||||
|
||||
if (foundstr == NULL) {
|
||||
nprintf(("Error", "Error. Looking for [%s], but never found it.\n", endstr));
|
||||
longjmp(parse_abort, 3);
|
||||
nprintf(("Error", "Error. Looking for [%s], but never found it.\n", endstr));
|
||||
throw parse::ParseException("End string not found");
|
||||
}
|
||||
|
||||
if (foundstr - instr + strlen(endstr) < (uint) max_chars) {
|
||||
@@ -1000,7 +933,7 @@ void copy_text_until(char *outstr, char *instr, char *endstr, int max_chars)
|
||||
nprintf(("Error", "Error. Too much text (%i chars, %i allowed) before %s\n",
|
||||
foundstr - instr - strlen(endstr), max_chars, endstr));
|
||||
|
||||
longjmp(parse_abort, 4);
|
||||
throw parse::ParseException("Too much text found");
|
||||
}
|
||||
|
||||
diag_printf("Here's the partial wad of text:\n%.30s\n", outstr);
|
||||
@@ -1015,8 +948,8 @@ void copy_text_until(SCP_string &outstr, char *instr, char *endstr)
|
||||
foundstr = stristr(instr, endstr);
|
||||
|
||||
if (foundstr == NULL) {
|
||||
nprintf(("Error", "Error. Looking for [%s], but never found it.\n", endstr));
|
||||
longjmp(parse_abort, 3);
|
||||
nprintf(("Error", "Error. Looking for [%s], but never found it.\n", endstr));
|
||||
throw parse::ParseException("End string not found");
|
||||
}
|
||||
|
||||
outstr.assign(instr, foundstr - instr);
|
||||
@@ -1112,8 +1045,8 @@ char* alloc_block(char* startstr, char* endstr, int extra_chars)
|
||||
//Check that we left the file
|
||||
if(level > 0)
|
||||
{
|
||||
Error(LOCATION, "Unclosed pair of \"%s\" and \"%s\" on line %d in file", startstr, endstr, get_line_num());
|
||||
longjmp(parse_abort, 3);
|
||||
Error(LOCATION, "Unclosed pair of \"%s\" and \"%s\" on line %d in file", startstr, endstr, get_line_num());
|
||||
throw parse::ParseException("End string not found");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1261,27 +1194,12 @@ void stuff_string(char *outstr, int type, int len, char *terminators)
|
||||
|
||||
switch (type) {
|
||||
case F_RAW:
|
||||
ignore_gray_space();
|
||||
copy_to_eoln(read_str, terminators, Mp, read_len);
|
||||
drop_trailing_white_space(read_str);
|
||||
advance_to_eoln(terminators);
|
||||
break;
|
||||
|
||||
case F_LNAME:
|
||||
ignore_gray_space();
|
||||
copy_to_eoln(read_str, terminators, Mp, read_len);
|
||||
drop_trailing_white_space(read_str);
|
||||
advance_to_eoln(terminators);
|
||||
break;
|
||||
|
||||
case F_NAME:
|
||||
ignore_gray_space();
|
||||
copy_to_eoln(read_str, terminators, Mp, read_len);
|
||||
drop_trailing_white_space(read_str);
|
||||
advance_to_eoln(terminators);
|
||||
break;
|
||||
|
||||
case F_DATE:
|
||||
case F_FILESPEC:
|
||||
case F_PATHNAME:
|
||||
case F_MESSAGE:
|
||||
ignore_gray_space();
|
||||
copy_to_eoln(read_str, terminators, Mp, read_len);
|
||||
drop_trailing_white_space(read_str);
|
||||
@@ -1295,13 +1213,6 @@ void stuff_string(char *outstr, int type, int len, char *terminators)
|
||||
required_string("$End Notes:");
|
||||
break;
|
||||
|
||||
case F_FILESPEC:
|
||||
ignore_gray_space();
|
||||
copy_to_eoln(read_str, terminators, Mp, read_len);
|
||||
drop_trailing_white_space(read_str);
|
||||
advance_to_eoln(terminators);
|
||||
break;
|
||||
|
||||
// F_MULTITEXTOLD keeping for backwards compatability with old missions
|
||||
// can be deleted once all missions are using new briefing format
|
||||
|
||||
@@ -1320,20 +1231,6 @@ void stuff_string(char *outstr, int type, int len, char *terminators)
|
||||
required_string("$end_multi_text");
|
||||
break;
|
||||
|
||||
case F_PATHNAME:
|
||||
ignore_gray_space();
|
||||
copy_to_eoln(read_str, terminators, Mp, read_len);
|
||||
drop_trailing_white_space(read_str);
|
||||
advance_to_eoln(terminators);
|
||||
break;
|
||||
|
||||
case F_MESSAGE:
|
||||
ignore_gray_space();
|
||||
copy_to_eoln(read_str, terminators, Mp, read_len);
|
||||
drop_trailing_white_space(read_str);
|
||||
advance_to_eoln(terminators);
|
||||
break;
|
||||
|
||||
default:
|
||||
Error(LOCATION, "Unhandled string type %d in stuff_string!", type);
|
||||
}
|
||||
@@ -1371,27 +1268,12 @@ void stuff_string(SCP_string &outstr, int type, char *terminators)
|
||||
|
||||
switch (type) {
|
||||
case F_RAW:
|
||||
ignore_gray_space();
|
||||
copy_to_eoln(read_str, terminators, Mp);
|
||||
drop_trailing_white_space(read_str);
|
||||
advance_to_eoln(terminators);
|
||||
break;
|
||||
|
||||
case F_LNAME:
|
||||
ignore_gray_space();
|
||||
copy_to_eoln(read_str, terminators, Mp);
|
||||
drop_trailing_white_space(read_str);
|
||||
advance_to_eoln(terminators);
|
||||
break;
|
||||
|
||||
case F_NAME:
|
||||
ignore_gray_space();
|
||||
copy_to_eoln(read_str, terminators, Mp);
|
||||
drop_trailing_white_space(read_str);
|
||||
advance_to_eoln(terminators);
|
||||
break;
|
||||
|
||||
case F_DATE:
|
||||
case F_FILESPEC:
|
||||
case F_PATHNAME:
|
||||
case F_MESSAGE:
|
||||
ignore_gray_space();
|
||||
copy_to_eoln(read_str, terminators, Mp);
|
||||
drop_trailing_white_space(read_str);
|
||||
@@ -1405,13 +1287,6 @@ void stuff_string(SCP_string &outstr, int type, char *terminators)
|
||||
required_string("$End Notes:");
|
||||
break;
|
||||
|
||||
case F_FILESPEC:
|
||||
ignore_gray_space();
|
||||
copy_to_eoln(read_str, terminators, Mp);
|
||||
drop_trailing_white_space(read_str);
|
||||
advance_to_eoln(terminators);
|
||||
break;
|
||||
|
||||
// F_MULTITEXTOLD keeping for backwards compatability with old missions
|
||||
// can be deleted once all missions are using new briefing format
|
||||
|
||||
@@ -1430,20 +1305,6 @@ void stuff_string(SCP_string &outstr, int type, char *terminators)
|
||||
required_string("$end_multi_text");
|
||||
break;
|
||||
|
||||
case F_PATHNAME:
|
||||
ignore_gray_space();
|
||||
copy_to_eoln(read_str, terminators, Mp);
|
||||
drop_trailing_white_space(read_str);
|
||||
advance_to_eoln(terminators);
|
||||
break;
|
||||
|
||||
case F_MESSAGE:
|
||||
ignore_gray_space();
|
||||
copy_to_eoln(read_str, terminators, Mp);
|
||||
drop_trailing_white_space(read_str);
|
||||
advance_to_eoln(terminators);
|
||||
break;
|
||||
|
||||
default:
|
||||
Error(LOCATION, "Unhandled string type %d in stuff_string!", type);
|
||||
}
|
||||
@@ -2105,8 +1966,9 @@ int parse_get_line(char *lineout, int max_line_len, char *start, int max_size, c
|
||||
void read_file_text(const char *filename, int mode, char *processed_text, char *raw_text)
|
||||
{
|
||||
// copy the filename
|
||||
if (!filename)
|
||||
longjmp(parse_abort, 10);
|
||||
if (!filename)
|
||||
throw parse::ParseException("Invalid filename");
|
||||
|
||||
strcpy_s(Current_filename_sub, filename);
|
||||
|
||||
// if we are paused then processed_text and raw_text must not be NULL!!
|
||||
@@ -2244,16 +2106,16 @@ void read_raw_file_text(const char *filename, int mode, char *raw_text)
|
||||
mf = cfopen(filename, "rb", CFILE_NORMAL, mode);
|
||||
if (mf == NULL)
|
||||
{
|
||||
nprintf(("Error", "Wokka! Error opening file (%s)!\n", filename));
|
||||
longjmp(parse_abort, 5);
|
||||
nprintf(("Error", "Wokka! Error opening file (%s)!\n", filename));
|
||||
throw parse::ParseException("Failed to open file");
|
||||
}
|
||||
|
||||
// read the entire file in
|
||||
int file_len = cfilelength(mf);
|
||||
|
||||
if(!file_len) {
|
||||
nprintf(("Error", "Oh noes!! File is empty! (%s)!\n", filename));
|
||||
longjmp(parse_abort, 5);
|
||||
nprintf(("Error", "Oh noes!! File is empty! (%s)!\n", filename));
|
||||
throw parse::ParseException("Failed to open file");
|
||||
}
|
||||
|
||||
// allocate, or reallocate, memory for Mission_text and Mission_text_raw based on size we need now
|
||||
@@ -2705,8 +2567,8 @@ int stuff_bool_list(bool *blp, int max_bools)
|
||||
ignore_white_space();
|
||||
|
||||
if (*Mp != '(') {
|
||||
error_display(1, "Reading boolean list. Found [%c]. Expecting '('.\n", *Mp);
|
||||
longjmp(parse_abort, 6);
|
||||
error_display(1, "Reading boolean list. Found [%c]. Expecting '('.\n", *Mp);
|
||||
throw parse::ParseException("Syntax error");
|
||||
}
|
||||
|
||||
Mp++;
|
||||
@@ -2803,8 +2665,8 @@ int stuff_string_list(SCP_vector<SCP_string>& slp)
|
||||
ignore_white_space();
|
||||
|
||||
if ( *Mp != '(' ) {
|
||||
error_display(1, "Reading string list. Found [%c]. Expecting '('.\n", *Mp);
|
||||
longjmp(parse_abort, 100);
|
||||
error_display(1, "Reading string list. Found [%c]. Expecting '('.\n", *Mp);
|
||||
throw parse::ParseException("Syntax error");
|
||||
}
|
||||
|
||||
Mp++;
|
||||
@@ -2837,8 +2699,8 @@ int stuff_string_list(char slp[][NAME_LENGTH], int max_strings)
|
||||
ignore_white_space();
|
||||
|
||||
if ( *Mp != '(' ) {
|
||||
error_display(1, "Reading string list. Found [%c]. Expecting '('.\n", *Mp);
|
||||
longjmp(parse_abort, 100);
|
||||
error_display(1, "Reading string list. Found [%c]. Expecting '('.\n", *Mp);
|
||||
throw parse::ParseException("Syntax error");
|
||||
}
|
||||
|
||||
Mp++;
|
||||
@@ -2894,8 +2756,8 @@ int stuff_int_list(int *ilp, int max_ints, int lookup_type)
|
||||
ignore_white_space();
|
||||
|
||||
if (*Mp != '(') {
|
||||
error_display(1, "Reading integer list. Found [%c]. Expecting '('.\n", *Mp);
|
||||
longjmp(parse_abort, 6);
|
||||
error_display(1, "Reading integer list. Found [%c]. Expecting '('.\n", *Mp);
|
||||
throw parse::ParseException("Syntax error");
|
||||
}
|
||||
|
||||
Mp++;
|
||||
@@ -2996,8 +2858,8 @@ int stuff_loadout_list (int *ilp, int max_ints, int lookup_type)
|
||||
ignore_white_space();
|
||||
|
||||
if (*Mp != '(') {
|
||||
error_display(1, "Reading loadout list. Found [%c]. Expecting '('.\n", *Mp);
|
||||
longjmp(parse_abort, 6);
|
||||
error_display(1, "Reading loadout list. Found [%c]. Expecting '('.\n", *Mp);
|
||||
throw parse::ParseException("Syntax error");
|
||||
}
|
||||
|
||||
Mp++;
|
||||
@@ -3100,8 +2962,8 @@ int stuff_float_list(float* flp, int max_floats)
|
||||
ignore_white_space();
|
||||
|
||||
if (*Mp != '(') {
|
||||
error_display(1, "Reading float list. Found [%c]. Expecting '('.\n", *Mp);
|
||||
longjmp(parse_abort, 6);
|
||||
error_display(1, "Reading float list. Found [%c]. Expecting '('.\n", *Mp);
|
||||
throw parse::ParseException("Syntax error");
|
||||
}
|
||||
|
||||
Mp++;
|
||||
@@ -3133,8 +2995,8 @@ void mark_int_list(int *ilp, int max_ints, int lookup_type)
|
||||
ignore_white_space();
|
||||
|
||||
if (*Mp != '(') {
|
||||
error_display(1, "Marking integer list. Found [%c]. Expecting '('.\n", *Mp);
|
||||
longjmp(parse_abort, 6);
|
||||
error_display(1, "Marking integer list. Found [%c]. Expecting '('.\n", *Mp);
|
||||
throw parse::ParseException("Syntax error");
|
||||
}
|
||||
|
||||
Mp++;
|
||||
@@ -3200,15 +3062,15 @@ void stuff_parenthesized_vec3d(vec3d *vp)
|
||||
ignore_white_space();
|
||||
|
||||
if (*Mp != '(') {
|
||||
error_display(1, "Reading parenthesized vec3d. Found [%c]. Expecting '('.\n", *Mp);
|
||||
longjmp(parse_abort, 11);
|
||||
error_display(1, "Reading parenthesized vec3d. Found [%c]. Expecting '('.\n", *Mp);
|
||||
throw parse::ParseException("Syntax error");
|
||||
} else {
|
||||
Mp++;
|
||||
stuff_vec3d(vp);
|
||||
ignore_white_space();
|
||||
if (*Mp != ')') {
|
||||
error_display(1, "Reading parenthesized vec3d. Found [%c]. Expecting ')'.\n", *Mp);
|
||||
longjmp(parse_abort, 12);
|
||||
error_display(1, "Reading parenthesized vec3d. Found [%c]. Expecting ')'.\n", *Mp);
|
||||
throw parse::ParseException("Syntax error");
|
||||
}
|
||||
Mp++;
|
||||
}
|
||||
@@ -3227,8 +3089,8 @@ int stuff_vec3d_list(vec3d *vlp, int max_vecs)
|
||||
ignore_white_space();
|
||||
|
||||
if (*Mp != '(') {
|
||||
error_display(1, "Reading vec3d list. Found [%c]. Expecting '('.\n", *Mp);
|
||||
longjmp(parse_abort, 6);
|
||||
error_display(1, "Reading vec3d list. Found [%c]. Expecting '('.\n", *Mp);
|
||||
throw parse::ParseException("Syntax error");
|
||||
}
|
||||
|
||||
Mp++;
|
||||
@@ -3258,8 +3120,8 @@ int stuff_vec3d_list(SCP_vector<vec3d> &vec_list)
|
||||
ignore_white_space();
|
||||
|
||||
if (*Mp != '(') {
|
||||
error_display(1, "Reading vec3d list. Found [%c]. Expecting '('.\n", *Mp);
|
||||
longjmp(parse_abort, 6);
|
||||
error_display(1, "Reading vec3d list. Found [%c]. Expecting '('.\n", *Mp);
|
||||
throw parse::ParseException("Syntax error");
|
||||
}
|
||||
|
||||
Mp++;
|
||||
|
||||
+11
-6
@@ -14,9 +14,7 @@
|
||||
#include "cfile/cfile.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
|
||||
#include <csetjmp>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <exception>
|
||||
|
||||
// NOTE: although the main game doesn't need this anymore, FRED2 still does
|
||||
#define MISSION_TEXT_SIZE 1000000
|
||||
@@ -27,7 +25,6 @@ extern char *Mp;
|
||||
extern char *token_found;
|
||||
extern int fred_parse_flag;
|
||||
extern int Token_found_flag;
|
||||
extern jmp_buf parse_abort;
|
||||
|
||||
|
||||
#define COMMENT_CHAR (char)';'
|
||||
@@ -110,8 +107,6 @@ extern int optional_string_one_of(int arg_count, ...);
|
||||
// required
|
||||
extern int required_string(char *pstr);
|
||||
extern int required_string_either(char *str1, char *str2);
|
||||
extern int required_string_3(char *str1, char *str2, char *str3);
|
||||
extern int required_string_4(char *str1, char *str2, char *str3, char *str4);
|
||||
extern int required_string_one_of(int arg_count, ...);
|
||||
|
||||
// stuff
|
||||
@@ -259,4 +254,14 @@ int get_string_or_variable (SCP_string &str);
|
||||
#define PARSING_FOUND_STRING 0
|
||||
#define PARSING_FOUND_VARIABLE 1
|
||||
|
||||
namespace parse
|
||||
{
|
||||
class ParseException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
ParseException(const std::string& msg) : std::runtime_error(msg) {}
|
||||
~ParseException() throw() {}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
+54
-52
@@ -109,46 +109,42 @@ bool script_hook_valid(script_hook *hook)
|
||||
void script_parse_table(const char *filename)
|
||||
{
|
||||
script_state *st = &Script_system;
|
||||
int rval;
|
||||
if ((rval = setjmp(parse_abort)) != 0)
|
||||
|
||||
try
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", filename, rval));
|
||||
return;
|
||||
}
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
if (optional_string("#Global Hooks"))
|
||||
{
|
||||
//int num = 42;
|
||||
//Script_system.SetHookVar("Version", 'i', &num);
|
||||
if (optional_string("$Global:")) {
|
||||
st->ParseChunk(&Script_globalhook, "Global");
|
||||
}
|
||||
|
||||
if(optional_string("#Global Hooks"))
|
||||
{
|
||||
//int num = 42;
|
||||
//Script_system.SetHookVar("Version", 'i', &num);
|
||||
if(optional_string("$Global:")) {
|
||||
st->ParseChunk(&Script_globalhook, "Global");
|
||||
if (optional_string("$Splash:")) {
|
||||
st->ParseChunk(&Script_splashhook, "Splash");
|
||||
}
|
||||
|
||||
if (optional_string("$GameInit:")) {
|
||||
st->ParseChunk(&Script_gameinithook, "GameInit");
|
||||
}
|
||||
|
||||
if (optional_string("$Simulation:")) {
|
||||
st->ParseChunk(&Script_simulationhook, "Simulation");
|
||||
}
|
||||
|
||||
if (optional_string("$HUD:")) {
|
||||
st->ParseChunk(&Script_hudhook, "HUD");
|
||||
}
|
||||
|
||||
required_string("#End");
|
||||
}
|
||||
|
||||
if(optional_string("$Splash:")) {
|
||||
st->ParseChunk(&Script_splashhook, "Splash");
|
||||
}
|
||||
|
||||
if(optional_string("$GameInit:")) {
|
||||
st->ParseChunk(&Script_gameinithook, "GameInit");
|
||||
}
|
||||
|
||||
if(optional_string("$Simulation:")) {
|
||||
st->ParseChunk(&Script_simulationhook, "Simulation");
|
||||
}
|
||||
|
||||
if(optional_string("$HUD:")) {
|
||||
st->ParseChunk(&Script_hudhook, "HUD");
|
||||
}
|
||||
|
||||
required_string("#End");
|
||||
}
|
||||
/*
|
||||
if(optional_string("#State Hooks"))
|
||||
{
|
||||
while(optional_string("$State:")) {
|
||||
/*
|
||||
if(optional_string("#State Hooks"))
|
||||
{
|
||||
while(optional_string("$State:")) {
|
||||
char buf[NAME_LENGTH];
|
||||
int idx;
|
||||
stuff_string(buf, F_NAME, sizeof(buf));
|
||||
@@ -157,25 +153,31 @@ void script_parse_table(const char *filename)
|
||||
|
||||
if(optional_string("$Hook:"))
|
||||
{
|
||||
if(idx > -1) {
|
||||
GS_state_hooks[idx] = st->ParseChunk(buf);
|
||||
} else {
|
||||
st->ParseChunk(buf);
|
||||
}
|
||||
if(idx > -1) {
|
||||
GS_state_hooks[idx] = st->ParseChunk(buf);
|
||||
} else {
|
||||
st->ParseChunk(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
required_string("#End");
|
||||
}
|
||||
*/
|
||||
if (optional_string("#Conditional Hooks"))
|
||||
{
|
||||
while (st->ParseCondition(filename));
|
||||
required_string("#End");
|
||||
}
|
||||
required_string("#End");
|
||||
}
|
||||
*/
|
||||
if(optional_string("#Conditional Hooks"))
|
||||
{
|
||||
while(st->ParseCondition(filename));
|
||||
required_string("#End");
|
||||
}
|
||||
|
||||
// add tbl/tbm to multiplayer validation list
|
||||
extern void fs2netd_add_table_validation(const char *tblname);
|
||||
fs2netd_add_table_validation(filename);
|
||||
// add tbl/tbm to multiplayer validation list
|
||||
extern void fs2netd_add_table_validation(const char *tblname);
|
||||
fs2netd_add_table_validation(filename);
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", filename, e.what()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//Initializes the (global) scripting system, as well as any subsystems.
|
||||
|
||||
+96
-74
@@ -3576,8 +3576,8 @@ int stuff_sexp_variable_list()
|
||||
|
||||
// check for start of list
|
||||
if (*Mp != '(') {
|
||||
error_display(1, "Reading sexp variable list. Found [%c]. Expecting '('.\n", *Mp);
|
||||
longjmp(parse_abort, 6);
|
||||
error_display(1, "Reading sexp variable list. Found [%c]. Expecting '('.\n", *Mp);
|
||||
throw parse::ParseException("Syntax error");
|
||||
}
|
||||
|
||||
Mp++;
|
||||
@@ -4392,7 +4392,7 @@ int sexp_and(int n)
|
||||
if (CAR(n) != -1)
|
||||
{
|
||||
result &= is_sexp_true(CAR(n));
|
||||
if ( Sexp_nodes[CAR(n)].value == SEXP_KNOWN_FALSE )
|
||||
if ( Sexp_nodes[CAR(n)].value == SEXP_KNOWN_FALSE || Sexp_nodes[CAR(n)].value == SEXP_NAN_FOREVER )
|
||||
return SEXP_KNOWN_FALSE; // if one of the AND clauses is FALSE, whole clause is false
|
||||
if ( Sexp_nodes[CAR(n)].value != SEXP_KNOWN_TRUE ) // if the value is still unknown, they all can't be true
|
||||
all_true = 0;
|
||||
@@ -4406,7 +4406,7 @@ int sexp_and(int n)
|
||||
|
||||
new_result = is_sexp_true(CDR(n));
|
||||
result &= new_result;
|
||||
if ( Sexp_nodes[CDR(n)].value == SEXP_KNOWN_FALSE )
|
||||
if ( Sexp_nodes[CDR(n)].value == SEXP_KNOWN_FALSE || Sexp_nodes[CDR(n)].value == SEXP_NAN_FOREVER )
|
||||
return SEXP_KNOWN_FALSE; // if one of the AND clauses is FALSE, whole clause is false
|
||||
if ( Sexp_nodes[CDR(n)].value != SEXP_KNOWN_TRUE ) // if the value is still unknown, they all can't be true
|
||||
all_true = 0;
|
||||
@@ -4435,7 +4435,7 @@ int sexp_and_in_sequence(int n)
|
||||
if (CAR(n) != -1)
|
||||
{
|
||||
result &= is_sexp_true(CAR(n));
|
||||
if ( Sexp_nodes[CAR(n)].value == SEXP_KNOWN_FALSE )
|
||||
if ( Sexp_nodes[CAR(n)].value == SEXP_KNOWN_FALSE || Sexp_nodes[CAR(n)].value == SEXP_NAN_FOREVER )
|
||||
return SEXP_KNOWN_FALSE; // if one of the AND clauses is FALSE, whole clause is false
|
||||
if ( Sexp_nodes[CAR(n)].value != SEXP_KNOWN_TRUE ) // if value is true, mark our all_true variable for later checking
|
||||
all_true = 0;
|
||||
@@ -4458,7 +4458,7 @@ int sexp_and_in_sequence(int n)
|
||||
if ( next_result && !result ) // if current result is true, and our running result is false, thngs didn't become true in order
|
||||
return SEXP_KNOWN_FALSE;
|
||||
result &= next_result;
|
||||
if ( Sexp_nodes[CDR(n)].value == SEXP_KNOWN_FALSE )
|
||||
if ( Sexp_nodes[CDR(n)].value == SEXP_KNOWN_FALSE || Sexp_nodes[CDR(n)].value == SEXP_NAN_FOREVER )
|
||||
return SEXP_KNOWN_FALSE; // if one of the OR clauses is TRUE, whole clause is true
|
||||
if ( Sexp_nodes[CDR(n)].value != SEXP_KNOWN_TRUE ) // if the value is still unknown, they all can't be false
|
||||
all_true = 0;
|
||||
@@ -4490,14 +4490,12 @@ int sexp_not(int n)
|
||||
if (CAR(n) != -1)
|
||||
{
|
||||
result = is_sexp_true(CAR(n));
|
||||
if ( Sexp_nodes[CAR(n)].value == SEXP_KNOWN_FALSE )
|
||||
if ( Sexp_nodes[CAR(n)].value == SEXP_KNOWN_FALSE || Sexp_nodes[CDR(n)].value == SEXP_NAN_FOREVER )
|
||||
return SEXP_KNOWN_TRUE; // not KNOWN_FALSE == KNOWN_TRUE;
|
||||
else if ( Sexp_nodes[CAR(n)].value == SEXP_KNOWN_TRUE ) // not KNOWN_TRUE == KNOWN_FALSE
|
||||
return SEXP_KNOWN_FALSE;
|
||||
else if ( Sexp_nodes[CAR(n)].value == SEXP_NAN ) // not NAN == TRUE (I think)
|
||||
return SEXP_TRUE;
|
||||
else if ( Sexp_nodes[CAR(n)].value == SEXP_NAN_FOREVER )
|
||||
return SEXP_TRUE;
|
||||
}
|
||||
else
|
||||
result = atoi(CTEXT(n));
|
||||
@@ -6242,7 +6240,7 @@ int sexp_directive_value(int n)
|
||||
replace_current_value = eval_sexp(n);
|
||||
}
|
||||
|
||||
if ((replace_current_value == SEXP_KNOWN_FALSE) || (replace_current_value == SEXP_FALSE) ) {
|
||||
if (replace_current_value == SEXP_FALSE) { // note: any SEXP_KNOWN_FALSE result will return SEXP_FALSE
|
||||
Directive_count += directive_value;
|
||||
}
|
||||
else {
|
||||
@@ -8367,12 +8365,8 @@ int eval_perform_actions(int n)
|
||||
}
|
||||
|
||||
// return whatever val was, but don't return known-*
|
||||
if (val == SEXP_KNOWN_TRUE)
|
||||
return SEXP_TRUE;
|
||||
else if (val == SEXP_KNOWN_FALSE)
|
||||
return SEXP_FALSE;
|
||||
else
|
||||
return val;
|
||||
// note: SEXP_KNOWN_TRUE/SEXP_KNOWN_FALSE are never returned from eval_sexp
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -8410,7 +8404,7 @@ int eval_when(int n, int when_op_num)
|
||||
|
||||
|
||||
// if value is true, perform the actions in the 'then' part
|
||||
if (val == SEXP_TRUE || val == SEXP_KNOWN_TRUE)
|
||||
if (val == SEXP_TRUE) // note: SEXP_KNOWN_TRUE is never returned from eval_sexp
|
||||
{
|
||||
// get the operator
|
||||
int exp = CAR(actions);
|
||||
@@ -8442,7 +8436,7 @@ int eval_when(int n, int when_op_num)
|
||||
}
|
||||
}
|
||||
// if-then-else has actions to perform under "else"
|
||||
else if ((val == SEXP_FALSE || val == SEXP_KNOWN_FALSE) && when_op_num == OP_IF_THEN_ELSE)
|
||||
else if (val == SEXP_FALSE && when_op_num == OP_IF_THEN_ELSE) // note: SEXP_KNOWN_FALSE is never returned from eval_sexp
|
||||
{
|
||||
// skip past the "if" action
|
||||
actions = CDR(actions);
|
||||
@@ -8460,10 +8454,8 @@ int eval_when(int n, int when_op_num)
|
||||
}
|
||||
|
||||
// invert val so that we behave like a when with opposite results
|
||||
if (val == SEXP_KNOWN_FALSE)
|
||||
val = SEXP_KNOWN_TRUE;
|
||||
else
|
||||
val = SEXP_TRUE;
|
||||
// note: SEXP_KNOWN_FALSE is never returned from eval_sexp
|
||||
val = SEXP_TRUE;
|
||||
}
|
||||
|
||||
if (is_blank_argument_op(when_op_num))
|
||||
@@ -8485,11 +8477,10 @@ int eval_when(int n, int when_op_num)
|
||||
// thanks to MageKing17 for noticing that we need to short-circuit on the correct node!
|
||||
int short_circuit_node = (arg_handler >= 0) ? arg_handler : cond;
|
||||
|
||||
if (Sexp_nodes[short_circuit_node].value == SEXP_KNOWN_FALSE)
|
||||
if (Sexp_nodes[short_circuit_node].value == SEXP_KNOWN_FALSE || Sexp_nodes[short_circuit_node].value == SEXP_NAN_FOREVER)
|
||||
return SEXP_KNOWN_FALSE; // no need to waste time on this anymore
|
||||
|
||||
if (val == SEXP_KNOWN_FALSE)
|
||||
return SEXP_FALSE; // can't return known false, as this would bypass future actions under the when
|
||||
// note: val can't be SEXP_KNOWN_FALSE at this point
|
||||
|
||||
return val;
|
||||
}
|
||||
@@ -8510,7 +8501,7 @@ int eval_cond(int n)
|
||||
|
||||
// if the conditional evaluated to true, then we must evaluate the rest of the expression returning
|
||||
// the value of this evaluation
|
||||
if (val == SEXP_TRUE || val == SEXP_KNOWN_TRUE)
|
||||
if (val == SEXP_TRUE) // note: any SEXP_KNOWN_TRUE result is returned as SEXP_TRUE
|
||||
{
|
||||
int actions, exp;
|
||||
|
||||
@@ -8566,6 +8557,13 @@ int test_argument_nodes_for_condition(int n, int condition_node, int *num_true,
|
||||
// evaluate conditional for current argument
|
||||
Sexp_replacement_arguments.push_back(Sexp_nodes[n].text);
|
||||
val = eval_sexp(condition_node);
|
||||
if ( Sexp_nodes[condition_node].value == SEXP_KNOWN_TRUE ||
|
||||
Sexp_nodes[condition_node].value == SEXP_KNOWN_FALSE) {
|
||||
val = Sexp_nodes[condition_node].value;
|
||||
} else if ( Sexp_nodes[condition_node].value == SEXP_NAN_FOREVER ) {
|
||||
// In accordance with SEXP_NAN/SEXP_NAN_FOREVER becoming SEXP_FALSE in eval_sexp()
|
||||
val = SEXP_KNOWN_FALSE;
|
||||
}
|
||||
|
||||
switch (val)
|
||||
{
|
||||
@@ -8640,6 +8638,13 @@ int test_argument_vector_for_condition(SCP_vector<char*> argument_vector, bool a
|
||||
// evaluate conditional for current argument
|
||||
Sexp_replacement_arguments.push_back(argument_vector[i]);
|
||||
val = eval_sexp(condition_node);
|
||||
if ( Sexp_nodes[condition_node].value == SEXP_KNOWN_TRUE ||
|
||||
Sexp_nodes[condition_node].value == SEXP_KNOWN_FALSE) {
|
||||
val = Sexp_nodes[condition_node].value;
|
||||
} else if ( Sexp_nodes[condition_node].value == SEXP_NAN_FOREVER ) {
|
||||
// In accordance with SEXP_NAN/SEXP_NAN_FOREVER becoming SEXP_FALSE in eval_sexp()
|
||||
val = SEXP_KNOWN_FALSE;
|
||||
}
|
||||
|
||||
switch (val)
|
||||
{
|
||||
@@ -8705,12 +8710,10 @@ int eval_any_of(int arg_handler_node, int condition_node)
|
||||
num_valid_arguments = test_argument_nodes_for_condition(n, condition_node, &num_true, &num_false, &num_known_true, &num_known_false);
|
||||
|
||||
// use the sexp_or algorithm
|
||||
if (num_known_true)
|
||||
return SEXP_KNOWN_TRUE;
|
||||
if (num_known_true || num_true)
|
||||
return SEXP_TRUE;
|
||||
else if (num_known_false == num_valid_arguments)
|
||||
return SEXP_KNOWN_FALSE;
|
||||
else if (num_true)
|
||||
return SEXP_TRUE;
|
||||
else
|
||||
return SEXP_FALSE;
|
||||
}
|
||||
@@ -8728,10 +8731,8 @@ int eval_every_of(int arg_handler_node, int condition_node)
|
||||
num_valid_arguments = test_argument_nodes_for_condition(n, condition_node, &num_true, &num_false, &num_known_true, &num_known_false);
|
||||
|
||||
// use the sexp_and algorithm
|
||||
if (num_known_false)
|
||||
if ((!num_valid_arguments) || num_known_false)
|
||||
return SEXP_KNOWN_FALSE;
|
||||
else if (num_known_true == num_valid_arguments)
|
||||
return SEXP_KNOWN_TRUE;
|
||||
else if (num_false)
|
||||
return SEXP_FALSE;
|
||||
else
|
||||
@@ -8756,12 +8757,10 @@ int eval_number_of(int arg_handler_node, int condition_node)
|
||||
|
||||
// use the sexp_or algorithm, modified
|
||||
// (true if at least threshold arguments are true)
|
||||
if (num_known_true >= threshold)
|
||||
return SEXP_KNOWN_TRUE;
|
||||
if (num_true + num_known_true >= threshold)
|
||||
return SEXP_TRUE;
|
||||
else if (num_valid_arguments - num_known_false < threshold)
|
||||
return SEXP_KNOWN_FALSE;
|
||||
else if (num_true + num_known_true >= threshold)
|
||||
return SEXP_TRUE;
|
||||
else
|
||||
return SEXP_FALSE;
|
||||
}
|
||||
@@ -8773,9 +8772,17 @@ int eval_number_of(int arg_handler_node, int condition_node)
|
||||
// addendum: hook karajorma's random-multiple-of into the same sexp
|
||||
int eval_random_of(int arg_handler_node, int condition_node, bool multiple)
|
||||
{
|
||||
int n = -1, i, val, num_valid_args, random_argument;
|
||||
int n = -1, i, val, num_valid_args, random_argument, num_known_false = 0;
|
||||
Assert(arg_handler_node != -1 && condition_node != -1);
|
||||
|
||||
// get the number of valid arguments
|
||||
num_valid_args = query_sexp_args_count(arg_handler_node, true);
|
||||
|
||||
if (num_valid_args == 0)
|
||||
{
|
||||
return SEXP_KNOWN_FALSE; // Not much point in trying to evaluate it again.
|
||||
}
|
||||
|
||||
// find which argument we picked, if we picked one
|
||||
if (!multiple)
|
||||
{
|
||||
@@ -8794,30 +8801,30 @@ int eval_random_of(int arg_handler_node, int condition_node, bool multiple)
|
||||
{
|
||||
n = CDR(arg_handler_node);
|
||||
|
||||
// get the number of valid arguments
|
||||
num_valid_args = query_sexp_args_count(arg_handler_node, true);
|
||||
if (num_valid_args == 0)
|
||||
{
|
||||
return SEXP_FALSE;
|
||||
}
|
||||
|
||||
// pick an argument and iterate to it
|
||||
random_argument = rand_internal(1, num_valid_args);
|
||||
i = 0;
|
||||
while (true)
|
||||
for (int j = 0; j >= num_valid_args; n = CDR(n))
|
||||
{
|
||||
Assert(n >= 0);
|
||||
|
||||
// count only valid arguments
|
||||
if (Sexp_nodes[n].flags & SNF_ARGUMENT_VALID)
|
||||
i++;
|
||||
if (Sexp_nodes[n].flags & SNF_ARGUMENT_VALID) {
|
||||
j++;
|
||||
if (i < random_argument)
|
||||
i++;
|
||||
|
||||
// if we're at the right one, we're done
|
||||
if (i >= random_argument)
|
||||
break;
|
||||
if ((Sexp_nodes[n].value == SEXP_KNOWN_FALSE) || (Sexp_nodes[n].value == SEXP_NAN_FOREVER))
|
||||
num_known_false++;
|
||||
|
||||
// iterate
|
||||
n = CDR(n);
|
||||
// if we're out of valid arguments, we're done
|
||||
if (j >= num_valid_args)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_known_false == num_valid_args) {
|
||||
return SEXP_KNOWN_FALSE; // We're going nowhere fast.
|
||||
}
|
||||
|
||||
// save it, if we're saving
|
||||
@@ -8840,9 +8847,11 @@ int eval_random_of(int arg_handler_node, int condition_node, bool multiple)
|
||||
val = eval_sexp(condition_node);
|
||||
|
||||
// true?
|
||||
if (val == SEXP_TRUE || val == SEXP_KNOWN_TRUE)
|
||||
if (val == SEXP_TRUE)
|
||||
{
|
||||
Sexp_applicable_argument_list.add_data(Sexp_nodes[n].text);
|
||||
} else if ((!multiple || num_valid_args == 1) && (Sexp_nodes[condition_node].value == SEXP_KNOWN_FALSE || Sexp_nodes[condition_node].value == SEXP_NAN_FOREVER)) {
|
||||
val = SEXP_KNOWN_FALSE; // If we can't randomly pick another one and this one is guaranteed never to be true, then give up now.
|
||||
}
|
||||
|
||||
// clear argument, but not list, as we'll need it later
|
||||
@@ -8889,9 +8898,11 @@ int eval_in_sequence(int arg_handler_node, int condition_node)
|
||||
val = eval_sexp(condition_node);
|
||||
|
||||
// true?
|
||||
if (val == SEXP_TRUE || val == SEXP_KNOWN_TRUE)
|
||||
if (val == SEXP_TRUE)
|
||||
{
|
||||
Sexp_applicable_argument_list.add_data(Sexp_nodes[n].text);
|
||||
} else if ((Sexp_nodes[condition_node].value == SEXP_KNOWN_FALSE) || (Sexp_nodes[condition_node].value == SEXP_NAN_FOREVER)) {
|
||||
val = SEXP_KNOWN_FALSE; // If we're wasting our time evaluating this ever again, just go ahead and short-circuit.
|
||||
}
|
||||
|
||||
// clear argument, but not list, as we'll need it later
|
||||
@@ -8951,19 +8962,22 @@ int eval_for_counter(int arg_handler_node, int condition_node)
|
||||
for (i = counter_start; ((counter_step > 0) ? i <= counter_stop : i >= counter_stop); i += counter_step)
|
||||
{
|
||||
sprintf(buf, "%d", i);
|
||||
argument_vector.push_back(strdup(buf));
|
||||
argument_vector.push_back(vm_strdup(buf));
|
||||
}
|
||||
|
||||
// test the whole argument vector
|
||||
num_valid_arguments = test_argument_vector_for_condition(argument_vector, true, condition_node, &num_true, &num_false, &num_known_true, &num_known_false);
|
||||
|
||||
while (!argument_vector.empty()) {
|
||||
vm_free(argument_vector.back());
|
||||
argument_vector.pop_back();
|
||||
}
|
||||
|
||||
// use the sexp_or algorithm
|
||||
if (num_known_true)
|
||||
return SEXP_KNOWN_TRUE;
|
||||
if (num_known_true || num_true)
|
||||
return SEXP_TRUE;
|
||||
else if (num_known_false == num_valid_arguments)
|
||||
return SEXP_KNOWN_FALSE;
|
||||
else if (num_true)
|
||||
return SEXP_TRUE;
|
||||
else
|
||||
return SEXP_FALSE;
|
||||
}
|
||||
@@ -10491,7 +10505,7 @@ void sexp_adjust_audio_volume(int node)
|
||||
|
||||
if (n > 0) {
|
||||
int option = audio_volume_option_lookup(CTEXT(n));
|
||||
if (option > 0) {
|
||||
if (option >= 0) {
|
||||
n = CDR(n);
|
||||
|
||||
float target_volume = 1.0f;
|
||||
@@ -16541,6 +16555,7 @@ void parse_copy_damage(p_object *target_pobjp, ship *source_shipp)
|
||||
// ...and shields
|
||||
target_pobjp->ship_max_shield_strength = source_shipp->ship_max_shield_strength;
|
||||
target_pobjp->initial_shields = fl2i(get_shield_pct(source_objp) * 100.0f);
|
||||
target_pobjp->max_shield_recharge = source_shipp->max_shield_recharge;
|
||||
|
||||
|
||||
// search through all subsystems on source ship and map them onto target ship
|
||||
@@ -22216,7 +22231,7 @@ int is_sexp_true(int cur_node, int referenced_node)
|
||||
{
|
||||
int result = eval_sexp(cur_node, referenced_node);
|
||||
|
||||
return ((result == SEXP_TRUE) || (result == SEXP_KNOWN_TRUE));
|
||||
return (result == SEXP_TRUE); // note: any SEXP_KNOWN_TRUE result will return SEXP_TRUE
|
||||
}
|
||||
|
||||
|
||||
@@ -22466,7 +22481,13 @@ int eval_sexp(int cur_node, int referenced_node)
|
||||
add_to_event_log_buffer(get_operator_index(cur_node), SEXP_KNOWN_FALSE);
|
||||
}
|
||||
return SEXP_FALSE;
|
||||
}
|
||||
}
|
||||
else if (Sexp_nodes[cur_node].value == SEXP_NAN_FOREVER) {
|
||||
if (Log_event) {
|
||||
add_to_event_log_buffer(get_operator_index(cur_node), SEXP_NAN_FOREVER);
|
||||
}
|
||||
return SEXP_FALSE;
|
||||
}
|
||||
|
||||
if (Sexp_nodes[cur_node].first != -1) {
|
||||
node = CAR(cur_node);
|
||||
@@ -24647,7 +24668,7 @@ int eval_sexp(int cur_node, int referenced_node)
|
||||
|
||||
// if we haven't returned, check the sexp value of the sexpression evaluation. A special
|
||||
// value of known true or known false means that we should set the sexp.value field for
|
||||
// short circuit eval (and return that special value as well).
|
||||
// short circuit eval.
|
||||
if (sexp_val == SEXP_KNOWN_TRUE) {
|
||||
Sexp_nodes[cur_node].value = SEXP_KNOWN_TRUE;
|
||||
return SEXP_TRUE;
|
||||
@@ -31465,7 +31486,8 @@ sexp_help_struct Sexp_help[] = {
|
||||
"friendly-stealth-invisible - If set, the ship can't be targeted even by ships on the same team\r\n"
|
||||
"hide-ship-name - If set, the ship name can't be seen when the ship is targeted\r\n"
|
||||
"hidden-from-sensors - If set, the ship can't be targeted and appears on radar as a blinking dot\r\n"
|
||||
"no-dynamic - Will stop allowing the AI to persue dynamic goals (eg: chasing ships it was not ordered to)\r\n"},
|
||||
"no-dynamic - Will stop allowing the AI to persue dynamic goals (eg: chasing ships it was not ordered to)\r\n"
|
||||
"no-secondary-lock-on - Will disable target acquisition for secondaries of all types (does not affect turrets)\r\n"},
|
||||
|
||||
{ OP_SHIP_VISIBLE, "ship-visible\r\n"
|
||||
"\tCauses the ships listed in this sexpression to be visible with player sensors.\r\n\r\n"
|
||||
@@ -32111,7 +32133,7 @@ sexp_help_struct Sexp_help[] = {
|
||||
"\tReturns a percentage from 0 to 100\r\n"
|
||||
"\t1: Ship name\r\n" },
|
||||
|
||||
{ OP_GET_ETS_VALUE, "get-ets-values\r\n"
|
||||
{ OP_GET_ETS_VALUE, "get-ets-value\r\n"
|
||||
"\tGets one ETS index for a ship\r\n"
|
||||
"\t1: ETS index to get, Engine|Shield|Weapon\r\n"
|
||||
"\t2: Ship name\r\n"},
|
||||
@@ -32432,8 +32454,8 @@ sexp_help_struct Sexp_help[] = {
|
||||
"\tSets the amount of ammo for the specified ballistic bank\r\n"
|
||||
"\t1: Ship name\r\n"
|
||||
"\t2: Bank to check (0, 1, and 2 are legal banks)\r\n"
|
||||
"\t3: Number to set this bank to (If this is larger than the maximimum, bank will be set to maximum).\r\n"
|
||||
"\t4: Rearm Limit. Support ships will only supply this number of weapons (If this is larger than the maximimum, bank will be set to maximum)"
|
||||
"\t3: Number to set this bank to (If this is larger than the maximum, bank will be set to maximum).\r\n"
|
||||
"\t4: Rearm Limit. Support ships will only supply this number of weapons (If this is larger than the maximum, bank will be set to maximum)"
|
||||
},
|
||||
|
||||
// Karajorma
|
||||
@@ -32441,8 +32463,8 @@ sexp_help_struct Sexp_help[] = {
|
||||
"\tSets the amount of ammo for the specified bank\r\n"
|
||||
"\t1: Ship name\r\n"
|
||||
"\t2: Bank to check (0, 1, 2 and 3 are legal banks)\r\n"
|
||||
"\t3: Number to set this bank to (If this is larger than the maximimum, bank will be set to maximum).\r\n"
|
||||
"\t4: Rearm Limit. Support ships will only supply this number of weapons (If this is larger than the maximimum, bank will be set to maximum)"
|
||||
"\t3: Number to set this bank to (If this is larger than the maximum, bank will be set to maximum).\r\n"
|
||||
"\t4: Rearm Limit. Support ships will only supply this number of weapons (If this is larger than the maximum, bank will be set to maximum)"
|
||||
},
|
||||
|
||||
// Karajorma
|
||||
@@ -32451,8 +32473,8 @@ sexp_help_struct Sexp_help[] = {
|
||||
"\t1: Ship name\r\n"
|
||||
"\t2: Bank to check (0, 1 and 2 are legal banks)\r\n"
|
||||
"\t3: Name of the primary weapon \r\n"
|
||||
"\t4: Number to set this bank to (If this is larger than the maximimum, bank will be set to maximum)\r\n"
|
||||
"\t5: Rearm Limit. Support ships will only supply this number of weapons (If this is larger than the maximimum, bank will be set to maximum)"
|
||||
"\t4: Number to set ammo of this bank to (If this is larger than the maximum, bank will be set to maximum)\r\n"
|
||||
"\t5: Rearm Limit. Support ships will only supply this number of weapons (If this is larger than the maximum, bank will be set to maximum)"
|
||||
},
|
||||
|
||||
// Karajorma
|
||||
@@ -32461,8 +32483,8 @@ sexp_help_struct Sexp_help[] = {
|
||||
"\t1: Ship name\r\n"
|
||||
"\t2: Bank to check (0, 1, 2 and 3 are legal banks)\r\n"
|
||||
"\t3: Name of the secondary weapon \r\n"
|
||||
"\t4: Number to set this bank to (If this is larger than the maximimum, bank will be set to maximum)\r\n"
|
||||
"\t5: Rearm Limit. Support ships will only supply this number of weapons (If this is larger than the maximimum, bank will be set to maximum)"
|
||||
"\t4: Number to set ammo of this bank to (If this is larger than the maximum, bank will be set to maximum)\r\n"
|
||||
"\t5: Rearm Limit. Support ships will only supply this number of weapons (If this is larger than the maximum, bank will be set to maximum)"
|
||||
},
|
||||
|
||||
|
||||
|
||||
@@ -101,6 +101,10 @@ void init_new_pilot(player *p, int reset)
|
||||
Mouse_sensitivity = 4;
|
||||
Joy_sensitivity = 9;
|
||||
Dead_zone_size = 10;
|
||||
|
||||
Master_sound_volume = Default_sound_volume;
|
||||
Master_event_music_volume = Default_music_volume;
|
||||
Master_voice_volume = Default_voice_volume;
|
||||
}
|
||||
|
||||
// unassigned squadron
|
||||
|
||||
@@ -637,22 +637,22 @@ void read_keyboard_controls( control_info * ci, float frame_time, physics_info *
|
||||
if (Axis_map_to[JOY_HEADING_AXIS] >= 0) {
|
||||
// check the heading on the x axis
|
||||
if ( check_control(BANK_WHEN_PRESSED) ) {
|
||||
delta = f2fl( axis[JOY_HEADING_AXIS] );
|
||||
delta = f2fl( axis[Axis_map_to[JOY_HEADING_AXIS]] );
|
||||
if ( (delta > 0.05f) || (delta < -0.05f) ) {
|
||||
ci->bank -= delta;
|
||||
}
|
||||
} else {
|
||||
ci->heading += f2fl( axis[JOY_HEADING_AXIS] );
|
||||
ci->heading += f2fl( axis[Axis_map_to[JOY_HEADING_AXIS]] );
|
||||
}
|
||||
}
|
||||
|
||||
// check the pitch on the y axis
|
||||
if (Axis_map_to[JOY_PITCH_AXIS] >= 0) {
|
||||
ci->pitch -= f2fl( axis[JOY_PITCH_AXIS] );
|
||||
ci->pitch -= f2fl( axis[Axis_map_to[JOY_PITCH_AXIS]] );
|
||||
}
|
||||
|
||||
if (Axis_map_to[JOY_BANK_AXIS] >= 0) {
|
||||
ci->bank -= f2fl( axis[JOY_BANK_AXIS] ) * 1.5f;
|
||||
ci->bank -= f2fl( axis[Axis_map_to[JOY_BANK_AXIS]] ) * 1.5f;
|
||||
}
|
||||
|
||||
// axis 2 is for throttle
|
||||
|
||||
+406
-314
File diff suppressed because it is too large.
Load diff
+23
-4
@@ -424,7 +424,7 @@ typedef struct ship_flag_name {
|
||||
int flag_list; // is this flag in the 1st or 2nd ship flags list?
|
||||
} ship_flag_name;
|
||||
|
||||
#define MAX_SHIP_FLAG_NAMES 17
|
||||
#define MAX_SHIP_FLAG_NAMES 18
|
||||
extern ship_flag_name Ship_flag_names[];
|
||||
|
||||
// states for the flags variable within the ship structure
|
||||
@@ -505,6 +505,7 @@ extern ship_flag_name Ship_flag_names[];
|
||||
#define SF2_WEAPONS_LOCKED (1<<25) // Karajorma - Prevents the player from changing the weapons on the ship on the loadout screen
|
||||
#define SF2_SHIP_SELECTIVE_LINKING (1<<26) // RSAXVC - Allow pilot to pick firing configuration
|
||||
#define SF2_SCRAMBLE_MESSAGES (1<<27) // Goober5000 - all messages sent from this ship appear scrambled
|
||||
#define SF2_NO_SECONDARY_LOCKON (1<<28) // zookeeper - secondary lock-on disabled
|
||||
|
||||
// If any of these bits in the ship->flags are set, ignore this ship when targeting
|
||||
extern int TARGET_SHIP_IGNORE_FLAGS;
|
||||
@@ -592,6 +593,8 @@ public:
|
||||
float ship_max_shield_strength;
|
||||
float ship_max_hull_strength;
|
||||
|
||||
float max_shield_recharge;
|
||||
|
||||
int ship_guardian_threshold; // Goober5000 - now also determines whether ship is guardian'd
|
||||
|
||||
|
||||
@@ -928,6 +931,7 @@ extern int ship_find_exited_ship_by_signature( int signature);
|
||||
#define SIF2_AUTO_SPREAD_SHIELDS (1 << 16) // zookeeper - auto spread shields
|
||||
#define SIF2_DRAW_WEAPON_MODELS (1 << 17) // the ship draws weapon models of any sort (used to be a boolean)
|
||||
#define SIF2_MODEL_POINT_SHIELDS (1 << 18) // zookeeper - uses model-defined shield points instead of quadrants
|
||||
#define SIF2_LOCK_DETAIL_BOXES (1 << 19) // zookeeper - don't scale detail boxes or spheres based on detail settings
|
||||
|
||||
#define SIF_DEFAULT_VALUE 0
|
||||
#define SIF2_DEFAULT_VALUE 0
|
||||
@@ -1144,6 +1148,8 @@ typedef struct ship_collision_physics {
|
||||
|
||||
typedef struct path_metadata {
|
||||
vec3d departure_rvec;
|
||||
float arrive_speed_mult;
|
||||
float depart_speed_mult;
|
||||
} path_metadata;
|
||||
|
||||
// The real FreeSpace ship_info struct.
|
||||
@@ -1175,6 +1181,7 @@ public:
|
||||
char pof_file_hud[MAX_FILENAME_LEN]; // POF file to load for the HUD target box
|
||||
int num_detail_levels; // number of detail levels for this ship
|
||||
int detail_distance[MAX_SHIP_DETAIL_LEVELS]; // distance to change detail levels at
|
||||
int collision_lod; // check for collisions using a LOD
|
||||
int cockpit_model_num; // cockpit model
|
||||
int model_num; // ship model
|
||||
int model_num_hud; // model to use when rendering to the HUD (eg, mini supercap)
|
||||
@@ -1293,14 +1300,20 @@ public:
|
||||
bool draw_secondary_models[MAX_SHIP_SECONDARY_BANKS];
|
||||
float weapon_model_draw_distance;
|
||||
|
||||
// Recoil modifier for the ship
|
||||
float ship_recoil_modifier;
|
||||
|
||||
float max_hull_strength; // Max hull strength of this class of ship.
|
||||
float max_shield_strength;
|
||||
float auto_shield_spread;
|
||||
bool auto_shield_spread_bypass;
|
||||
int auto_shield_spread_from_lod;
|
||||
float auto_shield_spread; // Thickness of the shield
|
||||
bool auto_shield_spread_bypass; // Whether weapons fired up close can bypass shields
|
||||
int auto_shield_spread_from_lod; // Which LOD to project the shield from
|
||||
float auto_shield_spread_min_span; // Minimum distance weapons must travel until allowed to collide with the shield
|
||||
|
||||
int shield_point_augment_ctrls[4]; // Re-mapping of shield augmentation controls for model point shields
|
||||
|
||||
float max_shield_recharge;
|
||||
|
||||
float hull_repair_rate; //How much of the hull is repaired every second
|
||||
float subsys_repair_rate; //How fast
|
||||
|
||||
@@ -1320,6 +1333,7 @@ public:
|
||||
|
||||
ubyte shield_icon_index; // index to locate ship-specific animation frames for the shield on HUD
|
||||
char icon_filename[MAX_FILENAME_LEN]; // filename for icon that is displayed in ship selection
|
||||
angles model_icon_angles; // angle from which the model icon should be rendered (if not 0,0,0)
|
||||
char anim_filename[MAX_FILENAME_LEN]; // filename for animation that plays in ship selection
|
||||
char overhead_filename[MAX_FILENAME_LEN]; // filename for animation that plays weapons loadout
|
||||
int selection_effect;
|
||||
@@ -1372,6 +1386,7 @@ public:
|
||||
float thruster02_glow_len_factor;
|
||||
float thruster_dist_rad_factor;
|
||||
float thruster_dist_len_factor;
|
||||
float thruster_glow_noise_mult;
|
||||
|
||||
bool draw_distortion;
|
||||
|
||||
@@ -1398,6 +1413,7 @@ public:
|
||||
vec3d topdown_offset;
|
||||
|
||||
int engine_snd; // handle to engine sound for ship (-1 if no engine sound)
|
||||
float min_engine_vol; // minimum volume modifier for engine sound when ship is stationary
|
||||
int glide_start_snd; // handle to sound to play at the beginning of a glide maneuver (default is 0 for regular throttle down sound)
|
||||
int glide_end_snd; // handle to sound to play at the end of a glide maneuver (default is 0 for regular throttle up sound)
|
||||
|
||||
@@ -1417,10 +1433,12 @@ public:
|
||||
float minimum_convergence_distance;
|
||||
float convergence_distance;
|
||||
vec3d convergence_offset;
|
||||
int autoaim_lock_snd, autoaim_lost_snd;
|
||||
|
||||
float emp_resistance_mod;
|
||||
|
||||
float piercing_damage_draw_limit;
|
||||
int shield_impact_explosion_anim;
|
||||
|
||||
int damage_lightning_type;
|
||||
|
||||
@@ -1591,6 +1609,7 @@ extern void ship_cleanup(int shipnum, int cleanup_mode);
|
||||
extern void ship_destroy_instantly(object *ship_obj, int shipnum);
|
||||
extern void ship_actually_depart(int shipnum, int method = SHIP_DEPARTED_WARP);
|
||||
|
||||
extern bool in_autoaim_fov(ship *shipp, int bank_to_fire, object *obj);
|
||||
extern int ship_fire_primary_debug(object *objp); // Fire the debug laser.
|
||||
extern int ship_stop_fire_primary(object * obj);
|
||||
extern int ship_fire_primary(object * objp, int stream_weapons, int force = 0);
|
||||
|
||||
+84
-84
@@ -78,7 +78,7 @@ void shipfx_remove_submodel_ship_sparks(ship *shipp, int submodel_num)
|
||||
*
|
||||
* DKA: 5/26/99 make velocity of debris scale according to size of debris subobject (at least for large subobjects)
|
||||
*/
|
||||
void shipfx_subsystem_maybe_create_live_debris(object *ship_obj, ship *ship_p, ship_subsys *subsys, vec3d *exp_center, float exp_mag)
|
||||
void shipfx_subsystem_maybe_create_live_debris(object *ship_objp, ship *ship_p, ship_subsys *subsys, vec3d *exp_center, float exp_mag)
|
||||
{
|
||||
// initializations
|
||||
polymodel *pm = model_get(Ship_info[ship_p->ship_info_index].model_num);
|
||||
@@ -94,7 +94,7 @@ void shipfx_subsystem_maybe_create_live_debris(object *ship_obj, ship *ship_p, s
|
||||
return;
|
||||
}
|
||||
|
||||
ship_model_start(ship_obj);
|
||||
ship_model_start(ship_objp);
|
||||
|
||||
// copy angles
|
||||
angles copy_angs = pm->submodel[submodel_num].angs;
|
||||
@@ -111,10 +111,10 @@ void shipfx_subsystem_maybe_create_live_debris(object *ship_obj, ship *ship_p, s
|
||||
|
||||
// get the rotvel
|
||||
void model_get_rotating_submodel_axis(vec3d *model_axis, vec3d *world_axis, int modelnum, int submodel_num, object *obj);
|
||||
model_get_rotating_submodel_axis(&model_axis, &world_axis, pm->id, submodel_num, ship_obj);
|
||||
model_get_rotating_submodel_axis(&model_axis, &world_axis, pm->id, submodel_num, ship_objp);
|
||||
vm_vec_copy_scale(&rotvel, &world_axis, sii->cur_turn_rate);
|
||||
|
||||
model_find_world_point(&world_axis_pt, &sii->pt_on_axis, pm->id, submodel_num, &ship_obj->orient, &ship_obj->pos);
|
||||
model_find_world_point(&world_axis_pt, &sii->pt_on_axis, pm->id, submodel_num, &ship_objp->orient, &ship_objp->pos);
|
||||
|
||||
vm_quaternion_rotate(&m_rot, vm_vec_mag((vec3d*)&sii->angs), &model_axis);
|
||||
} else {
|
||||
@@ -131,27 +131,27 @@ void shipfx_subsystem_maybe_create_live_debris(object *ship_obj, ship *ship_p, s
|
||||
|
||||
// get start world pos
|
||||
vm_vec_zero(&start_world_pos);
|
||||
model_find_world_point(&start_world_pos, &pm->submodel[live_debris_submodel].offset, pm->id, live_debris_submodel, &ship_obj->orient, &ship_obj->pos );
|
||||
model_find_world_point(&start_world_pos, &pm->submodel[live_debris_submodel].offset, pm->id, live_debris_submodel, &ship_objp->orient, &ship_objp->pos );
|
||||
|
||||
// convert to model coord of underlying submodel
|
||||
// set angle to zero
|
||||
pm->submodel[submodel_num].angs = zero_angs;
|
||||
world_find_model_point(&start_model_pos, &start_world_pos, pm, submodel_num, &ship_obj->orient, &ship_obj->pos);
|
||||
world_find_model_point(&start_model_pos, &start_world_pos, pm, submodel_num, &ship_objp->orient, &ship_objp->pos);
|
||||
|
||||
// rotate from submodel coord to world coords
|
||||
// reset angle to current angle
|
||||
pm->submodel[submodel_num].angs = copy_angs;
|
||||
model_find_world_point(&end_world_pos, &start_model_pos, pm->id, submodel_num, &ship_obj->orient, &ship_obj->pos);
|
||||
model_find_world_point(&end_world_pos, &start_model_pos, pm->id, submodel_num, &ship_objp->orient, &ship_objp->pos);
|
||||
|
||||
int fireball_type = fireball_ship_explosion_type(&Ship_info[ship_p->ship_info_index]);
|
||||
if(fireball_type < 0) {
|
||||
fireball_type = FIREBALL_EXPLOSION_MEDIUM;
|
||||
}
|
||||
// create fireball here.
|
||||
fireball_create(&end_world_pos, fireball_type, FIREBALL_MEDIUM_EXPLOSION, OBJ_INDEX(ship_obj), pm->submodel[live_debris_submodel].rad);
|
||||
fireball_create(&end_world_pos, fireball_type, FIREBALL_MEDIUM_EXPLOSION, OBJ_INDEX(ship_objp), pm->submodel[live_debris_submodel].rad);
|
||||
|
||||
// create debris
|
||||
live_debris_obj = debris_create(ship_obj, pm->id, live_debris_submodel, &end_world_pos, exp_center, 1, exp_mag);
|
||||
live_debris_obj = debris_create(ship_objp, pm->id, live_debris_submodel, &end_world_pos, exp_center, 1, exp_mag);
|
||||
|
||||
// only do if debris is created
|
||||
if (live_debris_obj) {
|
||||
@@ -177,7 +177,7 @@ void shipfx_subsystem_maybe_create_live_debris(object *ship_obj, ship *ship_p, s
|
||||
|
||||
// Add radial velocity (at least as large as exp velocity)
|
||||
vec3d temp_vel; // explosion velocity with ship_obj velocity removed
|
||||
vm_vec_sub(&temp_vel, &live_debris_obj->phys_info.vel, &ship_obj->phys_info.vel);
|
||||
vm_vec_sub(&temp_vel, &live_debris_obj->phys_info.vel, &ship_objp->phys_info.vel);
|
||||
|
||||
// find magnitudes of radial and temp velocity
|
||||
float vel_mag = vm_vec_mag(&temp_vel);
|
||||
@@ -202,8 +202,8 @@ void shipfx_subsystem_maybe_create_live_debris(object *ship_obj, ship *ship_p, s
|
||||
}
|
||||
|
||||
// scale up speed of debris if ship_obj > 125, but not for knossos
|
||||
if (ship_obj->radius > 250 && !(Ship_info[ship_p->ship_info_index].flags & SIF_KNOSSOS_DEVICE)) {
|
||||
vm_vec_scale(&live_debris_obj->phys_info.vel, ship_obj->radius/250.0f);
|
||||
if (ship_objp->radius > 250 && !(Ship_info[ship_p->ship_info_index].flags & SIF_KNOSSOS_DEVICE)) {
|
||||
vm_vec_scale(&live_debris_obj->phys_info.vel, ship_objp->radius/250.0f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,7 +211,7 @@ void shipfx_subsystem_maybe_create_live_debris(object *ship_obj, ship *ship_p, s
|
||||
}
|
||||
}
|
||||
|
||||
ship_model_stop(ship_obj);
|
||||
ship_model_stop(ship_objp);
|
||||
}
|
||||
|
||||
void set_ship_submodel_as_blown_off(ship *shipp, char *name)
|
||||
@@ -239,12 +239,12 @@ void set_ship_submodel_as_blown_off(ship *shipp, char *name)
|
||||
* 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)
|
||||
*/
|
||||
void shipfx_maybe_create_live_debris_at_ship_death( object *ship_obj )
|
||||
void shipfx_maybe_create_live_debris_at_ship_death( object *ship_objp )
|
||||
{
|
||||
// if ship has live debris, detonate that subsystem now
|
||||
// search for any live debris
|
||||
|
||||
ship *shipp = &Ships[ship_obj->instance];
|
||||
ship *shipp = &Ships[ship_objp->instance];
|
||||
polymodel *pm = model_get(Ship_info[shipp->ship_info_index].model_num);
|
||||
|
||||
// no subsystems -> no live debris.
|
||||
@@ -263,7 +263,7 @@ void shipfx_maybe_create_live_debris_at_ship_death( object *ship_obj )
|
||||
Assert(parent != -1);
|
||||
|
||||
// set model values only once (esp blown off)
|
||||
ship_model_start(ship_obj);
|
||||
ship_model_start(ship_objp);
|
||||
|
||||
// check if already blown off (ship model set)
|
||||
if ( !pm->submodel[parent].blown_off ) {
|
||||
@@ -281,14 +281,14 @@ void shipfx_maybe_create_live_debris_at_ship_death( object *ship_obj )
|
||||
if (pss != NULL) {
|
||||
if (pss->system_info != NULL) {
|
||||
vec3d exp_center, tmp = ZERO_VECTOR;
|
||||
model_find_world_point(&exp_center, &tmp, pm->id, parent, &ship_obj->orient, &ship_obj->pos );
|
||||
model_find_world_point(&exp_center, &tmp, pm->id, parent, &ship_objp->orient, &ship_objp->pos );
|
||||
|
||||
// if not blown off, blow it off
|
||||
shipfx_subsystem_maybe_create_live_debris(ship_obj, shipp, pss, &exp_center, 3.0f);
|
||||
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_obj->instance], pss->system_info->subobj_name);
|
||||
set_ship_submodel_as_blown_off(&Ships[ship_objp->instance], pss->system_info->subobj_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -296,36 +296,36 @@ void shipfx_maybe_create_live_debris_at_ship_death( object *ship_obj )
|
||||
}
|
||||
|
||||
// clean up
|
||||
ship_model_stop(ship_obj);
|
||||
ship_model_stop(ship_objp);
|
||||
|
||||
}
|
||||
|
||||
void shipfx_blow_off_subsystem(object *ship_obj,ship *ship_p,ship_subsys *subsys, vec3d *exp_center, bool no_explosion)
|
||||
void shipfx_blow_off_subsystem(object *ship_objp, ship *ship_p,ship_subsys *subsys, vec3d *exp_center, bool no_explosion)
|
||||
{
|
||||
vec3d subobj_pos;
|
||||
int model_num = Ship_info[ship_p->ship_info_index].model_num;
|
||||
|
||||
model_subsystem *psub = subsys->system_info;
|
||||
|
||||
get_subsystem_world_pos(ship_obj, subsys, &subobj_pos);
|
||||
get_subsystem_world_pos(ship_objp, subsys, &subobj_pos);
|
||||
|
||||
// get rid of sparks on submodel that is destroyed
|
||||
shipfx_remove_submodel_ship_sparks(ship_p, psub->subobj_num);
|
||||
|
||||
// create debris shards
|
||||
if (!(subsys->flags & SSF_VANISHED) && !no_explosion) {
|
||||
shipfx_blow_up_model(ship_obj, model_num, psub->subobj_num, 50, &subobj_pos );
|
||||
shipfx_blow_up_model(ship_objp, model_num, psub->subobj_num, 50, &subobj_pos );
|
||||
|
||||
// create live debris objects, if any
|
||||
// TODO: some MULITPLAYER implcations here!!
|
||||
shipfx_subsystem_maybe_create_live_debris(ship_obj, ship_p, subsys, exp_center, 1.0f);
|
||||
shipfx_subsystem_maybe_create_live_debris(ship_objp, ship_p, subsys, exp_center, 1.0f);
|
||||
|
||||
int fireball_type = fireball_ship_explosion_type(&Ship_info[ship_p->ship_info_index]);
|
||||
if(fireball_type < 0) {
|
||||
fireball_type = FIREBALL_EXPLOSION_MEDIUM;
|
||||
}
|
||||
// create first fireball
|
||||
fireball_create( &subobj_pos, fireball_type, FIREBALL_MEDIUM_EXPLOSION, OBJ_INDEX(ship_obj), psub->radius );
|
||||
fireball_create( &subobj_pos, fireball_type, FIREBALL_MEDIUM_EXPLOSION, OBJ_INDEX(ship_objp), psub->radius );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1687,29 +1687,29 @@ static int get_split_ship()
|
||||
}
|
||||
|
||||
static void maybe_fireball_wipe(clip_ship* half_ship, int* sound_handle);
|
||||
static void split_ship_init( ship* shipp, split_ship* split_ship )
|
||||
static void split_ship_init( ship* shipp, split_ship* split_shipp )
|
||||
{
|
||||
object* parent_ship_obj = &Objects[shipp->objnum];
|
||||
matrix* orient = &parent_ship_obj->orient;
|
||||
for (int ii=0; ii<NUM_SUB_EXPL_HANDLES; ++ii) {
|
||||
split_ship->sound_handle[ii] = shipp->sub_expl_sound_handle[ii];
|
||||
split_shipp->sound_handle[ii] = shipp->sub_expl_sound_handle[ii];
|
||||
}
|
||||
|
||||
// play 3d sound for shockwave explosion
|
||||
snd_play_3d( &Snds[SND_SHOCKWAVE_EXPLODE], &parent_ship_obj->pos, &View_position, 0.0f, NULL, 0, 1.0f, SND_PRIORITY_SINGLE_INSTANCE, NULL, 3.0f );
|
||||
|
||||
// initialize both ships
|
||||
split_ship->front_ship.parent_obj = parent_ship_obj;
|
||||
split_ship->back_ship.parent_obj = parent_ship_obj;
|
||||
split_ship->explosion_flash_timestamp = timestamp((int)(0.00075f*parent_ship_obj->radius));
|
||||
split_ship->explosion_flash_started = 0;
|
||||
split_ship->front_ship.orient = *orient;
|
||||
split_ship->back_ship.orient = *orient;
|
||||
split_ship->front_ship.next_fireball = timestamp_rand(0, 100);
|
||||
split_ship->back_ship.next_fireball = timestamp_rand(0, 100);
|
||||
split_shipp->front_ship.parent_obj = parent_ship_obj;
|
||||
split_shipp->back_ship.parent_obj = parent_ship_obj;
|
||||
split_shipp->explosion_flash_timestamp = timestamp((int)(0.00075f*parent_ship_obj->radius));
|
||||
split_shipp->explosion_flash_started = 0;
|
||||
split_shipp->front_ship.orient = *orient;
|
||||
split_shipp->back_ship.orient = *orient;
|
||||
split_shipp->front_ship.next_fireball = timestamp_rand(0, 100);
|
||||
split_shipp->back_ship.next_fireball = timestamp_rand(0, 100);
|
||||
|
||||
split_ship->front_ship.clip_plane_norm = vmd_z_vector;
|
||||
vm_vec_copy_scale(&split_ship->back_ship.clip_plane_norm, &vmd_z_vector, -1.0f);
|
||||
split_shipp->front_ship.clip_plane_norm = vmd_z_vector;
|
||||
vm_vec_copy_scale(&split_shipp->back_ship.clip_plane_norm, &vmd_z_vector, -1.0f);
|
||||
|
||||
// find the point at which the ship splits (relative to its pivot)
|
||||
polymodel* pm = model_get(Ship_info[shipp->ship_info_index].model_num);
|
||||
@@ -1721,18 +1721,18 @@ static void split_ship_init( ship* shipp, split_ship* split_ship )
|
||||
init_clip_plane_dist = 0.5f * (0.5f - frand())*pm->core_radius;
|
||||
}
|
||||
|
||||
split_ship->back_ship.cur_clip_plane_pt = init_clip_plane_dist;
|
||||
split_ship->front_ship.cur_clip_plane_pt = init_clip_plane_dist;
|
||||
split_shipp->back_ship.cur_clip_plane_pt = init_clip_plane_dist;
|
||||
split_shipp->front_ship.cur_clip_plane_pt = init_clip_plane_dist;
|
||||
|
||||
float dist;
|
||||
dist = (split_ship->front_ship.cur_clip_plane_pt+pm->maxs.xyz.z)/2.0f;
|
||||
vm_vec_copy_scale(&split_ship->front_ship.local_pivot, &orient->vec.fvec, dist);
|
||||
vm_vec_make(&split_ship->front_ship.model_center_disp_to_orig_center, 0.0f, 0.0f, -dist);
|
||||
dist = (split_ship->back_ship.cur_clip_plane_pt +pm->mins.xyz.z)/2.0f;
|
||||
vm_vec_copy_scale(&split_ship->back_ship.local_pivot, &orient->vec.fvec, dist);
|
||||
vm_vec_make(&split_ship->back_ship.model_center_disp_to_orig_center, 0.0f, 0.0f, -dist);
|
||||
vm_vec_add2(&split_ship->front_ship.local_pivot, &parent_ship_obj->pos );
|
||||
vm_vec_add2(&split_ship->back_ship.local_pivot, &parent_ship_obj->pos );
|
||||
dist = (split_shipp->front_ship.cur_clip_plane_pt+pm->maxs.xyz.z)/2.0f;
|
||||
vm_vec_copy_scale(&split_shipp->front_ship.local_pivot, &orient->vec.fvec, dist);
|
||||
vm_vec_make(&split_shipp->front_ship.model_center_disp_to_orig_center, 0.0f, 0.0f, -dist);
|
||||
dist = (split_shipp->back_ship.cur_clip_plane_pt +pm->mins.xyz.z)/2.0f;
|
||||
vm_vec_copy_scale(&split_shipp->back_ship.local_pivot, &orient->vec.fvec, dist);
|
||||
vm_vec_make(&split_shipp->back_ship.model_center_disp_to_orig_center, 0.0f, 0.0f, -dist);
|
||||
vm_vec_add2(&split_shipp->front_ship.local_pivot, &parent_ship_obj->pos );
|
||||
vm_vec_add2(&split_shipp->back_ship.local_pivot, &parent_ship_obj->pos );
|
||||
|
||||
// find which debris pieces are in the front and back split ships
|
||||
for (int i=0; i<pm->num_debris_objects; i++ ) {
|
||||
@@ -1742,30 +1742,30 @@ static void split_ship_init( ship* shipp, split_ship* split_ship )
|
||||
// tmp is world position, temp_pos is world_pivot, tmp1 is offset from world_pivot (in ship local coord)
|
||||
model_find_world_point(&tmp, &tmp1, pm->id, -1, &vmd_identity_matrix, &temp_pos );
|
||||
if (tmp.xyz.z > init_clip_plane_dist) {
|
||||
split_ship->front_ship.draw_debris[i] = DEBRIS_DRAW;
|
||||
split_ship->back_ship.draw_debris[i] = DEBRIS_NONE;
|
||||
split_shipp->front_ship.draw_debris[i] = DEBRIS_DRAW;
|
||||
split_shipp->back_ship.draw_debris[i] = DEBRIS_NONE;
|
||||
} else {
|
||||
split_ship->front_ship.draw_debris[i] = DEBRIS_NONE;
|
||||
split_ship->back_ship.draw_debris[i] = DEBRIS_DRAW;
|
||||
split_shipp->front_ship.draw_debris[i] = DEBRIS_NONE;
|
||||
split_shipp->back_ship.draw_debris[i] = DEBRIS_DRAW;
|
||||
}
|
||||
}
|
||||
|
||||
// set up physics
|
||||
physics_init( &split_ship->front_ship.phys_info );
|
||||
physics_init( &split_ship->back_ship.phys_info );
|
||||
split_ship->front_ship.phys_info.flags |= (PF_ACCELERATES | PF_DEAD_DAMP);
|
||||
split_ship->back_ship.phys_info.flags |= (PF_ACCELERATES | PF_DEAD_DAMP);
|
||||
split_ship->front_ship.phys_info.side_slip_time_const = 10000.0f;
|
||||
split_ship->back_ship.phys_info.side_slip_time_const = 10000.0f;
|
||||
split_ship->front_ship.phys_info.rotdamp = 10000.0f;
|
||||
split_ship->back_ship.phys_info.rotdamp = 10000.0f;
|
||||
physics_init( &split_shipp->front_ship.phys_info );
|
||||
physics_init( &split_shipp->back_ship.phys_info );
|
||||
split_shipp->front_ship.phys_info.flags |= (PF_ACCELERATES | PF_DEAD_DAMP);
|
||||
split_shipp->back_ship.phys_info.flags |= (PF_ACCELERATES | PF_DEAD_DAMP);
|
||||
split_shipp->front_ship.phys_info.side_slip_time_const = 10000.0f;
|
||||
split_shipp->back_ship.phys_info.side_slip_time_const = 10000.0f;
|
||||
split_shipp->front_ship.phys_info.rotdamp = 10000.0f;
|
||||
split_shipp->back_ship.phys_info.rotdamp = 10000.0f;
|
||||
|
||||
// set up explosion vel and relative velocities (assuming mass depends on length)
|
||||
float front_length = pm->maxs.xyz.z - split_ship->front_ship.cur_clip_plane_pt;
|
||||
float back_length = split_ship->back_ship.cur_clip_plane_pt - pm->mins.xyz.z;
|
||||
float front_length = pm->maxs.xyz.z - split_shipp->front_ship.cur_clip_plane_pt;
|
||||
float back_length = split_shipp->back_ship.cur_clip_plane_pt - pm->mins.xyz.z;
|
||||
float ship_length = front_length + back_length;
|
||||
split_ship->front_ship.length_left = front_length;
|
||||
split_ship->back_ship.length_left = back_length;
|
||||
split_shipp->front_ship.length_left = front_length;
|
||||
split_shipp->back_ship.length_left = back_length;
|
||||
|
||||
float expl_length_scale = (ship_length - 200.0f) / 2000.0f;
|
||||
// s_r_f effects speed of "wipe" and rotvel
|
||||
@@ -1773,8 +1773,8 @@ static void split_ship_init( ship* shipp, split_ship* split_ship )
|
||||
float explosion_time = (3.0f + expl_length_scale + (frand()-0.5f)) * speed_reduction_factor;
|
||||
float long_length = MAX(front_length, back_length);
|
||||
float expl_vel = long_length / explosion_time;
|
||||
split_ship->front_ship.explosion_vel = expl_vel;
|
||||
split_ship->back_ship.explosion_vel = -expl_vel;
|
||||
split_shipp->front_ship.explosion_vel = expl_vel;
|
||||
split_shipp->back_ship.explosion_vel = -expl_vel;
|
||||
|
||||
float rel_vel = (0.6f + 0.2f*frand()) * expl_vel * speed_reduction_factor;
|
||||
float front_vel = rel_vel * back_length / ship_length;
|
||||
@@ -1786,26 +1786,26 @@ static void split_ship_init( ship* shipp, split_ship* split_ship )
|
||||
rotvel.xyz.z = 0.0f;
|
||||
vm_vec_normalize(&rotvel);
|
||||
vm_vec_scale(&rotvel, 0.15f / speed_reduction_factor);
|
||||
split_ship->front_ship.phys_info.rotvel = rotvel;
|
||||
vm_vec_copy_scale(&split_ship->back_ship.phys_info.rotvel, &rotvel, -(front_length*front_length)/(back_length*back_length));
|
||||
split_ship->front_ship.phys_info.rotvel.xyz.z = parent_ship_obj->phys_info.rotvel.xyz.z;
|
||||
split_ship->back_ship.phys_info.rotvel.xyz.z = parent_ship_obj->phys_info.rotvel.xyz.z;
|
||||
split_shipp->front_ship.phys_info.rotvel = rotvel;
|
||||
vm_vec_copy_scale(&split_shipp->back_ship.phys_info.rotvel, &rotvel, -(front_length*front_length)/(back_length*back_length));
|
||||
split_shipp->front_ship.phys_info.rotvel.xyz.z = parent_ship_obj->phys_info.rotvel.xyz.z;
|
||||
split_shipp->back_ship.phys_info.rotvel.xyz.z = parent_ship_obj->phys_info.rotvel.xyz.z;
|
||||
|
||||
|
||||
// modify vel of each split ship based on rotvel of parent ship obj
|
||||
vec3d temp_rotvel = parent_ship_obj->phys_info.rotvel;
|
||||
temp_rotvel.xyz.z = 0.0f;
|
||||
vec3d vel_from_rotvel;
|
||||
vm_vec_crossprod(&vel_from_rotvel, &temp_rotvel, &split_ship->front_ship.local_pivot);
|
||||
vm_vec_crossprod(&vel_from_rotvel, &temp_rotvel, &split_ship->back_ship.local_pivot);
|
||||
vm_vec_crossprod(&vel_from_rotvel, &temp_rotvel, &split_shipp->front_ship.local_pivot);
|
||||
vm_vec_crossprod(&vel_from_rotvel, &temp_rotvel, &split_shipp->back_ship.local_pivot);
|
||||
|
||||
// set up velocity and make initial fireballs and particles
|
||||
split_ship->front_ship.phys_info.vel = parent_ship_obj->phys_info.vel;
|
||||
split_ship->back_ship.phys_info.vel = parent_ship_obj->phys_info.vel;
|
||||
maybe_fireball_wipe(&split_ship->front_ship, (int*)&split_ship->sound_handle);
|
||||
maybe_fireball_wipe(&split_ship->back_ship, (int*)&split_ship->sound_handle);
|
||||
vm_vec_scale_add2(&split_ship->front_ship.phys_info.vel, &orient->vec.fvec, front_vel);
|
||||
vm_vec_scale_add2(&split_ship->back_ship.phys_info.vel, &orient->vec.fvec, back_vel);
|
||||
split_shipp->front_ship.phys_info.vel = parent_ship_obj->phys_info.vel;
|
||||
split_shipp->back_ship.phys_info.vel = parent_ship_obj->phys_info.vel;
|
||||
maybe_fireball_wipe(&split_shipp->front_ship, (int*)&split_shipp->sound_handle);
|
||||
maybe_fireball_wipe(&split_shipp->back_ship, (int*)&split_shipp->sound_handle);
|
||||
vm_vec_scale_add2(&split_shipp->front_ship.phys_info.vel, &orient->vec.fvec, front_vel);
|
||||
vm_vec_scale_add2(&split_shipp->back_ship.phys_info.vel, &orient->vec.fvec, back_vel);
|
||||
|
||||
// HANDLE LIVE DEBRIS - blow off if not already gone
|
||||
shipfx_maybe_create_live_debris_at_ship_death( parent_ship_obj );
|
||||
@@ -1930,7 +1930,7 @@ void shipfx_debris_limit_speed(debris *db, ship *shipp)
|
||||
if(db == NULL || shipp == NULL)
|
||||
return;
|
||||
|
||||
object *ship_obj = &Objects[shipp->objnum];
|
||||
object *ship_objp = &Objects[shipp->objnum];
|
||||
physics_info *pi = &Objects[db->objnum].phys_info;
|
||||
ship_info *sip = &Ship_info[shipp->ship_info_index];
|
||||
|
||||
@@ -1945,7 +1945,7 @@ void shipfx_debris_limit_speed(debris *db, ship *shipp)
|
||||
}
|
||||
else
|
||||
{
|
||||
vm_vec_copy_scale(&pi->vel, &ship_obj->orient.vec.fvec, debris_speed);
|
||||
vm_vec_copy_scale(&pi->vel, &ship_objp->orient.vec.fvec, debris_speed);
|
||||
}
|
||||
}
|
||||
else if(sip->debris_min_speed >= 0.0f)
|
||||
@@ -1959,7 +1959,7 @@ void shipfx_debris_limit_speed(debris *db, ship *shipp)
|
||||
}
|
||||
else
|
||||
{
|
||||
vm_vec_copy_scale(&pi->vel, &ship_obj->orient.vec.fvec, sip->debris_min_speed);
|
||||
vm_vec_copy_scale(&pi->vel, &ship_objp->orient.vec.fvec, sip->debris_min_speed);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1974,7 +1974,7 @@ void shipfx_debris_limit_speed(debris *db, ship *shipp)
|
||||
}
|
||||
else
|
||||
{
|
||||
vm_vec_copy_scale(&pi->vel, &ship_obj->orient.vec.fvec, sip->debris_max_speed);
|
||||
vm_vec_copy_scale(&pi->vel, &ship_objp->orient.vec.fvec, sip->debris_max_speed);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1991,7 +1991,7 @@ void shipfx_debris_limit_speed(debris *db, ship *shipp)
|
||||
}
|
||||
else
|
||||
{
|
||||
vm_vec_copy_scale(&pi->rotvel, &ship_obj->orient.vec.uvec, debris_rotspeed);
|
||||
vm_vec_copy_scale(&pi->rotvel, &ship_objp->orient.vec.uvec, debris_rotspeed);
|
||||
}
|
||||
}
|
||||
else if(sip->debris_min_rotspeed >= 0.0f)
|
||||
@@ -2005,7 +2005,7 @@ void shipfx_debris_limit_speed(debris *db, ship *shipp)
|
||||
}
|
||||
else
|
||||
{
|
||||
vm_vec_copy_scale(&pi->rotvel, &ship_obj->orient.vec.uvec, sip->debris_min_rotspeed);
|
||||
vm_vec_copy_scale(&pi->rotvel, &ship_objp->orient.vec.uvec, sip->debris_min_rotspeed);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2021,7 +2021,7 @@ void shipfx_debris_limit_speed(debris *db, ship *shipp)
|
||||
}
|
||||
else
|
||||
{
|
||||
vm_vec_copy_scale(&pi->rotvel, &ship_obj->orient.vec.uvec, sip->debris_max_rotspeed);
|
||||
vm_vec_copy_scale(&pi->rotvel, &ship_objp->orient.vec.uvec, sip->debris_max_rotspeed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,10 @@ ubyte *Compressed_service_buffer = NULL; // Used to read in compressed data duri
|
||||
|
||||
#define AS_HIGHEST_MAX 999999999 // max uncompressed filesize supported is 999 meg
|
||||
|
||||
// Globalize the list of audio extensions for use in several sound related files
|
||||
const char *audio_ext_list[] = { ".ogg", ".wav" };
|
||||
const int NUM_AUDIO_EXT = sizeof(audio_ext_list) / sizeof(char*);
|
||||
|
||||
|
||||
int Audiostream_inited = 0;
|
||||
|
||||
@@ -436,8 +440,6 @@ bool WaveFile::Open(char *pszFilename, bool keep_ext)
|
||||
int FileSize, FileOffset;
|
||||
char fullpath[MAX_PATH];
|
||||
char filename[MAX_FILENAME_LEN];
|
||||
const int NUM_EXT = 2;
|
||||
const char *audio_ext[NUM_EXT] = { ".ogg", ".wav" };
|
||||
|
||||
m_total_uncompressed_bytes_read = 0;
|
||||
m_max_uncompressed_bytes_to_read = AS_HIGHEST_MAX;
|
||||
@@ -448,8 +450,8 @@ bool WaveFile::Open(char *pszFilename, bool keep_ext)
|
||||
|
||||
// if we are supposed to load the file as passed...
|
||||
if (keep_ext) {
|
||||
for (int i = 0; i < NUM_EXT; i++) {
|
||||
if ( stristr(pszFilename, audio_ext[i]) ) {
|
||||
for (int i = 0; i < NUM_AUDIO_EXT; i++) {
|
||||
if ( stristr(pszFilename, audio_ext_list[i]) ) {
|
||||
rc = i;
|
||||
break;
|
||||
}
|
||||
@@ -463,14 +465,14 @@ bool WaveFile::Open(char *pszFilename, bool keep_ext)
|
||||
}
|
||||
// ... otherwise we just find the best match
|
||||
else {
|
||||
rc = cf_find_file_location_ext(filename, NUM_EXT, audio_ext, CF_TYPE_ANY, sizeof(fullpath) - 1, fullpath, &FileSize, &FileOffset);
|
||||
rc = cf_find_file_location_ext(filename, NUM_AUDIO_EXT, audio_ext_list, CF_TYPE_ANY, sizeof(fullpath) - 1, fullpath, &FileSize, &FileOffset);
|
||||
}
|
||||
|
||||
if (rc < 0) {
|
||||
goto OPEN_ERROR;
|
||||
} else {
|
||||
// set proper filename for later use (assumes that it doesn't already have an extension)
|
||||
strcat_s( filename, audio_ext[rc] );
|
||||
strcat_s( filename, audio_ext_list[rc] );
|
||||
}
|
||||
|
||||
m_snd_info.cfp = mmioOpen( fullpath, NULL, MMIO_ALLOCBUF | MMIO_READ );
|
||||
|
||||
@@ -46,6 +46,9 @@ typedef struct {
|
||||
} STRHDL;
|
||||
#endif // NEED_STRHDL
|
||||
|
||||
extern const char *audio_ext_list[];
|
||||
extern const int NUM_AUDIO_EXT;
|
||||
|
||||
// Initializes the audio streaming library. Called
|
||||
// automatically when the sound stuff is inited.
|
||||
void audiostream_init();
|
||||
|
||||
Loaded 100 of 167 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user