1755 lines
43 KiB
C
1755 lines
43 KiB
C
//Copyright Paul Reiche, Fred Ford. 1992-2002
|
|
|
|
/*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include "hyper.h"
|
|
|
|
#include "build.h"
|
|
#include "collide.h"
|
|
#include "colors.h"
|
|
#include "controls.h"
|
|
#include "gameopt.h"
|
|
#include "menustat.h"
|
|
// for DrawMenuStateStrings()
|
|
#include "encount.h"
|
|
#include "ship.h"
|
|
#include "shipcont.h"
|
|
#include "process.h"
|
|
#include "globdata.h"
|
|
#include "sis.h"
|
|
#include "units.h"
|
|
#include "init.h"
|
|
#include "nameref.h"
|
|
#include "resinst.h"
|
|
#include "setup.h"
|
|
#include "sounds.h"
|
|
#include "options.h"
|
|
#include "libs/graphics/gfx_common.h"
|
|
#include "libs/mathlib.h"
|
|
|
|
|
|
#define XOFFS ((RADAR_SCAN_WIDTH + (UNIT_SCREEN_WIDTH << 2)) >> 1)
|
|
#define YOFFS ((RADAR_SCAN_HEIGHT + (UNIT_SCREEN_HEIGHT << 2)) >> 1)
|
|
|
|
static FRAME hyperstars[3];
|
|
static COLORMAP hypercmaps[2];
|
|
static BYTE fuel_ticks;
|
|
static COUNT hyper_dx, hyper_dy, hyper_extra;
|
|
|
|
// HyperspaceMenu() items
|
|
enum HyperMenuItems
|
|
{
|
|
// XXX: Must match the enum in menustat.h
|
|
STARMAP = 1,
|
|
EQUIP_DEVICE,
|
|
CARGO,
|
|
ROSTER,
|
|
GAME_MENU,
|
|
NAVIGATION,
|
|
};
|
|
|
|
|
|
void
|
|
MoveSIS (SIZE *pdx, SIZE *pdy)
|
|
{
|
|
SIZE new_dx, new_dy;
|
|
|
|
new_dx = *pdx;
|
|
GLOBAL_SIS (log_x) -= new_dx;
|
|
if (GLOBAL_SIS (log_x) < 0)
|
|
{
|
|
new_dx += (SIZE)GLOBAL_SIS (log_x);
|
|
GLOBAL_SIS (log_x) = 0;
|
|
}
|
|
else if (GLOBAL_SIS (log_x) > MAX_X_LOGICAL)
|
|
{
|
|
new_dx += (SIZE)(GLOBAL_SIS (log_x) - MAX_X_LOGICAL);
|
|
GLOBAL_SIS (log_x) = MAX_X_LOGICAL;
|
|
}
|
|
|
|
new_dy = *pdy;
|
|
GLOBAL_SIS (log_y) -= new_dy;
|
|
if (GLOBAL_SIS (log_y) < 0)
|
|
{
|
|
new_dy += (SIZE)GLOBAL_SIS (log_y);
|
|
GLOBAL_SIS (log_y) = 0;
|
|
}
|
|
else if (GLOBAL_SIS (log_y) > MAX_Y_LOGICAL)
|
|
{
|
|
new_dy += (SIZE)(GLOBAL_SIS (log_y) - MAX_Y_LOGICAL);
|
|
GLOBAL_SIS (log_y) = MAX_Y_LOGICAL;
|
|
}
|
|
|
|
if (new_dx != *pdx || new_dy != *pdy)
|
|
{
|
|
HELEMENT hElement, hNextElement;
|
|
|
|
*pdx = new_dx;
|
|
*pdy = new_dy;
|
|
|
|
for (hElement = GetTailElement ();
|
|
hElement != 0; hElement = hNextElement)
|
|
{
|
|
ELEMENT *ElementPtr;
|
|
|
|
LockElement (hElement, &ElementPtr);
|
|
|
|
if (!(ElementPtr->state_flags & PLAYER_SHIP))
|
|
hNextElement = GetPredElement (ElementPtr);
|
|
else
|
|
{
|
|
ElementPtr->next.location.x = (LOG_SPACE_WIDTH >> 1) - new_dx;
|
|
ElementPtr->next.location.y = (LOG_SPACE_HEIGHT >> 1) - new_dy;
|
|
hNextElement = 0;
|
|
}
|
|
|
|
UnlockElement (hElement);
|
|
}
|
|
}
|
|
|
|
if (GLOBAL_SIS (FuelOnBoard) && GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1)
|
|
{
|
|
COUNT cur_fuel_ticks;
|
|
COUNT hyper_dist;
|
|
DWORD adj_dx, adj_dy;
|
|
|
|
if (new_dx < 0)
|
|
new_dx = -new_dx;
|
|
hyper_dx += new_dx;
|
|
if (new_dy < 0)
|
|
new_dy = -new_dy;
|
|
hyper_dy += new_dy;
|
|
|
|
/* These macros are also used in the fuel estimate on the starmap. */
|
|
adj_dx = LOGX_TO_UNIVERSE(16 * hyper_dx);
|
|
adj_dy = MAX_Y_UNIVERSE - LOGY_TO_UNIVERSE(16 * hyper_dy);
|
|
|
|
hyper_dist = square_root (adj_dx * adj_dx + adj_dy * adj_dy)
|
|
+ hyper_extra;
|
|
cur_fuel_ticks = hyper_dist >> 4;
|
|
|
|
if (cur_fuel_ticks > (COUNT)fuel_ticks)
|
|
{
|
|
#ifndef TESTING
|
|
DeltaSISGauges (0, fuel_ticks - cur_fuel_ticks, 0);
|
|
#endif /* TESTING */
|
|
if (cur_fuel_ticks > 0x00FF)
|
|
{
|
|
hyper_dx = 0;
|
|
hyper_extra = hyper_dist & ((1 << 4) - 1);
|
|
hyper_dy = 0;
|
|
cur_fuel_ticks = 0;
|
|
}
|
|
|
|
fuel_ticks = (BYTE)cur_fuel_ticks;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
check_hyperspace_encounter (void)
|
|
{
|
|
BYTE Type;
|
|
POINT universe;
|
|
HFLEETINFO hStarShip, hNextShip;
|
|
COUNT EncounterPercent[] =
|
|
{
|
|
RACE_HYPERSPACE_PERCENT
|
|
};
|
|
|
|
universe.x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x));
|
|
universe.y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y));
|
|
for (hStarShip = GetHeadLink (&GLOBAL (avail_race_q)), Type = 0;
|
|
hStarShip && (GLOBAL (CurrentActivity) & IN_BATTLE);
|
|
hStarShip = hNextShip, ++Type)
|
|
{
|
|
COUNT encounter_radius;
|
|
FLEET_INFO *FleetPtr;
|
|
|
|
FleetPtr = LockFleetInfo (&GLOBAL (avail_race_q), hStarShip);
|
|
hNextShip = _GetSuccLink (FleetPtr);
|
|
|
|
encounter_radius = FleetPtr->actual_strength;
|
|
if (encounter_radius)
|
|
{
|
|
BYTE encounter_flags;
|
|
SIZE dx, dy;
|
|
COUNT percent;
|
|
HENCOUNTER hEncounter;
|
|
ENCOUNTER *EncounterPtr;
|
|
|
|
encounter_flags = 0;
|
|
percent = EncounterPercent[Type];
|
|
|
|
if (encounter_radius != INFINITE_RADIUS)
|
|
{
|
|
encounter_radius =
|
|
(encounter_radius * SPHERE_RADIUS_INCREMENT) >> 1;
|
|
}
|
|
else /* encounter_radius == infinity */
|
|
{
|
|
HENCOUNTER hNextEncounter;
|
|
|
|
encounter_radius = (MAX_X_UNIVERSE + 1) << 1;
|
|
if (Type == SLYLANDRO_SHIP)
|
|
{
|
|
encounter_flags = ONE_SHOT_ENCOUNTER;
|
|
if (!GET_GAME_STATE (STARBASE_AVAILABLE))
|
|
percent = 100;
|
|
else
|
|
percent *= GET_GAME_STATE (SLYLANDRO_MULTIPLIER);
|
|
}
|
|
else if (Type == MELNORME_SHIP
|
|
&& (GLOBAL_SIS (FuelOnBoard) == 0
|
|
|| GET_GAME_STATE (USED_BROADCASTER))
|
|
&& GET_GAME_STATE (MELNORME_ANGER) < 3)
|
|
{
|
|
if (!GET_GAME_STATE (USED_BROADCASTER))
|
|
percent = 30;
|
|
else
|
|
percent = 100;
|
|
encounter_flags = ONE_SHOT_ENCOUNTER;
|
|
}
|
|
|
|
|
|
for (hEncounter = GetHeadEncounter ();
|
|
hEncounter; hEncounter = hNextEncounter)
|
|
{
|
|
LockEncounter (hEncounter, &EncounterPtr);
|
|
hNextEncounter = GetSuccEncounter (EncounterPtr);
|
|
if (EncounterPtr->SD.Type == Type)
|
|
{
|
|
percent = 0;
|
|
hNextEncounter = 0;
|
|
}
|
|
UnlockEncounter (hEncounter);
|
|
}
|
|
|
|
|
|
if (percent == 100 && Type == MELNORME_SHIP)
|
|
{
|
|
SET_GAME_STATE (BROADCASTER_RESPONSE, 1);
|
|
}
|
|
}
|
|
|
|
dx = universe.x - FleetPtr->loc.x;
|
|
if (dx < 0)
|
|
dx = -dx;
|
|
dy = universe.y - FleetPtr->loc.y;
|
|
if (dy < 0)
|
|
dy = -dy;
|
|
if ((COUNT)dx < encounter_radius
|
|
&& (COUNT)dy < encounter_radius
|
|
&& (DWORD)dx * dx + (DWORD)dy * dy <
|
|
(DWORD)encounter_radius * encounter_radius
|
|
&& ((COUNT)TFB_Random () % 100) < percent)
|
|
{
|
|
// Ship spawned for encounter.
|
|
hEncounter = AllocEncounter ();
|
|
if (hEncounter)
|
|
{
|
|
LockEncounter (hEncounter, &EncounterPtr);
|
|
memset (EncounterPtr, 0, sizeof (*EncounterPtr));
|
|
EncounterPtr->origin = FleetPtr->loc;
|
|
EncounterPtr->radius = encounter_radius;
|
|
EncounterPtr->SD.Index = encounter_flags;
|
|
EncounterPtr->SD.Type = Type;
|
|
UnlockEncounter (hEncounter);
|
|
|
|
PutEncounter (hEncounter);
|
|
}
|
|
}
|
|
}
|
|
|
|
UnlockFleetInfo (&GLOBAL (avail_race_q), hStarShip);
|
|
}
|
|
|
|
SET_GAME_STATE (USED_BROADCASTER, 0);
|
|
}
|
|
|
|
void
|
|
FreeHyperData (void)
|
|
{
|
|
DestroyDrawable (ReleaseDrawable (hyperstars[0]));
|
|
hyperstars[0] = 0;
|
|
DestroyDrawable (ReleaseDrawable (hyperstars[1]));
|
|
hyperstars[1] = 0;
|
|
DestroyDrawable (ReleaseDrawable (hyperstars[2]));
|
|
hyperstars[2] = 0;
|
|
|
|
DestroyColorMap (ReleaseColorMap (hypercmaps[0]));
|
|
hypercmaps[0] = 0;
|
|
DestroyColorMap (ReleaseColorMap (hypercmaps[1]));
|
|
hypercmaps[1] = 0;
|
|
}
|
|
|
|
static void
|
|
LoadHyperData (void)
|
|
{
|
|
if (hyperstars[0] == 0)
|
|
{
|
|
hyperstars[0] = CaptureDrawable (
|
|
LoadGraphic (AMBIENT_MASK_PMAP_ANIM));
|
|
hyperstars[1] = CaptureDrawable (
|
|
LoadGraphic (HYPERSTARS_MASK_PMAP_ANIM));
|
|
hypercmaps[0] = CaptureColorMap (LoadColorMap (HYPER_COLOR_TAB));
|
|
|
|
hyperstars[2] = CaptureDrawable (
|
|
LoadGraphic (ARISPACE_MASK_PMAP_ANIM));
|
|
hypercmaps[1] = CaptureColorMap (LoadColorMap (ARISPACE_COLOR_TAB));
|
|
}
|
|
}
|
|
|
|
BOOLEAN
|
|
LoadHyperspace (void)
|
|
{
|
|
hyper_dx = 0;
|
|
hyper_dy = 0;
|
|
hyper_extra = 0;
|
|
fuel_ticks = 1;
|
|
|
|
GLOBAL (ShipStamp.origin.x) = -MAX_X_UNIVERSE;
|
|
GLOBAL (ShipStamp.origin.y) = -MAX_Y_UNIVERSE;
|
|
|
|
LoadHyperData ();
|
|
{
|
|
FRAME F;
|
|
|
|
F = hyperstars[0];
|
|
hyperstars[0] = stars_in_space;
|
|
stars_in_space = F;
|
|
}
|
|
|
|
if (!(LastActivity & CHECK_LOAD))
|
|
RepairSISBorder ();
|
|
else
|
|
{
|
|
if (LOBYTE (LastActivity) == 0)
|
|
{
|
|
DrawSISFrame ();
|
|
}
|
|
else
|
|
{
|
|
ClearSISRect (DRAW_SIS_DISPLAY);
|
|
RepairSISBorder ();
|
|
}
|
|
}
|
|
DrawSISMessage (NULL);
|
|
|
|
SetContext (RadarContext);
|
|
SetContextBackGroundColor (
|
|
BUILD_COLOR (MAKE_RGB15 (0x00, 0x0E, 0x00), 0x6C));
|
|
|
|
SetContext (SpaceContext);
|
|
if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1)
|
|
{
|
|
SetContextBackGroundColor (
|
|
BUILD_COLOR (MAKE_RGB15 (0x07, 0x00, 0x00), 0x2F));
|
|
SetColorMap (GetColorMapAddress (hypercmaps[0]));
|
|
}
|
|
else
|
|
{
|
|
SetContextBackGroundColor (
|
|
BUILD_COLOR (MAKE_RGB15 (0x00, 0x1A, 0x00), 0x2F));
|
|
SetColorMap (GetColorMapAddress (hypercmaps[1]));
|
|
SET_GAME_STATE (USED_BROADCASTER, 0);
|
|
SET_GAME_STATE (BROADCASTER_RESPONSE, 0);
|
|
}
|
|
// ClearDrawable ();
|
|
|
|
ClearSISRect (CLEAR_SIS_RADAR);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOLEAN
|
|
FreeHyperspace (void)
|
|
{
|
|
{
|
|
FRAME F;
|
|
|
|
F = hyperstars[0];
|
|
hyperstars[0] = stars_in_space;
|
|
stars_in_space = F;
|
|
}
|
|
// FreeHyperData ();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
ElementToUniverse (ELEMENT *ElementPtr, POINT *pPt)
|
|
{
|
|
SDWORD log_x, log_y;
|
|
|
|
log_x = GLOBAL_SIS (log_x)
|
|
+ (ElementPtr->next.location.x - (LOG_SPACE_WIDTH >> 1));
|
|
log_y = GLOBAL_SIS (log_y)
|
|
+ (ElementPtr->next.location.y - (LOG_SPACE_HEIGHT >> 1));
|
|
pPt->x = LOGX_TO_UNIVERSE (log_x);
|
|
pPt->y = LOGY_TO_UNIVERSE (log_y);
|
|
}
|
|
|
|
static void
|
|
cleanup_hyperspace (void)
|
|
{
|
|
HENCOUNTER hEncounter, hNextEncounter;
|
|
|
|
for (hEncounter = GetHeadEncounter ();
|
|
hEncounter != 0; hEncounter = hNextEncounter)
|
|
{
|
|
ENCOUNTER *EncounterPtr;
|
|
|
|
LockEncounter (hEncounter, &EncounterPtr);
|
|
hNextEncounter = GetSuccEncounter (EncounterPtr);
|
|
if (EncounterPtr->hElement)
|
|
{
|
|
ELEMENT *ElementPtr;
|
|
|
|
LockElement (EncounterPtr->hElement, &ElementPtr);
|
|
|
|
if (ElementPtr->hTarget)
|
|
{ // This is the encounter that collided with flagship
|
|
// Move the encounter to the head of the queue so that
|
|
// comm.c:RaceCommunication() gets the right one.
|
|
RemoveEncounter (hEncounter);
|
|
InsertEncounter (hEncounter, GetHeadEncounter ());
|
|
}
|
|
|
|
UnlockElement (EncounterPtr->hElement);
|
|
}
|
|
EncounterPtr->hElement = 0;
|
|
UnlockEncounter (hEncounter);
|
|
}
|
|
}
|
|
|
|
typedef enum
|
|
{
|
|
RANDOM_ENCOUNTER_TRANSITION,
|
|
INTERPLANETARY_TRANSITION,
|
|
ARILOU_SPACE_TRANSITION
|
|
} TRANSITION_TYPE;
|
|
|
|
static void
|
|
InterplanetaryTransition (ELEMENT *ElementPtr)
|
|
{
|
|
GLOBAL (ip_planet) = 0;
|
|
GLOBAL (in_orbit) = 0;
|
|
GLOBAL (ShipFacing) = 0; /* Not reentering the system */
|
|
SET_GAME_STATE (USED_BROADCASTER, 0);
|
|
if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1)
|
|
{
|
|
// Enter a solar system from HyperSpace.
|
|
GLOBAL (CurrentActivity) |= START_INTERPLANETARY;
|
|
SET_GAME_STATE (ESCAPE_COUNTER, 0);
|
|
}
|
|
else
|
|
{
|
|
POINT pt;
|
|
|
|
GLOBAL (autopilot.x) = ~0;
|
|
GLOBAL (autopilot.y) = ~0;
|
|
|
|
ElementToUniverse (ElementPtr, &pt);
|
|
CurStarDescPtr = FindStar (NULL, &pt, 5, 5);
|
|
if (CurStarDescPtr->star_pt.x == ARILOU_HOME_X
|
|
&& CurStarDescPtr->star_pt.y == ARILOU_HOME_Y)
|
|
{
|
|
// Meet the Arilou.
|
|
GLOBAL (CurrentActivity) |= START_ENCOUNTER;
|
|
}
|
|
else
|
|
{
|
|
// Transition from QuasiSpace to HyperSpace through
|
|
// one of the permanent portals.
|
|
COUNT index;
|
|
const POINT portal_pt[] = QUASISPACE_PORTALS_HYPERSPACE_ENDPOINTS;
|
|
|
|
index = CurStarDescPtr - &star_array[NUM_SOLAR_SYSTEMS + 1];
|
|
GLOBAL_SIS (log_x) = UNIVERSE_TO_LOGX (portal_pt[index].x);
|
|
GLOBAL_SIS (log_y) = UNIVERSE_TO_LOGY (portal_pt[index].y);
|
|
|
|
SET_GAME_STATE (ARILOU_SPACE_SIDE, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Enter QuasiSpace from HyperSpace by any portal, or HyperSpace from
|
|
* QuasiSpace through the periodically opening portal.
|
|
*/
|
|
static void
|
|
ArilouSpaceTransition (void)
|
|
{
|
|
GLOBAL (ShipFacing) = 0; /* Not reentering the system */
|
|
SET_GAME_STATE (USED_BROADCASTER, 0);
|
|
GLOBAL (autopilot.x) = ~0;
|
|
GLOBAL (autopilot.y) = ~0;
|
|
if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1)
|
|
{
|
|
// From HyperSpace to QuasiSpace.
|
|
GLOBAL_SIS (log_x) = UNIVERSE_TO_LOGX (QUASI_SPACE_X);
|
|
GLOBAL_SIS (log_y) = UNIVERSE_TO_LOGY (QUASI_SPACE_Y);
|
|
if (GET_GAME_STATE (PORTAL_COUNTER) == 0)
|
|
{
|
|
// Periodically appearing portal.
|
|
SET_GAME_STATE (ARILOU_SPACE_SIDE, 3);
|
|
}
|
|
else
|
|
{
|
|
// Player-induced portal.
|
|
SET_GAME_STATE (PORTAL_COUNTER, 0);
|
|
SET_GAME_STATE (ARILOU_SPACE_SIDE, 3);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// From QuasiSpace to HyperSpace through the periodically appearing
|
|
// portal.
|
|
GLOBAL_SIS (log_x) = UNIVERSE_TO_LOGX (ARILOU_SPACE_X);
|
|
GLOBAL_SIS (log_y) = UNIVERSE_TO_LOGY (ARILOU_SPACE_Y);
|
|
SET_GAME_STATE (ARILOU_SPACE_SIDE, 0);
|
|
}
|
|
}
|
|
|
|
static void
|
|
unhyper_transition (ELEMENT *ElementPtr)
|
|
{
|
|
COUNT frame_index;
|
|
|
|
ElementPtr->state_flags |= CHANGING;
|
|
|
|
frame_index = GetFrameIndex (ElementPtr->current.image.frame);
|
|
if (frame_index == 0)
|
|
frame_index += ANGLE_TO_FACING (FULL_CIRCLE);
|
|
else if (frame_index < ANGLE_TO_FACING (FULL_CIRCLE))
|
|
frame_index = NORMALIZE_FACING (frame_index + 1);
|
|
else if (++frame_index == GetFrameCount (ElementPtr->current.image.frame))
|
|
{
|
|
cleanup_hyperspace ();
|
|
|
|
GLOBAL (CurrentActivity) &= ~IN_BATTLE;
|
|
switch ((TRANSITION_TYPE) ElementPtr->turn_wait)
|
|
{
|
|
case RANDOM_ENCOUNTER_TRANSITION:
|
|
SaveSisHyperState ();
|
|
GLOBAL (CurrentActivity) |= START_ENCOUNTER;
|
|
break;
|
|
case INTERPLANETARY_TRANSITION:
|
|
InterplanetaryTransition (ElementPtr);
|
|
break;
|
|
case ARILOU_SPACE_TRANSITION:
|
|
ArilouSpaceTransition ();
|
|
break;
|
|
}
|
|
|
|
ZeroVelocityComponents (&ElementPtr->velocity);
|
|
SetPrimType (&DisplayArray[ElementPtr->PrimIndex], NO_PRIM);
|
|
return;
|
|
}
|
|
ElementPtr->next.image.frame =
|
|
SetAbsFrameIndex (ElementPtr->current.image.frame, frame_index);
|
|
}
|
|
|
|
static void
|
|
init_transition (ELEMENT *ElementPtr0, ELEMENT *ElementPtr1,
|
|
TRANSITION_TYPE which_transition)
|
|
{
|
|
SIZE dx, dy;
|
|
SIZE num_turns;
|
|
STARSHIP *StarShipPtr;
|
|
|
|
dx = WORLD_TO_VELOCITY (ElementPtr0->next.location.x
|
|
- ElementPtr1->next.location.x);
|
|
dy = WORLD_TO_VELOCITY (ElementPtr0->next.location.y
|
|
- ElementPtr1->next.location.y);
|
|
|
|
ElementPtr1->state_flags |= NONSOLID;
|
|
ElementPtr1->preprocess_func = unhyper_transition;
|
|
ElementPtr1->postprocess_func = NULL;
|
|
ElementPtr1->turn_wait = (BYTE) which_transition;
|
|
|
|
GetElementStarShip (ElementPtr1, &StarShipPtr);
|
|
num_turns = GetFrameCount (ElementPtr1->next.image.frame)
|
|
- ANGLE_TO_FACING (FULL_CIRCLE)
|
|
+ NORMALIZE_FACING (ANGLE_TO_FACING (FULL_CIRCLE)
|
|
- StarShipPtr->ShipFacing);
|
|
if (num_turns == 0)
|
|
num_turns = 1;
|
|
|
|
SetVelocityComponents (&ElementPtr1->velocity,
|
|
dx / num_turns, dy / num_turns);
|
|
}
|
|
|
|
BOOLEAN
|
|
hyper_transition (ELEMENT *ElementPtr)
|
|
{
|
|
if (ElementPtr->state_flags & APPEARING)
|
|
{
|
|
if (LastActivity & CHECK_LOAD)
|
|
{
|
|
LastActivity &= ~CHECK_LOAD;
|
|
|
|
ElementPtr->current = ElementPtr->next;
|
|
SetUpElement (ElementPtr);
|
|
|
|
ElementPtr->state_flags |= DEFY_PHYSICS;
|
|
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
ElementPtr->preprocess_func =
|
|
(void (*) (struct element *ElementPtr)) hyper_transition;
|
|
ElementPtr->postprocess_func = NULL;
|
|
ElementPtr->state_flags |= NONSOLID;
|
|
ElementPtr->next.image.frame =
|
|
SetAbsFrameIndex (ElementPtr->current.image.frame,
|
|
GetFrameCount (ElementPtr->current.image.frame) - 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
COUNT frame_index;
|
|
|
|
frame_index = GetFrameIndex (ElementPtr->current.image.frame);
|
|
if (frame_index-- <= ANGLE_TO_FACING (FULL_CIRCLE))
|
|
{
|
|
STARSHIP *StarShipPtr;
|
|
|
|
if (frame_index == ANGLE_TO_FACING (FULL_CIRCLE) - 1)
|
|
frame_index = 0;
|
|
else
|
|
frame_index = NORMALIZE_FACING (frame_index);
|
|
|
|
GetElementStarShip (ElementPtr, &StarShipPtr);
|
|
if (frame_index == StarShipPtr->ShipFacing)
|
|
{
|
|
ElementPtr->preprocess_func = ship_preprocess;
|
|
ElementPtr->postprocess_func = ship_postprocess;
|
|
ElementPtr->state_flags &= ~NONSOLID;
|
|
}
|
|
}
|
|
|
|
ElementPtr->state_flags |= CHANGING;
|
|
ElementPtr->next.image.frame =
|
|
SetAbsFrameIndex (ElementPtr->current.image.frame,
|
|
frame_index);
|
|
|
|
if (!(ElementPtr->state_flags & NONSOLID))
|
|
{
|
|
ElementPtr->current = ElementPtr->next;
|
|
SetUpElement (ElementPtr);
|
|
|
|
ElementPtr->state_flags |= DEFY_PHYSICS;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
hyper_collision (ELEMENT *ElementPtr0, POINT *pPt0,
|
|
ELEMENT *ElementPtr1, POINT *pPt1)
|
|
{
|
|
if ((ElementPtr1->state_flags & PLAYER_SHIP)
|
|
&& GET_GAME_STATE (PORTAL_COUNTER) == 0)
|
|
{
|
|
SIZE dx, dy;
|
|
POINT pt;
|
|
STAR_DESC *SDPtr;
|
|
STARSHIP *StarShipPtr;
|
|
|
|
ElementToUniverse (ElementPtr0, &pt);
|
|
|
|
SDPtr = FindStar (NULL, &pt, 5, 5);
|
|
|
|
GetElementStarShip (ElementPtr1, &StarShipPtr);
|
|
GetCurrentVelocityComponents (&ElementPtr1->velocity, &dx, &dy);
|
|
if (SDPtr == CurStarDescPtr
|
|
|| (ElementPtr1->state_flags & APPEARING)
|
|
|| !(dx || dy || (StarShipPtr->cur_status_flags
|
|
& (LEFT | RIGHT | THRUST | WEAPON | SPECIAL))))
|
|
{
|
|
CurStarDescPtr = SDPtr;
|
|
ElementPtr0->state_flags |= DEFY_PHYSICS | COLLISION;
|
|
}
|
|
else if ((GLOBAL (CurrentActivity) & IN_BATTLE)
|
|
&& (GLOBAL (autopilot.x) == ~0
|
|
|| GLOBAL (autopilot.y) == ~0
|
|
|| (GLOBAL (autopilot.x) == SDPtr->star_pt.x
|
|
&& GLOBAL (autopilot.y) == SDPtr->star_pt.y)))
|
|
{
|
|
CurStarDescPtr = SDPtr;
|
|
ElementPtr0->state_flags |= COLLISION;
|
|
|
|
init_transition (ElementPtr0, ElementPtr1,
|
|
INTERPLANETARY_TRANSITION);
|
|
}
|
|
}
|
|
(void) pPt0; /* Satisfying compiler (unused parameter) */
|
|
(void) pPt1; /* Satisfying compiler (unused parameter) */
|
|
}
|
|
|
|
static void
|
|
hyper_death (ELEMENT *ElementPtr)
|
|
{
|
|
if (!(ElementPtr->state_flags & DEFY_PHYSICS)
|
|
&& (GLOBAL (CurrentActivity) & IN_BATTLE))
|
|
CurStarDescPtr = 0;
|
|
}
|
|
|
|
static void
|
|
arilou_space_death (ELEMENT *ElementPtr)
|
|
{
|
|
if (!(ElementPtr->state_flags & DEFY_PHYSICS)
|
|
|| GET_GAME_STATE (ARILOU_SPACE_COUNTER) == 0)
|
|
{
|
|
if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1)
|
|
{
|
|
SET_GAME_STATE (ARILOU_SPACE_SIDE, 0);
|
|
}
|
|
else
|
|
{
|
|
SET_GAME_STATE (ARILOU_SPACE_SIDE, 3);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
arilou_space_collision (ELEMENT *ElementPtr0,
|
|
POINT *pPt0, ELEMENT *ElementPtr1, POINT *pPt1)
|
|
{
|
|
COUNT which_side;
|
|
|
|
if (!(ElementPtr1->state_flags & PLAYER_SHIP))
|
|
return;
|
|
|
|
which_side = GET_GAME_STATE (ARILOU_SPACE_SIDE);
|
|
if (which_side == 0 || which_side == 3)
|
|
{
|
|
if (ElementPtr1->state_flags & DEFY_PHYSICS)
|
|
{
|
|
SET_GAME_STATE (ARILOU_SPACE_SIDE, which_side ^ 1);
|
|
}
|
|
else
|
|
{
|
|
init_transition (ElementPtr0, ElementPtr1,
|
|
ARILOU_SPACE_TRANSITION);
|
|
}
|
|
}
|
|
|
|
ElementPtr0->state_flags |= DEFY_PHYSICS | COLLISION;
|
|
(void) pPt0; /* Satisfying compiler (unused parameter) */
|
|
(void) pPt1; /* Satisfying compiler (unused parameter) */
|
|
}
|
|
|
|
static HELEMENT
|
|
AllocHyperElement (STAR_DESC *SDPtr)
|
|
{
|
|
HELEMENT hHyperSpaceElement;
|
|
|
|
hHyperSpaceElement = AllocElement ();
|
|
if (hHyperSpaceElement)
|
|
{
|
|
ELEMENT *HyperSpaceElementPtr;
|
|
|
|
LockElement (hHyperSpaceElement, &HyperSpaceElementPtr);
|
|
HyperSpaceElementPtr->playerNr = NEUTRAL_PLAYER_NUM;
|
|
HyperSpaceElementPtr->state_flags = CHANGING | FINITE_LIFE;
|
|
HyperSpaceElementPtr->life_span = 1;
|
|
HyperSpaceElementPtr->mass_points = 1;
|
|
|
|
{
|
|
long lx, ly;
|
|
|
|
lx = UNIVERSE_TO_LOGX (SDPtr->star_pt.x)
|
|
+ (LOG_SPACE_WIDTH >> 1) - GLOBAL_SIS (log_x);
|
|
HyperSpaceElementPtr->current.location.x = WRAP_X (lx);
|
|
|
|
ly = UNIVERSE_TO_LOGY (SDPtr->star_pt.y)
|
|
+ (LOG_SPACE_HEIGHT >> 1) - GLOBAL_SIS (log_y);
|
|
HyperSpaceElementPtr->current.location.y = WRAP_Y (ly);
|
|
}
|
|
|
|
SetPrimType (&DisplayArray[HyperSpaceElementPtr->PrimIndex],
|
|
STAMP_PRIM);
|
|
HyperSpaceElementPtr->current.image.farray =
|
|
&hyperstars[1 + (GET_GAME_STATE (ARILOU_SPACE_SIDE) >> 1)];
|
|
|
|
UnlockElement (hHyperSpaceElement);
|
|
}
|
|
|
|
return hHyperSpaceElement;
|
|
}
|
|
|
|
static void
|
|
AddAmbientElement (void)
|
|
{
|
|
HELEMENT hHyperSpaceElement;
|
|
|
|
hHyperSpaceElement = AllocElement ();
|
|
if (hHyperSpaceElement)
|
|
{
|
|
SIZE dx, dy;
|
|
DWORD rand_val;
|
|
ELEMENT *HyperSpaceElementPtr;
|
|
|
|
LockElement (hHyperSpaceElement, &HyperSpaceElementPtr);
|
|
HyperSpaceElementPtr->playerNr = NEUTRAL_PLAYER_NUM;
|
|
HyperSpaceElementPtr->state_flags =
|
|
APPEARING | FINITE_LIFE | NONSOLID;
|
|
SetPrimType (&DisplayArray[HyperSpaceElementPtr->PrimIndex],
|
|
STAMP_PRIM);
|
|
HyperSpaceElementPtr->preprocess_func = animation_preprocess;
|
|
|
|
rand_val = TFB_Random ();
|
|
dy = LOWORD (rand_val);
|
|
dx = (SIZE)(LOBYTE (dy) % SPACE_WIDTH) - (SPACE_WIDTH >> 1);
|
|
dy = (SIZE)(HIBYTE (dy) % SPACE_HEIGHT) - (SPACE_HEIGHT >> 1);
|
|
HyperSpaceElementPtr->current.location.x = (LOG_SPACE_WIDTH >> 1)
|
|
+ DISPLAY_TO_WORLD (dx);
|
|
HyperSpaceElementPtr->current.location.y = (LOG_SPACE_HEIGHT >> 1)
|
|
+ DISPLAY_TO_WORLD (dy);
|
|
HyperSpaceElementPtr->current.image.farray = &stars_in_space;
|
|
|
|
if (HIWORD (rand_val) & 7)
|
|
{
|
|
HyperSpaceElementPtr->life_span = 14;
|
|
HyperSpaceElementPtr->current.image.frame = stars_in_space;
|
|
}
|
|
else
|
|
{
|
|
HyperSpaceElementPtr->life_span = 12;
|
|
HyperSpaceElementPtr->current.image.frame =
|
|
SetAbsFrameIndex (stars_in_space, 14);
|
|
}
|
|
|
|
UnlockElement (hHyperSpaceElement);
|
|
|
|
InsertElement (hHyperSpaceElement, GetHeadElement ());
|
|
}
|
|
}
|
|
|
|
#define NUM_VORTEX_TRANSITIONS 9
|
|
#define VORTEX_WAIT 1
|
|
|
|
static void
|
|
encounter_transition (ELEMENT *ElementPtr)
|
|
{
|
|
ElementPtr->state_flags &= ~DISAPPEARING;
|
|
ElementPtr->life_span = 1;
|
|
if (ElementPtr->turn_wait)
|
|
{
|
|
--ElementPtr->turn_wait;
|
|
}
|
|
else
|
|
{
|
|
FRAME f;
|
|
|
|
if (ElementPtr->hit_points)
|
|
{
|
|
f = DecFrameIndex (ElementPtr->current.image.frame);
|
|
ElementPtr->next.image.frame = f;
|
|
}
|
|
else
|
|
{
|
|
f = IncFrameIndex (ElementPtr->current.image.frame);
|
|
if (f != ElementPtr->current.image.farray[0])
|
|
ElementPtr->next.image.frame = f;
|
|
else
|
|
ElementPtr->death_func = NULL;
|
|
}
|
|
|
|
ElementPtr->turn_wait = VORTEX_WAIT;
|
|
}
|
|
}
|
|
|
|
static HELEMENT
|
|
getSisElement (void)
|
|
{
|
|
HSTARSHIP hSis;
|
|
HELEMENT hShip;
|
|
STARSHIP *StarShipPtr;
|
|
|
|
hSis = GetHeadLink (&race_q[RPG_PLAYER_NUM]);
|
|
if (!hSis)
|
|
return NULL;
|
|
|
|
StarShipPtr = LockStarShip (&race_q[RPG_PLAYER_NUM], hSis);
|
|
hShip = StarShipPtr->hShip;
|
|
UnlockStarShip (&race_q[RPG_PLAYER_NUM], hSis);
|
|
|
|
#ifdef DEBUG
|
|
{
|
|
ELEMENT *ElementPtr;
|
|
LockElement (hShip, &ElementPtr);
|
|
assert (ElementPtr->state_flags & PLAYER_SHIP);
|
|
UnlockElement (hShip);
|
|
}
|
|
#endif
|
|
|
|
return hShip;
|
|
}
|
|
|
|
static void
|
|
encounter_collision (ELEMENT *ElementPtr0, POINT *pPt0,
|
|
ELEMENT *ElementPtr1, POINT *pPt1)
|
|
{
|
|
HENCOUNTER hEncounter;
|
|
HENCOUNTER hNextEncounter;
|
|
|
|
if (!(ElementPtr1->state_flags & PLAYER_SHIP)
|
|
|| !(GLOBAL (CurrentActivity) & IN_BATTLE))
|
|
return;
|
|
|
|
init_transition (ElementPtr0, ElementPtr1, RANDOM_ENCOUNTER_TRANSITION);
|
|
|
|
for (hEncounter = GetHeadEncounter ();
|
|
hEncounter != 0; hEncounter = hNextEncounter)
|
|
{
|
|
ENCOUNTER *EncounterPtr;
|
|
|
|
LockEncounter (hEncounter, &EncounterPtr);
|
|
hNextEncounter = GetSuccEncounter (EncounterPtr);
|
|
if (EncounterPtr->hElement)
|
|
{
|
|
ELEMENT *ElementPtr;
|
|
|
|
LockElement (EncounterPtr->hElement, &ElementPtr);
|
|
ElementPtr->state_flags |= NONSOLID | IGNORE_SIMILAR;
|
|
UnlockElement (EncounterPtr->hElement);
|
|
}
|
|
UnlockEncounter (hEncounter);
|
|
}
|
|
|
|
// Mark this element as collided with flagship
|
|
// XXX: We could simply set hTarget to 1 or to ElementPtr1,
|
|
// but that would be too hacky ;)
|
|
ElementPtr0->hTarget = getSisElement ();
|
|
ZeroVelocityComponents (&ElementPtr0->velocity);
|
|
|
|
(void) pPt0; /* Satisfying compiler (unused parameter) */
|
|
(void) pPt1; /* Satisfying compiler (unused parameter) */
|
|
}
|
|
|
|
static HELEMENT
|
|
AddEncounterElement (ENCOUNTER *EncounterPtr, POINT *puniverse)
|
|
{
|
|
BOOLEAN NewEncounter;
|
|
HELEMENT hElement;
|
|
STAR_DESC SD;
|
|
|
|
if (GET_GAME_STATE (ARILOU_SPACE_SIDE) >= 2)
|
|
return 0;
|
|
|
|
if (EncounterPtr->SD.Index & ENCOUNTER_REFORMING)
|
|
{
|
|
EncounterPtr->SD.Index &= ~ENCOUNTER_REFORMING;
|
|
|
|
EncounterPtr->transition_state = 100;
|
|
if ((EncounterPtr->SD.Index & ONE_SHOT_ENCOUNTER)
|
|
|| LONIBBLE (EncounterPtr->SD.Index) == 0)
|
|
return 0;
|
|
}
|
|
|
|
if (LONIBBLE (EncounterPtr->SD.Index))
|
|
{
|
|
NewEncounter = FALSE;
|
|
SD.star_pt = EncounterPtr->SD.star_pt;
|
|
}
|
|
else
|
|
{
|
|
BYTE Type;
|
|
SIZE dx, dy;
|
|
COUNT i;
|
|
COUNT NumShips;
|
|
DWORD radius_squared;
|
|
BYTE EncounterMakeup[] =
|
|
{
|
|
RACE_ENCOUNTER_MAKEUP
|
|
};
|
|
|
|
NewEncounter = TRUE;
|
|
|
|
radius_squared = (DWORD)EncounterPtr->radius * EncounterPtr->radius;
|
|
|
|
Type = EncounterPtr->SD.Type;
|
|
NumShips = LONIBBLE (EncounterMakeup[Type]);
|
|
for (i = HINIBBLE (EncounterMakeup[Type]) - NumShips; i; --i)
|
|
{
|
|
if ((COUNT)TFB_Random () % 100 < 50)
|
|
++NumShips;
|
|
}
|
|
|
|
if (NumShips > MAX_HYPER_SHIPS)
|
|
NumShips = MAX_HYPER_SHIPS;
|
|
|
|
|
|
EncounterPtr->SD.Index =
|
|
MAKE_BYTE (NumShips, HINIBBLE (EncounterPtr->SD.Index));
|
|
for (i = 0; i < NumShips; ++i)
|
|
{
|
|
BRIEF_SHIP_INFO *BSIPtr = &EncounterPtr->ShipList[i];
|
|
HFLEETINFO hStarShip =
|
|
GetStarShipFromIndex (&GLOBAL (avail_race_q), Type);
|
|
FLEET_INFO *FleetPtr =
|
|
LockFleetInfo (&GLOBAL (avail_race_q), hStarShip);
|
|
BSIPtr->race_id = Type;
|
|
BSIPtr->crew_level = FleetPtr->crew_level;
|
|
BSIPtr->max_crew = FleetPtr->max_crew;
|
|
BSIPtr->max_energy = FleetPtr->max_energy;
|
|
UnlockFleetInfo (&GLOBAL (avail_race_q), hStarShip);
|
|
}
|
|
|
|
do
|
|
{
|
|
DWORD rand_val;
|
|
|
|
rand_val = TFB_Random ();
|
|
|
|
SD.star_pt.x = puniverse->x
|
|
+ (LOWORD (rand_val) % (XOFFS << 1)) - XOFFS;
|
|
if (SD.star_pt.x < 0)
|
|
SD.star_pt.x = 0;
|
|
else if (SD.star_pt.x > MAX_X_UNIVERSE)
|
|
SD.star_pt.x = MAX_X_UNIVERSE;
|
|
SD.star_pt.y = puniverse->y
|
|
+ (HIWORD (rand_val) % (YOFFS << 1)) - YOFFS;
|
|
if (SD.star_pt.y < 0)
|
|
SD.star_pt.y = 0;
|
|
else if (SD.star_pt.y > MAX_Y_UNIVERSE)
|
|
SD.star_pt.y = MAX_Y_UNIVERSE;
|
|
|
|
dx = SD.star_pt.x - EncounterPtr->origin.x;
|
|
dy = SD.star_pt.y - EncounterPtr->origin.y;
|
|
} while ((DWORD)((long)dx * dx + (long)dy * dy) > radius_squared);
|
|
|
|
EncounterPtr->SD.star_pt = SD.star_pt;
|
|
EncounterPtr->log_x = UNIVERSE_TO_LOGX (SD.star_pt.x);
|
|
EncounterPtr->log_y = UNIVERSE_TO_LOGY (SD.star_pt.y);
|
|
}
|
|
|
|
hElement = AllocHyperElement (&SD);
|
|
if (hElement)
|
|
{
|
|
SIZE i;
|
|
ELEMENT *ElementPtr;
|
|
|
|
LockElement (hElement, &ElementPtr);
|
|
|
|
i = EncounterPtr->transition_state;
|
|
if (i || NewEncounter)
|
|
{
|
|
if (i < 0)
|
|
{
|
|
i = -i;
|
|
ElementPtr->hit_points = 1;
|
|
}
|
|
if (i == 0 || i > NUM_VORTEX_TRANSITIONS)
|
|
i = NUM_VORTEX_TRANSITIONS;
|
|
|
|
ElementPtr->current.image.frame = SetRelFrameIndex (
|
|
ElementPtr->current.image.farray[0], -i);
|
|
ElementPtr->death_func = encounter_transition;
|
|
}
|
|
else
|
|
{
|
|
ElementPtr->current.image.frame =
|
|
DecFrameIndex (ElementPtr->current.image.farray[0]);
|
|
}
|
|
|
|
ElementPtr->turn_wait = VORTEX_WAIT;
|
|
ElementPtr->preprocess_func = NULL;
|
|
ElementPtr->postprocess_func = NULL;
|
|
ElementPtr->collision_func = encounter_collision;
|
|
|
|
SetUpElement (ElementPtr);
|
|
|
|
ElementPtr->IntersectControl.IntersectStamp.frame =
|
|
DecFrameIndex (stars_in_space);
|
|
SetPrimType (&DisplayArray[ElementPtr->PrimIndex], NO_PRIM);
|
|
ElementPtr->state_flags |= NONSOLID | IGNORE_VELOCITY;
|
|
|
|
UnlockElement (hElement);
|
|
|
|
InsertElement (hElement, GetTailElement ());
|
|
}
|
|
|
|
EncounterPtr->hElement = hElement;
|
|
return hElement;
|
|
}
|
|
|
|
#define GRID_OFFSET 200
|
|
|
|
static void
|
|
DrawHyperGrid (COORD ux, COORD uy, COORD ox, COORD oy)
|
|
{
|
|
COORD sx, sy, ex, ey;
|
|
RECT r;
|
|
|
|
ClearDrawable ();
|
|
SetContextForeGroundColor (
|
|
BUILD_COLOR (MAKE_RGB15 (0x00, 0x10, 0x00), 0x6B));
|
|
|
|
sx = ux - (RADAR_SCAN_WIDTH >> 1);
|
|
if (sx < 0)
|
|
sx = 0;
|
|
else
|
|
sx -= sx % GRID_OFFSET;
|
|
ex = ux + (RADAR_SCAN_WIDTH >> 1);
|
|
if (ex > MAX_X_UNIVERSE + 1)
|
|
ex = MAX_X_UNIVERSE + 1;
|
|
|
|
sy = uy - (RADAR_SCAN_HEIGHT >> 1);
|
|
if (sy < 0)
|
|
sy = 0;
|
|
else
|
|
sy -= sy % GRID_OFFSET;
|
|
ey = uy + (RADAR_SCAN_HEIGHT >> 1);
|
|
if (ey > MAX_Y_UNIVERSE + 1)
|
|
ey = MAX_Y_UNIVERSE + 1;
|
|
|
|
r.corner.y = (COORD) ((long)(MAX_Y_UNIVERSE - ey)
|
|
* RADAR_HEIGHT / RADAR_SCAN_HEIGHT) - oy;
|
|
r.extent.width = 1;
|
|
r.extent.height = ((COORD) ((long)(MAX_Y_UNIVERSE - sy)
|
|
* RADAR_HEIGHT / RADAR_SCAN_HEIGHT) - oy) - r.corner.y + 1;
|
|
for (ux = sx; ux <= ex; ux += GRID_OFFSET)
|
|
{
|
|
r.corner.x = (COORD) ((long)ux * RADAR_WIDTH / RADAR_SCAN_WIDTH) - ox;
|
|
DrawFilledRectangle (&r);
|
|
}
|
|
|
|
r.corner.x = (COORD) ((long)sx * RADAR_WIDTH / RADAR_SCAN_WIDTH) - ox;
|
|
r.extent.width = ((COORD) ((long)ex * RADAR_WIDTH / RADAR_SCAN_WIDTH)
|
|
- ox) - r.corner.x + 1;
|
|
r.extent.height = 1;
|
|
for (uy = sy; uy <= ey; uy += GRID_OFFSET)
|
|
{
|
|
r.corner.y = (COORD)((long)(MAX_Y_UNIVERSE - uy)
|
|
* RADAR_HEIGHT / RADAR_SCAN_HEIGHT) - oy;
|
|
DrawFilledRectangle (&r);
|
|
}
|
|
}
|
|
|
|
// Returns false iff the encounter is to be removed.
|
|
static bool
|
|
ProcessEncounter (ENCOUNTER *EncounterPtr, POINT *puniverse,
|
|
COORD ox, COORD oy, STAMP *stamp)
|
|
{
|
|
ELEMENT *ElementPtr;
|
|
COORD ex, ey;
|
|
|
|
if (EncounterPtr->hElement == 0
|
|
&& AddEncounterElement (EncounterPtr, puniverse) == 0)
|
|
return false;
|
|
|
|
LockElement (EncounterPtr->hElement, &ElementPtr);
|
|
|
|
if (ElementPtr->death_func)
|
|
{
|
|
if (EncounterPtr->transition_state && ElementPtr->turn_wait == 0)
|
|
{
|
|
--EncounterPtr->transition_state;
|
|
if (EncounterPtr->transition_state >= NUM_VORTEX_TRANSITIONS)
|
|
++ElementPtr->turn_wait;
|
|
else if (EncounterPtr->transition_state ==
|
|
-NUM_VORTEX_TRANSITIONS)
|
|
{
|
|
ElementPtr->death_func = NULL;
|
|
UnlockElement (EncounterPtr->hElement);
|
|
return false;
|
|
}
|
|
else
|
|
SetPrimType (&DisplayArray[ElementPtr->PrimIndex],
|
|
STAMP_PRIM);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SIZE delta_x, delta_y;
|
|
COUNT encounter_radius;
|
|
|
|
ElementPtr->life_span = 1;
|
|
GetNextVelocityComponents (&ElementPtr->velocity,
|
|
&delta_x, &delta_y, 1);
|
|
if (ElementPtr->thrust_wait)
|
|
--ElementPtr->thrust_wait;
|
|
else if (!ElementPtr->hTarget)
|
|
{ // This is an encounter that did not collide with flagship
|
|
// The colliding encounter does not move
|
|
COUNT cur_facing, delta_facing;
|
|
|
|
cur_facing = ANGLE_TO_FACING (
|
|
GetVelocityTravelAngle (&ElementPtr->velocity));
|
|
delta_facing = NORMALIZE_FACING (cur_facing - ANGLE_TO_FACING (
|
|
ARCTAN (puniverse->x - EncounterPtr->SD.star_pt.x,
|
|
puniverse->y - EncounterPtr->SD.star_pt.y)));
|
|
if (delta_facing || (delta_x == 0 && delta_y == 0))
|
|
{
|
|
SIZE speed;
|
|
const SIZE RaceHyperSpeed[] =
|
|
{
|
|
RACE_HYPER_SPEED
|
|
};
|
|
|
|
#define ENCOUNTER_TRACK_WAIT 3
|
|
speed = RaceHyperSpeed[EncounterPtr->SD.Type];
|
|
if (delta_facing < ANGLE_TO_FACING (HALF_CIRCLE))
|
|
--cur_facing;
|
|
else
|
|
++cur_facing;
|
|
if (NORMALIZE_FACING (delta_facing + ANGLE_TO_FACING (OCTANT))
|
|
> ANGLE_TO_FACING (QUADRANT))
|
|
{
|
|
if (delta_facing < ANGLE_TO_FACING (HALF_CIRCLE))
|
|
--cur_facing;
|
|
else
|
|
++cur_facing;
|
|
speed >>= 1;
|
|
}
|
|
cur_facing = FACING_TO_ANGLE (cur_facing);
|
|
SetVelocityComponents (&ElementPtr->velocity,
|
|
COSINE (cur_facing, speed), SINE (cur_facing, speed));
|
|
GetNextVelocityComponents (&ElementPtr->velocity,
|
|
&delta_x, &delta_y, 1);
|
|
|
|
ElementPtr->thrust_wait = ENCOUNTER_TRACK_WAIT;
|
|
}
|
|
}
|
|
EncounterPtr->log_x += delta_x;
|
|
EncounterPtr->log_y -= delta_y;
|
|
EncounterPtr->SD.star_pt.x = LOGX_TO_UNIVERSE (EncounterPtr->log_x);
|
|
EncounterPtr->SD.star_pt.y = LOGY_TO_UNIVERSE (EncounterPtr->log_y);
|
|
|
|
encounter_radius = EncounterPtr->radius + (GRID_OFFSET >> 1);
|
|
delta_x = EncounterPtr->SD.star_pt.x - EncounterPtr->origin.x;
|
|
if (delta_x < 0)
|
|
delta_x = -delta_x;
|
|
delta_y = EncounterPtr->SD.star_pt.y - EncounterPtr->origin.y;
|
|
if (delta_y < 0)
|
|
delta_y = -delta_y;
|
|
if ((COUNT)delta_x >= encounter_radius
|
|
|| (COUNT)delta_y >= encounter_radius
|
|
|| (DWORD)delta_x * delta_x + (DWORD)delta_y * delta_y >=
|
|
(DWORD)encounter_radius * encounter_radius)
|
|
{
|
|
ElementPtr->state_flags |= NONSOLID;
|
|
ElementPtr->life_span = 0;
|
|
|
|
if (EncounterPtr->transition_state == 0)
|
|
{
|
|
ElementPtr->death_func = encounter_transition;
|
|
EncounterPtr->transition_state = -1;
|
|
ElementPtr->hit_points = 1;
|
|
}
|
|
else
|
|
{
|
|
ElementPtr->death_func = NULL;
|
|
UnlockElement (EncounterPtr->hElement);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
ex = EncounterPtr->SD.star_pt.x;
|
|
ey = EncounterPtr->SD.star_pt.y;
|
|
if (ex - puniverse->x >= -UNIT_SCREEN_WIDTH
|
|
&& ex - puniverse->x <= UNIT_SCREEN_WIDTH
|
|
&& ey - puniverse->y >= -UNIT_SCREEN_HEIGHT
|
|
&& ey - puniverse->y <= UNIT_SCREEN_HEIGHT)
|
|
{
|
|
ElementPtr->next.location.x =
|
|
(SIZE)(EncounterPtr->log_x - GLOBAL_SIS (log_x))
|
|
+ (LOG_SPACE_WIDTH >> 1);
|
|
ElementPtr->next.location.y =
|
|
(SIZE)(EncounterPtr->log_y - GLOBAL_SIS (log_y))
|
|
+ (LOG_SPACE_HEIGHT >> 1);
|
|
if ((ElementPtr->state_flags & NONSOLID)
|
|
&& EncounterPtr->transition_state == 0)
|
|
{
|
|
ElementPtr->current.location = ElementPtr->next.location;
|
|
SetPrimType (&DisplayArray[ElementPtr->PrimIndex],
|
|
STAMP_PRIM);
|
|
if (ElementPtr->death_func == 0)
|
|
{
|
|
InitIntersectStartPoint (ElementPtr);
|
|
ElementPtr->state_flags &= ~NONSOLID;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ElementPtr->state_flags |= NONSOLID;
|
|
if (ex - puniverse->x < -XOFFS || ex - puniverse->x > XOFFS
|
|
|| ey - puniverse->y < -YOFFS || ey - puniverse->y > YOFFS)
|
|
{
|
|
ElementPtr->life_span = 0;
|
|
ElementPtr->death_func = NULL;
|
|
UnlockElement (EncounterPtr->hElement);
|
|
return false;
|
|
}
|
|
|
|
SetPrimType (&DisplayArray[ElementPtr->PrimIndex], NO_PRIM);
|
|
}
|
|
|
|
UnlockElement (EncounterPtr->hElement);
|
|
|
|
stamp->origin.x = (COORD)((long)ex * RADAR_WIDTH / RADAR_SCAN_WIDTH) - ox;
|
|
stamp->origin.y = (COORD)((long)(MAX_Y_UNIVERSE - ey) * RADAR_HEIGHT
|
|
/ RADAR_SCAN_HEIGHT) - oy;
|
|
DrawStamp (stamp);
|
|
|
|
return true;
|
|
}
|
|
|
|
static void
|
|
ProcessEncounters (POINT *puniverse, COORD ox, COORD oy)
|
|
{
|
|
STAMP stamp;
|
|
HENCOUNTER hEncounter, hNextEncounter;
|
|
|
|
stamp.frame = SetAbsFrameIndex (stars_in_space, 91);
|
|
for (hEncounter = GetHeadEncounter ();
|
|
hEncounter; hEncounter = hNextEncounter)
|
|
{
|
|
ENCOUNTER *EncounterPtr;
|
|
|
|
LockEncounter (hEncounter, &EncounterPtr);
|
|
hNextEncounter = GetSuccEncounter (EncounterPtr);
|
|
|
|
if (!ProcessEncounter (EncounterPtr, puniverse, ox, oy, &stamp))
|
|
{
|
|
UnlockEncounter (hEncounter);
|
|
RemoveEncounter (hEncounter);
|
|
FreeEncounter (hEncounter);
|
|
continue;
|
|
}
|
|
|
|
UnlockEncounter (hEncounter);
|
|
}
|
|
}
|
|
|
|
void
|
|
SeedUniverse (void)
|
|
{
|
|
COORD ox, oy;
|
|
COORD sx, sy, ex, ey;
|
|
SWORD portalCounter, arilouSpaceCounter, arilouSpaceSide;
|
|
POINT universe;
|
|
FRAME blip_frame;
|
|
STAMP s;
|
|
STAR_DESC *SDPtr;
|
|
HELEMENT hHyperSpaceElement;
|
|
ELEMENT *HyperSpaceElementPtr;
|
|
|
|
universe.x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x));
|
|
universe.y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y));
|
|
|
|
blip_frame = SetAbsFrameIndex (stars_in_space, 90);
|
|
|
|
SetContext (RadarContext);
|
|
BatchGraphics ();
|
|
|
|
ox = (COORD)((long)universe.x * RADAR_WIDTH / RADAR_SCAN_WIDTH)
|
|
- (RADAR_WIDTH >> 1);
|
|
oy = (COORD)((long)(MAX_Y_UNIVERSE - universe.y)
|
|
* RADAR_HEIGHT / RADAR_SCAN_HEIGHT) - (RADAR_HEIGHT >> 1);
|
|
|
|
ex = (COORD)((long)GLOBAL (ShipStamp.origin.x)
|
|
* RADAR_WIDTH / RADAR_SCAN_WIDTH) - (RADAR_WIDTH >> 1);
|
|
ey = (COORD)((long)(MAX_Y_UNIVERSE - GLOBAL (ShipStamp.origin.y))
|
|
* RADAR_HEIGHT / RADAR_SCAN_HEIGHT) - (RADAR_HEIGHT >> 1);
|
|
|
|
arilouSpaceCounter = GET_GAME_STATE (ARILOU_SPACE_COUNTER);
|
|
arilouSpaceSide = GET_GAME_STATE (ARILOU_SPACE_SIDE);
|
|
|
|
// if (ox != ex || oy != ey)
|
|
{
|
|
DrawHyperGrid (universe.x, universe.y, ox, oy);
|
|
|
|
{
|
|
SDPtr = 0;
|
|
while ((SDPtr = FindStar (SDPtr, &universe, XOFFS, YOFFS)))
|
|
{
|
|
BYTE star_type;
|
|
|
|
ex = SDPtr->star_pt.x;
|
|
ey = SDPtr->star_pt.y;
|
|
star_type = STAR_TYPE (SDPtr->Type);
|
|
if (arilouSpaceSide >= 2 &&
|
|
ex == ARILOU_HOME_X && ey == ARILOU_HOME_Y)
|
|
star_type = SUPER_GIANT_STAR;
|
|
|
|
s.origin.x = (COORD)((long)ex * RADAR_WIDTH
|
|
/ RADAR_SCAN_WIDTH) - ox;
|
|
s.origin.y = (COORD)((long)(MAX_Y_UNIVERSE - ey)
|
|
* RADAR_HEIGHT / RADAR_SCAN_HEIGHT) - oy;
|
|
s.frame = SetRelFrameIndex (blip_frame,
|
|
star_type + 2);
|
|
DrawStamp (&s);
|
|
}
|
|
}
|
|
}
|
|
|
|
portalCounter = GET_GAME_STATE (PORTAL_COUNTER);
|
|
if (portalCounter || arilouSpaceCounter)
|
|
{
|
|
COUNT i;
|
|
STAR_DESC SD[2];
|
|
// This array is filled with the STAR_DESC's of
|
|
// QuasiSpace portals that need to be taken into account.
|
|
// i is set to the number of active portals (max 2).
|
|
|
|
i = 0;
|
|
if (portalCounter)
|
|
{
|
|
// A player-created QuasiSpace portal is opening.
|
|
static POINT portal_pt;
|
|
|
|
SD[i].Index = ((portalCounter - 1) >> 1) + 18;
|
|
if (portalCounter == 1)
|
|
portal_pt = universe;
|
|
SD[i].star_pt = portal_pt;
|
|
++i;
|
|
|
|
if (++portalCounter == (10 + 1))
|
|
portalCounter = (9 + 1);
|
|
|
|
SET_GAME_STATE (PORTAL_COUNTER, portalCounter);
|
|
}
|
|
|
|
if (arilouSpaceCounter)
|
|
{
|
|
// The periodically appearing QuasiSpace portal is open.
|
|
SD[i].Index = arilouSpaceCounter >> 1;
|
|
if (arilouSpaceSide <= 1)
|
|
{
|
|
// The player is in HyperSpace
|
|
SD[i].Index += 18;
|
|
SD[i].star_pt.x = ARILOU_SPACE_X;
|
|
SD[i].star_pt.y = ARILOU_SPACE_Y;
|
|
}
|
|
else
|
|
{
|
|
// The player is in QuasiSpace
|
|
SD[i].star_pt.x = QUASI_SPACE_X;
|
|
SD[i].star_pt.y = QUASI_SPACE_Y;
|
|
}
|
|
++i;
|
|
}
|
|
|
|
// Process the i portals from SD.
|
|
do
|
|
{
|
|
--i;
|
|
sx = SD[i].star_pt.x - universe.x + XOFFS;
|
|
sy = SD[i].star_pt.y - universe.y + YOFFS;
|
|
if (sx < 0 || sy < 0 || sx >= (XOFFS << 1) || sy >= (YOFFS << 1))
|
|
continue;
|
|
|
|
ex = SD[i].star_pt.x;
|
|
ey = SD[i].star_pt.y;
|
|
s.origin.x = (COORD)((long)ex * RADAR_WIDTH / RADAR_SCAN_WIDTH)
|
|
- ox;
|
|
s.origin.y = (COORD)((long)(MAX_Y_UNIVERSE - ey)
|
|
* RADAR_HEIGHT / RADAR_SCAN_HEIGHT) - oy;
|
|
s.frame = SetAbsFrameIndex (stars_in_space, 95);
|
|
DrawStamp (&s);
|
|
|
|
ex -= universe.x;
|
|
if (ex < 0)
|
|
ex = -ex;
|
|
ey -= universe.y;
|
|
if (ey < 0)
|
|
ey = -ey;
|
|
|
|
if (ex > (XOFFS / NUM_RADAR_SCREENS)
|
|
|| ey > (YOFFS / NUM_RADAR_SCREENS))
|
|
continue;
|
|
|
|
hHyperSpaceElement = AllocHyperElement (&SD[i]);
|
|
if (hHyperSpaceElement == 0)
|
|
continue;
|
|
|
|
LockElement (hHyperSpaceElement, &HyperSpaceElementPtr);
|
|
HyperSpaceElementPtr->current.image.frame = SetAbsFrameIndex (
|
|
hyperstars[1 + (GET_GAME_STATE (ARILOU_SPACE_SIDE) >> 1)],
|
|
SD[i].Index);
|
|
HyperSpaceElementPtr->preprocess_func = NULL;
|
|
HyperSpaceElementPtr->postprocess_func = NULL;
|
|
HyperSpaceElementPtr->collision_func = arilou_space_collision;
|
|
|
|
SetUpElement (HyperSpaceElementPtr);
|
|
|
|
if (arilouSpaceSide == 1 || arilouSpaceSide == 2)
|
|
HyperSpaceElementPtr->death_func = arilou_space_death;
|
|
else
|
|
{
|
|
HyperSpaceElementPtr->death_func = NULL;
|
|
HyperSpaceElementPtr->IntersectControl.IntersectStamp.frame =
|
|
DecFrameIndex (stars_in_space);
|
|
}
|
|
|
|
UnlockElement (hHyperSpaceElement);
|
|
|
|
InsertElement (hHyperSpaceElement, GetHeadElement ());
|
|
} while (i);
|
|
}
|
|
|
|
{
|
|
SDPtr = 0;
|
|
while ((SDPtr = FindStar (SDPtr, &universe, XOFFS, YOFFS)))
|
|
{
|
|
BYTE star_type;
|
|
|
|
ex = SDPtr->star_pt.x - universe.x;
|
|
if (ex < 0)
|
|
ex = -ex;
|
|
ey = SDPtr->star_pt.y - universe.y;
|
|
if (ey < 0)
|
|
ey = -ey;
|
|
if (ex > (XOFFS / NUM_RADAR_SCREENS)
|
|
|| ey > (YOFFS / NUM_RADAR_SCREENS))
|
|
continue;
|
|
|
|
hHyperSpaceElement = AllocHyperElement (SDPtr);
|
|
if (hHyperSpaceElement == 0)
|
|
continue;
|
|
|
|
star_type = SDPtr->Type;
|
|
|
|
LockElement (hHyperSpaceElement, &HyperSpaceElementPtr);
|
|
HyperSpaceElementPtr->current.image.frame = SetAbsFrameIndex (
|
|
hyperstars[1 + (GET_GAME_STATE (ARILOU_SPACE_SIDE) >> 1)],
|
|
STAR_TYPE (star_type) * NUM_STAR_COLORS
|
|
+ STAR_COLOR (star_type));
|
|
HyperSpaceElementPtr->preprocess_func = NULL;
|
|
HyperSpaceElementPtr->postprocess_func = NULL;
|
|
HyperSpaceElementPtr->collision_func = hyper_collision;
|
|
|
|
SetUpElement (HyperSpaceElementPtr);
|
|
|
|
if (SDPtr == CurStarDescPtr
|
|
&& GET_GAME_STATE (PORTAL_COUNTER) == 0)
|
|
HyperSpaceElementPtr->death_func = hyper_death;
|
|
else
|
|
{
|
|
HyperSpaceElementPtr->death_func = NULL;
|
|
HyperSpaceElementPtr->IntersectControl.IntersectStamp.frame =
|
|
DecFrameIndex (stars_in_space);
|
|
}
|
|
UnlockElement (hHyperSpaceElement);
|
|
|
|
InsertElement (hHyperSpaceElement, GetHeadElement ());
|
|
}
|
|
ProcessEncounters (&universe, ox, oy);
|
|
}
|
|
|
|
s.origin.x = RADAR_WIDTH >> 1;
|
|
s.origin.y = RADAR_HEIGHT >> 1;
|
|
s.frame = blip_frame;
|
|
DrawStamp (&s);
|
|
|
|
{
|
|
// draws borders to mini-map
|
|
|
|
RECT r;
|
|
SetContextForeGroundColor (
|
|
BUILD_COLOR (MAKE_RGB15 (0x0E, 0x0E, 0x0E), 0x00));
|
|
r.corner.x = 0;
|
|
r.corner.y = 0;
|
|
r.extent.width = RADAR_WIDTH - 1;
|
|
r.extent.height = 1;
|
|
DrawFilledRectangle (&r);
|
|
r.extent.width = 1;
|
|
r.extent.height = RADAR_HEIGHT - 1;
|
|
DrawFilledRectangle (&r);
|
|
|
|
SetContextForeGroundColor (
|
|
BUILD_COLOR (MAKE_RGB15 (0x06, 0x06, 0x06), 0x00));
|
|
r.corner.x = RADAR_WIDTH - 1;
|
|
r.corner.y = 1;
|
|
r.extent.height = RADAR_HEIGHT - 1;
|
|
DrawFilledRectangle (&r);
|
|
r.corner.x = 1;
|
|
r.corner.y = RADAR_HEIGHT - 1;
|
|
r.extent.width = RADAR_WIDTH - 2;
|
|
r.extent.height = 1;
|
|
DrawFilledRectangle (&r);
|
|
|
|
SetContextForeGroundColor (
|
|
BUILD_COLOR (MAKE_RGB15 (0x08, 0x08, 0x08), 0x00));
|
|
r.corner.x = 0;
|
|
DrawPoint (&r.corner);
|
|
r.corner.x = RADAR_WIDTH - 1;
|
|
r.corner.y = 0;
|
|
DrawPoint (&r.corner);
|
|
}
|
|
|
|
UnbatchGraphics ();
|
|
|
|
SetContext (StatusContext);
|
|
|
|
if (!(LOWORD (TFB_Random ()) & 7))
|
|
AddAmbientElement ();
|
|
|
|
if (universe.x != GLOBAL (ShipStamp.origin.x)
|
|
|| universe.y != GLOBAL (ShipStamp.origin.y))
|
|
{
|
|
GLOBAL (ShipStamp.origin) = universe;
|
|
DrawHyperCoords (universe);
|
|
}
|
|
}
|
|
|
|
static BOOLEAN
|
|
DoHyperspaceMenu (MENU_STATE *pMS)
|
|
{
|
|
BOOLEAN select = PulsedInputState.menu[KEY_MENU_SELECT];
|
|
BOOLEAN handled;
|
|
|
|
if ((GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))
|
|
|| GLOBAL_SIS (CrewEnlisted) == (COUNT)~0)
|
|
return FALSE;
|
|
|
|
handled = DoMenuChooser (pMS, PM_STARMAP);
|
|
if (handled)
|
|
return TRUE;
|
|
|
|
if (!select)
|
|
return TRUE;
|
|
|
|
LockMutex (GraphicsLock);
|
|
SetFlashRect (NULL);
|
|
UnlockMutex (GraphicsLock);
|
|
|
|
switch (pMS->CurState)
|
|
{
|
|
case EQUIP_DEVICE:
|
|
select = DevicesMenu ();
|
|
if (GET_GAME_STATE (PORTAL_COUNTER))
|
|
{ // A player-induced portal to QuasiSpace is opening
|
|
return FALSE;
|
|
}
|
|
if (GLOBAL (CurrentActivity) & START_ENCOUNTER)
|
|
{ // Selected Talking Pet, going into conversation
|
|
return FALSE;
|
|
}
|
|
break;
|
|
case CARGO:
|
|
CargoMenu ();
|
|
break;
|
|
case ROSTER:
|
|
select = RosterMenu ();
|
|
break;
|
|
case GAME_MENU:
|
|
if (!GameOptions ())
|
|
return FALSE; // abort or load
|
|
break;
|
|
case STARMAP:
|
|
StarMap ();
|
|
return FALSE;
|
|
case NAVIGATION:
|
|
return FALSE;
|
|
}
|
|
|
|
if (!(GLOBAL (CurrentActivity) & CHECK_ABORT))
|
|
{
|
|
if (select)
|
|
{ // 3DO menu jumps to NAVIGATE after a successful submenu run
|
|
if (optWhichMenu != OPT_PC)
|
|
pMS->CurState = NAVIGATION;
|
|
DrawMenuStateStrings (PM_STARMAP, pMS->CurState);
|
|
}
|
|
LockMutex (GraphicsLock);
|
|
SetFlashRect (SFR_MENU_3DO);
|
|
UnlockMutex (GraphicsLock);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
HyperspaceMenu (void)
|
|
{
|
|
Color OldColor;
|
|
CONTEXT OldContext;
|
|
MENU_STATE MenuState;
|
|
|
|
UnbatchGraphics ();
|
|
|
|
OldContext = SetContext (SpaceContext);
|
|
OldColor = SetContextBackGroundColor (BLACK_COLOR);
|
|
|
|
UnlockMutex (GraphicsLock);
|
|
|
|
memset (&MenuState, 0, sizeof (MenuState));
|
|
MenuState.InputFunc = DoHyperspaceMenu;
|
|
MenuState.Initialized = TRUE;
|
|
MenuState.CurState = STARMAP;
|
|
|
|
DrawMenuStateStrings (PM_STARMAP, STARMAP);
|
|
LockMutex (GraphicsLock);
|
|
SetFlashRect (SFR_MENU_3DO);
|
|
UnlockMutex (GraphicsLock);
|
|
|
|
SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT);
|
|
DoInput (&MenuState, TRUE);
|
|
|
|
LockMutex (GraphicsLock);
|
|
SetFlashRect (NULL);
|
|
|
|
SetContext (SpaceContext);
|
|
|
|
if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)))
|
|
{
|
|
ClearSISRect (CLEAR_SIS_RADAR);
|
|
UnlockMutex (GraphicsLock);
|
|
WaitForNoInput (ONE_SECOND / 2, FALSE);
|
|
LockMutex (GraphicsLock);
|
|
}
|
|
|
|
SetContextBackGroundColor (OldColor);
|
|
SetContext (OldContext);
|
|
if (!(GLOBAL (CurrentActivity) & IN_BATTLE))
|
|
cleanup_hyperspace ();
|
|
|
|
BatchGraphics ();
|
|
}
|
|
|
|
void
|
|
SaveSisHyperState (void)
|
|
{
|
|
HELEMENT hSisElement;
|
|
ELEMENT *ElementPtr;
|
|
STARSHIP *StarShipPtr;
|
|
|
|
// Update 'GLOBAL (ShipFacing)' to the direction the flagship is facing
|
|
hSisElement = getSisElement ();
|
|
if (!hSisElement)
|
|
{ // Happens when saving a game from Hyperspace encounter screen
|
|
return;
|
|
}
|
|
//if (ElementPtr->state_flags & PLAYER_SHIP)
|
|
LockElement (hSisElement, &ElementPtr);
|
|
GetElementStarShip (ElementPtr, &StarShipPtr);
|
|
// XXX: Solar system reentry test depends on ShipFacing != 0
|
|
GLOBAL (ShipFacing) = StarShipPtr->ShipFacing + 1;
|
|
UnlockElement (hSisElement);
|
|
}
|
|
|