// NOTE - in both retail and SCP, the dock "leader" is defined as the only guy in his // group with a non-false arrival cue void initial_status_mark_dock_leader_helper(object *objp, dock_function_info *infop) { ship *shipp = &Ships[objp->instance]; int cue_to_check; // if this guy is part of a wing, he uses his wing's arrival cue if (shipp->wingnum >= 0) { cue_to_check = Wings[shipp->wingnum].arrival_cue; } // check the ship's arrival cue else { cue_to_check = shipp->arrival_cue; } // all ships except the leader should have a locked false arrival cue if (cue_to_check != Locked_sexp_false) { object *existing_leader; // increment number of leaders found infop->maintained_variables.int_value++; // see if we already found a leader existing_leader = infop->maintained_variables.objp_value; if (existing_leader != NULL) { ship *leader_shipp = &Ships[existing_leader->instance]; // keep existing leader if he has a higher priority than us if (ship_class_compare(shipp->ship_info_index, leader_shipp->ship_info_index) >= 0) { // set my arrival cue to false reset_arrival_to_false(SHIP_INDEX(shipp), true); return; } // otherwise, unmark the existing leader and set his arrival cue to false leader_shipp->flags.remove(Ship::Ship_Flags::Dock_leader); reset_arrival_to_false(SHIP_INDEX(leader_shipp), true); } // mark and save me as the leader shipp->flags.set(Ship::Ship_Flags::Dock_leader); infop->maintained_variables.objp_value = objp; } }
void multi_respawn_wing_stuff(ship *shipp) { wing *wingp; // deal with re-adding this ship to it's wing Assert( shipp->wingnum != -1 ); wingp = &Wings[shipp->wingnum]; wingp->ship_index[wingp->current_count] = SHIP_INDEX(shipp); wingp->current_count++; hud_set_wingman_status_alive(shipp->wing_status_wing_index, shipp->wing_status_wing_pos); }
/* * Take the red alert status information, and adjust the red alert ships accordingly * "red alert ships" are wingmen and any ship with the red-alert-carry flag * Wingmen without red alert data still need to be handled / removed */ void red_alert_bash_wingman_status() { int j; ship_obj *so; SCP_vector<red_alert_ship_status>::iterator rasii; SCP_vector<p_object>::iterator poii; SCP_unordered_map<int, int> Wing_pobjects_deleted; SCP_unordered_map<int, int>::iterator ii; if ( !(Game_mode & GM_CAMPAIGN_MODE) ) { return; } if ( Red_alert_wingman_status.empty() ) { return; } // go through all ships in the game, and see if there is red alert status data for any so = GET_FIRST(&Ship_obj_list); for ( ; so != END_OF_LIST(&Ship_obj_list); ) { object *ship_objp = &Objects[so->objnum]; Assert(ship_objp->type == OBJ_SHIP); ship *shipp = &Ships[ship_objp->instance]; if ( !(shipp->flags[Ship::Ship_Flags::From_player_wing]) && !(shipp->flags[Ship::Ship_Flags::Red_alert_store_status]) ) { so = GET_NEXT(so); continue; } bool ship_data_restored = false; int ship_state = RED_ALERT_DESTROYED_SHIP_CLASS; for ( rasii = Red_alert_wingman_status.begin(); rasii != Red_alert_wingman_status.end(); ++rasii ) { red_alert_ship_status *ras = &(*rasii); // red-alert data matches this ship! if ( !stricmp(ras->name.c_str(), shipp->ship_name) ) { // we only want to restore ships which haven't been destroyed, or were removed by the player if ( (ras->ship_class != RED_ALERT_DESTROYED_SHIP_CLASS) && (ras->ship_class != RED_ALERT_PLAYER_DEL_SHIP_CLASS) ) { // if necessary, restore correct ship class if ( ras->ship_class != shipp->ship_info_index ) { if (ras->ship_class >= 0 && ras->ship_class < static_cast<int>(Ship_info.size())) change_ship_type(SHIP_INDEX(shipp), ras->ship_class); else mprintf(("Invalid ship class specified in red alert data for ship %s. Using mission defaults.\n", shipp->ship_name)); } // restore hull (but not shields) if (ras->hull >= 0.0f && ras->hull <= ship_objp->hull_strength) ship_objp->hull_strength = ras->hull; else mprintf(("Invalid health in red alert data for ship %s. Using mission defaults.\n", shipp->ship_name)); // restore weapons and subsys red_alert_bash_weapons(ras, &shipp->weapons); red_alert_bash_subsys_status(ras, shipp); ship_data_restored = true; } // must be destroyed or deleted else { ship_state = ras->ship_class; } // we won't have two ships with the same name, so bail break; } } // remove ship if it was destroyed, or if there's no red-alert data for it if ( !ship_data_restored ) { // we need to be a little tricky here because deletion invalidates the ship_obj ship_obj *next_so = GET_NEXT(so); red_alert_delete_ship(ship_objp->instance, ship_state); so = next_so; } else { so = GET_NEXT(so); } } // NOTE: in retail, red alert data was not loaded for ships that arrived later in the mission if (!Red_alert_applies_to_delayed_ships) return; // go through all ships yet to arrive, and see if there is red alert status data for any for ( poii = Parse_objects.begin(); poii != Parse_objects.end(); ++poii ) { p_object *pobjp = &(*poii); // objects that have already arrived would have been handled in the above loop if ( pobjp->created_object != NULL ) continue; // if we're in a wing, check whether we're in the player wing bool from_player_wing = false; if (pobjp->wingnum >= 0) { for (j = 0; j < MAX_STARTING_WINGS; j++) { if (!stricmp(Starting_wing_names[j], Wings[pobjp->wingnum].name)) { from_player_wing = true; break; } } } // same condition as in ship_obj loop if ( !from_player_wing && !(pobjp->flags[Mission::Parse_Object_Flags::SF_Red_alert_store_status]) ) { continue; } bool ship_data_restored = false; int ship_state = RED_ALERT_DESTROYED_SHIP_CLASS; for ( rasii = Red_alert_wingman_status.begin(); rasii != Red_alert_wingman_status.end(); ++rasii ) { red_alert_ship_status *ras = &(*rasii); // red-alert data matches this ship! if ( !stricmp(ras->name.c_str(), pobjp->name) ) { // we only want to restore ships which haven't been destroyed, or were removed by the player if ( (ras->ship_class != RED_ALERT_DESTROYED_SHIP_CLASS) && (ras->ship_class != RED_ALERT_PLAYER_DEL_SHIP_CLASS) ) { // if necessary, restore correct ship class if ( ras->ship_class != pobjp->ship_class ) { if (ras->ship_class >= 0 && ras->ship_class < static_cast<int>(Ship_info.size())) swap_parse_object(pobjp, ras->ship_class); else { mprintf(("Invalid ship class specified in red alert data for ship %s. Using mission defaults.\n", pobjp->name)); // We will break anyway to this should work break; } } // restore hull (but not shields) if (ras->hull >= 0.0f && ras->hull <= (pobjp->initial_hull * pobjp->ship_max_hull_strength / 100.0f)) pobjp->initial_hull = (int) (ras->hull * 100.0f / pobjp->ship_max_hull_strength); else mprintf(("Invalid health in red alert data for ship %s. Using mission defaults.\n", pobjp->name)); // restore weapons and subsys red_alert_bash_weapons(ras, pobjp); red_alert_bash_subsys_status(ras, pobjp); ship_data_restored = true; } // must be destroyed or deleted else { ship_state = ras->ship_class; } // we won't have two ships with the same name, so bail break; } } // remove ship if it was destroyed, or if there's no red-alert data for it if ( !ship_data_restored ) { red_alert_delete_ship(pobjp, ship_state); if (pobjp->wingnum >= 0) Wing_pobjects_deleted[pobjp->wingnum]++; } } // if all parse objects in a wing have been removed, decrement the count for that wing for (ii = Wing_pobjects_deleted.begin(); ii != Wing_pobjects_deleted.end(); ++ii) { wing *wingp = &Wings[ii->first]; if (wingp->num_waves > 0 && wingp->wave_count == ii->second) { wingp->current_wave++; wingp->red_alert_skipped_ships += wingp->wave_count; 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)) { // ...and mark the ones in this wing if (pobjp->wingnum == ii->first) { // no waves left to arrive, so mark ships accordingly if (wingp->num_waves == 0) pobjp->flags.set(Mission::Parse_Object_Flags::SF_Cannot_arrive); // we skipped one complete wave, so clear the flag so the next wave creates all ships else pobjp->flags.remove(Mission::Parse_Object_Flags::Red_alert_deleted); } } } } }