1 //Copyright Paul Reiche, Fred Ford. 1992-2002
2
3 /*
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 #include "genall.h"
20 #include "../lander.h"
21 #include "../lifeform.h"
22 #include "../planets.h"
23 #include "../../build.h"
24 #include "../../comm.h"
25 #include "../../gendef.h"
26 #include "../../starmap.h"
27 #include "../../globdata.h"
28 #include "../../ipdisp.h"
29 #include "../../nameref.h"
30 #include "../../setup.h"
31 #include "../../sounds.h"
32 #include "../../state.h"
33 #include "libs/mathlib.h"
34
35
36 static bool GenerateVux_generatePlanets (SOLARSYS_STATE *solarSys);
37 static bool GenerateVux_generateOrbital (SOLARSYS_STATE *solarSys,
38 PLANET_DESC *world);
39 static COUNT GenerateVux_generateEnergy (const SOLARSYS_STATE *,
40 const PLANET_DESC *world, COUNT whichNode, NODE_INFO *);
41 static COUNT GenerateVux_generateLife (const SOLARSYS_STATE *,
42 const PLANET_DESC *world, COUNT whichNode, NODE_INFO *);
43 static bool GenerateVux_pickupEnergy (SOLARSYS_STATE *, PLANET_DESC *world,
44 COUNT whichNode);
45 static bool GenerateVux_pickupLife (SOLARSYS_STATE *, PLANET_DESC *world,
46 COUNT whichNode);
47
48
49 const GenerateFunctions generateVuxFunctions = {
50 /* .initNpcs = */ GenerateDefault_initNpcs,
51 /* .reinitNpcs = */ GenerateDefault_reinitNpcs,
52 /* .uninitNpcs = */ GenerateDefault_uninitNpcs,
53 /* .generatePlanets = */ GenerateVux_generatePlanets,
54 /* .generateMoons = */ GenerateDefault_generateMoons,
55 /* .generateName = */ GenerateDefault_generateName,
56 /* .generateOrbital = */ GenerateVux_generateOrbital,
57 /* .generateMinerals = */ GenerateDefault_generateMinerals,
58 /* .generateEnergy = */ GenerateVux_generateEnergy,
59 /* .generateLife = */ GenerateVux_generateLife,
60 /* .pickupMinerals = */ GenerateDefault_pickupMinerals,
61 /* .pickupEnergy = */ GenerateVux_pickupEnergy,
62 /* .pickupLife = */ GenerateVux_pickupLife,
63 };
64
65
66 static bool
GenerateVux_generatePlanets(SOLARSYS_STATE * solarSys)67 GenerateVux_generatePlanets (SOLARSYS_STATE *solarSys)
68 {
69 COUNT angle;
70
71 GenerateDefault_generatePlanets (solarSys);
72
73 if (CurStarDescPtr->Index == MAIDENS_DEFINED)
74 {
75 GenerateDefault_generatePlanets (solarSys);
76 // XXX: this is the second time that this function is
77 // called. Is it safe to remove one, or does this change
78 // the RNG so that the outcome is different?
79 solarSys->PlanetDesc[0].data_index = REDUX_WORLD;
80 solarSys->PlanetDesc[0].radius = EARTH_RADIUS * 212L / 100;
81 angle = ARCTAN (solarSys->PlanetDesc[0].location.x,
82 solarSys->PlanetDesc[0].location.y);
83 solarSys->PlanetDesc[0].location.x =
84 COSINE (angle, solarSys->PlanetDesc[0].radius);
85 solarSys->PlanetDesc[0].location.y =
86 SINE (angle, solarSys->PlanetDesc[0].radius);
87 }
88 else
89 {
90 if (CurStarDescPtr->Index == VUX_DEFINED)
91 {
92 solarSys->PlanetDesc[0].data_index = REDUX_WORLD;
93 solarSys->PlanetDesc[0].NumPlanets = 1;
94 solarSys->PlanetDesc[0].radius = EARTH_RADIUS * 42L / 100;
95 angle = HALF_CIRCLE + OCTANT;
96 }
97 else /* if (CurStarDescPtr->Index == VUX_BEAST_DEFINED) */
98 {
99 memmove (&solarSys->PlanetDesc[1], &solarSys->PlanetDesc[0],
100 sizeof (solarSys->PlanetDesc[0])
101 * solarSys->SunDesc[0].NumPlanets);
102 ++solarSys->SunDesc[0].NumPlanets;
103
104 angle = HALF_CIRCLE - OCTANT;
105 solarSys->PlanetDesc[0].data_index = WATER_WORLD;
106 solarSys->PlanetDesc[0].radius = EARTH_RADIUS * 110L / 100;
107 solarSys->PlanetDesc[0].NumPlanets = 0;
108 }
109
110 solarSys->PlanetDesc[0].location.x =
111 COSINE (angle, solarSys->PlanetDesc[0].radius);
112 solarSys->PlanetDesc[0].location.y =
113 SINE (angle, solarSys->PlanetDesc[0].radius);
114 solarSys->PlanetDesc[0].rand_seed = MAKE_DWORD (
115 solarSys->PlanetDesc[0].location.x,
116 solarSys->PlanetDesc[0].location.y);
117 }
118 return true;
119 }
120
121 static bool
GenerateVux_generateOrbital(SOLARSYS_STATE * solarSys,PLANET_DESC * world)122 GenerateVux_generateOrbital (SOLARSYS_STATE *solarSys, PLANET_DESC *world)
123 {
124 if ((matchWorld (solarSys, world, 0, MATCH_PLANET)
125 && (CurStarDescPtr->Index == VUX_DEFINED
126 || (CurStarDescPtr->Index == MAIDENS_DEFINED
127 && !GET_GAME_STATE (ZEX_IS_DEAD))))
128 && StartSphereTracking (VUX_SHIP))
129 {
130 NotifyOthers (VUX_SHIP, IPNL_ALL_CLEAR);
131 PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP);
132 ReinitQueue (&GLOBAL (ip_group_q));
133 assert (CountLinks (&GLOBAL (npc_built_ship_q)) == 0);
134
135 CloneShipFragment (VUX_SHIP,
136 &GLOBAL (npc_built_ship_q), INFINITE_FLEET);
137 if (CurStarDescPtr->Index == VUX_DEFINED)
138 {
139 SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7);
140 }
141 else
142 {
143 SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 6);
144 }
145
146 GLOBAL (CurrentActivity) |= START_INTERPLANETARY;
147 InitCommunication (VUX_CONVERSATION);
148
149 if (GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))
150 return true;
151
152 {
153 GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY;
154 ReinitQueue (&GLOBAL (npc_built_ship_q));
155 GetGroupInfo (GROUPS_RANDOM, GROUP_LOAD_IP);
156
157 if (CurStarDescPtr->Index == VUX_DEFINED
158 || !GET_GAME_STATE (ZEX_IS_DEAD))
159 return true;
160
161 RepairSISBorder ();
162 }
163 }
164
165 if (matchWorld (solarSys, world, 0, MATCH_PLANET))
166 {
167 if (CurStarDescPtr->Index == MAIDENS_DEFINED)
168 {
169 if (!GET_GAME_STATE (SHOFIXTI_MAIDENS))
170 {
171 LoadStdLanderFont (&solarSys->SysInfo.PlanetInfo);
172 solarSys->PlanetSideFrame[1] = CaptureDrawable (
173 LoadGraphic (MAIDENS_MASK_PMAP_ANIM));
174 solarSys->SysInfo.PlanetInfo.DiscoveryString =
175 CaptureStringTable (
176 LoadStringTable (MAIDENS_STRTAB));
177 }
178 }
179 else if (CurStarDescPtr->Index == VUX_BEAST_DEFINED)
180 {
181 if (!GET_GAME_STATE (VUX_BEAST))
182 {
183 LoadStdLanderFont (&solarSys->SysInfo.PlanetInfo);
184 solarSys->PlanetSideFrame[1] = 0;
185 solarSys->SysInfo.PlanetInfo.DiscoveryString =
186 CaptureStringTable (
187 LoadStringTable (BEAST_STRTAB));
188 }
189 }
190 else
191 {
192 LoadStdLanderFont (&solarSys->SysInfo.PlanetInfo);
193 solarSys->PlanetSideFrame[1] =
194 CaptureDrawable (LoadGraphic (RUINS_MASK_PMAP_ANIM));
195 solarSys->SysInfo.PlanetInfo.DiscoveryString =
196 CaptureStringTable (LoadStringTable (RUINS_STRTAB));
197 }
198 }
199
200 GenerateDefault_generateOrbital (solarSys, world);
201
202 if (matchWorld (solarSys, world, 0, MATCH_PLANET))
203 {
204 solarSys->SysInfo.PlanetInfo.Weather = 2;
205 solarSys->SysInfo.PlanetInfo.Tectonics = 0;
206 }
207
208 return true;
209 }
210
211 static COUNT
GenerateVux_generateEnergy(const SOLARSYS_STATE * solarSys,const PLANET_DESC * world,COUNT whichNode,NODE_INFO * info)212 GenerateVux_generateEnergy (const SOLARSYS_STATE *solarSys,
213 const PLANET_DESC *world, COUNT whichNode, NODE_INFO *info)
214 {
215 if (CurStarDescPtr->Index == MAIDENS_DEFINED
216 && matchWorld (solarSys, world, 0, MATCH_PLANET))
217 {
218 // This check is redundant since the retrieval bit will keep the
219 // node from showing up again
220 if (GET_GAME_STATE (SHOFIXTI_MAIDENS))
221 { // already picked up
222 return 0;
223 }
224
225 if (info)
226 {
227 info->loc_pt.x = MAP_WIDTH / 3;
228 info->loc_pt.y = MAP_HEIGHT * 5 / 8;
229 }
230
231 return 1; // only matters when count is requested
232 }
233
234 if (CurStarDescPtr->Index == VUX_DEFINED
235 && matchWorld (solarSys, world, 0, MATCH_PLANET))
236 {
237 return GenerateDefault_generateRuins (solarSys, whichNode, info);
238 }
239
240 return 0;
241 }
242
243 static bool
GenerateVux_pickupEnergy(SOLARSYS_STATE * solarSys,PLANET_DESC * world,COUNT whichNode)244 GenerateVux_pickupEnergy (SOLARSYS_STATE *solarSys, PLANET_DESC *world,
245 COUNT whichNode)
246 {
247 if (CurStarDescPtr->Index == MAIDENS_DEFINED
248 && matchWorld (solarSys, world, 0, MATCH_PLANET))
249 {
250 assert (!GET_GAME_STATE (SHOFIXTI_MAIDENS) && whichNode == 0);
251
252 GenerateDefault_landerReport (solarSys);
253 SetLanderTakeoff ();
254
255 SET_GAME_STATE (SHOFIXTI_MAIDENS, 1);
256 SET_GAME_STATE (MAIDENS_ON_SHIP, 1);
257
258 return true; // picked up
259 }
260
261 if (CurStarDescPtr->Index == VUX_DEFINED
262 && matchWorld (solarSys, world, 0, MATCH_PLANET))
263 {
264 // Standard ruins report
265 GenerateDefault_landerReportCycle (solarSys);
266 return false;
267 }
268
269 (void) whichNode;
270 return false;
271 }
272
273 static COUNT
GenerateVux_generateLife(const SOLARSYS_STATE * solarSys,const PLANET_DESC * world,COUNT whichNode,NODE_INFO * info)274 GenerateVux_generateLife (const SOLARSYS_STATE *solarSys,
275 const PLANET_DESC *world, COUNT whichNode, NODE_INFO *info)
276 {
277 if (CurStarDescPtr->Index == MAIDENS_DEFINED
278 && matchWorld (solarSys, world, 0, MATCH_PLANET))
279 {
280 static const SBYTE life[] =
281 {
282 9, 9, 9, 9, /* Carousel Beast */
283 14, 14, 14, 14, /* Amorphous Trandicula */
284 18, 18, 18, 18, /* Penguin Cyclops */
285 -1 /* term */
286 };
287 return GeneratePresetLife (&solarSys->SysInfo, life, whichNode, info);
288 }
289
290 if (CurStarDescPtr->Index == VUX_BEAST_DEFINED
291 && matchWorld (solarSys, world, 0, MATCH_PLANET))
292 {
293 static const SBYTE life[] =
294 {
295 NUM_CREATURE_TYPES + 2, /* VUX Beast */
296 // Must be the first node, see pickupLife() below
297 3, 3, 3, 3, 3, /* Whackin' Bush */
298 8, 8, 8, 8, 8, /* Glowing Medusa */
299 -1 /* term */
300 };
301 return GeneratePresetLife (&solarSys->SysInfo, life, whichNode, info);
302 }
303
304 return GenerateDefault_generateLife (solarSys, world, whichNode, info);
305 }
306
307 static bool
GenerateVux_pickupLife(SOLARSYS_STATE * solarSys,PLANET_DESC * world,COUNT whichNode)308 GenerateVux_pickupLife (SOLARSYS_STATE *solarSys, PLANET_DESC *world,
309 COUNT whichNode)
310 {
311 if (CurStarDescPtr->Index == VUX_BEAST_DEFINED
312 && matchWorld (solarSys, world, 0, MATCH_PLANET))
313 {
314 if (whichNode == 0)
315 { // Picked up Zex' Beauty
316 assert (!GET_GAME_STATE (VUX_BEAST));
317
318 GenerateDefault_landerReport (solarSys);
319 SetLanderTakeoff ();
320
321 SET_GAME_STATE (VUX_BEAST, 1);
322 SET_GAME_STATE (VUX_BEAST_ON_SHIP, 1);
323 }
324
325 return true; // picked up
326 }
327
328 return GenerateDefault_pickupLife (solarSys, world, whichNode);
329 }
330