//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "../commall.h" #include "resinst.h" #include "strings.h" #include "uqm/build.h" #include "uqm/hyper.h" // for SOL_X/SOL_Y static LOCDATA chmmr_desc = { NULL, /* init_encounter_func */ NULL, /* post_encounter_func */ NULL, /* uninit_encounter_func */ CHMMR_PMAP_ANIM, /* AlienFrame */ CHMMR_FONT, /* AlienFont */ WHITE_COLOR_INIT, /* AlienTextFColor */ BLACK_COLOR_INIT, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_TOP, /* AlienTextValign */ CHMMR_COLOR_MAP, /* AlienColorMap */ CHMMR_MUSIC, /* AlienSong */ NULL_RESOURCE, /* AlienAltSong */ 0, /* AlienSongFlags */ CHMMR_CONVERSATION_PHRASES, /* PlayerPhrases */ 6, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { 12, /* StartIndex */ 5, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 17, /* StartIndex */ 5, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 22, /* StartIndex */ 5, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 27, /* StartIndex */ 20, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 47, /* StartIndex */ 14, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 61, /* StartIndex */ 24, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, }, { /* AlienTransitionDesc */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc */ 1, /* StartIndex */ 11, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 60, 0, /* FrameRate */ ONE_SECOND / 60, 0, /* RestartRate */ 0, /* BlockMask */ }, NULL, /* AlienNumberSpeech - none */ /* Filler for loaded resources */ NULL, NULL, NULL, NULL, NULL, }; static void ExitConversation (RESPONSE_REF R) { setSegue (Segue_peace); if (PLAYER_SAID (R, bye)) NPCPhrase (GOODBYE); else if (PLAYER_SAID (R, bye_shielded)) NPCPhrase (GOODBYE_SHIELDED); else if (PLAYER_SAID (R, bye_after_bomb)) NPCPhrase (GOODBYE_AFTER_BOMB); else if (PLAYER_SAID (R, proceed)) { int i; NPCPhrase (TAKE_2_WEEKS); SetRaceAllied (CHMMR_SHIP, TRUE); SET_GAME_STATE (CHMMR_HOME_VISITS, 0); SET_GAME_STATE (CHMMR_STACK, 0); SET_GAME_STATE (CHMMR_BOMB_STATE, 2); SET_GAME_STATE (UTWIG_BOMB_ON_SHIP, 0); GLOBAL_SIS (ResUnits) = 1000000L; GLOBAL_SIS (NumLanders) = 0; GLOBAL (ModuleCost[PLANET_LANDER]) = 0; #define EARTH_INDEX 2 /* earth is 3rd planet --> 3 - 1 = 2 */ /* Magic numbers for Earth */ #define EARTH_OUTER_X (-725) #define EARTH_OUTER_Y (597) #define EARTH_INNER_X (121) #define EARTH_INNER_Y (113) /* Magic numbers for Earth Starbase */ #define STARBASE_INNER_X (86) #define STARBASE_INNER_Y (113) /* transport player to Earth */ GLOBAL_SIS (log_x) = UNIVERSE_TO_LOGX (SOL_X); GLOBAL_SIS (log_y) = UNIVERSE_TO_LOGY (SOL_Y); GLOBAL (ShipFacing) = 1; /* At Earth or at Starbase */ GLOBAL (ip_planet) = EARTH_INDEX + 1; GLOBAL (in_orbit) = 0; /* XXX : this should be unhardcoded eventually */ GLOBAL (ip_location.x) = EARTH_OUTER_X; GLOBAL (ip_location.y) = EARTH_OUTER_Y; if (GET_GAME_STATE (STARBASE_AVAILABLE)) { /* Normal game mode - you are transported to Starbase */ GLOBAL_SIS (FuelOnBoard) = FUEL_RESERVE; GLOBAL_SIS (CrewEnlisted) = 0; GLOBAL_SIS (TotalElementMass) = 0; GLOBAL (ModuleCost[STORAGE_BAY]) = 0; /* disable Storage Bay */ for (i = 0; i < NUM_ELEMENT_CATEGORIES; ++i) GLOBAL_SIS (ElementAmounts[i]) = 0; for (i = NUM_BOMB_MODULES; i < NUM_MODULE_SLOTS; ++i) GLOBAL_SIS (ModuleSlots[i]) = EMPTY_SLOT + 2; /* XXX : this should be unhardcoded eventually */ /* transport to Starbase */ GLOBAL (ShipStamp.origin.x) = STARBASE_INNER_X - SAFE_X; GLOBAL (ShipStamp.origin.y) = STARBASE_INNER_Y - SAFE_Y; } else { /* 'Beating Game Differently' mode - never visited Starbase, * so you are transported to Earth */ /* compress the layout -- move all to front */ for (i = NUM_MODULE_SLOTS - 1; i > 0; --i) { int m; /* find next unused slot */ for (; i > 0 && GLOBAL_SIS (ModuleSlots[i]) != EMPTY_SLOT + 2; --i) ; if (i == 0) break; /* find next module to move */ for (m = i - 1; m >= 0 && GLOBAL_SIS (ModuleSlots[m]) == EMPTY_SLOT + 2; --m) ; if (m < 0) break; /* move the module */ GLOBAL_SIS (ModuleSlots[i]) = GLOBAL_SIS (ModuleSlots[m]); GLOBAL_SIS (ModuleSlots[m]) = EMPTY_SLOT + 2; } /* XXX : this should be unhardcoded eventually */ /* transport to Earth itself */ GLOBAL (ShipStamp.origin.x) = EARTH_INNER_X - SAFE_X; GLOBAL (ShipStamp.origin.y) = EARTH_INNER_Y - SAFE_Y; } /* install Chmmr-supplied modules */ for (i = 0; i < NUM_DRIVE_SLOTS; ++i) GLOBAL_SIS (DriveSlots[i]) = FUSION_THRUSTER; for (i = 0; i < NUM_JET_SLOTS; ++i) GLOBAL_SIS (JetSlots[i]) = TURNING_JETS; GLOBAL_SIS (ModuleSlots[0]) = BOMB_MODULE_4; GLOBAL_SIS (ModuleSlots[1]) = BOMB_MODULE_5; GLOBAL_SIS (ModuleSlots[2]) = BOMB_MODULE_3; GLOBAL_SIS (ModuleSlots[3]) = BOMB_MODULE_1; GLOBAL_SIS (ModuleSlots[4]) = BOMB_MODULE_0; GLOBAL_SIS (ModuleSlots[5]) = BOMB_MODULE_1; GLOBAL_SIS (ModuleSlots[6]) = BOMB_MODULE_3; GLOBAL_SIS (ModuleSlots[7]) = BOMB_MODULE_4; GLOBAL_SIS (ModuleSlots[8]) = BOMB_MODULE_5; GLOBAL_SIS (ModuleSlots[9]) = BOMB_MODULE_2; } } static void NotReady (RESPONSE_REF R) { if (R == 0) NPCPhrase (RETURN_WHEN_READY); else if (PLAYER_SAID (R, further_assistance)) { NPCPhrase (NO_FURTHER_ASSISTANCE); DISABLE_PHRASE (further_assistance); } else if (PLAYER_SAID (R, tech_help)) { NPCPhrase (USE_OUR_SHIPS_BEFORE); SetRaceAllied (CHMMR_SHIP, TRUE); } else if (PLAYER_SAID (R, where_weapon)) { NPCPhrase (PRECURSOR_WEAPON); DISABLE_PHRASE (where_weapon); } else if (PLAYER_SAID (R, where_distraction)) { NPCPhrase (PSYCHIC_WEAPONRY); DISABLE_PHRASE (where_distraction); } if (CheckAlliance (CHMMR_SHIP) != GOOD_GUY) Response (tech_help, NotReady); else if (PHRASE_ENABLED (further_assistance)) Response (further_assistance, NotReady); if (PHRASE_ENABLED (where_weapon) && !GET_GAME_STATE (UTWIG_BOMB_ON_SHIP)) Response (where_weapon, NotReady); if (PHRASE_ENABLED (where_distraction) && !GET_GAME_STATE (TALKING_PET_ON_SHIP)) Response (where_distraction, NotReady); Response (bye, ExitConversation); } static void ImproveBomb (RESPONSE_REF R) { if (R == 0) NPCPhrase (WE_WILL_IMPROVE_BOMB); else if (PLAYER_SAID (R, what_now)) { NPCPhrase (MODIFY_VESSEL); DISABLE_PHRASE (what_now); } else if (PLAYER_SAID (R, wont_hurt_my_ship)) { NPCPhrase (WILL_DESTROY_IT); DISABLE_PHRASE (wont_hurt_my_ship); } else if (PLAYER_SAID (R, bummer_about_my_ship)) { NPCPhrase (DEAD_SILENCE); DISABLE_PHRASE (bummer_about_my_ship); } else if (PLAYER_SAID (R, other_assistance)) { NPCPhrase (USE_OUR_SHIPS_AFTER); SetRaceAllied (CHMMR_SHIP, TRUE); } if (PHRASE_ENABLED (what_now)) Response (what_now, ImproveBomb); else if (PHRASE_ENABLED (wont_hurt_my_ship)) Response (wont_hurt_my_ship, ImproveBomb); else if (PHRASE_ENABLED (bummer_about_my_ship)) Response (bummer_about_my_ship, ImproveBomb); if (CheckAlliance (CHMMR_SHIP) != GOOD_GUY) Response (other_assistance, ImproveBomb); Response (proceed, ExitConversation); } static void ChmmrFree (RESPONSE_REF R) { if (R == 0 || PLAYER_SAID (R, i_am_captain0) || PLAYER_SAID (R, i_am_savior) || PLAYER_SAID (R, i_am_silly)) { NPCPhrase (WHY_HAVE_YOU_FREED_US); AlienTalkSegue ((COUNT)~0); SET_GAME_STATE (CHMMR_EMERGING, 0); Response (serious_1, ChmmrFree); Response (serious_2, ChmmrFree); Response (silly, ChmmrFree); } else { NPCPhrase (WILL_HELP_ANALYZE_LOGS); if (GET_GAME_STATE (AWARE_OF_SAMATRA)) NPCPhrase (YOU_KNOW_SAMATRA); else { NPCPhrase (DONT_KNOW_ABOUT_SAMATRA); SET_GAME_STATE (AWARE_OF_SAMATRA, 1); } if (GET_GAME_STATE (TALKING_PET_ON_SHIP)) NPCPhrase (HAVE_TALKING_PET); else NPCPhrase (NEED_DISTRACTION); if (GET_GAME_STATE (UTWIG_BOMB_ON_SHIP)) NPCPhrase (HAVE_BOMB); else NPCPhrase (NEED_WEAPON); if (!GET_GAME_STATE (TALKING_PET_ON_SHIP) || !GET_GAME_STATE (UTWIG_BOMB_ON_SHIP)) NotReady ((RESPONSE_REF)0); else ImproveBomb ((RESPONSE_REF)0); } } static void ChmmrShielded (RESPONSE_REF R); static void ChmmrAdvice (RESPONSE_REF R) { BYTE AdviceLeft; if (PLAYER_SAID (R, need_advice)) NPCPhrase (WHAT_ADVICE); else if (PLAYER_SAID (R, how_defeat_urquan)) { NPCPhrase (DEFEAT_LIKE_SO); SET_GAME_STATE (CHMMR_BOMB_STATE, 1); DISABLE_PHRASE (how_defeat_urquan); } else if (PLAYER_SAID (R, what_about_tpet)) { NPCPhrase (SCARY_BUT_USEFUL); DISABLE_PHRASE (what_about_tpet); } else if (PLAYER_SAID (R, what_about_bomb)) { NPCPhrase (ABOUT_BOMB); DISABLE_PHRASE (what_about_bomb); } else if (PLAYER_SAID (R, what_about_sun_device)) { NPCPhrase (ABOUT_SUN_DEVICE); DISABLE_PHRASE (what_about_sun_device); } else if (PLAYER_SAID (R, what_about_samatra)) { NPCPhrase (ABOUT_SAMATRA); DISABLE_PHRASE (what_about_samatra); } AdviceLeft = 0; if (PHRASE_ENABLED (how_defeat_urquan)) { Response (how_defeat_urquan, ChmmrAdvice); AdviceLeft = TRUE; } if (PHRASE_ENABLED (what_about_tpet) && GET_GAME_STATE (TALKING_PET_ON_SHIP)) { Response (what_about_tpet, ChmmrAdvice); AdviceLeft = TRUE; } if (PHRASE_ENABLED (what_about_bomb) && GET_GAME_STATE (UTWIG_BOMB_ON_SHIP)) { Response (what_about_bomb, ChmmrAdvice); AdviceLeft = TRUE; } if (PHRASE_ENABLED (what_about_sun_device) && GET_GAME_STATE (SUN_DEVICE_ON_SHIP)) { Response (what_about_sun_device, ChmmrAdvice); AdviceLeft = TRUE; } if (PHRASE_ENABLED (what_about_samatra) && GET_GAME_STATE (AWARE_OF_SAMATRA)) { Response (what_about_samatra, ChmmrAdvice); AdviceLeft = TRUE; } Response (enough_advice, ChmmrShielded); if (!AdviceLeft) DISABLE_PHRASE (need_advice); } static void ChmmrShielded (RESPONSE_REF R) { if (PLAYER_SAID (R, find_out_whats_up)) { NPCPhrase (HYBRID_PROCESS); DISABLE_PHRASE (find_out_whats_up); } else if (PLAYER_SAID (R, need_help)) { NPCPhrase (CANT_HELP); SET_GAME_STATE (CHMMR_STACK, 1); } else if (PLAYER_SAID (R, why_no_help)) { NPCPhrase (LONG_TIME); SET_GAME_STATE (CHMMR_STACK, 2); } else if (PLAYER_SAID (R, what_if_more_energy)) { NPCPhrase (DANGER_TO_US); SET_GAME_STATE (CHMMR_STACK, 3); } else if (PLAYER_SAID (R, enough_advice)) NPCPhrase (OK_ENOUGH_ADVICE); switch (GET_GAME_STATE (CHMMR_STACK)) { case 0: Response (need_help, ChmmrShielded); break; case 1: Response (why_no_help, ChmmrShielded); break; case 2: Response (what_if_more_energy, ChmmrShielded); break; } if (PHRASE_ENABLED (find_out_whats_up)) Response (find_out_whats_up, ChmmrShielded); if (PHRASE_ENABLED (need_advice)) { Response (need_advice, ChmmrAdvice); } Response (bye_shielded, ExitConversation); } static void AfterBomb (RESPONSE_REF R) { if (PLAYER_SAID (R, whats_up_after_bomb)) { if (GET_GAME_STATE (CHMMR_STACK)) NPCPhrase (GENERAL_INFO_AFTER_BOMB_2); else { NPCPhrase (GENERAL_INFO_AFTER_BOMB_1); SET_GAME_STATE (CHMMR_STACK, 1); } DISABLE_PHRASE (whats_up_after_bomb); } else if (PLAYER_SAID (R, what_do_after_bomb)) { NPCPhrase (DO_AFTER_BOMB); DISABLE_PHRASE (what_do_after_bomb); } if (PHRASE_ENABLED (whats_up_after_bomb)) Response (whats_up_after_bomb, AfterBomb); if (PHRASE_ENABLED (what_do_after_bomb)) Response (what_do_after_bomb, AfterBomb); Response (bye_after_bomb, ExitConversation); } static void Intro (void) { BYTE NumVisits; if (GET_GAME_STATE (CHMMR_BOMB_STATE) >= 2) { NumVisits = GET_GAME_STATE (CHMMR_HOME_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HELLO_AFTER_BOMB_1); break; case 1: NPCPhrase (HELLO_AFTER_BOMB_2); --NumVisits; break; } SET_GAME_STATE (CHMMR_HOME_VISITS, NumVisits); AfterBomb ((RESPONSE_REF)0); } else if (GET_GAME_STATE (CHMMR_UNLEASHED)) { if (!GET_GAME_STATE (TALKING_PET_ON_SHIP) || !GET_GAME_STATE (UTWIG_BOMB_ON_SHIP)) NotReady ((RESPONSE_REF)0); else { NPCPhrase (YOU_ARE_READY); ImproveBomb ((RESPONSE_REF)0); } } else { NumVisits = GET_GAME_STATE (CHMMR_HOME_VISITS); if (!GET_GAME_STATE (CHMMR_EMERGING)) { CommData.AlienColorMap = SetAbsColorMapIndex ( CommData.AlienColorMap, 1 ); switch (NumVisits++) { case 0: NPCPhrase (WHY_YOU_HERE_1); break; case 1: NPCPhrase (WHY_YOU_HERE_2); break; case 2: NPCPhrase (WHY_YOU_HERE_3); break; case 3: NPCPhrase (WHY_YOU_HERE_4); --NumVisits; break; } ChmmrShielded ((RESPONSE_REF)0); } else { SetCommIntroMode (CIM_FADE_IN_SCREEN, ONE_SECOND * 2); NPCPhrase (WE_ARE_FREE); if (NumVisits) { ChmmrFree ((RESPONSE_REF)0); NumVisits = 0; } else { NPCPhrase (WHO_ARE_YOU); construct_response (shared_phrase_buf, i_am_captain0, GLOBAL_SIS (CommanderName), i_am_captain1, GLOBAL_SIS (ShipName), i_am_captain2, (UNICODE*)NULL); DoResponsePhrase (i_am_captain0, ChmmrFree, shared_phrase_buf); Response (i_am_savior, ChmmrFree); Response (i_am_silly, ChmmrFree); } SET_GAME_STATE (CHMMR_UNLEASHED, 1); } SET_GAME_STATE (CHMMR_HOME_VISITS, NumVisits); } } static COUNT uninit_chmmr (void) { return (0); } static void post_chmmr_enc (void) { // nothing defined so far } LOCDATA* init_chmmr_comm (void) { LOCDATA *retval; chmmr_desc.init_encounter_func = Intro; chmmr_desc.post_encounter_func = post_chmmr_enc; chmmr_desc.uninit_encounter_func = uninit_chmmr; chmmr_desc.AlienTextBaseline.x = TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); chmmr_desc.AlienTextBaseline.y = 0; chmmr_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; setSegue (Segue_peace); retval = &chmmr_desc; return (retval); }