diff options
Diffstat (limited to 'src/uqm/planets/generate/gendefault.c')
-rw-r--r-- | src/uqm/planets/generate/gendefault.c | 373 |
1 files changed, 373 insertions, 0 deletions
diff --git a/src/uqm/planets/generate/gendefault.c b/src/uqm/planets/generate/gendefault.c new file mode 100644 index 0000000..a88b89c --- /dev/null +++ b/src/uqm/planets/generate/gendefault.c @@ -0,0 +1,373 @@ +/* + * 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 "genall.h" +#include "../planets.h" +#include "../lander.h" +#include "../../encount.h" +#include "../../gamestr.h" +#include "../../globdata.h" +#include "../../grpinfo.h" +#include "../../races.h" +#include "../../state.h" +#include "../../sounds.h" +#include "libs/mathlib.h" + + +static void GeneratePlanets (SOLARSYS_STATE *system); +static void check_yehat_rebellion (void); + + +const GenerateFunctions generateDefaultFunctions = { + /* .initNpcs = */ GenerateDefault_initNpcs, + /* .reinitNpcs = */ GenerateDefault_reinitNpcs, + /* .uninitNpcs = */ GenerateDefault_uninitNpcs, + /* .generatePlanets = */ GenerateDefault_generatePlanets, + /* .generateMoons = */ GenerateDefault_generateMoons, + /* .generateName = */ GenerateDefault_generateName, + /* .generateOrbital = */ GenerateDefault_generateOrbital, + /* .generateMinerals = */ GenerateDefault_generateMinerals, + /* .generateEnergy = */ GenerateDefault_generateEnergy, + /* .generateLife = */ GenerateDefault_generateLife, + /* .pickupMinerals = */ GenerateDefault_pickupMinerals, + /* .pickupEnergy = */ GenerateDefault_pickupEnergy, + /* .pickupLife = */ GenerateDefault_pickupLife, +}; + + +bool +GenerateDefault_initNpcs (SOLARSYS_STATE *solarSys) +{ + if (!GetGroupInfo (GLOBAL (BattleGroupRef), GROUP_INIT_IP)) + { + GLOBAL (BattleGroupRef) = 0; + BuildGroups (); + } + + (void) solarSys; + return true; +} + +bool +GenerateDefault_reinitNpcs (SOLARSYS_STATE *solarSys) +{ + GetGroupInfo (GROUPS_RANDOM, GROUP_LOAD_IP); + // This is not a great place to do the Yehat rebellion check, but + // since you can start the rebellion in any star system (not just + // the Homeworld), I could not find a better place for it. + // At least it is better than where it was originally. + check_yehat_rebellion (); + + (void) solarSys; + return true; +} + +bool +GenerateDefault_uninitNpcs (SOLARSYS_STATE *solarSys) +{ + PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); + ReinitQueue (&GLOBAL (npc_built_ship_q)); + ReinitQueue (&GLOBAL (ip_group_q)); + + (void) solarSys; + return true; +} + +bool +GenerateDefault_generatePlanets (SOLARSYS_STATE *solarSys) +{ + FillOrbits (solarSys, (BYTE)~0, solarSys->PlanetDesc, FALSE); + GeneratePlanets (solarSys); + return true; +} + +bool +GenerateDefault_generateMoons (SOLARSYS_STATE *solarSys, PLANET_DESC *planet) +{ + FillOrbits (solarSys, planet->NumPlanets, solarSys->MoonDesc, FALSE); + return true; +} + +bool +GenerateDefault_generateName (const SOLARSYS_STATE *solarSys, + const PLANET_DESC *world) +{ + COUNT i = planetIndex (solarSys, world); + utf8StringCopy (GLOBAL_SIS (PlanetName), sizeof (GLOBAL_SIS (PlanetName)), + GAME_STRING (PLANET_NUMBER_BASE + (9 + 7) + i)); + SET_GAME_STATE (BATTLE_PLANET, world->data_index); + + return true; +} + +bool +GenerateDefault_generateOrbital (SOLARSYS_STATE *solarSys, PLANET_DESC *world) +{ + DWORD rand_val; + SYSTEM_INFO *sysInfo; + +#ifdef DEBUG_SOLARSYS + if (worldIsPlanet (solarSys, world)) + { + log_add (log_Debug, "Planet index = %d", + planetIndex (solarSys, world)); + } + else + { + log_add (log_Debug, "Planet index = %d, Moon index = %d", + planetIndex (solarSys, world), + moonIndex (solarSys, world)); + } +#endif /* DEBUG_SOLARSYS */ + + sysInfo = &solarSys->SysInfo; + + DoPlanetaryAnalysis (sysInfo, world); + rand_val = RandomContext_GetSeed (SysGenRNG); + + sysInfo->PlanetInfo.ScanSeed[BIOLOGICAL_SCAN] = rand_val; + GenerateLifeForms (sysInfo, GENERATE_ALL, NULL); + rand_val = RandomContext_GetSeed (SysGenRNG); + + sysInfo->PlanetInfo.ScanSeed[MINERAL_SCAN] = rand_val; + GenerateMineralDeposits (sysInfo, GENERATE_ALL, NULL); + + sysInfo->PlanetInfo.ScanSeed[ENERGY_SCAN] = rand_val; + LoadPlanet (NULL); + + return true; +} + +COUNT +GenerateDefault_generateMinerals (const SOLARSYS_STATE *solarSys, + const PLANET_DESC *world, COUNT whichNode, NODE_INFO *info) +{ + return GenerateMineralDeposits (&solarSys->SysInfo, whichNode, info); + (void) world; +} + +bool +GenerateDefault_pickupMinerals (SOLARSYS_STATE *solarSys, PLANET_DESC *world, + COUNT whichNode) +{ + // Minerals do not need any extra handling as of now + (void) solarSys; + (void) world; + (void) whichNode; + return true; +} + +COUNT +GenerateDefault_generateEnergy (const SOLARSYS_STATE *solarSys, + const PLANET_DESC *world, COUNT whichNode, NODE_INFO *info) +{ + (void) whichNode; + (void) solarSys; + (void) world; + (void) info; + return 0; +} + +bool +GenerateDefault_pickupEnergy (SOLARSYS_STATE *solarSys, PLANET_DESC *world, + COUNT whichNode) +{ + // This should never be called since every energy node needs + // special handling and the function should be overridden + assert (false); + (void) solarSys; + (void) world; + (void) whichNode; + return false; +} + +COUNT +GenerateDefault_generateLife (const SOLARSYS_STATE *solarSys, + const PLANET_DESC *world, COUNT whichNode, NODE_INFO *info) +{ + return GenerateLifeForms (&solarSys->SysInfo, whichNode, info); + (void) world; +} + +bool +GenerateDefault_pickupLife (SOLARSYS_STATE *solarSys, PLANET_DESC *world, + COUNT whichNode) +{ + // Bio does not need any extra handling as of now + (void) solarSys; + (void) world; + (void) whichNode; + return true; +} + +COUNT +GenerateDefault_generateArtifact (const SOLARSYS_STATE *solarSys, + COUNT whichNode, NODE_INFO *info) +{ + // Generate an energy node at a random location + return GenerateRandomNodes (&solarSys->SysInfo, ENERGY_SCAN, 1, 0, + whichNode, info); +} + +COUNT +GenerateDefault_generateRuins (const SOLARSYS_STATE *solarSys, + COUNT whichNode, NODE_INFO *info) +{ + // Generate a standard spread of city ruins of a destroyed civilization + return GenerateRandomNodes (&solarSys->SysInfo, ENERGY_SCAN, NUM_RACE_RUINS, + 0, whichNode, info); +} + +static inline void +runLanderReport (void) +{ + UnbatchGraphics (); + DoDiscoveryReport (MenuSounds); + BatchGraphics (); +} + +bool +GenerateDefault_landerReport (SOLARSYS_STATE *solarSys) +{ + PLANET_INFO *planetInfo = &solarSys->SysInfo.PlanetInfo; + + if (!planetInfo->DiscoveryString) + return false; + + runLanderReport (); + + // XXX: A non-cycling report is given only once and has to be deleted + // in some circumstances (like the Syreen Vault). It does not + // hurt to simply delete it in all cases. Nothing should rely on + // the presence of DiscoveryString, but the Syreen Vault and the + // Mycon Egg Cases rely on its absence. + DestroyStringTable (ReleaseStringTable (planetInfo->DiscoveryString)); + planetInfo->DiscoveryString = 0; + + return true; +} + +bool +GenerateDefault_landerReportCycle (SOLARSYS_STATE *solarSys) +{ + PLANET_INFO *planetInfo = &solarSys->SysInfo.PlanetInfo; + + if (!planetInfo->DiscoveryString) + return false; + + runLanderReport (); + // Advance to the next report + planetInfo->DiscoveryString = SetRelStringTableIndex ( + planetInfo->DiscoveryString, 1); + + // If our discovery strings have cycled, we're done + if (GetStringTableIndex (planetInfo->DiscoveryString) == 0) + { + DestroyStringTable (ReleaseStringTable (planetInfo->DiscoveryString)); + planetInfo->DiscoveryString = 0; + } + + return true; +} + +// NB. This function modifies the RNG state. +static void +GeneratePlanets (SOLARSYS_STATE *solarSys) +{ + COUNT i; + PLANET_DESC *planet; + + for (i = solarSys->SunDesc[0].NumPlanets, + planet = &solarSys->PlanetDesc[0]; i; --i, ++planet) + { + DWORD rand_val; + BYTE byte_val; + BYTE num_moons; + BYTE type; + + rand_val = RandomContext_Random (SysGenRNG); + byte_val = LOBYTE (rand_val); + + num_moons = 0; + type = PlanData[planet->data_index & ~PLANET_SHIELDED].Type; + switch (PLANSIZE (type)) + { + case LARGE_ROCKY_WORLD: + if (byte_val < 0x00FF * 25 / 100) + { + if (byte_val < 0x00FF * 5 / 100) + ++num_moons; + ++num_moons; + } + break; + case GAS_GIANT: + if (byte_val < 0x00FF * 90 / 100) + { + if (byte_val < 0x00FF * 75 / 100) + { + if (byte_val < 0x00FF * 50 / 100) + { + if (byte_val < 0x00FF * 25 / 100) + ++num_moons; + ++num_moons; + } + ++num_moons; + } + ++num_moons; + } + break; + } + planet->NumPlanets = num_moons; + } +} + +static void +check_yehat_rebellion (void) +{ + HIPGROUP hGroup, hNextGroup; + + // XXX: Is there a better way to do this? I could not find one. + // When you talk to a Yehat ship (YEHAT_SHIP) and start the rebellion, + // there is no battle following the comm. There is *never* a battle in + // an encounter with Rebels, but the group race_id (YEHAT_REBEL_SHIP) + // is different from Royalists (YEHAT_SHIP). There is *always* a battle + // in an encounter with Royalists. + // TRANSLATION: "If the civil war has not started yet, or the player + // battled a ship -- bail." + if (!GET_GAME_STATE (YEHAT_CIVIL_WAR) || EncounterRace >= 0) + return; // not this time + + // Send Yehat groups to flee the system, but only if the player + // has actually talked to a ship. + for (hGroup = GetHeadLink (&GLOBAL (ip_group_q)); hGroup; + hGroup = hNextGroup) + { + IP_GROUP *GroupPtr = LockIpGroup (&GLOBAL (ip_group_q), hGroup); + hNextGroup = _GetSuccLink (GroupPtr); + // IGNORE_FLAGSHIP was set in ipdisp.c:ip_group_collision() + // during a collision with the flagship. + if (GroupPtr->race_id == YEHAT_SHIP + && (GroupPtr->task & IGNORE_FLAGSHIP)) + { + GroupPtr->task &= REFORM_GROUP; + GroupPtr->task |= FLEE | IGNORE_FLAGSHIP; + GroupPtr->dest_loc = 0; + } + UnlockIpGroup (&GLOBAL (ip_group_q), hGroup); + } +} + + |