//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 "globdata.h" #include "coderes.h" #include "encount.h" #include "starmap.h" #include "master.h" #include "setup.h" #include "units.h" #include "hyper.h" #include "resinst.h" #include "nameref.h" #include "build.h" #include "state.h" #include "grpinfo.h" #include "gamestr.h" #include #include #ifdef STATE_DEBUG # include "libs/log.h" #endif static void CreateRadar (void); CONTEXT RadarContext; FRAME PlayFrame; GLOBDATA GlobData; BYTE getGameState (BYTE *state, int startBit, int endBit) { return (BYTE) (((startBit >> 3) == (endBit >> 3) ? (state[startBit >> 3] >> (startBit & 7)) : ((state[startBit >> 3] >> (startBit & 7)) | (state[endBit >> 3] << (endBit - startBit - (endBit & 7))))) & ((1 << (endBit - startBit + 1)) - 1)); } void setGameState (BYTE *state, int startBit, int endBit, BYTE val #ifdef STATE_DEBUG , const char *name #endif ) { state[startBit >> 3] = (state[startBit >> 3] & (BYTE) ~(((1 << (endBit - startBit + 1)) - 1) << (startBit & 7))) | (BYTE)((val) << (startBit & 7)); if ((startBit >> 3) < (endBit >> 3)) { state[endBit >> 3] = (state[endBit >> 3] & (BYTE)~((1 << ((endBit & 7) + 1)) - 1)) | (BYTE)((val) >> (endBit - startBit - (endBit & 7))); } #ifdef STATE_DEBUG log_add (log_Debug, "State '%s' set to %d.", name, (int)val); #endif } DWORD getGameState32 (BYTE *state, int startBit) { DWORD v; int shift; for (v = 0, shift = 0; shift < 32; shift += 8, startBit += 8) { v |= getGameState (state, startBit, startBit + 7) << shift; } return v; } void setGameState32 (BYTE *state, int startBit, DWORD val #ifdef STATE_DEBUG , const char *name #endif ) { DWORD v = val; int i; for (i = 0; i < 4; ++i, v >>= 8, startBit += 8) { setGameState (state, startBit, startBit + 7, v & 0xff #ifdef STATE_DEBUG , "(ignored)" #endif ); } #ifdef STATE_DEBUG log_add (log_Debug, "State '%s' set to %u.", name, (unsigned)val); #endif } void copyGameState (BYTE *dest, DWORD target, BYTE *src, DWORD begin, DWORD end) { while (begin < end) { BYTE b; DWORD delta = 7; if (begin + delta > end) delta = end - begin; b = getGameState (src, begin, begin + delta); setGameState (dest, target, target + delta, b); begin += 8; target += 8; } } static void CreateRadar (void) { if (RadarContext == 0) { RECT r; CONTEXT OldContext; RadarContext = CreateContext ("RadarContext"); OldContext = SetContext (RadarContext); SetContextFGFrame (Screen); r.corner.x = RADAR_X; r.corner.y = RADAR_Y; r.extent.width = RADAR_WIDTH; r.extent.height = RADAR_HEIGHT; SetContextClipRect (&r); SetContext (OldContext); } } BOOLEAN LoadSC2Data (void) { if (FlagStatFrame == 0) { FlagStatFrame = CaptureDrawable ( LoadGraphic (FLAGSTAT_MASK_PMAP_ANIM)); if (FlagStatFrame == NULL) return FALSE; MiscDataFrame = CaptureDrawable ( LoadGraphic (MISCDATA_MASK_PMAP_ANIM)); if (MiscDataFrame == NULL) return FALSE; FontGradFrame = CaptureDrawable ( LoadGraphic (FONTGRAD_PMAP_ANIM)); } CreateRadar (); if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) { GLOBAL (ShipStamp.origin.x) = GLOBAL (ShipStamp.origin.y) = -1; } return TRUE; } static void copyFleetInfo (FLEET_INFO *dst, SHIP_INFO *src, FLEET_STUFF *fleet) { // other leading fields are irrelevant dst->crew_level = src->crew_level; dst->max_crew = src->max_crew; dst->max_energy = src->max_energy; dst->race_strings = src->race_strings; dst->icons = src->icons; dst->melee_icon = src->melee_icon; dst->actual_strength = fleet->strength; dst->known_loc = fleet->known_loc; } BOOLEAN InitGameStructures (void) { COUNT i; InitGlobData (); PlayFrame = CaptureDrawable (LoadGraphic (PLAYMENU_ANIM)); { COUNT num_ships; SPECIES_ID s_id = ARILOU_ID; num_ships = KOHR_AH_ID - s_id + 1 + 2; /* Yehat Rebels and Ur-Quan probe */ InitQueue (&GLOBAL (avail_race_q), num_ships, sizeof (FLEET_INFO)); for (i = 0; i < num_ships; ++i) { SPECIES_ID ship_ref; HFLEETINFO hFleet; FLEET_INFO *FleetPtr; if (i < num_ships - 2) ship_ref = s_id++; else if (i == num_ships - 2) ship_ref = YEHAT_ID; else /* (i == num_ships - 1) */ ship_ref = UR_QUAN_PROBE_ID; hFleet = AllocLink (&GLOBAL (avail_race_q)); if (!hFleet) continue; FleetPtr = LockFleetInfo (&GLOBAL (avail_race_q), hFleet); FleetPtr->SpeciesID = ship_ref; if (i < num_ships - 1) { HMASTERSHIP hMasterShip; MASTER_SHIP_INFO *MasterPtr; hMasterShip = FindMasterShip (ship_ref); MasterPtr = LockMasterShip (&master_q, hMasterShip); // Grab a copy of loaded icons and strings (not owned) copyFleetInfo (FleetPtr, &MasterPtr->ShipInfo, &MasterPtr->Fleet); UnlockMasterShip (&master_q, hMasterShip); } else { // Ur-Quan probe. RACE_DESC *RDPtr = load_ship (FleetPtr->SpeciesID, FALSE); if (RDPtr) { // Grab a copy of loaded icons and strings copyFleetInfo (FleetPtr, &RDPtr->ship_info, &RDPtr->fleet); // avail_race_q owns these resources now free_ship (RDPtr, FALSE, FALSE); } } FleetPtr->allied_state = BAD_GUY; FleetPtr->known_strength = 0; FleetPtr->loc = FleetPtr->known_loc; // XXX: Hack: Rebel special case if (i == YEHAT_REBEL_SHIP) FleetPtr->actual_strength = 0; FleetPtr->growth = 0; FleetPtr->growth_fract = 0; FleetPtr->growth_err_term = 255 >> 1; FleetPtr->days_left = 0; FleetPtr->func_index = ~0; UnlockFleetInfo (&GLOBAL (avail_race_q), hFleet); PutQueue (&GLOBAL (avail_race_q), hFleet); } } InitSISContexts (); LoadSC2Data (); InitPlanetInfo (); InitGroupInfo (TRUE); GLOBAL (glob_flags) = 0; GLOBAL (ElementWorth[COMMON]) = 1; GLOBAL_SIS (ElementAmounts[COMMON]) = 0; GLOBAL (ElementWorth[CORROSIVE]) = 2; GLOBAL_SIS (ElementAmounts[CORROSIVE]) = 0; GLOBAL (ElementWorth[BASE_METAL]) = 3; GLOBAL_SIS (ElementAmounts[BASE_METAL]) = 0; GLOBAL (ElementWorth[NOBLE]) = 4; GLOBAL_SIS (ElementAmounts[NOBLE]) = 0; GLOBAL (ElementWorth[RARE_EARTH]) = 5; GLOBAL_SIS (ElementAmounts[RARE_EARTH]) = 0; GLOBAL (ElementWorth[PRECIOUS]) = 6; GLOBAL_SIS (ElementAmounts[PRECIOUS]) = 0; GLOBAL (ElementWorth[RADIOACTIVE]) = 8; GLOBAL_SIS (ElementAmounts[RADIOACTIVE]) = 0; GLOBAL (ElementWorth[EXOTIC]) = 25; GLOBAL_SIS (ElementAmounts[EXOTIC]) = 0; for (i = 0; i < NUM_DRIVE_SLOTS; ++i) GLOBAL_SIS (DriveSlots[i]) = EMPTY_SLOT + 0; GLOBAL_SIS (DriveSlots[5]) = GLOBAL_SIS (DriveSlots[6]) = FUSION_THRUSTER; for (i = 0; i < NUM_JET_SLOTS; ++i) GLOBAL_SIS (JetSlots[i]) = EMPTY_SLOT + 1; GLOBAL_SIS (JetSlots[0]) = GLOBAL_SIS (JetSlots[6]) = TURNING_JETS; for (i = 0; i < NUM_MODULE_SLOTS; ++i) GLOBAL_SIS (ModuleSlots[i]) = EMPTY_SLOT + 2; GLOBAL_SIS (ModuleSlots[15]) = GUN_WEAPON; GLOBAL_SIS (ModuleSlots[2]) = CREW_POD; GLOBAL_SIS (CrewEnlisted) = CREW_POD_CAPACITY; GLOBAL_SIS (ModuleSlots[8]) = STORAGE_BAY; GLOBAL_SIS (ModuleSlots[1]) = FUEL_TANK; GLOBAL_SIS (FuelOnBoard) = 10 * FUEL_TANK_SCALE; InitQueue (&GLOBAL (built_ship_q), MAX_BUILT_SHIPS, sizeof (SHIP_FRAGMENT)); InitQueue (&GLOBAL (npc_built_ship_q), MAX_SHIPS_PER_SIDE, sizeof (SHIP_FRAGMENT)); InitQueue (&GLOBAL (ip_group_q), MAX_BATTLE_GROUPS, sizeof (IP_GROUP)); InitQueue (&GLOBAL (encounter_q), MAX_ENCOUNTERS, sizeof (ENCOUNTER)); GLOBAL (CurrentActivity) = IN_INTERPLANETARY | START_INTERPLANETARY; GLOBAL_SIS (ResUnits) = 0; GLOBAL (CrewCost) = 3; GLOBAL (FuelCost) = 20; GLOBAL (ModuleCost[PLANET_LANDER]) = 500 / MODULE_COST_SCALE; GLOBAL (ModuleCost[FUSION_THRUSTER]) = 500 / MODULE_COST_SCALE; GLOBAL (ModuleCost[TURNING_JETS]) = 500 / MODULE_COST_SCALE; GLOBAL (ModuleCost[CREW_POD]) = 2000 / MODULE_COST_SCALE; GLOBAL (ModuleCost[STORAGE_BAY]) = 750 / MODULE_COST_SCALE; GLOBAL (ModuleCost[FUEL_TANK]) = 500 / MODULE_COST_SCALE; GLOBAL (ModuleCost[DYNAMO_UNIT]) = 2000 / MODULE_COST_SCALE; GLOBAL (ModuleCost[GUN_WEAPON]) = 2000 / MODULE_COST_SCALE; GLOBAL_SIS (NumLanders) = 1; utf8StringCopy (GLOBAL_SIS (ShipName), sizeof (GLOBAL_SIS (ShipName)), GAME_STRING (NAMING_STRING_BASE + 2)); utf8StringCopy (GLOBAL_SIS (CommanderName), sizeof (GLOBAL_SIS (CommanderName)), GAME_STRING (NAMING_STRING_BASE + 3)); SetRaceAllied (HUMAN_SHIP, TRUE); CloneShipFragment (HUMAN_SHIP, &GLOBAL (built_ship_q), 0); GLOBAL_SIS (log_x) = UNIVERSE_TO_LOGX (SOL_X); GLOBAL_SIS (log_y) = UNIVERSE_TO_LOGY (SOL_Y); CurStarDescPtr = 0; GLOBAL (autopilot.x) = ~0; GLOBAL (autopilot.y) = ~0; return (TRUE); } void FreeSC2Data (void) { DestroyContext (RadarContext); RadarContext = 0; DestroyDrawable (ReleaseDrawable (FontGradFrame)); FontGradFrame = 0; DestroyDrawable (ReleaseDrawable (MiscDataFrame)); MiscDataFrame = 0; DestroyDrawable (ReleaseDrawable (FlagStatFrame)); FlagStatFrame = 0; } void UninitGameStructures (void) { HFLEETINFO hStarShip; UninitQueue (&GLOBAL (encounter_q)); UninitQueue (&GLOBAL (ip_group_q)); UninitQueue (&GLOBAL (npc_built_ship_q)); UninitQueue (&GLOBAL (built_ship_q)); UninitGroupInfo (); UninitPlanetInfo (); // FreeSC2Data (); // The only resources avail_race_q owns are the Ur-Quan probe's // so free them now hStarShip = GetTailLink (&GLOBAL (avail_race_q)); if (hStarShip) { FLEET_INFO *FleetPtr; FleetPtr = LockFleetInfo (&GLOBAL (avail_race_q), hStarShip); DestroyDrawable (ReleaseDrawable (FleetPtr->melee_icon)); DestroyDrawable (ReleaseDrawable (FleetPtr->icons)); DestroyStringTable (ReleaseStringTable (FleetPtr->race_strings)); UnlockFleetInfo (&GLOBAL (avail_race_q), hStarShip); } UninitQueue (&GLOBAL (avail_race_q)); DestroyDrawable (ReleaseDrawable (PlayFrame)); PlayFrame = 0; } void InitGlobData (void) { COUNT i; i = GLOBAL (glob_flags); memset (&GlobData, 0, sizeof (GlobData)); GLOBAL (glob_flags) = (BYTE)i; GLOBAL (DisplayArray) = DisplayArray; } BOOLEAN inFullGame (void) { ACTIVITY act = LOBYTE (GLOBAL (CurrentActivity)); return (act == IN_LAST_BATTLE || act == IN_ENCOUNTER || act == IN_HYPERSPACE || act == IN_INTERPLANETARY || act == WON_LAST_BATTLE); } BOOLEAN inSuperMelee (void) { return (LOBYTE (GLOBAL (CurrentActivity)) == SUPER_MELEE); // TODO: && !inMainMenu () } #if 0 BOOLEAN inBattle (void) { // TODO: IN_BATTLE is also set while in HyperSpace/QuasiSpace. return ((GLOBAL (CurrentActivity) & IN_BATTLE) != 0); } #endif #if 0 // Disabled for now as there are similar functions in uqm/planets/planets.h // Pre: inFullGame() BOOLEAN inInterPlanetary (void) { assert (inFullGame ()); return (pSolarSysState != NULL); } // Pre: inFullGame() BOOLEAN inSolarSystem (void) { assert (inFullGame ()); return (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY); } // Pre: inFullGame() BOOLEAN inOrbit (void) { assert (inFullGame ()); return (pSolarSysState != NULL) && (pSolarSysState->pOrbitalDesc != NULL); } #endif // In HyperSpace or QuasiSpace // Pre: inFullGame() BOOLEAN inHQSpace (void) { //assert (inFullGame ()); return (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE); // IN_HYPERSPACE is also set for QuasiSpace } // In HyperSpace // Pre: inFullGame() BOOLEAN inHyperSpace (void) { //assert (inFullGame ()); return (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) && (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1); // IN_HYPERSPACE is also set for QuasiSpace } // In QuasiSpace // Pre: inFullGame() BOOLEAN inQuasiSpace (void) { //assert (inFullGame ()); return (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) && (GET_GAME_STATE (ARILOU_SPACE_SIDE) > 1); // IN_HYPERSPACE is also set for QuasiSpace }