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 "../commall.h"
20 #include "../comandr/resinst.h"
21 #include "strings.h"
22
23 #include "uqm/build.h"
24 #include "uqm/setup.h"
25 #include "uqm/shipcont.h"
26 #include "uqm/sis.h"
27 // for DeltaSISGauges()
28 #include "libs/graphics/gfx_common.h"
29 #include "libs/mathlib.h"
30 #include "libs/inplib.h"
31
32
33 static void TellMission (RESPONSE_REF R);
34 static void SellMinerals (RESPONSE_REF R);
35
36
37 static LOCDATA commander_desc =
38 {
39 NULL, /* init_encounter_func */
40 NULL, /* post_encounter_func */
41 NULL, /* uninit_encounter_func */
42 COMMANDER_PMAP_ANIM, /* AlienFrame */
43 COMMANDER_FONT, /* AlienFont */
44 WHITE_COLOR_INIT, /* AlienTextFColor */
45 BLACK_COLOR_INIT, /* AlienTextBColor */
46 {0, 0}, /* AlienTextBaseline */
47 0, /* SIS_TEXT_WIDTH, */ /* AlienTextWidth */
48 ALIGN_CENTER, /* AlienTextAlign */
49 VALIGN_MIDDLE, /* AlienTextValign */
50 COMMANDER_COLOR_MAP, /* AlienColorMap */
51 COMMANDER_MUSIC, /* AlienSong */
52 NULL_RESOURCE, /* AlienAltSong */
53 0, /* AlienSongFlags */
54 STARBASE_CONVERSATION_PHRASES, /* PlayerPhrases */
55 10, /* NumAnimations */
56 { /* AlienAmbientArray (ambient animations) */
57 { /* Blink */
58 1, /* StartIndex */
59 3, /* NumFrames */
60 YOYO_ANIM, /* AnimFlags */
61 ONE_SECOND / 15, 0, /* FrameRate */
62 0, ONE_SECOND * 8, /* RestartRate */
63 0, /* BlockMask */
64 },
65 { /* Running light */
66 10, /* StartIndex */
67 30, /* NumFrames */
68 CIRCULAR_ANIM, /* AnimFlags */
69 ONE_SECOND / 40, 0, /* FrameRate */
70 ONE_SECOND * 2, 0, /* RestartRate */
71 0, /* BlockMask */
72 },
73 { /* Arc welder 0 */
74 40, /* StartIndex */
75 7, /* NumFrames */
76 CIRCULAR_ANIM, /* AnimFlags */
77 ONE_SECOND / 40, 0, /* FrameRate */
78 0, ONE_SECOND * 8, /* RestartRate */
79 0, /* BlockMask */
80 },
81 { /* Arc welder 1 */
82 47, /* StartIndex */
83 8, /* NumFrames */
84 CIRCULAR_ANIM, /* AnimFlags */
85 ONE_SECOND / 40, 0, /* FrameRate */
86 0, ONE_SECOND * 8, /* RestartRate */
87 0, /* BlockMask */
88 },
89 { /* Arc welder 2 */
90 55, /* StartIndex */
91 6, /* NumFrames */
92 CIRCULAR_ANIM, /* AnimFlags */
93 ONE_SECOND / 40, 0, /* FrameRate */
94 0, ONE_SECOND * 8, /* RestartRate */
95 0, /* BlockMask */
96 },
97 { /* Arc welder 3 */
98 61, /* StartIndex */
99 6, /* NumFrames */
100 CIRCULAR_ANIM, /* AnimFlags */
101 ONE_SECOND / 40, 0, /* FrameRate */
102 0, ONE_SECOND * 8, /* RestartRate */
103 0, /* BlockMask */
104 },
105 { /* Arc welder 4 */
106 67, /* StartIndex */
107 7, /* NumFrames */
108 CIRCULAR_ANIM, /* AnimFlags */
109 ONE_SECOND / 40, 0, /* FrameRate */
110 0, ONE_SECOND * 8, /* RestartRate */
111 0, /* BlockMask */
112 },
113 { /* Arc welder 5 */
114 74, /* StartIndex */
115 11, /* NumFrames */
116 CIRCULAR_ANIM, /* AnimFlags */
117 ONE_SECOND / 40, 0, /* FrameRate */
118 0, ONE_SECOND * 8, /* RestartRate */
119 0, /* BlockMask */
120 },
121 { /* Arc welder 6 */
122 85, /* StartIndex */
123 10, /* NumFrames */
124 CIRCULAR_ANIM, /* AnimFlags */
125 ONE_SECOND / 40, 0, /* FrameRate */
126 0, ONE_SECOND * 8, /* RestartRate */
127 0, /* BlockMask */
128 },
129 { /* Flagship picture */
130 95, /* StartIndex */
131 1, /* NumFrames */
132 0, /* AnimFlags */
133 0, 0, /* FrameRate */
134 0, 0, /* RestartRate */
135 0, /* BlockMask */
136 },
137 },
138 { /* AlienTransitionDesc */
139 0, /* StartIndex */
140 0, /* NumFrames */
141 0, /* AnimFlags */
142 0, 0, /* FrameRate */
143 0, 0, /* RestartRate */
144 0, /* BlockMask */
145 },
146 { /* AlienTalkDesc */
147 4, /* StartIndex */
148 6, /* NumFrames */
149 0, /* AnimFlags */
150 ONE_SECOND / 10, ONE_SECOND / 15, /* FrameRate */
151 ONE_SECOND * 7 / 60, ONE_SECOND / 12, /* RestartRate */
152 0, /* BlockMask */
153 },
154 NULL, /* AlienNumberSpeech - none */
155 /* Filler for loaded resources */
156 NULL, NULL, NULL,
157 NULL,
158 NULL,
159 };
160
161 static DWORD CurBulletinMask;
162
163 static void
ByeBye(RESPONSE_REF R)164 ByeBye (RESPONSE_REF R)
165 {
166 (void) R; // ignored
167
168 CurBulletinMask |= GET_GAME_STATE_32 (STARBASE_BULLETS0);
169 SET_GAME_STATE_32 (STARBASE_BULLETS0, CurBulletinMask);
170
171 /* if (R == goodbye_starbase_commander) */
172 if (GET_GAME_STATE (CHMMR_BOMB_STATE) >= 2)
173 NPCPhrase (GOOD_LUCK_AGAIN);
174 else
175 {
176 RESPONSE_REF pStr0 = 0;
177 RESPONSE_REF pStr1 = 0;
178
179 switch ((BYTE)TFB_Random () & 7)
180 {
181 case 0:
182 pStr0 = NORMAL_GOODBYE_A0;
183 pStr1 = NORMAL_GOODBYE_A1;
184 break;
185 case 1:
186 pStr0 = NORMAL_GOODBYE_B0;
187 pStr1 = NORMAL_GOODBYE_B1;
188 break;
189 case 2:
190 pStr0 = NORMAL_GOODBYE_C0;
191 pStr1 = NORMAL_GOODBYE_C1;
192 break;
193 case 3:
194 pStr0 = NORMAL_GOODBYE_D0;
195 pStr1 = NORMAL_GOODBYE_D1;
196 break;
197 case 4:
198 pStr0 = NORMAL_GOODBYE_E0;
199 pStr1 = NORMAL_GOODBYE_E1;
200 break;
201 case 5:
202 pStr0 = NORMAL_GOODBYE_F0;
203 pStr1 = NORMAL_GOODBYE_F1;
204 break;
205 case 6:
206 pStr0 = NORMAL_GOODBYE_G0;
207 pStr1 = NORMAL_GOODBYE_G1;
208 break;
209 case 7:
210 pStr0 = NORMAL_GOODBYE_H0;
211 pStr1 = NORMAL_GOODBYE_H1;
212 break;
213 }
214
215 NPCPhrase (pStr0);
216 if (!usingSpeech)
217 {
218 NPCPhrase (SPACE);
219 NPCPhrase (GLOBAL_PLAYER_NAME);
220 }
221 NPCPhrase (pStr1);
222 }
223 }
224
225 static void NeedInfo (RESPONSE_REF R);
226 static void TellHistory (RESPONSE_REF R);
227 static void AlienRaces (RESPONSE_REF R);
228
229 static BYTE stack0;
230 static BYTE stack1;
231 static BYTE stack2;
232 static BYTE stack3;
233
234 static void
AllianceInfo(RESPONSE_REF R)235 AllianceInfo (RESPONSE_REF R)
236 {
237 #define ALLIANCE_SHOFIXTI (1 << 0)
238 #define ALLIANCE_YEHAT (1 << 1)
239 #define ALLIANCE_ARILOU (1 << 2)
240 #define ALLIANCE_CHENJESU (1 << 3)
241 #define ALLIANCE_MMRNMHRM (1 << 4)
242 #define ALLIANCE_SYREEN (1 << 5)
243 static BYTE AllianceMask = 0;
244
245 if (PLAYER_SAID (R, what_about_alliance))
246 {
247 NPCPhrase (WHICH_ALLIANCE);
248 AllianceMask = 0;
249 }
250 else if (PLAYER_SAID (R, shofixti))
251 {
252 NPCPhrase (ABOUT_SHOFIXTI);
253 AllianceMask |= ALLIANCE_SHOFIXTI;
254 }
255 else if (PLAYER_SAID (R, yehat))
256 {
257 NPCPhrase (ABOUT_YEHAT);
258 AllianceMask |= ALLIANCE_YEHAT;
259 }
260 else if (PLAYER_SAID (R, arilou))
261 {
262 NPCPhrase (ABOUT_ARILOU);
263 AllianceMask |= ALLIANCE_ARILOU;
264 }
265 else if (PLAYER_SAID (R, chenjesu))
266 {
267 NPCPhrase (ABOUT_CHENJESU);
268 AllianceMask |= ALLIANCE_CHENJESU;
269 }
270 else if (PLAYER_SAID (R, mmrnmhrm))
271 {
272 NPCPhrase (ABOUT_MMRNMHRM);
273 AllianceMask |= ALLIANCE_MMRNMHRM;
274 }
275 else if (PLAYER_SAID (R, syreen))
276 {
277 NPCPhrase (ABOUT_SYREEN);
278 AllianceMask |= ALLIANCE_SYREEN;
279 }
280
281 if (!(AllianceMask & ALLIANCE_SHOFIXTI))
282 Response (shofixti, AllianceInfo);
283 if (!(AllianceMask & ALLIANCE_YEHAT))
284 Response (yehat, AllianceInfo);
285 if (!(AllianceMask & ALLIANCE_ARILOU))
286 Response (arilou, AllianceInfo);
287 if (!(AllianceMask & ALLIANCE_CHENJESU))
288 Response (chenjesu, AllianceInfo);
289 if (!(AllianceMask & ALLIANCE_MMRNMHRM))
290 Response (mmrnmhrm, AllianceInfo);
291 if (!(AllianceMask & ALLIANCE_SYREEN))
292 Response (syreen, AllianceInfo);
293 Response (enough_alliance, AlienRaces);
294 }
295
296 static void
HierarchyInfo(RESPONSE_REF R)297 HierarchyInfo (RESPONSE_REF R)
298 {
299 #define HIERARCHY_MYCON (1 << 0)
300 #define HIERARCHY_SPATHI (1 << 1)
301 #define HIERARCHY_UMGAH (1 << 2)
302 #define HIERARCHY_ANDROSYNTH (1 << 3)
303 #define HIERARCHY_ILWRATH (1 << 4)
304 #define HIERARCHY_VUX (1 << 5)
305 #define HIERARCHY_URQUAN (1 << 6)
306 static BYTE HierarchyMask = 0;
307
308 if (PLAYER_SAID (R, what_about_hierarchy))
309 {
310 NPCPhrase (WHICH_HIERARCHY);
311 HierarchyMask = 0;
312 }
313 else if (PLAYER_SAID (R, urquan))
314 {
315 NPCPhrase (ABOUT_URQUAN);
316 HierarchyMask |= HIERARCHY_URQUAN;
317 }
318 else if (PLAYER_SAID (R, mycon))
319 {
320 NPCPhrase (ABOUT_MYCON);
321 HierarchyMask |= HIERARCHY_MYCON;
322 }
323 else if (PLAYER_SAID (R, spathi))
324 {
325 NPCPhrase (ABOUT_SPATHI);
326 HierarchyMask |= HIERARCHY_SPATHI;
327 }
328 else if (PLAYER_SAID (R, umgah))
329 {
330 NPCPhrase (ABOUT_UMGAH);
331 HierarchyMask |= HIERARCHY_UMGAH;
332 }
333 else if (PLAYER_SAID (R, androsynth))
334 {
335 NPCPhrase (ABOUT_ANDROSYNTH);
336 HierarchyMask |= HIERARCHY_ANDROSYNTH;
337 }
338 else if (PLAYER_SAID (R, ilwrath))
339 {
340 NPCPhrase (ABOUT_ILWRATH);
341 HierarchyMask |= HIERARCHY_ILWRATH;
342 }
343 else if (PLAYER_SAID (R, vux))
344 {
345 NPCPhrase (ABOUT_VUX);
346 HierarchyMask |= HIERARCHY_VUX;
347 }
348
349 if (!(HierarchyMask & HIERARCHY_URQUAN))
350 Response (urquan, HierarchyInfo);
351 if (!(HierarchyMask & HIERARCHY_MYCON))
352 Response (mycon, HierarchyInfo);
353 if (!(HierarchyMask & HIERARCHY_SPATHI))
354 Response (spathi, HierarchyInfo);
355 if (!(HierarchyMask & HIERARCHY_UMGAH))
356 Response (umgah, HierarchyInfo);
357 if (!(HierarchyMask & HIERARCHY_ANDROSYNTH))
358 Response (androsynth, HierarchyInfo);
359 if (!(HierarchyMask & HIERARCHY_ILWRATH))
360 Response (ilwrath, HierarchyInfo);
361 if (!(HierarchyMask & HIERARCHY_VUX))
362 Response (vux, HierarchyInfo);
363 Response (enough_hierarchy, AlienRaces);
364 }
365
366 static void
AlienRaces(RESPONSE_REF R)367 AlienRaces (RESPONSE_REF R)
368 {
369 #define RACES_ALLIANCE (1 << 0)
370 #define RACES_HIERARCHY (1 << 1)
371 #define RACES_OTHER (1 << 2)
372 static BYTE RacesMask = 0;
373
374 if (PLAYER_SAID (R, alien_races))
375 {
376 NPCPhrase (WHICH_ALIEN);
377 RacesMask = 0;
378 }
379 else if (PLAYER_SAID (R, enough_alliance))
380 {
381 NPCPhrase (OK_ENOUGH_ALLIANCE);
382 RacesMask |= RACES_ALLIANCE;
383 }
384 else if (PLAYER_SAID (R, enough_hierarchy))
385 {
386 NPCPhrase (OK_ENOUGH_HIERARCHY);
387 RacesMask |= RACES_HIERARCHY;
388 }
389 else if (PLAYER_SAID (R, what_about_other))
390 {
391 NPCPhrase (ABOUT_OTHER);
392 RacesMask |= RACES_OTHER;
393 }
394
395 if (!(RacesMask & RACES_ALLIANCE))
396 {
397 Response (what_about_alliance, AllianceInfo);
398 }
399 if (!(RacesMask & RACES_HIERARCHY))
400 {
401 Response (what_about_hierarchy, HierarchyInfo);
402 }
403 if (!(RacesMask & RACES_OTHER))
404 {
405 Response (what_about_other, AlienRaces);
406 }
407 Response (enough_aliens, TellHistory);
408 }
409
410 static void
WarInfo(RESPONSE_REF R)411 WarInfo (RESPONSE_REF R)
412 {
413 #define WAR_STARTED (1 << 0)
414 #define WAR_WAS_LIKE (1 << 1)
415 #define WAR_LOST (1 << 2)
416 #define WAR_AFTERMATH (1 << 3)
417 static BYTE WarMask = 0;
418
419 if (PLAYER_SAID (R, the_war))
420 {
421 NPCPhrase (WHICH_WAR);
422 WarMask = 0;
423 }
424 else if (PLAYER_SAID (R, what_started_war))
425 {
426 NPCPhrase (URQUAN_STARTED_WAR);
427 WarMask |= WAR_STARTED;
428 }
429 else if (PLAYER_SAID (R, what_was_war_like))
430 {
431 NPCPhrase (WAR_WAS_LIKE_SO);
432 WarMask |= WAR_WAS_LIKE;
433 }
434 else if (PLAYER_SAID (R, why_lose_war))
435 {
436 NPCPhrase (LOST_WAR_BECAUSE);
437 WarMask |= WAR_LOST;
438 }
439 else if (PLAYER_SAID (R, what_after_war))
440 {
441 NPCPhrase (AFTER_WAR);
442 WarMask |= WAR_AFTERMATH;
443 }
444
445 if (!(WarMask & WAR_STARTED))
446 Response (what_started_war, WarInfo);
447 if (!(WarMask & WAR_WAS_LIKE))
448 Response (what_was_war_like, WarInfo);
449 if (!(WarMask & WAR_LOST))
450 Response (why_lose_war, WarInfo);
451 if (!(WarMask & WAR_AFTERMATH))
452 Response (what_after_war, WarInfo);
453 Response (enough_war, TellHistory);
454 }
455
456 static void
AncientHistory(RESPONSE_REF R)457 AncientHistory (RESPONSE_REF R)
458 {
459 #define ANCIENT_PRECURSORS (1 << 0)
460 #define ANCIENT_RACES (1 << 1)
461 #define ANCIENT_EARTH (1 << 2)
462 static BYTE AncientMask = 0;
463
464 if (PLAYER_SAID (R, ancient_history))
465 {
466 NPCPhrase (WHICH_ANCIENT);
467 AncientMask = 0;
468 }
469 else if (PLAYER_SAID (R, precursors))
470 {
471 NPCPhrase (ABOUT_PRECURSORS);
472 AncientMask |= ANCIENT_PRECURSORS;
473 }
474 else if (PLAYER_SAID (R, old_races))
475 {
476 NPCPhrase (ABOUT_OLD_RACES);
477 AncientMask |= ANCIENT_RACES;
478 }
479 else if (PLAYER_SAID (R, aliens_on_earth))
480 {
481 NPCPhrase (ABOUT_ALIENS_ON_EARTH);
482 AncientMask |= ANCIENT_EARTH;
483 }
484
485 if (!(AncientMask & ANCIENT_PRECURSORS))
486 Response (precursors, AncientHistory);
487 if (!(AncientMask & ANCIENT_RACES))
488 Response (old_races, AncientHistory);
489 if (!(AncientMask & ANCIENT_EARTH))
490 Response (aliens_on_earth, AncientHistory);
491 Response (enough_ancient, TellHistory);
492 }
493
494 static void
TellHistory(RESPONSE_REF R)495 TellHistory (RESPONSE_REF R)
496 {
497 RESPONSE_REF pstack[3];
498
499 if (PLAYER_SAID (R, history))
500 {
501 NPCPhrase (WHICH_HISTORY);
502 stack0 = 0;
503 stack1 = 0;
504 stack2 = 0;
505 }
506 else if (PLAYER_SAID (R, enough_aliens))
507 {
508 NPCPhrase (OK_ENOUGH_ALIENS);
509
510 stack0 = 1;
511 }
512 else if (PLAYER_SAID (R, enough_war))
513 {
514 NPCPhrase (OK_ENOUGH_WAR);
515
516 stack1 = 1;
517 }
518 else if (PLAYER_SAID (R, enough_ancient))
519 {
520 NPCPhrase (OK_ENOUGH_ANCIENT);
521
522 stack2 = 1;
523 }
524
525 switch (stack0)
526 {
527 case 0:
528 pstack[0] = alien_races;
529 break;
530 default:
531 pstack[0] = 0;
532 break;
533 }
534 switch (stack1)
535 {
536 case 0:
537 pstack[1] = the_war;
538 break;
539 default:
540 pstack[1] = 0;
541 break;
542 }
543 switch (stack2)
544 {
545 case 0:
546 pstack[2] = ancient_history;
547 break;
548 default:
549 pstack[2] = 0;
550 break;
551 }
552
553 if (pstack[0])
554 {
555 Response (pstack[0], AlienRaces);
556 }
557 if (pstack[1])
558 {
559 Response (pstack[1], WarInfo);
560 }
561 if (pstack[2])
562 {
563 Response (pstack[2], AncientHistory);
564 }
565 Response (enough_history, NeedInfo);
566 }
567
568 static void
DefeatUrquan(RESPONSE_REF R)569 DefeatUrquan (RESPONSE_REF R)
570 {
571 #define HOW_FIND_URQUAN (1 << 0)
572 #define HOW_FIGHT_URQUAN (1 << 1)
573 #define HOW_ALLY_AGAINST_URQUAN (1 << 2)
574 #define HOW_STRONG_AGAINST_URQUAN (1 << 3)
575 static BYTE DefeatMask = 0;
576
577 if (PLAYER_SAID (R, how_defeat))
578 {
579 NPCPhrase (DEFEAT_LIKE_SO);
580 DefeatMask = 0;
581 }
582 else if (PLAYER_SAID (R, how_find_urquan))
583 {
584 NPCPhrase (FIND_URQUAN);
585 DefeatMask |= HOW_FIND_URQUAN;
586 }
587 else if (PLAYER_SAID (R, how_fight_urquan))
588 {
589 NPCPhrase (FIGHT_URQUAN);
590 DefeatMask |= HOW_FIGHT_URQUAN;
591 }
592 else if (PLAYER_SAID (R, how_ally))
593 {
594 NPCPhrase (ALLY_LIKE_SO);
595 DefeatMask |= HOW_ALLY_AGAINST_URQUAN;
596 }
597 else if (PLAYER_SAID (R, how_get_strong))
598 {
599 NPCPhrase (STRONG_LIKE_SO);
600 DefeatMask |= HOW_STRONG_AGAINST_URQUAN;
601 }
602
603 if (!(DefeatMask & HOW_FIND_URQUAN))
604 Response (how_find_urquan, DefeatUrquan);
605 if (!(DefeatMask & HOW_FIGHT_URQUAN))
606 Response (how_fight_urquan, DefeatUrquan);
607 if (!(DefeatMask & HOW_ALLY_AGAINST_URQUAN))
608 Response (how_ally, DefeatUrquan);
609 if (!(DefeatMask & HOW_STRONG_AGAINST_URQUAN))
610 Response (how_get_strong, DefeatUrquan);
611 Response (enough_defeat, TellMission);
612 }
613
614 static void
AnalyzeCondition(void)615 AnalyzeCondition (void)
616 {
617 BYTE i;
618 BYTE num_thrusters = 0,
619 num_jets = 0,
620 num_guns = 0,
621 num_bays = 0,
622 num_batts = 0,
623 num_track = 0,
624 num_defense = 0;
625 BOOLEAN HasMinimum;
626
627 for (i = 0; i < NUM_DRIVE_SLOTS; ++i)
628 {
629 if (GLOBAL_SIS (DriveSlots[i]) < EMPTY_SLOT)
630 ++num_thrusters;
631 }
632 for (i = 0; i < NUM_JET_SLOTS; ++i)
633 {
634 if (GLOBAL_SIS (JetSlots[i]) < EMPTY_SLOT)
635 ++num_jets;
636 }
637 for (i = 0; i < NUM_MODULE_SLOTS; ++i)
638 {
639 BYTE which_piece;
640
641 switch (which_piece = GLOBAL_SIS (ModuleSlots[i]))
642 {
643 case STORAGE_BAY:
644 ++num_bays;
645 break;
646 case DYNAMO_UNIT:
647 case SHIVA_FURNACE:
648 num_batts += 1 + (which_piece - DYNAMO_UNIT);
649 break;
650 case GUN_WEAPON:
651 case BLASTER_WEAPON:
652 case CANNON_WEAPON:
653 num_guns += 1 + (which_piece - GUN_WEAPON);
654 break;
655 case TRACKING_SYSTEM:
656 ++num_track;
657 break;
658 case ANTIMISSILE_DEFENSE:
659 ++num_defense;
660 break;
661 }
662 }
663 if (num_track && num_guns)
664 num_guns += 2;
665
666 HasMinimum = (num_thrusters >= 7 && num_jets >= 5
667 && GLOBAL_SIS (CrewEnlisted) >= CREW_POD_CAPACITY
668 && GLOBAL_SIS (FuelOnBoard) >= FUEL_TANK_CAPACITY
669 && num_bays >= 1 && GLOBAL_SIS (NumLanders)
670 && num_batts >= 1 && num_guns >= 2);
671 NPCPhrase (LETS_SEE);
672 if (!HasMinimum && GET_GAME_STATE (CHMMR_BOMB_STATE) < 2)
673 {
674 NPCPhrase (IMPROVE_1);
675 if (num_thrusters < 7)
676 NPCPhrase (NEED_THRUSTERS_1);
677 if (num_jets < 5)
678 NPCPhrase (NEED_TURN_1);
679 if (num_guns < 2)
680 NPCPhrase (NEED_GUNS_1);
681 if (GLOBAL_SIS (CrewEnlisted) < CREW_POD_CAPACITY)
682 NPCPhrase (NEED_CREW_1);
683 if (GLOBAL_SIS (FuelOnBoard) < FUEL_TANK_CAPACITY)
684 NPCPhrase (NEED_FUEL_1);
685 if (num_bays < 1)
686 NPCPhrase (NEED_STORAGE_1);
687 if (GLOBAL_SIS (NumLanders) == 0)
688 NPCPhrase (NEED_LANDERS_2);
689 if (num_batts < 1)
690 NPCPhrase (NEED_DYNAMOS_1);
691
692 if (GLOBAL_SIS (ResUnits) >= 3000)
693 NPCPhrase (IMPROVE_FLAGSHIP_WITH_RU);
694 else
695 NPCPhrase (GO_GET_MINERALS);
696 }
697 else
698 {
699 BYTE num_aliens = 0;
700 COUNT FleetStrength;
701 BOOLEAN HasMaximum;
702
703 FleetStrength = CalculateEscortsWorth ();
704 for (i = 0; i < NUM_AVAILABLE_RACES; ++i)
705 {
706 if (i != HUMAN_SHIP && CheckAlliance (i) == GOOD_GUY)
707 ++num_aliens;
708 }
709
710 HasMaximum = (num_thrusters == NUM_DRIVE_SLOTS
711 && num_jets == NUM_JET_SLOTS
712 && GLOBAL_SIS (CrewEnlisted) >= CREW_POD_CAPACITY * 3
713 && GLOBAL_SIS (FuelOnBoard) >= FUEL_TANK_CAPACITY * 3
714 && GLOBAL_SIS (NumLanders) >= 3
715 && num_batts >= 4 && num_guns >= 7 && num_defense >= 2);
716 if (!HasMaximum && GET_GAME_STATE (CHMMR_BOMB_STATE) < 2)
717 NPCPhrase (GOT_OK_FLAGSHIP);
718 else
719 NPCPhrase (GOT_AWESOME_FLAGSHIP);
720
721 if (GET_GAME_STATE (CHMMR_BOMB_STATE) >= 2)
722 {
723 NPCPhrase (CHMMR_IMPROVED_BOMB);
724 if (FleetStrength < 20000)
725 NPCPhrase (MUST_ACQUIRE_AWESOME_FLEET);
726 else
727 {
728 NPCPhrase (GOT_AWESOME_FLEET);
729 if (!GET_GAME_STATE (TALKING_PET_ON_SHIP))
730 NPCPhrase (MUST_ELIMINATE_URQUAN_GUARDS);
731 else
732 NPCPhrase (GO_DESTROY_SAMATRA);
733 }
734 }
735 else if (num_aliens < 2)
736 NPCPhrase (GO_ALLY_WITH_ALIENS);
737 else
738 {
739 NPCPhrase (MADE_SOME_ALLIES);
740 if (FleetStrength < 6000)
741 {
742 if (GLOBAL_SIS (ResUnits) >= 3000)
743 NPCPhrase (BUY_COMBAT_SHIPS);
744 else
745 NPCPhrase (GET_SHIPS_BY_MINING_OR_ALLIANCE);
746 }
747 else
748 {
749 NPCPhrase (GOT_OK_FLEET);
750 if (!HasMaximum)
751 {
752 NPCPhrase (IMPROVE_2);
753 if (num_thrusters < NUM_DRIVE_SLOTS)
754 NPCPhrase (NEED_THRUSTERS_2);
755 if (num_jets < NUM_JET_SLOTS)
756 NPCPhrase (NEED_TURN_2);
757 if (num_guns < 7)
758 NPCPhrase (NEED_GUNS_2);
759 if (GLOBAL_SIS (CrewEnlisted) < CREW_POD_CAPACITY * 3)
760 NPCPhrase (NEED_CREW_2);
761 if (GLOBAL_SIS (FuelOnBoard) < FUEL_TANK_CAPACITY * 3)
762 NPCPhrase (NEED_FUEL_2);
763 if (GLOBAL_SIS (NumLanders) < 3)
764 NPCPhrase (NEED_LANDERS_1);
765 if (num_batts < 4)
766 NPCPhrase (NEED_DYNAMOS_2);
767 if (num_defense < 2)
768 NPCPhrase (NEED_POINT);
769 }
770 else if (!GET_GAME_STATE (AWARE_OF_SAMATRA))
771 NPCPhrase (GO_LEARN_ABOUT_URQUAN);
772 else
773 {
774 NPCPhrase (KNOW_ABOUT_SAMATRA);
775 if (!GET_GAME_STATE (UTWIG_BOMB))
776 NPCPhrase (FIND_WAY_TO_DESTROY_SAMATRA);
777 else if (GET_GAME_STATE (UTWIG_BOMB_ON_SHIP))
778 NPCPhrase (MUST_INCREASE_BOMB_STRENGTH);
779 }
780 }
781 }
782 }
783 }
784
785 static void
TellMission(RESPONSE_REF R)786 TellMission (RESPONSE_REF R)
787 {
788 RESPONSE_REF pstack[4];
789
790 if (PLAYER_SAID (R, our_mission))
791 {
792 NPCPhrase (WHICH_MISSION);
793 stack0 = 0;
794 stack1 = 0;
795 stack2 = 0;
796 stack3 = 0;
797 }
798 else if (PLAYER_SAID (R, where_get_minerals))
799 {
800 NPCPhrase (GET_MINERALS);
801
802 stack0 = 1;
803 }
804 else if (PLAYER_SAID (R, what_about_aliens))
805 {
806 NPCPhrase (ABOUT_ALIENS);
807
808 stack1 = 1;
809 }
810 else if (PLAYER_SAID (R, what_do_now))
811 {
812 AnalyzeCondition ();
813
814 stack2 = 1;
815 }
816 else if (PLAYER_SAID (R, what_about_urquan))
817 {
818 NPCPhrase (MUST_DEFEAT);
819
820 stack3 = 1;
821 }
822 else if (PLAYER_SAID (R, enough_defeat))
823 {
824 NPCPhrase (OK_ENOUGH_DEFEAT);
825
826 stack3 = 2;
827 }
828
829 switch (stack0)
830 {
831 case 0:
832 pstack[0] = where_get_minerals;
833 break;
834 default:
835 pstack[0] = 0;
836 break;
837 }
838 switch (stack1)
839 {
840 case 0:
841 pstack[1] = what_about_aliens;
842 break;
843 default:
844 pstack[1] = 0;
845 break;
846 }
847 switch (stack2)
848 {
849 case 0:
850 pstack[2] = what_do_now;
851 break;
852 default:
853 pstack[2] = 0;
854 break;
855 }
856 switch (stack3)
857 {
858 case 0:
859 pstack[3] = what_about_urquan;
860 break;
861 case 1:
862 pstack[3] = how_defeat;
863 break;
864 default:
865 pstack[3] = 0;
866 break;
867 }
868
869 if (pstack[0])
870 Response (pstack[0], TellMission);
871 if (pstack[1])
872 Response (pstack[1], TellMission);
873 if (pstack[2])
874 Response (pstack[2], TellMission);
875 if (pstack[3])
876 {
877 if (stack3 == 1)
878 Response (pstack[3], DefeatUrquan);
879 else
880 Response (pstack[3], TellMission);
881 }
882
883 Response (enough_mission, NeedInfo);
884 }
885
886 static void
TellStarBase(RESPONSE_REF R)887 TellStarBase (RESPONSE_REF R)
888 {
889 RESPONSE_REF pstack[4];
890 static UNICODE buf0[80];
891
892 if (PLAYER_SAID (R, starbase_functions))
893 {
894 NPCPhrase (WHICH_FUNCTION);
895 stack0 = 0;
896 stack1 = 0;
897 stack2 = 0;
898 stack3 = 0;
899 }
900 else if (PLAYER_SAID (R, tell_me_about_fuel0))
901 {
902 NPCPhrase (ABOUT_FUEL);
903
904 stack1 = 1;
905 }
906 else if (PLAYER_SAID (R, tell_me_about_crew))
907 {
908 NPCPhrase (ABOUT_CREW0);
909 if (usingSpeech)
910 NPCPhrase (YOUR_FLAGSHIP_3DO2);
911 else {
912 NPCPhrase (YOUR_FLAGSHIP_PC);
913 NPCPhrase (GLOBAL_SHIP_NAME);
914 }
915 NPCPhrase (ABOUT_CREW1);
916
917 stack2 = 2;
918 }
919 else if (PLAYER_SAID (R, tell_me_about_modules0))
920 {
921 NPCPhrase (ABOUT_MODULES);
922
923 stack0 = 1;
924 }
925 else if (PLAYER_SAID (R, tell_me_about_ships))
926 {
927 NPCPhrase (ABOUT_SHIPS);
928
929 stack2 = 1;
930 }
931 else if (PLAYER_SAID (R, tell_me_about_ru))
932 {
933 NPCPhrase (ABOUT_RU);
934
935 stack3 = 1;
936 }
937 else if (PLAYER_SAID (R, tell_me_about_minerals))
938 {
939 NPCPhrase (ABOUT_MINERALS);
940
941 stack3 = 2;
942 }
943 else if (PLAYER_SAID (R, tell_me_about_life))
944 {
945 NPCPhrase (ABOUT_LIFE);
946
947 stack3 = 3;
948 }
949
950 switch (stack0)
951 {
952 case 0:
953 construct_response (
954 buf0,
955 tell_me_about_modules0,
956 GLOBAL_SIS (ShipName),
957 tell_me_about_modules1,
958 (UNICODE*)NULL);
959 pstack[0] = tell_me_about_modules0;
960 break;
961 default:
962 pstack[0] = 0;
963 break;
964 }
965 switch (stack1)
966 {
967 case 0:
968 construct_response (
969 shared_phrase_buf,
970 tell_me_about_fuel0,
971 GLOBAL_SIS (ShipName),
972 tell_me_about_fuel1,
973 (UNICODE*)NULL);
974 pstack[1] = tell_me_about_fuel0;
975 break;
976 default:
977 pstack[1] = 0;
978 break;
979 }
980 switch (stack2)
981 {
982 case 0:
983 pstack[2] = tell_me_about_ships;
984 break;
985 case 1:
986 pstack[2] = tell_me_about_crew;
987 break;
988 default:
989 pstack[2] = 0;
990 break;
991 }
992 switch (stack3)
993 {
994 case 0:
995 pstack[3] = tell_me_about_ru;
996 break;
997 case 1:
998 pstack[3] = tell_me_about_minerals;
999 break;
1000 case 2:
1001 pstack[3] = tell_me_about_life;
1002 break;
1003 default:
1004 pstack[3] = 0;
1005 break;
1006 }
1007
1008 if (pstack[0])
1009 DoResponsePhrase (pstack[0], TellStarBase, buf0);
1010 if (pstack[1])
1011 DoResponsePhrase (pstack[1], TellStarBase, shared_phrase_buf);
1012 if (pstack[2])
1013 Response (pstack[2], TellStarBase);
1014 if (pstack[3])
1015 Response (pstack[3], TellStarBase);
1016
1017 Response (enough_starbase, NeedInfo);
1018 }
1019
1020 static void NormalStarbase (RESPONSE_REF R);
1021
1022 static void
NeedInfo(RESPONSE_REF R)1023 NeedInfo (RESPONSE_REF R)
1024 {
1025 if (PLAYER_SAID (R, need_info))
1026 NPCPhrase (WHAT_KIND_OF_INFO);
1027 else if (PLAYER_SAID (R, enough_starbase))
1028 NPCPhrase (OK_ENOUGH_STARBASE);
1029 else if (PLAYER_SAID (R, enough_history))
1030 NPCPhrase (OK_ENOUGH_HISTORY);
1031 else if (PLAYER_SAID (R, enough_mission))
1032 NPCPhrase (OK_ENOUGH_MISSION);
1033
1034 Response (starbase_functions, TellStarBase);
1035 Response (history, TellHistory);
1036 Response (our_mission, TellMission);
1037 Response (no_need_info, NormalStarbase);
1038 }
1039
1040 static BOOLEAN
DiscussDevices(BOOLEAN TalkAbout)1041 DiscussDevices (BOOLEAN TalkAbout)
1042 {
1043 COUNT i, VuxBeastIndex, PhraseIndex;
1044 BOOLEAN Undiscussed;
1045
1046 if (TalkAbout)
1047 NPCPhrase (DEVICE_HEAD);
1048 PhraseIndex = 2;
1049
1050 VuxBeastIndex = 0;
1051 Undiscussed = FALSE;
1052 for (i = 0; i < NUM_DEVICES; ++i)
1053 {
1054 RESPONSE_REF pStr;
1055
1056 pStr = 0;
1057 switch (i)
1058 {
1059 case ROSY_SPHERE_DEVICE:
1060 if (GET_GAME_STATE (ROSY_SPHERE_ON_SHIP)
1061 && !GET_GAME_STATE (DISCUSSED_ROSY_SPHERE))
1062 {
1063 pStr = ABOUT_SPHERE;
1064 SET_GAME_STATE (DISCUSSED_ROSY_SPHERE, TalkAbout);
1065 }
1066 break;
1067 case ARTIFACT_2_DEVICE:
1068 if (GET_GAME_STATE (ARTIFACT_2_ON_SHIP)
1069 && !GET_GAME_STATE (DISCUSSED_ARTIFACT_2))
1070 {
1071 pStr = ABOUT_ARTIFACT_2;
1072 SET_GAME_STATE (DISCUSSED_ARTIFACT_2, TalkAbout);
1073 }
1074 break;
1075 case ARTIFACT_3_DEVICE:
1076 if (GET_GAME_STATE (ARTIFACT_3_ON_SHIP)
1077 && !GET_GAME_STATE (DISCUSSED_ARTIFACT_3))
1078 {
1079 pStr = ABOUT_ARTIFACT_3;
1080 SET_GAME_STATE (DISCUSSED_ARTIFACT_3, TalkAbout);
1081 }
1082 break;
1083 case SUN_EFFICIENCY_DEVICE:
1084 if (GET_GAME_STATE (SUN_DEVICE_ON_SHIP)
1085 && !GET_GAME_STATE (DISCUSSED_SUN_EFFICIENCY))
1086 {
1087 pStr = ABOUT_SUN;
1088 SET_GAME_STATE (DISCUSSED_SUN_EFFICIENCY, TalkAbout);
1089 }
1090 break;
1091 case UTWIG_BOMB_DEVICE:
1092 if (GET_GAME_STATE (UTWIG_BOMB_ON_SHIP)
1093 && !GET_GAME_STATE (DISCUSSED_UTWIG_BOMB))
1094 {
1095 pStr = ABOUT_BOMB;
1096 SET_GAME_STATE (DISCUSSED_UTWIG_BOMB, TalkAbout);
1097 }
1098 break;
1099 case ULTRON_0_DEVICE:
1100 if (GET_GAME_STATE (ULTRON_CONDITION) == 1
1101 && !GET_GAME_STATE (DISCUSSED_ULTRON))
1102 {
1103 pStr = ABOUT_ULTRON_0;
1104 SET_GAME_STATE (DISCUSSED_ULTRON, TalkAbout);
1105 }
1106 break;
1107 case ULTRON_1_DEVICE:
1108 if (GET_GAME_STATE (ULTRON_CONDITION) == 2
1109 && !GET_GAME_STATE (DISCUSSED_ULTRON))
1110 {
1111 pStr = ABOUT_ULTRON_1;
1112 SET_GAME_STATE (DISCUSSED_ULTRON, TalkAbout);
1113 }
1114 break;
1115 case ULTRON_2_DEVICE:
1116 if (GET_GAME_STATE (ULTRON_CONDITION) == 3
1117 && !GET_GAME_STATE (DISCUSSED_ULTRON))
1118 {
1119 pStr = ABOUT_ULTRON_2;
1120 SET_GAME_STATE (DISCUSSED_ULTRON, TalkAbout);
1121 }
1122 break;
1123 case ULTRON_3_DEVICE:
1124 if (GET_GAME_STATE (ULTRON_CONDITION) == 4
1125 && !GET_GAME_STATE (DISCUSSED_ULTRON))
1126 {
1127 pStr = ABOUT_ULTRON_3;
1128 SET_GAME_STATE (DISCUSSED_ULTRON, TalkAbout);
1129 }
1130 break;
1131 case MAIDENS_DEVICE:
1132 if (GET_GAME_STATE (MAIDENS_ON_SHIP)
1133 && !GET_GAME_STATE (DISCUSSED_MAIDENS))
1134 {
1135 pStr = ABOUT_MAIDENS;
1136 SET_GAME_STATE (DISCUSSED_MAIDENS, TalkAbout);
1137 }
1138 break;
1139 case TALKING_PET_DEVICE:
1140 if (GET_GAME_STATE (TALKING_PET_ON_SHIP)
1141 && !GET_GAME_STATE (DISCUSSED_TALKING_PET))
1142 {
1143 pStr = ABOUT_TALKPET;
1144 SET_GAME_STATE (DISCUSSED_TALKING_PET, TalkAbout);
1145 }
1146 break;
1147 case AQUA_HELIX_DEVICE:
1148 if (GET_GAME_STATE (AQUA_HELIX_ON_SHIP)
1149 && !GET_GAME_STATE (DISCUSSED_AQUA_HELIX))
1150 {
1151 pStr = ABOUT_HELIX;
1152 SET_GAME_STATE (DISCUSSED_AQUA_HELIX, TalkAbout);
1153 }
1154 break;
1155 case CLEAR_SPINDLE_DEVICE:
1156 if (GET_GAME_STATE (CLEAR_SPINDLE_ON_SHIP)
1157 && !GET_GAME_STATE (DISCUSSED_CLEAR_SPINDLE))
1158 {
1159 pStr = ABOUT_SPINDLE;
1160 SET_GAME_STATE (DISCUSSED_CLEAR_SPINDLE, TalkAbout);
1161 }
1162 break;
1163 case UMGAH_HYPERWAVE_DEVICE:
1164 if (GET_GAME_STATE (UMGAH_BROADCASTERS_ON_SHIP)
1165 && !GET_GAME_STATE (DISCUSSED_UMGAH_HYPERWAVE))
1166 {
1167 pStr = ABOUT_UCASTER;
1168 SET_GAME_STATE (DISCUSSED_UMGAH_HYPERWAVE, TalkAbout);
1169 }
1170 break;
1171 #ifdef NEVER
1172 case DATA_PLATE_1_DEVICE:
1173 if (GET_GAME_STATE (DATA_PLATE_1_ON_SHIP)
1174 && !GET_GAME_STATE (DISCUSSED_DATA_PLATE_1))
1175 {
1176 pStr = ABOUT_DATAPLATE_1;
1177 SET_GAME_STATE (DISCUSSED_DATA_PLATE_1, TalkAbout);
1178 }
1179 break;
1180 case DATA_PLATE_2_DEVICE:
1181 if (GET_GAME_STATE (DATA_PLATE_2_ON_SHIP)
1182 && !GET_GAME_STATE (DISCUSSED_DATA_PLATE_2))
1183 {
1184 pStr = ABOUT_DATAPLATE_2;
1185 SET_GAME_STATE (DISCUSSED_DATA_PLATE_2, TalkAbout);
1186 }
1187 break;
1188 case DATA_PLATE_3_DEVICE:
1189 if (GET_GAME_STATE (DATA_PLATE_3_ON_SHIP)
1190 && !GET_GAME_STATE (DISCUSSED_DATA_PLATE_3))
1191 {
1192 pStr = ABOUT_DATAPLATE_3;
1193 SET_GAME_STATE (DISCUSSED_DATA_PLATE_3, TalkAbout);
1194 }
1195 break;
1196 #endif /* NEVER */
1197 case TAALO_PROTECTOR_DEVICE:
1198 if (GET_GAME_STATE (TAALO_PROTECTOR_ON_SHIP)
1199 && !GET_GAME_STATE (DISCUSSED_TAALO_PROTECTOR))
1200 {
1201 pStr = ABOUT_SHIELD;
1202 SET_GAME_STATE (DISCUSSED_TAALO_PROTECTOR, TalkAbout);
1203 }
1204 break;
1205 case EGG_CASING0_DEVICE:
1206 if (GET_GAME_STATE (EGG_CASE0_ON_SHIP)
1207 && !GET_GAME_STATE (DISCUSSED_EGG_CASING0))
1208 {
1209 pStr = ABOUT_EGGCASE_0;
1210 SET_GAME_STATE (DISCUSSED_EGG_CASING0, TalkAbout);
1211 SET_GAME_STATE (DISCUSSED_EGG_CASING1, TalkAbout);
1212 SET_GAME_STATE (DISCUSSED_EGG_CASING2, TalkAbout);
1213 }
1214 break;
1215 case EGG_CASING1_DEVICE:
1216 if (GET_GAME_STATE (EGG_CASE1_ON_SHIP)
1217 && !GET_GAME_STATE (DISCUSSED_EGG_CASING1))
1218 {
1219 pStr = ABOUT_EGGCASE_0;
1220 SET_GAME_STATE (DISCUSSED_EGG_CASING0, TalkAbout);
1221 SET_GAME_STATE (DISCUSSED_EGG_CASING1, TalkAbout);
1222 SET_GAME_STATE (DISCUSSED_EGG_CASING2, TalkAbout);
1223 }
1224 break;
1225 case EGG_CASING2_DEVICE:
1226 if (GET_GAME_STATE (EGG_CASE2_ON_SHIP)
1227 && !GET_GAME_STATE (DISCUSSED_EGG_CASING2))
1228 {
1229 pStr = ABOUT_EGGCASE_0;
1230 SET_GAME_STATE (DISCUSSED_EGG_CASING0, TalkAbout);
1231 SET_GAME_STATE (DISCUSSED_EGG_CASING1, TalkAbout);
1232 SET_GAME_STATE (DISCUSSED_EGG_CASING2, TalkAbout);
1233 }
1234 break;
1235 case SYREEN_SHUTTLE_DEVICE:
1236 if (GET_GAME_STATE (SYREEN_SHUTTLE_ON_SHIP)
1237 && !GET_GAME_STATE (DISCUSSED_SYREEN_SHUTTLE))
1238 {
1239 pStr = ABOUT_SHUTTLE;
1240 SET_GAME_STATE (DISCUSSED_SYREEN_SHUTTLE, TalkAbout);
1241 }
1242 break;
1243 case VUX_BEAST_DEVICE:
1244 if (GET_GAME_STATE (VUX_BEAST_ON_SHIP)
1245 && !GET_GAME_STATE (DISCUSSED_VUX_BEAST))
1246 {
1247 pStr = ABOUT_VUXBEAST0;
1248 SET_GAME_STATE (DISCUSSED_VUX_BEAST, TalkAbout);
1249 }
1250 break;
1251 case DESTRUCT_CODE_DEVICE:
1252 if (GET_GAME_STATE (DESTRUCT_CODE_ON_SHIP)
1253 && !GET_GAME_STATE (DISCUSSED_DESTRUCT_CODE))
1254 {
1255 pStr = ABOUT_DESTRUCT;
1256 SET_GAME_STATE (DISCUSSED_DESTRUCT_CODE, TalkAbout);
1257 }
1258 break;
1259 case PORTAL_SPAWNER_DEVICE:
1260 if (GET_GAME_STATE (PORTAL_SPAWNER_ON_SHIP)
1261 && !GET_GAME_STATE (DISCUSSED_PORTAL_SPAWNER))
1262 {
1263 pStr = ABOUT_PORTAL;
1264 SET_GAME_STATE (DISCUSSED_PORTAL_SPAWNER, TalkAbout);
1265 }
1266 break;
1267 case URQUAN_WARP_DEVICE:
1268 if (GET_GAME_STATE (PORTAL_KEY_ON_SHIP)
1269 && !GET_GAME_STATE (DISCUSSED_URQUAN_WARP))
1270 {
1271 pStr = ABOUT_WARPPOD;
1272 SET_GAME_STATE (DISCUSSED_URQUAN_WARP, TalkAbout);
1273 }
1274 break;
1275 case BURVIX_HYPERWAVE_DEVICE:
1276 if (GET_GAME_STATE (BURV_BROADCASTERS_ON_SHIP)
1277 && !GET_GAME_STATE (DISCUSSED_BURVIX_HYPERWAVE))
1278 {
1279 pStr = ABOUT_BCASTER;
1280 SET_GAME_STATE (DISCUSSED_BURVIX_HYPERWAVE, TalkAbout);
1281 }
1282 break;
1283 }
1284
1285 if (pStr)
1286 {
1287 if (TalkAbout)
1288 {
1289 if (PhraseIndex > 2)
1290 NPCPhrase (BETWEEN_DEVICES);
1291 NPCPhrase (pStr);
1292 if (pStr == ABOUT_VUXBEAST0)
1293 {
1294 VuxBeastIndex = ++PhraseIndex;
1295 NPCPhrase (ABOUT_VUXBEAST1);
1296 }
1297 }
1298 PhraseIndex += 2;
1299 }
1300 }
1301
1302 if (TalkAbout)
1303 {
1304 NPCPhrase (DEVICE_TAIL);
1305
1306 if (VuxBeastIndex)
1307 {
1308 // Run all tracks upto the Vux Beast scientist's report
1309 AlienTalkSegue (VuxBeastIndex - 1);
1310 // Disable Commander's speech animation and run the report
1311 EnableTalkingAnim (FALSE);
1312 AlienTalkSegue (VuxBeastIndex);
1313 // Enable Commander's speech animation and run the rest
1314 EnableTalkingAnim (TRUE);
1315 AlienTalkSegue ((COUNT)~0);
1316 }
1317 }
1318
1319 return (PhraseIndex > 2);
1320 }
1321
1322 static BOOLEAN
CheckTiming(COUNT month_index,COUNT day_index)1323 CheckTiming (COUNT month_index, COUNT day_index)
1324 {
1325 COUNT mi, year_index;
1326 BYTE days_in_month[12] =
1327 {
1328 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
1329 };
1330
1331 mi = GET_GAME_STATE (STARBASE_MONTH);
1332 year_index = START_YEAR;
1333
1334 day_index += GET_GAME_STATE (STARBASE_DAY);
1335 while (day_index > days_in_month[mi - 1])
1336 {
1337 day_index -= days_in_month[mi - 1];
1338 if (++mi > 12)
1339 {
1340 mi = 1;
1341 ++year_index;
1342 }
1343 }
1344
1345 month_index += mi;
1346 year_index += (month_index - 1) / 12;
1347 month_index = ((month_index - 1) % 12) + 1;
1348
1349 return (year_index < GLOBAL (GameClock.year_index)
1350 || (year_index == GLOBAL (GameClock.year_index)
1351 && (month_index < GLOBAL (GameClock.month_index)
1352 || (month_index == GLOBAL (GameClock.month_index)
1353 && day_index < GLOBAL (GameClock.day_index)))));
1354 }
1355
1356 static void
CheckBulletins(BOOLEAN Repeat)1357 CheckBulletins (BOOLEAN Repeat)
1358 {
1359 RESPONSE_REF pIntro;
1360 BYTE b0;
1361 DWORD BulletinMask;
1362
1363 if (Repeat)
1364 BulletinMask = CurBulletinMask ^ 0xFFFFFFFFL;
1365 else
1366 BulletinMask = GET_GAME_STATE_32 (STARBASE_BULLETS0);
1367
1368 pIntro = 0;
1369 for (b0 = 0; b0 < 32; ++b0)
1370 {
1371 if (!(BulletinMask & (1L << b0)))
1372 {
1373 RESPONSE_REF pStr;
1374
1375 pStr = 0;
1376 switch (b0)
1377 {
1378 case 0:
1379 if (CheckAlliance (SPATHI_SHIP) == GOOD_GUY)
1380 {
1381 pStr = STARBASE_BULLETIN_1;
1382 }
1383 break;
1384 case 1:
1385 if (CheckAlliance (ZOQFOTPIK_SHIP) == GOOD_GUY)
1386 {
1387 pStr = STARBASE_BULLETIN_2;
1388 }
1389 break;
1390 case 2:
1391 if (CheckAlliance (SUPOX_SHIP) == GOOD_GUY)
1392 {
1393 pStr = STARBASE_BULLETIN_3;
1394 }
1395 break;
1396 case 3:
1397 if (CheckAlliance (UTWIG_SHIP) == GOOD_GUY)
1398 {
1399 pStr = STARBASE_BULLETIN_4;
1400 }
1401 break;
1402 case 4:
1403 if (CheckAlliance (ORZ_SHIP) == GOOD_GUY)
1404 {
1405 pStr = STARBASE_BULLETIN_5;
1406 }
1407 break;
1408 case 5:
1409 if (GET_GAME_STATE (ARILOU_MANNER) == 2)
1410 BulletinMask |= 1L << b0;
1411 else if (GET_GAME_STATE (PORTAL_SPAWNER)
1412 && (Repeat || EscortFeasibilityStudy (
1413 ARILOU_SHIP)))
1414 {
1415 #define NUM_GIFT_ARILOUS 3
1416 pStr = STARBASE_BULLETIN_6;
1417 if (!Repeat)
1418 AddEscortShips (ARILOU_SHIP, NUM_GIFT_ARILOUS);
1419 }
1420 break;
1421 case 6:
1422 if (GET_GAME_STATE (ZOQFOT_DISTRESS) == 1)
1423 {
1424 pStr = STARBASE_BULLETIN_7;
1425 }
1426 break;
1427 case 7:
1428 if (GET_GAME_STATE (MET_MELNORME))
1429 BulletinMask |= 1L << b0;
1430 else if (CheckTiming (3, 0))
1431 {
1432 pStr = STARBASE_BULLETIN_8;
1433 }
1434 break;
1435 case 8:
1436 if (GET_GAME_STATE (MET_MELNORME))
1437 BulletinMask |= 1L << b0;
1438 else if (CheckTiming (6, 0))
1439 {
1440 pStr = STARBASE_BULLETIN_9;
1441 }
1442 break;
1443 case 9:
1444 if (GET_GAME_STATE (FOUND_PLUTO_SPATHI))
1445 BulletinMask |= 1L << b0;
1446 else if (CheckTiming (0, 7))
1447 {
1448 pStr = STARBASE_BULLETIN_10;
1449 }
1450 break;
1451 case 10:
1452 if (GET_GAME_STATE (SPATHI_SHIELDED_SELVES))
1453 {
1454 pStr = STARBASE_BULLETIN_11;
1455 }
1456 break;
1457 case 11:
1458 if (GET_GAME_STATE (ZOQFOT_HOME_VISITS)
1459 || GET_GAME_STATE_32 (ZOQFOT_GRPOFFS0))
1460 BulletinMask |= 1L << b0;
1461 else if (CheckTiming (0, 42))
1462 {
1463 pStr = STARBASE_BULLETIN_12;
1464 }
1465 break;
1466 case 12:
1467 if (CheckAlliance (CHMMR_SHIP) == GOOD_GUY)
1468 {
1469 pStr = STARBASE_BULLETIN_13;
1470 }
1471 break;
1472 case 13:
1473 if (CheckAlliance (SHOFIXTI_SHIP) == GOOD_GUY)
1474 {
1475 pStr = STARBASE_BULLETIN_14;
1476 }
1477 break;
1478 case 14:
1479 if (GET_GAME_STATE (PKUNK_MISSION))
1480 {
1481 pStr = STARBASE_BULLETIN_15;
1482 }
1483 break;
1484 case 15:
1485 if (GET_GAME_STATE (DESTRUCT_CODE_ON_SHIP))
1486 BulletinMask |= 1L << b0;
1487 else if (CheckTiming (7, 0))
1488 {
1489 pStr = STARBASE_BULLETIN_16;
1490 }
1491 break;
1492 case 16:
1493 break;
1494 case 17:
1495 if (GET_GAME_STATE (YEHAT_ABSORBED_PKUNK))
1496 {
1497 pStr = STARBASE_BULLETIN_18;
1498 }
1499 break;
1500 case 18:
1501 if (GET_GAME_STATE (CHMMR_BOMB_STATE) == 2)
1502 {
1503 pStr = STARBASE_BULLETIN_19;
1504 }
1505 break;
1506 case 19:
1507 break;
1508 case 20:
1509 break;
1510 case 21:
1511 if (GET_GAME_STATE (ZOQFOT_DISTRESS) == 2)
1512 {
1513 pStr = STARBASE_BULLETIN_22;
1514 }
1515 break;
1516 case 22:
1517 break;
1518 case 23:
1519 break;
1520 case 24:
1521 break;
1522 case 25:
1523 break;
1524 case 26:
1525 {
1526 COUNT crew_sold;
1527
1528 crew_sold = MAKE_WORD (
1529 GET_GAME_STATE (CREW_SOLD_TO_DRUUGE0),
1530 GET_GAME_STATE (CREW_SOLD_TO_DRUUGE1)
1531 );
1532 if (crew_sold > 100)
1533 BulletinMask |= 1L << b0;
1534 else if (crew_sold)
1535 {
1536 pStr = STARBASE_BULLETIN_27;
1537 }
1538 break;
1539 }
1540 case 27:
1541 {
1542 COUNT crew_sold;
1543
1544 crew_sold = MAKE_WORD (
1545 GET_GAME_STATE (CREW_SOLD_TO_DRUUGE0),
1546 GET_GAME_STATE (CREW_SOLD_TO_DRUUGE1)
1547 );
1548 if (crew_sold > 250)
1549 BulletinMask |= 1L << b0;
1550 else if (crew_sold > 100)
1551 {
1552 pStr = STARBASE_BULLETIN_28;
1553 }
1554 break;
1555 }
1556 case 28:
1557 {
1558 COUNT crew_bought;
1559
1560 crew_bought = MAKE_WORD (
1561 GET_GAME_STATE (CREW_PURCHASED0),
1562 GET_GAME_STATE (CREW_PURCHASED1)
1563 );
1564 if (crew_bought >= CREW_EXPENSE_THRESHOLD)
1565 {
1566 pStr = STARBASE_BULLETIN_29;
1567 }
1568 break;
1569 }
1570 case 29:
1571 if (MAKE_WORD (
1572 GET_GAME_STATE (CREW_SOLD_TO_DRUUGE0),
1573 GET_GAME_STATE (CREW_SOLD_TO_DRUUGE1)
1574 ) > 250)
1575 {
1576 pStr = STARBASE_BULLETIN_30;
1577 }
1578 break;
1579 case 30:
1580 break;
1581 case 31:
1582 break;
1583 }
1584
1585 if (pStr)
1586 {
1587 if (pIntro)
1588 NPCPhrase (BETWEEN_BULLETINS);
1589 else if (Repeat)
1590 pIntro = BEFORE_WE_GO_ON_1;
1591 else
1592 {
1593 switch ((BYTE)TFB_Random () % 7)
1594 {
1595 case 0:
1596 pIntro = BEFORE_WE_GO_ON_1;
1597 break;
1598 case 1:
1599 pIntro = BEFORE_WE_GO_ON_2;
1600 break;
1601 case 2:
1602 pIntro = BEFORE_WE_GO_ON_3;
1603 break;
1604 case 3:
1605 pIntro = BEFORE_WE_GO_ON_4;
1606 break;
1607 case 4:
1608 pIntro = BEFORE_WE_GO_ON_5;
1609 break;
1610 case 5:
1611 pIntro = BEFORE_WE_GO_ON_6;
1612 break;
1613 default:
1614 pIntro = BEFORE_WE_GO_ON_7;
1615 break;
1616 }
1617
1618 NPCPhrase (pIntro);
1619 }
1620
1621 NPCPhrase (pStr);
1622 CurBulletinMask |= 1L << b0;
1623 }
1624 }
1625 }
1626
1627 if (pIntro == 0 && GET_GAME_STATE (STARBASE_VISITED))
1628 NPCPhrase (RETURN_HELLO);
1629 else if (!Repeat)
1630 SET_GAME_STATE_32 (STARBASE_BULLETS0, BulletinMask);
1631 }
1632
1633 static void
NormalStarbase(RESPONSE_REF R)1634 NormalStarbase (RESPONSE_REF R)
1635 {
1636 if (PLAYER_SAID (R, no_need_info))
1637 NPCPhrase (OK_NO_NEED_INFO);
1638 else if (PLAYER_SAID (R, new_devices))
1639 DiscussDevices (TRUE);
1640 else if (PLAYER_SAID (R, repeat_bulletins))
1641 CheckBulletins (TRUE);
1642 else if (R == 0)
1643 {
1644 if (GET_GAME_STATE (MOONBASE_ON_SHIP))
1645 {
1646 NPCPhrase (STARBASE_IS_READY_A);
1647 if (usingSpeech)
1648 NPCPhrase (YOUR_FLAGSHIP_3DO1);
1649 else {
1650 NPCPhrase (YOUR_FLAGSHIP_PC);
1651 NPCPhrase (GLOBAL_SHIP_NAME);
1652 }
1653 NPCPhrase (STARBASE_IS_READY_B);
1654 if (usingSpeech)
1655 NPCPhrase (YOUR_FLAGSHIP_3DO0);
1656 else
1657 NPCPhrase (GLOBAL_SHIP_NAME);
1658 NPCPhrase (STARBASE_IS_READY_C);
1659 DeltaSISGauges (0, 0, 2500);
1660 SET_GAME_STATE (STARBASE_MONTH,
1661 GLOBAL (GameClock.month_index));
1662 SET_GAME_STATE (STARBASE_DAY,
1663 GLOBAL (GameClock.day_index));
1664 }
1665 else if (GET_GAME_STATE (STARBASE_VISITED))
1666 {
1667 CheckBulletins (FALSE);
1668 }
1669 else
1670 {
1671 RESPONSE_REF pStr0 = 0;
1672 RESPONSE_REF pStr1 = 0;
1673
1674 switch ((BYTE)TFB_Random () & 7)
1675 {
1676 case 0:
1677 pStr0 = NORMAL_HELLO_A0;
1678 pStr1 = NORMAL_HELLO_A1;
1679 break;
1680 case 1:
1681 pStr0 = NORMAL_HELLO_B0;
1682 pStr1 = NORMAL_HELLO_B1;
1683 break;
1684 case 2:
1685 pStr0 = NORMAL_HELLO_C0;
1686 pStr1 = NORMAL_HELLO_C1;
1687 break;
1688 case 3:
1689 pStr0 = NORMAL_HELLO_D0;
1690 pStr1 = NORMAL_HELLO_D1;
1691 break;
1692 case 4:
1693 pStr0 = NORMAL_HELLO_E0;
1694 pStr1 = NORMAL_HELLO_E1;
1695 break;
1696 case 5:
1697 pStr0 = NORMAL_HELLO_F0;
1698 pStr1 = NORMAL_HELLO_F1;
1699 break;
1700 case 6:
1701 pStr0 = NORMAL_HELLO_G0;
1702 pStr1 = NORMAL_HELLO_G1;
1703 break;
1704 case 7:
1705 pStr0 = NORMAL_HELLO_H0;
1706 pStr1 = NORMAL_HELLO_H1;
1707 break;
1708 }
1709 NPCPhrase (pStr0);
1710 if (!usingSpeech)
1711 {
1712 NPCPhrase (SPACE);
1713 NPCPhrase (GLOBAL_PLAYER_NAME);
1714 }
1715 NPCPhrase (pStr1);
1716 CheckBulletins (FALSE);
1717 }
1718
1719 SET_GAME_STATE (STARBASE_VISITED, 1);
1720 }
1721
1722 if (GLOBAL_SIS (TotalElementMass))
1723 Response (have_minerals, SellMinerals);
1724 if (DiscussDevices (FALSE))
1725 Response (new_devices, NormalStarbase);
1726 if (CurBulletinMask)
1727 Response (repeat_bulletins, NormalStarbase);
1728 Response (need_info, NeedInfo);
1729 Response (goodbye_commander, ByeBye);
1730 }
1731
1732 static void
SellMinerals(RESPONSE_REF R)1733 SellMinerals (RESPONSE_REF R)
1734 {
1735 COUNT i, total;
1736 BOOLEAN Sleepy;
1737 RESPONSE_REF pStr1 = 0;
1738 RESPONSE_REF pStr2 = 0;
1739
1740 total = 0;
1741 Sleepy = TRUE;
1742 for (i = 0; i < NUM_ELEMENT_CATEGORIES; ++i)
1743 {
1744 COUNT amount;
1745 DWORD TimeIn = 0;
1746
1747 if (i == 0)
1748 {
1749 DrawCargoStrings ((BYTE)~0, (BYTE)~0);
1750 SleepThread (ONE_SECOND / 2);
1751 TimeIn = GetTimeCounter ();
1752 DrawCargoStrings ((BYTE)0, (BYTE)0);
1753 }
1754 else if (Sleepy)
1755 {
1756 DrawCargoStrings ((BYTE)(i - 1), (BYTE)i);
1757 TimeIn = GetTimeCounter ();
1758 }
1759
1760 if ((amount = GLOBAL_SIS (ElementAmounts[i])) != 0)
1761 {
1762 total += amount * GLOBAL (ElementWorth[i]);
1763 do
1764 {
1765 if (!Sleepy || AnyButtonPress (TRUE) ||
1766 (GLOBAL (CurrentActivity) & CHECK_ABORT))
1767 {
1768 Sleepy = FALSE;
1769 GLOBAL_SIS (ElementAmounts[i]) = 0;
1770 GLOBAL_SIS (TotalElementMass) -= amount;
1771 DeltaSISGauges (0, 0, amount * GLOBAL (ElementWorth[i]));
1772 break;
1773 }
1774
1775 --GLOBAL_SIS (ElementAmounts[i]);
1776 --GLOBAL_SIS (TotalElementMass);
1777 TaskSwitch ();
1778 TimeIn = GetTimeCounter ();
1779 DrawCargoStrings ((BYTE)i, (BYTE)i);
1780 ShowRemainingCapacity ();
1781 DeltaSISGauges (0, 0, GLOBAL (ElementWorth[i]));
1782 } while (--amount);
1783 }
1784 if (Sleepy) {
1785 SleepThreadUntil (TimeIn + (ONE_SECOND / 4));
1786 TimeIn = GetTimeCounter ();
1787 }
1788 }
1789 SleepThread (ONE_SECOND / 2);
1790
1791 ClearSISRect (DRAW_SIS_DISPLAY);
1792 // DrawStorageBays (FALSE);
1793
1794 if (total < 1000)
1795 {
1796 total = GET_GAME_STATE (LIGHT_MINERAL_LOAD);
1797 switch (total++)
1798 {
1799 case 0:
1800 pStr1 = LIGHT_LOAD_A0;
1801 pStr2 = LIGHT_LOAD_A1;
1802 break;
1803 case 1:
1804 pStr1 = LIGHT_LOAD_B0;
1805 pStr2 = LIGHT_LOAD_B1;
1806 break;
1807 case 2:
1808 pStr1 = LIGHT_LOAD_C0;
1809 pStr2 = LIGHT_LOAD_C1;
1810 break;
1811 case 3:
1812 pStr1 = LIGHT_LOAD_D0;
1813 pStr2 = LIGHT_LOAD_D1;
1814 break;
1815 case 4:
1816 pStr1 = LIGHT_LOAD_E0;
1817 pStr2 = LIGHT_LOAD_E1;
1818 break;
1819 case 5:
1820 pStr1 = LIGHT_LOAD_F0;
1821 pStr2 = LIGHT_LOAD_F1;
1822 break;
1823 case 6:
1824 --total;
1825 pStr1 = LIGHT_LOAD_G0;
1826 pStr2 = LIGHT_LOAD_G1;
1827 break;
1828 }
1829 SET_GAME_STATE (LIGHT_MINERAL_LOAD, total);
1830 }
1831 else if (total < 2500)
1832 {
1833 total = GET_GAME_STATE (MEDIUM_MINERAL_LOAD);
1834 switch (total++)
1835 {
1836 case 0:
1837 pStr1 = MEDIUM_LOAD_A0;
1838 pStr2 = MEDIUM_LOAD_A1;
1839 break;
1840 case 1:
1841 pStr1 = MEDIUM_LOAD_B0;
1842 pStr2 = MEDIUM_LOAD_B1;
1843 break;
1844 case 2:
1845 pStr1 = MEDIUM_LOAD_C0;
1846 pStr2 = MEDIUM_LOAD_C1;
1847 break;
1848 case 3:
1849 pStr1 = MEDIUM_LOAD_D0;
1850 pStr2 = MEDIUM_LOAD_D1;
1851 break;
1852 case 4:
1853 pStr1 = MEDIUM_LOAD_E0;
1854 pStr2 = MEDIUM_LOAD_E1;
1855 break;
1856 case 5:
1857 pStr1 = MEDIUM_LOAD_F0;
1858 pStr2 = MEDIUM_LOAD_F1;
1859 break;
1860 case 6:
1861 --total;
1862 pStr1 = MEDIUM_LOAD_G0;
1863 pStr2 = MEDIUM_LOAD_G1;
1864 break;
1865 }
1866 SET_GAME_STATE (MEDIUM_MINERAL_LOAD, total);
1867 }
1868 else
1869 {
1870 total = GET_GAME_STATE (HEAVY_MINERAL_LOAD);
1871 switch (total++)
1872 {
1873 case 0:
1874 pStr1 = HEAVY_LOAD_A0;
1875 pStr2 = HEAVY_LOAD_A1;
1876 break;
1877 case 1:
1878 pStr1 = HEAVY_LOAD_B0;
1879 pStr2 = HEAVY_LOAD_B1;
1880 break;
1881 case 2:
1882 pStr1 = HEAVY_LOAD_C0;
1883 pStr2 = HEAVY_LOAD_C1;
1884 break;
1885 case 3:
1886 pStr1 = HEAVY_LOAD_D0;
1887 pStr2 = HEAVY_LOAD_D1;
1888 break;
1889 case 4:
1890 pStr1 = HEAVY_LOAD_E0;
1891 pStr2 = HEAVY_LOAD_E1;
1892 break;
1893 case 5:
1894 pStr1 = HEAVY_LOAD_F0;
1895 pStr2 = HEAVY_LOAD_F1;
1896 break;
1897 case 6:
1898 --total;
1899 pStr1 = HEAVY_LOAD_G0;
1900 pStr2 = HEAVY_LOAD_G1;
1901 break;
1902 }
1903 SET_GAME_STATE (HEAVY_MINERAL_LOAD, total);
1904 }
1905
1906 NPCPhrase (pStr1);
1907 if (!usingSpeech)
1908 {
1909 NPCPhrase (SPACE);
1910 NPCPhrase (GLOBAL_PLAYER_NAME);
1911 }
1912 NPCPhrase (pStr2);
1913
1914 NormalStarbase (R);
1915 }
1916
1917 static void
Intro(void)1918 Intro (void)
1919 {
1920 NormalStarbase (0);
1921 }
1922
1923 static COUNT
uninit_starbase(void)1924 uninit_starbase (void)
1925 {
1926 return (0);
1927 }
1928
1929 static void
post_starbase_enc(void)1930 post_starbase_enc (void)
1931 {
1932 SET_GAME_STATE (MOONBASE_ON_SHIP, 0);
1933 if (GET_GAME_STATE (CHMMR_BOMB_STATE) == 2)
1934 {
1935 SET_GAME_STATE (CHMMR_BOMB_STATE, 3);
1936 }
1937 }
1938
1939 LOCDATA*
init_starbase_comm()1940 init_starbase_comm ()
1941 {
1942 LOCDATA *retval;
1943
1944 commander_desc.init_encounter_func = Intro;
1945 commander_desc.post_encounter_func = post_starbase_enc;
1946 commander_desc.uninit_encounter_func = uninit_starbase;
1947
1948 commander_desc.AlienTextWidth = 143;
1949 commander_desc.AlienTextBaseline.x = 164;
1950 commander_desc.AlienTextBaseline.y = 20;
1951
1952 // use alternate Starbase track if available
1953 commander_desc.AlienAltSongRes = STARBASE_ALT_MUSIC;
1954 commander_desc.AlienSongFlags |= LDASF_USE_ALTERNATE;
1955
1956 CurBulletinMask = 0;
1957 setSegue (Segue_peace);
1958 retval = &commander_desc;
1959
1960 return (retval);
1961 }
1962