summaryrefslogtreecommitdiff
path: root/world/map/npc
diff options
context:
space:
mode:
Diffstat (limited to 'world/map/npc')
-rw-r--r--world/map/npc/009-2/selim.txt5
-rw-r--r--world/map/npc/009-8/_import.txt8
-rw-r--r--world/map/npc/009-8/_mobs.txt3
-rw-r--r--world/map/npc/009-8/_nodes.txt4
-rw-r--r--world/map/npc/009-8/_warps.txt5
-rw-r--r--world/map/npc/009-8/celestia.txt306
-rw-r--r--world/map/npc/009-8/mapflags.txt2
-rw-r--r--world/map/npc/016-2/_import.txt6
-rw-r--r--world/map/npc/016-2/_mobs.txt3
-rw-r--r--world/map/npc/016-2/_nodes.txt4
-rw-r--r--world/map/npc/016-2/_warps.txt5
-rw-r--r--world/map/npc/029-2/sorfina.txt22
-rw-r--r--world/map/npc/_import.txt2
-rw-r--r--world/map/npc/functions/DyeConfig.txt4
-rw-r--r--world/map/npc/functions/global_event_handler.txt3
-rw-r--r--world/map/npc/functions/hug.txt13
-rw-r--r--world/map/npc/functions/mob_points.txt11
-rw-r--r--world/map/npc/magic/_procedures.txt10
-rw-r--r--world/map/npc/magic/level1-lesser-heal.txt3
-rw-r--r--world/map/npc/magic/level1-sense-spouse.txt2
-rw-r--r--world/map/npc/magic/level2-barrier.txt3
-rw-r--r--world/map/npc/magic/level2-detect-players.txt3
-rw-r--r--world/map/npc/magic/level2-flying-backpack.txt3
-rw-r--r--world/map/npc/magic/level2-happy-curse.txt5
-rw-r--r--world/map/npc/magic/level2-hide.txt3
-rw-r--r--world/map/npc/magic/level2-lay-on-hands.txt2
-rw-r--r--world/map/npc/magic/level2-lightning-strike.txt2
-rw-r--r--world/map/npc/magic/level2-protect.txt3
-rw-r--r--world/map/npc/magic/level3-necromancy.txt2
29 files changed, 416 insertions, 31 deletions
diff --git a/world/map/npc/009-2/selim.txt b/world/map/npc/009-2/selim.txt
index ce5cc424..708b2e13 100644
--- a/world/map/npc/009-2/selim.txt
+++ b/world/map/npc/009-2/selim.txt
@@ -11,8 +11,13 @@ L_Main:
"Can you dye something for me?", L_clothes_choice,
"Can you also remove color from clothing?", L_ask_bleach,
"About these sorcerer robes...", L_asksorcererrobe,
+ "Can you change my appearance?", L_barber,
"Never mind.", L_Close;
+L_barber:
+ callfunc "Barber";
+ goto L_Main;
+
L_ask_bleach:
mes "[Selim]";
mes "\"I'm afraid no.";
diff --git a/world/map/npc/009-8/_import.txt b/world/map/npc/009-8/_import.txt
new file mode 100644
index 00000000..315f39b2
--- /dev/null
+++ b/world/map/npc/009-8/_import.txt
@@ -0,0 +1,8 @@
+// Map 009-8: Chez Celestia
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+map: 009-8
+npc: npc/009-8/_mobs.txt
+npc: npc/009-8/_nodes.txt
+npc: npc/009-8/_warps.txt
+npc: npc/009-8/celestia.txt
+npc: npc/009-8/mapflags.txt
diff --git a/world/map/npc/009-8/_mobs.txt b/world/map/npc/009-8/_mobs.txt
new file mode 100644
index 00000000..af8e2169
--- /dev/null
+++ b/world/map/npc/009-8/_mobs.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Chez Celestia mobs
+
diff --git a/world/map/npc/009-8/_nodes.txt b/world/map/npc/009-8/_nodes.txt
new file mode 100644
index 00000000..0dd108da
--- /dev/null
+++ b/world/map/npc/009-8/_nodes.txt
@@ -0,0 +1,4 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Chez Celestia nodes
+
+// (no nodes)
diff --git a/world/map/npc/009-8/_warps.txt b/world/map/npc/009-8/_warps.txt
new file mode 100644
index 00000000..ff75c4ab
--- /dev/null
+++ b/world/map/npc/009-8/_warps.txt
@@ -0,0 +1,5 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Chez Celestia warps
+
+009-8,26,22|warp|-1,-1,009-1,74,50
+009-8,22,34|warp|-1,-1,009-1,72,54
diff --git a/world/map/npc/009-8/celestia.txt b/world/map/npc/009-8/celestia.txt
new file mode 100644
index 00000000..8b2ee06a
--- /dev/null
+++ b/world/map/npc/009-8/celestia.txt
@@ -0,0 +1,306 @@
+// celestia quest
+// allocation: 8 bit (byte) => QL_CELESTIA (id 22)
+// uses 3rd byte of QUEST_Hurnscald (16th bit to 23th bit)
+// (0000 0000) (0000 0000) (XXXX XXXX) (0000 000-)
+// could stretch to use 7 more bits to the right if need be
+//
+// QL_CELESTIA states:
+// 000 can not do the easy quest
+// 001 can do the easy quest (show quest marker)
+// 002 got the easy quest (show in quest log)
+// 003 completed the easy quest, can not do the adv quest
+// 004 can do the adv quest, scared celestia (show quest marker)
+// 005 got the adv quest (show in quest log)
+// 006 killed 1 yeti
+// [...]
+// 205 killed 200 yetis
+// 206 got reward
+
+009-8,31,23,0|script|Celestia|144
+{
+ callfunc "CelestiaState";
+ if (getequipid(equip_head) == 4027) // check if yeti mask (4027) is equipped
+ goto L_YetiMask;
+ if (getequipid(equip_head) == 647) // check if Developer's Cap (647) is equipped
+ goto L_Debug;
+ if (QL_CELESTIA == 2) // check if the player has the easy quest
+ goto L_ExplainEasy;
+ if (QL_CELESTIA >= 5 && QL_CELESTIA < 206) // check if the player has the adv quest
+ goto L_ExplainAdv;
+ if (QL_CELESTIA > 1) // the player finished a quest or both
+ goto L_ThankYou;
+ goto L_Intro; // if all checks fail go to L_Intro (first meeting)
+
+L_YetiMask:
+ mes "Celestia is clearly alarmed upon seeing you."; // send message to dialog window
+ next; // require the player to press the "next" button in the dialog window
+ mes "Before you have a chance to speak, she screams,"; // every use of "mes" creates a new line
+ mes "##B\"YETI IN MY HOUSE!\"##b"; // here we created a new line to add emphasis (and ##B to make bold)
+ mes "as she jumps back a few feet.";
+ next;
+ mes "You catch a glimpse of a black bow while some kind of dark mist quickly overcomes you.";
+ next;
+ mes "You feel a sharp pain in your heart and everything fades into darkness.";
+ heal -Hp, 0; // set the current hp to 0 (kill the player)
+ set @scared_celestia, 1; // set a temporary variable (resets on log out) in the player scope (variable is stored in the player, not in the npc)
+ close; // terminate the script and require the player to press the "close" button
+
+L_Intro:
+ mes "\"Hi, my name is Celestia.\"";
+ next;
+ mes "\"I used to be a great adventurer who's hunted thousands of yeti single-handedly, though, since I moved to Hurnscald I've been hosting tea parties instead.\"";
+ next;
+ goto L_MainMenu;
+
+L_MainMenu:
+ mes "\"Are you here for this afternoon's tea party?\"";
+ if (QL_CELESTIA == 1) // check if the player can do the easy quest
+ goto L_EasyQuestMenu; // go to a special menu that has one more option to start the easy quest
+ if (QL_CELESTIA == 4) // check if the player can do the quest
+ goto L_AdvQuestMenu; // go to a special menu that has one more option to start the adv quest
+ menu // else we just show a boring menu
+ "Party! Of course I came out for the party!", L_CameForParty,
+ "I'm sorry, life is much too serious for tea.", L_SrsBsns,
+ "(Walk away)", L_InstaClose;
+
+L_EasyQuestMenu:
+ menu // here we display a special menu
+ "Party! Of course I came out for the party!", L_CameForParty,
+ "I'm sorry, life is much too serious for tea.", L_SrsBsns,
+ "Is there anything that I can do to help?", L_OfferHelp, // <= this will start the first quest
+ "(Walk away)", L_InstaClose;
+
+L_AdvQuestMenu:
+ menu // here we display a special menu
+ "Party! Of course I came out for the party!", L_CameForParty,
+ "I'm sorry, life is much too serious for tea.", L_SrsBsns,
+ "I heard you were looking for help from experienced adventurers...", L_Scared, // <= this will start the adv quest
+ "(Walk away)", L_InstaClose;
+
+L_CameForParty:
+ mes "\"Wonderful, I am happy to have you over.";
+ mes "Lets get things started with some puerh tea.\"";
+ next;
+ mes "Celestia hands you a cup filled with some type of tea that is unlike anything you have seen before.";
+ mes "It has a very dark color and an unusual aroma reminiscent of a moist forest.";
+ next;
+ mes "For a moment you wonder if Celestia might have gotten confused and tossed in a handful of forest dirt into the teapot.";
+ mes "You ponder whether or not it would be wise to drink it.";
+ menu
+ "(Drink the tea, hoping for the best)", L_DrinkTea,
+ "Uh are you sure this is fit to drink?", L_QuestionTea;
+
+L_DrinkTea:
+ mes "To your pleasant surprise the tea is actually quite good.";
+ next;
+ mes "Despite its initial dubious fragrance, the tea comes off as very smooth and mellow with a bit of natural sweetness and a touch of an earthy forest like flavour, but in a very good way.";
+ next;
+ mes "Clearly an exotic tea, with a refined flavor fit for a refined woman such as Celestia.";
+ close;
+
+L_QuestionTea:
+ mes "\"Yes, did you really think I was some kind of monster that would try to poison you in my own house?\"";
+ mes "##a(it would be way too messy anyway)##0";
+ next;
+ mes "Celestia then picks up the cup of tea and drinks it in front of you to demonstrate that it is not only harmless but also quite delectable.";
+ close;
+
+L_SrsBsns:
+ mes "\"Have it your way.\"";
+ close;
+
+L_OfferHelp:
+ mes "\"Yes there is.\"";
+ next;
+ mes "\"I am a bit frustrated by the lack of a decent grocery store in Hurnscald, and there is only so much that I can get from Hinnak and Oscar.\"";
+ next;
+ mes "\"This poses a problem as the few items that I am not able to pick up locally are required for the tea parties that I host.\"";
+ next;
+ set QL_CELESTIA, 2; // set state to "got the easy quest"
+ goto L_ExplainEasy;
+
+L_ExplainEasy:
+ npcaction 9; // clear npc dialog to make room for the item list
+ mes "\"Please go out and find these items and I will make it more than worth your time and effort.\"";
+ mes; // send a blank line (line break)
+ mes " %%E 100 ["+ getitemlink("ChocolateBar") +"]"; // use getitemlink to display a click-able item link in the dialog
+ mes " %%E 50 ["+ getitemlink("GingerBreadMan") +"]";
+ next;
+ mes "\"I really hope you can find a reliable provider for these items before it forces me to put an end to my tea parties.\"";
+ if (countitem("ChocolateBar") >= 100 && countitem("GingerBreadMan") >= 50) // check if the player has the items
+ menu // if yes then allow the player to give them
+ "I have the grocery order of Chocolate Bars and Ginger Bread Men for you.", L_GiveGroceries,
+ "I will come back later.", L_InstaClose;
+ close;
+
+L_GiveGroceries:
+ mes "Celestia smiles.";
+ next;
+ mes "\"Wonderful, I am so glad you were able to track them down.";
+ mes "That will be enough to keep me in supply for some time.\"";
+ next;
+ mes "\"Here, take this Beret.";
+ mes "I hope it looks better on you than it does on me, as it does not go well with my fine dresses.\"";
+ next;
+ mes "Celestia also hands you a heavy pouch filled with gold pieces.";
+ mes;
+ mes "["+getitemlink("Beret")+"]";
+ mes "[20,000 GP]";
+ mes "[20,000 EXP]";
+ delitem "ChocolateBar", 100; // remove chocolate bars
+ delitem "GingerBreadMan", 50; // remove ginger bread men
+ getitem "Beret", 1; // give beret
+ getexp 20000, 0; // XXX is this amount reasonable?
+ set Zeny, Zeny + 10000; // XXX is this amount reasonable?
+ set QL_CELESTIA, 3; // set the state to "completed easy quest"
+ close;
+
+L_ThankYou:
+ mes "\"Welcome back %%1\"";
+ next;
+ goto L_MainMenu;
+
+L_Scared:
+ mes "Celestia takes a close look at you and seems to be satisfied.";
+ next;
+ mes "\"Wonderful, I am glad you came out.";
+ mes "I am really concerned about the growing yeti threat.";
+ mes "There simply does not seem to be enough yeti hunters out there to keep their population from growing.\"";
+ next;
+ mes "\"To the point that a few days ago a yeti somehow managed to get inside my house, and I have never heard of one moving this far south before.\"";
+ next;
+ menu
+ "A Yeti in your house, did you kill it?", L_YetiHouse,
+ "A Yeti in your house, are you alright?", L_YetiHouse;
+
+L_YetiHouse:
+ mes "Seemingly out of nowhere Celestia pulls a black bow and a fistful of arrows from her dress.";
+ mes "\"Don't worry about me, I am able to protect myself.";
+ mes "The real concern is the safety of the children of Hurnscald, as yeti tend to prefer children.\"";
+ next;
+ mes "\"It is scary to think about how many children that yeti could have run into before stumbling into my house to meet its doom.";
+ mes "If one yeti has already made it this far south it is only a matter of time before more will follow.\"";
+ next;
+ mes "\"What disturbs me the most is that Hurnscald is a favorite trading post for adventurers, yet none of them did anything when the yeti entered town.\"";
+ next;
+ mes "\"Since they are not concerned about keeping Hurnscald safe I am taking matters into my own hands and recruiting more yeti hunters.\"";
+ next;
+ set QL_CELESTIA, 5; // set state to "got advanced quest";
+ goto L_ExplainAdv;
+
+L_ExplainAdv:
+ mes "\"Please, for the sake of the children of Hurnscald go out and ##Bslay at least 200 yetis##b to help knock down their growing numbers.\"";
+ if (QL_CELESTIA == 205) // check if the player killed 200 yetis
+ menu
+ "I have returned from the great yeti hunt.", L_YetiComplete;
+ if (QL_CELESTIA > 5) // check if at least 1 yeti killed
+ menu
+ "About those yetis...", L_Encourage;
+ close;
+
+L_YetiComplete:
+ mes "\"You are my hero!\"";
+ next;
+ mes "\"Here, take it. This [@@677|family heirloom@@] has been passed from mother to daughter for countless generations now.\"";
+ next;
+ mes "\"It pains me to let it go, as it is the only remaining trinket of my late mother, but you have proven yourself worthy of it.\"";
+ next;
+ menu
+ "Thank you, I will cherish it dearly.", L_AcceptTrinket,
+ "This token is too important, you should keep it.", L_RefuseTrinket;
+
+L_AcceptTrinket:
+ mes "\"May our path cross again.\"";
+ mes;
+ mes "["+getitemlink("HeartNecklace")+"]";
+ getitem "HeartNecklace", 1;
+ set QL_CELESTIA, 206;
+ close;
+
+L_RefuseTrinket:
+ mes "\"Really?\"";
+ next;
+ mes "\"Please at least accept this humble payment for your trouble.\"";
+ next;
+ mes "\"May out path cross again.\"";
+ mes;
+ mes "[150,000 GP]";
+ set Zeny, Zeny + 150000;
+ set QL_CELESTIA, 206;
+ close;
+
+L_Encourage:
+ mes "\"You are doing great so far.";
+ mes "Keep it up and I know you will be able to make a difference in the growing Yeti threat.\"";
+ close;
+
+L_InstaClose:
+ close;
+
+
+
+////////////// BORING DEBUG STUFF BELOW ////////////////
+L_Debug:
+ npcaction 9;
+ mes "state: " + QL_CELESTIA;
+ mes "scared: " + @scared_celestia;
+ mes "---";
+ mes "000 can not do easy quest";
+ mes "001 can do easy quest";
+ mes "002 has gotten easy quest";
+ mes "003 completed easy quest";
+ mes "004 can do adv quest";
+ mes "005 got adv quest";
+ mes "006 killed 1 yeti";
+ mes "[...]";
+ mes "205 killed 200 yeti";
+ mes "206 got adv quest reward";
+ mes "---";
+ if (debug)
+ menu
+ "restart|reset quest", L_ResetState,
+ "toggle|toggle scared", L_ToggleScared,
+ // TODO set state to [...]
+ "edit|set state manually", L_SetState,
+ "close", L_InstaClose;
+ close;
+
+L_ToggleScared:
+ set @scared_celestia, !(@scared_celestia);
+ goto L_Debug;
+
+L_ResetState:
+ set QL_CELESTIA, 0;
+ set @scared_celestia, 0;
+ npcaction 5; // force close dialog
+ warp "009-1", 72, 48;
+ end;
+
+L_SetState:
+ input @cel_state;
+ if (@cel_state >= 0 && @cel_state < 256)
+ set QL_CELESTIA, @cel_state;
+ goto L_Debug;
+}
+
+function|script|CelestiaState
+{
+ if (BaseLevel >= 40 && QL_CELESTIA == 0) // if the player is at least level 40
+ set QL_CELESTIA, 1; // show the quest marker
+ if (BaseLevel >= 90 && QL_CELESTIA == 3 && @scared_celestia) // check if level >= 90, if scared celestia and if easy quest done
+ set QL_CELESTIA, 4; // show the quest marker for the secret advanced quest
+ return;
+}
+
+009-1,74,50,0|script|Celestia Door|32767,0,0
+{
+ warp "009-8", 26, 23;
+ callfunc "CelestiaState";
+ end;
+}
+009-1,72,54,0|script|Celestia BackDoor|32767,0,0
+{
+ warp "009-8", 23, 34;
+ callfunc "CelestiaState";
+ end;
+}
diff --git a/world/map/npc/009-8/mapflags.txt b/world/map/npc/009-8/mapflags.txt
new file mode 100644
index 00000000..2883b7a4
--- /dev/null
+++ b/world/map/npc/009-8/mapflags.txt
@@ -0,0 +1,2 @@
+009-8|mapflag|town
+009-8|mapflag|resave|009-2,149,43
diff --git a/world/map/npc/016-2/_import.txt b/world/map/npc/016-2/_import.txt
new file mode 100644
index 00000000..14046995
--- /dev/null
+++ b/world/map/npc/016-2/_import.txt
@@ -0,0 +1,6 @@
+// Map 016-2: Gwendolyn's
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+map: 016-2
+npc: npc/016-2/_mobs.txt
+npc: npc/016-2/_nodes.txt
+npc: npc/016-2/_warps.txt
diff --git a/world/map/npc/016-2/_mobs.txt b/world/map/npc/016-2/_mobs.txt
new file mode 100644
index 00000000..069b9d46
--- /dev/null
+++ b/world/map/npc/016-2/_mobs.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Gwendolyn's mobs
+
diff --git a/world/map/npc/016-2/_nodes.txt b/world/map/npc/016-2/_nodes.txt
new file mode 100644
index 00000000..71dc557d
--- /dev/null
+++ b/world/map/npc/016-2/_nodes.txt
@@ -0,0 +1,4 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Gwendolyn's nodes
+
+// (no nodes)
diff --git a/world/map/npc/016-2/_warps.txt b/world/map/npc/016-2/_warps.txt
new file mode 100644
index 00000000..f72f8b85
--- /dev/null
+++ b/world/map/npc/016-2/_warps.txt
@@ -0,0 +1,5 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Gwendolyn's warps
+
+016-2,28,32|warp|-1,-1,016-1,84,54
+016-2,26,22|warp|-1,-1,016-1,84,49
diff --git a/world/map/npc/029-2/sorfina.txt b/world/map/npc/029-2/sorfina.txt
index 8919bade..7c6a589f 100644
--- a/world/map/npc/029-2/sorfina.txt
+++ b/world/map/npc/029-2/sorfina.txt
@@ -86,10 +86,10 @@ L_Carpet:
mes "[Sorfina]";
mes "\"Try to take a few steps and walk to that carpet over there.";
next;
- npcaction 2, "#Carpet";
+ camera "#Carpet";
mapmask getmask() | 4;
next;
- npcaction 3;
+ camera;
mes "Press [###keyMoveUp;] to move up, press [###keyMoveDown;] to move down, ";
mes "press [###keyMoveLeft;] to move left, press [###keyMoveRight;] to move right ";
mes " or click on the place you want to go to.\"";
@@ -100,12 +100,12 @@ L_Dresser:
mes "[Sorfina]";
mes "\"You should get dressed now.\"";
next;
- npcaction 2, "Dresser#tutorial";
+ camera "Dresser#tutorial";
mapmask getmask() | 32;
mes "\"In that dresser there are some clothes you can wear.\"";
mes "\"To interact with things in your environment or talk to NPCs you can either click on it or press [###keyTargetNPC;] to focus and [###keyTalk;] to talk/activate.\"";
next;
- npcaction 3;
+ camera;
mes "\"Now get the clothes out of the dresser.\"";
goto L_Close;
@@ -169,6 +169,7 @@ L_Explain:
"... the inventory and items?",L_Items,
"... shortcuts?",L_Shortcut,
"... what to do in Candor?",L_Aidan,
+ "... change my appearence?",L_Barber,
"... nevermind.",L_Close;
L_Walk:
@@ -241,6 +242,15 @@ L_Aidan:
mes "Talk to everybody. You can never tell when they might know something useful.\"";
goto L_Close;
+L_Barber:
+ mes "[Sorfina]";
+ mes "\"Jessie downstairs can change your appearance.\"";
+ mes "\"They will allow you to change your hair color or style as well as gender.\"";
+ next;
+ mes "\"There are a number of people across the continent that can change this for you.\"";
+ mes "\"There is no cost or limit to the number of times it can be changed.\"";
+ goto L_Close;
+
L_Hasan:
mes "[Sorfina]";
mes "\"Make yourself at home! Do you have any questions?\"";
@@ -303,12 +313,12 @@ OnTouch:
mes "[Sorfina]";
mes "\"You should get dressed now.\"";
next;
- npcaction 2, "Dresser#tutorial";
+ camera "Dresser#tutorial";
mapmask getmask() | 16;
mes "\"In that dresser there are some clothes you can wear.\"";
mes "\"To interact with things in your environment or talk to NPCs you can either click on it or press N to focus and T to talk/activate.\"";
next;
- npcaction 3;
+ camera;
mes "\"Now get the clothes out of the dresser.\"";
set QL_BEGIN, 2;
close;
diff --git a/world/map/npc/_import.txt b/world/map/npc/_import.txt
index a0c07173..3d4c89e2 100644
--- a/world/map/npc/_import.txt
+++ b/world/map/npc/_import.txt
@@ -25,6 +25,7 @@ import: npc/009-4/_import.txt
import: npc/009-5/_import.txt
import: npc/009-6/_import.txt
import: npc/009-7/_import.txt
+import: npc/009-8/_import.txt
import: npc/010-1/_import.txt
import: npc/010-2/_import.txt
import: npc/011-1/_import.txt
@@ -42,6 +43,7 @@ import: npc/014-3/_import.txt
import: npc/015-1/_import.txt
import: npc/015-3/_import.txt
import: npc/016-1/_import.txt
+import: npc/016-2/_import.txt
import: npc/017-1/_import.txt
import: npc/017-2/_import.txt
import: npc/017-3/_import.txt
diff --git a/world/map/npc/functions/DyeConfig.txt b/world/map/npc/functions/DyeConfig.txt
index e2d9640e..999f6722 100644
--- a/world/map/npc/functions/DyeConfig.txt
+++ b/world/map/npc/functions/DyeConfig.txt
@@ -8,8 +8,8 @@ OnInit:
setarray $@DYE_color_names$, "Red", "Green", "Dark Blue", "Yellow", "Light blue", "Pink", "Black", "Orange", "Purple", "Dark Green";
setarray $@DYE_colors$, "Red", "Green", "DarkBlue", "Yellow", "LightBlue", "Pink", "Black", "Orange", "Purple", "DarkGreen";
- setarray $@DYE_items$, "CottonShirt", "CottonCloth", "VNeckSweater", "Turtleneck", "CottonShorts", "CottonTrousers", "CottonSkirt", "Miniskirt", "TankTop", "ShortTankTop", "SilkRobe", "CottonHeadband", "DesertHat", "CottonBoots", "CottonGloves", "RabbitEars", "WizardHat", "BowlerHat", "BowlerHatBrown", "FineDress", "Contributor", "SorcererRed", "SorcererGreen", "SorcererDBlue", "SorcererYellow", "SorcererLBlue", "SorcererPink", "SorcererBlack", "SorcererOrange", "SorcererPurple", "SorcererDGreen", "SorcererWhite";
- setarray $@DYE_item_names$, "Cotton Shirt", "Cotton Cloth", "V-Neck Sweater", "Turtleneck Sweater", "Cotton Shorts", "Cotton Trousers", "Cotton Skirt", "Miniskirt", "Tank Top", "Short Tank Top", "Silk Robe", "Cotton Headband", "Desert Hat", "Cotton Boots", "Cotton Gloves", "Rabbit Ears", "Wizard Hat", "Bowler Hat", "Bowler Hat (brown)", "Fine Dress", "Contributor Shirt", "Sorcerer Robe (Red)", "Sorcerer Robe (Green)", "Sorcerer Robe (Dark Blue)", "Sorcerer Robe (Yellow)", "Sorcerer Robe (Light Blue)", "Sorcerer Robe (Pink)", "Sorcerer Robe (Black)", "Sorcerer Robe (Orange)", "Sorcerer Robe (Purple)", "Sorcerer Robe (Dark Green)", "Sorcerer Robe (White)";
+ setarray $@DYE_items$, "Beret", "CottonShirt", "CottonCloth", "VNeckSweater", "Turtleneck", "CottonShorts", "CottonTrousers", "CottonSkirt", "Miniskirt", "TankTop", "ShortTankTop", "SilkRobe", "CottonHeadband", "DesertHat", "CottonBoots", "CottonGloves", "RabbitEars", "WizardHat", "BowlerHat", "BowlerHatBrown", "FineDress", "Contributor", "SorcererRed", "SorcererGreen", "SorcererDBlue", "SorcererYellow", "SorcererLBlue", "SorcererPink", "SorcererBlack", "SorcererOrange", "SorcererPurple", "SorcererDGreen", "SorcererWhite";
+ setarray $@DYE_item_names$, "Beret", "Cotton Shirt", "Cotton Cloth", "V-Neck Sweater", "Turtleneck Sweater", "Cotton Shorts", "Cotton Trousers", "Cotton Skirt", "Miniskirt", "Tank Top", "Short Tank Top", "Silk Robe", "Cotton Headband", "Desert Hat", "Cotton Boots", "Cotton Gloves", "Rabbit Ears", "Wizard Hat", "Bowler Hat", "Bowler Hat (brown)", "Fine Dress", "Contributor Shirt", "Sorcerer Robe (Red)", "Sorcerer Robe (Green)", "Sorcerer Robe (Dark Blue)", "Sorcerer Robe (Yellow)", "Sorcerer Robe (Light Blue)", "Sorcerer Robe (Pink)", "Sorcerer Robe (Black)", "Sorcerer Robe (Orange)", "Sorcerer Robe (Purple)", "Sorcerer Robe (Dark Green)", "Sorcerer Robe (White)";
/******************************
Config Ends Here
******************************/
diff --git a/world/map/npc/functions/global_event_handler.txt b/world/map/npc/functions/global_event_handler.txt
index 4d453c83..ad1ba65c 100644
--- a/world/map/npc/functions/global_event_handler.txt
+++ b/world/map/npc/functions/global_event_handler.txt
@@ -13,6 +13,7 @@ OnPCLoginEvent:
callfunc "ClearVariables"; // removes / converts old variables
callfunc "DisplayMOTD"; // send the motd to the client, if enabled
callfunc "getBroadcast"; // get the scheduled broadcast, if any
+ addtimer 0, "Magic Timer::OnLogin"; // prevent cast rate abuse
// add more here
set @login_event, 2;
end;
@@ -29,7 +30,7 @@ OnPCDieEvent:
callfunc "fightclub_GoBack"; // this used by the battle master
//callfunc "fightclub_event_die"; // this is used by the 1v1 arena
set @necromancer, 0;
- set @_M_BLOCK, 0; // reset magic block on death
+ addtimer 0, "Magic Timer::OnClear"; // reset magic block on death
set @killerrid, 0; // reset killer rid
end;
diff --git a/world/map/npc/functions/hug.txt b/world/map/npc/functions/hug.txt
index a663ea1d..f1bd2637 100644
--- a/world/map/npc/functions/hug.txt
+++ b/world/map/npc/functions/hug.txt
@@ -1,24 +1,23 @@
-|script|nonmagic-hug|32767
{
explode .@name$[0], @args$, "*"; // strip the trailing *
- set @target_id, if_then_else(.@name$[0], getcharid(3, .@name$[0]), BL_ID);
+ set @target_id, if_then_else(.@name$[0] != "", getcharid(3, .@name$[0]), BL_ID);
if (@target_id < 1 || !(isloggedin(@target_id))) set @target_id, BL_ID; // fallback to self
if (.@name$[0] == "Tree" || .@name$[0] == "tree") set @target_id, .tree_id;
- set .@range, 3;
+ set .@range, if_then_else(@target_id == .tree_id, 3, 6);
if (distance(BL_ID, @target_id) >= .@range) end;
+ if (gettimetick(2) - @hugspell_time < 3) end;
+
+ set @hugspell_time, gettimetick(2);
misceffect FX_HUG, strcharinfo(0);
if (@target_id != BL_ID) misceffect FX_HUG, @target_id;
+
if (@target_id != .tree_id) end;
callfunc "QuestTreeTouch";
close;
OnInit:
set .tree_id, getnpcid("#DruidTree0#_M");
- registercmd "hug", strnpcinfo(0);
- registercmd "*hug", strnpcinfo(0);
- registercmd "*hug*", strnpcinfo(0);
- registercmd "hugs", strnpcinfo(0);
registercmd "*hugs", strnpcinfo(0);
- registercmd "*hugs*", strnpcinfo(0);
end;
}
diff --git a/world/map/npc/functions/mob_points.txt b/world/map/npc/functions/mob_points.txt
index d60c68b6..72b5ac23 100644
--- a/world/map/npc/functions/mob_points.txt
+++ b/world/map/npc/functions/mob_points.txt
@@ -184,14 +184,21 @@ L_NatureKarma:
set @value, 3;
if (@value == 0)
- goto L_Return;
+ goto L_Celestia;
callfunc "QuestSagathaAnnoy";
- goto L_Return;
+ goto L_Celestia;
L_good:
set @value, 1;
callfunc "QuestSagathaHappy";
+ goto L_Celestia;
+
+L_Celestia:
+ if (QL_CELESTIA < 5 || QL_CELESTIA >= 205 || @mobID != 1072) goto L_Return;
+ set QL_CELESTIA, QL_CELESTIA + 1;
+ if (QL_CELESTIA == 205)
+ message strcharinfo(0), "Yeti : ##3This should be enough yetis killed to please Celestia.";
goto L_Return;
L_Return:
diff --git a/world/map/npc/magic/_procedures.txt b/world/map/npc/magic/_procedures.txt
index 466d8ca8..b53aaa7c 100644
--- a/world/map/npc/magic/_procedures.txt
+++ b/world/map/npc/magic/_procedures.txt
@@ -12,6 +12,12 @@ function|script|magic_register
-|script|Magic Timer|32767
{
end;
+
+OnLogin:
+ set @_M_BLOCK, 1;
+ addtimer 10000, "Magic Timer::OnClear";
+ end;
+
OnClear:
set @_M_BLOCK, 0;
end;
@@ -21,9 +27,11 @@ OnClear:
function|script|magic_checks
{
set .@r, 0;
- if(getpvpflag(1)) set .@r, 1; // FIXME: make HIDDEN into a param
+ if(HIDDEN) set .@r, 1; // can not cast with @hide
if(@_M_BLOCK) set .@r, 2; // check if last debuff ended
if(Hp < 1) set .@r, 3; // can not cast when dead
+ if (.@r)
+ smsg SMSG_FAILURE, "Magic: Impossible to cast right now.";
return .@r;
}
diff --git a/world/map/npc/magic/level1-lesser-heal.txt b/world/map/npc/magic/level1-lesser-heal.txt
index fcd9897a..d03031d6 100644
--- a/world/map/npc/magic/level1-lesser-heal.txt
+++ b/world/map/npc/magic/level1-lesser-heal.txt
@@ -4,7 +4,8 @@
if (Sp < 6) end;
if (getskilllv(SKILL_MAGIC) < .level) end;
set @target_id, getcharid(3, @args$);
- if (@target_id < 1 || !(isloggedin(@target_id))) set @target_id, BL_ID; // fallback to self
+ if (@target_id < 1 || !(isloggedin(@target_id)) || get(INVISIBLE, @target_id) == 1)
+ set @target_id, BL_ID; // fallback to self
if (@args$ == "Mouboo" || @args$ == "mouboo") set @target_id, getnpcid("Mouboo");
set .@range, (((MATK1 + getskilllv(SKILL_MAGIC) + getskilllv(.school) + 10) / 100) + 2);
if (distance(BL_ID, @target_id) >= .@range) end;
diff --git a/world/map/npc/magic/level1-sense-spouse.txt b/world/map/npc/magic/level1-sense-spouse.txt
index 1766276c..fe95c094 100644
--- a/world/map/npc/magic/level1-sense-spouse.txt
+++ b/world/map/npc/magic/level1-sense-spouse.txt
@@ -5,7 +5,7 @@
goto L_NotMarried;
if (isloggedin(.@m) < 1)
goto L_NotOnline;
- if (sc_check(SC_HIDE, .@m) || getpvpflag(1, .@m))
+ if (sc_check(SC_HIDE, .@m) || getpvpflag(1, .@m) || get(INVISIBLE, .@m))
goto L_NotOnline;
message strcharinfo(0), "Spouse : Your spouse is... somewhere.";
end;
diff --git a/world/map/npc/magic/level2-barrier.txt b/world/map/npc/magic/level2-barrier.txt
index 3f78677b..9afd4f38 100644
--- a/world/map/npc/magic/level2-barrier.txt
+++ b/world/map/npc/magic/level2-barrier.txt
@@ -8,7 +8,8 @@
if (.@level <= 3 && countitem("SmallMushroom") >= 1) delitem "SmallMushroom", 1;
elif (.@level <= 3) end;
set @target_id, getcharid(3, @args$);
- if (@target_id < 1 || !(isloggedin(@target_id))) set @target_id, BL_ID; // fallback to self
+ if (@target_id < 1 || !(isloggedin(@target_id)) || get(INVISIBLE, @target_id) == 1)
+ set @target_id, BL_ID; // fallback to self
set @asorm_caster, BL_ID, @target_id;
if (attachrid(@target_id) != 1) end;
diff --git a/world/map/npc/magic/level2-detect-players.txt b/world/map/npc/magic/level2-detect-players.txt
index 9867b700..7335770c 100644
--- a/world/map/npc/magic/level2-detect-players.txt
+++ b/world/map/npc/magic/level2-detect-players.txt
@@ -18,7 +18,8 @@
OnPC:
if (@target_id == BL_ID) end; // do not count the caster
if (sc_check(SC_HIDE, @target_id)) end; // do not count players with anwiltyp
- if (getpvpflag(1, @target_id)) end; // do not count invisible players
+ if (getpvpflag(1, @target_id)) end; // do not count hidden GMs
+ if (get(INVISIBLE, @target_id) == 1) end; // do not count invisible GMs
if (@inwilt$ != "") set @inwilt$, @inwilt$ + ", ";
set @inwilt$, @inwilt$ + strcharinfo(0, @target_id) + if_then_else(@spellpower > 99, "("+get(BaseLevel, @target_id)+")", "");
end;
diff --git a/world/map/npc/magic/level2-flying-backpack.txt b/world/map/npc/magic/level2-flying-backpack.txt
index b87fba02..5e19468e 100644
--- a/world/map/npc/magic/level2-flying-backpack.txt
+++ b/world/map/npc/magic/level2-flying-backpack.txt
@@ -14,7 +14,8 @@
misceffect FX_MAGIC_GREEN, strcharinfo(0);
callfunc "magic_exp";
set @target_id, getcharid(3, @args$);
- if (@target_id < 1 || !(isloggedin(@target_id))) set @target_id, BL_ID; // fallback to self
+ if (@target_id < 1 || !(isloggedin(@target_id)) || get(INVISIBLE, @target_id) == 1)
+ set @target_id, BL_ID; // fallback to self
if (distance(BL_ID, @target_id) >= (@spellpower/30)+2) set @target_id, BL_ID;
if (BL_ID != @target_id) misceffect FX_MAGIC_GENERIC, @args$;
if (BL_ID == @target_id) set @args$, strcharinfo(0);
diff --git a/world/map/npc/magic/level2-happy-curse.txt b/world/map/npc/magic/level2-happy-curse.txt
index 190c7d23..dbfea17a 100644
--- a/world/map/npc/magic/level2-happy-curse.txt
+++ b/world/map/npc/magic/level2-happy-curse.txt
@@ -1,6 +1,6 @@
-|script|happy-curse|32767
{
- if(call("magic_checks")) end;
+ if(call("magic_checks")) end;
if (Sp < 13) end;
set .@level, getskilllv(.school);
if (.@level < .level) end;
@@ -8,7 +8,8 @@
if (.@level <= 3 && countitem("GingerBreadMan") >= 1) delitem "GingerBreadMan", 1;
elif (.@level <= 3) end;
set @target_id, getcharid(3, @args$);
- if (@target_id < 1 || !(isloggedin(@target_id))) set @target_id, BL_ID; // fallback to self
+ if (@target_id < 1 || !(isloggedin(@target_id)) || get(INVISIBLE, @target_id))
+ set @target_id, BL_ID; // fallback to self
set @_M_BLOCK, 1; // block casting, until the timer clears it
addtimer 1000, "Magic Timer::OnClear"; // set the new debuff
diff --git a/world/map/npc/magic/level2-hide.txt b/world/map/npc/magic/level2-hide.txt
index 1895cff1..ff67e6a5 100644
--- a/world/map/npc/magic/level2-hide.txt
+++ b/world/map/npc/magic/level2-hide.txt
@@ -8,7 +8,8 @@
if (.@level <= 3 && countitem("CottonCloth") >= 1) delitem "CottonCloth", 1;
elif (.@level <= 3) end;
set @target_id, getcharid(3, @args$);
- if (@target_id < 1 || !(isloggedin(@target_id))) set @target_id, BL_ID; // fallback to self
+ if (@target_id < 1 || !(isloggedin(@target_id)) || get(INVISIBLE, @target_id))
+ set @target_id, BL_ID; // fallback to self
set @_M_BLOCK, 1; // block casting, until the timer clears it
addtimer 1000, "Magic Timer::OnClear"; // set the new debuff
diff --git a/world/map/npc/magic/level2-lay-on-hands.txt b/world/map/npc/magic/level2-lay-on-hands.txt
index 4e3a1e9c..60c2fc12 100644
--- a/world/map/npc/magic/level2-lay-on-hands.txt
+++ b/world/map/npc/magic/level2-lay-on-hands.txt
@@ -6,7 +6,7 @@
if (getskilllv(SKILL_MAGIC) < .level) end;
if (@args$ == "Mouboo" || @args$ == "mouboo") goto L_Mouboo;
set @target_id, getcharid(3, @args$);
- if (@target_id < 1 || !(isloggedin(@target_id))) end;
+ if (@target_id < 1 || !(isloggedin(@target_id)) || get(INVISIBLE, @target_id)) end;
if (Hp <= get(MaxHp, @target_id) / 20) end; // hp needs to be > 1/20 * target hp
callfunc "adjust_spellpower";
if (distance(BL_ID, @target_id) >= (((sqrt(@spellpower)*12)+@spellpower)/100)+2) end;
diff --git a/world/map/npc/magic/level2-lightning-strike.txt b/world/map/npc/magic/level2-lightning-strike.txt
index 3032d5ab..cf30a627 100644
--- a/world/map/npc/magic/level2-lightning-strike.txt
+++ b/world/map/npc/magic/level2-lightning-strike.txt
@@ -24,7 +24,7 @@
goto L_FreeRecast;
OnAttack:
- if (target(BL_ID, @target_id, 22) != 22) L_FreeRecast; // 0x10 | 0x02 | 0x04
+ if (target(BL_ID, @target_id, 22) != 22) goto L_FreeRecast; // 0x10 | 0x02 | 0x04
set .@p, get(.max_radius, "rain") + 1;
set @ingravspell[5], @target_id; // store it because foreach overwrites it
diff --git a/world/map/npc/magic/level2-protect.txt b/world/map/npc/magic/level2-protect.txt
index e66aab3a..a3096ad7 100644
--- a/world/map/npc/magic/level2-protect.txt
+++ b/world/map/npc/magic/level2-protect.txt
@@ -8,7 +8,8 @@
if (.@level <= 3 && countitem("HardSpike") >= 1) delitem "HardSpike", 1;
elif (.@level <= 3) end;
set @target_id, getcharid(3, @args$);
- if (@target_id < 1 || !(isloggedin(@target_id))) set @target_id, BL_ID; // fallback to self
+ if (@target_id < 1 || !(isloggedin(@target_id)) || get(INVISIBLE, @target_id))
+ set @target_id, BL_ID; // fallback to self
set @betsanc_caster, BL_ID, @target_id;
if (attachrid(@target_id) != 1) end;
diff --git a/world/map/npc/magic/level3-necromancy.txt b/world/map/npc/magic/level3-necromancy.txt
index ef2d761f..57f5a6cc 100644
--- a/world/map/npc/magic/level3-necromancy.txt
+++ b/world/map/npc/magic/level3-necromancy.txt
@@ -7,7 +7,7 @@
if (getskilllv(.school) < .level) end;
if (getskilllv(SKILL_MAGIC) < .level) end;
set @target_id, getcharid(3, @args$);
- if (@target_id < 1 || !(isloggedin(@target_id))) end;
+ if (@target_id < 1 || !(isloggedin(@target_id)) || get(INVISIBLE, @target_id)) end;
if (get(Hp, @target_id) > 0) end;
if (Hp < (get(MaxHp, @target_id) / 3)) end; // hp must be at least a third of the max hp of the target
callfunc "adjust_spellpower";