Compare commits

..
Author SHA1 Message Date
SirKnightly cad971f7b2 Automated build commit 2022-07-02 05:32:04 +00:00
52 changed files with 337 additions and 780 deletions

No files matched your search

+132 -180
View File
@@ -2400,7 +2400,6 @@ void ai_attack_object(object* attacker, object* attacked, int ship_info_index)
Assert(attacker != nullptr);
Assert(attacker->instance >= 0);
Assert(attacker->type == OBJ_SHIP);
Assert(Ships[attacker->instance].ai_index != -1);
// Bogus! Who tried to get me to attack myself!
if (attacker == attacked) {
@@ -10016,25 +10015,11 @@ void guard_object_was_hit(object *guard_objp, object *hitter_objp)
aip->submode_start_time = Missiontime;
aip->active_goal = AI_ACTIVE_GOAL_DYNAMIC;
} else {
// This section used to be a lot simpler, but some "invalid" object types were probably getting into num_ships_attacking
// below, so we have to manually return for some object types and make sure to assert for other object types
// that are symptomatic of a larger problem with the engine.
// This just checks to see that the target was a valid type. If it is not one of these, something really
// could be drastically wrong in the engine.
Assertion(Objects[aip->target_objnum].type == OBJ_SHIP || Objects[aip->target_objnum].type == OBJ_WEAPON || Objects[aip->target_objnum].type == OBJ_DEBRIS || Objects[aip->target_objnum].type == OBJ_ASTEROID || Objects[aip->target_objnum].type == OBJ_WAYPOINT,
"This function just discovered that %s has an invalid target object type of %d. This is bad. Please report!",
Ships[aip->shipnum].ship_name, Objects[aip->target_objnum].type);
if (!(Objects[aip->target_objnum].type == OBJ_SHIP || Objects[aip->target_objnum].type == OBJ_WEAPON || Objects[aip->target_objnum].type == OBJ_ASTEROID || Objects[aip->target_objnum].type == OBJ_DEBRIS)){
// it's probably a valid target, but retail would not count those cases, so just return.
return;
}
int num_attacking_cur = num_ships_attacking(aip->target_objnum);
int num_attacking_cur, num_attacking_new;
num_attacking_cur = num_ships_attacking(aip->target_objnum);
if (num_attacking_cur > 1) {
int num_attacking_new = num_ships_attacking(hitter_objnum);
num_attacking_new = num_ships_attacking(hitter_objnum);
if (num_attacking_new < num_attacking_cur) {
@@ -14505,13 +14490,6 @@ void validate_mode_submode(ai_info *aip)
*/
void ai_frame(int objnum)
{
// Cyborg - can you believe this was added in *2022*??
Assertion (Objects[objnum].type == OBJ_SHIP, "Ai_frame was called for a non-ship of type %d. Please report!", Objects[objnum].type);
if (Objects[objnum].type != OBJ_SHIP){
return;
}
ship *shipp = &Ships[Objects[objnum].instance];
ai_info *aip = &Ai_info[shipp->ai_index];
int target_objnum;
@@ -14594,7 +14572,7 @@ void ai_frame(int objnum)
} else if (aip->resume_goal_time == -1) {
// AL 12-9-97: Don't allow cargo and navbuoys to set their aip->target_objnum
if ( Ship_info[shipp->ship_info_index].class_type > -1 && (Ship_types[Ship_info[shipp->ship_info_index].class_type].flags[Ship::Type_Info_Flags::AI_auto_attacks]) ) {
target_objnum = find_enemy(objnum, MAX_ENEMY_DISTANCE, The_mission.ai_profile->max_attackers[Game_skill_level]); // Attack up to 2.5K units away.
target_objnum = find_enemy(objnum, MAX_ENEMY_DISTANCE, The_mission.ai_profile->max_attackers[Game_skill_level]); // Attack up to 25K units away.
if (target_objnum != -1) {
if (aip->target_objnum != target_objnum)
aip->aspect_locked_time = 0.0f;
@@ -14722,8 +14700,7 @@ void ai_frame(int objnum)
}
}
// set and removes any maneuver flags for ai maneuver overrides
static void ai_control_info_flags_upkeep(ai_info* aip, ship_info* sip, physics_info* pi)
static void ai_control_info_check(ai_info *aip, ship_info *sip, physics_info *pi)
{
if (aip->ai_override_flags.none_set())
return;
@@ -14754,37 +14731,6 @@ static void ai_control_info_flags_upkeep(ai_info* aip, ship_info* sip, physics_i
}
else
{
if (aip->ai_override_flags[AI::Maneuver_Override_Flags::Dont_bank_when_turning] || sip->flags[Ship::Info_Flags::Dont_bank_when_turning])
AI_ci.control_flags |= CIF_DONT_BANK_WHEN_TURNING;
if (aip->ai_override_flags[AI::Maneuver_Override_Flags::Dont_clamp_max_velocity] || sip->flags[Ship::Info_Flags::Dont_clamp_max_velocity])
AI_ci.control_flags |= CIF_DONT_CLAMP_MAX_VELOCITY;
if (aip->ai_override_flags[AI::Maneuver_Override_Flags::Instantaneous_acceleration] || sip->flags[Ship::Info_Flags::Instantaneous_acceleration])
AI_ci.control_flags |= CIF_INSTANTANEOUS_ACCELERATION;
}
// set physics flag according to whether we are instantaneously accelerating
if (AI_ci.control_flags & CIF_INSTANTANEOUS_ACCELERATION)
pi->flags |= PF_MANEUVER_NO_DAMP;
else
pi->flags &= ~PF_MANEUVER_NO_DAMP;
}
// applies any rotational or lateral maneuver values to the AI's CI
static void ai_control_info_apply(ai_info *aip)
{
if (aip->ai_override_flags.none_set())
return;
bool lateral_maneuver = false;
bool rotational_maneuver = false;
if (aip->ai_override_flags[AI::Maneuver_Override_Flags::Lateral_never_expire] || !timestamp_elapsed(aip->ai_override_lat_timestamp))
lateral_maneuver = true;
if (aip->ai_override_flags[AI::Maneuver_Override_Flags::Rotational_never_expire] || timestamp_elapsed(aip->ai_override_rot_timestamp))
rotational_maneuver = true;
if (lateral_maneuver || rotational_maneuver) {
if (aip->ai_override_flags[AI::Maneuver_Override_Flags::Full_rot])
{
AI_ci.pitch = aip->ai_override_ci.pitch;
@@ -14794,11 +14740,17 @@ static void ai_control_info_apply(ai_info *aip)
else
{
if (aip->ai_override_flags[AI::Maneuver_Override_Flags::Pitch])
{
AI_ci.pitch = aip->ai_override_ci.pitch;
}
if (aip->ai_override_flags[AI::Maneuver_Override_Flags::Heading])
{
AI_ci.heading = aip->ai_override_ci.heading;
}
if (aip->ai_override_flags[AI::Maneuver_Override_Flags::Roll])
{
AI_ci.bank = aip->ai_override_ci.bank;
}
}
if (aip->ai_override_flags[AI::Maneuver_Override_Flags::Full_lat])
@@ -14810,13 +14762,32 @@ static void ai_control_info_apply(ai_info *aip)
else
{
if (aip->ai_override_flags[AI::Maneuver_Override_Flags::Up])
{
AI_ci.vertical = aip->ai_override_ci.vertical;
}
if (aip->ai_override_flags[AI::Maneuver_Override_Flags::Sideways])
{
AI_ci.sideways = aip->ai_override_ci.sideways;
}
if (aip->ai_override_flags[AI::Maneuver_Override_Flags::Forward])
{
AI_ci.forward = aip->ai_override_ci.forward;
}
}
if (aip->ai_override_flags[AI::Maneuver_Override_Flags::Dont_bank_when_turning] || sip->flags[Ship::Info_Flags::Dont_bank_when_turning])
AI_ci.control_flags |= CIF_DONT_BANK_WHEN_TURNING;
if (aip->ai_override_flags[AI::Maneuver_Override_Flags::Dont_clamp_max_velocity] || sip->flags[Ship::Info_Flags::Dont_clamp_max_velocity])
AI_ci.control_flags |= CIF_DONT_CLAMP_MAX_VELOCITY;
if (aip->ai_override_flags[AI::Maneuver_Override_Flags::Instantaneous_acceleration] || sip->flags[Ship::Info_Flags::Instantaneous_acceleration])
AI_ci.control_flags |= CIF_INSTANTANEOUS_ACCELERATION;
}
// set physics flag according to whether we are instantaneously accelerating
if (AI_ci.control_flags & CIF_INSTANTANEOUS_ACCELERATION)
pi->flags |= PF_NO_DAMP;
else
pi->flags &= ~PF_NO_DAMP;
}
int Last_ai_obj = -1;
@@ -14876,12 +14847,9 @@ void ai_process( object * obj, int ai_index, float frametime )
if (shipp->flags[Ship::Ship_Flags::Dying] && sip->flags[Ship::Info_Flags::Large_ship_deathroll])
rfc = false;
// regardless if we're acting on them, upkeep maneuver flags
ai_control_info_flags_upkeep(aip, sip, &obj->phys_info);
if (rfc) {
// Wanderer - sexp based override goes here - only if rfc is valid though
ai_control_info_apply(aip);
ai_control_info_check(aip, sip, &obj->phys_info);
physics_read_flying_controls( &obj->orient, &obj->phys_info, &AI_ci, frametime);
}
@@ -15141,9 +15109,9 @@ void init_aip_from_class_and_profile(ai_info *aip, ai_class *aicp, ai_profile_t
void ai_do_default_behavior(object *obj)
{
Assertion(obj != nullptr, "Ai_do_default_behavior() was given a bad information. Specifically obj is a nullptr. This is a coder error, please report!");
Assertion((obj->type == OBJ_SHIP) && (obj->instance > -1) && (obj->instance < MAX_SHIPS), "This function that requires an object to be a ship was passed an invalid ship. Please report\n\nObject type: %d\nInstance #: %d", obj->type, obj->instance);
Assertion(Ships[obj->instance].ai_index >= 0, "A ship has been found to have an invalid ai_index of %d. This should have been assigned and is coder mistake, please report!", Ships[obj->instance].ai_index);
Assert(obj != NULL);
Assert(obj->instance != -1);
Assert(Ships[obj->instance].ai_index != -1);
ai_info *aip = &Ai_info[Ships[obj->instance].ai_index];
ship_info* sip = &Ship_info[Ships[obj->instance].ship_info_index];
@@ -15241,125 +15209,118 @@ void maybe_process_friendly_hit(object *objp_hitter, object *objp_hit, object *o
return;
}
// Cyborg -- I had to switch around the logic here because it was potentially
// sending non-ships to obj_team, which would trigger an assert
if (objp_hitter == Player_obj){
if ((obj_team(objp_hitter) == obj_team(objp_hit)) && (objp_hitter == Player_obj)) {
// Cyborg - So check if this is a ship first. Probably true, but you never know, with FSO
// (especially in multi)
// AL 12-4-97: It is possible the Player is a OBJ_GHOST at this point. If so, bail out.
if ( objp_hitter->type != OBJ_SHIP ) {
return;
}
// And assert that obj_hit is a ship as well.
Assert(objp_hitter->type == OBJ_SHIP);
Assert(objp_hit->type == OBJ_SHIP);
Assert((objp_weapon->type == OBJ_WEAPON) || (objp_weapon->type == OBJ_BEAM)); //beam added for traitor detection - FUBAR
if (obj_team(objp_hitter) == obj_team(objp_hit)) {
ship *shipp_hitter = &Ships[objp_hitter->instance];
ship *shipp_hit = &Ships[objp_hit->instance];
Assert((objp_weapon->type == OBJ_WEAPON) || (objp_weapon->type == OBJ_BEAM)); //beam added for traitor detection - FUBAR
if (shipp_hitter->team != shipp_hit->team) {
return;
}
ship *shipp_hitter = &Ships[objp_hitter->instance];
ship *shipp_hit = &Ships[objp_hit->instance];
// get the player
player *pp = &Players[Player_num];
if (shipp_hitter->team != shipp_hit->team) {
return;
}
// get the player
player *pp = &Players[Player_num];
// wacky stuff here
if (pp->friendly_hits != 0) {
float time_since_last_hit = f2fl(Missiontime - pp->friendly_last_hit_time);
if ((time_since_last_hit >= 0.0f) && (time_since_last_hit < 10000.0f)) {
if (time_since_last_hit > 60.0f) {
pp->friendly_hits = 0;
pp->friendly_damage = 0.0f;
} else if (time_since_last_hit > 2.0f) {
pp->friendly_hits -= (int) time_since_last_hit/2;
pp->friendly_damage -= time_since_last_hit;
}
if (pp->friendly_damage < 0.0f) {
pp->friendly_damage = 0.0f;
}
if (pp->friendly_hits < 0) {
pp->friendly_hits = 0;
}
}
}
float damage; // Damage done by weapon. Gets scaled down based on size of ship.
if (objp_weapon->type == OBJ_BEAM) // added beam for traitor detection -FUBAR
damage = beam_get_ship_damage(&Beams[objp_weapon->instance], objp_hit);
else
damage = Weapon_info[Weapons[objp_weapon->instance].weapon_info_index].damage;
// wacky stuff here
ship_info *sip = &Ship_info[Ships[objp_hit->instance].ship_info_index];
if (shipp_hit->ship_max_hull_strength > 1000.0f) {
float factor = shipp_hit->ship_max_hull_strength / 1000.0f;
factor = MIN(100.0f, factor);
damage /= factor;
}
// Don't penalize much at all for hitting cargo
if (sip->class_type > -1) {
damage *= Ship_types[sip->class_type].ff_multiplier;
}
// Hit ship, but not targeting it, so it's not so heinous, maybe an accident.
if (Ai_info[shipp_hitter->ai_index].target_objnum != OBJ_INDEX(objp_hit)) {
damage /= 5.0f;
}
pp->friendly_last_hit_time = Missiontime;
pp->friendly_hits++;
// cap damage and number of hits done this frame
float accredited_damage = MIN(MAX_BURST_DAMAGE, pp->damage_this_burst + damage) - pp->damage_this_burst;
pp->friendly_damage += accredited_damage;
pp->damage_this_burst += accredited_damage;
// Done with adjustments to damage. Evaluate based on current friendly_damage
nprintf(("AI", "Friendly damage: %.1f, threshold: %.1f, inc damage: %.1f, max burst: %d\n", pp->friendly_damage, FRIENDLY_DAMAGE_THRESHOLD * (1.0f + (float) (NUM_SKILL_LEVELS + 1 - Game_skill_level)/3.0f), pp->damage_this_burst, MAX_BURST_DAMAGE ));
if (is_instructor(objp_hit)) {
// it's not nice to hit your instructor
if (pp->friendly_damage > FRIENDLY_DAMAGE_THRESHOLD) {
message_send_builtin_to_player( MESSAGE_INSTRUCTOR_ATTACK, NULL, MESSAGE_PRIORITY_HIGH, MESSAGE_TIME_IMMEDIATE, 0, 0, -1, -1);
pp->last_warning_message_time = Missiontime;
ship_set_subsystem_strength( Player_ship, SUBSYSTEM_WEAPONS, 0.0f);
training_fail();
// Instructor leaves.
mission_do_departure(objp_hit);
gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_START_FORCED ); // Force player to warp out.
} else if (Missiontime - pp->last_warning_message_time > F1_0*4) {
// warning every 4 sec
// use NULL as the message sender here since it is the Terran Command persona
message_send_builtin_to_player( MESSAGE_INSTRUCTOR_HIT, NULL, MESSAGE_PRIORITY_HIGH, MESSAGE_TIME_IMMEDIATE, 0, 0, -1, -1);
pp->last_warning_message_time = Missiontime;
// wacky stuff here
if (pp->friendly_hits != 0) {
float time_since_last_hit = f2fl(Missiontime - pp->friendly_last_hit_time);
if ((time_since_last_hit >= 0.0f) && (time_since_last_hit < 10000.0f)) {
if (time_since_last_hit > 60.0f) {
pp->friendly_hits = 0;
pp->friendly_damage = 0.0f;
} else if (time_since_last_hit > 2.0f) {
pp->friendly_hits -= (int) time_since_last_hit/2;
pp->friendly_damage -= time_since_last_hit;
}
// not nice to hit your friends
} else if (pp->friendly_damage > FRIENDLY_DAMAGE_THRESHOLD * (1.0f + (float) (NUM_SKILL_LEVELS + 1 - Game_skill_level)/3.0f)) {
process_friendly_hit_message( MESSAGE_HAMMER_SWINE, objp_hit );
mission_goal_fail_all();
ai_abort_rearm_request( Player_obj );
if (pp->friendly_damage < 0.0f) {
pp->friendly_damage = 0.0f;
}
Player_ship->team = Iff_traitor;
if (pp->friendly_hits < 0) {
pp->friendly_hits = 0;
}
}
}
} else if ((damage > frand()) && (Missiontime - pp->last_warning_message_time > F1_0*4) && (pp->friendly_damage > FRIENDLY_DAMAGE_THRESHOLD)) {
// no closer than 4 sec intervals
// Note: (damage > frand()) added on 12/9/97 by MK. Since damage is now scaled down for big ships, we could get too
// many warnings. Kind of tedious. frand() returns a value in 0..1, so this won't affect legit hits.
process_friendly_hit_message( MESSAGE_OOPS, objp_hit );
float damage; // Damage done by weapon. Gets scaled down based on size of ship.
if (objp_weapon->type == OBJ_BEAM) // added beam for traitor detection -FUBAR
damage = beam_get_ship_damage(&Beams[objp_weapon->instance], objp_hit);
else
damage = Weapon_info[Weapons[objp_weapon->instance].weapon_info_index].damage;
// wacky stuff here
ship_info *sip = &Ship_info[Ships[objp_hit->instance].ship_info_index];
if (shipp_hit->ship_max_hull_strength > 1000.0f) {
float factor = shipp_hit->ship_max_hull_strength / 1000.0f;
factor = MIN(100.0f, factor);
damage /= factor;
}
// Don't penalize much at all for hitting cargo
if (sip->class_type > -1) {
damage *= Ship_types[sip->class_type].ff_multiplier;
}
// Hit ship, but not targeting it, so it's not so heinous, maybe an accident.
if (Ai_info[shipp_hitter->ai_index].target_objnum != OBJ_INDEX(objp_hit)) {
damage /= 5.0f;
}
pp->friendly_last_hit_time = Missiontime;
pp->friendly_hits++;
// cap damage and number of hits done this frame
float accredited_damage = MIN(MAX_BURST_DAMAGE, pp->damage_this_burst + damage) - pp->damage_this_burst;
pp->friendly_damage += accredited_damage;
pp->damage_this_burst += accredited_damage;
// Done with adjustments to damage. Evaluate based on current friendly_damage
nprintf(("AI", "Friendly damage: %.1f, threshold: %.1f, inc damage: %.1f, max burst: %d\n", pp->friendly_damage, FRIENDLY_DAMAGE_THRESHOLD * (1.0f + (float) (NUM_SKILL_LEVELS + 1 - Game_skill_level)/3.0f), pp->damage_this_burst, MAX_BURST_DAMAGE ));
if (is_instructor(objp_hit)) {
// it's not nice to hit your instructor
if (pp->friendly_damage > FRIENDLY_DAMAGE_THRESHOLD) {
message_send_builtin_to_player( MESSAGE_INSTRUCTOR_ATTACK, NULL, MESSAGE_PRIORITY_HIGH, MESSAGE_TIME_IMMEDIATE, 0, 0, -1, -1);
pp->last_warning_message_time = Missiontime;
ship_set_subsystem_strength( Player_ship, SUBSYSTEM_WEAPONS, 0.0f);
training_fail();
// Instructor leaves.
mission_do_departure(objp_hit);
gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_START_FORCED ); // Force player to warp out.
} else if (Missiontime - pp->last_warning_message_time > F1_0*4) {
// warning every 4 sec
// use NULL as the message sender here since it is the Terran Command persona
message_send_builtin_to_player( MESSAGE_INSTRUCTOR_HIT, NULL, MESSAGE_PRIORITY_HIGH, MESSAGE_TIME_IMMEDIATE, 0, 0, -1, -1);
pp->last_warning_message_time = Missiontime;
}
// not nice to hit your friends
} else if (pp->friendly_damage > FRIENDLY_DAMAGE_THRESHOLD * (1.0f + (float) (NUM_SKILL_LEVELS + 1 - Game_skill_level)/3.0f)) {
process_friendly_hit_message( MESSAGE_HAMMER_SWINE, objp_hit );
mission_goal_fail_all();
ai_abort_rearm_request( Player_obj );
Player_ship->team = Iff_traitor;
} else if ((damage > frand()) && (Missiontime - pp->last_warning_message_time > F1_0*4) && (pp->friendly_damage > FRIENDLY_DAMAGE_THRESHOLD)) {
// no closer than 4 sec intervals
// Note: (damage > frand()) added on 12/9/97 by MK. Since damage is now scaled down for big ships, we could get too
// many warnings. Kind of tedious. frand() returns a value in 0..1, so this won't affect legit hits.
process_friendly_hit_message( MESSAGE_OOPS, objp_hit );
pp->last_warning_message_time = Missiontime;
}
}
}
@@ -15584,14 +15545,11 @@ void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hit_normal)
return;
hitter_objnum = hit_objp->parent;
Assertion((hitter_objnum >= 0) && (hitter_objnum < MAX_OBJECTS), "hitter_objnum in this function is an invalid index of %d. This can cause random behavior, and is a coder mistake. Please report!", hitter_objnum);
Assert((hitter_objnum >= 0) && (hitter_objnum < MAX_OBJECTS));
objp_hitter = &Objects[hitter_objnum];
Assertion((objp_hitter->type == OBJ_SHIP) || (objp_hitter->type == OBJ_WEAPON) || (objp_hitter->type == OBJ_ASTEROID) || (objp_hitter->type == OBJ_BEAM) || (objp_hitter->type == OBJ_DEBRIS),
"The ai code is passing an invalid object type of %d to a function when trying to decide how to respond to something hitting it. This is a bug in the code, please report!", objp_hitter->type);
// lets not check hits by ghosts any further either
if(objp_hitter->type != OBJ_SHIP && objp_hitter->type != OBJ_WEAPON && objp_hitter->type != OBJ_ASTEROID && objp_hitter->type != OBJ_BEAM && objp_hitter->type != OBJ_DEBRIS)
if(objp_hitter->type == OBJ_GHOST)
return;
// Hit by a protected ship, don't attack it.
@@ -16189,12 +16147,6 @@ void maybe_cheat_fire_synaptic(object *objp)
ship *shipp;
int wing_index, time;
Assertion(objp->type == OBJ_SHIP, "This ai function requires a ship, but was called with a non-ship object type of %d. Please report!", objp->type);
if (objp->type != OBJ_SHIP) {
return;
}
shipp = &Ships[objp->instance];
if (!(strnicmp(shipp->ship_name, NOX("delta"), 5)))
-1
View File
@@ -51,7 +51,6 @@ void processEvents()
{
io::mouse::CursorManager::get()->showCursor(false);
os_remove_deferred_cutscene_key_events();
os_poll();
}
+1 -12
View File
@@ -407,21 +407,10 @@ void fireball_parse_tbl()
{
if (fi.lod_count > 1)
{
Assertion(fi.lod_count <= MAX_FIREBALL_LOD, "Fireball LOD (%d) greater than MAX_FIREBALL_LOD %d.", fi.lod_count, MAX_FIREBALL_LOD);
static_assert(MAX_FIREBALL_LOD < 10, "The fireball LOD naming scheme needs to be changed for LODs > 9");
auto lod0 = fi.lod[0].filename;
constexpr int MAX_BASENAME_LEN = MAX_FILENAME_LEN - 3; // ensure base file name + _*lod* fits in filename field
if (strlen(lod0) > MAX_BASENAME_LEN)
{
Warning(LOCATION, "A fireball base file name may not be longer than %d characters due to the LOD naming scheme.\nLODs other than LOD0 will be skipped for fireball %s", MAX_BASENAME_LEN, lod0);
fi.lod_count = 1;
continue;
}
for (int j = 1; j < fi.lod_count; ++j)
sprintf(fi.lod[j].filename, "%.*s_%d", MAX_BASENAME_LEN, lod0, j % MAX_FIREBALL_LOD /*to show gcc12 format string is safe*/);
sprintf(fi.lod[j].filename, "%s_%d", lod0, j);
}
}
+1 -1
View File
@@ -1294,7 +1294,7 @@ void parse_soundtrack()
continue;
// check for file
if (!cf_exists_full_ext(Soundtracks[strack_idx].patterns[i].fname, CF_TYPE_MUSIC, NUM_AUDIO_EXT, audio_ext_list))
if (!cf_exists_full(Soundtracks[strack_idx].patterns[i].fname, CF_TYPE_MUSIC))
return;
}
+16 -16
View File
@@ -31,23 +31,23 @@
#define GM_CAMPAIGN_MODE (1 << 10) // are we currently in a campaign.
#define GM_LAB (1 << 11) // We are currently in the F3 lab
#define VM_EXTERNAL (1 << 0) // Set if not viewing from player position.
#define VM_TRACK (1 << 1) // Set if viewer is tracking target.
#define VM_DEAD_VIEW (1 << 2) // Set if viewer is watching from dead view.
#define VM_CHASE (1 << 3) // Chase view.
#define VM_OTHER_SHIP (1 << 4) // View from another ship.
#define VM_CAMERA_LOCKED (1 << 5) // Set if player does not have control of the camera
#define VM_WARP_CHASE (1 << 6) // View while warping out (form normal view mode)
#define VM_PADLOCK_UP (1 << 7) // Set when player is looking up
#define VM_PADLOCK_REAR (1 << 8) // Set when player is looking behind
#define VM_PADLOCK_LEFT (1 << 9) // Set when player is looking left
#define VM_PADLOCK_RIGHT (1 << 10) // Set when player is looking right
#define VM_WARPIN_ANCHOR (1 << 11) // special warpin camera mode
#define VM_TOPDOWN (1 << 12) // Camera is looking down on ship
#define VM_FREECAMERA (1 << 13) // Camera is not attached to any particular object, probably under SEXP control
#define VM_CENTERING (1 << 14) // View is springing to center
#define VM_EXTERNAL (1 << 0) // Set if not viewing from player position.
#define VM_TRACK (1 << 1) // Set if viewer is tracking target.
#define VM_DEAD_VIEW (1 << 2) // Set if viewer is watching from dead view.
#define VM_CHASE (1 << 3) // Chase view.
#define VM_OTHER_SHIP (1 << 4) // View from another ship.
#define VM_CAMERA_LOCKED (1 << 5) // Set if player does not have control of the camera
#define VM_WARP_CHASE (1 << 6) // View while warping out (form normal view mode)
#define VM_PADLOCK_UP (1 << 7)
#define VM_PADLOCK_REAR (1 << 8)
#define VM_PADLOCK_LEFT (1 << 9)
#define VM_PADLOCK_RIGHT (1 << 10)
#define VM_WARPIN_ANCHOR (1 << 11) // special warpin camera mode
#define VM_TOPDOWN (1 << 12) //Camera is looking down on ship
#define VM_FREECAMERA (1 << 13) //Camera is not attached to any particular object, probably under SEXP control
#define VM_CENTERING (1 << 14) // View is springing to center
#define VM_PADLOCK_ANY (VM_PADLOCK_UP | VM_PADLOCK_REAR | VM_PADLOCK_LEFT | VM_PADLOCK_RIGHT)
#define VM_PADLOCK_ANY (VM_PADLOCK_UP|VM_PADLOCK_REAR|VM_PADLOCK_LEFT|VM_PADLOCK_RIGHT)
//-----Cutscene stuff
//No bars
+1 -10
View File
@@ -309,21 +309,12 @@ ship_info *sip = &Ship_info[Player_ship->ship_info_index];
}
void HudGaugeReticle::getFirepointStatus() {
// allow the firepoint status to be empty when a multiplayer observer
// this is not a bug, the observer will simply *not* have any firepoints.
if (Objects[Player->objnum].type == OBJ_OBSERVER) {
// only multiplayer instances should be getting here!
Assertion((Game_mode & GM_MULTIPLAYER), "Somehow FSO thinks its player object is an observer even though it's not in Multiplayer. Please report!");
return;
}
//First, get the player ship
ship_info* sip;
ship* shipp;
polymodel* pm;
Assertion(Objects[Player->objnum].type == OBJ_SHIP, "HudGaugeReticle::getFirepointStatus was passed an invalid object type of %d. Please report!", Objects[Player->objnum].type);
Assert(Objects[Player->objnum].type == OBJ_SHIP);
if (Objects[Player->objnum].type == OBJ_SHIP) {
shipp = &Ships[Objects[Player->objnum].instance];
-2
View File
@@ -1530,8 +1530,6 @@ void hud_target_missile(object *source_obj, int next_flag)
continue;
}
Assertion(Objects[so->objnum].type == OBJ_SHIP, "hud_target_missile was about to call obj_team with a non-ship obejct with type %d. Please report!", Objects[so->objnum].type);
// only allow targeting of hostile bombs
if (!iff_x_attacks_y(Player_ship->team, obj_team(A))) {
continue;
+2 -2
View File
@@ -372,7 +372,7 @@ bool CFtpGet::IssuePasv()
return false;
}
if ( connect(m_DataSock, reinterpret_cast<LPSOCKADDR>(&dataaddr), psnet_get_sockaddr_len(&dataaddr)) == SOCKET_ERROR ) {
if ( connect(m_DataSock, reinterpret_cast<LPSOCKADDR>(&dataaddr), sizeof(dataaddr)) == SOCKET_ERROR ) {
return false;
}
@@ -392,7 +392,7 @@ int CFtpGet::ConnectControlSocket()
}
// Now we will connect to the host
if ( connect(m_ControlSock, reinterpret_cast<LPSOCKADDR>(&m_ServerAddr), psnet_get_sockaddr_len(&m_ServerAddr)) ) {
if ( connect(m_ControlSock, reinterpret_cast<LPSOCKADDR>(&m_ServerAddr), sizeof(m_ServerAddr)) ) {
m_State = FTP_STATE_CANT_CONNECT;
return 0;
}
+2 -2
View File
@@ -331,7 +331,7 @@ int ChttpGet::ConnectSocket()
timeout.tv_sec = 0;
timeout.tv_usec = 0;
int serr = connect(m_DataSock, reinterpret_cast<LPSOCKADDR>(&hostaddr), psnet_get_sockaddr_len(&hostaddr));
int serr = connect(m_DataSock, reinterpret_cast<LPSOCKADDR>(&hostaddr), sizeof(hostaddr));
int cerr = WSAGetLastError();
if (serr) {
// fail after 20 seconds
@@ -360,7 +360,7 @@ int ChttpGet::ConnectSocket()
if (m_Aborting)
return 0;
serr = connect(m_DataSock, reinterpret_cast<LPSOCKADDR>(&hostaddr), psnet_get_sockaddr_len(&hostaddr));
serr = connect(m_DataSock, reinterpret_cast<LPSOCKADDR>(&hostaddr), sizeof(hostaddr));
if (serr == 0)
break;
-5
View File
@@ -642,8 +642,3 @@ fix timestamp_get_mission_time()
return static_cast<fix>(time / MICROSECONDS_PER_SECOND);
}
uint64_t timestamp_get_mission_time_in_microseconds()
{
return timestamp_get_microseconds() - Timestamp_microseconds_at_mission_start;
}
-2
View File
@@ -106,7 +106,6 @@ extern int timer_get_seconds(); // seconds since program started... not accur
constexpr int MILLISECONDS_PER_SECOND = 1000;
constexpr uint64_t MICROSECONDS_PER_SECOND = 1000000;
constexpr uint64_t NANOSECONDS_PER_SECOND = 1000000000;
constexpr uint64_t NANOSECONDS_PER_MICROSECOND = 1000;
// use this call to get the current counter value (which represents the time at the time
// this function is called). I.e. it doesn't return a count that would be in the future,
@@ -226,6 +225,5 @@ void timestamp_start_mission();
// Calculate the current mission time using the timestamps
fix timestamp_get_mission_time();
uint64_t timestamp_get_mission_time_in_microseconds();
#endif
-1
View File
@@ -2070,7 +2070,6 @@ void vm_angular_move_forward_vec(const vec3d* goal_f, const matrix* orient, cons
// handle bank separately, simpler, since its just a target velocity
{
CLAMP(bank_vel, -vel_limit->xyz.z, vel_limit->xyz.z);
float delta_bank_vel = bank_vel - w_in->xyz.z;
float delta_bank_accel = fl_abs(delta_bank_vel) / delta_t; // the accel required to reach the target vel this frame
float accel = (delta_bank_accel > acc_limit->xyz.z) ? acc_limit->xyz.z : delta_bank_accel;
+1 -2
View File
@@ -34,7 +34,6 @@
#include "scripting/scripting.h"
#include "ship/ship.h"
#include "ship/subsysdamage.h"
#include "sound/audiostr.h"
#include "sound/fsspeech.h"
#include "species_defs/species_defs.h"
#include "utils/Random.h"
@@ -1736,7 +1735,7 @@ void message_queue_message( int message_num, int priority, int timing, const cha
if (message_filename_has_fs1_wingman_prefix(filename)) {
char converted[MAX_FILENAME_LEN];
message_filename_convert_to_command(converted, filename);
if (cf_exists_full_ext(converted, CF_TYPE_VOICE_SPECIAL, NUM_AUDIO_EXT, audio_ext_list)) {
if (cf_exists_full(converted, CF_TYPE_VOICE_SPECIAL)) {
convert_to_command = true;
}
}
+1 -7
View File
@@ -6247,7 +6247,6 @@ bool post_process_mission()
SCP_string location_str;
SCP_string sexp_str;
SCP_string error_msg;
SCP_string bad_node_str;
// it's helpful to point out the goal/event, so do that if we can
int index;
@@ -6259,13 +6258,8 @@ bool post_process_mission()
convert_sexp_to_string(sexp_str, i, SEXP_ERROR_CHECK_MODE);
truncate_message_lines(sexp_str, 30);
stuff_sexp_text_string(bad_node_str, bad_node, SEXP_ERROR_CHECK_MODE);
if (!bad_node_str.empty()) { // the previous function adds a space at the end
bad_node_str.pop_back();
}
sprintf(error_msg, "%s%s.\n\nIn sexpression: %s\n\n(Bad node appears to be: %s)\n", location_str.c_str(), sexp_error_message(result), sexp_str.c_str(), bad_node_str.c_str());
sprintf(error_msg, "%s%s.\n\nIn sexpression: %s\n\n(Bad node appears to be: %s)\n", location_str.c_str(), sexp_error_message(result), sexp_str.c_str(), Sexp_nodes[bad_node].text);
Warning(LOCATION, "%s", error_msg.c_str());
// syntax errors are recoverable in Fred but not FS
+1 -1
View File
@@ -926,7 +926,7 @@ void debrief_choose_voice(char *voice_dest, size_t buf_size, char *voice_base, i
if (snprintf(voice_dest, buf_size, NOX("%d_%s"), persona_index, voice_base) < static_cast<int>(buf_size))
{
// if it exists, we're done
if (cf_exists_full_ext(voice_dest, CF_TYPE_VOICE_DEBRIEFINGS, NUM_AUDIO_EXT, audio_ext_list))
if (cf_exists_full(voice_dest, CF_TYPE_VOICE_DEBRIEFINGS))
return;
}
+3 -15
View File
@@ -885,14 +885,8 @@ void red_alert_bash_wingman_status()
mprintf(("Invalid ship class specified in red alert data for ship %s. Using mission defaults.\n", shipp->ship_name));
}
float max_hull;
if (shipp->special_hitpoints)
max_hull = shipp->ship_max_hull_strength;
else
max_hull = Ship_info[shipp->ship_info_index].max_hull_strength;
// restore hull (but not shields)
if (ras->hull >= 0.0f && ras->hull <= max_hull)
if (ras->hull >= 0.0f && ras->hull <= ship_objp->hull_strength)
ship_objp->hull_strength = ras->hull;
else
mprintf(("Invalid health in red alert data for ship %s. Using mission defaults.\n", shipp->ship_name));
@@ -985,15 +979,9 @@ void red_alert_bash_wingman_status()
}
}
float max_hull;
if (pobjp->special_hitpoints)
max_hull = pobjp->ship_max_hull_strength;
else
max_hull = Ship_info[pobjp->ship_class].max_hull_strength;
// restore hull (but not shields)
if (ras->hull >= 0.0f && ras->hull <= max_hull)
pobjp->initial_hull = (int) (ras->hull * 100.0f / max_hull);
if (ras->hull >= 0.0f && ras->hull <= (pobjp->initial_hull * pobjp->ship_max_hull_strength / 100.0f))
pobjp->initial_hull = (int) (ras->hull * 100.0f / pobjp->ship_max_hull_strength);
else
mprintf(("Invalid health in red alert data for ship %s. Using mission defaults.\n", pobjp->name));
+9 -12
View File
@@ -2385,29 +2385,26 @@ int read_model_file(polymodel * pm, const char *filename, int n_subsystems, mode
int n_banks = cfread_int(fp); // Number of turrets
for ( i = 0; i < n_banks; i++ ) {
int parent; // The parent subobj of the turret (the gun base)
int physical_parent; // The subobj that the firepoints are physically attached to (the gun barrel)
int n_slots; // How many firepoints the turret has
model_subsystem *subsystemp; // The actual turret subsystem
int base_obj = cfread_int(fp); // The parent subobj of the turret (the gun base)
int gun_obj = cfread_int(fp); // The subobj that the firepoints are physically attached to (the gun barrel)
if (base_obj != gun_obj && pm->submodel[gun_obj].parent != base_obj) {
Warning(LOCATION, "Model %s turret %s has a gun submodel that is not an immediate child object of the base", pm->filename, pm->submodel[base_obj].name);
gun_obj = base_obj; // fall back to singlepart handling
}
parent = cfread_int( fp );
physical_parent = cfread_int(fp);
int snum=-1;
if ( subsystems ) {
for ( snum = 0; snum < n_subsystems; snum++ ) {
subsystemp = &subsystems[snum];
if ( base_obj == subsystemp->subobj_num ) {
if ( parent == subsystemp->subobj_num ) {
cfread_vector( &temp_vec, fp );
vm_vec_normalize_safe(&temp_vec);
subsystemp->turret_norm = temp_vec;
n_slots = cfread_int( fp );
subsystemp->turret_gun_sobj = gun_obj;
subsystemp->turret_gun_sobj = physical_parent;
if(n_slots > MAX_TFP) {
Warning(LOCATION, "Model %s has %i turret firing points on subsystem %s, maximum is %i", pm->filename, n_slots, subsystemp->name, MAX_TFP);
}
@@ -2426,8 +2423,8 @@ int read_model_file(polymodel * pm, const char *filename, int n_subsystems, mode
subsystemp->turret_num_firing_points = n_slots;
// copy the subsystem index that the gun base submodel should have at this point
Assertion(pm->submodel[base_obj].subsys_num >= 0, "Turret gun base should have a subsystem index!");
pm->submodel[gun_obj].subsys_num = pm->submodel[base_obj].subsys_num;
Assertion(pm->submodel[parent].subsys_num >= 0, "Turret gun base should have a subsystem index!");
pm->submodel[physical_parent].subsys_num = pm->submodel[parent].subsys_num;
break;
}
@@ -2437,7 +2434,7 @@ int read_model_file(polymodel * pm, const char *filename, int n_subsystems, mode
if ( (n_subsystems == 0) || (snum == n_subsystems) ) {
vec3d bogus;
nprintf(("Warning", "Turret submodel %i not found for turret %i in model %s\n", base_obj, i, pm->filename));
nprintf(("Warning", "Turret submodel %i not found for turret %i in model %s\n", parent, i, pm->filename));
cfread_vector( &bogus, fp );
n_slots = cfread_int( fp );
for (j = 0; j < n_slots; j++ )
+2 -2
View File
@@ -152,7 +152,7 @@ int ConnectToChatServer(char *serveraddr, char *nickname, char *trackerid)
return -1;
}
if (SOCKET_ERROR==bind(Chatsock, reinterpret_cast<LPSOCKADDR>(&Chataddr), psnet_get_sockaddr_len(&Chataddr)))
if (SOCKET_ERROR==bind(Chatsock, reinterpret_cast<LPSOCKADDR>(&Chataddr), sizeof(Chataddr)))
{
return -1;
}
@@ -164,7 +164,7 @@ int ConnectToChatServer(char *serveraddr, char *nickname, char *trackerid)
return -2;
}
if(SOCKET_ERROR == connect(Chatsock, reinterpret_cast<LPSOCKADDR>(&Chataddr), psnet_get_sockaddr_len(&Chataddr)))
if(SOCKET_ERROR == connect(Chatsock, reinterpret_cast<LPSOCKADDR>(&Chataddr), sizeof(Chataddr)))
{
if(WSAEWOULDBLOCK == WSAGetLastError())
{
+1 -1
View File
@@ -1785,7 +1785,7 @@ void multi_ingame_send_ship_update(net_player *p)
// go through the list and send all ships which are mark as OF_COULD_BE_PLAYER
while(moveup!=END_OF_LIST(&Ship_obj_list)){
//Make sure the object can be a player and is on the same team as this guy
if(Objects[moveup->objnum].flags[Object::Object_Flags::Could_be_player] && Objects[moveup->objnum].type == OBJ_SHIP && obj_team(&Objects[moveup->objnum]) == p->p_info.team){
if(Objects[moveup->objnum].flags[Object::Object_Flags::Could_be_player] && obj_team(&Objects[moveup->objnum]) == p->p_info.team){
// send the update
send_ingame_ship_update_packet(p,&Ships[Objects[moveup->objnum].instance]);
}
+1 -2
View File
@@ -1368,10 +1368,9 @@ int multi_oo_pack_data(net_player *pl, object *objp, ushort oo_flags, ubyte *dat
// Check that we are not sending too much data, if so, don't actually send.
if (packet_size + ret <= OO_MAX_DATA_SIZE) {
nprintf(("Network","Had to remove subsystems section from data packet for %s\n", shipp->ship_name));
oo_flags |= OO_SUBSYSTEMS_NEW;
packet_size += ret;
} else {
nprintf(("Network","Had to remove subsystems section from data packet for %s\n", shipp->ship_name));
}
}
}
+5 -38
View File
@@ -332,14 +332,8 @@ int SENDTO(SOCKET s, char * buf, int len, int flags, SOCKADDR *to, int tolen, in
outbuf[0] = static_cast<char>(psnet_type);
memcpy(&outbuf[1], buf, static_cast<size_t>(len));
SOCKLEN_T addrlen = tolen;
if (addrlen == sizeof(SOCKADDR_STORAGE)) {
addrlen = psnet_get_sockaddr_len(reinterpret_cast<SOCKADDR_STORAGE*>(to));
}
// send it
return static_cast<int>( sendto(s, outbuf, len + 1, flags, reinterpret_cast<LPSOCKADDR>(to), addrlen) );
return static_cast<int>( sendto(s, outbuf, len + 1, flags, reinterpret_cast<LPSOCKADDR>(to), tolen) );
}
/**
@@ -553,7 +547,7 @@ bool psnet_init_my_addr()
continue;
}
rval = connect(tsock, reinterpret_cast<LPSOCKADDR>(&remote_addr), psnet_get_sockaddr_len(&remote_addr));
rval = connect(tsock, reinterpret_cast<LPSOCKADDR>(&remote_addr), sizeof(remote_addr));
if (rval) {
continue;
@@ -592,7 +586,7 @@ bool psnet_init_my_addr()
continue;
}
rval = connect(tsock, reinterpret_cast<LPSOCKADDR>(&remote_addr), psnet_get_sockaddr_len(&remote_addr));
rval = connect(tsock, reinterpret_cast<LPSOCKADDR>(&remote_addr), sizeof(remote_addr));
if (rval) {
continue;
@@ -925,25 +919,6 @@ static void psnet_sockaddr_storage_to_in6(const SOCKADDR_STORAGE *addr, SOCKADDR
}
}
/**
* @brief Helper to get the exact length of a specific protocol struct from
* a generic storage struct
*
* @param addr
* @return SOCKLEN_T
*/
SOCKLEN_T psnet_get_sockaddr_len(const SOCKADDR_STORAGE *addr)
{
// internally we should always use IPv6, but cover the bases
if (addr->ss_family == AF_INET6) {
return static_cast<SOCKLEN_T>(sizeof(SOCKADDR_IN6));
} else if (addr->ss_family == AF_INET) {
return static_cast<SOCKLEN_T>(sizeof(SOCKADDR_IN));
} else {
return static_cast<SOCKLEN_T>(sizeof(SOCKADDR_STORAGE));
}
}
/**
* Helper to map IPv4 to IPv6
*/
@@ -1151,11 +1126,6 @@ bool psnet_get_addr(const char *host, const char *port, SOCKADDR_STORAGE *addr,
SOCKADDR_IN6 si4to6;
int rval;
if (addr) {
// by the spec, sockaddr_in6 must be zero'd, so just do that always
memset(addr, 0, sizeof(*addr));
}
memset(&si4to6, 0, sizeof(si4to6));
memset(&hints, 0, sizeof(hints));
@@ -2347,12 +2317,9 @@ bool psnet_init_socket()
psnet_set_socket_options();
// bind the socket
if ( !psnet_get_addr(nullptr, Psnet_default_port, &sockaddr) ) {
ml_printf("Failed to get bind addr!");
return false;
}
psnet_get_addr(nullptr, Psnet_default_port, &sockaddr);
if ( bind(Psnet_socket, reinterpret_cast<LPSOCKADDR>(&sockaddr), psnet_get_sockaddr_len(&sockaddr)) == SOCKET_ERROR) {
if ( bind(Psnet_socket, reinterpret_cast<LPSOCKADDR>(&sockaddr), sizeof(sockaddr)) == SOCKET_ERROR) {
Psnet_failure_code = WSAGetLastError();
if (Psnet_failure_code == WSAEADDRINUSE) {
-3
View File
@@ -178,9 +178,6 @@ bool psnet_get_addr(const char *host, uint16_t port, SOCKADDR_STORAGE *addr, int
#define ADDR_FLAG_NUMERIC_SERVICE (1<<0)
#define ADDR_FLAG_PREFER_IPV4 (1<<1)
// get protocol struct length from generic storage struct
SOCKLEN_T psnet_get_sockaddr_len(const SOCKADDR_STORAGE *addr);
// map an IPv4 address to IPv6
void psnet_map4to6(const in_addr *in4, in6_addr *in6);
+8 -22
View File
@@ -300,7 +300,7 @@ static char szWinTitle[128];
static char szWinClass[128];
static int Os_inited = 0;
static SCP_vector<SDL_Event> deferred_events;
static SCP_vector<SDL_Event> buffered_events;
int Os_debugger_running = 0;
@@ -713,11 +713,11 @@ namespace os
}
}
void os_defer_events_on_load_screen() {
void os_ignore_events() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
// Add event to be handled later
deferred_events.push_back(event);
// Add event to buffer
buffered_events.push_back(event);
}
}
@@ -745,28 +745,14 @@ static void handle_sdl_event(const SDL_Event& event) {
}
}
void os_remove_deferred_cutscene_key_events() {
deferred_events.erase(
std::remove_if(deferred_events.begin(), deferred_events.end(), [](const SDL_Event &event)
{
return (event.type == SDL_KEYUP) && (
event.key.keysym.sym == SDLK_KP_ENTER ||
event.key.keysym.sym == SDLK_RETURN ||
event.key.keysym.sym == SDLK_SPACE
);
}),
deferred_events.end()
);
}
void os_poll()
{
// Replay the deferred events
auto end = deferred_events.end();
for (auto it = deferred_events.begin(); it != end; ++it) {
// Replay the buffered events
auto end = buffered_events.end();
for (auto it = buffered_events.begin(); it != end; ++it) {
handle_sdl_event(*it);
}
deferred_events.clear();
buffered_events.clear();
SDL_Event event;
+2 -5
View File
@@ -64,12 +64,9 @@ int os_foreground();
// process management --------------------------------------------------------------
/**
* @brief Defers all pending events to be handled later
* @brief Removes all pending events and ignores them
*/
void os_defer_events_on_load_screen();
// removes key events that may unintentionally skip the cutscene
void os_remove_deferred_cutscene_key_events();
void os_ignore_events();
// call to process windows messages. only does something in non THREADED mode
void os_poll();
+57 -169
View File
@@ -991,12 +991,8 @@ bool ship_class_unchanged(const ship_registry_entry *ship_entry);
void multi_sexp_modify_variable();
// jg18
// container_value_index is for using one specific value from a container
// container_value_index is for using one specific value from acontainer
int copy_node_to_replacement_args(int node, int container_value_index = -1);
// checks whether the node's value can change over the course of the mission
bool is_node_value_dynamic(int node);
// returns 0 on success or a SEXP_CHECK_* value on failure
int check_dynamic_value_node_type(int node, bool is_string, bool is_number);
#define NO_OPERATOR_INDEX_DEFINED -2
#define NOT_A_SEXP_OPERATOR -1
@@ -2125,12 +2121,6 @@ int check_sexp_syntax(int node, int return_type, int recursive, int *bad_node, i
} else if (Sexp_nodes[node].subtype == SEXP_ATOM_CONTAINER_DATA) {
// this is an instance of "Replace Container Data"
// can't be used in special argument list
if (type == OPF_ANYTHING || type == OPF_DATA_OR_STR_CONTAINER) {
return SEXP_CHECK_TYPE_MISMATCH;
}
const int modifier_node = Sexp_nodes[node].first;
if (modifier_node == -1) {
return SEXP_CHECK_MISSING_CONTAINER_MODIFIER;
@@ -2474,16 +2464,9 @@ int check_sexp_syntax(int node, int return_type, int recursive, int *bad_node, i
}
Assert(ship_node >= 0);
if (is_node_value_dynamic(ship_node)) {
const int dyn_val_check = check_dynamic_value_node_type(ship_node, true, false);
if (dyn_val_check) {
return dyn_val_check;
} else {
// since the value changes at runtime
// we can check only the type
break;
}
}
// we can't check special-arg ships
if (Sexp_nodes[ship_node].flags & SNF_SPECIAL_ARG_IN_NODE)
break;
auto shipname = CTEXT(ship_node);
shipnum = ship_name_lookup(shipname, 1);
@@ -2568,16 +2551,9 @@ int check_sexp_syntax(int node, int return_type, int recursive, int *bad_node, i
ship_node = CDR(op_node);
if (is_node_value_dynamic(ship_node)) {
const int dyn_val_check = check_dynamic_value_node_type(ship_node, true, false);
if (dyn_val_check) {
return dyn_val_check;
} else {
// since the value changes at runtime
// we can check only the type
break;
}
}
// we can't check special-arg ships
if (Sexp_nodes[ship_node].flags & SNF_SPECIAL_ARG_IN_NODE)
break;
auto shipname = CTEXT(ship_node);
shipnum = ship_name_lookup(shipname, 1);
@@ -2944,16 +2920,9 @@ int check_sexp_syntax(int node, int return_type, int recursive, int *bad_node, i
auto ship_node = Sexp_nodes[op_node].rest;
Assert(ship_node >= 0);
if (is_node_value_dynamic(ship_node)) {
const int dyn_val_check = check_dynamic_value_node_type(ship_node, true, false);
if (dyn_val_check) {
return dyn_val_check;
} else {
// since the value changes at runtime
// we can check only the type
break;
}
}
// we can't check special-arg ships
if (Sexp_nodes[ship_node].flags & SNF_SPECIAL_ARG_IN_NODE)
break;
ship_num = ship_name_lookup(CTEXT(ship_node), 1); // Goober5000 - include players
if (ship_num < 0) {
@@ -3091,16 +3060,9 @@ int check_sexp_syntax(int node, int return_type, int recursive, int *bad_node, i
z = Sexp_nodes[z].rest; // first argument of operator should be mission name
Assert(z >= 0);
if (is_node_value_dynamic(z)) {
const int dyn_val_check = check_dynamic_value_node_type(z, true, false);
if (dyn_val_check) {
return dyn_val_check;
} else {
// since the value changes at runtime
// we can check only the type
break;
}
}
// can't check special-arg
if (Sexp_nodes[z].flags & SNF_SPECIAL_ARG_IN_NODE)
break;
// look for mission
count = count_items_with_name(CTEXT(z), Campaign.missions, Campaign.num_missions);
@@ -3183,16 +3145,9 @@ int check_sexp_syntax(int node, int return_type, int recursive, int *bad_node, i
}
Assert(ship_node >= 0);
if (is_node_value_dynamic(ship_node)) {
const int dyn_val_check = check_dynamic_value_node_type(ship_node, true, false);
if (dyn_val_check) {
return dyn_val_check;
} else {
// since the value changes at runtime
// we can check only the type
break;
}
}
// can't check special-arg
if (Sexp_nodes[ship_node].flags & SNF_SPECIAL_ARG_IN_NODE)
break;
// look for the ship that has this dockpoint
ship_num = ship_name_lookup(CTEXT(ship_node), 1);
@@ -4551,23 +4506,36 @@ void stuff_sexp_text_string(SCP_string &dest, int node, int mode)
Assertion(sexp_variables_index != -1, "Couldn't find variable: %s\n", Sexp_nodes[node].text);
Assert((Sexp_variables[sexp_variables_index].type & SEXP_VARIABLE_NUMBER) || (Sexp_variables[sexp_variables_index].type & SEXP_VARIABLE_STRING));
auto var_name = (Fred_running) ? Sexp_nodes[node].text : Sexp_variables[sexp_variables_index].variable_name;
auto var_contents = Sexp_variables[sexp_variables_index].text;
// number
if (Sexp_nodes[node].subtype == SEXP_ATOM_NUMBER)
// Error check - can be Fred or FreeSpace
if (mode == SEXP_ERROR_CHECK_MODE)
{
Assert(Sexp_variables[sexp_variables_index].type & SEXP_VARIABLE_NUMBER);
sprintf(dest, "@%s[%s] ", var_name, var_contents);
}
// string
else if (Sexp_nodes[node].subtype == SEXP_ATOM_STRING)
{
Assert(Sexp_variables[sexp_variables_index].type & SEXP_VARIABLE_STRING);
sprintf(dest, "\"@%s[%s]\" ", var_name, var_contents);
if (Fred_running)
sprintf(dest, "@%s[%s] ", Sexp_nodes[node].text, Sexp_variables[sexp_variables_index].text);
else
sprintf(dest, "@%s[%s] ", Sexp_variables[sexp_variables_index].variable_name, Sexp_variables[sexp_variables_index].text);
}
else
UNREACHABLE("SEXP variable nodes must be SEXP_ATOM_NUMBER or SEXP_ATOM_STRING!");
{
// number
if (Sexp_nodes[node].subtype == SEXP_ATOM_NUMBER)
{
Assert(Sexp_variables[sexp_variables_index].type & SEXP_VARIABLE_NUMBER);
// Save as string - only Fred
Assert(mode == SEXP_SAVE_MODE);
sprintf(dest, "@%s[%s] ", Sexp_nodes[node].text, Sexp_variables[sexp_variables_index].text);
}
// string
else
{
Assert(Sexp_nodes[node].subtype == SEXP_ATOM_STRING);
Assert(Sexp_variables[sexp_variables_index].type & SEXP_VARIABLE_STRING);
// Save as string - only Fred
Assert(mode == SEXP_SAVE_MODE);
sprintf(dest, "\"@%s[%s]\" ", Sexp_nodes[node].text, Sexp_variables[sexp_variables_index].text);
}
}
}
// not a variable
else
@@ -4949,8 +4917,8 @@ const ship_registry_entry *eval_ship(int node)
auto ship_it = Ship_registry_map.find(CTEXT(node));
if (ship_it != Ship_registry_map.end())
{
// cache the value if it can't change later
if (!is_node_value_dynamic(node))
// cache the value, unless this node is a variable or argument because the value may change
if (!(Sexp_nodes[node].type & SEXP_FLAG_VARIABLE) && !(Sexp_nodes[node].flags & SNF_SPECIAL_ARG_IN_NODE))
Sexp_nodes[node].cache = new sexp_cached_data(OPF_SHIP, -1, ship_it->second);
return &Ship_registry[ship_it->second];
@@ -4992,8 +4960,8 @@ wing *eval_wing(int node)
{
auto wingp = &Wings[wing_num];
// cache the value if it can't change later
if (!is_node_value_dynamic(node))
// cache the value, unless this node is a variable or argument because the value may change
if (!(Sexp_nodes[node].type & SEXP_FLAG_VARIABLE) && !(Sexp_nodes[node].flags & SNF_SPECIAL_ARG_IN_NODE))
Sexp_nodes[node].cache = new sexp_cached_data(OPF_WING, wingp);
return wingp;
@@ -5034,8 +5002,10 @@ int sexp_atoi(int node)
int num = atoi(CTEXT(node));
// cache the value if it can't change later
if (!is_node_value_dynamic(node))
// cache the value, unless this node is a variable, argument, or container data, because the value may change
if (!(Sexp_nodes[node].type & SEXP_FLAG_VARIABLE) &&
!(Sexp_nodes[node].flags & SNF_SPECIAL_ARG_IN_NODE) &&
(Sexp_nodes[node].subtype != SEXP_ATOM_CONTAINER_DATA))
Sexp_nodes[node].cache = new sexp_cached_data(OPF_NUMBER, num, -1);
return num;
@@ -11035,13 +11005,6 @@ void sexp_change_argument_validity(int n, bool invalidate)
// first we must check if the arg_handler marks a selection. At the moment random-of is the only one that does this
arg_n = CDR(arg_handler);
while (invalidate && (arg_n != -1)) {
Assertion(Sexp_nodes[arg_n].subtype != SEXP_ATOM_CONTAINER_NAME,
"Attempt to use invalidate-argument with container %s. Please report!",
Sexp_nodes[arg_n].text);
Assertion(Sexp_nodes[arg_n].subtype != SEXP_ATOM_CONTAINER_DATA,
"Attempt to use invalidate-argument with data from container %s. Please report!",
Sexp_nodes[arg_n].text);
if (Sexp_nodes[arg_n].flags & SNF_ARGUMENT_SELECT) {
// now check if the selected argument matches the one we want to invalidate
if (!strcmp(CTEXT(n), CTEXT(arg_n))) {
@@ -11060,13 +11023,6 @@ void sexp_change_argument_validity(int n, bool invalidate)
arg_n = CDR(arg_handler);
while (arg_n != -1)
{
Assertion(Sexp_nodes[arg_n].subtype != SEXP_ATOM_CONTAINER_NAME,
"Attempt to change argument validity of container %s. Please report!",
Sexp_nodes[arg_n].text);
Assertion(Sexp_nodes[arg_n].subtype != SEXP_ATOM_CONTAINER_DATA,
"Attempt to change argument validity of data from container %s. Please report!",
Sexp_nodes[arg_n].text);
// match?
if (!strcmp(CTEXT(n), CTEXT(arg_n)))
{
@@ -11846,7 +11802,7 @@ void sexp_clear_goals(int n)
if (ship_entry)
{
if (ship_entry->status != ShipStatus::PRESENT)
continue; // ship not around anymore???? then forget it!
return; // ship not around anymore???? then forget it!
ai_clear_ship_goals(&(Ai_info[ship_entry->shipp->ai_index]));
continue;
@@ -11856,7 +11812,7 @@ void sexp_clear_goals(int n)
if (wingp)
{
if (wingp->flags[Ship::Wing_Flags::Gone])
continue; // wing not around anymore???? then forget it!
return; // wing not around anymore???? then forget it!
ai_clear_wing_goals(wingp);
}
@@ -12228,11 +12184,6 @@ void multi_sexp_hud_display_gauge()
void sexp_player_use_ai(int flag)
{
Player_use_ai = flag ? 1 : 0;
if (!flag) {
Player_ai->ai_override_flags.reset();
Player_obj->phys_info.flags &= ~PF_MANEUVER_NO_DAMP;
}
}
// Karajorma
@@ -22118,8 +22069,8 @@ int sexp_string_to_int(int n)
int num = atoi(buf);
// cache the value if it can't change later
if (!is_node_value_dynamic(n))
// cache the value, unless this node is a variable or argument because the value may change
if (!(Sexp_nodes[n].type & SEXP_FLAG_VARIABLE) && !(Sexp_nodes[n].flags & SNF_SPECIAL_ARG_IN_NODE))
Sexp_nodes[n].cache = new sexp_cached_data(OPF_NUMBER, num, -1);
return num;
@@ -31398,9 +31349,6 @@ const char *sexp_error_message(int num)
case SEXP_CHECK_WRONG_CONTAINER_DATA_TYPE:
return "Wrong container data type";
case SEXP_CHECK_INVALID_SPECIAL_ARG_TYPE:
return "Invalid special argument type";
default:
Warning(LOCATION, "Unhandled sexp error code %d!", num);
return "Unhandled sexp error code!";
@@ -31731,47 +31679,6 @@ int copy_node_to_replacement_args(int node, int container_value_index)
return num_args;
}
bool is_node_value_dynamic(int node)
{
Assertion(node >= 0, "Attempt to check whether a non-existent node has a dynamic value. Please report!");
return (Sexp_nodes[node].type & SEXP_FLAG_VARIABLE) || (Sexp_nodes[node].flags & SNF_SPECIAL_ARG_IN_NODE) ||
(Sexp_nodes[node].subtype == SEXP_ATOM_CONTAINER_DATA);
}
int check_dynamic_value_node_type(int node, bool is_string, bool is_number)
{
Assertion(is_node_value_dynamic(node),
"Attempt to check dynamic value type of a node that isn't a dynamic value. Please report!");
if (Sexp_nodes[node].type & SEXP_FLAG_VARIABLE) {
const int var_index = sexp_get_variable_index(node);
Assertion(var_index != -1,
"Attempt to get index of invalid variable %s. Please report!",
Sexp_nodes[node].text);
const int var_type = Sexp_variables[var_index].type;
if (((var_type & SEXP_VARIABLE_STRING) && !is_string) || ((var_type & SEXP_VARIABLE_NUMBER) && !is_number)) {
return SEXP_CHECK_INVALID_VARIABLE_TYPE;
}
} else if (Sexp_nodes[node].flags & SNF_SPECIAL_ARG_IN_NODE) {
if (((Sexp_nodes[node].subtype == SEXP_ATOM_STRING) && !is_string) ||
((Sexp_nodes[node].subtype == SEXP_ATOM_NUMBER) && !is_number)) {
return SEXP_CHECK_INVALID_SPECIAL_ARG_TYPE;
}
} else if (Sexp_nodes[node].subtype == SEXP_ATOM_CONTAINER_DATA) {
const auto *p_container = get_sexp_container(Sexp_nodes[node].text);
Assertion(p_container,
"Attempt to check dynamic value node type of data of nonexistent container %s. Please report!",
Sexp_nodes[node].text);
if (!check_container_data_sexp_arg_type(p_container->type, is_string, is_number)) {
return SEXP_CHECK_WRONG_CONTAINER_DATA_TYPE;
}
} else {
UNREACHABLE("Unhandled dynamic value node %s. Please report!", Sexp_nodes[node].text);
}
return 0;
}
void sexp_modify_variable(int n)
{
@@ -32318,21 +32225,6 @@ int get_category(int sexp_id)
return category;
}
// Goober5000
const char *get_category_name(int category_id)
{
if (category_id == OP_CATEGORY_CHANGE2)
category_id = OP_CATEGORY_CHANGE;
for (auto &category : op_menu)
{
if (category.id == category_id)
return category.name.c_str();
}
return "<unknown>";
}
// Goober5000
int category_of_subcategory(int subcategory_id)
{
@@ -33927,8 +33819,7 @@ SCP_vector<sexp_help_struct> Sexp_help = {
// Goober5000
{ OP_INVALIDATE_ARGUMENT, "Invalidate-argument (Conditional operator)\r\n"
"\tRemoves an argument from future consideration as a " SEXP_ARGUMENT_STRING " special data item.\r\n"
"\tFor argument-related SEXPs that accept containers as arguments, the retrieved arguments can't be individually invalidated.\r\n"
"\tAdditionally, you can't invalidate individual container arguments.\r\n\r\n"
"\tFor argument-related SEXPs that accept containers as arguments, the retrieved arguments can't be individually invalidated.\r\n\r\n"
"Takes 1 or more arguments...\r\n"
"\tAll:\tThe argument to remove from the preceding argument list." },
@@ -33936,22 +33827,19 @@ SCP_vector<sexp_help_struct> Sexp_help = {
{ OP_VALIDATE_ARGUMENT, "Validate-argument (Conditional operator)\r\n"
"\tRestores an argument for future consideration as a " SEXP_ARGUMENT_STRING " special data item.\r\n"
"\tIf the argument hasn't been previously invalidated, it will do nothing.\r\n"
"\tFor argument-related SEXPs that accept containers as arguments, the retrieved arguments can't be individually validated.\r\n"
"\tAdditionally, you can't validate individual container arguments.\r\n\r\n"
"\tFor argument-related SEXPs that accept containers as arguments, the retrieved arguments can't be individually validated.\r\n\r\n"
"Takes 1 or more arguments...\r\n"
"\tAll:\tThe argument to restore to the preceding argument list." },
// Karajorma
{ OP_INVALIDATE_ALL_ARGUMENTS, "Invalidate-all-arguments (Conditional operator)\r\n"
"\tRemoves all argument from future consideration as " SEXP_ARGUMENT_STRING " special data items.\r\n"
"\tFor argument-related SEXPs that accept containers as arguments, container arguments will also be invalidated, but they can't be indvidiually validated.\r\n\r\n"
"Takes no arguments." },
// Karajorma
{ OP_VALIDATE_ALL_ARGUMENTS, "Validate-all-arguments (Conditional operator)\r\n"
"\tRestores all arguments for future consideration as " SEXP_ARGUMENT_STRING " special data items.\r\n"
"\tIf the argument hasn't been previously invalidated, it will do nothing.\r\n"
"\tFor argument-related SEXPs that accept containers as arguments, container arguments will also be validated, but they can't be indvidiually invalidated.\r\n\r\n"
"Takes no arguments." },
// Goober5000 - added wing capability
-3
View File
@@ -1117,7 +1117,6 @@ const char *CTEXT(int n);
#define SEXP_CHECK_WRONG_CONTAINER_TYPE -170
#define SEXP_CHECK_INVALID_ANIMATION -171
#define SEXP_CHECK_WRONG_CONTAINER_DATA_TYPE -172
#define SEXP_CHECK_INVALID_SPECIAL_ARG_TYPE -173
#define TRAINING_CONTEXT_SPEED (1<<0)
@@ -1297,7 +1296,6 @@ extern int query_operator_argument_type(int op, int argnum);
extern void update_sexp_references(const char *old_name, const char *new_name);
extern void update_sexp_references(const char *old_name, const char *new_name, int format);
extern int query_referenced_in_sexp(int mode, const char *name, int *node);
extern void stuff_sexp_text_string(SCP_string &dest, int node, int mode);
extern int build_sexp_string(SCP_string &accumulator, int cur_node, int level, int mode);
extern int sexp_query_type_match(int opf, int opr);
extern bool sexp_recoverable_error(int num);
@@ -1359,7 +1357,6 @@ void set_turret_secondary_ammo(ship_subsys *turret, int requested_bank, int requ
extern int get_category(int sexp_id);
extern int category_of_subcategory(int subcategory_id);
extern int get_subcategory(int sexp_id);
extern const char *get_category_name(int category_id);
// Goober5000
extern void sexp_music_close();
+3 -16
View File
@@ -125,10 +125,8 @@ void parse_sexp_table(const char* filename) {
luaSexp->parseTable();
int op = add_dynamic_sexp(std::move(instance), SEXP_GOAL_OPERATOR);
if (op >= 0) {
luaSexp->registerAIMode(op);
luaSexp->maybeRegisterPlayerOrder(op);
}
luaSexp->registerAIMode(op);
luaSexp->maybeRegisterPlayerOrder(op);
}
required_string("#End");
}
@@ -179,19 +177,8 @@ int add_dynamic_sexp(std::unique_ptr<DynamicSEXP>&& sexp, int type)
new_op.min = sexp->getMinimumArguments();
new_op.max = sexp->getMaximumArguments();
int free_op_index = get_next_free_operator(sexp->getCategory());
if (free_op_index >= 256) {
Warning(LOCATION, "There are too many SEXPs in the %s category. The SEXP %s will not be added.", get_category_name(sexp->getCategory()), sexp->getName().c_str());
return -1;
}
if (Operators.size() >= FIRST_OP) {
Warning(LOCATION, "There are too many total SEXPs. The SEXP %s will not be added.", sexp->getName().c_str());
return -1;
}
// For now, all dynamic SEXPS are only valid in missions
new_op.value = free_op_index | sexp->getCategory() | OP_NONCAMPAIGN_FLAG;
new_op.value = get_next_free_operator(sexp->getCategory()) | sexp->getCategory() | OP_NONCAMPAIGN_FLAG;
new_op.type = type;
global.operator_const_mapping.insert(std::make_pair(new_op.value, std::move(sexp)));
+2 -2
View File
@@ -168,7 +168,7 @@ void physics_sim_rot(matrix * orient, physics_info * pi, float sim_time )
shock_amplitude = pi->shockwave_shake_amp * shock_fraction_time_left;
}
}
else if (pi->flags & PF_MANEUVER_NO_DAMP) {
else if (pi->flags & PF_NO_DAMP) {
rotdamp = 0.0f;
}
else {
@@ -305,7 +305,7 @@ void physics_sim_vel(vec3d * position, physics_info * pi, float sim_time, matrix
}
}
// no damping at all
else if (pi->flags & PF_MANEUVER_NO_DAMP) {
else if (pi->flags & PF_NO_DAMP) {
damp = vmd_zero_vector;
}
// newtonian
+1 -1
View File
@@ -32,7 +32,7 @@
#define PF_GLIDING (1 << 14)
#define PF_FORCE_GLIDE (1 << 15)
#define PF_NEWTONIAN_DAMP (1 << 16) // SUSHI: Whether or not to use newtonian dampening
#define PF_MANEUVER_NO_DAMP (1 << 17) // Goober5000 - don't damp velocity changes in physics; used for instantaneous acceleration
#define PF_NO_DAMP (1 << 17) // Goober5000 - don't damp velocity changes in physics; used for instantaneous acceleration
//information for physics sim for an object
typedef struct physics_info {
+3 -35
View File
@@ -1134,20 +1134,11 @@ void pilotfile::csg_write_variables()
void pilotfile::csg_read_settings()
{
clamped_range_warnings.clear();
// sound/voice/music
if (!Using_in_game_options) {
float temp_volume = cfread_float(cfp);
clamp_value_with_warn(&temp_volume, 0.f, 1.f, "Effects Volume");
snd_set_effects_volume(temp_volume);
temp_volume = cfread_float(cfp);
clamp_value_with_warn(&temp_volume, 0.f, 1.f, "Music Volume");
event_music_set_volume(temp_volume);
temp_volume = cfread_float(cfp);
clamp_value_with_warn(&temp_volume, 0.f, 1.f, "Voice Volume");
snd_set_voice_volume(temp_volume);
snd_set_effects_volume(cfread_float(cfp));
event_music_set_volume(cfread_float(cfp));
snd_set_voice_volume(cfread_float(cfp));
Briefing_voice_enabled = cfread_int(cfp) != 0;
} else {
@@ -1163,20 +1154,13 @@ void pilotfile::csg_read_settings()
// skill level
Game_skill_level = cfread_int(cfp);
clamp_value_with_warn(&Game_skill_level, 0, 4, "Game Skill Level");
// input options
if (!Using_in_game_options) {
Use_mouse_to_fly = cfread_int(cfp) != 0;
Mouse_sensitivity = cfread_int(cfp);
clamp_value_with_warn(&Mouse_sensitivity, 0, 9, "Mouse Sensitivity");
Joy_sensitivity = cfread_int(cfp);
clamp_value_with_warn(&Joy_sensitivity, 0, 9, "Joystick Sensitivity");
Joy_dead_zone_size = cfread_int(cfp);
clamp_value_with_warn(&Joy_dead_zone_size, 0, 45, "Joystick Deadzone");
} else {
// The values are set by the in-game menu but we still need to read the int from the file to maintain the correct offset
cfread_int(cfp);
@@ -1200,44 +1184,28 @@ void pilotfile::csg_read_settings()
dummy = cfread_int(cfp);
dummy = cfread_int(cfp);
}
if (!clamped_range_warnings.empty()) {
ReleaseWarning(LOCATION, "The following values in the campaign save file were out of bounds and were automatically reset:\n%s\nPlease check your settings!\n", clamped_range_warnings.c_str());
clamped_range_warnings.clear();
}
}
void pilotfile::csg_write_settings()
{
startSection(Section::Settings);
clamped_range_warnings.clear();
// sound/voice/music
clamp_value_with_warn(&Master_sound_volume, 0.f, 1.f, "Effects Volume");
cfwrite_float(Master_sound_volume, cfp);
clamp_value_with_warn(&Master_event_music_volume, 0.f, 1.f, "Music Volume");
cfwrite_float(Master_event_music_volume, cfp);
clamp_value_with_warn(&Master_voice_volume, 0.f, 1.f, "Voice Volume");
cfwrite_float(Master_voice_volume, cfp);
cfwrite_int(Briefing_voice_enabled ? 1 : 0, cfp);
// skill level
clamp_value_with_warn(&Game_skill_level, 0, 4, "Game Skill Level");
cfwrite_int(Game_skill_level, cfp);
// input options
cfwrite_int(Use_mouse_to_fly, cfp);
clamp_value_with_warn(&Mouse_sensitivity, 0, 9, "Mouse Sensitivity");
cfwrite_int(Mouse_sensitivity, cfp);
clamp_value_with_warn(&Joy_sensitivity, 0, 9, "Joystick Sensitivity");
cfwrite_int(Joy_sensitivity, cfp);
clamp_value_with_warn(&Joy_dead_zone_size, 0, 45, "Joystick Deadzone");
cfwrite_int(Joy_dead_zone_size, cfp);
if (!clamped_range_warnings.empty()) {
ReleaseWarning(LOCATION, "The following values were out of bounds when saving the campaign file and were automatically reset.\n%s\nThis shouldn't be possible, please contact the FreeSpace 2 Open Source Code Project!\n", clamped_range_warnings.c_str());
clamped_range_warnings.clear();
}
endSection();
}
-11
View File
@@ -157,17 +157,6 @@ class pilotfile {
// file offset of the size value for the current section (set with startSection())
size_t m_size_offset;
SCP_string clamped_range_warnings = "";
template <typename T> void clamp_value_with_warn(T* value, T min, T max, const char* name) {
if (*value < min) {
clamped_range_warnings += SCP_string(name) + ": too low (" + std::to_string(*value) + "). Will reset to minimum (" + std::to_string(min) + ")\n";
*value = min;
} else if (*value > max) {
clamped_range_warnings += SCP_string(name) + ": too high (" + std::to_string(*value) + "). Will reset to maximum (" + std::to_string(max) + ")\n";
*value = max;
}
}
// --------------------------------------------------------------------
// PLR specific
+3 -49
View File
@@ -795,20 +795,11 @@ void pilotfile::plr_write_controls()
void pilotfile::plr_read_settings()
{
clamped_range_warnings.clear();
// sound/voice/music
if (!Using_in_game_options) {
float temp_volume = handler->readFloat("master_sound_volume");
clamp_value_with_warn(&temp_volume, 0.f, 1.f, "Effects Volume");
snd_set_effects_volume(temp_volume);
temp_volume = handler->readFloat("master_event_music_volume");
clamp_value_with_warn(&temp_volume, 0.f, 1.f, "Music Volume");
event_music_set_volume(temp_volume);
temp_volume = handler->readFloat("aster_voice_volume");
clamp_value_with_warn(&temp_volume, 0.f, 1.f, "Voice Volume");
snd_set_voice_volume(temp_volume);
snd_set_effects_volume(handler->readFloat("master_sound_volume"));
event_music_set_volume(handler->readFloat("master_event_music_volume"));
snd_set_voice_volume(handler->readFloat("aster_voice_volume"));
Briefing_voice_enabled = handler->readInt("briefing_voice_enabled") != 0;
} else {
@@ -823,37 +814,24 @@ void pilotfile::plr_read_settings()
// skill level
Game_skill_level = handler->readInt("game_skill_level");
clamp_value_with_warn(&Game_skill_level, 0, 4, "Skill Level");
// input options
if (!Using_in_game_options) {
Use_mouse_to_fly = handler->readInt("use_mouse_to_fly") != 0;
Mouse_sensitivity = handler->readInt("mouse_sensitivity");
clamp_value_with_warn(&Mouse_sensitivity, 0, 9, "Mouse Sensitivity");
Joy_sensitivity = handler->readInt("joy_sensitivity");
clamp_value_with_warn(&Joy_sensitivity, 0, 9, "Joystick Sensitivity");
Joy_dead_zone_size = handler->readInt("joy_dead_zone_size");
clamp_value_with_warn(&Joy_dead_zone_size, 0, 45, "Joystick Deadzone");
// detail
Detail.setting = handler->readInt("setting");
clamp_value_with_warn(&Detail.setting, -1, NUM_DEFAULT_DETAIL_LEVELS - 1, "Detail Level Preset");
Detail.nebula_detail = handler->readInt("nebula_detail");
clamp_value_with_warn(&Detail.nebula_detail, 0, MAX_DETAIL_LEVEL, "Nebula Detail");
Detail.detail_distance = handler->readInt("detail_distance");
clamp_value_with_warn(&Detail.detail_distance, 0, MAX_DETAIL_LEVEL, "Model Detail");
Detail.hardware_textures = handler->readInt("hardware_textures");
clamp_value_with_warn(&Detail.hardware_textures, 0, MAX_DETAIL_LEVEL, "3D Hardware Textures");
Detail.num_small_debris = handler->readInt("num_small_debris");
clamp_value_with_warn(&Detail.num_small_debris, 0, MAX_DETAIL_LEVEL, "Impact Effects");
Detail.num_particles = handler->readInt("num_particles");
clamp_value_with_warn(&Detail.num_particles, 0, MAX_DETAIL_LEVEL, "Particles");
Detail.num_stars = handler->readInt("num_stars");
clamp_value_with_warn(&Detail.num_stars, 0, MAX_DETAIL_LEVEL, "Stars");
Detail.shield_effects = handler->readInt("shield_effects");
clamp_value_with_warn(&Detail.shield_effects, 0, MAX_DETAIL_LEVEL, "Shield Hit Effects");
Detail.lighting = handler->readInt("lighting");
clamp_value_with_warn(&Detail.lighting, 0, MAX_DETAIL_LEVEL, "Lighting");
Detail.targetview_model = handler->readInt("targetview_model");
Detail.planets_suns = handler->readInt("planets_suns");
Detail.weapon_extras = handler->readInt("weapon_extras");
@@ -878,10 +856,6 @@ void pilotfile::plr_read_settings()
handler->readInt("planets_suns");
handler->readInt("weapon_extras");
}
if (!clamped_range_warnings.empty()) {
ReleaseWarning(LOCATION, "The following values in the pilot file were out of bounds and were automatically reset:\n%s\nPlease check your settings!\n", clamped_range_warnings.c_str());
clamped_range_warnings.clear();
}
}
void pilotfile::plr_write_settings()
@@ -889,55 +863,35 @@ void pilotfile::plr_write_settings()
handler->startSectionWrite(Section::Settings);
// sound/voice/music
clamp_value_with_warn(&Master_sound_volume, 0.f, 1.f, "Effects Volume");
handler->writeFloat("master_sound_volume", Master_sound_volume);
clamp_value_with_warn(&Master_event_music_volume, 0.f, 1.f, "Music Volume");
handler->writeFloat("master_event_music_volume", Master_event_music_volume);
clamp_value_with_warn(&Master_voice_volume, 0.f, 1.f, "Voice Volume");
handler->writeFloat("aster_voice_volume", Master_voice_volume);
handler->writeInt("briefing_voice_enabled", Briefing_voice_enabled ? 1 : 0);
// skill level
clamp_value_with_warn(&Game_skill_level, 0, 4, "Skill Level");
handler->writeInt("game_skill_level", Game_skill_level);
// input options
handler->writeInt("use_mouse_to_fly", Use_mouse_to_fly);
clamp_value_with_warn(&Mouse_sensitivity, 0, 9, "Mouse Sensitivity");
handler->writeInt("mouse_sensitivity", Mouse_sensitivity);
clamp_value_with_warn(&Joy_sensitivity, 0, 9, "Joystick Sensitivity");
handler->writeInt("joy_sensitivity", Joy_sensitivity);
clamp_value_with_warn(&Joy_dead_zone_size, 0, 45, "Joystick Deadzone");
handler->writeInt("joy_dead_zone_size", Joy_dead_zone_size);
// detail
clamp_value_with_warn(&Detail.setting, -1, NUM_DEFAULT_DETAIL_LEVELS - 1, "Detail Level Preset");
handler->writeInt("setting", Detail.setting);
clamp_value_with_warn(&Detail.nebula_detail, 0, MAX_DETAIL_LEVEL, "Nebula Detail");
handler->writeInt("nebula_detail", Detail.nebula_detail);
clamp_value_with_warn(&Detail.detail_distance, 0, MAX_DETAIL_LEVEL, "Model Detail");
handler->writeInt("detail_distance", Detail.detail_distance);
clamp_value_with_warn(&Detail.hardware_textures, 0, MAX_DETAIL_LEVEL, "3D Hardware Textures");
handler->writeInt("hardware_textures", Detail.hardware_textures);
clamp_value_with_warn(&Detail.num_small_debris, 0, MAX_DETAIL_LEVEL, "Impact Effects");
handler->writeInt("num_small_debris", Detail.num_small_debris);
clamp_value_with_warn(&Detail.num_particles, 0, MAX_DETAIL_LEVEL, "Particles");
handler->writeInt("num_particles", Detail.num_particles);
clamp_value_with_warn(&Detail.num_stars, 0, MAX_DETAIL_LEVEL, "Stars");
handler->writeInt("num_stars", Detail.num_stars);
clamp_value_with_warn(&Detail.shield_effects, 0, MAX_DETAIL_LEVEL, "Shield Hit Effects");
handler->writeInt("shield_effects", Detail.shield_effects);
clamp_value_with_warn(&Detail.lighting, 0, MAX_DETAIL_LEVEL, "Lighting");
handler->writeInt("lighting", Detail.lighting);
handler->writeInt("targetview_model", Detail.targetview_model);
handler->writeInt("planets_suns", Detail.planets_suns);
handler->writeInt("weapon_extras", Detail.weapon_extras);
if (!clamped_range_warnings.empty()) {
ReleaseWarning(LOCATION, "The following values were out of bounds when saving the Pilot file and were automatically reset.\n%s\nThis shouldn't be possible, please contact the FreeSpace 2 Open Source Code Project!\n", clamped_range_warnings.c_str());
clamped_range_warnings.clear();
}
handler->endSectionWrite();
}
+13 -8
View File
@@ -510,6 +510,16 @@ void do_view_external()
Viewer_external_info.angles.h = PI2 + Viewer_external_info.angles.h;
}
/**
* Separate out the reading of thrust keys, so we can call this from external view as well as from normal view
*/
void do_thrust_keys(control_info *ci)
{
ci->forward = check_control_timef(FORWARD_THRUST) - check_control_timef(REVERSE_THRUST);
ci->sideways = (check_control_timef(RIGHT_SLIDE_THRUST) - check_control_timef(LEFT_SLIDE_THRUST));//for slideing-Bobboau
ci->vertical = (check_control_timef(UP_SLIDE_THRUST) - check_control_timef(DOWN_SLIDE_THRUST));//for slideing-Bobboau
}
/**
* Called by single and multiplayer modes to reset information inside of control info structure
*/
@@ -542,12 +552,12 @@ void read_keyboard_controls( control_info * ci, float frame_time, physics_info *
// Camera & View controls
if ( Viewer_mode & VM_EXTERNAL ) {
// External mode
control_used(VIEW_EXTERNAL);
do_view_external();
do_thrust_keys(ci);
} else if ( Viewer_mode & VM_CHASE ) {
// Chase mode
do_view_chase();
} else {
@@ -560,6 +570,7 @@ void read_keyboard_controls( control_info * ci, float frame_time, physics_info *
// Ship controls
if (Viewer_mode & VM_CAMERA_LOCKED) {
// From keyboard...
do_thrust_keys(ci);
if ( check_control(BANK_WHEN_PRESSED) ) {
ci->bank = check_control_timef(BANK_LEFT) + check_control_timef(YAW_LEFT) - check_control_timef(YAW_RIGHT) - check_control_timef(BANK_RIGHT);
ci->heading = 0.0f;
@@ -598,12 +609,6 @@ void read_keyboard_controls( control_info * ci, float frame_time, physics_info *
}
if (!(Game_mode & GM_DEAD)) {
// Thrust controls
ci->forward = check_control_timef(FORWARD_THRUST) - check_control_timef(REVERSE_THRUST);
ci->sideways = (check_control_timef(RIGHT_SLIDE_THRUST) - check_control_timef(LEFT_SLIDE_THRUST)); // for slideing-Bobboau
ci->vertical = (check_control_timef(UP_SLIDE_THRUST) - check_control_timef(DOWN_SLIDE_THRUST)); // for slideing-Bobboau
// Throttle controls
if ( button_info_query(&Player->bi, ONE_THIRD_THROTTLE) ) {
control_used(ONE_THIRD_THROTTLE);
player_clear_speed_matching();
+1 -6
View File
@@ -10,15 +10,10 @@ namespace api {
ADE_LIB(l_Time, "Time", "time", "Real-Time library");
ADE_FUNC(getCurrentTime, l_Time, nullptr, "Gets the current real-time timestamp, i.e. the actual elapsed time, regardless of whether the game has changed time compression or been paused.", "timestamp", "The current time")
ADE_FUNC(getCurrentTime, l_Time, nullptr, "Gets the current real-time timestamp.", "timestamp", "The current time")
{
return ade_set_args(L, "o", l_Timestamp.Set(timer_get_nanoseconds()));
}
ADE_FUNC(getCurrentMissionTime, l_Time, nullptr, "Gets the current mission-time timestamp, which can be affected by time compression and paused.", "timestamp", "The current mission time")
{
return ade_set_args(L, "o", l_Timestamp.Set(timestamp_get_mission_time_in_microseconds() * NANOSECONDS_PER_MICROSECOND));
}
} // namespace api
} // namespace scripting
+1 -1
View File
@@ -63,7 +63,7 @@ ADE_VIRTVAR(FPS, l_MoviePlayer, "number", "Determines the frames per second of t
LuaError(L, "Tried to modify read-only member!");
}
return ade_set_args(L, "f", ph->player()->getMovieProperties().fps);
return ade_set_args(L, "f", (int)ph->player()->getMovieProperties().fps);
}
ADE_FUNC(update, l_MoviePlayer, "timespan step_time",
+1 -1
View File
@@ -31,7 +31,7 @@ ADE_FUNC(getSeconds, l_TimeSpan, nullptr, "Gets the value of this timestamp in s
}
// Timestamps and spans are stored in nanoseconds
return ade_set_args(L, "f", (float)((long double)value / (long double)NANOSECONDS_PER_SECOND));
return ade_set_args(L, "f", (float)value / 1000000000.f);
}
} // namespace api
+2 -5
View File
@@ -172,15 +172,12 @@ LuaValueList LuaFunction::call(lua_State* L, const LuaValueList& args) const {
stackTop = lua_gettop(L);
}
if(!lua_checkstack(L, (int)args.size() + 1))
throw LuaException("Lua Stack Overflow!");
// Push the function onto the stack
this->pushValue(L, true);
this->pushValue(L);
// Push the arguments onto the stack
for (const auto& arg : args) {
arg.pushValue(L, true);
arg.pushValue(L);
}
// actually call the function now!
+1 -5
View File
@@ -80,14 +80,10 @@ bool UniqueLuaReference::isValid() const {
return true;
}
void UniqueLuaReference::pushValue(lua_State* thread, bool manualStackAllocation) const
void UniqueLuaReference::pushValue(lua_State* thread) const
{
Assertion(thread != nullptr, "Valid thread state must be specified!");
if (!manualStackAllocation) {
lua_checkstack(thread, 1);
}
if (this->isValid()) {
lua_rawgeti(thread, LUA_REGISTRYINDEX, this->getReference());
}
+1 -2
View File
@@ -100,9 +100,8 @@ class UniqueLuaReference {
/**
* @brief Pushes the referenced value onto the stack.
* @param thread A specific thread state to push the value to. nullptr for the default state of this reference
* @param manualStackAllocation Set to true if you manually allocate sufficient stack size before calling this function. Keep false unless you know what you are doing.
*/
void pushValue(lua_State* thread, bool manualStackAllocation = false) const;
void pushValue(lua_State* thread) const;
};
}
+2 -2
View File
@@ -88,10 +88,10 @@ bool LuaValue::isValid() const {
return _reference && _reference->isValid();
}
bool LuaValue::pushValue(lua_State* thread, bool manualStackAllocation) const
bool LuaValue::pushValue(lua_State* thread) const
{
if (this->_reference->isValid()) {
this->_reference->pushValue(thread, manualStackAllocation);
this->_reference->pushValue(thread);
return true;
} else {
return false;
+1 -2
View File
@@ -185,9 +185,8 @@ class LuaValue {
* @brief Pushes this lua value onto the stack.
* @param thread The thread stack onto which this value should be pushed. May be nullptr for the default state of
* this value
* @param manualStackAllocation Set to true if you manually allocate sufficient stack size before calling this function. Keep false unless you know what you are doing.
*/
bool pushValue(lua_State* thread, bool manualStackAllocation = false) const;
bool pushValue(lua_State* thread) const;
lua_State* getLuaState() const;
-6
View File
@@ -337,20 +337,14 @@ bool script_state::EvalStringWithReturn(const char* string, const char* format,
scripting::ade_get_args(LuaState, format, rtn);
}
} catch (const LuaException&) {
lua_pop(LuaState, 1);
return false;
}
} catch (const LuaException& e) {
LuaError(GetLuaSession(), "%s", e.what());
lua_pop(LuaState, 1);
return false;
}
lua_pop(LuaState, 1);
return true;
}
+2 -2
View File
@@ -4616,7 +4616,7 @@ static void parse_ship_values(ship_info* sip, const bool is_template, const bool
}
for (auto it = Ship_info.cbegin(); it != Ship_info.cend(); ++it) {
//find the index number of the current ship info type
if (&(*it) == sip) {
if (it->name == sip->name) {
Ai_tp_list[i].ship_class.push_back((int)std::distance(Ship_info.cbegin(), it));
break;
}
@@ -20263,4 +20263,4 @@ int ship_check_visibility(const ship* viewed, ship* viewer)
}
return ship_is_visible;
}
}
+2 -8
View File
@@ -423,7 +423,7 @@ int campaign_tree_wnd::internal_error(const char *msg, ...)
int campaign_tree_wnd::fred_check_sexp(int sexp, int type, char *msg, ...)
{
SCP_string buf, sexp_buf, error_buf, bad_node_str;
SCP_string buf, sexp_buf, error_buf;
int err = 0, z, faulty_node;
va_list args;
@@ -440,13 +440,7 @@ int campaign_tree_wnd::fred_check_sexp(int sexp, int type, char *msg, ...)
convert_sexp_to_string(sexp_buf, sexp, SEXP_ERROR_CHECK_MODE);
truncate_message_lines(sexp_buf, 30);
stuff_sexp_text_string(bad_node_str, faulty_node, SEXP_ERROR_CHECK_MODE);
if (!bad_node_str.empty()) { // the previous function adds a space at the end
bad_node_str.pop_back();
}
sprintf(error_buf, "Error in %s: %s\n\nIn sexpression: %s\n\n(Bad node appears to be: %s)", buf.c_str(), sexp_error_message(z), sexp_buf.c_str(), bad_node_str.c_str());
sprintf(error_buf, "Error in %s: %s\n\nIn sexpression: %s\n\n(Bad node appears to be: %s)", buf.c_str(), sexp_error_message(z), sexp_buf.c_str(), Sexp_nodes[faulty_node].text);
if (z < 0 && z > -100)
err = 1;
+1 -1
View File
@@ -445,7 +445,7 @@ IDR_MENU_EDIT_SEXP_TREE MENU
BEGIN
POPUP "Edit sexp tree"
BEGIN
MENUITEM "&Delete Item", ID_DELETE
MENUITEM "&Delete Item\tDelete", ID_DELETE
MENUITEM "&Edit Data\tSpace Bar", ID_EDIT_TEXT
MENUITEM "Expand All", ID_EXPAND_ALL
MENUITEM SEPARATOR
+2 -8
View File
@@ -3376,7 +3376,7 @@ int CFREDView::internal_error(const char *msg, ...)
int CFREDView::fred_check_sexp(int sexp, int type, const char *msg, ...)
{
SCP_string buf, sexp_buf, error_buf, bad_node_str;
SCP_string buf, sexp_buf, error_buf;
int err = 0, z, faulty_node;
va_list args;
@@ -3393,13 +3393,7 @@ int CFREDView::fred_check_sexp(int sexp, int type, const char *msg, ...)
convert_sexp_to_string(sexp_buf, sexp, SEXP_ERROR_CHECK_MODE);
truncate_message_lines(sexp_buf, 30);
stuff_sexp_text_string(bad_node_str, faulty_node, SEXP_ERROR_CHECK_MODE);
if (!bad_node_str.empty()) { // the previous function adds a space at the end
bad_node_str.pop_back();
}
sprintf(error_buf, "Error in %s: %s\n\nIn sexpression: %s\n\n(Bad node appears to be: %s)", buf.c_str(), sexp_error_message(z), sexp_buf.c_str(), bad_node_str.c_str());
sprintf(error_buf, "Error in %s: %s\n\nIn sexpression: %s\n\n(Bad node appears to be: %s)", buf.c_str(), sexp_error_message(z), sexp_buf.c_str(), Sexp_nodes[faulty_node].text);
if (z < 0 && z > -100)
err = 1;
+19 -58
View File
@@ -21,8 +21,7 @@
static char THIS_FILE[] = __FILE__;
#endif
constexpr auto INPUT_THRESHOLD = 0.01f; // smallest increment of input box
constexpr auto INPUT_FORMAT = "%.01f";
const float input_threshold = 0.01f; // smallest increment of input box
/////////////////////////////////////////////////////////////////////////////
// orient_editor dialog
@@ -46,15 +45,15 @@ orient_editor::orient_editor(CWnd* pParent /*=NULL*/)
Assert(query_valid_object());
auto pos = &Objects[cur_object_index].pos;
m_position_x.Format(INPUT_FORMAT, pos->xyz.x);
m_position_y.Format(INPUT_FORMAT, pos->xyz.y);
m_position_z.Format(INPUT_FORMAT, pos->xyz.z);
m_position_x.Format("%.01f", pos->xyz.x);
m_position_y.Format("%.01f", pos->xyz.y);
m_position_z.Format("%.01f", pos->xyz.z);
angles ang;
vm_extract_angles_matrix(&ang, &Objects[cur_object_index].orient);
m_orientation_p.Format(INPUT_FORMAT, to_degrees(ang.p));
m_orientation_b.Format(INPUT_FORMAT, to_degrees(ang.b));
m_orientation_h.Format(INPUT_FORMAT, to_degrees(ang.h));
m_orientation_p.Format("%.01f", to_degrees(ang.p));
m_orientation_b.Format("%.01f", to_degrees(ang.b));
m_orientation_h.Format("%.01f", to_degrees(ang.h));
}
void orient_editor::DoDataExchange(CDataExchange* pDX)
@@ -183,47 +182,29 @@ BOOL orient_editor::OnInitDialog()
return TRUE;
}
/**
* Checks whether the position value is close enough to the input string value that we can assume the input has not changed.
*/
bool orient_editor::is_close(float val, const CString &input_str) const
bool orient_editor::close(float val, const CString &str)
{
val = perform_input_rounding(val);
float input_val = convert(input_str);
float diff = val - input_val;
return abs(diff) < INPUT_THRESHOLD;
}
/**
* Checks whether the angle value is close enough to the input string value that we can assume the input has not changed.
*/
bool orient_editor::is_angle_close(float rad, const CString &input_str) const
{
float deg = perform_input_rounding(to_degrees(rad));
float input_deg = normalize_degrees(convert(input_str));
float diff = deg - input_deg;
return abs(diff) < INPUT_THRESHOLD;
float diff = val - convert(str);
return diff > -input_threshold && diff < input_threshold;
}
bool orient_editor::query_modified()
{
if (!is_close(Objects[cur_object_index].pos.xyz.x, m_position_x))
if (!close(Objects[cur_object_index].pos.xyz.x, m_position_x))
return true;
if (!is_close(Objects[cur_object_index].pos.xyz.y, m_position_y))
if (!close(Objects[cur_object_index].pos.xyz.y, m_position_y))
return true;
if (!is_close(Objects[cur_object_index].pos.xyz.z, m_position_z))
if (!close(Objects[cur_object_index].pos.xyz.z, m_position_z))
return true;
angles ang;
vm_extract_angles_matrix(&ang, &Objects[cur_object_index].orient);
if (!is_angle_close(ang.p, m_orientation_p))
if (!close(to_degrees(ang.p), m_orientation_p))
return true;
if (!is_angle_close(ang.b, m_orientation_b))
if (!close(to_degrees(ang.b), m_orientation_b))
return true;
if (!is_angle_close(ang.h, m_orientation_h))
if (!close(to_degrees(ang.h), m_orientation_h))
return true;
if (((CButton *) GetDlgItem(IDC_POINT_TO_CHECKBOX))->GetCheck() == TRUE)
@@ -243,7 +224,7 @@ void orient_editor::OnOK()
// there's enough difference in our position that we're changing it
cur_pos = &Objects[cur_object_index].pos;
if (!is_close(cur_pos->xyz.x, m_position_x) || !is_close(cur_pos->xyz.y, m_position_y) || !is_close(cur_pos->xyz.z, m_position_z))
if (!close(cur_pos->xyz.x, m_position_x) || !close(cur_pos->xyz.y, m_position_y) || !close(cur_pos->xyz.z, m_position_z))
{
vec3d pos;
pos.xyz.x = convert(m_position_x);
@@ -256,7 +237,7 @@ void orient_editor::OnOK()
// there's enough difference in our orientation that we're changing it
vm_extract_angles_matrix(&ang, &Objects[cur_object_index].orient);
if (!is_angle_close(ang.p, m_orientation_p) || !is_angle_close(ang.b, m_orientation_b) || !is_angle_close(ang.h, m_orientation_h))
if (!close(to_degrees(ang.p), m_orientation_p) || !close(to_degrees(ang.b), m_orientation_b) || !close(to_degrees(ang.h), m_orientation_h))
{
ang.p = fl_radians(convert(m_orientation_p));
ang.b = fl_radians(convert(m_orientation_b));
@@ -373,11 +354,6 @@ void orient_editor::actually_point_object(object *ptr)
float orient_editor::to_degrees(float rad)
{
float deg = fl_degrees(rad);
return normalize_degrees(deg);
}
float orient_editor::normalize_degrees(float deg)
{
while (deg < -180.0f)
deg += 180.0f;
while (deg > 180.0f)
@@ -388,10 +364,7 @@ float orient_editor::normalize_degrees(float deg)
return deg;
}
/**
* Extract a float from the CString, being mindful of any comma separators.
*/
float orient_editor::convert(const CString &str) const
float orient_editor::convert(const CString &str)
{
char buf[256];
size_t i, j, len;
@@ -406,18 +379,6 @@ float orient_editor::convert(const CString &str) const
return (float) atof(buf);
}
/**
* Perform rounding of the float value by loading it into the input box format string and parsing it again.
* This accounts for not only decimal rounding to the precision of the input box, but also floating point rounding due to inexact fractions such as 1/10.
* See also GitHub PR #4475.
*/
float orient_editor::perform_input_rounding(float val) const
{
CString str;
str.Format(INPUT_FORMAT, val);
return convert(str);
}
void orient_editor::OnPointTo()
{
UpdateData(TRUE);
+2 -7
View File
@@ -24,7 +24,6 @@ public:
orient_editor(CWnd* pParent = NULL); // standard constructor
static float to_degrees(float radians);
static float normalize_degrees(float degrees);
// Dialog Data
//{{AFX_DATA(orient_editor)
@@ -70,12 +69,8 @@ protected:
DECLARE_MESSAGE_MAP()
private:
float convert(const CString &str) const;
float perform_input_rounding(float val) const;
bool is_close(float val, const CString &input_str) const;
bool is_angle_close(float rad, const CString &input_str) const;
float convert(const CString &str);
bool close(float val, const CString &str);
int total;
int index[MAX_OBJECTS];
void actually_point_object(object *ptr);
+4 -4
View File
@@ -2509,13 +2509,13 @@ void sexp_tree::NodeCopy()
void sexp_tree::NodeReplacePaste()
{
if (item_index < 0 || Sexp_clipboard < 0)
if (item_index < 0)
return;
int i;
// the following assumptions are made..
Assert(Sexp_nodes[Sexp_clipboard].type != SEXP_NOT_USED);
Assert((Sexp_clipboard > -1) && (Sexp_nodes[Sexp_clipboard].type != SEXP_NOT_USED));
Assert(Sexp_nodes[Sexp_clipboard].subtype != SEXP_ATOM_LIST);
Assertion(Sexp_nodes[Sexp_clipboard].subtype != SEXP_ATOM_CONTAINER_NAME,
"Attempt to use container name %s from SEXP clipboard. Please report!",
@@ -2587,13 +2587,13 @@ void sexp_tree::NodeReplacePaste()
void sexp_tree::NodeAddPaste()
{
if (item_index < 0 || Sexp_clipboard < 0)
if (item_index < 0)
return;
int i;
// the following assumptions are made..
Assert(Sexp_nodes[Sexp_clipboard].type != SEXP_NOT_USED);
Assert((Sexp_clipboard > -1) && (Sexp_nodes[Sexp_clipboard].type != SEXP_NOT_USED));
Assert(Sexp_nodes[Sexp_clipboard].subtype != SEXP_ATOM_LIST);
Assertion(Sexp_nodes[Sexp_clipboard].subtype != SEXP_ATOM_CONTAINER_NAME,
"Attempt to use container name %s from SEXP clipboard. Please report!",
+17 -16
View File
@@ -902,7 +902,6 @@ void game_level_close()
lock_time_compression(false);
audiostream_unpause_all();
snd_aav_init();
gr_set_ambient_light(120, 120, 120);
@@ -1193,7 +1192,7 @@ void game_loading_callback(int count)
Script_system.RemHookVar("Progress");
os_defer_events_on_load_screen();
os_ignore_events();
if (do_flip)
gr_flip();
@@ -5273,6 +5272,7 @@ void game_leave_state( int old_state, int new_state )
if ( (Game_mode & GM_MULTIPLAYER) && (new_state == GS_STATE_MAIN_MENU) ){
multi_quit_game(PROMPT_NONE);
}
snd_aav_init();
freespace_stop_mission();
@@ -6683,7 +6683,17 @@ void game_shutdown(void)
gr_clear();
gr_flip();
}
// Free the scripting resources of the new UI first
scpui::shutdown_scripting();
// Everything after this should be done without scripting so we can free those resources here
Script_system.Clear();
// Deinitialize the new UI system, needs to be done after scripting shutdown to make sure the resources were
// released properly
scpui::shutdown();
// if the player has left the "player select" screen and quit the game without actually choosing
// a player, Player will be nullptr, in which case we shouldn't write the player file out!
if (!(Game_mode & GM_STANDALONE_SERVER) && (Player!=nullptr) && !Is_standalone){
@@ -6719,6 +6729,9 @@ void game_shutdown(void)
scoring_close();
// Free SEXP resources
sexp_shutdown();
stars_close(); // clean out anything used by stars code
// the menu close functions will unload the bitmaps if they were displayed during the game
@@ -6728,19 +6741,6 @@ void game_shutdown(void)
// free left over memory from table parsing
player_tips_close();
// more fundamental shutdowns begin here ----------
sexp_shutdown(); // Free SEXP resources
scpui::shutdown_scripting(); // Free the scripting resources of the new UI first
Script_system.Clear(); // Everything after this should be done without scripting so we can free those resources here.
// By this point, all things that hold Lua References must be destroyed (such as Lua SEXPs)
scpui::shutdown(); // Deinitialize the new UI system, needs to be done after scripting shutdown to make sure the resources were released properly
control_config_common_close();
io::joystick::shutdown();
@@ -6779,6 +6779,7 @@ void game_shutdown(void)
}
lcl_xstr_close();
}
// game_stop_looped_sounds()
+2 -8
View File
@@ -2571,7 +2571,7 @@ int Editor::internal_error(const char* msg, ...) {
return -1;
}
int Editor::fred_check_sexp(int sexp, int type, const char* msg, ...) {
SCP_string buf, sexp_buf, error_buf, bad_node_str;
SCP_string buf, sexp_buf, error_buf;
int err = 0, z, faulty_node;
va_list args;
@@ -2588,18 +2588,12 @@ int Editor::fred_check_sexp(int sexp, int type, const char* msg, ...) {
convert_sexp_to_string(sexp_buf, sexp, SEXP_ERROR_CHECK_MODE);
truncate_message_lines(sexp_buf, 30);
stuff_sexp_text_string(bad_node_str, faulty_node, SEXP_ERROR_CHECK_MODE);
if (!bad_node_str.empty()) { // the previous function adds a space at the end
bad_node_str.pop_back();
}
sprintf(error_buf,
"Error in %s: %s\n\nIn sexpression: %s\n\n(Bad node appears to be: %s)",
buf.c_str(),
sexp_error_message(z),
sexp_buf.c_str(),
bad_node_str.c_str());
Sexp_nodes[faulty_node].text);
if (z < 0 && z > -100)
err = 1;
+5
View File
@@ -0,0 +1,5 @@
set(FSO_VERSION_MAJOR 22)
set(FSO_VERSION_MINOR 2)
set(FSO_VERSION_BUILD 0)
set(FSO_VERSION_REVISION 0)
set(FSO_VERSION_REVISION_STR RC5)