Ejemplo n.º 1
0
static void
butt_missile_preprocess (ELEMENT *ElementPtr)
{
	if (ElementPtr->turn_wait > 0)
		--ElementPtr->turn_wait;
	else
	{
		COUNT facing;
		// COUNT num_frames;
		SIZE delta_x, delta_y, delta_facing;
		ELEMENT *EnemyPtr;

		facing = GetFrameIndex (ElementPtr->next.image.frame);
		
		if (ElementPtr->hTarget)
		{
			LockElement (ElementPtr->hTarget, &EnemyPtr);
			delta_x = EnemyPtr->current.location.x
					- ElementPtr->current.location.x;
			delta_x = WRAP_DELTA_X (delta_x);
			delta_y = EnemyPtr->current.location.y
					- ElementPtr->current.location.y;
			delta_y = WRAP_DELTA_Y (delta_y);
	
			/* num_frames = (square_root ((long)delta_x * delta_x
					+ (long)delta_y * delta_y)) / DISCRIMINATOR_SPEED;

			if (num_frames == 0)
				num_frames = 1;
	
			GetNextVelocityComponents (&EnemyPtr->velocity,
					&delta_x, &delta_y, num_frames);
	
			// Lead the target by its apparent trajectory.
			delta_x = (EnemyPtr->current.location.x + (delta_x / 2))
					- ElementPtr->current.location.x;
			delta_y = (EnemyPtr->current.location.y + (delta_y / 2))
					- ElementPtr->current.location.y; */
	
			delta_facing = NORMALIZE_FACING (
					ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) - facing);
	
			if (delta_facing > 0 && !OBJECT_CLOAKED(EnemyPtr))
			{
				if (delta_facing == ANGLE_TO_FACING (HALF_CIRCLE))
					facing += (((BYTE)TFB_Random () & 1) << 1) - 1;
				else if (delta_facing < ANGLE_TO_FACING (HALF_CIRCLE))
					++facing;
				else
					--facing;
			}
	
			ElementPtr->next.image.frame =
				SetAbsFrameIndex (ElementPtr->next.image.frame, facing);

			ElementPtr->state_flags |= CHANGING;
	
			SetVelocityVector (&ElementPtr->velocity, DISCRIMINATOR_SPEED, facing);

			UnlockElement (ElementPtr->hTarget);
		}
		else if (TrackShip (ElementPtr, &facing) > 0)
		{
			ElementPtr->next.image.frame =
					SetAbsFrameIndex (ElementPtr->next.image.frame,
					facing);
			ElementPtr->state_flags |= CHANGING;
	
			SetVelocityVector (&ElementPtr->velocity,
					DISCRIMINATOR_SPEED, facing);
		}

		ElementPtr->turn_wait = TRACK_WAIT;
	}
}
Ejemplo n.º 2
0
static COUNT
initialize_flak (ELEMENT *ShipPtr, HELEMENT MissileArray[])
{
	COUNT i;
	STARSHIP *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;
	MissileBlock.face = MissileBlock.index = StarShipPtr->ShipFacing;
	MissileBlock.sender = ShipPtr->playerNr;
	MissileBlock.flags = IGNORE_SIMILAR;
	MissileBlock.pixoffs = SPATHI_FORWARD_OFFSET;
	MissileBlock.speed = (MISSILE_SPEED << RESOLUTION_FACTOR);
	MissileBlock.hit_points = MISSILE_HITS;
	MissileBlock.damage = MISSILE_DAMAGE;
	MissileBlock.life = MISSILE_LIFE;
	MissileBlock.preprocess_func = flak_preprocess;
	MissileBlock.blast_offs = MISSILE_OFFSET;

	for(i = 0; i < 3; ++i)
	{
		if (i == 0)
		{
			MissileBlock.cx = ShipPtr->next.location.x;
			MissileBlock.cy = ShipPtr->next.location.y;
		}
		else if (i == 1)
		{
			MissileBlock.cx = ShipPtr->next.location.x
				+ COSINE(FACING_TO_ANGLE(StarShipPtr->ShipFacing + 4), 12);
			MissileBlock.cy = ShipPtr->next.location.y
				+ SINE(FACING_TO_ANGLE(StarShipPtr->ShipFacing + 4), 12);
		}
		else if (i == 2)
		{
			MissileBlock.cx = ShipPtr->next.location.x
				+ COSINE(FACING_TO_ANGLE(StarShipPtr->ShipFacing + 4), -12);
			MissileBlock.cy = ShipPtr->next.location.y
				+ SINE(FACING_TO_ANGLE(StarShipPtr->ShipFacing + 4), -12);
		}
		
		if ((MissileArray[i] = initialize_missile (&MissileBlock)))
		{
			SIZE dx, dy, angle, speed;
			ELEMENT *MissilePtr;

			LockElement (MissileArray[i], &MissilePtr);

			if (i > 0)
			{
				angle = GetVelocityTravelAngle (&MissilePtr->velocity);
				GetCurrentVelocityComponents(&MissilePtr->velocity, &dx, &dy);
				speed = square_root (dx*dx + dy*dy);

				if (i == 1)
					angle += 1;
				else if (i == 2)
					angle -= 1;

				SetVelocityComponents(&MissilePtr->velocity, COSINE(angle, speed), SINE(angle, speed));
			}

			GetCurrentVelocityComponents (&ShipPtr->velocity, &dx, &dy);

			// Add the Eluder's velocity to its projectiles.
			DeltaVelocityComponents (&MissilePtr->velocity, dx, dy);
			MissilePtr->current.location.x -= VELOCITY_TO_WORLD (dx);
			MissilePtr->current.location.y -= VELOCITY_TO_WORLD (dy);

			MissilePtr->turn_wait = 1;

			UnlockElement (MissileArray[i]);
		}
	}

	return (3);
}
Ejemplo n.º 3
0
static void
destruct_preprocess (ELEMENT *ElementPtr)
{
#define DESTRUCT_SWITCH ((NUM_EXPLOSION_FRAMES * 3) - 3)
    PRIMITIVE *lpPrim;

    // ship_death() set the ship element's life_span to
    // (NUM_EXPLOSION_FRAMES * 3)
    lpPrim = &(GLOBAL (DisplayArray))[ElementPtr->PrimIndex];
    ElementPtr->state_flags |= CHANGING;
    if (ElementPtr->life_span > DESTRUCT_SWITCH)
    {
        // First, stamp-fill the ship's own element with changing colors
        // for 3 frames. No explosion element yet.
        SetPrimType (lpPrim, STAMPFILL_PRIM);
        if (ElementPtr->life_span == DESTRUCT_SWITCH + 2)
            SetPrimColor (lpPrim,
                          BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x0A), 0x0E));
        else
            SetPrimColor (lpPrim,
                          BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F));
    }
    else if (ElementPtr->life_span < DESTRUCT_SWITCH)
    {
        // Stamp-fill the explosion element with cycling colors for the
        // remainder of the glory explosion frames.
        Color color = GetPrimColor (lpPrim);

        ElementPtr->next.image.frame =
            IncFrameIndex (ElementPtr->current.image.frame);
        if (sameColor (color,
                       BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F)))
            SetPrimColor (lpPrim,
                          BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x0A), 0x0E));
        else if (sameColor (color,
                            BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x0A), 0x0E)))
            SetPrimColor (lpPrim,
                          BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x0A), 0x0C));
        else if (sameColor (color,
                            BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x0A), 0x0C)))
            SetPrimColor (lpPrim,
                          BUILD_COLOR (MAKE_RGB15 (0x14, 0x0A, 0x00), 0x06));
        else if (sameColor (color,
                            BUILD_COLOR (MAKE_RGB15 (0x14, 0x0A, 0x00), 0x06)))
            SetPrimColor (lpPrim,
                          BUILD_COLOR (MAKE_RGB15 (0x14, 0x00, 0x00), 0x04));
    }
    else
    {
        HELEMENT hDestruct;

        SetPrimType (lpPrim, NO_PRIM);
        // The ship's own element will not be drawn anymore but will remain
        // alive all through the glory explosion.
        ElementPtr->preprocess_func = NULL;

        // Spawn a separate glory explosion element.
        // XXX: Why? Why not keep using the ship's element?
        //   Is it because of conflicting state_flags, hit_points or
        //   mass_points?
        hDestruct = AllocElement ();
        if (hDestruct)
        {
            ELEMENT *DestructPtr;
            STARSHIP *StarShipPtr;

            GetElementStarShip (ElementPtr, &StarShipPtr);

            PutElement (hDestruct);
            LockElement (hDestruct, &DestructPtr);
            SetElementStarShip (DestructPtr, StarShipPtr);
            DestructPtr->hit_points = DestructPtr->mass_points = 0;
            DestructPtr->playerNr = NEUTRAL_PLAYER_NUM;
            DestructPtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID;
            DestructPtr->life_span = (NUM_EXPLOSION_FRAMES - 3) - 1;
            SetPrimType (&(GLOBAL (DisplayArray))[DestructPtr->PrimIndex],
                         STAMPFILL_PRIM);
            SetPrimColor (&(GLOBAL (DisplayArray))[DestructPtr->PrimIndex],
                          BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F));
            DestructPtr->current.image.farray =
                StarShipPtr->RaceDescPtr->ship_data.special;
            DestructPtr->current.image.frame =
                StarShipPtr->RaceDescPtr->ship_data.special[0];
            DestructPtr->current.location = ElementPtr->current.location;
            DestructPtr->preprocess_func = destruct_preprocess;
            DestructPtr->postprocess_func = NULL;
            DestructPtr->death_func = NULL;
            ZeroVelocityComponents (&DestructPtr->velocity);
            UnlockElement (hDestruct);
        }
    }
}
Ejemplo n.º 4
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);
        }
    }
}
Ejemplo n.º 5
0
void
spawn_ion_trail (ELEMENT *ElementPtr)
{
	STARSHIP *StarShipPtr;
	SHIP_INFO *ShipInfoPtr;
	HELEMENT hIonElement;

	assert (ElementPtr->state_flags & PLAYER_SHIP);

	// JMS: Get the pointers to element's owner ship.
	// They are needed to see if the ship's thrust is damaged
	GetElementStarShip (ElementPtr, &StarShipPtr);
	ShipInfoPtr = &StarShipPtr->RaceDescPtr->ship_info;

	hIonElement = AllocElement ();
	if (hIonElement)
	{
#define ION_LIFE 1
		COUNT angle;
		RECT r;
		ELEMENT *IonElementPtr;
		STARSHIP *StarShipPtr;

		GetElementStarShip (ElementPtr, &StarShipPtr);
		angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing) + HALF_CIRCLE;
		GetFrameRect (StarShipPtr->RaceDescPtr->ship_data.ship[0], &r);
		r.extent.height = DISPLAY_TO_WORLD (r.extent.height + r.corner.y);

		InsertElement (hIonElement, GetHeadElement ());
		LockElement (hIonElement, &IonElementPtr);
		IonElementPtr->playerNr = NEUTRAL_PLAYER_NUM;
		IonElementPtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID;
		IonElementPtr->thrust_wait = ION_LIFE;
		IonElementPtr->life_span = IonElementPtr->thrust_wait;
				// When the element "dies", in the death_func
				// 'cycle_ion_trail', it is given new life a number of
				// times, by setting life_span to thrust_wait.
		SetPrimType (&DisplayArray[IonElementPtr->PrimIndex], POINT_PRIM);
		// JMS: Damaged thruster emits differently colored particles
		if (ShipInfoPtr->damage_flags & DAMAGE_THRUST)
		{
			SetPrimColor (&DisplayArray[IonElementPtr->PrimIndex],
				      START_ION_COLOR_DAMAGED);
		}
		else
		{
			SetPrimColor (&DisplayArray[IonElementPtr->PrimIndex],
				      START_ION_COLOR);
		}

		IonElementPtr->colorCycleIndex = 0;
		IonElementPtr->current.image.frame =
				DecFrameIndex (stars_in_space);
		IonElementPtr->current.image.farray = &stars_in_space;
		IonElementPtr->current.location = ElementPtr->current.location;
		IonElementPtr->current.location.x +=
				(COORD)COSINE (angle, r.extent.height);
		IonElementPtr->current.location.y +=
				(COORD)SINE (angle, r.extent.height);
		IonElementPtr->death_func = cycle_ion_trail;

		SetElementStarShip (IonElementPtr, StarShipPtr);

		{
			/* normally done during preprocess, but because
			 * object is being inserted at head rather than
			 * appended after tail it may never get preprocessed.
			 */
			IonElementPtr->next = IonElementPtr->current;
			--IonElementPtr->life_span;
			IonElementPtr->state_flags |= PRE_PROCESS;
		}

		UnlockElement (hIonElement);
	}
}
Ejemplo n.º 6
0
void
AbandonShip (ELEMENT *ShipPtr, ELEMENT *TargetPtr,
		COUNT crew_loss)
{
	SIZE dx, dy;
	COUNT direction;
	RECT r;
	STARSHIP *StarShipPtr;
	HELEMENT hCrew;
	INTERSECT_CONTROL ShipIntersect;

	GetElementStarShip (ShipPtr, &StarShipPtr);
	if (StarShipPtr->RaceDescPtr->ship_info.ship_flags & CREW_IMMUNE)
		return;

	ShipIntersect = ShipPtr->IntersectControl;
	GetFrameRect (ShipIntersect.IntersectStamp.frame, &r);

	if ((direction = GetVelocityTravelAngle (
			&ShipPtr->velocity)) == FULL_CIRCLE)
		dx = dy = 0;
	else
	{
#define MORE_THAN_ENOUGH 100
		direction += HALF_CIRCLE;
		dx = COSINE (direction, MORE_THAN_ENOUGH);
		dy = SINE (direction, MORE_THAN_ENOUGH);
	}

	while (crew_loss-- && (hCrew = AllocElement ()))
	{
#define CREW_LIFE 300
		ELEMENT *CrewPtr;

		DeltaCrew (ShipPtr, -1);

		PutElement (hCrew);
		LockElement (hCrew, &CrewPtr);
		CrewPtr->playerNr = NEUTRAL_PLAYER_NUM;
		CrewPtr->hit_points = 1;
		CrewPtr->state_flags = APPEARING | FINITE_LIFE | CREW_OBJECT;
		CrewPtr->life_span = CREW_LIFE;
		SetPrimType (&DisplayArray[CrewPtr->PrimIndex], POINT_PRIM);
		SetPrimColor (&DisplayArray[CrewPtr->PrimIndex],
				BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x00), 0x02));
		CrewPtr->current.image.frame = DecFrameIndex (stars_in_space);
		CrewPtr->current.image.farray = &stars_in_space;
		CrewPtr->preprocess_func = crew_preprocess;
		CrewPtr->collision_func = crew_collision;

		SetElementStarShip (CrewPtr, StarShipPtr);

		GetElementStarShip (TargetPtr, &StarShipPtr);
		CrewPtr->hTarget = StarShipPtr->hShip;

		{
			SIZE w, h;
			INTERSECT_CONTROL CrewIntersect;

			ShipIntersect.IntersectStamp.origin =
					ShipPtr->IntersectControl.EndPoint;

			w = (SIZE)((COUNT)TFB_Random () % r.extent.width);
			h = (SIZE)((COUNT)TFB_Random () % r.extent.height);
			CrewIntersect.EndPoint = ShipIntersect.EndPoint;
			CrewIntersect.IntersectStamp.frame = DecFrameIndex (stars_in_space);
			if (dx == 0 && dy == 0)
			{
				CrewIntersect.EndPoint.x += w - (r.extent.width >> 1);
				CrewIntersect.EndPoint.y += h - (r.extent.height >> 1);
				CrewIntersect.IntersectStamp.origin =
						TargetPtr->IntersectControl.EndPoint;
			}
			else
			{
				if (dx == 0)
					CrewIntersect.EndPoint.x += w - (r.extent.width >> 1);
				else if (dx > 0)
					CrewIntersect.EndPoint.x += w;
				else
					CrewIntersect.EndPoint.x -= w;
				if (dy == 0)
					CrewIntersect.EndPoint.y += h - (r.extent.height >> 1);
				else if (dy > 0)
Ejemplo n.º 7
0
static void
spawn_crew (PELEMENT ElementPtr)
{
	if (ElementPtr->state_flags & PLAYER_SHIP)
	{
		HELEMENT hCrew;

		hCrew = AllocElement ();
		if (hCrew != 0)
		{
			ELEMENTPTR CrewPtr;

			LockElement (hCrew, &CrewPtr);
			CrewPtr->next.location = ElementPtr->next.location;
			CrewPtr->state_flags = APPEARING | NONSOLID | FINITE_LIFE
					| (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY));
			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)
		{
			ELEMENTPTR ObjPtr;

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

			if ((ObjPtr->state_flags & PLAYER_SHIP)
					&& (ObjPtr->state_flags & (GOOD_GUY | BAD_GUY)) !=
					(ElementPtr->state_flags & (GOOD_GUY | BAD_GUY))
					&& 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 /* 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);
		}
	}
}
Ejemplo n.º 8
0
static void
explosion_preprocess (ELEMENT *ShipPtr)
{
	BYTE i;

	i = (NUM_EXPLOSION_FRAMES * 3) - ShipPtr->life_span;
	switch (i)
	{
		case 25:
			ShipPtr->preprocess_func = NULL;
		case 0:
		case 1:
		case 2:
		case 20:
		case 21:
		case 22:
		case 23:
		case 24:
			i = 1;
			break;
		case 3:
		case 4:
		case 5:
		case 18:
		case 19:
			i = 2;
			break;
		case 15:
			SetPrimType (&DisplayArray[ShipPtr->PrimIndex], NO_PRIM);
			ShipPtr->state_flags |= CHANGING;
		default:
			i = 3;
			break;
	}

	do
	{
		HELEMENT hElement;

		hElement = AllocElement ();
		if (hElement)
		{
			COUNT angle, dist;
			DWORD rand_val;
			ELEMENT *ElementPtr;
			extern FRAME explosion[];

			PutElement (hElement);
			LockElement (hElement, &ElementPtr);
			ElementPtr->playerNr = NEUTRAL_PLAYER_NUM;
			ElementPtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID;
			ElementPtr->life_span = 9;
			SetPrimType (&DisplayArray[ElementPtr->PrimIndex], STAMP_PRIM);
			ElementPtr->current.image.farray = explosion;
			ElementPtr->current.image.frame = explosion[0];
			rand_val = TFB_Random ();
			angle = LOBYTE (HIWORD (rand_val));
			dist = DISPLAY_TO_WORLD (LOBYTE (LOWORD (rand_val)) % 8);
			if (HIBYTE (LOWORD (rand_val)) < 256 * 1 / 3)
				dist += DISPLAY_TO_WORLD (8);
			ElementPtr->current.location.x =
					ShipPtr->current.location.x + COSINE (angle, dist);
			ElementPtr->current.location.y =
					ShipPtr->current.location.y + SINE (angle, dist);
			ElementPtr->preprocess_func = animation_preprocess;
			rand_val = TFB_Random ();
			angle = LOBYTE (LOWORD (rand_val));
			dist = WORLD_TO_VELOCITY (
					DISPLAY_TO_WORLD (HIBYTE (LOWORD (rand_val)) % 5));
			SetVelocityComponents (&ElementPtr->velocity,
					COSINE (angle, dist), SINE (angle, dist));
			UnlockElement (hElement);
		}
	} while (--i);
}
Ejemplo n.º 9
0
static void
spawn_point_defense (ELEMENT *ElementPtr)
{
	STARSHIP *StarShipPtr;

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

		hDefense = AllocElement ();
		if (hDefense)
		{
			ELEMENT *DefensePtr;

			LockElement (hDefense, &DefensePtr);
			DefensePtr->playerNr = ElementPtr->playerNr;
			DefensePtr->state_flags = APPEARING | NONSOLID | FINITE_LIFE;
			DefensePtr->death_func = spawn_point_defense;

			GetElementStarShip (ElementPtr, &StarShipPtr);
			SetElementStarShip (DefensePtr, StarShipPtr);
			UnlockElement (hDefense);

			PutElement (hDefense);
		}
	}
	else
	{
		BOOLEAN PaidFor;
		HELEMENT hObject, hNextObject;
		ELEMENT *ShipPtr;

		PaidFor = FALSE;

		LockElement (StarShipPtr->hShip, &ShipPtr);
		for (hObject = GetTailElement (); hObject; hObject = hNextObject)
		{
			ELEMENT *ObjectPtr;

			LockElement (hObject, &ObjectPtr);
			hNextObject = GetPredElement (ObjectPtr);
			if (ObjectPtr != ShipPtr && CollidingElement (ObjectPtr) &&
					!OBJECT_CLOAKED (ObjectPtr))
			{
#define LASER_RANGE (UWORD)(100 << RESOLUTION_FACTOR) // JMS_GFX
				SIZE delta_x, delta_y;

				delta_x = ObjectPtr->next.location.x -
						ShipPtr->next.location.x;
				delta_y = ObjectPtr->next.location.y -
						ShipPtr->next.location.y;
				if (delta_x < 0)
					delta_x = -delta_x;
				if (delta_y < 0)
					delta_y = -delta_y;
				delta_x = WORLD_TO_DISPLAY (delta_x);
				delta_y = WORLD_TO_DISPLAY (delta_y);
				if ((UWORD)delta_x <= LASER_RANGE &&
						(UWORD)delta_y <= LASER_RANGE &&
						(UWORD)delta_x * (UWORD)delta_x +
						(UWORD)delta_y * (UWORD)delta_y <=
						LASER_RANGE * LASER_RANGE)
				{
					HELEMENT hPointDefense;
					LASER_BLOCK LaserBlock;

					if (!PaidFor)
					{
						if (!DeltaEnergy (ShipPtr, -SPECIAL_ENERGY_COST))
							break;

						ProcessSound (SetAbsSoundIndex (
										/* POINT_DEFENSE_LASER */
								StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ElementPtr);
						StarShipPtr->special_counter =
								StarShipPtr->RaceDescPtr->characteristics.special_wait;
						PaidFor = TRUE;
					}

					LaserBlock.cx = ShipPtr->next.location.x;
					LaserBlock.cy = ShipPtr->next.location.y;
					LaserBlock.face = 0;
					LaserBlock.ex = ObjectPtr->next.location.x
							- ShipPtr->next.location.x;
					LaserBlock.ey = ObjectPtr->next.location.y
							- ShipPtr->next.location.y;
					LaserBlock.sender = ShipPtr->playerNr;
					LaserBlock.flags = IGNORE_SIMILAR;
					LaserBlock.pixoffs = 0;
					LaserBlock.color = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F);
					hPointDefense = initialize_laser (&LaserBlock);
					if (hPointDefense)
					{
						ELEMENT *PDPtr;

						LockElement (hPointDefense, &PDPtr);
						SetElementStarShip (PDPtr, StarShipPtr);
						PDPtr->hTarget = 0;
						UnlockElement (hPointDefense);

						PutElement (hPointDefense);
					}
				}
			}
			UnlockElement (hObject);
		}
		UnlockElement (StarShipPtr->hShip);
	}
}
Ejemplo n.º 10
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);
}
Ejemplo n.º 11
0
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;
			}

			if (!antiCheat(ElementPtr1, FALSE)) {
				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) */
}
Ejemplo n.º 12
0
static void
confuse_preprocess (ELEMENT *ElementPtr)
{
	if (!(ElementPtr->state_flags & NONSOLID))
	{
		ElementPtr->next.image.frame = SetAbsFrameIndex (
				ElementPtr->current.image.frame,
				(GetFrameIndex (ElementPtr->current.image.frame) + 1) & 7);
		ElementPtr->state_flags |= CHANGING;
	}
	else if (ElementPtr->hTarget == 0)
	{
		ElementPtr->life_span = 0;
		ElementPtr->state_flags |= DISAPPEARING;
	}
	else
	{
		ELEMENT *eptr;

		LockElement (ElementPtr->hTarget, &eptr);

		ElementPtr->next.location = eptr->next.location;

		if (ElementPtr->turn_wait)
		{
			HELEMENT hEffect;
			STARSHIP *StarShipPtr;

			if (GetFrameIndex (ElementPtr->next.image.frame =
					IncFrameIndex (ElementPtr->current.image.frame)) == 0)
				ElementPtr->next.image.frame =
						SetRelFrameIndex (ElementPtr->next.image.frame, -8);

			GetElementStarShip (eptr, &StarShipPtr);
			StarShipPtr->ship_input_state =
					(StarShipPtr->ship_input_state
					& ~(LEFT | RIGHT | SPECIAL))
					| ElementPtr->turn_wait;

			hEffect = AllocElement ();
			if (hEffect)
			{
				LockElement (hEffect, &eptr);
				eptr->playerNr = ElementPtr->playerNr;
				eptr->state_flags = FINITE_LIFE | NONSOLID | CHANGING;
				eptr->life_span = 1;
				eptr->current = eptr->next = ElementPtr->next;
				eptr->preprocess_func = confuse_preprocess;
				SetPrimType (&(GLOBAL (DisplayArray))[eptr->PrimIndex],
						STAMP_PRIM);

				GetElementStarShip (ElementPtr, &StarShipPtr);
				SetElementStarShip (eptr, StarShipPtr);
				eptr->hTarget = ElementPtr->hTarget;

				UnlockElement (hEffect);
				PutElement (hEffect);
			}
		}

		UnlockElement (ElementPtr->hTarget);
	}
}
Ejemplo n.º 13
0
static void
pump_up_postprocess (ELEMENT *ElementPtr)
{
	if (ElementPtr->state_flags & APPEARING)
	{
		ZeroVelocityComponents (&ElementPtr->velocity);
	}
	else
	{
		HELEMENT hPumpUp;
		ELEMENT *EPtr;
		ELEMENT *ShipPtr;
		STARSHIP *StarShipPtr;

		GetElementStarShip (ElementPtr, &StarShipPtr);
		LockElement (StarShipPtr->hShip, &ShipPtr);
		initialize_pump_up (ShipPtr, &hPumpUp);
		DeltaEnergy (ShipPtr, 0);
		UnlockElement (StarShipPtr->hShip);

		LockElement (hPumpUp, &EPtr);

		EPtr->current.image.frame = ElementPtr->current.image.frame;
		EPtr->turn_wait = ElementPtr->turn_wait;
		EPtr->thrust_wait = ElementPtr->thrust_wait;
		if (--EPtr->thrust_wait == 0)
		{
			if ((EPtr->turn_wait & ~REVERSE_DIR) < MAX_PUMP - 1)
			{
				++EPtr->turn_wait;
				EPtr->current.image.frame = SetRelFrameIndex (
						EPtr->current.image.frame, NUM_PUMP_ANIMS);
				ProcessSound (SetAbsSoundIndex (
						StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 2),
						EPtr);
			}
			if (antiCheat(ElementPtr, FALSE)) {
				EPtr->thrust_wait = 5;
			} else {
				EPtr->thrust_wait = LEVEL_COUNTER;
			}
		}

		EPtr->mass_points = EPtr->hit_points =
				(PUMPUP_DAMAGE << (ElementPtr->turn_wait & ~REVERSE_DIR));
		SetElementStarShip (EPtr, StarShipPtr);

		if (EPtr->thrust_wait & 1)
		{
			COUNT frame_index;

			frame_index = GetFrameIndex (EPtr->current.image.frame);
			if (((EPtr->turn_wait & REVERSE_DIR)
					&& (frame_index % NUM_PUMP_ANIMS) != 0)
					|| (!(EPtr->turn_wait & REVERSE_DIR)
					&& ((frame_index + 1) % NUM_PUMP_ANIMS) == 0))
			{
				--frame_index;
				EPtr->turn_wait |= REVERSE_DIR;
			}
			else
			{
				++frame_index;
				EPtr->turn_wait &= ~REVERSE_DIR;
			}

			EPtr->current.image.frame = SetAbsFrameIndex (
					EPtr->current.image.frame, frame_index);
		}

		if (StarShipPtr->cur_status_flags & StarShipPtr->old_status_flags
				& WEAPON)
		{
			StarShipPtr->weapon_counter = WEAPON_WAIT;
		}
		else
		{
			COUNT angle;

			EPtr->life_span = PUMPUP_LIFE;
			EPtr->preprocess_func = pump_up_preprocess;
			EPtr->postprocess_func = 0;

			angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing);
			SetVelocityComponents (&EPtr->velocity,
					COSINE (angle, WORLD_TO_VELOCITY (RES_SCALE(PUMPUP_SPEED))),
					SINE (angle, WORLD_TO_VELOCITY (RES_SCALE(PUMPUP_SPEED))));

			ProcessSound (SetAbsSoundIndex (
					StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 3), EPtr);
		}

		UnlockElement (hPumpUp);
		PutElement (hPumpUp);

		SetPrimType (&(GLOBAL (DisplayArray))[ElementPtr->PrimIndex],
				NO_PRIM);
		ElementPtr->state_flags |= NONSOLID;
	}
}
Ejemplo n.º 14
0
static void
thraddash_preprocess (ELEMENT *ElementPtr)
{
	STARSHIP *StarShipPtr;

	GetElementStarShip (ElementPtr, &StarShipPtr);
	if (!(StarShipPtr->cur_status_flags & SPECIAL))
	{
		if ((StarShipPtr->old_status_flags & SPECIAL)
				&& (StarShipPtr->cur_status_flags & SHIP_AT_MAX_SPEED))
			StarShipPtr->cur_status_flags |= SHIP_BEYOND_MAX_SPEED;
	}
	else if (DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST))
	{
		COUNT max_thrust, thrust_increment;
		STATUS_FLAGS thrust_status;
		HELEMENT hTrailElement;

		if (!(StarShipPtr->old_status_flags & SPECIAL))
			StarShipPtr->cur_status_flags &=
					~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED);

		if (ElementPtr->thrust_wait == 0)
			++ElementPtr->thrust_wait;

		thrust_increment =
				StarShipPtr->RaceDescPtr->characteristics.thrust_increment;
		max_thrust = StarShipPtr->RaceDescPtr->characteristics.max_thrust;
		StarShipPtr->RaceDescPtr->characteristics.thrust_increment =
				SPECIAL_THRUST_INCREMENT;
		StarShipPtr->RaceDescPtr->characteristics.max_thrust =
				SPECIAL_MAX_THRUST;

		thrust_status = inertial_thrust (ElementPtr);
		StarShipPtr->cur_status_flags &=
				~(SHIP_AT_MAX_SPEED
				| SHIP_BEYOND_MAX_SPEED
				| SHIP_IN_GRAVITY_WELL);
		StarShipPtr->cur_status_flags |= thrust_status;

		StarShipPtr->RaceDescPtr->characteristics.thrust_increment =
				thrust_increment;
		StarShipPtr->RaceDescPtr->characteristics.max_thrust = max_thrust;

		{
			MISSILE_BLOCK MissileBlock;

			MissileBlock.cx = ElementPtr->next.location.x;
			MissileBlock.cy = ElementPtr->next.location.y;
			MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.special;
			MissileBlock.face = 0;
			MissileBlock.index = GetFrameCount (
					StarShipPtr->RaceDescPtr->ship_data.special[0]
					) - 1;
			MissileBlock.sender = ElementPtr->playerNr;
			MissileBlock.flags = IGNORE_SIMILAR;
			MissileBlock.pixoffs = 0;
			MissileBlock.speed = 0;
			MissileBlock.hit_points = NAPALM_HITS;
			MissileBlock.damage = NAPALM_DAMAGE;
			MissileBlock.life = NAPALM_LIFE;
			MissileBlock.preprocess_func = flame_napalm_preprocess;
			MissileBlock.blast_offs = NAPALM_OFFSET;

			hTrailElement = initialize_missile (&MissileBlock);
			if (hTrailElement)
			{
				ELEMENT *TrailElementPtr;

				LockElement (hTrailElement, &TrailElementPtr);
				SetElementStarShip (TrailElementPtr, StarShipPtr);
				TrailElementPtr->hTarget = 0;

				/* turn_wait is abused here to store the speed of the decay
				 * animation */
				TrailElementPtr->turn_wait = NAPALM_DECAY_RATE;

				TrailElementPtr->state_flags |= NONSOLID;
				SetPrimType (
						&(GLOBAL (DisplayArray))[TrailElementPtr->PrimIndex],
						NO_PRIM
						);

						/* normally done during preprocess, but because
						 * object is being inserted at head rather than
						 * appended after tail it may never get preprocessed.
						 */
				TrailElementPtr->next = TrailElementPtr->current;
				TrailElementPtr->state_flags |= PRE_PROCESS;

				UnlockElement (hTrailElement);
				InsertElement (hTrailElement, GetHeadElement ());

				ProcessSound (SetAbsSoundIndex (
						StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ElementPtr);
			}
		}
	}
}
Ejemplo n.º 15
0
static void
new_pkunk (ELEMENT *ElementPtr)
{
	STARSHIP *StarShipPtr;

	GetElementStarShip (ElementPtr, &StarShipPtr);
	if (!(ElementPtr->state_flags & PLAYER_SHIP))
	{
		ELEMENT *ShipPtr;

		LockElement (StarShipPtr->hShip, &ShipPtr);
		ShipPtr->death_func = new_pkunk;
		UnlockElement (StarShipPtr->hShip);
	}
	else
	{
		ElementPtr->state_flags = APPEARING | PLAYER_SHIP | IGNORE_SIMILAR;
		ElementPtr->mass_points = SHIP_MASS;
		ElementPtr->preprocess_func = StarShipPtr->RaceDescPtr->preprocess_func;
		ElementPtr->postprocess_func = StarShipPtr->RaceDescPtr->postprocess_func;
		ElementPtr->death_func =
				(void (*) (ELEMENT *ElementPtr))
						StarShipPtr->RaceDescPtr->init_weapon_func;
		StarShipPtr->RaceDescPtr->preprocess_func = pkunk_preprocess;
		StarShipPtr->RaceDescPtr->postprocess_func = pkunk_postprocess;
		StarShipPtr->RaceDescPtr->init_weapon_func = initialize_bug_missile;
		StarShipPtr->RaceDescPtr->ship_info.crew_level = MAX_CREW;
		StarShipPtr->RaceDescPtr->ship_info.energy_level = MAX_ENERGY;
					/* fix vux impairment */
		StarShipPtr->RaceDescPtr->characteristics.max_thrust = MAX_THRUST;
		StarShipPtr->RaceDescPtr->characteristics.thrust_increment = THRUST_INCREMENT;
		StarShipPtr->RaceDescPtr->characteristics.turn_wait = TURN_WAIT;
		StarShipPtr->RaceDescPtr->characteristics.thrust_wait = THRUST_WAIT;
		StarShipPtr->RaceDescPtr->characteristics.special_wait = 0;

		StarShipPtr->ship_input_state = 0;
		StarShipPtr->cur_status_flags = 0;
		StarShipPtr->old_status_flags = 0;
		StarShipPtr->energy_counter = 0;
		StarShipPtr->weapon_counter = 0;
		StarShipPtr->special_counter = 0;
		ElementPtr->crew_level = 0;
		ElementPtr->turn_wait = 0;
		ElementPtr->thrust_wait = 0;
		ElementPtr->life_span = NORMAL_LIFE;

		StarShipPtr->ShipFacing = NORMALIZE_FACING (TFB_Random ());
		ElementPtr->current.image.farray = StarShipPtr->RaceDescPtr->ship_data.ship;
		ElementPtr->current.image.frame =
				SetAbsFrameIndex (StarShipPtr->RaceDescPtr->ship_data.ship[0],
				StarShipPtr->ShipFacing);
		SetPrimType (&(GLOBAL (DisplayArray))[
				ElementPtr->PrimIndex
				], STAMP_PRIM);

		do
		{
			ElementPtr->current.location.x =
					WRAP_X (DISPLAY_ALIGN_X (TFB_Random ()));
			ElementPtr->current.location.y =
					WRAP_Y (DISPLAY_ALIGN_Y (TFB_Random ()));
		} while (CalculateGravity (ElementPtr)
				|| TimeSpaceMatterConflict (ElementPtr));

		ElementPtr->hTarget = StarShipPtr->hShip;
	}
}
Ejemplo n.º 16
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);
	}
}
Ejemplo n.º 17
0
static void
phoenix_transition (ELEMENT *ElementPtr)
{
	HELEMENT hShipImage;
	ELEMENT *ShipImagePtr;
	STARSHIP *StarShipPtr;
	
	GetElementStarShip (ElementPtr, &StarShipPtr);
	LockElement (StarShipPtr->hShip, &ShipImagePtr);

	if (!(ShipImagePtr->state_flags & NONSOLID))
	{
		ElementPtr->preprocess_func = NULL;
	}
	else if ((hShipImage = AllocElement ()))
	{
#define TRANSITION_SPEED DISPLAY_TO_WORLD (20)
		COUNT angle;

		PutElement (hShipImage);

		LockElement (hShipImage, &ShipImagePtr);
		ShipImagePtr->playerNr = NEUTRAL_PLAYER_NUM;
		ShipImagePtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID;
		ShipImagePtr->life_span = TRANSITION_LIFE;
		SetPrimType (&(GLOBAL (DisplayArray))[ShipImagePtr->PrimIndex],
				STAMPFILL_PRIM);
		SetPrimColor (
				&(GLOBAL (DisplayArray))[ShipImagePtr->PrimIndex],
				START_PHOENIX_COLOR);
		ShipImagePtr->colorCycleIndex = 0;
		ShipImagePtr->current.image = ElementPtr->current.image;
		ShipImagePtr->current.location = ElementPtr->current.location;
		if (!(ElementPtr->state_flags & PLAYER_SHIP))
		{
			angle = ElementPtr->mass_points;

			ShipImagePtr->current.location.x +=
					COSINE (angle, TRANSITION_SPEED);
			ShipImagePtr->current.location.y +=
					SINE (angle, TRANSITION_SPEED);
			ElementPtr->preprocess_func = NULL;
		}
		else
		{
			angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing);

			ShipImagePtr->current.location.x -=
					COSINE (angle, TRANSITION_SPEED)
					* (ElementPtr->life_span - 1);
			ShipImagePtr->current.location.y -=
					SINE (angle, TRANSITION_SPEED)
					* (ElementPtr->life_span - 1);

			ShipImagePtr->current.location.x =
					WRAP_X (ShipImagePtr->current.location.x);
			ShipImagePtr->current.location.y =
					WRAP_Y (ShipImagePtr->current.location.y);
		}

		ShipImagePtr->mass_points = (BYTE)angle;
		ShipImagePtr->preprocess_func = phoenix_transition;
		ShipImagePtr->death_func = spawn_phoenix_trail;
		SetElementStarShip (ShipImagePtr, StarShipPtr);

		UnlockElement (hShipImage);
	}

	UnlockElement (StarShipPtr->hShip);
}
Ejemplo n.º 18
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);
}
Ejemplo n.º 19
0
static void
pkunk_preprocess (ELEMENT *ElementPtr)
{
	STARSHIP *StarShipPtr;

	GetElementStarShip (ElementPtr, &StarShipPtr);
	if (ElementPtr->state_flags & APPEARING)
	{
		HELEMENT hPhoenix = 0;

		if ((BYTE)TFB_Random () & 1)
			hPhoenix = AllocElement ();

		if (hPhoenix)
		{
			ELEMENT *PhoenixPtr;

			LockElement (hPhoenix, &PhoenixPtr);
			PhoenixPtr->playerNr = ElementPtr->playerNr;
			PhoenixPtr->state_flags = FINITE_LIFE | NONSOLID | IGNORE_SIMILAR;
			PhoenixPtr->life_span = 1;

			PhoenixPtr->death_func = intercept_pkunk_death;

			SetElementStarShip (PhoenixPtr, StarShipPtr);

			UnlockElement (hPhoenix);
			InsertElement (hPhoenix, GetHeadElement ());
		}
		StarShipPtr->RaceDescPtr->data = (intptr_t) hPhoenix;

		if (ElementPtr->hTarget == 0)
			StarShipPtr->RaceDescPtr->preprocess_func = 0;
		else
		{
			COUNT angle, facing;

			ProcessSound (SetAbsSoundIndex (
					StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1
					), ElementPtr);

			ElementPtr->life_span = PHOENIX_LIFE;
			SetPrimType (&(GLOBAL (DisplayArray))[ElementPtr->PrimIndex],
					NO_PRIM);
			ElementPtr->state_flags |= NONSOLID | FINITE_LIFE | CHANGING;

			facing = StarShipPtr->ShipFacing;
			for (angle = OCTANT; angle < FULL_CIRCLE; angle += QUADRANT)
			{
				StarShipPtr->ShipFacing = NORMALIZE_FACING (
						facing + ANGLE_TO_FACING (angle)
						);
				phoenix_transition (ElementPtr);
			}
			StarShipPtr->ShipFacing = facing;
		}
	}

	if (StarShipPtr->RaceDescPtr->preprocess_func)
	{
		StarShipPtr->cur_status_flags &=
				~(LEFT | RIGHT | THRUST | WEAPON | SPECIAL);

		if (ElementPtr->life_span == NORMAL_LIFE)
		{
			ElementPtr->current.image.frame =
					ElementPtr->next.image.frame =
					SetEquFrameIndex (
					ElementPtr->current.image.farray[0],
					ElementPtr->current.image.frame);
			SetPrimType (&(GLOBAL (DisplayArray))[ElementPtr->PrimIndex],
					STAMP_PRIM);
			InitIntersectStartPoint (ElementPtr);
			InitIntersectEndPoint (ElementPtr);
			InitIntersectFrame (ElementPtr);
			ZeroVelocityComponents (&ElementPtr->velocity);
			ElementPtr->state_flags &= ~(NONSOLID | FINITE_LIFE);
			ElementPtr->state_flags |= CHANGING;

			StarShipPtr->RaceDescPtr->preprocess_func = 0;
		}
	}
}
Ejemplo n.º 20
0
// Preprocess function for spawning a ship into or out of battle.
// Used when a new ship warps in, or a ship escapes by warping out, but not
// when a Pkunk ship is reborn.
void
ship_transition (ELEMENT *ElementPtr)
{
	if (ElementPtr->state_flags & PLAYER_SHIP)
	{
		if (ElementPtr->state_flags & APPEARING)
		{
			ElementPtr->life_span = HYPERJUMP_LIFE;
			ElementPtr->preprocess_func = ship_transition;
			ElementPtr->postprocess_func = NULL;
			SetPrimType (&DisplayArray[ElementPtr->PrimIndex], NO_PRIM);
			ElementPtr->state_flags |= NONSOLID | FINITE_LIFE | CHANGING;
		}
		else if (ElementPtr->life_span < HYPERJUMP_LIFE)
		{
			if (ElementPtr->life_span == NORMAL_LIFE
					&& ElementPtr->crew_level)
			{
				ElementPtr->current.image.frame =
						ElementPtr->next.image.frame =
						SetEquFrameIndex (
						ElementPtr->current.image.farray[0],
						ElementPtr->current.image.frame);
				SetPrimType (&DisplayArray[ElementPtr->PrimIndex], STAMP_PRIM);
				InitIntersectStartPoint (ElementPtr);
				InitIntersectEndPoint (ElementPtr);
				InitIntersectFrame (ElementPtr);
				ZeroVelocityComponents (&ElementPtr->velocity);
				ElementPtr->state_flags &= ~(NONSOLID | FINITE_LIFE);
				ElementPtr->state_flags |= CHANGING;

				ElementPtr->preprocess_func = ship_preprocess;
				ElementPtr->postprocess_func = ship_postprocess;
			}

			return;
		}
	}

	{
		HELEMENT hShipImage;
		ELEMENT *ShipImagePtr;
		STARSHIP *StarShipPtr;
		
		GetElementStarShip (ElementPtr, &StarShipPtr);
		LockElement (StarShipPtr->hShip, &ShipImagePtr);

		if (!(ShipImagePtr->state_flags & NONSOLID))
		{
			ElementPtr->preprocess_func = NULL;
		}
		else if ((hShipImage = AllocElement ()))
		{
#define TRANSITION_SPEED DISPLAY_TO_WORLD (40 << RESOLUTION_FACTOR) // JMS_GFX
#define TRANSITION_LIFE 1
			COUNT angle;

			PutElement (hShipImage);

			angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing);

			LockElement (hShipImage, &ShipImagePtr);
			ShipImagePtr->playerNr = NEUTRAL_PLAYER_NUM;
			ShipImagePtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID;
			ShipImagePtr->thrust_wait = TRANSITION_LIFE;
			ShipImagePtr->life_span = ShipImagePtr->thrust_wait;
					// When the element "dies", in the death_func
					// 'cycle_ion_trail', it is given new life a number of
					// times, by setting life_span to thrust_wait.
			SetPrimType (&DisplayArray[ShipImagePtr->PrimIndex],
					STAMPFILL_PRIM);
			SetPrimColor (&DisplayArray[ShipImagePtr->PrimIndex],
					START_ION_COLOR);
			ShipImagePtr->colorCycleIndex = 0;
			ShipImagePtr->current.image = ElementPtr->current.image;
			ShipImagePtr->current.location = ElementPtr->current.location;
			if (!(ElementPtr->state_flags & PLAYER_SHIP))
			{
				ShipImagePtr->current.location.x +=
						COSINE (angle, TRANSITION_SPEED);
				ShipImagePtr->current.location.y +=
						SINE (angle, TRANSITION_SPEED);
				ElementPtr->preprocess_func = NULL;
			}
			else if (ElementPtr->crew_level)
			{
				ShipImagePtr->current.location.x -=
						COSINE (angle, TRANSITION_SPEED)
						* (ElementPtr->life_span - 1);
				ShipImagePtr->current.location.y -=
						SINE (angle, TRANSITION_SPEED)
						* (ElementPtr->life_span - 1);

				ShipImagePtr->current.location.x =
						WRAP_X (ShipImagePtr->current.location.x);
				ShipImagePtr->current.location.y =
						WRAP_Y (ShipImagePtr->current.location.y);
			}
			ShipImagePtr->preprocess_func = ship_transition;
			ShipImagePtr->death_func = cycle_ion_trail;
			SetElementStarShip (ShipImagePtr, StarShipPtr);

			UnlockElement (hShipImage);
		}

		UnlockElement (StarShipPtr->hShip);
	}
}
Ejemplo n.º 21
0
void
spawn_asteroid (ELEMENT *ElementPtr)
{
	HELEMENT hAsteroidElement;

	if ((hAsteroidElement = AllocElement ()) == 0)
	{
		if (ElementPtr != 0)
		{
			ElementPtr->state_flags &= ~DISAPPEARING;
			SetPrimType (&DisplayArray[ElementPtr->PrimIndex], NO_PRIM);
			ElementPtr->life_span = 1;
		}
	}
	else
	{
		ELEMENT *AsteroidElementPtr;
		COUNT val;

		LockElement (hAsteroidElement, &AsteroidElementPtr);
		AsteroidElementPtr->playerNr = NEUTRAL_PLAYER_NUM;
		AsteroidElementPtr->hit_points = 1;
		AsteroidElementPtr->mass_points = 3;
		AsteroidElementPtr->state_flags = APPEARING;
		AsteroidElementPtr->life_span = NORMAL_LIFE;
		SetPrimType (&DisplayArray[AsteroidElementPtr->PrimIndex], STAMP_PRIM);
		if ((val = (COUNT)TFB_Random ()) & (1 << 0))
		{
			if (!(val & (1 << 1)))
				AsteroidElementPtr->current.location.x = 0;
			else
				AsteroidElementPtr->current.location.x = LOG_SPACE_WIDTH;
			AsteroidElementPtr->current.location.y =
					WRAP_Y (DISPLAY_ALIGN_Y (TFB_Random ()));
		}
		else
		{
			AsteroidElementPtr->current.location.x =
					WRAP_X (DISPLAY_ALIGN_X (TFB_Random ()));
			if (!(val & (1 << 1)))
				AsteroidElementPtr->current.location.y = 0;
			else
				AsteroidElementPtr->current.location.y = LOG_SPACE_HEIGHT;
		}

		{
			// Using these temporary variables because the execution order
			// of function arguments may vary per system, which may break
			// synchronisation on network games.
			SIZE magnitude =
					DISPLAY_TO_WORLD (((SIZE)TFB_Random () & 7) + 4);
			COUNT facing = (COUNT)TFB_Random ();
			SetVelocityVector (&AsteroidElementPtr->velocity, magnitude,
					facing);
		}
		AsteroidElementPtr->current.image.farray = asteroid;
		AsteroidElementPtr->current.image.frame =
				SetAbsFrameIndex (asteroid[0],
				NORMALIZE_FACING (TFB_Random ()));
		AsteroidElementPtr->turn_wait =
				AsteroidElementPtr->thrust_wait =
				(BYTE)TFB_Random () & (BYTE)((1 << 2) - 1);
		AsteroidElementPtr->thrust_wait |=
				(BYTE)TFB_Random () & (BYTE)(1 << 7);
		AsteroidElementPtr->preprocess_func = asteroid_preprocess;
		AsteroidElementPtr->death_func = spawn_rubble;
		AsteroidElementPtr->collision_func = collision;

		AsteroidElementPtr->triggers_teleport_safety = TRUE;

		UnlockElement (hAsteroidElement);

		PutElement (hAsteroidElement);
	}
}