diff options
Diffstat (limited to 'npc')
-rw-r--r-- | npc/001-3/_import.txt | 1 | ||||
-rw-r--r-- | npc/001-3/_warps.txt (renamed from npc/003-6/_import.txt) | 6 | ||||
-rw-r--r-- | npc/003-6/_warps.txt | 4 | ||||
-rw-r--r-- | npc/003-6/cyndala.txt | 249 | ||||
-rw-r--r-- | npc/003-6/tamiloc.txt | 83 | ||||
-rw-r--r-- | npc/006-10/_config.txt | 128 | ||||
-rw-r--r-- | npc/006-10/_import.txt | 1 | ||||
-rw-r--r-- | npc/006-10/_mobs.txt | 2 | ||||
-rw-r--r-- | npc/006-10/logic.txt | 485 | ||||
-rw-r--r-- | npc/017-3/gambler.txt | 165 | ||||
-rw-r--r-- | npc/026-2/_mobs.txt | 11 | ||||
-rw-r--r-- | npc/026-2/_warps.txt | 2 | ||||
-rw-r--r-- | npc/033-1/_import.txt | 2 | ||||
-rw-r--r-- | npc/033-1/misc.txt | 111 | ||||
-rw-r--r-- | npc/033-1/nico.txt (renamed from npc/017-3/nico.txt) | 174 | ||||
-rw-r--r-- | npc/033-1/trainer.txt (renamed from npc/020-1/trainer.txt) | 69 | ||||
-rw-r--r-- | npc/033-2/magic.txt | 5 | ||||
-rw-r--r-- | npc/config/events.txt | 105 | ||||
-rw-r--r-- | npc/config/traps.txt | 4 | ||||
-rw-r--r-- | npc/craft/price.txt | 2 | ||||
-rw-r--r-- | npc/functions/main.txt | 28 | ||||
-rw-r--r-- | npc/functions/mobpoint.txt | 2 | ||||
-rw-r--r-- | npc/items/grenade.txt | 8 |
23 files changed, 988 insertions, 659 deletions
diff --git a/npc/001-3/_import.txt b/npc/001-3/_import.txt index 2118c10..38587a4 100644 --- a/npc/001-3/_import.txt +++ b/npc/001-3/_import.txt @@ -1,3 +1,4 @@ // Map 001-3: Dark Forest // This file is generated automatically. All manually added changes will be removed when running the Converter. +"npc/001-3/_warps.txt", "npc/001-3/ctrl.txt", diff --git a/npc/003-6/_import.txt b/npc/001-3/_warps.txt index 95f4096..99c9589 100644 --- a/npc/003-6/_import.txt +++ b/npc/001-3/_warps.txt @@ -1,5 +1,3 @@ -// Map 003-6: Laundry // This file is generated automatically. All manually added changes will be removed when running the Converter. -"npc/003-6/_warps.txt", -"npc/003-6/cyndala.txt", -"npc/003-6/tamiloc.txt", +// Map 001-3: Dark Forest warps +001-3,164,32,0 warp #001-3_164_32 0,0,033-1,72,191 diff --git a/npc/003-6/_warps.txt b/npc/003-6/_warps.txt deleted file mode 100644 index d540cc5..0000000 --- a/npc/003-6/_warps.txt +++ /dev/null @@ -1,4 +0,0 @@ -// This file is generated automatically. All manually added changes will be removed when running the Converter. -// Map 003-6: Laundry warps -003-6,40,39,0 warp #003-6_40_39 0,0,003-1,112,148 -003-6,32,39,0 warp #003-6_32_39 0,0,003-1,106,148 diff --git a/npc/003-6/cyndala.txt b/npc/003-6/cyndala.txt deleted file mode 100644 index 9dd039f..0000000 --- a/npc/003-6/cyndala.txt +++ /dev/null @@ -1,249 +0,0 @@ -// TMW2 Script. -// Author: -// Saulc -// Jesusalva -// Dye Quest added by: -// Povo -// Description: -// Will be with dye functions for a while... May be wrong. Only Card2 is available per hercules rules - -// Original code from evol -// Authors: -// Reid - -003-6,33,30,0 script Cyndala NPC_FEMALE_ARGAES,{ - function explain_dyes; - function item_is_bleachable; - function remove_cards_from_item; - function give_yellow_dye; - function deny_yellow_dye; - function craft_yellow_dye; - - mesn; - mesq l("Hello, darling!"); - mes ""; - - do - { - .@q = getq(TulimsharQuest_Cyndala); - select - l("Excuse me."), - l("Could you bleach my equipment?"), - l("What can you say about dyes?"), - rif(.@q > 0, l("I would like to order some dye.")), - rif(is_staff(), "Technical problem, gimme info about an item."); - - switch (@menu) { - case 2: - remove_cards_from_item(); - break; - case 3: - explain_dyes(); - break; - case 4: - craft_yellow_dye(); - break; - case 5: - .@item = requestitemindex(); - mes "Item index selected: " + str(.@item); - mes "slots=" + str(MAX_SLOTS); - for (.@i = 0; .@i < MAX_SLOTS; .@i++) - { - mes "slot " + str(.@i) + " = " + str(getcardbyindex(.@item, .@i)); - } - mes str(@inventorylist_card1[.@item]); - mes str(YellowDye); - mes "item options:"; - for (.@i = 0; .@i < 5; .@i ++) - { - mes sprintf("%d: Option: %d, Value: %d", .@i, getitemoptionidbyindex(.@item, .@i), - getitemoptionvaluebyindex(.@item, .@i)); - } - mes "Note named items (Card1 254 and 255) have Card3 and Card4 reserved"; - break; - default: - mes ""; - mesn; - mesq l("I wish you a good time in town."); - next; - break; - } - - } while (@menu != 1); - - - closeclientdialog; - goodbye; - close; - -///////////////////////////////////////////////////////////////////////////////// -function explain_dyes { - .@q = getq(TulimsharQuest_Cyndala); - speech S_FIRST_BLANK_LINE | S_LAST_NEXT, - l("Dyes are a special kind of ink to make certain objects fancier."), - l("Once you have the appropriate colorant for the item, ##bdrag the colorant##b to the material."), - l("Example:"), - l("Drag and drop a %s in a %s, and you will obtain a %s.", getitemlink(YellowDye), - getitemlink(ArtisTankTop), getitemlink(ArtisTankTop, YellowDye)), - l("Dye cards are not the only thing which exist, but they are the coolest!"); - if (.@q < 1) { - speech S_FIRST_BLANK_LINE | S_LAST_NEXT, - l("By the way, did you know that the official color of Tulimshar is yellow?"), - l("In fact, the Tulimshar Noble District is world-renowned for crafting high-quality yellow garments!"), - l("Normally I would offer to make you some %s, but economic problems in Halinarzo have caused a shortage of supplies...", - getitemlink(YellowDye)); - if (BaseLevel > 20 && - .@q < 1) { - speech S_FIRST_BLANK_LINE | S_LAST_NEXT, - l("Wait a minute! I have an idea!"), - l("You look like you have enough experience to know your way around town..."), - l("If you can manage to gather the supplies I need, I can surely craft some %s for you!", - getitemlink(YellowDye)), - l("Of course, I do charge a nominal fee of for the service. %s GP to be exact.", fnum(50)), - l("In addition to my fee, I will also need the following items:"); - mesq l("%d/%d %s", countitem(BottleOfSewerWater), 1, getitemlink(BottleOfSewerWater)); - mesq l("%d/%d %s", countitem(PiouFeathers), 50, getitemlink(PiouFeathers)); - next; - mesq l("I am sure that an adventurer like you can gather everything in no time at all!"); - setq TulimsharQuest_Cyndala, 1; - } - } -} - -function item_is_bleachable -{ - .@item_index = getarg(0); - if (.@item_index < 0) - return false; - - // Collect the item ID - delinventorylist(); - getinventorylist(); - .@x=@inventorylist_id[.@id]; - - // Debug info - if (is_staff()) - mesf "Item Index %d (%s) - ID %d", .@item_index, - getitemlink(@inventorylist_id[.@item_index]), - @inventorylist_id[.@item_index]; - - // No duplicates - if (countitem(.@x) > 1) { - mesc l("You are carrying duplicates of the same item. Sorry, but I have no idea which one you want to tweak."), 1; - return false; - } - - // Must have a card, d'oh - if (@inventorylist_card1[.@item_index] == 0) - return false; - - return true; -} - -function remove_cards_from_item -{ - .@item_index = -1; - - speech S_FIRST_BLANK_LINE, - l("What item would you like to bleach?"); - - narrator S_FIRST_BLANK_LINE | S_LAST_NEXT, - l("You can drag and drop an item to the NPC window or select an item through your inventory."); - - .@item_index = requestitemindex(); - if (!item_is_bleachable(.@item_index)) { - speech S_LAST_NEXT, - l("You should know this, an item like this can't be bleached."); - - return; - } - .@item_id = @inventorylist_id[.@item_index]; - - speech S_LAST_NEXT, - l("Your mind is set? You will probably lose all the dyes and/or cards during on the item during this process. You're bleaching a %s by the way.", getitemlink(.@item_id)); - - switch (askyesno()) { - case ASK_YES: - speech S_FIRST_BLANK_LINE | S_LAST_NEXT, - l("Ok, let me see..."), - l("..."); - - // FIXME: Register this on picklog - if (rand2(1, 800) > readparam2(bLuk)) { - failedremovecardsindex .@item_index, 1; - logmes("Deleted Cards from item: "+.@item_id); - } else { - successremovecardsindex(.@item_index); - logmes("Removed Cards from item: "+.@item_id); - } - - // First option slot of weapon: Raises STR in 5 - // setequipoption(EQI_HAND_R, 1, VAR_STRAMOUNT, 5); - // This is an option :3 - - speech S_LAST_NEXT | S_NO_NPC_NAME, - l("..."), - l("Here it is, clean like a whistle!"); - break; - default: - speech S_FIRST_BLANK_LINE | S_LAST_NEXT, - l("Is it truly a hard choice to make?"); - break; - } - return; -} - -function give_yellow_dye { - .@q = getq(TulimsharQuest_Cyndala); - - inventoryplace YellowDye, 1, EmptyBottle, 1; - Zeny = Zeny - 50; - delitem BottleOfSewerWater, 1; - delitem PiouFeathers, 50; - - mesn; - mesq l("Here you are, you won't find a dye more yellow than this!"); - getitem(YellowDye, 1); - getitem(EmptyBottle, 1); - - if (.@q == 1) { - setq TulimsharQuest_Cyndala, 2; - getexp 80, 0; - } - return; -} - -function deny_yellow_dye { - mesn; - mesc l("I am sorry, but it does not look like you have everything. You will need to bring:"); - next; - mesc l("%d/%d %s", countitem(BottleOfSewerWater), 1, getitemlink(BottleOfSewerWater)); - mesc l("%d/%d %s", countitem(PiouFeathers), 50, getitemlink(PiouFeathers)); - mesc l("%s/%s GP", fnum(Zeny), fnum(50)); - next; - return; -} - -function craft_yellow_dye { - if (countitem(BottleOfSewerWater) < 1 || - countitem(PiouFeathers) < 50 || - Zeny < 50) - deny_yellow_dye(); - else - give_yellow_dye(); - return; -} - -OnInit: - .@npcId = getnpcid(.name$); - setunitdata(.@npcId, UDT_HEADTOP, NPCEyesD); - setunitdata(.@npcId, UDT_HEADMIDDLE, ValentineDress); //TODO - setunitdata(.@npcId, UDT_HEADBOTTOM, CottonTrousers); - setunitdata(.@npcId, UDT_WEAPON, DeepBlackBoots); // Boots - setunitdata(.@npcId, UDT_HAIRSTYLE, 16); - setunitdata(.@npcId, UDT_HAIRCOLOR, 11); - - .sex = G_FEMALE; - .distance = 5; - end; -} diff --git a/npc/003-6/tamiloc.txt b/npc/003-6/tamiloc.txt deleted file mode 100644 index 6f88398..0000000 --- a/npc/003-6/tamiloc.txt +++ /dev/null @@ -1,83 +0,0 @@ -// TMW2 scripts. -// Authors: -// Saulc -// Jesusalva -// Reid -// Travolta -// Description: -// Tamiloc is the barber. - -003-6,46,30,0 script Tamiloc NPC_ELVEN_FEMALE_ARMOR_SHOP,{ - function setRace { - clear; - setnpcdialogtitle l("%s - Modify Race", .name$); - mes l("Race") + ": " + get_race(); - next; - mes l("Please select the desired race."); - select - l("Kaizei Human"), - l("Argaes Human"), - l("Tonori Human"), - l("Elf"), - l("Orc"), - l("Raijin"), - l("Tritan"), - l("Ukar"), - l("Redy"), - l("Savior"); - switch (@menu) - { - default: - jobchange max(0, @menu-1); - } - return; - } - - - mesn; - mesq l("Hi! Do you want a hair cut?"); - - do - { - select - l("What is my current hairstyle and hair color?"), - l("I'd like to get a different style."), - l("Can you do something with my color?"), - rif(is_gm() || REBIRTH >= 5, l("I want to change my Race!")), - l("I'm fine for now, thank you."); - - switch (@menu) - { - case 1: - BarberSayStyle 3; - break; - case 2: - BarberChangeStyle; - speech S_FIRST_BLANK_LINE | S_LAST_NEXT, - l("Enjoy your new style."); - l("Anything else?"); - break; - case 3: - BarberChangeColor; - speech S_FIRST_BLANK_LINE | S_LAST_NEXT, - l("I hope you like this color."); - l("Anything else?"); - break; - case 4: - setRace; - break; - case 5: - speech S_FIRST_BLANK_LINE | S_LAST_NEXT, - l("Feel free to come visit me another time."); - - goodbye; - } - } while (1); - close; - - -OnInit: - .sex = G_FEMALE; - .distance = 5; - end; -} diff --git a/npc/006-10/_config.txt b/npc/006-10/_config.txt new file mode 100644 index 0000000..333acee --- /dev/null +++ b/npc/006-10/_config.txt @@ -0,0 +1,128 @@ +// This file is generated automatically. All manually added changes will be removed when running the Converter. +// Map 006-10: Fefe's Crypt conf + +006-10,68,50,0 script #006-10_68_50 NPC_TRAP,0,0,{ + mesn strcharinfo(0); + mesq l("Something seems off with that!"); + close; +OnTouch: +OnTouchNPC: + IronTrap(80, 15, 1); + end; +OnTimer15000: + stopnpctimer; setnpctimer 0; setnpcdisplay "#006-10_68_50", NPC_TRAP; end; +} + +006-10,70,51,0 script #006-10_70_51 NPC_TRAP,0,0,{ + mesn strcharinfo(0); + mesq l("Something seems off with that!"); + close; +OnTouch: +OnTouchNPC: + IronTrap(80, 15, 1); + end; +OnTimer15000: + stopnpctimer; setnpctimer 0; setnpcdisplay "#006-10_70_51", NPC_TRAP; end; +} + +006-10,72,49,0 script #006-10_72_49 NPC_TRAP,0,0,{ + mesn strcharinfo(0); + mesq l("Something seems off with that!"); + close; +OnTouch: +OnTouchNPC: + IronTrap(80, 15, 1); + end; +OnTimer15000: + stopnpctimer; setnpctimer 0; setnpcdisplay "#006-10_72_49", NPC_TRAP; end; +} + +006-10,73,52,0 script #006-10_73_52 NPC_TRAP,0,0,{ + mesn strcharinfo(0); + mesq l("Something seems off with that!"); + close; +OnTouch: +OnTouchNPC: + IronTrap(80, 15, 1); + end; +OnTimer15000: + stopnpctimer; setnpctimer 0; setnpcdisplay "#006-10_73_52", NPC_TRAP; end; +} + +006-10,75,49,0 script #006-10_75_49 NPC_TRAP,0,0,{ + mesn strcharinfo(0); + mesq l("Something seems off with that!"); + close; +OnTouch: +OnTouchNPC: + IronTrap(80, 15, 1); + end; +OnTimer15000: + stopnpctimer; setnpctimer 0; setnpcdisplay "#006-10_75_49", NPC_TRAP; end; +} + +006-10,50,27,0 script #006-10_50_27 NPC_TRAP,0,0,{ + mesn strcharinfo(0); + mesq l("Something seems off with that!"); + close; +OnTouch: + IronTrap(30, 15, 1); + end; +OnTimer15000: + stopnpctimer; setnpctimer 0; setnpcdisplay "#006-10_50_27", NPC_TRAP; end; +} + +006-10,50,28,0 script #006-10_50_28 NPC_TRAP,0,0,{ + mesn strcharinfo(0); + mesq l("Something seems off with that!"); + close; +OnTouch: + IronTrap(30, 15, 1); + end; +OnTimer15000: + stopnpctimer; setnpctimer 0; setnpcdisplay "#006-10_50_28", NPC_TRAP; end; +} + +006-10,52,27,0 script #006-10_52_27 NPC_TRAP,0,0,{ + mesn strcharinfo(0); + mesq l("Something seems off with that!"); + close; +OnTouch: + IronTrap(30, 15, 1); + end; +OnTimer15000: + stopnpctimer; setnpctimer 0; setnpcdisplay "#006-10_52_27", NPC_TRAP; end; +} + +006-10,52,28,0 script #006-10_52_28 NPC_TRAP,0,0,{ + mesn strcharinfo(0); + mesq l("Something seems off with that!"); + close; +OnTouch: + IronTrap(30, 15, 1); + end; +OnTimer15000: + stopnpctimer; setnpctimer 0; setnpcdisplay "#006-10_52_28", NPC_TRAP; end; +} + +006-10,54,27,0 script #006-10_54_27 NPC_TRAP,0,0,{ + mesn strcharinfo(0); + mesq l("Something seems off with that!"); + close; +OnTouch: + IronTrap(30, 15, 1); + end; +OnTimer15000: + stopnpctimer; setnpctimer 0; setnpcdisplay "#006-10_54_27", NPC_TRAP; end; +} + +006-10,54,28,0 script #006-10_54_28 NPC_TRAP,0,0,{ + mesn strcharinfo(0); + mesq l("Something seems off with that!"); + close; +OnTouch: + IronTrap(30, 15, 1); + end; +OnTimer15000: + stopnpctimer; setnpctimer 0; setnpcdisplay "#006-10_54_28", NPC_TRAP; end; +} diff --git a/npc/006-10/_import.txt b/npc/006-10/_import.txt index 4c0c28f..72ca523 100644 --- a/npc/006-10/_import.txt +++ b/npc/006-10/_import.txt @@ -1,5 +1,6 @@ // Map 006-10: Fefe's Crypt // This file is generated automatically. All manually added changes will be removed when running the Converter. +"npc/006-10/_config.txt", "npc/006-10/_mobs.txt", "npc/006-10/_warps.txt", "npc/006-10/logic.txt", diff --git a/npc/006-10/_mobs.txt b/npc/006-10/_mobs.txt index 16b27b7..9575b1a 100644 --- a/npc/006-10/_mobs.txt +++ b/npc/006-10/_mobs.txt @@ -1,3 +1,5 @@ // This file is generated automatically. All manually added changes will be removed when running the Converter. // Map 006-10: Fefe's Crypt mobs 006-10,54,44,24,24 monster Vampire Bat 1063,18,300000,30000 +006-10,73,28,3,1 monster Vicious Chest 1148,1,10000,10000 +006-10,71,26,3,1 monster Evil Chest 1149,1,10000,10000 diff --git a/npc/006-10/logic.txt b/npc/006-10/logic.txt index 601563d..f662b2d 100644 --- a/npc/006-10/logic.txt +++ b/npc/006-10/logic.txt @@ -2,129 +2,430 @@ // Author: // Jesusalva // Description: -// Crazyfefe's Shrine +// Crazyfefe's Shrine (remastered) 006-10 mapflag zone MMO +026-2 mapflag zone MMO // We need to refactor this warp system, replace NPC_HIDDEN, and include the boss +006-10,54,58,0 script Blanc NPC_BLANC,{ + if (getunittype(.blanc) >= 0) end; + mesc l("Isn't that Blanc? Should we attempt to capture him?"); + mesc l("Advised: 6+ players"), 1; + mesc l("Advised: 1+ mage, 1+ tanker, 2+ healers"), 1; + mesc l("No Time Limit"), 1; + mesc l("Enter/Leave after start: %s", b(l("YES"))), 1; + next; + select + l("Not yet."), + l("Bring it on!"), + rif(is_gm(), l("Bring me, my worst nightmare.")); + mes ""; + if (@menu == 1) { + closeclientdialog; + close; + } + if (@menu == 2) + .hard = false; + else + .hard = true; -006-10,46,45,0 script #00610WA NPC_HIDDEN,0,3,{ - end; -OnTouch: - slide 53, 46; end; -} + // Create the boss + .blanc = monster("006-10", 54, 61, "Blanc Halifax", Blanc, 1); + .@mlt = (.hard ? 15 : 10); -006-10,58,45,0 script #00610WB NPC_HIDDEN,0,3,{ - end; -OnTouch: - slide 54, 38; end; -} + // Basic attributes + .maxhp = (750000 * .@mlt / 10); // 750k ~ 1250k + setunitdata(.blanc, UDT_MAXHP, .maxhp); + setunitdata(.blanc, UDT_HP, .maxhp); + setunitdata(.blanc, UDT_ATKRANGE, (.hard ? 7 : 6)); -006-10,49,38,0 script #00610WC NPC_HIDDEN,0,3,{ - end; -OnTouch: - slide 42, 40; end; -} + // Reconfigure the AI + .@opt=getunitdata(.blanc, UDT_MODE); + // Disable looting + if (.@opt & MD_LOOTER) + .@opt=.@opt^MD_LOOTER; + // Add knockback immunity + .@opt=.@opt|MD_NOKNOCKBACK; + // Mark as boss + .@opt=.@opt|MD_BOSS; + // Mark as aggressive + .@opt=.@opt|MD_AGGRESSIVE; + .@opt=.@opt|MD_ANGRY; + // Make it more op + .@opt=.@opt|MD_DETECTOR; + .@opt=.@opt|MD_CASTSENSOR_CHASE; + .@opt=.@opt|MD_CASTSENSOR_IDLE; + .@opt=.@opt|MD_CHANGECHASE; + .@opt=.@opt|MD_CHANGETARGET_MELEE; + .@opt=.@opt|MD_CHANGETARGET_CHASE; + setunitdata(.blanc, UDT_MODE, .@opt); -006-10,55,37,0 script #00610WD NPC_HIDDEN,0,3,{ - end; -OnTouch: - slide 45, 46; end; -} + // Nerf the damage, but never miss a hit + setunitdata(.blanc, UDT_ATKMIN, 60 * .@mlt / 10); // 60~90 dmg + setunitdata(.blanc, UDT_ATKMAX, 60 * .@mlt / 10); + setunitdata(.blanc, UDT_ADELAY, 2220 / .@mlt * 10); // 2220 or 1480ms + setunitdata(.blanc, UDT_HIT, 2400); -006-10,44,39,0 script #00610WE NPC_HIDDEN,0,3,{ - end; -OnTouch: - slide 50, 38; end; -} + // Boosting the defense is not necessary + // It nerfs weapons to 40% (bows to 20%) + // Then it resists 50% of Neutral element. + // Note it is strong against Water (25% dmg) + // And weak against Fire (snow) and Wind (100% dmg) + // Otherwise, behave as Ghost element -006-10,38,39,0 script #00610WF NPC_HIDDEN,0,3,{ - end; -OnTouch: - slide 35, 35; end; -} + // Make Blanc damn hard to damage until his reinforcements appear + sc_start SC_PRESTIGE, 5000, 120000, 10000, SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE, .blanc; + // TODO: Defense and attributes are wrong? + disablenpc .name$; + initnpctimer; + closeclientdialog; + close; -006-10,30,34,0 script #00610WG NPC_HIDDEN,0,3,{ +OnRw: + dispbottom l("Mission accomplished. Well played!"); + // Mark as "done" on Mirror Lake Quest Tracker + ##01_CRQUEST = ##01_CRQUEST | MLP_CR_DEBUT; + specialeffect(FX_FANFARE, AREA, getcharid(3)); + sleep2(15000); + $@EVENT_08 = PORTHOS_UNUSED; + warp("033-1", 72, 191); end; -OnTouch: - slide 33, 25; end; -} -006-10,38,24,0 script #00610WH NPC_HIDDEN,0,3,{ +// Fail-safe Mechanism (will never happen) +OnTimer60000: + consolebug("Warning! final fail-safe mechanism triggered to Blanc."); + initnpctimer; end; -OnTouch: - slide 45, 22; end; -} +OnTimer25000: +OnTimer15000: + consolewarn("Warning, fail-safe mechanism triggered to Blanc."); +// This is the boss' core +OnTimer5000: + /* Regeneration & Defeat Loop */ + .@end = false; + // FIXME: Don't check the WHOLE map, just the current platform? + if (!getmapusers("006-10")) { + .@hp = getunitdata(.blanc, UDT_HP); + .@mh = .maxhp; + .@hp = max(.@mh, .@hp + (.@mh / 500)); // Regenerates 0.2% HP + // Fully healed, players lost + if (.@hp >= .@mh) + .@end = true; + // Regeneration + setunitdata(.blanc, UDT_HP, .@hp); + } -006-10,50,21,0 script #00610WI NPC_HIDDEN,0,3,{ - end; -OnTouch: - slide 57, 29; end; -} + /* Maybe the fight is over */ + if (!mobcount("006-10", "all") || getunittype(.blanc) < 0) { + $@EVENT_08 = PORTHOS_BUSY; + maptimer2("006-10", 10, "Blanc::OnRw"); + } + if (!mobcount("006-10", "all") || getunittype(.blanc) < 0 || .@end) { + killmonsterall("006-10"); + enablenpc .name$; + kamibroadcast("The battle is over!", "Blanc Showdown"); + .beats = 0; + stopnpctimer; + end; + } -006-10,52,28,0 script #00610WJ NPC_HIDDEN,0,3,{ - end; -OnTouch: - slide 45, 31; end; -} + /* Move platform according to HP threshold */ + .@hp = getunitdata(.blanc, UDT_HP) * 10 / .maxhp; + .@state = 9 - limit(0, .@hp, 9); // The platform ID they should be on + debugmes "HP %d / %d (%d%%) (S %d/%d) [%03d@%d]", getunitdata(.blanc, UDT_HP), .maxhp, .@hp, .@state, .state, .beats, .blanc; + if (.state != .@state) { + unittalk(.blanc, "Damn, you guys are tough! I must fall back!"); + sleep(100); + unitwarp(.blanc, "006-10", $@BLANC_X[.@state], $@BLANC_Y[.@state]); + sleep(100); + unittalk(.blanc, "Outta the way!"); + .state = .@state; + } -006-10,40,30,0 script #00610WK NPC_HIDDEN,0,3,{ - end; -OnTouch: - slide 37, 25; end; -} + /* Prepare some combat data */ + // TODO: Maybe not universal? Maybe we should impose a range? + getmapxy(.@m$, .@x, .@y, UNITTYPE_MOB, .blanc); + .@c=getunits(BL_PC, .@pcs, MAX_CYCLE_PC, .@m$); + .@mvp=0;.@rnd=0;.@def=-1; + for (.@i = 0; .@i < .@c; .@i++) { + if (!.@rnd || !rand2(.@c)) + .@rnd=.@pcs[.@i]; + if (readbattleparam(.@pcs[.@i], UDT_DEF) > .@def) { + if (readparam(Hp, .@pcs[.@i]) < 1) continue; + .@mvp=.@pcs[.@i]; + .@def=readbattleparam(.@pcs[.@i], UDT_DEF); + } + } + .beats += 1; -006-10,32,24,0 script #00610WL NPC_HIDDEN,0,3,{ - end; -OnTouch: - slide 31, 46; end; -} + /* Everyone is dead, get rid of their corpses */ + if (!.@mvp || !.@rnd) { + mapwarp("006-10", "033-1", 72, 191); + initnpctimer; + end; + } -006-10,36,45,0 script #00610WM NPC_HIDDEN,0,3,{ - end; -OnTouch: - slide 41, 46; end; -} + //debugmes "----------- Skill Loop, beat is %d", .beats % 18; + /* Decide the skill to use based on ~5s beats over 3 minutes */ + switch (.beats % 18) { + // (1/6) Summon Reinforcements (every 60s) + case 1: + case 7: + case 13: + unittalk(.blanc, "Come forth, ##BHalifax's Crew##b, do not let these fools arrest your captain!"); + specialeffect(FX_MGWARP, AREA, .blanc); // Maybe 65 would also work + sleep(1000); + // Default amount: Half players + Half magnifying HP + .@max = (getmapusers("006-10")/2) + (max(1, (11 - .@hp) / 10)/2); + // Keep boundaries: Never less than 1, never more than 10 + .@max = limit(1, .@max, 10); + for (.@i=0; .@i < .@max; .@i++) { + .@mob = any(Thug, Grenadier, Swashbuckler); + monster(.@m$, .@x, .@y, strmobinfo(1, .@mob), .@mob, 1); + } + break; + // (2/6) Tanker (~30s) + case 0: + case 4: + case 6: + case 10: + case 12: + case 16: + specialeffect(FX_ATTACK, AREA, .blanc); + sleep(1000); + if (.@hp < 3) { + // Third Attack Pattern: Judgment + unittalk(.blanc, sprintf("%s cannot stop me! ##BElectric Judgment##b!", strcharinfo(0, "cursed player", .@mvp))); + .@PW=240; .@SPW=60; .@RG=3; + } else if (.@hp < 7) { + // Second Attack Pattern: Holy Light + unittalk(.blanc, sprintf("%s, I'll show you no mercy! ##BThunder Bolt##b!", strcharinfo(0, "cursed player", .@mvp))); + .@PW=125; .@SPW=25; .@RG=1; + } else { + // First Attack Pattern: Napalm Beat + unittalk(.blanc, sprintf("This battle is over, %s! ##BThunder Neddle##b!", strcharinfo(0, "cursed player", .@mvp))); + .@PW=35; .@SPW=5; .@RG=2; + } + .@mtk = calcdmg(.blanc, .@mvp, HARM_MAGI); + .@dmg = .@mtk * .@PW / 100; + .@dsb = .@mtk * .@SPW / 100; + sleep(1000); + specialeffect(FX_LIGHTNING, AREA, .@mvp); + areaharm(.@mvp, .@RG, .@dsb, HARM_MAGI, Ele_Wind, "filter_always", BL_PC|BL_MER|BL_HOM); + harm(.@mvp, .@dmg, HARM_MAGI, Ele_Holy); + break; + // (3/6) Random Target (~60s) + case 2: + case 8: + case 14: + specialeffect(FX_SMOKE, AREA, .blanc); + sleep(1000); + .@time=rand2(18000, 36000) + 10000 - (.@hp * 1000); + // Switch between curse and disable + if (any(true,false)) { + unittalk(.blanc, sprintf("I hereby ##Bcurse##b you, %s!", strcharinfo(0, "cursed player", .@rnd))); + sc_start(SC_CURSE, .@time, 1, 10000, SCFLAG_FIXEDRATE, .@rnd); + } else { + unittalk(.blanc, sprintf("I shall ##Bdisable##b you, %s!", strcharinfo(0, "cursed player", .@rnd))); + sc_start(SC_BLIND, .@time / 2, 1, 10000, SCFLAG_FIXEDRATE, .@rnd); + sc_start(SC_SILENCE, .@time / 2, 1, 10000, SCFLAG_FIXEDRATE, .@rnd); + } + // Second pattern: Bleeding ON + if (.@hp < 7) { + sc_start(SC_BLOODING, 10000, 1, 9000-(.@hp*1000), SCFLAG_FIXEDRATE, .@rnd); + } + specialeffect(FX_LIGHTNING, AREA, .@rnd); + break; + // (4/6) Traps (~60s) + case 3: + case 9: + case 15: + // Determine if there'll be 4 or 2 AoE explosions + .@extra = (.@hp < 5 || .hard); + // Coordinates are between origin and Blanc + // ID 3 and ID 6 were disabled - the platforms are small + .@mx=$@BLANC_X[.@state]; + .@my=$@BLANC_Y[.@state]; + .@x1=rand2(.@mx, .@x); .@x2=rand2(.@mx, .@x); + .@y1=rand2(.@my, .@y); .@y2=rand2(.@my, .@y); + // TODO: Maybe replace Dummy/EnergyBall with an invisible monster? + .@t1=monster("006-10", .@x1, .@y1, "", EnergyBall, 1); + .@t2=monster("006-10", .@x2, .@y2, "", EnergyBall, 1); + specialeffect(67, AREA, .@t1); + specialeffect(67, AREA, .@t2); + immortal(.@t1); immortal(.@t2); + if (.@extra) { + .@x4=rand2(.@mx, .@x); .@x5=rand2(.@mx, .@x); + .@y4=rand2(.@my, .@y); .@y5=rand2(.@my, .@y); + .@t4=monster("006-10", .@x1, .@y1, "", EnergyBall, 1); + .@t5=monster("006-10", .@x2, .@y2, "", EnergyBall, 1); + specialeffect(67, AREA, .@t4); + specialeffect(67, AREA, .@t5); + immortal(.@t4); immortal(.@t5); + } + sleep(1500); + // This is just a prop + specialeffect(FX_LIGHTNING, AREA, .@t1); + specialeffect(FX_LIGHTNING, AREA, .@t2); + if (.@extra) { + specialeffect(FX_LIGHTNING, AREA, .@t4); + specialeffect(FX_LIGHTNING, AREA, .@t5); + } + sleep(500); + specialeffect(FX_CRITICAL, AREA, .@t1); + specialeffect(FX_CRITICAL, AREA, .@t2); + if (.@extra) { + specialeffect(FX_CRITICAL, AREA, .@t4); + specialeffect(FX_CRITICAL, AREA, .@t5); + } + areaharm(.@t1, 1, 450, HARM_MISC, Ele_Neutral, "filter_always", BL_PC|BL_MER|BL_HOM); + areaharm(.@t2, 1, 450, HARM_MISC, Ele_Neutral, "filter_always", BL_PC|BL_MER|BL_HOM); + if (.@extra) { + areaharm(.@t4, 1, 450, HARM_MISC, Ele_Neutral, "filter_always", BL_PC|BL_MER|BL_HOM); + areaharm(.@t5, 1, 450, HARM_MISC, Ele_Neutral, "filter_always", BL_PC|BL_MER|BL_HOM); + } + sleep(1000); + // FIXME: M+ fails to remove them, need @refresh (maybe @refreshall?) + // NOTE: The effect Nº 67 (halo circle) is also not cleaned by M+ + unitkill(.@t1); unitkill(.@t2); + if (.@extra) { + unitkill(.@t4); unitkill(.@t5); + } + break; + // (5/6) Weak AOE (~60s) + case 5: + case 11: + case 17: + specialeffect(60, AREA, .blanc); + sleep(500); + switch (rand2(3)) { + case 1: + unittalk(.blanc, "Cease! I shall ##Bpoison##b all of you!"); + .@sc = (.@hp < 1 ? SC_DPOISON : SC_POISON); + break; + case 2: + unittalk(.blanc, "Cease! I shall ##Bhurt##b all of you!"); + .@sc = SC_BLOODING; + break; + case 3: + unittalk(.blanc, "Cease! I shall ##Bsilence##b all of you!"); + .@sc = SC_SILENCE; + break; + default: + unittalk(.blanc, "Cease! I shall ##Bcripple##b all of you!"); + .@sc = SC_BLIND; + break; + } + areasc((.hard ? 7 : 5), 30000, .@sc, BL_PC|BL_HOM|BL_MER, 1, "filter_always", .blanc, 95000); + areaharm(.blanc, (.hard ? 7 : 5), 100, HARM_MAGI, Ele_Wind, "filter_always", BL_PC|BL_MER|BL_HOM); + // Forces everyone to sit, for cosmetic effect + areasc(18, 500, SC_BANANA_BOMB_SITDOWN_POSTDELAY, BL_PC|BL_HOM|BL_MER, 1, "filter_always", .blanc); + break; + } + // Strong AOE: Every 3 minutes (case = 0) + // Stalls all other skills for a while + if (.beats % 18 == 0) { + specialeffect(66, AREA, .blanc); + unittalk(.blanc, "I am Blanc, Halifax's captain!"); + sleep((.hard ? 1000 : 1500)); + specialeffect(700, AREA, .blanc); + unittalk(.blanc, "I'll never be caught by your ilk alive!"); + sleep((.hard ? 1000 : 1500)); + specialeffect(700, AREA, .blanc); + if (.@hp < 3) { + unittalk(.blanc, "Perish! ##BRage of Hungry Thunder##b!"); + .@dmg=rand2(900, 1100); + areasc3((.hard ? 5 : 4), 11000, SC_STOMACHACHE, BL_PC|BL_HOM|BL_MER, (.hard ? 20 : 15), "filter_always", .blanc, 6000); + areasc(6, 10000, SC_BLIND, BL_PC|BL_HOM|BL_MER, 1, "filter_always", .blanc, 2000); + } else if (.@hp < 7) { + unittalk(.blanc, "Perish! ##BVoracious Thunder Storm##b!"); + .@dmg=rand2(650, 900); + areasc3((.hard ? 4 : 3), 11000, SC_STOMACHACHE, BL_PC|BL_HOM|BL_MER, (.hard ? 15 : 10), "filter_always", .blanc, 4500); + } else { + unittalk(.blanc, "Perish! ##BEletric Needles##b!"); + .@dmg=rand2(400, 650); + } + /* Three blocks */ + specialeffect(66, AREA, .blanc); + areaharm(.blanc, (.hard ? 7 : 5), .@dmg, HARM_MAGI, Ele_Fire, "filter_always", BL_PC|BL_MER|BL_HOM); + sleep(500); + specialeffect(66, AREA, .blanc); + areaharm(.blanc, (.hard ? 15 : 10), .@dmg, HARM_MAGI, Ele_Holy, "filter_always", BL_PC|BL_MER|BL_HOM); + sleep(500); + specialeffect(66, AREA, .blanc); + specialeffect(FX_LIGHTNING, AREA, .blanc); + areaharm(.blanc, (.hard ? 24 : 18), .@dmg, HARM_MAGI, Ele_Wind, "filter_always", BL_PC|BL_MER|BL_HOM); + areasc((.hard ? 24 : 18), .@dmg*rand2(50, 100), SC_FROSTMISTY, BL_PC|BL_HOM|BL_MER, 1, "filter_always", .blanc, 10001 - (.@hp * 1000)); // SC_FROSTMISTY - General crippling + } -006-10,30,45,0 script #00610WN NPC_HIDDEN,0,3,{ - end; -OnTouch: - slide 57, 46; end; -} -// -------------------------------------------------- -006-10,52,45,0 script #00610WO NPC_HIDDEN,0,3,{ + initnpctimer; end; -OnTouch: - slide 45, 46; end; -} -006-10,40,45,0 script #00610WP NPC_HIDDEN,0,3,{ - end; -OnTouch: - slide 35, 35; end; -} +OnInit: + .distance = 4; + .beats = 0; // Skill cooldown timer + .hard = 0; // Hard mode (for GMs) + .blanc = 0; // Boss GID + .state = 0; // Current platform ID + .maxhp = 0; // Blanc's max HP (getunitdata(.blanc, UDT_MAXHP) is broken) -006-10,36,34,0 script #00610WQ NPC_HIDDEN,0,3,{ - end; -OnTouch: - slide 40, 40; end; -} + // TODO: In general, we have no idea of platforms size + setarray $@BLANC_X, 53, 72, 71, 72, 52, 36, 34, 35, 35, 52; + setarray $@BLANC_Y, 63, 67, 53, 30, 30, 27, 48, 36, 63, 36; -006-10,58,28,0 script #00610WR NPC_HIDDEN,0,3,{ + // .@index = miller_rand(.@state, getcharid(0), 10); end; -OnTouch: - slide 49, 22; end; } -006-10,46,30,0 script #00610WS NPC_HIDDEN,0,3,{ +// Below be the warp system. Rightmost forwards, leftmost rewinds. + +006-10,51,64,0 script #00610XX NPC_HIDDEN,1,0,{ end; OnTouch: - slide 53, 29; end; + // Now... WTF are we on miller rand? + if (!@miller_fix) { + for (.@i=0;.@i<10;.@i++) { + if (miller_rand(.@i, getcharid(0), 10) == 0) { + @miller_fix = .@i; + break; + } + } + } + // Set "@state" properly + @state = @miller_fix; + end; } - -006-10,44,21,0 script #00610WT NPC_HIDDEN,0,3,{ +006-10,57,61,0 script #00610WA+ NPC_FANCY_CIRCLE,0,0,{ end; OnTouch: - slide 37, 25; end; + // All portals are the same, anyway + if (compare(strnpcinfo(2), "+")) + @state = ((@state+1) % 10); // Technically, the loop is not needed + else + @state = ((@state-1) % 10); // Technically, this loop is not needed + .@index = miller_rand(@state, getcharid(0), 10); + slide $@BLANC_X[.@index], $@BLANC_Y[.@index]; + end; } +// NOTE: Vampire Bats are aggressive, they're tasked in disposing non-fighters +006-10,49,60,0 duplicate(#00610WA+) #00610WA- NPC_FANCY_CIRCLE,0,0 +006-10,75,65,0 duplicate(#00610WA+) #00610WB+ NPC_FANCY_CIRCLE,0,0 +006-10,68,64,0 duplicate(#00610WA+) #00610WB- NPC_FANCY_CIRCLE,0,0 +006-10,75,50,0 duplicate(#00610WA+) #00610WC+ NPC_FANCY_CIRCLE,0,0 +006-10,67,49,0 duplicate(#00610WA+) #00610WC- NPC_FANCY_CIRCLE,0,0 +006-10,76,27,0 duplicate(#00610WA+) #00610WD+ NPC_FANCY_CIRCLE,0,0 +006-10,68,26,0 duplicate(#00610WA+) #00610WD- NPC_FANCY_CIRCLE,0,0 +006-10,56,27,0 duplicate(#00610WA+) #00610WE+ NPC_FANCY_CIRCLE,0,0 +006-10,48,26,0 duplicate(#00610WA+) #00610WE- NPC_FANCY_CIRCLE,0,0 +006-10,40,24,0 duplicate(#00610WA+) #00610WF+ NPC_FANCY_CIRCLE,0,0 +006-10,32,24,0 duplicate(#00610WA+) #00610WF- NPC_FANCY_CIRCLE,0,0 +006-10,37,51,0 duplicate(#00610WA+) #00610WG+ NPC_FANCY_CIRCLE,0,0 +006-10,30,45,0 duplicate(#00610WA+) #00610WG- NPC_FANCY_CIRCLE,0,0 +006-10,41,33,0 duplicate(#00610WA+) #00610WH+ NPC_FANCY_CIRCLE,0,0 +006-10,30,33,0 duplicate(#00610WA+) #00610WH- NPC_FANCY_CIRCLE,0,0 +006-10,44,63,0 duplicate(#00610WA+) #00610WI+ NPC_FANCY_CIRCLE,0,0 +006-10,35,57,0 duplicate(#00610WA+) #00610WI- NPC_FANCY_CIRCLE,0,0 +006-10,55,37,0 duplicate(#00610WA+) #00610WJ+ NPC_FANCY_CIRCLE,0,0 +006-10,49,37,0 duplicate(#00610WA+) #00610WJ- NPC_FANCY_CIRCLE,0,0 diff --git a/npc/017-3/gambler.txt b/npc/017-3/gambler.txt deleted file mode 100644 index 7d5c848..0000000 --- a/npc/017-3/gambler.txt +++ /dev/null @@ -1,165 +0,0 @@ -// TMW2 Scripts -// Author: -// Jesusalva -// Description: -// Gambler: Can you remember the sequence? - -017-3,23,38,0 script Gambler#017-3 NPC_PLAYER,{ - function colorname { - switch (getarg(0)) { - case 1: - return "Green"; break; - case 2: - return "Blue"; break; - case 3: - return "Red"; break; - case 4: - return "Yellow"; break; - case 5: - return "Exit"; break; - default: - return l("ERROR: %d", getarg(0)); - } - } - - goto L_Menu; - -L_Menu: - showavatar NPC_FLOPPED_NOBLEMAN; - mesn; - mesc l("Gambling is for the weak, I offer you a true game!"); - mesc l("You need %d %s. I'll start showing you sequences of colors.", .price, getitemlink(CasinoCoins)); - mesc l("The farther you go on the sequence, the better the payout!"); - next; - menu - rif(countitem(CasinoCoins) >= .price, l("Let's play!")), L_Start, - l("Information"), L_Info, - l("Leave"), -; - close; - -L_Info: - mes ""; - mesc l("Rules:"); - mesc l("A color sequence will be displayed on the avatar frame."); - mesc l("You must then repeat the sequence at the board which will show."); - next; - mesc l("Prizes:"); - mesc l("You'll get %d GP every time you finish the sequence.", .prize); - next; - mesc l("Winning Strike Prizes:"); - mesc l("Every %d sequences, you'll get a %s!", 10, getitemlink(StrangeCoin)); - mesc l("If you get %d sequence, you'll get a %s!", 30, getitemlink(BronzeGift)); - mesc l("If you get %d sequence, you'll get a %s!", 50, getitemlink(SilverGift)); - //mesc l("If you get %d sequence, you'll get a %s!", 50, getitemlink(GoldenGift)); - next; - goto L_Menu; - - -L_Start: - showavatar AVATAR_SEQBOARD; - mesc l("Pay attention to the sequence!"); - next; - delitem CasinoCoins, .price; - deletearray(@sequence); - @streak=0; - -L_Sequence: - // Configure - setnpcdialogtitle l("Memorize the sequence!"); - array_push(@sequence, 1+rand2(4)); - sleep2(1000); - - // Display - freeloop(true); - for (.@i=0;.@i < getarraysize(@sequence);.@i++) { - showavatar 1200+@sequence[.@i]; - sleep2(1200-(@streak*20)); - } - freeloop(false); - - // Request - setnpcdialogtitle l("What was the sequence?"); - showavatar AVATAR_SEQBOARD; - sleep2(500); - - for (.@i=0;.@i < getarraysize(@sequence);.@i++) { - setskin "seqboard"; - select - l("Green"), - l("Blue"), - l("Red"), - l("Yellow"), - l("Exit"); - .@ans=@menu; - setskin ""; - mes ""; - mes l("%s", colorname(.@ans)); - //next; - setnpcdialogtitle strnpcinfo(1); - - // Exit - if (.@ans == 5) - goto L_Close; - - // Wrong reply - if (.@ans != @sequence[.@i]) - goto L_Wrong; - // Correct! - } - mes ""; - showavatar AVATAR_SEQBOARD_WELL; - - // Seems like everything is/was correct - mesn; - mesq l("Congratulations! Everything was correct!"); - Zeny+=.prize; - @streak+=1; - - // Winning Streak - if (@streak % 10 == 0) - getitem StrangeCoin, 1; - if (@streak == 30) - getitem BronzeGift, 1; - if (@streak == 50) - getitem SilverGift, 1; - mesc l("Your current win streak is @@!", @streak); - next; - // Game over - if (@streak == 50) - goto L_Close; - // Otherwise, go ahead - mesn; - mesc l("Continue?"), 1; - next; - if (askyesno() == ASK_YES) - goto L_Sequence; - goto L_Close; - -L_Wrong: - showavatar AVATAR_SEQBOARD_FAIL; - mesn; - mesq l("Oh no... That is wrong! %%3"); - next; - mesn; - mesq l("Better luck next time!"); - close; - -L_Close: - mesn; - mesq l("Thanks for playing!"); - close; - -OnInit: - .@npcId = getnpcid(.name$); - setunitdata(.@npcId, UDT_HEADTOP, TopHat); - setunitdata(.@npcId, UDT_HEADMIDDLE, CreasedShirt); - setunitdata(.@npcId, UDT_HEADBOTTOM, JeansShorts); - - .sex = G_MALE; - .distance = 4; - .price = 5; - .prize = 50; - npcsit; - end; -} - diff --git a/npc/026-2/_mobs.txt b/npc/026-2/_mobs.txt index a5b827f..bcaa771 100644 --- a/npc/026-2/_mobs.txt +++ b/npc/026-2/_mobs.txt @@ -1,7 +1,8 @@ // This file is generated automatically. All manually added changes will be removed when running the Converter. // Map 026-2: Count's Fortress mobs -026-2,61,35,39,17 monster Piou Knight 1434,8,300000,30000 -026-2,62,81,39,17 monster Grenadier 1444,18,300000,30000 -026-2,70,57,39,17 monster Swashbuckler 1443,18,300000,30000 -026-2,57,59,39,27 monster Thug 1442,18,300000,30000 -026-2,61,57,20,45 monster Revolver Shooter 1208,18,300000,30000 +026-2,61,35,39,17 monster Piou Knight 1434,6,300000,30000 +026-2,62,81,39,17 monster Grenadier 1444,10,300000,30000 +026-2,70,57,39,17 monster Swashbuckler 1443,10,300000,30000 +026-2,57,59,39,27 monster Thug 1442,10,300000,30000 +026-2,61,58,20,43 monster Revolver Shooter 1208,11,300000,30000 +026-2,61,23,39,7 monster Grenadier 1444,3,300000,30000 diff --git a/npc/026-2/_warps.txt b/npc/026-2/_warps.txt index 98b9d22..f15a3bf 100644 --- a/npc/026-2/_warps.txt +++ b/npc/026-2/_warps.txt @@ -1,5 +1,5 @@ // This file is generated automatically. All manually added changes will be removed when running the Converter. // Map 026-2: Count's Fortress warps -026-2,32,98,0 warp #026-2_32_98 0,0,001-3,118,114 +026-2,32,97,0 warp #026-2_32_97 0,0,001-3,118,114 026-2,86,26,0 warp #026-2_86_26 0,0,006-10,52,64 026-2,29,26,0 warp #026-2_29_26 0,0,006-10,51,64 diff --git a/npc/033-1/_import.txt b/npc/033-1/_import.txt index 90c62d6..bd2a012 100644 --- a/npc/033-1/_import.txt +++ b/npc/033-1/_import.txt @@ -2,3 +2,5 @@ // This file is generated automatically. All manually added changes will be removed when running the Converter. "npc/033-1/_warps.txt", "npc/033-1/misc.txt", +"npc/033-1/nico.txt", +"npc/033-1/trainer.txt", diff --git a/npc/033-1/misc.txt b/npc/033-1/misc.txt index f57cc03..608cc1f 100644 --- a/npc/033-1/misc.txt +++ b/npc/033-1/misc.txt @@ -44,21 +44,69 @@ OnTouch: function script SetPorthosPortal { .@id = getarg(0); mesn l("Portal %02d", .@id); - mes l("Do you want to activate an event?"); + switch (.@id) { + case 6: + mesc l("Event: Moubootaur Showdown"), 1; break; + case 7: + mesc l("Warp: TMW Classic"), 1; close; + case 8: + mesc l("Event: Blanc's Showdown"), 1; break; + case 9: + mesc l("Warp: TMW ML"), 1; close; + default: + mesc l("This portal has not been coded yet."); close; + } next; - select - l("Cancel"), - l("Moubootaur Showdown"); - mes ""; - switch (@menu) { - case 2: + mes l("Do you want to activate the event?"); + if (askyesno() == ASK_NO) close; + switch (.@id) { + case 6: setd(sprintf("$@EVENT_%02d", .@id), PORTHOS_ACTIVE); setd(sprintf("$@EVENT_%02d_M$", .@id), "001-13-2"); setd(sprintf("$@EVENT_%02d_X", .@id), 47); setd(sprintf("$@EVENT_%02d_Y", .@id), 52); break; + case 8: + // Clean-up 001-3 in case there are already mobs there + killmonsterall("001-3"); + // Environment Monsters, they do not respawn + .@m$="001-3"; + // Thematic mobs + areamonster(.@m$, 20, 20, getmapinfo(MAPINFO_SIZE_X, .@m$), getmapinfo(MAPINFO_SIZE_Y, .@m$), strmobinfo(1, Thug), Thug, 150); + areamonster(.@m$, 20, 20, getmapinfo(MAPINFO_SIZE_X, .@m$), getmapinfo(MAPINFO_SIZE_Y, .@m$), strmobinfo(1, Swashbuckler), Swashbuckler, 150); + areamonster(.@m$, 20, 20, getmapinfo(MAPINFO_SIZE_X, .@m$), getmapinfo(MAPINFO_SIZE_Y, .@m$), strmobinfo(1, Grenadier), Grenadier, 140); + areamonster(.@m$, 20, 20, getmapinfo(MAPINFO_SIZE_X, .@m$), getmapinfo(MAPINFO_SIZE_Y, .@m$), strmobinfo(1, OceanPirate), OceanPirate, 100); + // There's `Marley` but they're listed as boss + // We'll likely use them in the mazes, as your target? + // Environment runt + areamonster(.@m$, 20, 20, getmapinfo(MAPINFO_SIZE_X, .@m$), getmapinfo(MAPINFO_SIZE_Y, .@m$), strmobinfo(1, DeathCat), DeathCat, 100); + areamonster(.@m$, 20, 20, getmapinfo(MAPINFO_SIZE_X, .@m$), getmapinfo(MAPINFO_SIZE_Y, .@m$), strmobinfo(1, BlackSlime), BlackSlime, 90); + areamonster(.@m$, 20, 20, getmapinfo(MAPINFO_SIZE_X, .@m$), getmapinfo(MAPINFO_SIZE_Y, .@m$), strmobinfo(1, SmallFrog), SmallFrog, 80); + areamonster(.@m$, 20, 20, getmapinfo(MAPINFO_SIZE_X, .@m$), getmapinfo(MAPINFO_SIZE_Y, .@m$), strmobinfo(1, BigFrog), BigFrog, 80); + // The lower tier + areamonster(.@m$, 20, 20, getmapinfo(MAPINFO_SIZE_X, .@m$), getmapinfo(MAPINFO_SIZE_Y, .@m$), strmobinfo(1, WickedMushroom), WickedMushroom, 50); + areamonster(.@m$, 20, 20, getmapinfo(MAPINFO_SIZE_X, .@m$), getmapinfo(MAPINFO_SIZE_Y, .@m$), strmobinfo(1, Forain), Forain, 50); + areamonster(.@m$, 20, 20, getmapinfo(MAPINFO_SIZE_X, .@m$), getmapinfo(MAPINFO_SIZE_Y, .@m$), strmobinfo(1, Assassin), Assassin, 50); + // The mid tier + areamonster(.@m$, 20, 20, getmapinfo(MAPINFO_SIZE_X, .@m$), getmapinfo(MAPINFO_SIZE_Y, .@m$), strmobinfo(1, HoodedNinja), HoodedNinja, 30); + // The high tier + areamonster(.@m$, 20, 20, getmapinfo(MAPINFO_SIZE_X, .@m$), getmapinfo(MAPINFO_SIZE_Y, .@m$), strmobinfo(1, BlackSlimeMother), BlackSlimeMother, 10); + // The boss level spawns + areamonster(.@m$, 20, 20, getmapinfo(MAPINFO_SIZE_X, .@m$), getmapinfo(MAPINFO_SIZE_Y, .@m$), strmobinfo(1, Reaper), Reaper, 2); + areamonster(.@m$, 20, 20, getmapinfo(MAPINFO_SIZE_X, .@m$), getmapinfo(MAPINFO_SIZE_Y, .@m$), strmobinfo(1, NightmareDragon), NightmareDragon, 2); + areamonster(.@m$, 20, 20, getmapinfo(MAPINFO_SIZE_X, .@m$), getmapinfo(MAPINFO_SIZE_Y, .@m$), strmobinfo(1, Mandragora), Mandragora, 1); + areamonster(.@m$, 20, 20, getmapinfo(MAPINFO_SIZE_X, .@m$), getmapinfo(MAPINFO_SIZE_Y, .@m$), strmobinfo(1, SiegeTower), SiegeTower, 1); + areamonster(.@m$, 20, 20, getmapinfo(MAPINFO_SIZE_X, .@m$), getmapinfo(MAPINFO_SIZE_Y, .@m$), strmobinfo(1, Golem), Golem, 2); + areamonster(.@m$, 20, 20, getmapinfo(MAPINFO_SIZE_X, .@m$), getmapinfo(MAPINFO_SIZE_Y, .@m$), strmobinfo(1, ShadowTortuga), ShadowTortuga, 1); + // Set everything up + setd(sprintf("$@EVENT_%02d", .@id), PORTHOS_ACTIVE); + setd(sprintf("$@EVENT_%02d_M$", .@id), "001-3"); + setd(sprintf("$@EVENT_%02d_X", .@id), 164); + setd(sprintf("$@EVENT_%02d_Y", .@id), 33); + kamibroadcast("Blanc's Showdown was enabled."); + break; default: - mes l("Ok."); + mes l("Error."); break; } close; @@ -66,25 +114,40 @@ function script SetPorthosPortal { } -033-1,72,190,0 script #Porthos01 NPC_NO_SPRITE,0,0,{ +// Shortcut to TMW Classic? +033-1,85,227,0 script #Porthos07 NPC_NO_SPRITE,0,0,{ + end; +OnTouch: + slide 85, 228; + mes l("Do you want to visit The Mana World: Classic?"); + next; + if (askyesno() == ASK_YES) + MirrorLakeSendTo(MLP_TMW, 0); + closeclientdialog; + end; +} + +// Event: Blanc's Manhunt +033-1,72,190,0 script #Porthos08 NPC_NO_SPRITE,0,0,{ end; OnTouch: - if ($@EVENT_01 == PORTHOS_BUSY) { + if ($@EVENT_06 == PORTHOS_BUSY) { dispbottom l("This portal is currently busy - an event must be in progress."); end; } - if ($@EVENT_01 == PORTHOS_UNUSED) { + // 001-3 portals + if ($@EVENT_08 == PORTHOS_UNUSED) { if (is_admin() || is_master()) - SetPorthosPortal(1); + SetPorthosPortal(8); dispbottom l("This portal is not currently active."); end; } - warp $@EVENT_01_M$, $@EVENT_01_X, $@EVENT_01_Y; + warp $@EVENT_08_M$, $@EVENT_08_X, $@EVENT_08_Y; end; } // Shortcut to Moubootaur Legends? -033-1,31,155,0 script #Porthos02 NPC_NO_SPRITE,0,0,{ +033-1,31,155,0 script #Porthos09 NPC_NO_SPRITE,0,0,{ end; OnTouch: slide 31, 156; @@ -96,3 +159,23 @@ OnTouch: end; } +// TODO: Event: Zax De'Kagen Showdown +// Event: Moubootaur Showdown +// This is a draft in npc/config/events.txt +033-1,154,238,0 script #Porthos06 NPC_NO_SPRITE,0,0,{ + end; +OnTouch: + if ($@EVENT_06 == PORTHOS_BUSY) { + dispbottom l("This portal is currently busy - an event must be in progress."); + end; + } + if ($@EVENT_06 == PORTHOS_UNUSED) { + if (is_admin() || is_master()) + SetPorthosPortal(6); + dispbottom l("This portal is not currently active."); + end; + } + warp $@EVENT_06_M$, $@EVENT_06_X, $@EVENT_06_Y; + end; +} + diff --git a/npc/017-3/nico.txt b/npc/033-1/nico.txt index 19dd79e..e656f4b 100644 --- a/npc/017-3/nico.txt +++ b/npc/033-1/nico.txt @@ -4,7 +4,9 @@ // Description: // Arcmage Cards Enhancer -017-3,37,84,0 script Nico Goethe NPC_PLAYER,{ +033-1,157,89,0 script Nico Goethe NPC_PLAYER,{ + function colorname; + function gameinfo; mesn; mesq l("My name is Nico Goethe, an %s card player.", "[@@https://arcmage.org|Arcmage@@]"); next; @@ -13,6 +15,7 @@ next; mesn; mesq l("However, I am still up for trading cards, if you wish."); + mesc l("%s discreetly point out that cards only works well in Moubootaur Legends weapons, but this depends on your origin server.", .name$); next; goto L_Main; @@ -20,6 +23,7 @@ L_Main: select l("Trade a card"), l("Evolve a card"), + l("Remove a card"), l("Lets play!"), l("Bye."); mes ""; @@ -269,11 +273,49 @@ L_Main: break; } break; - // TODO: Play minigame + // Remove a card case 3: + mesc l("You can drag and drop an item to the NPC window or select an item through your inventory."); + + delinventorylist(); + getinventorylist(); + .@item_index = requestitemindex(); + .@item_id = @inventorylist_id[.@item_index]; + + mesn; + mesq l("Your mind is set? You will probably lose all the dyes and/or cards during on the item during this process. You're bleaching a %s by the way, and THERE ARE NO REFUNDS even if the item go ablaze.", getitemlink(.@item_id)); + + if (askyesno() == ASK_YES) { + mesn; + mesq l("Sure, I'll be done in a jiff."); + next; + successremovecardsindex(.@item_index); // *should* return the card + mesn; + mesq l("Here it is, clean like a whistle!"); + } else { + mesn; + mesq l("Is it truly a hard choice to make?"); + } + next; + break; + // Play minigame + case 4: mesn; mesq l("...Are you trying to troll me?"); next; + mesn; + mesq l("Well, I can't offer you an %s match, but do you want to play something else? I would charge %d GP for a match.", "[@@https://arcmage.org|Arcmage@@]", .price); + next; + if (askyesno() == ASK_NO) { + mesn; + mesq l("Suit yourself."); + next; + break; + } + gameinfo(); + mesn; + mesq l("Ready to begin?"); + if (askyesno() == ASK_YES) goto L_Start; break; // Leave default: @@ -284,6 +326,132 @@ L_Main: } goto L_Main; +function colorname { + switch (getarg(0)) { + case 1: + return "Green"; break; + case 2: + return "Blue"; break; + case 3: + return "Red"; break; + case 4: + return "Yellow"; break; + case 5: + return "Exit"; break; + default: + return l("ERROR: %d", getarg(0)); + } +} + +function gameinfo { + showavatar NPC_FLOPPED_NOBLEMAN; + mes ""; + mesc l("Rules:"); + mesc l("A color sequence will be displayed on the avatar frame."); + mesc l("You must then repeat the sequence at the board which will show."); + next; + mesc l("Prizes:"); + mesc l("You'll get %d GP every time you finish the sequence.", .prize); + mesc l("If you finish %d sequences, you'll get a(n) %s!", 10, getitemlink(ArcmageBoxset)); + next; + return; +} + +L_Start: + showavatar AVATAR_SEQBOARD; + mesc l("Pay attention to the sequence!"); + next; + Zeny -= .price; + deletearray(@sequence); + @streak=0; + +L_Sequence: + // Configure + setnpcdialogtitle l("Memorize the sequence!"); + array_push(@sequence, 1+rand2(4)); + sleep2(1000); + + // Display + freeloop(true); + for (.@i=0;.@i < getarraysize(@sequence);.@i++) { + showavatar 1200+@sequence[.@i]; + sleep2(1200-(@streak*20)); + } + freeloop(false); + + // Request + setnpcdialogtitle l("What was the sequence?"); + showavatar AVATAR_SEQBOARD; + sleep2(500); + + for (.@i=0;.@i < getarraysize(@sequence);.@i++) { + setskin "seqboard"; + select + l("Green"), + l("Blue"), + l("Red"), + l("Yellow"), + l("Exit"); + .@ans=@menu; + setskin ""; + mes ""; + mes l("%s", colorname(.@ans)); + //next; + setnpcdialogtitle strnpcinfo(1); + + // Exit + if (.@ans == 5) + goto L_Close; + + // Wrong reply + if (.@ans != @sequence[.@i]) + goto L_Wrong; + // Correct! + } + mes ""; + showavatar AVATAR_SEQBOARD_WELL; + + // Seems like everything is/was correct + mesn; + mesq l("Congratulations! Everything was correct!"); + Zeny+=.prize; + @streak+=1; + + // Winning Streak + if (@streak % 10 == 0) + getitem ArcmageBoxset, 1; + mesc l("Your current win streak is @@!", @streak); + next; + // Game over + if (@streak == 50) + goto L_Close; + // Otherwise, go ahead + mesn; + mesc l("Continue?"), 1; + next; + if (askyesno() == ASK_YES) + goto L_Sequence; + goto L_Close; + +L_Wrong: + showavatar AVATAR_SEQBOARD_FAIL; + mesn; + mesq l("Oh no... That is wrong! %%3"); + next; + mesn; + mesq l("Better luck next time!"); + next; + showavatar; + goto L_Main; + +L_Close: + showavatar; + mesn; + mesq l("Thanks for the match, it was fun!"); + next; + goto L_Main; + + OnInit: .@npcId = getnpcid(.name$); setunitdata(.@npcId, UDT_HEADTOP, TopHat); @@ -296,6 +464,8 @@ OnInit: .sex = G_MALE; .distance = 4; + .price = 100; + .prize = 25; end; } diff --git a/npc/020-1/trainer.txt b/npc/033-1/trainer.txt index 1fb4774..c4be75b 100644 --- a/npc/020-1/trainer.txt +++ b/npc/033-1/trainer.txt @@ -4,12 +4,13 @@ // Description: // Mercenary Trainer -020-1,39,89,0 script Mercenary Trainer NPC_REDY_MALE_SWORD,{ +033-1,180,100,0 script Mercenary Trainer NPC_REDY_MALE_SWORD,{ mesn; mesq l("Hello, I am a sword to hire, a Mercenary Trainer and Chief."); next; mesn; mesq l("Do you want to hire a mercenary? Or perhaps get a card so you can invoke them later? I can even make them stronger if you wish."); + mesc l("With a discrete motion, you notice they also sell scrolls."); next; goto L_Main; @@ -24,15 +25,15 @@ L_Main: // Hire Card case 1: menuint - l("[%d GP] [Lv 1~25] Hire for one hour", 2500), 1, - l("[%d GP] [Lv 26~40] Hire for one hour", 7500), 2, - l("[%d GP] [Lv 41~60] Hire for one hour", 15000), 3, - l("[%d GP] [Lv 61~79] Hire for one hour", 30000), 4, - l("[%d GP] [Lv 80~100] Hire for one hour", 50000), 5, + l("[%d GP] [Lv 1~25] Hire for one hour", 1000), 1, + l("[%d GP] [Lv 26~40] Hire for one hour", 3000), 2, + l("[%d GP] [Lv 41~60] Hire for one hour", 7500), 3, + l("[%d GP] [Lv 61~79] Hire for one hour", 15000), 4, + l("[%d GP] [Lv 80~100] Hire for one hour", 25000), 5, l("I've changed my mind"), 0; switch (@menuret) { case 1: - .@gp=max(2000, POL_AdjustPrice(2500)); + .@gp=1000; if (Zeny < .@gp) { mesc l("You cannot pay."), 1; next; @@ -43,7 +44,7 @@ L_Main: } break; case 2: - .@gp=max(7000, POL_AdjustPrice(7500)); + .@gp=3000; if (Zeny < .@gp) { mesc l("You cannot pay."), 1; next; @@ -54,7 +55,7 @@ L_Main: } break; case 3: - .@gp=max(14000, POL_AdjustPrice(15000)); + .@gp=7500; if (Zeny < .@gp) { mesc l("You cannot pay."), 1; next; @@ -64,7 +65,7 @@ L_Main: } break; case 4: - .@gp=max(27000, POL_AdjustPrice(30000)); + .@gp=15000; if (Zeny < .@gp) { mesc l("You cannot pay."), 1; next; @@ -74,7 +75,7 @@ L_Main: } break; case 5: - .@gp=max(45000, POL_AdjustPrice(50000)); + .@gp=25000; if (Zeny < .@gp) { mesc l("You cannot pay."), 1; next; @@ -132,26 +133,42 @@ L_Main: goto L_Main; OnInit: - tradertype(NST_MARKET); - sellitem MercBoxEE, 25000, 1; - sellitem MercBoxDD, 15000, 2; - sellitem MercBoxCC, 7500, 3; - sellitem MercBoxBB, 3750, 4; - sellitem MercBoxAA, 1250, 5; + tradertype(NST_ZENY); + sellitem MercBoxEE, 25000; + sellitem MercBoxDD, 15000; + sellitem MercBoxCC, 7500; + sellitem MercBoxBB, 3750; + sellitem MercBoxAA, 1250; + + sellitem ScrollSMaggot, 1000; + sellitem ScrollSCave, 1500; + sellitem ScrollSWolvern, 2000; + sellitem ScrollSYeti, 2500; + sellitem ScrollSTerranite, 3000; + sellitem ScrollSDragon, 3500; + + sellitem SacredImmortalityPotion, 25000; + + sellitem ScrollMagnusHealA, 500; + sellitem ScrollMagnusHealB,1000; + sellitem ScrollMagnusHealC,2000; + + sellitem ScrollBattlePlansA, 400; + sellitem ScrollBattlePlansB,1000; + //sellitem ScrollBattlePlansC,1500; + + sellitem ScrollDefenseBlessA, 400; + sellitem ScrollDefenseBlessB,1000; + //sellitem ScrollDefenseBlessC,1500; + + sellitem ScrollCriticalFortuneA, 400; + sellitem ScrollCriticalFortuneB,1000; + //sellitem ScrollCriticalFortuneC,1500; .distance=5; .sex=G_MALE; end; -OnClock0001: -OnClock1201: - restoreshopitem MercBoxEE, 25000, 1; - restoreshopitem MercBoxDD, 15000, 2; - restoreshopitem MercBoxCC, 7500, 3; - restoreshopitem MercBoxBB, 3750, 4; - restoreshopitem MercBoxAA, 1250, 5; - end; - // Pay your taxes! OnBuyItem: debugmes("Purchase confirmed"); diff --git a/npc/033-2/magic.txt b/npc/033-2/magic.txt index 35f2145..0ee0dc2 100644 --- a/npc/033-2/magic.txt +++ b/npc/033-2/magic.txt @@ -39,6 +39,9 @@ OnInit: function script Crossroads_Magic { + // Respect SC_SILENCE + if (getstatus(SC_SILENCE)) return; + // Structure: "«Power» «Element», «Action» «Range»!" .@msg$ = getarg(0); explode(.@x$, .@msg$, " "); @@ -207,7 +210,7 @@ function script Crossroads_Magic { // areaharm() if (.@TY & 1) { - .@dmg = AdjustSpellpower(.@PW); + .@dmg = AdjustSpellpower(.@PW) * 11 / 10; areaharm(getcharid(3), .@RG, .@dmg, HARM_MAGI, .@EL, .@F$); } diff --git a/npc/config/events.txt b/npc/config/events.txt index 3dd4311..89e7f37 100644 --- a/npc/config/events.txt +++ b/npc/config/events.txt @@ -4,7 +4,11 @@ // Description: // Some of the event scripts +001-3 mapflag zone MMO 001-13-2 mapflag zone MMO + +///////////////////////////////////////////////////////////////////////////////// +// Area 06: Moubootaur Showdown 001-13-2,47,26,0 script #FoSCore NPC_NO_SPRITE,{ if (!is_admin() && !is_master()) end; if ($@FIRESOFSTEAM_BOSS) end; @@ -22,7 +26,7 @@ l("Portable Apocalypse"); mes ""; $@FIRESOFSTEAM_DIFF=70+(@menu*30); - $@EVENT_01 = PORTHOS_BUSY; + $@EVENT_06 = PORTHOS_BUSY; switch (@menu) { case 1: .@d$="##2Easy"; break; case 2: .@d$="##3Crazy"; break; @@ -35,7 +39,7 @@ changemusic("001-13-2", "mythica.ogg"); closeclientdialog; // Dispose of the GM - warp "033-1", 72, 185; + warp "033-1", 49, 193; sleep(200); // PC no longer attached // Start the event @@ -152,7 +156,7 @@ OnEventEnd: mapannounce("001-13-2", "Moubootaur : ##1##BI'll come back... Stronger than ever!", 0); sleep(3000); maptimer2("001-13-2", 10, "#FoSCore::OnMFSurvive"); - $@EVENT_01 = PORTHOS_UNUSED; + $@EVENT_06 = PORTHOS_UNUSED; end; @@ -171,7 +175,7 @@ OnMFShake: end; OnMFDispose: - if (ispcdead()) warp("033-1", 72, 191); + if (ispcdead()) warp("033-1", 154, 240); end; OnMFSurvive: @@ -180,7 +184,7 @@ OnMFSurvive: ##01_CRQUEST = ##01_CRQUEST | MLP_CR_DEBUT; specialeffect(FX_FANFARE, AREA, getcharid(3)); sleep2(15000); - warp("033-1", 72, 191); + warp("033-1", 154, 240); end; ////////////// Heartbeat ////////////// @@ -308,7 +312,7 @@ L_Defeat: .Support5=0; killmonsterall("001-13-2"); kamibroadcast("The players were defeated at Fires of Steam Showdown.", "Fires of Steam"); - $@EVENT_01 = PORTHOS_UNUSED; + $@EVENT_06 = PORTHOS_UNUSED; stopnpctimer; end; @@ -320,3 +324,92 @@ OnInit: end; } + +///////////////////////////////////////////////////////////////////////////////// +// Area 08: Blanc's Showdown +001-3,147,153,0 script #E08_CF NPC_HIDDEN,2,0,{ + end; +OnTouch: + if (!(get_byte(EVENT_08, 0) & EV08_KEY)) { + dispbottom l("Darn, it is locked. A few keys will be necessary to open this."); + end; + } + warp "026-2", 32, 96; + end; +OnBossDie: + .@p=get_nibble(EVENT_08, 2)+1; + set_nibble(EVENT_08, 2, .@p); + if (.@p >= 3) { + set_byte(EVENT_08, 0, get_byte(EVENT_08, 0) | EV08_KEY); + dispbottom l("I got all the keys! Time to get out of here!"); + sleep2(500); + warp "001-3", 164, 33; + end; + } + dispbottom l("Keys: %d/%d", .@p, 3); + end; +OnInit: + .sex = G_OTHER; + end; +} + +001-3,35,32,0 script #E08WP_150 NPC_HIDDEN,0,0,{ + end; +OnTouch: + if ($@EVENT_08 != PORTHOS_ACTIVE) end; + //if (get_byte(EVENT_08, 0) & EV08_P150) end; + if (get_byte(EVENT_08, 0) & EV08_KEY) end; + setpcblock(PCBLOCK_HARD, true); + mesc l("STORY MODE ENABLED. Monsters won't attack you, so you can read without worries."), 1; + next; + mesc l("Seems like our prey was through. This portal connects to a Level %d Maze.", .lvl); + if (BaseLevel > .lvl*2) { + mesc l("Meaning I cannot use this one. Dang!"); + next; + goto L_Close; + } + mesc l("If I can find Elmo or Marley inside, they should be holding the keys for the castle, where we presume Blanc ran off to."); + mesc l("I need to defeat at least three of them."), 1; + next; + mesc l("Will I explore this Maze? Or will I look another?"), 1; + next; + if (askyesno() == ASK_YES) { + set_nibble(EVENT_08, 2, 0); + CreateMaze(IOT_CHAR, MAZE_SIZE_G | MAZE_SIZE_X); + if (BaseLevel > .lvl) + .density=12; + else + .density=15; + MazeMobs(.lvl, false, .density); + + // Spawn & Configure the boss monster + .@mx=getmapinfo(MAPINFO_SIZE_X, MAZE_MAP$)-20; + .@my=getmapinfo(MAPINFO_SIZE_Y, MAZE_MAP$)-20; + .@mob=areamonster(MAZE_MAP$, 20, 20, .@mx, .@my, "Elmo", Marley, 5, "#E08_CF::OnBossDie"); + InitMaze(7200); + dispbottom col(l("Reminder : Defeat 3/5 %s to win. Time limit: %d minutes or death.", b("Elmo"), 120), 2); + } + +L_Close: + closeclientdialog; + setpcblock(PCBLOCK_HARD, false); + end; +OnInit: + .sex = G_OTHER; + .@n$ = strnpcinfo(0, "_0"); + explode(.@ni$, .@n$, "_"); + .lvl = atoi(.@ni$[1]); + end; +} + +001-3,113,148,0 duplicate(#E08WP_150) #E08WP_100 NPC_HIDDEN,0,0 +001-3,258,39,0 duplicate(#E08WP_150) #E08WP_75 NPC_HIDDEN,0,0 +001-3,38,257,0 duplicate(#E08WP_150) #E08WP_50 NPC_HIDDEN,0,0 +001-3,229,188,0 duplicate(#E08WP_150) #E08WP_25 NPC_HIDDEN,0,0 + +// 35,32 NW (150) OK +// 113,148 Central circle (100) +// 258,39 NE (75) +// 38,257 SW (50) +// 229,188 SE (25) + diff --git a/npc/config/traps.txt b/npc/config/traps.txt index 1b43e5c..560abcf 100644 --- a/npc/config/traps.txt +++ b/npc/config/traps.txt @@ -65,7 +65,9 @@ function script IronTrap { // Boom - Hurt and Stun (only works on players and mobs) .@stun*=1000; - sc_start SC_STUN, rand2(.@stun,.@stun*3), 0; + // Replaced SC_STUN with something else, which is not SC_Start* controlled + // But basically, SC_STUN causes lag in M+ because the client is dumb + sc_start2 SC_QUAGMIRE, rand2(.@stun,.@stun*3), 20000, 20000; .@gid=(playerattached() ? playerattached() : mobattached()); // Just to be sure diff --git a/npc/craft/price.txt b/npc/craft/price.txt index 4b0ab9c..34ff919 100644 --- a/npc/craft/price.txt +++ b/npc/craft/price.txt @@ -58,7 +58,7 @@ function script _fix_cPrice { // Update the final price if (.@price > 0) { - debugmes("Price for %s adjusted from %d (%d) to %d (%d) GP", getitemname(.@item), getiteminfo(.@item, ITEMINFO_BUYPRICE), getiteminfo(.@item, ITEMINFO_SELLPRICE), .@price * .@m / 10, .@price); + //debugmes("Price for %s adjusted from %d (%d) to %d (%d) GP", getitemname(.@item), getiteminfo(.@item, ITEMINFO_BUYPRICE), getiteminfo(.@item, ITEMINFO_SELLPRICE), .@price * .@m / 10, .@price); setiteminfo(.@item, ITEMINFO_BUYPRICE, .@price * .@m / 10); setiteminfo(.@item, ITEMINFO_SELLPRICE, .@price); //debugmes("New Price for %s is now %d (%d) GP", getitemname(.@item), getiteminfo(.@item, ITEMINFO_BUYPRICE), getiteminfo(.@item, ITEMINFO_SELLPRICE)); diff --git a/npc/functions/main.txt b/npc/functions/main.txt index b2a7a78..999d18c 100644 --- a/npc/functions/main.txt +++ b/npc/functions/main.txt @@ -299,6 +299,34 @@ function script any_of { return getelementofarray(getarg(0), getarrayindex(getarg(0)) + rand2(getarraysize(getarg(0)) - getarrayindex(getarg(0)))); } +// Miller Algorithm implementation for shuffling (PRIG) +// miller_rand( state, seed, array_size ) +function script miller_rand { + .@inx = getarg(0); + .@shuffleID = getarg(1); + .@listSize = getarg(2); + + .@shuffleID += 131 * (.@inx/.@listSize); // have inx overflow effect the mix + .@si = (.@inx + .@shuffleID) % .@listSize; // cut the deck + + .@topEven = .@listSize - (.@listSize & 1); // compute reference value + .@r1 = .@shuffleID % 0xFFF; // improved randomizing values + .@r2 = .@shuffleID % 0x3FFF ^ .@r1; + .@r3 = .@shuffleID / 881 + 3; + .@rx = (.@shuffleID / .@listSize) % .@listSize + 1; + + // NOTE: the next line operates only 1/3 the time, the following line 1/2 + if (.@si % 3 == 0) + .@si = (((.@si/3)*3343+.@r1) % ((.@listSize+2)/3)) * 3; // spin multiples of 3 + if (.@si&1) + .@si = (2 * .@r2 + .@topEven - .@si) % .@topEven; // reverse+rotate flow of odd #s + if ((.@si ^ .@rx) < .@listSize) + .@si ^= .@rx; // flip some bits with Xor + .@si = (.@si * 9973 + .@r3) % .@listSize; // turn more prime wheels + + return .@si; +} + function script die { if ($HARDCORE) { @grace=true; diff --git a/npc/functions/mobpoint.txt b/npc/functions/mobpoint.txt index b49baa9..08b3ff7 100644 --- a/npc/functions/mobpoint.txt +++ b/npc/functions/mobpoint.txt @@ -85,8 +85,6 @@ OnNPCKillEvent: callfunc "CoffeeDay"; callfunc "FSFDay"; callfunc "CraftmasterDay"; - callfunc "CadisQuestCheck"; - callfunc "GeminiKill"; callfunc "SK_drops"; // Other updates diff --git a/npc/items/grenade.txt b/npc/items/grenade.txt index 12a314b..a3ddf9f 100644 --- a/npc/items/grenade.txt +++ b/npc/items/grenade.txt @@ -78,7 +78,7 @@ function script areasc2 { return; } -// areasc3(range, time, sc, bl, val1, val2, filter) +// areasc3(range, time, sc, bl, val1, val2, filter, target, chances) // Defaults to 3x3 square, sleep mob for 500ms. Ignores you. // Need a player caster. Valid BL: BL_MOB | BL_PC | BL_HOM | BL_MER function script areasc3 { @@ -89,14 +89,16 @@ function script areasc3 { .@v1=getarg(4, 1); .@v2=getarg(5, 1); .@f$=getarg(6, "filter_notme"); + .@t=getarg(7, playerattached()); + .@sr=getarg(8, 10000); - getmapxy(.@m$, .@x, .@y, 0); + getmapxy(.@m$, .@x, .@y, getunittype(.@t), .@t); .@c=getunits(.@b, .@mbs, false, .@m$, .@x-.@r, .@y-.@r, .@x+.@r, .@y+.@r); for (.@i = 0; .@i < .@c; .@i++) { // Filtering if (!callfunc(.@f$, .@mbs[.@i])) continue; - sc_start2 .@s, .@d, .@v1, .@v2, 10000, SCFLAG_NONE, .@mbs[.@i]; + sc_start2 .@s, .@d, .@v1, .@v2, .@sr, SCFLAG_NONE, .@mbs[.@i]; specialeffect(FX_BUFF, AREA, .@mbs[.@i]); } return; |