From 1a060aa6d7870d709bc9da78b5d06035ef522422 Mon Sep 17 00:00:00 2001 From: Fabian Woltermann Date: Fri, 19 Aug 2016 09:24:54 +0200 Subject: [PATCH 01/16] Converts the other weapon flags --- code/ai/aibig.cpp | 6 +-- code/ai/aicode.cpp | 6 +-- code/ai/aiturret.cpp | 4 +- code/object/collideweaponweapon.cpp | 20 +++++----- code/object/object.cpp | 2 +- code/parse/lua.cpp | 7 +--- code/ship/ship.cpp | 2 +- code/stats/scoring.cpp | 2 +- code/weapon/emp.cpp | 2 +- code/weapon/shockwave.cpp | 2 +- code/weapon/weapon.h | 17 +------- code/weapon/weapons.cpp | 60 ++++++++++++++--------------- 12 files changed, 57 insertions(+), 73 deletions(-) diff --git a/code/ai/aibig.cpp b/code/ai/aibig.cpp index bb1959725d..4f4f4bd70d 100644 --- a/code/ai/aibig.cpp +++ b/code/ai/aibig.cpp @@ -786,13 +786,13 @@ void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy, vec3d *f int current_bank_adjusted = MAX_SHIP_PRIMARY_BANKS + current_bank; - if ((aip->ai_flags & AIF_UNLOAD_SECONDARIES) || (swip->burst_flags & WBF_FAST_FIRING)) { + if ((aip->ai_flags & AIF_UNLOAD_SECONDARIES) || (swip->burst_flags[Weapon::Burst_Flags::Fast_firing])) { if (swip->burst_shots > swp->burst_counter[current_bank_adjusted]) { t = swip->burst_delay; swp->burst_counter[current_bank_adjusted]++; } else { t = swip->fire_wait; - if ((swip->burst_shots > 0) && (swip->burst_flags & WBF_RANDOM_LENGTH)) { + if ((swip->burst_shots > 0) && (swip->burst_flags[Weapon::Burst_Flags::Random_length])) { swp->burst_counter[current_bank_adjusted] = myrand() % swip->burst_shots; } else { swp->burst_counter[current_bank_adjusted] = 0; @@ -804,7 +804,7 @@ void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy, vec3d *f swp->burst_counter[current_bank_adjusted]++; } else { t = set_secondary_fire_delay(aip, temp_shipp, swip, false); - if ((swip->burst_shots > 0) && (swip->burst_flags & WBF_RANDOM_LENGTH)) { + if ((swip->burst_shots > 0) && (swip->burst_flags[Weapon::Burst_Flags::Random_length])) { swp->burst_counter[current_bank_adjusted] = myrand() % swip->burst_shots; } else { swp->burst_counter[current_bank_adjusted] = 0; diff --git a/code/ai/aicode.cpp b/code/ai/aicode.cpp index c87b20b723..ac59b713bf 100644 --- a/code/ai/aicode.cpp +++ b/code/ai/aicode.cpp @@ -8842,13 +8842,13 @@ void ai_chase() float t; int current_bank_adjusted = MAX_SHIP_PRIMARY_BANKS + current_bank; - if ((aip->ai_flags & AIF_UNLOAD_SECONDARIES) || (swip->burst_flags & WBF_FAST_FIRING)) { + if ((aip->ai_flags & AIF_UNLOAD_SECONDARIES) || (swip->burst_flags[Weapon::Burst_Flags::Fast_firing])) { if (swip->burst_shots > swp->burst_counter[current_bank_adjusted]) { t = swip->burst_delay; swp->burst_counter[current_bank_adjusted]++; } else { t = swip->fire_wait; - if ((swip->burst_shots > 0) && (swip->burst_flags & WBF_RANDOM_LENGTH)) { + if ((swip->burst_shots > 0) && (swip->burst_flags[Weapon::Burst_Flags::Random_length])) { swp->burst_counter[current_bank_adjusted] = myrand() % swip->burst_shots; } else { swp->burst_counter[current_bank_adjusted] = 0; @@ -8860,7 +8860,7 @@ void ai_chase() swp->burst_counter[current_bank_adjusted]++; } else { t = set_secondary_fire_delay(aip, temp_shipp, swip, false); - if ((swip->burst_shots > 0) && (swip->burst_flags & WBF_RANDOM_LENGTH)) { + if ((swip->burst_shots > 0) && (swip->burst_flags[Weapon::Burst_Flags::Random_length])) { swp->burst_counter[current_bank_adjusted] = myrand() % swip->burst_shots; } else { swp->burst_counter[current_bank_adjusted] = 0; diff --git a/code/ai/aiturret.cpp b/code/ai/aiturret.cpp index 7a588fe313..02d78c60e3 100644 --- a/code/ai/aiturret.cpp +++ b/code/ai/aiturret.cpp @@ -1677,7 +1677,7 @@ void turret_set_next_fire_timestamp(int weapon_num, weapon_info *wip, ship_subsy turret->weapons.burst_counter[weapon_num]++; } else { wait *= wip->fire_wait; - if ((wip->burst_shots > 0) && (wip->burst_flags & WBF_RANDOM_LENGTH)) { + if ((wip->burst_shots > 0) && (wip->burst_flags[Weapon::Burst_Flags::Random_length])) { turret->weapons.burst_counter[weapon_num] = (myrand() % wip->burst_shots); } else { turret->weapons.burst_counter[weapon_num] = 0; @@ -1691,7 +1691,7 @@ void turret_set_next_fire_timestamp(int weapon_num, weapon_info *wip, ship_subsy fs_dest = &turret->weapons.next_secondary_fire_stamp[weapon_num - MAX_SHIP_PRIMARY_BANKS]; //Check for the new cooldown flag - if(!((wip->wi_flags[Weapon::Info_Flags::Same_turret_cooldown]) || ((wip->burst_shots > 0) && (wip->burst_flags & WBF_FAST_FIRING)))) + if(!((wip->wi_flags[Weapon::Info_Flags::Same_turret_cooldown]) || ((wip->burst_shots > 0) && (wip->burst_flags[Weapon::Burst_Flags::Fast_firing])))) { // make side even for team vs. team diff --git a/code/object/collideweaponweapon.cpp b/code/object/collideweaponweapon.cpp index 5b770f0041..34d61bfc14 100644 --- a/code/object/collideweaponweapon.cpp +++ b/code/object/collideweaponweapon.cpp @@ -104,8 +104,8 @@ int collide_weapon_weapon( obj_pair * pair ) if ((wipA->wi_flags[Weapon::Info_Flags::Bomb]) && (wipB->wi_flags[Weapon::Info_Flags::Bomb])) { wpA->lifeleft = 0.01f; wpB->lifeleft = 0.01f; - wpA->weapon_flags |= WF_DESTROYED_BY_WEAPON; - wpB->weapon_flags |= WF_DESTROYED_BY_WEAPON; + wpA->weapon_flags.set(Weapon::Weapon_Flags::Destroyed_by_weapon); + wpB->weapon_flags.set(Weapon::Weapon_Flags::Destroyed_by_weapon); } else { A->hull_strength -= bDamage; B->hull_strength -= aDamage; @@ -121,29 +121,29 @@ int collide_weapon_weapon( obj_pair * pair ) if (A->hull_strength < 0.0f) { wpA->lifeleft = 0.01f; - wpA->weapon_flags |= WF_DESTROYED_BY_WEAPON; + wpA->weapon_flags.set(Weapon::Weapon_Flags::Destroyed_by_weapon); } if (B->hull_strength < 0.0f) { wpB->lifeleft = 0.01f; - wpB->weapon_flags |= WF_DESTROYED_BY_WEAPON; + wpB->weapon_flags.set(Weapon::Weapon_Flags::Destroyed_by_weapon); } } } else { A->hull_strength -= bDamage; wpB->lifeleft = 0.01f; - wpB->weapon_flags |= WF_DESTROYED_BY_WEAPON; + wpB->weapon_flags.set(Weapon::Weapon_Flags::Destroyed_by_weapon); if (A->hull_strength < 0.0f) { wpA->lifeleft = 0.01f; - wpA->weapon_flags |= WF_DESTROYED_BY_WEAPON; + wpA->weapon_flags.set(Weapon::Weapon_Flags::Destroyed_by_weapon); } } } else if (wipB->weapon_hitpoints > 0) { B->hull_strength -= aDamage; wpA->lifeleft = 0.01f; - wpA->weapon_flags |= WF_DESTROYED_BY_WEAPON; + wpA->weapon_flags.set(Weapon::Weapon_Flags::Destroyed_by_weapon); if (B->hull_strength < 0.0f) { wpB->lifeleft = 0.01f; - wpB->weapon_flags |= WF_DESTROYED_BY_WEAPON; + wpB->weapon_flags.set(Weapon::Weapon_Flags::Destroyed_by_weapon); } } @@ -154,14 +154,14 @@ int collide_weapon_weapon( obj_pair * pair ) if (wipA->wi_flags[Weapon::Info_Flags::Bomb]) { //Update stats. -Halleck scoring_eval_hit(A, B, 0); - if (wpA->weapon_flags & WF_DESTROYED_BY_WEAPON) { + if (wpA->weapon_flags[Weapon::Weapon_Flags::Destroyed_by_weapon]) { scoring_eval_kill_on_weapon(A, B); } } if (wipB->wi_flags[Weapon::Info_Flags::Bomb]) { //Update stats. -Halleck scoring_eval_hit(B, A, 0); - if (wpB->weapon_flags & WF_DESTROYED_BY_WEAPON) { + if (wpB->weapon_flags[Weapon::Weapon_Flags::Destroyed_by_weapon]) { scoring_eval_kill_on_weapon(B, A); } } diff --git a/code/object/object.cpp b/code/object/object.cpp index a170d4baba..8f1c3e42b5 100644 --- a/code/object/object.cpp +++ b/code/object/object.cpp @@ -853,7 +853,7 @@ void obj_move_call_physics(object *objp, float frametime) } // if a weapon is flagged as dead, kill its engines just like a ship - if((objp->type == OBJ_WEAPON) && (Weapons[objp->instance].weapon_flags & WF_DEAD_IN_WATER)){ + if((objp->type == OBJ_WEAPON) && (Weapons[objp->instance].weapon_flags[Weapon::Weapon_Flags::Dead_in_water])){ vm_vec_zero(&objp->phys_info.desired_vel); vm_vec_zero(&objp->phys_info.desired_rotvel); objp->phys_info.flags |= (PF_REDUCED_DAMP | PF_DEAD_DAMP); diff --git a/code/parse/lua.cpp b/code/parse/lua.cpp index ccf83896ae..8a169342ef 100644 --- a/code/parse/lua.cpp +++ b/code/parse/lua.cpp @@ -10745,13 +10745,10 @@ ADE_VIRTVAR(DestroyedByWeapon, l_Weapon, "boolean", "Whether weapon was destroye weapon *wp = &Weapons[oh->objp->instance]; if(ADE_SETTING_VAR && numargs > 1) { - if(b) - wp->weapon_flags |= WF_DESTROYED_BY_WEAPON; - else - wp->weapon_flags &= ~WF_DESTROYED_BY_WEAPON; + wp->weapon_flags.set(Weapon::Weapon_Flags::Destroyed_by_weapon, b); } - return ade_set_args(L, "b", (wp->weapon_flags & WF_DESTROYED_BY_WEAPON) > 0); + return ade_set_args(L, "b", (wp->weapon_flags[Weapon::Weapon_Flags::Destroyed_by_weapon]) > 0); } ADE_VIRTVAR(LifeLeft, l_Weapon, "number", "Weapon life left (in seconds)", "number", "Life left (seconds) or 0 if weapon handle is invalid") diff --git a/code/ship/ship.cpp b/code/ship/ship.cpp index 14c7477556..58f5fbdbbd 100644 --- a/code/ship/ship.cpp +++ b/code/ship/ship.cpp @@ -10767,7 +10767,7 @@ int ship_fire_primary(object * obj, int stream_weapons, int force) if (winfo_p->burst_shots > swp->burst_counter[bank_to_fire]) { next_fire_delay = winfo_p->burst_delay * 1000.0f; swp->burst_counter[bank_to_fire]++; - if (winfo_p->burst_flags & WBF_FAST_FIRING) + if (winfo_p->burst_flags[Weapon::Burst_Flags::Fast_firing]) fast_firing = true; } else if (winfo_p->max_delay != 0.0f && winfo_p->min_delay != 0.0f) { // Random fire delay (DahBlount) next_fire_delay = (((float)rand()) / (((float)RAND_MAX + 1.0f) * (winfo_p->max_delay - winfo_p->min_delay + 1.0f) + winfo_p->min_delay)) * 1000.0f; diff --git a/code/stats/scoring.cpp b/code/stats/scoring.cpp index 67252b29ab..3abd30b5b8 100644 --- a/code/stats/scoring.cpp +++ b/code/stats/scoring.cpp @@ -1086,7 +1086,7 @@ void scoring_eval_hit(object *hit_obj, object *other_obj,int from_blast) return; } - if((other_obj->type == OBJ_WEAPON) && !(Weapons[other_obj->instance].weapon_flags & WF_ALREADY_APPLIED_STATS)){ + if((other_obj->type == OBJ_WEAPON) && !(Weapons[other_obj->instance].weapon_flags[Weapon::Weapon_Flags::Already_applied_stats])){ // bogus weapon if(other_obj->instance >= MAX_WEAPONS){ return; diff --git a/code/weapon/emp.cpp b/code/weapon/emp.cpp index 39b665694a..5f401828c1 100644 --- a/code/weapon/emp.cpp +++ b/code/weapon/emp.cpp @@ -138,7 +138,7 @@ void emp_apply(vec3d *pos, float inner_radius, float outer_radius, float emp_int // if the bomb was within 1/4 of the outer radius, castrate it if(dist_mag <= (outer_radius * 0.25f)){ // memset(&target->phys_info, 0, sizeof(physics_info)); - Weapons[target->instance].weapon_flags |= WF_DEAD_IN_WATER; + Weapons[target->instance].weapon_flags.set(Weapon::Weapon_Flags::Dead_in_water); mprintf(("EMP killing weapon\n")); } } diff --git a/code/weapon/shockwave.cpp b/code/weapon/shockwave.cpp index c1023c7081..e10f39c55d 100644 --- a/code/weapon/shockwave.cpp +++ b/code/weapon/shockwave.cpp @@ -328,7 +328,7 @@ void shockwave_move(object *shockwave_objp, float frametime) objp->hull_strength -= damage; if (objp->hull_strength < 0.0f) { Weapons[objp->instance].lifeleft = 0.01f; - Weapons[objp->instance].weapon_flags |= WF_DESTROYED_BY_WEAPON; + Weapons[objp->instance].weapon_flags.set(Weapon::Weapon_Flags::Destroyed_by_weapon); } break; default: diff --git a/code/weapon/weapon.h b/code/weapon/weapon.h index 90f3f43eec..1a303f75a8 100644 --- a/code/weapon/weapon.h +++ b/code/weapon/weapon.h @@ -41,19 +41,6 @@ extern int Num_weapon_subtypes; #define WEAPON_EXHAUST_DELTA_TIME 75 // Delay in milliseconds between exhaust blobs -#define WF_LOCK_WARNING_PLAYED (1<<0) // set when a lock warning sound is played for the player - // (needed since we don't want to play multiple lock sounds) -#define WF_ALREADY_APPLIED_STATS (1<<1) // for use in ship_apply_local and ship_apply_global damage functions - // so that we don't record multiple hits (stats) for one impact -#define WF_PLAYED_FLYBY_SOUND (1<<2) // flyby sound has been played for this weapon -#define WF_CONSIDER_FOR_FLYBY_SOUND (1<<3) // consider for flyby -#define WF_DEAD_IN_WATER (1<<4) // a missiles engines have died -#define WF_LOCKED_WHEN_FIRED (1<<5) // fired with a lock -#define WF_DESTROYED_BY_WEAPON (1<<6) // destroyed by damage from other weapon -#define WF_SPAWNED (1<<7) //Spawned from a spawning type weapon -#define WF_HOMING_UPDATE_NEEDED (1<<8) // this is a newly spawned homing weapon which needs to update client machines -#define WF_NO_HOMING (1<<9) // this weapon should ignore any homing behavior it'd usually have - // flags for setting burst fire #define WBF_FAST_FIRING (1<<0) // burst is to use only the firewait to determine firing delays #define WBF_RANDOM_LENGTH (1<<1) // burst is to fire random length bursts @@ -101,7 +88,7 @@ typedef struct weapon { int target_sig; // So we know if the target is the same one we've been tracking float nearest_dist; // nearest distance yet attained to target fix creation_time; // time at which created, stuffed Missiontime - int weapon_flags; // bit flags defining behavior, see WF_xxxx + flagset weapon_flags; // bit flags defining behavior, see WF_xxxx object* homing_object; // object this weapon is homing on. ship_subsys* homing_subsys; // subsystem this weapon is homing on vec3d homing_pos; // world position missile is homing on @@ -450,7 +437,7 @@ typedef struct weapon_info { int burst_shots; float burst_delay; - int burst_flags; + flagset burst_flags; // Thruster effects generic_anim thruster_flame; diff --git a/code/weapon/weapons.cpp b/code/weapon/weapons.cpp index b199353ef5..6bf38e912d 100644 --- a/code/weapon/weapons.cpp +++ b/code/weapon/weapons.cpp @@ -94,12 +94,12 @@ char *Weapon_subtype_names[] = { }; int Num_weapon_subtypes = sizeof(Weapon_subtype_names)/sizeof(char *); -flag_def_list Burst_fire_flags[] = { - { "fast firing", WBF_FAST_FIRING, 0 }, - { "random length", WBF_RANDOM_LENGTH, 0 } +flag_def_list_new Burst_fire_flags[] = { + { "fast firing", Weapon::Burst_Flags::Fast_firing, true, false }, + { "random length", Weapon::Burst_Flags::Random_length, true, false } }; -int Num_burst_fire_flags = sizeof(Burst_fire_flags)/sizeof(flag_def_list); +const int Num_burst_fire_flags = sizeof(Burst_fire_flags)/sizeof(flag_def_list_new); weapon_explosions Weapon_explosions; @@ -2641,7 +2641,7 @@ int parse_weapon(int subtype, bool replace, const char *filename) } if (optional_string("$Burst Flags:")) { - parse_string_flag_list((int*)&wip->burst_flags, Burst_fire_flags, Num_burst_fire_flags); + parse_string_flag_list(wip->burst_flags, Burst_fire_flags, Num_burst_fire_flags, NULL); } if (optional_string("$Thruster Flame Effect:")) { @@ -3591,8 +3591,8 @@ void weapon_delete(object *obj) void weapon_maybe_play_warning(weapon *wp) { if ( wp->homing_object == Player_obj ) { - if ( !(wp->weapon_flags & WF_LOCK_WARNING_PLAYED) ) { - wp->weapon_flags |= WF_LOCK_WARNING_PLAYED; + if ( !(wp->weapon_flags[Weapon::Weapon_Flags::Lock_warning_played]) ) { + wp->weapon_flags.set(Weapon::Weapon_Flags::Lock_warning_played); // Use heatlock-warning sound for Heat and Javelin for now // Possibly add an additional third sound later if ( (Weapon_info[wp->weapon_info_index].wi_flags[Weapon::Info_Flags::Homing_heat]) || @@ -3689,11 +3689,11 @@ void find_homing_object(object *weapon_objp, int num) //WMC - Spawn weapons shouldn't go for protected ships // ditto for untargeted heat seekers - niffiwan if ( (objp->flags[Object::Object_Flags::Protected]) && - ((wp->weapon_flags & WF_SPAWNED) || (wip->wi_flags[Weapon::Info_Flags::Untargeted_heat_seeker])) ) + ((wp->weapon_flags[Weapon::Weapon_Flags::Spawned]) || (wip->wi_flags[Weapon::Info_Flags::Untargeted_heat_seeker])) ) continue; // Spawned weapons should never home in on their parent - even in multiplayer dogfights where they would pass the iff test below - if ((wp->weapon_flags & WF_SPAWNED) && (objp == &Objects[weapon_objp->parent])) + if ((wp->weapon_flags[Weapon::Weapon_Flags::Spawned]) && (objp == &Objects[weapon_objp->parent])) continue; homing_object_team = obj_team(objp); @@ -4008,8 +4008,8 @@ void weapon_home(object *obj, int num, float frame_time) return; } } - else if (MULTIPLAYER_MASTER && (wip->is_locked_homing()) && (wp->weapon_flags & WF_HOMING_UPDATE_NEEDED)) { - wp->weapon_flags &= ~WF_HOMING_UPDATE_NEEDED; + else if (MULTIPLAYER_MASTER && (wip->is_locked_homing()) && (wp->weapon_flags[Weapon::Weapon_Flags::Homing_update_needed])) { + wp->weapon_flags.remove(Weapon::Weapon_Flags::Homing_update_needed); send_homing_weapon_info(num); } @@ -4435,7 +4435,7 @@ void weapon_maybe_play_flyby_sound(object *weapon_objp, weapon *wp) return; } - if ( !(wp->weapon_flags & WF_PLAYED_FLYBY_SOUND) && (wp->weapon_flags & WF_CONSIDER_FOR_FLYBY_SOUND) ) { + if ( !(wp->weapon_flags[Weapon::Weapon_Flags::Played_flyby_sound]) && (wp->weapon_flags[Weapon::Weapon_Flags::Consider_for_flyby_sound]) ) { float dist, dot, radius; if ( (Weapon_info[wp->weapon_info_index].wi_flags[Weapon::Info_Flags::Corkscrew]) ) { @@ -4474,7 +4474,7 @@ void weapon_maybe_play_flyby_sound(object *weapon_objp, weapon *wp) } } Weapon_flyby_sound_timer = timestamp(200); - wp->weapon_flags |= WF_PLAYED_FLYBY_SOUND; + wp->weapon_flags.set(Weapon::Weapon_Flags::Played_flyby_sound); } } } @@ -4716,7 +4716,7 @@ void weapon_process_post(object * obj, float frame_time) } // a single player or multiplayer server function -- it affects actual weapon movement. - if (wip->is_homing() && !(wp->weapon_flags & WF_NO_HOMING)) { + if (wip->is_homing() && !(wp->weapon_flags[Weapon::Weapon_Flags::No_homing])) { weapon_home(obj, num, frame_time); // If this is a swarm type missile, @@ -4905,7 +4905,7 @@ void weapon_set_tracking_info(int weapon_objnum, int parent_objnum, int target_o wp = &Weapons[Objects[weapon_objnum].instance]; wip = &Weapon_info[wp->weapon_info_index]; - if (wp->weapon_flags & WF_NO_HOMING) { + if (wp->weapon_flags[Weapon::Weapon_Flags::No_homing]) { return; } @@ -4917,7 +4917,7 @@ void weapon_set_tracking_info(int weapon_objnum, int parent_objnum, int target_o } if (parent_objp != NULL && (Ships[parent_objp->instance].flags[Ship::Ship_Flags::No_secondary_lockon])) { - wp->weapon_flags |= WF_NO_HOMING; + wp->weapon_flags.set(Weapon::Weapon_Flags::No_homing); wp->homing_object = &obj_used_list; wp->homing_subsys = NULL; wp->target_num = -1; @@ -5002,7 +5002,7 @@ void weapon_set_tracking_info(int weapon_objnum, int parent_objnum, int target_o if (target_is_locked && (wp->target_num != -1) && (wip->is_locked_homing()) ) { wp->lifeleft *= LOCKED_HOMING_EXTENDED_LIFE_FACTOR; if (MULTIPLAYER_MASTER) { - wp->weapon_flags |= WF_HOMING_UPDATE_NEEDED; + wp->weapon_flags.set(Weapon::Weapon_Flags::Homing_update_needed); } } @@ -5202,7 +5202,7 @@ int weapon_create( vec3d * pos, matrix * porient, int weapon_type, int parent_ob } wp->turret_subsys = NULL; vm_vec_zero(&wp->homing_pos); - wp->weapon_flags = 0; + wp->weapon_flags.reset(); wp->target_sig = -1; wp->cmeasure_ignore_list = nullptr; wp->det_range = wip->det_range; @@ -5415,7 +5415,7 @@ int weapon_create( vec3d * pos, matrix * porient, int weapon_type, int parent_ob // Ensure weapon flyby sound doesn't get played for player lasers if ( parent_objp != NULL && parent_objp == Player_obj ) { - wp->weapon_flags |= WF_PLAYED_FLYBY_SOUND; + wp->weapon_flags.set(Weapon::Weapon_Flags::Played_flyby_sound); } wp->pick_big_attack_point_timestamp = timestamp(1); @@ -5446,12 +5446,12 @@ int weapon_create( vec3d * pos, matrix * porient, int weapon_type, int parent_ob // if the weapon was fired locked if(is_locked){ - wp->weapon_flags |= WF_LOCKED_WHEN_FIRED; + wp->weapon_flags.set(Weapon::Weapon_Flags::Locked_when_fired); } //if the weapon was spawned from a spawning type weapon if(is_spawned){ - wp->weapon_flags |= WF_SPAWNED; + wp->weapon_flags.set(Weapon::Weapon_Flags::Spawned); } wp->alpha_current = -1.0f; @@ -5564,7 +5564,7 @@ void spawn_child_weapons(object *objp) beam_fire(&fire_info); } else { vm_vector_2_matrix(&orient, &tvec, NULL, NULL); - weapon_objnum = weapon_create(&pos, &orient, child_id, parent_num, -1, wp->weapon_flags & WF_LOCKED_WHEN_FIRED, 1); + weapon_objnum = weapon_create(&pos, &orient, child_id, parent_num, -1, wp->weapon_flags[Weapon::Weapon_Flags::Locked_when_fired], 1); //if the child inherits parent target, do it only if the parent weapon was locked to begin with if ((child_wip->wi_flags[Weapon::Info_Flags::Inherit_parent_target]) && (wp->homing_object != &obj_used_list)) @@ -5977,7 +5977,7 @@ void weapon_do_area_effect(object *wobjp, shockwave_create_info *sci, vec3d *pos objp->hull_strength -= damage; if (objp->hull_strength < 0.0f) { Weapons[objp->instance].lifeleft = 0.01f; - Weapons[objp->instance].weapon_flags |= WF_DESTROYED_BY_WEAPON; + Weapons[objp->instance].weapon_flags.set(Weapon::Weapon_Flags::Destroyed_by_weapon); } break; default: @@ -6012,7 +6012,7 @@ bool weapon_armed(weapon *wp, bool hit_target) weapon_info *wip = &Weapon_info[wp->weapon_info_index]; - if((wp->weapon_flags & WF_DESTROYED_BY_WEAPON) + if((wp->weapon_flags[Weapon::Weapon_Flags::Destroyed_by_weapon]) && !wip->arm_time && wip->arm_dist == 0.0f && wip->arm_radius == 0.0f) @@ -6217,7 +6217,7 @@ void weapon_hit( object * weapon_obj, object * other_obj, vec3d * hitpos, int qu //Set shockwaves flag int sw_flag = SW_WEAPON; - if ( ((other_obj) && (other_obj->type == OBJ_WEAPON)) || (Weapons[num].weapon_flags & WF_DESTROYED_BY_WEAPON)) { + if ( ((other_obj) && (other_obj->type == OBJ_WEAPON)) || (Weapons[num].weapon_flags[Weapon::Weapon_Flags::Destroyed_by_weapon])) { sw_flag |= SW_WEAPON_KILL; } @@ -6962,7 +6962,7 @@ float weapon_get_damage_scale(weapon_info *wip, object *wep, object *target) } // if this is a lockarm weapon, and it was fired unlocked - if((wip->wi_flags[Weapon::Info_Flags::Lockarm]) && !(wp->weapon_flags & WF_LOCKED_WHEN_FIRED)){ + if((wip->wi_flags[Weapon::Info_Flags::Lockarm]) && !(wp->weapon_flags[Weapon::Weapon_Flags::Locked_when_fired])){ total_scale *= 0.1f; } @@ -7125,10 +7125,10 @@ void weapon_render(object* obj, draw_list *scene) vec3d headp; vm_vec_scale_add(&headp, &obj->pos, &obj->orient.vec.fvec, wip->laser_length); - wp->weapon_flags &= ~WF_CONSIDER_FOR_FLYBY_SOUND; + wp->weapon_flags.remove(Weapon::Weapon_Flags::Consider_for_flyby_sound); if ( batch_add_laser(wip->laser_bitmap.first_frame + framenum, &headp, wip->laser_head_radius, &obj->pos, wip->laser_tail_radius, alpha, alpha, alpha) ) { - wp->weapon_flags |= WF_CONSIDER_FOR_FLYBY_SOUND; + wp->weapon_flags.set(Weapon::Weapon_Flags::Consider_for_flyby_sound); } } @@ -7234,7 +7234,7 @@ void weapon_render(object* obj, draw_list *scene) render_info.set_flags(render_flags); model_render_queue(&render_info, scene, wip->model_num, &obj->orient, &obj->pos); - wp->weapon_flags |= WF_CONSIDER_FOR_FLYBY_SOUND; + wp->weapon_flags.set(Weapon::Weapon_Flags::Consider_for_flyby_sound); break; } @@ -7554,7 +7554,7 @@ void weapon_info::reset() this->burst_delay = 1.0f; // 1 second, just incase its not defined this->burst_shots = 0; - this->burst_flags = 0; + this->burst_flags.reset(); generic_anim_init(&this->thruster_flame); generic_anim_init(&this->thruster_glow); From 941129f460eeac4c063f692c46d6fd95275a668c Mon Sep 17 00:00:00 2001 From: Fabian Woltermann Date: Fri, 19 Aug 2016 09:26:57 +0200 Subject: [PATCH 02/16] weapon.h cleanup --- code/weapon/weapon.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/code/weapon/weapon.h b/code/weapon/weapon.h index 1a303f75a8..f051d9075a 100644 --- a/code/weapon/weapon.h +++ b/code/weapon/weapon.h @@ -41,10 +41,6 @@ extern int Num_weapon_subtypes; #define WEAPON_EXHAUST_DELTA_TIME 75 // Delay in milliseconds between exhaust blobs -// flags for setting burst fire -#define WBF_FAST_FIRING (1<<0) // burst is to use only the firewait to determine firing delays -#define WBF_RANDOM_LENGTH (1<<1) // burst is to fire random length bursts - //particle names go here -nuke #define PSPEW_NONE -1 //used to disable a spew, useful for xmts #define PSPEW_DEFAULT 0 //std fs2 pspew From 5d96e493545ca7f7cef0d99ead03a32f931a9e66 Mon Sep 17 00:00:00 2001 From: Risto Toijala Date: Fri, 19 Aug 2016 18:17:45 +0300 Subject: [PATCH 03/16] Fix weapon flag parsing Starting with git 127976c (#851), FSO fails to start, displaying an error. This is my attempt to fix it. FSO starts, but I do not know how to check that the flags are parsed correctly. --- code/weapon/weapons.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/code/weapon/weapons.cpp b/code/weapon/weapons.cpp index b199353ef5..9a32db37fd 100644 --- a/code/weapon/weapons.cpp +++ b/code/weapon/weapons.cpp @@ -561,10 +561,8 @@ void parse_wi_flags(weapon_info *weaponp, flagset wi_flags) if (!optional_string("$Flags:")) return; - char weapon_strings[MAX_WEAPON_FLAGS][NAME_LENGTH]; - int num_strings; - - num_strings = stuff_string_list(weapon_strings, MAX_WEAPON_FLAGS); + SCP_vector unparsed_or_special; + parse_string_flag_list(weaponp->wi_flags, Weapon_Info_Flags, num_weapon_info_flags, &unparsed_or_special); if (optional_string("+override")) { // reseting the flag values if set to override the existing flags @@ -574,9 +572,6 @@ void parse_wi_flags(weapon_info *weaponp, flagset wi_flags) bool set_pierce = false; bool set_nopierce = false; - SCP_vector unparsed_or_special; - parse_string_flag_list(weaponp->wi_flags, Weapon_Info_Flags, num_weapon_info_flags, &unparsed_or_special); - if (unparsed_or_special.size() > 0) { for (auto flag = unparsed_or_special.begin(); flag != unparsed_or_special.end(); ++flag) { From 41e370fd2e962f79a3223643f1b4340dcee459bd Mon Sep 17 00:00:00 2001 From: asarium Date: Fri, 19 Aug 2016 16:05:37 +0200 Subject: [PATCH 04/16] Add option for writing pilot files in JSON format This is a new implementation of the JSON dumping which was already proposed in #22 but this version tries to allow implementing both reading and writing JSON files without having to change the existing code too much. This is done by using an abstract class to hide the differences between writing the JSON and binary files. This is currently only capable of writing the files but not reading them so if the option is enabled all changes to the pilot file are lost. I will implement reading after this PR has been merged since I would like to reduce the amount of changes that need to be reviewed. --- code/CMakeLists.txt | 3 +- code/cmdline/cmdline.cpp | 8 + code/cmdline/cmdline.h | 1 + code/cutscene/cutscenes.h | 8 + code/globalincs/vmallocator.h | 14 +- code/pilotfile/BinaryFileHandler.cpp | 89 +++++++ code/pilotfile/BinaryFileHandler.h | 53 ++++ code/pilotfile/FileHandler.h | 68 +++++ code/pilotfile/JSONFileHandler.cpp | 146 +++++++++++ code/pilotfile/JSONFileHandler.h | 56 ++++ code/pilotfile/csg.cpp | 4 +- code/pilotfile/pilotfile.cpp | 2 +- code/pilotfile/pilotfile.h | 26 +- code/pilotfile/plr.cpp | 365 ++++++++++++++------------- code/source_groups.cmake | 5 + lib/CMakeLists.txt | 3 +- lib/jansson/CMakeLists.txt | 4 +- 17 files changed, 648 insertions(+), 207 deletions(-) create mode 100644 code/pilotfile/BinaryFileHandler.cpp create mode 100644 code/pilotfile/BinaryFileHandler.h create mode 100644 code/pilotfile/FileHandler.h create mode 100644 code/pilotfile/JSONFileHandler.cpp create mode 100644 code/pilotfile/JSONFileHandler.h diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 507d5331e0..d79fff897d 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -38,9 +38,10 @@ IF (FSO_USE_SPEECH) target_link_libraries(code PUBLIC speech) ENDIF(FSO_USE_SPEECH) +TARGET_LINK_LIBRARIES(code PUBLIC jansson) + # Headers for standalone "gui" on UNIX IF(UNIX) - TARGET_LINK_LIBRARIES(code PUBLIC jansson) TARGET_LINK_LIBRARIES(code PUBLIC ${MONGOOSE_LIBS}) ENDIF(UNIX) diff --git a/code/cmdline/cmdline.cpp b/code/cmdline/cmdline.cpp index 942e2e7190..3d46b1ecd3 100644 --- a/code/cmdline/cmdline.cpp +++ b/code/cmdline/cmdline.cpp @@ -239,6 +239,7 @@ Flag exe_params[] = { "-no_unfocused_pause","Don't pause if the window isn't focused", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_unfocused_pause", }, { "-benchmark_mode", "Puts the game into benchmark mode", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-benchmark_mode", }, { "-noninteractive", "Disables interactive dialogs", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noninteractive", }, + { "-json_pilot", "Dump pilot files in JSON format", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-json_pilot", }, }; // forward declaration @@ -485,6 +486,7 @@ cmdline_parm frame_profile_write_file("-profile_write_file", NULL, AT_NONE); // cmdline_parm no_unfocused_pause_arg("-no_unfocused_pause", NULL, AT_NONE); //Cmdline_no_unfocus_pause cmdline_parm benchmark_mode_arg("-benchmark_mode", NULL, AT_NONE); //Cmdline_benchmark_mode cmdline_parm noninteractive_arg("-noninteractive", NULL, AT_NONE); //Cmdline_noninteractive +cmdline_parm json_pilot("-json_pilot", NULL, AT_NONE); //Cmdline_json_pilot char *Cmdline_start_mission = NULL; @@ -511,6 +513,7 @@ bool Cmdline_profile_write_file = false; bool Cmdline_no_unfocus_pause = false; bool Cmdline_benchmark_mode = false; bool Cmdline_noninteractive = false; +bool Cmdline_json_pilot = false; // Other cmdline_parm get_flags_arg("-get_flags", "Output the launcher flags file", AT_NONE); @@ -1853,6 +1856,11 @@ bool SetCmdlineParams() Cmdline_noninteractive = true; } + if (json_pilot.found()) + { + Cmdline_json_pilot = true; + } + //Deprecated flags - CommanderDJ if( deprecated_spec_arg.found() ) { diff --git a/code/cmdline/cmdline.h b/code/cmdline/cmdline.h index c49230a20b..e650a4eab9 100644 --- a/code/cmdline/cmdline.h +++ b/code/cmdline/cmdline.h @@ -158,5 +158,6 @@ extern bool Cmdline_profile_write_file; extern bool Cmdline_no_unfocus_pause; extern bool Cmdline_benchmark_mode; extern bool Cmdline_noninteractive; +extern bool Cmdline_json_pilot; #endif diff --git a/code/cutscene/cutscenes.h b/code/cutscene/cutscenes.h index 0d59e01f79..17627bf9fe 100644 --- a/code/cutscene/cutscenes.h +++ b/code/cutscene/cutscenes.h @@ -21,7 +21,15 @@ typedef struct cutscene_info { bool viewable; } cutscene_info; +#if SCP_COMPILER_IS_GNU +#pragma GCC diagnostic push +// This suppresses a GCC bug where it thinks that the Cutscenes from the enum class below shadows a global variable +#pragma GCC diagnostic ignored "-Wshadow" +#endif extern SCP_vector Cutscenes; +#if SCP_COMPILER_IS_GNU +#pragma GCC diagnostic pop +#endif // initializa table data void cutscene_init(); diff --git a/code/globalincs/vmallocator.h b/code/globalincs/vmallocator.h index 5ea828a772..9b54ff3728 100644 --- a/code/globalincs/vmallocator.h +++ b/code/globalincs/vmallocator.h @@ -14,28 +14,28 @@ #include template< typename T > -class SCP_vector : public std::vector< T, std::allocator< T > > { }; +using SCP_vector = std::vector< T, std::allocator< T > >; template< typename T > -class SCP_list : public std::list< T, std::allocator< T > > { }; +using SCP_list = std::list< T, std::allocator< T > >; typedef std::basic_string, std::allocator > SCP_string; typedef std::basic_stringstream, std::allocator > SCP_stringstream; template< typename T, typename U > -class SCP_map : public std::map, std::allocator > > { }; +using SCP_map = std::map, std::allocator > >; template< typename T, typename U > -class SCP_multimap : public std::multimap, std::allocator > > { }; +using SCP_multimap = std::multimap, std::allocator > >; template< typename T > -class SCP_queue : public std::queue< T, std::deque< T, std::allocator< T > > > { }; +using SCP_queue = std::queue< T, std::deque< T, std::allocator< T > > >; template< typename T > -class SCP_deque : public std::deque< T, std::allocator< T > > { }; +using SCP_deque = std::deque< T, std::allocator< T > >; template< typename Key, typename T, typename Hash = std::hash, typename KeyEqual = std::equal_to > -class SCP_unordered_map : public std::unordered_map< Key, T, Hash, KeyEqual, std::allocator< std::pair > > { }; +using SCP_unordered_map = std::unordered_map< Key, T, Hash, KeyEqual, std::allocator< std::pair > >; #endif // _VMALLOCATOR_H_INCLUDED_ diff --git a/code/pilotfile/BinaryFileHandler.cpp b/code/pilotfile/BinaryFileHandler.cpp new file mode 100644 index 0000000000..8165308705 --- /dev/null +++ b/code/pilotfile/BinaryFileHandler.cpp @@ -0,0 +1,89 @@ + +#include "pilotfile/BinaryFileHandler.h" + +pilot::BinaryFileHandler::BinaryFileHandler(CFILE* cfp) : _cfp(cfp) { + Assertion(cfp != nullptr, "File pointer must be valid!"); +} + +pilot::BinaryFileHandler::~BinaryFileHandler() { + cfclose(_cfp); + _cfp = nullptr; +} + +void pilot::BinaryFileHandler::writeUByte(const char*, std::uint8_t value) { + cfwrite_ubyte(value, _cfp); +} +void pilot::BinaryFileHandler::writeShort(const char*, std::int16_t value) { + cfwrite_short(value, _cfp); +} + +void pilot::BinaryFileHandler::writeInt(const char*, std::int32_t value) { + cfwrite_int(value, _cfp); +} + +void pilot::BinaryFileHandler::writeUInt(const char*, std::uint32_t value) { + cfwrite_uint(value, _cfp); +} + +void pilot::BinaryFileHandler::writeFloat(const char*, float value) { + cfwrite_float(value, _cfp); +} + +void pilot::BinaryFileHandler::writeString(const char*, const char* str) { + cfwrite_string_len(str, _cfp); +} + +void pilot::BinaryFileHandler::startSectionWrite(Section id) { + if (id == Section::Unnamed) { + _sectionOffsets.push_back({id, 0}); + return; + } + + cfwrite_ushort((ushort) id, _cfp); + + // to be updated when endSection() is called + cfwrite_int(0, _cfp); + + // starting offset, for size of section + _sectionOffsets.push_back({id, (size_t)cftell(_cfp)}); +} + +void pilot::BinaryFileHandler::endSectionWrite() { + Assertion(!_sectionOffsets.empty(), "No active section!"); + auto previous_off = _sectionOffsets.back(); + + if (previous_off.id == Section::Unnamed) { + // ignore unnamed sections, these are only needed for JSON + return; + } + + + size_t cur = (size_t) cftell(_cfp); + _sectionOffsets.pop_back(); + + Assert(cur >= previous_off.offset); + + size_t section_size = cur - previous_off.offset; + + if (section_size) { + // go back to section size in file and write proper value + cfseek(_cfp, (int) (cur - section_size - sizeof(int)), CF_SEEK_SET); + cfwrite_int((int) section_size, _cfp); + + // go back to previous location for next section + cfseek(_cfp, (int) cur, CF_SEEK_SET); + } +} +void pilot::BinaryFileHandler::startArrayWrite(const char*, size_t size, bool short_index) { + if (short_index) { + cfwrite_ushort((short)size, _cfp); + } else { + cfwrite_int((int)size, _cfp); + } +} +void pilot::BinaryFileHandler::endArrayWrite() { + // Nothing to do here for the binary version +} +void pilot::BinaryFileHandler::flush() { + cflush(_cfp); +} diff --git a/code/pilotfile/BinaryFileHandler.h b/code/pilotfile/BinaryFileHandler.h new file mode 100644 index 0000000000..e83da02ba8 --- /dev/null +++ b/code/pilotfile/BinaryFileHandler.h @@ -0,0 +1,53 @@ + +#ifndef BINARY_FILE_HANDLER_H +#define BINARY_FILE_HANDLER_H +#pragma once + +#include "pilotfile/FileHandler.h" + +#include "globalincs/pstypes.h" +#include "cfile/cfile.h" + +namespace pilot { +class BinaryFileHandler: public FileHandler { + CFILE* _cfp; + + struct SectionOffset { + Section id; + size_t offset; + }; + + SCP_vector _sectionOffsets; + public: + explicit BinaryFileHandler(CFILE* cfp); + + ~BinaryFileHandler() override; + + void writeUByte(const char* name, std::uint8_t value) override; + + void writeShort(const char* name, std::int16_t value) override; + + void writeInt(const char* name, std::int32_t value) override; + + void writeUInt(const char* name, std::uint32_t value) override; + + void writeFloat(const char* name, float value) override; + + void writeString(const char* name, const char* str) override; + + + void startSectionWrite(Section id) override; + + void endSectionWrite() override; + + + void startArrayWrite(const char* name, size_t size, bool short_length = false) override; + + void endArrayWrite() override; + + + virtual void flush() override; +}; +} + +#endif // BINARY_FILE_HANDLER_H diff --git a/code/pilotfile/FileHandler.h b/code/pilotfile/FileHandler.h new file mode 100644 index 0000000000..966874f827 --- /dev/null +++ b/code/pilotfile/FileHandler.h @@ -0,0 +1,68 @@ + +#ifndef FILEHANDLER_H +#define FILEHANDLER_H +#pragma once + +#include +#include + +#include "globalincs/pstypes.h" + +#if SCP_COMPILER_IS_GNU +#pragma GCC diagnostic push +// This suppresses a GCC bug where it thinks that the Cutscenes from the enum class below shadows a global variable +#pragma GCC diagnostic ignored "-Wshadow" +#endif +// sections of a pilot file. includes both plr and csg sections +enum class Section { + Unnamed = 0, //!< Special unnamed section + Flags = 0x0001, + Info = 0x0002, + Loadout = 0x0003, + Controls = 0x0004, + Multiplayer = 0x0005, + Scoring = 0x0006, + ScoringMulti = 0x0007, + Techroom = 0x0008, + HUD = 0x0009, + Settings = 0x0010, + RedAlert = 0x0011, + Variables = 0x0012, + Missions = 0x0013, + Cutscenes = 0x0014, + LastMissions = 0x0015 +}; +#if SCP_COMPILER_IS_GNU +#pragma GCC diagnostic pop +#endif + +namespace pilot { +class FileHandler { + public: + virtual ~FileHandler() {} + + virtual void writeUByte(const char* name, std::uint8_t value) = 0; + + virtual void writeShort(const char* name, std::int16_t value) = 0; + + virtual void writeInt(const char* name, std::int32_t value) = 0; + + virtual void writeUInt(const char* name, std::uint32_t value) = 0; + + virtual void writeFloat(const char* name, float value) = 0; + + virtual void writeString(const char* name, const char* str) = 0; + + virtual void startSectionWrite(Section id) = 0; + + virtual void endSectionWrite() = 0; + + virtual void startArrayWrite(const char* name, size_t size, bool short_length = false) = 0; + + virtual void endArrayWrite() = 0; + + virtual void flush() = 0; +}; +} + +#endif // FILEHANDLER_H diff --git a/code/pilotfile/JSONFileHandler.cpp b/code/pilotfile/JSONFileHandler.cpp new file mode 100644 index 0000000000..50c7c276e4 --- /dev/null +++ b/code/pilotfile/JSONFileHandler.cpp @@ -0,0 +1,146 @@ + +#include "pilotfile/JSONFileHandler.h" + +namespace { +int json_write_callback(const char *buffer, size_t size, void *data) { + CFILE* cfp = (CFILE*)data; + + if (cfwrite(buffer, 1, (int)size, cfp) != size) { + return -1; // Error + } else { + return 0; // Success + } +} + +const SCP_vector> SectionMapping { + std::pair(Section::Unnamed, nullptr), + std::pair(Section::Flags, "flags"), + std::pair(Section::Info, "info"), + std::pair(Section::Loadout, "loadout"), + std::pair(Section::Controls, "controls"), + std::pair(Section::Multiplayer, "multiplayer"), + std::pair(Section::Scoring, "scoring"), + std::pair(Section::ScoringMulti, "scoring_multi"), + std::pair(Section::Techroom, "techroom"), + std::pair(Section::HUD, "hud"), + std::pair(Section::Settings, "settings"), + std::pair(Section::RedAlert, "red_alert"), + std::pair(Section::Variables, "variables"), + std::pair(Section::Missions, "missions"), + std::pair(Section::Cutscenes, "cutscenes"), + std::pair(Section::LastMissions, "last_mission") +}; + +const char* lookupSectionName(Section s) { + for (auto& pair : SectionMapping) { + if (pair.first == s) { + return pair.second; + } + } + Assertion(false, "Unknown section!"); + return nullptr; +} + +Section lookupSectionValue(const char* name) { + for (auto& pair : SectionMapping) { + if (!strcmp(pair.second, name)) { + return pair.first; + } + } + Assertion(false, "Unknown section name!"); + return Section::Unnamed; +} +} + +pilot::JSONFileHandler::JSONFileHandler(CFILE* cfp) : _cfp(cfp) { + Assertion(cfp != nullptr, "File pointer must be valid!"); + + _rootObj = json_object(); + _currentEl = _rootObj; + _elementStack.push_back(_currentEl); +} + +pilot::JSONFileHandler::~JSONFileHandler() { + json_decref(_rootObj); + + cfclose(_cfp); + _cfp = nullptr; +} +void pilot::JSONFileHandler::writeUByte(const char* name, std::uint8_t value) { + writeInteger(name, value); +} +void pilot::JSONFileHandler::writeShort(const char* name, std::int16_t value) { + writeInteger(name, value); +} +void pilot::JSONFileHandler::writeInt(const char* name, std::int32_t value) { + writeInteger(name, value); +} +void pilot::JSONFileHandler::writeUInt(const char* name, std::uint32_t value) { + writeInteger(name, value); +} +void pilot::JSONFileHandler::writeFloat(const char* name, float value) { + ensureNotExists(name); + json_object_set_new(_currentEl, name, json_real(value)); +} +void pilot::JSONFileHandler::writeString(const char* name, const char* str) { + ensureNotExists(name); + json_object_set_new(_currentEl, name, json_string(str)); +} +void pilot::JSONFileHandler::startSectionWrite(Section id) { + auto key_name = lookupSectionName(id); + + json_t* obj = json_object(); + + if (json_is_array(_currentEl)) { + // We are in an array, section must be unnamed + Assertion(key_name == nullptr, "Inside an array there can be no named section!"); + json_array_append_new(_currentEl, obj); + } else { + Assertion(key_name != nullptr, "Section outside of arrays must be named!"); + json_object_set_new(_currentEl, key_name, obj); + } + _currentEl = obj; + _elementStack.push_back(_currentEl); +} +void pilot::JSONFileHandler::endSectionWrite() { + Assertion(json_is_object(_currentEl), "Section ended while not in a section!"); + + _elementStack.pop_back(); + _currentEl = _elementStack.back(); +} +void pilot::JSONFileHandler::startArrayWrite(const char* name, size_t, bool) { + auto array = json_array(); + + if (json_is_array(_currentEl)) { + // We are in an array, section must be unnamed + Assertion(name == nullptr, "Inside an array there can be no named section!"); + json_array_append_new(_currentEl, array); + } else { + Assertion(name != nullptr, "Section outside of arrays must be named!"); + json_object_set_new(_currentEl, name, array); + } + _currentEl = array; + _elementStack.push_back(_currentEl); +} +void pilot::JSONFileHandler::endArrayWrite() { + Assertion(json_is_array(_currentEl), "Array ended while not in an array!"); + + _elementStack.pop_back(); + _currentEl = _elementStack.back(); +} +void pilot::JSONFileHandler::flush() { + Assertion(_elementStack.size() == 1, "Not all sections or arrays have been ended!"); + + json_dump_callback(_rootObj, json_write_callback, _cfp, JSON_INDENT(4)); +} +void pilot::JSONFileHandler::writeInteger(const char* name, json_int_t val) { + ensureNotExists(name); + + json_object_set_new(_currentEl, name, json_integer(val)); +} +void pilot::JSONFileHandler::ensureNotExists(const char* name) { + Assertion(json_is_object(_currentEl), "Currently not in an element that supports keys!"); + // Make sure we don't overwrite previous values + Assertion(json_object_get(_currentEl, name) == nullptr, "Entry with name %s already exists!", name); +} + diff --git a/code/pilotfile/JSONFileHandler.h b/code/pilotfile/JSONFileHandler.h new file mode 100644 index 0000000000..25818d9d7c --- /dev/null +++ b/code/pilotfile/JSONFileHandler.h @@ -0,0 +1,56 @@ + +#ifndef JSON_FILE_HANDLER_H +#define JSON_FILE_HANDLER_H +#pragma once + +#include "pilotfile/FileHandler.h" + +#include "globalincs/pstypes.h" +#include "cfile/cfile.h" + +#include + +namespace pilot { +class JSONFileHandler: public FileHandler { + CFILE* _cfp; + + json_t* _rootObj; + + json_t* _currentEl; + + SCP_vector _elementStack; + + void ensureNotExists(const char* name); + void writeInteger(const char* name, json_int_t value); + public: + explicit JSONFileHandler(CFILE* cfp); + + ~JSONFileHandler() override; + + void writeUByte(const char* name, std::uint8_t value) override; + + void writeShort(const char* name, std::int16_t value) override; + + void writeInt(const char* name, std::int32_t value) override; + + void writeUInt(const char* name, std::uint32_t value) override; + + void writeFloat(const char* name, float value) override; + + void writeString(const char* name, const char* str) override; + + + void startSectionWrite(Section id) override; + + void endSectionWrite() override; + + + void startArrayWrite(const char* name, size_t size, bool short_length = false) override; + + void endArrayWrite() override; + + void flush() override; +}; +} + +#endif // JSON_FILE_HANDLER_H diff --git a/code/pilotfile/csg.cpp b/code/pilotfile/csg.cpp index 51bd1e409d..947ad43b5d 100644 --- a/code/pilotfile/csg.cpp +++ b/code/pilotfile/csg.cpp @@ -1408,7 +1408,7 @@ bool pilotfile::load_savefile(const char *campaign) // the point of all this: read in the CSG contents while ( !cfeof(cfp) ) { - ushort section_id = cfread_ushort(cfp); + Section section_id = static_cast
(cfread_ushort(cfp)); uint section_size = cfread_uint(cfp); size_t start_pos = cftell(cfp); @@ -1647,7 +1647,7 @@ bool pilotfile::get_csg_rank(int *rank) // the point of all this: read in the CSG contents while ( !m_have_flags && !cfeof(cfp) ) { - ushort section_id = cfread_ushort(cfp); + Section section_id = static_cast
(cfread_ushort(cfp)); uint section_size = cfread_uint(cfp); size_t start_pos = cftell(cfp); diff --git a/code/pilotfile/pilotfile.cpp b/code/pilotfile/pilotfile.cpp index 5291d8d0a2..72faa18c3b 100644 --- a/code/pilotfile/pilotfile.cpp +++ b/code/pilotfile/pilotfile.cpp @@ -27,7 +27,7 @@ pilotfile::~pilotfile() } } -void pilotfile::startSection(Section::id section_id) +void pilotfile::startSection(Section section_id) { Assert( cfp ); diff --git a/code/pilotfile/pilotfile.h b/code/pilotfile/pilotfile.h index 25f1906d5a..9505ef5038 100644 --- a/code/pilotfile/pilotfile.h +++ b/code/pilotfile/pilotfile.h @@ -5,7 +5,9 @@ #include "cfile/cfile.h" #include "globalincs/pstypes.h" #include "stats/scoring.h" +#include "pilotfile/FileHandler.h" +#include class player; @@ -60,6 +62,7 @@ class pilotfile { // info shared between PLR and CSG ... // -------------------------------------------------------------------- CFILE *cfp; + std::unique_ptr handler; SCP_string filename; player *p; @@ -129,29 +132,8 @@ class pilotfile { scoring_special_t all_time_stats; scoring_special_t multi_stats; - // sections of a pilot file. includes both plr and csg sections - struct Section { - enum id { - Flags = 0x0001, - Info = 0x0002, - Loadout = 0x0003, - Controls = 0x0004, - Multiplayer = 0x0005, - Scoring = 0x0006, - ScoringMulti = 0x0007, - Techroom = 0x0008, - HUD = 0x0009, - Settings = 0x0010, - RedAlert = 0x0011, - Variables = 0x0012, - Missions = 0x0013, - Cutscenes = 0x0014, - LastMissions = 0x0015 - }; - }; - // for writing files, sets/updates section info - void startSection(Section::id section_id); + void startSection(Section section_id); void endSection(); // file offset of the size value for the current section (set with startSection()) size_t m_size_offset; diff --git a/code/pilotfile/plr.cpp b/code/pilotfile/plr.cpp index 13a1d31030..c233e0c240 100644 --- a/code/pilotfile/plr.cpp +++ b/code/pilotfile/plr.cpp @@ -10,6 +10,8 @@ #include "network/multi.h" #include "osapi/osregistry.h" #include "pilotfile/pilotfile.h" +#include "pilotfile/BinaryFileHandler.h" +#include "pilotfile/JSONFileHandler.h" #include "playerman/managepilot.h" #include "playerman/player.h" #include "ship/ship.h" @@ -56,31 +58,31 @@ void pilotfile::plr_read_flags() void pilotfile::plr_write_flags() { - startSection(Section::Flags); + handler->startSectionWrite(Section::Flags); // tips - cfwrite_ubyte((unsigned char)p->tips, cfp); + handler->writeUByte("tips", (unsigned char)p->tips); // saved flags - cfwrite_int(p->save_flags, cfp); + handler->writeInt("save_flags", p->save_flags); // listing mode (single or campaign missions) - cfwrite_int(p->readyroom_listing_mode, cfp); + handler->writeInt("readyroom_listing_mode", p->readyroom_listing_mode); // briefing auto-play - cfwrite_int(p->auto_advance, cfp); + handler->writeInt("auto_advance", p->auto_advance); // special rank setting (to avoid having to read all stats on verify) // should be multi only from now on - cfwrite_int(multi_stats.rank, cfp); + handler->writeInt("multi_rank", multi_stats.rank); // What game mode we were in last on this pilot - cfwrite_int(p->player_was_multi, cfp); + handler->writeInt("was_multi", p->player_was_multi); // which language was this pilot created with - cfwrite_string_len(p->language, cfp); + handler->writeString("language", p->language); - endSection(); + handler->endSectionWrite(); } void pilotfile::plr_read_info() @@ -104,21 +106,21 @@ void pilotfile::plr_read_info() void pilotfile::plr_write_info() { - startSection(Section::Info); + handler->startSectionWrite(Section::Info); // pilot image - cfwrite_string_len(p->image_filename, cfp); + handler->writeString("image_filename", p->image_filename); // multi squad name - cfwrite_string_len(p->m_squad_name, cfp); + handler->writeString("squad_name", p->m_squad_name); // squad image - cfwrite_string_len(p->m_squad_filename, cfp); + handler->writeString("squad_filename", p->m_squad_filename); // active campaign - cfwrite_string_len(p->current_campaign, cfp); + handler->writeString("current_campaign", p->current_campaign); - endSection(); + handler->endSectionWrite(); } void pilotfile::plr_read_hud() @@ -172,36 +174,40 @@ void pilotfile::plr_write_hud() { int idx; - startSection(Section::HUD); + handler->startSectionWrite(Section::HUD); // flags - cfwrite_int(HUD_config.show_flags, cfp); - cfwrite_int(HUD_config.show_flags2, cfp); + handler->writeInt("show_flags", HUD_config.show_flags); + handler->writeInt("show_flags2", HUD_config.show_flags2); - cfwrite_int(HUD_config.popup_flags, cfp); - cfwrite_int(HUD_config.popup_flags2, cfp); + handler->writeInt("popup_flags", HUD_config.popup_flags); + handler->writeInt("popup_flags2", HUD_config.popup_flags2); // settings - cfwrite_ubyte(HUD_config.num_msg_window_lines, cfp); + handler->writeUByte("num_msg_window_lines", HUD_config.num_msg_window_lines); - cfwrite_int(HUD_config.rp_flags, cfp); - cfwrite_int(HUD_config.rp_dist, cfp); + handler->writeInt("rp_flags", HUD_config.rp_flags); + handler->writeInt("rp_dist", HUD_config.rp_dist); // basic colors - cfwrite_int(HUD_config.main_color, cfp); - cfwrite_int(HUD_color_alpha, cfp); + handler->writeInt("main_color", HUD_config.main_color); + handler->writeInt("color_alpha", HUD_color_alpha); // gauge-specific colors - cfwrite_int(NUM_HUD_GAUGES, cfp); - + handler->startArrayWrite("hud_gauges", NUM_HUD_GAUGES); for (idx = 0; idx < NUM_HUD_GAUGES; idx++) { - cfwrite_ubyte(HUD_config.clr[idx].red, cfp); - cfwrite_ubyte(HUD_config.clr[idx].green, cfp); - cfwrite_ubyte(HUD_config.clr[idx].blue, cfp); - cfwrite_ubyte(HUD_config.clr[idx].alpha, cfp); - } + handler->startSectionWrite(Section::Unnamed); - endSection(); + handler->writeUByte("red", HUD_config.clr[idx].red); + handler->writeUByte("green", HUD_config.clr[idx].green); + handler->writeUByte("blue", HUD_config.clr[idx].blue); + handler->writeUByte("alpha", HUD_config.clr[idx].alpha); + + handler->endSectionWrite(); + } + handler->endArrayWrite(); + + handler->endSectionWrite(); } void pilotfile::plr_read_variables() @@ -229,22 +235,21 @@ void pilotfile::plr_read_variables() void pilotfile::plr_write_variables() { - int list_size = 0; - int idx; + handler->startSectionWrite(Section::Variables); - startSection(Section::Variables); + handler->startArrayWrite("variables", p->variables.size()); + for (auto& var : p->variables) { + handler->startSectionWrite(Section::Unnamed); - list_size = (int)p->variables.size(); + handler->writeInt("type", var.type); + handler->writeString("text", var.text); + handler->writeString("variable_name", var.variable_name); - cfwrite_int(list_size, cfp); - - for (idx = 0; idx < list_size; idx++) { - cfwrite_int(p->variables[idx].type, cfp); - cfwrite_string_len(p->variables[idx].text, cfp); - cfwrite_string_len(p->variables[idx].variable_name, cfp); + handler->endSectionWrite(); } + handler->endArrayWrite(); - endSection(); + handler->endSectionWrite(); } void pilotfile::plr_read_multiplayer() @@ -276,29 +281,29 @@ void pilotfile::plr_read_multiplayer() void pilotfile::plr_write_multiplayer() { - startSection(Section::Multiplayer); + handler->startSectionWrite(Section::Multiplayer); // netgame options - cfwrite_ubyte(p->m_server_options.squad_set, cfp); - cfwrite_ubyte(p->m_server_options.endgame_set, cfp); - cfwrite_int(p->m_server_options.flags, cfp); - cfwrite_uint(p->m_server_options.respawn, cfp); - cfwrite_ubyte(p->m_server_options.max_observers, cfp); - cfwrite_ubyte(p->m_server_options.skill_level, cfp); - cfwrite_ubyte(p->m_server_options.voice_qos, cfp); - cfwrite_int(p->m_server_options.voice_token_wait, cfp); - cfwrite_int(p->m_server_options.voice_record_time, cfp); - cfwrite_int((int)p->m_server_options.mission_time_limit, cfp); - cfwrite_int(p->m_server_options.kill_limit, cfp); + handler->writeUByte("squad_set", p->m_server_options.squad_set); + handler->writeUByte("endgame_set", p->m_server_options.endgame_set); + handler->writeInt("server_flags", p->m_server_options.flags); + handler->writeUInt("respawn", p->m_server_options.respawn); + handler->writeUByte("max_observers", p->m_server_options.max_observers); + handler->writeUByte("skill_level", p->m_server_options.skill_level); + handler->writeUByte("voice_qos", p->m_server_options.voice_qos); + handler->writeInt("voice_token_wait", p->m_server_options.voice_token_wait); + handler->writeInt("voice_record_time", p->m_server_options.voice_record_time); + handler->writeInt("mission_time_limit", (int)p->m_server_options.mission_time_limit); + handler->writeInt("kill_limit", p->m_server_options.kill_limit); // local options - cfwrite_int(p->m_local_options.flags, cfp); - cfwrite_int(p->m_local_options.obj_update_level, cfp); + handler->writeInt("local_flags", p->m_local_options.flags); + handler->writeInt("obj_update_level", p->m_local_options.obj_update_level); // netgame protocol - cfwrite_int(Multi_options_g.protocol, cfp); + handler->writeInt("protocol", Multi_options_g.protocol); - endSection(); + handler->endSectionWrite(); } void pilotfile::plr_read_stats() @@ -402,50 +407,50 @@ void pilotfile::plr_read_stats() void pilotfile::plr_write_stats() { - int idx, list_size = 0; - - startSection(Section::Scoring); + handler->startSectionWrite(Section::Scoring); // global, all-time stats - cfwrite_int(all_time_stats.score, cfp); - cfwrite_int(all_time_stats.rank, cfp); - cfwrite_int(all_time_stats.assists, cfp); - cfwrite_int(all_time_stats.kill_count, cfp); - cfwrite_int(all_time_stats.kill_count_ok, cfp); - cfwrite_int(all_time_stats.bonehead_kills, cfp); + handler->writeInt("score", all_time_stats.score); + handler->writeInt("rank", all_time_stats.rank); + handler->writeInt("assists", all_time_stats.assists); + handler->writeInt("kill_count", all_time_stats.kill_count); + handler->writeInt("kill_count_ok", all_time_stats.kill_count_ok); + handler->writeInt("bonehead_kills", all_time_stats.bonehead_kills); - cfwrite_uint(all_time_stats.p_shots_fired, cfp); - cfwrite_uint(all_time_stats.p_shots_hit, cfp); - cfwrite_uint(all_time_stats.p_bonehead_hits, cfp); + handler->writeUInt("p_shots_fired", all_time_stats.p_shots_fired); + handler->writeUInt("p_shots_hit", all_time_stats.p_shots_hit); + handler->writeUInt("p_bonehead_hits", all_time_stats.p_bonehead_hits); - cfwrite_uint(all_time_stats.s_shots_fired, cfp); - cfwrite_uint(all_time_stats.s_shots_hit, cfp); - cfwrite_uint(all_time_stats.s_bonehead_hits, cfp); + handler->writeUInt("s_shots_fired", all_time_stats.s_shots_fired); + handler->writeUInt("s_shots_hit", all_time_stats.s_shots_hit); + handler->writeUInt("s_bonehead_hits", all_time_stats.s_bonehead_hits); - cfwrite_uint(all_time_stats.flight_time, cfp); - cfwrite_uint(all_time_stats.missions_flown, cfp); - cfwrite_int((int)all_time_stats.last_flown, cfp); - cfwrite_int((int)all_time_stats.last_backup, cfp); + handler->writeUInt("flight_time", all_time_stats.flight_time); + handler->writeUInt("missions_flown", all_time_stats.missions_flown); + handler->writeInt("last_flown", (int)all_time_stats.last_flown); + handler->writeInt("last_backup", (int)all_time_stats.last_backup); // ship kills (contains ships across all mods, not just current) - list_size = (int)all_time_stats.ship_kills.size(); - cfwrite_int(list_size, cfp); - - for (idx = 0; idx < list_size; idx++) { - cfwrite_string_len(all_time_stats.ship_kills[idx].name.c_str(), cfp); - cfwrite_int(all_time_stats.ship_kills[idx].val, cfp); + handler->startArrayWrite("kills", all_time_stats.ship_kills.size()); + for (auto& kill : all_time_stats.ship_kills) { + handler->startSectionWrite(Section::Unnamed); + handler->writeString("name", kill.name.c_str()); + handler->writeInt("val", kill.val); + handler->endSectionWrite(); } + handler->endArrayWrite(); // medals earned (contains medals across all mods, not just current) - list_size = (int)all_time_stats.medals_earned.size(); - cfwrite_int(list_size, cfp); - - for (idx = 0; idx < list_size; idx++) { - cfwrite_string_len(all_time_stats.medals_earned[idx].name.c_str(), cfp); - cfwrite_int(all_time_stats.medals_earned[idx].val, cfp); + handler->startArrayWrite("medals", all_time_stats.medals_earned.size()); + for (auto& medal : all_time_stats.medals_earned) { + handler->startSectionWrite(Section::Unnamed); + handler->writeString("name", medal.name.c_str()); + handler->writeInt("val", medal.val); + handler->endSectionWrite(); } + handler->endArrayWrite(); - endSection(); + handler->endSectionWrite(); } void pilotfile::plr_read_stats_multi() @@ -549,50 +554,48 @@ void pilotfile::plr_read_stats_multi() void pilotfile::plr_write_stats_multi() { - int idx, list_size = 0; - - startSection(Section::ScoringMulti); + handler->startSectionWrite(Section::ScoringMulti); // global, all-time stats - cfwrite_int(multi_stats.score, cfp); - cfwrite_int(multi_stats.rank, cfp); - cfwrite_int(multi_stats.assists, cfp); - cfwrite_int(multi_stats.kill_count, cfp); - cfwrite_int(multi_stats.kill_count_ok, cfp); - cfwrite_int(multi_stats.bonehead_kills, cfp); + handler->writeInt("score", multi_stats.score); + handler->writeInt("rank", multi_stats.rank); + handler->writeInt("assists", multi_stats.assists); + handler->writeInt("kill_count", multi_stats.kill_count); + handler->writeInt("kill_count_ok", multi_stats.kill_count_ok); + handler->writeInt("bonehead_kills", multi_stats.bonehead_kills); - cfwrite_uint(multi_stats.p_shots_fired, cfp); - cfwrite_uint(multi_stats.p_shots_hit, cfp); - cfwrite_uint(multi_stats.p_bonehead_hits, cfp); + handler->writeUInt("p_shots_fired", multi_stats.p_shots_fired); + handler->writeUInt("p_shots_hit", multi_stats.p_shots_hit); + handler->writeUInt("p_bonehead_hits", multi_stats.p_bonehead_hits); - cfwrite_uint(multi_stats.s_shots_fired, cfp); - cfwrite_uint(multi_stats.s_shots_hit, cfp); - cfwrite_uint(multi_stats.s_bonehead_hits, cfp); + handler->writeUInt("s_shots_fired", multi_stats.s_shots_fired); + handler->writeUInt("s_shots_hit", multi_stats.s_shots_hit); + handler->writeUInt("s_bonehead_hits", multi_stats.s_bonehead_hits); - cfwrite_uint(multi_stats.flight_time, cfp); - cfwrite_uint(multi_stats.missions_flown, cfp); - cfwrite_int((int)multi_stats.last_flown, cfp); - cfwrite_int((int)multi_stats.last_backup, cfp); + handler->writeUInt("flight_time", multi_stats.flight_time); + handler->writeUInt("missions_flown", multi_stats.missions_flown); + handler->writeInt("last_flown", (int)multi_stats.last_flown); + handler->writeInt("last_backup", (int)multi_stats.last_backup); // ship kills (contains medals across all mods, not just current) - list_size = (int)multi_stats.ship_kills.size(); - cfwrite_int(list_size, cfp); - - for (idx = 0; idx < list_size; idx++) { - cfwrite_string_len(multi_stats.ship_kills[idx].name.c_str(), cfp); - cfwrite_int(multi_stats.ship_kills[idx].val, cfp); + handler->startArrayWrite("kills", multi_stats.ship_kills.size()); + for (auto& kill : multi_stats.ship_kills) { + handler->startSectionWrite(Section::Unnamed); + handler->writeString("name", kill.name.c_str()); + handler->writeInt("val", kill.val); + handler->endSectionWrite(); } + handler->endArrayWrite(); // medals earned (contains medals across all mods, not just current) - list_size = (int)multi_stats.medals_earned.size(); - cfwrite_int(list_size, cfp); - - for (idx = 0; idx < list_size; idx++) { - cfwrite_string_len(multi_stats.medals_earned[idx].name.c_str(), cfp); - cfwrite_int(multi_stats.medals_earned[idx].val, cfp); + handler->startArrayWrite("medals", multi_stats.medals_earned.size()); + for (auto& medal : multi_stats.medals_earned) { + handler->writeString("name", medal.name.c_str()); + handler->writeInt("val", medal.val); } + handler->endArrayWrite(); - endSection(); + handler->endSectionWrite(); } void pilotfile::plr_read_controls() @@ -627,27 +630,34 @@ void pilotfile::plr_read_controls() void pilotfile::plr_write_controls() { - int idx; + handler->startSectionWrite(Section::Controls); - startSection(Section::Controls); + // For some unknown reason, the old code used a short for the array length here... + handler->startArrayWrite("controls", CCFG_MAX, true); + for (size_t idx = 0; idx < CCFG_MAX; idx++) { + handler->startSectionWrite(Section::Unnamed); - cfwrite_ushort(CCFG_MAX, cfp); - - for (idx = 0; idx < CCFG_MAX; idx++) { - cfwrite_short(Control_config[idx].key_id, cfp); - cfwrite_short(Control_config[idx].joy_id, cfp); + handler->writeShort("key", Control_config[idx].key_id); + handler->writeShort("joystick", Control_config[idx].joy_id); // placeholder? for future mouse_id? - cfwrite_short(-1, cfp); + handler->writeShort("mouse", -1); + + handler->endSectionWrite(); } + handler->endArrayWrite(); - cfwrite_int(NUM_JOY_AXIS_ACTIONS, cfp); + handler->startArrayWrite("axes", NUM_JOY_AXIS_ACTIONS); + for (size_t idx = 0; idx < NUM_JOY_AXIS_ACTIONS; idx++) { + handler->startSectionWrite(Section::Unnamed); - for (idx = 0; idx < NUM_JOY_AXIS_ACTIONS; idx++) { - cfwrite_int(Axis_map_to[idx], cfp); - cfwrite_int(Invert_axis[idx], cfp); + handler->writeInt("axis_map", Axis_map_to[idx]); + handler->writeInt("invert_axis", Invert_axis[idx]); + + handler->endSectionWrite(); } + handler->endArrayWrite(); - endSection(); + handler->endSectionWrite(); } void pilotfile::plr_read_settings() @@ -694,39 +704,39 @@ void pilotfile::plr_read_settings() void pilotfile::plr_write_settings() { - startSection(Section::Settings); + handler->startSectionWrite(Section::Settings); // sound/voice/music - cfwrite_float(Master_sound_volume, cfp); - cfwrite_float(Master_event_music_volume, cfp); - cfwrite_float(Master_voice_volume, cfp); + handler->writeFloat("master_sound_volume", Master_sound_volume); + handler->writeFloat("master_event_music_volume", Master_event_music_volume); + handler->writeFloat("aster_voice_volume", Master_voice_volume); - cfwrite_int(Briefing_voice_enabled, cfp); + handler->writeInt("briefing_voice_enabled", Briefing_voice_enabled); // skill level - cfwrite_int(Game_skill_level, cfp); + handler->writeInt("game_skill_level", Game_skill_level); // input options - cfwrite_int(Use_mouse_to_fly, cfp); - cfwrite_int(Mouse_sensitivity, cfp); - cfwrite_int(Joy_sensitivity, cfp); - cfwrite_int(Joy_dead_zone_size, cfp); + handler->writeInt("use_mouse_to_fly", Use_mouse_to_fly); + handler->writeInt("mouse_sensitivity", Mouse_sensitivity); + handler->writeInt("joy_sensitivity", Joy_sensitivity); + handler->writeInt("joy_dead_zone_size", Joy_dead_zone_size); // detail - cfwrite_int(Detail.setting, cfp); - cfwrite_int(Detail.nebula_detail, cfp); - cfwrite_int(Detail.detail_distance, cfp); - cfwrite_int(Detail.hardware_textures, cfp); - cfwrite_int(Detail.num_small_debris, cfp); - cfwrite_int(Detail.num_particles, cfp); - cfwrite_int(Detail.num_stars, cfp); - cfwrite_int(Detail.shield_effects, cfp); - cfwrite_int(Detail.lighting, cfp); - cfwrite_int(Detail.targetview_model, cfp); - cfwrite_int(Detail.planets_suns, cfp); - cfwrite_int(Detail.weapon_extras, cfp); + handler->writeInt("setting", Detail.setting); + handler->writeInt("nebula_detail", Detail.nebula_detail); + handler->writeInt("detail_distance", Detail.detail_distance); + handler->writeInt("hardware_textures", Detail.hardware_textures); + handler->writeInt("num_small_debris", Detail.num_small_debris); + handler->writeInt("num_particles", Detail.num_particles); + handler->writeInt("num_stars", Detail.num_stars); + handler->writeInt("shield_effects", Detail.shield_effects); + 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); - endSection(); + handler->endSectionWrite(); } void pilotfile::plr_reset_data() @@ -763,6 +773,9 @@ void pilotfile::plr_close() cfclose(cfp); cfp = NULL; } + if (handler) { + handler.reset(); + } p = NULL; filename = ""; @@ -828,7 +841,7 @@ bool pilotfile::load_player(const char *callsign, player *_p) // the point of all this: read in the PLR contents while ( !cfeof(cfp) ) { - ushort section_id = cfread_ushort(cfp); + Section section_id = static_cast
(cfread_ushort(cfp)); uint section_size = cfread_uint(cfp); size_t start_pos = cftell(cfp); @@ -952,24 +965,34 @@ bool pilotfile::save_player(player *_p) } filename = p->callsign; - filename += ".plr"; - - if ( filename.size() == 4 ) { + if ( filename.empty() ) { mprintf(("PLR => Invalid filename '%s'!\n", filename.c_str())); return false; } - // open it, hopefully... - cfp = cfopen((char*)filename.c_str(), "wb", CFILE_NORMAL, CF_TYPE_PLAYERS); + if (Cmdline_json_pilot) { + filename += ".json"; + } else { + filename += ".plr"; + } - if ( !cfp ) { + // open it, hopefully... + auto fp = cfopen((char*)filename.c_str(), "wb", CFILE_NORMAL, CF_TYPE_PLAYERS); + + if ( !fp ) { mprintf(("PLR => Unable to open '%s' for saving!\n", filename.c_str())); return false; } + if (Cmdline_json_pilot) { + handler.reset(new pilot::JSONFileHandler(fp)); + } else { + handler.reset(new pilot::BinaryFileHandler(fp)); + } + // header and version - cfwrite_int(PLR_FILE_ID, cfp); - cfwrite_ubyte(PLR_VERSION, cfp); + handler->writeInt("signature", PLR_FILE_ID); + handler->writeUByte("version", PLR_VERSION); mprintf(("PLR => Saving '%s' with version %d...\n", filename.c_str(), (int)PLR_VERSION)); @@ -995,6 +1018,8 @@ bool pilotfile::save_player(player *_p) mprintf(("PLR => Saving: Settings...\n")); plr_write_settings(); + handler->flush(); + // Done! mprintf(("PLR => Saving complete!\n")); @@ -1039,7 +1064,7 @@ bool pilotfile::verify(const char *fname, int *rank, char *valid_language) // the point of all this: read in the PLR contents while ( !(m_have_flags && m_have_info) && !cfeof(cfp) ) { - ushort section_id = cfread_ushort(cfp); + Section section_id = static_cast
(cfread_ushort(cfp)); uint section_size = cfread_uint(cfp); size_t start_pos = cftell(cfp); diff --git a/code/source_groups.cmake b/code/source_groups.cmake index 8037a84407..bb3598e832 100644 --- a/code/source_groups.cmake +++ b/code/source_groups.cmake @@ -831,7 +831,12 @@ set (file_root_physics # PilotFile files set (file_root_pilotfile + pilotfile/BinaryFileHandler.cpp + pilotfile/BinaryFileHandler.h pilotfile/csg.cpp + pilotfile/FileHandler.h + pilotfile/JSONFileHandler.cpp + pilotfile/JSONFileHandler.h pilotfile/csg_convert.cpp pilotfile/pilotfile.cpp pilotfile/pilotfile.h diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index ddb77bbf93..cc9ea712ad 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -19,9 +19,8 @@ add_subdirectory(opengl) ADD_SUBDIRECTORY(libsdl) +ADD_SUBDIRECTORY(jansson) # These are only required for the web-ui which is non-Windows IF(UNIX) - ADD_SUBDIRECTORY(jansson) - ADD_SUBDIRECTORY(mongoose) ENDIF(UNIX) diff --git a/lib/jansson/CMakeLists.txt b/lib/jansson/CMakeLists.txt index 5bee9f8ec0..4905268675 100644 --- a/lib/jansson/CMakeLists.txt +++ b/lib/jansson/CMakeLists.txt @@ -49,7 +49,7 @@ # the source directory. # The rest is down to the usual make process. -IF(NOT ${FSO_BUILD_INCLUDED_LIBS} AND ${UNIX}) +IF(NOT FSO_BUILD_INCLUDED_LIBS AND UNIX) find_package(PkgConfig) if (PKG_CONFIG_FOUND) @@ -66,7 +66,7 @@ IF(NOT ${FSO_BUILD_INCLUDED_LIBS} AND ${UNIX}) endif() ENDIF() -IF(${FSO_BUILD_INCLUDED_LIBS} OR NOT ${JANSSON_FOUND}) +IF(FSO_BUILD_INCLUDED_LIBS OR NOT JANSSON_FOUND) MESSAGE(STATUS "Building jansson from source...") # Options set(USE_URANDOM ON) From c1307fc2130a5eeb8bf28f43cac7785eae538a06 Mon Sep 17 00:00:00 2001 From: Risto Toijala Date: Fri, 19 Aug 2016 20:45:39 +0300 Subject: [PATCH 05/16] Fix _mkdir on non-Windows _mkdir was horribly broken. It was creating all directories in the given path but failed to create the actually wanted last portion. On Windows, _mkdir only creates the last portion. Fix this by simply calling mkdir, which does the Right Thing (TM). --- code/windows_stub/stubs.cpp | 31 +++---------------------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/code/windows_stub/stubs.cpp b/code/windows_stub/stubs.cpp index 3eb75f12b0..58230135dc 100644 --- a/code/windows_stub/stubs.cpp +++ b/code/windows_stub/stubs.cpp @@ -201,34 +201,9 @@ int _chdir(const char *path) // make specified directory int _mkdir(const char *path) { - int status = 1; // if we don't ever call mkdir() to update this then assume we are in error - char *c, tmp_path[MAX_PATH]; - - memset(tmp_path, 0, MAX_PATH); - strncpy(tmp_path, path, MAX_PATH-1); - - c = &tmp_path[1]; - - while (c++) { - c = strchr(c, '/'); - - if (c) { - *c = '\0'; - - status = mkdir(tmp_path, 0755); - -#ifndef NDEBUG - int m_error = errno; - - if (status && (m_error != EEXIST) ) { - Warning(__FILE__, __LINE__, "Cannot mkdir %s: %s", tmp_path, strerror(m_error)); - } -#endif - *c = '/'; - } - } - - return status; + // Windows _mkdir does not take file permissions as a parameter. + // umask already deals with that, so 0777 should be fine. + return mkdir(path, 0777); } void _splitpath (char *path, char *drive, char *dir, char *fname, char *ext) From 1471cfac38b5bbf34464bf7546d7c8c9b1e9ccd8 Mon Sep 17 00:00:00 2001 From: Fabian Woltermann Date: Fri, 19 Aug 2016 21:11:57 +0200 Subject: [PATCH 06/16] Adds ai_flags master file --- code/ai/ai_flags.h | 119 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 code/ai/ai_flags.h diff --git a/code/ai/ai_flags.h b/code/ai/ai_flags.h new file mode 100644 index 0000000000..62d8497c9a --- /dev/null +++ b/code/ai/ai_flags.h @@ -0,0 +1,119 @@ +#ifndef AI_FLAGS_H +#define AI_FLAGS_H + +#include "globalincs/pstypes.h" + +namespace AI { + FLAG_LIST(AI_Flags) { + Formation_wing, // Fly in formation as part of wing. + Awaiting_repair, // Awaiting a repair ship. + Being_repaired, // Currently docked with repair ship. + Repairing, // Repairing a ship (or going to repair a ship) + Seek_lock, // set if should focus on gaining aspect lock, not hitting with lasers + Formation_object, // Fly in formation off a specific object. + Temporary_ignore, // Means current ignore_objnum is only temporary, not an order from the player. + Use_exit_path, // Used by path code, to flag path as an exit path + Use_static_path, // Used by path code, use fixed path, don't try to recreate + Target_collision, // Collided with aip->target_objnum last frame. Avoid that ship for half a second or so. + Unload_secondaries, // Fire secondaries as fast as possible! + On_subsys_path, // Current path leads to a subsystem + Avoid_shockwave_ship, // Avoid an existing shockwave from a ship. + Avoid_shockwave_weapon, // Avoid an expected shockwave from a weapon. shockwave_object field contains object index. + Avoid_shockwave_started, // Already started avoiding shockwave, don't keep deciding whether to avoid. + Attack_slowly, // Move slowly while attacking. + Repair_obstructed, // Ship wants to be repaired, but path is obstructed. + Kamikaze, // Crash into target + No_dynamic, // Not allowed to get dynamic goals + Avoiding_small_ship, // Avoiding a player ship. + Avoiding_big_ship, // Avoiding a large ship. + Big_ship_collide_recover_1, // Collided into a big ship. Recovering by flying away. + Big_ship_collide_recover_2, // Collided into a big ship. Fly towards big ship sphere perimeter. + Stealth_pursuit, // AI is trying to fight stealth ship + Unload_primaries, // Fire primaries as fast as possible! + Trying_unsuccessfully_to_warp, // Trying to warp, but can't warp at the moment + Free_afterburner_use, // Use afterburners while following waypoints or flying towards objects + + NUM_VALUES + }; + + FLAG_LIST(Goal_flags) { + Docker_index_valid, // when set, index field for docker is valid + Dockee_index_valid, // when set, index field for dockee is valid + Goal_on_hold, // when set, this goal cannot currently be satisfied, although it could be in the future + Subsys_needs_fixup, // when set, the subsystem index (for a destroy subsystem goal) is invalid and must be gotten from the subsys name stored in docker.name field!! + Goal_override, // paired with AIG_TYPE_DYNAMIC to mean this goal overrides any other goal + Purge, // purge this goal next time we process + Goals_purged, // this goal has already caused other goals to get purged + Depart_sound_played,// Goober5000 - replacement for AL's hack ;) + Target_own_team, + + NUM_VALUES + }; + + FLAG_LIST(Override_flags) { + Full, // Full sexp control + Roll, // Sexp forced roll maneuver + Pitch, // Sexp forced pitch change + Heading, // Sexp forced heading change + Full_lat, // full control over up/side/forward movement + Up, // vertical movement + Sideways, // horizontal movement + Forward, // forward movement + + NUM_VALUES + }; + + FLAG_LIST(Profile_flags) { + Smart_shield_management, + Big_ships_can_attack_beam_turrets_on_untargeted_ships, + Smart_primary_weapon_selection, + Smart_secondary_weapon_selection, + Allow_rapid_secondary_dumbfire, + Huge_turret_weapons_ignore_bombs, + Dont_insert_random_turret_fire_delay, + Hack_improve_non_homing_swarm_turret_fire_accuracy, + Shockwaves_damage_small_ship_subsystems, + Navigation_subsys_governs_warp, + No_min_dock_speed_cap, + Disable_linked_fire_penalty, + Disable_weapon_damage_scaling, + Use_additive_weapon_velocity, + Use_newtonian_dampening, + Include_beams_in_stat_calcs, + Kill_scoring_scales_with_damage, + Assist_scoring_scales_with_damage, + Allow_multi_event_scoring, + Smart_afterburner_management, + Fix_linked_primary_bug, + Prevent_targeting_bombs_beyond_range, + Smart_subsystem_targeting_for_turrets, + Fix_heat_seeker_stealth_bug, + Multi_allow_empty_primaries, + Multi_allow_empty_secondaries, + Allow_turrets_target_weapons_freely, + Use_only_single_fov_for_turrets, + Allow_vertical_dodge, + Force_beam_turret_fov, + Fix_ai_class_bug, + Turrets_ignore_target_radius, + No_special_player_avoid, + Perform_fewer_scream_checks, + All_ships_manage_shields, + Advanced_turret_fov_edge_checks, + Require_turret_to_have_target_in_fov, + Ai_aims_from_ship_center, + Allow_primary_link_at_start, + Beams_damage_weapons, + Player_weapon_scale_fix, + No_warp_camera, + Aspect_lock_countermeasure, + Ai_guards_specific_ship_in_wing, + Fix_ai_path_order_bug, + Strict_turred_tagged_only_targeting, + Aspect_invulnerability_fix, + + NUM_VALUES + }; +} + +#endif \ No newline at end of file From 9942bf7e19e520fc0a08fc3158f2c9107821aeee Mon Sep 17 00:00:00 2001 From: Fabian Woltermann Date: Fri, 19 Aug 2016 21:12:21 +0200 Subject: [PATCH 07/16] Add to cmake --- code/source_groups.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/code/source_groups.cmake b/code/source_groups.cmake index 8037a84407..5c32f72cda 100644 --- a/code/source_groups.cmake +++ b/code/source_groups.cmake @@ -6,6 +6,7 @@ set (file_root set (file_root_ai ai/ai.cpp ai/ai.h + ai/ai_flags.h ai/ai_profiles.cpp ai/ai_profiles.h ai/aibig.cpp From 0591b7ef49872946ad0db0880bdf2552960af4e4 Mon Sep 17 00:00:00 2001 From: Fabian Woltermann Date: Fri, 19 Aug 2016 22:44:39 +0200 Subject: [PATCH 08/16] ai profile flags --- code/ai/ai.h | 9 +- code/ai/ai_flags.h | 104 +++++++-------- code/ai/ai_profiles.cpp | 193 +++++++++++++++++----------- code/ai/ai_profiles.h | 11 +- code/ai/aibig.cpp | 6 +- code/ai/aicode.cpp | 122 +++++++----------- code/ai/aiturret.cpp | 26 ++-- code/hud/hudobserver.cpp | 2 +- code/hud/hudtarget.cpp | 4 +- code/mission/missiongoals.cpp | 2 +- code/mission/missionparse.cpp | 2 +- code/network/multiteamselect.cpp | 4 +- code/object/collideweaponweapon.cpp | 4 +- code/object/objectshield.cpp | 2 +- code/physics/physics.cpp | 2 +- code/ship/ship.cpp | 14 +- code/ship/shiphit.cpp | 4 +- code/stats/scoring.cpp | 6 +- code/weapon/beam.cpp | 6 +- code/weapon/weapons.cpp | 12 +- freespace2/freespace.cpp | 2 +- 21 files changed, 279 insertions(+), 258 deletions(-) diff --git a/code/ai/ai.h b/code/ai/ai.h index 0b4e62f5a8..e94c922571 100644 --- a/code/ai/ai.h +++ b/code/ai/ai.h @@ -228,10 +228,8 @@ typedef struct ai_class { int ai_chance_to_use_missiles_on_plr[NUM_SKILL_LEVELS]; float ai_max_aim_update_delay[NUM_SKILL_LEVELS]; float ai_turret_max_aim_update_delay[NUM_SKILL_LEVELS]; - int ai_profile_flags; //Holds the state of flags that are set - int ai_profile_flags_set; //Holds which flags are set and which are just left alone - int ai_profile_flags2; - int ai_profile_flags2_set; + flagset ai_profile_flags; //Holds the state of flags that are set + flagset ai_profile_flags_set; //Holds which flags are set and which are just left alone //SUSHI: These are optional overrides to an AI class to prevent the automatic scaling based on AI class index int ai_aburn_use_factor[NUM_SKILL_LEVELS]; @@ -461,8 +459,7 @@ typedef struct ai_info { int ai_chance_to_use_missiles_on_plr; float ai_max_aim_update_delay; float ai_turret_max_aim_update_delay; - int ai_profile_flags; //Holds AI_Profiles flags (possibly overriden by AI class) that actually apply to AI - int ai_profile_flags2; + flagset ai_profile_flags; //Holds AI_Profiles flags (possibly overriden by AI class) that actually apply to AI union { diff --git a/code/ai/ai_flags.h b/code/ai/ai_flags.h index 62d8497c9a..389c3fdeda 100644 --- a/code/ai/ai_flags.h +++ b/code/ai/ai_flags.h @@ -1,7 +1,7 @@ #ifndef AI_FLAGS_H #define AI_FLAGS_H -#include "globalincs/pstypes.h" +#include "globalincs/flagset.h" namespace AI { FLAG_LIST(AI_Flags) { @@ -36,7 +36,7 @@ namespace AI { NUM_VALUES }; - FLAG_LIST(Goal_flags) { + FLAG_LIST(Goal_Flags) { Docker_index_valid, // when set, index field for docker is valid Dockee_index_valid, // when set, index field for dockee is valid Goal_on_hold, // when set, this goal cannot currently be satisfied, although it could be in the future @@ -50,7 +50,7 @@ namespace AI { NUM_VALUES }; - FLAG_LIST(Override_flags) { + FLAG_LIST(Override_Flags) { Full, // Full sexp control Roll, // Sexp forced roll maneuver Pitch, // Sexp forced pitch change @@ -63,54 +63,56 @@ namespace AI { NUM_VALUES }; - FLAG_LIST(Profile_flags) { - Smart_shield_management, - Big_ships_can_attack_beam_turrets_on_untargeted_ships, - Smart_primary_weapon_selection, - Smart_secondary_weapon_selection, - Allow_rapid_secondary_dumbfire, - Huge_turret_weapons_ignore_bombs, - Dont_insert_random_turret_fire_delay, - Hack_improve_non_homing_swarm_turret_fire_accuracy, - Shockwaves_damage_small_ship_subsystems, - Navigation_subsys_governs_warp, - No_min_dock_speed_cap, - Disable_linked_fire_penalty, - Disable_weapon_damage_scaling, - Use_additive_weapon_velocity, - Use_newtonian_dampening, - Include_beams_in_stat_calcs, - Kill_scoring_scales_with_damage, - Assist_scoring_scales_with_damage, - Allow_multi_event_scoring, - Smart_afterburner_management, - Fix_linked_primary_bug, - Prevent_targeting_bombs_beyond_range, - Smart_subsystem_targeting_for_turrets, - Fix_heat_seeker_stealth_bug, - Multi_allow_empty_primaries, - Multi_allow_empty_secondaries, - Allow_turrets_target_weapons_freely, - Use_only_single_fov_for_turrets, - Allow_vertical_dodge, - Force_beam_turret_fov, - Fix_ai_class_bug, - Turrets_ignore_target_radius, - No_special_player_avoid, - Perform_fewer_scream_checks, - All_ships_manage_shields, - Advanced_turret_fov_edge_checks, - Require_turret_to_have_target_in_fov, - Ai_aims_from_ship_center, - Allow_primary_link_at_start, - Beams_damage_weapons, - Player_weapon_scale_fix, - No_warp_camera, - Aspect_lock_countermeasure, - Ai_guards_specific_ship_in_wing, - Fix_ai_path_order_bug, - Strict_turred_tagged_only_targeting, - Aspect_invulnerability_fix, + FLAG_LIST(Profile_Flags) { + Advanced_turret_fov_edge_checks, + Ai_aims_from_ship_center, + Ai_can_slow_down_attacking_big_ships, + Ai_guards_specific_ship_in_wing, + All_ships_manage_shields, + Allow_multi_event_scoring, + Allow_primary_link_at_start, + Allow_rapid_secondary_dumbfire, + Allow_turrets_target_weapons_freely, + Allow_vertical_dodge, + Aspect_invulnerability_fix, + Aspect_lock_countermeasure, + Assist_scoring_scales_with_damage, + Beams_damage_weapons, + Big_ships_can_attack_beam_turrets_on_untargeted_ships, + Disable_linked_fire_penalty, + Disable_weapon_damage_scaling, + Dont_insert_random_turret_fire_delay, + Fix_ai_class_bug, + Fix_ai_path_order_bug, + Fix_heat_seeker_stealth_bug, + Fix_linked_primary_bug, + Force_beam_turret_fov, + Glide_decay_requires_thrust, + Hack_improve_non_homing_swarm_turret_fire_accuracy, + Huge_turret_weapons_ignore_bombs, + Include_beams_in_stat_calcs, + Kill_scoring_scales_with_damage, + Multi_allow_empty_primaries, + Multi_allow_empty_secondaries, + Navigation_subsys_governs_warp, + No_min_dock_speed_cap, + No_special_player_avoid, + No_warp_camera, + Perform_fewer_scream_checks, + Player_weapon_scale_fix, + Prevent_targeting_bombs_beyond_range, + Require_turret_to_have_target_in_fov, + Shockwaves_damage_small_ship_subsystems, + Smart_afterburner_management, + Smart_primary_weapon_selection, + Smart_secondary_weapon_selection, + Smart_shield_management, + Smart_subsystem_targeting_for_turrets, + Strict_turred_tagged_only_targeting, + Turrets_ignore_target_radius, + Use_additive_weapon_velocity, + Use_newtonian_dampening, + Use_only_single_fov_for_turrets, NUM_VALUES }; diff --git a/code/ai/ai_profiles.cpp b/code/ai/ai_profiles.cpp index 46e2ada57b..43c5535af1 100644 --- a/code/ai/ai_profiles.cpp +++ b/code/ai/ai_profiles.cpp @@ -28,24 +28,13 @@ static char Default_profile_name[NAME_LENGTH]; // utility -void set_flag(ai_profile_t *profile, char *name, int flag, int type) +void set_flag(ai_profile_t *profile, char *name, AI::Profile_Flags flag) { if (optional_string(name)) { bool val; stuff_boolean(&val); - - if (type == AIP_FLAG) { - if (val) - profile->flags |= flag; - else - profile->flags &= ~flag; - } else { - if (val) - profile->flags2 |= flag; - else - profile->flags2 &= ~flag; - } + profile->flags.set(flag, val); } } @@ -152,12 +141,12 @@ void parse_ai_profiles_tbl(const char *filename) // base profile, so zero it out if (profile == &Ai_profiles[0]) { - memset(profile, 0, sizeof(ai_profile_t)); + profile->reset(); } // brand new profile, so set it to the base defaults else { - memcpy(profile, &Ai_profiles[0], sizeof(ai_profile_t)); + *profile = Ai_profiles[0]; } } @@ -358,91 +347,91 @@ void parse_ai_profiles_tbl(const char *filename) if (optional_string("$Detail Distance Multiplier:")) parse_float_list(profile->detail_distance_mult, NUM_SKILL_LEVELS); - set_flag(profile, "$big ships can attack beam turrets on untargeted ships:", AIPF_BIG_SHIPS_CAN_ATTACK_BEAM_TURRETS_ON_UNTARGETED_SHIPS, AIP_FLAG); + set_flag(profile, "$big ships can attack beam turrets on untargeted ships:", AI::Profile_Flags::Big_ships_can_attack_beam_turrets_on_untargeted_ships); - set_flag(profile, "$smart primary weapon selection:", AIPF_SMART_PRIMARY_WEAPON_SELECTION, AIP_FLAG); + set_flag(profile, "$smart primary weapon selection:", AI::Profile_Flags::Smart_primary_weapon_selection); - set_flag(profile, "$smart secondary weapon selection:", AIPF_SMART_SECONDARY_WEAPON_SELECTION, AIP_FLAG); + set_flag(profile, "$smart secondary weapon selection:", AI::Profile_Flags::Smart_secondary_weapon_selection); - set_flag(profile, "$smart shield management:", AIPF_SMART_SHIELD_MANAGEMENT, AIP_FLAG); + set_flag(profile, "$smart shield management:", AI::Profile_Flags::Smart_shield_management); - set_flag(profile, "$smart afterburner management:", AIPF_SMART_AFTERBURNER_MANAGEMENT, AIP_FLAG); + set_flag(profile, "$smart afterburner management:", AI::Profile_Flags::Smart_afterburner_management); - set_flag(profile, "$allow rapid secondary dumbfire:", AIPF_ALLOW_RAPID_SECONDARY_DUMBFIRE, AIP_FLAG); + set_flag(profile, "$allow rapid secondary dumbfire:", AI::Profile_Flags::Allow_rapid_secondary_dumbfire); - set_flag(profile, "$huge turret weapons ignore bombs:", AIPF_HUGE_TURRET_WEAPONS_IGNORE_BOMBS, AIP_FLAG); + set_flag(profile, "$huge turret weapons ignore bombs:", AI::Profile_Flags::Huge_turret_weapons_ignore_bombs); - set_flag(profile, "$don't insert random turret fire delay:", AIPF_DONT_INSERT_RANDOM_TURRET_FIRE_DELAY, AIP_FLAG); + set_flag(profile, "$don't insert random turret fire delay:", AI::Profile_Flags::Dont_insert_random_turret_fire_delay); - set_flag(profile, "$hack improve non-homing swarm turret fire accuracy:", AIPF_HACK_IMPROVE_NON_HOMING_SWARM_TURRET_FIRE_ACCURACY, AIP_FLAG); + set_flag(profile, "$hack improve non-homing swarm turret fire accuracy:", AI::Profile_Flags::Hack_improve_non_homing_swarm_turret_fire_accuracy); - set_flag(profile, "$shockwaves damage small ship subsystems:", AIPF_SHOCKWAVES_DAMAGE_SMALL_SHIP_SUBSYSTEMS, AIP_FLAG); + set_flag(profile, "$shockwaves damage small ship subsystems:", AI::Profile_Flags::Shockwaves_damage_small_ship_subsystems); - set_flag(profile, "$navigation subsystem governs warpout capability:", AIPF_NAVIGATION_SUBSYS_GOVERNS_WARP, AIP_FLAG); + set_flag(profile, "$navigation subsystem governs warpout capability:", AI::Profile_Flags::Navigation_subsys_governs_warp); - set_flag(profile, "$ignore lower bound for minimum speed of docked ship:", AIPF_NO_MIN_DOCK_SPEED_CAP, AIP_FLAG); + set_flag(profile, "$ignore lower bound for minimum speed of docked ship:", AI::Profile_Flags::No_min_dock_speed_cap); - set_flag(profile, "$disable linked fire penalty:", AIPF_DISABLE_LINKED_FIRE_PENALTY, AIP_FLAG); + set_flag(profile, "$disable linked fire penalty:", AI::Profile_Flags::Disable_linked_fire_penalty); - set_flag(profile, "$disable weapon damage scaling:", AIPF_DISABLE_WEAPON_DAMAGE_SCALING, AIP_FLAG); + set_flag(profile, "$disable weapon damage scaling:", AI::Profile_Flags::Disable_weapon_damage_scaling); - set_flag(profile, "$use additive weapon velocity:", AIPF_USE_ADDITIVE_WEAPON_VELOCITY, AIP_FLAG); + set_flag(profile, "$use additive weapon velocity:", AI::Profile_Flags::Use_additive_weapon_velocity); - set_flag(profile, "$use newtonian dampening:", AIPF_USE_NEWTONIAN_DAMPENING, AIP_FLAG); + set_flag(profile, "$use newtonian dampening:", AI::Profile_Flags::Use_newtonian_dampening); - set_flag(profile, "$include beams for kills and assists:", AIPF_INCLUDE_BEAMS_IN_STAT_CALCS, AIP_FLAG); + set_flag(profile, "$include beams for kills and assists:", AI::Profile_Flags::Include_beams_in_stat_calcs); - set_flag(profile, "$score kills based on damage caused:", AIPF_KILL_SCORING_SCALES_WITH_DAMAGE, AIP_FLAG); + set_flag(profile, "$score kills based on damage caused:", AI::Profile_Flags::Kill_scoring_scales_with_damage); - set_flag(profile, "$score assists based on damage caused:", AIPF_ASSIST_SCORING_SCALES_WITH_DAMAGE, AIP_FLAG); + set_flag(profile, "$score assists based on damage caused:", AI::Profile_Flags::Assist_scoring_scales_with_damage); - set_flag(profile, "$allow event and goal scoring in multiplayer:", AIPF_ALLOW_MULTI_EVENT_SCORING, AIP_FLAG); + set_flag(profile, "$allow event and goal scoring in multiplayer:", AI::Profile_Flags::Allow_multi_event_scoring); - set_flag(profile, "$fix linked primary weapon decision bug:", AIPF_FIX_LINKED_PRIMARY_BUG, AIP_FLAG); + set_flag(profile, "$fix linked primary weapon decision bug:", AI::Profile_Flags::Fix_linked_primary_bug); - set_flag(profile, "$prevent turrets targeting too distant bombs:", AIPF_PREVENT_TARGETING_BOMBS_BEYOND_RANGE, AIP_FLAG); + set_flag(profile, "$prevent turrets targeting too distant bombs:", AI::Profile_Flags::Prevent_targeting_bombs_beyond_range); - set_flag(profile, "$smart subsystem targeting for turrets:", AIPF_SMART_SUBSYSTEM_TARGETING_FOR_TURRETS, AIP_FLAG); + set_flag(profile, "$smart subsystem targeting for turrets:", AI::Profile_Flags::Smart_subsystem_targeting_for_turrets); - set_flag(profile, "$fix heat seekers homing on stealth ships bug:", AIPF_FIX_HEAT_SEEKER_STEALTH_BUG, AIP_FLAG); + set_flag(profile, "$fix heat seekers homing on stealth ships bug:", AI::Profile_Flags::Fix_heat_seeker_stealth_bug); - set_flag(profile, "$multi allow empty primaries:", AIPF_MULTI_ALLOW_EMPTY_PRIMARIES, AIP_FLAG); + set_flag(profile, "$multi allow empty primaries:", AI::Profile_Flags::Multi_allow_empty_primaries); - set_flag(profile, "$multi allow empty secondaries:", AIPF_MULTI_ALLOW_EMPTY_SECONDARIES, AIP_FLAG); + set_flag(profile, "$multi allow empty secondaries:", AI::Profile_Flags::Multi_allow_empty_secondaries); - set_flag(profile, "$allow turrets target weapons freely:", AIPF_ALLOW_TURRETS_TARGET_WEAPONS_FREELY, AIP_FLAG); + set_flag(profile, "$allow turrets target weapons freely:", AI::Profile_Flags::Allow_turrets_target_weapons_freely); - set_flag(profile, "$use only single fov for turrets:", AIPF_USE_ONLY_SINGLE_FOV_FOR_TURRETS, AIP_FLAG); + set_flag(profile, "$use only single fov for turrets:", AI::Profile_Flags::Use_only_single_fov_for_turrets); - set_flag(profile, "$allow vertical dodge:", AIPF_ALLOW_VERTICAL_DODGE, AIP_FLAG); + set_flag(profile, "$allow vertical dodge:", AI::Profile_Flags::Allow_vertical_dodge); - set_flag(profile, "$force beam turrets to use normal fov:", AIPF_FORCE_BEAM_TURRET_FOV, AIP_FLAG); + set_flag(profile, "$force beam turrets to use normal fov:", AI::Profile_Flags::Force_beam_turret_fov); - set_flag(profile, "$fix ai class bug:", AIPF_FIX_AI_CLASS_BUG, AIP_FLAG); + set_flag(profile, "$fix ai class bug:", AI::Profile_Flags::Fix_ai_class_bug); - set_flag(profile, "$turrets ignore targets radius in range checks:", AIPF2_TURRETS_IGNORE_TARGET_RADIUS, AIP_FLAG2); + set_flag(profile, "$turrets ignore targets radius in range checks:", AI::Profile_Flags::Turrets_ignore_target_radius); - set_flag(profile, "$no extra collision avoidance vs player:", AIPF2_NO_SPECIAL_PLAYER_AVOID, AIP_FLAG2); + set_flag(profile, "$no extra collision avoidance vs player:", AI::Profile_Flags::No_special_player_avoid); - set_flag(profile, "$perform fewer checks for death screams:", AIPF2_PERFORM_FEWER_SCREAM_CHECKS, AIP_FLAG2); + set_flag(profile, "$perform fewer checks for death screams:", AI::Profile_Flags::Perform_fewer_scream_checks); - set_flag(profile, "$advanced turret fov edge checks:", AIPF2_ADVANCED_TURRET_FOV_EDGE_CHECKS, AIP_FLAG2); + set_flag(profile, "$advanced turret fov edge checks:", AI::Profile_Flags::Advanced_turret_fov_edge_checks); - set_flag(profile, "$require turrets to have target in fov:", AIPF2_REQUIRE_TURRET_TO_HAVE_TARGET_IN_FOV, AIP_FLAG2); + set_flag(profile, "$require turrets to have target in fov:", AI::Profile_Flags::Require_turret_to_have_target_in_fov); - set_flag(profile, "$all ships manage shields:", AIPF2_ALL_SHIPS_MANAGE_SHIELDS, AIP_FLAG2); + set_flag(profile, "$all ships manage shields:", AI::Profile_Flags::All_ships_manage_shields); - set_flag(profile, "$ai aims from ship center:", AIPF2_AI_AIMS_FROM_SHIP_CENTER, AIP_FLAG2); + set_flag(profile, "$ai aims from ship center:", AI::Profile_Flags::Ai_aims_from_ship_center); - set_flag(profile, "$allow primary link at mission start:", AIPF2_ALLOW_PRIMARY_LINK_AT_START, AIP_FLAG2); + set_flag(profile, "$allow primary link at mission start:", AI::Profile_Flags::Allow_primary_link_at_start); - set_flag(profile, "$allow beams to damage bombs:", AIPF2_BEAMS_DAMAGE_WEAPONS, AIP_FLAG2); + set_flag(profile, "$allow beams to damage bombs:", AI::Profile_Flags::Beams_damage_weapons); - set_flag(profile, "$disable weapon damage scaling for player:", AIPF2_PLAYER_WEAPON_SCALE_FIX, AIP_FLAG2); + set_flag(profile, "$disable weapon damage scaling for player:", AI::Profile_Flags::Player_weapon_scale_fix); - set_flag(profile, "$countermeasures affect aspect seekers:", AIPF2_ASPECT_LOCK_COUNTERMEASURE, AIP_FLAG2); + set_flag(profile, "$countermeasures affect aspect seekers:", AI::Profile_Flags::Aspect_lock_countermeasure); - set_flag(profile, "$ai guards specific ship in wing:", AIPF2_AI_GUARDS_SPECIFIC_SHIP_IN_WING, AIP_FLAG2); + set_flag(profile, "$ai guards specific ship in wing:", AI::Profile_Flags::Ai_guards_specific_ship_in_wing); profile->ai_path_mode = AI_PATH_MODE_NORMAL; if (optional_string("$ai path mode:")) @@ -457,17 +446,17 @@ void parse_ai_profiles_tbl(const char *filename) } } - set_flag(profile, "$no warp camera:", AIPF2_NO_WARP_CAMERA, AIP_FLAG2); + set_flag(profile, "$no warp camera:", AI::Profile_Flags::No_warp_camera); - set_flag(profile, "$fix ai path order bug:", AIPF2_FIX_AI_PATH_ORDER_BUG, AIP_FLAG2); + set_flag(profile, "$fix ai path order bug:", AI::Profile_Flags::Fix_ai_path_order_bug); - set_flag(profile, "$strict turret-tagged-only targeting:", AIPF2_STRICT_TURRET_TAGGED_ONLY_TARGETING, AIP_FLAG2); + set_flag(profile, "$strict turret-tagged-only targeting:", AI::Profile_Flags::Strict_turred_tagged_only_targeting); - set_flag(profile, "$aspect bomb invulnerability fix:", AIPF2_ASPECT_INVULNERABILITY_FIX, AIP_FLAG2); + set_flag(profile, "$aspect bomb invulnerability fix:", AI::Profile_Flags::Aspect_invulnerability_fix); - set_flag(profile, "$glide decay requires thrust:", AIPF2_GLIDE_DECAY_REQUIRES_THRUST, AIP_FLAG2); + set_flag(profile, "$glide decay requires thrust:", AI::Profile_Flags::Glide_decay_requires_thrust); - set_flag(profile, "$ai can slow down when attacking big ships:", AIPF2_AI_CAN_SLOW_DOWN_ATTACKING_BIG_SHIPS, AIP_FLAG2); + set_flag(profile, "$ai can slow down when attacking big ships:", AI::Profile_Flags::Ai_can_slow_down_attacking_big_ships); profile->bay_arrive_speed_mult = 1.0f; profile->bay_depart_speed_mult = 1.0f; @@ -486,20 +475,14 @@ void parse_ai_profiles_tbl(const char *filename) mprintf(("Warning: \"$perform less checks for death screams\" flag is deprecated in favor of \"$perform fewer checks for death screams\"\n")); bool temp; stuff_boolean(&temp); - if (temp) - profile->flags2 |= AIPF2_PERFORM_FEWER_SCREAM_CHECKS; - else - profile->flags2 &= ~AIPF2_PERFORM_FEWER_SCREAM_CHECKS; + profile->flags.set(AI::Profile_Flags::Perform_fewer_scream_checks, temp); } if (optional_string("$allow primary link delay:")) { mprintf(("Warning: \"$allow primary link delay\" flag is deprecated in favor of \"$allow primary link at mission start\"\n")); bool temp; stuff_boolean(&temp); - if (temp) - profile->flags2 &= ~AIPF2_ALLOW_PRIMARY_LINK_AT_START; - else - profile->flags2 |= AIPF2_ALLOW_PRIMARY_LINK_AT_START; + profile->flags.set(AI::Profile_Flags::Allow_primary_link_at_start, temp); } @@ -570,3 +553,69 @@ int ai_profile_lookup(char *name) return -1; } + +void ai_profile_t::reset() +{ + memset(profile_name, 0, sizeof(profile_name)); + + flags.reset(); + + ai_path_mode = 0; + bay_arrive_speed_mult = 0; + bay_depart_speed_mult = 0; + + for (int i = 0; i < NUM_SKILL_LEVELS; ++i) { + max_incoming_asteroids[i] = 0; + max_allowed_player_homers[i] = 0; + max_attackers[i] = 0; + predict_position_delay[i] = 0; + in_range_time[i] = 0; + shield_manage_delay[i] = 0; + + link_energy_levels_always[i] = 0; + link_energy_levels_maybe[i] = 0; + + link_ammo_levels_always[i] = 0; + link_ammo_levels_maybe[i] = 0; + primary_ammo_burst_mult[i] = 0; + + cmeasure_life_scale[i] = 0; + cmeasure_fire_chance[i] = 0; + weapon_energy_scale[i] = 0; + shield_energy_scale[i] = 0; + afterburner_recharge_scale[i] = 0; + player_damage_scale[i] = 0; + + subsys_damage_scale[i] = 0; + beam_friendly_damage_cap[i] = 0; + turn_time_scale[i] = 0; + glide_attack_percent[i] = 0; + circle_strafe_percent[i] = 0; + glide_strafe_percent[i] = 0; + random_sidethrust_percent[i] = 0; + stalemate_time_thresh[i] = 0; + stalemate_dist_thresh[i] = 0; + max_aim_update_delay[i] = 0; + turret_max_aim_update_delay[i] = 0; + + ship_fire_delay_scale_hostile[i] = 0; + ship_fire_delay_scale_friendly[i] = 0; + + ship_fire_secondary_delay_scale_hostile[i] = 0; + ship_fire_secondary_delay_scale_friendly[i] = 0; + + max_turret_ownage_target[i] = 0; + max_turret_ownage_player[i] = 0; + + kill_percentage_scale[i] = 0; + assist_percentage_scale[i] = 0; + + assist_award_percentage_scale[i] = 0; + + repair_penalty[i] = 0; + delay_bomb_arm_timer[i] = 0; + chance_to_use_missiles_on_plr[i] = 0; + player_autoaim_fov[i] = 0; + detail_distance_mult[i] = 0; + } +} diff --git a/code/ai/ai_profiles.h b/code/ai/ai_profiles.h index ba712399fa..27f14fd465 100644 --- a/code/ai/ai_profiles.h +++ b/code/ai/ai_profiles.h @@ -12,6 +12,7 @@ #include "globalincs/globals.h" #include "globalincs/pstypes.h" #include "globalincs/systemvars.h" +#include "ai/ai_flags.h" // flag int defines #define AIP_FLAG 1 @@ -76,12 +77,11 @@ #define MAX_AI_PROFILES 5 -typedef struct ai_profile_t { - +class ai_profile_t { +public: char profile_name[NAME_LENGTH]; - int flags; - int flags2; + flagset flags; // difficulty-related values int max_incoming_asteroids[NUM_SKILL_LEVELS]; // max number of asteroids thrown at friendlies @@ -159,7 +159,8 @@ typedef struct ai_profile_t { float bay_arrive_speed_mult; float bay_depart_speed_mult; -} ai_profile_t; + void reset(); +}; extern int Num_ai_profiles; diff --git a/code/ai/aibig.cpp b/code/ai/aibig.cpp index bb1959725d..1cd3ec4968 100644 --- a/code/ai/aibig.cpp +++ b/code/ai/aibig.cpp @@ -1206,7 +1206,7 @@ void ai_big_attack_get_data(vec3d *enemy_pos, float *dist_to_enemy, float *dot_t float weapon_speed; // Compute position of gun in absolute space and use that as fire position. - if (po->n_guns > 0 && !(The_mission.ai_profile->flags2 & AIPF2_AI_AIMS_FROM_SHIP_CENTER)) { + if (po->n_guns > 0 && !(The_mission.ai_profile->flags[AI::Profile_Flags::Ai_aims_from_ship_center])) { pnt = po->gun_banks[0].pnt[0]; vm_vec_unrotate(&gun_pos, &pnt, &Pl_objp->orient); vm_vec_add2(&gun_pos, &Pl_objp->pos); @@ -1351,7 +1351,7 @@ void ai_big_strafe_attack() turn_towards_point(Pl_objp, &target_pos, NULL, 0.0f); fix last_hit = Missiontime - aip->last_hit_time; - if ( aip->ai_profile_flags2 & AIPF2_AI_CAN_SLOW_DOWN_ATTACKING_BIG_SHIPS ) { + if ( aip->ai_profile_flags[AI::Profile_Flags::Ai_can_slow_down_attacking_big_ships] ) { // Slow down if we've not been hit for a while if ( target_dist > 1200 || last_hit < F1_0*6) { accel = 1.0f; @@ -1809,7 +1809,7 @@ void ai_big_strafe_maybe_attack_turret(object *ship_objp, object *weapon_objp) // the ai will not always go after different ships firing beams at them. // Approx 1/4 chance we'll go after the other ship's beam. - bool attack_turret_on_different_ship = (aip->ai_profile_flags & AIPF_BIG_SHIPS_CAN_ATTACK_BEAM_TURRETS_ON_UNTARGETED_SHIPS) + bool attack_turret_on_different_ship = (aip->ai_profile_flags[AI::Profile_Flags::Big_ships_can_attack_beam_turrets_on_untargeted_ships]) && (Weapon_info[Weapons[weapon_objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Beam]) && (frand()*100 < 25.0f); // unless we're making an exception, we should only attack a turret if it sits on the current target diff --git a/code/ai/aicode.cpp b/code/ai/aicode.cpp index c87b20b723..9ae9f85709 100644 --- a/code/ai/aicode.cpp +++ b/code/ai/aicode.cpp @@ -555,10 +555,8 @@ void init_ai_class(ai_class *aicp) aicp->ai_max_aim_update_delay[i] = FLT_MIN; aicp->ai_turret_max_aim_update_delay[i] = FLT_MIN; } - aicp->ai_profile_flags = 0; - aicp->ai_profile_flags_set = 0; - aicp->ai_profile_flags2 = 0; - aicp->ai_profile_flags2_set = 0; + aicp->ai_profile_flags.reset(); + aicp->ai_profile_flags_set.reset(); //AI Class autoscale overrides //INT_MIN and FLT_MIN represent the "not set" state @@ -572,25 +570,22 @@ void init_ai_class(ai_class *aicp) aicp->ai_class_autoscale = true; //Retail behavior is to do the stupid autoscaling } -void set_aic_flag(ai_class *aicp, char *name, int flag, int type) +void set_aic_flag(ai_class *aicp, char *name, AI::Profile_Flags flag) { - int* flags = (type == AIP_FLAG) ? &(aicp->ai_profile_flags) : &(aicp->ai_profile_flags2); - int* set = (type == AIP_FLAG) ? &(aicp->ai_profile_flags_set) : &(aicp->ai_profile_flags2_set); + auto flags = &(aicp->ai_profile_flags); + auto set = &(aicp->ai_profile_flags_set); if (optional_string(name)) { bool val; stuff_boolean(&val); - if (val) - *flags |= flag; - else - *flags &= ~flag; + flags->set(flag, val); - *set |= flag; - } + set->set(flag); + } else - *set &= ~flag; + set->remove(flag); } void parse_ai_class() @@ -740,35 +735,35 @@ void parse_ai_class() if (optional_string("$Turret Max Aim Update Delay:")) parse_float_list(aicp->ai_turret_max_aim_update_delay, NUM_SKILL_LEVELS); - set_aic_flag(aicp, "$big ships can attack beam turrets on untargeted ships:", AIPF_BIG_SHIPS_CAN_ATTACK_BEAM_TURRETS_ON_UNTARGETED_SHIPS, AIP_FLAG); + set_aic_flag(aicp, "$big ships can attack beam turrets on untargeted ships:", AI::Profile_Flags::Big_ships_can_attack_beam_turrets_on_untargeted_ships); - set_aic_flag(aicp, "$smart primary weapon selection:", AIPF_SMART_PRIMARY_WEAPON_SELECTION, AIP_FLAG); + set_aic_flag(aicp, "$smart primary weapon selection:", AI::Profile_Flags::Smart_primary_weapon_selection); - set_aic_flag(aicp, "$smart secondary weapon selection:", AIPF_SMART_SECONDARY_WEAPON_SELECTION, AIP_FLAG); + set_aic_flag(aicp, "$smart secondary weapon selection:", AI::Profile_Flags::Smart_secondary_weapon_selection); - set_aic_flag(aicp, "$smart shield management:", AIPF_SMART_SHIELD_MANAGEMENT, AIP_FLAG); + set_aic_flag(aicp, "$smart shield management:", AI::Profile_Flags::Smart_shield_management); - set_aic_flag(aicp, "$smart afterburner management:", AIPF_SMART_AFTERBURNER_MANAGEMENT, AIP_FLAG); + set_aic_flag(aicp, "$smart afterburner management:", AI::Profile_Flags::Smart_afterburner_management); - set_aic_flag(aicp, "$allow rapid secondary dumbfire:", AIPF_ALLOW_RAPID_SECONDARY_DUMBFIRE, AIP_FLAG); + set_aic_flag(aicp, "$allow rapid secondary dumbfire:", AI::Profile_Flags::Allow_rapid_secondary_dumbfire); - set_aic_flag(aicp, "$huge turret weapons ignore bombs:", AIPF_HUGE_TURRET_WEAPONS_IGNORE_BOMBS, AIP_FLAG); + set_aic_flag(aicp, "$huge turret weapons ignore bombs:", AI::Profile_Flags::Huge_turret_weapons_ignore_bombs); - set_aic_flag(aicp, "$don't insert random turret fire delay:", AIPF_DONT_INSERT_RANDOM_TURRET_FIRE_DELAY, AIP_FLAG); + set_aic_flag(aicp, "$don't insert random turret fire delay:", AI::Profile_Flags::Dont_insert_random_turret_fire_delay); - set_aic_flag(aicp, "$prevent turrets targeting too distant bombs:", AIPF_PREVENT_TARGETING_BOMBS_BEYOND_RANGE, AIP_FLAG); + set_aic_flag(aicp, "$prevent turrets targeting too distant bombs:", AI::Profile_Flags::Prevent_targeting_bombs_beyond_range); - set_aic_flag(aicp, "$smart subsystem targeting for turrets:", AIPF_SMART_SUBSYSTEM_TARGETING_FOR_TURRETS, AIP_FLAG); + set_aic_flag(aicp, "$smart subsystem targeting for turrets:", AI::Profile_Flags::Smart_subsystem_targeting_for_turrets); - set_aic_flag(aicp, "$allow turrets target weapons freely:", AIPF_ALLOW_TURRETS_TARGET_WEAPONS_FREELY, AIP_FLAG); + set_aic_flag(aicp, "$allow turrets target weapons freely:", AI::Profile_Flags::Allow_turrets_target_weapons_freely); - set_aic_flag(aicp, "$allow vertical dodge:", AIPF_ALLOW_VERTICAL_DODGE, AIP_FLAG); + set_aic_flag(aicp, "$allow vertical dodge:", AI::Profile_Flags::Allow_vertical_dodge); - set_aic_flag(aicp, "$no extra collision avoidance vs player:", AIPF2_NO_SPECIAL_PLAYER_AVOID, AIP_FLAG2); + set_aic_flag(aicp, "$no extra collision avoidance vs player:", AI::Profile_Flags::No_special_player_avoid); - set_aic_flag(aicp, "$all ships manage shields:", AIPF2_ALL_SHIPS_MANAGE_SHIELDS, AIP_FLAG2); + set_aic_flag(aicp, "$all ships manage shields:", AI::Profile_Flags::All_ships_manage_shields); - set_aic_flag(aicp, "$ai can slow down when attacking big ships:", AIPF2_AI_CAN_SLOW_DOWN_ATTACKING_BIG_SHIPS, AIP_FLAG2); + set_aic_flag(aicp, "$ai can slow down when attacking big ships:", AI::Profile_Flags::Ai_can_slow_down_attacking_big_ships); } void reset_ai_class_names() @@ -1354,7 +1349,7 @@ void adjust_accel_for_docking(ai_info *aip) float ratio = objp->phys_info.mass / dock_calc_total_docked_mass(objp); // put cap on how much ship can slow down - if ( (ratio < 0.8f) && !(The_mission.ai_profile->flags & AIPF_NO_MIN_DOCK_SPEED_CAP) ) { + if ( (ratio < 0.8f) && !(The_mission.ai_profile->flags[AI::Profile_Flags::No_min_dock_speed_cap]) ) { ratio = 0.8f; } @@ -4995,7 +4990,7 @@ void evade_weapon() rdot = vm_vec_dot(&Pl_objp->orient.vec.rvec, &vec_from_enemy); udot = vm_vec_dot(&Pl_objp->orient.vec.uvec, &vec_from_enemy); - if (aip->ai_profile_flags & AIPF_ALLOW_VERTICAL_DODGE && fl_abs(udot) > fl_abs(rdot)) + if (aip->ai_profile_flags[AI::Profile_Flags::Allow_vertical_dodge] && fl_abs(udot) > fl_abs(rdot)) { if ((udot < -0.5f) || (udot > 0.5f)) vm_vec_scale_add(&goal_point, &Pl_objp->pos, &Pl_objp->orient.vec.uvec, -200.0f); @@ -5119,7 +5114,7 @@ void evade_ship() if (percent_left > 30.0f + ((OBJ_INDEX(Pl_objp)) & 0x0f)) { afterburners_start(Pl_objp); - if (aip->ai_profile_flags & AIPF_SMART_AFTERBURNER_MANAGEMENT) { + if (aip->ai_profile_flags[AI::Profile_Flags::Smart_afterburner_management]) { aip->afterburner_stop_time = (fix) (Missiontime + F1_0 + static_randf(OBJ_INDEX(Pl_objp)) * F1_0 / 4); } else { aip->afterburner_stop_time = Missiontime + F1_0 + static_rand(OBJ_INDEX(Pl_objp))/4; @@ -5315,7 +5310,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, Weapon::Info_Flag } //not using the new AI, use the old version of this function instead. - if (!(Ai_info[shipp->ai_index].ai_profile_flags & AIPF_SMART_PRIMARY_WEAPON_SELECTION)) + if (!(Ai_info[shipp->ai_index].ai_profile_flags[AI::Profile_Flags::Smart_primary_weapon_selection])) { return ai_select_primary_weapon_OLD(objp, other_objp, flags); } @@ -5555,7 +5550,7 @@ void set_primary_weapon_linkage(object *objp) } // Don't want all ships always linking weapons at start, so asynchronize. - if (!(The_mission.ai_profile->flags2 & AIPF2_ALLOW_PRIMARY_LINK_AT_START)) + if (!(The_mission.ai_profile->flags[AI::Profile_Flags::Allow_primary_link_at_start])) { if (Missiontime < i2f(30)) return; @@ -5569,7 +5564,7 @@ void set_primary_weapon_linkage(object *objp) // get energy level float energy; - if (The_mission.ai_profile->flags & AIPF_FIX_LINKED_PRIMARY_BUG) { + if (The_mission.ai_profile->flags[AI::Profile_Flags::Fix_linked_primary_bug]) { energy = shipp->weapon_energy / sip->max_weapon_reserve * 100.0f; } else { energy = shipp->weapon_energy; @@ -5850,7 +5845,7 @@ void ai_select_secondary_weapon(object *objp, ship_weapon *swp, flagsetai_profile_flags & AIPF_SMART_SECONDARY_WEAPON_SELECTION) && (prio1.none_set())) { + if ((aip->ai_profile_flags[AI::Profile_Flags::Smart_secondary_weapon_selection]) && (prio1.none_set())) { ignore_mask.set(Weapon::Info_Flags::Homing_aspect).set(Weapon::Info_Flags::Homing_heat).set(Weapon::Info_Flags::Homing_javelin); } @@ -5858,7 +5853,7 @@ void ai_select_secondary_weapon(object *objp, ship_weapon *swp, flagsetsecondary_bank_weapons[weapon_bank_list[i]]].wi_flags; - auto ignore_mask_to_use = ((aip->ai_profile_flags & AIPF_SMART_SECONDARY_WEAPON_SELECTION) && (wi_flags[Weapon::Info_Flags::Bomber_plus])) ? (ignore_mask - Weapon::Info_Flags::Huge) : ignore_mask; + auto ignore_mask_to_use = ((aip->ai_profile_flags[AI::Profile_Flags::Smart_secondary_weapon_selection]) && (wi_flags[Weapon::Info_Flags::Bomber_plus])) ? (ignore_mask - Weapon::Info_Flags::Huge) : ignore_mask; if (!(wi_flags & ignore_mask_to_use).any_set()) { // Maybe bombs are illegal. if ((wi_flags & prio1).any_set()) { @@ -5870,7 +5865,7 @@ void ai_select_secondary_weapon(object *objp, ship_weapon *swp, flagsetai_profile_flags & AIPF_SMART_SECONDARY_WEAPON_SELECTION) && (prio2.none_set())) { + if ((aip->ai_profile_flags[AI::Profile_Flags::Smart_secondary_weapon_selection]) && (prio2.none_set())) { ignore_mask.set(Weapon::Info_Flags::Homing_aspect).set(Weapon::Info_Flags::Homing_heat).set(Weapon::Info_Flags::Homing_javelin); } @@ -5880,7 +5875,7 @@ void ai_select_secondary_weapon(object *objp, ship_weapon *swp, flagsetsecondary_bank_weapons[weapon_bank_list[i]]].wi_flags; - auto ignore_mask_to_use = ((aip->ai_profile_flags & AIPF_SMART_SECONDARY_WEAPON_SELECTION) && (wi_flags[Weapon::Info_Flags::Bomber_plus])) ? (ignore_mask - Weapon::Info_Flags::Huge) : ignore_mask; + auto ignore_mask_to_use = ((aip->ai_profile_flags[AI::Profile_Flags::Smart_secondary_weapon_selection]) && (wi_flags[Weapon::Info_Flags::Bomber_plus])) ? (ignore_mask - Weapon::Info_Flags::Huge) : ignore_mask; if (!(wi_flags & ignore_mask_to_use).any_set()) { // Maybe bombs are illegal. if (swp->secondary_bank_ammo[weapon_bank_list[i]] > 0) { @@ -5904,7 +5899,7 @@ void ai_select_secondary_weapon(object *objp, ship_weapon *swp, flagsetsecondary_bank_weapons[swp->current_secondary_bank]]; // phreak -- rapid dumbfire? let it rip! - if ((aip->ai_profile_flags & AIPF_ALLOW_RAPID_SECONDARY_DUMBFIRE) && !(wip->is_homing()) && (wip->fire_wait < .5f)) + if ((aip->ai_profile_flags[AI::Profile_Flags::Allow_rapid_secondary_dumbfire]) && !(wip->is_homing()) && (wip->fire_wait < .5f)) { aip->ai_flags |= AIF_UNLOAD_SECONDARIES; } @@ -6407,7 +6402,7 @@ void set_predicted_enemy_pos(vec3d *predicted_enemy_pos, object *pobjp, vec3d *e wip = ai_get_weapon(&shipp->weapons); target_moving_direction = *enemy_vel; - if (wip != NULL && The_mission.ai_profile->flags & AIPF_USE_ADDITIVE_WEAPON_VELOCITY) + if (wip != NULL && The_mission.ai_profile->flags[AI::Profile_Flags::Use_additive_weapon_velocity]) vm_vec_scale_sub2(&target_moving_direction, &pobjp->phys_info.vel, wip->vel_inherit_amount); if (wip != NULL) @@ -6439,7 +6434,7 @@ void set_predicted_enemy_pos(vec3d *predicted_enemy_pos, object *pobjp, vec3d *e // Compute position of gun in absolute space and use that as fire position // ...unless we want to just use the ship center - if(pm->gun_banks != NULL && !(The_mission.ai_profile->flags2 & AIPF2_AI_AIMS_FROM_SHIP_CENTER)){ + if(pm->gun_banks != NULL && !(The_mission.ai_profile->flags[AI::Profile_Flags::Ai_aims_from_ship_center])){ pnt = pm->gun_banks[0].pnt[0]; } else { //Use the convergence offset, if there is one @@ -6697,7 +6692,7 @@ void attack_set_accel(ai_info *aip, ship_info *sip, float dist_to_enemy, float d percent_left = 100.0f * shipp->afterburner_fuel / sip_local->afterburner_fuel_capacity; if (percent_left > 30.0f + ((OBJ_INDEX(Pl_objp)) & 0x0f)) { afterburners_start(Pl_objp); - if (aip->ai_profile_flags & AIPF_SMART_AFTERBURNER_MANAGEMENT) { + if (aip->ai_profile_flags[AI::Profile_Flags::Smart_afterburner_management]) { float max_ab_vel; float time_to_exhaust_25pct_fuel; float time_to_fly_75pct_of_distance; @@ -7230,7 +7225,7 @@ void ai_chase_attack(ai_info *aip, ship_info *sip, vec3d *predicted_enemy_pos, f float dot_to_enemy, dot_from_enemy; float bank_override = 0.0f; - if (!(aip->ai_profile_flags2 & AIPF2_NO_SPECIAL_PLAYER_AVOID) && avoid_player(Pl_objp, predicted_enemy_pos)) + if (!(aip->ai_profile_flags[AI::Profile_Flags::No_special_player_avoid]) && avoid_player(Pl_objp, predicted_enemy_pos)) return; compute_dots(Pl_objp, En_objp, &dot_to_enemy, &dot_from_enemy); @@ -7548,7 +7543,7 @@ void ai_set_guard_object(object *objp, object *other_objp) // If ship to guard is in a wing, guard that whole wing, unless the appropriate flag has been set ai_info *other_aip = &Ai_info[Ships[other_objp->instance].ai_index]; - if ((other_aip->wing != -1) && (other_aip->wing != aip->wing) && !(The_mission.ai_profile->flags2 & AIPF2_AI_GUARDS_SPECIFIC_SHIP_IN_WING)) { + if ((other_aip->wing != -1) && (other_aip->wing != aip->wing) && !(The_mission.ai_profile->flags[AI::Profile_Flags::Ai_guards_specific_ship_in_wing])) { ai_set_guard_wing(objp, Ai_info[Ships[other_objp->instance].ai_index].wing); } else { @@ -7743,7 +7738,7 @@ void ai_choose_secondary_weapon(object *objp, ai_info *aip, object *en_objp) if (is_big_ship) { wif_priority1.set(Weapon::Info_Flags::Huge); - if (aip->ai_profile_flags & AIPF_SMART_SECONDARY_WEAPON_SELECTION) { + if (aip->ai_profile_flags[AI::Profile_Flags::Smart_secondary_weapon_selection]) { wif_priority2.set(Weapon::Info_Flags::Bomber_plus); } else { @@ -7760,7 +7755,7 @@ void ai_choose_secondary_weapon(object *objp, ai_info *aip, object *en_objp) wif_priority1.set(Weapon::Info_Flags::Puncture); wif_priority2.set(Weapon::Info_Flags::Homing_aspect).set(Weapon::Info_Flags::Homing_heat).set(Weapon::Info_Flags::Homing_javelin); } - else if ((aip->ai_profile_flags & AIPF_SMART_SECONDARY_WEAPON_SELECTION) && (en_objp->type == OBJ_ASTEROID)) //prefer dumbfires if its an asteroid + else if ((aip->ai_profile_flags[AI::Profile_Flags::Smart_secondary_weapon_selection]) && (en_objp->type == OBJ_ASTEROID)) //prefer dumbfires if its an asteroid { wif_priority1.reset(); wif_priority2.reset(); @@ -11727,7 +11722,7 @@ int ai_formation() if (aip->mode == AIM_WAYPOINTS) { - if (The_mission.ai_profile->flags2 & AIPF2_FIX_AI_PATH_ORDER_BUG){ + if (The_mission.ai_profile->flags[AI::Profile_Flags::Fix_ai_path_order_bug]){ // skip if wing leader has no waypoint order or a different waypoint list if ((laip->mode != AIM_WAYPOINTS) || !(aip->wp_list == laip->wp_list)){ return 1; @@ -12285,7 +12280,7 @@ void ai_balance_shield(object *objp) for (i=0; in_quadrants; i++) { if (objp->shield_quadrant[i] < shield_strength_avg) { // only do it the retail way if using smart shields (since that's a bigger thing) - taylor - if (Ai_info[Ships[objp->instance].ai_index].ai_profile_flags & AIPF_SMART_SHIELD_MANAGEMENT) + if (Ai_info[Ships[objp->instance].ai_index].ai_profile_flags[AI::Profile_Flags::Smart_shield_management]) shield_add_strength(objp, delta); else objp->shield_quadrant[i] += delta/objp->n_quadrants; @@ -12295,7 +12290,7 @@ void ai_balance_shield(object *objp) } else { // only do it the retail way if using smart shields (since that's a bigger thing) - taylor - if (Ai_info[Ships[objp->instance].ai_index].ai_profile_flags & AIPF_SMART_SHIELD_MANAGEMENT) + if (Ai_info[Ships[objp->instance].ai_index].ai_profile_flags[AI::Profile_Flags::Smart_shield_management]) shield_add_strength(objp, -delta); else objp->shield_quadrant[i] -= delta/objp->n_quadrants; @@ -12335,7 +12330,7 @@ void ai_manage_shield(object *objp, ai_info *aip) // set timestamp aip->shield_manage_timestamp = timestamp((int) (delay * 1000.0f)); - if (sip->is_small_ship() || (aip->ai_profile_flags2 & AIPF2_ALL_SHIPS_MANAGE_SHIELDS)) { + if (sip->is_small_ship() || (aip->ai_profile_flags[AI::Profile_Flags::All_ships_manage_shields])) { if (Missiontime - aip->last_hit_time < F1_0*10) ai_transfer_shield(objp, aip->last_hit_quadrant); else @@ -14459,28 +14454,6 @@ void init_ai_system() Ppfp = Path_points; } -int combine_flags(int base_flags, int override_flags, int override_set) -{ - int result = 0; - //Scan through every bit in the flag int - for (int i = 0; i < 31; i++) - { - int flag = (1 << i); - //If this flag is marked in the override as set, copy it from the override - if (override_set & flag) - { - if (override_flags & flag) - result |= flag; - } - else //Otherwise, copy it from the base flag - { - if (base_flags & flag) - result |= flag; - } - } - return result; -} - //Sets the ai_info stuff based on what is in the ai class and the current ai profile //Stuff in the ai class will override what is in the ai profile, but only if it is set. //Unset per-difficulty-level values are marked with FLT_MIN or INT_MIN @@ -14556,8 +14529,7 @@ void init_aip_from_class_and_profile(ai_info *aip, ai_class *aicp, ai_profile_t profile->turret_max_aim_update_delay[Game_skill_level] : aicp->ai_turret_max_aim_update_delay[Game_skill_level]; //Combine AI profile and AI class flags - aip->ai_profile_flags = combine_flags(profile->flags, aicp->ai_profile_flags, aicp->ai_profile_flags_set); - aip->ai_profile_flags2 = combine_flags(profile->flags2, aicp->ai_profile_flags2, aicp->ai_profile_flags2_set); + aip->ai_profile_flags = profile->flags | (aicp->ai_profile_flags & aicp->ai_profile_flags_set); } void ai_do_default_behavior(object *obj) diff --git a/code/ai/aiturret.cpp b/code/ai/aiturret.cpp index 7a588fe313..e598d5cfeb 100644 --- a/code/ai/aiturret.cpp +++ b/code/ai/aiturret.cpp @@ -494,7 +494,7 @@ int valid_turret_enemy(object *objp, object *turret_parent) return 0; } - if ( (!((wip->wi_flags[Weapon::Info_Flags::Bomb]) || (wip->wi_flags[Weapon::Info_Flags::Turret_Interceptable])) && !(Ai_info[Ships[turret_parent->instance].ai_index].ai_profile_flags & AIPF_ALLOW_TURRETS_TARGET_WEAPONS_FREELY) ) ) { + if ( (!((wip->wi_flags[Weapon::Info_Flags::Bomb]) || (wip->wi_flags[Weapon::Info_Flags::Turret_Interceptable])) && !(Ai_info[Ships[turret_parent->instance].ai_index].ai_profile_flags[AI::Profile_Flags::Allow_turrets_target_weapons_freely]) ) ) { return 0; } @@ -598,7 +598,7 @@ void evaluate_obj_as_target(object *objp, eval_enemy_obj_struct *eeo) // however if this is removed turrets still track targets but don't fire at them (which looks silly) if (eeo->eeo_flags & EEOF_TAGGED_ONLY) { if (!ship_is_tagged(objp) && - ( (The_mission.ai_profile->flags2 & AIPF2_STRICT_TURRET_TAGGED_ONLY_TARGETING) || + ( (The_mission.ai_profile->flags[AI::Profile_Flags::Strict_turred_tagged_only_targeting]) || ( !(objp->type == OBJ_WEAPON) && !(turret_weapon_has_flags(&eeo->turret_subsys->weapons, Weapon::Info_Flags::Spawn))) )) { return; } @@ -656,7 +656,7 @@ void evaluate_obj_as_target(object *objp, eval_enemy_obj_struct *eeo) // check if bomb is homing on the turret parent ship bool check_weapon = true; - if ((Ai_info[Ships[turret_parent_obj->instance].ai_index].ai_profile_flags & AIPF_PREVENT_TARGETING_BOMBS_BEYOND_RANGE) && (dist > eeo->weapon_travel_dist)) { + if ((Ai_info[Ships[turret_parent_obj->instance].ai_index].ai_profile_flags[AI::Profile_Flags::Prevent_targeting_bombs_beyond_range]) && (dist > eeo->weapon_travel_dist)) { check_weapon = false; } @@ -1044,7 +1044,7 @@ int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subs case 0: //Return if a bomb is found //don't fire anti capital ship turrets at bombs. - if ( !((aip->ai_profile_flags & AIPF_HUGE_TURRET_WEAPONS_IGNORE_BOMBS) && big_only_flag) ) + if ( !((aip->ai_profile_flags[AI::Profile_Flags::Huge_turret_weapons_ignore_bombs]) && big_only_flag) ) { // Missile_obj_list for( mo = GET_FIRST(&Missile_obj_list); mo != END_OF_LIST(&Missile_obj_list); mo = GET_NEXT(mo) ) { @@ -1321,7 +1321,7 @@ void ship_get_global_turret_gun_info(object *objp, ship_subsys *ssp, vec3d *gpos vec3d target_moving_direction = ssp->last_aim_enemy_vel; //Try to guess where the enemy will be, and store that spot in predicted_enemy_pos - if (The_mission.ai_profile->flags & AIPF_USE_ADDITIVE_WEAPON_VELOCITY) { + if (The_mission.ai_profile->flags[AI::Profile_Flags::Use_additive_weapon_velocity]) { vm_vec_scale_sub2(&target_moving_direction, &objp->phys_info.vel, wip->vel_inherit_amount); } @@ -1417,7 +1417,7 @@ int aifft_rotate_turret(ship *shipp, int parent_objnum, ship_subsys *ss, object target_moving_direction = ss->last_aim_enemy_vel; //Try to guess where the enemy will be, and store that spot in predicted_enemy_pos - if (The_mission.ai_profile->flags & AIPF_USE_ADDITIVE_WEAPON_VELOCITY) { + if (The_mission.ai_profile->flags[AI::Profile_Flags::Use_additive_weapon_velocity]) { vm_vec_scale_sub2(&target_moving_direction, &objp->phys_info.vel, wip->vel_inherit_amount); } @@ -1490,7 +1490,7 @@ float aifft_compute_turret_dot(object *objp, object *enemy_objp, vec3d *abs_gunp vm_vec_unrotate(&turret_norm, &turret_subsysp->system_info->turret_norm, &objp->orient); float dot_return = vm_vec_dot(&turret_norm, &vector_out); - if (Ai_info[Ships[objp->instance].ai_index].ai_profile_flags & AIPF_SMART_SUBSYSTEM_TARGETING_FOR_TURRETS) { + if (Ai_info[Ships[objp->instance].ai_index].ai_profile_flags[AI::Profile_Flags::Smart_subsystem_targeting_for_turrets]) { if (dot_return > turret_subsysp->system_info->turret_fov) { // target is in sight and in fov return dot_return; @@ -1619,7 +1619,7 @@ ship_subsys *aifft_find_turret_subsys(object *objp, ship_subsys *ssp, object *en int idx; float dot_fov_modifier = 0.0f; - if (Ai_info[shipp->ai_index].ai_profile_flags & AIPF_SMART_SUBSYSTEM_TARGETING_FOR_TURRETS) { + if (Ai_info[shipp->ai_index].ai_profile_flags[AI::Profile_Flags::Smart_subsystem_targeting_for_turrets]) { if (ssp->system_info->turret_fov < 0) dot_fov_modifier = ssp->system_info->turret_fov; } @@ -2065,7 +2065,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum, } } //Not useful -WMC - else if (!(parent_aip->ai_profile_flags & AIPF_DONT_INSERT_RANDOM_TURRET_FIRE_DELAY) && last_shot_in_salvo) + else if (!(parent_aip->ai_profile_flags[AI::Profile_Flags::Dont_insert_random_turret_fire_delay]) && last_shot_in_salvo) { float wait = 1000.0f * frand_range(0.9f, 1.1f); turret->turret_next_fire_stamp = timestamp((int) wait); @@ -2104,7 +2104,7 @@ void turret_swarm_fire_from_turret(turret_swarm_info *tsi) // *If it's a non-homer, then use the last fire direction instead of turret orientation to fix inaccuracy // problems with non-homing swarm weapons -Et1 - if ( (Weapon_info[tsi->weapon_class].subtype == WP_LASER) || ((The_mission.ai_profile->flags & AIPF_HACK_IMPROVE_NON_HOMING_SWARM_TURRET_FIRE_ACCURACY) + if ( (Weapon_info[tsi->weapon_class].subtype == WP_LASER) || ((The_mission.ai_profile->flags[AI::Profile_Flags::Hack_improve_non_homing_swarm_turret_fire_accuracy]) && !(Weapon_info[tsi->weapon_class].is_homing())) ) { turret_fvec = tsi->turret->turret_last_fire_direction; @@ -2292,7 +2292,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum) //WMC - build a list of valid weapons. Fire spawns if there are any. float dist_to_enemy = 0.0f; if(lep != NULL) { - if (The_mission.ai_profile->flags2 & AIPF2_TURRETS_IGNORE_TARGET_RADIUS) + if (The_mission.ai_profile->flags[AI::Profile_Flags::Turrets_ignore_target_radius]) dist_to_enemy = MAX(0,vm_vec_normalized_dir(&v2e, &predicted_enemy_pos, &gpos)); else dist_to_enemy = MAX(0,vm_vec_normalized_dir(&v2e, &predicted_enemy_pos, &gpos) - lep->radius); @@ -2441,7 +2441,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum) else { // check tagged-only for non-ship targets - if (tagged_only && (!(lep->type == OBJ_WEAPON) || (The_mission.ai_profile->flags2 & AIPF2_STRICT_TURRET_TAGGED_ONLY_TARGETING))) { + if (tagged_only && (!(lep->type == OBJ_WEAPON) || (The_mission.ai_profile->flags[AI::Profile_Flags::Strict_turred_tagged_only_targeting]))) { continue; } } @@ -2608,7 +2608,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum) //turret_weapon_class = tp->turret_weapon_type; bool in_sight = false; - if (The_mission.ai_profile->flags & AIPF_USE_ONLY_SINGLE_FOV_FOR_TURRETS) { + if (The_mission.ai_profile->flags[AI::Profile_Flags::Use_only_single_fov_for_turrets]) { // we have already passed the FOV test of the turret so... in_sight = true; } else { diff --git a/code/hud/hudobserver.cpp b/code/hud/hudobserver.cpp index e80e131402..05e49e16ce 100644 --- a/code/hud/hudobserver.cpp +++ b/code/hud/hudobserver.cpp @@ -26,7 +26,7 @@ ai_info Hud_obs_ai; void hud_observer_init(ship *shipp, ai_info *aip) { // setup the pseduo ship and ai - memcpy(&Hud_obs_ai, aip, sizeof(ai_info)); + Hud_obs_ai = *aip; // (we used to do a memcpy here, but that doesn't work any longer, so let's just assign the values we need) Hud_obs_ship.clear(); strcpy_s(Hud_obs_ship.ship_name, shipp->ship_name); diff --git a/code/hud/hudtarget.cpp b/code/hud/hudtarget.cpp index ae9de01642..06ab2a1d39 100644 --- a/code/hud/hudtarget.cpp +++ b/code/hud/hudtarget.cpp @@ -3704,7 +3704,7 @@ void hud_calculate_lead_pos(vec3d *lead_target_pos, vec3d *target_pos, object *t target_moving_direction = targetp->phys_info.vel; - if(The_mission.ai_profile->flags & AIPF_USE_ADDITIVE_WEAPON_VELOCITY) + if(The_mission.ai_profile->flags[AI::Profile_Flags::Use_additive_weapon_velocity]) vm_vec_scale_sub2(&target_moving_direction, &Player_obj->phys_info.vel, wip->vel_inherit_amount); // test if the target is moving at all @@ -3797,7 +3797,7 @@ void polish_predicted_target_pos(weapon_info *wip, object *targetp, vec3d *enemy // additive velocity stuff // not just the player's main target vec3d enemy_vel = targetp->phys_info.vel; - if (The_mission.ai_profile->flags & AIPF_USE_ADDITIVE_WEAPON_VELOCITY) { + if (The_mission.ai_profile->flags[AI::Profile_Flags::Use_additive_weapon_velocity]) { vm_vec_scale_sub2( &enemy_vel, &Player_obj->phys_info.vel, wip->vel_inherit_amount); } diff --git a/code/mission/missiongoals.cpp b/code/mission/missiongoals.cpp index 88e882326b..293b3c95d6 100644 --- a/code/mission/missiongoals.cpp +++ b/code/mission/missiongoals.cpp @@ -734,7 +734,7 @@ void multi_player_maybe_add_score (int score, int team) return; } - if (!(The_mission.ai_profile->flags & AIPF_ALLOW_MULTI_EVENT_SCORING)) { + if (!(The_mission.ai_profile->flags[AI::Profile_Flags::Allow_multi_event_scoring])) { return; } diff --git a/code/mission/missionparse.cpp b/code/mission/missionparse.cpp index 4e942b2628..7d7e087e5d 100644 --- a/code/mission/missionparse.cpp +++ b/code/mission/missionparse.cpp @@ -1929,7 +1929,7 @@ int parse_create_object_sub(p_object *p_objp) aip->ai_class = p_objp->ai_class; shipp->weapons.ai_class = p_objp->ai_class; // Fred uses this instead of above. //Fixes a bug where the AI class attributes were not copied if the AI class was set in the mission. - if (The_mission.ai_profile->flags & AIPF_FIX_AI_CLASS_BUG) + if (The_mission.ai_profile->flags[AI::Profile_Flags::Fix_ai_class_bug]) ship_set_new_ai_class(shipnum, p_objp->ai_class); // must reset the number of ai goals when the object is created diff --git a/code/network/multiteamselect.cpp b/code/network/multiteamselect.cpp index 8f5f7ca093..d20428536d 100644 --- a/code/network/multiteamselect.cpp +++ b/code/network/multiteamselect.cpp @@ -2754,12 +2754,12 @@ int multi_ts_ok_to_commit() } // if the ship doesn't have primary weapons - if (!primary_ok && !(The_mission.ai_profile->flags & AIPF_MULTI_ALLOW_EMPTY_PRIMARIES)) { + if (!primary_ok && !(The_mission.ai_profile->flags[AI::Profile_Flags::Multi_allow_empty_secondaries])) { return 2; } // if the ship doesn't have secondary weapons - if (!secondary_ok && !(The_mission.ai_profile->flags & AIPF_MULTI_ALLOW_EMPTY_SECONDARIES)) { + if (!secondary_ok && !(The_mission.ai_profile->flags[AI::Profile_Flags::Multi_allow_empty_secondaries])) { return 3; } } diff --git a/code/object/collideweaponweapon.cpp b/code/object/collideweaponweapon.cpp index 5b770f0041..91a3844980 100644 --- a/code/object/collideweaponweapon.cpp +++ b/code/object/collideweaponweapon.cpp @@ -59,7 +59,7 @@ int collide_weapon_weapon( obj_pair * pair ) A_radius *= 2; // Makes bombs easier to hit } - if ((The_mission.ai_profile->flags2 & AIPF2_ASPECT_INVULNERABILITY_FIX) && (wipA->is_locked_homing()) && (wpA->homing_object != &obj_used_list)) { + if ((The_mission.ai_profile->flags[AI::Profile_Flags::Aspect_invulnerability_fix]) && (wipA->is_locked_homing()) && (wpA->homing_object != &obj_used_list)) { if ( (wipA->max_lifetime - wpA->lifeleft) < The_mission.ai_profile->delay_bomb_arm_timer[Game_skill_level] ) return 0; } @@ -71,7 +71,7 @@ int collide_weapon_weapon( obj_pair * pair ) if (!(wipB->wi_flags[Weapon::Info_Flags::Hard_target_bomb])) { B_radius *= 2; // Makes bombs easier to hit } - if ((The_mission.ai_profile->flags2 & AIPF2_ASPECT_INVULNERABILITY_FIX) && (wipB->is_locked_homing()) && (wpB->homing_object != &obj_used_list)) { + if ((The_mission.ai_profile->flags[AI::Profile_Flags::Aspect_invulnerability_fix]) && (wipB->is_locked_homing()) && (wpB->homing_object != &obj_used_list)) { if ( (wipB->max_lifetime - wpB->lifeleft) < The_mission.ai_profile->delay_bomb_arm_timer[Game_skill_level] ) return 0; } diff --git a/code/object/objectshield.cpp b/code/object/objectshield.cpp index c5d31e9566..23d303755f 100644 --- a/code/object/objectshield.cpp +++ b/code/object/objectshield.cpp @@ -55,7 +55,7 @@ void shield_add_strength(object *objp, float delta) if (shield_str >= shield_recharge_limit) return; - if (!(Ai_info[Ships[objp->instance].ai_index].ai_profile_flags & AIPF_SMART_SHIELD_MANAGEMENT) + if (!(Ai_info[Ships[objp->instance].ai_index].ai_profile_flags[AI::Profile_Flags::Smart_shield_management]) || delta <= 0.0f) //SUSHI: We don't want smart shield management for negative delta { // set the limit for the shield recharge diff --git a/code/physics/physics.cpp b/code/physics/physics.cpp index e813823bf2..93940bda45 100644 --- a/code/physics/physics.cpp +++ b/code/physics/physics.cpp @@ -716,7 +716,7 @@ void physics_read_flying_controls( matrix * orient, physics_info * pi, control_i // Only do the glide cap if we have one and are actively thrusting in some direction. // Unless AIPF2_GLIDE_DECAY_REQUIRES_THRUST isn't set. -MageKing17 - if ( curGlideCap >= 0.0f && (!(The_mission.ai_profile->flags2 & AIPF2_GLIDE_DECAY_REQUIRES_THRUST) || ci->forward != 0.0f || ci->sideways != 0.0f || ci->vertical != 0.0f) ) { + if ( curGlideCap >= 0.0f && (!(The_mission.ai_profile->flags[AI::Profile_Flags::Glide_decay_requires_thrust]) || ci->forward != 0.0f || ci->sideways != 0.0f || ci->vertical != 0.0f) ) { float currentmag = vm_vec_mag(&pi->desired_vel); if ( currentmag > curGlideCap ) { vm_vec_scale( &pi->desired_vel, curGlideCap / currentmag ); diff --git a/code/ship/ship.cpp b/code/ship/ship.cpp index 14c7477556..aa362f511a 100644 --- a/code/ship/ship.cpp +++ b/code/ship/ship.cpp @@ -5567,7 +5567,7 @@ void physics_ship_init(object *objp) pi->glide_accel_mult = sinfo->glide_accel_mult; //SUSHI: This defaults to the AI_Profile value, and is only optionally overridden - pi->use_newtonian_damp = ((The_mission.ai_profile->flags & AIPF_USE_NEWTONIAN_DAMPENING) != 0); + pi->use_newtonian_damp = The_mission.ai_profile->flags[AI::Profile_Flags::Use_newtonian_dampening]; if (sinfo->newtonian_damp_override) pi->use_newtonian_damp = sinfo->use_newtonian_damp; @@ -6494,9 +6494,9 @@ int subsys_set(int objnum, int ignore_subsys_info) // Wanderer if (model_system->flags & MSS_FLAG_NO_SS_TARGETING) ship_system->flags.set(Ship::Subsystem_Flags::No_SS_targeting); - if ((The_mission.ai_profile->flags2 & AIPF2_ADVANCED_TURRET_FOV_EDGE_CHECKS) || (model_system->flags & MSS_FLAG_FOV_EDGE_CHECK)) + if ((The_mission.ai_profile->flags[AI::Profile_Flags::Advanced_turret_fov_edge_checks]) || (model_system->flags & MSS_FLAG_FOV_EDGE_CHECK)) ship_system->flags.set(Ship::Subsystem_Flags::FOV_edge_check); - if ((The_mission.ai_profile->flags2 & AIPF2_REQUIRE_TURRET_TO_HAVE_TARGET_IN_FOV) || (model_system->flags & MSS_FLAG_FOV_REQUIRED)) + if ((The_mission.ai_profile->flags[AI::Profile_Flags::Require_turret_to_have_target_in_fov]) || (model_system->flags & MSS_FLAG_FOV_REQUIRED)) ship_system->flags.set(Ship::Subsystem_Flags::FOV_Required); if (model_system->flags & MSS_FLAG_NO_REPLACE) @@ -10717,7 +10717,7 @@ int ship_fire_primary(object * obj, int stream_weapons, int force) if (needs_target_pos) { target_velocity_vec = Objects[aip->target_objnum].phys_info.vel; - if (The_mission.ai_profile->flags & AIPF_USE_ADDITIVE_WEAPON_VELOCITY) + if (The_mission.ai_profile->flags[AI::Profile_Flags::Use_additive_weapon_velocity]) vm_vec_scale_sub2(&target_velocity_vec, &obj->phys_info.vel, winfo_p->vel_inherit_amount); } @@ -10786,7 +10786,7 @@ int ship_fire_primary(object * obj, int stream_weapons, int force) polymodel *pm = model_get( sip->model_num ); // Goober5000 (thanks to _argv[-1] for the original idea) - if ( (num_primary_banks > 1) && !(winfo_p->wi_flags[Weapon::Info_Flags::No_linked_penalty]) && !(The_mission.ai_profile->flags & AIPF_DISABLE_LINKED_FIRE_PENALTY) ) + if ( (num_primary_banks > 1) && !(winfo_p->wi_flags[Weapon::Info_Flags::No_linked_penalty]) && !(The_mission.ai_profile->flags[AI::Profile_Flags::Disable_linked_fire_penalty]) ) { int effective_primary_banks = 0; for (int it = 0; it < num_primary_banks; it++) @@ -14617,7 +14617,7 @@ int ship_engine_ok_to_warp(ship *sp) int ship_navigation_ok_to_warp(ship *sp) { // if not using the special flag, warp is always allowed - if (!(The_mission.ai_profile->flags & AIPF_NAVIGATION_SUBSYS_GOVERNS_WARP)) + if (!(The_mission.ai_profile->flags[AI::Profile_Flags::Navigation_subsys_governs_warp])) return 1; float navigation_strength = ship_get_subsystem_strength(sp, SUBSYSTEM_NAVIGATION); @@ -15613,7 +15613,7 @@ void ship_maybe_scream(ship *sp) return; // for WCSaga, only do a subset of the checks - if (!(The_mission.ai_profile->flags2 & AIPF2_PERFORM_FEWER_SCREAM_CHECKS)) + if (!(The_mission.ai_profile->flags[AI::Profile_Flags::Perform_fewer_scream_checks])) { // bail if this ship isn't from the player wing if (!(sp->flags[Ship_Flags::From_player_wing])) diff --git a/code/ship/shiphit.cpp b/code/ship/shiphit.cpp index 1bdcb67a03..d1bc2816af 100755 --- a/code/ship/shiphit.cpp +++ b/code/ship/shiphit.cpp @@ -478,7 +478,7 @@ float do_subobj_hit_stuff(object *ship_objp, object *other_obj, vec3d *hitpos, i { // MK, 9/2/99. Shockwaves do zero subsystem damage on small ships. // Goober5000 - added back in via flag - if ((Ship_info[ship_p->ship_info_index].is_small_ship()) && !(The_mission.ai_profile->flags & AIPF_SHOCKWAVES_DAMAGE_SMALL_SHIP_SUBSYSTEMS)) + if ((Ship_info[ship_p->ship_info_index].is_small_ship()) && !(The_mission.ai_profile->flags[AI::Profile_Flags::Shockwaves_damage_small_ship_subsystems])) return damage; else { damage_left = shockwave_get_damage(other_obj->instance) / 4.0f; @@ -2230,7 +2230,7 @@ static void ship_do_damage(object *ship_objp, object *other_obj, vec3d *hitpos, // Goober5000 - only count beams fired by fighters or bombers unless the ai profile says different if (bobjn >= 0) { - if ( !(The_mission.ai_profile->flags & AIPF_INCLUDE_BEAMS_IN_STAT_CALCS) && + if ( !(The_mission.ai_profile->flags[AI::Profile_Flags::Include_beams_in_stat_calcs]) && !(Ship_info[Ships[Objects[bobjn].instance].ship_info_index].is_fighter_bomber()) && !(Objects[bobjn].flags[Object::Object_Flags::Player_ship]) ) { bobjn = -1; diff --git a/code/stats/scoring.cpp b/code/stats/scoring.cpp index 67252b29ab..5079c5532c 100644 --- a/code/stats/scoring.cpp +++ b/code/stats/scoring.cpp @@ -673,7 +673,7 @@ int scoring_eval_kill(object *ship_objp) killer_sig = dead_ship->damage_ship_id[max_damage_index]; // set the scale value if we only award 100% score for 100% damage - if (The_mission.ai_profile->flags & AIPF_KILL_SCORING_SCALES_WITH_DAMAGE) { + if (The_mission.ai_profile->flags[AI::Profile_Flags::Kill_scoring_scales_with_damage]) { scoring_scale_by_damage = max_damage_pct; } @@ -998,7 +998,7 @@ void scoring_eval_assists(ship *sp,int killer_sig, bool is_enemy_player) // evaluate each damage slot to see if it did enough to give the assis for(idx=0;idxdamage_ship[idx]/sp->total_damage_received) >= Assist_percentage) || (The_mission.ai_profile->flags & AIPF_ASSIST_SCORING_SCALES_WITH_DAMAGE)){ + if(((sp->damage_ship[idx]/sp->total_damage_received) >= Assist_percentage) || (The_mission.ai_profile->flags[AI::Profile_Flags::Assist_scoring_scales_with_damage])){ // get the player which did this damage (if any) plr = NULL; @@ -1036,7 +1036,7 @@ void scoring_eval_assists(ship *sp,int killer_sig, bool is_enemy_player) // maybe award assist points based on damage - if (The_mission.ai_profile->flags & AIPF_ASSIST_SCORING_SCALES_WITH_DAMAGE) { + if (The_mission.ai_profile->flags[AI::Profile_Flags::Assist_scoring_scales_with_damage]) { scoring_scale_by_damage = (sp->damage_ship[idx]/sp->total_damage_received); assist_score = (int)(sp->score * scoring_scale_factor * scoring_scale_by_damage); plr->stats.m_score += assist_score; diff --git a/code/weapon/beam.cpp b/code/weapon/beam.cpp index c809db8c14..2ffcfc0f39 100644 --- a/code/weapon/beam.cpp +++ b/code/weapon/beam.cpp @@ -2913,7 +2913,7 @@ int beam_collide_early_out(object *a, object *b) /* if(bwi->b_info.beam_type == BEAM_TYPE_C){ return 1; }*/ - if(The_mission.ai_profile->flags2 & AIPF2_BEAMS_DAMAGE_WEAPONS) { + if(The_mission.ai_profile->flags[AI::Profile_Flags::Beams_damage_weapons]) { if((Weapon_info[Weapons[b->instance].weapon_info_index].weapon_hitpoints <= 0) && (Weapon_info[Weapons[b->instance].weapon_info_index].subtype == WP_LASER)) { return 1; } @@ -3199,7 +3199,7 @@ void beam_handle_collisions(beam *b) break; case OBJ_WEAPON: - if (The_mission.ai_profile->flags2 & AIPF2_BEAMS_DAMAGE_WEAPONS) { + if (The_mission.ai_profile->flags[AI::Profile_Flags::Beams_damage_weapons]) { if (!(Game_mode & GM_MULTIPLAYER) || MULTIPLAYER_MASTER) { object *trgt = &Objects[target]; @@ -3401,7 +3401,7 @@ int beam_ok_to_fire(beam *b) vm_vec_sub(&aim_dir, &b->last_shot, &b->last_start); vm_vec_normalize(&aim_dir); - if (The_mission.ai_profile->flags & AIPF_FORCE_BEAM_TURRET_FOV) { + if (The_mission.ai_profile->flags[AI::Profile_Flags::Force_beam_turret_fov]) { vec3d turret_normal; if (b->flags & BF_IS_FIGHTER_BEAM) { diff --git a/code/weapon/weapons.cpp b/code/weapon/weapons.cpp index 9a32db37fd..6acbbcf3f1 100644 --- a/code/weapon/weapons.cpp +++ b/code/weapon/weapons.cpp @@ -3714,7 +3714,7 @@ void find_homing_object(object *weapon_objp, int num) // Goober5000: if missiles can't home on sensor-ghosted ships, // they definitely shouldn't home on stealth ships - if ( sp->flags[Ship::Ship_Flags::Stealth] && (The_mission.ai_profile->flags & AIPF_FIX_HEAT_SEEKER_STEALTH_BUG) ) { + if ( sp->flags[Ship::Ship_Flags::Stealth] && (The_mission.ai_profile->flags[AI::Profile_Flags::Fix_heat_seeker_stealth_bug]) ) { continue; } @@ -3945,7 +3945,7 @@ bool aspect_should_lose_target(weapon* wp) if (target_info->wi_flags[Weapon::Info_Flags::Cmeasure]) { // Check if we can home on this countermeasure - bool home_on_cmeasure = The_mission.ai_profile->flags2 & AIPF2_ASPECT_LOCK_COUNTERMEASURE + bool home_on_cmeasure = The_mission.ai_profile->flags[AI::Profile_Flags::Aspect_lock_countermeasure] || target_info->wi_flags[Weapon::Info_Flags::Cmeasure_aspect_home_on]; if (!home_on_cmeasure) @@ -4128,7 +4128,7 @@ void weapon_home(object *obj, int num, float frame_time) break; case OBJ_WEAPON: { - bool home_on_cmeasure = The_mission.ai_profile->flags2 & AIPF2_ASPECT_LOCK_COUNTERMEASURE + bool home_on_cmeasure = The_mission.ai_profile->flags[AI::Profile_Flags::Aspect_lock_countermeasure] || hobj_infop->wi_flags[Weapon::Info_Flags::Cmeasure_aspect_home_on]; // don't home on countermeasures or non-bombs, that's handled elsewhere @@ -5350,7 +5350,7 @@ int weapon_create( vec3d * pos, matrix * porient, int weapon_type, int parent_ob // Turey - maybe make the initial speed of the weapon take into account the velocity of the parent. // Improves aiming during gliding. - if ((parent_objp != NULL) && (The_mission.ai_profile->flags & AIPF_USE_ADDITIVE_WEAPON_VELOCITY)) { + if ((parent_objp != NULL) && (The_mission.ai_profile->flags[AI::Profile_Flags::Use_additive_weapon_velocity])) { float pspeed = vm_vec_mag( &parent_objp->phys_info.vel ); vm_vec_scale_add2( &objp->phys_info.vel, &parent_objp->phys_info.vel, wip->vel_inherit_amount ); wp->weapon_max_vel += pspeed * wip->vel_inherit_amount; @@ -6963,7 +6963,7 @@ float weapon_get_damage_scale(weapon_info *wip, object *wep, object *target) // if the hit object was a ship and we're doing damage scaling if ( (target->type == OBJ_SHIP) && - !(The_mission.ai_profile->flags & AIPF_DISABLE_WEAPON_DAMAGE_SCALING) && + !(The_mission.ai_profile->flags[AI::Profile_Flags::Disable_weapon_damage_scaling]) && !(Ship_info[Ships[target->instance].ship_info_index].flags[Ship::Info_Flags::Disable_weapon_damage_scaling]) ) { ship_info *sip; @@ -7000,7 +7000,7 @@ float weapon_get_damage_scale(weapon_info *wip, object *wep, object *target) if( is_big_damage_ship && !(wip->hurts_big_ships()) ){ // if the player is firing it - if ( from_player && !(The_mission.ai_profile->flags2 & AIPF2_PLAYER_WEAPON_SCALE_FIX)) { + if ( from_player && !(The_mission.ai_profile->flags[AI::Profile_Flags::Player_weapon_scale_fix])) { // if it's a laser weapon if(wip->subtype == WP_LASER){ total_scale *= 0.01f; diff --git a/freespace2/freespace.cpp b/freespace2/freespace.cpp index 353a51a160..c7f2b8d629 100644 --- a/freespace2/freespace.cpp +++ b/freespace2/freespace.cpp @@ -5360,7 +5360,7 @@ void game_process_event( int current_state, int event ) shipfx_warpout_start( Player_obj ); Player->control_mode = PCM_WARPOUT_STAGE2; - if (!(The_mission.ai_profile->flags2 & AIPF2_NO_WARP_CAMERA)) { + if (!(The_mission.ai_profile->flags[AI::Profile_Flags::No_warp_camera])) { Player->saved_viewer_mode = Viewer_mode; Viewer_mode |= VM_WARP_CHASE; Warp_camera = warp_camera(Player_obj); From 69f33c5d959d2cedc8c6ed3a25307447073602ce Mon Sep 17 00:00:00 2001 From: Fabian Woltermann Date: Fri, 19 Aug 2016 22:45:35 +0200 Subject: [PATCH 09/16] Fixes an assert that got inadvertently inverted --- code/mission/missionmessage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/mission/missionmessage.cpp b/code/mission/missionmessage.cpp index f7da574594..686a600bbb 100644 --- a/code/mission/missionmessage.cpp +++ b/code/mission/missionmessage.cpp @@ -1976,7 +1976,7 @@ void message_send_builtin_to_player( int type, ship *shipp, int priority, int ti nprintf(("messaging", "Couldn't find persona for %s\n", shipp->ship_name )); // be sure that this ship can actually send a message!!! (i.e. not-not-flyable -- get it!) - Assert( !Ship_info[shipp->ship_info_index].is_flyable() ); // get allender or alan + Assert( Ship_info[shipp->ship_info_index].is_flyable() ); // get allender or alan } else { persona_index = The_mission.command_persona; // use the terran command persona } From 325442207cc6f197d2463f3334b1d52d30944451 Mon Sep 17 00:00:00 2001 From: Fabian Woltermann Date: Sat, 20 Aug 2016 12:57:32 +0200 Subject: [PATCH 10/16] Addressing feedback --- code/weapon/weapons.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/weapon/weapons.cpp b/code/weapon/weapons.cpp index 6bf38e912d..51c0d2ec28 100644 --- a/code/weapon/weapons.cpp +++ b/code/weapon/weapons.cpp @@ -99,7 +99,7 @@ flag_def_list_new Burst_fire_flags[] = { { "random length", Weapon::Burst_Flags::Random_length, true, false } }; -const int Num_burst_fire_flags = sizeof(Burst_fire_flags)/sizeof(flag_def_list_new); +const size_t Num_burst_fire_flags = sizeof(Burst_fire_flags)/sizeof(flag_def_list_new); weapon_explosions Weapon_explosions; From 204bb600ab89dd682c110b996436d7a5491ebe17 Mon Sep 17 00:00:00 2001 From: Risto Toijala Date: Sat, 20 Aug 2016 16:15:51 +0300 Subject: [PATCH 11/16] Remove leftovers of -debug_window cmdline arg --- code/cmdline/cmdline.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/code/cmdline/cmdline.cpp b/code/cmdline/cmdline.cpp index 3d46b1ecd3..b8fc2ae911 100644 --- a/code/cmdline/cmdline.cpp +++ b/code/cmdline/cmdline.cpp @@ -231,7 +231,6 @@ Flag exe_params[] = { "-output_sexps", "Output SEXPs to sexps.html", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-output_sexps", }, { "-output_scripting", "Output scripting to scripting.html", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-output_scripting", }, { "-save_render_target", "Save render targets to file", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-save_render_target", }, - { "-debug_window", "Display debug window", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-debug_window", }, { "-verify_vps", "Spew VP CRCs to vp_crcs.txt", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-verify_vps", }, { "-reparse_mainhall", "Reparse mainhall.tbl when loading halls", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-reparse_mainhall", }, { "-profile_frame_time","Profile engine subsystems", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-profile_frame_timings", }, From 16883beeb03821f9add2b76fe6596263a80f27fc Mon Sep 17 00:00:00 2001 From: Risto Toijala Date: Sat, 20 Aug 2016 17:31:54 +0300 Subject: [PATCH 12/16] Fix deferred lighting shader compilation --- code/def_files/deferred-f.sdr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/def_files/deferred-f.sdr b/code/def_files/deferred-f.sdr index ddb45a5c49..6789bd4ac7 100644 --- a/code/def_files/deferred-f.sdr +++ b/code/def_files/deferred-f.sdr @@ -30,7 +30,7 @@ vec3 FresnelSchlick(vec3 specColor, vec3 light, vec3 halfVec) } vec3 SpecularBlinnPhong(vec3 specColor, vec3 light, vec3 normal, vec3 halfVec, float specPower, float dotNL) { - return FresnelSchlick(max(specColor, vec3(0.04)), light, halfVec) * ((specPower + 2) / 8 ) * pow(clamp(dot(normal, halfVec), 0.0, 1.0), specPower) * dotNL; + return FresnelSchlick(max(specColor, vec3(0.04)), light, halfVec) * ((specPower + 2.0) / 8.0 ) * pow(clamp(dot(normal, halfVec), 0.0, 1.0), specPower) * dotNL; } vec4 SpecularLegacy(vec4 specColor, vec3 normal, vec3 halfVec, float specPower) { From c57e59d76aff0b82ebc8e1beafc700aa4c9dd985 Mon Sep 17 00:00:00 2001 From: Fabian Woltermann Date: Sat, 20 Aug 2016 20:42:22 +0200 Subject: [PATCH 13/16] Addressing feedback --- code/ai/ai_profiles.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/ai/ai_profiles.cpp b/code/ai/ai_profiles.cpp index 43c5535af1..4e32ab602c 100644 --- a/code/ai/ai_profiles.cpp +++ b/code/ai/ai_profiles.cpp @@ -28,7 +28,7 @@ static char Default_profile_name[NAME_LENGTH]; // utility -void set_flag(ai_profile_t *profile, char *name, AI::Profile_Flags flag) +void set_flag(ai_profile_t *profile, const char *name, AI::Profile_Flags flag) { if (optional_string(name)) { @@ -482,7 +482,7 @@ void parse_ai_profiles_tbl(const char *filename) mprintf(("Warning: \"$allow primary link delay\" flag is deprecated in favor of \"$allow primary link at mission start\"\n")); bool temp; stuff_boolean(&temp); - profile->flags.set(AI::Profile_Flags::Allow_primary_link_at_start, temp); + profile->flags.set(AI::Profile_Flags::Allow_primary_link_at_start, !temp); } From c74eb9a88bc1765dda63c4e8186669539c4e8b04 Mon Sep 17 00:00:00 2001 From: asarium Date: Fri, 19 Aug 2016 23:58:09 +0200 Subject: [PATCH 14/16] Enable cotire by default for Visual Studio --- CMakeLists.txt | 10 ++++-- cmake/toolchain-msvc.cmake | 38 ++++++++++---------- cmake/util.cmake | 7 +--- code/sound/acm.cpp | 72 ++++++++++++++++++-------------------- 4 files changed, 63 insertions(+), 64 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f39dd1fa95..0439bc7049 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -108,7 +108,13 @@ SET(FSO_RUN_ARGUMENTS "" CACHE STRING "Additional arguments passed to a generate option(FSO_INSTALL_DEBUG_FILES "Install some debug files (currently only PDB files on windows)" OFF) -OPTION(COTIRE_ENABLE "Enable cotire, this speeds up builds but may cause issues while developing (default = OFF)" OFF) +set(DEFAULT_VAL OFF) +if(MSVC) + # MSVC has been tested + set(DEFAULT_VAL ON) +endif() + +OPTION(COTIRE_ENABLE "Enable cotire, this speeds up builds but may cause issues while developing (default = OFF)" ${DEFAULT_VAL}) MARK_AS_ADVANCED(FORCE FSO_CMAKE_DEBUG) MARK_AS_ADVANCED(FORCE FSO_BUILD_INCLUDED_LIBS) @@ -189,4 +195,4 @@ elseif(UNIX) ENDIF() message(STATUS "Building FSO tools: ${FSO_BUILD_TOOLS}") message(STATUS "Building wxFRED: ${FSO_BUILD_WXFRED2}") -message(STATUS "Fatal warnings: ${FSO_FATAL_WARNINGS}") \ No newline at end of file +message(STATUS "Fatal warnings: ${FSO_FATAL_WARNINGS}") diff --git a/cmake/toolchain-msvc.cmake b/cmake/toolchain-msvc.cmake index 2c3276dcac..492df012c7 100644 --- a/cmake/toolchain-msvc.cmake +++ b/cmake/toolchain-msvc.cmake @@ -12,25 +12,25 @@ MARK_AS_ADVANCED(FORCE MSVC_USE_RUNTIME_DLL) # These are the warnings we disable set(WARNING_FLAGS - /wd"4100" # unreferenced formal parameters - /wd"4127" # constant conditional (assert) - /wd"4201" # nonstandard extension used: nameless struct/union (happens a lot in Windows include headers) - /wd"4290" # C++ exception specification ignored except to indicate a function is not __declspec(nothrow) - /wd"4390" # empty control statement (triggered by nprintf and mprintf's inside of one-line if's, etc) - /wd"4410" # illegal size for operand... ie... fxch st(1) - /wd"4511" # copy constructor could not be generated (happens a lot in Windows include headers) - /wd"4512" # assignment operator could not be generated (happens a lot in Windows include headers) - /wd"4514" # unreferenced inline function removed - /wd"4611" # _setjmp warning. Since we use setjmp alot, and we don't really use constructors or destructors, this warning doesn't really apply to us. - /wd"4663" # C++ language change (template specification) - /wd"4710" # is inline function not expanded (who cares?) - /wd"4711" # tells us an inline function was expanded (who cares?) - /wd"4786" # is identifier truncated to 255 characters (happens all the time in Microsoft #includes) -- Goober5000" - /wd"4996" # deprecated strcpy, strcat, sprintf, etc. (from MSVC 2005) - taylor - /wd"4311" # Disables warnings about casting pointer types to ints. The funny thing is these warnings can't be resolved, just disabled... - m!m - /wd"4302" # Same as above - m!m - /wd"4366" # The result of the unary '&' operator may be unaligned - m!m - $<$:/wd"4101"> # In release mode there are unreferenced variables because debug needs them + /wd4100 # unreferenced formal parameters + /wd4127 # constant conditional (assert) + /wd4201 # nonstandard extension used: nameless struct/union (happens a lot in Windows include headers) + /wd4290 # C++ exception specification ignored except to indicate a function is not __declspec(nothrow) + /wd4390 # empty control statement (triggered by nprintf and mprintf's inside of one-line if's, etc) + /wd4410 # illegal size for operand... ie... fxch st(1) + /wd4511 # copy constructor could not be generated (happens a lot in Windows include headers) + /wd4512 # assignment operator could not be generated (happens a lot in Windows include headers) + /wd4514 # unreferenced inline function removed + /wd4611 # _setjmp warning. Since we use setjmp alot, and we don't really use constructors or destructors, this warning doesn't really apply to us. + /wd4663 # C++ language change (template specification) + /wd4710 # is inline function not expanded (who cares?) + /wd4711 # tells us an inline function was expanded (who cares?) + /wd4786 # is identifier truncated to 255 characters (happens all the time in Microsoft #includes) -- Goober5000" + /wd4996 # deprecated strcpy, strcat, sprintf, etc. (from MSVC 2005) - taylor + /wd4311 # Disables warnings about casting pointer types to ints. The funny thing is these warnings can't be resolved, just disabled... - m!m + /wd4302 # Same as above - m!m + /wd4366 # The result of the unary '&' operator may be unaligned - m!m + $<$:/wd4101> # In release mode there are unreferenced variables because debug needs them ) target_compile_options(compiler INTERFACE ${WARNING_FLAGS}) diff --git a/cmake/util.cmake b/cmake/util.cmake index 010627a15d..cd9b47979e 100644 --- a/cmake/util.cmake +++ b/cmake/util.cmake @@ -128,12 +128,7 @@ macro(configure_cotire target) # add ignored paths for the precompiled header here set_target_properties(code PROPERTIES COTIRE_PREFIX_HEADER_IGNORE_PATH "${CMAKE_SOURCE_DIR};${CMAKE_BINARY_DIR}") - - IF(DEFINED CMAKE_CONFIGURATION_TYPES) - cotire(${target} CONFIGURATIONS ${CMAKE_CONFIGURATION_TYPES}) - ELSE(DEFINED CMAKE_CONFIGURATION_TYPES) - cotire(${target}) - ENDIF(DEFINED CMAKE_CONFIGURATION_TYPES) + cotire(${target}) ENDIF(COTIRE_ENABLE) endmacro(configure_cotire) diff --git a/code/sound/acm.cpp b/code/sound/acm.cpp index dcb8bbb1bb..0695884d72 100644 --- a/code/sound/acm.cpp +++ b/code/sound/acm.cpp @@ -13,34 +13,33 @@ #include -// we aren't including all of mmreg.h on Windows so this picks up the slack #ifndef WAVE_FORMAT_ADPCM #define WAVE_FORMAT_ADPCM 2 #endif -typedef struct adpcmcoef_tag { +typedef struct fs_adpcmcoef_tag { short iCoef1; short iCoef2; -} ADPCMCOEFSET; +} FS_ADPCMCOEFSET; -typedef struct adpcmblockheader_tag { +typedef struct fs_adpcmblockheader_tag { ubyte bPredictor; ushort iDelta; short iSamp1; short iSamp2; -} ADPCMBLOCKHEADER; +} FS_ADPCMBLOCKHEADER; -typedef struct adpcmwaveformat_tag { +typedef struct fs_adpcmwaveformat_tag { WAVEFORMATEX wav; WORD wSamplesPerBlock; WORD wNumCoef; - ADPCMCOEFSET *aCoef; -} ADPCMWAVEFORMAT; + FS_ADPCMCOEFSET *aCoef; +} FS_ADPCMWAVEFORMAT; -typedef struct ADPCM_FMT_T { - ADPCMWAVEFORMAT adpcm; - ADPCMBLOCKHEADER *header; +typedef struct FS_ADPCM_FMT_T { + FS_ADPCMWAVEFORMAT adpcm; + FS_ADPCMBLOCKHEADER *header; int bytes_remaining; uint bytes_processed; @@ -51,14 +50,13 @@ typedef struct ADPCM_FMT_T { ubyte nibble; ushort dest_bps; -} adpcm_fmt_t; +} fs_adpcm_fmt_t; -typedef struct acm_stream_t { - adpcm_fmt_t *fmt; +typedef struct fs_acm_stream_t { + fs_adpcm_fmt_t *fmt; ushort dest_bps; ushort src_bps; -} acm_stream_t; - +} fs_acm_stream_t; // similar to BIAL_IF_MACRO in SDL_sound #define IF_ERR(a, b) if (a) { mprintf(("ACM ERROR, line %d...\n", __LINE__)); return b; } @@ -126,7 +124,7 @@ static int read_ubyte(SDL_RWops* rw, ubyte *i) } // decoding functions -static int read_adpcm_block_headers(SDL_RWops* rw, adpcm_fmt_t *fmt) +static int read_adpcm_block_headers(SDL_RWops* rw, fs_adpcm_fmt_t *fmt) { int i; int max = fmt->adpcm.wav.nChannels; @@ -160,7 +158,7 @@ static int read_adpcm_block_headers(SDL_RWops* rw, adpcm_fmt_t *fmt) return 1; } -static void do_adpcm_nibble(ubyte nib, ADPCMBLOCKHEADER *header, int lPredSamp) +static void do_adpcm_nibble(ubyte nib, FS_ADPCMBLOCKHEADER *header, int lPredSamp) { static const short max_audioval = ((1<<(16-1))-1); static const short min_audioval = -(1<<(16-1)); @@ -196,7 +194,7 @@ static void do_adpcm_nibble(ubyte nib, ADPCMBLOCKHEADER *header, int lPredSamp) header->iSamp1 = (short)lNewSamp; } -static int decode_adpcm_sample_frame(SDL_RWops* rw, adpcm_fmt_t *fmt) +static int decode_adpcm_sample_frame(SDL_RWops* rw, fs_adpcm_fmt_t *fmt) { int i; int max = fmt->adpcm.wav.nChannels; @@ -224,7 +222,7 @@ static int decode_adpcm_sample_frame(SDL_RWops* rw, adpcm_fmt_t *fmt) return 1; } -static void put_adpcm_sample_frame1(ubyte *_buf, adpcm_fmt_t *fmt) +static void put_adpcm_sample_frame1(ubyte *_buf, fs_adpcm_fmt_t *fmt) { int i; @@ -246,7 +244,7 @@ static void put_adpcm_sample_frame1(ubyte *_buf, adpcm_fmt_t *fmt) } } -static void put_adpcm_sample_frame2(ubyte *_buf, adpcm_fmt_t *fmt) +static void put_adpcm_sample_frame2(ubyte *_buf, fs_adpcm_fmt_t *fmt) { int i; @@ -268,7 +266,7 @@ static void put_adpcm_sample_frame2(ubyte *_buf, adpcm_fmt_t *fmt) } } -static uint read_sample_fmt_adpcm(ubyte *data, SDL_RWops* rw, adpcm_fmt_t *fmt) +static uint read_sample_fmt_adpcm(ubyte *data, SDL_RWops* rw, fs_adpcm_fmt_t *fmt) { uint bw = 0; @@ -310,7 +308,7 @@ static uint read_sample_fmt_adpcm(ubyte *data, SDL_RWops* rw, adpcm_fmt_t *fmt) /* End ADPCM Compression Handler * *****************************************************************************/ -static void adpcm_memory_free(adpcm_fmt_t *fmt) +static void adpcm_memory_free(fs_adpcm_fmt_t *fmt) { if (fmt->adpcm.aCoef != NULL) { vm_free(fmt->adpcm.aCoef); @@ -371,9 +369,9 @@ int ACM_convert_ADPCM_to_PCM(WAVEFORMATEX *pwfxSrc, ubyte *src, int src_len, uby int left_over = 0; int i; - adpcm_fmt_t *fmt = (adpcm_fmt_t *)vm_malloc(sizeof(adpcm_fmt_t)); + fs_adpcm_fmt_t *fmt = (fs_adpcm_fmt_t *)vm_malloc(sizeof(fs_adpcm_fmt_t)); IF_ERR(fmt == NULL, -1); - memset(fmt, '\0', sizeof(adpcm_fmt_t)); + memset(fmt, '\0', sizeof(fs_adpcm_fmt_t)); // wav header info (WAVEFORMATEX) IF_ERR2(!read_word(hdr, &fmt->adpcm.wav.wFormatTag), goto Error); @@ -388,7 +386,7 @@ int ACM_convert_ADPCM_to_PCM(WAVEFORMATEX *pwfxSrc, ubyte *src, int src_len, uby IF_ERR2(!read_word_s(hdr, &fmt->adpcm.wNumCoef), goto Error); // allocate memory for COEF struct and fill it - fmt->adpcm.aCoef = (ADPCMCOEFSET *)vm_malloc(sizeof(ADPCMCOEFSET) * fmt->adpcm.wNumCoef); + fmt->adpcm.aCoef = (FS_ADPCMCOEFSET *)vm_malloc(sizeof(FS_ADPCMCOEFSET) * fmt->adpcm.wNumCoef); IF_ERR2(fmt->adpcm.aCoef == NULL, goto Error); for (i = 0; i < fmt->adpcm.wNumCoef; i++) { @@ -397,7 +395,7 @@ int ACM_convert_ADPCM_to_PCM(WAVEFORMATEX *pwfxSrc, ubyte *src, int src_len, uby } // allocate memory for the ADPCM block header that's to be filled later - fmt->header = (ADPCMBLOCKHEADER *)vm_malloc(sizeof(ADPCMBLOCKHEADER) * fmt->adpcm.wav.nChannels); + fmt->header = (FS_ADPCMBLOCKHEADER *)vm_malloc(sizeof(FS_ADPCMBLOCKHEADER) * fmt->adpcm.wav.nChannels); IF_ERR2(fmt->header == NULL, goto Error); // estimate size of uncompressed data @@ -498,13 +496,13 @@ int ACM_stream_open(WAVEFORMATEX *pwfxSrc, WAVEFORMATEX *pwfxDest, void **stream Assert( pwfxSrc->wFormatTag == WAVE_FORMAT_ADPCM ); int i; - acm_stream_t *str = NULL; + fs_acm_stream_t *str = NULL; auto hdr = SDL_RWFromConstMem((void*)pwfxSrc, sizeof(WAVEFORMATEX) + pwfxSrc->cbSize); - adpcm_fmt_t *fmt = (adpcm_fmt_t *)vm_malloc(sizeof(adpcm_fmt_t)); + fs_adpcm_fmt_t *fmt = (fs_adpcm_fmt_t *)vm_malloc(sizeof(fs_adpcm_fmt_t)); IF_ERR2(fmt == NULL, goto Error); - memset(fmt, '\0', sizeof(adpcm_fmt_t)); + memset(fmt, '\0', sizeof(fs_adpcm_fmt_t)); // wav header info (WAVEFORMATEX) IF_ERR2(!read_word(hdr, &fmt->adpcm.wav.wFormatTag), goto Error); @@ -519,7 +517,7 @@ int ACM_stream_open(WAVEFORMATEX *pwfxSrc, WAVEFORMATEX *pwfxDest, void **stream IF_ERR2(!read_word_s(hdr, &fmt->adpcm.wNumCoef), goto Error); // allocate memory for COEF struct and fill it - fmt->adpcm.aCoef = (ADPCMCOEFSET *)vm_malloc(sizeof(ADPCMCOEFSET) * fmt->adpcm.wNumCoef); + fmt->adpcm.aCoef = (FS_ADPCMCOEFSET *)vm_malloc(sizeof(FS_ADPCMCOEFSET) * fmt->adpcm.wNumCoef); IF_ERR2(fmt->adpcm.aCoef == NULL, goto Error); for (i = 0; i < fmt->adpcm.wNumCoef; i++) { @@ -528,7 +526,7 @@ int ACM_stream_open(WAVEFORMATEX *pwfxSrc, WAVEFORMATEX *pwfxDest, void **stream } // allocate memory for the ADPCM block header that's to be filled later - fmt->header = (ADPCMBLOCKHEADER *)vm_malloc(sizeof(ADPCMBLOCKHEADER) * fmt->adpcm.wav.nChannels); + fmt->header = (FS_ADPCMBLOCKHEADER *)vm_malloc(sizeof(FS_ADPCMBLOCKHEADER) * fmt->adpcm.wav.nChannels); IF_ERR2(fmt->header == NULL, goto Error); // sanity check, should always be 4 @@ -542,7 +540,7 @@ int ACM_stream_open(WAVEFORMATEX *pwfxSrc, WAVEFORMATEX *pwfxDest, void **stream fmt->sample_frame_size = dest_bps/8*pwfxSrc->nChannels; fmt->dest_bps = (ushort)dest_bps; - str = (acm_stream_t *)vm_malloc(sizeof(acm_stream_t)); + str = (fs_acm_stream_t *)vm_malloc(sizeof(fs_acm_stream_t)); IF_ERR2(str == NULL, goto Error); str->fmt = fmt; str->dest_bps = (ushort)dest_bps; @@ -578,7 +576,7 @@ int ACM_stream_close(void *stream) return 0; } - acm_stream_t *str = (acm_stream_t *)stream; + fs_acm_stream_t *str = (fs_acm_stream_t *)stream; adpcm_memory_free(str->fmt); vm_free(str); @@ -592,7 +590,7 @@ int ACM_query_source_size(void *stream, int dest_len) return 0; } - acm_stream_t *str = (acm_stream_t *)stream; + fs_acm_stream_t *str = (fs_acm_stream_t *)stream; // estimate size of compressed data // uncompressed data has: channels=pfwxScr->nChannels, bitPerSample=destbits @@ -607,7 +605,7 @@ int ACM_query_dest_size(void *stream, int src_len) return 0; } - acm_stream_t *str = (acm_stream_t *)stream; + fs_acm_stream_t *str = (fs_acm_stream_t *)stream; // estimate size of uncompressed data // uncompressed data has: channels=pfwxScr->nChannels, bitPerSample=destbits @@ -626,7 +624,7 @@ int ACM_convert(void *stream, ubyte *src, int src_len, ubyte *dest, int max_dest return 0; } - acm_stream_t *str = (acm_stream_t *)stream; + fs_acm_stream_t *str = (fs_acm_stream_t *)stream; uint rc; auto rw = SDL_RWFromConstMem((void*) src, src_len); From d87babfd928a01e815e3ac22ae85ca45d1fbb8bb Mon Sep 17 00:00:00 2001 From: Goober5000 Date: Sat, 13 Aug 2016 19:23:06 -0400 Subject: [PATCH 15/16] remove the SIF_BALLISTIC_PRIMARIES flag See also my comments on #762. The flag is almost entirely redundant, so this PR removes it in all instances where it's used in the ballistic primaries code. There are one or two places where removing it was not a no-op, so I adjusted the rest of the code accordingly (most notably in the parsing validation when it checks that primary weapon cargo has been assigned). I also added a few divide-by-zero checks and slightly tweaked the support ship rearm code. The use of the SIF_BALLISTIC_PRIMARIES flag in the ingame_join code was replaced with a dummy value to avoid bumping the multiplayer packet version number. --- code/ai/aicode.cpp | 72 +++--- code/hud/hudtarget.cpp | 14 +- code/io/keycontrol.cpp | 17 +- code/missionui/missionweaponchoice.cpp | 13 +- code/network/multi_ingame.cpp | 10 +- code/parse/sexp.cpp | 26 +- code/ship/ship.cpp | 330 ++++++++++++------------- 7 files changed, 226 insertions(+), 256 deletions(-) diff --git a/code/ai/aicode.cpp b/code/ai/aicode.cpp index ac59b713bf..e7b7c31a98 100644 --- a/code/ai/aicode.cpp +++ b/code/ai/aicode.cpp @@ -5506,11 +5506,6 @@ void set_primary_weapon_linkage(object *objp) ai_info *aip; ship_weapon *swp; weapon_info *wip; - - int total_ammo; - int current_ammo; - float ammo_pct; - int i; shipp = &Ships[objp->instance]; sip = &Ship_info[shipp->ship_info_index]; @@ -5585,29 +5580,31 @@ void set_primary_weapon_linkage(object *objp) } // also check ballistics - Goober5000 - if (sip->flags[Ship::Info_Flags::Ballistic_primaries]) + int total_ammo = 0; + int current_ammo = 0; + bool all_ballistic = true; + + // count ammo, and do not continue unless all weapons are ballistic + for (int i = 0; i < swp->num_primary_banks; i++) { - total_ammo = 0; - current_ammo = 0; + wip = &Weapon_info[swp->primary_bank_weapons[i]]; - // count ammo, and do not continue unless all weapons are ballistic - for (i = 0; i < swp->num_primary_banks; i++) + if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) { - wip = &Weapon_info[swp->primary_bank_weapons[i]]; - - if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) - { - total_ammo += swp->primary_bank_start_ammo[i]; - current_ammo += swp->primary_bank_ammo[i]; - } - else - { - return; - } + total_ammo += swp->primary_bank_start_ammo[i]; + current_ammo += swp->primary_bank_ammo[i]; } + else + { + all_ballistic = false; + break; + } + } + if (all_ballistic) + { Assert(total_ammo); // Goober5000: div-0 check - ammo_pct = float (current_ammo) / float (total_ammo) * 100.0f; + float ammo_pct = float (current_ammo) / float (total_ammo) * 100.0f; // link according to defined levels if (ammo_pct > aip->ai_link_ammo_levels_always) @@ -5616,7 +5613,7 @@ void set_primary_weapon_linkage(object *objp) } else if (ammo_pct > aip->ai_link_ammo_levels_maybe) { - if (objp->hull_strength < shipp->ship_max_hull_strength/3.0f) + if (objp->hull_strength < shipp->ship_max_hull_strength / 3.0f) { shipp->flags.set(Ship::Ship_Flags::Primary_linked); } @@ -13234,30 +13231,29 @@ int maybe_request_support(object *objp) desire += mrs_subsystem(shipp, SUBSYSTEM_SENSORS); - // Set desire based on percentage of secondary weapons. ship_weapon *swp = &shipp->weapons; - for ( i = 0; i < swp->num_secondary_banks; i++ ) { - if (swp->secondary_bank_start_ammo[i] > 0) { - r = (float) swp->secondary_bank_ammo[i]/swp->secondary_bank_start_ammo[i]; - desire += (int) ((1.0f - r) * 3.0f); + // Set desire based on percentage of secondary weapons. + for (i = 0; i < swp->num_secondary_banks; ++i) + { + if (swp->secondary_bank_start_ammo[i] > 0) + { + r = (float)swp->secondary_bank_ammo[i] / swp->secondary_bank_start_ammo[i]; + desire += (int)((1.0f - r) * 3.0f); } } // Set desire based on ballistic weapons - Goober5000 - if (sip->flags[Ship::Info_Flags::Ballistic_primaries]) + for (i = 0; i < swp->num_primary_banks; ++i) { - for (i = 0; i < swp->num_primary_banks; i++) + wip = &Weapon_info[swp->primary_bank_weapons[i]]; + + if (wip->wi_flags[Weapon::Info_Flags::Ballistic] && swp->primary_bank_start_ammo[i] > 0) { - wip = &Weapon_info[swp->primary_bank_weapons[i]]; + r = (float) swp->primary_bank_ammo[i] / swp->primary_bank_start_ammo[i]; - if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) - { - r = (float) swp->primary_bank_ammo[i] / swp->primary_bank_start_ammo[i]; - - // cube ammo level for better behavior, and adjust for number of banks - desire += (int) ((1.0f - r)*(1.0f - r)*(1.0f - r) * (5.0f / swp->num_primary_banks)); - } + // cube ammo level for better behavior, and adjust for number of banks + desire += (int) ((1.0f - r)*(1.0f - r)*(1.0f - r) * (5.0f / swp->num_primary_banks)); } } diff --git a/code/hud/hudtarget.cpp b/code/hud/hudtarget.cpp index ae9de01642..cd14dd0b9a 100644 --- a/code/hud/hudtarget.cpp +++ b/code/hud/hudtarget.cpp @@ -5541,11 +5541,11 @@ void HudGaugeWeaponEnergy::render(float frametime) bool use_new_gauge = false; // Goober5000 - only check for the new gauge in case of command line + a ballistic-capable ship - if (Cmdline_ballistic_gauge && Ship_info[Player_ship->ship_info_index].flags[Ship::Info_Flags::Ballistic_primaries]) + if (Cmdline_ballistic_gauge) { - for(x = 0; x < Player_ship->weapons.num_primary_banks; x++) + for (x = 0; x < Player_ship->weapons.num_primary_banks; ++x) { - if(Weapon_info[Player_ship->weapons.primary_bank_weapons[x]].wi_flags[Weapon::Info_Flags::Ballistic]) + if (Weapon_info[Player_ship->weapons.primary_bank_weapons[x]].wi_flags[Weapon::Info_Flags::Ballistic]) { use_new_gauge = true; break; @@ -5651,7 +5651,7 @@ void HudGaugeWeaponEnergy::render(float frametime) sw = &Player_ship->weapons; // show ballistic ammunition in energy gauge if need be - if ( Show_ballistic && Ship_info[Player_ship->ship_info_index].flags[Ship::Info_Flags::Ballistic_primaries] ) { + if ( Show_ballistic ) { if ( Player_ship->flags[Ship::Ship_Flags::Primary_linked] ) { // go through all ballistic primaries and add up their ammunition totals and max capacities @@ -5670,7 +5670,11 @@ void HudGaugeWeaponEnergy::render(float frametime) max_ballistic_ammo = sw->primary_bank_start_ammo[sw->current_primary_bank]; } - percent_left = i2fl(ballistic_ammo) / i2fl(max_ballistic_ammo); + if (max_ballistic_ammo > 0) { + percent_left = i2fl(ballistic_ammo) / i2fl(max_ballistic_ammo); + } else { + percent_left = 1.0f; + } } else { // also leave if no energy can be stored for weapons - Goober5000 if (!ship_has_energy_weapons(Player_ship)) diff --git a/code/io/keycontrol.cpp b/code/io/keycontrol.cpp index 0a4d3d8fb3..4f651e2ce7 100644 --- a/code/io/keycontrol.cpp +++ b/code/io/keycontrol.cpp @@ -588,18 +588,15 @@ void debug_max_primary_weapons(object *objp) // Goober5000 ship_weapon *swp = &shipp->weapons; weapon_info *wip; - if (sip->flags[Ship::Info_Flags::Ballistic_primaries]) + for ( index = 0; index < MAX_SHIP_PRIMARY_BANKS; index++ ) { - for ( index = 0; index < MAX_SHIP_PRIMARY_BANKS; index++ ) + wip = &Weapon_info[swp->primary_bank_weapons[index]]; + if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) { - wip = &Weapon_info[swp->primary_bank_weapons[index]]; - if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) - { - float capacity, size; - capacity = (float) sip->primary_bank_ammo_capacity[index]; - size = (float) wip->cargo_size; - swp->primary_bank_ammo[index] = fl2i((capacity / size)+0.5f); - } + float capacity, size; + capacity = (float) sip->primary_bank_ammo_capacity[index]; + size = (float) wip->cargo_size; + swp->primary_bank_ammo[index] = fl2i((capacity / size)+0.5f); } } } diff --git a/code/missionui/missionweaponchoice.cpp b/code/missionui/missionweaponchoice.cpp index 7b4bf9dc77..885df92774 100644 --- a/code/missionui/missionweaponchoice.cpp +++ b/code/missionui/missionweaponchoice.cpp @@ -1119,16 +1119,6 @@ void wl_set_disabled_weapons(int ship_class) // Determine whether weapon #i is allowed on this ship class in the current type of mission. // As of 9/6/99, the only difference is dogfight missions have a different list of legal weapons. Wl_icons[i].can_use = eval_weapon_flag_for_game_type(sip->allowed_weapons[i]); - - // Goober5000: ballistic primaries - if (Weapon_info[i].wi_flags[Weapon::Info_Flags::Ballistic]) - { - // not allowed if this ship is not ballistic - if (!(sip->flags[Ship::Info_Flags::Ballistic_primaries])) - { - Wl_icons[i].can_use = 0; - } - } } } @@ -4043,8 +4033,7 @@ void wl_apply_current_loadout_to_all_ships_in_current_wing() } // make sure this ship can accept this weapon - if (!eval_weapon_flag_for_game_type(sip->allowed_weapons[weapon_type_to_add]) - || ((wip->wi_flags[Weapon::Info_Flags::Ballistic]) && !(sip->flags[Ship::Info_Flags::Ballistic_primaries]))) + if (!eval_weapon_flag_for_game_type(sip->allowed_weapons[weapon_type_to_add])) { SCP_string temp; sprintf(temp, XSTR("%s is unable to carry %s weaponry", 1629), ship_name, wep_display_name); diff --git a/code/network/multi_ingame.cpp b/code/network/multi_ingame.cpp index 709ddf0f97..53508bf80e 100644 --- a/code/network/multi_ingame.cpp +++ b/code/network/multi_ingame.cpp @@ -1439,11 +1439,8 @@ void send_ingame_ship_request_packet(int code,int rdata,net_player *pl) val = (ubyte)shipp->engine_recharge_index; ADD_DATA(val); - // add the ballistic primary flag - Goober5000 + // dummy field to replace ballistic primary flag val = 0; - if(sip->flags[Ship::Info_Flags::Ballistic_primaries]){ - val |= (1<<0); - } ADD_DATA(val); // add current primary and secondary banks, and add link status @@ -1685,11 +1682,8 @@ void process_ingame_ship_request_packet(ubyte *data, header *hinfo) GET_DATA(val); Player_ship->engine_recharge_index = val; - // handle the ballistic primary flag - Goober5000 + // handle the dummy value that used to be the ballistic primary flag GET_DATA(val); - if(val & (1<<0)){ - Ship_info[Player_ship->ship_info_index].flags.set(Ship::Info_Flags::Ballistic_primaries); - } // get current primary and secondary banks, and add link status GET_DATA(val); diff --git a/code/parse/sexp.cpp b/code/parse/sexp.cpp index 8b79584b29..68ce24dda3 100755 --- a/code/parse/sexp.cpp +++ b/code/parse/sexp.cpp @@ -15142,30 +15142,25 @@ int sexp_primaries_depleted(int node) return SEXP_FALSE; } - // see if ship has ballistic primary weapons - if (!(Ship_info[shipp->ship_info_index].flags[Ship::Info_Flags::Ballistic_primaries])) - return SEXP_FALSE; - // get num primary banks num_banks = shipp->weapons.num_primary_banks; num_depleted_banks = 0; // get number of depleted banks - for (int idx=0; idxweapons.primary_bank_weapons[idx]].wi_flags[Weapon::Info_Flags::Ballistic]) - { - // is this bank out of ammo? - if (shipp->weapons.primary_bank_ammo[idx] == 0) - { - num_depleted_banks++; - } + if (!(Weapon_info[shipp->weapons.primary_bank_weapons[idx]].wi_flags[Weapon::Info_Flags::Ballistic])) { + continue; + } + + // is this bank out of ammo? + if (shipp->weapons.primary_bank_ammo[idx] == 0) { + num_depleted_banks++; } } // are they all depleted? - return (num_depleted_banks == num_banks); + return (num_depleted_banks == num_banks) ? SEXP_TRUE : SEXP_FALSE; } int sexp_secondaries_depleted(int node) @@ -15190,13 +15185,14 @@ int sexp_secondaries_depleted(int node) // get number of depleted banks for (int idx=0; idxweapons.secondary_bank_ammo[idx] == 0) { num_depleted_banks++; } } // are they all depleted? - return (num_depleted_banks == num_banks); + return (num_depleted_banks == num_banks) ? SEXP_TRUE : SEXP_FALSE; } int sexp_facing(int node) diff --git a/code/ship/ship.cpp b/code/ship/ship.cpp index 58f5fbdbbd..43a260d90d 100644 --- a/code/ship/ship.cpp +++ b/code/ship/ship.cpp @@ -3441,21 +3441,6 @@ int parse_ship_values(ship_info* sip, const bool is_template, const bool first_t } } - sip->flags.remove(Ship::Info_Flags::Ballistic_primaries); - - //Set ship ballistic flag if necessary - for (i = 0; i < MAX_SHIP_PRIMARY_BANKS; i++) - { - for (j = 0; j < Num_weapon_types; j++) - { - if(sip->allowed_bank_restricted_weapons[i][j] && (Weapon_info[j].wi_flags[Weapon::Info_Flags::Ballistic])) - { - sip->flags.set(Ship::Info_Flags::Ballistic_primaries); - break; - } - } - } - find_and_stuff_optional("$AI Class:", &sip->ai_class, F_NAME, Ai_class_names, Num_ai_classes, "AI class names"); // Get Afterburner information @@ -5095,6 +5080,20 @@ int ship_show_velocity_dot = 0; DCF_BOOL( show_velocity_dot, ship_show_velocity_dot ) +bool ballistic_possible_for_this_ship(const ship_info *sip) +{ + for (int i = 0; i < MAX_SHIP_PRIMARY_BANKS; i++) + { + for (int j = 0; j < Num_weapon_types; ++j) + { + if (sip->allowed_bank_restricted_weapons[i][j] && (Weapon_info[j].wi_flags2 & WIF2_BALLISTIC)) + return true; + } + } + + return false; +} + /** * Clean up ship entries, making sure various flags and settings are correct */ @@ -5119,7 +5118,7 @@ void ship_parse_post_cleanup() // be friendly; ensure ballistic flags check out if (pbank_capacity_specified) { - if ( !(sip->flags[Ship::Info_Flags::Ballistic_primaries]) ) { + if ( !ballistic_possible_for_this_ship(&(*sip)) ) { Warning(LOCATION, "Pbank capacity specified for non-ballistic-primary-enabled ship %s.\nResetting capacities to 0.\nTo fix this, add a ballistic primary to the list of allowed primaries.\n", sip->name); for (j = 0; j < MAX_SHIP_PRIMARY_BANKS; j++) { @@ -5127,7 +5126,7 @@ void ship_parse_post_cleanup() } } } else { - if (sip->flags[Ship::Info_Flags::Ballistic_primaries]) { + if ( ballistic_possible_for_this_ship(&(*sip)) ) { Warning(LOCATION, "Pbank capacity not specified for ballistic-primary-enabled ship %s.\nDefaulting to capacity of 1 per bank.\n", sip->name); for (j = 0; j < MAX_SHIP_PRIMARY_BANKS; j++) { @@ -8823,19 +8822,16 @@ void ship_process_post(object * obj, float frametime) } } - if ( sip->flags[Ship::Info_Flags::Ballistic_primaries] ) + for ( int i=0; iship_info_index, i, shipp->weapons.primary_bank_weapons[i]); - shipp->weapons.primary_bank_start_ammo[i] = max_missiles; - } - else - { - shipp->weapons.primary_bank_start_ammo[i] = shipp->weapons.primary_bank_ammo[i]; - } + max_missiles = get_max_ammo_count_for_primary_bank(shipp->ship_info_index, i, shipp->weapons.primary_bank_weapons[i]); + shipp->weapons.primary_bank_start_ammo[i] = max_missiles; + } + else + { + shipp->weapons.primary_bank_start_ammo[i] = shipp->weapons.primary_bank_ammo[i]; } } @@ -11018,10 +11014,6 @@ int ship_fire_primary(object * obj, int stream_weapons, int force) // ballistics support for primaries - Goober5000 if ( winfo_p->wi_flags[Weapon::Info_Flags::Ballistic] ) { - // Make sure this ship is set up for ballistics. - // If you get this error, add the ballistic primaries tags to ships.tbl. - Assert ( sip->flags[Ship::Info_Flags::Ballistic_primaries] ); - // If ship is being repaired/rearmed, it cannot fire ballistics if ( aip->ai_flags & AIF_BEING_REPAIRED ) { @@ -12114,6 +12106,19 @@ int primary_out_of_ammo(ship_weapon *swp, int bank) return 0; } +bool ship_has_a_ballistic_primary(const ship *shipp) +{ + const ship_weapon *swp = &shipp->weapons; + + for (int i = 0; i < swp->num_primary_banks; i++) + { + if (Weapon_info[swp->primary_bank_weapons[i]].wi_flags2 & WIF2_BALLISTIC) + return true; + } + + return false; +} + /** * Return true if a new index gets selected. * @@ -12228,7 +12233,7 @@ int ship_select_next_primary(object *objp, int direction) } // test for ballistics - Goober5000 - if ( sip->flags[Ship::Info_Flags::Ballistic_primaries] ) + if (ship_has_a_ballistic_primary(shipp)) { // if we can't link, disengage primary linking and change to next available bank if (shipp->flags[Ship_Flags::Primary_linked]) @@ -13395,35 +13400,32 @@ float ship_calculate_rearm_duration( object *objp ) //now do the primary rearm time found_first_empty = false; - if (sip->flags[Ship::Info_Flags::Ballistic_primaries]) + for (i = 0; i < swp->num_primary_banks; i++) { - for (i = 0; i < swp->num_primary_banks; i++) + wip = &Weapon_info[swp->primary_bank_weapons[i]]; + if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) { - wip = &Weapon_info[swp->primary_bank_weapons[i]]; - if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) + //check how many full reloads we need + num_reloads = (swp->primary_bank_start_ammo[i] - swp->primary_bank_ammo[i])/REARM_NUM_BALLISTIC_PRIMARIES_PER_BATCH; + + //take into account a fractional reload + if ((swp->primary_bank_start_ammo[i] - swp->primary_bank_ammo[i]) % REARM_NUM_BALLISTIC_PRIMARIES_PER_BATCH != 0) { - //check how many full reloads we need - num_reloads = (swp->primary_bank_start_ammo[i] - swp->primary_bank_ammo[i])/REARM_NUM_BALLISTIC_PRIMARIES_PER_BATCH; - - //take into account a fractional reload - if ((swp->primary_bank_start_ammo[i] - swp->primary_bank_ammo[i]) % REARM_NUM_BALLISTIC_PRIMARIES_PER_BATCH != 0) - { - num_reloads++; - } - - //don't factor in the time it takes for the first reload, since that is loaded instantly - num_reloads--; - - if (num_reloads < 0) continue; - - if (!found_first_empty && (swp->primary_bank_start_ammo[i] - swp->primary_bank_ammo[i])) - { - found_first_empty = true; - prim_rearm_time += (float)snd_get_duration(Snds[SND_MISSILE_START_LOAD].id) / 1000.0f; - } - - prim_rearm_time += num_reloads * wip->rearm_rate; + num_reloads++; } + + //don't factor in the time it takes for the first reload, since that is loaded instantly + num_reloads--; + + if (num_reloads < 0) continue; + + if (!found_first_empty && (swp->primary_bank_start_ammo[i] - swp->primary_bank_ammo[i])) + { + found_first_empty = true; + prim_rearm_time += (float)snd_get_duration(Snds[SND_MISSILE_START_LOAD].id) / 1000.0f; + } + + prim_rearm_time += num_reloads * wip->rearm_rate; } } @@ -13471,7 +13473,7 @@ float ship_calculate_rearm_duration( object *objp ) // int ship_do_rearm_frame( object *objp, float frametime ) { - int i, banks_full, primary_banks_full, subsys_type, subsys_all_ok, last_ballistic_idx = 0; + int i, banks_full, primary_banks_full, subsys_type, subsys_all_ok, last_ballistic_idx = -1; float shield_str, repair_delta, repair_allocated, max_hull_repair, max_subsys_repair; ship *shipp; ship_weapon *swp; @@ -13661,80 +13663,22 @@ int ship_do_rearm_frame( object *objp, float frametime ) } // end for // rearm ballistic primaries - Goober5000 - if (sip->flags[Ship::Info_Flags::Ballistic_primaries]) + if ( aip->rearm_first_ballistic_primary == TRUE) { - if ( aip->rearm_first_ballistic_primary == TRUE) - { - for (i = 1; i < swp->num_primary_banks; i++ ) - { - if ( Weapon_info[swp->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Ballistic] ) - last_ballistic_idx = i; - } - } - for (i = 0; i < swp->num_primary_banks; i++ ) { if ( Weapon_info[swp->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Ballistic] ) - { - // Actual loading of bullets is preceded by a sound effect which is the bullet - // loading equipment moving into place - if ( aip->rearm_first_ballistic_primary == TRUE ) - { - // Goober5000 - int sound_index; - if (Snds[SND_BALLISTIC_START_LOAD].id >= 0) - sound_index = SND_BALLISTIC_START_LOAD; - else - sound_index = SND_MISSILE_START_LOAD; + last_ballistic_idx = i; + } + } - swp->primary_bank_rearm_time[i] = timestamp(snd_get_duration(Snds[sound_index].id)); - - if (i == last_ballistic_idx) - aip->rearm_first_ballistic_primary = FALSE; - } - - if ( swp->primary_bank_ammo[i] < swp->primary_bank_start_ammo[i] ) - { - float rearm_time; - - if ( objp == Player_obj ) - { - hud_gauge_popup_start(HUD_WEAPONS_GAUGE); - } - - if ( timestamp_elapsed(swp->primary_bank_rearm_time[i]) ) - { - rearm_time = Weapon_info[swp->primary_bank_weapons[i]].rearm_rate; - swp->primary_bank_rearm_time[i] = timestamp( (int)(rearm_time * 1000.f) ); - - // Goober5000 - int sound_index; - if (Snds[SND_BALLISTIC_LOAD].id >= 0) - sound_index = SND_BALLISTIC_LOAD; - else - sound_index = SND_MISSILE_LOAD; - - snd_play_3d( &Snds[sound_index], &objp->pos, &View_position ); - - swp->primary_bank_ammo[i] += REARM_NUM_BALLISTIC_PRIMARIES_PER_BATCH; - if ( swp->primary_bank_ammo[i] > swp->primary_bank_start_ammo[i] ) - { - swp->primary_bank_ammo[i] = swp->primary_bank_start_ammo[i]; - } - } - } - else - { - primary_banks_full++; - } - } - // if the bank is not a ballistic - else - { - primary_banks_full++; - } - - if ((aip->rearm_first_ballistic_primary == TRUE) && (i == swp->num_primary_banks - 1) && (primary_banks_full != swp->num_primary_banks)) + for (i = 0; i < swp->num_primary_banks; i++ ) + { + if (Weapon_info[swp->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Ballistic]) + { + // Actual loading of bullets is preceded by a sound effect which is the bullet + // loading equipment moving into place + if ( aip->rearm_first_ballistic_primary == TRUE ) { // Goober5000 int sound_index; @@ -13743,10 +13687,65 @@ int ship_do_rearm_frame( object *objp, float frametime ) else sound_index = SND_MISSILE_START_LOAD; - snd_play_3d( &Snds[sound_index], &objp->pos, &View_position ); + swp->primary_bank_rearm_time[i] = timestamp(snd_get_duration(Snds[sound_index].id)); + + if (i == last_ballistic_idx) + aip->rearm_first_ballistic_primary = FALSE; } - } // end for - } // end if - rearm ballistic primaries + + if ( swp->primary_bank_ammo[i] < swp->primary_bank_start_ammo[i] ) + { + float rearm_time; + + if ( objp == Player_obj ) + { + hud_gauge_popup_start(HUD_WEAPONS_GAUGE); + } + + if ( timestamp_elapsed(swp->primary_bank_rearm_time[i]) ) + { + rearm_time = Weapon_info[swp->primary_bank_weapons[i]].rearm_rate; + swp->primary_bank_rearm_time[i] = timestamp( (int)(rearm_time * 1000.f) ); + + // Goober5000 + int sound_index; + if (Snds[SND_BALLISTIC_LOAD].id >= 0) + sound_index = SND_BALLISTIC_LOAD; + else + sound_index = SND_MISSILE_LOAD; + + snd_play_3d( &Snds[sound_index], &objp->pos, &View_position ); + + swp->primary_bank_ammo[i] += REARM_NUM_BALLISTIC_PRIMARIES_PER_BATCH; + if ( swp->primary_bank_ammo[i] > swp->primary_bank_start_ammo[i] ) + { + swp->primary_bank_ammo[i] = swp->primary_bank_start_ammo[i]; + } + } + } + else + { + primary_banks_full++; + } + } + // if the bank is not a ballistic + else + { + primary_banks_full++; + } + + if ((aip->rearm_first_ballistic_primary == TRUE) && (i == last_ballistic_idx) && (primary_banks_full != swp->num_primary_banks)) + { + // Goober5000 + int sound_index; + if (Snds[SND_BALLISTIC_START_LOAD].id >= 0) + sound_index = SND_BALLISTIC_START_LOAD; + else + sound_index = SND_MISSILE_START_LOAD; + + snd_play_3d( &Snds[sound_index], &objp->pos, &View_position ); + } + } // end for } // end if (subsys_all_ok) if ( banks_full == swp->num_secondary_banks ) @@ -13789,8 +13788,7 @@ int ship_do_rearm_frame( object *objp, float frametime ) aip->rearm_release_delay = timestamp(1200); // check both primary and secondary banks are full - if ( (banks_full == swp->num_secondary_banks) && - ( !(sip->flags[Ship::Info_Flags::Ballistic_primaries]) || ((sip->flags[Ship::Info_Flags::Ballistic_primaries]) && (primary_banks_full == swp->num_primary_banks)) ) ) + if ( (banks_full == swp->num_secondary_banks) && (primary_banks_full == swp->num_primary_banks) ) { if ( timestamp_elapsed(aip->rearm_release_delay) ) return 1; @@ -15680,34 +15678,31 @@ void ship_maybe_tell_about_low_ammo(ship *sp) swp = &sp->weapons; // stole the code for this from ship_maybe_tell_about_rearm() - if (Ship_info[sp->ship_info_index].flags[Ship::Info_Flags::Ballistic_primaries]) + for (i = 0; i < swp->num_primary_banks; i++) { - for (i = 0; i < swp->num_primary_banks; i++) + wip = &Weapon_info[swp->primary_bank_weapons[i]]; + + if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) { - wip = &Weapon_info[swp->primary_bank_weapons[i]]; - - if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) + if (swp->primary_bank_start_ammo[i] > 0) { - if (swp->primary_bank_start_ammo[i] > 0) + if ((float)swp->primary_bank_ammo[i] / (float)swp->primary_bank_start_ammo[i] < 0.3f) { - if ((float)swp->primary_bank_ammo[i] / (float)swp->primary_bank_start_ammo[i] < 0.3f) - { - // multiplayer tvt - if(MULTI_TEAM) { - multi_team_filter = sp->team; - } - - message_send_builtin_to_player(MESSAGE_PRIMARIES_LOW, sp, MESSAGE_PRIORITY_NORMAL, MESSAGE_TIME_SOON, 0, 0, -1, multi_team_filter); - - Player->allow_ammo_timestamp = timestamp(PLAYER_LOW_AMMO_MSG_INTERVAL); - - // better reset this one too - Player->request_repair_timestamp = timestamp(PLAYER_REQUEST_REPAIR_MSG_INTERVAL); - - Player->low_ammo_complaint_count++; - sp->ammo_low_complaint_count++; - break; + // multiplayer tvt + if(MULTI_TEAM) { + multi_team_filter = sp->team; } + + message_send_builtin_to_player(MESSAGE_PRIMARIES_LOW, sp, MESSAGE_PRIORITY_NORMAL, MESSAGE_TIME_SOON, 0, 0, -1, multi_team_filter); + + Player->allow_ammo_timestamp = timestamp(PLAYER_LOW_AMMO_MSG_INTERVAL); + + // better reset this one too + Player->request_repair_timestamp = timestamp(PLAYER_REQUEST_REPAIR_MSG_INTERVAL); + + Player->low_ammo_complaint_count++; + sp->ammo_low_complaint_count++; + break; } } } @@ -15761,21 +15756,18 @@ void ship_maybe_tell_about_rearm(ship *sp) } // also check ballistic primaries - Goober5000 - if (Ship_info[sp->ship_info_index].flags[Ship::Info_Flags::Ballistic_primaries]) + for (i = 0; i < swp->num_primary_banks; i++) { - for (i = 0; i < swp->num_primary_banks; i++) - { - wip = &Weapon_info[swp->primary_bank_weapons[i]]; + wip = &Weapon_info[swp->primary_bank_weapons[i]]; - if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) + if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) + { + if (swp->primary_bank_start_ammo[i] > 0) { - if (swp->primary_bank_start_ammo[i] > 0) + if ((float)swp->primary_bank_ammo[i] / (float)swp->primary_bank_start_ammo[i] < 0.3f) { - if ((float)swp->primary_bank_ammo[i] / (float)swp->primary_bank_start_ammo[i] < 0.3f) - { - message_type = MESSAGE_REARM_PRIMARIES; - break; - } + message_type = MESSAGE_REARM_PRIMARIES; + break; } } } @@ -16071,13 +16063,14 @@ int get_max_ammo_count_for_primary_bank(int ship_class, int bank, int ammo_type) { float capacity, size; - if (!(Ship_info[ship_class].flags[Ship::Info_Flags::Ballistic_primaries])) + if (!(Weapon_info[ammo_type].wi_flags2 & WIF2_BALLISTIC)) { return 0; } capacity = (float) Ship_info[ship_class].primary_bank_ammo_capacity[bank]; size = (float) Weapon_info[ammo_type].cargo_size; + Assertion(size > 0.0f, "Weapon cargo size for %s must be greater than 0!", Weapon_info[ammo_type].name); return fl2i((capacity / size)+0.5f); } @@ -16097,6 +16090,7 @@ int get_max_ammo_count_for_bank(int ship_class, int bank, int ammo_type) } else { capacity = (float) Ship_info[ship_class].secondary_bank_ammo_capacity[bank]; size = (float) Weapon_info[ammo_type].cargo_size; + Assertion(size > 0.0f, "Weapon cargo size for %s must be greater than 0!", Weapon_info[ammo_type].name); return (int) (capacity / size); } } From 795bb861487d24345910c8f76e6b66a2005ac880 Mon Sep 17 00:00:00 2001 From: Goober5000 Date: Sun, 21 Aug 2016 18:02:20 -0400 Subject: [PATCH 16/16] additional tweaks for WIF flag refactoring --- code/ship/ship.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/code/ship/ship.cpp b/code/ship/ship.cpp index 43a260d90d..f003399aef 100644 --- a/code/ship/ship.cpp +++ b/code/ship/ship.cpp @@ -5086,7 +5086,7 @@ bool ballistic_possible_for_this_ship(const ship_info *sip) { for (int j = 0; j < Num_weapon_types; ++j) { - if (sip->allowed_bank_restricted_weapons[i][j] && (Weapon_info[j].wi_flags2 & WIF2_BALLISTIC)) + if (sip->allowed_bank_restricted_weapons[i][j] && (Weapon_info[j].wi_flags[Weapon::Info_Flags::Ballistic])) return true; } } @@ -12112,7 +12112,7 @@ bool ship_has_a_ballistic_primary(const ship *shipp) for (int i = 0; i < swp->num_primary_banks; i++) { - if (Weapon_info[swp->primary_bank_weapons[i]].wi_flags2 & WIF2_BALLISTIC) + if (Weapon_info[swp->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Ballistic]) return true; } @@ -16055,7 +16055,6 @@ float ship_get_secondary_weapon_range(ship *shipp) return srange; } -// Goober5000 - added for ballistic primaries /** * Determine the number of primary ammo units allowed max for a ship */ @@ -16063,10 +16062,8 @@ int get_max_ammo_count_for_primary_bank(int ship_class, int bank, int ammo_type) { float capacity, size; - if (!(Weapon_info[ammo_type].wi_flags2 & WIF2_BALLISTIC)) - { + if (!(Weapon_info[ammo_type].wi_flags[Weapon::Info_Flags::Ballistic])) return 0; - } capacity = (float) Ship_info[ship_class].primary_bank_ammo_capacity[bank]; size = (float) Weapon_info[ammo_type].cargo_size;