// 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;
	}
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
/*
 * 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);
				}
			}
		}
	}
}