mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-08 07:28:22 -10:00
red-alert will now work with ships that appear at some point subsequent to mission start
git-svn-id: svn://svn.icculus.org/fs2open/trunk/fs2_open@10267 387891d4-d844-0410-90c0-e4c51a9137d3
This commit is contained in:
1 parent
180115feba
commit
a04e83ab01
6 files changed
+372
-94
No files matched your search
@@ -599,49 +599,46 @@ bool HudGaugeWingmanStatus::maybeFlashStatus(int wing_index, int wing_pos)
|
||||
return draw_bright;
|
||||
}
|
||||
|
||||
int hud_wingman_status_wing_pos(int shipnum, int wing_status_index, wing *wingp)
|
||||
void hud_wingman_status_set_index(wing *wingp, ship *shipp, p_object *pobjp)
|
||||
{
|
||||
int i, wing_pos = -1;
|
||||
|
||||
for (i = 0; i < wingp->wave_count; i++) {
|
||||
if ( wingp->ship_index[i] == shipnum ) {
|
||||
wing_pos = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return wing_pos;
|
||||
}
|
||||
|
||||
void hud_wingman_status_set_index(int shipnum)
|
||||
{
|
||||
int wing_index, wing_pos;
|
||||
ship *shipp;
|
||||
wing *wingp;
|
||||
|
||||
if ( shipnum < 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
shipp = &Ships[shipnum];
|
||||
|
||||
if ( shipp->wingnum < 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wingp = &Wings[shipp->wingnum];
|
||||
int wing_index;
|
||||
|
||||
// Check for squadron wings
|
||||
wing_index = ship_squadron_wing_lookup(wingp->name);
|
||||
if ( wing_index < 0 ) {
|
||||
if ( wing_index < 0 )
|
||||
return;
|
||||
|
||||
// this wing is shown on the squadron display
|
||||
shipp->wing_status_wing_index = (char) wing_index;
|
||||
|
||||
// for the first wave, just use the parse object position
|
||||
if (wingp->current_wave == 1)
|
||||
{
|
||||
shipp->wing_status_wing_pos = (char) pobjp->pos_in_wing;
|
||||
}
|
||||
// for subsequent waves, find the first position not taken
|
||||
else
|
||||
{
|
||||
int i, pos, wing_bitfield = 0;
|
||||
|
||||
shipp->wing_status_wing_index = (char)wing_index;
|
||||
// fill in all the positions currently used by this wing
|
||||
for (i = 0; i < wingp->wave_count; i++)
|
||||
{
|
||||
pos = Ships[wingp->ship_index[i]].wing_status_wing_pos;
|
||||
if (pos >= 0)
|
||||
wing_bitfield |= (1<<pos);
|
||||
}
|
||||
|
||||
wing_pos = hud_wingman_status_wing_pos(shipnum, wing_index, wingp);
|
||||
|
||||
shipp->wing_status_wing_pos = (char)wing_pos;
|
||||
// now assign the first available slot
|
||||
for (i = 0; i < MAX_SHIPS_PER_WING; i++)
|
||||
{
|
||||
if (!(wing_bitfield & (1<<i)))
|
||||
{
|
||||
shipp->wing_status_wing_pos = (char) i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HudGaugeWingmanStatus::pageIn()
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
|
||||
#include "hud/hud.h"
|
||||
|
||||
struct wing;
|
||||
class ship;
|
||||
class p_object;
|
||||
|
||||
void hud_init_wingman_status_gauge();
|
||||
void hud_wingman_status_update();
|
||||
void hud_wingman_status_render();
|
||||
@@ -24,7 +28,7 @@ void hud_set_wingman_status_departed(int wing_index, int wing_pos);
|
||||
void hud_set_wingman_status_alive( int wing_index, int wing_pos);
|
||||
void hud_set_wingman_status_none( int wing_index, int wing_pos);
|
||||
void hud_wingman_status_start_flash(int wing_index, int wing_pos);
|
||||
void hud_wingman_status_set_index(int shipnum);
|
||||
void hud_wingman_status_set_index(wing *wingp, ship *shipp, p_object *pobjp);
|
||||
|
||||
class HudGaugeWingmanStatus: public HudGauge
|
||||
{
|
||||
|
||||
@@ -2354,8 +2354,7 @@ void parse_bring_in_docked_wing(p_object *p_objp, int wingnum, int shipnum)
|
||||
wing *wingp = &Wings[wingnum];
|
||||
|
||||
// link ship and wing together
|
||||
// (do this first because mission log relies on ship_index
|
||||
// and hud_wingman_status_set_index relies on ship's wingnum)
|
||||
// (do this first because mission log relies on ship_index)
|
||||
wingp->ship_index[p_objp->pos_in_wing] = shipnum;
|
||||
Ships[shipnum].wingnum = wingnum;
|
||||
|
||||
@@ -2379,7 +2378,7 @@ void parse_bring_in_docked_wing(p_object *p_objp, int wingnum, int shipnum)
|
||||
// at this point the wing has arrived, so handle the stuff for this particular ship
|
||||
|
||||
// set up wingman status index
|
||||
hud_wingman_status_set_index(shipnum);
|
||||
hud_wingman_status_set_index(wingp, &Ships[shipnum], p_objp);
|
||||
|
||||
// copy to parse object
|
||||
p_objp->wing_status_wing_index = Ships[shipnum].wing_status_wing_index;
|
||||
@@ -3987,6 +3986,23 @@ int parse_wing_create_ships( wing *wingp, int num_to_create, int force, int spec
|
||||
specific_instance--;
|
||||
continue;
|
||||
}
|
||||
// when not creating a specific ship, we should skip over any ships that weren't carried along in the red-alert
|
||||
else if (p_objp->flags2 & P2_RED_ALERT_DELETED)
|
||||
{
|
||||
num_to_create--;
|
||||
num_create_save--;
|
||||
ship_add_ship_type_count(p_objp->ship_class, -1);
|
||||
wingp->red_alert_skipped_ships++;
|
||||
|
||||
// clear the flag so that this parse object can be used for the next wave
|
||||
p_objp->flags2 &= ~P2_RED_ALERT_DELETED;
|
||||
|
||||
// skip over this parse object
|
||||
if (num_to_create == 0)
|
||||
break;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
Assert (!(p_objp->flags & P_SF_CANNOT_ARRIVE)); // get allender
|
||||
|
||||
@@ -4001,7 +4017,7 @@ int parse_wing_create_ships( wing *wingp, int num_to_create, int force, int spec
|
||||
// bash the ship name to be the name of the wing + some number if there is > 1 wave in this wing
|
||||
wingp->total_arrived_count++;
|
||||
if (wingp->num_waves > 1)
|
||||
wing_bash_ship_name(p_objp->name, wingp->name, wingp->total_arrived_count);
|
||||
wing_bash_ship_name(p_objp->name, wingp->name, wingp->total_arrived_count + wingp->red_alert_skipped_ships);
|
||||
|
||||
// also, if multiplayer, set the parse object's net signature to be wing's net signature
|
||||
// base + total_arrived_count (before adding 1)
|
||||
@@ -4037,7 +4053,7 @@ int parse_wing_create_ships( wing *wingp, int num_to_create, int force, int spec
|
||||
}
|
||||
|
||||
// set up wingman status index
|
||||
hud_wingman_status_set_index(Objects[objnum].instance);
|
||||
hud_wingman_status_set_index(wingp, &Ships[Objects[objnum].instance], p_objp);
|
||||
|
||||
p_objp->wing_status_wing_index = Ships[Objects[objnum].instance].wing_status_wing_index;
|
||||
p_objp->wing_status_wing_pos = Ships[Objects[objnum].instance].wing_status_wing_pos;
|
||||
@@ -4092,20 +4108,29 @@ int parse_wing_create_ships( wing *wingp, int num_to_create, int force, int spec
|
||||
Assert (num_to_create == 0);
|
||||
|
||||
// wing current_count needs to match the end of the ship_index[] list, but there
|
||||
// is a very off chance it could have holes in it, so make sure to compact the list
|
||||
for (i = 0; i < (MAX_SHIPS_PER_WING-1); i++) {
|
||||
if (wingp->ship_index[i] == -1) {
|
||||
j = i;
|
||||
while ( j < (MAX_SHIPS_PER_WING-1) ) {
|
||||
// is a very off chance it could have holes in it (especially if it's a red-alert
|
||||
// wing that arrives late), so make sure to compact the list
|
||||
int length = MAX_SHIPS_PER_WING;
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
if (wingp->ship_index[i] == -1)
|
||||
{
|
||||
// shift actual values downward
|
||||
for (j = i; j < length - 1; j++)
|
||||
{
|
||||
wingp->ship_index[j] = wingp->ship_index[j+1];
|
||||
|
||||
// update "special" ship too
|
||||
if (wingp->special_ship == j+1) {
|
||||
if (wingp->special_ship == j+1)
|
||||
wingp->special_ship--;
|
||||
}
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
// last value becomes -1
|
||||
wingp->ship_index[j] = -1;
|
||||
length--;
|
||||
|
||||
// stay on the current index in case we still have a -1
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4204,6 +4229,7 @@ void parse_wing(mission *pm)
|
||||
wingnum = Num_wings;
|
||||
|
||||
wingp->total_arrived_count = 0;
|
||||
wingp->red_alert_skipped_ships = 0;
|
||||
wingp->total_destroyed = 0;
|
||||
wingp->total_departed = 0; // Goober5000
|
||||
wingp->total_vanished = 0; // Goober5000
|
||||
|
||||
@@ -512,8 +512,9 @@ public:
|
||||
#define P2_SF2_SCRAMBLE_MESSAGES (1<<22)
|
||||
|
||||
// and again: these flags do not appear in the array
|
||||
//#define blah (1<<28)
|
||||
//#define blah (1<<29)
|
||||
//#define blah (1<<30)
|
||||
#define P2_RED_ALERT_DELETED (1<<30) // Goober5000 - used analogously to SEF_PLAYER_DELETED
|
||||
#define P2_ALREADY_HANDLED (1<<31) // Goober5000 - used for docking currently, but could be used generically
|
||||
|
||||
|
||||
|
||||
+292
-43
@@ -520,7 +520,7 @@ void red_alert_bash_weapons(red_alert_ship_status *ras, ship_weapon *swp)
|
||||
}
|
||||
swp->num_primary_banks = list_size;
|
||||
|
||||
|
||||
// bash secondary weapons
|
||||
list_size = (int)ras->secondary_weapons.size();
|
||||
CLAMP(list_size, 0, MAX_SHIP_SECONDARY_BANKS);
|
||||
for (i = 0; i < list_size; i++) {
|
||||
@@ -532,6 +532,63 @@ void red_alert_bash_weapons(red_alert_ship_status *ras, ship_weapon *swp)
|
||||
swp->num_secondary_banks = list_size;
|
||||
}
|
||||
|
||||
void red_alert_bash_weapons(red_alert_ship_status *ras, p_object *pobjp)
|
||||
{
|
||||
int i, list_size = 0;
|
||||
ship_info *sip;
|
||||
subsys_status *sssp = NULL;
|
||||
|
||||
// restore from ship_exited
|
||||
if ( (ras->ship_class == RED_ALERT_DESTROYED_SHIP_CLASS) || (ras->ship_class == RED_ALERT_PLAYER_DEL_SHIP_CLASS) )
|
||||
return;
|
||||
sip = &Ship_info[ras->ship_class];
|
||||
|
||||
// parse objects use the "pilot" subsystem
|
||||
for (i = 0; i < pobjp->subsys_count; i++)
|
||||
{
|
||||
if (!stricmp(Subsys_status[pobjp->subsys_index + i].name, "pilot"))
|
||||
{
|
||||
sssp = &Subsys_status[pobjp->subsys_index + i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sssp == NULL)
|
||||
{
|
||||
Warning(LOCATION, "Parse object data for ship '%s' doesn't contain the 'Pilot' subsystem!", pobjp->name);
|
||||
return;
|
||||
}
|
||||
|
||||
// bash primary weapons
|
||||
list_size = (int)ras->primary_weapons.size();
|
||||
CLAMP(list_size, 0, MAX_SHIP_PRIMARY_BANKS);
|
||||
for (i = 0; i < list_size; i++)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
sssp->primary_ammo[i] = 100;
|
||||
}
|
||||
|
||||
// bash secondary weapons
|
||||
list_size = (int)ras->secondary_weapons.size();
|
||||
CLAMP(list_size, 0, MAX_SHIP_SECONDARY_BANKS);
|
||||
for (i = 0; i < list_size; i++)
|
||||
{
|
||||
Assert( ras->secondary_weapons[i].index >= 0 );
|
||||
sssp->secondary_banks[i] = ras->secondary_weapons[i].index;
|
||||
|
||||
float max_count = sip->secondary_bank_ammo_capacity[i] / Weapon_info[sssp->secondary_banks[i]].cargo_size;
|
||||
sssp->secondary_ammo[i] = fl2i(100.0f * ras->secondary_weapons[i].count / max_count + 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
void red_alert_bash_subsys_status(red_alert_ship_status *ras, ship *shipp)
|
||||
{
|
||||
ship_subsys *ss;
|
||||
@@ -568,6 +625,53 @@ void red_alert_bash_subsys_status(red_alert_ship_status *ras, ship *shipp)
|
||||
}
|
||||
}
|
||||
|
||||
extern int insert_subsys_status(p_object *pobjp);
|
||||
|
||||
void red_alert_bash_subsys_status(red_alert_ship_status *ras, p_object *pobjp)
|
||||
{
|
||||
int i, j;
|
||||
ship_info *sip;
|
||||
model_subsystem *psub = NULL;
|
||||
subsys_status *sssp = NULL;
|
||||
|
||||
// restore from ship_exited
|
||||
if ( (ras->ship_class == RED_ALERT_DESTROYED_SHIP_CLASS) || (ras->ship_class == RED_ALERT_PLAYER_DEL_SHIP_CLASS) )
|
||||
return;
|
||||
sip = &Ship_info[ras->ship_class];
|
||||
|
||||
// do this differently than the other bash_subsys_status... since the p_object may not contain
|
||||
// all the subsystems, iterate on the red_alert_ship_status entries rather than the p_object's
|
||||
// and create missing subsystems where necessary
|
||||
for (i = 0; i < (int) ras->subsys_current_hits.size(); i++)
|
||||
{
|
||||
psub = &sip->subsystems[i];
|
||||
|
||||
// in the p_object, subsystem 0 is the pilot, and afterwards the subsystems go in order
|
||||
j = i + 1;
|
||||
|
||||
// this subsystem is in the p_object
|
||||
if (j < pobjp->subsys_count)
|
||||
{
|
||||
sssp = &Subsys_status[pobjp->subsys_index + j];
|
||||
}
|
||||
// must create subsystem (same technique as in parse_copy_damage)
|
||||
else
|
||||
{
|
||||
// jam in the new subsystem at the end of the existing list for this parse object
|
||||
int new_idx = insert_subsys_status(pobjp);
|
||||
Assert(new_idx == pobjp->subsys_index + j);
|
||||
sssp = &Subsys_status[new_idx];
|
||||
|
||||
strcpy_s(sssp->name, psub->subobj_name);
|
||||
}
|
||||
|
||||
float max_hits = psub->max_subsys_strength * (pobjp->ship_max_hull_strength / sip->max_hull_strength);
|
||||
|
||||
float current_hits = ras->subsys_current_hits[i];
|
||||
|
||||
sssp->percent = 100.0f * (max_hits - current_hits) / max_hits;
|
||||
}
|
||||
}
|
||||
|
||||
void red_alert_store_subsys_status(red_alert_ship_status *ras, ship *shipp)
|
||||
{
|
||||
@@ -690,6 +794,20 @@ void red_alert_delete_ship(ship *shipp, int ship_state)
|
||||
}
|
||||
}
|
||||
|
||||
// just mark the parse object as never going to arrive
|
||||
void red_alert_delete_ship(p_object *pobjp, int ship_state)
|
||||
{
|
||||
if (ship_state == RED_ALERT_DESTROYED_SHIP_CLASS || ship_state == RED_ALERT_PLAYER_DEL_SHIP_CLASS)
|
||||
{
|
||||
pobjp->flags2 |= P2_RED_ALERT_DELETED;
|
||||
|
||||
if (pobjp->wingnum < 0)
|
||||
pobjp->flags |= P_SF_CANNOT_ARRIVE;
|
||||
}
|
||||
else
|
||||
Error(LOCATION, "Red Alert: asked to delete ship (%s) with invalid ship state (%d)", pobjp->name, ship_state);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
@@ -697,11 +815,14 @@ void red_alert_delete_ship(ship *shipp, int ship_state)
|
||||
*/
|
||||
void red_alert_bash_wingman_status()
|
||||
{
|
||||
int i;
|
||||
ship *shipp;
|
||||
red_alert_ship_status *ras;
|
||||
int j;
|
||||
ship_obj *so;
|
||||
object *ship_objp;
|
||||
|
||||
SCP_vector<red_alert_ship_status>::iterator rasii;
|
||||
SCP_vector<p_object>::iterator poii;
|
||||
|
||||
SCP_hash_map<int, int> Wing_pobjects_deleted;
|
||||
SCP_hash_map<int, int>::iterator ii;
|
||||
|
||||
if ( !(Game_mode & GM_CAMPAIGN_MODE) ) {
|
||||
return;
|
||||
@@ -713,61 +834,189 @@ void red_alert_bash_wingman_status()
|
||||
|
||||
// go through all ships in the game, and see if there is red alert status data for any
|
||||
|
||||
int remove_list[MAX_SHIPS];
|
||||
int remove_state[MAX_SHIPS];
|
||||
int remove_count = 0;
|
||||
|
||||
for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
|
||||
ship_objp = &Objects[so->objnum];
|
||||
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);
|
||||
shipp = &Ships[ship_objp->instance];
|
||||
ship *shipp = &Ships[ship_objp->instance];
|
||||
|
||||
if ( !(shipp->flags & SF_FROM_PLAYER_WING) && !(shipp->flags & SF_RED_ALERT_STORE_STATUS) ) {
|
||||
so = GET_NEXT(so);
|
||||
continue;
|
||||
}
|
||||
|
||||
int found_match = 0;
|
||||
bool ship_data_restored = false;
|
||||
int ship_state = RED_ALERT_DESTROYED_SHIP_CLASS;
|
||||
|
||||
for ( i = 0; i < (int)Red_alert_wingman_status.size(); i++ ) {
|
||||
ras = &Red_alert_wingman_status[i];
|
||||
for ( rasii = Red_alert_wingman_status.begin(); rasii != Red_alert_wingman_status.end(); ++rasii )
|
||||
{
|
||||
red_alert_ship_status *ras = &(*rasii);
|
||||
|
||||
// we only want to restore ships which haven't been destroyed, or were removed by the player
|
||||
if ( !stricmp(ras->name.c_str(), shipp->ship_name) && (ras->ship_class != RED_ALERT_DESTROYED_SHIP_CLASS) && (ras->ship_class != RED_ALERT_PLAYER_DEL_SHIP_CLASS) ) {
|
||||
found_match = 1;
|
||||
|
||||
// if necessary, restore correct ship class
|
||||
if ( ras->ship_class != shipp->ship_info_index ) {
|
||||
if (ras->ship_class < MAX_SHIP_CLASSES && ras->ship_class > -1) {
|
||||
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));
|
||||
// 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 < MAX_SHIP_CLASSES)
|
||||
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 and weapons
|
||||
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));
|
||||
}
|
||||
red_alert_bash_weapons(ras, &shipp->weapons);
|
||||
red_alert_bash_subsys_status(ras, shipp);
|
||||
|
||||
} else if ( !stricmp(ras->name.c_str(), shipp->ship_name) && ( (ras->ship_class == RED_ALERT_DESTROYED_SHIP_CLASS) || (ras->ship_class == RED_ALERT_PLAYER_DEL_SHIP_CLASS) ) ) {
|
||||
ship_state = ras->ship_class;
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !found_match ) {
|
||||
remove_state[remove_count] = ship_state;
|
||||
remove_list[remove_count++] = SHIP_INDEX(shipp);
|
||||
// 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(shipp, ship_state);
|
||||
so = next_so;
|
||||
} else {
|
||||
so = GET_NEXT(so);
|
||||
}
|
||||
}
|
||||
|
||||
// remove ships
|
||||
for ( i = 0; i < remove_count; i++ ) {
|
||||
// remove ship
|
||||
red_alert_delete_ship(&Ships[remove_list[i]], remove_state[i]);
|
||||
// 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 & P_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 < MAX_SHIP_CLASSES)
|
||||
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));
|
||||
}
|
||||
|
||||
// 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 |= WF_WING_GONE;
|
||||
wingp->flags |= WF_NEVER_EXISTED;
|
||||
}
|
||||
|
||||
// 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 |= P_SF_CANNOT_ARRIVE;
|
||||
// we skipped one complete wave, so clear the flag so the next wave creates all ships
|
||||
else
|
||||
pobjp->flags2 &= ~P2_RED_ALERT_DELETED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1480,6 +1480,7 @@ typedef struct wing {
|
||||
|
||||
int wave_count; // max ships per wave (as defined by the number of ships in the ships list)
|
||||
int total_arrived_count; // count of number of ships that we have created, regardless of wave
|
||||
int red_alert_skipped_ships; // Goober5000 - if we skipped over any indexes while creating red-alert ships
|
||||
int current_count; // count of number of ships actually in this wing -- used for limit in next array
|
||||
int ship_index[MAX_SHIPS_PER_WING]; // index into ships array of all ships currently in the wing
|
||||
|
||||
|
||||
Reference in new issue
Block a user