Exemple #1
0
static void
intercept_pkunk_death (ELEMENT *ElementPtr)
{
	STARSHIP *StarShipPtr;

	ElementPtr->state_flags &= ~DISAPPEARING;
	ElementPtr->life_span = 1;

	GetElementStarShip (ElementPtr, &StarShipPtr);
	if (StarShipPtr->RaceDescPtr->ship_info.crew_level == 0)
	{
		ELEMENT *ShipPtr;

		LockElement (StarShipPtr->hShip, &ShipPtr);
		if (GRAVITY_MASS (ShipPtr->mass_points + 1))
		{
			ElementPtr->state_flags |= DISAPPEARING;
			ElementPtr->life_span = 0;
		}
		else
		{
			ShipPtr->mass_points = MAX_SHIP_MASS + 1;
			StarShipPtr->RaceDescPtr->preprocess_func = ShipPtr->preprocess_func;
			StarShipPtr->RaceDescPtr->postprocess_func = ShipPtr->postprocess_func;
			StarShipPtr->RaceDescPtr->init_weapon_func =
					(COUNT (*) (ELEMENT *ElementPtr, HELEMENT Weapon[]))
							ShipPtr->death_func;

			ElementPtr->death_func = new_pkunk;
		}
		UnlockElement (StarShipPtr->hShip);
	}
}
Exemple #2
0
void
do_damage (ELEMENT *ElementPtr, SIZE damage)
{
	if (ElementPtr->state_flags & PLAYER_SHIP)
	{
		if (!DeltaCrew (ElementPtr, -damage))
		{
			ElementPtr->life_span = 0;
			ElementPtr->state_flags |= NONSOLID;
		}
	}
	else if (!GRAVITY_MASS (ElementPtr->mass_points))
	{
		if ((BYTE)damage < ElementPtr->hit_points)
			ElementPtr->hit_points -= (BYTE)damage;
		else
		{
			ElementPtr->hit_points = 0;
			ElementPtr->life_span = 0;
			ElementPtr->state_flags |= NONSOLID;
		}
	}
}
Exemple #3
0
static void
cannon_collision (ELEMENT *ElementPtr0, POINT *pPt0,
		ELEMENT *ElementPtr1, POINT *pPt1)
{
	weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1);

	if ((ElementPtr1->state_flags & PLAYER_SHIP)
			&& ElementPtr1->crew_level
			&& !GRAVITY_MASS (ElementPtr1->mass_points + 1))
	{
		COUNT angle;
		SIZE cur_delta_x, cur_delta_y;
		STARSHIP *StarShipPtr;

		GetElementStarShip (ElementPtr1, &StarShipPtr);
		StarShipPtr->cur_status_flags &=
				~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED);

		angle = FACING_TO_ANGLE (
				GetFrameIndex (ElementPtr0->next.image.frame)
				);
		DeltaVelocityComponents (&ElementPtr1->velocity,
				COSINE (angle, RECOIL_VELOCITY),
				SINE (angle, RECOIL_VELOCITY));
		GetCurrentVelocityComponents (&ElementPtr1->velocity,
				&cur_delta_x, &cur_delta_y);
		if ((long)cur_delta_x * (long)cur_delta_x
				+ (long)cur_delta_y * (long)cur_delta_y
				> (long)MAX_RECOIL_VELOCITY * (long)MAX_RECOIL_VELOCITY)
		{
			angle = ARCTAN (cur_delta_x, cur_delta_y);
			SetVelocityComponents (&ElementPtr1->velocity,
					COSINE (angle, MAX_RECOIL_VELOCITY),
					SINE (angle, MAX_RECOIL_VELOCITY));
		}
	}
}
Exemple #4
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 #5
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 #6
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 #7
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);
}