Exemple #1
0
static COUNT
initialize_turret_missile (PELEMENT ShipPtr, HELEMENT MissileArray[])
{
#define MISSILE_HITS 2
#define MISSILE_DAMAGE 3
#define MISSILE_OFFSET 1
	ELEMENTPTR TurretPtr;
	STARSHIPPTR StarShipPtr;
	MISSILE_BLOCK MissileBlock;

	GetElementStarShip (ShipPtr, &StarShipPtr);
	MissileBlock.cx = ShipPtr->next.location.x;
	MissileBlock.cy = ShipPtr->next.location.y;
	MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon;

	LockElement (GetSuccElement (ShipPtr), &TurretPtr);
	if (TurretPtr->turn_wait == 0
			&& (StarShipPtr->cur_status_flags & SPECIAL)
			&& (StarShipPtr->cur_status_flags & (LEFT | RIGHT)))
	{
		if (StarShipPtr->cur_status_flags & RIGHT)
			++TurretPtr->thrust_wait;
		else
			--TurretPtr->thrust_wait;

		TurretPtr->turn_wait = TURRET_WAIT + 1;
	}
	MissileBlock.face = MissileBlock.index =
			NORMALIZE_FACING (StarShipPtr->ShipFacing
			+ TurretPtr->thrust_wait);
	UnlockElement (GetSuccElement (ShipPtr));

	MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY))
			| IGNORE_SIMILAR;
	MissileBlock.pixoffs = TURRET_OFFSET;
	MissileBlock.speed = MISSILE_SPEED;
	MissileBlock.hit_points = MISSILE_HITS;
	MissileBlock.damage = MISSILE_DAMAGE;
	MissileBlock.life = MISSILE_LIFE;
	MissileBlock.preprocess_func = NULL_PTR;
	MissileBlock.blast_offs = MISSILE_OFFSET;
	MissileArray[0] = initialize_missile (&MissileBlock);

	if (MissileArray[0])
	{
		ELEMENTPTR HowitzerPtr;

		LockElement (MissileArray[0], &HowitzerPtr);
		HowitzerPtr->collision_func = howitzer_collision;
		UnlockElement (MissileArray[0]);
	}

	return (1);
}
Exemple #2
0
void
crc_processDispQueue(crc_State *state) {
	HELEMENT element;
	HELEMENT nextElement;

#ifdef DUMP_CRC_OPS
	size_t i = 0;
	log_add(log_Debug, "START crc_processDispQueue().");
#endif
	for (element = GetHeadElement(); element != 0; element = nextElement) {
		ELEMENTPTR elementPtr;

#ifdef DUMP_CRC_OPS
		log_add(log_Debug, "===== disp_q[%d]:", i);
#endif
		LockElement(element, &elementPtr);

		crc_processELEMENT(state, element);

		nextElement = GetSuccElement(elementPtr);
		UnlockElement(element);
#ifdef DUMP_CRC_OPS
		i++;
#endif
	}
#ifdef DUMP_CRC_OPS
	log_add(log_Debug, "END   crc_processDispQueue().");
#endif
}
Exemple #3
0
// playerNr should be 0 or 1
STARSHIP*
findPlayerShip (SIZE playerNr)
{
	HELEMENT hElement, hNextElement;

	for (hElement = GetHeadElement (); hElement; hElement = hNextElement)
	{
		ELEMENT *ElementPtr;

		LockElement (hElement, &ElementPtr);
		hNextElement = GetSuccElement (ElementPtr);
					
		if ((ElementPtr->state_flags & PLAYER_SHIP)	&&
				ElementPtr->playerNr == playerNr)
		{
			STARSHIP *StarShipPtr;
			GetElementStarShip (ElementPtr, &StarShipPtr);
			UnlockElement (hElement);
			return StarShipPtr;
		}
		
		UnlockElement (hElement);
	}
	return NULL;
}
Exemple #4
0
void
DrawScannedObjects (BOOLEAN Reversed)
{
	HELEMENT hElement, hNextElement;

	for (hElement = Reversed ? GetTailElement () : GetHeadElement ();
			hElement; hElement = hNextElement)
	{
		ELEMENT *ElementPtr;

		LockElement (hElement, &ElementPtr);
		hNextElement = Reversed ?
				GetPredElement (ElementPtr) :
				GetSuccElement (ElementPtr);

		if (ElementPtr->state_flags & APPEARING)
		{
			STAMP s;

			s.origin = ElementPtr->current.location;
			s.frame = ElementPtr->next.image.frame;
			DrawStamp (&s);
		}

		UnlockElement (hElement);
	}
}
Exemple #5
0
BOOLEAN
TimeSpaceMatterConflict (ELEMENT *ElementPtr)
{
	HELEMENT hTestElement, hSuccElement;
	INTERSECT_CONTROL ElementControl;

	ElementControl.IntersectStamp.origin.x =
			WORLD_TO_DISPLAY (ElementPtr->current.location.x);
	ElementControl.IntersectStamp.origin.y =
			WORLD_TO_DISPLAY (ElementPtr->current.location.y);
	ElementControl.IntersectStamp.frame =
			 SetEquFrameIndex (ElementPtr->current.image.farray[0],
			 ElementPtr->current.image.frame);
	ElementControl.EndPoint = ElementControl.IntersectStamp.origin;
	for (hTestElement = GetHeadElement ();
			hTestElement != 0; hTestElement = hSuccElement)
	{
		ELEMENT *TestElementPtr;

		LockElement (hTestElement, &TestElementPtr);
		hSuccElement = GetSuccElement (TestElementPtr);
		if (TestElementPtr != ElementPtr
				&& (CollidingElement (TestElementPtr)
						/* ship in transition */
				|| (TestElementPtr->state_flags & PLAYER_SHIP)))
		{
			INTERSECT_CONTROL TestElementControl;

			TestElementControl.IntersectStamp.origin.x =
					WORLD_TO_DISPLAY (TestElementPtr->current.location.x);
			TestElementControl.IntersectStamp.origin.y =
					WORLD_TO_DISPLAY (TestElementPtr->current.location.y);
			TestElementControl.IntersectStamp.frame =
					 SetEquFrameIndex (TestElementPtr->current.image.farray[0],
					 TestElementPtr->current.image.frame);
			TestElementControl.EndPoint = TestElementControl.IntersectStamp.origin;
			if (DrawablesIntersect (&ElementControl,
					&TestElementControl, MAX_TIME_VALUE))
			{
				UnlockElement (hTestElement);

				break;
			}
		}
		UnlockElement (hTestElement);
	}

	return (hTestElement != 0 ? TRUE : FALSE);
}
Exemple #6
0
BOOLEAN
OpponentAlive (STARSHIP *TestStarShipPtr)
{
	HELEMENT hElement, hSuccElement;

	for (hElement = GetHeadElement (); hElement; hElement = hSuccElement)
	{
		ELEMENT *ElementPtr;
		STARSHIP *StarShipPtr;

		LockElement (hElement, &ElementPtr);
		hSuccElement = GetSuccElement (ElementPtr);
		GetElementStarShip (ElementPtr, &StarShipPtr);
		UnlockElement (hElement);

		if (StarShipPtr && StarShipPtr != TestStarShipPtr
				&& StarShipPtr->RaceDescPtr->ship_info.crew_level == 0)
			return FALSE;
	}

	return TRUE;
}
Exemple #7
0
static void
checkOtherShipLifeSpan (ELEMENT *deadShip)
{
	STARSHIP *deadStarShip;

	GetElementStarShip (deadShip, &deadStarShip);

	if (winnerStarShip != NULL && deadStarShip != winnerStarShip
			&& winnerStarShip->RaceDescPtr->ship_info.crew_level == 0)
	{	// The opponent ship also died but won anyway (e.g. Glory device)
		// We need to keep the opponent ship alive longer so that the
		// winning player picks last.
		setMinStarShipLifeSpan (winnerStarShip, deadShip->life_span + 1);
	}
	else if (winnerStarShip == NULL)
	{	// Both died at the same time, or the loser has already expired
		HELEMENT hElement, hNextElement;

		// Find the other dead ship(s) and keep them alive for at least as
		// long as this ship.
		for (hElement = GetHeadElement (); hElement; hElement = hNextElement)
		{
			ELEMENT *element;
			STARSHIP *starShip;

			LockElement (hElement, &element);
			hNextElement = GetSuccElement (element);
			GetElementStarShip (element, &starShip);
			
			if (starShip != NULL && element != deadShip
					&& starShip->RaceDescPtr->ship_info.crew_level == 0)
			{	// This is another dead ship
				setMinShipLifeSpan (element, deadShip->life_span);
			}

			UnlockElement (hElement);
		}
	}
}
Exemple #8
0
// Count the crew elements in the display list.
static COUNT
CountCrewElements (void)
{
	COUNT result;
	HELEMENT hElement, hNextElement;

	result = 0;
	for (hElement = GetHeadElement ();
			hElement != 0; hElement = hNextElement)
	{
		ELEMENT *ElementPtr;

		LockElement (hElement, &ElementPtr);
		hNextElement = GetSuccElement (ElementPtr);
		if (ElementPtr->state_flags & CREW_OBJECT)
			++result;

		UnlockElement (hElement);
	}

	return result;
}
static void
confusion_collision (ELEMENT *ElementPtr0, POINT *pPt0,
                     ELEMENT *ElementPtr1, POINT *pPt1)
{
    if (ElementPtr1->state_flags & PLAYER_SHIP)
    {
        HELEMENT hConfusionElement, hNextElement;
        ELEMENT *ConfusionPtr;
        STARSHIP *StarShipPtr;

        GetElementStarShip (ElementPtr0, &StarShipPtr);
        for (hConfusionElement = GetHeadElement ();
                hConfusionElement; hConfusionElement = hNextElement)
        {
            LockElement (hConfusionElement, &ConfusionPtr);
            if (elementsOfSamePlayer (ConfusionPtr, ElementPtr0)
                    && ConfusionPtr->current.image.farray ==
                    StarShipPtr->RaceDescPtr->ship_data.special
                    && (ConfusionPtr->state_flags & NONSOLID))
            {
                UnlockElement (hConfusionElement);
                break;
            }
            hNextElement = GetSuccElement (ConfusionPtr);
            UnlockElement (hConfusionElement);
        }

        if (hConfusionElement || (hConfusionElement = AllocElement ()))
        {
            LockElement (hConfusionElement, &ConfusionPtr);

            if (ConfusionPtr->state_flags == 0) /* not allocated before */
            {
                InsertElement (hConfusionElement, GetHeadElement ());

                ConfusionPtr->current = ElementPtr0->next;
                ConfusionPtr->current.image.frame = SetAbsFrameIndex (
                                                        ConfusionPtr->current.image.frame, 8
                                                    );
                ConfusionPtr->next = ConfusionPtr->current;
                ConfusionPtr->playerNr = ElementPtr0->playerNr;
                ConfusionPtr->state_flags = FINITE_LIFE | NONSOLID | CHANGING;
                ConfusionPtr->preprocess_func = confuse_preprocess;
                SetPrimType (
                    &(GLOBAL (DisplayArray))[ConfusionPtr->PrimIndex],
                    NO_PRIM
                );

                SetElementStarShip (ConfusionPtr, StarShipPtr);
                GetElementStarShip (ElementPtr1, &StarShipPtr);
                ConfusionPtr->hTarget = StarShipPtr->hShip;
            }

            ConfusionPtr->life_span = 400;
            ConfusionPtr->turn_wait =
                (BYTE)(1 << ((BYTE)TFB_Random () & 1)); /* LEFT or RIGHT */

            UnlockElement (hConfusionElement);
        }

        ElementPtr0->hit_points = 0;
        ElementPtr0->life_span = 0;
        ElementPtr0->state_flags |= DISAPPEARING | COLLISION | NONSOLID;
    }
    (void) pPt0;  /* Satisfying compiler (unused parameter) */
    (void) pPt1;  /* Satisfying compiler (unused parameter) */
}
static void
spawn_crew (ELEMENT *ElementPtr)
{
	if (ElementPtr->state_flags & PLAYER_SHIP)
	{
		HELEMENT hCrew;

		hCrew = AllocElement ();
		if (hCrew != 0)
		{
			ELEMENT *CrewPtr;

			LockElement (hCrew, &CrewPtr);
			CrewPtr->next.location = ElementPtr->next.location;
			CrewPtr->playerNr = ElementPtr->playerNr;
			CrewPtr->state_flags = APPEARING | NONSOLID | FINITE_LIFE;
			CrewPtr->life_span = 0;
			CrewPtr->death_func = spawn_crew;
			CrewPtr->pParent = ElementPtr->pParent;
			CrewPtr->hTarget = 0;
			UnlockElement (hCrew);

			PutElement (hCrew);
		}
	}
	else
	{
		HELEMENT hElement, hNextElement;

		for (hElement = GetHeadElement ();
				hElement != 0; hElement = hNextElement)
		{
			ELEMENT *ObjPtr;
            STARSHIP *EnemyStarShipPtr;

			LockElement (hElement, &ObjPtr);
            GetElementStarShip (ObjPtr, &EnemyStarShipPtr);
			hNextElement = GetSuccElement (ObjPtr);

			if ((ObjPtr->state_flags & PLAYER_SHIP)
					&& !elementsOfSamePlayer (ObjPtr, ElementPtr)
					&& ObjPtr->crew_level > 1)
			{
				SIZE dx, dy;
				DWORD d_squared;

				dx = ObjPtr->next.location.x - ElementPtr->next.location.x;
				if (dx < 0)
					dx = -dx;
				dy = ObjPtr->next.location.y - ElementPtr->next.location.y;
				if (dy < 0)
					dy = -dy;

				dx = WORLD_TO_DISPLAY (dx);
				dy = WORLD_TO_DISPLAY (dy);
                
				if (dx <= ABANDONER_RANGE && dy <= ABANDONER_RANGE
						&& (d_squared = (DWORD)((UWORD)dx * (UWORD)dx)
						+ (DWORD)((UWORD)dy * (UWORD)dy)) <=
						(DWORD)((UWORD)ABANDONER_RANGE * (UWORD)ABANDONER_RANGE))
				{
					COUNT crew_loss;

					if (EnemyStarShipPtr && EnemyStarShipPtr->SpeciesID == SYREEN_ID)
					{
						crew_loss = ((LIMITED_MAX_ABANDONERS
							* (ABANDONER_RANGE - square_root (d_squared)))
							/ ABANDONER_RANGE) + 1;
					}
					else
					{
						crew_loss = ((MAX_ABANDONERS
							* (ABANDONER_RANGE - square_root (d_squared)))
							/ ABANDONER_RANGE) + 1;
                    }
                    
					if (crew_loss >= ObjPtr->crew_level)
						crew_loss = ObjPtr->crew_level - 1;

					AbandonShip (ObjPtr, ElementPtr, crew_loss);
				}
			}

			UnlockElement (hElement);
		}
	}
}
Exemple #11
0
static void
self_destruct (PELEMENT ElementPtr)
{
	STARSHIPPTR StarShipPtr;

	GetElementStarShip (ElementPtr, &StarShipPtr);
	if (ElementPtr->state_flags & PLAYER_SHIP)
	{
		HELEMENT hDestruct;
		
		hDestruct = AllocElement ();
		if (hDestruct)
		{
			ELEMENTPTR DestructPtr;

			LockElement (hDestruct, &DestructPtr);
			DestructPtr->state_flags = APPEARING | NONSOLID | FINITE_LIFE |
					(ElementPtr->state_flags & (GOOD_GUY | BAD_GUY));
			DestructPtr->next.location = ElementPtr->next.location;
			DestructPtr->life_span = 0;
			DestructPtr->pParent = ElementPtr->pParent;
			DestructPtr->hTarget = 0;

			DestructPtr->death_func = self_destruct;

			UnlockElement (hDestruct);

			PutElement (hDestruct);
		}

		ElementPtr->state_flags |= NONSOLID;
		ElementPtr->life_span = 0;

		ElementPtr->preprocess_func = destruct_preprocess;
	}
	else
	{
		HELEMENT hElement, hNextElement;

		for (hElement = GetHeadElement ();
				hElement != 0; hElement = hNextElement)
		{
			ELEMENTPTR ObjPtr;

			LockElement (hElement, &ObjPtr);
			hNextElement = GetSuccElement (ObjPtr);

			if (CollidingElement (ObjPtr) || ORZ_MARINE (ObjPtr))
			{
#define DESTRUCT_RANGE 180
				SIZE delta_x, delta_y;
				DWORD dist;

				if ((delta_x = ObjPtr->next.location.x
						- ElementPtr->next.location.x) < 0)
					delta_x = -delta_x;
				if ((delta_y = ObjPtr->next.location.y
						- ElementPtr->next.location.y) < 0)
					delta_y = -delta_y;
				delta_x = WORLD_TO_DISPLAY (delta_x);
				delta_y = WORLD_TO_DISPLAY (delta_y);
				if (delta_x <= DESTRUCT_RANGE && delta_y <= DESTRUCT_RANGE
						&& (dist = (DWORD)(delta_x * delta_x)
						+ (DWORD)(delta_y * delta_y)) <=
						(DWORD)(DESTRUCT_RANGE * DESTRUCT_RANGE))
				{
#define MAX_DESTRUCTION (DESTRUCT_RANGE / 10)
					SIZE destruction;

					destruction = ((MAX_DESTRUCTION
							* (DESTRUCT_RANGE - square_root (dist)))
							/ DESTRUCT_RANGE) + 1;

					if (ObjPtr->state_flags & PLAYER_SHIP)
					{
						if (!DeltaCrew (ObjPtr, -destruction))
							ObjPtr->life_span = 0;
					}
					else if (!GRAVITY_MASS (ObjPtr->mass_points))
					{
						if ((BYTE)destruction < ObjPtr->hit_points)
							ObjPtr->hit_points -= (BYTE)destruction;
						else
						{
							ObjPtr->hit_points = 0;
							ObjPtr->life_span = 0;
						}
					}
				}
			}

			UnlockElement (hElement);
		}
	}
}
Exemple #12
0
BOOLEAN
CalculateGravity (ELEMENT *ElementPtr)
{
	BOOLEAN retval, HasGravity;
	HELEMENT hTestElement, hSuccElement;

	retval = FALSE;
	HasGravity = (BOOLEAN)(CollidingElement (ElementPtr)
			&& GRAVITY_MASS (ElementPtr->mass_points + 1));
	for (hTestElement = GetHeadElement ();
			hTestElement != 0; hTestElement = hSuccElement)
	{
		BOOLEAN TestHasGravity;
		ELEMENT *TestElementPtr;

		LockElement (hTestElement, &TestElementPtr);
		if (TestElementPtr != ElementPtr
				&& CollidingElement (TestElementPtr)
				&& (TestHasGravity =
				GRAVITY_MASS (TestElementPtr->mass_points + 1)) != HasGravity)
		{
			COUNT abs_dx, abs_dy;
			SIZE dx, dy;

			if (!(ElementPtr->state_flags & PRE_PROCESS))
			{
				dx = ElementPtr->current.location.x
						- TestElementPtr->current.location.x;
				dy = ElementPtr->current.location.y
						- TestElementPtr->current.location.y;
			}
			else
			{
				dx = ElementPtr->next.location.x
						- TestElementPtr->next.location.x;
				dy = ElementPtr->next.location.y
						- TestElementPtr->next.location.y;
			}
#ifdef DEBUG_GRAVITY
			if (TestElementPtr->state_flags & PLAYER_SHIP)
			{
				log_add (log_Debug, "CalculateGravity:");
				log_add (log_Debug, "\tdx = %d, dy = %d", dx, dy);
			}
#endif /* DEBUG_GRAVITY */
			dx = WRAP_DELTA_X (dx);
			dy = WRAP_DELTA_Y (dy);
#ifdef DEBUG_GRAVITY
			if (TestElementPtr->state_flags & PLAYER_SHIP)
				log_add (log_Debug, "\twrap_dx = %d, wrap_dy = %d", dx, dy);
#endif /* DEBUG_GRAVITY */
			abs_dx = dx >= 0 ? dx : -dx;
			abs_dy = dy >= 0 ? dy : -dy;
			abs_dx = WORLD_TO_DISPLAY (abs_dx);
			abs_dy = WORLD_TO_DISPLAY (abs_dy);
#ifdef DEBUG_GRAVITY
			if (TestElementPtr->state_flags & PLAYER_SHIP)
				log_add (log_Debug, "\tdisplay_dx = %d, display_dy = %d",
						abs_dx, abs_dy);
#endif /* DEBUG_GRAVITY */
			if (abs_dx <= GRAVITY_THRESHOLD
					&& abs_dy <= GRAVITY_THRESHOLD)
			{
				DWORD dist_squared;

				dist_squared = (DWORD)(abs_dx * abs_dx)
						+ (DWORD)(abs_dy * abs_dy);
				if (dist_squared <= (DWORD)(GRAVITY_THRESHOLD
						* GRAVITY_THRESHOLD))
				{
#ifdef NEVER
					COUNT magnitude;

#define DIFUSE_GRAVITY RES_SCALE(175) // JMS_GFX: Because of the ifdef NEVER this is actually never run. Well, changed it for consistency
					dist_squared += (DWORD)abs_dx * (DIFUSE_GRAVITY << 1)
							+ (DWORD)abs_dy * (DIFUSE_GRAVITY << 1)
							+ ((DWORD)(DIFUSE_GRAVITY * DIFUSE_GRAVITY) << 1);
					if ((magnitude = (COUNT)((DWORD)(GRAVITY_THRESHOLD
							* GRAVITY_THRESHOLD) / dist_squared)) == 0)
						magnitude = 1;

#define MAX_MAGNITUDE RES_SCALE(6) // JMS_GFX: Because of the ifdef NEVER this is actually never run. Well, changed it for consistency
					else if (magnitude > MAX_MAGNITUDE)
						magnitude = MAX_MAGNITUDE;
					log_add (log_Debug, "magnitude = %u", magnitude);
#endif /* NEVER */

#ifdef DEBUG_GRAVITY
					if (TestElementPtr->state_flags & PLAYER_SHIP)
						log_add (log_Debug, "dist_squared = %lu", dist_squared);
#endif /* DEBUG_GRAVITY */
					if (TestHasGravity)
					{
						retval = TRUE;
						UnlockElement (hTestElement);
						break;
					}
					else
					{
						COUNT angle;

						angle = ARCTAN (dx, dy);
						DeltaVelocityComponents (&TestElementPtr->velocity,
								COSINE (angle, WORLD_TO_VELOCITY (RES_SCALE(1))),
								SINE (angle, WORLD_TO_VELOCITY (RES_SCALE(1)))); // JMS_GFX
						if (TestElementPtr->state_flags & PLAYER_SHIP)
						{
							STARSHIP *StarShipPtr;

							GetElementStarShip (TestElementPtr, &StarShipPtr);
							StarShipPtr->cur_status_flags &= ~SHIP_AT_MAX_SPEED;
							StarShipPtr->cur_status_flags |= SHIP_IN_GRAVITY_WELL;
						}
					}
				}
			}
		}

		hSuccElement = GetSuccElement (TestElementPtr);
		UnlockElement (hTestElement);
	}

	return (retval);
}
Exemple #13
0
void
UninitShips (void)
{
	BYTE crew_retrieved;
	SIZE i;
	HELEMENT hElement, hNextElement;
	STARSHIPPTR SPtr[NUM_PLAYERS];

	StopSound ();

	UninitSpace ();

	for (i = 0; i < NUM_PLAYERS; ++i)
		SPtr[i] = 0;

	// Count the crew floating in space.
	crew_retrieved = 0;
	for (hElement = GetHeadElement ();
			hElement != 0; hElement = hNextElement)
	{
		ELEMENTPTR ElementPtr;
		LockElement (hElement, &ElementPtr);
		hNextElement = GetSuccElement (ElementPtr);
		if (ElementPtr->state_flags & CREW_OBJECT)
			++crew_retrieved;
		UnlockElement (hElement);
	}

	for (hElement = GetHeadElement ();
			hElement != 0; hElement = hNextElement)
	{
		ELEMENTPTR ElementPtr;
		extern void new_ship (PELEMENT ElementPtr);

		LockElement (hElement, &ElementPtr);
		hNextElement = GetSuccElement (ElementPtr);
		if ((ElementPtr->state_flags & PLAYER_SHIP)
				|| ElementPtr->death_func == new_ship)
		{
			STARSHIPPTR StarShipPtr;

			GetElementStarShip (ElementPtr, &StarShipPtr);

			// There should only be one ship left in battle.
			// He gets the crew still floating in space.
			if (StarShipPtr->RaceDescPtr->ship_info.crew_level)
			{
				if (crew_retrieved >=
						StarShipPtr->RaceDescPtr->ship_info.max_crew -
						StarShipPtr->RaceDescPtr->ship_info.crew_level)
					StarShipPtr->RaceDescPtr->ship_info.crew_level =
							StarShipPtr->RaceDescPtr->ship_info.max_crew;
				else
					StarShipPtr->RaceDescPtr->ship_info.crew_level +=
							crew_retrieved;
			}

			if (StarShipPtr->RaceDescPtr->uninit_func != NULL)
				(*StarShipPtr->RaceDescPtr->uninit_func) (
						StarShipPtr->RaceDescPtr);
			StarShipPtr->ShipFacing =
					StarShipPtr->RaceDescPtr->ship_info.var2;
			StarShipPtr->special_counter =
					StarShipPtr->RaceDescPtr->ship_info.crew_level;
			SPtr[WHICH_SIDE (ElementPtr->state_flags)] = StarShipPtr;
			free_ship (StarShipPtr, TRUE);
		}
		UnlockElement (hElement);
	}

	GLOBAL (CurrentActivity) &= ~IN_BATTLE;

	if (LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE)
	{
	}
	else if (LOBYTE (GLOBAL (CurrentActivity)) <= IN_ENCOUNTER
			&& !(GLOBAL (CurrentActivity) & CHECK_ABORT))
	{
		for (i = NUM_PLAYERS - 1; i >= 0; --i)
		{
			if (SPtr[i])
				GetEncounterStarShip (SPtr[i], i);
		}
	}

	if (LOBYTE (GLOBAL (CurrentActivity)) != IN_ENCOUNTER)
	{
		ReinitQueue (&race_q[0]);
		ReinitQueue (&race_q[1]);

		if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE)
			FreeHyperspace ();
	}
}
Exemple #14
0
void
ship_death (ELEMENT *ShipPtr)
{
	STARSHIP *StarShipPtr;
	STARSHIP *VictoriousStarShipPtr;
	HELEMENT hElement, hNextElement;
	ELEMENT *ElementPtr;

	StopDitty ();
	StopMusic ();

	GetElementStarShip (ShipPtr, &StarShipPtr);
	
	// JMS: Make sure the Foon-foon's spinning blade sound ends when the ship dies.
	if (StarShipPtr->SpeciesID == FOONFOON_ID)
	{
		COUNT i;
		
		for (i = FIRST_SFX_CHANNEL; i <= LAST_SFX_CHANNEL; ++i)
		{
			ELEMENT *posobj;
			if (!ChannelPlaying(i))
				continue;
			
			posobj = GetPositionalObject (i);
			
			if (posobj)
				StopSource (i);
		}
	}

	if (ShipPtr->mass_points <= MAX_SHIP_MASS)
	{	// Not running away and not reincarnating (Pkunk)
		// When a ship tries to run away, it is (dis)counted in DoRunAway(),
		// so when it dies while running away, we will not count it again
		assert (StarShipPtr->playerNr >= 0);
		battle_counter[StarShipPtr->playerNr]--;
	}

	VictoriousStarShipPtr = NULL;
	for (hElement = GetHeadElement (); hElement; hElement = hNextElement)
	{
		LockElement (hElement, &ElementPtr);
		if ((ElementPtr->state_flags & PLAYER_SHIP)
				&& ElementPtr != ShipPtr
						/* and not running away */
				&& ElementPtr->mass_points <= MAX_SHIP_MASS)
		{
			GetElementStarShip (ElementPtr, &VictoriousStarShipPtr);
			if (VictoriousStarShipPtr->RaceDescPtr->ship_info.crew_level == 0)
				VictoriousStarShipPtr = NULL;

			UnlockElement (hElement);
			break;
		}
		hNextElement = GetSuccElement (ElementPtr);
		UnlockElement (hElement);
	}

	StarShipPtr->cur_status_flags &= ~PLAY_VICTORY_DITTY;

	DeltaEnergy (ShipPtr,
			-(SIZE)StarShipPtr->RaceDescPtr->ship_info.energy_level);

	ShipPtr->life_span = NUM_EXPLOSION_FRAMES * 3;
	ShipPtr->state_flags &= ~DISAPPEARING;
	ShipPtr->state_flags |= FINITE_LIFE | NONSOLID;
	ShipPtr->postprocess_func = PostProcessStatus;
	ShipPtr->death_func = cleanup_dead_ship;
	ShipPtr->hTarget = 0;
	ZeroVelocityComponents (&ShipPtr->velocity);
	if (ShipPtr->crew_level) /* only happens for shofixti self-destruct */
	{
		PlaySound (SetAbsSoundIndex (
				StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1),
				CalcSoundPosition (ShipPtr), ShipPtr,
				GAME_SOUND_PRIORITY + 1);

		DeltaCrew (ShipPtr, -(SIZE)ShipPtr->crew_level);
		if (VictoriousStarShipPtr == NULL)
		{	// No ships left alive after a Shofixti Glory device,
			// thus Shofixti wins
			VictoriousStarShipPtr = StarShipPtr;
		}
	}
	else
	{
		ShipPtr->preprocess_func = explosion_preprocess;

		PlaySound (SetAbsSoundIndex (GameSounds, SHIP_EXPLODES),
				CalcSoundPosition (ShipPtr), ShipPtr, GAME_SOUND_PRIORITY + 1);
	}

	if (VictoriousStarShipPtr != NULL)
		VictoriousStarShipPtr->cur_status_flags |= PLAY_VICTORY_DITTY;

	// The winner is set once per battle. If both ships die, this function is
	// called twice, once for each ship. We need to preserve the winner
	// determined on the first call.
	if (winnerStarShip == NULL)
		winnerStarShip = VictoriousStarShipPtr;

	if (LOBYTE (GLOBAL (CurrentActivity)) == SUPER_MELEE)
		MeleeShipDeath (StarShipPtr);
}
Exemple #15
0
void
cleanup_dead_ship (ELEMENT *DeadShipPtr)
{
	STARSHIP *DeadStarShipPtr;

	ProcessSound ((SOUND)~0, NULL);

	GetElementStarShip (DeadShipPtr, &DeadStarShipPtr);
	
	{
		// Ship explosion has finished, or ship has just warped out
		// if DeadStarShipPtr->crew_level != 0
		BOOLEAN MusicStarted;
		HELEMENT hElement, hSuccElement;

		/* Record crew left after the battle */
		DeadStarShipPtr->crew_level =
				DeadStarShipPtr->RaceDescPtr->ship_info.crew_level;

		MusicStarted = FALSE;

		for (hElement = GetHeadElement (); hElement; hElement = hSuccElement)
		{
			ELEMENT *ElementPtr;
			STARSHIP *StarShipPtr;

			LockElement (hElement, &ElementPtr);
			hSuccElement = GetSuccElement (ElementPtr);
			GetElementStarShip (ElementPtr, &StarShipPtr);
					// Get the STARSHIP that this ELEMENT belongs to.

			if (StarShipPtr == DeadStarShipPtr)
			{
				// This element belongs to the dead ship; it may be the
				// ship's own element.
				SetElementStarShip (ElementPtr, 0);

				if (!(ElementPtr->state_flags & CREW_OBJECT)
						|| ElementPtr->preprocess_func != crew_preprocess)
				{
					// Set the element up for deletion.
					SetPrimType (&DisplayArray[ElementPtr->PrimIndex],
							NO_PRIM);
					ElementPtr->life_span = 0;
					ElementPtr->state_flags =
							NONSOLID | DISAPPEARING | FINITE_LIFE;
					ElementPtr->preprocess_func = 0;
					ElementPtr->postprocess_func = 0;
					ElementPtr->death_func = 0;
					ElementPtr->collision_func = 0;
				}
			}

			if (StarShipPtr
					&& (StarShipPtr->cur_status_flags & PLAY_VICTORY_DITTY))
			{
				// StarShipPtr points to the remaining ship.
				MusicStarted = TRUE;
				PlayDitty (StarShipPtr);
				StarShipPtr->cur_status_flags &= ~PLAY_VICTORY_DITTY;
			}

			UnlockElement (hElement);
		}
		DeadShipPtr->state_flags |= DeadShipPtr->turn_wait;
#define MIN_DITTY_FRAME_COUNT  ((ONE_SECOND * 3) / BATTLE_FRAME_RATE)
		// The ship will be "alive" for at least 2 more frames to make sure
		// the elements it owns (set up for deletion above) expire first.
		// Ditty does NOT play in the following circumstances:
		//  * The winning ship dies before the loser finishes exploding
		//  * At the moment the losing ship dies, the winner has started
		//    the warp out sequence
		DeadShipPtr->life_span = MusicStarted ? MIN_DITTY_FRAME_COUNT : 1;
		if (DeadStarShipPtr == winnerStarShip)
		{	// This ship died but won the battle. We need to keep it alive
			// longer than the dead opponent ship so that the winning player
			// picks last.
			DeadShipPtr->life_span = MIN_DITTY_FRAME_COUNT + 1;
		}
		DeadShipPtr->death_func = new_ship;
		DeadShipPtr->preprocess_func = preprocess_dead_ship;
		DeadShipPtr->state_flags &= ~DISAPPEARING;
		// XXX: this increment was originally done by another piece of code
		//   just below this one. I am almost sure it is not needed, but it
		//   keeps the original framecount.
		++DeadShipPtr->life_span;
		SetElementStarShip (DeadShipPtr, DeadStarShipPtr);
	}
}
Exemple #16
0
// XXX: This function should be split into two
static void
self_destruct (ELEMENT *ElementPtr)
{
    STARSHIP *StarShipPtr;

    GetElementStarShip (ElementPtr, &StarShipPtr);
    if (ElementPtr->state_flags & PLAYER_SHIP)
    {
        HELEMENT hDestruct;

        // Spawn a temporary element, which dies in this same frame, in order
        // to defer the effects of the glory explosion.
        // It will be the last element (or one of the last) for which the
        // death_func will be called from PostProcessQueue() in this frame.
        hDestruct = AllocElement ();
        if (hDestruct)
        {
            ELEMENT *DestructPtr;

            LockElement (hDestruct, &DestructPtr);
            DestructPtr->playerNr = ElementPtr->playerNr;
            DestructPtr->state_flags = APPEARING | NONSOLID | FINITE_LIFE;
            DestructPtr->next.location = ElementPtr->next.location;
            DestructPtr->life_span = 0;
            DestructPtr->pParent = ElementPtr->pParent;
            DestructPtr->hTarget = 0;

            DestructPtr->death_func = self_destruct;

            UnlockElement (hDestruct);

            PutElement (hDestruct);
        }

        ElementPtr->state_flags |= NONSOLID;
        // The ship is now dead. It's death_func, i.e. ship_death(), will be
        // called the next frame.
        ElementPtr->life_span = 0;

        ElementPtr->preprocess_func = destruct_preprocess;
    }
    else
    {
        // This is called during PostProcessQueue(), close to or at the end,
        // for the temporary destruct element to apply the effects of glory
        // explosion. The effects are not seen until the next frame.
        HELEMENT hElement, hNextElement;

        for (hElement = GetHeadElement ();
                hElement != 0; hElement = hNextElement)
        {
            ELEMENT *ObjPtr;

            LockElement (hElement, &ObjPtr);
            hNextElement = GetSuccElement (ObjPtr);

            if (CollidingElement (ObjPtr) || ORZ_MARINE (ObjPtr))
            {
#define DESTRUCT_RANGE 180
                SIZE delta_x, delta_y;
                DWORD dist;

                if ((delta_x = ObjPtr->next.location.x
                               - ElementPtr->next.location.x) < 0)
                    delta_x = -delta_x;
                if ((delta_y = ObjPtr->next.location.y
                               - ElementPtr->next.location.y) < 0)
                    delta_y = -delta_y;
                delta_x = WORLD_TO_DISPLAY (delta_x);
                delta_y = WORLD_TO_DISPLAY (delta_y);
                if (delta_x <= DESTRUCT_RANGE && delta_y <= DESTRUCT_RANGE
                        && (dist = (DWORD)(delta_x * delta_x)
                                   + (DWORD)(delta_y * delta_y)) <=
                        (DWORD)(DESTRUCT_RANGE * DESTRUCT_RANGE))
                {
#define MAX_DESTRUCTION (DESTRUCT_RANGE / 10)
                    SIZE destruction;

                    destruction = ((MAX_DESTRUCTION
                                    * (DESTRUCT_RANGE - square_root (dist)))
                                   / DESTRUCT_RANGE) + 1;

                    if (ObjPtr->state_flags & PLAYER_SHIP)
                    {
                        if (!DeltaCrew (ObjPtr, -destruction))
                            ObjPtr->life_span = 0;
                    }
                    else if (!GRAVITY_MASS (ObjPtr->mass_points))
                    {
                        if ((BYTE)destruction < ObjPtr->hit_points)
                            ObjPtr->hit_points -= (BYTE)destruction;
                        else
                        {
                            ObjPtr->hit_points = 0;
                            ObjPtr->life_span = 0;
                        }
                    }
                }
            }

            UnlockElement (hElement);
        }
    }
}
Exemple #17
0
void
UninitShips (void)
{
	COUNT crew_retrieved;
	int i;
	HELEMENT hElement, hNextElement;
	STARSHIP *SPtr[NUM_PLAYERS];

	StopSound ();

	UninitSpace ();

	for (i = 0; i < NUM_PLAYERS; ++i)
		SPtr[i] = 0;

	// Count the crew floating in space.
	crew_retrieved = CountCrewElements();

	for (hElement = GetHeadElement ();
			hElement != 0; hElement = hNextElement)
	{
		ELEMENT *ElementPtr;

		LockElement (hElement, &ElementPtr);
		hNextElement = GetSuccElement (ElementPtr);
		if ((ElementPtr->state_flags & PLAYER_SHIP)
				|| ElementPtr->death_func == new_ship)
		{
			STARSHIP *StarShipPtr;

			GetElementStarShip (ElementPtr, &StarShipPtr);

			// There should only be one ship left in battle.
			// He gets the crew still floating in space.
			if (StarShipPtr->RaceDescPtr->ship_info.crew_level)
			{
				if (crew_retrieved >=
						StarShipPtr->RaceDescPtr->ship_info.max_crew -
						StarShipPtr->RaceDescPtr->ship_info.crew_level)
					StarShipPtr->RaceDescPtr->ship_info.crew_level =
							StarShipPtr->RaceDescPtr->ship_info.max_crew;
				else
					StarShipPtr->RaceDescPtr->ship_info.crew_level +=
							crew_retrieved;
			}

			/* Record crew left after battle */
			StarShipPtr->crew_level =
					StarShipPtr->RaceDescPtr->ship_info.crew_level;
			SPtr[StarShipPtr->playerNr] = StarShipPtr;
			free_ship (StarShipPtr->RaceDescPtr, TRUE, TRUE);
			StarShipPtr->RaceDescPtr = 0;
		}
		UnlockElement (hElement);
	}

	GLOBAL (CurrentActivity) &= ~IN_BATTLE;

	if (LOBYTE (GLOBAL (CurrentActivity)) == IN_ENCOUNTER
			&& !(GLOBAL (CurrentActivity) & CHECK_ABORT))
	{
		// Encounter battle in full game.
		//   Record the crew left in the last ship standing. The crew left
		//   is first recorded into STARSHIP.crew_level just a few lines
		//   above here.
		for (i = NUM_PLAYERS - 1; i >= 0; --i)
		{
			if (SPtr[i] && !FleetIsInfinite (i))
				UpdateShipFragCrew (SPtr[i]);
		}
	}

	if (LOBYTE (GLOBAL (CurrentActivity)) != IN_ENCOUNTER)
	{
		// Remove any ships left from the race queue.
		for (i = 0; i < NUM_PLAYERS; i++)
			ReinitQueue (&race_q[i]);

		if (inHQSpace ())
			FreeHyperspace ();
	}
}
Exemple #18
0
// When hit by Baul spray, gas clouds explodes transforming into a lethal shockwave.
static void
generate_shockwave (ELEMENT *ElementPtr, BYTE which_player)
{
	STARSHIP *StarShipPtr;
	
	GetElementStarShip (ElementPtr, &StarShipPtr);
	
	// Gas is still 'solid' when it's hit by the spray. Let's make a shockwave and kill the gas cloud. 
	if (!(ElementPtr->state_flags & NONSOLID))
	{
		HELEMENT hShockwave;
				
		hShockwave = AllocElement ();
		if (hShockwave)
		{
			ELEMENT *ShockwavePtr;
			STARSHIP *StarShipPtr;
			
			GetElementStarShip (ElementPtr, &StarShipPtr);
			
			PutElement (hShockwave);
			LockElement (hShockwave, &ShockwavePtr);
			SetElementStarShip (ShockwavePtr, StarShipPtr);
			ShockwavePtr->hit_points = ShockwavePtr->mass_points = 0;
			ShockwavePtr->playerNr = which_player;
			ShockwavePtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID | IGNORE_SIMILAR;
			ShockwavePtr->life_span = SHOCKWAVE_FRAMES;
			SetPrimType (&(GLOBAL (DisplayArray))[ShockwavePtr->PrimIndex], STAMP_PRIM);
			ShockwavePtr->current.image.farray = StarShipPtr->RaceDescPtr->ship_data.special;
			ShockwavePtr->current.image.frame = SetAbsFrameIndex(StarShipPtr->RaceDescPtr->ship_data.special[0], LAST_GAS_INDEX);
			ShockwavePtr->next.image.frame = SetAbsFrameIndex(ElementPtr->current.image.frame, LAST_GAS_INDEX);
			ShockwavePtr->current.location = ElementPtr->current.location;
			ShockwavePtr->preprocess_func = shockwave_preprocess;
			ShockwavePtr->postprocess_func = NULL;
			ShockwavePtr->death_func = NULL;
			ZeroVelocityComponents (&ShockwavePtr->velocity);
			UnlockElement (hShockwave);
		}
		
		// Gas dies on the next turn.
		ElementPtr->state_flags |= NONSOLID;
		
		// Explosion sounds.
		ProcessSound (SetAbsSoundIndex (StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 2), ElementPtr);
		ProcessSound (SetAbsSoundIndex (GameSounds, TARGET_DAMAGED_FOR_6_PLUS_PT), ElementPtr);
	}

	{
		// This is called during PostProcessQueue(), close to or at the end,
		// for the temporary shockwave element to apply the damage.
		// The effects are not seen until the next frame.
		HELEMENT hElement, hNextElement;
		
		for (hElement = GetHeadElement (); hElement != 0; hElement = hNextElement)
		{
			ELEMENT *ObjPtr;
			
			LockElement (hElement, &ObjPtr);
			hNextElement = GetSuccElement (ObjPtr);
			
			if (IS_GAS (ObjPtr))
			{
				SIZE delta_x, delta_y;
				DWORD dist;
				
				if ((delta_x = ObjPtr->next.location.x - ElementPtr->next.location.x) < 0) delta_x = -delta_x;
				if ((delta_y = ObjPtr->next.location.y - ElementPtr->next.location.y) < 0) delta_y = -delta_y;
				
				delta_x = WORLD_TO_DISPLAY (delta_x);
				delta_y = WORLD_TO_DISPLAY (delta_y);
				
				if (delta_x <= SHOCKWAVE_RANGE && delta_y <= SHOCKWAVE_RANGE
					&& (dist = (DWORD)(delta_x * delta_x) + (DWORD)(delta_y * delta_y)) <= (DWORD)(SHOCKWAVE_RANGE * SHOCKWAVE_RANGE))
				{
					SIZE destruction;
					
					destruction = ((MAX_DESTRUCTION * (SHOCKWAVE_RANGE - square_root (dist))) / SHOCKWAVE_RANGE) + 1;
					
					// The shockwave is delayed according to how far it is from the shockwave that set it off.
					ObjPtr->life_span = (10 / destruction);
					ObjPtr->death_func = generate_shockwave_2;
					ObjPtr->playerNr = which_player;
				}
			}
			else if (CollidingElement (ObjPtr) || ORZ_MARINE (ObjPtr))
			{
				SIZE delta_x, delta_y;
				DWORD dist;
				
				if ((delta_x = ObjPtr->next.location.x - ElementPtr->next.location.x) < 0) delta_x = -delta_x;
				if ((delta_y = ObjPtr->next.location.y - ElementPtr->next.location.y) < 0) delta_y = -delta_y;
				
				delta_x = WORLD_TO_DISPLAY (delta_x);
				delta_y = WORLD_TO_DISPLAY (delta_y);
				
				if (delta_x <= SHOCKWAVE_RANGE && delta_y <= SHOCKWAVE_RANGE
					&& (dist = (DWORD)(delta_x * delta_x) + (DWORD)(delta_y * delta_y)) <= (DWORD)(SHOCKWAVE_RANGE * SHOCKWAVE_RANGE))
				{
					SIZE destruction;
					
					destruction = ((MAX_DESTRUCTION * (SHOCKWAVE_RANGE - square_root (dist))) / SHOCKWAVE_RANGE) + 1;
					
					if (ObjPtr->state_flags & PLAYER_SHIP && ObjPtr->playerNr != which_player)
					{
						STARSHIP *EnemyShipPtr;
						
						GetElementStarShip (ObjPtr, &EnemyShipPtr);
						
						// Deal damage to ships except shield-using Yehat & Utwig.
						if (!((EnemyShipPtr->SpeciesID == YEHAT_ID || EnemyShipPtr->SpeciesID == UTWIG_ID) 
							  && ObjPtr->life_span > NORMAL_LIFE))
						{
							if (!DeltaCrew (ObjPtr, -destruction))
								ObjPtr->life_span = 0;
						}
						// Charge Utwig shield.
						else if (EnemyShipPtr->SpeciesID == UTWIG_ID && ObjPtr->life_span > NORMAL_LIFE)
							ObjPtr->life_span += destruction;
					}
					else if (!GRAVITY_MASS (ObjPtr->mass_points) && ObjPtr->playerNr != which_player)
					{
						if ((BYTE)destruction < ObjPtr->hit_points)
							ObjPtr->hit_points -= (BYTE)destruction;
						else
						{
							ObjPtr->hit_points = 0;
							ObjPtr->life_span = 0;
						}
					}
				}
			}
			
			UnlockElement (hElement);
		}
	}
}
Exemple #19
0
static void
spawn_crew (ELEMENT *ElementPtr)
{
	if (ElementPtr->state_flags & PLAYER_SHIP)
	{
		HELEMENT hCrew;

		hCrew = AllocElement ();
		if (hCrew != 0)
		{
			ELEMENT *CrewPtr;

			LockElement (hCrew, &CrewPtr);
			CrewPtr->next.location = ElementPtr->next.location;
			CrewPtr->playerNr = ElementPtr->playerNr;
			CrewPtr->state_flags = APPEARING | NONSOLID | FINITE_LIFE;
			CrewPtr->life_span = 0;
			CrewPtr->death_func = spawn_crew;
			CrewPtr->pParent = ElementPtr->pParent;
			CrewPtr->hTarget = 0;
			UnlockElement (hCrew);

			PutElement (hCrew);
		}
	}
	else
	{
		HELEMENT hElement, hNextElement;

		for (hElement = GetHeadElement ();
				hElement != 0; hElement = hNextElement)
		{
			ELEMENT *ObjPtr;

			LockElement (hElement, &ObjPtr);
			hNextElement = GetSuccElement (ObjPtr);

			if ((ObjPtr->state_flags & PLAYER_SHIP)
					&& !elementsOfSamePlayer (ObjPtr, ElementPtr)
					&& ObjPtr->crew_level > 1)
			{
				SIZE dx, dy;
				DWORD d_squared;

				dx = ObjPtr->next.location.x - ElementPtr->next.location.x;
				if (dx < 0)
					dx = -dx;
				dy = ObjPtr->next.location.y - ElementPtr->next.location.y;
				if (dy < 0)
					dy = -dy;

				dx = WORLD_TO_DISPLAY (dx);
				dy = WORLD_TO_DISPLAY (dy);
#define ABANDONER_RANGE (208 << RESOLUTION_FACTOR) // JMS_GFX /* originally SPACE_HEIGHT */
				if (dx <= ABANDONER_RANGE && dy <= ABANDONER_RANGE
						&& (d_squared = (DWORD)((UWORD)dx * (UWORD)dx)
						+ (DWORD)((UWORD)dy * (UWORD)dy)) <=
						(DWORD)((UWORD)ABANDONER_RANGE * (UWORD)ABANDONER_RANGE))
				{
#define MAX_ABANDONERS 8
					COUNT crew_loss;

					crew_loss = ((MAX_ABANDONERS
							* (ABANDONER_RANGE - square_root (d_squared)))
							/ ABANDONER_RANGE) + 1;
					if (crew_loss >= ObjPtr->crew_level)
						crew_loss = ObjPtr->crew_level - 1;

					AbandonShip (ObjPtr, ElementPtr, crew_loss);
				}
			}

			UnlockElement (hElement);
		}
	}
}
Exemple #20
0
void
UninitShips (void)
{
	COUNT crew_retrieved;
	SIZE i;
	HELEMENT hElement, hNextElement;
	STARSHIP *SPtr[NUM_PLAYERS];

	StopSound ();

	UninitSpace ();

	for (i = 0; i < NUM_PLAYERS; ++i)
		SPtr[i] = 0;

	// Count the crew floating in space.
	crew_retrieved = CountCrewElements();

	for (hElement = GetHeadElement ();
			hElement != 0; hElement = hNextElement)
	{
		ELEMENT *ElementPtr;
		extern void new_ship (ELEMENT *ElementPtr);

		LockElement (hElement, &ElementPtr);
		hNextElement = GetSuccElement (ElementPtr);
		if ((ElementPtr->state_flags & PLAYER_SHIP)
				|| ElementPtr->death_func == new_ship)
		{
			STARSHIP *StarShipPtr;

			GetElementStarShip (ElementPtr, &StarShipPtr);

			// There should only be one ship left in battle.
			// He gets the crew still floating in space.
			if (StarShipPtr->RaceDescPtr->ship_info.crew_level)
			{
				if (crew_retrieved >=
						StarShipPtr->RaceDescPtr->ship_info.max_crew -
						StarShipPtr->RaceDescPtr->ship_info.crew_level)
					StarShipPtr->RaceDescPtr->ship_info.crew_level =
							StarShipPtr->RaceDescPtr->ship_info.max_crew;
				else
					StarShipPtr->RaceDescPtr->ship_info.crew_level +=
							crew_retrieved;
			}

			if (StarShipPtr->RaceDescPtr->uninit_func != NULL)
				(*StarShipPtr->RaceDescPtr->uninit_func) (
						StarShipPtr->RaceDescPtr);
			/* Record crew left after battle */
			StarShipPtr->crew_level =
					StarShipPtr->RaceDescPtr->ship_info.crew_level;
			SPtr[WHICH_SIDE (ElementPtr->state_flags)] = StarShipPtr;
			free_ship (StarShipPtr->RaceDescPtr, TRUE, TRUE);
			StarShipPtr->RaceDescPtr = 0;
		}
		UnlockElement (hElement);
	}

	GLOBAL (CurrentActivity) &= ~IN_BATTLE;

	if (LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE)
	{
	}
	else if (LOBYTE (GLOBAL (CurrentActivity)) <= IN_ENCOUNTER
			&& !(GLOBAL (CurrentActivity) & CHECK_ABORT))
	{
		// XXX: This has no purpose for SuperMelee
		//   In full-game, the sole purpose of this is to record the crew
		//   left in the last ship standing. The crew left is first recorded
		//   into STARSHIP.crew_level just a few lines above here.
		for (i = NUM_PLAYERS - 1; i >= 0; --i)
		{
			if (SPtr[i])
				GetEncounterStarShip (SPtr[i], i);
		}
	}

	if (LOBYTE (GLOBAL (CurrentActivity)) != IN_ENCOUNTER)
	{
		// Remove any ships left from the race queue.
		for (i = 0; i < NUM_PLAYERS; i++)
			ReinitQueue (&race_q[i]);

		if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE)
			FreeHyperspace ();
	}
}