diff --git a/sc2/doc/devel/queues b/sc2/doc/devel/queues index 9325221be..10035ae00 100644 --- a/sc2/doc/devel/queues +++ b/sc2/doc/devel/queues @@ -7,14 +7,14 @@ GlobData.Game_state.avail_race_q: It contains information about the various races, not really about specific ships. Filled in InitSIS(). - ShipInfo->RaceDescPtr is an actual pointer. - Several pointers point to within master_q (TODO: more info). + RaceDescPtr is an actual pointer, but to EXTENDED_SHIP_INFO + and not RACE_DESC Partially included in savegames. GlobData.Game_state.built_ship_q: The fleet accompanying the flagship. Elements are of type SHIP_FRAGMENT. - ShipInfo->RaceDescPtr is abused to store the captain's name index, + RaceDescPtr is abused to store the captain's name index. and the side that this ship is on (always GOOD_GUY here). Partially included in savegames. @@ -23,14 +23,14 @@ master_q: Elements are of type SHIP_FRAGMENT. Sorted on the (abbreviated) race name (see doc/racestrings). Filled in LoadMasterShipList(). - ShipInfo->RaceDescPtr is an actual pointer. + RaceDescPtr is an actual pointer, but to SHIP_INFO and not RACE_DESC GlobData.Game_state.npc_built_ship_q: The npc ships in an encounter. Empty when not in an encounter. Elements are of type SHIP_FRAGMENT. For encounters with an infinite number of ships, the queue consists of a single ship with ShipInfo.crew_level set to (BYTE)~0. - ShipInfo->RaceDescPtr is abused to store the captain's name index, + RaceDescPtr is abused to store the captain's name index. and the side that this ship is on. Partially included in savegames. @@ -38,7 +38,9 @@ race_q[NUM_PLAYERS]: Contains the ships participating in a battle for each player. Elements are of type STARSHIP. Filled in BuildBattle(). - ShipInfo->RaceDescPtr is abused to store the captain's name index, + RaceDescPtr is abused to store the captain's name index, + until the ship is loaded in spawn_ship(), at which time + it becomes an actual pointer to RACE_DESC. and the side that this ship is on. diff --git a/sc2/src/sc2code/build.c b/sc2/src/sc2code/build.c index 10f1d04f3..bd70c37ae 100644 --- a/sc2/src/sc2code/build.c +++ b/sc2/src/sc2code/build.c @@ -31,7 +31,8 @@ Build (QUEUE *pQueue, DWORD RaceResIndex, COUNT which_player, BYTE { HSTARSHIP hNewShip; - if ((hNewShip = AllocStarShip (pQueue)) != 0) + hNewShip = AllocStarShip (pQueue); + if (hNewShip != 0) { STARSHIP *StarShipPtr; @@ -256,7 +257,7 @@ ActivateStarShip (COUNT which_ship, SIZE state) HSTARSHIP hOldShip; SHIP_FRAGMENT *StarShipPtr; - hStarShip = CloneShipFragment ((COUNT) which_ship, + hStarShip = CloneShipFragment (which_ship, &GLOBAL (built_ship_q), 0); if (!hStarShip) break; diff --git a/sc2/src/sc2code/build.h b/sc2/src/sc2code/build.h index 1c7e0861f..1d6e7e9e6 100644 --- a/sc2/src/sc2code/build.h +++ b/sc2/src/sc2code/build.h @@ -71,9 +71,9 @@ extern COUNT GetIndexFromStarShip (QUEUE *pShipQ, HSTARSHIP hStarShip); extern int SetEscortCrewComplement (COUNT which_ship, COUNT crew_level, BYTE captain); -extern MEM_HANDLE load_ship (STARSHIP *StarShipPtr, BOOLEAN - LoadBattleData); -extern void free_ship (STARSHIP *StarShipPtr, BOOLEAN FreeBattleData); +extern RACE_DESC *load_ship (DWORD RaceResIndex, BOOLEAN LoadBattleData); +extern void free_ship (RACE_DESC *RaceDescPtr, BOOLEAN FreeIconData, + BOOLEAN FreeBattleData); extern void DrawCrewFuelString (COORD y, SIZE state); extern void ClearShipStatus (COORD y); diff --git a/sc2/src/sc2code/cyborg.c b/sc2/src/sc2code/cyborg.c index 706c471d8..637993849 100644 --- a/sc2/src/sc2code/cyborg.c +++ b/sc2/src/sc2code/cyborg.c @@ -1037,6 +1037,7 @@ tactical_intelligence (COUNT player, STARSHIP *StarShipPtr) } ShipMoved = TRUE; + /* Disable ship's special completely for the Standard AI */ if (PlayerControl[player] & STANDARD_RATING) ++StarShipPtr->special_counter; diff --git a/sc2/src/sc2code/encount.c b/sc2/src/sc2code/encount.c index fe62f04a3..96917e186 100644 --- a/sc2/src/sc2code/encount.c +++ b/sc2/src/sc2code/encount.c @@ -82,6 +82,7 @@ DoSelectAction (MENU_STATE *pMS) return (TRUE); } +// Called by comm code to intialize battle fleets during encounter void BuildBattle (COUNT which_player) { @@ -135,15 +136,19 @@ BuildBattle (COUNT which_player) if (hBuiltShip) { BuiltShipPtr = LockStarShip (&race_q[which_player], hBuiltShip); - BuiltShipPtr->captains_name_index = - StarShipCaptain (BuiltShipPtr); - BuiltShipPtr->cur_status_flags = - StarShipPlayer (BuiltShipPtr); + BuiltShipPtr->captains_name_index = StarShipCaptain (BuiltShipPtr); + BuiltShipPtr->which_side = StarShipPlayer (BuiltShipPtr); if (FragPtr->ShipInfo.crew_level != INFINITE_FLEET) - BuiltShipPtr->special_counter = FragPtr->ShipInfo.crew_level; + BuiltShipPtr->crew_level = FragPtr->ShipInfo.crew_level; else /* if infinite ships */ - BuiltShipPtr->special_counter = FragPtr->ShipInfo.max_crew; - BuiltShipPtr->RaceDescPtr = (RACE_DESC*)&FragPtr->ShipInfo; + BuiltShipPtr->crew_level = FragPtr->ShipInfo.max_crew; + BuiltShipPtr->max_crew = FragPtr->ShipInfo.max_crew; + BuiltShipPtr->race_strings = FragPtr->ShipInfo.race_strings; + BuiltShipPtr->icons = FragPtr->ShipInfo.icons; + BuiltShipPtr->index = FragPtr->ShipInfo.var2; + /* This is not technically necessary, but still */ + BuiltShipPtr->ship_cost = FragPtr->ShipInfo.ship_cost; + BuiltShipPtr->RaceDescPtr = 0; UnlockStarShip (&race_q[which_player], hBuiltShip); } @@ -156,11 +161,17 @@ BuildBattle (COUNT which_player) { BuiltShipPtr = LockStarShip (&race_q[0], hBuiltShip); BuiltShipPtr->captains_name_index = StarShipCaptain (BuiltShipPtr); - BuiltShipPtr->cur_status_flags = StarShipPlayer (BuiltShipPtr); - BuiltShipPtr->special_counter = 0; + BuiltShipPtr->which_side = StarShipPlayer (BuiltShipPtr); + BuiltShipPtr->crew_level = 0; + BuiltShipPtr->max_crew = 0; // Crew will be copied directly from // GLOBAL_SIS (CrewEnlisted) later. + BuiltShipPtr->race_strings = 0; + BuiltShipPtr->icons = 0; + BuiltShipPtr->index = -1; + BuiltShipPtr->ship_cost = 0; BuiltShipPtr->energy_counter = MAX_ENERGY_SIZE; + BuiltShipPtr->RaceDescPtr = 0; UnlockStarShip (&race_q[0], hBuiltShip); } } @@ -267,16 +278,16 @@ InitEncounter (void) {-44, -27}, }; - for (hStarShip = GetHeadLink (&race_q[1]), i = 0; + for (hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q)), i = 0; hStarShip && i < 60; hStarShip = hNextShip, ++i) { RECT r; - STARSHIP *StarShipPtr; + SHIP_FRAGMENT *FragPtr; - StarShipPtr = LockStarShip (&race_q[1], hStarShip); - if (StarShipPtr->RaceDescPtr->ship_info.crew_level != - INFINITE_FLEET) - hNextShip = _GetSuccLink (StarShipPtr); + FragPtr = (SHIP_FRAGMENT *) LockStarShip ( + &GLOBAL (npc_built_ship_q), hStarShip); + if (FragPtr->ShipInfo.crew_level != INFINITE_FLEET) + hNextShip = _GetSuccLink (FragPtr); else /* if infinite ships */ hNextShip = hStarShip; @@ -293,14 +304,13 @@ InitEncounter (void) s.origin.x = COSINE (angle, radius); s.origin.y = SINE (angle, radius); } - s.frame = SetAbsFrameIndex ( - StarShipPtr->RaceDescPtr->ship_info.icons, 0); + s.frame = SetAbsFrameIndex (FragPtr->ShipInfo.icons, 0); GetFrameRect (s.frame, &r); s.origin.x += (SIS_SCREEN_WIDTH >> 1) - (r.extent.width >> 1); s.origin.y += (SIS_SCREEN_HEIGHT >> 1) - (r.extent.height >> 1); DrawStamp (&s); - UnlockStarShip (&race_q[1], hStarShip); + UnlockStarShip (&GLOBAL (npc_built_ship_q), hStarShip); } } diff --git a/sc2/src/sc2code/globdata.c b/sc2/src/sc2code/globdata.c index 27d5a458a..cf2e35124 100644 --- a/sc2/src/sc2code/globdata.c +++ b/sc2/src/sc2code/globdata.c @@ -218,27 +218,30 @@ InitSIS (void) if (i < num_ships - 1) { HSTARSHIP hMasterShip; - STARSHIP *MasterShipPtr; + SHIP_FRAGMENT *MasterShipPtr; hMasterShip = FindMasterShip (ship_ref); - MasterShipPtr = LockStarShip (&master_q, hMasterShip); - FragPtr->ShipInfo = - ((SHIP_FRAGMENT*)MasterShipPtr)->ShipInfo; + MasterShipPtr = (SHIP_FRAGMENT *) LockStarShip (&master_q, + hMasterShip); + // Grab a copy of loaded icons and strings (not owned) + FragPtr->ShipInfo = MasterShipPtr->ShipInfo; UnlockStarShip (&master_q, hMasterShip); } else { // Ur-Quan probe. - load_ship ((STARSHIP*)FragPtr, FALSE); - FragPtr->ShipInfo = FragPtr->RaceDescPtr->ship_info; - FragPtr->RaceDescPtr->ship_info.melee_icon = 0; - FragPtr->RaceDescPtr->ship_info.icons = 0; - FragPtr->RaceDescPtr->ship_info.race_strings = 0; - free_ship ((STARSHIP*)FragPtr, FALSE); + RACE_DESC *RDPtr = load_ship (FragPtr->RaceResIndex, + FALSE); + if (RDPtr) + { // Grab a copy of loaded icons and strings + // avail_race_q owns these resources now + FragPtr->ShipInfo = RDPtr->ship_info; + free_ship (RDPtr, FALSE, FALSE); + } } - FragPtr->ShipInfo.ship_flags = BAD_GUY; ExtFragPtr = (EXTENDED_SHIP_FRAGMENT*)FragPtr; + ExtFragPtr->ShipInfo.ship_flags = BAD_GUY; ExtFragPtr->ShipInfo.known_strength = 0; ExtFragPtr->ShipInfo.known_loc = ExtFragPtr->ShipInfo.loc; if (FragPtr->ShipInfo.var2 == (BYTE)~0) @@ -252,7 +255,7 @@ InitSIS (void) ExtFragPtr->ShipInfo.growth_err_term = 255 >> 1; ExtFragPtr->ShipInfo.energy_level = 0; ExtFragPtr->ShipInfo.days_left = 0; - FragPtr->RaceDescPtr = (RACE_DESC*)&ExtFragPtr->ShipInfo; + ExtFragPtr->ExtShipInfoPtr = &ExtFragPtr->ShipInfo; UnlockStarShip (&GLOBAL (avail_race_q), hStarShip); } @@ -380,6 +383,8 @@ UninitSIS (void) // 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) { diff --git a/sc2/src/sc2code/init.c b/sc2/src/sc2code/init.c index 10289b727..12da22cc2 100644 --- a/sc2/src/sc2code/init.c +++ b/sc2/src/sc2code/init.c @@ -275,12 +275,12 @@ UninitShips (void) if (StarShipPtr->RaceDescPtr->uninit_func != NULL) (*StarShipPtr->RaceDescPtr->uninit_func) ( StarShipPtr->RaceDescPtr); - StarShipPtr->ShipFacing = - StarShipPtr->RaceDescPtr->ship_info.var2; - StarShipPtr->special_counter = + /* Record crew left after battle */ + StarShipPtr->crew_level = StarShipPtr->RaceDescPtr->ship_info.crew_level; SPtr[WHICH_SIDE (ElementPtr->state_flags)] = StarShipPtr; - free_ship (StarShipPtr, TRUE); + free_ship (StarShipPtr->RaceDescPtr, TRUE, TRUE); + StarShipPtr->RaceDescPtr = 0; } UnlockElement (hElement); } @@ -293,8 +293,10 @@ UninitShips (void) else if (LOBYTE (GLOBAL (CurrentActivity)) <= IN_ENCOUNTER && !(GLOBAL (CurrentActivity) & CHECK_ABORT)) { - // XXX: What is the reason for this? At least for SuperMelee, - // it has no purpose (it will return immediately). + // XXX: This has no purpose for SuperMelee + // In full-game, the sole purpose of this is to record the crew + // left in the last ship standing. The crew left is first recorded + // into STARSHIP.crew_level just a few lines above here. for (i = NUM_PLAYERS - 1; i >= 0; --i) { if (SPtr[i]) diff --git a/sc2/src/sc2code/loadship.c b/sc2/src/sc2code/loadship.c index 61173c8bd..c7df62472 100644 --- a/sc2/src/sc2code/loadship.c +++ b/sc2/src/sc2code/loadship.c @@ -23,134 +23,120 @@ #include "races.h" -MEM_HANDLE -load_ship (STARSHIP *StarShipPtr, BOOLEAN LoadBattleData) +RACE_DESC * +load_ship (DWORD RaceResIndex, BOOLEAN LoadBattleData) { - BOOLEAN retval; MEM_HANDLE h; - - h = OpenResourceIndexInstance (StarShipPtr->RaceResIndex); - - retval = FALSE; - if (h) - { + RACE_DESC *RDPtr = 0; #define INITIAL_CODE_RES MAKE_RESOURCE (1, CODE, 0) - BYTE captains_name_index; - void *CodeRef; - MEM_HANDLE hOldIndex; - COUNT which_player; + void *CodeRef; + MEM_HANDLE hOldIndex; - captains_name_index = StarShipCaptain (StarShipPtr); - which_player = StarShipPlayer (StarShipPtr); - hOldIndex = SetResourceIndex (h); + h = OpenResourceIndexInstance (RaceResIndex); + if (!h) + return 0; - CodeRef = CaptureCodeRes (LoadCodeRes (INITIAL_CODE_RES), - &GlobData, &StarShipPtr->RaceDescPtr); - if (CodeRef == 0) - goto BadLoad; - StarShipPtr->RaceDescPtr->CodeRef = CodeRef; + hOldIndex = SetResourceIndex (h); - StarShipPtr->RaceDescPtr->ship_info.icons = - CaptureDrawable (LoadGraphic ( - (RESOURCE)StarShipPtr->RaceDescPtr->ship_info.icons)); - if (StarShipPtr->RaceDescPtr->ship_info.icons == 0) - { - /* goto BadLoad */ - } - - StarShipPtr->RaceDescPtr->ship_info.melee_icon = - CaptureDrawable (LoadGraphic ( - (RESOURCE)StarShipPtr->RaceDescPtr->ship_info.melee_icon)); - if (StarShipPtr->RaceDescPtr->ship_info.melee_icon == 0) - { - /* goto BadLoad */ - } + CodeRef = CaptureCodeRes (LoadCodeRes (INITIAL_CODE_RES), + &GlobData, &RDPtr); + if (!CodeRef) + goto BadLoad; + RDPtr->CodeRef = CodeRef; - StarShipPtr->RaceDescPtr->ship_info.race_strings = - CaptureStringTable (LoadStringTable ( - (RESOURCE)StarShipPtr->RaceDescPtr->ship_info.race_strings)); - if (StarShipPtr->RaceDescPtr->ship_info.race_strings == 0) - { - /* goto BadLoad */ - } - - if (LoadBattleData) - { - DATA_STUFF *RawPtr; - - StarShipPtr->captains_name_index = captains_name_index; - StarShipPtr->RaceDescPtr->ship_info.ship_flags |= which_player; - - RawPtr = &StarShipPtr->RaceDescPtr->ship_data; - if (!load_animation (RawPtr->ship, - (RESOURCE)RawPtr->ship[0], - (RESOURCE)RawPtr->ship[1], - (RESOURCE)RawPtr->ship[2])) - goto BadLoad; - - if (RawPtr->weapon[0] != 0) - { - if (!load_animation (RawPtr->weapon, - (RESOURCE)RawPtr->weapon[0], - (RESOURCE)RawPtr->weapon[1], - (RESOURCE)RawPtr->weapon[2])) - goto BadLoad; - } - - if (RawPtr->special[0] != 0) - { - if (!load_animation (RawPtr->special, - (RESOURCE)RawPtr->special[0], - (RESOURCE)RawPtr->special[1], - (RESOURCE)RawPtr->special[2])) - goto BadLoad; - } - - if (RawPtr->captain_control.background != 0) - { - RawPtr->captain_control.background = - CaptureDrawable (LoadGraphic ( - (RESOURCE)RawPtr->captain_control.background)); - if (RawPtr->captain_control.background == 0) - goto BadLoad; - } - - if (RawPtr->victory_ditty != 0) - { - RawPtr->victory_ditty = - LoadMusic ((RESOURCE)RawPtr->victory_ditty); - if (RawPtr->victory_ditty == 0) - goto BadLoad; - } - - if (RawPtr->ship_sounds != 0) - { - RawPtr->ship_sounds = CaptureSound ( - LoadSound ((RESOURCE)RawPtr->ship_sounds)); - if (RawPtr->ship_sounds == 0) - goto BadLoad; - } - - if (StarShipPtr->RaceDescPtr->ship_info.icons) - StarShipPtr->silhouette = IncFrameIndex ( - StarShipPtr->RaceDescPtr->ship_info.icons); - } - - retval = TRUE; -BadLoad: - SetResourceIndex (hOldIndex); - CloseResourceIndex (h); + RDPtr->ship_info.icons = CaptureDrawable (LoadGraphic ( + (RESOURCE)RDPtr->ship_info.icons)); + if (!RDPtr->ship_info.icons) + { + /* goto BadLoad */ + } + + RDPtr->ship_info.melee_icon = CaptureDrawable (LoadGraphic ( + (RESOURCE)RDPtr->ship_info.melee_icon)); + if (!RDPtr->ship_info.melee_icon) + { + /* goto BadLoad */ } - return (retval); + RDPtr->ship_info.race_strings = CaptureStringTable (LoadStringTable ( + (RESOURCE)RDPtr->ship_info.race_strings)); + if (!RDPtr->ship_info.race_strings) + { + /* goto BadLoad */ + } + + if (LoadBattleData) + { + DATA_STUFF *RawPtr = &RDPtr->ship_data; + if (!load_animation (RawPtr->ship, + (RESOURCE)RawPtr->ship[0], + (RESOURCE)RawPtr->ship[1], + (RESOURCE)RawPtr->ship[2])) + goto BadLoad; + + if (RawPtr->weapon[0] != 0) + { + if (!load_animation (RawPtr->weapon, + (RESOURCE)RawPtr->weapon[0], + (RESOURCE)RawPtr->weapon[1], + (RESOURCE)RawPtr->weapon[2])) + goto BadLoad; + } + + if (RawPtr->special[0] != 0) + { + if (!load_animation (RawPtr->special, + (RESOURCE)RawPtr->special[0], + (RESOURCE)RawPtr->special[1], + (RESOURCE)RawPtr->special[2])) + goto BadLoad; + } + + if (RawPtr->captain_control.background != 0) + { + RawPtr->captain_control.background = CaptureDrawable (LoadGraphic ( + (RESOURCE)RawPtr->captain_control.background)); + if (!RawPtr->captain_control.background) + goto BadLoad; + } + + if (RawPtr->victory_ditty != 0) + { + RawPtr->victory_ditty = + LoadMusic ((RESOURCE)RawPtr->victory_ditty); + if (!RawPtr->victory_ditty) + goto BadLoad; + } + + if (RawPtr->ship_sounds != 0) + { + RawPtr->ship_sounds = CaptureSound ( + LoadSound ((RESOURCE)RawPtr->ship_sounds)); + if (!RawPtr->ship_sounds) + goto BadLoad; + } + } + +ExitFunc: + SetResourceIndex (hOldIndex); + CloseResourceIndex (h); + + return RDPtr; + + // TODO: We should really free the resources that did load here +BadLoad: + if (CodeRef) + DestroyCodeRes (ReleaseCodeRes (CodeRef)); + + RDPtr = 0; /* failed */ + + goto ExitFunc; } void -free_ship (STARSHIP *StarShipPtr, BOOLEAN FreeBattleData) +free_ship (RACE_DESC *raceDescPtr, BOOLEAN FreeIconData, + BOOLEAN FreeBattleData) { - RACE_DESC *raceDescPtr = StarShipPtr->RaceDescPtr; - SHIP_INFO *shipInfo = &raceDescPtr->ship_info; - if (FreeBattleData) { DATA_STUFF *shipData = &raceDescPtr->ship_data; @@ -165,13 +151,16 @@ free_ship (STARSHIP *StarShipPtr, BOOLEAN FreeBattleData) DestroySound (ReleaseSound (shipData->ship_sounds)); } - DestroyDrawable (ReleaseDrawable (shipInfo->melee_icon)); - DestroyDrawable (ReleaseDrawable (shipInfo->icons)); - DestroyStringTable (ReleaseStringTable (shipInfo->race_strings)); + if (FreeIconData) + { + SHIP_INFO *shipInfo = &raceDescPtr->ship_info; + + DestroyDrawable (ReleaseDrawable (shipInfo->melee_icon)); + DestroyDrawable (ReleaseDrawable (shipInfo->icons)); + DestroyStringTable (ReleaseStringTable (shipInfo->race_strings)); + } DestroyCodeRes (ReleaseCodeRes (raceDescPtr->CodeRef)); - - StarShipPtr->RaceDescPtr = 0; } diff --git a/sc2/src/sc2code/master.c b/sc2/src/sc2code/master.c index 7f8c2dbd3..b2d199284 100644 --- a/sc2/src/sc2code/master.c +++ b/sc2/src/sc2code/master.c @@ -42,57 +42,60 @@ LoadMasterShipList (void (* YieldProcessing)(void)) while (num_entries--) { HSTARSHIP hBuiltShip; + char built_buf[30]; + HSTARSHIP hStarShip, hNextShip; + SHIP_FRAGMENT *BuiltFragPtr; + RACE_DESC *RDPtr; hBuiltShip = Build (&master_q, MAKE_RESOURCE (rp++, rt, ri++), 0, 0); - if (hBuiltShip) + if (!hBuiltShip) + continue; + + // Allow other things to run + // supposedly, loading ship packages and data takes some time + if (YieldProcessing) + YieldProcessing (); + + BuiltFragPtr = (SHIP_FRAGMENT *) LockStarShip (&master_q, hBuiltShip); + RDPtr = load_ship (BuiltFragPtr->RaceResIndex, FALSE); + if (!RDPtr) { - char built_buf[30]; - HSTARSHIP hStarShip, hNextShip; - STARSHIP *BuiltShipPtr; - SHIP_INFO *ShipInfoPtr; - - // Allow other things to run - // supposedly, loading ship packages and data takes some time - if (YieldProcessing) - YieldProcessing (); - - BuiltShipPtr = LockStarShip (&master_q, hBuiltShip); - load_ship (BuiltShipPtr, FALSE); - ShipInfoPtr = &((SHIP_FRAGMENT*)BuiltShipPtr)->ShipInfo; - *ShipInfoPtr = BuiltShipPtr->RaceDescPtr->ship_info; - BuiltShipPtr->RaceDescPtr->ship_info.melee_icon = 0; - BuiltShipPtr->RaceDescPtr->ship_info.icons = 0; - BuiltShipPtr->RaceDescPtr->ship_info.race_strings = 0; - free_ship (BuiltShipPtr, FALSE); - BuiltShipPtr->RaceDescPtr = (RACE_DESC*)ShipInfoPtr; - - GetStringContents (SetAbsStringTableIndex ( - BuiltShipPtr->RaceDescPtr->ship_info.race_strings, 2 - ), (STRINGPTR)built_buf, FALSE); UnlockStarShip (&master_q, hBuiltShip); - RemoveQueue (&master_q, hBuiltShip); - - // Insert the ship in the master queue in the right location - // to keep the list sorted on the name of the race. - for (hStarShip = GetHeadLink (&master_q); - hStarShip; hStarShip = hNextShip) - { - char ship_buf[30]; - STARSHIP *StarShipPtr; - - StarShipPtr = LockStarShip (&master_q, hStarShip); - hNextShip = _GetSuccLink (StarShipPtr); - GetStringContents (SetAbsStringTableIndex ( - StarShipPtr->RaceDescPtr->ship_info.race_strings, 2 - ), (STRINGPTR)ship_buf, FALSE); - UnlockStarShip (&master_q, hStarShip); - - if (strcmp (built_buf, ship_buf) < 0) - break; - } - InsertQueue (&master_q, hBuiltShip, hStarShip); + continue; } + + // Grab a copy of loaded icons and strings + BuiltFragPtr->ShipInfo = RDPtr->ship_info; + free_ship (RDPtr, FALSE, FALSE); + BuiltFragPtr->ShipInfoPtr = &BuiltFragPtr->ShipInfo; + + GetStringContents (SetAbsStringTableIndex ( + BuiltFragPtr->ShipInfo.race_strings, 2 + ), (STRINGPTR)built_buf, FALSE); + UnlockStarShip (&master_q, hBuiltShip); + + RemoveQueue (&master_q, hBuiltShip); + + // Insert the ship in the master queue in the right location + // to keep the list sorted on the name of the race. + for (hStarShip = GetHeadLink (&master_q); + hStarShip; hStarShip = hNextShip) + { + char ship_buf[30]; + SHIP_FRAGMENT *FragPtr; + + FragPtr = (SHIP_FRAGMENT *) LockStarShip (&master_q, hStarShip); + hNextShip = _GetSuccLink (FragPtr); + GetStringContents (SetAbsStringTableIndex ( + FragPtr->ShipInfo.race_strings, 2 + ), (STRINGPTR)ship_buf, FALSE); + UnlockStarShip (&master_q, hStarShip); + + if (strcmp (built_buf, ship_buf) < 0) + break; + } + InsertQueue (&master_q, hBuiltShip, hStarShip); } } @@ -104,17 +107,15 @@ FreeMasterShipList (void) for (hStarShip = GetHeadLink (&master_q); hStarShip != 0; hStarShip = hNextShip) { - STARSHIP *StarShipPtr; + SHIP_FRAGMENT *FragPtr; - StarShipPtr = LockStarShip (&master_q, hStarShip); - hNextShip = _GetSuccLink (StarShipPtr); + FragPtr = (SHIP_FRAGMENT *) LockStarShip (&master_q, hStarShip); + hNextShip = _GetSuccLink (FragPtr); - DestroyDrawable (ReleaseDrawable ( - StarShipPtr->RaceDescPtr->ship_info.melee_icon)); - DestroyDrawable (ReleaseDrawable ( - StarShipPtr->RaceDescPtr->ship_info.icons)); + DestroyDrawable (ReleaseDrawable (FragPtr->ShipInfo.melee_icon)); + DestroyDrawable (ReleaseDrawable (FragPtr->ShipInfo.icons)); DestroyStringTable (ReleaseStringTable ( - StarShipPtr->RaceDescPtr->ship_info.race_strings)); + FragPtr->ShipInfo.race_strings)); UnlockStarShip (&master_q, hStarShip); } @@ -126,26 +127,20 @@ HSTARSHIP FindMasterShip (DWORD ship_ref) { HSTARSHIP hStarShip; + HSTARSHIP hNextShip; - hStarShip = GetHeadLink (&master_q); - if (hStarShip) + for (hStarShip = GetHeadLink (&master_q); hStarShip; hStarShip = hNextShip) { - do - { - DWORD ref; - HSTARSHIP hNextShip; - STARSHIP *StarShipPtr; + DWORD ref; + SHIP_FRAGMENT *FragPtr; - StarShipPtr = LockStarShip (&master_q, hStarShip); - hNextShip = _GetSuccLink (StarShipPtr); - ref = StarShipPtr->RaceResIndex; - UnlockStarShip (&master_q, hStarShip); + FragPtr = (SHIP_FRAGMENT *) LockStarShip (&master_q, hStarShip); + hNextShip = _GetSuccLink (FragPtr); + ref = FragPtr->RaceResIndex; + UnlockStarShip (&master_q, hStarShip); - if (ref == ship_ref) - break; - - hStarShip = hNextShip; - } while (hStarShip); + if (ref == ship_ref) + break; } return (hStarShip); diff --git a/sc2/src/sc2code/melee.c b/sc2/src/sc2code/melee.c index b9dfa46b7..91f701f24 100644 --- a/sc2/src/sc2code/melee.c +++ b/sc2/src/sc2code/melee.c @@ -2128,11 +2128,17 @@ BuildAndDrawShipList (MELEE_STATE *pMS) UnlockStarShip (&master_q, hStarShip); BuiltShipPtr = LockStarShip (&race_q[side], hBuiltShip); - BuiltShipPtr->ShipFacing = index; - BuiltShipPtr->special_counter = ship_cost; + BuiltShipPtr->index = index; + BuiltShipPtr->ship_cost = ship_cost; + BuiltShipPtr->which_side = 1 << side; BuiltShipPtr->captains_name_index = StarShipCaptain (BuiltShipPtr); - BuiltShipPtr->RaceDescPtr = StarShipPtr->RaceDescPtr; + // The next ones are not used in Melee + BuiltShipPtr->crew_level = 0; + BuiltShipPtr->max_crew = 0; + BuiltShipPtr->race_strings = 0; + BuiltShipPtr->icons = 0; + BuiltShipPtr->RaceDescPtr = 0; UnlockStarShip (&race_q[side], hBuiltShip); } } diff --git a/sc2/src/sc2code/pickmele.c b/sc2/src/sc2code/pickmele.c index 8983d67a9..9fcd4d039 100644 --- a/sc2/src/sc2code/pickmele.c +++ b/sc2/src/sc2code/pickmele.c @@ -85,7 +85,7 @@ MeleeShipByQueueIndex (const QUEUE *queue, COUNT index) for (hShip = GetHeadLink (queue); hShip != 0; hShip = hNextShip) { STARSHIP *StarShipPtr = LockStarShip (queue, hShip); - if (StarShipPtr->ShipFacing == index) + if (StarShipPtr->index == index) { hNextShip = hShip; if (StarShipPtr->RaceResIndex == 0) @@ -128,7 +128,7 @@ queueIndexFromShip (HSTARSHIP hShip) { COUNT result; STARSHIP *StarShipPtr = LockStarShip (queue, hShip); - result = StarShipPtr->ShipFacing; + result = StarShipPtr->index; UnlockStarShip (queue, hShip); } #endif @@ -380,7 +380,7 @@ GetRaceQueueValue (const QUEUE *queue) { if (StarShipPtr->RaceResIndex == 0) continue; // Not active any more. - result += StarShipPtr->special_counter; + result += StarShipPtr->ship_cost; UnlockStarShip (queue, hBattleShip); } @@ -517,7 +517,7 @@ MeleeShipDeath (STARSHIP *ship, COUNT which_player) { ship->RaceResIndex = 0; frame = SetAbsFrameIndex (PickMeleeFrame, which_player); - CrossOutShip (frame, ship->ShipFacing); + CrossOutShip (frame, ship->index); UpdatePickMeleeFleetValue (frame, which_player); if (battle_counter[0] == 0 || battle_counter[1] == 0) diff --git a/sc2/src/sc2code/pickship.c b/sc2/src/sc2code/pickship.c index 972c4fda4..b105f0021 100644 --- a/sc2/src/sc2code/pickship.c +++ b/sc2/src/sc2code/pickship.c @@ -146,9 +146,8 @@ ChangeSelection: hBattleShip = hNextShip) { StarShipPtr = LockStarShip (&race_q[0], hBattleShip); - if ((COUNT)LONIBBLE ( - StarShipPtr->RaceDescPtr->ship_info.var2 - ) == ship_index && StarShipPtr->RaceResIndex) + if (StarShipPtr->index == ship_index + && StarShipPtr->RaceResIndex) { UnlockStarShip (&race_q[0], hBattleShip); break; @@ -198,12 +197,12 @@ ChangeSelection: STRING locString; locString = SetAbsStringTableIndex ( - StarShipPtr->RaceDescPtr->ship_info.race_strings, + StarShipPtr->race_strings, StarShipPtr->captains_name_index); t.pStr = (UNICODE *)GetStringAddress (locString); t.CharCount = GetStringLength (locString); - crew_level = StarShipPtr->RaceDescPtr->ship_info.crew_level; - max_crew = StarShipPtr->RaceDescPtr->ship_info.max_crew; + crew_level = StarShipPtr->crew_level; + max_crew = StarShipPtr->max_crew; } UnlockStarShip (&race_q[0], hBattleShip); @@ -314,11 +313,9 @@ GetEncounterStarShip (STARSHIP *LastStarShipPtr, COUNT which_player) if (!(GLOBAL (CurrentActivity) & IN_BATTLE)) { - // XXX: This check should not be needed, but Uninitships() - // calls this function after the battle is over for some - // reason. Perhaps because one of the non-supermelee cases. - // (Note that the reason isn't to display the battle - // summary; that has already been done). + // XXX: This check is needed, because UninitShips() calls + // this function after the battle is over to record + // the crew left in the last ship standing. hBattleShip = 0; } else if (!MeleeShipDeath (LastStarShipPtr, which_player)) @@ -387,16 +384,20 @@ GetEncounterStarShip (STARSHIP *LastStarShipPtr, COUNT which_player) { if (FragPtr->ShipInfo.crew_level != INFINITE_FLEET) { - FragPtr->ShipInfo.crew_level = SPtr->special_counter; - SPtr->RaceDescPtr = (RACE_DESC*)&FragPtr->ShipInfo; + /* Record crew left after the battle */ + FragPtr->ShipInfo.crew_level = SPtr->crew_level; if (GLOBAL (CurrentActivity) & IN_BATTLE) SPtr->RaceResIndex = 0; + // deactivates the ship } else /* if infinite ships */ { hBattleShip = GetTailLink (&race_q[which_player]); - SPtr->special_counter = FragPtr->ShipInfo.max_crew; - SPtr->cur_status_flags = 1 << which_player; + /* XXX: Note that if Syreen had a homeworld you could + * fight, all Syreen ships there would be crewed to + * the maximum, instead of the normal level */ + SPtr->crew_level = FragPtr->ShipInfo.max_crew; + SPtr->which_side = 1 << which_player; SPtr->captains_name_index = PickCaptainName (); battle_counter[1]++; @@ -417,7 +418,7 @@ GetEncounterStarShip (STARSHIP *LastStarShipPtr, COUNT which_player) { #define RUN_AWAY_FUEL_COST (5 * FUEL_TANK_SCALE) hBattleShip = 0; - if (LastStarShipPtr->special_counter == 0) + if (LastStarShipPtr->crew_level == 0) { /* Died in the line of duty */ GLOBAL_SIS (CrewEnlisted) = (COUNT)~0; @@ -434,10 +435,11 @@ GetEncounterStarShip (STARSHIP *LastStarShipPtr, COUNT which_player) } } + // XXX: STARSHIP refactor; this whole thing is not really needed anymore if (hBattleShip) { SPtr = LockStarShip (&race_q[which_player], hBattleShip); - OwnStarShip (SPtr, SPtr->cur_status_flags, + OwnStarShip (SPtr, SPtr->which_side, SPtr->captains_name_index); UnlockStarShip (&race_q[which_player], hBattleShip); } @@ -513,11 +515,10 @@ DrawArmadaPickShip (BOOLEAN draw_salvage_frame, RECT *pPickRect) StarShipPtr = LockStarShip (&race_q[0], hBattleShip); if (StarShipPtr->captains_name_index) - { + { // Escort ship, not SIS COUNT ship_index; - ship_index = (COUNT)LONIBBLE ( - StarShipPtr->RaceDescPtr->ship_info.var2); + ship_index = StarShipPtr->index; s.origin.x = pick_r.corner.x + (5 + ((ICON_WIDTH + 4) @@ -528,12 +529,11 @@ DrawArmadaPickShip (BOOLEAN draw_salvage_frame, RECT *pPickRect) s.origin.y = pick_r.corner.y + (16 + ((ICON_HEIGHT + 4) * (ship_index / NUM_PICK_SHIP_COLUMNS))); - s.frame = StarShipPtr->RaceDescPtr->ship_info.icons; + s.frame = StarShipPtr->icons; r.corner = s.origin; SetContextForeGroundColor (BLACK_COLOR); DrawFilledRectangle (&r); - if (StarShipPtr->RaceResIndex - || StarShipPtr->RaceDescPtr->ship_info.crew_level == 0) + if (StarShipPtr->RaceResIndex || StarShipPtr->crew_level == 0) { DrawStamp (&s); if (StarShipPtr->RaceResIndex == 0) diff --git a/sc2/src/sc2code/races.h b/sc2/src/sc2code/races.h index 668ee8d12..9cf8f9d65 100644 --- a/sc2/src/sc2code/races.h +++ b/sc2/src/sc2code/races.h @@ -25,6 +25,7 @@ #include "libs/sndlib.h" +// TODO: remove RACES_PER_PLAYER remnant of SC1 #define RACES_PER_PLAYER 7 #define MAX_SHIPS_PER_SIDE 14 @@ -265,7 +266,8 @@ typedef QUEUE_HANDLE HSTARSHIP; * to each other in many places. Some of those are unsafe and potentially * destructive if the code is changed later. * Currently, the first 4 members of each struct MUST remain the same, - * the first 2 being the queue links. + * the first 2 being the queue links. Functions Build() and CloneShipFragment() + * expect these 4 members to be there. */ typedef struct { @@ -288,20 +290,37 @@ typedef struct } s; }; + // Ship information BYTE captains_name_index; + // Also used in full-game to detect if a STARSHIP is an escort + // or the flagship (captains_name_index == 0) + BYTE crew_level; + // In full-game battles: crew left + // In SuperMelee: irrelevant + COUNT max_crew; + BYTE ship_cost; + // In Super Melee ship queue: ship cost + // In full-game: irrelevant + UWORD which_side; + // In race_q: side the ship is on + COUNT index; + // original queue index + STRING race_strings; + FRAME icons; + + // Battle states BYTE weapon_counter; + // In battle: frames left before primary weapon can be used BYTE special_counter; - // In the ship queue: Ship cost - // In between battles: crew left - // In battle: ship dependant + // In battle: frames left before special can be used BYTE energy_counter; + // In battle: frames left before energy regeneration BYTE ship_input_state; UWORD cur_status_flags _ALIGNED_ON(sizeof (UWORD)); UWORD old_status_flags _ALIGNED_ON(sizeof (UWORD)); - FRAME silhouette _ALIGNED_ON(sizeof (FRAME)); HELEMENT hShip _ALIGNED_ON(sizeof (HELEMENT)); COUNT ShipFacing _ALIGNED_ON(sizeof (COUNT)); } STARSHIP; @@ -320,7 +339,10 @@ typedef struct * the ship (accessed through StarShipCaptain()). * These values are set using OwnStarShip(). */ union { + // TODO: make RaceDescPtr inaccessible RACE_DESC *RaceDescPtr; + SHIP_INFO *ShipInfoPtr; + EXTENDED_SHIP_INFO *ExtShipInfoPtr; struct { COUNT Player; BYTE Captain; @@ -342,7 +364,12 @@ typedef struct * instead of a RACE_DESC when GLOBAL(avail_race_q) is initialized * [see InitSIS]. For this reason, RACE_DESC must maintain a SHIP_INFO * as the first member. */ - RACE_DESC *RaceDescPtr; + union { + // TODO: make RaceDescPtr inaccessible + RACE_DESC *RaceDescPtr; + SHIP_INFO *ShipInfoPtr; + EXTENDED_SHIP_INFO *ExtShipInfoPtr; + }; EXTENDED_SHIP_INFO ShipInfo; } EXTENDED_SHIP_FRAGMENT; diff --git a/sc2/src/sc2code/ship.c b/sc2/src/sc2code/ship.c index 559a7e15c..2151059a6 100644 --- a/sc2/src/sc2code/ship.c +++ b/sc2/src/sc2code/ship.c @@ -380,11 +380,16 @@ spawn_ship (STARSHIP *StarShipPtr) HELEMENT hShip; RACE_DESC *RDPtr; - if (!load_ship (StarShipPtr, TRUE)) - return (FALSE); + RDPtr = load_ship (StarShipPtr->RaceResIndex, TRUE); + if (!RDPtr) + return FALSE; - RDPtr = StarShipPtr->RaceDescPtr; - RDPtr->ship_info.var2 = (BYTE)StarShipPtr->ShipFacing; + // XXX: Ship captain and side are stored in RaceDescPtr, so + // get them first + StarShipPtr->captains_name_index = StarShipCaptain (StarShipPtr); + RDPtr->ship_info.ship_flags |= StarShipPlayer (StarShipPtr); + + StarShipPtr->RaceDescPtr = RDPtr; StarShipPtr->ship_input_state = 0; StarShipPtr->cur_status_flags = 0; @@ -393,13 +398,13 @@ spawn_ship (STARSHIP *StarShipPtr) if (LOBYTE (GLOBAL (CurrentActivity)) == IN_ENCOUNTER || LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) { - if (StarShipPtr->special_counter == 0) + if (StarShipPtr->crew_level == 0) { // SIS, already handled from sis_ship.c. // RDPtr->ship_info.crew_level = GLOBAL_SIS (CrewEnlisted); } else - RDPtr->ship_info.crew_level = StarShipPtr->special_counter; + RDPtr->ship_info.crew_level = StarShipPtr->crew_level; if (RDPtr->ship_info.crew_level > RDPtr->ship_info.max_crew) RDPtr->ship_info.crew_level = RDPtr->ship_info.max_crew; diff --git a/sc2/src/sc2code/tactrans.c b/sc2/src/sc2code/tactrans.c index 692c48641..70b19c416 100644 --- a/sc2/src/sc2code/tactrans.c +++ b/sc2/src/sc2code/tactrans.c @@ -241,11 +241,10 @@ new_ship (ELEMENT *DeadShipPtr) BOOLEAN MusicStarted; HELEMENT hElement, hSuccElement; - DeadStarShipPtr->ShipFacing = - DeadStarShipPtr->RaceDescPtr->ship_info.var2; - DeadStarShipPtr->special_counter = + /* Record crew left after the battle */ + DeadStarShipPtr->crew_level = DeadStarShipPtr->RaceDescPtr->ship_info.crew_level; - if (DeadStarShipPtr->special_counter) + if (DeadStarShipPtr->crew_level) { // We've just warped out. new_ship() will still be called // a few times, to process the trace left behind (I assume). @@ -336,7 +335,8 @@ new_ship (ELEMENT *DeadShipPtr) if (DeadStarShipPtr->RaceDescPtr->uninit_func != NULL) (*DeadStarShipPtr->RaceDescPtr->uninit_func) ( DeadStarShipPtr->RaceDescPtr); - free_ship (DeadStarShipPtr, TRUE); + free_ship (DeadStarShipPtr->RaceDescPtr, TRUE, TRUE); + DeadStarShipPtr->RaceDescPtr = 0; UnbatchGraphics (); #ifdef NETPLAY diff --git a/sc2/src/sc2code/weapon.c b/sc2/src/sc2code/weapon.c index 993e7119b..b3ccd5def 100644 --- a/sc2/src/sc2code/weapon.c +++ b/sc2/src/sc2code/weapon.c @@ -251,7 +251,8 @@ ModifySilhouette (ELEMENT *ElementPtr, STAMP *modify_stamp, GetElementStarShip (ElementPtr, &StarShipPtr); if (modify_flags & MODIFY_IMAGE) { - ShipIntersect.IntersectStamp.frame = StarShipPtr->silhouette; + ShipIntersect.IntersectStamp.frame = SetAbsFrameIndex ( + StarShipPtr->RaceDescPtr->ship_info.icons, 1); if (ShipIntersect.IntersectStamp.frame == 0) return (0);