summaryrefslogtreecommitdiff
path: root/npc/items
diff options
context:
space:
mode:
Diffstat (limited to 'npc/items')
-rwxr-xr-xnpc/items/check_wand.txt0
-rw-r--r--npc/items/cookie.txt22
-rw-r--r--npc/items/croconut.txt72
-rw-r--r--npc/items/gift.txt35
-rwxr-xr-xnpc/items/launcher_ammo.txt19
-rw-r--r--npc/items/master_skillbook.txt164
-rwxr-xr-xnpc/items/mirror.txt18
-rw-r--r--npc/items/music_toys.txt18
-rwxr-xr-xnpc/items/pickled_beets.txt9
-rwxr-xr-xnpc/items/purification_potion.txt26
-rw-r--r--npc/items/rand_sc_heal.txt85
-rw-r--r--npc/items/recipes.txt352
-rwxr-xr-xnpc/items/require_stat.txt13
-rwxr-xr-xnpc/items/restricted_item.txt14
-rwxr-xr-xnpc/items/rubber_bat.txt10
-rwxr-xr-xnpc/items/scissors.txt13
-rwxr-xr-xnpc/items/shock_sweet.txt14
-rw-r--r--npc/items/shovel.txt361
-rwxr-xr-xnpc/items/unequipcb.txt22
-rwxr-xr-xnpc/items/unreleased_item.txt12
-rwxr-xr-xnpc/items/warpTowels.txt152
21 files changed, 322 insertions, 1109 deletions
diff --git a/npc/items/check_wand.txt b/npc/items/check_wand.txt
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/npc/items/check_wand.txt
diff --git a/npc/items/cookie.txt b/npc/items/cookie.txt
deleted file mode 100644
index e451e844..00000000
--- a/npc/items/cookie.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-// Evol script.
-// Author:
-// Jesusalva
-// Reid (?)
-// Description:
-// Prevents cookie from being used for too long
-
-function script UnequipCookie {
- if (getequipid(EQI_HEAD_MID) == DeliciousCookie)
- unequip(EQI_HEAD_MID);
- return;
-}
-
-- script #DeliciousCookie NPC_HIDDEN,{
- end;
-
-OnUnequip:
- UnequipCookie();
- end;
-
-}
-
diff --git a/npc/items/croconut.txt b/npc/items/croconut.txt
deleted file mode 100644
index 8e54971d..00000000
--- a/npc/items/croconut.txt
+++ /dev/null
@@ -1,72 +0,0 @@
-// Evol scripts.
-// Authors:
-// 4144
-// Reid
-// Description:
-// Allows to cut a Croconut in multiple parts.
-//
-// Possible choices for L_Weapon:
-// rif(countitem(35xx), l(getitemname(xx))), L_Weak,
-// rif(countitem(35yy), l(getitemname(yy))), L_Good,
-
-000-2-1,0,0,0 script Croconut NPC_HIDDEN,{
- close;
-
-OnUse:
- mesn "Narrator";
- mesc(l("Do you want to cut this @@?", getitemlink(Croconut)), 9);
- next;
-
- menu
- l("Yes."), L_Weapon,
- l("No."), -;
-
- getitem Croconut, 1;
- close;
-
-L_Weapon:
- mes "";
- mesn "Narrator";
- mesc(l("Which of your weapons do you want to use in order to cut this @@?", getitemlink(Croconut)), 9);
- next;
-
- menu
- rif(countitem(Knife) > 0, l(getitemname(Knife))), L_Weak,
- rif(countitem(PiouSlayer) > 0, l(getitemname(PiouSlayer))), L_Weak,
- rif(countitem(TrainingGladius) > 0, l(getitemname(TrainingGladius))), L_Good,
- rif(countitem(WoodenSword) > 0, l(getitemname(WoodenSword))), L_Weak,
- rif(countitem(ArtisBacksword) > 0, l(getitemname(ArtisBacksword))), L_Good,
- l("Bare Hands"), -;
-
-L_TooWeak:
- mes "";
- mesn "Narrator";
-
- .@q = rand(5);
- if (.@q == 0) goto L_TooWeakLost;
- if ( (.@q == 1) || (.@q == 2) ) goto L_TooWeakFail;
- if ( (.@q == 3) || (.@q == 4) || (.@q == 5) ) goto L_Weak;
-
-L_TooWeakLost:
- mesc(l("You hit too hard with your fist, you destroyed your @@.", getitemlink(Croconut)), 9);
-
- close;
-
-L_TooWeakFail:
- mesc(l("Your hands are too weak, you did not succeed in opening this @@.", getitemlink(Croconut)), 9);
-
- getitem Croconut, 1;
- close;
-
-L_Weak:
- mesc(l("You opened the @@ in two parts, but you crushed one of them.", getitemlink(Croconut)), 9);
-
- getitem HalfCroconut, 1;
- close;
-
-L_Good:
- mesc(l("You perfectly cut your @@ into two edible parts.", getitemlink(Croconut)), 9);
-
- getitem HalfCroconut, 2;
- close;
-}
diff --git a/npc/items/gift.txt b/npc/items/gift.txt
deleted file mode 100644
index be77bdfa..00000000
--- a/npc/items/gift.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-// Referral Gifts
-// Rebased from Moubootaur Legends
-// Author:
-// Jesusalva
-
-function script OpenFriendGift {
- if (BaseLevel < 5) {
- dispbottom(l("You must reach level 5 to open this gift."));
- getitembound(FriendGift, 1, 1);
- return;
- }
-
- getitem(Acorn, 1); // FIXME: placeholder
- //getitem(EventCoin, rand(1,3));
-
- .@refVault = bitwise_get(getvaultvar(REFERRAL_PROG), 0x00FFFFFF, 0);
- .@refChar = "playerCache"::vault2char(.@refVault);
- .@refName$ = "playerCache"::char2name(.@refChar);
-
- //$REFERRAL_IDS[.@refVault] += 1;
- // ^ this doesn't seem to serve any purpose...
- // if we want to keep track of how many accounts someone referred it
- // should be something like:
- // .@count = getvaultvar(REFERRAL_COUNT, .@refVault);
- // setvaultvar(REFERRAL_COUNT, .@count + 1, .@refVault);
-
- dispbottom(l("Oooh, a gift from %s!", .@refName$));
- rodex_sendmail(.@refChar, "TMW Team",
- "Invite Accepted",
- sprintf("%s accepted your invitation and reached level 5!\n"
- "As they get stronger, more rewards will be sent to you!",
- strcharinfo(PC_NAME)),
- rand(50, 150));
- return;
-}
diff --git a/npc/items/launcher_ammo.txt b/npc/items/launcher_ammo.txt
new file mode 100755
index 00000000..4c84e950
--- /dev/null
+++ b/npc/items/launcher_ammo.txt
@@ -0,0 +1,19 @@
+
+function script CheckLauncher {
+ if (getequipid(equip_arrow) == -1)
+ @LauncherType = 0;
+ return;
+}
+
+function script CheckAmmo {
+ if ((@LauncherType == @AmmoType) || (!@LauncherType))
+ goto L_Return;
+
+ callfunc "UnequipLater";
+ goto L_Return;
+
+L_Return:
+ @LauncherType = 0;
+ @AmmoType = 0;
+ return;
+}
diff --git a/npc/items/master_skillbook.txt b/npc/items/master_skillbook.txt
deleted file mode 100644
index 007125cc..00000000
--- a/npc/items/master_skillbook.txt
+++ /dev/null
@@ -1,164 +0,0 @@
-// The Mana World script.
-// Author:
-// Jesusalva
-// Elvano
-// Description:
-// Contains master skills which can only be learnt after killing boss
-// See also: https://forums.themanaworld.org/viewtopic.php?f=2&t=19918
-// Notes:
-// Not exactly as Elvano proposal. I actually care for restrictions you know...
-// Variables:
-// PERMANENT:
-// MASTERBOOK_PAGES - How many pages your Master Book have.
-// Defaults to zero, so you can't @item it.
-// MASTERBOOK_SKILL - An array with the skills you have learnt from Master Book.
-// - It's more flexible this way.
-// TEMPORARY:
-// @mb_BossId - Contains the MobID of the boss your party killed.
-// @mb_SkillId - Contains the SkillID which can be learnt with the boss.
-// @mb_ItemId - Contains the Feather Id to write (or whatever)
-// @mb_ItemAm - How many ink is required to write the skill
-// Remember: @mb_BossId will be reset to zero after 15 seconds from boss death.
-// Or upon logout. Or when changing maps. Temporary variables aren't reliable.
-//
-// @mb_BossId controls if you'll try to LEARN a skill, or READ the book.
-// Remember: A dialog prevents timer events from happening, but doesn't stops the timer.
-// TODO: Currently no way to get skill name from database (add getskillinfo() to server-plugin please)
-// TODO: Reset @mb_* when register_skill() finish
-// TODO: You cannot get Magic Feather anywhere in the game (yet)
-// TODO: See if the time (15s) is enough.
-// TODO: Skill level up
-// TODO: Use the data supplied by magic.txt
-
-- script #MasterBook NPC_HIDDEN,{
-
-
- function register_skill {
-
- setnpcdialogtitle l(.book_name$);
-
- // If boss is set, but is negative, this means somebody else defeated it
- if (@mb_BossId < 0)
- {
- mesc l("You did not defeat the boss, you can't learn any skills.");
- @mb_BossId=0;
- close;
- }
-
- // Report the boss you killed, and the boss level
- .@mb_lvl=strmobinfo(3, @mb_BossId);
- mesc l("You just defeated the following boss: @@ (Lv. @@)", strmobinfo(1, @mb_BossId), .@mb_lvl);
-
- // The boss must have a skill
- if (!@mb_SkillId)
- {
- mesc l("But there is no skill to be learnt from this boss.");
- @mb_BossId=0;
- close;
- }
- // You must have free pages
- if (array_entries(MASTERBOOK_SKILL) >= MASTERBOOK_PAGES)
- {
- mesc l("But you ran out of empty pages on this book.");
- @mb_BossId=0;
- close;
- }
- // TODO: Party Level Range
- // You must be at most 30 levels below the monster level
- if (BaseLevel+30 < .@mb_lvl)
- {
- mesc l("But you are out of the boss level range.");
- @mb_BossId=0;
- close;
- }
- // You must have enough materials
- if (countitem(@mb_ItemId) < @mb_ItemAm)
- {
- mesc l("But you do not have enough Magic Ink. (You need: @@ @@)", @mb_ItemAm, getitemlink(@mb_ItemId));
- //@mb_BossId=0;
- close;
- }
-
- // Allow you to check which skills are here to learn
- mes "";
- mesc l("You have: @@/@@ @@", countitem(@mb_ItemId), @mb_ItemAm, getitemlink(@mb_ItemId));
- mesc l("Skill Available: %s", getskillname(@mb_SkillId));
- select
- rif(!getskilllv(@mb_SkillId), l("Learn Skill")),
- l("Do not learn");
- mes "";
- if (@menu == 1)
- {
- delitem @mb_ItemId, @mb_ItemAm;
- skill(@mb_SkillId, 1, 0);
- array_push(MASTERBOOK_SKILL, @mb_SkillId);
- closeclientdialog;
- dispbottom l("You have learnt the skill.");
- }
- @mb_BossId=0;
- close;
- }
-
-
- function read_book {
-
- setnpcdialogtitle l(.book_name$);
- mesc l("@@/@@ pages used.", array_entries(MASTERBOOK_SKILL), MASTERBOOK_PAGES);
-
- mesc l("List of known master skills:");
- mes "";
- for (.@i = 0; .@i < getarraysize(MASTERBOOK_SKILL); ++.@i) {
- mesc l("* Skill ID: @@", MASTERBOOK_SKILL[.@i]);
- }
- close;
- }
-
-OnUse:
- // We assume if @mb_BossId is set, everything else is set, too
- if (@mb_BossId)
- register_skill;
- if (openbook())
- read_book;
- closeclientdialog();
- close;
-
-OnInit:
- .book_name$ = getitemname(MasterBook);
- .distance = 1;
- end;
-
-OnUnset:
- @mb_BossId=0;
- @mb_SkillId=0;
- @mb_ItemId=0;
- @mb_ItemAm=0;
- end;
-}
-
-// Script Helper
-// BossSlain(npcname, "variable")
-function script BossSlain {
- .@n$=getarg(0);
- // Error
- if (!playerattached())
- return;
- // Only the party which defeated the boss can learn the skill
- getmapxy(.@m$, .@x, .@y, 0);
- .@party=getcharid(1);
- if (.@party > 0)
- {
- setd(getarg(1), .@party);
- areatimer(.@m$, .@x-15, .@y-15, .@x+15, .@y+15, 10, .@n$+"::OnBossCheck");
- mapannounce .@m$, "Boss deafeated by Party: " + getpartyname(.@party), bc_all;
- }
- else
- {
- setd(getarg(1), -2);
- areatimer(.@m$, .@x-15, .@y-15, .@x+15, .@y+15, 10, .@n$+"::OnBossCheck");
- addtimer(20, .@n$+"::OnBegin");
- mapannounce .@m$, "Boss deafeated by: " + strcharinfo(0), bc_all;
- }
- return;
-}
-
-
diff --git a/npc/items/mirror.txt b/npc/items/mirror.txt
new file mode 100755
index 00000000..9e114c36
--- /dev/null
+++ b/npc/items/mirror.txt
@@ -0,0 +1,18 @@
+function script useMirror {
+ callfunc "getHeadStyles";
+ goto L_Rand;
+
+L_Rand:
+ @mirror_rnd = @mirror_rnd + 1;
+ @style = rand(1,getarraysize(@HairStyles$));
+ @color = rand((15 * (Class - 1)),((15 * (Class - 1)) + (getarraysize(@HairColors$) - 1)));
+ if(((getlook(LOOK_HAIR_STYLE) == @style) || (getlook(LOOK_HAIR_COLOR) == @color)) && @mirror_rnd < 15)
+ goto L_Rand;
+ if(@fixedMirror)
+ setlook LOOK_HAIR_STYLE, @style;
+ setlook LOOK_HAIR_COLOR, @color;
+ //if(!@fixedMirror) getitem "SilverMirror", 1; <== this can be used in the future to have a portable hair color changer (like scissors but for the color)
+ @fixedMirror = 0;
+ @mirror_rnd = 0;
+ return;
+}
diff --git a/npc/items/music_toys.txt b/npc/items/music_toys.txt
deleted file mode 100644
index 8583f65e..00000000
--- a/npc/items/music_toys.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-// Evol scripts.
-// Authors:
-// Quillia
-// mekolat (legacy delay logic)
-// Description:
-// Allows the RubberBat to be squeezed.
-//
-
-- script RubberBat NPC_HIDDEN,{
- close;
-
-OnUse:
- if (gettimetick(2) - @lastbat < 2) close;
- specialeffect(70, AREA, playerattached()); // effect 70 defined in client-data/effects.xml
- @lastbat = gettimetick(2);
-
- close;
-}
diff --git a/npc/items/pickled_beets.txt b/npc/items/pickled_beets.txt
new file mode 100755
index 00000000..98d7360f
--- /dev/null
+++ b/npc/items/pickled_beets.txt
@@ -0,0 +1,9 @@
+function script usePickledBeets {
+ heal 50, 0, 1;
+ if (Class == 1)
+ setlook LOOK_HAIR_COLOR, HC_PURPLE;
+ elif (Class == 2)
+ setlook LOOK_HAIR_COLOR, 18;
+ // add more here for races that have purple
+ return;
+}
diff --git a/npc/items/purification_potion.txt b/npc/items/purification_potion.txt
new file mode 100755
index 00000000..47f84f3b
--- /dev/null
+++ b/npc/items/purification_potion.txt
@@ -0,0 +1,26 @@
+
+function script usePurificationPotion {
+ if (isat("011-1", 88,67))
+ goto L_Wyara_Pond;
+ goto L_NoUse;
+
+L_NoUse:
+ message strcharinfo(0), "You don't know what to do with this.";
+ getitem "PurificationPotion", 1;
+ return;
+
+L_Wyara_Pond:
+ @Q_MASK = NIBBLE_2_MASK;
+ @Q_SHIFT = NIBBLE_2_SHIFT;
+ @Q_status = (QUEST_MAGIC2 & @Q_MASK) >> @Q_SHIFT;
+
+ if (@Q_status < 1)
+ goto L_NoUse;
+ if (@Q_status <= 2)
+ @Q_status = @Q_status + 1;
+
+ message strcharinfo(0), "You pour the potion into the pond.";
+
+ QUEST_MAGIC2 = (QUEST_MAGIC2 & ~(@Q_MASK) | (@Q_status << @Q_SHIFT));
+ return;
+}
diff --git a/npc/items/rand_sc_heal.txt b/npc/items/rand_sc_heal.txt
deleted file mode 100644
index e4b0875a..00000000
--- a/npc/items/rand_sc_heal.txt
+++ /dev/null
@@ -1,85 +0,0 @@
-// Evol scripts.
-// Author:
-// Reid
-// Description:
-// Random heal every x seconds.
-//
-// Variables:
-// @delay Second of healing
-// @min Min amount of healing
-// @max Max amount of healing
-// @type 1 Heal
-// 2 Other
-// 3 Special 1
-// 4 Special 2
-
-- script rand_sc_heal -1,{
-
- // Add remaning bonus if the last one hasn't finished
- function remaining_bonus
- {
- if (getstatus(getarg(0)))
- {
- .@old_val1 = getstatus(getarg(0), 1);
- .@old_delay = getstatus(getarg(0), 4) * 1000;
-
- // change the delay to prevent fast healing
- if (.@old_delay > @delay)
- {
- @delay = .@old_delay;
- @val1 += .@old_val1;
- }
- else
- {
- @val1 += (.@old_val1 * .@old_delay) / @delay;
- }
- }
- else
- {
- @val1 = @val3;
- }
- return;
- }
-
-OnUse:
- if (@delay <= 0) close;
-
- // minimum between @min and bVit / 2 * BaseLevel / 10
- .@vitality_bonus = min(@min, readparam(bVit) * BaseLevel / 20);
- .@rand_heal_val = rand(@min, @max);
-
- // val1 is the heal value without the vitality bonus
- @val1 = .@rand_heal_val / @delay;
- @val3 = (.@rand_heal_val + .@vitality_bonus) / @delay;
-
- if (@val1 <= 0) close;
-
- @delay *= 1000; // Put the delay in ms
-
- switch (@type)
- {
- case 1:
- .@skill = SC_S_LIFEPOTION;
- break;
- case 2:
- .@skill = SC_L_LIFEPOTION;
- break;
- case 3:
- .@skill = SC_G_LIFEPOTION;
- break;
- case 4:
- .@skill = SC_M_LIFEPOTION;
- break;
- default :
- .@skill = 0;
- break;
- }
- if (.@skill != 0)
- {
- remaining_bonus(.@skill);
- sc_end .@skill;
- sc_start2 .@skill, @delay, @val1, 1;
- }
-
- close;
-}
diff --git a/npc/items/recipes.txt b/npc/items/recipes.txt
deleted file mode 100644
index 42cdf51b..00000000
--- a/npc/items/recipes.txt
+++ /dev/null
@@ -1,352 +0,0 @@
-// Evol script.
-// Author:
-// Jesusalva
-// Micksha
-// Description:
-// Contains recipe books for Evol Online
-
-// showRecipe( recipe{, recipe...} )
-function script showRecipe {
- freeloop(true);
- for (.@a = 0; .@a < getargcount(); ++.@a) {
- .@const$ = data_to_string(getarg(.@a));
-
- if (startswith(.@const$, "Craft")) {
- // infer the item constant from the craft constant
- .@recipe = getarg(.@a);
-
- .@item = string_to_data(substr(.@const$, 5, getstrlen(.@const$) - 1));
- } else {
- // infer the craft constant from the item constant
- .@recipe = string_to_data(sprintf("Craft%s", .@const$));
- .@item = getarg(.@a);
- }
-
- if (.@item <= 0) {
- // target item not found
- continue;
- }
-
- if (!RECIPES[.@recipe] && !debug) {
- // does not have the recipe
- continue;
- }
-
- for (.@inv = 0; .@inv < 9; ++.@inv) {
- .@size = getcraftrecipe(.@recipe, .@inv, .@qty[0], .@item_id[0]);
-
- if (.@size < 0) {
- if (.@size == -1) {
- // recipe does not exist
- break;
- }
- // inventory does not exist
- break;
- }
-
- mes(l(".:: %s Recipe ::.", getitemlink(.@item)));
-
- for (.@it = 0; .@it < .@size; ++.@it) {
- .@recipe_item = .@item_id[.@it];
- .@recipe_qty = .@qty[.@it];
-
- if (.@recipe_item <= 0) {
- break;
- }
-
- mesc(sprintf("%d/%d %s", countitem(.@recipe_item), .@recipe_qty, getitemlink(.@recipe_item)));
- }
-
- mes("");
- .@count++;
- }
- }
- freeloop(false);
-
- return .@count > 0;
-}
-
-- script #RecipeBook NPC_HIDDEN,{
- function read_book;
- function read_cooking;
- function read_smithery;
- function read_tailoring;
- end;
-
-function read_book {
- setnpcdialogtitle l(.book_name$);
- mesc l("This book has several bookmarks. Which one will you open?");
- next;
- menuint
- l("Cooking"), CRAFT_COOKING,
- l("Alchemy"), CRAFT_ALCHEMY,
- l("Smithery"), CRAFT_SMITHERY,
- l("Tailoring"), CRAFT_TAILORING,
- l("Jewelery"), CRAFT_JEWELERY;
- mes "";
- switch (@menuret) {
- case CRAFT_COOKING:
- read_cooking(); break;
- case CRAFT_SMITHERY:
- read_smithery(); break;
- case CRAFT_TAILORING:
- read_tailoring(); break;
- default:
- mesc l("Unfortunately, there is nothing on this bookmark.");
- mesc l("Perhaps, in future, someone adds it to this world.");
- break;
- }
- close2();
- return;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-function read_cooking {
-
- setnpcdialogtitle l("Cooking Recipes");
-
- mesc l("Eating is a necessity, but cooking is an art.");
- mesc l("(All items must be placed exactly in this order for cooking work.)");
- next;
- mesc l("List of known cooking recipes:");
- mes "";
- mes ".:: " + l("Sandwiches") + " ::.";
- mes "";
-
- showRecipe(CarpSandwich,
- PioulegSandwich,
- MananaSandwich);
-
- mes "";
- mes ".:: " + l("Stew") + " ::.";
- mes "";
-
- showRecipe(SailorStew,
- SquirrelStew,
- MoubooStew);
-
- mes "";
- mes ".:: " + l("Plates") + " ::.";
- mes "";
-
- showRecipe(SeafoodPlate,
- BarbecuePlate,
- VeggiePlate);
-
- mes "";
- mes ".:: " + l("Desserts") + " ::.";
- mes "";
-
- showRecipe(Donut,
- BlueberryCake,
- CarrotCake);
- return;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-function read_smithery {
-
- setnpcdialogtitle l("Smithery Recipes");
-
- mesc l("You will trust your life to this, so you better do a good job!");
- mesc l("(All items must be placed exactly in this order.)");
- next;
- mesc l("List of known smithery recipes:");
-
- mes();
- mesf(".:: %s ::.", l("Chest Armor"));
- mes();
-
- showRecipe(LegionTrainingShirt,
- LegionCopperArmor,
- Chainmail,
- Snakeplate,
- LightPlatemail,
- JustifierChest,
- LegionIronArmor,
- WarlordPlate,
- TerraniteArmor,
- AssassinChest,
- BlackArmor,
- GoldenWarlordPlate);
-
- next();
- mes();
- mesf(".:: %s ::.", l("Leg Armor"));
- mes();
-
- showRecipe(ChainmailSkirt,
- TerranitePants,
- AssassinPants);
-
- next();
- mes();
- mesf(".:: %s ::.", l("Gloves"));
- mes();
-
- showRecipe(CopperArmbands,
- BromenalGloves,
- IronArmbands);
-
- next();
- mes();
- mesf(".:: %s ::.", l("Boots"));
- mes();
-
- showRecipe(BromenalBoots,
- WarlordBoots);
-
- return;
-}
-
-function read_tailoring {
- setnpcdialogtitle(l("Tailoring Recipes"));
-
- mesc(l("(All items must be placed exactly in this order.)"));
- next();
- mesc(l("List of known tailoring recipes:"));
-
- mes();
- mesf(".:: %s ::.", l("Chest Armor"));
- mes();
-
- showRecipe(CreasedShirt,
- ArtisTankTop,
- VneckJumper,
- SailorShirt,
- FineDress,
- SilkRobe,
- ForestArmor,
- ApprenticeRobe,
- PeltJacket,
- SorcererRobe,
- WizardRobe,
- EvocatorRobe);
-
- next();
- mes();
- mesf(".:: %s ::.", l("Leg Armor"));
- mes();
-
- showRecipe(CreasedShorts,
- CottonSkirt,
- PirateShorts,
- SilkPants,
- BrownTrousers,
- BanditTrousers,
- JeansChaps,
- LeatherTrousers);
-
- next();
- mes();
- mesf(".:: %s ::.", l("Gloves"));
- mes();
-
- showRecipe(ShortGloves,
- Armbands,
- CottonGloves,
- BanditGloves,
- SilkGloves,
- LeatherGloves,
- AssassinGloves);
-
- next();
- mes();
- mesf(".:: %s ::.", l("Boots"));
- mes();
-
- showRecipe(LousyMoccasins,
- Slippers,
- CottonBoots,
- BanditBoots,
- ManaSlippers,
- SquirrelBoots,
- LeatherBoots,
- RidingBoots,
- AssassinBoots);
-
- return;
-}
-
-
-OnUse:
- if (openbook())
- read_book();
- closeclientdialog();
- close;
-
-OnInit:
- .book_name$ = getitemname(RecipeBook);
- .distance = 1;
- end;
-}
-
-//////////////////////////////////////////////////////
-// Below this line are utils for Gacha. We use callfunc() on itemDB.
-// Types: see constants.db - everything is a bitwise here
-// Rarity: 1 - basic, 2 - intermediary, 4 - advanced, 8 - expert, 16 - master
-// Rarity: 1 - training, 2 - basic, 4 - advanced, 8 - expert, 16 - legendary
-// Keep in mind! Expert and Master blueprints must be restricted!
-// MakeBlueprint(type, rarity)
-function script MakeBlueprint {
- .@type=getarg(0, -1);
- .@rarity=getarg(1, 1);
-
- if (.@type & CRAFT_COOKING) {
-
- // ----------------------------------
- if (.@rarity & CRAFT_BASIC) {
- }
- if (.@rarity & CRAFT_INTERMEDIARY) {
- }
- if (.@rarity & CRAFT_ADVANCED) {
- }
- if (.@rarity & CRAFT_EXPERT) {
- }
- if (.@rarity & CRAFT_MASTER) {
- }
- // ----------------------------------
-
- }
- else if (.@type & CRAFT_SMITHERY)
- {
-
- // ----------------------------------
- if (.@rarity & CRAFT_BASIC) {
- }
- if (.@rarity & CRAFT_INTERMEDIARY) {
- array_push(.@recipes, CraftInfantryHelmet);
- }
- if (.@rarity & CRAFT_ADVANCED) {
- }
- if (.@rarity & CRAFT_EXPERT) {
- }
- if (.@rarity & CRAFT_MASTER) {
- }
- // ----------------------------------
-
- }
-
- // We don't have a .@recipes array D:
- if (array_entries(.@recipes) <= 0) {
- dispbottom l("This blueprint was blank.");
- return;
- }
-
- // Select a recipe randomly
- .@rcp=any_of(.@recipes);
-
- // Double precision failsafe
- if (RECIPES[.@rcp])
- .@rcp=any_of(.@recipes);
-
- // Learn the recipe or lose the item (and gain some EXP)
- if (RECIPES_[.@rcp]) {
- dispbottom l("It was a recipe you already knew...");
- getexp (BaseLevel+JobLevel)*rand2(1,.@rarity), JobLevel+rand2(1,.@rarity);
- } else {
- dispbottom l("Learned a new recipe!");
- RECIPES[.@rcp]=true;
- }
- return;
-}
diff --git a/npc/items/require_stat.txt b/npc/items/require_stat.txt
new file mode 100755
index 00000000..cd274b62
--- /dev/null
+++ b/npc/items/require_stat.txt
@@ -0,0 +1,13 @@
+
+function script RequireStat {
+ @bStatVal = @bStat;
+ // If the requirement isn't met, we set an unequip trigger.
+ // The item is now removed.
+ if (@bStat < @minbStatVal)
+ goto L_Unequip;
+ return;
+
+L_Unequip:
+ callfunc "UnequipLater";
+ return;
+}
diff --git a/npc/items/restricted_item.txt b/npc/items/restricted_item.txt
new file mode 100755
index 00000000..96a60272
--- /dev/null
+++ b/npc/items/restricted_item.txt
@@ -0,0 +1,14 @@
+
+function script RestrictedItem {
+ if (!@minLvl) set @minLvl, 60;
+ if (debug || getgmlevel() >= @minLvl) goto L_Return; // If the active character is staff, do nothing.
+ message strcharinfo(0), "This item repells you with extreme force. It does not seem to be meant for you.";
+ callfunc "UnequipLater";
+ if (getgmlevel()) goto L_Return;
+ wgm "Restricted item '" + @itemId + "' used by character '" + strcharinfo(0) + "'.";
+ gmlog "Restricted item '" + @itemId + "' used by character '" + strcharinfo(0) + "'.";
+ goto L_Return;
+
+L_Return:
+ return;
+}
diff --git a/npc/items/rubber_bat.txt b/npc/items/rubber_bat.txt
new file mode 100755
index 00000000..a5921674
--- /dev/null
+++ b/npc/items/rubber_bat.txt
@@ -0,0 +1,10 @@
+function script rubberBat {
+ if (gettimetick(2) - @lastbat < 2) goto L_Return;
+ misceffect 403;
+ @lastbat = gettimetick(2);
+ goto L_Return;
+
+L_Return:
+ getitem "RubberBat", 1;
+ return;
+}
diff --git a/npc/items/scissors.txt b/npc/items/scissors.txt
new file mode 100755
index 00000000..d27e8f6f
--- /dev/null
+++ b/npc/items/scissors.txt
@@ -0,0 +1,13 @@
+function script useScissors {
+ getitem "Scissors", 1;
+ if (rand(3))
+ goto L_Change;
+ message strcharinfo(0), "Whoops!";
+ heal -20 - rand(Hp >> 1), 0;
+ return;
+
+L_Change:
+ callfunc "getHeadStyles";
+ setlook LOOK_HAIR_STYLE, rand(1,getarraysize(@HairStyles$));
+ return;
+}
diff --git a/npc/items/shock_sweet.txt b/npc/items/shock_sweet.txt
new file mode 100755
index 00000000..f1f1df71
--- /dev/null
+++ b/npc/items/shock_sweet.txt
@@ -0,0 +1,14 @@
+function script useShockSweet {
+ if (rand(5))
+ goto L_Change;
+ message strcharinfo(0), "Yuck, this tastes like earwax!";
+ heal -20 - (Hp >> 2), 0;
+ return;
+
+L_Change:
+ setlook LOOK_HAIR_COLOR, (HC_WHITE - Class) + 1;
+ message strcharinfo(0), "Gah! That was some strong stuff!";
+ sc_start SC_POISON, 1, 20;
+ misceffect 15, strcharinfo(0);
+ return;
+}
diff --git a/npc/items/shovel.txt b/npc/items/shovel.txt
deleted file mode 100644
index b4a5a968..00000000
--- a/npc/items/shovel.txt
+++ /dev/null
@@ -1,361 +0,0 @@
-// Evol scripts.
-// Author:
-// Travolta
-// Jesusalva
-// Description:
-// NPC to use shovel (dig, bury etc)
-
-- script Shovel -1,{
-
- function CheckDigLocation {
- getmapxy(.@map$, .@x, .@y, 0);
-
- if (.@map$ != "001-1") {
- if (getunits(BL_NPC, .@units, 1, .@map$, .@x - 1, .@y, .@x + 1, .@y + 1))
- {
- dispbottom(l("You cannot bury under a NPC!"));
- return false;
- }
- }
-
- // TODO: we should have a way to check for GROUNDTOP collisions too
-
- for (.@i = 0; .@i < getarraysize(.WorldDigRect_Map$); .@i++)
- {
- if (!strcmp(.WorldDigRect_Map$[.@i], .@map$) &&
- .WorldDigRect_x1[.@i] <= .@x &&
- .WorldDigRect_x2[.@i] >= .@x &&
- .WorldDigRect_y1[.@i] <= .@y &&
- .WorldDigRect_y2[.@i] >= .@y)
- {
- return true;
- }
- }
-
- dispbottom(l("You can't use the shovel here."));
- return false;
- }
-
- function AddDigRect {
- if (getargcount() < 5)
- {
- consolemes(CONSOLEMES_ERROR, "usage: AddDigRect(map$,x1,y1,x2,y2)");
- return 0;
- }
- .@map$ = str(getarg(0));
- .@x1 = getarg(1);
- .@y1 = getarg(2);
- .@x2 = getarg(3);
- .@y2 = getarg(4);
- .@size = getarraysize(.WorldDigRect_Map$);
- .WorldDigRect_Map$[.@size] = .@map$;
- .WorldDigRect_x1[.@size] = .@x1;
- .WorldDigRect_y1[.@size] = .@y1;
- .WorldDigRect_x2[.@size] = .@x2;
- .WorldDigRect_y2[.@size] = .@y2;
- return 1;
- }
-
- function AddMapDigRect {
- .@m$=getarg(0);
- .@x=getmapinfo(MAPINFO_SIZE_X, .@m$)-20;
- .@y=getmapinfo(MAPINFO_SIZE_Y, .@m$)-20;
- return AddDigRect(.@m$, 20, 20, .@x, .@y);
- }
-
- function PlayerIsTired {
- if (is_evtc())
- return false; // event coordinators are never tired
-
- .@tick = gettimetick(1);
- .@playertick = .PlayerTiredTime - readparam(bStr);
- if (@ShovelLastUsed + max(4, .@playertick) > .@tick)
- {
- narrator S_FIRST_BLANK_LINE,
- l("You are exhausted, you should rest a bit.");
- return true;
- }
- @ShovelLastUsed = .@tick;
- return false;
- }
-
- function Dig {
- getmapxy(.@map$, .@x, .@y, 0);
- for (.@i = 0; .@i < getarraysize($WorldBuriedTreasures_id); .@i++)
- {
- if (!strcmp($WorldBuriedTreasures_map$[.@i], .@map$) &&
- $WorldBuriedTreasures_x[.@i] == .@x &&
- $WorldBuriedTreasures_y[.@i] == .@y)
- {
- .@id = $WorldBuriedTreasures_id[.@i];
- .@amount = $WorldBuriedTreasures_amount[.@i];
- deletearray $WorldBuriedTreasures_id[.@i], 1;
- deletearray $WorldBuriedTreasures_amount[.@i], 1;
- deletearray $WorldBuriedTreasures_map$[.@i], 1;
- deletearray $WorldBuriedTreasures_x[.@i], 1;
- deletearray $WorldBuriedTreasures_y[.@i], 1;
- getitem .@id, .@amount;
- narrator S_FIRST_BLANK_LINE,
- l("You found something!"),
- l("It's @@ @@.", .@amount, getitemname(.@id));
- return 1;
- }
- }
- narrator S_FIRST_BLANK_LINE, l("Sadly, you found nothing but dirt.");
- return 0;
- }
-
- function Bury {
- narrator S_FIRST_BLANK_LINE | S_LAST_BLANK_LINE, l("What would you like to bury?");
- .@items$ = "";
-
- mes "##B" + l("Drag and drop an item from your inventory.") + "##b";
-
- .@id = requestitem();
-
- // If ID is invalid, there's not enough items, it is an Iron Shovel, it is bound = Cannot bury
- // NOBODY bypass notrade check. (ITR_NONE is 0)
- if (.@id < 1) close;
- if (.@id < 1 || countitem(.@id) < 1 || .@id == IronShovel || checkbound(.@id) ||
- (!getiteminfo(.@id, ITEMINFO_TRADE))
- ) {
- @ShovelLastUsed = 0;
- if (.@id == IronShovel || .@id == SteelShovel || checkbound(.@id))
- mesc l("You cannot bury this item!");
- else if (!getiteminfo(.@id, ITEMINFO_TRADE))
- mesc l("This item is too precious, you cannot part with it!");
- else
- mesc l("You give up.");
- close;
- return;
- }
-
- .@amount = 1;
- if (countitem(.@id) > 1)
- {
- narrator S_FIRST_BLANK_LINE | S_LAST_BLANK_LINE, l("Amount?");
- input .@amount, 1, countitem(.@id);
- }
-
- getmapxy(.@map$, .@x, .@y, 0);
-
- delitem .@id, .@amount;
- .@wtc = getarraysize($WorldBuriedTreasures_id);
- $WorldBuriedTreasures_id[.@wtc] = .@id;
- $WorldBuriedTreasures_amount[.@wtc] = .@amount;
- $WorldBuriedTreasures_map$[.@wtc] = .@map$;
- $WorldBuriedTreasures_x[.@wtc] = .@x;
- $WorldBuriedTreasures_y[.@wtc] = .@y;
- narrator S_FIRST_BLANK_LINE, l("You buried @@ @@.", .@amount, getitemname(.@id));
-
- return true;
- }
-
- function ShovelQuests {
- getmapxy(.@map$, .@x, .@y, 0);
- for (.@i = 0; .@i < getarraysize(ShovelQuests_func$); .@i++)
- {
- if (!strcmp(ShovelQuests_map$[.@i], .@map$) &&
- ShovelQuests_x[.@i] == .@x &&
- ShovelQuests_y[.@i] == .@y)
- {
- .@func$ = ShovelQuests_func$[.@i];
- deletearray ShovelQuests_func$[.@i], 1;
- deletearray ShovelQuests_map$[.@i], 1;
- deletearray ShovelQuests_x[.@i], 1;
- deletearray ShovelQuests_y[.@i], 1;
- callfunc(.@func$);
- return 1;
- }
- }
- return 0;
- }
-
-OnUse:
- if (!CheckDigLocation())
- end;
-
- narrator S_LAST_BLANK_LINE,
- l("You hold the shovel in your hands."),
- l("What are you going to do?");
-
- .@action = select(
- l("Dig."),
- l("Bury."),
- l("Nothing."));
-
- switch(.@action)
- {
- case 1:
- if (PlayerIsTired())
- close;
- if (!ShovelQuests())
- Dig();
- break;
- case 2:
- if (PlayerIsTired())
- close;
- Bury();
- break;
- case 3:
- narrator S_FIRST_BLANK_LINE, l("You hide your shovel.");
- break;
- }
- close;
-
-OnHour00:
- if (playerattached())
- @ShovelLastUsed = 0;
- end;
-
-OnInit:
- .PlayerTiredTime = 20;
-
- // Partial maps
- AddDigRect("001-1", 172, 26, 200, 48);
- AddDigRect("001-1", 198, 60, 201, 63);
- AddDigRect("008-1-1", 32, 42, 46, 88);
- AddDigRect("008-1-2", 40, 52, 114, 146);
- AddDigRect("012-1", 44, 21, 139, 47);
-
- // Whole maps
- AddMapDigRect("008-1");
- AddMapDigRect("008-3-5");
- AddMapDigRect("012-3-1");
- end;
-
-}
-
-function script shovel_addquest {
- if (getargcount() < 4)
- {
- consolemes(CONSOLEMES_ERROR, "usage: shovel_addquest(map$,x,y,func$)");
- return 0;
- }
- .@map$ = str(getarg(0));
- .@x = getarg(1);
- .@y = getarg(2);
- .@func$ = str(getarg(3));
- .@size = getarraysize(ShovelQuests_func$);
- ShovelQuests_func$[.@size] = .@func$;
- ShovelQuests_map$[.@size] = .@map$;
- ShovelQuests_x[.@size] = .@x;
- ShovelQuests_y[.@size] = .@y;
- return 1;
-}
-
-function script shovel_adddigrect {
- if (getargcount() < 5)
- {
- consolemes(CONSOLEMES_ERROR, "usage: shovel_adddigrect(map$,x1,y1,x2,y2)");
- return 0;
- }
- .@map$ = str(getarg(0));
- .@x1 = getarg(1);
- .@y1 = getarg(2);
- .@x2 = getarg(3);
- .@y2 = getarg(4);
- .@size = getarraysize(getvariableofnpc(.WorldDigRect_Map$, strnpcinfo(3)));
- set getvariableofnpc(.WorldDigRect_Map$[.@size], strnpcinfo(3)), .@map$;
- set getvariableofnpc(.WorldDigRect_x1[.@size], strnpcinfo(3)), .@x1;
- set getvariableofnpc(.WorldDigRect_y1[.@size], strnpcinfo(3)), .@y1;
- set getvariableofnpc(.WorldDigRect_x2[.@size], strnpcinfo(3)), .@x2;
- set getvariableofnpc(.WorldDigRect_y2[.@size], strnpcinfo(3)), .@y2;
- return 1;
-}
-
-// [Treasure Map] functions
-
-function script shovel_getcity {
- .@a$=getarg(0);
-
- // else is not required (return prevails)
- if (.@a$ == "001-1")
- return l("Artis East Beach");
- if (.@a$ == "008-1")
- return l("East Woodlands");
- if (.@a$ == "008-1-1")
- return l("West Woodland Beach");
- if (.@a$ == "008-1-2")
- return l("Swamps");
- if (.@a$ == "008-3-5")
- return l("Hurnscald Bandit Cave");
- if (.@a$ == "012-1")
- return l("Candor North");
- if (.@a$ == "012-3-1")
- return l("Candor Main Cave");
-
- return .@a$;
-}
-
-function script shovel_randomtreasure {
- .@id=any(TreasureKey,CoinBag,CoinBag,CoinBag,Coal,
- Diamond,Ruby,Emerald,Sapphire,Topaz,Amethyst,
- CrudeDiamond,CrudeRuby,CrudeEmerald,
- CrudeSapphire,CrudeTopaz,CrudeAmethyst,
- MaggotSlimePotion, LargeMana, LargeHealing);
- delitem TreasureMap, 1;
- .@amount=any(1,1,2);
- // Very Commons
- if (.@id == CoinBag || .@id == MaggotSlimePotion || .@id == TreasureKey)
- .@amount+=any(0,1,0,1,2);
- // Super commons
- if (.@id == LargeMana || .@id == LargeHealing)
- .@amount+=rand2(0,8);
- // Rares
- if (.@id == Coal)
- .@amount=1;
- getitem .@id, .@amount;
- ShovelQuests_AssignedMAP$="";
- ShovelQuests_AssignedX=0;
- ShovelQuests_AssignedY=0;
-
- mesn strcharinfo(0);
- mesc l("You found something!");
- mesc l("It's %d %s.", .@amount, getitemlink(.@id));
- next;
- closeclientdialog;
- return;
-}
-
-function script shovel_genrandtreasure {
- .@m$=any("008-1", "008-1-1", "008-1-2", "008-3-5",
- "012-1", "012-3-1");
-
- // Prepare good defaults
- .@x1=.@y1=20;
- .@x2=getmapinfo(MAPINFO_SIZE_X, .@m$)-20;
- .@y2=getmapinfo(MAPINFO_SIZE_Y, .@m$)-20;
-
- // Default overrides
- if (.@m$ == "008-1-1") {
- // West Woodland Beach
- .@x1=32; .@y1=42;
- .@x2=46; .@y2=88;
- } else if (.@m$ == "008-1-2") {
- // Swamps
- .@x1=40; .@y1=52;
- .@x2=114; .@y2=146;
- } else if (.@m$ == "012-1") {
- // Candor North
- .@x1=44; .@y1=139;
- .@x2=21; .@y2=47;
- }
-
- // Dangerous, but I never had issues with this
- do {
- .@x=rand2(.@x1, .@x2);
- .@y=rand2(.@y1, .@y2);
- } while (!checkcell(.@m$, .@x, .@y, cell_chkpass));
-
- // Success
- if (checkcell(.@m$, .@x, .@y, cell_chkpass)) {
- shovel_addquest(.@m$, .@x, .@y, "shovel_randomtreasure");
- ShovelQuests_AssignedMAP$=shovel_getcity(.@m$);
- ShovelQuests_AssignedX=.@x;
- ShovelQuests_AssignedY=.@y;
- }
- return;
-}
-
-
diff --git a/npc/items/unequipcb.txt b/npc/items/unequipcb.txt
new file mode 100755
index 00000000..a1c7881d
--- /dev/null
+++ b/npc/items/unequipcb.txt
@@ -0,0 +1,22 @@
+- script UnequipCB NPC32767,{
+ end;
+
+OnUnequip:
+ unequipbyid (@unequip_slot - 1);
+ @unequip_slot = 0;
+ end;
+}
+
+function script UnequipLater {
+ // if there are multiple items that want to be removed,
+ // only schedule one timer - scripts will be called again
+ if (@unequip_slot)
+ goto L_Return;
+
+ @unequip_slot = (@slotId + 1);
+ addtimer 0, "UnequipCB::OnUnequip";
+ goto L_Return;
+
+L_Return:
+ return;
+}
diff --git a/npc/items/unreleased_item.txt b/npc/items/unreleased_item.txt
new file mode 100755
index 00000000..c88df137
--- /dev/null
+++ b/npc/items/unreleased_item.txt
@@ -0,0 +1,12 @@
+
+function script UnreleasedItem {
+ // If the server allows equipping unreleased items or if the active character is staff, do nothing.
+ if (debug || getgmlevel())
+ goto L_Return;
+ message strcharinfo(0), "You have difficulties equipping this item, as if it is not yet fully in this world.";
+ callfunc "UnequipLater";
+ goto L_Return;
+
+L_Return:
+ return;
+}
diff --git a/npc/items/warpTowels.txt b/npc/items/warpTowels.txt
new file mode 100755
index 00000000..18fea9f7
--- /dev/null
+++ b/npc/items/warpTowels.txt
@@ -0,0 +1,152 @@
+function script WarpTowel {
+ @seconds = TowelLastUsed - (gettimetick(2) - 1200);
+ if (@seconds > 0)
+ goto L_DontPanic;
+ if (isin("botcheck",25,27,51,47))
+ goto L_Prison;
+ if (getmapflag(getmapname(), mf_nosave) || getmapflag(getmapname(), MF_NOTELEPORT) || getmapflag(getmapname(), MF_NOWARP) || isin("009-7",$@fightclub_x1,$@fightclub_y1,$@fightclub_x2,$@fightclub_y2))
+ goto L_Forbid;
+
+ if (@warpTowelName$ == "HitchhikersTowel")
+ goto L_Save;
+ if(@warpTowelName$ == "WhiteHitchhikersTowel")
+ goto L_White;
+ if(@warpTowelName$ == "RedHitchhikersTowel")
+ goto L_Red;
+ if(@warpTowelName$ == "GreenHitchhikersTowel")
+ goto L_Green;
+ if(@warpTowelName$ == "BlueHitchhikersTowel")
+ goto L_Blue;
+ if(@warpTowelName$ == "YellowHitchhikersTowel")
+ goto L_Yellow;
+ if(@warpTowelName$ == "PurpleHitchhikersTowel")
+ goto L_Purple;
+ if(@warpTowelName$ == "OrangeHitchhikersTowel")
+ goto L_Orange;
+ if(@warpTowelName$ == "PinkHitchhikersTowel")
+ goto L_Pink;
+ if(@warpTowelName$ == "TealHitchhikersTowel")
+ goto L_Teal;
+ if(@warpTowelName$ == "LimeHitchhikersTowel")
+ goto L_Lime;
+ goto L_Save;
+
+L_White:
+ // Koga
+ @NextLocationMap$ = "035-2";
+ @NextLocationX = 20;
+ @NextLocationY = 21;
+ goto L_WarpPlayer;
+
+L_Red:
+ // Barbarians
+ @NextLocationMap$ = "033-1";
+ @NextLocationX = 66;
+ @NextLocationY = 33;
+ goto L_WarpPlayer;
+
+L_Green:
+ // Candor
+ @NextLocationMap$ = "029-1";
+ @NextLocationX = 69;
+ @NextLocationY = 69;
+ goto L_WarpPlayer;
+
+L_Blue:
+ // Blue Sages
+ @NextLocationMap$ = "048-2";
+ @NextLocationX = 26;
+ @NextLocationY = 47;
+ goto L_WarpPlayer;
+
+L_Yellow:
+ // Tulimshar Mines
+ @NextLocationMap$ = "002-2";
+ @NextLocationX = 27;
+ @NextLocationY = 28;
+ goto L_WarpPlayer;
+
+L_Purple:
+ // Dimonds Inn
+ @NextLocationMap$ = "010-1";
+ @NextLocationX = 27;
+ @NextLocationY = 97;
+ goto L_WarpPlayer;
+
+L_Orange:
+ // Graveyard
+ @NextLocationMap$ = "027-1";
+ @NextLocationX = 70;
+ @NextLocationY = 100;
+ goto L_WarpPlayer;
+
+L_Pink:
+ // Terranite Cave
+ @NextLocationMap$ = "012-3";
+ @NextLocationX = 448;
+ @NextLocationY = 66;
+ goto L_WarpPlayer;
+
+L_Teal:
+ // Mana Seed
+ @NextLocationMap$ = "012-3";
+ @NextLocationX = 64;
+ @NextLocationY = 130;
+ goto L_WarpPlayer;
+
+L_Lime:
+ // Pachua
+ @NextLocationMap$ = "006-1";
+ @NextLocationX = 28;
+ @NextLocationY = 97;
+ if(QUEST_MIRIAM_start != 0) goto L_Cheat;
+ goto L_WarpPlayer;
+
+L_Cheat:
+ QUEST_MIRIAM_cheat = 1;
+ QUEST_MIRIAM_run = gettimetick(2) - QUEST_MIRIAM_start;
+ QUEST_MIRIAM_start = 0;
+ goto L_WarpPlayer;
+
+L_Save:
+ // Soul Menhir
+ @NextLocationMap$ = getsavepoint(0);
+ @NextLocationX = getsavepoint(1);
+ @NextLocationY = getsavepoint(2);
+ goto L_WarpPlayer;
+
+L_WarpPlayer:
+ TowelLastUsed = gettimetick(2);
+ warp @NextLocationMap$,@NextLocationX,@NextLocationY;
+ goto L_BreakChance;
+
+L_BreakChance:
+ if (rand(15))
+ goto L_Keep;
+ getitem "HitchhikersTowel", 1;
+ goto L_End;
+
+L_Forbid:
+ message strcharinfo(0), "Towel : This area is protected by a force that doesn't tolerate the power of the Towel.";
+ goto L_Keep;
+
+L_Prison:
+ message strcharinfo(0), "Towel : You must be warped by a GM to leave the botcheck area.";
+ goto L_Keep;
+
+L_DontPanic:
+ callfunc "HumanTime";
+ message strcharinfo(0), "Towel : Your towel is still too low on power to jump again. Try again in ##B"+ @time$ + "##b.";
+ goto L_Keep;
+
+L_Keep:
+ getitem @warpTowelName$, 1;
+ goto L_End;
+
+L_End:
+ @NextLocationMap$ = "";
+ @NextLocationX = 0;
+ @NextLocationY = 0;
+ @warpTowelName$ = "";
+ return;
+}