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/ai/aibig.cpp b/code/ai/aibig.cpp index 9616b82cde..4f4f4bd70d 100644 --- a/code/ai/aibig.cpp +++ b/code/ai/aibig.cpp @@ -754,7 +754,7 @@ void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy, vec3d *f if (current_bank > -1) { weapon_info *swip = &Weapon_info[tswp->secondary_bank_weapons[current_bank]]; - if(!(En_objp->flags[Object::Object_Flags::Protected]) || ((aip->goals[0].ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP)) && swip->wi_flags & WIF_PUNCTURE )) { //override lockdown on protected ships when using anti subsystem weapons - Valathil + if(!(En_objp->flags[Object::Object_Flags::Protected]) || ((aip->goals[0].ai_mode & (AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP)) && swip->wi_flags[Weapon::Info_Flags::Puncture] )) { //override lockdown on protected ships when using anti subsystem weapons - Valathil // If ship is protected and very low on hits, don't fire missiles. if (!(En_objp->flags[Object::Object_Flags::Protected]) || (En_objp->hull_strength > 10*swip->damage)) { if (aip->ai_flags & AIF_UNLOAD_SECONDARIES) { @@ -765,7 +765,7 @@ void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy, vec3d *f if (timestamp_elapsed(swp->next_secondary_fire_stamp[current_bank])) { float firing_range; - if (swip->wi_flags2 & WIF2_LOCAL_SSM) + if (swip->wi_flags[Weapon::Info_Flags::Local_ssm]) firing_range=swip->lssm_lock_range; else firing_range = MIN((swip->max_speed * swip->lifetime), swip->weapon_range); @@ -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; @@ -1810,7 +1810,7 @@ void ai_big_strafe_maybe_attack_turret(object *ship_objp, object *weapon_objp) // 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) - && (Weapon_info[Weapons[weapon_objp->instance].weapon_info_index].wi_flags & WIF_BEAM) && (frand()*100 < 25.0f); + && (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 if ( !attack_turret_on_different_ship ) diff --git a/code/ai/aicode.cpp b/code/ai/aicode.cpp index 76ace13f7d..ac59b713bf 100644 --- a/code/ai/aicode.cpp +++ b/code/ai/aicode.cpp @@ -1283,7 +1283,7 @@ int set_target_objnum(ai_info *aip, int objnum) return aip->target_objnum; } -int ai_select_primary_weapon(object *objp, object *other_objp, int flags); +int ai_select_primary_weapon(object *objp, object *other_objp, Weapon::Info_Flags flags); /** * Make new_subsys the targeted subsystem of ship *aip. @@ -1301,7 +1301,7 @@ ship_subsys *set_targeted_subsys(ai_info *aip, ship_subsys *new_subsys, int pare if (new_subsys->system_info->type == SUBSYSTEM_ENGINE) { if ( aip != Player_ai ) { Assert( aip->shipnum >= 0 ); - ai_select_primary_weapon(&Objects[Ships[aip->shipnum].objnum], &Objects[parent_objnum], WIF_PUNCTURE); + ai_select_primary_weapon(&Objects[Ships[aip->shipnum].objnum], &Objects[parent_objnum], Weapon::Info_Flags::Puncture); ship_primary_changed(&Ships[aip->shipnum]); // AL: maybe send multiplayer information when AI ship changes primaries } } @@ -4326,7 +4326,7 @@ void ai_fly_to_target_position(vec3d* target_pos, bool* pl_done_p=NULL, bool* pl vec3d perp, goal_point; - bool carry_flag = ((shipp->flags[Ship::Ship_Flags::Navpoint_carry]) || ((shipp->wingnum >= 0) && (Wings[shipp->wingnum].flags & WF_NAV_CARRY))); + bool carry_flag = ((shipp->flags[Ship::Ship_Flags::Navpoint_carry]) || ((shipp->wingnum >= 0) && (Wings[shipp->wingnum].flags[Ship::Wing_Flags::Nav_carry]))); if (AutoPilotEngaged) ab_allowed = false; @@ -5221,25 +5221,25 @@ vec3d G_predicted_pos, G_fire_pos; //old version of this fuction, this will be useful for playing old missions and not having the new primary //selection code throw off the balance of the mission. // If: -// flags & WIF_PUNCTURE +// flags & Weapon::Info_Flags::Puncture // Then Select a Puncture weapon. // Else // Select Any ol' weapon. // Returns primary_bank index. -int ai_select_primary_weapon_OLD(object *objp, object *other_objp, int flags) +int ai_select_primary_weapon_OLD(object *objp, object *other_objp, Weapon::Info_Flags flags) { ship *shipp = &Ships[objp->instance]; ship_weapon *swp = &shipp->weapons; Assert( shipp->ship_info_index >= 0 && shipp->ship_info_index < static_cast(Ship_info.size())); - if (flags & WIF_PUNCTURE) { + if (flags == Weapon::Info_Flags::Puncture) { if (swp->current_primary_bank >= 0) { int bank_index; bank_index = swp->current_primary_bank; - if (Weapon_info[swp->primary_bank_weapons[bank_index]].wi_flags & WIF_PUNCTURE) { + if (Weapon_info[swp->primary_bank_weapons[bank_index]].wi_flags[Weapon::Info_Flags::Puncture]) { return swp->current_primary_bank; } } @@ -5249,7 +5249,7 @@ int ai_select_primary_weapon_OLD(object *objp, object *other_objp, int flags) weapon_info_index = swp->primary_bank_weapons[i]; if (weapon_info_index > -1){ - if (Weapon_info[weapon_info_index].wi_flags & WIF_PUNCTURE) { + if (Weapon_info[weapon_info_index].wi_flags[Weapon::Info_Flags::Puncture]) { swp->current_primary_bank = i; return i; } @@ -5265,13 +5265,13 @@ int ai_select_primary_weapon_OLD(object *objp, object *other_objp, int flags) } else { // Don't need to be using a puncture weapon. if (swp->current_primary_bank >= 0) { - if (!(Weapon_info[swp->primary_bank_weapons[swp->current_primary_bank]].wi_flags & WIF_PUNCTURE)){ + if (!(Weapon_info[swp->primary_bank_weapons[swp->current_primary_bank]].wi_flags[Weapon::Info_Flags::Puncture])){ return swp->current_primary_bank; } } for (int i=0; inum_primary_banks; i++) { if (swp->primary_bank_weapons[i] > -1) { - if (!(Weapon_info[swp->primary_bank_weapons[i]].wi_flags & WIF_PUNCTURE)) { + if (!(Weapon_info[swp->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Puncture])) { swp->current_primary_bank = i; nprintf(("AI", "%i: Ship %s selecting weapon %s\n", Framecount, Ships[objp->instance].ship_name, Weapon_info[swp->primary_bank_weapons[i]].name)); return i; @@ -5287,7 +5287,7 @@ int ai_select_primary_weapon_OLD(object *objp, object *other_objp, int flags) } // If: -// flags & WIF_PUNCTURE +// flags == Weapon::Info_Flags::Puncture // Then Select a Puncture weapon. // Else // Select Any ol' weapon. @@ -5299,7 +5299,7 @@ int ai_select_primary_weapon_OLD(object *objp, object *other_objp, int flags) * The AI will now intelligently choose the best weapon to use based on the overall shield * status of the target. */ -int ai_select_primary_weapon(object *objp, object *other_objp, int flags) +int ai_select_primary_weapon(object *objp, object *other_objp, Weapon::Info_Flags flags) { // Pointer Set Up ship *shipp = &Ships[objp->instance]; @@ -5323,7 +5323,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, int flags) Assert( shipp->ship_info_index >= 0 && shipp->ship_info_index < static_cast(Ship_info.size())); //made it so it only selects puncture weapons if the active goal is to disable something -Bobboau - if ((flags & WIF_PUNCTURE) && (Ai_info[shipp->ai_index].goals[0].ai_mode & (AI_GOAL_DISARM_SHIP | AI_GOAL_DISABLE_SHIP))) + if ((flags == Weapon::Info_Flags::Puncture) && (Ai_info[shipp->ai_index].goals[0].ai_mode & (AI_GOAL_DISARM_SHIP | AI_GOAL_DISABLE_SHIP))) { if (swp->current_primary_bank >= 0) { @@ -5331,7 +5331,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, int flags) bank_index = swp->current_primary_bank; - if (Weapon_info[swp->primary_bank_weapons[bank_index]].wi_flags & WIF_PUNCTURE) + if (Weapon_info[swp->primary_bank_weapons[bank_index]].wi_flags[Weapon::Info_Flags::Puncture]) { return swp->current_primary_bank; } @@ -5344,7 +5344,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, int flags) if (weapon_info_index > -1) { - if (Weapon_info[weapon_info_index].wi_flags & WIF_PUNCTURE) + if (Weapon_info[weapon_info_index].wi_flags[Weapon::Info_Flags::Puncture]) { swp->current_primary_bank = i; return i; @@ -5360,7 +5360,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, int flags) { if (swp->primary_bank_weapons[i] > -1) // Make sure there is a weapon in the bank { - if (Weapon_info[swp->primary_bank_weapons[i]].wi_flags2 & WIF2_CAPITAL_PLUS) + if (Weapon_info[swp->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Capital_plus]) { swp->current_primary_bank = i; nprintf(("AI", "%i: Ship %s selecting weapon %s\n", Framecount, Ships[objp->instance].ship_name, Weapon_info[swp->primary_bank_weapons[i]].name)); @@ -5387,7 +5387,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, int flags) { if ((((Weapon_info[swp->primary_bank_weapons[i]].armor_factor) * (Weapon_info[swp->primary_bank_weapons[i]].damage)) / Weapon_info[swp->primary_bank_weapons[i]].fire_wait) > i_hullfactor_prev) { - if ( !(Weapon_info[swp->primary_bank_weapons[i]].wi_flags2 & WIF2_CAPITAL_PLUS) ) + if ( !(Weapon_info[swp->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Capital_plus]) ) { // This weapon is the new candidate i_hullfactor_prev = ( ((Weapon_info[swp->primary_bank_weapons[i]].armor_factor) * (Weapon_info[swp->primary_bank_weapons[i]].damage)) / Weapon_info[swp->primary_bank_weapons[i]].fire_wait ); @@ -5413,7 +5413,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, int flags) bank_index = swp->current_primary_bank; - if ((Weapon_info[swp->primary_bank_weapons[bank_index]].wi_flags2 & WIF2_PIERCE_SHIELDS) && !(Weapon_info[swp->primary_bank_weapons[bank_index]].wi_flags2 & WIF2_CAPITAL_PLUS)) + if ((Weapon_info[swp->primary_bank_weapons[bank_index]].wi_flags[Weapon::Info_Flags::Pierce_shields]) && !(Weapon_info[swp->primary_bank_weapons[bank_index]].wi_flags[Weapon::Info_Flags::Capital_plus])) { return swp->current_primary_bank; } @@ -5426,7 +5426,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, int flags) if (weapon_info_index > -1) { - if ((Weapon_info[weapon_info_index].wi_flags2 & WIF2_PIERCE_SHIELDS) && !(Weapon_info[swp->primary_bank_weapons[i]].wi_flags2 & WIF2_CAPITAL_PLUS)) + if ((Weapon_info[weapon_info_index].wi_flags[Weapon::Info_Flags::Pierce_shields]) && !(Weapon_info[swp->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Capital_plus])) { swp->current_primary_bank = i; return i; @@ -5449,7 +5449,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, int flags) { if ((((Weapon_info[swp->primary_bank_weapons[i]].armor_factor + Weapon_info[swp->primary_bank_weapons[i]].shield_factor) * Weapon_info[swp->primary_bank_weapons[i]].damage) / Weapon_info[swp->primary_bank_weapons[i]].fire_wait) > i_hullfactor_prev) { - if ( !(Weapon_info[swp->primary_bank_weapons[i]].wi_flags2 & WIF2_CAPITAL_PLUS) ) + if ( !(Weapon_info[swp->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Capital_plus]) ) { // This weapon is the new candidate i_hullfactor_prev = ((((Weapon_info[swp->primary_bank_weapons[i]].armor_factor + Weapon_info[swp->primary_bank_weapons[i]].shield_factor) * Weapon_info[swp->primary_bank_weapons[i]].damage) / Weapon_info[swp->primary_bank_weapons[i]].fire_wait)); @@ -5478,7 +5478,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, int flags) { if ((((Weapon_info[swp->primary_bank_weapons[i]].shield_factor) * Weapon_info[swp->primary_bank_weapons[i]].damage) / Weapon_info[swp->primary_bank_weapons[i]].fire_wait) > i_hullfactor_prev) { - if ( !(Weapon_info[swp->primary_bank_weapons[i]].wi_flags2 & WIF2_CAPITAL_PLUS) ) + if ( !(Weapon_info[swp->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Capital_plus]) ) { // This weapon is the new candidate i_hullfactor_prev = ( ((Weapon_info[swp->primary_bank_weapons[i]].shield_factor) * (Weapon_info[swp->primary_bank_weapons[i]].damage)) / Weapon_info[swp->primary_bank_weapons[i]].fire_wait ); @@ -5546,9 +5546,9 @@ void set_primary_weapon_linkage(object *objp) { // only continue if both primaries are puncture weapons if ( swp->num_primary_banks == 2 ) { - if ( !(Weapon_info[swp->primary_bank_weapons[0]].wi_flags & WIF_PUNCTURE) ) + if ( !(Weapon_info[swp->primary_bank_weapons[0]].wi_flags[Weapon::Info_Flags::Puncture]) ) return; - if ( !(Weapon_info[swp->primary_bank_weapons[1]].wi_flags & WIF_PUNCTURE) ) + if ( !(Weapon_info[swp->primary_bank_weapons[1]].wi_flags[Weapon::Info_Flags::Puncture]) ) return; } } @@ -5595,7 +5595,7 @@ void set_primary_weapon_linkage(object *objp) { wip = &Weapon_info[swp->primary_bank_weapons[i]]; - if (wip->wi_flags2 & WIF2_BALLISTIC) + if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) { total_ammo += swp->primary_bank_start_ammo[i]; current_ammo += swp->primary_bank_ammo[i]; @@ -5662,9 +5662,9 @@ int ai_fire_primary_weapon(object *objp) } if ( (swp->current_primary_bank < 0) || (swp->current_primary_bank >= swp->num_primary_banks) || timestamp_elapsed(aip->primary_select_timestamp)) { - int flags = 0; + Weapon::Info_Flags flags = Weapon::Info_Flags::NUM_VALUES; if ( aip->targeted_subsys != NULL ) { - flags = WIF_PUNCTURE; + flags = Weapon::Info_Flags::Puncture; } ai_select_primary_weapon(objp, enemy_objp, flags); ship_primary_changed(shipp); // AL: maybe send multiplayer information when AI ship changes primaries @@ -5691,7 +5691,7 @@ int ai_fire_primary_weapon(object *objp) (enemy_objp->phys_info.speed >= 1.0f) && //Only burst for moving ships (enemy_sip->is_small_ship() || enemy_sip->flags[Ship::Info_Flags::Transport]) && //Only burst for small ships (transports count) swp->primary_bank_start_ammo[swp->current_primary_bank] > 0 && //Prevent div by 0 - Weapon_info[swp->primary_bank_weapons[swp->current_primary_bank]].wi_flags2 & WIF2_BALLISTIC) //Current weapon must be ballistic + Weapon_info[swp->primary_bank_weapons[swp->current_primary_bank]].wi_flags[Weapon::Info_Flags::Ballistic]) //Current weapon must be ballistic { float percentAmmoLeft = ((float)swp->primary_bank_ammo[swp->current_primary_bank] / (float)swp->primary_bank_start_ammo[swp->current_primary_bank]); float distToTarget = vm_vec_dist(&enemy_objp->pos, &objp->pos); @@ -5739,7 +5739,7 @@ int ai_fire_primary_weapon(object *objp) if ((enemy_objp->hull_strength < 750.0f) && ((aip->targeted_subsys == NULL) || (enemy_objp->hull_strength < aip->targeted_subsys->current_hits + 50.0f)) && (swp->current_primary_bank >= 0) ) { - if (!(Weapon_info[swp->primary_bank_weapons[swp->current_primary_bank]].wi_flags & WIF_PUNCTURE)) { + if (!(Weapon_info[swp->primary_bank_weapons[swp->current_primary_bank]].wi_flags[Weapon::Info_Flags::Puncture])) { swp->next_primary_fire_stamp[swp->current_primary_bank] = timestamp(1000); return 0; } @@ -5804,35 +5804,39 @@ int num_nearby_fighters(int enemy_team_mask, vec3d *pos, float threshold) // Favor aspect seekers when attacking small ships faraway. // Favor rapid fire dumbfire when attacking a large ship. // Ignore heat seekers because we're not sure how they'll work. -void ai_select_secondary_weapon(object *objp, ship_weapon *swp, int priority1 = -1, int priority2 = -1, int wif2_priority1 = -1, int wif2_priority2 = -1) +void ai_select_secondary_weapon(object *objp, ship_weapon *swp, flagset* priority1 = NULL, flagset* priority2 = NULL) { int num_weapon_types; int weapon_id_list[MAX_WEAPON_TYPES], weapon_bank_list[MAX_WEAPON_TYPES]; int i; - int ignore_mask, ignore_mask_without_huge; + flagset ignore_mask, prio1, prio2; int initial_bank; ai_info *aip = &Ai_info[Ships[objp->instance].ai_index]; initial_bank = swp->current_secondary_bank; + if (priority1 != NULL) + prio1 = *priority1; + if (priority2 != NULL) + prio2 = *priority2; + + // set up ignore masks - ignore_mask = 0; - ignore_mask_without_huge = 0; + ignore_mask.reset(); // Ignore bombs unless one of the priorities asks for them to be selected. - if (!(WIF_HUGE & (priority1 | priority2))) { - ignore_mask |= WIF_HUGE; + if (!(prio1[Weapon::Info_Flags::Huge] || prio2[Weapon::Info_Flags::Huge])) { + ignore_mask.set(Weapon::Info_Flags::Huge); } // Ignore capital+ unless one of the priorities asks for it. - if (!(WIF2_CAPITAL_PLUS & (wif2_priority1 | wif2_priority2))) { - ignore_mask |= WIF2_CAPITAL_PLUS; + if (!(prio1[Weapon::Info_Flags::Capital_plus] || prio2[Weapon::Info_Flags::Capital_plus])) { + ignore_mask.set(Weapon::Info_Flags::Capital_plus); } // Ignore bomber+ unless one of the priorities asks for them to be selected - if (!(WIF_BOMBER_PLUS & (priority1 | priority2))) { - ignore_mask |= WIF_BOMBER_PLUS; - ignore_mask_without_huge |= WIF_BOMBER_PLUS; + if (!(prio1[Weapon::Info_Flags::Bomber_plus] || prio2[Weapon::Info_Flags::Bomber_plus])) { + ignore_mask.set(Weapon::Info_Flags::Bomber_plus); } #ifndef NDEBUG @@ -5846,38 +5850,28 @@ void ai_select_secondary_weapon(object *objp, ship_weapon *swp, int priority1 = num_weapon_types = get_available_secondary_weapons(objp, weapon_id_list, weapon_bank_list); // Ignore homing weapons if we didn't specify a flag - for priority 1 - if ((aip->ai_profile_flags & AIPF_SMART_SECONDARY_WEAPON_SELECTION) && (priority1 == 0)) { - ignore_mask |= WIF_HOMING; - ignore_mask_without_huge |= WIF_HOMING; + if ((aip->ai_profile_flags & AIPF_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); } int priority2_index = -1; for (i=0; isecondary_bank_weapons[weapon_bank_list[i]]].wi_flags; - int wi_flags2 = Weapon_info[swp->secondary_bank_weapons[weapon_bank_list[i]]].wi_flags2; - int ignore_mask_to_use = ((aip->ai_profile_flags & AIPF_SMART_SECONDARY_WEAPON_SELECTION) && (wi_flags & WIF_BOMBER_PLUS)) ? ignore_mask_without_huge : ignore_mask; + auto wi_flags = Weapon_info[swp->secondary_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; - if (!(wi_flags & ignore_mask_to_use)) { // Maybe bombs are illegal. - if (wi_flags & priority1) { + if (!(wi_flags & ignore_mask_to_use).any_set()) { // Maybe bombs are illegal. + if ((wi_flags & prio1).any_set()) { swp->current_secondary_bank = weapon_bank_list[i]; // Found first priority, return it. break; - } else if (wi_flags & priority2) - priority2_index = weapon_bank_list[i]; // Found second priority, but might still find first priority. - } - if (!(wi_flags2 & ignore_mask_to_use)) { // Maybe bombs are illegal. - if (wi_flags2 & wif2_priority1) { - swp->current_secondary_bank = weapon_bank_list[i]; // Found first priority, return it. - break; - } else if (wi_flags2 & wif2_priority2) + } else if ((wi_flags & prio2).any_set()) priority2_index = weapon_bank_list[i]; // Found second priority, but might still find first priority. } } // Ignore homing weapons if we didn't specify a flag - for priority 2 - if ((aip->ai_profile_flags & AIPF_SMART_SECONDARY_WEAPON_SELECTION) && (priority2 == 0)) { - ignore_mask |= WIF_HOMING; - ignore_mask_without_huge |= WIF_HOMING; + if ((aip->ai_profile_flags & AIPF_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); } // If didn't find anything above, then pick any secondary weapon. @@ -5885,10 +5879,10 @@ void ai_select_secondary_weapon(object *objp, ship_weapon *swp, int priority1 = swp->current_secondary_bank = priority2_index; // Assume we won't find anything. if (priority2_index == -1) { for (i=0; isecondary_bank_weapons[weapon_bank_list[i]]].wi_flags; - int ignore_mask_to_use = ((aip->ai_profile_flags & AIPF_SMART_SECONDARY_WEAPON_SELECTION) && (wi_flags & WIF_BOMBER_PLUS)) ? ignore_mask_without_huge : ignore_mask; + auto wi_flags = Weapon_info[swp->secondary_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; - if (!(wi_flags & ignore_mask_to_use)) { // Maybe bombs are illegal. + if (!(wi_flags & ignore_mask_to_use).any_set()) { // Maybe bombs are illegal. if (swp->secondary_bank_ammo[weapon_bank_list[i]] > 0) { swp->current_secondary_bank = weapon_bank_list[i]; break; @@ -5910,7 +5904,7 @@ void ai_select_secondary_weapon(object *objp, ship_weapon *swp, int priority1 = weapon_info *wip=&Weapon_info[swp->secondary_bank_weapons[swp->current_secondary_bank]]; // phreak -- rapid dumbfire? let it rip! - if ((aip->ai_profile_flags & AIPF_ALLOW_RAPID_SECONDARY_DUMBFIRE) && !(wip->wi_flags & WIF_HOMING) && (wip->fire_wait < .5f)) + if ((aip->ai_profile_flags & AIPF_ALLOW_RAPID_SECONDARY_DUMBFIRE) && !(wip->is_homing()) && (wip->fire_wait < .5f)) { aip->ai_flags |= AIF_UNLOAD_SECONDARIES; } @@ -5929,7 +5923,7 @@ int compute_num_homing_objects(object *target_objp) for ( objp = GET_FIRST(&obj_used_list); objp !=END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) { if (objp->type == OBJ_WEAPON) { - if (Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags & WIF_HOMING) { + if (Weapon_info[Weapons[objp->instance].weapon_info_index].is_homing()) { if (Weapons[objp->instance].homing_object == target_objp) { count++; } @@ -6012,7 +6006,7 @@ int check_ok_to_fire(int objnum, int target_objnum, weapon_info *wip) // If player, maybe fire based on Skill_level and number of incoming weapons. // If non-player, maybe fire based on payload of incoming weapons. - if (wip->wi_flags & WIF_HOMING) { + if (wip->is_homing()) { if ((target_objnum > -1) && (tobjp->flags[Object::Object_Flags::Player_ship])) { if (Ai_info[Ships[tobjp->instance].ai_index].target_objnum != objnum) { // Don't allow AI ships to fire at player for fixed periods of time based on skill level. @@ -6024,7 +6018,7 @@ int check_ok_to_fire(int objnum, int target_objnum, weapon_info *wip) } } int swarmers = 0; - if (wip->wi_flags & WIF_SWARM) + if (wip->wi_flags[Weapon::Info_Flags::Swarm]) swarmers = 2; // Note, always want to be able to fire swarmers if no currently incident homers. if (The_mission.ai_profile->max_allowed_player_homers[Game_skill_level] < num_homers + swarmers) { return 0; @@ -6083,9 +6077,9 @@ int ai_fire_secondary_weapon(object *objp, int priority1, int priority2) weapon_info *wip = &Weapon_info[shipp->weapons.secondary_bank_weapons[current_bank]]; - if ((wip->wi_flags & WIF_LOCKED_HOMING) && (!Ai_info[shipp->ai_index].current_target_is_locked)) { + if ((wip->is_locked_homing()) && (!Ai_info[shipp->ai_index].current_target_is_locked)) { swp->next_secondary_fire_stamp[current_bank] = timestamp(250); - } else if ((wip->wi_flags & WIF_BOMB) || (vm_vec_dist_quick(&objp->pos, &En_objp->pos) > 50.0f)) { + } else if ((wip->wi_flags[Weapon::Info_Flags::Bomb]) || (vm_vec_dist_quick(&objp->pos, &En_objp->pos) > 50.0f)) { // This might look dumb, firing a bomb even if closer than 50 meters, but the reason is, if you're carrying // bombs, delivering them is probably more important than surviving. ai_info *aip; @@ -7609,7 +7603,7 @@ void update_aspect_lock_information(ai_info *aip, vec3d *vec_to_enemy, float dis wip = &Weapon_info[swp->secondary_bank_weapons[swp->current_secondary_bank]]; - if (num_weapon_types && (wip->wi_flags & WIF_LOCKED_HOMING) && !(shipp->flags[Ship::Ship_Flags::No_secondary_lockon])) { + if (num_weapon_types && (wip->is_locked_homing()) && !(shipp->flags[Ship::Ship_Flags::No_secondary_lockon])) { if (dist_to_enemy > 300.0f - MIN(enemy_radius, 100.0f)) aip->ai_flags |= AIF_SEEK_LOCK; else @@ -7621,8 +7615,8 @@ void update_aspect_lock_information(ai_info *aip, vec3d *vec_to_enemy, float dis float needed_dot = 0.9f - 0.5f * enemy_radius/(dist_to_enemy + enemy_radius); // Replaced MIN_TRACKABLE_DOT with 0.9f if (dot_to_enemy > needed_dot && - (wip->wi_flags & WIF_HOMING_ASPECT || - (wip->wi_flags & WIF_HOMING_JAVELIN && + (wip->wi_flags[Weapon::Info_Flags::Homing_aspect] || + (wip->wi_flags[Weapon::Info_Flags::Homing_javelin] && (tshpp == NULL || ship_get_closest_subsys_in_sight(tshpp, SUBSYSTEM_ENGINE, &aiobjp->pos))))) { aip->aspect_locked_time += flFrametime; @@ -7706,7 +7700,8 @@ int has_preferred_secondary(object *objp, object *en_objp, ship_weapon *swp) void ai_choose_secondary_weapon(object *objp, ai_info *aip, object *en_objp) { float subsystem_strength = 0.0f; - int is_big_ship, wif_priority1, wif_priority2, wif2_priority1, wif2_priority2; + int is_big_ship; + flagset wif_priority1, wif_priority2; ship_weapon *swp; ship_info *esip; @@ -7747,41 +7742,36 @@ void ai_choose_secondary_weapon(object *objp, ai_info *aip, object *en_objp) if (is_big_ship) { - wif_priority1 = WIF_HUGE; - wif_priority2 = (aip->ai_profile_flags & AIPF_SMART_SECONDARY_WEAPON_SELECTION) ? WIF_BOMBER_PLUS : WIF_HOMING; - wif2_priority1 = WIF2_CAPITAL_PLUS; - wif2_priority2 = 0; + wif_priority1.set(Weapon::Info_Flags::Huge); + if (aip->ai_profile_flags & AIPF_SMART_SECONDARY_WEAPON_SELECTION) { + wif_priority2.set(Weapon::Info_Flags::Bomber_plus); + } + else { + wif_priority2.set(Weapon::Info_Flags::Homing_aspect).set(Weapon::Info_Flags::Homing_heat).set(Weapon::Info_Flags::Homing_javelin); + } } else if ( (esip != NULL) && (esip->flags[Ship::Info_Flags::Bomber]) ) { - wif_priority1 = WIF_BOMBER_PLUS; - wif_priority2 = WIF_HOMING; - wif2_priority1 = 0; - wif2_priority2 = 0; + wif_priority1.set(Weapon::Info_Flags::Bomber_plus); + wif_priority2.set(Weapon::Info_Flags::Homing_aspect).set(Weapon::Info_Flags::Homing_heat).set(Weapon::Info_Flags::Homing_javelin); } else if (subsystem_strength > 100.0f) { - wif_priority1 = WIF_PUNCTURE; - wif_priority2 = WIF_HOMING; - wif2_priority1 = 0; - wif2_priority2 = 0; + 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 { - wif_priority1 = 0; - wif_priority2 = 0; - wif2_priority1 = 0; - wif2_priority2 = 0; + wif_priority1.reset(); + wif_priority2.reset(); } else { - wif_priority1 = WIF_HOMING; - wif_priority2 = 0; - wif2_priority1 = 0; - wif2_priority2 = 0; + wif_priority1.set(Weapon::Info_Flags::Homing_aspect).set(Weapon::Info_Flags::Homing_heat).set(Weapon::Info_Flags::Homing_javelin); + wif_priority2.reset(); } - ai_select_secondary_weapon(objp, swp, wif_priority1, wif_priority2, wif2_priority1, wif2_priority2); + ai_select_secondary_weapon(objp, swp, &wif_priority1, &wif_priority2); } } @@ -8204,7 +8194,7 @@ void ai_chase() return; } - if (sip->class_type > -1 && (Ship_types[sip->class_type].ai_bools & STI_AI_ATTEMPT_BROADSIDE)) { + if (sip->class_type > -1 && (Ship_types[sip->class_type].flags[Ship::Type_Info_Flags::AI_attempt_broadside])) { ai_cruiser_chase(); return; } @@ -8805,9 +8795,9 @@ void ai_chase() if (current_bank >= 0) { float firing_range; - if (swip->wi_flags2 & WIF2_LOCAL_SSM) + if (swip->wi_flags[Weapon::Info_Flags::Local_ssm]) firing_range=swip->lssm_lock_range; //that should be enough - else if (swip->wi_flags & WIF_BOMB) + else if (swip->wi_flags[Weapon::Info_Flags::Bomb]) firing_range = MIN((swip->max_speed * swip->lifetime * 0.75f), swip->weapon_range); else { @@ -8828,7 +8818,7 @@ void ai_chase() // If firing a spawn weapon, distance doesn't matter. int spawn_fire = 0; - if (swip->wi_flags & WIF_SPAWN) { + if (swip->wi_flags[Weapon::Info_Flags::Spawn]) { int count; count = num_nearby_fighters(iff_get_attackee_mask(obj_team(Pl_objp)), &Pl_objp->pos, 1000.0f); @@ -8852,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; @@ -8870,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; @@ -9635,7 +9625,7 @@ int ai_guard_find_nearby_bomb(object *guarding_objp, object *guarded_objp) wp = &Weapons[bomb_objp->instance]; wip = &Weapon_info[wp->weapon_info_index]; - if ( !((wip->wi_flags & WIF_BOMB) || (wip->wi_flags3 & WIF3_FIGHTER_INTERCEPTABLE)) ) { + if ( !((wip->wi_flags[Weapon::Info_Flags::Bomb]) || (wip->wi_flags[Weapon::Info_Flags::Fighter_Interceptable])) ) { continue; } @@ -9691,7 +9681,7 @@ void ai_guard_find_nearby_ship(object *guarding_objp, object *guarded_objp) if (iff_x_attacks_y(guarding_shipp->team, eshipp->team)) { // Don't attack a cargo container or other harmless ships - if (Ship_info[eshipp->ship_info_index].class_type >= 0 && (Ship_types[Ship_info[eshipp->ship_info_index].class_type].ai_bools & STI_AI_GUARDS_ATTACK)) + if (Ship_info[eshipp->ship_info_index].class_type >= 0 && (Ship_types[Ship_info[eshipp->ship_info_index].class_type].flags[Ship::Type_Info_Flags::AI_guards_attack])) { dist = vm_vec_dist_quick(&enemy_objp->pos, &guarded_objp->pos); if (dist < (MAX_GUARD_DIST + guarded_objp->radius)*3) @@ -12385,7 +12375,7 @@ void ai_maybe_evade_locked_missile(object *objp, ai_info *aip) return; } - if ((missile_objp->type == OBJ_WEAPON) && (Weapon_info[Weapons[missile_objp->instance].weapon_info_index].wi_flags & WIF_HOMING)) { + if ((missile_objp->type == OBJ_WEAPON) && (Weapon_info[Weapons[missile_objp->instance].weapon_info_index].is_homing())) { float dist = vm_vec_dist_quick(&missile_objp->pos, &objp->pos); float dist2 = 4.0f * vm_vec_mag_quick(&missile_objp->phys_info.vel); if (dist < dist2) { @@ -13261,7 +13251,7 @@ int maybe_request_support(object *objp) { wip = &Weapon_info[swp->primary_bank_weapons[i]]; - if (wip->wi_flags2 & WIF2_BALLISTIC) + if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) { r = (float) swp->primary_bank_ammo[i] / swp->primary_bank_start_ammo[i]; @@ -13618,7 +13608,7 @@ int aas_1(object *objp, ai_info *aip, vec3d *safe_pos) // If an aspect locked missile, assume it will detonate at the homing position. // If not, which is not possible in a default FreeSpace weapon, then predict it will detonate at some // time in the future, this time based on max lifetime and life left. - if (wip->wi_flags & WIF_LOCKED_HOMING) { + if (wip->is_locked_homing()) { expected_pos = weaponp->homing_pos; if (weaponp->homing_object && weaponp->homing_object->type == OBJ_SHIP) { target_ship_obj = weaponp->homing_object; @@ -14058,7 +14048,7 @@ void ai_frame(int objnum) aip->active_goal = AI_GOAL_NONE; } else if (aip->resume_goal_time == -1) { // AL 12-9-97: Don't allow cargo and navbuoys to set their aip->target_objnum - if ( Ship_info[shipp->ship_info_index].class_type > -1 && (Ship_types[Ship_info[shipp->ship_info_index].class_type].ai_bools & STI_AI_AUTO_ATTACKS) ) { + if ( Ship_info[shipp->ship_info_index].class_type > -1 && (Ship_types[Ship_info[shipp->ship_info_index].class_type].flags[Ship::Type_Info_Flags::AI_auto_attacks]) ) { target_objnum = find_enemy(objnum, MAX_ENEMY_DISTANCE, The_mission.ai_profile->max_attackers[Game_skill_level]); // Attack up to 25K units away. if (target_objnum != -1) { if (aip->target_objnum != target_objnum) @@ -14103,7 +14093,7 @@ void ai_frame(int objnum) } // AL 12-10-97: ensure that cargo and navbuoys aip->target_objnum is always -1. - if ( Ship_info[shipp->ship_info_index].class_type > -1 && !(Ship_types[Ship_info[shipp->ship_info_index].class_type].ai_bools & STI_AI_AUTO_ATTACKS)) { + if ( Ship_info[shipp->ship_info_index].class_type > -1 && !(Ship_types[Ship_info[shipp->ship_info_index].class_type].flags[Ship::Type_Info_Flags::AI_auto_attacks])) { aip->target_objnum = -1; } @@ -14834,8 +14824,8 @@ int firing_aspect_seeking_bomb(object *objp) if (bank_index != -1) { if (swp->secondary_bank_weapons[bank_index] > 0) { if (swp->secondary_bank_ammo[bank_index] > 0) { - if (Weapon_info[swp->secondary_bank_weapons[bank_index]].wi_flags & WIF_BOMB) { - if (Weapon_info[swp->secondary_bank_weapons[bank_index]].wi_flags & WIF_HOMING_ASPECT) { + if (Weapon_info[swp->secondary_bank_weapons[bank_index]].wi_flags[Weapon::Info_Flags::Bomb]) { + if (Weapon_info[swp->secondary_bank_weapons[bank_index]].wi_flags[Weapon::Info_Flags::Homing_aspect]) { return 1; } } @@ -14915,7 +14905,7 @@ void ai_update_lethality(object *pship_obj, object *other_obj, float damage) // if parent is BIG|HUGE, don't count beam if ( Ship_info[Ships[Objects[parent].instance].ship_info_index].is_big_or_huge() ) { - if (wif->wi_flags & WIF_BEAM) { + if (wif->wi_flags[Weapon::Info_Flags::Beam]) { dont_count = TRUE; } } @@ -15565,8 +15555,9 @@ void cheat_fire_synaptic(object *objp, ship *shipp, ai_info *aip) ship_weapon *swp; swp = &shipp->weapons; int current_bank = swp->current_secondary_bank; - - ai_select_secondary_weapon(objp, swp, WIF_SPAWN, 0); + flagset flags; + flags += Weapon::Info_Flags::Spawn; + ai_select_secondary_weapon(objp, swp, &flags, NULL); if (timestamp_elapsed(swp->next_secondary_fire_stamp[current_bank])) { if (ship_fire_secondary(objp)) { nprintf(("AI", "ship %s cheat fired synaptic!\n", shipp->ship_name)); diff --git a/code/ai/aigoals.cpp b/code/ai/aigoals.cpp index b31f2dfe7a..6e9c86f4b1 100644 --- a/code/ai/aigoals.cpp +++ b/code/ai/aigoals.cpp @@ -1573,7 +1573,7 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp ) wing *wingp = &Wings[sindex]; - if ( wingp->flags & WF_WING_GONE ) + if ( wingp->flags[Ship::Wing_Flags::Gone] ) return AI_GOAL_NOT_ACHIEVABLE; else if ( wingp->total_arrived_count == 0 ) return AI_GOAL_NOT_KNOWN; @@ -2198,7 +2198,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip ) if (current_goal->ai_mode != AI_GOAL_DESTROY_SUBSYSTEM) { if (aip->target_objnum != -1) { // Only protect if _not_ a capital ship. We don't want the Lucifer accidentally getting protected. - if (Ship_types[Ship_info[Ships[shipnum].ship_info_index].class_type].ai_bools & STI_AI_PROTECTED_ON_CRIPPLE) + if (Ship_types[Ship_info[Ships[shipnum].ship_info_index].class_type].flags[Ship::Type_Info_Flags::AI_protected_on_cripple]) Objects[aip->target_objnum].flags.set(Object::Object_Flags::Protected); } } else // Just in case this ship had been protected, unprotect it. diff --git a/code/ai/aiturret.cpp b/code/ai/aiturret.cpp index 4ea04a39f7..02d78c60e3 100644 --- a/code/ai/aiturret.cpp +++ b/code/ai/aiturret.cpp @@ -256,54 +256,46 @@ int turret_select_best_weapon(ship_subsys *turret, object *target) /** * Returns true if all weapons in swp have the specified flag - * - * @note doesn't work for WIF2 */ -bool all_turret_weapons_have_flags(ship_weapon *swp, int flags) +bool all_turret_weapons_have_flags(ship_weapon *swp, flagset flags) { int i; for(i = 0; i < swp->num_primary_banks; i++) { - if(!(Weapon_info[swp->primary_bank_weapons[i]].wi_flags & flags)) + if(!(Weapon_info[swp->primary_bank_weapons[i]].wi_flags & flags).any_set()) return false; } for(i = 0; i < swp->num_secondary_banks; i++) { - if(!(Weapon_info[swp->secondary_bank_weapons[i]].wi_flags & flags)) + if(!(Weapon_info[swp->secondary_bank_weapons[i]].wi_flags & flags).any_set()) return false; } return true; } -/** - * Returns true if all weapons in swp have the specified flag - * - * @note does work for WIF2, but not WIF - */ -bool all_turret_weapons_have_flags2(ship_weapon *swp, int flags) +bool all_turret_weapons_have_flags(ship_weapon *swp, Weapon::Info_Flags flags) { - int i; - for(i = 0; i < swp->num_primary_banks; i++) - { - if(!(Weapon_info[swp->primary_bank_weapons[i]].wi_flags2 & flags)) - return false; - } - for(i = 0; i < swp->num_secondary_banks; i++) - { - if(!(Weapon_info[swp->secondary_bank_weapons[i]].wi_flags2 & flags)) - return false; - } + int i; + for (i = 0; i < swp->num_primary_banks; i++) + { + if (!(Weapon_info[swp->primary_bank_weapons[i]].wi_flags[flags])) + return false; + } + for (i = 0; i < swp->num_secondary_banks; i++) + { + if (!(Weapon_info[swp->secondary_bank_weapons[i]].wi_flags[flags])) + return false; + } - return true; + return true; } /** * Returns true if any of the weapons in swp have flags * - * @note doesn't work for WIF2 */ -bool turret_weapon_has_flags(ship_weapon *swp, int flags) +bool turret_weapon_has_flags(ship_weapon *swp, Weapon::Info_Flags flags) { Assert(swp != NULL); @@ -311,42 +303,14 @@ bool turret_weapon_has_flags(ship_weapon *swp, int flags) for(i = 0; i < swp->num_primary_banks; i++) { if(swp->primary_bank_weapons[i] >=0) { - if(Weapon_info[swp->primary_bank_weapons[i]].wi_flags & flags) + if(Weapon_info[swp->primary_bank_weapons[i]].wi_flags[flags]) return true; } } for(i = 0; i < swp->num_secondary_banks; i++) { if(swp->secondary_bank_weapons[i] >=0) { - if(Weapon_info[swp->secondary_bank_weapons[i]].wi_flags & flags) - return true; - } - } - - return false; -} - -/** - * Returns true if any of the weapons in swp have flags - * - * @note does work for WIF2, but not WIF - */ -bool turret_weapon_has_flags2(ship_weapon *swp, int flags) -{ - Assert(swp != NULL); - - int i = 0; - for(i = 0; i < swp->num_primary_banks; i++) - { - if(swp->primary_bank_weapons[i] >=0) { - if(Weapon_info[swp->primary_bank_weapons[i]].wi_flags2 & flags) - return true; - } - } - for(i = 0; i < swp->num_secondary_banks; i++) - { - if(swp->secondary_bank_weapons[i] >=0) { - if(Weapon_info[swp->secondary_bank_weapons[i]].wi_flags2 & flags) + if(Weapon_info[swp->secondary_bank_weapons[i]].wi_flags[flags]) return true; } } @@ -357,11 +321,12 @@ bool turret_weapon_has_flags2(ship_weapon *swp, int flags) /** * Just gloms all the flags from all the weapons into one variable. More efficient if all you need to do is test for the existence of a flag. */ -int turret_weapon_aggregate_flags(ship_weapon *swp) +flagset turret_weapon_aggregate_flags(ship_weapon *swp) { Assert(swp != NULL); - int i = 0, flags = 0; + int i = 0; + flagset flags; for (i = 0; i < swp->num_primary_banks; i++) { if (swp->primary_bank_weapons[i] >= 0) { @@ -378,30 +343,6 @@ int turret_weapon_aggregate_flags(ship_weapon *swp) return flags; } -/** - * Just gloms all the flags from all the weapons into one variable. More efficient if all you need to do is test for the existence of a flag. - */ -int turret_weapon_aggregate_flags2(ship_weapon *swp) -{ - Assert(swp != NULL); - - int i = 0, flags2 = 0; - for (i = 0; i < swp->num_primary_banks; i++) - { - if (swp->primary_bank_weapons[i] >= 0) { - flags2 |= Weapon_info[swp->primary_bank_weapons[i]].wi_flags2; - } - } - for (i = 0; i < swp->num_secondary_banks; i++) - { - if (swp->secondary_bank_weapons[i] >= 0) { - flags2 |= Weapon_info[swp->secondary_bank_weapons[i]].wi_flags2; - } - } - - return flags2; -} - /** * Returns true if any of the weapons in swp have the subtype specified * @@ -473,7 +414,7 @@ float longest_turret_weapon_range(ship_weapon *swp) for(i = 0; i < swp->num_primary_banks; i++) { wip = &Weapon_info[swp->primary_bank_weapons[i]]; - if (wip->wi_flags2 & WIF2_LOCAL_SSM) + if (wip->wi_flags[Weapon::Info_Flags::Local_ssm]) weapon_range = wip->lssm_lock_range; else weapon_range = MIN(wip->lifetime * wip->max_speed, wip->weapon_range); @@ -484,7 +425,7 @@ float longest_turret_weapon_range(ship_weapon *swp) for(i = 0; i < swp->num_secondary_banks; i++) { wip = &Weapon_info[swp->secondary_bank_weapons[i]]; - if (wip->wi_flags2 & WIF2_LOCAL_SSM) + if (wip->wi_flags[Weapon::Info_Flags::Local_ssm]) weapon_range = wip->lssm_lock_range; else weapon_range = MIN(wip->lifetime * wip->max_speed, wip->weapon_range); @@ -537,7 +478,7 @@ int valid_turret_enemy(object *objp, object *turret_parent) } // Goober5000 - don't fire at cargo containers (now specified in ship_types) - if ( (sip->class_type >= 0) && !(Ship_types[sip->class_type].ai_bools & STI_AI_TURRETS_ATTACK) ) { + if ( (sip->class_type >= 0) && !(Ship_types[sip->class_type].flags[Ship::Type_Info_Flags::AI_turrets_attack]) ) { return 0; } @@ -549,15 +490,15 @@ int valid_turret_enemy(object *objp, object *turret_parent) weapon *wp = &Weapons[objp->instance]; weapon_info *wip = &Weapon_info[wp->weapon_info_index]; - if (wip->subtype == WP_LASER && !(wip->wi_flags3 & WIF3_TURRET_INTERCEPTABLE)) { // If the thing can't be shot down, don't try. -MageKing17 + if (wip->subtype == WP_LASER && !(wip->wi_flags[Weapon::Info_Flags::Turret_Interceptable])) { // If the thing can't be shot down, don't try. -MageKing17 return 0; } - if ( (!((wip->wi_flags & WIF_BOMB) || (wip->wi_flags3 & WIF3_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 & AIPF_ALLOW_TURRETS_TARGET_WEAPONS_FREELY) ) ) { return 0; } - if ( (wip->wi_flags2 & WIF2_LOCAL_SSM) && (wp->lssm_stage == 3) ) { + if ( (wip->wi_flags[Weapon::Info_Flags::Local_ssm]) && (wp->lssm_stage == 3) ) { return 0; } @@ -658,7 +599,7 @@ void evaluate_obj_as_target(object *objp, eval_enemy_obj_struct *eeo) if (eeo->eeo_flags & EEOF_TAGGED_ONLY) { if (!ship_is_tagged(objp) && ( (The_mission.ai_profile->flags2 & AIPF2_STRICT_TURRET_TAGGED_ONLY_TARGETING) || - ( !(objp->type == OBJ_WEAPON) && !(turret_weapon_has_flags(&eeo->turret_subsys->weapons, WIF_SPAWN))) )) { + ( !(objp->type == OBJ_WEAPON) && !(turret_weapon_has_flags(&eeo->turret_subsys->weapons, Weapon::Info_Flags::Spawn))) )) { return; } } @@ -842,12 +783,12 @@ void evaluate_obj_as_target(object *objp, eval_enemy_obj_struct *eeo) int is_target_beam_valid(ship_weapon *swp, object *objp) { // check if turret has beam weapon - if (all_turret_weapons_have_flags(swp, WIF_BEAM)) { + if (all_turret_weapons_have_flags(swp, Weapon::Info_Flags::Beam)) { if (objp->flags[Object::Object_Flags::Beam_protected]) { return 0; } - if (all_turret_weapons_have_flags(swp, WIF_HUGE)) { + if (all_turret_weapons_have_flags(swp, Weapon::Info_Flags::Huge)) { if (objp->type == OBJ_SHIP && !(Ship_info[Ships[objp->instance].ship_info_index].is_big_or_huge()) ) { return 0; } @@ -889,7 +830,7 @@ int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subs //wip=&Weapon_info[tp->turret_weapon_type]; //weapon_travel_dist = MIN(wip->lifetime * wip->max_speed, wip->weapon_range); - //if (wip->wi_flags2 & WIF2_LOCAL_SSM) + //if (wip->wi_flags[Weapon::Info_Flags::Local_ssm]) // weapon_travel_dist=wip->lssm_lock_range; // Set flag based on strength of weapons subsystem. If weapons subsystem is destroyed, don't let turrets fire at bombs @@ -960,8 +901,8 @@ int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subs n_tgt_priorities = Weapon_info[priority_weapon_idx].num_targeting_priorities; } - if (n_tgt_priorities > 0) { - + if (n_tgt_priorities > 0) + { for(int i = 0; i < n_tgt_priorities; i++) { // courtesy of WMC... ai_target_priority *tt; @@ -1008,10 +949,8 @@ int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subs } } - if( ( (tt->wif_flags != 0) || (tt->wif2_flags != 0) || (tt->wif3_flags != 0) ) && (ptr->type == OBJ_WEAPON) ) { - if( ( (Weapon_info[Weapons[ptr->instance].weapon_info_index].wi_flags & tt->wif_flags ) == tt->wif_flags) - && ( (Weapon_info[Weapons[ptr->instance].weapon_info_index].wi_flags2 & tt->wif2_flags ) == tt->wif2_flags) - && ( (Weapon_info[Weapons[ptr->instance].weapon_info_index].wi_flags3 & tt->wif3_flags ) == tt->wif3_flags) ) { + if( (tt->wif_flags.any_set()) && (ptr->type == OBJ_WEAPON) ) { + if( ( (Weapon_info[Weapons[ptr->instance].weapon_info_index].wi_flags & tt->wif_flags ) == tt->wif_flags) ) { found_something = true; } } @@ -1087,7 +1026,11 @@ int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subs return return_objnum; } } - } else { + } else + { + flagset tmp_flagset; + const Weapon::Info_Flags weapon_flags[] = { Weapon::Info_Flags::Huge, Weapon::Info_Flags::Flak, Weapon::Info_Flags::Homing_aspect, Weapon::Info_Flags::Homing_heat, Weapon::Info_Flags::Homing_javelin, Weapon::Info_Flags::Spawn }; + tmp_flagset.set_multiple(std::begin(weapon_flags), std::end(weapon_flags)); for(int i = 0; i < NUM_TURRET_ORDER_TYPES; i++) { @@ -1108,7 +1051,7 @@ int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subs objp = &Objects[mo->objnum]; Assert(objp->type == OBJ_WEAPON); - if ((Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags & WIF_BOMB) || (Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags3 & WIF3_TURRET_INTERCEPTABLE)) + if ((Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Bomb]) || (Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Turret_Interceptable])) { evaluate_obj_as_target(objp, &eeo); } @@ -1151,7 +1094,8 @@ int get_nearest_turret_objnum(int turret_parent_objnum, ship_subsys *turret_subs // - lasers // - dumbfire type missiles // - AAA beams - if ( !all_turret_weapons_have_flags(swp, WIF_HUGE | WIF_FLAK | WIF_HOMING | WIF_SPAWN) ) { + + if ( !all_turret_weapons_have_flags(swp, tmp_flagset) ) { // Asteroid_obj_list for ( ao = GET_FIRST(&Asteroid_obj_list); ao != END_OF_LIST(&Asteroid_obj_list); ao = GET_NEXT(ao) ) { objp = &Objects[ao->objnum]; @@ -1192,12 +1136,12 @@ int find_turret_enemy(ship_subsys *turret_subsys, int objnum, vec3d *tpos, vec3d enemy_team_mask = iff_get_attackee_mask(obj_team(&Objects[objnum])); - bool big_only_flag = all_turret_weapons_have_flags(&turret_subsys->weapons, WIF_HUGE); - bool small_only_flag = all_turret_weapons_have_flags2(&turret_subsys->weapons, WIF2_SMALL_ONLY); - bool tagged_only_flag = all_turret_weapons_have_flags2(&turret_subsys->weapons, WIF2_TAGGED_ONLY) || (turret_subsys->weapons.flags[Ship::Weapon_Flags::Tagged_Only]); + bool big_only_flag = all_turret_weapons_have_flags(&turret_subsys->weapons, Weapon::Info_Flags::Huge); + bool small_only_flag = all_turret_weapons_have_flags(&turret_subsys->weapons, Weapon::Info_Flags::Small_only); + bool tagged_only_flag = all_turret_weapons_have_flags(&turret_subsys->weapons, Weapon::Info_Flags::Tagged_only) || (turret_subsys->weapons.flags[Ship::Weapon_Flags::Tagged_Only]); - bool beam_flag = turret_weapon_has_flags(&turret_subsys->weapons, WIF_BEAM); - bool flak_flag = turret_weapon_has_flags(&turret_subsys->weapons, WIF_FLAK); + bool beam_flag = turret_weapon_has_flags(&turret_subsys->weapons, Weapon::Info_Flags::Beam); + bool flak_flag = turret_weapon_has_flags(&turret_subsys->weapons, Weapon::Info_Flags::Flak); bool laser_flag = turret_weapon_has_subtype(&turret_subsys->weapons, WP_LASER); bool missile_flag = turret_weapon_has_subtype(&turret_subsys->weapons, WP_MISSILE); @@ -1205,7 +1149,7 @@ int find_turret_enemy(ship_subsys *turret_subsys, int objnum, vec3d *tpos, vec3d ai_info *aip = &Ai_info[Ships[Objects[objnum].instance].ai_index]; sip = &Ship_info[Ships[Objects[objnum].instance].ship_info_index]; - if ((Ship_types[sip->class_type].ship_bools & STI_TURRET_TGT_SHIP_TGT) && (aip->target_objnum != -1)) { + if ((Ship_types[sip->class_type].flags[Ship::Type_Info_Flags::Turret_tgt_ship_tgt]) && (aip->target_objnum != -1)) { int target_objnum = aip->target_objnum; if (Objects[target_objnum].signature == aip->target_signature) { @@ -1733,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; @@ -1747,13 +1691,13 @@ 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_flags2 & WIF2_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 if (MULTI_TEAM) { // flak guns need to fire more rapidly - if (wip->wi_flags & WIF_FLAK) { + if (wip->wi_flags[Weapon::Info_Flags::Flak]) { wait *= aip->ai_ship_fire_delay_scale_friendly * 0.5f; if (aip->ai_class_autoscale) wait += (Num_ai_classes - aip->ai_class - 1) * 40.0f; @@ -1764,7 +1708,7 @@ void turret_set_next_fire_timestamp(int weapon_num, weapon_info *wip, ship_subsy } } else { // flak guns need to fire more rapidly - if (wip->wi_flags & WIF_FLAK) { + if (wip->wi_flags[Weapon::Info_Flags::Flak]) { if (Ships[aip->shipnum].team == Player_ship->team) { wait *= aip->ai_ship_fire_delay_scale_friendly * 0.5f; } else { @@ -1773,7 +1717,7 @@ void turret_set_next_fire_timestamp(int weapon_num, weapon_info *wip, ship_subsy if (aip->ai_class_autoscale) wait += (Num_ai_classes - aip->ai_class - 1) * 40.0f; - } else if (wip->wi_flags & WIF_HUGE) { + } else if (wip->wi_flags[Weapon::Info_Flags::Huge]) { // make huge weapons fire independently of team wait *= aip->ai_ship_fire_delay_scale_friendly; if (aip->ai_class_autoscale) @@ -1869,12 +1813,12 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum, object *tobjp = &Objects[turret->turret_enemy_objnum]; // should not get this far. check if ship is protected from beam and weapon is type beam - if ( (wip->wi_flags & WIF_BEAM) && (tobjp->flags[Object::Object_Flags::Beam_protected]) ) { + if ( (wip->wi_flags[Weapon::Info_Flags::Beam]) && (tobjp->flags[Object::Object_Flags::Beam_protected]) ) { Int3(); return 0; } // should not get this far. check if ship is protected from flak and weapon is type flak - else if ( (wip->wi_flags & WIF_FLAK) && (tobjp->flags[Object::Object_Flags::Flak_protected]) ) { + else if ( (wip->wi_flags[Weapon::Info_Flags::Flak]) && (tobjp->flags[Object::Object_Flags::Flak_protected]) ) { Int3(); return 0; } @@ -1900,7 +1844,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum, turret_set_next_fire_timestamp(weapon_num, wip, turret, parent_aip); // if this weapon is a beam weapon, handle it specially - if (wip->wi_flags & WIF_BEAM) { + if (wip->wi_flags[Weapon::Info_Flags::Beam]) { // if this beam isn't free to fire if (!(turret->weapons.flags[Ship::Weapon_Flags::Beam_Free])) { return false; @@ -1914,7 +1858,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum, fire_info.beam_info_override = NULL; fire_info.shooter = &Objects[parent_objnum]; fire_info.target = &Objects[turret->turret_enemy_objnum]; - if (wip->wi_flags2 & WIF2_ANTISUBSYSBEAM) + if (wip->wi_flags[Weapon::Info_Flags::Antisubsysbeam]) fire_info.target_subsys = turret->targeted_subsys; else fire_info.target_subsys = NULL; @@ -1938,7 +1882,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum, return true; } // don't fire swam, but set up swarm info instead - else if ((wip->wi_flags & WIF_SWARM) || (wip->wi_flags & WIF_CORKSCREW)) { + else if ((wip->wi_flags[Weapon::Info_Flags::Swarm]) || (wip->wi_flags[Weapon::Info_Flags::Corkscrew])) { ship_weapon *swp = &turret->weapons; if (swp->current_secondary_bank < 0) { swp->current_secondary_bank = 0; @@ -2069,7 +2013,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum, Script_system.RemHookVars(4, "Ship", "Weapon", "Beam", "Target"); // if the gun is a flak gun - if (wip->wi_flags & WIF_FLAK) { + if (wip->wi_flags[Weapon::Info_Flags::Flak]) { // show a muzzle flash flak_muzzle_flash(turret_pos, turret_fvec, &Objects[parent_ship->objnum].phys_info, turret_weapon_class); @@ -2097,7 +2041,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum, subsys_index = ship_get_index_from_subsys(turret, parent_objnum ); Assert( subsys_index != -1 ); - if(wip->wi_flags & WIF_FLAK){ + if(wip->wi_flags[Weapon::Info_Flags::Flak]){ send_flak_fired_packet( parent_objnum, subsys_index, weapon_objnum, flak_range ); } else { send_turret_fired_packet( parent_objnum, subsys_index, weapon_objnum ); @@ -2155,13 +2099,13 @@ void turret_swarm_fire_from_turret(turret_swarm_info *tsi) tsi->turret->turret_next_fire_pos++; //check if this really is a swarm. If not, how the hell did it get here? - Assert((Weapon_info[tsi->weapon_class].wi_flags & WIF_SWARM) || (Weapon_info[tsi->weapon_class].wi_flags & WIF_CORKSCREW)); + Assert((Weapon_info[tsi->weapon_class].wi_flags[Weapon::Info_Flags::Swarm]) || (Weapon_info[tsi->weapon_class].wi_flags[Weapon::Info_Flags::Corkscrew])); // *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) - && !(Weapon_info[tsi->weapon_class].wi_flags & WIF_HOMING)) ) + && !(Weapon_info[tsi->weapon_class].is_homing())) ) { turret_fvec = tsi->turret->turret_last_fire_direction; } @@ -2273,7 +2217,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum) } // If beam weapon, check beam free - if ( all_turret_weapons_have_flags(swp, WIF_BEAM) && !(swp->flags[Ship::Weapon_Flags::Beam_Free]) ) { + if ( all_turret_weapons_have_flags(swp, Weapon::Info_Flags::Beam) && !(swp->flags[Ship::Weapon_Flags::Beam_Free]) ) { return; } @@ -2396,7 +2340,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum) //If this is a spawning type weapon, shoot it! //If 'smart spawn' just use it like normal weapons - if ( (wip->wi_flags & WIF_SPAWN) && !(wip->wi_flags2 & WIF2_SMART_SPAWN) ) + if ( (wip->wi_flags[Weapon::Info_Flags::Spawn]) && !(wip->wi_flags[Weapon::Info_Flags::Smart_spawn]) ) { if (( num_ships_nearby >= 3 ) || ((num_ships_nearby >= 2) && (frand() < 0.1f))) { turret_fire_weapon(i, ss, parent_objnum, &gpos, &ss->turret_last_fire_direction); @@ -2409,7 +2353,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum) } - if(wip->wi_flags2 & WIF2_LOCAL_SSM) + if(wip->wi_flags[Weapon::Info_Flags::Local_ssm]) { weapon_firing_range=wip->lssm_lock_range; WeaponMinRange = 0.0f; @@ -2421,7 +2365,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum) } - if (wip->wi_flags & WIF_BEAM) { + if (wip->wi_flags[Weapon::Info_Flags::Beam]) { if ( !((shipp->tag_left > 0) || (shipp->level2_tag_left > 0)) ) { if (Nebula_sec_range) { @@ -2439,7 +2383,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum) { if( (dist_to_enemy <= weapon_firing_range) && (dist_to_enemy >= WeaponMinRange) ) { - if ( wip->wi_flags & WIF_HUGE ) { + if ( wip->wi_flags[Weapon::Info_Flags::Huge] ) { if ( lep->type != OBJ_SHIP ) { continue; } @@ -2448,13 +2392,13 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum) } } - if ( wip->wi_flags2 & WIF2_SMALL_ONLY ) { + if ( wip->wi_flags[Weapon::Info_Flags::Small_only] ) { if ( (lep->type == OBJ_SHIP) && (Ship_info[Ships[lep->instance].ship_info_index].is_big_or_huge()) ) { continue; } } - bool tagged_only = ((wip->wi_flags2 & WIF2_TAGGED_ONLY) || (ss->weapons.flags[Ship::Weapon_Flags::Tagged_Only])); + bool tagged_only = ((wip->wi_flags[Weapon::Info_Flags::Tagged_only]) || (ss->weapons.flags[Ship::Weapon_Flags::Tagged_Only])); if (lep->type == OBJ_SHIP) { // Check if we're targeting a protected ship @@ -2465,13 +2409,13 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum) } // Check if we're targeting a beam protected ship with a beam weapon - if ( (lep->flags[Object::Object_Flags::Beam_protected]) && (wip->wi_flags & WIF_BEAM) ) { + if ( (lep->flags[Object::Object_Flags::Beam_protected]) && (wip->wi_flags[Weapon::Info_Flags::Beam]) ) { ss->turret_enemy_objnum = -1; ss->turret_time_enemy_in_range = 0.0f; continue; } // Check if we're targeting a flak protected ship with a flak weapon - else if ( (lep->flags[Object::Object_Flags::Flak_protected]) && (wip->wi_flags & WIF_FLAK) ) { + else if ( (lep->flags[Object::Object_Flags::Flak_protected]) && (wip->wi_flags[Weapon::Info_Flags::Flak]) ) { ss->turret_enemy_objnum = -1; ss->turret_time_enemy_in_range = 0.0f; continue; @@ -2653,7 +2597,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum) // if the weapon is a flak gun, add some jitter to its aim so it fires in a "cone" // to make a cool visual effect and make them less lethal - if(wip->wi_flags & WIF_FLAK){ + if(wip->wi_flags[Weapon::Info_Flags::Flak]){ flak_jitter_aim(&tv2e, dist_to_enemy, ship_get_subsystem_strength(shipp, SUBSYSTEM_WEAPONS), wip); } @@ -2668,7 +2612,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum) // we have already passed the FOV test of the turret so... in_sight = true; } else { - if (wip->wi_flags & WIF_HOMING_HEAT) { + if (wip->wi_flags[Weapon::Info_Flags::Homing_heat]) { if (dot > AICODE_TURRET_HEATSEEK_ANGLE) { in_sight = true; } @@ -2679,7 +2623,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum) } } - if ( !(wip->wi_flags & WIF_HOMING) ) + if ( !(wip->is_homing()) ) { if ((dist_to_enemy < 75.0f) || in_sight) { @@ -2687,7 +2631,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum) ok_to_fire = true; } } - else if ( wip->wi_flags & WIF_HOMING_HEAT ) + else if ( wip->wi_flags[Weapon::Info_Flags::Homing_heat] ) { // if heat seekers if ((dist_to_enemy < 50.0f) || in_sight) { @@ -2695,7 +2639,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum) ok_to_fire = true; } } - else if ( wip->wi_flags & WIF_HOMING_ASPECT ) + else if ( wip->wi_flags[Weapon::Info_Flags::Homing_aspect] ) { // if aspect seeker if ((dist_to_enemy < 50.0f) || in_sight) { @@ -2706,7 +2650,7 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum) ok_to_fire = true; } } - else if ( wip->wi_flags & WIF_HOMING_JAVELIN ) + else if ( wip->wi_flags[Weapon::Info_Flags::Homing_javelin] ) { // if javelin heat seeker if ((dist_to_enemy < 50.0f) || in_sight) { diff --git a/code/autopilot/autopilot.cpp b/code/autopilot/autopilot.cpp index 49bdf1185e..7940c8261e 100644 --- a/code/autopilot/autopilot.cpp +++ b/code/autopilot/autopilot.cpp @@ -335,7 +335,7 @@ bool StartAutopilot() { if (Ships[i].objnum != -1 && (Ships[i].flags[Ship::Ship_Flags::Navpoint_carry] || - (Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags & WF_NAV_CARRY) + (Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags[Ship::Wing_Flags::Nav_carry]) ) ) { @@ -368,7 +368,7 @@ bool StartAutopilot() { if (Ships[i].objnum != -1 && (Ships[i].flags[Ship::Ship_Flags::Navpoint_carry] || - (Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags & WF_NAV_CARRY) + (Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags[Ship::Wing_Flags::Nav_carry]) ) ) { @@ -423,7 +423,7 @@ bool StartAutopilot() // snap wings into formation if (The_mission.flags[Mission::Mission_Flags::Use_ap_cinematics] && // only if using cinematics - (Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags & WF_NAV_CARRY) // only if in a wing + (Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags[Ship::Wing_Flags::Nav_carry]) // only if in a wing && Autopilot_flight_leader != &Objects[Ships[i].objnum]) //only if not flight leader's object { ai_info *aip = &Ai_info[Ships[i].ai_index]; @@ -501,7 +501,7 @@ bool StartAutopilot() { for (i = 0; i < MAX_WINGS; i++) { - if (Wings[i].flags & WF_NAV_CARRY ) + if (Wings[i].flags[Ship::Wing_Flags::Nav_carry] ) { //ai_add_ship_goal_player( int type, int mode, int submode, char *shipname, ai_info *aip ); @@ -540,7 +540,7 @@ bool StartAutopilot() if (Ships[i].objnum != -1) { if (Ships[i].flags[Ship::Ship_Flags::Navpoint_carry] || - (Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags & WF_NAV_CARRY)) + (Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags[Ship::Wing_Flags::Nav_carry])) for (j = 0; j < MAX_AI_GOALS; j++) { if (Ai_info[Ships[i].ai_index].goals[j].ai_mode == AI_GOAL_WAYPOINTS_ONCE || @@ -915,7 +915,7 @@ void EndAutoPilot() if (Ships[i].objnum != -1 && ( Ships[i].flags[Ship::Ship_Flags::Navpoint_carry] || - (Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags & WF_NAV_CARRY ) + (Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags[Ship::Wing_Flags::Nav_carry] ) ) ) { @@ -962,7 +962,7 @@ void EndAutoPilot() { for (i = 0; i < MAX_WINGS; i++) { - if (Wings[i].flags & WF_NAV_CARRY ) + if (Wings[i].flags[Ship::Wing_Flags::Nav_carry] ) { for (j = 0; j < MAX_AI_GOALS; j++) { @@ -1045,7 +1045,7 @@ void nav_warp(bool prewarp=false) { if (Ships[i].objnum != -1 && (Ships[i].flags[Ship::Ship_Flags::Navpoint_carry] - || (Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags & WF_NAV_CARRY))) + || (Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags[Ship::Wing_Flags::Nav_carry]))) { vm_vec_add(&Objects[Ships[i].objnum].pos, &Objects[Ships[i].objnum].pos, &targetPos); Objects[Ships[i].objnum].phys_info.vel = velocity; diff --git a/code/cmdline/cmdline.cpp b/code/cmdline/cmdline.cpp index c7186c6f4f..bde413b36d 100644 --- a/code/cmdline/cmdline.cpp +++ b/code/cmdline/cmdline.cpp @@ -229,7 +229,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", }, @@ -237,6 +236,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 @@ -479,6 +479,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; @@ -505,6 +506,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); @@ -1838,6 +1840,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 cf5a883178..98f907b9b0 100644 --- a/code/cmdline/cmdline.h +++ b/code/cmdline/cmdline.h @@ -157,5 +157,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/cmeasure/cmeasure.cpp b/code/cmeasure/cmeasure.cpp index 274bfe9194..2af77c492d 100644 --- a/code/cmeasure/cmeasure.cpp +++ b/code/cmeasure/cmeasure.cpp @@ -62,7 +62,7 @@ void cmeasure_select_next(ship *shipp) { new_index = (shipp->current_cmeasure + i) % Num_weapon_types; - if(Weapon_info[new_index].wi_flags & WIF_CMEASURE) + if(Weapon_info[new_index].wi_flags[Weapon::Info_Flags::Cmeasure]) { shipp->current_cmeasure = new_index; return; @@ -88,7 +88,7 @@ void cmeasure_maybe_alert_success(object *objp) return; } - Assert(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags & WIF_CMEASURE); + Assert(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Cmeasure]); if ( objp->parent == OBJ_INDEX(Player_obj) ) { hud_start_text_flash(XSTR("Evaded", 1430), 800); 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/def_files/deferred-f.sdr b/code/def_files/deferred-f.sdr index a710eed75c..95d28eb525 100644 --- a/code/def_files/deferred-f.sdr +++ b/code/def_files/deferred-f.sdr @@ -31,7 +31,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) { diff --git a/code/globalincs/flagset.h b/code/globalincs/flagset.h index 9f53503ac3..9b3e2be0df 100644 --- a/code/globalincs/flagset.h +++ b/code/globalincs/flagset.h @@ -120,8 +120,8 @@ class flagset { return *this; } - bool any_set() const { return values.any(); } - bool none_set() const { return values.none(); } + bool any_set() { return values.any(); } + bool none_set() { return values.none(); } void from_long(std::uint64_t num) { values = num; } std::uint64_t to_long() const { return values.to_ulong(); } diff --git a/code/globalincs/vmallocator.h b/code/globalincs/vmallocator.h index 6150008619..9b54ff3728 100644 --- a/code/globalincs/vmallocator.h +++ b/code/globalincs/vmallocator.h @@ -14,29 +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/graphics/gropengldraw.cpp b/code/graphics/gropengldraw.cpp index ac691e59d0..985f428250 100644 --- a/code/graphics/gropengldraw.cpp +++ b/code/graphics/gropengldraw.cpp @@ -2529,7 +2529,7 @@ void opengl_setup_scene_textures() } //Setup thruster distortion framebuffer - if (Cmdline_fb_thrusters) + if (Cmdline_fb_thrusters || Cmdline_fb_explosions) { glGenFramebuffers(1, &Distortion_framebuffer); glBindFramebuffer(GL_FRAMEBUFFER, Distortion_framebuffer); diff --git a/code/headtracking/freetrack.cpp b/code/headtracking/freetrack.cpp index 48ccdc53b0..1766dd527d 100644 --- a/code/headtracking/freetrack.cpp +++ b/code/headtracking/freetrack.cpp @@ -58,7 +58,7 @@ namespace value.resize(value.length() - 1); // Fix paths without slash at the end - if (value[value.length() - 1] != '\\' && value[value.length() - 1] != '/') + if (!value.empty() && value[value.length() - 1] != '\\' && value[value.length() - 1] != '/') { value.append("/"); } diff --git a/code/hud/hudartillery.cpp b/code/hud/hudartillery.cpp index 3a5daac74d..e21fdd9e54 100755 --- a/code/hud/hudartillery.cpp +++ b/code/hud/hudartillery.cpp @@ -308,7 +308,7 @@ void ssm_create(object *target, vec3d *start, size_t ssm_index, ssm_firing_info ssm_info *si = &Ssm_info[ssm_index]; weapon_info *wip = &Weapon_info[si->weapon_info_index]; - if (wip->wi_flags & WIF_BEAM) { + if (wip->wi_flags[Weapon::Info_Flags::Beam]) { ssm.sinfo.duration = ((si->warp_time - ((wip->b_info.beam_warmup / 1000.0f) + wip->b_info.beam_life + (wip->b_info.beam_warmdown / 1000.0f))) / 2.0f) / si->warp_time; } else { ssm.sinfo.duration = 0.5f; @@ -371,7 +371,7 @@ void ssm_process() if ((1.0f - fireball_lifeleft_percent(&Objects[moveup->fireballs[idx]])) >= moveup->sinfo.duration) { weapon_info *wip = &Weapon_info[si->weapon_info_index]; // are we a beam? -MageKing17 - if (wip->wi_flags & WIF_BEAM) { + if (wip->wi_flags[Weapon::Info_Flags::Beam]) { beam_fire_info fire_info; memset(&fire_info, 0, sizeof(beam_fire_info)); diff --git a/code/hud/hudlock.cpp b/code/hud/hudlock.cpp index 1f3e274fee..3b5f678023 100644 --- a/code/hud/hudlock.cpp +++ b/code/hud/hudlock.cpp @@ -322,7 +322,7 @@ int hud_lock_world_pos_in_range(vec3d *target_world_pos, vec3d *vec_to_target) dist_to_target = vm_vec_mag(vec_to_target); //local ssms are always in range :) - if (wip->wi_flags2 & WIF2_LOCAL_SSM) + if (wip->wi_flags[Weapon::Info_Flags::Local_ssm]) weapon_range=wip->lssm_lock_range; else // calculate the range of the weapon, and only display the lead target indicator when @@ -532,7 +532,7 @@ void hud_do_lock_indicator(float frametime) vec3d dir_to_target; vm_vec_normalized_dir(&dir_to_target, &tobjp->pos, &Player_obj->pos); - if ( !(wip->wi_flags & WIF_LOCKED_HOMING) ) { + if ( !(wip->is_locked_homing()) ) { hud_lock_reset(); return; } @@ -544,7 +544,7 @@ void hud_do_lock_indicator(float frametime) } // Javelins must lock on engines if locking on a ship and those must be in sight - if (wip->wi_flags & WIF_HOMING_JAVELIN && + if (wip->wi_flags[Weapon::Info_Flags::Homing_javelin] && tobjp->type == OBJ_SHIP && Player->locking_subsys != NULL) { vec3d subobj_pos; @@ -558,7 +558,7 @@ void hud_do_lock_indicator(float frametime) } } - if (wip->wi_flags & WIF_HOMING_JAVELIN && + if (wip->wi_flags[Weapon::Info_Flags::Homing_javelin] && tobjp->type == OBJ_SHIP && Player->locking_subsys == NULL) { Player->locking_subsys = @@ -989,7 +989,7 @@ void hud_lock_update_lock_pos(object *target_objp) ship_weapon *swp = &Player_ship->weapons; weapon_info *wip = &Weapon_info[swp->secondary_bank_weapons[swp->current_secondary_bank]]; - if ( Player_ai->targeted_subsys && !(wip->wi_flags & WIF_HOMING_JAVELIN) ) { + if ( Player_ai->targeted_subsys && !(wip->wi_flags[Weapon::Info_Flags::Homing_javelin]) ) { get_subsystem_world_pos(target_objp, Player_ai->targeted_subsys, &lock_world_pos); return; } @@ -1022,7 +1022,7 @@ void hud_lock_get_new_lock_pos(object *target_objp) // if a large ship, lock to pos closest to center and within range if ( (target_shipp) && (Ship_info[target_shipp->ship_info_index].is_big_or_huge()) && - !(wip->wi_flags & WIF_HOMING_JAVELIN) ) { + !(wip->wi_flags[Weapon::Info_Flags::Homing_javelin]) ) { // check all the subsystems and the center of the ship // assume best lock pos is the center of the ship @@ -1060,7 +1060,7 @@ void hud_lock_get_new_lock_pos(object *target_objp) } ss = GET_NEXT( ss ); } - } else if ( (target_shipp) && (wip->wi_flags & WIF_HOMING_JAVELIN)) { + } else if ( (target_shipp) && (wip->wi_flags[Weapon::Info_Flags::Homing_javelin])) { Player->locking_subsys = ship_get_closest_subsys_in_sight(target_shipp, SUBSYSTEM_ENGINE, &Player_obj->pos); if (Player->locking_subsys != NULL) { get_subsystem_world_pos(target_objp, Player->locking_subsys, &lock_world_pos); @@ -1099,12 +1099,12 @@ void hud_lock_determine_lock_point(vec3d *lock_world_pos_out) wip = &Weapon_info[swp->secondary_bank_weapons[swp->current_secondary_bank]]; // If subsystem is targeted, we must try to lock on that - if ( Player_ai->targeted_subsys && !(wip->wi_flags & WIF_HOMING_JAVELIN) ) { + if ( Player_ai->targeted_subsys && !(wip->wi_flags[Weapon::Info_Flags::Homing_javelin]) ) { hud_lock_update_lock_pos(target_objp); Player->locking_on_center=0; Player->locking_subsys=Player_ai->targeted_subsys; Player->locking_subsys_parent=Player_ai->target_objnum; - } else if ( (wip->wi_flags & WIF_HOMING_JAVELIN) && (target_objp->type == OBJ_SHIP)) { + } else if ( (wip->wi_flags[Weapon::Info_Flags::Homing_javelin]) && (target_objp->type == OBJ_SHIP)) { if (!Player->locking_subsys || Player->locking_subsys->system_info->type != SUBSYSTEM_ENGINE) { Player->locking_subsys = ship_get_closest_subsys_in_sight(&Ships[target_objp->instance], SUBSYSTEM_ENGINE, &Player_obj->pos); diff --git a/code/hud/hudreticle.cpp b/code/hud/hudreticle.cpp index c91ce95b6d..19505ebc1e 100644 --- a/code/hud/hudreticle.cpp +++ b/code/hud/hudreticle.cpp @@ -318,7 +318,7 @@ void HudGaugeReticle::getFirepointStatus() { if ( !( (j >= (shipp->last_fired_point[i]+1) % num_slots) && (j <= (shipp->last_fired_point[i]+swp->primary_bank_slot_count[i]) % num_slots) ) ) { fpactive--; } - } else if (Weapon_info[swp->primary_bank_weapons[i]].wi_flags2 & WIF2_CYCLE) { + } else if (Weapon_info[swp->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Cycle]) { // If this firepoint is not the next one to be fired, dim it one step if (j != (shipp->last_fired_point[i]+1) % num_slots) { fpactive--; diff --git a/code/hud/hudsquadmsg.cpp b/code/hud/hudsquadmsg.cpp index b3b83035b2..51de01b10b 100644 --- a/code/hud/hudsquadmsg.cpp +++ b/code/hud/hudsquadmsg.cpp @@ -338,7 +338,7 @@ bool hud_squadmsg_ship_valid(ship *shipp, object *objp) objp = &Objects[shipp->objnum]; // ships must be able to receive a message - if ( Ship_info[shipp->ship_info_index].class_type < 0 || !(Ship_types[Ship_info[shipp->ship_info_index].class_type].ai_bools & STI_AI_ACCEPT_PLAYER_ORDERS) ) + if ( Ship_info[shipp->ship_info_index].class_type < 0 || !(Ship_types[Ship_info[shipp->ship_info_index].class_type].flags[Ship::Type_Info_Flags::AI_accept_player_orders]) ) return false; // be sure ship is on correct team @@ -426,7 +426,7 @@ int hud_squadmsg_wing_valid(wing *wingp) // a couple of special cases to account for before adding to count (or to menu). Don't count // wings that are leaving or left. - if ( wingp->flags & (WF_WING_GONE|WF_WING_DEPARTING) ) + if ( wingp->flags[Ship::Wing_Flags::Gone, Ship::Wing_Flags::Departing] ) return 0; // Goober5000 - instead of checking wing leader, let's check all ships in wing; @@ -850,7 +850,7 @@ int hud_squadmsg_is_target_order_valid(int order, int find_order, ai_info *aip ) } if ( (Comm_orders[order].item == ATTACK_TARGET_ITEM ) - && ((Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags & WIF_BOMB) || (Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags3 & WIF3_FIGHTER_INTERCEPTABLE)) + && ((Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Bomb]) || (Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Fighter_Interceptable])) && (Weapons[objp->instance].team != ordering_shipp->team) ) return 1; @@ -942,10 +942,10 @@ void hud_squadmsg_send_to_all_fighters( int command, int player_num ) for ( i = 0; i < Num_wings; i++ ) { int shipnum; - if ( (Wings[i].flags & WF_WING_GONE) || (Wings[i].current_count == 0) ) + if ( (Wings[i].flags[Ship::Wing_Flags::Gone]) || (Wings[i].current_count == 0) ) continue; - if ( Wings[i].flags & WF_WING_DEPARTING ) + if ( Wings[i].flags[Ship::Wing_Flags::Departing] ) continue; // get the first ship on the wing list and look at its team and then its type @@ -1500,7 +1500,7 @@ int hud_squadmsg_send_wing_command( int wingnum, int command, int send_message, ai_mode = AI_GOAL_WARP; ai_submode = -1; message = MESSAGE_WARP_OUT; - Wings[wingnum].flags |= WF_DEPARTURE_ORDERED; + Wings[wingnum].flags.set(Ship::Wing_Flags::Departure_ordered); break; case REARM_REPAIR_ME_ITEM: @@ -1817,8 +1817,8 @@ void hud_squadmsg_call_reinforcement(int reinforcement_num, int player_num) if ( !stricmp(rp->name, Wings[i].name) ) { // found a wingname. Call the parse function to create all the ships in this wing // we must set the arrival cue of the wing to true, otherwise, this won't work!! - Wings[i].flags &= ~WF_REINFORCEMENT; - Wings[i].flags |= WF_RESET_REINFORCEMENT; + Wings[i].flags.remove(Ship::Wing_Flags::Reinforcement); + Wings[i].flags.set(Ship::Wing_Flags::Reset_reinforcement); // set up the arrival delay. If it is 0, then make is some random number of seconds delay = rp->arrival_delay; diff --git a/code/hud/hudtarget.cpp b/code/hud/hudtarget.cpp index 5956603603..a0f992c5d0 100644 --- a/code/hud/hudtarget.cpp +++ b/code/hud/hudtarget.cpp @@ -1021,7 +1021,7 @@ void hud_init_ballistic_index() ballistic_hud_index = 0; for (i = 0; i < Player_ship->weapons.num_primary_banks; i++) { - if (Weapon_info[Player_ship->weapons.primary_bank_weapons[i]].wi_flags2 & WIF2_BALLISTIC) + if (Weapon_info[Player_ship->weapons.primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Ballistic]) { ballistic_hud_index = 1; break; @@ -1179,8 +1179,8 @@ void hud_target_common(int team_mask, int next_flag) continue; if (A->type == OBJ_WEAPON) { - if ( !(Weapon_info[Weapons[A->instance].weapon_info_index].wi_flags2 & WIF2_CAN_BE_TARGETED) ) - if ( !(Weapon_info[Weapons[A->instance].weapon_info_index].wi_flags & WIF_BOMB) ) + if ( !(Weapon_info[Weapons[A->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Can_be_targeted]) ) + if ( !(Weapon_info[Weapons[A->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Bomb]) ) continue; if (Weapons[A->instance].lssm_stage == 3) @@ -1470,8 +1470,8 @@ void hud_target_missile(object *source_obj, int next_flag) wip = &Weapon_info[wp->weapon_info_index]; // only allow targeting of bombs - if ( !(wip->wi_flags2 & WIF2_CAN_BE_TARGETED) ) { - if ( !(wip->wi_flags & WIF_BOMB) ) { + if ( !(wip->wi_flags[Weapon::Info_Flags::Can_be_targeted]) ) { + if ( !(wip->wi_flags[Weapon::Info_Flags::Bomb]) ) { continue; } } @@ -1566,7 +1566,7 @@ int hud_target_ship_can_be_scanned(ship *shipp) return 1; // ignore ships that don't carry cargo - if ((sip->class_type < 0) || !(Ship_types[sip->class_type].ship_bools & STI_SHIP_SCANNABLE)) + if ((sip->class_type < 0) || !(Ship_types[sip->class_type].flags[Ship::Type_Info_Flags::Scannable])) return 0; return 1; @@ -1726,7 +1726,7 @@ int turret_compare_func(const void *e1, const void *e2) } } -extern bool turret_weapon_has_flags(ship_weapon *swp, int flags); +extern bool turret_weapon_has_flags(ship_weapon *swp, Weapon::Info_Flags flags); extern bool turret_weapon_has_subtype(ship_weapon *swp, int subtype); // target the next/prev live turret on the current target // auto_advance from hud_update_closest_turret @@ -1809,9 +1809,9 @@ void hud_target_live_turret(int next_flag, int auto_advance, int only_player_tar } // set weapon_type to allow sort of ent on type - if (turret_weapon_has_flags(&A->weapons, WIF_BEAM)) { + if (turret_weapon_has_flags(&A->weapons, Weapon::Info_Flags::Beam)) { ent[num_live_turrets].type = TYPE_FACING_BEAM; - } else if (turret_weapon_has_flags(&A->weapons, WIF_FLAK)) { + } else if (turret_weapon_has_flags(&A->weapons, Weapon::Info_Flags::Flak)) { ent[num_live_turrets].type = TYPE_FACING_FLAK; } else { if (turret_weapon_has_subtype(&A->weapons, WP_MISSILE)) { @@ -1941,7 +1941,7 @@ void hud_target_closest_locked_missile(object *locked_obj) continue; } - if ( !(wip->wi_flags & WIF_HOMING ) ){ + if ( !(wip->is_homing() ) ){ continue; } @@ -2107,7 +2107,7 @@ bool evaluate_ship_as_closest_target(esct *esct_p) } // bail if harmless - if ( Ship_info[esct_p->shipp->ship_info_index].class_type > -1 && !(Ship_types[Ship_info[esct_p->shipp->ship_info_index].class_type].hud_bools & STI_HUD_TARGET_AS_THREAT)) { + if ( Ship_info[esct_p->shipp->ship_info_index].class_type > -1 && !(Ship_types[Ship_info[esct_p->shipp->ship_info_index].class_type].flags[Ship::Type_Info_Flags::Target_as_threat])) { return false; } @@ -2146,9 +2146,9 @@ bool evaluate_ship_as_closest_target(esct *esct_p) /* // GET TURRET TYPE, FAVOR BEAM, FLAK, OTHER int turret_type = ss->system_info->turret_weapon_type; - if (Weapon_info[turret_type].wi_flags & WIF_BEAM) { + if (Weapon_info[turret_type].wi_flags[Weapon::Info_Flags::Beam]) { new_distance *= 0.3f; - } else if (Weapon_info[turret_type].wi_flags & WIF_FLAK) { + } else if (Weapon_info[turret_type].wi_flags[Weapon::Info_Flags::Flak]) { new_distance *= 0.6f; } */ @@ -2357,9 +2357,9 @@ void hud_update_closest_turret() // GET TURRET TYPE, FAVOR BEAM, FLAK, OTHER int turret_type = ss->system_info->turret_weapon_type; - if (Weapon_info[turret_type].wi_flags & WIF_BEAM) { + if (Weapon_info[turret_type].wi_flags[Weapon::Info_Flags::Beam]) { new_distance *= 0.3f; - } else if (Weapon_info[turret_type].wi_flags & WIF_FLAK) { + } else if (Weapon_info[turret_type].wi_flags[Weapon::Info_Flags::Flak]) { new_distance *= 0.6f; } @@ -2512,8 +2512,8 @@ void hud_target_in_reticle_new() } if ( A->type == OBJ_WEAPON ) { - if ( !(Weapon_info[Weapons[A->instance].weapon_info_index].wi_flags2 & WIF2_CAN_BE_TARGETED) ) { - if ( !(Weapon_info[Weapons[A->instance].weapon_info_index].wi_flags & WIF_BOMB) ){ + if ( !(Weapon_info[Weapons[A->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Can_be_targeted]) ) { + if ( !(Weapon_info[Weapons[A->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Bomb]) ){ continue; } } @@ -2620,8 +2620,8 @@ void hud_target_in_reticle_old() } if ( A->type == OBJ_WEAPON ) { - if ( !(Weapon_info[Weapons[A->instance].weapon_info_index].wi_flags2 & WIF2_CAN_BE_TARGETED) ){ - if ( !(Weapon_info[Weapons[A->instance].weapon_info_index].wi_flags & WIF_BOMB) ){ + if ( !(Weapon_info[Weapons[A->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Can_be_targeted]) ){ + if ( !(Weapon_info[Weapons[A->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Bomb]) ){ continue; } } @@ -3133,7 +3133,7 @@ void hud_process_homing_missiles() if (dist < nearest_dist) { nearest_dist = dist; - if ( Weapon_info[wp->weapon_info_index].wi_flags & WIF_LOCKED_HOMING ) { + if ( Weapon_info[wp->weapon_info_index].is_locked_homing() ) { closest_is_aspect=1; } else { closest_is_aspect=0; @@ -3193,7 +3193,7 @@ void HudGaugeMissileTriangles::render(float frametime) wp = &Weapons[A->instance]; if (wp->homing_object == Player_obj) { - renderTriangle(&A->pos, Weapon_info[wp->weapon_info_index].wi_flags & WIF_LOCKED_HOMING, 1, 1); + renderTriangle(&A->pos, Weapon_info[wp->weapon_info_index].is_locked_homing(), 1, 1); } } @@ -3252,7 +3252,7 @@ void hud_process_remote_detonate_missile() mobjp = &Objects[mo->objnum]; if ((Player_obj != NULL) && (mobjp->parent_sig == Player_obj->parent_sig)) { - if (Weapon_info[Weapons[mobjp->instance].weapon_info_index].wi_flags & WIF_REMOTE) { + if (Weapon_info[Weapons[mobjp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Remote]) { // get box center point g3_rotate_vertex(&target_point,&mobjp->pos); @@ -3604,7 +3604,7 @@ void hud_show_hostile_triangle() } // always ignore cargo containers and navbuoys - if ( Ship_info[sp->ship_info_index].class_type > -1 && !(Ship_types[Ship_info[sp->ship_info_index].class_type].hud_bools & STI_HUD_SHOW_ATTACK_DIRECTION) ) { + if ( Ship_info[sp->ship_info_index].class_type > -1 && !(Ship_types[Ship_info[sp->ship_info_index].class_type].flags[Ship::Type_Info_Flags::Show_attack_direction]) ) { continue; } @@ -3767,7 +3767,7 @@ int hud_get_best_primary_bank(float *range) weapon_range = MIN((wip->max_speed * wip->lifetime), wip->weapon_range); // don't consider this primary if it's a ballistic that's out of ammo - Goober5000 - if ( wip->wi_flags2 & WIF2_BALLISTIC ) + if ( wip->wi_flags[Weapon::Info_Flags::Ballistic] ) { if ( swp->primary_bank_ammo[bank_to_fire] <= 0) { @@ -3967,8 +3967,8 @@ void HudGaugeLeadIndicator::renderLeadCurrentTarget() // only allow bombs to have lead indicator displayed if ( targetp->type == OBJ_WEAPON ) { - if ( !(Weapon_info[Weapons[targetp->instance].weapon_info_index].wi_flags2 & WIF2_CAN_BE_TARGETED) ) { - if ( !(Weapon_info[Weapons[targetp->instance].weapon_info_index].wi_flags & WIF_BOMB) ) { + if ( !(Weapon_info[Weapons[targetp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Can_be_targeted]) ) { + if ( !(Weapon_info[Weapons[targetp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Bomb]) ) { return; } } @@ -4035,7 +4035,7 @@ void HudGaugeLeadIndicator::renderLeadCurrentTarget() { int bank = swp->current_secondary_bank; tmp = &Weapon_info[swp->secondary_bank_weapons[bank]]; - if ( !(tmp->wi_flags & WIF_HOMING) && !(tmp->wi_flags & WIF_LOCKED_HOMING && Player->target_in_lock_cone) ) { + if ( !(tmp->is_homing()) && !(tmp->is_locked_homing() && Player->target_in_lock_cone) ) { //The secondary lead indicator is handled farther below if it is a non-locking type srange = -1.0f; } @@ -4056,7 +4056,7 @@ void HudGaugeLeadIndicator::renderLeadCurrentTarget() wip=&Weapon_info[swp->secondary_bank_weapons[bank]]; //get out of here if the secondary weapon is a homer or if its out of range - if ( wip->wi_flags & WIF_HOMING ) + if ( wip->is_homing() ) return; double max_dist = MIN((wip->lifetime * wip->max_speed), wip->weapon_range); @@ -4093,8 +4093,8 @@ void HudGaugeLeadIndicator::renderLeadQuick(vec3d *target_world_pos, object *tar // only allow bombs to have lead indicator displayed if ( targetp->type == OBJ_WEAPON ) { - if ( !(Weapon_info[Weapons[targetp->instance].weapon_info_index].wi_flags2 & WIF2_CAN_BE_TARGETED) ) { - if ( !(Weapon_info[Weapons[targetp->instance].weapon_info_index].wi_flags & WIF_BOMB) ) { + if ( !(Weapon_info[Weapons[targetp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Can_be_targeted]) ) { + if ( !(Weapon_info[Weapons[targetp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Bomb]) ) { return; } } @@ -4254,7 +4254,7 @@ void HudGaugeLeadSight::render(float frametime) // only allow bombs to have lead indicator displayed if ( targetp->type == OBJ_WEAPON ) { - if ( !(Weapon_info[Weapons[targetp->instance].weapon_info_index].wi_flags & WIF_BOMB) ) { + if ( !(Weapon_info[Weapons[targetp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Bomb]) ) { return; } } @@ -4329,7 +4329,7 @@ void HudGaugeLeadSight::render(float frametime) wip=&Weapon_info[swp->secondary_bank_weapons[bank]]; //get out of here if the secondary weapon is a homer or if its out of range - if ( wip->wi_flags & WIF_HOMING ) { + if ( wip->is_homing() ) { return; } @@ -5553,7 +5553,7 @@ void HudGaugeWeaponEnergy::render(float frametime) { for(x = 0; x < Player_ship->weapons.num_primary_banks; x++) { - if(Weapon_info[Player_ship->weapons.primary_bank_weapons[x]].wi_flags2 & WIF2_BALLISTIC) + if(Weapon_info[Player_ship->weapons.primary_bank_weapons[x]].wi_flags[Weapon::Info_Flags::Ballistic]) { use_new_gauge = true; break; @@ -5603,7 +5603,7 @@ void HudGaugeWeaponEnergy::render(float frametime) for(x = 0; x < Player_ship->weapons.num_primary_banks; x++) { //Skip all pure-energy weapons - if(!(Weapon_info[Player_ship->weapons.primary_bank_weapons[x]].wi_flags2 & WIF2_BALLISTIC)) + if(!(Weapon_info[Player_ship->weapons.primary_bank_weapons[x]].wi_flags[Weapon::Info_Flags::Ballistic])) continue; //Draw the weapon bright or normal depending if it's active or not. @@ -5666,7 +5666,7 @@ void HudGaugeWeaponEnergy::render(float frametime) for ( i = 0; i < sw->num_primary_banks; i++ ) { // skip all pure-energy weapons - if( ! ( Weapon_info[sw->primary_bank_weapons[i]].wi_flags2 & WIF2_BALLISTIC ) ) { + if( ! ( Weapon_info[sw->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Ballistic] ) ) { continue; } @@ -6049,7 +6049,7 @@ void HudGaugeWeapons::render(float frametime) } // indicate if this is linked or currently armed - if ( ((sw->current_primary_bank == i) && !(Player_ship->flags[Ship::Ship_Flags::Primary_linked])) || ((Player_ship->flags[Ship::Ship_Flags::Primary_linked]) && !(Weapon_info[sw->primary_bank_weapons[i]].wi_flags3 & WIF3_NOLINK))) { + if ( ((sw->current_primary_bank == i) && !(Player_ship->flags[Ship::Ship_Flags::Primary_linked])) || ((Player_ship->flags[Ship::Ship_Flags::Primary_linked]) && !(Weapon_info[sw->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Nolink]))) { renderPrintf(position[0] + Weapon_plink_offset_x, name_y, EG_NULL, "%c", Weapon_link_icon); } @@ -6061,7 +6061,7 @@ void HudGaugeWeapons::render(float frametime) } // if this is a ballistic primary with ammo, render the ammo count - if (Weapon_info[sw->primary_bank_weapons[i]].wi_flags2 & WIF2_BALLISTIC) { + if (Weapon_info[sw->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Ballistic]) { // print out the ammo right justified sprintf(ammo_str, "%d", sw->primary_bank_ammo[i]); @@ -6929,7 +6929,7 @@ void HudGaugePrimaryWeapons::render(float frametime) } // if this is a ballistic primary with ammo, render the ammo count - if (Weapon_info[sw->primary_bank_weapons[i]].wi_flags2 & WIF2_BALLISTIC) { + if (Weapon_info[sw->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Ballistic]) { // print out the ammo right justified sprintf(ammo_str, "%d", sw->primary_bank_ammo[i]); @@ -7206,7 +7206,7 @@ void HudGaugeHardpoints::render(float frametime) bank = &(model_get(sip->model_num))->missile_banks[i]; - if (Weapon_info[swp->secondary_bank_weapons[i]].wi_flags2 & WIF2_EXTERNAL_WEAPON_LNCH) { + if (Weapon_info[swp->secondary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::External_weapon_lnch]) { for(k = 0; k < bank->num_slots; k++) { model_render_params weapon_render_info; diff --git a/code/hud/hudtargetbox.cpp b/code/hud/hudtargetbox.cpp index ec748a9c22..ed84958521 100644 --- a/code/hud/hudtargetbox.cpp +++ b/code/hud/hudtargetbox.cpp @@ -814,7 +814,7 @@ void HudGaugeTargetBox::renderTargetWeapon(object *target_objp) return; is_homing = FALSE; - if ( target_wip->wi_flags & WIF_HOMING && wp->homing_object != &obj_used_list ) + if ( target_wip->is_homing() && wp->homing_object != &obj_used_list ) is_homing = TRUE; is_player_missile = FALSE; @@ -1541,8 +1541,7 @@ void HudGaugeExtraTargetData::endFlashDock() } //from aicode.cpp. Less include...problems...this way. -extern int turret_weapon_aggregate_flags(ship_weapon *swp); -extern int turret_weapon_aggregate_flags2(ship_weapon *swp); +extern flagset turret_weapon_aggregate_flags(ship_weapon *swp); extern bool turret_weapon_has_subtype(ship_weapon *swp, int subtype); void get_turret_subsys_name(ship_weapon *swp, char *outstr) { @@ -1550,25 +1549,24 @@ void get_turret_subsys_name(ship_weapon *swp, char *outstr) //WMC - find the first weapon, if there is one if (swp->num_primary_banks || swp->num_secondary_banks) { - int flags = turret_weapon_aggregate_flags(swp); - int flags2 = turret_weapon_aggregate_flags2(swp); + auto flags = turret_weapon_aggregate_flags(swp); // check if beam or flak using weapon flags - if (flags & WIF_BEAM) { + if (flags[Weapon::Info_Flags::Beam]) { sprintf(outstr, "%s", XSTR("Beam turret", 1567)); - } else if (flags & WIF_FLAK) { + } else if (flags[Weapon::Info_Flags::Flak]) { sprintf(outstr, "%s", XSTR("Flak turret", 1566)); } else { if (turret_weapon_has_subtype(swp, WP_MISSILE)) { sprintf(outstr, "%s", XSTR("Missile lnchr", 1569)); } else if (turret_weapon_has_subtype(swp, WP_LASER)) { // ballistic too! - Goober5000 - if (flags2 & WIF2_BALLISTIC) + if (flags[Weapon::Info_Flags::Ballistic]) { sprintf(outstr, "%s", XSTR("Turret", 1487)); } // the TVWP has some primaries flagged as bombs - else if (flags & WIF_BOMB) + else if (flags[Weapon::Info_Flags::Bomb]) { sprintf(outstr, "%s", XSTR("Missile lnchr", 1569)); } @@ -1578,7 +1576,7 @@ void get_turret_subsys_name(ship_weapon *swp, char *outstr) } } else { // Mantis #2226: find out if there are any weapons here at all - if (flags == 0 && flags2 == 0) { + if (flags.none_set()) { sprintf(outstr, "%s", NOX("Unused")); } else { // Illegal subtype diff --git a/code/io/keycontrol.cpp b/code/io/keycontrol.cpp index f7ec9f85a0..0a4d3d8fb3 100644 --- a/code/io/keycontrol.cpp +++ b/code/io/keycontrol.cpp @@ -593,7 +593,7 @@ void debug_max_primary_weapons(object *objp) // Goober5000 for ( index = 0; index < MAX_SHIP_PRIMARY_BANKS; index++ ) { wip = &Weapon_info[swp->primary_bank_weapons[index]]; - if (wip->wi_flags2 & WIF2_BALLISTIC) + if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) { float capacity, size; capacity = (float) sip->primary_bank_ammo_capacity[index]; diff --git a/code/lab/lab.cpp b/code/lab/lab.cpp index 91b7c5aee0..a228bab661 100644 --- a/code/lab/lab.cpp +++ b/code/lab/lab.cpp @@ -944,7 +944,7 @@ void labviewer_render_model(float frametime) continue; if (Lab_weaponmodel_num[l] >= 0) { bank = &(model_get(Lab_model_num))->missile_banks[j]; - if (Weapon_info[sip->secondary_bank_weapons[j]].wi_flags2 & WIF2_EXTERNAL_WEAPON_LNCH) { + if (Weapon_info[sip->secondary_bank_weapons[j]].wi_flags[Weapon::Info_Flags::External_weapon_lnch]) { for(k = 0; k < bank->num_slots; k++) { render_info.set_flags(render_flags); model_render_immediate(&render_info, Lab_weaponmodel_num[l], &vmd_identity_matrix, &bank->pnt[k]); @@ -1014,7 +1014,7 @@ void labviewer_render_model(float frametime) continue; if (Lab_weaponmodel_num[l] >= 0) { bank = &(model_get(Lab_model_num))->missile_banks[j]; - if (Weapon_info[sip->secondary_bank_weapons[j]].wi_flags2 & WIF2_EXTERNAL_WEAPON_LNCH) { + if (Weapon_info[sip->secondary_bank_weapons[j]].wi_flags[Weapon::Info_Flags::External_weapon_lnch]) { for(k = 0; k < bank->num_slots; k++) { render_info.set_flags(render_flags); model_render_immediate(&render_info, Lab_weaponmodel_num[l], &vmd_identity_matrix, &bank->pnt[k]); @@ -2277,7 +2277,7 @@ void labviewer_change_weapon(Tree *caller) int weap_index = (int)(caller->GetSelectedItem()->GetData()); Assert( weap_index >= 0 ); - if ( !(Weapon_info[weap_index].wi_flags & WIF_BEAM) ) { + if ( !(Weapon_info[weap_index].wi_flags[Weapon::Info_Flags::Beam]) ) { switch (Weapon_info[weap_index].render_type) { case WRT_POF: labviewer_change_bitmap(); @@ -2359,7 +2359,7 @@ void labviewer_make_weap_window(Button* caller) continue; } - if (Weapon_info[i].wi_flags & WIF_BEAM) { + if (Weapon_info[i].wi_flags[Weapon::Info_Flags::Beam]) { stip = type_nodes[WP_BEAM]; } else { stip = type_nodes[Weapon_info[i].subtype]; diff --git a/code/menuui/techmenu.cpp b/code/menuui/techmenu.cpp index 85e1d2a293..bab16c0ad2 100644 --- a/code/menuui/techmenu.cpp +++ b/code/menuui/techmenu.cpp @@ -737,8 +737,9 @@ void techroom_anim_render(float frametime) void techroom_change_tab(int num) { - int multi = 0, wi_mask, wi_mask2, font_height, max_num_entries_viewable; - Ship::Info_Flags si_mask, si_mask2; + int multi = 0, font_height, max_num_entries_viewable; + flagset wi_mask; + flagset si_mask; //unload the current animation, we load another one for the new current entry if(Tab != SHIPS_DATA_TAB) @@ -761,8 +762,8 @@ void techroom_change_tab(int num) switch (Tab) { case SHIPS_DATA_TAB: - si_mask = multi ? Ship::Info_Flags::In_tech_database_m : Ship::Info_Flags::In_tech_database; - si_mask2 = multi ? Ship::Info_Flags::Default_in_tech_database_m : Ship::Info_Flags::Default_in_tech_database; + si_mask.set(multi ? Ship::Info_Flags::In_tech_database_m : Ship::Info_Flags::In_tech_database); + si_mask.set(multi ? Ship::Info_Flags::Default_in_tech_database_m : Ship::Info_Flags::Default_in_tech_database); // load ship info if necessary if ( Ships_loaded == 0 ) { @@ -777,7 +778,7 @@ void techroom_change_tab(int num) for (auto it = Ship_info.begin(); it != Ship_info.end(); ++it) { - if (Techroom_show_all || (it->flags[si_mask]) || (it->flags[si_mask2])) + if (Techroom_show_all || (it->flags & si_mask).any_set()) { // this ship should be displayed, fill out the entry struct Ship_list[Ship_list_size].bitmap = -1; @@ -830,12 +831,12 @@ void techroom_change_tab(int num) } Weapon_list_size = 0; - wi_mask = multi ? WIF_PLAYER_ALLOWED : WIF_IN_TECH_DATABASE; - wi_mask2 = WIF2_DEFAULT_IN_TECH_DATABASE; + wi_mask.set(multi ? Weapon::Info_Flags::Player_allowed : Weapon::Info_Flags::In_tech_database); + wi_mask.set(Weapon::Info_Flags::Default_in_tech_database); for (int i=0; iobjnum].instance; // filter out cargo containers, navbouys, etc, and non-ships - if ( Ship_info[Ships[shipnum].ship_info_index].class_type < 0 || !(Ship_types[Ship_info[Ships[shipnum].ship_info_index].class_type].hud_bools & STI_HUD_HOTKEY_ON_LIST )) + if ( Ship_info[Ships[shipnum].ship_info_index].class_type < 0 || !(Ship_types[Ship_info[Ships[shipnum].ship_info_index].class_type].flags[Ship::Type_Info_Flags::Hotkey_on_list] )) continue; // don't process ships invisible to sensors, dying or departing @@ -649,7 +649,7 @@ int hotkey_build_team_listing(int enemy_team_mask, int y, bool list_enemies) continue; z = hotkey_line_add_sorted(Wings[i].name, HOTKEY_LINE_WING, i, start); - if (Wings[i].flags & WF_EXPANDED) { + if (Wings[i].flags[Ship::Wing_Flags::Expanded]) { for (j=0; jship_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 } diff --git a/code/mission/missionparse.cpp b/code/mission/missionparse.cpp index be401a570f..4e942b2628 100644 --- a/code/mission/missionparse.cpp +++ b/code/mission/missionparse.cpp @@ -499,7 +499,7 @@ void parse_mission_info(mission *pm, bool basic = false) pm->flags.reset(); if (optional_string("+Flags:")){ - stuff_flagset>(&pm->flags); + stuff_flagset(&pm->flags); } // nebula mission stuff @@ -921,7 +921,7 @@ void parse_player_info2(mission *pm) if ( (list2[i] >= 0) && (list2[i] < MAX_WEAPON_TYPES) ) { // always allow the pool to be added in FRED, it is a verbal warning // to let the mission dev know about the problem - if ( (Weapon_info[list2[i]].wi_flags & WIF_PLAYER_ALLOWED) || Fred_running ) { + if ( (Weapon_info[list2[i]].wi_flags[Weapon::Info_Flags::Player_allowed]) || Fred_running ) { ptr->weaponry_pool[num_choices] = list2[i]; ptr->weaponry_count[num_choices] = list2[i+2]; @@ -2082,14 +2082,14 @@ int parse_create_object_sub(p_object *p_objp) // if ship is in a wing, and the wing's no_warp_effect flag is set, then set the equivalent // flag for the ship - if ((shipp->wingnum != -1) && (Wings[shipp->wingnum].flags & WF_NO_ARRIVAL_WARP)) + if ((shipp->wingnum != -1) && (Wings[shipp->wingnum].flags[Ship::Wing_Flags::No_arrival_warp])) shipp->flags.set(Ship::Ship_Flags::No_arrival_warp); - if ((shipp->wingnum != -1) && (Wings[shipp->wingnum].flags & WF_NO_DEPARTURE_WARP)) + if ((shipp->wingnum != -1) && (Wings[shipp->wingnum].flags[Ship::Wing_Flags::No_departure_warp])) shipp->flags.set(Ship::Ship_Flags::No_departure_warp); // ditto for Kazan - if ((shipp->wingnum != -1) && (Wings[shipp->wingnum].flags & WF_NAV_CARRY)) + if ((shipp->wingnum != -1) && (Wings[shipp->wingnum].flags[Ship::Wing_Flags::Nav_carry])) shipp->flags.set(Ship::Ship_Flags::Navpoint_carry); // if the wing index and wing pos are set for this parse object, set them for the ship. This @@ -2159,7 +2159,7 @@ int parse_create_object_sub(p_object *p_objp) { wp->primary_bank_ammo[j] = sssp->primary_ammo[j]; } - else if (wp->primary_bank_weapons[j] >= 0 && Weapon_info[wp->primary_bank_weapons[j]].wi_flags2 & WIF2_BALLISTIC) + else if (wp->primary_bank_weapons[j] >= 0 && Weapon_info[wp->primary_bank_weapons[j]].wi_flags[Weapon::Info_Flags::Ballistic]) { Assertion(Weapon_info[wp->primary_bank_weapons[j]].cargo_size > 0.0f, "Primary weapon cargo size <= 0. Ship (%s) Subsystem (%s) Bank (%i) Weapon (%s)", @@ -2253,7 +2253,7 @@ int parse_create_object_sub(p_object *p_objp) { if (Fred_running) { ptr->weapons.primary_bank_ammo[j] = sssp->primary_ammo[j]; - } else if (ptr->weapons.primary_bank_weapons[j] >= 0 && Weapon_info[ptr->weapons.primary_bank_weapons[j]].wi_flags2 & WIF2_BALLISTIC) { + } else if (ptr->weapons.primary_bank_weapons[j] >= 0 && Weapon_info[ptr->weapons.primary_bank_weapons[j]].wi_flags[Weapon::Info_Flags::Ballistic]) { Assertion(Weapon_info[ptr->weapons.primary_bank_weapons[j]].cargo_size > 0.0f, "Primary weapon cargo size <= 0. Ship (%s) Subsystem (%s) Bank (%i) Weapon (%s)", shipp->ship_name, sssp->name, j, Weapon_info[ptr->weapons.primary_bank_weapons[j]].name); @@ -2474,7 +2474,7 @@ void parse_bring_in_docked_wing(p_object *p_objp, int wingnum, int shipnum) ai_info *aip = &Ai_info[Ships[shipnum].ai_index]; aip->wing = wingnum; - if (wingp->flags & WF_NO_DYNAMIC) + if (wingp->flags[Ship::Wing_Flags::No_dynamic]) aip->ai_flags |= AIF_NO_DYNAMIC; // copy any goals from the wing to the newly created ship @@ -3966,7 +3966,7 @@ int parse_wing_create_ships( wing *wingp, int num_to_create, int force, int spec // set the wing variables appropriately. Good for directives. // set the gone flag - wingp->flags |= WF_WING_GONE; + wingp->flags.set(Ship::Wing_Flags::Gone); // mark the number of waves and number of ships destroyed equal to the last wave and the number // of ships yet to arrive @@ -4130,7 +4130,7 @@ int parse_wing_create_ships( wing *wingp, int num_to_create, int force, int spec Ai_info[Ships[Objects[objnum].instance].ai_index].wing = wingnum; - if (wingp->flags & WF_NO_DYNAMIC) + if (wingp->flags[Ship::Wing_Flags::No_dynamic]) aip->ai_flags |= AIF_NO_DYNAMIC; // update housekeeping variables @@ -4244,7 +4244,7 @@ int parse_wing_create_ships( wing *wingp, int num_to_create, int force, int spec mission_log_add_entry( LOG_WING_ARRIVED, wingp->name, NULL, wingp->current_wave ); ship_num = wingp->ship_index[0]; - if ( !(Ships[ship_num].flags[Ship::Ship_Flags::No_arrival_music]) && !(wingp->flags & WF_NO_ARRIVAL_MUSIC) ) { + if ( !(Ships[ship_num].flags[Ship::Ship_Flags::No_arrival_music]) && !(wingp->flags[Ship::Wing_Flags::No_arrival_music]) ) { if ( timestamp_elapsed(Allow_arrival_music_timestamp) ) { Allow_arrival_music_timestamp = timestamp(ARRIVAL_MUSIC_MIN_SEPARATION); event_music_arrival(Ships[ship_num].team); @@ -4288,7 +4288,7 @@ void parse_wing(mission *pm) { int wingnum, i, wing_goals, delay, saved_arrival_delay; char name[NAME_LENGTH], ship_names[MAX_SHIPS_PER_WING][NAME_LENGTH]; - char wing_flag_strings[MAX_WING_FLAGS][NAME_LENGTH]; + char wing_flag_strings[PARSEABLE_WING_FLAGS][NAME_LENGTH]; wing *wingp; Assert(pm != NULL); @@ -4306,7 +4306,7 @@ void parse_wing(mission *pm) wingp->total_destroyed = 0; wingp->total_departed = 0; // Goober5000 wingp->total_vanished = 0; // Goober5000 - wingp->flags = 0; + wingp->flags.reset(); // squad logo - Goober5000 if (optional_string("+Squad Logo:")) @@ -4462,26 +4462,26 @@ void parse_wing(mission *pm) if (optional_string("+Flags:")) { int count; - count = stuff_string_list( wing_flag_strings, MAX_WING_FLAGS ); - for (i = 0; i < count; i++ ) { - if ( !stricmp( wing_flag_strings[i], NOX("ignore-count")) ) - wingp->flags |= WF_IGNORE_COUNT; - else if ( !stricmp( wing_flag_strings[i], NOX("reinforcement")) ) - wingp->flags |= WF_REINFORCEMENT; - else if ( !stricmp( wing_flag_strings[i], NOX("no-arrival-music")) ) - wingp->flags |= WF_NO_ARRIVAL_MUSIC; - else if ( !stricmp( wing_flag_strings[i], NOX("no-arrival-message")) ) - wingp->flags |= WF_NO_ARRIVAL_MESSAGE; - else if ( !stricmp( wing_flag_strings[i], NOX("no-arrival-warp")) ) - wingp->flags |= WF_NO_ARRIVAL_WARP; - else if ( !stricmp( wing_flag_strings[i], NOX("no-departure-warp")) ) - wingp->flags |= WF_NO_DEPARTURE_WARP; - else if ( !stricmp( wing_flag_strings[i], NOX("no-dynamic")) ) - wingp->flags |= WF_NO_DYNAMIC; - else if ( !stricmp( wing_flag_strings[i], NOX("nav-carry-status")) ) - wingp->flags |= WF_NAV_CARRY; - else - Warning(LOCATION, "unknown wing flag\n%s\n\nSkipping.", wing_flag_strings[i]); + count = stuff_string_list( wing_flag_strings, PARSEABLE_WING_FLAGS); + for (i = 0; i < count; i++) { + if (!stricmp(wing_flag_strings[i], NOX("ignore-count"))) + wingp->flags.set(Ship::Wing_Flags::Ignore_count); + else if (!stricmp(wing_flag_strings[i], NOX("reinforcement"))) + wingp->flags.set(Ship::Wing_Flags::Reinforcement); + else if (!stricmp(wing_flag_strings[i], NOX("no-arrival-music"))) + wingp->flags.set(Ship::Wing_Flags::No_arrival_music); + else if (!stricmp(wing_flag_strings[i], NOX("no-arrival-message"))) + wingp->flags.set(Ship::Wing_Flags::No_arrival_message); + else if (!stricmp(wing_flag_strings[i], NOX("no-arrival-warp"))) + wingp->flags.set(Ship::Wing_Flags::No_arrival_warp); + else if (!stricmp(wing_flag_strings[i], NOX("no-departure-warp"))) + wingp->flags.set(Ship::Wing_Flags::No_departure_warp); + else if (!stricmp(wing_flag_strings[i], NOX("no-dynamic"))) + wingp->flags.set(Ship::Wing_Flags::No_dynamic); + else if (!stricmp(wing_flag_strings[i], NOX("nav-carry-status"))) + wingp->flags.set(Ship::Wing_Flags::Nav_carry); + else + Warning(LOCATION, "unknown wing flag\n%s\n\nSkipping.", wing_flag_strings[i]); } } @@ -4758,7 +4758,7 @@ void post_process_ships_wings() wing *wingp = &Wings[i]; // create the wing if is isn't a reinforcement. - if (!(wingp->flags & WF_REINFORCEMENT)) + if (!(wingp->flags[Ship::Wing_Flags::Reinforcement])) parse_wing_create_ships(wingp, wingp->wave_count); } } @@ -5779,7 +5779,7 @@ void post_process_mission() continue; if ( Ships[shipnum].flags[Ship::Ship_Flags::Ignore_count] ) continue; - if ( (Ships[shipnum].wingnum != -1) && (Wings[Ships[shipnum].wingnum].flags & WF_IGNORE_COUNT) ) + if ( (Ships[shipnum].wingnum != -1) && (Wings[Ships[shipnum].wingnum].flags[Ship::Wing_Flags::Ignore_count]) ) continue; num = 1; @@ -5795,7 +5795,7 @@ void post_process_mission() // go through similar motions as above if ( p_objp->flags[Mission::Parse_Object_Flags::SF_Ignore_count] ) continue; - if ( (p_objp->wingnum != -1) && (Wings[p_objp->wingnum].flags & WF_IGNORE_COUNT) ) + if ( (p_objp->wingnum != -1) && (Wings[p_objp->wingnum].flags[Ship::Wing_Flags::Ignore_count]) ) continue; if ( p_objp->wingnum == -1 ) @@ -6858,11 +6858,11 @@ void mission_eval_arrivals() wingp = &Wings[i]; // should we process this wing anymore - if (wingp->flags & WF_WING_GONE) + if (wingp->flags[Ship::Wing_Flags::Gone]) continue; // if we have a reinforcement wing, then don't try to create new ships automatically. - if (wingp->flags & WF_REINFORCEMENT) + if (wingp->flags[Ship::Wing_Flags::Reinforcement]) { // check to see in the wings arrival cue is true, and if so, then mark the reinforcement // as available @@ -6874,7 +6874,7 @@ void mission_eval_arrivals() } // don't do evaluations for departing wings - if (wingp->flags & WF_WING_DEPARTING) + if (wingp->flags[Ship::Wing_Flags::Departing]) continue; // must check to see if we are at the last wave. Code above to determine when a wing is gone only @@ -6896,15 +6896,15 @@ void mission_eval_arrivals() // If this wing was a reinforcement wing, then we need to reset the reinforcement flag for the wing // so the user can call in another set if need be. - if (wingp->flags & WF_RESET_REINFORCEMENT) + if (wingp->flags[Ship::Wing_Flags::Reset_reinforcement]) { - wingp->flags &= ~WF_RESET_REINFORCEMENT; - wingp->flags |= WF_REINFORCEMENT; + wingp->flags.remove(Ship::Wing_Flags::Reset_reinforcement); + wingp->flags.set(Ship::Wing_Flags::Reinforcement); } // probably send a message to the player when this wing arrives. // if no message, nothing more to do for this wing - if (wingp->flags & WF_NO_ARRIVAL_MESSAGE) + if (wingp->flags[Ship::Wing_Flags::No_arrival_message]) continue; // multiplayer team vs. team @@ -7009,7 +7009,7 @@ int mission_do_departure(object *objp, bool goal_is_to_warp) if (goal_is_to_warp) { // aha, but not if we were ORDERED to depart, because the comms menu ALSO uses the goal code, and yet the comms menu means any departure method! - if ((shipp->flags[Ship::Ship_Flags::Departure_ordered]) || ((shipp->wingnum >= 0) && (Wings[shipp->wingnum].flags & WF_DEPARTURE_ORDERED))) + if ((shipp->flags[Ship::Ship_Flags::Departure_ordered]) || ((shipp->wingnum >= 0) && (Wings[shipp->wingnum].flags[Ship::Wing_Flags::Departure_ordered]))) { mprintf(("Looks like we were ordered to depart; initiating the standard departure logic\n")); } @@ -7165,7 +7165,7 @@ void mission_eval_departures() wingp = &Wings[i]; // should we process this wing anymore - if ( wingp->flags & WF_WING_DEPARTING ) + if ( wingp->flags[Ship::Wing_Flags::Departing] ) continue; // evaluate the sexpression. If true, mark all the ships in this wing as departing and increment @@ -7182,7 +7182,7 @@ void mission_eval_departures() if ( !timestamp_elapsed(wingp->departure_delay) ) continue; - wingp->flags |= WF_WING_DEPARTING; + wingp->flags.set(Ship::Wing_Flags::Departing); for ( j = 0; j < wingp->current_count; j++ ) { ship *shipp; diff --git a/code/missionui/missionbrief.cpp b/code/missionui/missionbrief.cpp index 22c57b4696..d2500b96b8 100644 --- a/code/missionui/missionbrief.cpp +++ b/code/missionui/missionbrief.cpp @@ -1276,7 +1276,7 @@ int brief_setup_closeup(brief_icon *bi) end_string_at_first_hash_symbol(Closeup_icon->closeup_label); // Goober5000 - wcsaga doesn't want this - if (Ship_types[sip->class_type].hud_bools & STI_HUD_NO_CLASS_DISPLAY ) { + if (Ship_types[sip->class_type].flags[Ship::Type_Info_Flags::No_class_display] ) { strcat_s(Closeup_icon->closeup_label, XSTR( " class", 434)); } diff --git a/code/missionui/missionweaponchoice.cpp b/code/missionui/missionweaponchoice.cpp index 7f53b88e77..ae107613d1 100644 --- a/code/missionui/missionweaponchoice.cpp +++ b/code/missionui/missionweaponchoice.cpp @@ -1122,7 +1122,7 @@ void wl_set_disabled_weapons(int ship_class) Wl_icons[i].can_use = eval_weapon_flag_for_game_type(sip->allowed_weapons[i]); // Goober5000: ballistic primaries - if (Weapon_info[i].wi_flags2 & WIF2_BALLISTIC) + 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])) @@ -1503,7 +1503,7 @@ int wl_calc_ballistic_fit(int wi_index, int capacity) Assert(Weapon_info[wi_index].subtype == WP_LASER); - Assert(Weapon_info[wi_index].wi_flags2 & WIF2_BALLISTIC); + Assert(Weapon_info[wi_index].wi_flags[Weapon::Info_Flags::Ballistic]); return fl2i( capacity / Weapon_info[wi_index].cargo_size + 0.5f ); } @@ -3281,7 +3281,7 @@ void wl_update_parse_object_weapons(p_object *pobjp, wss_unit *slot) ss->primary_banks[j] = slot->wep[i]; // ballistic primaries - Goober5000 - if (Weapon_info[slot->wep[i]].wi_flags2 & WIF2_BALLISTIC) + if (Weapon_info[slot->wep[i]].wi_flags[Weapon::Info_Flags::Ballistic]) { // Important: the primary_ammo[] value is a percentage of max capacity! // which means that it's always 100%, since ballistic primaries are completely @@ -3404,7 +3404,7 @@ void wl_bash_ship_weapons(ship_weapon *swp, wss_unit *slot) swp->primary_bank_weapons[j] = slot->wep[i]; // ballistic primaries - Goober5000 - if (Weapon_info[swp->primary_bank_weapons[j]].wi_flags2 & WIF2_BALLISTIC) { + if (Weapon_info[swp->primary_bank_weapons[j]].wi_flags[Weapon::Info_Flags::Ballistic]) { // this is a bit tricky: we must recalculate ammo for full capacity // since wep_count for primaries does not store the ammo; ballistic // primaries always come with a full magazine @@ -4045,7 +4045,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_flags2 & WIF2_BALLISTIC) && !(sip->flags[Ship::Info_Flags::Ballistic_primaries]))) + || ((wip->wi_flags[Weapon::Info_Flags::Ballistic]) && !(sip->flags[Ship::Info_Flags::Ballistic_primaries]))) { SCP_string temp; sprintf(temp, XSTR("%s is unable to carry %s weaponry", 1629), ship_name, wep_display_name); diff --git a/code/missionui/redalert.cpp b/code/missionui/redalert.cpp index 7d5029b495..d41433a62c 100644 --- a/code/missionui/redalert.cpp +++ b/code/missionui/redalert.cpp @@ -470,7 +470,7 @@ void red_alert_store_weapons(red_alert_ship_status *ras, ship_weapon *swp) wip = &Weapon_info[weapons.index]; - if (wip->wi_flags2 & WIF2_BALLISTIC) { + if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) { // to avoid triggering the below condition: this way, minimum ammo will be 2... // since the red-alert representation of a conventional primary is 0 -> not used, // 1 -> used, I added the representation 2 and above -> ballistic primary @@ -514,7 +514,7 @@ void red_alert_bash_weapons(red_alert_ship_status *ras, ship_weapon *swp) swp->primary_bank_weapons[i] = ras->primary_weapons[i].index; swp->primary_bank_ammo[i] = ras->primary_weapons[i].count; - 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]) { // adjust to correct ammo count, per red_alert_store_weapons() swp->primary_bank_ammo[i] -= 2; } @@ -568,7 +568,7 @@ void red_alert_bash_weapons(red_alert_ship_status *ras, p_object *pobjp) Assert( ras->primary_weapons[i].index >= 0 ); sssp->primary_banks[i] = ras->primary_weapons[i].index; - if (Weapon_info[sssp->primary_banks[i]].wi_flags2 & WIF2_BALLISTIC) + if (Weapon_info[sssp->primary_banks[i]].wi_flags[Weapon::Info_Flags::Ballistic]) { float max_count = sip->primary_bank_ammo_capacity[i] / Weapon_info[sssp->primary_banks[i]].cargo_size; sssp->primary_ammo[i] = fl2i(100.0f * (ras->primary_weapons[i].count - 2) / max_count + 0.5f); @@ -1006,8 +1006,8 @@ void red_alert_bash_wingman_status() wingp->current_wave++; wingp->red_alert_skipped_ships += wingp->wave_count; - if (wingp->num_waves == 0) - wingp->flags |= WF_WING_GONE; + if (wingp->num_waves == 0) + wingp->flags.set(Ship::Wing_Flags::Gone); // look through all ships yet to arrive... for (p_object *pobjp = GET_FIRST(&Ship_arrival_list); pobjp != END_OF_LIST(&Ship_arrival_list); pobjp = GET_NEXT(pobjp)) diff --git a/code/network/multimsgs.cpp b/code/network/multimsgs.cpp index 9b96ea9070..61c0f872f1 100644 --- a/code/network/multimsgs.cpp +++ b/code/network/multimsgs.cpp @@ -2997,7 +2997,7 @@ void send_secondary_fired_packet( ship *shipp, ushort starting_sig, int starting } if ( Objects[aip->target_objnum].type == OBJ_WEAPON ) { - Assert(Weapon_info[Weapons[Objects[aip->target_objnum].instance].weapon_info_index].wi_flags & WIF_BOMB); + Assert(Weapon_info[Weapons[Objects[aip->target_objnum].instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Bomb]); } } @@ -7303,7 +7303,7 @@ void send_homing_weapon_info( int weapon_num ) wp = &Weapons[weapon_num]; // be sure that this weapon object is a homing object. - if ( !(Weapon_info[wp->weapon_info_index].wi_flags & WIF_HOMING) ) + if ( !(Weapon_info[wp->weapon_info_index].is_homing()) ) return; // default the subsystem @@ -7369,11 +7369,11 @@ void process_homing_weapon_info( ubyte *data, header *hinfo ) } if ( homing_object->type == OBJ_WEAPON ) { - int flags = Weapon_info[Weapons[homing_object->instance].weapon_info_index].wi_flags; + auto flags = Weapon_info[Weapons[homing_object->instance].weapon_info_index].wi_flags; // Assert( (flags & WIF_BOMB) || (flags & WIF_CMEASURE) ); - if ( !((flags & WIF_BOMB) || (flags & WIF_CMEASURE)) ) { + if ( !((flags[Weapon::Info_Flags::Bomb, Weapon::Info_Flags::Cmeasure])) ) { nprintf(("Network", "Homing object is invalid for homing update\n")); return; } @@ -8123,7 +8123,7 @@ void process_flak_fired_packet(ubyte *data, header *hinfo) wid = ssp->weapons.secondary_bank_weapons[0]; } - if((wid < 0) || !(Weapon_info[wid].wi_flags & WIF_FLAK)){ + if((wid < 0) || !(Weapon_info[wid].wi_flags[Weapon::Info_Flags::Flak])){ return; } diff --git a/code/object/collideshipship.cpp b/code/object/collideshipship.cpp index 061bbdf947..8ee624db7b 100644 --- a/code/object/collideshipship.cpp +++ b/code/object/collideshipship.cpp @@ -1029,8 +1029,8 @@ void maybe_push_little_ship_from_fast_big_ship(object *big_obj, object *small_ob // Move player out of the way of a BIG|HUGE ship warping in or out int big_class = Ship_info[Ships[big_obj->instance].ship_info_index].class_type; int small_class = Ship_info[Ships[small_obj->instance].ship_info_index].class_type; - if (big_class > -1 && Ship_types[big_class].ship_bools & STI_SHIP_WARP_PUSHES) { - if (small_class > -1 && Ship_types[small_class].ship_bools & STI_SHIP_WARP_PUSHABLE) { + if (big_class > -1 && Ship_types[big_class].flags[Ship::Type_Info_Flags::Warp_pushes]) { + if (small_class > -1 && Ship_types[small_class].flags[Ship::Type_Info_Flags::Warp_pushable]) { float big_speed = vm_vec_mag_quick(&big_obj->phys_info.vel); if (big_speed > 3*big_obj->phys_info.max_vel.xyz.z) { // push player away in direction perp to forward of big ship diff --git a/code/object/collideshipweapon.cpp b/code/object/collideshipweapon.cpp index a3149657b7..ccc98aed35 100644 --- a/code/object/collideshipweapon.cpp +++ b/code/object/collideshipweapon.cpp @@ -364,7 +364,7 @@ int ship_weapon_check_collision(object *ship_objp, object *weapon_objp, float ti // if this weapon pierces the shield, then do the hit effect, but act like a shield collision never occurred; // otherwise, we have a valid hit on this shield - if (wip->wi_flags2 & WIF2_PIERCE_SHIELDS) + if (wip->wi_flags[Weapon::Info_Flags::Pierce_shields]) quadrant_num = -1; else valid_hit_occurred = 1; @@ -441,7 +441,7 @@ int ship_weapon_check_collision(object *ship_objp, object *weapon_objp, float ti Script_system.RemHookVars(4, "Ship", "Weapon", "Self","Object"); } - else if ((Missiontime - wp->creation_time > F1_0/2) && (wip->wi_flags & WIF_HOMING) && (wp->homing_object == ship_objp)) { + else if ((Missiontime - wp->creation_time > F1_0/2) && (wip->is_homing()) && (wp->homing_object == ship_objp)) { if (dist < wip->shockwave.inner_rad) { vec3d vec_to_ship; diff --git a/code/object/collideweaponweapon.cpp b/code/object/collideweaponweapon.cpp index 168aa3ea3d..34d61bfc14 100644 --- a/code/object/collideweaponweapon.cpp +++ b/code/object/collideweaponweapon.cpp @@ -55,11 +55,11 @@ int collide_weapon_weapon( obj_pair * pair ) B_radius = B->radius; if (wipA->weapon_hitpoints > 0) { - if (!(wipA->wi_flags2 & WIF2_HARD_TARGET_BOMB)) { + if (!(wipA->wi_flags[Weapon::Info_Flags::Hard_target_bomb])) { A_radius *= 2; // Makes bombs easier to hit } - if ((The_mission.ai_profile->flags2 & AIPF2_ASPECT_INVULNERABILITY_FIX) && (wipA->wi_flags & WIF_LOCKED_HOMING) && (wpA->homing_object != &obj_used_list)) { + if ((The_mission.ai_profile->flags2 & AIPF2_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; } @@ -68,10 +68,10 @@ int collide_weapon_weapon( obj_pair * pair ) } if (wipB->weapon_hitpoints > 0) { - if (!(wipB->wi_flags2 & WIF2_HARD_TARGET_BOMB)) { + 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->wi_flags & WIF_LOCKED_HOMING) && (wpB->homing_object != &obj_used_list)) { + if ((The_mission.ai_profile->flags2 & AIPF2_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; } @@ -101,11 +101,11 @@ int collide_weapon_weapon( obj_pair * pair ) if (wipA->weapon_hitpoints > 0) { if (wipB->weapon_hitpoints > 0) { // Two bombs collide, detonate both. - if ((wipA->wi_flags & WIF_BOMB) && (wipB->wi_flags & WIF_BOMB)) { + 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); } } @@ -151,17 +151,17 @@ int collide_weapon_weapon( obj_pair * pair ) if (!MULTIPLAYER_CLIENT) { // If bomb was destroyed, do scoring - if (wipA->wi_flags & WIF_BOMB) { + 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 & WIF_BOMB) { + 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/objcollide.cpp b/code/object/objcollide.cpp index 4bc9bff98c..04165fd7c3 100644 --- a/code/object/objcollide.cpp +++ b/code/object/objcollide.cpp @@ -296,11 +296,11 @@ void obj_add_pair( object *A, object *B, int check_time, int add_to_end ) if (awip->subtype != WP_LASER || bwip->subtype != WP_LASER) { if (awip->subtype == WP_LASER) { - if ( bwip->wi_flags & WIF_BOMB ) { + if ( bwip->wi_flags[Weapon::Info_Flags::Bomb] ) { check_collision = collide_weapon_weapon; } } else if (bwip->subtype == WP_LASER) { - if ( awip->wi_flags & WIF_BOMB ) { + if ( awip->wi_flags[Weapon::Info_Flags::Bomb] ) { check_collision = collide_weapon_weapon; swapped=1; } @@ -357,7 +357,7 @@ void obj_add_pair( object *A, object *B, int check_time, int add_to_end ) // only check debris:weapon collisions for player if (check_collision == collide_debris_weapon) { // weapon is B - if ( !(Weapon_info[Weapons[B->instance].weapon_info_index].wi_flags & WIF_TURNS) ) { + if ( !(Weapon_info[Weapons[B->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Turns]) ) { // check for dumbfire weapon // check if debris is behind laser float vdot; @@ -738,7 +738,7 @@ int weapon_will_never_hit( object *obj_weapon, object *other, obj_pair * current // Do some checks for weapons that don't turn - if ( !(wip->wi_flags & WIF_TURNS) ) { + if ( !(wip->wi_flags[Weapon::Info_Flags::Turns]) ) { // This first check is to see if a weapon is behind an object, and they // are heading in opposite directions. If so, we don't need to ever check @@ -810,7 +810,7 @@ int weapon_will_never_hit( object *obj_weapon, object *other, obj_pair * current // compare (weeapon) ray with expanding sphere (ship) to find earliest possible collision time // look for two time solutions to Xw = Xs, where Xw = Xw0 + Vwt*t Xs = Xs + Vs*(t+dt), where Vs*dt = radius of ship // Since direction of Vs is unknown, solve for (Vs*t) and find norm of both sides - if ( !(wip->wi_flags & WIF_TURNS) ) { + if ( !(wip->wi_flags[Weapon::Info_Flags::Turns]) ) { vec3d delta_x, laser_vel; float a,b,c, delta_x_dot_vl, delta_t; float root1, root2, root, earliest_time; @@ -1587,7 +1587,7 @@ void obj_collide_pair(object *A, object *B) // only check debris:weapon collisions for player if (check_collision == collide_debris_weapon) { // weapon is B - if ( !(Weapon_info[Weapons[B->instance].weapon_info_index].wi_flags & WIF_TURNS) ) { + if ( !(Weapon_info[Weapons[B->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Turns]) ) { // check for dumbfire weapon // check if debris is behind laser float vdot; 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 05f3ab26dd..98896f280e 100644 --- a/code/parse/lua.cpp +++ b/code/parse/lua.cpp @@ -4659,18 +4659,11 @@ ADE_VIRTVAR(Bomb, l_Weaponclass, "boolean", "Is weapon class flagged as bomb", " if(ADE_SETTING_VAR) { - if(newVal) - { - info->wi_flags |= WIF_BOMB; - } - else - { - info->wi_flags &= ~WIF_BOMB; - } + info->wi_flags.set(Weapon::Info_Flags::Bomb, newVal); } - if (info->wi_flags & WIF_BOMB) + if (info->wi_flags[Weapon::Info_Flags::Bomb]) return ADE_RETURN_TRUE; else return ADE_RETURN_FALSE; @@ -4796,7 +4789,7 @@ ADE_FUNC(isBeam, l_Weaponclass, NULL, "Return true if the weapon is a beam", "bo if(idx < 0 || idx >= Num_weapon_types) return ADE_RETURN_FALSE; - if (Weapon_info[idx].wi_flags & WIF_BEAM || Weapon_info[idx].subtype == WP_BEAM) + if (Weapon_info[idx].wi_flags[Weapon::Info_Flags::Beam] || Weapon_info[idx].subtype == WP_BEAM) return ADE_RETURN_TRUE; else return ADE_RETURN_FALSE; @@ -10752,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/parse/parselo.cpp b/code/parse/parselo.cpp index 54941f5984..c7a14f974f 100644 --- a/code/parse/parselo.cpp +++ b/code/parse/parselo.cpp @@ -2926,7 +2926,7 @@ int stuff_loadout_list (int *ilp, int max_ints, int lookup_type) Warning(LOCATION, "Ship type \"%s\" found in loadout of mission file. This class is not marked as a player ship...skipping", str); continue; } - else if ((lookup_type == MISSION_LOADOUT_WEAPON_LIST) && (!(Weapon_info[index].wi_flags & WIF_PLAYER_ALLOWED)) ) { + else if ((lookup_type == MISSION_LOADOUT_WEAPON_LIST) && (!(Weapon_info[index].wi_flags[Weapon::Info_Flags::Player_allowed])) ) { clean_loadout_list_entry(); nprintf(("Warning", "Warning: Weapon type %s found in loadout of mission file. This class is not marked as a player allowed weapon...skipping\n", str)); if ( !Is_standalone ) diff --git a/code/parse/parselo.h b/code/parse/parselo.h index 32bb12a102..68767428fc 100644 --- a/code/parse/parselo.h +++ b/code/parse/parselo.h @@ -13,6 +13,7 @@ #include "cfile/cfile.h" #include "globalincs/globals.h" #include "globalincs/pstypes.h" +#include "globalincs/flagset.h" #include "def_files/def_files.h" #include @@ -148,7 +149,7 @@ extern int parse_string_flag_list(int *dest, flag_def_list defs[], int defs_size // If the "is_special" flag is set, or a string was not found in the def list, it will be added to the unparsed_or_special_strings Vector // so that you can process it properly later template -int parse_string_flag_list(Flagset& dest, flag_def_list_new defs[], size_t n_defs, SCP_vector* unparsed_or_special_strings) +int parse_string_flag_list(Flagset& dest, flag_def_list_new defs [], size_t n_defs, SCP_vector* unparsed_or_special_strings) { char(*slp)[NAME_LENGTH] = (char(*)[32])new char[n_defs*NAME_LENGTH]; int num_strings = stuff_string_list(slp, (int)n_defs); @@ -179,8 +180,8 @@ int parse_string_flag_list(Flagset& dest, flag_def_list_new defs[], size_t n_ extern long atol2(); extern int my_errno; -template -void stuff_flagset(Flagset *dest) { +template +void stuff_flagset(T *dest) { dest->from_long(atol2()); if (my_errno) @@ -213,6 +214,15 @@ extern void stuff_parenthesized_vec3d(vec3d *vp); extern void stuff_boolean(int *i, bool a_to_eol=true); extern void stuff_boolean(bool *b, bool a_to_eol=true); extern void stuff_boolean_flag(int *i, int flag, bool a_to_eol=true); + +template +void stuff_boolean_flag(Flagset& destination, Flags flag, bool a_to_eol = true) +{ + bool temp; + stuff_boolean(&temp, a_to_eol); + destination.set(flag, temp); +} + extern int check_for_string(const char *pstr); extern int check_for_string_raw(const char *pstr); extern int check_for_eof(); diff --git a/code/parse/scripting.cpp b/code/parse/scripting.cpp index 7c1a3e2591..51fa665777 100644 --- a/code/parse/scripting.cpp +++ b/code/parse/scripting.cpp @@ -343,7 +343,7 @@ bool ConditionedHook::ConditionsValid(int action, object *objp, int more_data) if (!(primary || secondary)) return false; - if ((shipp->flags[Ship::Ship_Flags::Primary_linked]) && primary && (Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].wi_flags3 & WIF3_NOLINK)) + if ((shipp->flags[Ship::Ship_Flags::Primary_linked]) && primary && (Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].wi_flags[Weapon::Info_Flags::Nolink])) return false; break; @@ -353,7 +353,7 @@ bool ConditionedHook::ConditionsValid(int action, object *objp, int more_data) secondary = stricmp(Weapon_info[shipp->weapons.secondary_bank_weapons[shipp->weapons.current_secondary_bank]].name, scp->data.name) == 0; prev_secondary = stricmp(Weapon_info[shipp->weapons.secondary_bank_weapons[shipp->weapons.previous_secondary_bank]].name, scp->data.name) == 0; - if ((shipp->flags[Ship::Ship_Flags::Primary_linked]) && prev_primary && (Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.previous_primary_bank]].wi_flags3 & WIF3_NOLINK)) + if ((shipp->flags[Ship::Ship_Flags::Primary_linked]) && prev_primary && (Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.previous_primary_bank]].wi_flags[Weapon::Info_Flags::Nolink])) return true; if ( !prev_secondary && ! secondary && !prev_primary && !primary ) @@ -408,7 +408,7 @@ bool ConditionedHook::ConditionsValid(int action, object *objp, int more_data) secondary = stricmp(Weapon_info[shipp->weapons.secondary_bank_weapons[shipp->weapons.current_secondary_bank]].name, scp->data.name) == 0; } - if ((shipp->flags[Ship::Ship_Flags::Primary_linked]) && primary && (Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].wi_flags3 & WIF3_NOLINK)) + if ((shipp->flags[Ship::Ship_Flags::Primary_linked]) && primary && (Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].wi_flags[Weapon::Info_Flags::Nolink])) return false; return more_data == 1 ? primary : secondary; diff --git a/code/parse/sexp.cpp b/code/parse/sexp.cpp index 67d38a5b7b..8b79584b29 100755 --- a/code/parse/sexp.cpp +++ b/code/parse/sexp.cpp @@ -2918,7 +2918,7 @@ int check_sexp_syntax(int node, int return_type, int recursive, int *bad_node, i // we need to be sure that for huge weapons, the WIF_HUGE flag is set if ( type == OPF_HUGE_WEAPON ) { - if ( !(Weapon_info[i].wi_flags & WIF_HUGE) ) + if ( !(Weapon_info[i].wi_flags[Weapon::Info_Flags::Huge]) ) return SEXP_CHECK_INVALID_WEAPON_NAME; } @@ -7700,7 +7700,7 @@ int sexp_destroyed_departed_delay(int n) // for wings, check the WF_GONE flag to see if there are no more ships in this wing to arrive. wingnum = wing_name_lookup(name, 1); if ( wingnum != -1 ) { - if ( Wings[wingnum].flags & WF_WING_GONE ) { + if ( Wings[wingnum].flags[Ship::Wing_Flags::Gone] ) { // be sure to get the latest time of one of these if ( Wings[wingnum].time_gone > latest_time ){ time_gone = Wings[wingnum].time_gone; @@ -12601,8 +12601,8 @@ void sexp_tech_add_weapon(int node) while (node >= 0) { name = CTEXT(node); i = weapon_info_lookup(name); - if (i >= 0) - Weapon_info[i].wi_flags |= WIF_IN_TECH_DATABASE; + if (i >= 0) + Weapon_info[i].wi_flags.set(Weapon::Info_Flags::In_tech_database); else Warning(LOCATION, "In tech-add-weapon, weapon class \"%s\" invalid", name); @@ -13871,9 +13871,14 @@ int sexp_event_delay_status( int n, int want_true, bool use_msecs = false) return SEXP_FALSE; } - delay = i2f(eval_num(CDR(n))); if (use_msecs) { - delay = delay / 1000; + uint64_t tempDelay = eval_num(CDR(n)); + tempDelay = tempDelay << 16; + tempDelay = tempDelay / 1000; + + delay = (fix) tempDelay; + } else { + delay = i2f(eval_num(CDR(n))); } for (i = 0; i < Num_mission_events; i++ ) { @@ -15149,7 +15154,7 @@ int sexp_primaries_depleted(int node) for (int idx=0; idxweapons.primary_bank_weapons[idx]].wi_flags2 & WIF2_BALLISTIC) + if (Weapon_info[shipp->weapons.primary_bank_weapons[idx]].wi_flags[Weapon::Info_Flags::Ballistic]) { // is this bank out of ammo? if (shipp->weapons.primary_bank_ammo[idx] == 0) @@ -15668,7 +15673,7 @@ int sexp_primary_ammo_pct(int node) for(idx=0; idxweapons.num_primary_banks; idx++) { // ballistic - if (Weapon_info[shipp->weapons.primary_bank_weapons[idx]].wi_flags2 & WIF2_BALLISTIC) + if (Weapon_info[shipp->weapons.primary_bank_weapons[idx]].wi_flags[Weapon::Info_Flags::Ballistic]) { ret_sum[idx] = (int)(((float)shipp->weapons.primary_bank_ammo[idx] / (float)shipp->weapons.primary_bank_start_ammo[idx]) * 100.0f); } @@ -15690,7 +15695,7 @@ int sexp_primary_ammo_pct(int node) else { // ballistic - if (Weapon_info[shipp->weapons.primary_bank_weapons[check]].wi_flags2 & WIF2_BALLISTIC) + if (Weapon_info[shipp->weapons.primary_bank_weapons[check]].wi_flags[Weapon::Info_Flags::Ballistic]) { ret = (int)(((float)shipp->weapons.primary_bank_ammo[check] / (float)shipp->weapons.primary_bank_start_ammo[check]) * 100.0f); } @@ -15787,7 +15792,7 @@ int sexp_get_primary_ammo(int node) for(int bank=0; bankweapons.num_primary_banks; bank++) { // Only ballistic weapons need to be counted - if (Weapon_info[shipp->weapons.primary_bank_weapons[bank]].wi_flags2 & WIF2_BALLISTIC) + if (Weapon_info[shipp->weapons.primary_bank_weapons[bank]].wi_flags[Weapon::Info_Flags::Ballistic]) { ammo_left += shipp->weapons.primary_bank_ammo[bank] ; } @@ -15796,7 +15801,7 @@ int sexp_get_primary_ammo(int node) else { // Again only ballistic weapons need to be counted - if (Weapon_info[shipp->weapons.primary_bank_weapons[check]].wi_flags2 & WIF2_BALLISTIC) + if (Weapon_info[shipp->weapons.primary_bank_weapons[check]].wi_flags[Weapon::Info_Flags::Ballistic]) { ammo_left = shipp->weapons.primary_bank_ammo[check] ; } @@ -15892,7 +15897,7 @@ void set_primary_ammo (int ship_index, int requested_bank, int requested_ammo, i } // Check that this isn't a non-ballistic bank as it's pointless to set the amount of ammo for those - if (!(Weapon_info[shipp->weapons.primary_bank_weapons[requested_bank]].wi_flags2 & WIF2_BALLISTIC)) + if (!(Weapon_info[shipp->weapons.primary_bank_weapons[requested_bank]].wi_flags[Weapon::Info_Flags::Ballistic])) { return ; } @@ -16893,7 +16898,7 @@ void sexp_beam_fire(int node, bool at_coords) Assertion(fire_info.turret->weapons.primary_bank_weapons[idx] >= 0 && fire_info.turret->weapons.primary_bank_weapons[idx] < MAX_WEAPON_TYPES, "sexp_beam_fire: found invalid weapon index (%i), get a coder\n!", fire_info.turret->weapons.primary_bank_weapons[idx]); // store the weapon info index - if (Weapon_info[fire_info.turret->weapons.primary_bank_weapons[idx]].wi_flags & WIF_BEAM) { + if (Weapon_info[fire_info.turret->weapons.primary_bank_weapons[idx]].wi_flags[Weapon::Info_Flags::Beam]) { fire_info.beam_info_index = fire_info.turret->weapons.primary_bank_weapons[idx]; } } @@ -16923,7 +16928,7 @@ void sexp_beam_floating_fire(int n) Warning(LOCATION, "Invalid weapon class passed to beam-create; weapon type '%s' does not exist!\n", CTEXT(n)); return; } - if (!(Weapon_info[fire_info.beam_info_index].wi_flags & WIF_BEAM)) { + if (!(Weapon_info[fire_info.beam_info_index].wi_flags[Weapon::Info_Flags::Beam])) { Warning(LOCATION, "Invalid weapon class passed to beam-create; weapon type '%s' is not a beam!\n", CTEXT(n)); return; } @@ -17980,14 +17985,14 @@ int sexp_get_turret_primary_ammo(int node) for (bank = 0; bank < swp->num_primary_banks; bank++) { // Only ballistic weapons need to be counted - if (Weapon_info[swp->primary_bank_weapons[bank]].wi_flags2 & WIF2_BALLISTIC) + if (Weapon_info[swp->primary_bank_weapons[bank]].wi_flags[Weapon::Info_Flags::Ballistic]) { ammo_left += swp->primary_bank_ammo[bank]; } } } else { // Again only ballistic weapons need to be counted - if (Weapon_info[swp->primary_bank_weapons[check]].wi_flags2 & WIF2_BALLISTIC) + if (Weapon_info[swp->primary_bank_weapons[check]].wi_flags[Weapon::Info_Flags::Ballistic]) { ammo_left = swp->primary_bank_ammo[check]; } @@ -18073,7 +18078,7 @@ void set_turret_primary_ammo(ship_subsys *turret, int requested_bank, int reques } // Check that this isn't a non-ballistic bank as it's pointless to set the amount of ammo for those - if (!(Weapon_info[turret->weapons.primary_bank_weapons[requested_bank]].wi_flags2 & WIF2_BALLISTIC)) + if (!(Weapon_info[turret->weapons.primary_bank_weapons[requested_bank]].wi_flags[Weapon::Info_Flags::Ballistic])) { return; } @@ -18266,10 +18271,10 @@ void sexp_set_subsys_rotation_lock_free(int node, int locked) rotate->flags.set(Ship::Subsystem_Flags::Rotates, locked != 0); if (locked) { - if (rotate->subsys_snd_flags & SSSF_ROTATE) + if (rotate->subsys_snd_flags[Ship::Subsys_Sound_Flags::Rotate]) { obj_snd_delete_type(Ships[ship_num].objnum, rotate->system_info->rotation_snd, rotate); - rotate->subsys_snd_flags &= ~SSSF_ROTATE; + rotate->subsys_snd_flags.remove(Ship::Subsys_Sound_Flags::Rotate); } } else @@ -18277,8 +18282,8 @@ void sexp_set_subsys_rotation_lock_free(int node, int locked) if (rotate->system_info->rotation_snd >= 0) { obj_snd_assign(Ships[ship_num].objnum, rotate->system_info->rotation_snd, &rotate->system_info->pnt, 0, OS_SUBSYS_ROTATION, rotate); - rotate->subsys_snd_flags |= SSSF_ROTATE; - } + rotate->subsys_snd_flags.set(Ship::Subsys_Sound_Flags::Rotate); + } } } } @@ -18773,7 +18778,7 @@ void sexp_set_arrival_info(int node) oswpt.shipp->arrival_path_mask = arrival_mask; oswpt.shipp->arrival_distance = arrival_distance; oswpt.shipp->arrival_delay = arrival_delay; - oswpt.shipp->flags.set(Ship::Ship_Flags::No_arrival_warp, show_warp); + oswpt.shipp->flags.set(Ship::Ship_Flags::No_arrival_warp, !show_warp); } else if (oswpt.type == OSWPT_TYPE_WING || oswpt.type == OSWPT_TYPE_WING_NOT_PRESENT) { @@ -18783,10 +18788,7 @@ void sexp_set_arrival_info(int node) oswpt.wingp->arrival_distance = arrival_distance; oswpt.wingp->arrival_delay = arrival_delay; - if (show_warp) - oswpt.wingp->flags &= ~WF_NO_ARRIVAL_WARP; - else - oswpt.wingp->flags |= WF_NO_ARRIVAL_WARP; + oswpt.wingp->flags.set(Ship::Wing_Flags::No_arrival_warp, !show_warp); } else if (oswpt.type == OSWPT_TYPE_PARSE_OBJECT) { @@ -18796,7 +18798,7 @@ void sexp_set_arrival_info(int node) oswpt.p_objp->arrival_distance = arrival_distance; oswpt.p_objp->arrival_delay = arrival_delay; - oswpt.p_objp->flags.set(Mission::Parse_Object_Flags::SF_No_arrival_warp, show_warp); + oswpt.p_objp->flags.set(Mission::Parse_Object_Flags::SF_No_arrival_warp, !show_warp); } } @@ -18874,7 +18876,7 @@ void sexp_set_departure_info(int node) oswpt.shipp->departure_anchor = departure_anchor; oswpt.shipp->departure_path_mask = departure_mask; oswpt.shipp->departure_delay = departure_delay; - oswpt.shipp->flags.set(Ship::Ship_Flags::No_departure_warp, show_warp); + oswpt.shipp->flags.set(Ship::Ship_Flags::No_departure_warp, !show_warp); } else if (oswpt.type == OSWPT_TYPE_WING || oswpt.type == OSWPT_TYPE_WING_NOT_PRESENT) { @@ -18883,10 +18885,7 @@ void sexp_set_departure_info(int node) oswpt.wingp->departure_path_mask = departure_mask; oswpt.wingp->departure_delay = departure_delay; - if (show_warp) - oswpt.wingp->flags &= ~WF_NO_DEPARTURE_WARP; - else - oswpt.wingp->flags |= WF_NO_DEPARTURE_WARP; + oswpt.wingp->flags.set(Ship::Wing_Flags::No_departure_warp, !show_warp); } else if (oswpt.type == OSWPT_TYPE_PARSE_OBJECT) { @@ -18894,7 +18893,7 @@ void sexp_set_departure_info(int node) oswpt.p_objp->departure_anchor = departure_anchor; oswpt.p_objp->departure_path_mask = departure_mask; oswpt.p_objp->departure_delay = departure_delay; - oswpt.shipp->flags.set(Ship::Ship_Flags::No_departure_warp, show_warp); + oswpt.shipp->flags.set(Ship::Ship_Flags::No_departure_warp, !show_warp); } } @@ -19050,7 +19049,7 @@ void set_nav_carry_status(int node) { if (!stricmp(Wings[i].name, name)) { - Wings[i].flags |= WF_NAV_CARRY; + Wings[i].flags.set(Ship::Wing_Flags::Nav_carry); skip = true; break; } @@ -19091,7 +19090,7 @@ void unset_nav_carry_status(int node) { if (!stricmp(Wings[i].name, name)) { - Wings[i].flags &= ~WF_NAV_CARRY; + Wings[i].flags.remove(Ship::Wing_Flags::Nav_carry); skip = true; break; 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 31cdf3c3a5..947ad43b5d 100644 --- a/code/pilotfile/csg.cpp +++ b/code/pilotfile/csg.cpp @@ -445,7 +445,7 @@ void pilotfile::csg_read_techroom() if (visible) { if (weapon_list[idx].index >= 0) { - Weapon_info[weapon_list[idx].index].wi_flags |= WIF_IN_TECH_DATABASE; + Weapon_info[weapon_list[idx].index].wi_flags.set(Weapon::Info_Flags::In_tech_database); } else { m_data_invalid = true; } @@ -494,7 +494,7 @@ void pilotfile::csg_write_techroom() // visible weapons for (idx = 0; idx < Num_weapon_types; idx++) { // only visible if not in techroom by default - if ( (Weapon_info[idx].wi_flags & WIF_IN_TECH_DATABASE) && !(Weapon_info[idx].wi_flags2 & WIF2_DEFAULT_IN_TECH_DATABASE) ) { + if ( (Weapon_info[idx].wi_flags[Weapon::Info_Flags::In_tech_database]) && !(Weapon_info[idx].wi_flags[Weapon::Info_Flags::Default_in_tech_database]) ) { visible = 1; } else { visible = 0; @@ -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/playerman/playercontrol.cpp b/code/playerman/playercontrol.cpp index fd901184be..128517b44e 100644 --- a/code/playerman/playercontrol.cpp +++ b/code/playerman/playercontrol.cpp @@ -1172,7 +1172,7 @@ void player_init_all_alone_msg() if ( Ships[objp->instance].team == Player_ship->team ) { int ship_type = Ship_info[Ships[objp->instance].ship_info_index].class_type; - if ( ship_type != -1 && (Ship_types[ship_type].message_bools & STI_MSG_COUNTS_FOR_ALONE) ) { + if ( ship_type != -1 && (Ship_types[ship_type].flags[Ship::Type_Info_Flags::Counts_for_alone]) ) { return; } } @@ -1913,7 +1913,7 @@ void player_maybe_play_all_alone_msg() if ( Ships[objp->instance].team == Player_ship->team ) { int ship_type = Ship_info[Ships[objp->instance].ship_info_index].class_type; - if ( ship_type != -1 && (Ship_types[ship_type].message_bools & STI_MSG_COUNTS_FOR_ALONE) ) { + if ( ship_type != -1 && (Ship_types[ship_type].flags[Ship::Type_Info_Flags::Counts_for_alone]) ) { return; } } diff --git a/code/radar/radarsetup.cpp b/code/radar/radarsetup.cpp index 60ce0e6a1e..4516f24d2e 100644 --- a/code/radar/radarsetup.cpp +++ b/code/radar/radarsetup.cpp @@ -207,16 +207,16 @@ void radar_plot_object( object *objp ) case OBJ_WEAPON: { // if not a bomb, return - if ( !(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags2 & WIF2_SHOWN_ON_RADAR) ) - if ( !(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags & WIF_BOMB) ) + if ( !(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Shown_on_radar]) ) + if ( !(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Bomb]) ) return; // if explicitly hidden, return - if (Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags2 & WIF2_DONT_SHOW_ON_RADAR) + if (Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Dont_show_on_radar]) return; // if we don't attack the bomb, return - if ( (!(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags2 & WIF2_SHOW_FRIENDLY)) && (!iff_x_attacks_y(Player_ship->team, obj_team(objp)))) + if ( (!(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Show_friendly])) && (!iff_x_attacks_y(Player_ship->team, obj_team(objp)))) return; // if a local ssm is in subspace, return @@ -224,7 +224,7 @@ void radar_plot_object( object *objp ) return; // if corkscrew missile use last frame pos for pos - if ( (Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags & WIF_CORKSCREW) ) + if ( (Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Corkscrew]) ) world_pos = objp->last_pos; break; @@ -561,16 +561,16 @@ RadarVisibility radar_is_visible( object *objp ) case OBJ_WEAPON: { // if not a bomb, return - if ( !(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags2 & WIF2_SHOWN_ON_RADAR) ) - if ( !(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags & WIF_BOMB) ) + if ( !(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Shown_on_radar]) ) + if ( !(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Bomb]) ) return NOT_VISIBLE; // if explicitly hidden, return - if (Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags2 & WIF2_DONT_SHOW_ON_RADAR) + if (Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Dont_show_on_radar]) return NOT_VISIBLE; // if we don't attack the bomb, return - if ( (!(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags2 & WIF2_SHOW_FRIENDLY)) && (!iff_x_attacks_y(Player_ship->team, obj_team(objp)))) + if ( (!(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Show_friendly])) && (!iff_x_attacks_y(Player_ship->team, obj_team(objp)))) return NOT_VISIBLE; // if a local ssm is in subspace, return diff --git a/code/ship/ship.cpp b/code/ship/ship.cpp index 0b379efe77..dfa80f50ba 100644 --- a/code/ship/ship.cpp +++ b/code/ship/ship.cpp @@ -178,22 +178,23 @@ flag_def_list Armor_flags[] = { const int Num_armor_flags = sizeof(Armor_flags)/sizeof(flag_def_list); -flag_def_list Man_types[] = { - { "Bank right", MT_BANK_RIGHT, 0 }, - { "Bank left", MT_BANK_LEFT, 0 }, - { "Pitch up", MT_PITCH_UP, 0 }, - { "Pitch down", MT_PITCH_DOWN, 0 }, - { "Roll right", MT_ROLL_RIGHT, 0 }, - { "Roll left", MT_ROLL_LEFT, 0 }, - { "Slide right", MT_SLIDE_RIGHT, 0 }, - { "Slide left", MT_SLIDE_LEFT, 0 }, - { "Slide up", MT_SLIDE_UP, 0 }, - { "Slide down", MT_SLIDE_DOWN, 0 }, - { "Forward", MT_FORWARD, 0 }, - { "Reverse", MT_REVERSE, 0 } + +flag_def_list_new Man_types[] = { + { "Bank right", Thruster_Flags::Bank_right, true, false }, + { "Bank left", Thruster_Flags::Bank_left, true, false }, + { "Pitch up", Thruster_Flags::Pitch_up, true, false }, + { "Pitch down", Thruster_Flags::Pitch_down, true, false }, + { "Roll right", Thruster_Flags::Roll_right, true, false }, + { "Roll left", Thruster_Flags::Roll_left, true, false }, + { "Slide right",Thruster_Flags::Slide_right,true, false }, + { "Slide left", Thruster_Flags::Slide_left, true, false }, + { "Slide up", Thruster_Flags::Slide_up, true, false }, + { "Slide down", Thruster_Flags::Slide_down, true, false }, + { "Forward", Thruster_Flags::Forward, true, false }, + { "Reverse", Thruster_Flags::Reverse, true, false } }; -const int Num_man_types = sizeof(Man_types)/sizeof(flag_def_list); +const size_t Num_man_types = sizeof(Man_types) / sizeof(flag_def_list_new); // Goober5000 - I figured we should keep this separate // from Comm_orders, considering how I redid it :p @@ -405,87 +406,87 @@ flag_def_list_new ai_tgt_ship_flags[] = { const int num_ai_tgt_ship_flags = sizeof(ai_tgt_ship_flags) / sizeof(flag_def_list_new); -flag_def_list ai_tgt_weapon_flags[] = { - { "bomb", WIF_BOMB, 0 }, - { "huge damage", WIF_HUGE, 0 }, - { "supercap damage", WIF_SUPERCAP, 0 }, - { "bomber+", WIF_BOMBER_PLUS, 0 }, - { "electronics", WIF_ELECTRONICS, 0 }, - { "puncture", WIF_PUNCTURE, 0 }, - { "emp", WIF_EMP, 0 }, - { "heat seeking", WIF_HOMING_HEAT, 0 }, - { "aspect seeking", WIF_HOMING_ASPECT, 0 }, - { "engine seeking", WIF_HOMING_JAVELIN, 0 }, - { "pierce shields", WIF2_PIERCE_SHIELDS, 1 }, - { "local ssm", WIF2_LOCAL_SSM, 1 }, - { "capital+", WIF2_CAPITAL_PLUS, 1 }, - { "heat-seeking", WIF_HOMING_HEAT, 0 }, - { "aspect-seeking", WIF_HOMING_ASPECT, 0 }, - { "javelin", WIF_HOMING_JAVELIN, 0 }, - { "spawn", WIF_SPAWN, 0 }, - { "remote detonate", WIF_REMOTE, 0 }, - { "countermeasure", WIF_CMEASURE, 0 }, - { "turns", WIF_TURNS, 0 }, - { "swarm", WIF_SWARM, 0 }, - { "trail", WIF_TRAIL, 0 }, - { "big ship", WIF_BIG_ONLY, 0 }, - { "child", WIF_CHILD, 0 }, - { "no dumbfire", WIF_NO_DUMBFIRE, 0 }, - { "thruster", WIF_THRUSTER, 0 }, - { "in tech database", WIF_IN_TECH_DATABASE, 0 }, - { "player allowed", WIF_PLAYER_ALLOWED, 0 }, - { "corkscrew", WIF_CORKSCREW, 0 }, - { "particle spew", WIF_PARTICLE_SPEW, 0 }, - { "esuck", WIF_ENERGY_SUCK, 0 }, - { "flak", WIF_FLAK, 0 }, - //{ "beam", WIF_BEAM, 0 }, // Okay, this one probably doesn't make sense. - { "tag", WIF_TAG, 0 }, - { "shudder", WIF_SHUDDER, 0 }, - { "lockarm", WIF_LOCKARM, 0 }, - { "stream", WIF_STREAM, 0 }, - { "ballistic", WIF2_BALLISTIC, 0 }, - { "default in tech database", WIF2_DEFAULT_IN_TECH_DATABASE, 1 }, - { "tagged only", WIF2_TAGGED_ONLY, 1 }, - { "cycle", WIF2_CYCLE, 1 }, - { "small only", WIF2_SMALL_ONLY, 1 }, - { "same turret cooldown", WIF2_SAME_TURRET_COOLDOWN, 1 }, - { "apply no light", WIF2_MR_NO_LIGHTING, 1 }, - { "transparent", WIF2_TRANSPARENT, 1 }, - { "training", WIF2_TRAINING, 1 }, - { "smart spawn", WIF2_SMART_SPAWN, 1 }, - { "inherit parent target", WIF2_INHERIT_PARENT_TARGET, 1 }, - { "no emp kill", WIF2_NO_EMP_KILL, 1 }, - { "variable lead homing", WIF2_VARIABLE_LEAD_HOMING, 1 }, - { "untargeted heat seeker", WIF2_UNTARGETED_HEAT_SEEKER, 1 }, - { "no radius doubling", WIF2_HARD_TARGET_BOMB, 1 }, - { "no subsystem homing", WIF2_NON_SUBSYS_HOMING, 1 }, - { "no lifeleft penalty", WIF2_NO_LIFE_LOST_IF_MISSED, 1 }, - { "custom seeker str", WIF2_CUSTOM_SEEKER_STR, 1 }, - { "can be targeted", WIF2_CAN_BE_TARGETED, 1 }, - { "show on radar", WIF2_SHOWN_ON_RADAR, 1 }, - { "show friendly on radar", WIF2_SHOW_FRIENDLY, 1 }, - { "chain external model fps", WIF2_EXTERNAL_WEAPON_FP, 1 }, - { "external model launcher", WIF2_EXTERNAL_WEAPON_LNCH, 1 }, - { "takes blast damage", WIF2_TAKES_BLAST_DAMAGE, 1 }, - { "takes shockwave damage", WIF2_TAKES_SHOCKWAVE_DAMAGE, 1 }, - { "hide from radar", WIF2_DONT_SHOW_ON_RADAR, 1 }, - { "render flak", WIF2_RENDER_FLAK, 1 }, - { "ciws", WIF2_CIWS, 1 }, - { "anti-subsystem beam", WIF2_ANTISUBSYSBEAM, 1 }, - { "no primary linking", WIF3_NOLINK, 2 }, - { "same emp time for capships", WIF3_USE_EMP_TIME_FOR_CAPSHIP_TURRETS, 2 }, - { "no primary linked penalty", WIF3_NO_LINKED_PENALTY, 2 }, - { "no homing speed ramp", WIF3_NO_HOMING_SPEED_RAMP, 2 }, - { "pulls aspect seekers", WIF3_CMEASURE_ASPECT_HOME_ON, 2 }, - { "turret interceptable", WIF3_TURRET_INTERCEPTABLE, 2 }, - { "fighter interceptable", WIF3_FIGHTER_INTERCEPTABLE, 2 }, - { "aoe electronics", WIF3_AOE_ELECTRONICS, 2 }, - { "apply recoil", WIF3_APPLY_RECOIL, 2 }, - { "don't spawn if shot", WIF3_DONT_SPAWN_IF_SHOT, 2 }, - { "die on lost lock", WIF3_DIE_ON_LOST_LOCK, 2 }, +flag_def_list_new ai_tgt_weapon_flags[] = { + { "bomb", Weapon::Info_Flags::Bomb, true, false }, + { "huge damage", Weapon::Info_Flags::Huge, true, false }, + { "supercap damage", Weapon::Info_Flags::Supercap, true, false }, + { "bomber+", Weapon::Info_Flags::Bomber_plus, true, false }, + { "electronics", Weapon::Info_Flags::Electronics, true, false }, + { "puncture", Weapon::Info_Flags::Puncture, true, false }, + { "emp", Weapon::Info_Flags::Emp, true, false }, + { "heat seeking", Weapon::Info_Flags::Homing_heat, true, false }, + { "aspect seeking", Weapon::Info_Flags::Homing_aspect, true, false }, + { "engine seeking", Weapon::Info_Flags::Homing_javelin, true, false }, + { "pierce shields", Weapon::Info_Flags::Pierce_shields, true, false }, + { "local ssm", Weapon::Info_Flags::Local_ssm, true, false }, + { "capital+", Weapon::Info_Flags::Capital_plus, true, false }, + { "heat-seeking", Weapon::Info_Flags::Homing_heat, true, false }, + { "aspect-seeking", Weapon::Info_Flags::Homing_aspect, true, false }, + { "javelin", Weapon::Info_Flags::Homing_javelin, true, false }, + { "spawn", Weapon::Info_Flags::Spawn, true, false }, + { "remote detonate", Weapon::Info_Flags::Remote, true, false }, + { "countermeasure", Weapon::Info_Flags::Cmeasure, true, false }, + { "turns", Weapon::Info_Flags::Turns, true, false }, + { "swarm", Weapon::Info_Flags::Swarm, true, false }, + { "trail", Weapon::Info_Flags::Trail, true, false }, + { "big ship", Weapon::Info_Flags::Big_only, true, false }, + { "child", Weapon::Info_Flags::Child, true, false }, + { "no dumbfire", Weapon::Info_Flags::No_dumbfire, true, false }, + { "thruster", Weapon::Info_Flags::Thruster, true, false }, + { "in tech database", Weapon::Info_Flags::In_tech_database, true, false }, + { "player allowed", Weapon::Info_Flags::Player_allowed, true, false }, + { "corkscrew", Weapon::Info_Flags::Corkscrew, true, false }, + { "particle spew", Weapon::Info_Flags::Particle_spew, true, false }, + { "esuck", Weapon::Info_Flags::Energy_suck, true, false }, + { "flak", Weapon::Info_Flags::Flak, true, false }, + //{ "beam", Weapon::Info_Flags::Beam, true, false }, // Okay, this one probably doesn't make sense. + { "tag", Weapon::Info_Flags::Tag, true, false }, + { "shudder", Weapon::Info_Flags::Shudder, true, false }, + { "lockarm", Weapon::Info_Flags::Lockarm, true, false }, + { "stream", Weapon::Info_Flags::Stream, true, false }, + { "ballistic", Weapon::Info_Flags::Ballistic, true, false }, + { "default in tech database", Weapon::Info_Flags::Default_in_tech_database, true, false }, + { "tagged only", Weapon::Info_Flags::Tagged_only, true, false }, + { "cycle", Weapon::Info_Flags::Cycle, true, false }, + { "small only", Weapon::Info_Flags::Small_only, true, false }, + { "same turret cooldown", Weapon::Info_Flags::Same_turret_cooldown, true, false }, + { "apply no light", Weapon::Info_Flags::Mr_no_lighting, true, false }, + { "transparent", Weapon::Info_Flags::Transparent, true, false }, + { "training", Weapon::Info_Flags::Training, true, false }, + { "smart spawn", Weapon::Info_Flags::Smart_spawn, true, false }, + { "inherit parent target", Weapon::Info_Flags::Inherit_parent_target, true, false }, + { "no emp kill", Weapon::Info_Flags::No_emp_kill, true, false }, + { "variable lead homing", Weapon::Info_Flags::Variable_lead_homing, true, false }, + { "untargeted heat seeker", Weapon::Info_Flags::Untargeted_heat_seeker, true, false }, + { "no radius doubling", Weapon::Info_Flags::Hard_target_bomb, true, false }, + { "no subsystem homing", Weapon::Info_Flags::Non_subsys_homing, true, false }, + { "no lifeleft penalty", Weapon::Info_Flags::No_life_lost_if_missed, true, false }, + { "custom seeker str", Weapon::Info_Flags::Custom_seeker_str, true, false }, + { "can be targeted", Weapon::Info_Flags::Can_be_targeted, true, false }, + { "show on radar", Weapon::Info_Flags::Shown_on_radar, true, false }, + { "show friendly on radar", Weapon::Info_Flags::Show_friendly, true, false }, + { "chain external model fps", Weapon::Info_Flags::External_weapon_fp, true, false }, + { "external model launcher", Weapon::Info_Flags::External_weapon_lnch, true, false }, + { "takes blast damage", Weapon::Info_Flags::Takes_blast_damage, true, false }, + { "takes shockwave damage", Weapon::Info_Flags::Takes_shockwave_damage, true, false }, + { "hide from radar", Weapon::Info_Flags::Dont_show_on_radar, true, false }, + { "render flak", Weapon::Info_Flags::Render_flak, true, false }, + { "ciws", Weapon::Info_Flags::Ciws, true, false }, + { "anti-subsystem beam", Weapon::Info_Flags::Antisubsysbeam, true, false }, + { "no primary linking", Weapon::Info_Flags::Nolink, true, false }, + { "same emp time for capships", Weapon::Info_Flags::Use_emp_time_for_capship_turrets, true, false }, + { "no primary linked penalty", Weapon::Info_Flags::No_linked_penalty, true, false }, + { "no homing speed ramp", Weapon::Info_Flags::No_homing_speed_ramp, true, false }, + { "pulls aspect seekers", Weapon::Info_Flags::Cmeasure_aspect_home_on, true, false }, + { "turret interceptable", Weapon::Info_Flags::Turret_Interceptable, true, false }, + { "fighter interceptable", Weapon::Info_Flags::Fighter_Interceptable, true, false }, + { "aoe electronics", Weapon::Info_Flags::Aoe_Electronics, true, false }, + { "apply recoil", Weapon::Info_Flags::Apply_recoil, true, false }, + { "don't spawn if shot", Weapon::Info_Flags::Dont_spawn_if_shot, true, false }, + { "die on lost lock", Weapon::Info_Flags::Die_on_lost_lock, true, false }, }; -const int num_ai_tgt_weapon_flags = sizeof(ai_tgt_weapon_flags) / sizeof(flag_def_list); +const int num_ai_tgt_weapon_info_flags = sizeof(ai_tgt_weapon_flags) / sizeof(flag_def_list_new); SCP_vector Ai_tp_list; @@ -1059,7 +1060,11 @@ void ship_info::clone(const ship_info& other) ship_sounds = other.ship_sounds; num_maneuvering = other.num_maneuvering; - memcpy(maneuvering, other.maneuvering, sizeof(man_thruster) * MAX_MAN_THRUSTERS); + + for (int i = 0; i < MAX_MAN_THRUSTERS; ++i) + { + maneuvering[i] = other.maneuvering[i]; + } radar_image_2d_idx = other.radar_image_2d_idx; radar_color_image_2d_idx = other.radar_color_image_2d_idx; @@ -1739,13 +1744,10 @@ ship_info::ship_info() ship_sounds.clear(); num_maneuvering = 0; - memset(maneuvering, 0, MAX_MAN_THRUSTERS * sizeof(man_thruster)); + for (i = 0; i < MAX_MAN_THRUSTERS; i++) { - maneuvering[i].start_snd = -1; - maneuvering[i].loop_snd = -1; - maneuvering[i].stop_snd = -1; - maneuvering[i].tex_id = -1; + maneuvering[i].reset(); } radar_image_2d_idx = -1; @@ -3447,7 +3449,7 @@ int parse_ship_values(ship_info* sip, const bool is_template, const bool first_t { for (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])) { sip->flags.set(Ship::Info_Flags::Ballistic_primaries); break; @@ -3540,7 +3542,7 @@ int parse_ship_values(ship_info* sip, const bool is_template, const bool first_t int res = weapon_info_lookup(buf); if (res < 0) { Warning(LOCATION, "Could not find weapon type '%s' to use as countermeasure on %s '%s'", buf, info_type_name, sip->name); - } else if (Weapon_info[res].wi_flags & WIF_BEAM) { + } else if (Weapon_info[res].wi_flags[Weapon::Info_Flags::Beam]) { Warning(LOCATION, "Attempt made to set a beam weapon as a countermeasure on %s '%s'", info_type_name, sip->name); } else { sip->cmeasure_type = res; @@ -3919,7 +3921,7 @@ int parse_ship_values(ship_info* sip, const bool is_template, const bool first_t } if(optional_string("+Used for:")) { - parse_string_flag_list(&mtp->use_flags, Man_types, Num_man_types); + parse_string_flag_list(mtp->use_flags, Man_types, Num_man_types, NULL); } if(optional_string("+Position:")) { @@ -4783,39 +4785,39 @@ void parse_ship_type() } if(optional_string("$Counts for Alone:")) { - stuff_boolean_flag(&stp->message_bools, STI_MSG_COUNTS_FOR_ALONE); + stuff_boolean_flag(stp->flags, Ship::Type_Info_Flags::Counts_for_alone); } if(optional_string("$Praise Destruction:")) { - stuff_boolean_flag(&stp->message_bools, STI_MSG_PRAISE_DESTRUCTION); + stuff_boolean_flag(stp->flags, Ship::Type_Info_Flags::Praise_destruction); } if(optional_string("$On Hotkey list:")) { - stuff_boolean_flag(&stp->hud_bools, STI_HUD_HOTKEY_ON_LIST); + stuff_boolean_flag(stp->flags, Ship::Type_Info_Flags::Hotkey_on_list); } if(optional_string("$Target as Threat:")) { - stuff_boolean_flag(&stp->hud_bools, STI_HUD_TARGET_AS_THREAT); + stuff_boolean_flag(stp->flags, Ship::Type_Info_Flags::Target_as_threat); } if(optional_string("$Show Attack Direction:")) { - stuff_boolean_flag(&stp->hud_bools, STI_HUD_SHOW_ATTACK_DIRECTION); + stuff_boolean_flag(stp->flags, Ship::Type_Info_Flags::Show_attack_direction); } if(optional_string("$Scannable:")) { - stuff_boolean_flag(&stp->ship_bools, STI_SHIP_SCANNABLE); + stuff_boolean_flag(stp->flags, Ship::Type_Info_Flags::Scannable); } if(optional_string("$Warp Pushes:")) { - stuff_boolean_flag(&stp->ship_bools, STI_SHIP_WARP_PUSHES); + stuff_boolean_flag(stp->flags, Ship::Type_Info_Flags::Warp_pushes); } if(optional_string("$Warp Pushable:")) { - stuff_boolean_flag(&stp->ship_bools, STI_SHIP_WARP_PUSHABLE); + stuff_boolean_flag(stp->flags, Ship::Type_Info_Flags::Warp_pushable); } if(optional_string("$Turrets prioritize ship target:")) { - stuff_boolean_flag(&stp->ship_bools, STI_TURRET_TGT_SHIP_TGT); + stuff_boolean_flag(stp->flags, Ship::Type_Info_Flags::Turret_tgt_ship_tgt); } if(optional_string("$Max Debris Speed:")) { @@ -4831,19 +4833,19 @@ void parse_ship_type() } if(optional_string("$Beams Easily Hit:")) { - stuff_boolean_flag(&stp->weapon_bools, STI_WEAP_BEAMS_EASILY_HIT); + stuff_boolean_flag(stp->flags, Ship::Type_Info_Flags::Beams_easily_hit); } if(optional_string("$Protected on cripple:")) { - stuff_boolean_flag(&stp->ai_bools, STI_AI_PROTECTED_ON_CRIPPLE); + stuff_boolean_flag(stp->flags, Ship::Type_Info_Flags::AI_protected_on_cripple); } if(optional_string("$No Huge Beam Impact Effects:")) { - stuff_boolean_flag(&stp->weapon_bools, STI_WEAP_NO_HUGE_IMPACT_EFF); + stuff_boolean_flag(stp->flags, Ship::Type_Info_Flags::No_huge_impact_eff); } if(optional_string("$Don't display class in briefing:")) { - stuff_boolean_flag(&stp->hud_bools, STI_HUD_NO_CLASS_DISPLAY); + stuff_boolean_flag(stp->flags, Ship::Type_Info_Flags::No_class_display); } if(optional_string("$Fog:")) @@ -4864,7 +4866,7 @@ void parse_ship_type() } if(optional_string("+Accept Player Orders:")) { - stuff_boolean_flag(&stp->ai_bools, STI_AI_ACCEPT_PLAYER_ORDERS); + stuff_boolean_flag(stp->flags, Ship::Type_Info_Flags::AI_accept_player_orders); } if(optional_string("+Player Orders:")) { @@ -4872,11 +4874,11 @@ void parse_ship_type() } if(optional_string("+Auto attacks:")) { - stuff_boolean_flag(&stp->ai_bools, STI_AI_AUTO_ATTACKS); + stuff_boolean_flag(stp->flags, Ship::Type_Info_Flags::AI_auto_attacks); } if(optional_string("+Attempt broadside:")) { - stuff_boolean_flag(&stp->ai_bools, STI_AI_ATTEMPT_BROADSIDE); + stuff_boolean_flag(stp->flags, Ship::Type_Info_Flags::AI_attempt_broadside); } if(optional_string("+Actively Pursues:")) { @@ -4884,15 +4886,15 @@ void parse_ship_type() } if(optional_string("+Guards attack this:")) { - stuff_boolean_flag(&stp->ai_bools, STI_AI_GUARDS_ATTACK); + stuff_boolean_flag(stp->flags, Ship::Type_Info_Flags::AI_guards_attack); } if(optional_string("+Turrets attack this:")) { - stuff_boolean_flag(&stp->ai_bools, STI_AI_TURRETS_ATTACK); + stuff_boolean_flag(stp->flags, Ship::Type_Info_Flags::AI_turrets_attack); } if(optional_string("+Can form wing:")) { - stuff_boolean_flag(&stp->ai_bools, STI_AI_CAN_FORM_WING); + stuff_boolean_flag(stp->flags, Ship::Type_Info_Flags::AI_can_form_wing); } if(optional_string("+Active docks:")) { @@ -5199,7 +5201,7 @@ void ship_parse_post_cleanup() if (n_tgt_groups > 0) { for(i = 0; i < n_tgt_groups; i++) { - if (!(Ai_tp_list[i].obj_flags.any_set() || Ai_tp_list[i].sif_flags.any_set() || Ai_tp_list[i].wif_flags || Ai_tp_list[i].wif2_flags || Ai_tp_list[i].wif3_flags)) { + if (!(Ai_tp_list[i].obj_flags.any_set() || Ai_tp_list[i].sif_flags.any_set() || Ai_tp_list[i].wif_flags.any_set())) { //had none of these, check next if (Ai_tp_list[i].obj_type == -1) { //didn't have this one @@ -5888,7 +5890,7 @@ void ship::clear() lightning_stamp = timestamp(-1); // set awacs warning flags so awacs ship only asks for help once at each level - awacs_warning_flag = AWACS_WARN_NONE; + awacs_warning_flag.reset(); special_warpin_objnum = -1; special_warpout_objnum = -1; @@ -6229,58 +6231,58 @@ void ship_recalc_subsys_strength( ship *shipp ) //if a subsystem is brought back from the dead, other than this if(ship_system->current_hits > 0.0f) { - if(ship_system->subsys_snd_flags & SSSF_DEAD) - { - obj_snd_delete_type(shipp->objnum, ship_system->system_info->dead_snd, ship_system); - ship_system->subsys_snd_flags &= ~SSSF_DEAD; - } - if((ship_system->system_info->alive_snd != -1) && !(ship_system->subsys_snd_flags & SSSF_ALIVE)) - { - obj_snd_assign(shipp->objnum, ship_system->system_info->alive_snd, &ship_system->system_info->pnt, 0, OS_SUBSYS_ALIVE, ship_system); - ship_system->subsys_snd_flags |= SSSF_ALIVE; - } - if(!(ship_system->subsys_snd_flags & SSSF_TURRET_ROTATION)) - { - if(ship_system->system_info->turret_base_rotation_snd != -1) - { - obj_snd_assign(shipp->objnum, ship_system->system_info->turret_base_rotation_snd, &ship_system->system_info->pnt, 0, OS_TURRET_BASE_ROTATION, ship_system); - ship_system->subsys_snd_flags |= SSSF_TURRET_ROTATION; - } - if(ship_system->system_info->turret_gun_rotation_snd != -1) - { - obj_snd_assign(shipp->objnum, ship_system->system_info->turret_gun_rotation_snd, &ship_system->system_info->pnt, 0, OS_TURRET_GUN_ROTATION, ship_system); - ship_system->subsys_snd_flags |= SSSF_TURRET_ROTATION; - } - } - if((ship_system->flags[Ship::Subsystem_Flags::Rotates]) && (ship_system->system_info->rotation_snd != -1) && !(ship_system->subsys_snd_flags & SSSF_ROTATE)) - { - obj_snd_assign(shipp->objnum, ship_system->system_info->rotation_snd, &ship_system->system_info->pnt, 0, OS_SUBSYS_ROTATION, ship_system); - ship_system->subsys_snd_flags |= SSSF_ROTATE; - } + if (ship_system->subsys_snd_flags[Ship::Subsys_Sound_Flags::Dead]) + { + obj_snd_delete_type(shipp->objnum, ship_system->system_info->dead_snd, ship_system); + ship_system->subsys_snd_flags.set(Ship::Subsys_Sound_Flags::Dead, false); + } + if ((ship_system->system_info->alive_snd != -1) && !(ship_system->subsys_snd_flags[Ship::Subsys_Sound_Flags::Alive])) + { + obj_snd_assign(shipp->objnum, ship_system->system_info->alive_snd, &ship_system->system_info->pnt, 0, OS_SUBSYS_ALIVE, ship_system); + ship_system->subsys_snd_flags.set(Ship::Subsys_Sound_Flags::Alive); + } + if (!(ship_system->subsys_snd_flags[Ship::Subsys_Sound_Flags::Turret_rotation])) + { + if (ship_system->system_info->turret_base_rotation_snd != -1) + { + obj_snd_assign(shipp->objnum, ship_system->system_info->turret_base_rotation_snd, &ship_system->system_info->pnt, 0, OS_TURRET_BASE_ROTATION, ship_system); + ship_system->subsys_snd_flags.set(Ship::Subsys_Sound_Flags::Turret_rotation); + } + if (ship_system->system_info->turret_gun_rotation_snd != -1) + { + obj_snd_assign(shipp->objnum, ship_system->system_info->turret_gun_rotation_snd, &ship_system->system_info->pnt, 0, OS_TURRET_GUN_ROTATION, ship_system); + ship_system->subsys_snd_flags.set(Ship::Subsys_Sound_Flags::Turret_rotation); + } + } + if ((ship_system->flags[Subsystem_Flags::Rotates]) && (ship_system->system_info->rotation_snd != -1) && !(ship_system->subsys_snd_flags[Ship::Subsys_Sound_Flags::Rotate])) + { + obj_snd_assign(shipp->objnum, ship_system->system_info->rotation_snd, &ship_system->system_info->pnt, 0, OS_SUBSYS_ROTATION, ship_system); + ship_system->subsys_snd_flags.set(Ship::Subsys_Sound_Flags::Rotate); + } } else { - if(ship_system->subsys_snd_flags & SSSF_ALIVE) - { - obj_snd_delete_type(shipp->objnum, ship_system->system_info->alive_snd, ship_system); - ship_system->subsys_snd_flags &= ~SSSF_ALIVE; - } - if(ship_system->subsys_snd_flags & SSSF_TURRET_ROTATION) - { - obj_snd_delete_type(shipp->objnum, ship_system->system_info->turret_base_rotation_snd, ship_system); - obj_snd_delete_type(shipp->objnum, ship_system->system_info->turret_gun_rotation_snd, ship_system); - ship_system->subsys_snd_flags &= ~SSSF_TURRET_ROTATION; - } - if(ship_system->subsys_snd_flags & SSSF_ROTATE) - { - obj_snd_delete_type(shipp->objnum, ship_system->system_info->rotation_snd, ship_system); - ship_system->subsys_snd_flags &= ~SSSF_ROTATE; - } - if((ship_system->system_info->dead_snd != -1) && !(ship_system->subsys_snd_flags & SSSF_DEAD)) - { - obj_snd_assign(shipp->objnum, ship_system->system_info->dead_snd, &ship_system->system_info->pnt, 0, OS_SUBSYS_DEAD, ship_system); - ship_system->subsys_snd_flags |= SSSF_DEAD; - } + if (ship_system->subsys_snd_flags[Ship::Subsys_Sound_Flags::Alive]) + { + obj_snd_delete_type(shipp->objnum, ship_system->system_info->alive_snd, ship_system); + ship_system->subsys_snd_flags.set(Ship::Subsys_Sound_Flags::Alive, false);; + } + if (ship_system->subsys_snd_flags[Ship::Subsys_Sound_Flags::Turret_rotation]) + { + obj_snd_delete_type(shipp->objnum, ship_system->system_info->turret_base_rotation_snd, ship_system); + obj_snd_delete_type(shipp->objnum, ship_system->system_info->turret_gun_rotation_snd, ship_system); + ship_system->subsys_snd_flags.set(Ship::Subsys_Sound_Flags::Turret_rotation, false); + } + if (ship_system->subsys_snd_flags[Ship::Subsys_Sound_Flags::Rotate]) + { + obj_snd_delete_type(shipp->objnum, ship_system->system_info->rotation_snd, ship_system); + ship_system->subsys_snd_flags.set(Ship::Subsys_Sound_Flags::Rotate, false); + } + if ((ship_system->system_info->dead_snd != -1) && !(ship_system->subsys_snd_flags[Ship::Subsys_Sound_Flags::Dead])) + { + obj_snd_assign(shipp->objnum, ship_system->system_info->dead_snd, &ship_system->system_info->pnt, 0, OS_SUBSYS_DEAD, ship_system); + ship_system->subsys_snd_flags.set(Ship::Subsys_Sound_Flags::Dead, false); + } } } @@ -6403,7 +6405,7 @@ void ship_subsys::clear() base_rotation_rate_pct = 0.0f; gun_rotation_rate_pct = 0.0f; - subsys_snd_flags = 0; + subsys_snd_flags.reset(); rotation_timestamp = timestamp(0); @@ -6485,7 +6487,7 @@ int subsys_set(int objnum, int ignore_subsys_info) // zero flags ship_system->flags.reset(); ship_system->weapons.flags.reset(); - ship_system->subsys_snd_flags = 0; + ship_system->subsys_snd_flags.reset(); // Goober5000 if (model_system->flags & MSS_FLAG_UNTARGETABLE) @@ -7305,7 +7307,7 @@ void ship_wing_cleanup( int shipnum, wing *wingp ) // waves so we can mark the wing as gone and no other ships arrive // Goober5000 - also if it's departing... this is sort of, but not exactly, what :V: did; // but it seems to be consistent with how it should behave - if (wingp->flags & (WF_WING_DEPARTING | WF_DEPARTURE_ORDERED)) + if (wingp->flags[Ship::Wing_Flags::Departing, Ship::Wing_Flags::Departure_ordered]) wingp->current_wave = wingp->num_waves; // Goober5000 - some changes for clarity and closing holes @@ -7313,7 +7315,7 @@ void ship_wing_cleanup( int shipnum, wing *wingp ) if ((wingp->current_wave == wingp->num_waves) && (wingp->total_destroyed + wingp->total_departed + wingp->total_vanished == wingp->total_arrived_count)) { // mark the wing as gone - wingp->flags |= WF_WING_GONE; + wingp->flags.set(Ship::Wing_Flags::Gone); wingp->time_gone = Missiontime; // if all ships were destroyed, log it as destroyed @@ -7440,7 +7442,7 @@ void ship_cleanup(int shipnum, int cleanup_mode) // determine if we need to count this ship as a kill in counting number of kills per ship type // look at the ignore flag for the ship (if not in a wing), or the ignore flag for the wing // (if the ship is in a wing), and add to the kill count if the flags are not set - if ( !(shipp->flags[Ship_Flags::Ignore_count]) || ((shipp->wingnum != -1) && !(Wings[shipp->wingnum].flags & WF_IGNORE_COUNT)) ) + if ( !(shipp->flags[Ship_Flags::Ignore_count]) || ((shipp->wingnum != -1) && !(Wings[shipp->wingnum].flags[Ship::Wing_Flags::Ignore_count])) ) ship_add_ship_type_kill_count( shipp->ship_info_index ); // let the event music system know an enemy was destroyed (important for deciding when to transition from battle to normal music) @@ -9056,7 +9058,7 @@ void ship_set_default_weapons(ship *shipp, ship_info *sip) { wip = &Weapon_info[swp->primary_bank_weapons[i]]; - if ( wip->wi_flags2 & WIF2_BALLISTIC ) + if ( wip->wi_flags[Weapon::Info_Flags::Ballistic] ) { if (Fred_running){ swp->primary_bank_ammo[i] = 100; @@ -10372,7 +10374,7 @@ void ship_maybe_play_primary_fail_sound() if ( timestamp_elapsed(Laser_energy_out_snd_timer) ) { // check timestamp according to ballistics - if (Weapon_info[swp->primary_bank_weapons[swp->current_primary_bank]].wi_flags2 & WIF2_BALLISTIC) + if (Weapon_info[swp->primary_bank_weapons[swp->current_primary_bank]].wi_flags[Weapon::Info_Flags::Ballistic]) { stampval = 500; } @@ -10394,7 +10396,7 @@ int ship_maybe_play_secondary_fail_sound(weapon_info *wip) if ( timestamp_elapsed(Missile_out_snd_timer) ) { - if ( wip->wi_flags & WIF_SWARM ) { + if ( wip->wi_flags[Weapon::Info_Flags::Swarm] ) { Missile_out_snd_timer = timestamp(500); } else { Missile_out_snd_timer = timestamp(50); @@ -10735,17 +10737,17 @@ int ship_fire_primary(object * obj, int stream_weapons, int force) continue; } // if this is a targeting laser, start it up ///- only targeting laser if it is tag-c, otherwise it's a fighter beam -Bobboau - if((winfo_p->wi_flags & WIF_BEAM) && (winfo_p->tag_level == 3) && (shipp->flags[Ship_Flags::Trigger_down]) && (winfo_p->b_info.beam_type == BEAM_TYPE_C) ){ + if((winfo_p->wi_flags[Weapon::Info_Flags::Beam]) && (winfo_p->tag_level == 3) && (shipp->flags[Ship_Flags::Trigger_down]) && (winfo_p->b_info.beam_type == BEAM_TYPE_C) ){ ship_start_targeting_laser(shipp); continue; } // if we're firing stream weapons and this is a non stream weapon, skip it - if(stream_weapons && !(winfo_p->wi_flags & WIF_STREAM)){ + if(stream_weapons && !(winfo_p->wi_flags[Weapon::Info_Flags::Stream])){ continue; } // if we're firing non stream weapons and this is a stream weapon, skip it - if(!stream_weapons && (winfo_p->wi_flags & WIF_STREAM)){ + if(!stream_weapons && (winfo_p->wi_flags[Weapon::Info_Flags::Stream])){ continue; } @@ -10755,7 +10757,7 @@ int ship_fire_primary(object * obj, int stream_weapons, int force) } // if weapons are linked and this is a nolink weapon, skip it - if (shipp->flags[Ship_Flags::Primary_linked] && winfo_p->wi_flags3 & WIF3_NOLINK) { + if (shipp->flags[Ship_Flags::Primary_linked] && winfo_p->wi_flags[Weapon::Info_Flags::Nolink]) { continue; } @@ -10765,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; @@ -10784,12 +10786,12 @@ 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_flags3 & WIF3_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 & AIPF_DISABLE_LINKED_FIRE_PENALTY) ) { int effective_primary_banks = 0; for (int it = 0; it < num_primary_banks; it++) { - if ((it == bank_to_fire) || !(Weapon_info[swp->primary_bank_weapons[it]].wi_flags3 & (WIF3_NOLINK | WIF3_NO_LINKED_PENALTY))) + if ((it == bank_to_fire) || !(Weapon_info[swp->primary_bank_weapons[it]].wi_flags[Weapon::Info_Flags::Nolink, Weapon::Info_Flags::No_linked_penalty])) effective_primary_banks++; } Assert(effective_primary_banks >= 1); @@ -10835,7 +10837,7 @@ int ship_fire_primary(object * obj, int stream_weapons, int force) Assert(pm->gun_banks[bank_to_fire].num_slots != 0); swp->next_primary_fire_stamp[bank_to_fire] = timestamp((int)(next_fire_delay * ( swp->primary_bank_slot_count[ bank_to_fire ] ) / pm->gun_banks[bank_to_fire].num_slots ) ); swp->last_primary_fire_stamp[bank_to_fire] = timestamp(); - } else if (winfo_p->wi_flags2 & WIF2_CYCLE) { + } else if (winfo_p->wi_flags[Weapon::Info_Flags::Cycle]) { Assert(pm->gun_banks[bank_to_fire].num_slots != 0); swp->next_primary_fire_stamp[bank_to_fire] = timestamp((int)(next_fire_delay / pm->gun_banks[bank_to_fire].num_slots)); swp->last_primary_fire_stamp[bank_to_fire] = timestamp(); @@ -10896,7 +10898,7 @@ int ship_fire_primary(object * obj, int stream_weapons, int force) } } - if(winfo_p->wi_flags & WIF_BEAM){ // the big change I made for fighter beams, if there beams fill out the Fire_Info for a targeting laser then fire it, for each point in the weapon bank -Bobboau + if(winfo_p->wi_flags[Weapon::Info_Flags::Beam]){ // the big change I made for fighter beams, if there beams fill out the Fire_Info for a targeting laser then fire it, for each point in the weapon bank -Bobboau float t; if (winfo_p->burst_shots > swp->burst_counter[bank_to_fire]) { t = winfo_p->burst_delay; @@ -10986,7 +10988,7 @@ int ship_fire_primary(object * obj, int stream_weapons, int force) if ( sip->flags[Ship::Info_Flags::Dyn_primary_linking] ) { numtimes = 1; points = MIN( num_slots, swp->primary_bank_slot_count[ bank_to_fire ] ); - } else if ( winfo_p->wi_flags2 & WIF2_CYCLE ) { + } else if ( winfo_p->wi_flags[Weapon::Info_Flags::Cycle] ) { numtimes = 1; points = MIN(num_slots, winfo_p->shots); } else { @@ -11014,7 +11016,7 @@ int ship_fire_primary(object * obj, int stream_weapons, int force) // moved the above to here to use points instead of num_slots for energy consumption check // ballistics support for primaries - Goober5000 - if ( winfo_p->wi_flags2 & WIF2_BALLISTIC ) + 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. @@ -11078,7 +11080,7 @@ int ship_fire_primary(object * obj, int stream_weapons, int force) vec3d *firepoint_list; size_t current_firepoint = 0; - if (winfo_p->wi_flags3 & WIF3_APPLY_RECOIL){ + if (winfo_p->wi_flags[Weapon::Info_Flags::Apply_recoil]){ firepoint_list = new vec3d[numtimes * points]; vm_vec_zero(&total_impulse); } else { @@ -11096,7 +11098,7 @@ int ship_fire_primary(object * obj, int stream_weapons, int force) for ( j = 0; j < points; j++ ) { int pt; //point - if ( (winfo_p->wi_flags2 & WIF2_CYCLE) || (sip->flags[Ship::Info_Flags::Dyn_primary_linking]) ){ + if ( (winfo_p->wi_flags[Weapon::Info_Flags::Cycle]) || (sip->flags[Ship::Info_Flags::Dyn_primary_linking]) ){ pt = (shipp->last_fired_point[bank_to_fire]+1)%num_slots; }else{ pt = j; @@ -11105,14 +11107,14 @@ int ship_fire_primary(object * obj, int stream_weapons, int force) int sub_shots = 1; // Use 0 instead of bank_to_fire as index when checking the number of external weapon model firingpoints if (weapon_model && weapon_model->n_guns) - if (!(winfo_p->wi_flags2 & WIF2_EXTERNAL_WEAPON_FP)) + if (!(winfo_p->wi_flags[Weapon::Info_Flags::External_weapon_fp])) sub_shots = weapon_model->gun_banks[0].num_slots; for(int s = 0; sgun_banks[bank_to_fire].pnt[pt]; // Use 0 instead of bank_to_fire as index to external weapon model firingpoints if (weapon_model && weapon_model->n_guns) { - if (winfo_p->wi_flags2 & WIF2_EXTERNAL_WEAPON_FP) { + if (winfo_p->wi_flags[Weapon::Info_Flags::External_weapon_fp]) { vm_vec_add2(&pnt, &weapon_model->gun_banks[0].pnt[swp->external_model_fp_counter[bank_to_fire]]); } else { vm_vec_add2(&pnt, &weapon_model->gun_banks[0].pnt[s]); @@ -11178,7 +11180,7 @@ int ship_fire_primary(object * obj, int stream_weapons, int force) firing_orient = obj->orient; } - if (winfo_p->wi_flags3 & WIF3_APPLY_RECOIL){ // Function to add recoil functionality - DahBlount + if (winfo_p->wi_flags[Weapon::Info_Flags::Apply_recoil]){ // Function to add recoil functionality - DahBlount vec3d local_impulse = firing_orient.vec.fvec; float recoil_force = (winfo_p->mass * winfo_p->max_speed * winfo_p->recoil_modifier * sip->ship_recoil_modifier); @@ -11198,7 +11200,7 @@ int ship_fire_primary(object * obj, int stream_weapons, int force) weapon_set_tracking_info(weapon_objnum, OBJ_INDEX(obj), aip->target_objnum, aip->current_target_is_locked, aip->targeted_subsys); - if (winfo_p->wi_flags & WIF_FLAK) + if (winfo_p->wi_flags[Weapon::Info_Flags::Flak]) { object *target; vec3d predicted_pos; @@ -11240,7 +11242,7 @@ int ship_fire_primary(object * obj, int stream_weapons, int force) } // maybe shudder the ship - if its me - if((winfo_p->wi_flags & WIF_SHUDDER) && (obj == Player_obj) && !(Game_mode & GM_STANDALONE_SERVER)){ + if((winfo_p->wi_flags[Weapon::Info_Flags::Shudder]) && (obj == Player_obj) && !(Game_mode & GM_STANDALONE_SERVER)){ // calculate some arbitrary value between 100 // (mass * velocity) / 10 game_shudder_apply(500, (winfo_p->mass * winfo_p->max_speed) * 0.1f); @@ -11252,7 +11254,7 @@ int ship_fire_primary(object * obj, int stream_weapons, int force) } swp->external_model_fp_counter[bank_to_fire]++; } - if (winfo_p->wi_flags3 & WIF3_APPLY_RECOIL){ + if (winfo_p->wi_flags[Weapon::Info_Flags::Apply_recoil]){ vec3d avg_firepoint; vm_vec_avg_n(&avg_firepoint, current_firepoint, firepoint_list); @@ -11272,7 +11274,7 @@ int ship_fire_primary(object * obj, int stream_weapons, int force) // avoid playing the same sound multiple times when banks are linked with the // same weapon. - if (!(winfo_p->wi_flags & WIF_BEAM)){ // not a beam weapon? + if (!(winfo_p->wi_flags[Weapon::Info_Flags::Beam])){ // not a beam weapon? if ( sound_played != winfo_p->launch_snd ) { sound_played = winfo_p->launch_snd; if ( obj == Player_obj ) { @@ -11307,7 +11309,7 @@ int ship_fire_primary(object * obj, int stream_weapons, int force) int force_level = (int) ((wip->armor_factor + wip->shield_factor * 0.2f) * (wip->damage * wip->damage - 7.5f) * 0.45f + 0.6f) * 10 + 2000; // modify force feedback for ballistics: make it stronger - if (wip->wi_flags2 & WIF2_BALLISTIC) + if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) joy_ff_play_primary_shoot(force_level * 2); // no ballistics else @@ -11378,10 +11380,10 @@ void ship_start_targeting_laser(ship *shipp) int bank1_laser = 0; // determine if either of our banks have a targeting laser - if((shipp->weapons.primary_bank_weapons[0] >= 0) && (Weapon_info[shipp->weapons.primary_bank_weapons[0]].wi_flags & WIF_BEAM) && (Weapon_info[shipp->weapons.primary_bank_weapons[0]].b_info.beam_type == BEAM_TYPE_C)){ + if((shipp->weapons.primary_bank_weapons[0] >= 0) && (Weapon_info[shipp->weapons.primary_bank_weapons[0]].wi_flags[Weapon::Info_Flags::Beam]) && (Weapon_info[shipp->weapons.primary_bank_weapons[0]].b_info.beam_type == BEAM_TYPE_C)){ bank0_laser = 1; } - if((shipp->weapons.primary_bank_weapons[1] >= 0) && (Weapon_info[shipp->weapons.primary_bank_weapons[1]].wi_flags & WIF_BEAM) && (Weapon_info[shipp->weapons.primary_bank_weapons[1]].b_info.beam_type == BEAM_TYPE_C)){ + if((shipp->weapons.primary_bank_weapons[1] >= 0) && (Weapon_info[shipp->weapons.primary_bank_weapons[1]].wi_flags[Weapon::Info_Flags::Beam]) && (Weapon_info[shipp->weapons.primary_bank_weapons[1]].b_info.beam_type == BEAM_TYPE_C)){ bank1_laser = 1; } @@ -11512,7 +11514,7 @@ int maybe_detonate_weapon(ship_weapon *swp, object *src) Assert(Weapons[objp->instance].weapon_info_index != -1); wip = &Weapon_info[Weapons[objp->instance].weapon_info_index]; - if (wip->wi_flags & WIF_REMOTE) { + if (wip->wi_flags[Weapon::Info_Flags::Remote]) { int weapon_sig; @@ -11548,7 +11550,7 @@ int ship_fire_secondary_detonate(object *obj, ship_weapon *swp) Assert(mo->objnum >= 0 && mo->objnum < MAX_OBJECTS); mobjp = &Objects[mo->objnum]; if ((mobjp != first_objp) && (mobjp->parent_sig == obj->parent_sig)) { - if (Weapon_info[Weapons[mobjp->instance].weapon_info_index].wi_flags & WIF_REMOTE) { + if (Weapon_info[Weapons[mobjp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Remote]) { weapon_detonate(mobjp); } } @@ -11729,14 +11731,14 @@ int ship_fire_secondary( object *obj, int allow_swarm ) } // Ensure if this is a "require-lock" missile, that a lock actually exists - if ( wip->wi_flags & WIF_NO_DUMBFIRE ) { + if ( wip->wi_flags[Weapon::Info_Flags::No_dumbfire] ) { if ( aip->current_target_is_locked <= 0 ) { if ( obj == Player_obj ) { if ( !Weapon_energy_cheat ) { float max_dist; max_dist = wip->lifetime * wip->max_speed; - if (wip->wi_flags2 & WIF2_LOCAL_SSM){ + if (wip->wi_flags[Weapon::Info_Flags::Local_ssm]){ max_dist= wip->lssm_lock_range; } @@ -11763,7 +11765,7 @@ int ship_fire_secondary( object *obj, int allow_swarm ) } } - if (wip->wi_flags2 & WIF2_TAGGED_ONLY) + if (wip->wi_flags[Weapon::Info_Flags::Tagged_only]) { if (!ship_is_tagged(&Objects[aip->target_objnum])) { @@ -11790,7 +11792,7 @@ int ship_fire_secondary( object *obj, int allow_swarm ) // if trying to fire a swarm missile, make sure being called from right place - if ( (wip->wi_flags & WIF_SWARM) && !allow_swarm ) { + if ( (wip->wi_flags[Weapon::Info_Flags::Swarm]) && !allow_swarm ) { Assert(wip->swarm_count > 0); if(wip->swarm_count <= 0){ shipp->num_swarm_missiles_to_fire = SWARM_DEFAULT_NUM_MISSILES_FIRED; @@ -11802,7 +11804,7 @@ int ship_fire_secondary( object *obj, int allow_swarm ) } // if trying to fire a corkscrew missile, make sure being called from right place - if ( (wip->wi_flags & WIF_CORKSCREW) && !allow_swarm ) { + if ( (wip->wi_flags[Weapon::Info_Flags::Corkscrew]) && !allow_swarm ) { //phreak 11-9-02 //changed this from 4 to custom number defined in tables shipp->num_corkscrew_to_fire = (ubyte)(shipp->num_corkscrew_to_fire + (ubyte)wip->cs_num_fired); @@ -11911,7 +11913,7 @@ int ship_fire_secondary( object *obj, int allow_swarm ) if (weapon_model && weapon_model->n_guns) { int external_bank = bank + MAX_SHIP_PRIMARY_BANKS; - if (wip->wi_flags2 & WIF2_EXTERNAL_WEAPON_FP) { + if (wip->wi_flags[Weapon::Info_Flags::External_weapon_fp]) { if ((weapon_model->n_guns <= swp->external_model_fp_counter[external_bank]) || (swp->external_model_fp_counter[external_bank] < 0)) swp->external_model_fp_counter[external_bank] = 0; vm_vec_add2(&pnt, &weapon_model->gun_banks[0].pnt[swp->external_model_fp_counter[external_bank]]); @@ -11955,7 +11957,7 @@ int ship_fire_secondary( object *obj, int allow_swarm ) shipfx_flash_create(obj, sip->model_num, &pnt, &obj->orient.vec.fvec, 0, weapon_idx); } - if((wip->wi_flags & WIF_SHUDDER) && (obj == Player_obj) && !(Game_mode & GM_STANDALONE_SERVER)){ + if((wip->wi_flags[Weapon::Info_Flags::Shudder]) && (obj == Player_obj) && !(Game_mode & GM_STANDALONE_SERVER)){ // calculate some arbitrary value between 100 // (mass * velocity) / 10 game_shudder_apply(500, (wip->mass * wip->max_speed) * 0.1f); @@ -12100,7 +12102,7 @@ int primary_out_of_ammo(ship_weapon *swp, int bank) // true if both ballistic and ammo <= 0, // false if not ballistic or if ballistic and ammo > 0 - if ( Weapon_info[swp->primary_bank_weapons[bank]].wi_flags2 & WIF2_BALLISTIC ) + if ( Weapon_info[swp->primary_bank_weapons[bank]].wi_flags[Weapon::Info_Flags::Ballistic] ) { if (swp->primary_bank_ammo[bank] <= 0) { @@ -13398,7 +13400,7 @@ float ship_calculate_rearm_duration( object *objp ) for (i = 0; i < swp->num_primary_banks; i++) { wip = &Weapon_info[swp->primary_bank_weapons[i]]; - if (wip->wi_flags2 & WIF2_BALLISTIC) + 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; @@ -13665,14 +13667,14 @@ int ship_do_rearm_frame( object *objp, float frametime ) { for (i = 1; 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] ) last_ballistic_idx = i; } } for (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] ) { // Actual loading of bullets is preceded by a sound effect which is the bullet // loading equipment moving into place @@ -14031,22 +14033,22 @@ void ship_assign_sound(ship *sp) if(moveup->system_info->alive_snd != -1) { obj_snd_assign(sp->objnum, moveup->system_info->alive_snd, &moveup->system_info->pnt, 0, OS_SUBSYS_ALIVE, moveup); - moveup->subsys_snd_flags |= SSSF_ALIVE; + moveup->subsys_snd_flags.set(Ship::Subsys_Sound_Flags::Alive); } if(moveup->system_info->turret_base_rotation_snd != -1) { obj_snd_assign(sp->objnum, moveup->system_info->turret_base_rotation_snd, &moveup->system_info->pnt, 0, OS_TURRET_BASE_ROTATION, moveup); - moveup->subsys_snd_flags |= SSSF_TURRET_ROTATION; + moveup->subsys_snd_flags.set(Ship::Subsys_Sound_Flags::Turret_rotation); } if(moveup->system_info->turret_gun_rotation_snd != -1) { obj_snd_assign(sp->objnum, moveup->system_info->turret_gun_rotation_snd, &moveup->system_info->pnt, 0, OS_TURRET_GUN_ROTATION, moveup); - moveup->subsys_snd_flags |= SSSF_TURRET_ROTATION; + moveup->subsys_snd_flags.set(Ship::Subsys_Sound_Flags::Turret_rotation); } if((moveup->system_info->rotation_snd != -1) && (moveup->flags[Ship::Subsystem_Flags::Rotates])) { obj_snd_assign(sp->objnum, moveup->system_info->rotation_snd, &moveup->system_info->pnt, 0, OS_SUBSYS_ROTATION, moveup); - moveup->subsys_snd_flags |= SSSF_ROTATE; + moveup->subsys_snd_flags.set(Ship::Subsys_Sound_Flags::Rotate); } } else @@ -14054,7 +14056,7 @@ void ship_assign_sound(ship *sp) if(moveup->system_info->dead_snd != -1) { obj_snd_assign(sp->objnum, moveup->system_info->dead_snd, &moveup->system_info->pnt, 0, OS_SUBSYS_DEAD, moveup); - moveup->subsys_snd_flags |= SSSF_DEAD; + moveup->subsys_snd_flags.set(Ship::Subsys_Sound_Flags::Dead); } } @@ -14920,7 +14922,7 @@ int ship_has_homing_missile_locked(ship *shipp) if ( wip->subtype != WP_MISSILE ) continue; - if ( !(wip->wi_flags & WIF_HOMING ) ) + if ( !(wip->is_homing() ) ) continue; if (wp->homing_object == locked_objp) { @@ -15362,7 +15364,7 @@ void ship_maybe_praise_player(ship *deader_sp) } // don't praise the destruction of navbuoys, cargo or other non-flyable ship types - if ( (Ship_info[deader_sp->ship_info_index].class_type > 0) && !(Ship_types[Ship_info[deader_sp->ship_info_index].class_type].message_bools & STI_MSG_PRAISE_DESTRUCTION) ) { + if ((Ship_info[deader_sp->ship_info_index].class_type > 0) && !(Ship_types[Ship_info[deader_sp->ship_info_index].class_type].flags[Ship::Type_Info_Flags::Praise_destruction])) { return; } @@ -15418,7 +15420,7 @@ void ship_maybe_praise_self(ship *deader_sp, ship *killer_sp) } // don't praise the destruction of navbuoys, cargo or other non-flyable ship types - if ( (Ship_info[deader_sp->ship_info_index].class_type > 0) && !(Ship_types[Ship_info[deader_sp->ship_info_index].class_type].message_bools & STI_MSG_PRAISE_DESTRUCTION) ) { + if ( (Ship_info[deader_sp->ship_info_index].class_type > 0) && !(Ship_types[Ship_info[deader_sp->ship_info_index].class_type].flags[Ship::Type_Info_Flags::Praise_destruction]) ) { return; } @@ -15451,15 +15453,15 @@ void awacs_maybe_ask_for_help(ship *sp, int multi_team_filter) if ( objp->hull_strength < ( (AWACS_HELP_HULL_LOW + 0.01f *(static_rand(objp-Objects) & 5)) * sp->ship_max_hull_strength) ) { // awacs ship below 25 + (0-4) % - if (!(sp->awacs_warning_flag & AWACS_WARN_25)) { + if (!(sp->awacs_warning_flag[Ship::Awacs_Warning_Flags::Warn_25])) { message = MESSAGE_AWACS_25; - sp->awacs_warning_flag |= AWACS_WARN_25; + sp->awacs_warning_flag.set(Ship::Awacs_Warning_Flags::Warn_25); } } else if ( objp->hull_strength < ( (AWACS_HELP_HULL_HI + 0.01f*(static_rand(objp-Objects) & 5)) * sp->ship_max_hull_strength) ) { // awacs ship below 75 + (0-4) % - if (!(sp->awacs_warning_flag & AWACS_WARN_75)) { + if (!(sp->awacs_warning_flag[Ship::Awacs_Warning_Flags::Warn_75])) { message = MESSAGE_AWACS_75; - sp->awacs_warning_flag |= AWACS_WARN_75; + sp->awacs_warning_flag.set(Ship::Awacs_Warning_Flags::Warn_75); } } @@ -15684,7 +15686,7 @@ void ship_maybe_tell_about_low_ammo(ship *sp) { wip = &Weapon_info[swp->primary_bank_weapons[i]]; - if (wip->wi_flags2 & WIF2_BALLISTIC) + if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) { if (swp->primary_bank_start_ammo[i] > 0) { @@ -15765,7 +15767,7 @@ void ship_maybe_tell_about_rearm(ship *sp) { wip = &Weapon_info[swp->primary_bank_weapons[i]]; - if (wip->wi_flags2 & WIF2_BALLISTIC) + if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) { if (swp->primary_bank_start_ammo[i] > 0) { @@ -16991,8 +16993,8 @@ void ship_update_artillery_lock() if(shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank] < 0){ continue; } - Assert((Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].wi_flags & WIF_BEAM) && (Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].b_info.beam_type == BEAM_TYPE_C)); - if(!(Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].wi_flags & WIF_BEAM) || (Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].b_info.beam_type != BEAM_TYPE_C)){ + Assert((Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].wi_flags[Weapon::Info_Flags::Beam]) && (Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].b_info.beam_type == BEAM_TYPE_C)); + if(!(Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].wi_flags[Weapon::Info_Flags::Beam]) || (Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].b_info.beam_type != BEAM_TYPE_C)){ continue; } @@ -18302,19 +18304,13 @@ void parse_ai_target_priorities() num_strings = stuff_string_list(temp_strings); for (i = 0; i < num_strings; i++) { - for (j = 0; j < num_ai_tgt_weapon_flags; j++) { + for (j = 0; j < num_ai_tgt_weapon_info_flags; j++) { if ( !stricmp(ai_tgt_weapon_flags[j].name, temp_strings[i].c_str()) ) { - if (ai_tgt_weapon_flags[j].var == 0) { - temp_priority.wif_flags |= ai_tgt_weapon_flags[j].def; - } else if (ai_tgt_weapon_flags[j].var == 1) { - temp_priority.wif2_flags |= ai_tgt_weapon_flags[j].def; - } else { - temp_priority.wif3_flags |= ai_tgt_weapon_flags[j].def; - } + temp_priority.wif_flags |= ai_tgt_weapon_flags[j].def; break; } } - if (j == num_ai_tgt_weapon_flags) { + if (j == num_ai_tgt_weapon_info_flags) { Warning(LOCATION, "Unidentified weapon class flag '%s' set for target priority group '%s'\n", temp_strings[i].c_str(), temp_priority.name); } } @@ -18340,9 +18336,7 @@ ai_target_priority init_ai_target_priorities() temp_priority.ship_type.clear(); temp_priority.sif_flags.reset(); temp_priority.weapon_class.clear(); - temp_priority.wif_flags = 0; - temp_priority.wif2_flags = 0; - temp_priority.wif3_flags = 0; + temp_priority.wif_flags.reset(); temp_priority.name[0] = '\0'; //return the initialized @@ -18542,32 +18536,32 @@ void ship_render_batch_thrusters(object *obj) vec3d des_vel; vm_vec_rotate(&des_vel, &pi->desired_vel, &obj->orient); - if(pi->desired_rotvel.xyz.x < 0 && (mtp->use_flags & MT_PITCH_UP)) { + if(pi->desired_rotvel.xyz.x < 0 && (mtp->use_flags[Ship::Thruster_Flags::Pitch_up])) { render_amount = fl_abs(pi->desired_rotvel.xyz.x) / pi->max_rotvel.xyz.x; - } else if(pi->desired_rotvel.xyz.x > 0 && (mtp->use_flags & MT_PITCH_DOWN)) { + } else if(pi->desired_rotvel.xyz.x > 0 && (mtp->use_flags[Ship::Thruster_Flags::Pitch_down])) { render_amount = fl_abs(pi->desired_rotvel.xyz.x) / pi->max_rotvel.xyz.x; - } else if(pi->desired_rotvel.xyz.y < 0 && (mtp->use_flags & MT_ROLL_RIGHT)) { + } else if(pi->desired_rotvel.xyz.y < 0 && (mtp->use_flags[Ship::Thruster_Flags::Roll_right])) { render_amount = fl_abs(pi->desired_rotvel.xyz.y) / pi->max_rotvel.xyz.y; - } else if(pi->desired_rotvel.xyz.y > 0 && (mtp->use_flags & MT_ROLL_LEFT)) { + } else if(pi->desired_rotvel.xyz.y > 0 && (mtp->use_flags[Ship::Thruster_Flags::Roll_left])) { render_amount = fl_abs(pi->desired_rotvel.xyz.y) / pi->max_rotvel.xyz.y; - } else if(pi->desired_rotvel.xyz.z < 0 && (mtp->use_flags & MT_BANK_RIGHT)) { + } else if(pi->desired_rotvel.xyz.z < 0 && (mtp->use_flags[Ship::Thruster_Flags::Bank_right])) { render_amount = fl_abs(pi->desired_rotvel.xyz.z) / pi->max_rotvel.xyz.z; - } else if(pi->desired_rotvel.xyz.z > 0 && (mtp->use_flags & MT_BANK_LEFT)) { + } else if(pi->desired_rotvel.xyz.z > 0 && (mtp->use_flags[Ship::Thruster_Flags::Bank_left])) { render_amount = fl_abs(pi->desired_rotvel.xyz.z) / pi->max_rotvel.xyz.z; } //Backslash - show thrusters according to thrust amount, not speed - if(pi->side_thrust > 0 && (mtp->use_flags & MT_SLIDE_RIGHT)) { + if(pi->side_thrust > 0 && (mtp->use_flags[Ship::Thruster_Flags::Slide_right])) { render_amount = pi->side_thrust; - } else if(pi->side_thrust < 0 && (mtp->use_flags & MT_SLIDE_LEFT)) { + } else if(pi->side_thrust < 0 && (mtp->use_flags[Ship::Thruster_Flags::Slide_left])) { render_amount = -pi->side_thrust; - } else if(pi->vert_thrust > 0 && (mtp->use_flags & MT_SLIDE_UP)) { + } else if(pi->vert_thrust > 0 && (mtp->use_flags[Ship::Thruster_Flags::Slide_up])) { render_amount = pi->vert_thrust; - } else if(pi->vert_thrust < 0 && (mtp->use_flags & MT_SLIDE_DOWN)) { + } else if(pi->vert_thrust < 0 && (mtp->use_flags[Ship::Thruster_Flags::Slide_down])) { render_amount = -pi->vert_thrust; - } else if(pi->forward_thrust > 0 && (mtp->use_flags & MT_FORWARD)) { + } else if(pi->forward_thrust > 0 && (mtp->use_flags[Ship::Thruster_Flags::Forward])) { render_amount = pi->forward_thrust; - } else if(pi->forward_thrust < 0 && (mtp->use_flags & MT_REVERSE)) { + } else if(pi->forward_thrust < 0 && (mtp->use_flags[Ship::Thruster_Flags::Reverse])) { render_amount = -pi->forward_thrust; } @@ -18701,7 +18695,7 @@ void ship_render_weapon_models(model_render_params *ship_render_info, draw_list bank = &(model_get(sip->model_num))->missile_banks[i]; - if (Weapon_info[swp->secondary_bank_weapons[i]].wi_flags2 & WIF2_EXTERNAL_WEAPON_LNCH) { + if (Weapon_info[swp->secondary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::External_weapon_lnch]) { for(k = 0; k < bank->num_slots; k++) { render_info.set_flags(render_flags); diff --git a/code/ship/ship.h b/code/ship/ship.h index 1a90c3ac1e..7d4dde8fe4 100644 --- a/code/ship/ship.h +++ b/code/ship/ship.h @@ -31,6 +31,7 @@ #include "weapon/shockwave.h" #include "weapon/trails.h" #include "ship/ship_flags.h" +#include "weapon/weapon_flags.h" #include @@ -274,35 +275,6 @@ typedef struct cockpit_display_info { int size[2]; } cockpit_display_info; -// Goober5000 -#define SSF_CARGO_REVEALED (1 << 0) -#define SSF_UNTARGETABLE (1 << 1) -#define SSF_NO_SS_TARGETING (1 << 2) - -//nuke -#define SSF_HAS_FIRED (1 << 3) //used by scripting to flag a turret as having been fired -#define SSF_FOV_REQUIRED (1 << 4) -#define SSF_FOV_EDGE_CHECK (1 << 5) - -#define SSF_NO_REPLACE (1 << 6) // prevents 'destroyed' submodel from being rendered if subsys is destroyed. -#define SSF_NO_LIVE_DEBRIS (1 << 7) // prevents subsystem from generating live debris -#define SSF_VANISHED (1 << 8) // allows subsystem to be made to disappear without a trace (for swapping it for a true model for example. -#define SSF_MISSILES_IGNORE_IF_DEAD (1 << 9) // forces homing missiles to target hull if subsystem is dead before missile hits it. -#define SSF_ROTATES (1 << 10) -#define SSF_DAMAGE_AS_HULL (1 << 11) // Applies armor damage instead of subsystem damge. - FUBAR -#define SSF_NO_AGGREGATE (1 << 12) // exclude this subsystem from the aggregate subsystem-info tracking - Goober5000 -#define SSF_PLAY_SOUND_FOR_PLAYER ( 1 << 13) // If this subsystem is a turret on a player ship, play firing sounds - The E -#define SSF_NO_DISAPPEAR ( 1 << 14) // prevents submodel from disappearing when subsys destroyed -#define SSF_AUTOREPAIR_IF_DISABLED (1 << 15) // Allows the subsystem to repair itself even when disabled - MageKing17 -#define SSF_NO_AUTOREPAIR_IF_DISABLED (1 << 16) // Inversion of the above; allow a specific subsystem not to repair itself after being disabled if the ship has the "repair disabled subsystems" flag - MageKing17 - - -// Wanderer -#define SSSF_ALIVE (1 << 0) // subsystem has active alive sound -#define SSSF_DEAD (1 << 1) // subsystem has active dead sound -#define SSSF_ROTATE (1 << 2) // subsystem has active rotation sound -#define SSSF_TURRET_ROTATION (1 << 3) // rotation sound to be scaled like turrets do - // structure definition for a linked list of subsystems for a ship. Each subsystem has a pointer // to the static data for the subsystem. The obj_subsystem data is defined and read in the model // code. Other dynamic data (such as current_hits) should remain in this structure. @@ -379,7 +351,7 @@ public: float gun_rotation_rate_pct; // still going through these... - int subsys_snd_flags; + flagset subsys_snd_flags; int rotation_timestamp; matrix world_to_turret_matrix; @@ -442,10 +414,6 @@ typedef struct ship_spark { int end_time; } ship_spark; -#define AWACS_WARN_NONE (1 << 0) -#define AWACS_WARN_25 (1 << 1) -#define AWACS_WARN_75 (1 << 2) - // NOTE: Can't be treated as a struct anymore, since it has STL data structures in its object tree! class ship { @@ -649,7 +617,7 @@ public: int lightning_stamp; // AWACS warning flag - ubyte awacs_warning_flag; + flagset awacs_warning_flag; // Special warp objnum (warping at knossos) int special_warpin_objnum; @@ -735,9 +703,9 @@ public: void clear(); //Helper functions - inline bool is_arriving() { return flags[Ship::Ship_Flags::Arriving_stage_1] || flags[Ship::Ship_Flags::Arriving_stage_2]; } - inline bool is_departing() { return flags[Ship::Ship_Flags::Depart_warp] || flags[Ship::Ship_Flags::Depart_dockbay]; } - inline bool cannot_warp() { return flags[Ship::Ship_Flags::Warp_broken] || flags[Ship::Ship_Flags::Warp_never] || flags[Ship::Ship_Flags::Disabled]; } + inline bool is_arriving() { return flags[Ship::Ship_Flags::Arriving_stage_1, Ship::Ship_Flags::Arriving_stage_2]; } + inline bool is_departing() { return flags[Ship::Ship_Flags::Depart_warp, Ship::Ship_Flags::Depart_dockbay]; } + inline bool cannot_warp() { return flags[Ship::Ship_Flags::Warp_broken, Ship::Ship_Flags::Warp_never, Ship::Ship_Flags::Disabled]; } inline bool is_dying_or_departing() { return is_departing() || flags[Ship::Ship_Flags::Dying]; } }; @@ -751,9 +719,7 @@ struct ai_target_priority { flagset obj_flags; flagset sif_flags; - int wif_flags; - int wif2_flags; - int wif3_flags; + flagset wif_flags; }; extern SCP_vector Ai_tp_list; @@ -789,12 +755,6 @@ extern int ship_find_exited_ship_by_signature( int signature); #define REGULAR_WEAPON (1<<0) #define DOGFIGHT_WEAPON (1<<1) -#define AIM_FLAG_AUTOAIM (1 << 0) // has autoaim -#define AIM_FLAG_AUTO_CONVERGENCE (1 << 1) // has automatic convergence -#define AIM_FLAG_STD_CONVERGENCE (1 << 2) // has standard - ie. non-automatic - convergence -#define AIM_FLAG_AUTOAIM_CONVERGENCE (1 << 3) // has autoaim with convergence -#define AIM_FLAG_CONVERGENCE_OFFSET (1 << 4) // marks that convergence has offset value - typedef struct thruster_particles { generic_anim thruster_bitmap; float min_rad; @@ -816,45 +776,13 @@ typedef struct particle_effect { float variance; } particle_effect; -#define STI_MSG_COUNTS_FOR_ALONE (1<<0) -#define STI_MSG_PRAISE_DESTRUCTION (1<<1) - -#define STI_HUD_HOTKEY_ON_LIST (1<<0) -#define STI_HUD_TARGET_AS_THREAT (1<<1) -#define STI_HUD_SHOW_ATTACK_DIRECTION (1<<2) -#define STI_HUD_NO_CLASS_DISPLAY (1<<3) - -#define STI_SHIP_SCANNABLE (1<<0) -#define STI_SHIP_WARP_PUSHES (1<<1) -#define STI_SHIP_WARP_PUSHABLE (1<<2) -#define STI_TURRET_TGT_SHIP_TGT (1<<3) - -#define STI_WEAP_BEAMS_EASILY_HIT (1<<0) -#define STI_WEAP_NO_HUGE_IMPACT_EFF (1<<1) - -#define STI_AI_ACCEPT_PLAYER_ORDERS (1<<0) -#define STI_AI_AUTO_ATTACKS (1<<1) -#define STI_AI_ATTEMPT_BROADSIDE (1<<2) -#define STI_AI_GUARDS_ATTACK (1<<3) -#define STI_AI_TURRETS_ATTACK (1<<4) -#define STI_AI_CAN_FORM_WING (1<<5) -#define STI_AI_PROTECTED_ON_CRIPPLE (1<<6) - typedef struct ship_type_info { char name[NAME_LENGTH]; - //Messaging? - int message_bools; + flagset flags; - //HUD - int hud_bools; - - //Ship - int ship_bools; //For lack of better term float debris_max_speed; - //Weapons - int weapon_bools; float ff_multiplier; float emp_multiplier; @@ -865,7 +793,6 @@ typedef struct ship_type_info { //AI int ai_valid_goals; int ai_player_orders; - int ai_bools; int ai_active_dock; int ai_passive_dock; SCP_vector ai_actively_pursues; @@ -882,13 +809,14 @@ typedef struct ship_type_info { SCP_vector ai_cripple_ignores_temp; ship_type_info( ) - : message_bools( 0 ), hud_bools( 0 ), ship_bools( 0 ), debris_max_speed( 0.f ), - weapon_bools( 0 ), ff_multiplier( 0.f ), emp_multiplier( 0.f ), + : debris_max_speed( 0.f ), + ff_multiplier( 0.f ), emp_multiplier( 0.f ), fog_start_dist( 0.f ), fog_complete_dist( 0.f ), - ai_valid_goals( 0 ), ai_player_orders( 0 ), ai_bools( 0 ), ai_active_dock( 0 ), ai_passive_dock( 0 ), + ai_valid_goals( 0 ), ai_player_orders( 0 ), ai_active_dock( 0 ), ai_passive_dock( 0 ), vaporize_chance( 0.f ) { + flags.reset(); name[ 0 ] = '\0'; } } ship_type_info; @@ -904,21 +832,9 @@ struct man_thruster_renderer { extern SCP_vector Man_thrusters; -#define MT_BANK_RIGHT (1<<0) -#define MT_BANK_LEFT (1<<1) -#define MT_PITCH_UP (1<<2) -#define MT_PITCH_DOWN (1<<3) -#define MT_ROLL_RIGHT (1<<4) -#define MT_ROLL_LEFT (1<<5) -#define MT_SLIDE_RIGHT (1<<6) -#define MT_SLIDE_LEFT (1<<7) -#define MT_SLIDE_UP (1<<8) -#define MT_SLIDE_DOWN (1<<9) -#define MT_FORWARD (1<<10) -#define MT_REVERSE (1<<11) - -typedef struct man_thruster { - int use_flags; +class man_thruster { + public: + flagset use_flags; int start_snd; int loop_snd; @@ -931,7 +847,22 @@ typedef struct man_thruster { float radius; vec3d pos, norm; -} man_thruster; + + void reset() { + length = 0; + norm.xyz.x = norm.xyz.y = norm.xyz.z = 0.0f; // I wanted to do norm = ZERO_VECTOR here, but apparently that breaks the MSVC 2015 compiler.... + pos.xyz.x = pos.xyz.y = pos.xyz.z = 0.0f; + radius = 0.0f; + tex_fps = 0; + tex_nframes = 0; + use_flags.reset(); + + start_snd = -1; + loop_snd = -1; + stop_snd = -1; + tex_id = -1; + } +}; //Warp type defines #define WT_DEFAULT 0 @@ -1297,12 +1228,12 @@ public: //Helper functions - inline bool is_small_ship() const { return flags[Ship::Info_Flags::Fighter] || flags[Ship::Info_Flags::Bomber] || flags[Ship::Info_Flags::Support] || flags[Ship::Info_Flags::Escapepod]; } - inline bool is_big_ship() const { return flags[Ship::Info_Flags::Cruiser] || flags[Ship::Info_Flags::Freighter] || flags[Ship::Info_Flags::Transport] || flags[Ship::Info_Flags::Corvette] || flags[Ship::Info_Flags::Gas_miner] || flags[Ship::Info_Flags::Awacs]; } - inline bool is_huge_ship() const { return flags[Ship::Info_Flags::Capital] || flags[Ship::Info_Flags::Supercap] || flags[Ship::Info_Flags::Drydock] || flags[Ship::Info_Flags::Knossos_device]; } - inline bool is_flyable() const { return !(flags[Ship::Info_Flags::Cargo] || flags[Ship::Info_Flags::Navbuoy] || flags[Ship::Info_Flags::Escapepod]); } + inline bool is_small_ship() const { return flags[Ship::Info_Flags::Fighter, Ship::Info_Flags::Bomber, Ship::Info_Flags::Support, Ship::Info_Flags::Escapepod]; } + inline bool is_big_ship() const { return flags[Ship::Info_Flags::Cruiser, Ship::Info_Flags::Freighter, Ship::Info_Flags::Transport, Ship::Info_Flags::Corvette, Ship::Info_Flags::Gas_miner, Ship::Info_Flags::Awacs]; } + inline bool is_huge_ship() const { return flags[Ship::Info_Flags::Capital, Ship::Info_Flags::Supercap, Ship::Info_Flags::Drydock, Ship::Info_Flags::Knossos_device]; } + inline bool is_flyable() const { return !(flags[Ship::Info_Flags::Cargo, Ship::Info_Flags::Navbuoy, Ship::Info_Flags::Escapepod]); } inline bool is_harmless() const { return !is_flyable(); } - inline bool is_fighter_bomber() const { return flags[Ship::Info_Flags::Fighter] || flags[Ship::Info_Flags::Bomber]; } + inline bool is_fighter_bomber() const { return flags[Ship::Info_Flags::Fighter, Ship::Info_Flags::Bomber]; } inline bool is_big_or_huge() const { return is_big_ship() || is_huge_ship(); } inline bool avoids_shockwaves() const { return is_small_ship(); } @@ -1338,21 +1269,6 @@ typedef struct engine_wash_info extern SCP_vector Engine_wash_info; -// flags defined for wings -#define MAX_WING_FLAGS 8 // total number of flags in the wing structure -- used for parsing wing flags -#define WF_WING_GONE (1<<0) // all ships were either destroyed or departed -#define WF_WING_DEPARTING (1<<1) // wing's departure cue turned true -#define WF_IGNORE_COUNT (1<<2) // ignore all ships in this wing for goal counting purposes. -#define WF_REINFORCEMENT (1<<3) // is this wing a reinforcement wing -#define WF_RESET_REINFORCEMENT (1<<4) // needed when we need to reset the wing's reinforcement flag (after calling it in) -#define WF_NO_ARRIVAL_MUSIC (1<<5) // don't play arrival music when wing arrives -#define WF_EXPANDED (1<<6) // wing expanded in hotkey select screen -#define WF_NO_ARRIVAL_MESSAGE (1<<7) // don't play any arrival message -#define WF_NO_ARRIVAL_WARP (1<<8) // don't play warp effect for any arriving ships in this wing. -#define WF_NO_DEPARTURE_WARP (1<<9) // don't play warp effect for any departing ships in this wing. -#define WF_NO_DYNAMIC (1<<10) // members of this wing relentlessly pursue their ai goals -#define WF_DEPARTURE_ORDERED (1<<11) // departure of this wing was ordered by player -#define WF_NAV_CARRY (1<<12) // Kazan - Wing has nav-carry-status // Defines a wing of ships. typedef struct wing { @@ -1395,7 +1311,7 @@ typedef struct wing { int wave_delay_max; // maximum number of seconds before new wave can arrive int wave_delay_timestamp; // timestamp used for delaying arrival of next wave - int flags; + flagset flags; ai_goal ai_goals[MAX_AI_GOALS]; // goals for the wing -- converted to ai_goal struct diff --git a/code/ship/ship_flags.h b/code/ship/ship_flags.h index 2fc8b8e60d..3b9fc04a27 100644 --- a/code/ship/ship_flags.h +++ b/code/ship/ship_flags.h @@ -188,49 +188,29 @@ namespace Ship { NUM_VALUES }; - FLAG_LIST(Type_Info_Msg) { - Counts_for_alone, - Praise_destruction, + FLAG_LIST(Type_Info_Flags) { + Counts_for_alone, + Praise_destruction, + Hotkey_on_list, + Target_as_threat, + Show_attack_direction, + No_class_display, + Scannable, + Warp_pushes, + Warp_pushable, + Turret_tgt_ship_tgt, + Beams_easily_hit, + No_huge_impact_eff, + AI_accept_player_orders, + AI_auto_attacks, + AI_attempt_broadside, + AI_guards_attack, + AI_turrets_attack, + AI_can_form_wing, + AI_protected_on_cripple, - NUM_VALUES - }; - - FLAG_LIST(Type_Info_Hud) { - Hotkey_on_list, - Target_as_threat, - Show_attack_direction, - No_class_display, - - NUM_VALUES - }; - - FLAG_LIST(Type_Info_Ship) { - Scannable, - Warp_pushes, - Warp_pushable, - Turret_tgt_ship_tgt, - - NUM_VALUES - }; - - FLAG_LIST(Type_Info_Weapon) { - Beams_easily_hit, - No_huge_impact_eff, - - NUM_VALUES - }; - - FLAG_LIST(Type_Info_AI) { - Accept_player_orders, - Auto_attacks, - Attempt_broadside, - Guards_attack, - Turrets_attack, - Can_form_wing, - Protected_on_cripple, - - NUM_VALUES - }; + NUM_VALUES + }; FLAG_LIST(Thruster_Flags) { Bank_right, @@ -249,7 +229,13 @@ namespace Ship { NUM_VALUES }; - FLAG_LIST(Wing_Flags) { + + // Not all wing flags are parseable or saveable in mission files. Right now, the only ones which can be set by mission designers are: + // ignore_count, reinforcement, no_arrival_music, no_arrival_message, no_arrival_warp, no_departure_warp, no_dynamic and nav_carry_status + // Should that change, bump this variable and make sure to make the necessary changes to parse_wing (in missionparse) +#define PARSEABLE_WING_FLAGS 8 + + FLAG_LIST(Wing_Flags) { Gone, // all ships were either destroyed or departed Departing, // wing's departure cue turned true Ignore_count, // ignore all ships in this wing for goal counting purposes. @@ -272,13 +258,12 @@ namespace Ship { Alive, Dead, Rotate, - Turret_Rotation, + Turret_rotation, NUM_VALUES }; FLAG_LIST(Awacs_Warning_Flags) { - None = 0, Warn_25, Warn_75, diff --git a/code/ship/shipfx.cpp b/code/ship/shipfx.cpp index 2a24547823..f45f53bf7c 100644 --- a/code/ship/shipfx.cpp +++ b/code/ship/shipfx.cpp @@ -1244,7 +1244,7 @@ void shipfx_flash_create(object *objp, int model_num, vec3d *gun_pos, vec3d *gun // ALWAYS do this - since this is called once per firing // if this is a cannon type weapon, create a muzzle flash // HACK - let the flak guns do this on their own since they fire so quickly - if ((Weapon_info[weapon_info_index].muzzle_flash >= 0) && !(Weapon_info[weapon_info_index].wi_flags & WIF_FLAK)) { + if ((Weapon_info[weapon_info_index].muzzle_flash >= 0) && !(Weapon_info[weapon_info_index].wi_flags[Weapon::Info_Flags::Flak])) { vec3d real_dir; vm_vec_rotate(&real_dir, gun_dir,&objp->orient); mflash_create(gun_pos, &real_dir, &objp->phys_info, Weapon_info[weapon_info_index].muzzle_flash, objp); diff --git a/code/ship/shiphit.cpp b/code/ship/shiphit.cpp index e55ae7bfdc..1bdcb67a03 100755 --- a/code/ship/shiphit.cpp +++ b/code/ship/shiphit.cpp @@ -290,26 +290,26 @@ void do_subobj_destroyed_stuff( ship *ship_p, ship_subsys *subsys, vec3d* hitpos } // make the shipsounds work as they should... - if(subsys->subsys_snd_flags & SSSF_ALIVE) + if(subsys->subsys_snd_flags[Ship::Subsys_Sound_Flags::Alive]) { obj_snd_delete_type(ship_p->objnum, subsys->system_info->alive_snd, subsys); - subsys->subsys_snd_flags &= ~SSSF_ALIVE; + subsys->subsys_snd_flags.remove(Ship::Subsys_Sound_Flags::Alive); } - if(subsys->subsys_snd_flags & SSSF_TURRET_ROTATION) + if(subsys->subsys_snd_flags[Ship::Subsys_Sound_Flags::Turret_rotation]) { obj_snd_delete_type(ship_p->objnum, subsys->system_info->turret_base_rotation_snd, subsys); obj_snd_delete_type(ship_p->objnum, subsys->system_info->turret_gun_rotation_snd, subsys); - subsys->subsys_snd_flags &= ~SSSF_TURRET_ROTATION; + subsys->subsys_snd_flags.remove(Ship::Subsys_Sound_Flags::Turret_rotation); } - if(subsys->subsys_snd_flags & SSSF_ROTATE) + if(subsys->subsys_snd_flags[Ship::Subsys_Sound_Flags::Rotate]) { obj_snd_delete_type(ship_p->objnum, subsys->system_info->rotation_snd, subsys); - subsys->subsys_snd_flags &= ~SSSF_ROTATE; + subsys->subsys_snd_flags.remove(Ship::Subsys_Sound_Flags::Rotate); } - if((subsys->system_info->dead_snd != -1) && !(subsys->subsys_snd_flags & SSSF_DEAD)) + if((subsys->system_info->dead_snd != -1) && !(subsys->subsys_snd_flags[Ship::Subsys_Sound_Flags::Dead])) { obj_snd_assign(ship_p->objnum, subsys->system_info->dead_snd, &subsys->system_info->pnt, 0, OS_SUBSYS_DEAD, subsys); - subsys->subsys_snd_flags |= SSSF_DEAD; + subsys->subsys_snd_flags.remove(Ship::Subsys_Sound_Flags::Dead); } } @@ -495,7 +495,7 @@ float do_subobj_hit_stuff(object *ship_objp, object *other_obj, vec3d *hitpos, i weapon_info_index = shiphit_get_damage_weapon(other_obj); // Goober5000 - a NULL other_obj returns -1 if ((weapon_info_index >= 0) && ((other_obj->type == OBJ_WEAPON) || (Beams_use_damage_factors && (other_obj->type == OBJ_BEAM)))) { - if ( Weapon_info[weapon_info_index].wi_flags2 & WIF2_TRAINING ) { + if ( Weapon_info[weapon_info_index].wi_flags[Weapon::Info_Flags::Training] ) { return damage_left; } damage_left *= Weapon_info[weapon_info_index].subsystem_factor; @@ -2160,7 +2160,7 @@ static void ship_do_damage(object *ship_objp, object *other_obj, vec3d *hitpos, if (damage > 0.0f) { weapon_info_index = shiphit_get_damage_weapon(other_obj); // Goober5000 - a NULL other_obj returns -1 if ( weapon_info_index >= 0 ) { - if (Weapon_info[weapon_info_index].wi_flags & WIF_PUNCTURE) { + if (Weapon_info[weapon_info_index].wi_flags[Weapon::Info_Flags::Puncture]) { damage /= 4; } @@ -2185,7 +2185,7 @@ static void ship_do_damage(object *ship_objp, object *other_obj, vec3d *hitpos, // Check if this is simulated damage. weapon_info_index = shiphit_get_damage_weapon(other_obj); if ( weapon_info_index >= 0 ) { - if (Weapon_info[weapon_info_index].wi_flags2 & WIF2_TRAINING) { + if (Weapon_info[weapon_info_index].wi_flags[Weapon::Info_Flags::Training]) { // diag_printf2("Simulated Hull for Ship %s hit, dropping from %.32f to %d.\n", shipp->ship_name, (int) ( ship_objp->sim_hull_strength * 100 ), (int) ( ( ship_objp->sim_hull_strength - damage ) * 100 ) ); ship_objp->sim_hull_strength -= damage; ship_objp->sim_hull_strength = MAX( 0, ship_objp->sim_hull_strength ); @@ -2265,7 +2265,7 @@ static void ship_do_damage(object *ship_objp, object *other_obj, vec3d *hitpos, if (other_obj->type == OBJ_BEAM) { int beam_weapon_info_index = beam_get_weapon_info_index(other_obj); - if ( (beam_weapon_info_index > -1) && (Weapon_info[beam_weapon_info_index].wi_flags & (WIF_HUGE)) ) { + if ( (beam_weapon_info_index > -1) && (Weapon_info[beam_weapon_info_index].wi_flags[Weapon::Info_Flags::Huge]) ) { // Flag as vaporized shipp->flags.set(Ship::Ship_Flags::Vaporize); } @@ -2307,7 +2307,7 @@ static void ship_do_damage(object *ship_objp, object *other_obj, vec3d *hitpos, wip = &Weapon_info[Weapons[other_obj->instance].weapon_info_index]; // if its a leech weapon - NOTE - unknownplayer: Perhaps we should do something interesting like direct the leeched energy into the attacker ? - if (wip->wi_flags & WIF_ENERGY_SUCK) { + if (wip->wi_flags[Weapon::Info_Flags::Energy_suck]) { // reduce afterburner fuel shipp->afterburner_fuel -= wip->afterburner_reduce; shipp->afterburner_fuel = (shipp->afterburner_fuel < 0.0f) ? 0.0f : shipp->afterburner_fuel; @@ -2401,7 +2401,7 @@ void ship_apply_local_damage(object *ship_objp, object *other_obj, vec3d *hitpos Assert(wip != NULL); - if (wip->wi_flags & WIF_TAG) { + if (wip->wi_flags[Weapon::Info_Flags::Tag]) { // ssm stuff vec3d *start = hitpos; int ssm_index = wip->SSM_index; @@ -2413,7 +2413,7 @@ void ship_apply_local_damage(object *ship_objp, object *other_obj, vec3d *hitpos #ifndef NDEBUG if (other_obj->type == OBJ_WEAPON) { weapon_info *wip = &Weapon_info[Weapons[other_obj->instance].weapon_info_index]; - if (wip->wi_flags & WIF_HOMING) { + if (wip->is_homing()) { Homing_hits++; // nprintf(("AI", " Hit! Hits = %i/%i\n", Homing_hits, (Homing_hits + Homing_misses))); } @@ -2451,7 +2451,7 @@ void ship_apply_local_damage(object *ship_objp, object *other_obj, vec3d *hitpos Assert(wip != NULL); - if (wip->wi_flags2 & WIF2_TRAINING) { + if (wip->wi_flags[Weapon::Info_Flags::Training]) { create_sparks = false; } } diff --git a/code/source_groups.cmake b/code/source_groups.cmake index 290f722bae..8754f929c5 100644 --- a/code/source_groups.cmake +++ b/code/source_groups.cmake @@ -833,7 +833,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/code/stats/scoring.cpp b/code/stats/scoring.cpp index c99705273b..3abd30b5b8 100644 --- a/code/stats/scoring.cpp +++ b/code/stats/scoring.cpp @@ -879,7 +879,7 @@ int scoring_eval_kill_on_weapon(object *weapon_obj, object *other_obj) { weapon_info *dead_wip = &Weapon_info[dead_wp->weapon_info_index]; // info on the weapon that was killed // we don't evaluate kills on anything except bombs, currently. -Halleck - if(!(dead_wip->wi_flags & WIF_BOMB)) { + if(!(dead_wip->wi_flags[Weapon::Info_Flags::Bomb])) { return -1; } @@ -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; @@ -1116,7 +1116,7 @@ void scoring_eval_hit(object *hit_obj, object *other_obj,int from_blast) return; } - hit_obj_is_bomb = (Weapon_info[Weapons[hit_obj->instance].weapon_info_index].wi_flags & WIF_BOMB) ? true : false; + hit_obj_is_bomb = (Weapon_info[Weapons[hit_obj->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Bomb]) ? true : false; //If it's not a bomb but just a regular weapon, we don't care about it (for now, at least.) -Halleck if (!hit_obj_is_bomb) { @@ -1170,7 +1170,7 @@ void scoring_eval_hit(object *hit_obj, object *other_obj,int from_blast) // hostile hit else { // if its a bomb, count every bit of damage it does - if(Weapon_info[Weapons[other_obj->instance].weapon_info_index].wi_flags & WIF_BOMB){ + if(Weapon_info[Weapons[other_obj->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Bomb]){ // once we get impact damage, stop keeping track of it Net_players[player_num].m_player->stats.ms_shots_hit++; } @@ -1206,7 +1206,7 @@ void scoring_eval_hit(object *hit_obj, object *other_obj,int from_blast) // hostile hit else { // if its a bomb, count every bit of damage it does - if(Weapon_info[Weapons[other_obj->instance].weapon_info_index].wi_flags & WIF_BOMB){ + if(Weapon_info[Weapons[other_obj->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Bomb]){ // once we get impact damage, stop keeping track of it Player->stats.ms_shots_hit++; } diff --git a/code/weapon/beam.cpp b/code/weapon/beam.cpp index c6969d714e..d761ca15aa 100644 --- a/code/weapon/beam.cpp +++ b/code/weapon/beam.cpp @@ -307,7 +307,7 @@ int beam_fire(beam_fire_info *fire_info) } // make sure the beam_info_index is valid - if ((fire_info->beam_info_index < 0) || (fire_info->beam_info_index >= Num_weapon_types) || !(Weapon_info[fire_info->beam_info_index].wi_flags & WIF_BEAM)) { + if ((fire_info->beam_info_index < 0) || (fire_info->beam_info_index >= Num_weapon_types) || !(Weapon_info[fire_info->beam_info_index].wi_flags[Weapon::Info_Flags::Beam])) { Assertion(false, "beam_info_index (%d) invalid (either <0, >= %d, or not actually a beam)!\n", fire_info->beam_info_index, Num_weapon_types); return -1; } @@ -411,7 +411,7 @@ int beam_fire(beam_fire_info *fire_info) ship *target_ship = &Ships[fire_info->target->instance]; // maybe force to be a type A - if(Ship_info[target_ship->ship_info_index].class_type > -1 && (Ship_types[Ship_info[target_ship->ship_info_index].class_type].weapon_bools & STI_WEAP_BEAMS_EASILY_HIT)){ + if(Ship_info[target_ship->ship_info_index].class_type > -1 && (Ship_types[Ship_info[target_ship->ship_info_index].class_type].flags[Ship::Type_Info_Flags::Beams_easily_hit])){ new_item->type = BEAM_TYPE_A; } } @@ -494,8 +494,8 @@ int beam_fire_targeting(fighter_beam_fire_info *fire_info) } // make sure the beam_info_index is valid - Assert((fire_info->beam_info_index >= 0) && (fire_info->beam_info_index < MAX_WEAPON_TYPES) && (Weapon_info[fire_info->beam_info_index].wi_flags & WIF_BEAM)); - if((fire_info->beam_info_index < 0) || (fire_info->beam_info_index >= MAX_WEAPON_TYPES) || !(Weapon_info[fire_info->beam_info_index].wi_flags & WIF_BEAM)){ + Assert((fire_info->beam_info_index >= 0) && (fire_info->beam_info_index < MAX_WEAPON_TYPES) && (Weapon_info[fire_info->beam_info_index].wi_flags[Weapon::Info_Flags::Beam])); + if((fire_info->beam_info_index < 0) || (fire_info->beam_info_index >= MAX_WEAPON_TYPES) || !(Weapon_info[fire_info->beam_info_index].wi_flags[Weapon::Info_Flags::Beam])){ return -1; } wip = &Weapon_info[fire_info->beam_info_index]; @@ -2518,7 +2518,7 @@ int beam_collide_ship(obj_pair *pair) // if this weapon pierces the shield, then do the hit effect, but act like a shield collision never occurred; // otherwise, we have a valid hit on this shield - if (bwi->wi_flags2 & WIF2_PIERCE_SHIELDS) + if (bwi->wi_flags[Weapon::Info_Flags::Pierce_shields]) quadrant_num = -1; else valid_hit_occurred = 1; @@ -3040,11 +3040,11 @@ void beam_handle_collisions(beam *b) continue; } - if (wi->wi_flags & WIF_HUGE) { + if (wi->wi_flags[Weapon::Info_Flags::Huge]) { if (Objects[target].type == OBJ_SHIP) { ship_type_info *sti; sti = ship_get_type_info(&Objects[target]); - if (sti->weapon_bools & STI_WEAP_NO_HUGE_IMPACT_EFF) + if (sti->flags[Ship::Type_Info_Flags::No_huge_impact_eff]) draw_effects = 0; } } @@ -3594,7 +3594,7 @@ int beam_will_tool_target(beam *b, object *objp) } // calculate total strength, factoring in shield - if (!(wip->wi_flags2 & WIF2_PIERCE_SHIELDS)) + if (!(wip->wi_flags[Weapon::Info_Flags::Pierce_shields])) total_strength += shield_get_strength(objp); // if the beam is going to apply more damage in about 1 and a half than the ship can take @@ -3613,7 +3613,7 @@ DCF(beam_list, "Lists all beams") int b_count = 0; for(idx=0; idx= 0 && weapon_info_index < MAX_WEAPON_TYPES ); // if current secondary bank is not a corkscrew missile, return - if ( !(Weapon_info[weapon_info_index].wi_flags & WIF_CORKSCREW) ) { + if ( !(Weapon_info[weapon_info_index].wi_flags[Weapon::Info_Flags::Corkscrew]) ) { sp->num_corkscrew_to_fire = 0; sp->corkscrew_missile_bank = -1; return; diff --git a/code/weapon/emp.cpp b/code/weapon/emp.cpp index c033b851d2..5f401828c1 100644 --- a/code/weapon/emp.cpp +++ b/code/weapon/emp.cpp @@ -130,7 +130,7 @@ void emp_apply(vec3d *pos, float inner_radius, float outer_radius, float emp_int // if we have a bomb weapon wip_target = &Weapon_info[Weapons[target->instance].weapon_info_index]; - if((wip_target->weapon_hitpoints > 0) && !(wip_target->wi_flags2 & WIF2_NO_EMP_KILL)) { + if((wip_target->weapon_hitpoints > 0) && !(wip_target->wi_flags[Weapon::Info_Flags::No_emp_kill])) { // get the distance between the detonation and the target object vm_vec_sub(&dist, &target->pos, pos); dist_mag = vm_vec_mag(&dist); @@ -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/flak.cpp b/code/weapon/flak.cpp index a8a4b12f0b..5b7fa3e536 100644 --- a/code/weapon/flak.cpp +++ b/code/weapon/flak.cpp @@ -44,7 +44,7 @@ void flak_pick_range(object *objp, vec3d *firing_pos, vec3d *predicted_target_po Assert(objp->type == OBJ_WEAPON); Assert(objp->instance >= 0); Assert(Weapons[objp->instance].weapon_info_index >= 0); - Assert(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags & WIF_FLAK); + Assert(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Flak]); weapon_info* wip = &Weapon_info[Weapons[objp->instance].weapon_info_index]; @@ -124,8 +124,8 @@ void flak_muzzle_flash(vec3d *pos, vec3d *dir, physics_info *pip, int turret_wea if((turret_weapon_class < 0) || (turret_weapon_class >= Num_weapon_types)){ return; } - Assert(Weapon_info[turret_weapon_class].wi_flags & WIF_FLAK); - if(!(Weapon_info[turret_weapon_class].wi_flags & WIF_FLAK)){ + Assert(Weapon_info[turret_weapon_class].wi_flags[Weapon::Info_Flags::Flak]); + if(!(Weapon_info[turret_weapon_class].wi_flags[Weapon::Info_Flags::Flak])){ return; } diff --git a/code/weapon/shockwave.cpp b/code/weapon/shockwave.cpp index 9dfae74ca0..73d5ef1e48 100644 --- a/code/weapon/shockwave.cpp +++ b/code/weapon/shockwave.cpp @@ -273,7 +273,7 @@ void shockwave_move(object *shockwave_objp, float frametime) if (wip->weapon_hitpoints <= 0) continue; - if (!(wip->wi_flags2 & WIF2_TAKES_SHOCKWAVE_DAMAGE || (sw->weapon_info_index >= 0 && Weapon_info[sw->weapon_info_index].wi_flags2 & WIF2_CIWS))) + if (!(wip->wi_flags[Weapon::Info_Flags::Takes_shockwave_damage] || (sw->weapon_info_index >= 0 && Weapon_info[sw->weapon_info_index].wi_flags[Weapon::Info_Flags::Ciws]))) continue; } @@ -312,7 +312,7 @@ void shockwave_move(object *shockwave_objp, float frametime) case OBJ_SHIP: sw->obj_sig_hitlist[sw->num_objs_hit++] = objp->signature; // If we're doing an AoE Electronics shockwave, do the electronics stuff. -MageKing17 - if ( (sw->weapon_info_index >= 0) && (Weapon_info[sw->weapon_info_index].wi_flags3 & WIF3_AOE_ELECTRONICS) && !(objp->flags[Object::Object_Flags::Invulnerable]) ) { + if ( (sw->weapon_info_index >= 0) && (Weapon_info[sw->weapon_info_index].wi_flags[Weapon::Info_Flags::Aoe_Electronics]) && !(objp->flags[Object::Object_Flags::Invulnerable]) ) { weapon_do_electronics_effect(objp, &sw->pos, sw->weapon_info_index); } ship_apply_global_damage(objp, shockwave_objp, &sw->pos, damage ); @@ -329,7 +329,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/swarm.cpp b/code/weapon/swarm.cpp index c4c4cefa0f..cf2d5902d2 100644 --- a/code/weapon/swarm.cpp +++ b/code/weapon/swarm.cpp @@ -111,7 +111,7 @@ void swarm_maybe_fire_missile(int shipnum) Assert( weapon_info_index >= 0 && weapon_info_index < MAX_WEAPON_TYPES ); // if swarm secondary bank is not a swarm missile, return - if ( !(Weapon_info[weapon_info_index].wi_flags & WIF_SWARM) ) { + if ( !(Weapon_info[weapon_info_index].wi_flags[Weapon::Info_Flags::Swarm]) ) { sp->num_swarm_missiles_to_fire = 0; sp->swarm_missile_bank = -1; return; @@ -451,9 +451,9 @@ void turret_swarm_set_up_info(int parent_objnum, ship_subsys *turret, weapon_inf target_obj = &Objects[turret->turret_enemy_objnum]; // valid swarm weapon - Assert(((wip->wi_flags & WIF_SWARM) && (wip->swarm_count > 0)) || ((wip->wi_flags & WIF_CORKSCREW) && (wip->cs_num_fired > 0))); + Assert(((wip->wi_flags[Weapon::Info_Flags::Swarm]) && (wip->swarm_count > 0)) || ((wip->wi_flags[Weapon::Info_Flags::Corkscrew]) && (wip->cs_num_fired > 0))); - if(!((wip->wi_flags & WIF_SWARM) || (wip->wi_flags & WIF_CORKSCREW)) || ((wip->wi_flags & WIF_SWARM) && (wip->swarm_count <= 0)) || ((wip->wi_flags & WIF_CORKSCREW) && (wip->cs_num_fired <= 0))) + if(!((wip->wi_flags[Weapon::Info_Flags::Swarm]) || (wip->wi_flags[Weapon::Info_Flags::Corkscrew])) || ((wip->wi_flags[Weapon::Info_Flags::Swarm]) && (wip->swarm_count <= 0)) || ((wip->wi_flags[Weapon::Info_Flags::Corkscrew]) && (wip->cs_num_fired <= 0))) return; // get turret_swarm_info @@ -499,7 +499,7 @@ void turret_swarm_set_up_info(int parent_objnum, ship_subsys *turret, weapon_inf // initialize tsi tsi->weapon_class = WEAPON_INFO_INDEX(wip); - if (wip->wi_flags & WIF_SWARM) { + if (wip->wi_flags[Weapon::Info_Flags::Swarm]) { tsi->num_to_launch = wip->swarm_count; } else { tsi->num_to_launch = wip->cs_num_fired; @@ -582,7 +582,7 @@ void turret_swarm_maybe_fire_missile(int shipnum) } // *Get timestamp from weapon info's -Et1 - if (wip->wi_flags & WIF_SWARM) { + if (wip->wi_flags[Weapon::Info_Flags::Swarm]) { tsi->time_to_fire = timestamp( wip->SwarmWait ); } else { tsi->time_to_fire = timestamp( wip->cs_delay ); diff --git a/code/weapon/weapon.h b/code/weapon/weapon.h index f3f188d9da..f051d9075a 100644 --- a/code/weapon/weapon.h +++ b/code/weapon/weapon.h @@ -20,6 +20,7 @@ #include "weapon/shockwave.h" #include "weapon/trails.h" #include "particle/ParticleManager.h" +#include "weapon/weapon_flags.h" class object; class ship_subsys; @@ -38,118 +39,8 @@ extern int Num_weapon_subtypes; // Bitflags controlling weapon behavior #define MAX_WEAPON_FLAGS 18 // Maximum number of different bit flags legal to specify in a single weapons.tbl Flags line -#define WIF_DEFAULT_VALUE 0 -#define WIF2_DEFAULT_VALUE 0 -#define WIF3_DEFAULT_VALUE 0 - -#define WIF_HOMING_HEAT (1 << 0) // if set, this weapon homes via seeking heat -#define WIF_HOMING_ASPECT (1 << 1) // if set, this weapon homes via chasing aspect -#define WIF_ELECTRONICS (1 << 2) // Takes out electronics systems. -#define WIF_SPAWN (1 << 3) // Spawns projectiles on detonation. -#define WIF_REMOTE (1 << 4) // Can be remotely detonated by parent. -#define WIF_PUNCTURE (1 << 5) // Punctures armor, damaging subsystems. -#define WIF_SUPERCAP (1 << 6) // This is a weapon which does supercap class damage (meaning, it applies real damage to supercap ships) -#define WIF_CMEASURE (1 << 7) // Weapon acts as a countermeasure -//#define WIF_AREA_EFFECT (1 << 7) // Explosion has an area effect -//#define WIF_SHOCKWAVE (1 << 8) // Explosion has a shockwave -//WMC - These are no longer needed so these spots are free -#define WIF_HOMING_JAVELIN (1 << 8) // WC Saga Javelin HS style heatseeker, locks only on target's engines -#define WIF_TURNS (1 << 9) // Set this if the weapon ever changes heading. If you - // don't set this and the weapon turns, collision detection - // won't work, I promise! -#define WIF_SWARM (1 << 10) // Missile "swarms".. ie changes heading and twists on way to target -#define WIF_TRAIL (1 << 11) // Has a trail -#define WIF_BIG_ONLY (1 << 12) // Only big ships (cruiser, capital, etc.) can arm this weapon -#define WIF_CHILD (1 << 13) // No ship can have this weapon. It gets created by weapon detonations. -#define WIF_BOMB (1 << 14) // Bomb-type missile, can be targeted -#define WIF_HUGE (1 << 15) // Huge damage (generally 500+), probably only fired at huge ships. -#define WIF_NO_DUMBFIRE (1 << 16) // Missile cannot be fired dumbfire (ie requires aspect lock) -#define WIF_THRUSTER (1 << 17) // Has thruster cone and/or glow -#define WIF_IN_TECH_DATABASE (1 << 18) -#define WIF_PLAYER_ALLOWED (1 << 19) // allowed to be on starting wing ships/in weaponry pool -#define WIF_BOMBER_PLUS (1 << 20) // Fire this missile only at a bomber or big ship. But not a fighter. - -#define WIF_CORKSCREW (1 << 21) // corkscrew style missile -#define WIF_PARTICLE_SPEW (1 << 22) // spews particles as it travels -#define WIF_EMP (1 << 23) // weapon explodes with a serious EMP effect -#define WIF_ENERGY_SUCK (1 << 24) // energy suck primary (impact effect) -#define WIF_FLAK (1 << 25) // use for big-ship turrets - flak gun -#define WIF_BEAM (1 << 26) // if this is a beam weapon : NOTE - VERY SPECIAL CASE -#define WIF_TAG (1 << 27) // this weapon has a tag effect when it hits -#define WIF_SHUDDER (1 << 28) // causes the weapon to shudder. shudder is proportional to the mass and damage of the weapon -#define WIF_LOCKARM (1 << 29) // if the missile was fired without a lock, it does significanlty less damage on impact -#define WIF_STREAM (1 << 30) // handled by "trigger down/trigger up" instead of "fire - wait - fire - wait" -// NOTE: the remaining WIF is reserved for a flag that truly needs to be in the WIF_ flag field, -// as opposed to any typical new flag that can be added to WIF3 - -#define WIF2_BALLISTIC (1 << 0) // ballistic primaries - Goober5000 -#define WIF2_PIERCE_SHIELDS (1 << 1) // shield pierceing -Bobboau -#define WIF2_DEFAULT_IN_TECH_DATABASE (1 << 2) // default in tech database - Goober5000 -#define WIF2_LOCAL_SSM (1 << 3) // localized ssm. ship that fires ssm is in mission. ssms also warp back in during mission -#define WIF2_TAGGED_ONLY (1 << 4) // can only fire if target is tagged -#define WIF2_CYCLE (1 << 5) // will only fire from (shots (defalts to 1)) points at a time -#define WIF2_SMALL_ONLY (1 << 6) // can only be used against small ships like fighters or bombers -#define WIF2_SAME_TURRET_COOLDOWN (1 << 7) // the weapon has the same cooldown time on turrets -#define WIF2_MR_NO_LIGHTING (1 << 8) // don't render with lighting, regardless of user options -#define WIF2_TRANSPARENT (1 << 9) // render as transparent -#define WIF2_TRAINING (1 << 10) // Weapon does shield/hull damage, but doesn't hurt subsystems, whack you, or put marks on your ship. -#define WIF2_SMART_SPAWN (1 << 11) // Spawn weapon that is fired via turrets like normal weapons -#define WIF2_INHERIT_PARENT_TARGET (1 << 12) // child weapons home in on the target their parent is homing on. -#define WIF2_NO_EMP_KILL (1 << 13) // though weapon has hitpoints it can not be disabled by EMP -#define WIF2_VARIABLE_LEAD_HOMING (1 << 14) // allows user defined scaler to be added to lead (to enable, lead, pure or lag pursuit for missiles) -#define WIF2_UNTARGETED_HEAT_SEEKER (1 << 15) // forces heat seeker to lose target immeadiately (and acquire a random new one) -#define WIF2_HARD_TARGET_BOMB (1 << 16) // removes the radius doubling effect bombs have for collisions -#define WIF2_NON_SUBSYS_HOMING (1 << 17) // spreads fired missiles around the target ships hull -#define WIF2_NO_LIFE_LOST_IF_MISSED (1 << 18) // prevents game from shortening the lifeleft of the missed but still homing missiles -#define WIF2_CUSTOM_SEEKER_STR (1 << 19) // sets the game to use custom seeker strengths instead of default values -#define WIF2_CAN_BE_TARGETED (1 << 20) // allows non-bomb weapons to be targeted -#define WIF2_SHOWN_ON_RADAR (1 << 21) // allows non-bombs be visible on radar -#define WIF2_SHOW_FRIENDLY (1 << 22) // allows friendly weapon radar dots be drawn -#define WIF2_CAPITAL_PLUS (1 << 23) // AI will not use this weapon on fighters or bombers -#define WIF2_EXTERNAL_WEAPON_FP (1 << 24) // will try to use external models FPs if possible -#define WIF2_EXTERNAL_WEAPON_LNCH (1 << 25) // render external secondary as a launcher -#define WIF2_TAKES_BLAST_DAMAGE (1 << 26) // This weapon can take blast damage -#define WIF2_TAKES_SHOCKWAVE_DAMAGE (1 << 27) // This weapon can take shockwave damage -#define WIF2_DONT_SHOW_ON_RADAR (1 << 28) // Force a weapon to not show on radar -#define WIF2_RENDER_FLAK (1 << 29) // Even though this is a flak weapon, render the shell -#define WIF2_CIWS (1 << 30) // This weapons' burst and shockwave damage can damage bombs (Basically, a reverse for TAKES_BLAST/SHOCKWAVE_DAMAGE -#define WIF2_ANTISUBSYSBEAM (1 << 31) // This beam can target subsystems as per normal - -#define WIF3_NOLINK (1 << 0) // This weapon can not be linked with others -#define WIF3_USE_EMP_TIME_FOR_CAPSHIP_TURRETS (1 << 1) // override MAX_TURRET_DISRUPT_TIME in emp.cpp - Goober5000 -#define WIF3_NO_LINKED_PENALTY (1 << 2) // This weapon does not count into linked firing penalty -#define WIF3_NO_HOMING_SPEED_RAMP (1 << 3) // Disables the 1s long speed ramping when firing locked-on secondaries -#define WIF3_CMEASURE_ASPECT_HOME_ON (1 << 4) // This countermeasure flag makes aspect seekers home on the countermeasure instead of going into dumbfire mode -#define WIF3_TURRET_INTERCEPTABLE (1 << 5) // These two flags mark a weapon as being interceptable by the AI -#define WIF3_FIGHTER_INTERCEPTABLE (1 << 6) // (like WIF_BOMB), without forcing it to be tagetable -MageKing17 -#define WIF3_AOE_ELECTRONICS (1 << 7) // Apply electronics effect across the weapon's entire area of effect instead of just on the impacted ship -MageKing17 -#define WIF3_APPLY_RECOIL (1 << 8) // Apply recoil using weapon and ship info -#define WIF3_DONT_SPAWN_IF_SHOT (1 << 9) // Prevent shot down parent weapons from spawning children (DahBlount) -#define WIF3_DIE_ON_LOST_LOCK (1 << 10) // WIF_LOCKED_HOMING missiles will die if they lose their lock - -#define WIF_HOMING (WIF_HOMING_HEAT | WIF_HOMING_ASPECT | WIF_HOMING_JAVELIN) -#define WIF_LOCKED_HOMING (WIF_HOMING_ASPECT | WIF_HOMING_JAVELIN) -#define WIF_HURTS_BIG_SHIPS (WIF_BOMB | WIF_BEAM | WIF_HUGE | WIF_BIG_ONLY) - #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 - //particle names go here -nuke #define PSPEW_NONE -1 //used to disable a spew, useful for xmts #define PSPEW_DEFAULT 0 //std fs2 pspew @@ -193,7 +84,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 @@ -398,9 +289,7 @@ typedef struct weapon_info { float max_lifetime ; // How long this weapon will actually live for float lifetime; // How long the AI thinks this thing lives (used for distance calculations etc) float energy_consumed; // Energy used up when weapon is fired - int wi_flags; // bit flags defining behavior, see WIF_xxxx - int wi_flags2; // stupid int wi_flags, only 32 bits... argh - Goober5000 - int wi_flags3; // stupid int wi_flags2, only 32 bits... argh - The E + flagset wi_flags; // bit flags defining behavior, see WIF_xxxx float turn_time; float cargo_size; // cargo space taken up by individual weapon (missiles only) float rearm_rate; // rate per second at which secondary weapons are loaded during rearming @@ -544,7 +433,7 @@ typedef struct weapon_info { int burst_shots; float burst_delay; - int burst_flags; + flagset burst_flags; // Thruster effects generic_anim thruster_flame; @@ -570,6 +459,11 @@ typedef struct weapon_info { public: weapon_info(); + inline bool is_homing() { return wi_flags[Weapon::Info_Flags::Homing_heat, Weapon::Info_Flags::Homing_aspect, Weapon::Info_Flags::Homing_javelin]; } + inline bool is_locked_homing() { return wi_flags[Weapon::Info_Flags::Homing_aspect, Weapon::Info_Flags::Homing_javelin]; } + inline bool hurts_big_ships() { return wi_flags[Weapon::Info_Flags::Bomb, Weapon::Info_Flags::Beam, Weapon::Info_Flags::Huge, Weapon::Info_Flags::Big_only]; } + inline bool is_interceptable() { return wi_flags[Weapon::Info_Flags::Fighter_Interceptable, Weapon::Info_Flags::Turret_Interceptable]; } + void reset(); } weapon_info; diff --git a/code/weapon/weapon_flags.h b/code/weapon/weapon_flags.h index c782220002..a14c5fa728 100644 --- a/code/weapon/weapon_flags.h +++ b/code/weapon/weapon_flags.h @@ -81,8 +81,9 @@ namespace Weapon { Apply_Recoil, // Apply Recoil Dont_spawn_if_shot, // Prevent shot down parent weapons from spawning children (DahBlount) Die_on_lost_lock, // WIF_LOCKED_HOMING missiles will die if they lose their lock - - NUM_VALUES + Apply_recoil, // Apply recoil using weapon and ship info + + NUM_VALUES }; FLAG_LIST(Weapon_Flags) { diff --git a/code/weapon/weapons.cpp b/code/weapon/weapons.cpp index 131d3d8a9c..c9b2285377 100644 --- a/code/weapon/weapons.cpp +++ b/code/weapon/weapons.cpp @@ -95,17 +95,86 @@ 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 size_t Num_burst_fire_flags = sizeof(Burst_fire_flags)/sizeof(flag_def_list_new); weapon_explosions Weapon_explosions; SCP_vector LOD_checker; +flag_def_list_new Weapon_Info_Flags[] = { + { "spawn", Weapon::Info_Flags::Spawn, true, true }, //special case + { "remote detonate", Weapon::Info_Flags::Remote, true, false }, + { "puncture", Weapon::Info_Flags::Puncture, true, false }, + { "big ship", Weapon::Info_Flags::Big_only, true, false }, + { "huge", Weapon::Info_Flags::Huge, true, false }, + { "bomber+", Weapon::Info_Flags::Bomber_plus, true, false }, + { "child", Weapon::Info_Flags::Child, true, false }, + { "bomb", Weapon::Info_Flags::Bomb, true, false }, + { "no dumbfire", Weapon::Info_Flags::No_dumbfire, true, false }, + { "in tech database", Weapon::Info_Flags::In_tech_database, true, false }, + { "player allowed", Weapon::Info_Flags::Player_allowed, true, false }, + { "particle spew", Weapon::Info_Flags::Particle_spew, true, false }, + { "emp", Weapon::Info_Flags::Emp, true, false }, + { "esuck", Weapon::Info_Flags::Energy_suck, true, false }, + { "flak", Weapon::Info_Flags::Flak, true, false }, + { "corkscrew", Weapon::Info_Flags::Corkscrew, true, false }, + { "shudder", Weapon::Info_Flags::Shudder, true, false }, + { "electronics", Weapon::Info_Flags::Electronics, true, false }, + { "lockarm", Weapon::Info_Flags::Lockarm, true, false }, + { "beam", Weapon::Info_Flags::Beam, true, false }, + { "stream", Weapon::Info_Flags::Stream, true, false }, + { "supercap", Weapon::Info_Flags::Supercap, true, false }, + { "countermeasure", Weapon::Info_Flags::Cmeasure, true, false }, + { "ballistic", Weapon::Info_Flags::Ballistic, true, false }, + { "pierce shields", Weapon::Info_Flags::Pierce_shields, true, false }, + { "no pierce shields", Weapon::Info_Flags::NUM_VALUES, true, true }, //special case + { "local ssm", Weapon::Info_Flags::Local_ssm, true, false }, + { "tagged only", Weapon::Info_Flags::Tagged_only, true, false }, + { "beam no whack", Weapon::Info_Flags::NUM_VALUES, false, true }, //special case + { "cycle", Weapon::Info_Flags::Cycle, true, false }, + { "small only", Weapon::Info_Flags::Small_only, true, false }, + { "same turret cooldown", Weapon::Info_Flags::Same_turret_cooldown, true, false }, + { "apply no light", Weapon::Info_Flags::Mr_no_lighting, true, false }, + { "training", Weapon::Info_Flags::Training, true, false }, + { "smart spawn", Weapon::Info_Flags::Smart_spawn, true, false }, + { "inherit parent target", Weapon::Info_Flags::Inherit_parent_target, true, false }, + { "no emp kill", Weapon::Info_Flags::No_emp_kill, true, false }, + { "untargeted heat seeker", Weapon::Info_Flags::Untargeted_heat_seeker, true, false }, + { "no radius doubling", Weapon::Info_Flags::Hard_target_bomb, true, false }, + { "no subsystem homing", Weapon::Info_Flags::Non_subsys_homing, true, false }, + { "no lifeleft penalty", Weapon::Info_Flags::No_life_lost_if_missed, true, false }, + { "can be targeted", Weapon::Info_Flags::Can_be_targeted, true, false }, + { "show on radar", Weapon::Info_Flags::Shown_on_radar, true, false }, + { "show friendly on radar", Weapon::Info_Flags::Show_friendly, true, false }, + { "capital+", Weapon::Info_Flags::Capital_plus, true, false }, + { "chain external model fps", Weapon::Info_Flags::External_weapon_fp, true, false }, + { "external model launcher", Weapon::Info_Flags::External_weapon_lnch, true, false }, + { "takes blast damage", Weapon::Info_Flags::Takes_blast_damage, true, false }, + { "takes shockwave damage", Weapon::Info_Flags::Takes_shockwave_damage, true, false }, + { "hide from radar", Weapon::Info_Flags::Dont_show_on_radar, true, false }, + { "render flak", Weapon::Info_Flags::Render_flak, true, false }, + { "ciws", Weapon::Info_Flags::Ciws, true, false }, + { "anti-subsystem beam", Weapon::Info_Flags::Antisubsysbeam, true, false }, + { "no primary linking", Weapon::Info_Flags::Nolink, true, false }, + { "same emp time for capships", Weapon::Info_Flags::Use_emp_time_for_capship_turrets, true, false }, + { "no primary linked penalty", Weapon::Info_Flags::No_linked_penalty, true, false }, + { "no homing speed ramp", Weapon::Info_Flags::No_homing_speed_ramp, true, false }, + { "pulls aspect seekers", Weapon::Info_Flags::Cmeasure_aspect_home_on, true, false }, + { "turret interceptable", Weapon::Info_Flags::Turret_Interceptable, true, false }, + { "fighter interceptable", Weapon::Info_Flags::Fighter_Interceptable, true, false }, + { "aoe electronics", Weapon::Info_Flags::Aoe_Electronics, true, false }, + { "apply recoil", Weapon::Info_Flags::Apply_Recoil, true, false }, + { "don't spawn if shot", Weapon::Info_Flags::Dont_spawn_if_shot, true, false }, + { "die on lost lock", Weapon::Info_Flags::Die_on_lost_lock, true, true }, //special case +}; + +const size_t num_weapon_info_flags = sizeof(Weapon_Info_Flags) / sizeof(flag_def_list_new); + int Num_weapon_types = 0; int Num_weapons = 0; @@ -484,281 +553,151 @@ int weapon_info_lookup(const char *name) #define DEFAULT_WEAPON_SPAWN_COUNT 10 // Parse the weapon flags. -void parse_wi_flags(weapon_info *weaponp, int wi_flags, int wi_flags2, int wi_flags3) +void parse_wi_flags(weapon_info *weaponp, flagset wi_flags) { - const char *spawn_str = NOX("Spawn"); - const size_t spawn_str_len = strlen(spawn_str); + const char *spawn_str = NOX("Spawn"); + const size_t spawn_str_len = strlen(spawn_str); - //Make sure we HAVE flags :p - if(!optional_string("$Flags:")) - return; + //Make sure we HAVE flags :p + if (!optional_string("$Flags:")) + return; - char weapon_strings[MAX_WEAPON_FLAGS][NAME_LENGTH]; - int num_strings; + SCP_vector unparsed_or_special; + parse_string_flag_list(weaponp->wi_flags, Weapon_Info_Flags, num_weapon_info_flags, &unparsed_or_special); - num_strings = stuff_string_list(weapon_strings, MAX_WEAPON_FLAGS); + if (optional_string("+override")) { + // reseting the flag values if set to override the existing flags + weaponp->wi_flags = wi_flags; + } - if (optional_string("+override")) { - // reseting the flag values if set to override the existing flags - weaponp->wi_flags = wi_flags; - weaponp->wi_flags2 = wi_flags2; - weaponp->wi_flags3 = wi_flags3; - } + bool set_pierce = false; + bool set_nopierce = false; - bool set_pierce = false; - bool set_nopierce = false; - - for (int i=0; inum_spawn_weapons_defined < MAX_SPAWN_TYPES_PER_WEAPON) - { - //We need more spawning slots - //allocate in slots of 10 - if((Num_spawn_types % 10) == 0) { - Spawn_names = (char **)vm_realloc(Spawn_names, (Num_spawn_types + 10) * sizeof(*Spawn_names)); - } + if (unparsed_or_special.size() > 0) { - int skip_length, name_length; - char *temp_string; + for (auto flag = unparsed_or_special.begin(); flag != unparsed_or_special.end(); ++flag) { + SCP_string flag_text = *flag; + //deal with spawn flag + if (!strnicmp(spawn_str, flag_text.c_str(), 5)) + { + if (weaponp->num_spawn_weapons_defined < MAX_SPAWN_TYPES_PER_WEAPON) + { + //We need more spawning slots + //allocate in slots of 10 + if ((Num_spawn_types % 10) == 0) { + Spawn_names = (char **)vm_realloc(Spawn_names, (Num_spawn_types + 10) * sizeof(*Spawn_names)); + } - temp_string = weapon_strings[i]; + int skip_length, name_length; + char *temp_string = new char[flag_text.size() + 1]; - weaponp->wi_flags |= WIF_SPAWN; - weaponp->spawn_info[weaponp->num_spawn_weapons_defined].spawn_type = (short)Num_spawn_types; - skip_length = spawn_str_len + strspn(&temp_string[spawn_str_len], NOX(" \t")); - char *num_start = strchr(&temp_string[skip_length], ','); - if (num_start == NULL) { - weaponp->spawn_info[weaponp->num_spawn_weapons_defined].spawn_count = DEFAULT_WEAPON_SPAWN_COUNT; - name_length = 999; - } else { - weaponp->spawn_info[weaponp->num_spawn_weapons_defined].spawn_count = (short)atoi(num_start+1); - name_length = num_start - temp_string - skip_length; - } + strcpy(temp_string, flag_text.c_str()); - weaponp->total_children_spawned += weaponp->spawn_info[weaponp->num_spawn_weapons_defined].spawn_count; + weaponp->wi_flags.set(Weapon::Info_Flags::Spawn); + weaponp->spawn_info[weaponp->num_spawn_weapons_defined].spawn_type = (short)Num_spawn_types; + skip_length = spawn_str_len + strspn(&temp_string[spawn_str_len], NOX(" \t")); + char *num_start = strchr(&temp_string[skip_length], ','); + if (num_start == NULL) { + weaponp->spawn_info[weaponp->num_spawn_weapons_defined].spawn_count = DEFAULT_WEAPON_SPAWN_COUNT; + name_length = 999; + } + else { + weaponp->spawn_info[weaponp->num_spawn_weapons_defined].spawn_count = (short)atoi(num_start + 1); + name_length = num_start - temp_string - skip_length; + } - Spawn_names[Num_spawn_types] = vm_strndup( &weapon_strings[i][skip_length], name_length ); - Num_spawn_types++; - weaponp->num_spawn_weapons_defined++; - } else { - Warning(LOCATION, "Illegal to have more than %d spawn types for one weapon.\nIgnoring weapon %s", MAX_SPAWN_TYPES_PER_WEAPON, weaponp->name); - } - } else if (!stricmp(NOX("Remote Detonate"), weapon_strings[i])) - weaponp->wi_flags |= WIF_REMOTE; - else if (!stricmp(NOX("Puncture"), weapon_strings[i])) - weaponp->wi_flags |= WIF_PUNCTURE; - else if (!stricmp(NOX("Big Ship"), weapon_strings[i])) - weaponp->wi_flags |= WIF_BIG_ONLY; - else if (!stricmp(NOX("Huge"), weapon_strings[i])) - weaponp->wi_flags |= WIF_HUGE; - else if (!stricmp(NOX("Bomber+"), weapon_strings[i])) - weaponp->wi_flags |= WIF_BOMBER_PLUS; - else if (!stricmp(NOX("child"), weapon_strings[i])) - weaponp->wi_flags |= WIF_CHILD; - else if (!stricmp(NOX("Bomb"), weapon_strings[i])) - weaponp->wi_flags |= WIF_BOMB; - else if (!stricmp(NOX("No Dumbfire"), weapon_strings[i])) - weaponp->wi_flags |= WIF_NO_DUMBFIRE; - else if (!stricmp(NOX("In tech database"), weapon_strings[i])) - weaponp->wi_flags |= WIF_IN_TECH_DATABASE; - else if (!stricmp(NOX("Player allowed"), weapon_strings[i])) - weaponp->wi_flags |= WIF_PLAYER_ALLOWED; - else if (!stricmp(NOX("Particle Spew"), weapon_strings[i])) - weaponp->wi_flags |= WIF_PARTICLE_SPEW; - else if (!stricmp(NOX("EMP"), weapon_strings[i])) - weaponp->wi_flags |= WIF_EMP; - else if (!stricmp(NOX("Esuck"), weapon_strings[i])) - weaponp->wi_flags |= WIF_ENERGY_SUCK; - else if (!stricmp(NOX("Flak"), weapon_strings[i])) - weaponp->wi_flags |= WIF_FLAK; - else if (!stricmp(NOX("Corkscrew"), weapon_strings[i])) - weaponp->wi_flags |= WIF_CORKSCREW; - else if (!stricmp(NOX("Shudder"), weapon_strings[i])) - weaponp->wi_flags |= WIF_SHUDDER; - else if (!stricmp(NOX("Electronics"), weapon_strings[i])) - weaponp->wi_flags |= WIF_ELECTRONICS; - else if (!stricmp(NOX("lockarm"), weapon_strings[i])) - weaponp->wi_flags |= WIF_LOCKARM; - else if (!stricmp(NOX("beam"), weapon_strings[i])) - { - weaponp->wi_flags |= WIF_BEAM; + weaponp->total_children_spawned += weaponp->spawn_info[weaponp->num_spawn_weapons_defined].spawn_count; - // IMPORTANT: beams pierce shields by default :rolleyes: :p - Goober5000 - weaponp->wi_flags2 |= WIF2_PIERCE_SHIELDS; - } - else if (!stricmp(NOX("stream"), weapon_strings[i])) - weaponp->wi_flags |= WIF_STREAM; - else if (!stricmp(NOX("supercap"), weapon_strings[i])) - weaponp->wi_flags |= WIF_SUPERCAP; - else if (!stricmp(NOX("countermeasure"), weapon_strings[i])) - weaponp->wi_flags |= WIF_CMEASURE; - else if (!stricmp(NOX("ballistic"), weapon_strings[i])) - weaponp->wi_flags2 |= WIF2_BALLISTIC; - else if (!stricmp(NOX("pierce shields"), weapon_strings[i])) - set_pierce = true; - else if (!stricmp(NOX("no pierce shields"), weapon_strings[i])) // only for beams - set_nopierce = true; - else if (!stricmp(NOX("local ssm"), weapon_strings[i])) - weaponp->wi_flags2 |= WIF2_LOCAL_SSM; - else if (!stricmp(NOX("tagged only"), weapon_strings[i])) - weaponp->wi_flags2 |= WIF2_TAGGED_ONLY; - else if (!stricmp(NOX("beam no whack"), weapon_strings[i])) - { - Warning(LOCATION, "The \"beam no whack\" flag has been deprecated. Set the beam's mass to 0 instead. This has been done for you.\n"); - weaponp->mass = 0.0f; - } - else if (!stricmp(NOX("cycle"), weapon_strings[i])) - weaponp->wi_flags2 |= WIF2_CYCLE; - else if (!stricmp(NOX("small only"), weapon_strings[i])) - weaponp->wi_flags2 |= WIF2_SMALL_ONLY; - else if (!stricmp(NOX("same turret cooldown"), weapon_strings[i])) - weaponp->wi_flags2 |= WIF2_SAME_TURRET_COOLDOWN; - else if (!stricmp(NOX("apply no light"), weapon_strings[i])) - weaponp->wi_flags2 |= WIF2_MR_NO_LIGHTING; - else if (!stricmp(NOX("training"), weapon_strings[i])) - weaponp->wi_flags2 |= WIF2_TRAINING; - else if (!stricmp(NOX("smart spawn"), weapon_strings[i])) - weaponp->wi_flags2 |= WIF2_SMART_SPAWN; - else if (!stricmp(NOX("inherit parent target"), weapon_strings[i])) - weaponp->wi_flags2 |= WIF2_INHERIT_PARENT_TARGET; - else if (!stricmp(NOX("no emp kill"), weapon_strings[i])) - weaponp->wi_flags2 |= WIF2_NO_EMP_KILL; - else if (!stricmp(NOX("untargeted heat seeker"), weapon_strings[i])) - weaponp->wi_flags2 |= WIF2_UNTARGETED_HEAT_SEEKER; - else if (!stricmp(NOX("no radius doubling"), weapon_strings[i])) { - if (weaponp->wi_flags & WIF_BOMB) { - weaponp->wi_flags2 |= WIF2_HARD_TARGET_BOMB; - } - else { - Warning(LOCATION, "Weapon %s is not a bomb but has \"no radius doubling\" set. Ignoring this flag", weaponp->name); - } - } - else if (!stricmp(NOX("no subsystem homing"), weapon_strings[i])) - weaponp->wi_flags2 |= WIF2_NON_SUBSYS_HOMING; - else if (!stricmp(NOX("no lifeleft penalty"), weapon_strings[i])) - weaponp->wi_flags2 |= WIF2_NO_LIFE_LOST_IF_MISSED; - else if (!stricmp(NOX("can be targeted"), weapon_strings[i])) - weaponp->wi_flags2 |= WIF2_CAN_BE_TARGETED; - else if (!stricmp(NOX("show on radar"), weapon_strings[i])) - weaponp->wi_flags2 |= WIF2_SHOWN_ON_RADAR; - else if (!stricmp(NOX("show friendly on radar"), weapon_strings[i])) - weaponp->wi_flags2 |= WIF2_SHOW_FRIENDLY; - else if (!stricmp(NOX("capital+"), weapon_strings[i])) - weaponp->wi_flags2 |= WIF2_CAPITAL_PLUS; - else if (!stricmp(NOX("chain external model fps"), weapon_strings[i])) - weaponp->wi_flags2 |= WIF2_EXTERNAL_WEAPON_FP; - else if (!stricmp(NOX("external model launcher"), weapon_strings[i])) - weaponp->wi_flags2 |= WIF2_EXTERNAL_WEAPON_LNCH; - else if (!stricmp(NOX("takes blast damage"), weapon_strings[i])) - weaponp->wi_flags2 |= WIF2_TAKES_BLAST_DAMAGE; - else if (!stricmp(NOX("takes shockwave damage"), weapon_strings[i])) - weaponp->wi_flags2 |= WIF2_TAKES_SHOCKWAVE_DAMAGE; - else if (!stricmp(NOX("hide from radar"), weapon_strings[i])) - weaponp->wi_flags2 |= WIF2_DONT_SHOW_ON_RADAR; - else if (!stricmp(NOX("render flak"), weapon_strings[i])) - weaponp->wi_flags2 |= WIF2_RENDER_FLAK; - else if (!stricmp(NOX("ciws"), weapon_strings[i])) - weaponp->wi_flags2 |= WIF2_CIWS; - else if (!stricmp(NOX("anti-subsystem beam"), weapon_strings[i])) - weaponp->wi_flags2 |= WIF2_ANTISUBSYSBEAM; - else if (!stricmp(NOX("no primary linking"), weapon_strings[i])) - weaponp->wi_flags3 |= WIF3_NOLINK; - else if (!stricmp(NOX("same emp time for capships"), weapon_strings[i])) - weaponp->wi_flags3 |= WIF3_USE_EMP_TIME_FOR_CAPSHIP_TURRETS; - else if (!stricmp(NOX("no primary linked penalty"), weapon_strings[i])) - weaponp->wi_flags3 |= WIF3_NO_LINKED_PENALTY; - else if (!stricmp(NOX("no homing speed ramp"), weapon_strings[i])) - weaponp->wi_flags3 |= WIF3_NO_HOMING_SPEED_RAMP; - else if (!stricmp(NOX("pulls aspect seekers"), weapon_strings[i])) - { - if (!(weaponp->wi_flags & WIF_CMEASURE)) - { - Warning(LOCATION, "\"pulls aspect seekers\" may only be used for countermeasures!"); - } - else - { - weaponp->wi_flags3 |= WIF3_CMEASURE_ASPECT_HOME_ON; - } - } - else if (!stricmp(NOX("interceptable"), weapon_strings[i])) - weaponp->wi_flags3 |= WIF3_TURRET_INTERCEPTABLE | WIF3_FIGHTER_INTERCEPTABLE; - else if (!stricmp(NOX("turret interceptable"), weapon_strings[i])) - weaponp->wi_flags3 |= WIF3_TURRET_INTERCEPTABLE; - else if (!stricmp(NOX("fighter interceptable"), weapon_strings[i])) - weaponp->wi_flags3 |= WIF3_FIGHTER_INTERCEPTABLE; - else if (!stricmp(NOX("apply recoil"), weapon_strings[i])) - weaponp->wi_flags3 |= WIF3_APPLY_RECOIL; - else if (!stricmp(NOX("don't spawn if shot"), weapon_strings[i])) - weaponp->wi_flags3 |= WIF3_DONT_SPAWN_IF_SHOT; - else if (!stricmp(NOX("die on lost lock"), weapon_strings[i])) { - if (!(weaponp->wi_flags & WIF_LOCKED_HOMING)) { - Warning(LOCATION, "\"die on lost lock\" may only be used for Homing Type ASPECT/JAVELIN!"); - } - else { - weaponp->wi_flags3 |= WIF3_DIE_ON_LOST_LOCK; - } - } - else - Warning(LOCATION, "Bogus string in weapon flags: %s\n", weapon_strings[i]); - } + Spawn_names[Num_spawn_types] = vm_strndup(&flag_text[skip_length], name_length); + Num_spawn_types++; + weaponp->num_spawn_weapons_defined++; + } + else { + Warning(LOCATION, "Illegal to have more than %d spawn types for one weapon.\nIgnoring weapon %s", MAX_SPAWN_TYPES_PER_WEAPON, weaponp->name); + } + } + else if (!stricmp(NOX("pierce shields"), flag_text.c_str())) { + set_pierce = true; + } + else if (!stricmp(NOX("no pierce shields"), flag_text.c_str())) { + set_nopierce = true; + } + else if (!stricmp(NOX("beam no whack"), flag_text.c_str())) { + Warning(LOCATION, "The \"beam no whack\" flag has been deprecated. Set the beam's mass to 0 instead. This has been done for you.\n"); + weaponp->mass = 0.0f; + } + else if (!stricmp(NOX("interceptable"), flag_text.c_str())) { + weaponp->wi_flags.set(Weapon::Info_Flags::Turret_Interceptable); + weaponp->wi_flags.set(Weapon::Info_Flags::Fighter_Interceptable); + } + else if (!stricmp(NOX("die on lost lock"), flag_text.c_str())) { + if (!(weaponp->is_locked_homing())) { + Warning(LOCATION, "\"die on lost lock\" may only be used for Homing Type ASPECT/JAVELIN!"); + weaponp->wi_flags.remove(Weapon::Info_Flags::Die_on_lost_lock); + } + } + else { + Warning(LOCATION, "Unrecognized flag in flag list for weapon %s: \"%s\"", weaponp->name, (*flag).c_str()); + } + } - // Goober5000 - fix up pierce/nopierce flags, per Mantis #2442 - if (set_pierce) - weaponp->wi_flags2 |= WIF2_PIERCE_SHIELDS; - if (set_nopierce) - weaponp->wi_flags2 &= ~WIF2_PIERCE_SHIELDS; + //Do cleanup and sanity checks + if (set_nopierce) + weaponp->wi_flags.remove(Weapon::Info_Flags::Pierce_shields); - // set default tech room status - Goober5000 - if (weaponp->wi_flags & WIF_IN_TECH_DATABASE) - weaponp->wi_flags2 |= WIF2_DEFAULT_IN_TECH_DATABASE; + if (weaponp->wi_flags[Weapon::Info_Flags::Hard_target_bomb] && !weaponp->wi_flags[Weapon::Info_Flags::Bomb]) { + weaponp->wi_flags.remove(Weapon::Info_Flags::Hard_target_bomb); + Warning(LOCATION, "Weapon %s is not a bomb but has \"no radius doubling\" set. Ignoring this flag", weaponp->name); + } - // SWARM, CORKSCREW and FLAK should be mutually exclusive - if (weaponp->wi_flags & WIF_FLAK) - { - if ((weaponp->wi_flags & WIF_SWARM) || (weaponp->wi_flags & WIF_CORKSCREW)) - { - Warning(LOCATION, "Swarm, Corkscrew, and Flak are mutually exclusive! Removing Swarm and Corkscrew attributes.\n"); - weaponp->wi_flags &= ~WIF_SWARM; - weaponp->wi_flags &= ~WIF_CORKSCREW; - } - } - else - { - if ((weaponp->wi_flags & WIF_SWARM) && (weaponp->wi_flags & WIF_CORKSCREW)) - { - Warning(LOCATION, "Swarm and Corkscrew are mutually exclusive! Defaulting to Swarm.\n"); - weaponp->wi_flags &= ~WIF_CORKSCREW; - } - } + if (weaponp->wi_flags[Weapon::Info_Flags::In_tech_database]) + weaponp->wi_flags.set(Weapon::Info_Flags::Default_in_tech_database); - if (weaponp->wi_flags2 & WIF2_LOCAL_SSM) - { - if (!(weaponp->wi_flags & WIF_HOMING) || (weaponp->subtype !=WP_MISSILE)) - { - Warning(LOCATION, "local ssm must be guided missile: %s", weaponp->name); - } - } + if (weaponp->wi_flags[Weapon::Info_Flags::Flak]) { + if (weaponp->wi_flags[Weapon::Info_Flags::Swarm] || weaponp->wi_flags[Weapon::Info_Flags::Corkscrew]) { + weaponp->wi_flags.remove(Weapon::Info_Flags::Swarm); + weaponp->wi_flags.remove(Weapon::Info_Flags::Corkscrew); + Warning(LOCATION, "Swarm, Corkscrew, and Flak are mutually exclusive! Removing Swarm and Corkscrew attributes from weapon %s.\n", weaponp->name); + } + } - if ((weaponp->wi_flags2 & WIF2_SMALL_ONLY) && (weaponp->wi_flags & WIF_HUGE)) - { - Warning(LOCATION,"\"small only\" and \"huge\" flags are mutually exclusive.\nThey are used together in %s\nAI will most likely not use this weapon",weaponp->name); - } + if (weaponp->wi_flags[Weapon::Info_Flags::Swarm] && weaponp->wi_flags[Weapon::Info_Flags::Corkscrew]) { + weaponp->wi_flags.remove(Weapon::Info_Flags::Corkscrew); + Warning(LOCATION, "Swarm and Corkscrew are mutually exclusive! Defaulting to Swarm on weapon %s.\n", weaponp->name); + } - if (!(weaponp->wi_flags & WIF_SPAWN) && (weaponp->wi_flags2 & WIF2_SMART_SPAWN)) - { - Warning(LOCATION,"\"smart spawn\" flag used without \"spawn\" flag in %s\n",weaponp->name); - } + if (weaponp->wi_flags[Weapon::Info_Flags::Local_ssm]) { + if (!weaponp->is_homing() || weaponp->subtype != WP_MISSILE) { + Warning(LOCATION, "local ssm must be guided missile: %s", weaponp->name); + } + } - if ((weaponp->wi_flags2 & WIF2_INHERIT_PARENT_TARGET) && (!(weaponp->wi_flags & WIF_CHILD))) - { - Warning(LOCATION,"Weapon %s has the \"inherit parent target\" flag, but not the \"child\" flag. No changes in behavior will occur.", weaponp->name); - } + if (weaponp->wi_flags[Weapon::Info_Flags::Small_only] && weaponp->wi_flags[Weapon::Info_Flags::Huge]) + { + Warning(LOCATION, "\"small only\" and \"huge\" flags are mutually exclusive.\nThey are used together in %s\nAI will most likely not use this weapon", weaponp->name); + } - if (!(weaponp->wi_flags & WIF_HOMING_HEAT) && (weaponp->wi_flags2 & WIF2_UNTARGETED_HEAT_SEEKER)) - { - Warning(LOCATION,"Weapon '%s' has the \"untargeted heat seeker\" flag, but Homing Type is not set to \"HEAT\".", weaponp->name); - } + if (!weaponp->wi_flags[Weapon::Info_Flags::Spawn] && weaponp->wi_flags[Weapon::Info_Flags::Smart_spawn]) + { + Warning(LOCATION, "\"smart spawn\" flag used without \"spawn\" flag in %s\n", weaponp->name); + } + + if (weaponp->wi_flags[Weapon::Info_Flags::Inherit_parent_target] && (!weaponp->wi_flags[Weapon::Info_Flags::Child])) + { + Warning(LOCATION, "Weapon %s has the \"inherit parent target\" flag, but not the \"child\" flag. No changes in behavior will occur.", weaponp->name); + } + + if (!weaponp->wi_flags[Weapon::Info_Flags::Homing_heat] && weaponp->wi_flags[Weapon::Info_Flags::Untargeted_heat_seeker]) + { + Warning(LOCATION, "Weapon '%s' has the \"untargeted heat seeker\" flag, but Homing Type is not set to \"HEAT\".", weaponp->name); + } + + if (!weaponp->wi_flags[Weapon::Info_Flags::Cmeasure] && weaponp->wi_flags[Weapon::Info_Flags::Cmeasure_aspect_home_on]) + { + weaponp->wi_flags.remove(Weapon::Info_Flags::Cmeasure_aspect_home_on); + Warning(LOCATION, "Weapon %s has the \"pulls aspect seekers\" flag, but is not a countermeasure.\n", weaponp->name); + } + } } void parse_shockwave_info(shockwave_create_info *sci, char *pre_char) @@ -847,9 +786,7 @@ int parse_weapon(int subtype, bool replace, const char *filename) int primary_rearm_rate_specified=0; bool first_time = false; bool create_if_not_found = true; - int wi_flags = WIF_DEFAULT_VALUE; - int wi_flags2 = WIF2_DEFAULT_VALUE; - int wi_flags3 = WIF3_DEFAULT_VALUE; + flagset wi_flags; required_string("$Name:"); stuff_string(fname, F_NAME, NAME_LENGTH); @@ -1270,7 +1207,7 @@ int parse_weapon(int subtype, bool replace, const char *filename) stuff_boolean(&is_homing); } - if (is_homing || (wip->wi_flags & WIF_HOMING)) + if (is_homing || (wip->is_homing())) { char temp_type[NAME_LENGTH]; @@ -1280,45 +1217,38 @@ int parse_weapon(int subtype, bool replace, const char *filename) stuff_string(temp_type, F_NAME, NAME_LENGTH); if (!stricmp(temp_type, NOX("HEAT"))) { - if(wip->wi_flags & WIF_HOMING_ASPECT) { - wip->wi_flags &= ~WIF_HOMING_ASPECT; - } - if(wip->wi_flags & WIF_HOMING_JAVELIN) { - wip->wi_flags &= ~WIF_HOMING_JAVELIN; - } + wip->wi_flags.remove(Weapon::Info_Flags::Homing_aspect); + wip->wi_flags.remove(Weapon::Info_Flags::Homing_javelin); - wip->wi_flags |= WIF_HOMING_HEAT | WIF_TURNS; - wi_flags |= WIF_HOMING_HEAT | WIF_TURNS; + wip->wi_flags.set(Weapon::Info_Flags::Homing_heat); + wi_flags.set(Weapon::Info_Flags::Homing_heat); + + } else if (!stricmp(temp_type, NOX("ASPECT"))) { - if(wip->wi_flags & WIF_HOMING_HEAT) { - wip->wi_flags &= ~WIF_HOMING_HEAT; - } - if(wip->wi_flags & WIF_HOMING_JAVELIN) { - wip->wi_flags &= ~WIF_HOMING_JAVELIN; - } + wip->wi_flags.remove(Weapon::Info_Flags::Homing_heat); + wip->wi_flags.remove(Weapon::Info_Flags::Homing_javelin); - wip->wi_flags |= WIF_HOMING_ASPECT | WIF_TURNS; - wi_flags |= WIF_HOMING_ASPECT | WIF_TURNS; + wip->wi_flags.set(Weapon::Info_Flags::Homing_aspect); + wi_flags.set(Weapon::Info_Flags::Homing_aspect); } else if (!stricmp(temp_type, NOX("JAVELIN"))) { - if(wip->wi_flags & WIF_HOMING_HEAT) { - wip->wi_flags &= ~WIF_HOMING_HEAT; - } - if(wip->wi_flags & WIF_HOMING_ASPECT) { - wip->wi_flags &= ~WIF_HOMING_ASPECT; - } + wip->wi_flags.remove(Weapon::Info_Flags::Homing_heat); + wip->wi_flags.remove(Weapon::Info_Flags::Homing_aspect); - wip->wi_flags |= (WIF_HOMING_JAVELIN | WIF_TURNS); - wi_flags |= (WIF_HOMING_JAVELIN | WIF_TURNS); + wip->wi_flags.set(Weapon::Info_Flags::Homing_javelin); + wi_flags.set(Weapon::Info_Flags::Homing_javelin); } + + wip->wi_flags.set(Weapon::Info_Flags::Turns); + wi_flags.set(Weapon::Info_Flags::Turns); //If you want to add another weapon, remember you need to reset //ALL homing flags. } - if (wip->wi_flags & WIF_HOMING_HEAT) + if (wip->wi_flags[Weapon::Info_Flags::Homing_heat]) { float view_cone_angle; @@ -1335,32 +1265,32 @@ int parse_weapon(int subtype, bool replace, const char *filename) { //heat default seeker strength is 3 stuff_float(&wip->seeker_strength); - wip->wi_flags2 |= WIF2_CUSTOM_SEEKER_STR; + wip->wi_flags.set(Weapon::Info_Flags::Custom_seeker_str); if (wip->seeker_strength <= 0) { Warning(LOCATION,"Seeker Strength for missile \'%s\' must be greater than zero\nReseting value to default.", wip->name); wip->seeker_strength = 3.0f; - wip->wi_flags2 &= ~WIF2_CUSTOM_SEEKER_STR; + wip->wi_flags.remove(Weapon::Info_Flags::Custom_seeker_str); } } else { - if(!(wip->wi_flags2 & WIF2_CUSTOM_SEEKER_STR)) + if(!(wip->wi_flags[Weapon::Info_Flags::Custom_seeker_str])) wip->seeker_strength = 3.0f; } if (optional_string("+Target Lead Scaler:")) { stuff_float(&wip->target_lead_scaler); - if (wip->target_lead_scaler == 0.0f) - wip->wi_flags2 &= ~WIF2_VARIABLE_LEAD_HOMING; + if (wip->target_lead_scaler == 0.0f) + wip->wi_flags.remove(Weapon::Info_Flags::Variable_lead_homing); else { - wip->wi_flags2 |= WIF2_VARIABLE_LEAD_HOMING; - wi_flags2 |= WIF2_VARIABLE_LEAD_HOMING; + wip->wi_flags.set(Weapon::Info_Flags::Variable_lead_homing); + wi_flags.set(Weapon::Info_Flags::Variable_lead_homing); } } } - else if ((wip->wi_flags & WIF_HOMING_ASPECT) || (wip->wi_flags & WIF_HOMING_JAVELIN)) + else if ((wip->wi_flags[Weapon::Info_Flags::Homing_aspect]) || (wip->wi_flags[Weapon::Info_Flags::Homing_javelin])) { if(optional_string("+Turn Time:")) { stuff_float(&wip->turn_time); @@ -1393,31 +1323,31 @@ int parse_weapon(int subtype, bool replace, const char *filename) { //aspect default seeker strength is 2 stuff_float(&wip->seeker_strength); - wip->wi_flags2 |= WIF2_CUSTOM_SEEKER_STR; + wip->wi_flags.set(Weapon::Info_Flags::Custom_seeker_str); if (wip->seeker_strength <= 0) { Warning(LOCATION,"Seeker Strength for missile \'%s\' must be greater than zero\nReseting value to default.", wip->name); wip->seeker_strength = 2.0f; - wip->wi_flags2 &= ~WIF2_CUSTOM_SEEKER_STR; + wip->wi_flags.remove(Weapon::Info_Flags::Custom_seeker_str); } } else { - if(!(wip->wi_flags2 & WIF2_CUSTOM_SEEKER_STR)) + if(!(wip->wi_flags[Weapon::Info_Flags::Custom_seeker_str])) wip->seeker_strength = 2.0f; } if (optional_string("+Target Lead Scaler:")) { stuff_float(&wip->target_lead_scaler); if (wip->target_lead_scaler == 1.0f) - wip->wi_flags2 &= ~WIF2_VARIABLE_LEAD_HOMING; + wip->wi_flags.remove(Weapon::Info_Flags::Variable_lead_homing); else { - wip->wi_flags2 |= WIF2_VARIABLE_LEAD_HOMING; - wi_flags2 |= WIF2_VARIABLE_LEAD_HOMING; + wip->wi_flags.set(Weapon::Info_Flags::Variable_lead_homing); + wi_flags.set(Weapon::Info_Flags::Variable_lead_homing); } } - if (wip->wi_flags & WIF_LOCKED_HOMING) { + if (wip->is_locked_homing()) { // locked homing missiles have a much longer lifespan than the AI think they do wip->max_lifetime = wip->lifetime * LOCKED_HOMING_EXTENDED_LIFE_FACTOR; } @@ -1439,12 +1369,12 @@ int parse_weapon(int subtype, bool replace, const char *filename) wip->swarm_count = (short)s_count; // flag as being a swarm weapon - wip->wi_flags |= WIF_SWARM; - wi_flags |= WIF_SWARM; + wip->wi_flags.set(Weapon::Info_Flags::Swarm); + wi_flags.set(Weapon::Info_Flags::Swarm); } // *Swarm wait token -Et1 - if((wip->wi_flags & WIF_SWARM) && optional_string( "+SwarmWait:" )) + if((wip->wi_flags[Weapon::Info_Flags::Swarm]) && optional_string( "+SwarmWait:" )) { float SwarmWait; stuff_float( &SwarmWait ); @@ -1573,14 +1503,14 @@ int parse_weapon(int subtype, bool replace, const char *filename) } - parse_wi_flags(wip, wi_flags, wi_flags2, wi_flags3); + parse_wi_flags(wip, wi_flags); // be friendly; make sure ballistic flags are synchronized - Goober5000 // primary if (subtype == WP_LASER) { // ballistic - if (wip->wi_flags2 & WIF2_BALLISTIC) + if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) { // rearm rate not specified if (!primary_rearm_rate_specified && first_time) @@ -1604,15 +1534,15 @@ int parse_weapon(int subtype, bool replace, const char *filename) else { // ballistic - if (wip->wi_flags2 & WIF2_BALLISTIC) + if (wip->wi_flags[Weapon::Info_Flags::Ballistic]) { Warning(LOCATION, "Secondary weapon %s can't be ballistic. Removing this flag...\n", wip->name); - wip->wi_flags2 &= ~WIF2_BALLISTIC; + wip->wi_flags.remove(Weapon::Info_Flags::Ballistic); } } // also make sure EMP is friendly - Goober5000 - if (wip->wi_flags & WIF_EMP) + if (wip->wi_flags[Weapon::Info_Flags::Emp]) { if (!wip->shockwave.outer_rad) { @@ -1621,7 +1551,7 @@ int parse_weapon(int subtype, bool replace, const char *filename) } // also make sure secondaries and ballistic primaries do not have 0 cargo size - if (subtype == WP_MISSILE || wip->wi_flags2 & WIF2_BALLISTIC) + if (subtype == WP_MISSILE || wip->wi_flags[Weapon::Info_Flags::Ballistic]) { if (wip->cargo_size == 0.0f) { @@ -1632,7 +1562,7 @@ int parse_weapon(int subtype, bool replace, const char *filename) if ( optional_string("$Trail:") ) { trail_info *ti = &wip->tr_info; - wip->wi_flags |= WIF_TRAIL; // missile leaves a trail + wip->wi_flags.set(Weapon::Info_Flags::Trail); // missile leaves a trail if ( optional_string("+Start Width:") ) stuff_float(&ti->w_start); @@ -1926,9 +1856,9 @@ int parse_weapon(int subtype, bool replace, const char *filename) // This is an optional modifier for a weapon that uses the "apply recoil" flag. recoil_force in ship.cpp line 10445 is multiplied by this if defined. if (optional_string("$Recoil Modifier:")){ - if (!(wip->wi_flags3 & WIF3_APPLY_RECOIL)){ + if (!(wip->wi_flags[Weapon::Info_Flags::Apply_recoil])){ Warning(LOCATION, "$Recoil Modifier specified for weapon %s but this weapon does not have the \"apply recoil\" weapon flag set. Automatically setting the flag", wip->name); - wip->wi_flags3 |= WIF3_APPLY_RECOIL; + wip->wi_flags.set(Weapon::Info_Flags::Apply_Recoil); } stuff_float(&wip->recoil_modifier); } @@ -1978,7 +1908,7 @@ int parse_weapon(int subtype, bool replace, const char *filename) } if(optional_string("+Area Of Effect")) { - wip->wi_flags3 |= WIF3_AOE_ELECTRONICS; + wip->wi_flags.set(Weapon::Info_Flags::Aoe_Electronics); } //New only -WMC @@ -2037,7 +1967,7 @@ int parse_weapon(int subtype, bool replace, const char *filename) } } - if (wip->wi_flags2 & WIF2_LOCAL_SSM && optional_string("$Local SSM:")) + if (wip->wi_flags[Weapon::Info_Flags::Local_ssm] && optional_string("$Local SSM:")) { if(optional_string("+Warpout Delay:")) { stuff_int(&wip->lssm_warpout_delay); @@ -2062,7 +1992,7 @@ int parse_weapon(int subtype, bool replace, const char *filename) if (optional_string("$Countermeasure:")) { - if (!(wip->wi_flags & WIF_CMEASURE)) + if (!(wip->wi_flags[Weapon::Info_Flags::Cmeasure])) { Warning(LOCATION,"Weapon \'%s\' has countermeasure information defined, but the \"countermeasure\" flag wasn\'t found in the \'$Flags:\' field.\n", wip->name); } @@ -2445,9 +2375,9 @@ int parse_weapon(int subtype, bool replace, const char *filename) while ( optional_string("$Pspew:") ) { int spew_index = -1; // check for pspew flag - if (!( wip->wi_flags & WIF_PARTICLE_SPEW )) { + if (!( wip->wi_flags[Weapon::Info_Flags::Particle_spew] )) { Warning(LOCATION, "$Pspew specified for weapon %s but this weapon does not have the \"Particle Spew\" weapon flag set. Automatically setting the flag", wip->name); - wip->wi_flags |= WIF_PARTICLE_SPEW; + wip->wi_flags.set(Weapon::Info_Flags::Particle_spew); } // index for xmt edit, replace and remove support if (optional_string("+Index:")) { @@ -2559,7 +2489,7 @@ int parse_weapon(int subtype, bool replace, const char *filename) } } // check to see if the pspew flag was enabled but no pspew tags were given, for compatability with retail tables - if (wip->wi_flags & WIF_PARTICLE_SPEW) { + if (wip->wi_flags[Weapon::Info_Flags::Particle_spew]) { bool nospew = true; for (size_t s = 0; s < MAX_PARTICLE_SPEWERS; s++) if (wip->particle_spewers[s].particle_spew_type != PSPEW_NONE) { @@ -2574,7 +2504,7 @@ int parse_weapon(int subtype, bool replace, const char *filename) if( optional_string("$Tag:")){ stuff_int(&wip->tag_level); stuff_float(&wip->tag_time); - wip->wi_flags |= WIF_TAG; + wip->wi_flags.set(Weapon::Info_Flags::Tag); } if( optional_string("$SSM:")){ @@ -2648,7 +2578,7 @@ int parse_weapon(int subtype, bool replace, const char *filename) if (optional_string("$Transparent:")) { - wip->wi_flags2 |= WIF2_TRANSPARENT; + wip->wi_flags.set(Weapon::Info_Flags::Transparent); required_string("+Alpha:"); stuff_float(&wip->alpha_max); @@ -2675,12 +2605,12 @@ int parse_weapon(int subtype, bool replace, const char *filename) if (optional_string("$Weapon Hitpoints:")) { stuff_int(&wip->weapon_hitpoints); - } else if (first_time && (wip->wi_flags3 & (WIF3_TURRET_INTERCEPTABLE | WIF3_FIGHTER_INTERCEPTABLE))) { + } else if (first_time && (wip->wi_flags[Weapon::Info_Flags::Turret_Interceptable, Weapon::Info_Flags::Fighter_Interceptable])) { wip->weapon_hitpoints = 25; } // making sure bombs get their hitpoints assigned - if ((wip->wi_flags & WIF_BOMB) && (wip->weapon_hitpoints == 0)) { + if ((wip->wi_flags[Weapon::Info_Flags::Bomb]) && (wip->weapon_hitpoints == 0)) { wip->weapon_hitpoints = 50; } @@ -2707,7 +2637,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:")) { @@ -2729,7 +2659,7 @@ int parse_weapon(int subtype, bool replace, const char *filename) } //pretty stupid if a target must be tagged to shoot tag missiles at it - if ((wip->wi_flags & WIF_TAG) && (wip->wi_flags2 & WIF2_TAGGED_ONLY)) + if ((wip->wi_flags[Weapon::Info_Flags::Tag]) && (wip->wi_flags[Weapon::Info_Flags::Tagged_only])) { Warning(LOCATION, "%s is a tag missile, but the target must be tagged to shoot it", wip->name); } @@ -2919,7 +2849,7 @@ void parse_weaponstbl(const char *filename) } //Make sure cmeasure flag is set - Weapon_info[idx].wi_flags |= WIF_CMEASURE; + Weapon_info[idx].wi_flags.set(Weapon::Info_Flags::Cmeasure); //Set cmeasure index if (!strlen(Default_cmeasure_name)) { @@ -2970,9 +2900,9 @@ void weapon_sort_by_type() continue; case WP_LASER: - if (Weapon_info[i].wi_flags & WIF_CHILD) + if (Weapon_info[i].wi_flags[Weapon::Info_Flags::Child]) num_child_primaries++; - else if (Weapon_info[i].wi_flags & WIF_BIG_ONLY) + else if (Weapon_info[i].wi_flags[Weapon::Info_Flags::Big_only]) num_big_lasers++; else num_lasers++; @@ -2983,9 +2913,9 @@ void weapon_sort_by_type() break; case WP_MISSILE: - if (Weapon_info[i].wi_flags & WIF_CHILD) + if (Weapon_info[i].wi_flags[Weapon::Info_Flags::Child]) num_child_secondaries++; - else if (Weapon_info[i].wi_flags & WIF_BIG_ONLY) + else if (Weapon_info[i].wi_flags[Weapon::Info_Flags::Big_only]) num_big_missiles++; else num_missiles++; @@ -3048,9 +2978,9 @@ void weapon_sort_by_type() continue; case WP_LASER: - if (Weapon_info[i].wi_flags & WIF_CHILD) + if (Weapon_info[i].wi_flags[Weapon::Info_Flags::Child]) child_primaries[num_child_primaries++] = Weapon_info[i]; - else if (Weapon_info[i].wi_flags & WIF_BIG_ONLY) + else if (Weapon_info[i].wi_flags[Weapon::Info_Flags::Big_only]) big_lasers[num_big_lasers++] = Weapon_info[i]; else lasers[num_lasers++] = Weapon_info[i]; @@ -3061,9 +2991,9 @@ void weapon_sort_by_type() break; case WP_MISSILE: - if (Weapon_info[i].wi_flags & WIF_CHILD) + if (Weapon_info[i].wi_flags[Weapon::Info_Flags::Child]) child_secondaries[num_child_secondaries++] = Weapon_info[i]; - else if (Weapon_info[i].wi_flags & WIF_BIG_ONLY) + else if (Weapon_info[i].wi_flags[Weapon::Info_Flags::Big_only]) big_missiles[num_big_missiles++] = Weapon_info[i]; else missiles[num_missiles++]=Weapon_info[i]; @@ -3122,7 +3052,7 @@ void weapon_clean_entries() for (i = 0; i < Num_weapon_types; i++) { wip = &Weapon_info[i]; - if (wip->wi_flags & WIF_BEAM) { + if (wip->wi_flags[Weapon::Info_Flags::Beam]) { // clean up any beam sections which may have been deleted int removed = 0; @@ -3185,7 +3115,7 @@ void weapon_release_bitmaps() } } - if (wip->wi_flags & WIF_BEAM) { + if (wip->wi_flags[Weapon::Info_Flags::Beam]) { // particle animation if (wip->b_info.beam_particle_ani.first_frame >= 0) { bm_release(wip->b_info.beam_particle_ani.first_frame); @@ -3209,14 +3139,14 @@ void weapon_release_bitmaps() } } - if (wip->wi_flags & WIF_TRAIL) { + if (wip->wi_flags[Weapon::Info_Flags::Trail]) { if (wip->tr_info.texture.bitmap_id >= 0) { bm_release(wip->tr_info.texture.bitmap_id); wip->tr_info.texture.bitmap_id = -1; } } - if (wip->wi_flags & WIF_PARTICLE_SPEW) { // tweaked for multiple particle spews -nuke + if (wip->wi_flags[Weapon::Info_Flags::Particle_spew]) { // tweaked for multiple particle spews -nuke for (size_t s = 0; s < MAX_PARTICLE_SPEWERS; s++) { // just bitmaps that got loaded if (wip->particle_spewers[s].particle_spew_type != PSPEW_NONE){ if (wip->particle_spewers[s].particle_spew_anim.first_frame >= 0) { @@ -3289,7 +3219,7 @@ void weapon_load_bitmaps(int weapon_index) } } - if (wip->wi_flags & WIF_BEAM) { + if (wip->wi_flags[Weapon::Info_Flags::Beam]) { // particle animation if ( (wip->b_info.beam_particle_ani.first_frame < 0) && strlen(wip->b_info.beam_particle_ani.filename) ) generic_anim_load(&wip->b_info.beam_particle_ani); @@ -3331,11 +3261,11 @@ void weapon_load_bitmaps(int weapon_index) } } - if ( (wip->wi_flags & WIF_TRAIL) && (wip->tr_info.texture.bitmap_id < 0) ) + if ( (wip->wi_flags[Weapon::Info_Flags::Trail]) && (wip->tr_info.texture.bitmap_id < 0) ) generic_bitmap_load(&wip->tr_info.texture); //WMC - Don't try to load an anim if no anim is specified, Mmkay? - if (wip->wi_flags & WIF_PARTICLE_SPEW) { + if (wip->wi_flags[Weapon::Info_Flags::Particle_spew]) { for (size_t s = 0; s < MAX_PARTICLE_SPEWERS; s++) { // looperfied for multiple pspewers -nuke if (wip->particle_spewers[s].particle_spew_type != PSPEW_NONE){ @@ -3430,7 +3360,7 @@ void weapon_do_post_parse() } // catch a fall back cmeasure index, just in case - if ( (first_cmeasure_index < 0) && (wip->wi_flags & WIF_CMEASURE) ) + if ( (first_cmeasure_index < 0) && (wip->wi_flags[Weapon::Info_Flags::Cmeasure]) ) first_cmeasure_index = i; } @@ -3446,7 +3376,7 @@ void weapon_do_post_parse() int index = weapon_info_lookup(ii->cmeasure_name); if (index < 0) Warning(LOCATION, "Could not find weapon type '%s' to use as countermeasure on species '%s'", ii->cmeasure_name, ii->species_name); - else if (Weapon_info[index].wi_flags & WIF_BEAM) + else if (Weapon_info[index].wi_flags[Weapon::Info_Flags::Beam]) Warning(LOCATION, "Attempt made to set a beam weapon as a countermeasure on species '%s'", ii->species_name); else ii->cmeasure_index = index; @@ -3657,15 +3587,15 @@ 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 & WIF_HOMING_HEAT) || - (Weapon_info[wp->weapon_info_index].wi_flags & WIF_HOMING_JAVELIN) ) { + if ( (Weapon_info[wp->weapon_info_index].wi_flags[Weapon::Info_Flags::Homing_heat]) || + (Weapon_info[wp->weapon_info_index].wi_flags[Weapon::Info_Flags::Homing_javelin]) ) { snd_play(&Snds[ship_get_sound(Player_obj, SND_HEATLOCK_WARN)]); } else { - Assert(Weapon_info[wp->weapon_info_index].wi_flags & WIF_HOMING_ASPECT); + Assert(Weapon_info[wp->weapon_info_index].wi_flags[Weapon::Info_Flags::Homing_aspect]); snd_play(&Snds[ship_get_sound(Player_obj, SND_ASPECTLOCK_WARN)]); } } @@ -3750,16 +3680,16 @@ void find_homing_object(object *weapon_objp, int num) // Scan all objects, find a weapon to home on. for ( objp = GET_FIRST(&obj_used_list); objp !=END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) { - if ((objp->type == OBJ_SHIP) || ((objp->type == OBJ_WEAPON) && (Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags & WIF_CMEASURE))) + if ((objp->type == OBJ_SHIP) || ((objp->type == OBJ_WEAPON) && (Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Cmeasure]))) { //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_flags2 & WIF2_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); @@ -3772,7 +3702,7 @@ void find_homing_object(object *weapon_objp, int num) //if the homing weapon is a huge weapon and the ship that is being //looked at is not huge, then don't home - if ((wip->wi_flags & WIF_HUGE) && + if ((wip->wi_flags[Weapon::Info_Flags::Huge]) && (sip->is_small_ship() || !sip->is_flyable() || sip->is_harmless())) { continue; @@ -3789,7 +3719,7 @@ void find_homing_object(object *weapon_objp, int num) continue; } - if (wip->wi_flags & WIF_HOMING_JAVELIN) + if (wip->wi_flags[Weapon::Info_Flags::Homing_javelin]) { target_engines = ship_get_closest_subsys_in_sight(sp, SUBSYSTEM_ENGINE, &weapon_objp->pos); @@ -3810,7 +3740,7 @@ void find_homing_object(object *weapon_objp, int num) else if (objp->type == OBJ_WEAPON) { //don't attempt to home on weapons if the weapon is a huge weapon or is a javelin homing weapon. - if (wip->wi_flags & (WIF_HUGE | WIF_HOMING_JAVELIN)) + if (wip->wi_flags[Weapon::Info_Flags::Huge, Weapon::Info_Flags::Homing_javelin]) continue; //don't look for local ssms that are gone for the time being @@ -3820,7 +3750,7 @@ void find_homing_object(object *weapon_objp, int num) dist = vm_vec_normalized_dir(&vec_to_object, &objp->pos, &weapon_objp->pos); - if (objp->type == OBJ_WEAPON && (Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags & WIF_CMEASURE)) { + if (objp->type == OBJ_WEAPON && (Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Cmeasure])) { dist *= 0.5f; } @@ -3872,7 +3802,7 @@ void find_homing_object_cmeasures_1(object *weapon_objp) cm_wp = &Weapons[objp->instance]; cm_wip = &Weapon_info[cm_wp->weapon_info_index]; - if (cm_wip->wi_flags & WIF_CMEASURE) + if (cm_wip->wi_flags[Weapon::Info_Flags::Cmeasure]) { //don't have a weapon try to home in on itself if (objp==weapon_objp) @@ -3907,7 +3837,7 @@ void find_homing_object_cmeasures_1(object *weapon_objp) } } - if (wip->wi_flags & WIF_HOMING_ASPECT) { + if (wip->wi_flags[Weapon::Info_Flags::Homing_aspect]) { // aspect seeker this likely to chase a countermeasure chance = cm_wip->cm_aspect_effectiveness/wip->seeker_strength; } else { @@ -3963,7 +3893,7 @@ void find_homing_object_cmeasures() if (weapon_objp->type == OBJ_WEAPON) { weapon_info *wip = &Weapon_info[Weapons[weapon_objp->instance].weapon_info_index]; - if (wip->wi_flags & WIF_HOMING) + if (wip->is_homing()) find_homing_object_cmeasures_1(weapon_objp); } } @@ -4013,11 +3943,11 @@ bool aspect_should_lose_target(weapon* wp) { weapon_info* target_info = &Weapon_info[Weapons[wp->homing_object->instance].weapon_info_index]; - if (target_info->wi_flags & WIF_CMEASURE) + 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 - || target_info->wi_flags3 & WIF3_CMEASURE_ASPECT_HOME_ON; + || target_info->wi_flags[Weapon::Info_Flags::Cmeasure_aspect_home_on]; if (!home_on_cmeasure) { @@ -4051,7 +3981,7 @@ void weapon_home(object *obj, int num, float frame_time) float max_speed; - if ((wip->wi_flags2 & WIF2_LOCAL_SSM) && (wp->lssm_stage==5)) + if ((wip->wi_flags[Weapon::Info_Flags::Local_ssm]) && (wp->lssm_stage==5)) max_speed=wip->lssm_stage5_vel; else max_speed=wip->max_speed; @@ -4063,19 +3993,19 @@ void weapon_home(object *obj, int num, float frame_time) if (f2fl(Missiontime - wp->creation_time) > wip->free_flight_time) { // If this is a heat seeking homing missile and [free-flight-time] has elapsed since firing // and we don't have a target (else we wouldn't be inside the IF), find a new target. - if (wip->wi_flags & WIF_HOMING_HEAT) { + if (wip->wi_flags[Weapon::Info_Flags::Homing_heat]) { find_homing_object(obj, num); } // modders may want aspect homing missiles to die if they lose their target - else if (wip->wi_flags & WIF_LOCKED_HOMING && wip->wi_flags3 & WIF3_DIE_ON_LOST_LOCK) { + else if (wip->is_locked_homing() && wip->wi_flags[Weapon::Info_Flags::Die_on_lost_lock]) { if (wp->lifeleft > 0.5f) { wp->lifeleft = frand_range(0.1f, 0.5f); // randomise a bit to avoid multiple missiles detonating in one frame } return; } } - else if (MULTIPLAYER_MASTER && (wip->wi_flags & WIF_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); } @@ -4091,7 +4021,7 @@ void weapon_home(object *obj, int num, float frame_time) else if (wip->free_flight_time > 0.0f) { if (obj->phys_info.speed > max_speed) { obj->phys_info.speed -= frame_time * (2 / wip->free_flight_time); - } else if ((obj->phys_info.speed < max_speed / (2 / wip->free_flight_time)) && (wip->wi_flags & WIF_HOMING_HEAT)) { + } else if ((obj->phys_info.speed < max_speed / (2 / wip->free_flight_time)) && (wip->wi_flags[Weapon::Info_Flags::Homing_heat])) { obj->phys_info.speed = max_speed / (2 / wip->free_flight_time); } } @@ -4121,7 +4051,7 @@ void weapon_home(object *obj, int num, float frame_time) // AL 4-8-98: If original target for aspect lock missile is lost, stop homing // WCS - or javelin - if (wip->wi_flags & WIF_LOCKED_HOMING) { + if (wip->is_locked_homing()) { if ( wp->target_sig > 0 ) { if (aspect_should_lose_target(wp)) { @@ -4132,7 +4062,7 @@ void weapon_home(object *obj, int num, float frame_time) } // AL 4-13-98: Stop homing on a subsystem if parent ship has changed - if (wip->wi_flags & WIF_HOMING_HEAT) { + if (wip->wi_flags[Weapon::Info_Flags::Homing_heat]) { if ( wp->target_sig > 0 ) { if ( wp->homing_object->signature != wp->target_sig ) { wp->homing_subsys = NULL; @@ -4151,7 +4081,7 @@ void weapon_home(object *obj, int num, float frame_time) } // Make sure Javelin HS missiles always home on engine subsystems if ships - if ((wip->wi_flags & WIF_HOMING_JAVELIN) && + if ((wip->wi_flags[Weapon::Info_Flags::Homing_javelin]) && (hobjp->type == OBJ_SHIP) && (wp->target_sig > 0) && (wp->homing_subsys != NULL) && @@ -4166,7 +4096,7 @@ void weapon_home(object *obj, int num, float frame_time) // If Javelin HS missile doesn't home in on a subsystem but homing in on a // ship, lose lock alltogether // Javelins can only home in one Engines or bombs. - if ((wip->wi_flags & WIF_HOMING_JAVELIN) && + if ((wip->wi_flags[Weapon::Info_Flags::Homing_javelin]) && (hobjp->type == OBJ_SHIP) && (wp->target_sig > 0) && (wp->homing_subsys == NULL)) { @@ -4178,7 +4108,7 @@ void weapon_home(object *obj, int num, float frame_time) switch (hobjp->type) { case OBJ_NONE: - if (wip->wi_flags & WIF_LOCKED_HOMING) { + if (wip->is_locked_homing()) { find_homing_object_by_sig(obj, wp->target_sig); } else { @@ -4188,7 +4118,7 @@ void weapon_home(object *obj, int num, float frame_time) break; case OBJ_SHIP: if (hobjp->signature != wp->target_sig) { - if (wip->wi_flags & WIF_LOCKED_HOMING) { + if (wip->is_locked_homing()) { find_homing_object_by_sig(obj, wp->target_sig); } else { @@ -4200,19 +4130,19 @@ void weapon_home(object *obj, int num, float frame_time) case OBJ_WEAPON: { bool home_on_cmeasure = The_mission.ai_profile->flags2 & AIPF2_ASPECT_LOCK_COUNTERMEASURE - || hobj_infop->wi_flags3 & WIF3_CMEASURE_ASPECT_HOME_ON; + || hobj_infop->wi_flags[Weapon::Info_Flags::Cmeasure_aspect_home_on]; // don't home on countermeasures or non-bombs, that's handled elsewhere - if (((hobj_infop->wi_flags & WIF_CMEASURE) && !home_on_cmeasure)) + if (((hobj_infop->wi_flags[Weapon::Info_Flags::Cmeasure]) && !home_on_cmeasure)) { break; } - else if (!(hobj_infop->wi_flags & WIF_BOMB)) + else if (!(hobj_infop->wi_flags[Weapon::Info_Flags::Bomb])) { break; } - if (wip->wi_flags & WIF_LOCKED_HOMING) { + if (wip->is_locked_homing()) { find_homing_object_by_sig(obj, wp->target_sig); } else { @@ -4255,7 +4185,7 @@ void weapon_home(object *obj, int num, float frame_time) // world coordinates of that subsystem so the homing missile can seek it out. // For now, March 7, 1997, MK, heat seeking homing missiles will be able to home on // any subsystem. Probably makes sense for them to only home on certain kinds of subsystems. - if ( (wp->homing_subsys != NULL) && !(wip->wi_flags2 & WIF2_NON_SUBSYS_HOMING) && hobjp->type == OBJ_SHIP) { + if ( (wp->homing_subsys != NULL) && !(wip->wi_flags[Weapon::Info_Flags::Non_subsys_homing]) && hobjp->type == OBJ_SHIP) { get_subsystem_world_pos(hobjp, Weapons[num].homing_subsys, &target_pos); wp->homing_pos = target_pos; // store the homing position in weapon data Assert( !vm_is_vec_nan(&wp->homing_pos) ); @@ -4264,7 +4194,7 @@ void weapon_home(object *obj, int num, float frame_time) float dist; dist = vm_vec_dist_quick(&obj->pos, &hobjp->pos); - if (hobjp->type == OBJ_WEAPON && (hobj_infop->wi_flags & WIF_CMEASURE)) + if (hobjp->type == OBJ_WEAPON && (hobj_infop->wi_flags[Weapon::Info_Flags::Cmeasure])) { if (dist < hobj_infop->cm_detonation_rad) { @@ -4296,7 +4226,7 @@ void weapon_home(object *obj, int num, float frame_time) wp->pick_big_attack_point_timestamp = 0; } - if ( pick_homing_point && !(wip->wi_flags2 & WIF2_NON_SUBSYS_HOMING) ) { + if ( pick_homing_point && !(wip->wi_flags[Weapon::Info_Flags::Non_subsys_homing]) ) { // If *any* player is parent of homing missile, then use position where lock indicator is if ( Objects[obj->parent].flags[Object::Object_Flags::Player_ship] ) { player *pp; @@ -4315,7 +4245,7 @@ void weapon_home(object *obj, int num, float frame_time) // If player has apect lock, we don't want to find a homing point on the closest // octant... setting the timestamp to 0 ensures this. - if (wip->wi_flags & WIF_LOCKED_HOMING) { + if (wip->is_locked_homing()) { wp->pick_big_attack_point_timestamp = 0; } else { wp->pick_big_attack_point_timestamp = 1; @@ -4374,24 +4304,24 @@ void weapon_home(object *obj, int num, float frame_time) // Only lead target if more than one second away. Otherwise can miss target. I think this // is what's causing Harbingers to miss the super destroyer. -- MK, 4/15/98 if ((old_dot > 0.1f) && (time_to_target > 0.1f)) { - if (wip->wi_flags2 & WIF2_VARIABLE_LEAD_HOMING) { + if (wip->wi_flags[Weapon::Info_Flags::Variable_lead_homing]) { vm_vec_scale_add2(&target_pos, &hobjp->phys_info.vel, (0.33f * wip->target_lead_scaler * MIN(time_to_target, 6.0f))); - } else if (wip->wi_flags & WIF_LOCKED_HOMING) { + } else if (wip->is_locked_homing()) { vm_vec_scale_add2(&target_pos, &hobjp->phys_info.vel, MIN(time_to_target, 2.0f)); } } // If a HEAT seeking (rather than ASPECT seeking) homing missile, verify that target is in viewcone. - if (wip->wi_flags & WIF_HOMING_HEAT) { + if (wip->wi_flags[Weapon::Info_Flags::Homing_heat]) { if ((old_dot < wip->fov) && (dist_to_target > wip->shockwave.inner_rad*1.1f)) { // Delay finding new target one frame to allow detonation. find_homing_object(obj, num); return; // Maybe found a new homing object. Return, process more next frame. } else // Subtract out life based on how far from target this missile points. - if ((wip->fov < 0.95f) && !(wip->wi_flags2 & WIF2_NO_LIFE_LOST_IF_MISSED)) { + if ((wip->fov < 0.95f) && !(wip->wi_flags[Weapon::Info_Flags::No_life_lost_if_missed])) { wp->lifeleft -= flFrametime * (0.95f - old_dot); } - } else if (wip->wi_flags & WIF_LOCKED_HOMING) { // subtract life as if max turn is 90 degrees. - if ((wip->fov < 0.95f) && !(wip->wi_flags2 & WIF2_NO_LIFE_LOST_IF_MISSED)) + } else if (wip->is_locked_homing()) { // subtract life as if max turn is 90 degrees. + if ((wip->fov < 0.95f) && !(wip->wi_flags[Weapon::Info_Flags::No_life_lost_if_missed])) wp->lifeleft -= flFrametime * (0.95f - old_dot); } else { Warning(LOCATION, "Tried to make weapon '%s' home, but found it wasn't aspect-seeking or heat-seeking or a Javelin!", wip->name); @@ -4416,7 +4346,7 @@ void weapon_home(object *obj, int num, float frame_time) t = f2fl(Missiontime - wp->creation_time) / wip->acceleration_time; obj->phys_info.speed = wp->launch_speed + MAX(0.0f, wp->weapon_max_vel - wp->launch_speed) * t; } - } else if (!(wip->wi_flags3 & WIF3_NO_HOMING_SPEED_RAMP) && Missiontime - wp->creation_time < i2f(1)) { + } else if (!(wip->wi_flags[Weapon::Info_Flags::No_homing_speed_ramp]) && Missiontime - wp->creation_time < i2f(1)) { // Default behavior: // For first second of weapon's life, it doesn't fly at top speed. It ramps up. float t; @@ -4501,10 +4431,10 @@ void weapon_maybe_play_flyby_sound(object *weapon_objp, weapon *wp) return; } - if ( !(wp->weapon_flags & WF_PLAYED_FLYBY_SOUND) ) { + if ( !(wp->weapon_flags[Weapon::Weapon_Flags::Played_flyby_sound]) ) { float dist, dot, radius; - if ( (Weapon_info[wp->weapon_info_index].wi_flags & WIF_CORKSCREW) ) { + if ( (Weapon_info[wp->weapon_info_index].wi_flags[Weapon::Info_Flags::Corkscrew]) ) { dist = vm_vec_dist_quick(&weapon_objp->last_pos, &Eye_position); } else { dist = vm_vec_dist_quick(&weapon_objp->pos, &Eye_position); @@ -4540,7 +4470,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); } } } @@ -4656,7 +4586,7 @@ void weapon_process_post(object * obj, float frame_time) wip = &Weapon_info[wp->weapon_info_index]; - if (wip->wi_flags2 & WIF2_LOCAL_SSM) + if (wip->wi_flags[Weapon::Info_Flags::Local_ssm]) { if ((wp->lssm_stage != 5) && (wp->lssm_stage != 0)) { @@ -4670,13 +4600,13 @@ void weapon_process_post(object * obj, float frame_time) if ( wp->lifeleft < 0.0f ) { if ( wip->subtype & WP_MISSILE ) { if(Game_mode & GM_MULTIPLAYER){ - if ( !MULTIPLAYER_CLIENT || (MULTIPLAYER_CLIENT && (wp->lifeleft < -2.0f)) || (MULTIPLAYER_CLIENT && (wip->wi_flags & WIF_CHILD))) { // don't call this function multiplayer client -- host will send this packet to us + if ( !MULTIPLAYER_CLIENT || (MULTIPLAYER_CLIENT && (wp->lifeleft < -2.0f)) || (MULTIPLAYER_CLIENT && (wip->wi_flags[Weapon::Info_Flags::Child]))) { // don't call this function multiplayer client -- host will send this packet to us weapon_detonate(obj); } } else { weapon_detonate(obj); } - if (wip->wi_flags & WIF_HOMING) { + if (wip->is_homing()) { Homing_misses++; } } else { @@ -4687,14 +4617,14 @@ void weapon_process_post(object * obj, float frame_time) } // plot homing missiles on the radar - if (((wip->wi_flags & WIF_BOMB) || (wip->wi_flags2 & WIF2_SHOWN_ON_RADAR)) && !(wip->wi_flags2 & WIF2_DONT_SHOW_ON_RADAR)) { + if (((wip->wi_flags[Weapon::Info_Flags::Bomb]) || (wip->wi_flags[Weapon::Info_Flags::Shown_on_radar])) && !(wip->wi_flags[Weapon::Info_Flags::Dont_show_on_radar])) { if ( hud_gauge_active(HUD_RADAR) ) { radar_plot_object( obj ); } } // trail missiles - if ((wip->wi_flags & WIF_TRAIL) && !(wip->wi_flags & WIF_CORKSCREW)) { + if ((wip->wi_flags[Weapon::Info_Flags::Trail]) && !(wip->wi_flags[Weapon::Info_Flags::Corkscrew])) { if ( (wp->trail_ptr != NULL ) && (wp->lssm_stage!=3)) { vec3d pos; @@ -4717,7 +4647,7 @@ void weapon_process_post(object * obj, float frame_time) } } - if ( wip->wi_flags & WIF_THRUSTER ) { + if ( wip->wi_flags[Weapon::Info_Flags::Thruster] ) { ship_do_weapon_thruster_frame( wp, obj, flFrametime ); } @@ -4777,12 +4707,12 @@ void weapon_process_post(object * obj, float frame_time) } } - if(wip->wi_flags & WIF_PARTICLE_SPEW){ + if(wip->wi_flags[Weapon::Info_Flags::Particle_spew]){ weapon_maybe_spew_particle(obj); } // a single player or multiplayer server function -- it affects actual weapon movement. - if (wip->wi_flags & WIF_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, @@ -4808,7 +4738,7 @@ void weapon_process_post(object * obj, float frame_time) } //local ssm stuff - if (wip->wi_flags2 & WIF2_LOCAL_SSM) + if (wip->wi_flags[Weapon::Info_Flags::Local_ssm]) { //go into subspace if the missile is locked and its time to warpout if ((wp->lssm_stage==1) && (timestamp_elapsed(wp->lssm_warpout_time))) @@ -4971,7 +4901,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; } @@ -4983,7 +4913,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; @@ -5020,11 +4950,11 @@ void weapon_set_tracking_info(int weapon_objnum, int parent_objnum, int target_o wp->target_num = target_objnum; wp->target_sig = Objects[target_objnum].signature; wp->nearest_dist = 99999.0f; - if ( (wip->wi_flags & WIF_HOMING_ASPECT) && target_is_locked) { + if ( (wip->wi_flags[Weapon::Info_Flags::Homing_aspect]) && target_is_locked) { wp->homing_object = &Objects[target_objnum]; wp->homing_subsys = target_subsys; weapon_maybe_play_warning(wp); - } else if ( (wip->wi_flags & WIF_HOMING_JAVELIN) && target_is_locked) { + } else if ( (wip->wi_flags[Weapon::Info_Flags::Homing_javelin]) && target_is_locked) { if ((Objects[target_objnum].type == OBJ_SHIP) && ( (wp->homing_subsys == NULL) || (wp->homing_subsys->system_info->type != SUBSYSTEM_ENGINE) )) { @@ -5042,10 +4972,10 @@ void weapon_set_tracking_info(int weapon_objnum, int parent_objnum, int target_o wp->homing_subsys = target_subsys; weapon_maybe_play_warning(wp); } - } else if ( wip->wi_flags & WIF_HOMING_HEAT ) { + } else if ( wip->wi_flags[Weapon::Info_Flags::Homing_heat] ) { // Make a heat seeking missile try to home. If the target is outside the view cone, it will // immediately drop it and try to find one in its view cone. - if ((target_objnum != -1) && !(wip->wi_flags2 & WIF2_UNTARGETED_HEAT_SEEKER)) { + if ((target_objnum != -1) && !(wip->wi_flags[Weapon::Info_Flags::Untargeted_heat_seeker])) { wp->homing_object = &Objects[target_objnum]; wp->homing_subsys = target_subsys; weapon_maybe_play_warning(wp); @@ -5065,10 +4995,10 @@ void weapon_set_tracking_info(int weapon_objnum, int parent_objnum, int target_o // DB - removed 7:14 pm 9/6/99. was totally messing up lifetimes for all weapons. // MK, 7:11 am, 9/7/99. Put it back in, but with a proper check here to make sure it's an aspect seeker and // put a sanity check in the color changing laser code that was broken by this code. - if (target_is_locked && (wp->target_num != -1) && (wip->wi_flags & WIF_LOCKED_HOMING) ) { + 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); } } @@ -5121,7 +5051,7 @@ int weapon_create( vec3d * pos, matrix * porient, int weapon_type, int parent_ob wip = &Weapon_info[weapon_type]; // beam weapons should never come through here! - if(wip->wi_flags & WIF_BEAM) + if(wip->wi_flags[Weapon::Info_Flags::Beam]) { Warning(LOCATION, "An attempt to fire a beam ('%s') through weapon_create() was made.\n", wip->name); return -1; @@ -5242,7 +5172,7 @@ int weapon_create( vec3d * pos, matrix * porient, int weapon_type, int parent_ob // check if laser or dumbfire missile // set physics flag to allow optimization - if ((wip->subtype == WP_LASER) || ((wip->subtype == WP_MISSILE) && !(wip->wi_flags & WIF_HOMING) && wip->acceleration_time == 0.0f)) { + if ((wip->subtype == WP_LASER) || ((wip->subtype == WP_MISSILE) && !(wip->is_homing()) && wip->acceleration_time == 0.0f)) { // set physics flag objp->phys_info.flags |= PF_CONST_VEL; } @@ -5268,7 +5198,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; @@ -5287,14 +5217,14 @@ int weapon_create( vec3d * pos, matrix * porient, int weapon_type, int parent_ob // init the weapon state wp->weapon_state = WeaponState::INVALID; - if ( wip->wi_flags & WIF_SWARM ) { + if ( wip->wi_flags[Weapon::Info_Flags::Swarm] ) { wp->swarm_index = (short)swarm_create(); } else { wp->swarm_index = -1; } // if this is a particle spewing weapon, setup some stuff - if (wip->wi_flags & WIF_PARTICLE_SPEW) { + if (wip->wi_flags[Weapon::Info_Flags::Particle_spew]) { for (size_t s = 0; s < MAX_PARTICLE_SPEWERS; s++) { // allow for multiple time values if (wip->particle_spewers[s].particle_spew_type != PSPEW_NONE) { wp->particle_spew_time[s] = -1; @@ -5311,7 +5241,7 @@ int weapon_create( vec3d * pos, matrix * porient, int weapon_type, int parent_ob // for weapons that respawn, add the number of respawnable weapons to the net signature pool // to reserve N signatures for the spawned weapons - if ( wip->wi_flags & WIF_SPAWN ){ + if ( wip->wi_flags[Weapon::Info_Flags::Spawn] ){ multi_set_network_signature( (ushort)(Objects[objnum].net_signature + wip->total_children_spawned), MULTI_SIG_NON_PERMANENT ); } } else { @@ -5336,19 +5266,19 @@ int weapon_create( vec3d * pos, matrix * porient, int weapon_type, int parent_ob wp->lifeleft = wip->lifetime; } else { wp->lifeleft = (rand_val) * (wip->life_max - wip->life_min) / wip->life_min; - if((wip->wi_flags & WIF_CMEASURE) && (parent_objp != NULL) && (parent_objp->flags[Object::Object_Flags::Player_ship])) { + if((wip->wi_flags[Weapon::Info_Flags::Cmeasure]) && (parent_objp != NULL) && (parent_objp->flags[Object::Object_Flags::Player_ship])) { wp->lifeleft *= The_mission.ai_profile->cmeasure_life_scale[Game_skill_level]; } wp->lifeleft = wip->life_min + wp->lifeleft * (wip->life_max - wip->life_min); } - if(wip->wi_flags & WIF_CMEASURE) { + if(wip->wi_flags[Weapon::Info_Flags::Cmeasure]) { //2-frame homing check, to fend off sync errors Cmeasures_homing_check = 2; } // Make remote detonate missiles look like they're getting detonated by firer simply by giving them variable lifetimes. - if (parent_objp != NULL && !(parent_objp->flags[Object::Object_Flags::Player_ship]) && (wip->wi_flags & WIF_REMOTE)) { + if (parent_objp != NULL && !(parent_objp->flags[Object::Object_Flags::Player_ship]) && (wip->wi_flags[Weapon::Info_Flags::Remote])) { wp->lifeleft = wp->lifeleft/2.0f + rand_val * wp->lifeleft/2.0f; } @@ -5390,7 +5320,7 @@ int weapon_create( vec3d * pos, matrix * porient, int weapon_type, int parent_ob objp->phys_info.vel = objp->phys_info.desired_vel; objp->phys_info.speed = 0.0f; wp->launch_speed = 0.0f; - } else if (!(wip->wi_flags & WIF_HOMING)) { + } else if (!(wip->is_homing())) { vm_vec_copy_scale(&objp->phys_info.desired_vel, &objp->orient.vec.fvec, objp->phys_info.max_vel.xyz.z ); objp->phys_info.vel = objp->phys_info.desired_vel; objp->phys_info.speed = vm_vec_mag(&objp->phys_info.desired_vel); @@ -5432,13 +5362,13 @@ int weapon_create( vec3d * pos, matrix * porient, int weapon_type, int parent_ob } // create the corkscrew - if ( wip->wi_flags & WIF_CORKSCREW ) { + if ( wip->wi_flags[Weapon::Info_Flags::Corkscrew] ) { wp->cscrew_index = (short)cscrew_create(objp); } else { wp->cscrew_index = -1; } - if (wip->wi_flags2 & WIF2_LOCAL_SSM) + if (wip->wi_flags[Weapon::Info_Flags::Local_ssm]) { Assert(parent_objp); //local ssms must have a parent @@ -5454,7 +5384,7 @@ int weapon_create( vec3d * pos, matrix * porient, int weapon_type, int parent_ob // if this is a flak weapon shell, make it so // NOTE : this function will change some fundamental things about the weapon object - if ( (wip->wi_flags & WIF_FLAK) && !(wip->wi_flags2 & WIF2_RENDER_FLAK) ) { + if ( (wip->wi_flags[Weapon::Info_Flags::Flak]) && !(wip->wi_flags[Weapon::Info_Flags::Render_flak]) ) { obj_set_flags(&Objects[wp->objnum], Objects[wp->objnum].flags - Object::Object_Flags::Renders); } @@ -5464,7 +5394,7 @@ int weapon_create( vec3d * pos, matrix * porient, int weapon_type, int parent_ob wp->missile_list_index = missile_obj_list_add(objnum); } - if (wip->wi_flags & WIF_TRAIL /*&& !(wip->wi_flags & WIF_CORKSCREW) */) { + if (wip->wi_flags[Weapon::Info_Flags::Trail] /*&& !(wip->wi_flags[Weapon::Info_Flags::Corkscrew]) */) { wp->trail_ptr = trail_create(&wip->tr_info); if ( wp->trail_ptr != NULL ) { @@ -5481,7 +5411,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); @@ -5505,19 +5435,19 @@ int weapon_create( vec3d * pos, matrix * porient, int weapon_type, int parent_ob // to enable thrusters for previously non-loaded weapons (ie, weapons_page_in_cheats()) // when using cheat-keys, so we need to make sure and enable thrusters here if needed if (pm->n_thrusters > 0) { - wip->wi_flags |= WIF_THRUSTER; + wip->wi_flags.set(Weapon::Info_Flags::Thruster); } #endif } // 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; @@ -5611,7 +5541,7 @@ void spawn_child_weapons(object *objp) vm_vec_scale_add(&pos, opos, &tvec, objp->radius); // Let's allow beam-spawn! -MageKing17 - if (child_wip->wi_flags & WIF_BEAM) { + if (child_wip->wi_flags[Weapon::Info_Flags::Beam]) { beam_fire_info fire_info; memset(&fire_info, 0, sizeof(beam_fire_info)); @@ -5630,10 +5560,10 @@ 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_flags2 & WIF2_INHERIT_PARENT_TARGET) && (wp->homing_object != &obj_used_list)) + if ((child_wip->wi_flags[Weapon::Info_Flags::Inherit_parent_target]) && (wp->homing_object != &obj_used_list)) { //Deal with swarm weapons if (wp->swarm_index >= 0) { @@ -5707,7 +5637,7 @@ void weapon_hit_do_sound(object *hit_obj, weapon_info *wip, vec3d *hitpos, bool if ( wip->subtype != WP_MISSILE ) { if ( !hit_obj ) { // flak weapons make sounds - if(wip->wi_flags & WIF_FLAK) + if(wip->wi_flags[Weapon::Info_Flags::Flak]) { weapon_play_impact_sound(wip, hitpos, is_armed); } @@ -5789,7 +5719,7 @@ void weapon_hit_do_sound(object *hit_obj, weapon_info *wip, vec3d *hitpos, bool } } -extern bool turret_weapon_has_flags(ship_weapon *swp, int flags); +extern bool turret_weapon_has_flags(ship_weapon *swp, Weapon::Info_Flags flags); /** * Distrupt any subsystems that fall into damage sphere of this Electronics missile @@ -5841,7 +5771,7 @@ void weapon_do_electronics_effect(object *ship_objp, vec3d *blast_pos, int wi_in //I figure, the big fancy electronics on beams will be used for the other //weapons as well. No reason having two targeting computers on a turret. //Plus, it's easy and fast to code. :) - if ((psub->type==SUBSYSTEM_TURRET) && turret_weapon_has_flags(&ss->weapons, WIF_BEAM)) + if ((psub->type==SUBSYSTEM_TURRET) && turret_weapon_has_flags(&ss->weapons, Weapon::Info_Flags::Beam)) { disrupt_time*=wip->elec_beam_mult; } @@ -6002,7 +5932,7 @@ void weapon_do_area_effect(object *wobjp, shockwave_create_info *sci, vec3d *pos weapon_info* wip2 = &Weapon_info[Weapons[objp->instance].weapon_info_index]; if (wip2->weapon_hitpoints <= 0) continue; - if (!((wip2->wi_flags2 & WIF2_TAKES_BLAST_DAMAGE) || (wip->wi_flags2 & WIF2_CIWS))) + if (!((wip2->wi_flags[Weapon::Info_Flags::Takes_blast_damage]) || (wip->wi_flags[Weapon::Info_Flags::Ciws]))) continue; } @@ -6026,7 +5956,7 @@ void weapon_do_area_effect(object *wobjp, shockwave_create_info *sci, vec3d *pos case OBJ_SHIP: // If we're doing an AoE Electronics blast, do the electronics stuff (unless it also has the regular "electronics" // flag and this is the ship the missile directly impacted; then leave it for the regular code below) -MageKing17 - if ( (wip->wi_flags3 & WIF3_AOE_ELECTRONICS) && !((objp->flags[Object::Object_Flags::Invulnerable]) || ((objp == other_obj) && (wip->wi_flags & WIF_ELECTRONICS))) ) { + if ( (wip->wi_flags[Weapon::Info_Flags::Aoe_Electronics]) && !((objp->flags[Object::Object_Flags::Invulnerable]) || ((objp == other_obj) && (wip->wi_flags[Weapon::Info_Flags::Electronics]))) ) { weapon_do_electronics_effect(objp, pos, Weapons[wobjp->instance].weapon_info_index); } ship_apply_global_damage(objp, wobjp, pos, damage); @@ -6043,7 +5973,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: @@ -6054,7 +5984,7 @@ void weapon_do_area_effect(object *wobjp, shockwave_create_info *sci, vec3d *pos } // end for // if this weapon has the "Electronics" flag set, then disrupt subsystems in sphere - if ( (other_obj != NULL) && (wip->wi_flags & WIF_ELECTRONICS) ) { + if ( (other_obj != NULL) && (wip->wi_flags[Weapon::Info_Flags::Electronics]) ) { if ( other_obj->type == OBJ_SHIP ) { weapon_do_electronics_effect(other_obj, pos, Weapons[wobjp->instance].weapon_info_index); } @@ -6078,7 +6008,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) @@ -6283,7 +6213,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; } @@ -6305,13 +6235,13 @@ void weapon_hit( object * weapon_obj, object * other_obj, vec3d * hitpos, int qu } // check if this is an EMP weapon - if(wip->wi_flags & WIF_EMP){ - emp_apply(&weapon_obj->pos, wip->shockwave.inner_rad, wip->shockwave.outer_rad, wip->emp_intensity, wip->emp_time, (wip->wi_flags3 & WIF3_USE_EMP_TIME_FOR_CAPSHIP_TURRETS) != 0); + if(wip->wi_flags[Weapon::Info_Flags::Emp]){ + emp_apply(&weapon_obj->pos, wip->shockwave.inner_rad, wip->shockwave.outer_rad, wip->emp_intensity, wip->emp_time, (wip->wi_flags[Weapon::Info_Flags::Use_emp_time_for_capship_turrets]) != 0); } // spawn weapons - note the change from FS 1 multiplayer. - if (wip->wi_flags & WIF_SPAWN){ - if (!((wip->wi_flags3 & WIF3_DONT_SPAWN_IF_SHOT) && (sw_flag == SW_WEAPON_KILL))){ // prevent spawning of children if shot down and the dont spawn if shot flag is set (DahBlount) + if (wip->wi_flags[Weapon::Info_Flags::Spawn]){ + if (!((wip->wi_flags[Weapon::Info_Flags::Dont_spawn_if_shot]) && (sw_flag == SW_WEAPON_KILL))){ // prevent spawning of children if shot down and the dont spawn if shot flag is set (DahBlount) spawn_child_weapons(weapon_obj); } } @@ -6335,7 +6265,7 @@ void weapon_detonate(object *objp) // call weapon hit // Wanderer - use last frame pos for the corkscrew missiles - if ( (Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags & WIF_CORKSCREW) ) { + if ( (Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Corkscrew]) ) { weapon_hit(objp, NULL, &objp->last_pos); } else { weapon_hit(objp, NULL, &objp->pos); @@ -6423,7 +6353,7 @@ void weapons_page_in() weapon_info *wip = &Weapon_info[i]; - wip->wi_flags &= (~WIF_THRUSTER); // Assume no thrusters + wip->wi_flags.remove(Weapon::Info_Flags::Thruster); // Assume no thrusters switch (wip->render_type) { @@ -6436,7 +6366,7 @@ void weapons_page_in() // If it has a model, and the model pof has thrusters, then set // the flags if (pm->n_thrusters > 0) { - wip->wi_flags |= WIF_THRUSTER; + wip->wi_flags.set(Weapon::Info_Flags::Thruster); } for (j = 0; j < pm->n_textures; j++) @@ -6471,11 +6401,11 @@ void weapons_page_in() shockwave_create_info_load(&wip->dinky_shockwave); // trail bitmaps - if ( (wip->wi_flags & WIF_TRAIL) && (wip->tr_info.texture.bitmap_id > -1) ) + if ( (wip->wi_flags[Weapon::Info_Flags::Trail]) && (wip->tr_info.texture.bitmap_id > -1) ) bm_page_in_texture( wip->tr_info.texture.bitmap_id ); // if this is a beam weapon, page in its stuff - if (wip->wi_flags & WIF_BEAM) { + if (wip->wi_flags[Weapon::Info_Flags::Beam]) { // all beam sections for (idx = 0; idx < wip->b_info.beam_num_sections; idx++) bm_page_in_texture(wip->b_info.sections[idx].texture.first_frame); @@ -6487,7 +6417,7 @@ void weapons_page_in() bm_page_in_texture(wip->b_info.beam_particle_ani.first_frame); } - if (wip->wi_flags & WIF_PARTICLE_SPEW) { + if (wip->wi_flags[Weapon::Info_Flags::Particle_spew]) { for (size_t s = 0; s < MAX_PARTICLE_SPEWERS; s++) { // looped, multi particle spew -nuke if (wip->particle_spewers[s].particle_spew_type != PSPEW_NONE) { bm_page_in_texture(wip->particle_spewers[s].particle_spew_anim.first_frame); @@ -6534,7 +6464,7 @@ void weapons_page_in_cheats() weapon_info *wip = &Weapon_info[i]; - wip->wi_flags &= (~WIF_THRUSTER); // Assume no thrusters + wip->wi_flags.remove(Weapon::Info_Flags::Thruster); // Assume no thrusters if ( wip->render_type == WRT_POF ) { wip->model_num = model_load( wip->pofbitmap_name, 0, NULL ); @@ -6544,7 +6474,7 @@ void weapons_page_in_cheats() // If it has a model, and the model pof has thrusters, then set // the flags if ( pm->n_thrusters > 0 ) { - wip->wi_flags |= WIF_THRUSTER; + wip->wi_flags.set(Weapon::Info_Flags::Thruster); } } @@ -6638,7 +6568,7 @@ void weapon_maybe_spew_particle(object *obj) Assert(obj->type == OBJ_WEAPON); Assert(obj->instance >= 0); Assert(Weapons[obj->instance].weapon_info_index >= 0); - Assert(Weapon_info[Weapons[obj->instance].weapon_info_index].wi_flags & WIF_PARTICLE_SPEW); + Assert(Weapon_info[Weapons[obj->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Particle_spew]); wp = &Weapons[obj->instance]; wip = &Weapon_info[wp->weapon_info_index]; @@ -6709,7 +6639,7 @@ void weapon_maybe_spew_particle(object *obj) vm_vec_add2(&direct, &spawn_pos); } - if (wip->wi_flags & WIF_CORKSCREW) { + if (wip->wi_flags[Weapon::Info_Flags::Corkscrew]) { vm_vec_add(&particle_pos, &obj->last_pos, &direct); } else { vm_vec_add(&particle_pos, &obj->pos, &direct); @@ -7028,7 +6958,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 & WIF_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; } @@ -7050,7 +6980,7 @@ float weapon_get_damage_scale(weapon_info *wip, object *wep, object *target) hull_pct = get_hull_pct(target); // if it has hit a supercap ship and is not a supercap class weapon - if((sip->flags[Ship::Info_Flags::Supercap]) && !(wip->wi_flags & WIF_SUPERCAP)){ + if((sip->flags[Ship::Info_Flags::Supercap]) && !(wip->wi_flags[Weapon::Info_Flags::Supercap])){ // if the supercap is around 3/4 damage, apply nothing if(hull_pct <= 0.75f){ return 0.0f; @@ -7063,12 +6993,12 @@ float weapon_get_damage_scale(weapon_info *wip, object *wep, object *target) is_big_damage_ship = (sip->flags[Ship::Info_Flags::Big_damage]); // if this is a large ship, and is being hit by flak - if(is_big_damage_ship && (wip->wi_flags & WIF_FLAK)){ + if(is_big_damage_ship && (wip->wi_flags[Weapon::Info_Flags::Flak])){ total_scale *= FLAK_DAMAGE_SCALE; } // if the weapon is a small weapon being fired at a big ship - if( is_big_damage_ship && !(wip->wi_flags & (WIF_HURTS_BIG_SHIPS)) ){ + 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)) { @@ -7144,7 +7074,7 @@ void weapon_render(object* obj, draw_list *scene) wp = &Weapons[num]; wip = &Weapon_info[Weapons[num].weapon_info_index]; - if (wip->wi_flags2 & WIF2_TRANSPARENT) { + if (wip->wi_flags[Weapon::Info_Flags::Transparent]) { if (wp->alpha_current == -1.0f) { wp->alpha_current = wip->alpha_max; } else if (wip->alpha_cycle > 0.0f) { @@ -7185,7 +7115,7 @@ void weapon_render(object* obj, draw_list *scene) framenum = bm_get_anim_frame(wip->laser_bitmap.first_frame, wp->laser_bitmap_frame, wip->laser_bitmap.total_time, true); } - if (wip->wi_flags2 & WIF2_TRANSPARENT) + if (wip->wi_flags[Weapon::Info_Flags::Transparent]) alpha = fl2i(wp->alpha_current * 255.0f); vec3d headp; @@ -7226,7 +7156,7 @@ void weapon_render(object* obj, draw_list *scene) CLAMP(framenum, 0, wip->laser_glow_bitmap.num_frames-1); } - if (wip->wi_flags2 & WIF2_TRANSPARENT) { + if (wip->wi_flags[Weapon::Info_Flags::Transparent]) { alpha = fl2i(wp->alpha_current * 255.0f); alpha -= 38; // take 1.5f into account for the normal glow alpha @@ -7248,17 +7178,17 @@ void weapon_render(object* obj, draw_list *scene) uint render_flags = MR_NORMAL|MR_IS_MISSILE|MR_NO_LIGHTING|MR_NO_BATCH; - if (Cmdline_missile_lighting && !(wip->wi_flags2 & WIF2_MR_NO_LIGHTING)) + if (Cmdline_missile_lighting && !(wip->wi_flags[Weapon::Info_Flags::Mr_no_lighting])) render_flags &= ~MR_NO_LIGHTING; - if (wip->wi_flags2 & WIF2_TRANSPARENT) { + if (wip->wi_flags[Weapon::Info_Flags::Transparent]) { render_info.set_alpha(wp->alpha_current); render_flags |= MR_ALL_XPARENT; } model_clear_instance(wip->model_num); - if ( (wip->wi_flags & WIF_THRUSTER) && ((wp->thruster_bitmap > -1) || (wp->thruster_glow_bitmap > -1)) ) { + if ( (wip->wi_flags[Weapon::Info_Flags::Thruster]) && ((wp->thruster_bitmap > -1) || (wp->thruster_glow_bitmap > -1)) ) { float ft; mst_info mst; @@ -7355,8 +7285,7 @@ void weapon_info::reset() // The order should match the order in the struct! int i, j; - this->wi_flags = WIF_DEFAULT_VALUE; - this->wi_flags2 = WIF2_DEFAULT_VALUE; + this->wi_flags.reset(); this->subtype = WP_UNUSED; this->render_type = WRT_NONE; @@ -7617,7 +7546,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); 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) diff --git a/fred2/fredview.cpp b/fred2/fredview.cpp index 285d7c558c..42060c68d7 100644 --- a/fred2/fredview.cpp +++ b/fred2/fredview.cpp @@ -2428,7 +2428,7 @@ void CFREDView::OnUpdateFormWing(CCmdUI* pCmdUI) if (ptr->type == OBJ_SHIP) { int ship_type = ship_query_general_type(ptr->instance); - if(ship_type > -1 && (Ship_types[ship_type].ai_bools & STI_AI_CAN_FORM_WING)) + if(ship_type > -1 && (Ship_types[ship_type].flags[Ship::Type_Info_Flags::AI_can_form_wing])) { count++; } @@ -2955,7 +2955,7 @@ int CFREDView::global_error_check() } int ship_type = ship_query_general_type(ship); - if(ship_type < 0 || !(Ship_types[ship_type].ai_bools & STI_AI_CAN_FORM_WING)) + if(ship_type < 0 || !(Ship_types[ship_type].flags[Ship::Type_Info_Flags::AI_can_form_wing])) { if (error("Ship \"%s\" is an illegal type to be in a wing", Ships[ship].ship_name)){ return 1; @@ -3178,7 +3178,7 @@ int CFREDView::global_error_check() starting_wing = (ship_starting_wing_lookup(Wings[i].name) != -1); // first, be sure this isn't a reinforcement wing. - if ( starting_wing && (Wings[i].flags & WF_REINFORCEMENT) ) { + if ( starting_wing && (Wings[i].flags[Ship::Wing_Flags::Reinforcement]) ) { if ( error("Starting Wing %s marked as reinforcement. This wing\nshould either be renamed, or unmarked as reinforcement.", Wings[i].name) ){ // Goober5000 return 1; } diff --git a/fred2/management.cpp b/fred2/management.cpp index cfd873092c..561d9e4579 100644 --- a/fred2/management.cpp +++ b/fred2/management.cpp @@ -882,7 +882,7 @@ void clear_mission() count = 0; for (j=0; jtype == OBJ_SHIP) { int ship_type = ship_query_general_type(ptr->instance); - if (ship_type < 0 || !(Ship_types[ship_type].ai_bools & STI_AI_CAN_FORM_WING)) { + if (ship_type < 0 || !(Ship_types[ship_type].flags[Ship::Type_Info_Flags::AI_can_form_wing])) { illegal_ships++; unmark_object(OBJ_INDEX(ptr)); } diff --git a/fred2/wing_editor.cpp b/fred2/wing_editor.cpp index 0980353f1d..2a505f2ac5 100644 --- a/fred2/wing_editor.cpp +++ b/fred2/wing_editor.cpp @@ -327,7 +327,7 @@ void wing_editor::initialize_data_safe(int full_update) m_arrival_dist = Wings[cur_wing].arrival_distance; m_arrival_target = Wings[cur_wing].arrival_anchor; m_departure_target = Wings[cur_wing].departure_anchor; - m_no_dynamic = (Wings[cur_wing].flags & WF_NO_DYNAMIC)?1:0; + m_no_dynamic = (Wings[cur_wing].flags[Ship::Wing_Flags::No_dynamic])?1:0; // Add the ships/special items to the combo box here before data is updated if ( m_arrival_location == ARRIVE_FROM_DOCK_BAY ) { @@ -375,27 +375,27 @@ void wing_editor::initialize_data_safe(int full_update) m_departure_tree.load_tree(Wings[cur_wing].departure_cue, "false"); m_hotkey = Wings[cur_wing].hotkey+1; - if (Wings[cur_wing].flags & WF_IGNORE_COUNT) + if (Wings[cur_wing].flags[Ship::Wing_Flags::Ignore_count]) m_ignore_count = 1; else m_ignore_count = 0; - if (Wings[cur_wing].flags & WF_NO_ARRIVAL_MUSIC) + if (Wings[cur_wing].flags[Ship::Wing_Flags::No_arrival_music]) m_no_arrival_music = 1; else m_no_arrival_music = 0; - if ( Wings[cur_wing].flags & WF_NO_ARRIVAL_MESSAGE ) + if ( Wings[cur_wing].flags[Ship::Wing_Flags::No_arrival_message] ) m_no_arrival_message = 1; else m_no_arrival_message = 0; - if ( Wings[cur_wing].flags & WF_NO_ARRIVAL_WARP ) + if ( Wings[cur_wing].flags[Ship::Wing_Flags::No_arrival_warp] ) m_no_arrival_warp = 1; else m_no_arrival_warp = 0; - if ( Wings[cur_wing].flags & WF_NO_DEPARTURE_WARP ) + if ( Wings[cur_wing].flags[Ship::Wing_Flags::No_departure_warp] ) m_no_departure_warp = 1; else m_no_departure_warp = 0; @@ -818,70 +818,76 @@ void wing_editor::update_data_safe() MODIFY(Wings[cur_wing].departure_delay, m_departure_delay); hotkey = m_hotkey - 1; MODIFY(Wings[cur_wing].hotkey, hotkey); - if ( m_ignore_count ) { - if ( !(Wings[cur_wing].flags & WF_IGNORE_COUNT) ) - set_modified(); - Wings[cur_wing].flags |= WF_IGNORE_COUNT; + if (m_ignore_count) { + if (!(Wings[cur_wing].flags[Ship::Wing_Flags::Ignore_count])) + set_modified(); + Wings[cur_wing].flags.set(Ship::Wing_Flags::Ignore_count); - } else { - if ( Wings[cur_wing].flags & WF_IGNORE_COUNT ) - set_modified(); - Wings[cur_wing].flags &= ~WF_IGNORE_COUNT; - } + } + else { + if (Wings[cur_wing].flags[Ship::Wing_Flags::Ignore_count]) + set_modified(); + Wings[cur_wing].flags.remove(Ship::Wing_Flags::Ignore_count); + } - if ( m_no_arrival_music ) { - if ( !(Wings[cur_wing].flags & WF_NO_ARRIVAL_MUSIC) ) - set_modified(); - Wings[cur_wing].flags |= WF_NO_ARRIVAL_MUSIC; + if (m_no_arrival_music) { + if (!(Wings[cur_wing].flags[Ship::Wing_Flags::No_arrival_music])) + set_modified(); + Wings[cur_wing].flags.set(Ship::Wing_Flags::No_arrival_music); - } else { - if ( Wings[cur_wing].flags & WF_NO_ARRIVAL_MUSIC ) - set_modified(); - Wings[cur_wing].flags &= ~WF_NO_ARRIVAL_MUSIC; - } + } + else { + if (Wings[cur_wing].flags[Ship::Wing_Flags::No_arrival_music]) + set_modified(); + Wings[cur_wing].flags.remove(Ship::Wing_Flags::No_arrival_music); + } - // check the no message flag - if ( m_no_arrival_message ) { - if ( !(Wings[cur_wing].flags & WF_NO_ARRIVAL_MESSAGE) ) - set_modified(); - Wings[cur_wing].flags |= WF_NO_ARRIVAL_MESSAGE; + // check the no message flag + if (m_no_arrival_message) { + if (!(Wings[cur_wing].flags[Ship::Wing_Flags::No_arrival_message])) + set_modified(); + Wings[cur_wing].flags.set(Ship::Wing_Flags::No_arrival_message); - } else { - if ( Wings[cur_wing].flags & WF_NO_ARRIVAL_MESSAGE ) - set_modified(); - Wings[cur_wing].flags &= ~WF_NO_ARRIVAL_MESSAGE; - } + } + else { + if (Wings[cur_wing].flags[Ship::Wing_Flags::No_arrival_message]) + set_modified(); + Wings[cur_wing].flags.remove(Ship::Wing_Flags::No_arrival_message); + } - // set the no warp effect for wings flag - if ( m_no_arrival_warp ) { - if ( !(Wings[cur_wing].flags & WF_NO_ARRIVAL_WARP) ) - set_modified(); - Wings[cur_wing].flags |= WF_NO_ARRIVAL_WARP; - } else { - if ( Wings[cur_wing].flags & WF_NO_ARRIVAL_WARP ) - set_modified(); - Wings[cur_wing].flags &= ~WF_NO_ARRIVAL_WARP; - } - // set the no warp effect for wings flag - if ( m_no_departure_warp ) { - if ( !(Wings[cur_wing].flags & WF_NO_DEPARTURE_WARP) ) - set_modified(); - Wings[cur_wing].flags |= WF_NO_DEPARTURE_WARP; - } else { - if ( Wings[cur_wing].flags & WF_NO_DEPARTURE_WARP ) - set_modified(); - Wings[cur_wing].flags &= ~WF_NO_DEPARTURE_WARP; - } + // set the no warp effect for wings flag + if (m_no_arrival_warp) { + if (!(Wings[cur_wing].flags[Ship::Wing_Flags::No_arrival_warp])) + set_modified(); + Wings[cur_wing].flags.set(Ship::Wing_Flags::No_arrival_warp); + } + else { + if (Wings[cur_wing].flags[Ship::Wing_Flags::No_arrival_warp]) + set_modified(); + Wings[cur_wing].flags.remove(Ship::Wing_Flags::No_arrival_warp); + } + // set the no warp effect for wings flag + if (m_no_departure_warp) { + if (!(Wings[cur_wing].flags[Ship::Wing_Flags::No_departure_warp])) + set_modified(); + Wings[cur_wing].flags.set(Ship::Wing_Flags::No_departure_warp); + } + else { + if (Wings[cur_wing].flags[Ship::Wing_Flags::No_departure_warp]) + set_modified(); + Wings[cur_wing].flags.remove(Ship::Wing_Flags::No_departure_warp); + } - if ( m_no_dynamic ) { - if ( !(Wings[cur_wing].flags & WF_NO_DYNAMIC) ) - set_modified(); - Wings[cur_wing].flags |= WF_NO_DYNAMIC; - } else { - if ( Wings[cur_wing].flags & WF_NO_DYNAMIC ) - set_modified(); - Wings[cur_wing].flags &= ~WF_NO_DYNAMIC; - } + if (m_no_dynamic) { + if (!(Wings[cur_wing].flags[Ship::Wing_Flags::No_dynamic])) + set_modified(); + Wings[cur_wing].flags.set(Ship::Wing_Flags::No_dynamic); + } + else { + if (Wings[cur_wing].flags[Ship::Wing_Flags::No_dynamic]) + set_modified(); + Wings[cur_wing].flags.remove(Ship::Wing_Flags::No_dynamic); + } if (Wings[cur_wing].arrival_cue >= 0) free_sexp2(Wings[cur_wing].arrival_cue); 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)