From: <ma...@us...> - 2006-01-29 20:29:35
|
Update of /cvsroot/exult/./exult/content/bgkeyring/src/misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6030/src/misc Added Files: codex_eggs.uc inn_key_eggs.uc rest_functions.uc show_codex.uc Log Message: Adding the Keyring mod to CVS. --- NEW FILE: codex_eggs.uc --- /* * This source file contains usecode for the Codex-ralated eggs. * * Author: Marzo Junior * Last Modified: 2001-01-20 */ eggCodexLenses 0xBF0 () { var pos; var quality; var lens; var npc; var framenum; var bark; if ((event == EGG || event == SCRIPTED)) { //Get egg's position and quality: pos = get_object_position(); quality = get_item_quality(); //Find the nearest lens: lens = pos->find_nearby(SHAPE_LENS, 0, MASK_NONE); if (lens) { //there is a lens nearby; //see if it is the right one: framenum = lens->get_item_frame_rot(); if (framenum == (quality + 32)) { //It is, and correctly rotated too //Indicate to player that he did something right: UI_sprite_effect(ANIMATION_GREEN_BUBBLES, pos[X] - 2, pos[Y] - 2, 0, 0, 0, -1); UI_play_sound_effect(67); if (event == SCRIPTED) { //This was a scripted call, which means both //lenses are in place and properly rotated //Halt scheduled scripts: halt_scheduled(); //Display Codex: script AVATAR after 16 ticks call displayCodex, SCRIPTED; } else { //Egg event; call the other egg to see if //the other lens is there and correctly //rotated as well: pos = [(0xAA3 - quality * 7), 0xAE7, 4]; var egg = pos->find_nearby(SHAPE_EGG, 1, MASK_EGG); if (egg) { egg->halt_scheduled(); event = SCRIPTED; egg->eggCodexLenses(); } } } else if (framenum == quality) { //Right lens, needs to be rotated: if (event == SCRIPTED) //This means that the *other* lens is rotated, and //this one isn't bark = "@Rotate the other lens too@"; else //Neither lens are rotated bark = "@Rotate the lens@"; UI_item_say(randomPartyMember(), bark); } else { //Wrong lens in the right place: bark = "@It goes on the other side@"; UI_item_say(randomPartyMember(), bark); } } } } eggCodexShrineEntrance 0xBF1 () { if (event != EGG) return; var statues = UI_find_nearby(item, SHAPE_GUARDIAN_STATUE, 20, MASK_NONE); var statue; if (statues) { //If the Avatar is facing south, he is most likely leaving //the shrine of the Codex. Do not display the statues' message //in this case. var avframe = AVATAR->get_item_frame_rot(); if (!((avframe >= 16) && (avframe <= 31))) { //Allow Avatar to see the Codex if there is any shrine quest which the Avatar //hasn't completed yet: var in_quest = false; if ((gflags[MEDITATED_AT_SACRIFICE] && !gflags[VIEWED_CODEX_FOR_SACRIFICE] ) || (gflags[MEDITATED_AT_JUSTICE] && !gflags[VIEWED_CODEX_FOR_JUSTICE] ) || (gflags[MEDITATED_AT_HUMILITY] && !gflags[VIEWED_CODEX_FOR_HUMILITY] ) || (gflags[MEDITATED_AT_SPIRITUALITY] && !gflags[VIEWED_CODEX_FOR_SPIRITUALITY]) || (gflags[MEDITATED_AT_VALOR] && !gflags[VIEWED_CODEX_FOR_VALOR] ) || (gflags[MEDITATED_AT_COMPASSION] && !gflags[VIEWED_CODEX_FOR_COMPASSION] ) || (gflags[MEDITATED_AT_HONOR] && !gflags[VIEWED_CODEX_FOR_HONOR] ) || (gflags[MEDITATED_AT_HONESTY] && !gflags[VIEWED_CODEX_FOR_HONESTY] )) in_quest = true; //Allow for attunement of white virtue stone: if (gflags[SPIRITUALITY_STONE_QUEST]) in_quest = true; //Or if the player is in the Codex quest: if (gflags[CODEX_ALL_EIGHT_SHRINES]) in_quest = true; //But not if the Codex Quest is over: if (gflags[RELOCATE_CODEX_QUEST]) in_quest = false; if (in_quest) { //The Avatar is in a sacred quest, so let him enter: statue = statues[2]; script statue say "@Thou art welcome, seeker@"; statue = statues[1]; script statue after 15 ticks say("@Let Virtue bring thee wisdom@"); //Anti-cheater flag: gflags[IN_CODEX_QUEST] = true; } else { //The Avatar is trying to enter without a quest; //boot him out: statue = statues[2]; script statue say "@Thou art not on a sacred quest!@"; statue = statues[1]; script statue after 15 ticks say("@Passage denied!@"); var pos = [2719, 2852, 0]; AVATAR->halt_scheduled(); AVATAR->trueFreeze(); AVATAR->si_path_run_usecode(pos, PATH_SUCCESS, AVATAR, trueUnfreeze, true); UI_set_path_failure(trueUnfreeze, AVATAR, PATH_FAILURE); AVATAR->obj_sprite_effect(ANIMATION_FIREWORKS, 0, 0, 0, 0, 0, 6); } } } } eggCodexQuest 0xBF2 () { if (event != EGG) return; if (!gflags[CODEX_ALL_EIGHT_SHRINES]) return; //Get the quality of the egg: var qual = get_item_quality(); //To see if all items are where they should, I am using //bit flags in a pathegg's frame. These are the bit flags //for each different egg quality: var pathegg_frame_flags = [1, 2, 4, 8]; //The bit flag corresponding to the current egg: var frflag = pathegg_frame_flags[qual + 1]; //This will hold the pathegg's frame number: var frnum = 0; //This will store the set flags, if any: var setflags = []; //See if the path egg exists: var pathegg = find_nearest(SHAPE_PATH_EGG, 10); if (pathegg) { //It does; get the frame number: frnum = pathegg->get_item_frame(); //Fill in the setflags array with the flags which are set: var currflag = frnum; var index = 4; while (index > 0) { if (currflag >= pathegg_frame_flags[index]) { setflags = [index - 1, setflags]; currflag = currflag - pathegg_frame_flags[index]; } index = index - 1; } } var objshape; //Check to see if we must detect items of principle or //the Vortex Cube: if (qual < 3) objshape = SHAPE_ITEM_OF_PRINCIPLE; else objshape = SHAPE_VORTEX_CUBE; //Find the object: var obj = find_nearest(objshape, 0); //No needed object nearby; check if we need to //delete the corresponding flag, as the item might //have been moved just now: if (!obj) { //No pathegg means nothing to do: if (!pathegg) return; //If the egg's quality is in the set flags, remove it: if (qual in setflags) { pathegg->set_item_frame(frnum - frflag); //Just to make sure: gflags[CODEX_ALL_ITEMS_IN_PLACE] = false; } //Leave now: return; } //Get the item's frame: var objframe = obj->get_item_frame(); //Get object position: var pos = obj->get_object_position(); //Check to see if the egg's quality matches the frame //of the items of principle, if any: if ((objshape == SHAPE_ITEM_OF_PRINCIPLE) && (objframe != qual)) { //It is not; have some user feedback and leave: UI_sprite_effect(ANIMATION_POOF, pos[X] - 2, pos[Y] - 2, 0, 0, 0, -1); return; } //If we got here, the object exists and is in the correct //place; have some user feedback: UI_sprite_effect(ANIMATION_GREEN_BUBBLES, pos[X] - 2, pos[Y] - 2, 0, 0, 0, -1); UI_play_sound_effect(67); //If the pathegg does not exist, create it: if (!pathegg) { pathegg = UI_create_new_object(SHAPE_PATH_EGG); UI_update_last_created([2719, 2797, 4]); } //The pathegg always exists at this point; see if the flag is //already set (shouldn't happen): if (qual in setflags) //Nothing to do; leave: return; else { //It is not; set the flag: pathegg->set_item_frame(frnum + frflag); setflags = [setflags, qual]; } //See if all items are in place: if (UI_get_array_size(setflags) == 4) //Yes, they are: gflags[CODEX_ALL_ITEMS_IN_PLACE] = true; else //No, they are not: gflags[CODEX_ALL_ITEMS_IN_PLACE] = false; } eggDeleteTimelord 0xBFD () { if (event != EGG) return; if (gflags[BROKE_SPHERE]) { var objs = UI_find_nearby(item, SHAPE_STATUE, 10, MASK_NONE); objs = [objs, UI_find_nearby(item, SHAPE_TIME_BARRIER, 10, MASK_TRANLUCENT)]; var obj; var index; var max; for (obj in objs with index to max) obj->remove_item(); remove_item(); } } eggReturnedItemsOfPrinciple 0xBFE () { if (event != EGG) return; var obj = find_nearest(SHAPE_ITEM_OF_PRINCIPLE, 1); if (!obj) return; if (gflags[RELOCATE_CODEX_QUEST] && (get_item_quality() == obj->get_item_frame())) { //Give experience to Avatar if he returns the items of Principle //to where they belong: giveExperience(75); remove_item(); } } eggsPartyLocationBarks 0x621 () { var qual = get_item_quality(); var msg; var npcnum; var istalk; if (event != EGG) abort; if (qual < 44) { eggsPartyLocationBarks.original(); abort; } else if (qual == 44) { msg = "The Shrine of the Codex!"; npcnum = SHAMINO; istalk = false; } else if (qual == 45) { msg = false; if (gflags[RELOCATE_CODEX_QUEST]) { var num = PARTY->count_objects(SHAPE_LENS, QUALITY_ANY, FRAME_ANY); if (num != 2) if (num == 0) msg = "You left the lenses behind!"; else msg = "You left one of the lenses behind!"; num = PARTY->count_objects(SHAPE_ITEM_OF_PRINCIPLE, QUALITY_ANY, FRAME_ANY); if (num != 3) { var has_book = contHasItemCount(PARTY, 1, SHAPE_ITEM_OF_PRINCIPLE, QUALITY_ANY, 0); var has_candle = contHasItemCount(PARTY, 1, SHAPE_ITEM_OF_PRINCIPLE, QUALITY_ANY, 1); var has_bell = contHasItemCount(PARTY, 1, SHAPE_ITEM_OF_PRINCIPLE, QUALITY_ANY, 2); var princitems = [" the Book of Truth", " the Candle of Love", " the Bell of Courage"]; var index = 0; if (msg) msg = msg + " You also forgot"; else msg = "You left"; if (num == 0) msg = msg + " the three Items of Principle!"; else if (num == 1) { if (has_book) index = [2, 3]; else if (has_candle) index = [1, 3]; else if (has_bell) index = [1, 2]; msg = msg + princitems[index[1]] + " and" + princitems[index[2]] + "!"; } else if (num == 2) { if (!has_book) index = 1; else if (!has_candle) index = 2; else if (!has_bell) index = 3; msg = msg + princitems[index] + "!"; } } if (!contHasItemCount(PARTY, 1, SHAPE_VORTEX_CUBE, QUALITY_ANY, FRAME_ANY)) if (msg) msg = msg + " And the Vortex Cube!"; else msg = "You left the Vortex Cube behind!"; } else abort; if (msg) { msg = "@" + msg + "@"; npcnum = PARTY; istalk = true; } } if (npcnum == PARTY) { npcnum = randomPartyMember(); if (npcnum == AVATAR) abort; } if (!isNearby(npcnum)) abort; if (!istalk) UI_item_say(npcnum, "@" + msg + "@"); else if (istalk) npcnum.say(msg); } --- NEW FILE: inn_key_eggs.uc --- /* * This source file contains the code for innkeepers reclaiming the Inn Keys. * * Author: Marzo Junior * Last Modified: 2001-01-20 */ //Inn identifiers: const int INN_WAYFARERS_NORTH = 1; const int INN_WAYFARERS_SOUTH = 2; const int INN_FALLEN_VIRGIN = 3; const int INN_OUT_N_INN = 4; const int INN_BUNK_AND_STOOL = 5; const int INN_MODEST_DAMSEL = 6; const int INN_SALTY_DOG = 7; const int INN_HONORABLE_HOUND = 8; const int INN_CHEQUERED_CORK_EAST = 9; const int INN_CHEQUERED_CORK_SOUTH = 10; //To make innkeeper move towards Avatar: const int EVENT_WALKING = 12; //For locking doors: enum door_states { DOOR_UNLOCKED = 0, DOOR_OPEN = 1, DOOR_LOCKED = 2, DOOR_MAGIC_LOCK = 3 }; //For making beds: enum bed_states { BED_MADE = 0, BED_UNMADE = 1 }; eggLockInnDoors 0xBFC () { var polite_title = getPoliteTitle(); var inn_keepers = [JAMES, JAMES, MANDY, PAMELA, OPHELIA, BORIS, POLLY, APOLLONIA, RUTHERFORD, RUTHERFORD]; var inn_names = ["Wayfarer's Inn", "Wayfarer's Inn", "Fallen Virgin", "Out 'n' Inn", "Bunk and Stool", "Modest Damsel", "Salty Dog", "Honorable Hound", "Chequered Cork", "Chequered Cork"]; var step_directions = [SOUTH, NORTH, NORTH, NORTHEAST, WEST, WEST, NORTH, WEST, WEST, NORTH]; //Get the innkeeper's index: var egg_quality = get_item_quality(); var inn_keeper = inn_keepers[egg_quality]; if (event == EVENT_WALKING) { //The innkeeper should have started moving towards the //Avatar; give him a boost: var keeper_pos = inn_keeper->get_object_position(); var avatar_pos = AVATAR->get_object_position(); //Vector from innkeeper to Avatar var delta_pos = [keeper_pos[X] - avatar_pos[X], keeper_pos[Y] - avatar_pos[Y], keeper_pos[Z] - avatar_pos[Z]]; //Length of said vector: var len = inn_keeper->get_distance(AVATAR); //Renormalized vector with length 5: delta_pos = [(5 * delta_pos[X]) / len, (5 * delta_pos[Y]) / len, (5 * delta_pos[Z]) / len]; //Innkeeper's final destination: var dest_pos = [avatar_pos[X] + delta_pos[X], avatar_pos[Y] + delta_pos[Y], avatar_pos[Z] + delta_pos[Z]]; //Force innkeeper to move to Avatar (or call usecode //anyway if not possible): inn_keeper->si_path_run_usecode(dest_pos, PATH_SUCCESS, item, eggLockInnDoors, true); //LEAVE: abort; } //Get the egg's position: var pos = get_object_position(); //Use the egg's position to determine the offsets to the doors // and beds if (egg_quality == INN_WAYFARERS_NORTH) pos[Y] = pos[Y] - 15; else if (egg_quality == INN_OUT_N_INN) { pos[X] = pos[X] + 8; pos[Y] = pos[Y] - 16; } else if (egg_quality == INN_BUNK_AND_STOOL) { pos[X] = pos[X] - 48; pos[Y] = pos[Y] - 8; } else if (egg_quality == INN_MODEST_DAMSEL) pos[X] = pos[X] - 24; else if (egg_quality == INN_SALTY_DOG) { pos[X] = pos[X] - 18; pos[Y] = pos[Y] - 16; } else if (egg_quality == INN_HONORABLE_HOUND) pos[Y] = pos[Y] + 27; else if (egg_quality == INN_CHEQUERED_CORK_EAST) { pos[X] = pos[X] - 47; pos[Y] = pos[Y] + 9; } else if (egg_quality == INN_CHEQUERED_CORK_SOUTH) { pos[X] = pos[X] - 7; pos[Y] = pos[Y] - 15; } var index; var max; var key; //Find all inn keys owner by the party: var inn_keys = PARTY->count_objects(SHAPE_KEY, KEY_INN, FRAME_ANY); //Find all keys in the ground: var ground_keys = pos->find_nearby(SHAPE_KEY, 50, MASK_NONE); for (key in ground_keys with index to max) { //See how many are inn keys: if (key->get_item_quality() == KEY_INN) inn_keys = inn_keys + 1; } if (inn_keys) { //If there are any inn keys at all, if (UI_is_pc_inside() || (event == PATH_SUCCESS)) { //And if the Avatar is inside OR the innkeeper reached the Avatar, if (event == EGG) { //If the Avatar is inside and innkeeper hasn't started //moving towards him yet //Halt scripts for Avatar and innkeeper: AVATAR->halt_scheduled(); inn_keeper->halt_scheduled(); //Freeze Avatar: AVATAR->trueFreeze(); //Start to move the innkeeper towards the Avatar: inn_keeper->approach_avatar(0, 0); var delay = inn_keeper->get_distance(AVATAR) / 5; //Innkeeper calls out to Avatar: script inn_keeper after (delay - 2) ticks { nohalt; call trueFreeze; say "@Hold on a bit...@"; call trueUnfreeze;} //Avatar replies: script AVATAR after 2 * delay ticks { face AVATAR->direction_from(inn_keeper); wait 2; say "@Yes?@";} //After a little while, call this function again: script item after 4 ticks { call eggLockInnDoors, EVENT_WALKING;} abort; } else if (event == PATH_SUCCESS) { //The innkeeper has reached destination (or gave up //trying and called the usecode anyway...) inn_keeper.say("@I take it that thou art checking out then, " + polite_title + "?@"); //Ask Avatar is he is checking out: if (askYesNo()) { //Yes he is; say("@Here, let me have the room keys then. Worry not, I shall lock the doors myself.@"); say("@I hope thou didst enjoy thy stay at the " + inn_names[egg_quality] + "!@"); //Unfreeze Avatar: AVATAR->trueUnfreeze(); //Make innkeeper revert to normal schedule and unfreeze him: inn_keeper->run_schedule(); script inn_keeper after 2 ticks { nohalt; call trueUnfreeze; actor frame STAND; say "@Do come back!!@";} } else { //No, he is not; say("@Come back inside, then, and enjoy thy room, " + polite_title + "!@"); var step_to = step_directions[egg_quality]; //Halt scripts: AVATAR->halt_scheduled(); //Unfreeze innkeeper: script inn_keeper after 2 ticks { nohalt; call trueUnfreeze; actor frame STAND; say "@Enjoy thy stay!@";} //Determine were the Avatar is going to: pos = get_object_position(); var dir = step_directions[egg_quality]; if (dir == NORTH) pos[Y] = pos[Y] - 8; else if (dir == EAST) pos[X] = pos[X] + 8; else if (dir == SOUTH) pos[Y] = pos[Y] + 8; else if (dir == WEST) pos[X] = pos[X] - 8; //Force Avatar back inside the inn: AVATAR->si_path_run_usecode(pos, PATH_SUCCESS, AVATAR, trueUnfreeze, true); UI_set_path_failure(trueUnfreeze, AVATAR, PATH_FAILURE); abort; } } } } //Remove inn keys from party: inn_keys->remove_party_items(SHAPE_KEY, KEY_INN, FRAME_ANY, true); //Delete innkeys from the ground: for (key in ground_keys with index to max) { if (key->get_item_quality() == KEY_INN) key->remove_item(); } var inn_doors = []; var door_shapes = [ SHAPE_DOOR_HORIZONTAL, SHAPE_DOOR_VERTICAL, SHAPE_DOOR2_HORIZONTAL, SHAPE_DOOR2_VERTICAL ]; var door; //Find unlocked doors for (door in door_shapes with index to max) inn_doors = inn_doors & pos->find_nearby(door, 20, MASK_NONE); var door_state; var door_function; for (door in inn_doors with index to max) { //For each nearby door, if (door->get_item_quality() == KEY_INN) { //If it is in inn door, door_state = (door->get_item_frame() % 4); if (door_state == DOOR_OPEN) { //and if it is open, //get usecode function #: door_function = door->get_usecode_fun(); //Set event to DOUBLECLICK: event = DOUBLECLICK; //Close door; this is an indirect calle: door->(*door_function)(); //Lock door UseKeyOnDoor(door); } else if (door_state == DOOR_UNLOCKED) //If the door is closed, lock it: UseKeyOnDoor(door); } } //Find all nearby beds: var inn_beds = pos->find_nearby(SHAPE_BED_HORIZONTAL, 20, MASK_NONE); inn_beds = inn_beds & pos->find_nearby(SHAPE_BED_VERTICAL, 20, MASK_NONE); var bed; var bed_state; for (bed in inn_beds with index to max) { //For each bed found, bed_state = bed->get_item_frame(); if (bed_state > 2) { //If the bed is actually a sheet, get its state: bed_state = (bed_state - 3) % 2; if (bed_state == BED_UNMADE) //Bed not made, so make it: bed->set_item_frame(bed->get_item_frame() - 1); } } } --- NEW FILE: rest_functions.uc --- EnsureExtinguishHeldTorch () { //Prevent torch from further burning out: halt_scheduled(); //Set it to spent: set_item_quality(QUALITY_TORCH_SPENT); } //Reimplemented to account for NPC "mana": advanceTimeDueToRest 0x93A (var sleep_time, var itemref) { var party; var counter; var party_count; var member; var light_sources = []; var source_count; var light_obj; var obj_quality; var obj_shape; var obj_count; party = UI_get_party_list2(); for (member in party with counter to party_count) { //The party member gets nothing from rest if he is starving: if (member->get_npc_prop(FOODLEVEL) >= 10) { //If the member is the Avatar, clear sleeping flag: if (!(member == AVATAR->get_npc_object())) member->clear_item_flag(ASLEEP); //Clear flags that go away with time: member->clear_item_flag(POISONED); member->clear_item_flag(PARALYZED); member->clear_item_flag(CURSED); member->clear_item_flag(CHARMED); member->clear_item_flag(INVISIBLE); member->clear_item_flag(PROTECTION); //Recover Health and mana: recoverPropByRest(member, HEALTH, STRENGTH, sleep_time); recoverPropByRest(member, MANA, MAX_MANA, sleep_time); //Make the NPC hungrier; why food level isn't reduced if //the NPC is already starving??? member->set_npc_prop(FOODLEVEL, (sleep_time * -1)); } //Gather readied light sources and torches: light_sources = (light_sources & member->get_cont_items(SHAPE_TORCH_LIT, QUALITY_ANY, FRAME_ANY)); light_sources = (light_sources & member->get_cont_items(SHAPE_LIGHTSOURCE_LIT, QUALITY_ANY, FRAME_ANY)); } //Gather all nearby torches and light sources: light_sources = (light_sources & itemref->find_nearby(SHAPE_TORCH_LIT, 30, 0)); light_sources = (light_sources & itemref->find_nearby(SHAPE_LIGHTSOURCE_LIT, 30, 0)); //Unfortunately, the original left out all readied light sources and torches, which means //a torch wouldn't go out if you were holding it... //Advance time for each one: for (light_obj in light_sources with counter to obj_count) { obj_quality = light_obj->get_item_quality(); //If the quality is below a certain threshold, the light source //would be spent due to the passing time: if (obj_quality <= (sleep_time * 30)) { //Cancel all scripts without nohalt for the light source: light_obj->halt_scheduled(); obj_shape = light_obj->get_item_shape(); //Actually extinguish the light source, and set if to spent: if (obj_shape == SHAPE_LIGHTSOURCE_LIT) light_obj->set_item_shape(SHAPE_LIGHTSOURCE_SPENT); else if (obj_shape == SHAPE_TORCH_LIT) { light_obj->set_item_shape(SHAPE_TORCH); //This (combined with UI_halt_scheduled, above) should //be enough to extinguish all torches... but it is not. //The reason is that, when you ignite a torch and ready //it, the first script to run has nohalt in it... this //causes the quality to be decremented once or twice //during the sleep period from QUALITY_TORCH_SPENT... light_obj->set_item_quality(QUALITY_TORCH_SPENT); //Therefore, this 'hack' ensures that their quality is //indeed what it should be: script light_obj after 35 ticks call EnsureExtinguishHeldTorch; //Another possibility would be to edit the beginLightSourceEvolution //function (0x905) to remove nohalt from the script. //It would have been much better if torches also had a //"spent" shape like light sources do... } } //Otherwise, just reduce the quality by an appropriate amount: else light_obj->set_item_quality((obj_quality - (sleep_time * 30))); } } --- NEW FILE: show_codex.uc --- /* * This source file contains usecode for the Codex of Ultimate Wisdom. * Things would be much easier if gflags accepted variables as well as * constants... * * Author: Marzo Junior * Last Modified: 2001-01-20 */ const int CODEX = -295; displayCodex () { if (event == SCRIPTED) { //item is one of the lenses //Halt usecode for Avatar: halt_scheduled(); //Sprite effects and sound associated with the Codex's appearance: UI_sprite_effect(ANIMATION_TELEPORT, 0xA9D, 0xAE4, 0, 0, 0, -1); UI_play_sound_effect(67); //After a little while, call this function again: script item after 10 ticks call displayCodex, EGG; } else if (event == EGG) { //The main part of the function. var codex_opens = "The pages of the Codex start to turn, and they stop in the page containing a message that you need."; var page_turning = "Once again the pages of the Codex start to turn, and they stop in the page containing a message that you need."; var ominous_turning = "Suddenly, a great wind starts blowing from nowhere. Amidst the terrible roar, the pages of the Codex turn wildly.~When the pages stop turning, "; var single_line = "there is but a single line in the page, containing exactly the message you need to see the most."; //Create the "Codex" and place it atop the pedestal: var codex = UI_create_new_object(SHAPE_JOURNAL); codex->set_item_frame(1); UI_update_last_created([0xAA1, 0xAE7, 7]); if (!gflags[SEEN_CODEX_ONCE]) { //First time the Codex appears in the game; extended intro: CODEX.say("Before you stands an image of the Codex of Ultimate Wisdom, brought forth from the Void by the combined actions of the Britannian and Gargoyle lenses."); //Mark as done: gflags[SEEN_CODEX_ONCE] = true; giveExperience(100); } else CODEX.say("Once again, the Codex appears before you."); //Check to see if the avatar cheated his way //inside the shrine of the Codex if (gflags[IN_CODEX_QUEST]) { //Nope, honest Avatar. var shrine_quests = 0; var displayed_messages = 0; //Display true codex message(s) //Boring and long... I wish gflags could be variables //as well as constants... //The basic idea is this: // - Count how many messages have been displayed by the Codex // in a previous call to this function // - Display the messages that haven't been displayed yet, and count // how many messages are being displayed if (gflags[VIEWED_CODEX_FOR_SACRIFICE]) shrine_quests = shrine_quests + 1; else if (gflags[MEDITATED_AT_SACRIFICE]) { gflags[VIEWED_CODEX_FOR_SACRIFICE] = true; gflags[MEDITATED_AT_SACRIFICE] = false; say(codex_opens); say("@Sacrifice is a virtue only if it is voluntary; to force others to Sacrifice of themselves is a grave injustice.~@Each man must be his own judge when determining how far he is willing to go to help others.@"); displayed_messages = displayed_messages + 1; } if (gflags[VIEWED_CODEX_FOR_JUSTICE]) shrine_quests = shrine_quests + 1; else if (gflags[MEDITATED_AT_JUSTICE]) { gflags[VIEWED_CODEX_FOR_JUSTICE] = true; gflags[MEDITATED_AT_JUSTICE] = false; if (displayed_messages > 0) say(page_turning); else say(codex_opens); say("@The laws of the land are imperfect and do not always serve Justice.~@Keep always in mind that obeying or enforcing an unjust law is itself unjust.@"); displayed_messages = displayed_messages + 1; } if (gflags[VIEWED_CODEX_FOR_HUMILITY]) shrine_quests = shrine_quests + 1; else if (gflags[MEDITATED_AT_HUMILITY]) { gflags[VIEWED_CODEX_FOR_HUMILITY] = true; gflags[MEDITATED_AT_HUMILITY] = false; if (displayed_messages > 0) say(page_turning); else say(codex_opens); say("@Pride is the bane of Virtue. When one deems himself to be better or to know more than others,~@he is opening the gates to unvirtuous behaviour by disregarding Truth, Love and Courage.@"); displayed_messages = displayed_messages + 1; } if (gflags[VIEWED_CODEX_FOR_SPIRITUALITY]) shrine_quests = shrine_quests + 1; else if (gflags[MEDITATED_AT_SPIRITUALITY]) { gflags[VIEWED_CODEX_FOR_SPIRITUALITY] = true; gflags[MEDITATED_AT_SPIRITUALITY] = false; if (displayed_messages > 0) say(page_turning); else say(codex_opens); say("@The path to Spirituality is paved by wisdom and knowledge. Thou hast the need to know the right questions to ask,~@and hast to have learned enough of the world to be able to understand those questions.~@Spirituality is the never-ending search for the answers.@"); displayed_messages = displayed_messages + 1; } if (gflags[VIEWED_CODEX_FOR_VALOR]) shrine_quests = shrine_quests + 1; else if (gflags[MEDITATED_AT_VALOR]) { gflags[VIEWED_CODEX_FOR_VALOR] = true; gflags[MEDITATED_AT_VALOR] = false; if (displayed_messages > 0) say(page_turning); else say(codex_opens); say("@There is a fine line between Valor and recklessness; wisdom lies in being able to tell one from another.~@Know that discretion is the better part of Valor.@"); displayed_messages = displayed_messages + 1; } if (gflags[VIEWED_CODEX_FOR_COMPASSION]) shrine_quests = shrine_quests + 1; else if (gflags[MEDITATED_AT_COMPASSION]) { gflags[VIEWED_CODEX_FOR_COMPASSION] = true; gflags[MEDITATED_AT_COMPASSION] = false; if (displayed_messages > 0) say(page_turning); else say(codex_opens); say("@A life without enlightenment is a form of suffering about which the unenlightened is unaware.~@The enlightened can show their Compassion by fighting against such ignorance.@"); displayed_messages = displayed_messages + 1; } if (gflags[VIEWED_CODEX_FOR_HONOR]) shrine_quests = shrine_quests + 1; else if (gflags[MEDITATED_AT_HONOR]) { gflags[VIEWED_CODEX_FOR_HONOR] = true; gflags[MEDITATED_AT_HONOR] = false; if (displayed_messages > 0) say(page_turning); else say(codex_opens); say("@Honor is more than being true to his word and being willing to defend one's convictions.~@Honor is also the courage to -revise- one's convictions when they are shown to be flawed or based on false assumptions.@"); displayed_messages = displayed_messages + 1; } if (gflags[VIEWED_CODEX_FOR_HONESTY]) shrine_quests = shrine_quests + 1; else if (gflags[MEDITATED_AT_HONESTY]) { gflags[VIEWED_CODEX_FOR_HONESTY] = true; gflags[MEDITATED_AT_HONESTY] = false; if (displayed_messages > 0) say(page_turning); else say(codex_opens); say("@Honesty starts with one's self. Know thyself well, and maintain not a false assessment of thy knowledge or martial skills.~@Only when this is done can one achieve true enlightenment.@"); displayed_messages = displayed_messages + 1; } var msg; var single_message = "The Codex of Ultimate Wisdom closes after displaying its message and then returns to the Void, until such a time when it is needed again."; var multi_message = "The Codex of Ultimate Wisdom closes after displaying its messages and then returns to the Void, until such a time when it is needed again."; var no_messages = "You await expectantly for it to display a message, but the Codex remains closed.~Eventually, it returns to the Void until such a time as when it is needed."; giveExperience(displayed_messages * 25); //Now see what else happens: if (gflags[RELOCATE_CODEX_QUEST]) { //Player has relocaed the Codex, finishing the Codex Quest; //Display congratulatory message: say(codex_opens); say("@This Codex is now safe again, seeker. Thou hast done well!@"); if (displayed_messages == 0) msg = single_message; } else if (gflags[CODEX_ALL_EIGHT_SHRINES]) { //Player has been to all eight Shrines, and received the Codex Quest. if (gflags[CODEX_ALL_ITEMS_IN_PLACE]) { //The Vortex Cube and the three Items of Principle are //in their respective positions say(ominous_turning + single_line); say("@Speak ye the three-part Word of Passage!@"); var choices = ["Infinity", "Singularity", "British", "Avidus", "Malum", "Ignavus", "Veramocor", "Inopia", "Vilis", "Infama", "Fallax"]; var choice = askForResponse(choices); if (choice == "Veramocor") { //Player knows what he is talking about! CODEX.hide(); avatarSay("In an ominous tone, you speak the three-part Word of Passage, which you learned so long ago while you where still on the Quest of the Avatar: @Veramocor!@"); UI_earthquake(24); say("The image of the Codex disappears suddenly, and something begins to happen."); //Mark quest as completed and give XP: gflags[RELOCATE_CODEX_QUEST] = true; giveExperience(300); //Freeze Avatar, bark WoP, wait and unfreeze: script AVATAR { call trueFreeze; say "Veramocor!"; wait 15; call trueUnfreeze;} //Animations & sounds: var pos = codex->get_object_position(); UI_sprite_effect(ANIMATION_CIRCLE_BARRIER, pos[X] - pos[Z]/2, pos[Y] - pos[Z]/2 + 12, 0, -9, 0, -1); UI_sprite_effect(ANIMATION_TELEPORT, pos[X] - pos[Z]/2, pos[Y] - pos[Z]/2, 0, 0, 0, -1); UI_play_sound_effect(64); //Delayed removal of the Codex: script codex after 13 ticks remove; pos = [2719, 2801, 4]; var itemsofprinc = pos->find_nearby(SHAPE_ITEM_OF_PRINCIPLE, 3, MASK_NONE); var obj; var index; var max; //Animations in the items of principle: for (obj in itemsofprinc with index to max) { pos = obj->get_object_position(); UI_sprite_effect(ANIMATION_PURPLE_BUBBLES, pos[X] - pos[Z]/2, pos[Y] - pos[Z]/2, 0, 0, 0, -1); } abort; } else if (choice in ["Infinity", "Singularity", "British"]) { say("In an ominous tone, you speak the word of your choice: @" + choice + "!@"); say("After a while, you realize that nothing happened at all."); } else { say("In an ominous tone, you speak the Word of Power: @" + choice + "!@ The ground trembles for a while afterwards."); UI_earthquake(12); say("After a while, you realize that nothing else happened."); } if (displayed_messages == 0) msg = single_message; } else { say(ominous_turning + "you can see the instructions to relocating the Codex in the Void."); say("@Look ye at the Codex symbol in the middle of this shrine. There shall ye place the Items of Principle.~@Each item must sit atop the circle which represents the same Principle."); say("@Place then the Vortex Cube midway between the Items of Principle and the two Lenses, and read again from this Codex.@"); if (displayed_messages == 0) msg = single_message; } } else if (shrine_quests + displayed_messages == 8) { say(ominous_turning + "the displayed message is none other than the one you need the most."); say("@Know ye, seeker, that this Codex is in peril!~@A malevolent entity called 'The Guardian' seeks to pervert this Codex and turn it into a weapon of conquest and oppression."); say("@In order to prevent this, this Codex -must- be relocated unto another position in the Void.~@Bring thou the Vortex Cube unto this shrine, together with the Book of Truth, the Candle of Love and the Bell of Courage, and read once more from this Codex!@"); //The player visited all eight shrines, viewed all eight messages: gflags[CODEX_ALL_EIGHT_SHRINES] = true; giveExperience(50); msg = multi_message; } else if ((shrine_quests + displayed_messages >= 7) && (!gflags[VIEWED_CODEX_FOR_SPIRITUALITY] || !gflags[MEDITATED_AT_SPIRITUALITY]) && (gflags[BROKE_SPHERE] || !gflags[ORB_FIXED_TIMELORD]) && !gflags[ATTUNED_SPIRITUALITY_STONE]) { //The player has visited all shrines but the Shrine of Spirituality //Also, player does not have access to that shrine //This also happens if the player meditated at that shrine but //hasn't returned to it yet. if (displayed_messages > 0) say(page_turning); else say(codex_opens); if (PARTY->count_objects(SHAPE_VIRTUE_STONE, QUALITY_ANY, 7)) { //The party has the white virtue stone say("@Hold the Virtue Stone of Spirituality in thy hand and speak ye the Word of Power of Spirituality!@"); var choices = ["Avidus", "Malum", "Ignavus", "Veramocor", "Inopia", "Vilis", "Infama", "Fallax"]; var choice = askForResponse(choices); CODEX.hide(); avatarSay("In an ominous tone, you speak the Word of Power: @" + choice + "!@ The ground trembles for a while afterwards."); UI_earthquake(12); if (choice == "Ignavus") { //Player knows his Ultima Lore well! var stone = PARTY->find_object(SHAPE_VIRTUE_STONE, QUALITY_ANY, 7); if (stone) { //Move stone to the correct place, set it and //return it to where it was: var cont = stone->get_container(); stone->move_object([2919, 2435, 1, 1]); stone->mark_virtue_stone(); stone->set_last_created(); cont->give_last_created(); gflags[SPIRITUALITY_STONE_QUEST] = false; gflags[ATTUNED_SPIRITUALITY_STONE] = true; } say("The Virtue Stone glows brightly for a moment, and you sense the flux of magic."); } else say("After a while, you realize that nothing else happened."); script codex remove; abort; } else { say("@Bring ye the Virtue Stone of Spirituality unto this shrine. Once that is done, read again from this Codex~@and learn how to attune the stone to the Shrine of Spirituality.@"); gflags[SPIRITUALITY_STONE_QUEST] = true; } if (displayed_messages > 1) msg = multi_message; else msg = single_message; } else if (displayed_messages == 0) msg = no_messages; else { if (displayed_messages > 1) msg = multi_message; else msg = single_message; } say(msg); } else { //Cheater, cheater, compulsive cheater :-) say(ominous_turning + single_line); say("@CHEATERS NEVER WIN!@"); } //Remove Codex: script codex remove; } } |