mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-09 04:49:39 -10:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cad971f7b2 |
No files matched your search
+132
-180
@@ -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)))
|
||||
|
||||
@@ -51,7 +51,6 @@ void processEvents()
|
||||
{
|
||||
io::mouse::CursorManager::get()->showCursor(false);
|
||||
|
||||
os_remove_deferred_cutscene_key_events();
|
||||
os_poll();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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++ )
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
Reference in new issue
Block a user