diff options
author | HoraK-FDF <horak-fdf@web.de> | 2021-12-07 23:01:55 +0100 |
---|---|---|
committer | HoraK-FDF <horak-fdf@web.de> | 2021-12-07 23:01:55 +0100 |
commit | 71d0cdfe8bdb0567303825850ad36a5e8506ab2b (patch) | |
tree | 28f778dc81a65c531a9485e38456a60d6b4daf3f | |
parent | c1be7bd1eab5b0c230001c369292abe757a7f32a (diff) | |
parent | cd6424df5baf7d46b96fa1ee4be500ad8b131a82 (diff) | |
download | serverdata-71d0cdfe8bdb0567303825850ad36a5e8506ab2b.tar.gz serverdata-71d0cdfe8bdb0567303825850ad36a5e8506ab2b.tar.bz2 serverdata-71d0cdfe8bdb0567303825850ad36a5e8506ab2b.tar.xz serverdata-71d0cdfe8bdb0567303825850ad36a5e8506ab2b.zip |
Merge branch 'xmas2021' of https://gitlab.com/themanaworld/evolved/serverdata into xmas2021
29 files changed, 1797 insertions, 16 deletions
diff --git a/conf/map/maps.conf b/conf/map/maps.conf index 68d2bd20..1fc1e11b 100644 --- a/conf/map/maps.conf +++ b/conf/map/maps.conf @@ -122,6 +122,11 @@ map_list: ( "069-2", "070-1", "070-3", + "080-1", + "080-3", + "081-1", + "081-2", + "081-3", "099-1", "099-2", "099-3", diff --git a/db/constants.conf b/db/constants.conf index 21bfd5f3..ac58a2af 100644 --- a/db/constants.conf +++ b/db/constants.conf @@ -3185,6 +3185,9 @@ more than one separator can be used in a row (so 12_3___456 is illegal). NPC432:432 NPC433:433 NPC434:434 + NPC435:435 + NPC436:436 + NPC437:437 NPC32767:32767 // NPCs decently named @@ -3214,7 +3217,7 @@ more than one separator can be used in a row (so 12_3___456 is illegal). NPC_UNUSED__MOBTOMB: 565 NPC_WARP_DEBUG: 722 NPC_UNUSED__FLAG: 722 - NPC_NO_SPRITE: 999 + NPC_NO_SPRITE: 400 NPC_HIDDEN: 32767 comment__: "Walk masks" @@ -3376,6 +3379,23 @@ more than one separator can be used in a row (so 12_3___456 is illegal). ROSSY_READY: 1023 ROSSY_BOSSCAVE: 1024 + comment__: "Christmas 2021 Constants" + X21_ACCEPTED: 1 + X21_CANDLES: 64 + X21_PLANTPUZZLE: 128 + X21_LEVEL3: 256 + X21_RIDDLEDONE: 512 + X21_BOSSDEFEAT: 1024 + X21_ALYSSAINIT: 2048 + X21_ALYSSARESCUE: 4096 + + X21BC1_ON: 1 + X21BC1_OFF: 2 + X21_EXP_PUZZLE: 15000 + X21_TICKET_PUZZLE: 15 + X21_TICKET_BOSS: 5 + X21_TICKET_SUPPORT: 2 + comment__: "Focus Constants" FSKILL_MALLARDS_EYE: 1 FSKILL_BRAWLING: 2 diff --git a/db/map_index.txt b/db/map_index.txt index 354f427b..be37ef1b 100644 --- a/db/map_index.txt +++ b/db/map_index.txt @@ -119,14 +119,19 @@ 069-2 119 070-1 120 070-3 121 -099-1 122 -099-2 123 -099-3 124 -099-4 125 -099-5 126 -099-6 127 -099-7 128 -099-8 129 -botcheck 130 -fermi 131 -sec_pri 132 +080-1 122 +080-3 123 +081-1 124 +081-2 125 +081-3 126 +099-1 127 +099-2 128 +099-3 129 +099-4 130 +099-5 131 +099-6 132 +099-7 133 +099-8 134 +botcheck 135 +fermi 136 +sec_pri 137 diff --git a/db/pre-re/item_db.conf b/db/pre-re/item_db.conf index a037f0cd..99467306 100644 --- a/db/pre-re/item_db.conf +++ b/db/pre-re/item_db.conf @@ -1112,6 +1112,7 @@ item_db: ( Id5260: 1 } }, +/* Rings & Accessories */ { Id: 702 AegisName: "WeddingRing" @@ -1517,6 +1518,7 @@ item_db: ( bonus bHit, 25; "> }, +/* Boots */ { Id: 528 AegisName: "Boots" @@ -4794,6 +4796,26 @@ item_db: ( ViewSprite: 5265 }, { + Id: 5276 + AegisName: "ThermalNapalm" + Name: "Thermal Napalm" + Type: "IT_ETC" + Buy: 9999 + Sell: 0 + Weight: 1 + ViewSprite: 5276 + Trade: { + partneroverride: true + notrade: false + nodrop: true + nogstorage: true + nomail: true + noauction: true + noselltonpc: true + } +}, +/* Chest Armor */ +{ Id: 523 AegisName: "LeatherShirt" Name: "LeatherShirt" @@ -12074,6 +12096,7 @@ item_db: ( bonus bMatkRate, -5; "> }, +/* Usable items */ { Id: 501 AegisName: "CactusDrink" @@ -13738,6 +13761,29 @@ item_db: ( "> }, { + Id: 5277 + AegisName: "XmasSeeds" + Name: "Christmas Seeds" + Type: "IT_USABLE" + Buy: 9999 + Sell: 0 + Weight: 1 + ViewSprite: 5277 + Trade: { + partneroverride: true + notrade: true + nodrop: true + nogstorage: true + nomail: true + noauction: true + noselltonpc: true + } + Script: <" + callfunc "X21_SEEDS"; + "> +}, +/* Legs Armor */ +{ Id: 586 AegisName: "CottonShorts" Name: "CottonShorts" diff --git a/db/pre-re/mob_db.conf b/db/pre-re/mob_db.conf index 50798b57..67e3611d 100644 --- a/db/pre-re/mob_db.conf +++ b/db/pre-re/mob_db.conf @@ -7002,4 +7002,162 @@ mob_db: ( CandyPumpkin: 1250 } }, +{ + Id: 1164 + SpriteName: "ChristmasTree" + Name: "Christmas Tree" + Lv: 40 + Hp: 10000 + Sp: 0 + Exp: 3647 + JExp: 392 + AttackRange: 2 + Attack: [40, 40] + Def: 20 + Mdef: 40 + Stats: { + Str: 30 + Agi: 30 + Vit: 30 + Int: 30 + Dex: 30 + Luk: 30 + } + ViewRange: 9 + ChaseRange: 10 + Size: 1 + Race: 0 + Element: (0, 1) + Mode: { + CanMove: false + CanAttack: true + ChangeTargetMelee: true + ChangeTargetChase: true + } + MoveSpeed: 190 + AttackDelay: 1500 + AttackMotion: 800 + DamageMotion: 800 +}, +{ + Id: 1165 + SpriteName: "ChristmasGift" + Name: "Christmas Gift" + Lv: 1 + Hp: 1 + Sp: 0 + Exp: 1 + JExp: 1 + AttackRange: 1 + Attack: [0, 0] + Def: 0 + Mdef: 5 + Stats: { + Str: 0 + Agi: 0 + Vit: 0 + Int: 0 + Dex: 0 + Luk: 0 + } + ViewRange: 9 + ChaseRange: 10 + Size: 1 + Race: 3 + Element: (2, 1) + MoveSpeed: 800 + AttackDelay: 800 + AttackMotion: 672 + DamageMotion: 480 + Drops: { + FourLeafClover: 5 + } +}, +{ + Id: 1166 + SpriteName: "Snowman" + Name: "Snowman" + Lv: 100 + Hp: 5000 + Sp: 0 + Exp: 2897 + JExp: 689 + AttackRange: 1 + Attack: [60, 80] + Def: 5 + Mdef: 20 + Stats: { + Str: 15 + Agi: 25 + Vit: 40 + Int: 15 + Dex: 45 + Luk: 30 + } + ViewRange: 8 + ChaseRange: 10 + Size: 1 + Race: 3 + Element: (0, 1) + Mode: { + CanMove: true + Aggressive: true + CanAttack: true + ChangeTargetMelee: true + ChangeTargetChase: true + } + MoveSpeed: 800 + AttackDelay: 1872 + AttackMotion: 672 + DamageMotion: 480 + Drops: { + IronPotion: 800 + ConcentrationPotion: 800 + Diamond: 50 + } +}, +{ + Id: 1167 + SpriteName: "SnowmanBoss" + Name: "Der Schneemann" + Lv: 100 + Hp: 35000 + Sp: 0 + Exp: 2897 + JExp: 689 + AttackRange: 3 + Attack: [60, 80] + Def: 20 + Mdef: 20 + Stats: { + Str: 15 + Agi: 15 + Vit: 10 + Int: 15 + Dex: 75 + Luk: 50 + } + ViewRange: 14 + ChaseRange: 16 + Size: 1 + Race: 3 + Element: (0, 1) + Mode: { + CanMove: true + Aggressive: true + CanAttack: true + ChangeTargetMelee: true + ChangeTargetChase: true + Boss: true + } + MoveSpeed: 700 + AttackDelay: 1672 + AttackMotion: 672 + DamageMotion: 480 + Drops: { + IronPotion: 800 + ConcentrationPotion: 800 + Diamond: 50 + } +}, ) diff --git a/maps/pre-re/080-1.mcache b/maps/pre-re/080-1.mcache Binary files differnew file mode 100644 index 00000000..09891164 --- /dev/null +++ b/maps/pre-re/080-1.mcache diff --git a/maps/pre-re/080-3.mcache b/maps/pre-re/080-3.mcache Binary files differnew file mode 100644 index 00000000..037aa549 --- /dev/null +++ b/maps/pre-re/080-3.mcache diff --git a/maps/pre-re/081-1.mcache b/maps/pre-re/081-1.mcache Binary files differnew file mode 100644 index 00000000..60f55155 --- /dev/null +++ b/maps/pre-re/081-1.mcache diff --git a/maps/pre-re/081-2.mcache b/maps/pre-re/081-2.mcache Binary files differnew file mode 100644 index 00000000..0e69fb70 --- /dev/null +++ b/maps/pre-re/081-2.mcache diff --git a/maps/pre-re/081-3.mcache b/maps/pre-re/081-3.mcache Binary files differnew file mode 100644 index 00000000..8250d273 --- /dev/null +++ b/maps/pre-re/081-3.mcache diff --git a/npc/080-1/_import.txt b/npc/080-1/_import.txt new file mode 100644 index 00000000..e28064cf --- /dev/null +++ b/npc/080-1/_import.txt @@ -0,0 +1,3 @@ +// Map 080-1: Mysterious Glade +// This file is generated automatically. All manually added changes will be removed when running the Converter. +"npc/080-1/final.txt", diff --git a/npc/080-1/final.txt b/npc/080-1/final.txt new file mode 100644 index 00000000..72326ed1 --- /dev/null +++ b/npc/080-1/final.txt @@ -0,0 +1,123 @@ +// TMW Script. +// Author: +// Jesusalva +// Notes: +// Christmas 2021 - Mysterious Glade (Final fights, cutscene & final shops) +// CANON: +// From now and hence forth, by the power vested to me due to mapmakers being +// lazy and all that, I declare that it is canon that: +// - Gak and Alissa used to live on this glade +// - Back in 2010, Gak went to Asphodel. First event. +// - Between 2011 and 2015, Gak found out someone built a house here +// - aka. The Pink Boots mage. Gak also got mad at how they got +// Zealite and were using it for petty reasons. +// - Gak took the mask as an offense to Alissa, and the manor as well. +// - As I forgot who is the Pink Boots mage... I can't say any further. +// - Oh, and in 2016, Gak went to visit Asphodel again. + +080-1,98,41,0 script Alissa#ED2 NPC106,{ + end; +OnInstanceInit: + disablenpc .name$; + end; +OnInit: + .distance=4; + /* I thought in making a shop here */ + /* Valentine Dress, Love Potions, Pinkie Crystal... */ + /* Would be confusing and bad, so removed. */ + end; +} + +080-1,97,41,0 script Gak#X21 NPC183,{ + // FIXME: Cutscene + // FIXME: Enablenpc Alissa#ED2 + // FIXME: Do not repeat cutscene if quest once completed + // FIXME: Do not repeat cutscene if Alissa is enabled? + openshop; + closedialog; + end; + +OnInit: + .distance=4; + setarray .prizes, BlinkingEvil, BlinkingEvilRed, BlinkingEvilBlue, + BlinkingEvilPink, BlinkingEvilYellow, GuyFawkesMask, + OperaMask, JesterMask, GoblinMask, WitchHat; + setarray .prices, 1500, 1650, 1600, + 1650, 1600, 250, + 900, 700, 250, 450; + tradertype(NST_CUSTOM); + freeloop(true); + for (.@i = 0; .@i < getarraysize(.prizes); .@i++) { + sellitem(.prizes[.@i], .prices[.@i]); + } + freeloop(false); + end; + +OnCountFunds: + setcurrency(countitem(AquaTicket)); + end; + +/* @price is total cost. @points is if we accept two items as currency. */ +OnPayFunds: + //dispbottom "Hi: price="+@price+" and points="+@points; + if( countitem(AquaTicket) < @price ) + end; + /* Verify if you're not purchasing a dupe */ + /* This requires servercode@712c09c2c6d848243c3426aeb3dbdf730c1e0b08 to work */ + for (.@i=0;.@i < getarraysize(@bought_nameid); .@i++) { + if (debug || $@XMAS21_OVERRIDE) + debugmes("%dx %s", @bought_quantity[.@i], getitemname(@bought_nameid[.@i])); + + .@arr = array_find(.prizes, @bought_nameid[.@i]); + if (.@arr < 0) { dispbottom "REPORT ME: Array Error (Gak)"; end;} + .@bit = (2 ** .@arr); + + if (#X21PRIZES_GAK & .@bit) { + dispbottom l("You already purchased a(n) %s during the event.", getitemlink(@bought_nameid[.@i])); + dispbottom l("Therefore, the operation was cancelled."); + end; + } + } + delitem AquaTicket, @price; + /* Record the items on the bitmask (far more important) */ + /* This requires servercode@712c09c2c6d848243c3426aeb3dbdf730c1e0b08 to work */ + for (.@i=0;.@i < getarraysize(@bought_nameid); .@i++) { + .@arr = array_find(.prizes, @bought_nameid[.@i]); + if (.@arr < 0) { dispbottom "REPORT ME: Fatal Array Error (Gak)"; end;} + .@bit = (2 ** .@arr); + #X21PRIZES_GAK = #X21PRIZES_GAK | .@bit; + } + purchaseok(); + end; +} + +// But then, Gak *did* "kidnap" a zealite specialist, right? +080-1,83,136,0 script #X21BarrierF NPC_HIDDEN,3,0,{ + if ('XMAS21FINAL) + end; + + if (mobcount(getmap(), "#X21BarrierF::OnKil")) { + dispbottom strcharinfo(0) + " : " + l("This clearly is not a real gate; Most likely an illusion to prevent access. I should be able to dispel it by killing the guardians."); + end; + } + delcells("X21LF@"+X21ID()); + specialeffect(FX_MAGIC_WICKED_SPAWN, AREA, getcharid(3)); + getitem AquaTicket, X21_TICKET_BOSS; + 'XMAS21FINAL = true; + maptimer2(getmap(), 10, "#X21BarrierF::OnSesame"); + end; +OnInit: + .distance=1; + end; +OnSesame: + dispbottom l("Without the guardians, the illusion is just that: An illusion. The path is clear."); + getitem AquaTicket, X21_TICKET_SUPPORT; + getexp X21_EXP_PUZZLE, 0; + end; +OnKil: + mapannounce getmap(), "One of the guardians has been eliminated by "+strcharinfo(0), 0; + getitem AquaTicket, X21_TICKET_SUPPORT + 1; + X21INIT(); + end; +} + diff --git a/npc/080-3/_import.txt b/npc/080-3/_import.txt new file mode 100644 index 00000000..6bd09a7b --- /dev/null +++ b/npc/080-3/_import.txt @@ -0,0 +1,3 @@ +// Map 080-3: Forgotten Glade +// This file is generated automatically. All manually added changes will be removed when running the Converter. +"npc/080-3/cutscene.txt", diff --git a/npc/080-3/cutscene.txt b/npc/080-3/cutscene.txt new file mode 100644 index 00000000..5cb03656 --- /dev/null +++ b/npc/080-3/cutscene.txt @@ -0,0 +1,236 @@ +// TMW Script. +// Author: +// Jesusalva +// Notes: +// Christmas 2021 - Peaceful Glade +// FIXME: Santa must tell about Gak acting "out of character" by getting the +// Mask of Blinking Evil. Otherwise, it'll be a seriously loose end. + +080-3,83,155,0 script #0803exit NPC_HIDDEN,1,0,{ + end; +OnTouch: + if (!isChristmas21()) { warp "081-1", 68, 31; end; } + if (!X21ED1_CLEAR()) { dispbottom l("It is too early to leave yet!"); end; } + mesn strcharinfo(0); + mesq l("Are we done here? We won't be able to return later!"); + next; + if (askyesno() == ASK_YES) + warp "081-1", 68, 31; + closeclientdialog; + end; +} + +/* The Story Books */ +080-3,116,116,0 script Book#X21B01 NPC_NO_SPRITE,{ + mes l("Gorrik, member of the Bells Society. Thanks for attending the opera."); + next; + mes l("Along this %s, you will find the instructions regarding the plot to murder Efeniunkanduti Khan, king of Tonori.", getitemlink(OperaMask)); + next; + mes l("It is of utmost importance to find out what happened to Fawkes. Therefore, wear a %s and infiltrate the palace.", getitemlink(JesterMask)); + next; + mes l("Beware Akhendo-Al, prince of Tonori. Even the captain of the palace guard won't get away investigating the fire."); + next; + mes l("-- @@1226|The Silver Bell@@"); + close; +OnInit: + .distance=2; + end; +} + +080-3,129,56,0 script Book#X21B02 NPC_NO_SPRITE,{ + mes l("Gorrik's Diary, final entry"); + next; + mes l("I was convinced my friend %s did not die on the explosion which destroyed Tulimshar palace. Therefore, I set out to find the truth about it.", "@@769|Guy Fawkes@@"); + next; + mes l("But I had been fooled. King Khan has been murdered, and I was accused of regicide. All thanks to this accursed %s.", getitemlink(JesterMask)); + next; + mes l("I am sure it was a plot so I would take the fall for the king's murder. However, I still have friends among the guard, whom know I would not kill your majesty. At least, not this way."); + next; + mes l("I'll take a %s, cut all my hair, and use the landbridge to reach the Woodlands. It should be weakly guarded, so hopefully, I'll make it out of Tonori safely.", getitemlink(Scissors)); + next; + mes l("For precaution, I'll also stop using this name. Do not seek for me. For I shall exile myself until the last day of my life."); + close; +OnInit: + .distance=2; + end; +} + +080-3,46,80,0 script Book#X21B04 NPC_NO_SPRITE,{ + mes l("Gak's Diary, firsy entry"); + next; + mes l("So my new life begun, and I realized my training as a palace guard did not really cover survival in the wilderness... Or navigation on dense forests."); + next; + mes l("But just when I was about to resign myself to my fate, to die of hunger in the middle of Argaes southeastern forests... I saw what seemed like an illusion."); + next; + mes l("A candy house. With my judgment clouded from hunger, I immediately begun eating the wall, without a care in the world. It was %s!", "@@1281|shocking@@"); + next; + mes l("But suddenly, a witch came out of the cottage. I ran for my life! However, being only used to deserts instead of rainforests, I could not outrun her. I thought my life was over, but..."); + next; + mes l("...instead, she just scolded me. Told me how difficult was to maintain a sweet house. I never felt so much shame in my life, it was worse than if I had actually killed the king!"); + next; + mes l("From now on, I'll be a witch's apprentice, to repay for what I ate. I am nervous, but... also glad for this chance, to rebuild my life, far from the conspiracies and backstabbings of Tulimshar court."); + close; +OnInit: + .distance=2; + end; +} + +080-3,64,120,0 script Book#X21B05 NPC_NO_SPRITE,{ + mes l("Report to Hurnscald Government, year unknown."); + next; + mesn strcharinfo(0); + mes l("It describes a brutal goblin attack which decimated a small settlement southwest of Hurnscald, called Turnap."); // Later became known as Asphodel Moors + next; + mesn strcharinfo(0); + mes l("Apparently, the citizens there tried using %s to thwart goblin attacks, but did not account for the clan system of the goblin society.", getitemlink(GoblinMask)); + next; + mesn strcharinfo(0); + mes l("...Needless to say, the goblins thought it was an invading tribe and decimated the town, killing and destroying anything on the vicinity. There has been ##Bno survivors##b."); + next; + mes l("The farthest body found was of a man called \"Gak\". According to the report, he likely tried to run away from the town alone but did not made it."); + close; +OnInit: + .distance=2; + end; +} + +080-3,98,90,0 script Package#X21B06 NPC_NO_SPRITE,{ + mesn strcharinfo(0); + mes l("This bag is full of pictures. I'll briefly describe them."); + next; + mes l("1. A woman wearing a %s, close to a tall man whose face is obscured by an %s.", getitemlink(WitchHat), getitemlink(OperaMask)); + next; + mes l("2. A photo of Asphodel Moors, back when it was inhabited by living beings."); + next; + mes l("3. A photo of a candy cottage. There's a man tending to it, but his face is not visible."); + next; + mes l("4. A photo of two great dragons clashing against a raging one."); + next; + mes l("5. The woman from the first photo, but without her hat and... floating? hovering? well, she is lying above the abyss."); + close; +OnInit: + .distance=2; + end; +} + + +// FIXME: Alissa's NPC ID; Make more clear the sequence to players. +080-3,85,52,0 script Alissa#ED1 NPC106,{ + function rushed; + function ending; + if (!isChristmas21()) end; + if (.stable == 6) ending(); + if (.stable >= 7) end; + mesn; + mesq l("..."); + next; + mesn strcharinfo(0); + mesq l("Alissa seems unresponsive, as if her mind wasn't fully back in the world yet."); + next; + mesn strcharinfo(0); + mesq l("Perhaps I could ##Bshow her##b something?"); + next; + select + l("I really don't know what to show."), + l("A Mask of Blinking Evil"), + l("An Opera Mask"), + l("A Jester Mask"), + l("A Witch's Hat"), + l("A Goblin Mask"), + l("A Fawkes Mask"), + l("Some Scissors"), + l("A Shock Sweet"); + mes ""; + if (@menu < 1) { closeclientdialog; close; } + if (.memory & (2 ** @menu)) { + mesn strcharinfo(0); + mesq l("...I already showed her that."); + close; + } + if (!.stable) { + mesc l("I probably should start with something about where she was supposed to be and who she is, and tell her the whole story from that."); + } + + /* First Cutscene */ + switch (@menu) { + case 2: // Blinking Mask + rushed(5); + mesc l("Suddenly, Alissa's eyes shot open."); + next; + mesn; + mesq l("...Gorrik is... Alive...?"); + break; + case 3: // Opera Mask + rushed(); + break; + case 4: // Jester Mask + rushed(3); + mesn; + mesq l("...I remember... Running from a coup'detat..."); + next; + mesn; + mesq l("...What happened... to him...?"); + break; + case 5: // Witch Hat + rushed(1); + mesn; + mesq l("...Gorrik..."); + break; + case 6: // Goblin Mask + rushed(4); + mesn; + mesq l("...Yes... A slaughter..."); + break; + case 7: // Fawkes Mask + rushed(); + break; + case 8: // Scissors + rushed(2); + mesn; + mesq l("...His... Past?"); + break; + case 9: // Shock Candy + rushed(0); + mesn; + mesq l("...The Candy House..."); + break; + } + .memory = .memory | (2 ** @menu); + close; + +function rushed { + if (.stable == getarg(0, -1)) { .stable+=1; return; } + mesn strcharinfo(0); + mesq l("...No, I should look for more clues before showing this item."); + close; +} + +function ending { + mesn; + mesq l("What happened to Gorrik...?"); + next; + mesc l("While you do not know the details, you still try to explain the situation to Alissa."); + mesc l("How Gak became an undead, how long he sought for her, until finally, when he had almost given hope... How Santa decided to intervene."); + next; + mesc l("After hearing your history, you could not tell if Alissa was glad or sad."); + next; + mesn; + mesq l("...I'll follow."); + next; + mesn; + mesq l("Bring me to him."); + // (Poor Gak, he is up to an earful once player completes this quest...) + // FIXME: Prize? + .stable += 1; + X21ED1_DOCLEAR(); + disablenpc instance_npcname(.name$); + close; +} + +OnInit: + .distance=4; + .stable=0; + .memory=0; + end; +} + diff --git a/npc/081-1/_import.txt b/npc/081-1/_import.txt new file mode 100644 index 00000000..37fd1add --- /dev/null +++ b/npc/081-1/_import.txt @@ -0,0 +1,3 @@ +// Map 081-1: Aethyr +// This file is generated automatically... All manually added changes will be removed when running the Converter. +"npc/081-1/dungeon.txt", diff --git a/npc/081-1/dungeon.txt b/npc/081-1/dungeon.txt new file mode 100644 index 00000000..fd125dd0 --- /dev/null +++ b/npc/081-1/dungeon.txt @@ -0,0 +1,29 @@ +// TMW Script. +// Author: +// Jesusalva +// Notes: +// Christmas 2021 - Northen Lights Dungeon Entrance + +081-1,68,30,0 script #0811Nexit NPC_HIDDEN,0,0,{ + end; +OnTouch: + if (!isChristmas21()) end; + + /* We need to determine if instance exists and is needed */ + X21INIT(); + + .@mapa$="0812@"+X21ID2(); + warp .@mapa$, 90, 298; + end; +} + +081-1,64,34,0 script #X21_SIGN01 NPC_NO_SPRITE,{ + if (!isChristmas21()) end; + npctalk3 l("Northern Lights Dungeon - Form a party to join or enter alone. Be careful!"); + end; +OnInit: + .distance=5; + end; +} + + diff --git a/npc/081-2/_import.txt b/npc/081-2/_import.txt new file mode 100644 index 00000000..f777ef1b --- /dev/null +++ b/npc/081-2/_import.txt @@ -0,0 +1,4 @@ +// Map 081-2: Northern Lights +// This file is generated automatically. All manually added changes will be removed when running the Converter. +"npc/081-2/_warps.txt", +"npc/081-2/logic.txt", diff --git a/npc/081-2/_warps.txt b/npc/081-2/_warps.txt new file mode 100644 index 00000000..22644e17 --- /dev/null +++ b/npc/081-2/_warps.txt @@ -0,0 +1,3 @@ +// This file is generated automatically. All manually added changes will be removed when running the Converter. +// Map 081-2: Northern Lights warps +081-2,90,299,0 warp #081-2_90_299 0,0,081-1,68,31 diff --git a/npc/081-2/logic.txt b/npc/081-2/logic.txt new file mode 100644 index 00000000..ba9b6abd --- /dev/null +++ b/npc/081-2/logic.txt @@ -0,0 +1,322 @@ +// TMW Script. +// Author: +// Jesusalva +// Notes: +// Christmas 2021 - Northen Lights Dungeon + +081-2,90,20,0 script #0812Nexit NPC_HIDDEN,0,0,{ + end; +OnTouch: + if (!isChristmas21()) end; + + /* We need to determine if instance exists and is needed */ + X21INIT(); + + .@mapn$="0813@"+X21ID2(); + warp .@mapn$, 44, 49; + // FIXME: Cleanup if inst returns -4 + //doevent instance_npcname("Pentagram#Xmas21A", .@inst)+"::OnClean"; + end; +} + +/* *************************************************************************** */ +/* Candle Puzzle */ +081-2,130,255,0 script #X21Candle_0 NPC_NO_SPRITE,{ + if (!countitem(ThermalNapalm)) { dispbottom(l("I don't have anything to lit this candle.")); end; } + if ('XMAS21CANDLE) end; + // Extract ID + .@n$=strnpcinfo(2, "_-1"); + explode(.@ni$, .@n$, "_"); + .@id=atoi(.@ni$[1]); + if (.@id < 0) { consolemes(CONSOLEMES_ERROR, "ERROR, X21 Invalid Candle"); end; } + .@c = 'X21_CANDLE[.@id]; + .@c$ = (.@c == 0 ? l("No") : (.@c == 1 ? l("Regular") : l("Magic"))); + + mes l("This candle is using %s Fire.", .@c$); + mes l("Do you want to change it?"); + mesc l("Cost: 1x %s", getitemlink(ThermalNapalm)), 1; + next; + menuint + l("No, leave it alone."), -1, + rif(.@c != 1, l("Lit a regular fire.")), 1, + rif(.@c != 2, l("Lit a magic fire.")), 2, + rif(.@c != 0, l("Remove the fire.")), 0; + mes ""; + if (@menuret < 0) { closeclientdialog; close; } + delitem ThermalNapalm, 1; + 'X21_CANDLE[.@id] = @menuret; + // Modify the flame sprite + setnpcdisplay(instance_npcname(strnpcinfo(0)), (@menuret ? (@menuret == 1 ? NPC436 : NPC437) : NPC_NO_SPRITE)); + //debugmes "Sprite %s (%s) to %d", strnpcinfo(0), instance_npcname(strnpcinfo(0)), (@menuret ? (@menuret == 1 ? NPC436 : NPC437) : NPC_NO_SPRITE); + // What about 374 instead of 437? + // Unlock the gate once the puzzle is complete + if (X21CANDLE_CHECK()) { + delcells("X21L1@"+X21ID()); + specialeffect(FX_MAGIC_WICKED_SPAWN, AREA, getcharid(3)); + getexp X21_EXP_PUZZLE, 0; + getitem AquaTicket, X21_TICKET_PUZZLE; + X21INIT(); + } + closeclientdialog; + close; +OnInit: + .distance=1; + end; +} + +081-2,131,257,0 duplicate(#X21Candle_0) #X21Candle_1 NPC_NO_SPRITE +081-2,132,249,0 duplicate(#X21Candle_0) #X21Candle_2 NPC_NO_SPRITE +081-2,133,253,0 duplicate(#X21Candle_0) #X21Candle_3 NPC_NO_SPRITE +081-2,134,258,0 duplicate(#X21Candle_0) #X21Candle_4 NPC_NO_SPRITE +081-2,135,251,0 duplicate(#X21Candle_0) #X21Candle_5 NPC_NO_SPRITE + +081-2,79,279,0 script Hint#X21C0 NPC_NO_SPRITE,{ + .@c = 0; + .@c += ('COLORCODE[0] ? 0 : 1); + .@c += ('COLORCODE[1] ? 0 : 1); + .@c += ('COLORCODE[2] ? 0 : 1); + .@c += ('COLORCODE[3] ? 0 : 1); + .@c += ('COLORCODE[4] ? 0 : 1); + .@c += ('COLORCODE[5] ? 0 : 1); + dispbottom l("%d candles should always be off.", .@c); + end; +OnInit: + .distance=1; + end; +} + +081-2,65,274,0 script Hint#X21C1 NPC_NO_SPRITE,{ + .@c = 0; + .@c += ('COLORCODE[0] == 1 ? 1 : 0); + .@c += ('COLORCODE[1] == 1 ? 1 : 0); + .@c += ('COLORCODE[2] == 1 ? 1 : 0); + .@c += ('COLORCODE[3] == 1 ? 1 : 0); + .@c += ('COLORCODE[4] == 1 ? 1 : 0); + .@c += ('COLORCODE[5] == 1 ? 1 : 0); + dispbottom l("%d candles should use regular fire.", .@c); + end; +OnInit: + .distance=1; + end; +} + +081-2,51,271,0 script Hint#X21C2 NPC_NO_SPRITE,{ + if ('COLORCODE[0] == 2) + dispbottom l("The leftmost candle is magical."); + else if ('COLORCODE[5] == 2) + dispbottom l("The rightmost candle is magical."); + else + dispbottom l("Neither extremes are magical."); +OnInit: + .distance=1; + end; +} + +081-2,41,267,0 script Hint#X21C3 NPC_NO_SPRITE,{ + if ('COLORCODE[0] == 'COLORCODE[5]) + dispbottom l("The leftmost and the rightmost candle are identical."); + else + dispbottom l("The extremes are different."); +OnInit: + .distance=1; + end; +} + +081-2,51,247,0 script Hint#X21C4 NPC_NO_SPRITE,{ + .@n$ = ('COLORCODE[2] ? ('COLORCODE[2] == 1 ? "Regular" : "Magical") : "No"); + dispbottom l("The northmost candle should use %s Fire.", .@n$); +OnInit: + .distance=1; + end; +} + +081-2,63,236,0 script Hint#X21C5 NPC_NO_SPRITE,{ + .@n$=""; + if (!'COLORCODE[3]) + .@n$=('OBSCURECOLOR ? "Regular" : "Magical"); + else if ('COLORCODE[3] == 1) + .@n$=('OBSCURECOLOR ? "No" : "Magical"); + else + .@n$=('OBSCURECOLOR ? "Regular" : "No"); + + dispbottom l("The central candle should NOT use %s Fire.", .@n$); +OnInit: + .distance=1; + end; +} + +081-2,88,257,0 script Hint#X21C6 NPC_NO_SPRITE,{ + .@c=('COLORCODE[1]+'COLORCODE[4]); + if (.@c <= 1) + .@n$="Bleakness"; + else if (.@c >= 3) + .@n$="Brightness, perhaps Magical Fire"; + else + .@n$="either Regular Fire, or they may diverge"; + + dispbottom l("The two southern candles lean towards %s.", .@n$); +OnInit: + .distance=1; + end; +} + +081-2,105,213,0 script #X21Barrier1 NPC_HIDDEN,2,0,{ + if (!'XMAS21CANDLE) + npctalkonce l("The strong shall yield the powder to enlighten the way, according to the established sequence."); + end; +OnInit: + .distance=1; + end; +} + +/* *************************************************************************** */ +/* Seeds Puzzle - See 2021.txt */ + +081-2,127,129,0 script #X21Barrier2 NPC_HIDDEN,4,0,{ + if (!'XMAS21TREE) + npctalkonce l("In this year Christmas, kids shall play ball. Once the Christmas Tree is set, the festivities may proceed."); + end; +OnInit: + .distance=1; + end; +} + +081-2,118,169,0 script #X21SeedFlag NPC_NO_SPRITE,{ + if (!'XMAS21TREE) + npctalkonce l("The leaves in a room, the objects from the other; When they merge together, the festivities shall proceed."); + end; +OnInit: + .distance=2; + end; +} + +/* *************************************************************************** */ +/* Ambush Puzzle */ + +081-2,49,73,0 script #X21Barrier3 NPC_HIDDEN,2,0,{ + if (!'XMAS21AMBUSH) + npctalkonce l("One room, Seventeen buttons, Three truths, and a lever to bring joy to the children."); + end; +OnInit: + .distance=1; + end; +} + +081-2,112,90,0 script Nutcracker O'Panel#X21 NPC_NO_SPRITE,{ + if ('XMAS21AMBUSH) + end; + mes l("This Nutcracker has a lever on it."); + mesc l("Do you flip it?"), 1; + next; + if (askyesno() == ASK_NO) { + closeclientdialog; + close; + } + + .@goal = (2**'AMBUSHTRI[0]) + (2**'AMBUSHTRI[1]) + (2**'AMBUSHTRI[2]); + if ('AMBUSH_BMASK == .@goal) { + npctalk l("*beep*"); + delcells("X21L3@"+X21ID()); + 'XMAS21AMBUSH = true; + specialeffect(FX_MAGIC_WICKED_SPAWN, AREA, getcharid(3)); + getexp X21_EXP_PUZZLE, 0; + getitem AquaTicket, X21_TICKET_PUZZLE; + X21INIT(); + } else { + npctalk l("*click*"); + } + 'AMBUSH_BMASK = 0; + .@amb = any(ManaGuardian, ManaGuardian, ManaSlayer, (X21TYPE() == IOT_PARTY ? ManaTyrant : ManaGuardian), Tengu, Sasquatch); + areamonster getmap(), 108, 82, 128, 102, strmobinfo(1, .@amb), .@amb, 1; + closeclientdialog; + close; +OnInit: + .distance=1; + end; +} + +081-2,117,87,0 script Star of Bethlem#X21_0 NPC_NO_SPRITE,{ + if ('XMAS21AMBUSH) + end; + // Extract ID + .@n$=strnpcinfo(2, "_-1"); + explode(.@ni$, .@n$, "_"); + .@id=atoi(.@ni$[1]); + if (.@id < 0) { consolemes(CONSOLEMES_ERROR, "ERROR, X21 Invalid Ambush Hint"); end; } + + .@n='AMBUSHTRI[.@id]+2; // Account for the invisible frame + .@c=(.@n % 5 == 0) ? 5 : (.@n % 5); + .@r=(.@n / 5)+((.@n % 5 == 0) ? 0 : 1); + npctalkonce l("%s column, %s row", X21SRLZ(.@c), X21SRLZ(.@r)); + end; +OnInit: + .distance=1; + end; +} +081-2,124,94,0 duplicate(Star of Bethlem#X21_0) Canes#X21_1 NPC_NO_SPRITE +081-2,120,100,0 duplicate(Star of Bethlem#X21_0) Crown#X21_2 NPC_NO_SPRITE + +081-2,60,118,0 script Switch#X21AB_1 NPC_NO_SPRITE,{ + if ('XMAS21AMBUSH) + end; + // Extract ID + .@n$=strnpcinfo(2, "_0"); + explode(.@ni$, .@n$, "_"); + .@id=atoi(.@ni$[1]); + if (.@id < 1) { consolemes(CONSOLEMES_ERROR, "ERROR, X21 Invalid Ambush Switch"); end; } + + // Already flipped + .@bit=(2**.@id); + if ('AMBUSH_BMASK & .@bit) + end; + + mesc l("There is a switch here."); + mesc l("Do you flip it?"), 1; + next; + if (askyesno() == ASK_YES) { + 'AMBUSH_BMASK = 'AMBUSH_BMASK | .@bit; + npctalk l("*click*"); + } + + closeclientdialog; + close; +OnInit: + .distance=1; + end; +} +081-2,65,118,0 duplicate(Switch#X21AB_1) Switch#X21AB_2 NPC_NO_SPRITE +081-2,70,118,0 duplicate(Switch#X21AB_1) Switch#X21AB_3 NPC_NO_SPRITE +081-2,50,123,0 duplicate(Switch#X21AB_1) Switch#X21AB_4 NPC_NO_SPRITE +081-2,55,123,0 duplicate(Switch#X21AB_1) Switch#X21AB_5 NPC_NO_SPRITE +081-2,60,123,0 duplicate(Switch#X21AB_1) Switch#X21AB_6 NPC_NO_SPRITE +081-2,65,123,0 duplicate(Switch#X21AB_1) Switch#X21AB_7 NPC_NO_SPRITE +081-2,70,123,0 duplicate(Switch#X21AB_1) Switch#X21AB_8 NPC_NO_SPRITE +081-2,50,128,0 duplicate(Switch#X21AB_1) Switch#X21AB_9 NPC_NO_SPRITE +081-2,55,128,0 duplicate(Switch#X21AB_1) Switch#X21AB_10 NPC_NO_SPRITE +081-2,60,128,0 duplicate(Switch#X21AB_1) Switch#X21AB_11 NPC_NO_SPRITE +081-2,65,128,0 duplicate(Switch#X21AB_1) Switch#X21AB_12 NPC_NO_SPRITE +081-2,70,128,0 duplicate(Switch#X21AB_1) Switch#X21AB_13 NPC_NO_SPRITE +081-2,50,133,0 duplicate(Switch#X21AB_1) Switch#X21AB_14 NPC_NO_SPRITE +081-2,55,133,0 duplicate(Switch#X21AB_1) Switch#X21AB_15 NPC_NO_SPRITE +081-2,60,133,0 duplicate(Switch#X21AB_1) Switch#X21AB_16 NPC_NO_SPRITE +081-2,65,133,0 duplicate(Switch#X21AB_1) Switch#X21AB_17 NPC_NO_SPRITE + +/* *************************************************************************** */ +/* The Enigma */ + +/* +// FIXME (137,68 and 130,56 and 120,69) (no sprite) (no code) +081-2,137,68,0 script Enigma#X21A1 NPC_NO_SPRITE,{ + mes l("Three Enigmas, one always say the truth, one always says a lie, and the third may either say the truth or a lie."); + mes ""; + if ('TRUTHSTAT[0]) + mesc l("The truth"), 1; + else + mesc l("A lie"), 1; + close; +OnInit: + .distance=2; + end; +} +*/ + diff --git a/npc/081-3/_import.txt b/npc/081-3/_import.txt new file mode 100644 index 00000000..5e2a38a7 --- /dev/null +++ b/npc/081-3/_import.txt @@ -0,0 +1,3 @@ +// Map 081-3: Existential Frontier +// This file is generated automatically. All manually added changes will be removed when running the Converter. +"npc/081-3/logic.txt", diff --git a/npc/081-3/logic.txt b/npc/081-3/logic.txt new file mode 100644 index 00000000..d77bd34c --- /dev/null +++ b/npc/081-3/logic.txt @@ -0,0 +1,203 @@ +// TMW Script. +// Author: +// Jesusalva +// Notes: +// Christmas 2021 - Boss Chamber #1 +// FIXME: What if players *fail* this? e.g. die + +081-3,44,36,0 script Pentagram#Xmas21A NPC424,{ + .@id = X21ID(); + if ($@XMAS21_BC1[.@id] == X21BC1_ON) end; + .@n$ = instance_npcname("Pentagram#Xmas21A"); + .@cl = X21BC1_CLEAR(); + + mesn; + mesq l("Should we break the Pentagram?"); + next; + select + l("I'm not ready yet."), + l("Bring it on!"), + rif(.@cl, l("Make it harder!")), + rif(.@cl, l("Make it a nightmare!")), + rif(.@cl, l("Kill me semi-instantly!")); + mes ""; + closeclientdialog; + if (@menu == 1 || 'LOCKD) { + close; + } + + 'LOCKD = true; + 'BC1LV = @menu - 1; + @BC1ME = getcharid(3); + .@mg = monster(getmap(), 44, 36, "Der Schneemann", SnowmanBoss, 1, "Pentagram#Xmas21A::OnFin"); + + // Prepare the difficulty settings + // Each difficulty level doubles the nÂș of players difficulty setting + // Can go up to 12 * 4 = 48, but we use 16 as the theoretical max + .@df = max(1, getmapusers(getmap()) * ('BC1LV * 2)); + .@lv = BaseLevel; + + setunitdata(.@mg, UDT_MAXHP, 5000 + (.@lv * 150) + (1200 * .@df)); + setunitdata(.@mg, UDT_HP, 5000 + (.@lv * 150) + (1200 * .@df)); + + setunitdata(.@mg, UDT_ADELAY, 2200 - max(1200, 75 * .@df)); + setunitdata(.@mg, UDT_ATKRANGE, 3); + + /* + setunitdata(.@mg, UDT_ATKMIN, .@lv*4+.@df*3); + setunitdata(.@mg, UDT_ATKMAX, .@lv*4+.@df*3); + */ + setunitdata(.@mg, UDT_ATKMIN, (.@lv+.@df)*5); + setunitdata(.@mg, UDT_ATKMAX, (.@lv+.@df)*6); + setunitdata(.@mg, UDT_DEF, min(50+.@df, 98)); + setunitdata(.@mg, UDT_MDEF, min(50+.@df, 98)); + setunitdata(.@mg, UDT_HIT, 9999); + + // Destroy the instance only after half hour has passed + instance_set_timeout(1800, 1800); + initnpctimer; + setnpctimer(39000); + disablenpc(.@n$); + $@XMAS21_BC1[.@id] = X21BC1_ON; + .BC1ID = .@mg; + close; + +OnFin: + if (!playerattached()) { + consolemes(CONSOLEMES_ERROR, "Player not attached after Christmas 2021 victory! Script aborted!"); + end; + } + killmonsterall(getmap()); + getexp 10000, 0; + getitem AquaTicket, 1 + 'BC1LV; + maptimer(getmap(), 10, "Pentagram#Xmas21A::OnFlush"); + end; + +// Distribute experience and handle quest progress +OnFlush: + getexp 5000, 0; + if (@BC1ME > 0) { + if (!X21BC1_CLEAR()) { + dispbottom l("Whatever that guardian was, the path is now clear, and the gate, open."); + X21BC1_DOCLEAR(); + } + } + @BC1ME = 0; + .@id = X21ID(); + $@XMAS21_BC1[.@id] = X21BC1_OFF; + getitem AquaTicket, X21_TICKET_SUPPORT + ('BC1LV / 2); + end; + +// Pseudo-Magic +OnTimer40000: + if (getunittype(.BC1ID) < 0) { + stopnpctimer; + end; + } + + .CYCLE += 1; + .@m$=getmapinfo(MAPINFO_NAME); // We could use .map$ too + areamonster(.@m$, 31, 23, 58, 50, "Snowballz", Snowman, 1+getmapusers(.@m$)); + + if (.CYCLE % 2 != 0) { + initnpctimer; + end; + } + + // The boss special skill depends on its health + .@hp = 100 * getunitdata(.BC1ID, UDT_HP) / getunitdata(.BC1ID, UDT_MAXHP); + + // HP > 70%, just some warm-up + if (.@hp > 70) { + unittalk(.BC1ID, "Blizzard!"); + rectharm(.BC1ID, 6, 6, rand2(250), HARM_MAGI, Ele_Neutral, "filter_always", BL_PC); + + // HP < 70%, cripple half the attackers + } else if (.@hp > 40) { + .@sc = any(SC_SILENCE, SC_BLIND); + if (.@sc == SC_SILENCE) + unittalk(.BC1ID, "Silence!"); + else + unittalk(.BC1ID, "Blind!"); + areasc2(.@m$, 44, 36, 14, rand2(15000), BL_PC, .@sc); + rectharm(.BC1ID, 5, 5, rand2(50), HARM_MAGI, Ele_Neutral, "filter_always", BL_PC); + + // HP < 40%, cause great damage + } else if (.@hp > 15) { + unittalk(.BC1ID, "Greater Blizzard!"); + rectharm(.BC1ID, 8, 8, 100+rand2(250), HARM_MAGI, Ele_Neutral, "filter_always", BL_PC); + + // HP < 15%, use more dangerous conditions + } else { + .@sc = any(SC_POISON, SC_CURSE); + if (.@sc == SC_SILENCE) + unittalk(.BC1ID, "Poison!"); + else + unittalk(.BC1ID, "Curse!"); + areasc2(.@m$, 44, 36, 14, rand2(15000), BL_PC, .@sc); + rectharm(.BC1ID, 5, 5, rand2(100), HARM_MAGI, Ele_Neutral, "filter_always", BL_PC); + } + + // Repeat forever + initnpctimer; + end; + +OnClean: + enablenpc(.name$); + killmonsterall(getmapinfo(MAPINFO_NAME)); +OnInit: + .distance=2; + .BC1ID = 0; + .CYCLE = 0; + end; +} + + +081-3,44,22,0 script #0813Nexit NPC_HIDDEN,0,0,{ + end; +OnTouch: + if (!isChristmas21()) end; + if (!X21BC1_CLEAR()) { + dispbottom l("A strong magic barrier prevents me from using this exit."); + end; + } + .@id = X21ID(); + if ($@XMAS21_BC1[.@id] == X21BC1_ON) end; + if ($@XMAS21_BC1[.@id] == X21BC1_OFF) { + mesn l("Northern Lights"); + mes l("Past this gate, beyond the existential frontier, I can see the Northern Lights."); + mes l("Should we walk toward it?"); + next; + select + l("Yes"), + l("Not yet"), + l("[Run away]"); + mes ""; + if (@menu == 1) { + /* We need to determine if instance exists and is needed */ + X21INIT(); + + .@mapn$="0803@"+X21ID2(); + warp .@mapn$, 83, 154; + } + // NOTE: Right now, anyone can do so? + else if (@menu == 3) { + enablenpc(instance_npcname("Pentagram#Xmas21A")); + warp "081-2", 90, 21; + 'LOCKD = false; + } + closeclientdialog; + close; + } + end; +} + +081-3,44,50,0 script #0813Sexit NPC_HIDDEN,0,0,{ + end; +OnTouch: + .@id = X21ID(); + if ($@XMAS21_BC1[.@id] == X21BC1_ON) end; + warp "081-2", 90, 21; + end; +} + diff --git a/npc/_import.txt b/npc/_import.txt index b8dcd152..7ac2d194 100644 --- a/npc/_import.txt +++ b/npc/_import.txt @@ -121,6 +121,11 @@ @include "npc/069-2/_import.txt" @include "npc/070-1/_import.txt" @include "npc/070-3/_import.txt" +@include "npc/080-1/_import.txt" +@include "npc/080-3/_import.txt" +@include "npc/081-1/_import.txt" +@include "npc/081-2/_import.txt" +@include "npc/081-3/_import.txt" @include "npc/099-1/_import.txt" @include "npc/099-2/_import.txt" @include "npc/099-3/_import.txt" diff --git a/npc/annuals/xmas/2021.txt b/npc/annuals/xmas/2021.txt new file mode 100644 index 00000000..27451e99 --- /dev/null +++ b/npc/annuals/xmas/2021.txt @@ -0,0 +1,565 @@ +// TMW Script. +// Author: +// Jesusalva +// Notes: +// Christmas 2021 - Configuration Files + +function script X21ID { + return (getcharid(1) > 0 ? getcharid(1) : getcharid(3)); +} + +function script X21ID2 { + return (getcharid(1) > 0 ? getcharid(1) : getcharid(0)); +} + +function script X21TYPE { + return (getcharid(1) > 0 ? IOT_PARTY : IOT_CHAR); +} + +function script X21BC1_CLEAR { + return (XMAS2021 & X21_BOSSDEFEAT); +} + +function script X21BC1_DOCLEAR { + XMAS2021 = (XMAS2021 | X21_BOSSDEFEAT); + return; +} +function script X21ED1_CLEAR { + return (XMAS2021 & X21_ALYSSARESCUE); +} + +function script X21ED1_DOCLEAR { + XMAS2021 = (XMAS2021 | X21_ALYSSARESCUE); + return; +} + +function script X21SRLZ { + .@n=getarg(0); + switch (.@n) { + case 1: return l("first"); + case 2: return l("second"); + case 3: return l("third"); + case 4: return l("fourth"); + case 5: return l("fifth"); + //case 6: return l("sixth"); + //case 7: return l("seventh"); + } + return str(.@n); +} + +function script X21QUESTON { + // Create and setup the challenge. Allow to reset quest. + XMAS2021 = X21_ACCEPTED; + /* Prepare something */ + return; +} + +function script X21INIT { + .@inst = instance_create("Northern Lights", X21ID(), X21TYPE()); + // Instance must be created + if (.@inst >= 0) { + // We... Could use base name, actually, but whatever + .@mapa$ = "0812@"+X21ID2(); // Northern Lights + .@mapb$ = "0813@"+X21ID2(); // Existential Frontier + .@mapc$ = "0803@"+X21ID2(); // Forgotten/Mystic/Peaceful Glade + .@mapd$ = "0801@"+X21ID2(); // Peaceful Glade (Present) + + instance_attachmap("081-2", .@inst, false, .@mapa$); + instance_attachmap("081-3", .@inst, false, .@mapb$); + instance_attachmap("080-3", .@inst, false, .@mapc$); + instance_attachmap("080-1", .@inst, false, .@mapd$); + + instance_set_timeout(1800, 1800, .@inst); + instance_init(.@inst); + + /* Create locks */ + setcells .@mapa$, 103, 211, 107, 212, 1, "X21L1@"+X21ID(); + setcells .@mapa$, 124, 127, 131, 128, 1, "X21L2@"+X21ID(); + setcells .@mapa$, 47, 71, 51, 72, 1, "X21L3@"+X21ID(); + setcells .@mapd$, 81, 131, 86, 135, 1, "X21LF@"+X21ID(); + + /* Spawn Special Monsters */ + "#XMAS21Core"::spawn(Grinchboo, 5, .@mapa$); + "#XMAS21Core"::spawn(Grinchboo, 3, .@mapc$); + "#XMAS21Core"::spawn(Moonshroom, 10, .@mapa$); + "#XMAS21Core"::spawn(Moonshroom, 14, .@mapc$); + "#XMAS21Core"::spawn2(BlueSpark, 47, 191, 65, 212, 2, .@mapa$); + "#XMAS21Core"::spawn2(RedSpark, 47, 191, 65, 212, 2, .@mapa$); + if (X21TYPE() == IOT_PARTY) + "#XMAS21Core"::spawn2(Koyntety, 70, 250, 99, 265, 1, .@mapa$, true); + else + "#XMAS21Core"::spawn2(ManaGuardian, 70, 250, 99, 265, 1, .@mapa$, true); + + /* Northern Lights Dungeon */ + "#XMAS21Core"::spawn(WhiteSlime, 37, .@mapa$); + "#XMAS21Core"::spawn(Archant, 7, .@mapa$); + //"#XMAS21Core"::spawn(BlueSpark, 1, .@mapa$); //? + //"#XMAS21Core"::spawn(RedSpark, 1, .@mapa$); //? + "#XMAS21Core"::spawn(AzulSlime, 21, .@mapa$); + "#XMAS21Core"::spawn(SantaSlime, 18, .@mapa$); + "#XMAS21Core"::spawn(Moggun, 27, .@mapa$); + "#XMAS21Core"::spawn(Yeti, 4, .@mapa$); + "#XMAS21Core"::spawn(Wisp, 5, .@mapa$); + "#XMAS21Core"::spawn(Poltergeist, 12, .@mapa$); + "#XMAS21Core"::spawn(Spectre, 5, .@mapa$); + "#XMAS21Core"::spawn(ManaGhost, 14, .@mapa$); + "#XMAS21Core"::spawn(IceElement, 2, .@mapa$); + "#XMAS21Core"::spawn(IceSkull, 2, .@mapa$); + "#XMAS21Core"::spawn(Nutcracker, 6, .@mapa$); + "#XMAS21Core"::spawn(Fluffy, 16, .@mapa$); + + /* Peaceful/Mystic/Forgotten Glade (Past) */ + "#XMAS21Core"::spawn(CrotcherScorpion, 10, .@mapc$); + "#XMAS21Core"::spawn(Snail, 18, .@mapc$); + "#XMAS21Core"::spawn(Bee, 9, .@mapc$); + "#XMAS21Core"::spawn(Butterfly, 24, .@mapc$); + "#XMAS21Core"::spawn(PinkFlower, 42, .@mapc$); + "#XMAS21Core"::spawn(Pinkie, 32, .@mapc$); + "#XMAS21Core"::spawn(Hyvern, 6, .@mapc$); + "#XMAS21Core"::spawn(WitchGuard, 8, .@mapc$); + + /* Peaceful/Mystic/Forgotten Glade (Present) */ + "#XMAS21Core"::spawn(Fluffy, 9, .@mapd$); + "#XMAS21Core"::spawn(Snail, 11, .@mapd$); + "#XMAS21Core"::spawn(Bee, 5, .@mapd$); + "#XMAS21Core"::spawn(Butterfly, 15, .@mapd$); + "#XMAS21Core"::spawn(PinkFlower, 24, .@mapd$); + "#XMAS21Core"::spawn(Pinkie, 18, .@mapd$); + "#XMAS21Core"::spawn(Hyvern, 3, .@mapd$); + + /* The Three Guardians */ + .@bon = 0; + if (X21TYPE() == IOT_PARTY) + .@bon = 20000; + + .@mg = monster(.@mapd$, 43, 47, "Der Schneemann (Alpha)", SnowmanBoss, 1, "#X21BarrierF::OnKil"); + .@hp = .@bon + rand2(35000, 47000); + setunitdata(.@mg, UDT_MAXHP, .@hp); + setunitdata(.@mg, UDT_HP, .@hp); + setunitdata(.@mg, UDT_ATKRANGE, 2); + setunitdata(.@mg, UDT_ATKMIN, 30); + setunitdata(.@mg, UDT_ATKMAX, 40); + + .@mg = monster(.@mapd$, 144, 154, "Der Schneemann (Beta)", SnowmanBoss, 1, "#X21BarrierF::OnKil"); + .@hp = .@bon + rand2(35000, 47000); + setunitdata(.@mg, UDT_MAXHP, .@hp); + setunitdata(.@mg, UDT_HP, .@hp); + setunitdata(.@mg, UDT_ATKRANGE, 2); + setunitdata(.@mg, UDT_ATKMIN, 30); + setunitdata(.@mg, UDT_ATKMAX, 40); + + .@mg = monster(.@mapd$, 42, 147, "Der Schneemann (Gamma)", SnowmanBoss, 1, "#X21BarrierF::OnKil"); + .@hp = .@bon + rand2(35000, 47000); + setunitdata(.@mg, UDT_MAXHP, .@hp); + setunitdata(.@mg, UDT_HP, .@hp); + setunitdata(.@mg, UDT_ATKRANGE, 2); + setunitdata(.@mg, UDT_ATKMIN, 30); + setunitdata(.@mg, UDT_ATKMAX, 40); + + /* The Three Guardians Friends */ + if (X21TYPE() == IOT_PARTY) { .@g = 12; } else { .@g = 7; } + + freeloop(true); + for (.@i=0; .@i < .@g; .@i++) { + .@mg = areamonster(.@mapd$, 30, 38, 50, 51, "Snowman (Alpha)", Snowman, 1); + .@hp = rand2(3500, 5700); + .@ak = rand2(70, 120); + setunitdata(.@mg, UDT_MAXHP, .@hp); + setunitdata(.@mg, UDT_HP, .@hp); + setunitdata(.@mg, UDT_ATKRANGE, 1); + setunitdata(.@mg, UDT_ATKMIN, .@ak); + setunitdata(.@mg, UDT_ATKMAX, .@ak+20); + } + + for (.@i=0; .@i < .@g; .@i++) { + .@mg = areamonster(.@mapd$, 30, 38, 50, 51, "Snowman (Beta)", Snowman, 1); + .@hp = rand2(3500, 5700); + .@ak = rand2(70, 120); + setunitdata(.@mg, UDT_MAXHP, .@hp); + setunitdata(.@mg, UDT_HP, .@hp); + setunitdata(.@mg, UDT_ATKRANGE, 1); + setunitdata(.@mg, UDT_ATKMIN, .@ak); + setunitdata(.@mg, UDT_ATKMAX, .@ak+20); + } + + for (.@i=0; .@i < .@g; .@i++) { + .@mg = areamonster(.@mapd$, 30, 38, 50, 51, "Snowman (Gamma)", Snowman, 1); + .@hp = rand2(3500, 5700); + .@ak = rand2(70, 120); + setunitdata(.@mg, UDT_MAXHP, .@hp); + setunitdata(.@mg, UDT_HP, .@hp); + setunitdata(.@mg, UDT_ATKRANGE, 1); + setunitdata(.@mg, UDT_ATKMIN, .@ak); + setunitdata(.@mg, UDT_ATKMAX, .@ak+20); + } + freeloop(false); + + } + if (instance_id() >= 0) + instance_set_timeout(1800, 1800); + return; +} + +function script X21CANDLE_CHECK { + if ('XMAS21CANDLE) return false; + // NOTE: We could check here if player already finished this + // And skip the challenge after litting one candle? + if ('X21_CANDLE[0] != 'COLORCODE[0]) return false; + if ('X21_CANDLE[1] != 'COLORCODE[1]) return false; + if ('X21_CANDLE[2] != 'COLORCODE[2]) return false; + if ('X21_CANDLE[3] != 'COLORCODE[3]) return false; + if ('X21_CANDLE[4] != 'COLORCODE[4]) return false; + if ('X21_CANDLE[5] != 'COLORCODE[5]) return false; + // This instance challenge is over + 'XMAS21CANDLE = true; + // Record on player as well, just to be safe. + if (XMAS2021 & X21_CANDLES) return true; + XMAS2021 = (XMAS2021 | X21_CANDLES); + return true; +} + +function script X21SEED_CHECK { + /* Protip: You don't have to fill all spots + * + * If you plant a "L" it also works + * This is because "L" is the first letter of "Lazy" + * And I was particularly lazy to make a proper script + */ + if ('XMAS21TREE) return false; + // NOTE: We could check here if player already finished this + // And skip the challenge after planting one tree? + if (!'XMAS21TREE_X[116]) return false; + if (!'XMAS21TREE_X[117]) return false; + if (!'XMAS21TREE_X[118]) return false; + if (!'XMAS21TREE_X[119]) return false; + if (!'XMAS21TREE_X[120]) return false; + if (!'XMAS21TREE_Y[168]) return false; + if (!'XMAS21TREE_Y[169]) return false; + if (!'XMAS21TREE_Y[170]) return false; + // This instance challenge is over + 'XMAS21TREE = true; + // Record on player as well, just to be safe. + if (XMAS2021 & X21_PLANTPUZZLE) return true; + XMAS2021 = (XMAS2021 | X21_PLANTPUZZLE); + return true; +} + +function script X21_SEEDS { + getmapxy(.@m$, .@x, .@y, 0); + // If planted in the wrong region, vanish without effect + if (.@m$ != "0812@"+X21ID2()) + return; + if (.@x < 107 || .@x > 126) + return; + if (.@y < 159 || .@y > 177) + return; + // Should never happen, so nuke everything + //if (instance_id() < 0) end; + // Already planted this spot + if ('XMAS21TREE_X[.@x] && 'XMAS21TREE_Y[.@y]) return; + // Record the success planting it + 'XMAS21TREE_X[.@x] = true; + 'XMAS21TREE_Y[.@y] = true; + // Sprout a Christmas Tree IF position was not already filled + monster(.@m$, .@x, .@y, strmobinfo(1, ChristmasTree), ChristmasTree, 1, "#XMAS21Core::OnX1164"); + // Unlock the gate once the puzzle is complete + if (X21SEED_CHECK()) { + delcells("X21L2@"+X21ID()); + specialeffect(FX_MAGIC_WICKED_SPAWN, AREA, getcharid(3)); + getexp X21_EXP_PUZZLE, 0; + getitem AquaTicket, X21_TICKET_PUZZLE; + X21INIT(); + } + return; +} + +/* You cannot fiddle with party in this region */ +080-1 mapflag partylock +080-3 mapflag partylock +//081-1 mapflag partylock +081-2 mapflag partylock +081-3 mapflag partylock + +081-2 mapflag bexp 125 +080-3 mapflag bexp 125 +080-1 mapflag bexp 125 + +/* Secure regions */ +081-3 mapflag zone MMO +081-3 mapflag nosave 081-1,68,31 + +/* Script Core */ +080-1,0,0,0 script #XMAS21Core NPC_HIDDEN,{ + end; + +// "#XMAS21Core"::spawn(MonsterID, {Amount=1, {Map=this}}) +public function spawn { + if (playerattached()) + .@m$=getarg(2, getmap()); + else + .@m$=getarg(2); + .@n$="#XMAS21Core::On"+getarg(0); + if (mobcount(.@m$, .@n$) < 200) + areamonster .@m$, 20, 20, getmapinfo(MAPINFO_SIZE_X, .@m$)-20, getmapinfo(MAPINFO_SIZE_Y, .@m$)-20, strmobinfo(1, getarg(0)), getarg(0), getarg(1, 1), .@n$; + + /* Aqua Ticket Drops */ + if (playerattached()) { + if (instance_id() < 0) return; // No drops outside instanced maps + fix_mobkill(getarg(0)); + } + return; +} + +// "#XMAS21Core"::spawn2(MonsterID, X1, Y1, X2, Y2, {Amount=1, {Map=this}}) +// Function Changes from On<ID> to OnX<ID> +public function spawn2 { + .@m$=getarg(6, getmap()); + .@n$="#XMAS21Core::OnX"+getarg(0); + .@x1=max(getarg(1), 20); + .@y1=max(getarg(2), 20); + .@x2=min(getarg(3), getmapinfo(MAPINFO_SIZE_X, .@m$)-20); + .@y2=min(getarg(4), getmapinfo(MAPINFO_SIZE_Y, .@m$)-20); + .@noob=getarg(7, false); + /* + // Radius-based, was scrapped in favor of rectangles + .@x1=max(getarg(1)-getarg(3), 20); + .@y1=max(getarg(2)-getarg(3), 20); + .@x2=min(getarg(1)+getarg(3), getmapinfo(MAPINFO_SIZE_X, .@m$)-20); + .@y2=min(getarg(2)+getarg(3), getmapinfo(MAPINFO_SIZE_Y, .@m$)-20); + */ + if (mobcount(.@m$, .@n$) < 200) { + .@mg=areamonster(.@m$, .@x1, .@y1, .@x2, .@y2, strmobinfo(1, getarg(0)), getarg(0), getarg(5, 1), .@n$); + if (.@noob && .@mg) { + .@hp = getunitdata(.@mg, UDT_MAXHP) * 3 / 5; // Reduce to 60% HP + .@ak = getunitdata(.@mg, UDT_ATKMIN) * 4 / 5; // Reduce to 80% ATK + .@ax = getunitdata(.@mg, UDT_ATKMAX) * 4 / 5; // Reduce to 80% ATK + + setunitdata(.@mg, UDT_MAXHP, .@hp); + setunitdata(.@mg, UDT_HP, .@hp); + setunitdata(.@mg, UDT_ATKMIN, .@ak); + setunitdata(.@mg, UDT_ATKMAX, .@ax); + } + } + return; +} + +/* Special */ +// Sparkles Chamber, drops seeds +OnX1080: +OnX1081: + spawn2(any(BlueSpark, RedSpark), 47, 191, 65, 212); + /* Give player enough seeds */ + getmapxy(.@m$, .@x, .@y, 0); + .@x1=.@x-1; + .@y1=.@y-1; + .@x2=.@x+1; + .@y2=.@y+1; + .@x=cap_value(rand2(.@x1, .@x2), 47, 65); + .@y=cap_value(rand2(.@y1, .@y2), 191, 212); + makeitem(XmasSeeds, rand2(1, 3), .@m$, .@x, .@y); + end; +// Mini-Boss Chamberlain, drops candle +OnX1146: +OnX1147: + spawn2(any(Flashmob, Koyntety), 70, 250, 99, 265, 1, getmap(), true); + /* Give player enough fuel potions */ + getmapxy(.@m$, .@x, .@y, 0); + .@x1=.@x-1; + .@y1=.@y-1; + .@x2=.@x+1; + .@y2=.@y+1; + .@x=cap_value(rand2(.@x1, .@x2), 70, 99); + .@y=cap_value(rand2(.@y1, .@y2), 250, 265); + makeitem(ThermalNapalm, rand2(3, 5), .@m$, .@x, .@y); + end; +// Mini-Boss Chamberlain, drops candle (easy mode) +OnX1140: +OnX1143: +OnX1138: + spawn2(any(Tengu, ManaSlayer, ManaGuardian, ManaGuardian), 70, 250, 99, 265, 1, getmap(), true); + /* Give player enough fuel potions */ + getmapxy(.@m$, .@x, .@y, 0); + .@x1=.@x-1; + .@y1=.@y-1; + .@x2=.@x+1; + .@y2=.@y+1; + .@x=cap_value(rand2(.@x1, .@x2), 70, 99); + .@y=cap_value(rand2(.@y1, .@y2), 250, 265); + makeitem(ThermalNapalm, rand2(3, 5), .@m$, .@x, .@y); + end; +// Christmas Tree, spawns a (few?) gift boxes +OnX1164: + getmapxy(.@m$, .@x, .@y, 0); + .@x1=.@x-2; + .@y1=.@y-2; + .@x2=.@x+2; + .@y2=.@y+2; + .@x=cap_value(rand2(.@x1, .@x2), 47, 65); + .@y=cap_value(rand2(.@y1, .@y2), 191, 212); + spawn2(ChristmasGift, .@x1, .@y1, .@x2, .@y2, rand2(1, 3)); + end; +// Christmas Gift Box, gives you Tickets +OnX1165: + getmapxy(.@m$, .@x, .@y, 0); + .@x1=.@x-2; + .@y1=.@y-2; + .@x2=.@x+2; + .@y2=.@y+2; + .@x=cap_value(rand2(.@x1, .@x2), 47, 65); + .@y=cap_value(rand2(.@y1, .@y2), 191, 212); + makeitem(AquaTicket, any(1, 1, 2), .@m$, .@x, .@y); + end; + +/* Experimental */ +On1162: + spawn(Grinchboo, 2); + end; +On1130: + spawn(Moonshroom); + end; + +/* Ice Caves */ +On1093: + spawn(WhiteSlime); + end; +On1060: + spawn(Archant); + end; +On1080: + spawn(BlueSpark); + end; +On1081: + spawn(RedSpark); + end; +On1100: + spawn(AzulSlime); + end; +On1015: + spawn(SantaSlime); + end; +On1061: + spawn(Moggun); + end; +On1072: + spawn(Yeti); + end; +On1040: + spawn(Wisp); + end; +On1047: + spawn(Poltergeist); + end; +On1042: + spawn(Spectre); + end; +On1125: + spawn(ManaGhost); + end; +On1071: + spawn(IceElement); + end; +On1085: + spawn(IceSkull); + end; +On1114: + spawn(Nutcracker); + end; +On1020: + spawn(Fluffy); + end; + +/* Woodlands */ +On1084: + spawn(CrotcherScorpion); + end; +On1041: + spawn(Snail); + end; +On1049: + spawn(Bee); + end; +On1055: + spawn(Butterfly); + end; +On1014: + spawn(PinkFlower); + end; +On1018: + spawn(Pinkie); + end; +On1088: + spawn(Hyvern); + end; +On1103: + spawn(WitchGuard); + end; + +/* Ambush */ +On1140: + spawn(Tengu); + end; +On1138: + spawn(ManaGuardian); + end; +On1143: + spawn(ManaSlayer); + end; +On1150: + spawn(ManaTyrant); + end; +On1147: + spawn(Koyntety); + end; +On1146: + spawn(Flashmob); + end; + +/* Other Christmas settings */ +OnInstanceInit: + /* Prepare the color code */ + 'COLORCODE[0] = rand2(0, 2); + 'COLORCODE[1] = rand2(0, 2); + 'COLORCODE[2] = rand2(0, 2); + 'COLORCODE[3] = rand2(0, 2); + 'COLORCODE[4] = rand2(0, 2); + 'COLORCODE[5] = rand2(0, 2); + 'OBSCURECOLOR = any(0, 1); + + /* Prepare the Ambush Chamber */ + 'AMBUSHTRI[0] = rand2(1, 17); + do + { + 'AMBUSHTRI[1] = rand2(1, 17); + } while ('AMBUSHTRI[1] == 'AMBUSHTRI[0]); + do + { + 'AMBUSHTRI[2] = rand2(1, 17); + } while ('AMBUSHTRI[2] == 'AMBUSHTRI[0] || 'AMBUSHTRI[2] == 'AMBUSHTRI[1]); + 'AMBUSH_BMASK = 0; + + /* Prepare the Enigma */ + 'TRUES=0; + 'TRUTHSTAT[0]=any(false, true); + if ('TRUTHSTAT[0]) + 'TRUES+=1; + 'TRUTHSTAT[1]=any(false, true); + if ('TRUTHSTAT[1]) + 'TRUES+=1; + 'TRUTHSTAT[2]=any(false, ('TRUES >= 2 ? false : true)); + 'TRUES=0; + end; + +OnInit: + /* Aethyra - Frontier Town */ + "#XMAS21Core"::spawn(Fluffy, 16, "081-1"); + "#XMAS21Core"::spawn(Poltergeist, 7, "081-1"); + "#XMAS21Core"::spawn(Wisp, 7, "081-1"); + "#XMAS21Core"::spawn(Spectre, 7, "081-1"); + "#XMAS21Core"::spawn(WhiteSlime, 12, "081-1"); + "#XMAS21Core"::spawn(SantaSlime, 4, "081-1"); + "#XMAS21Core"::spawn(Moggun, 10, "081-1"); + "#XMAS21Core"::spawn(Moonshroom, 7, "081-1"); + end; +} + + diff --git a/npc/functions/clear_vars.txt b/npc/functions/clear_vars.txt index e5e6e5d4..aac27666 100644 --- a/npc/functions/clear_vars.txt +++ b/npc/functions/clear_vars.txt @@ -1,7 +1,11 @@ +// Update variables on server init, login and logout -function script ClearVariables { - if (@login_event != 1) goto L_Deprecated; +function script isChristmas21 { + // FIXME: 12/12 = 346; 26/12 = 360; 09/01 = 9 (OBVIOUSLY) + return (gettime(8) >= 346 || gettime(8) <= 360 || $@XMAS21_OVERRIDE); +} +function script ClearVariables { // Some temporary bugfix GM = getgroupid(); @@ -138,10 +142,38 @@ function script ClearVariables { //QUEST_MAGIC2 = 0; OrumQuest = 0; } + + // Christmas 2021 Event + if (isChristmas21()) { + #OLD_EXP=BaseExp; + #OLD_LV=BaseLevel; + } return; } +function script FlushVariables { + // Some variables should not be saved + GM = 0; + ##01_TMWEXP = 0; + + // Christmas 2021 Event + if (isChristmas21()) { + #NEW_LV+=(BaseLevel-#OLD_LV); + if (BaseLevel != #OLD_LV) { + #NEW_EXP=BaseExp; + } else { + #NEW_EXP+=BaseExp-#OLD_EXP; + } + #OLD_EXP=0; + #OLD_LV=0; + if (getvaultid()) ##01_TMWEXP=#NEW_EXP; // (Techinically wrong) + } + return; +} + + + function script ServerUpdate { if ($@STARTUP) { debugmes "Cowardly refusing to update server outside startup"; diff --git a/npc/functions/global_event_handler.txt b/npc/functions/global_event_handler.txt index b63fb28f..f94e7fc8 100644 --- a/npc/functions/global_event_handler.txt +++ b/npc/functions/global_event_handler.txt @@ -15,7 +15,7 @@ OnPCLoginEvent: end; OnPCLogoutEvent: - GM = 0; + FlushVariables(); vaultOnLogout(); end; diff --git a/npc/functions/mob_points.txt b/npc/functions/mob_points.txt index b4361f0a..fb13def9 100644 --- a/npc/functions/mob_points.txt +++ b/npc/functions/mob_points.txt @@ -15,6 +15,17 @@ function script MobPoints { MONSTERS_KILLED+=1; @mobId=killedrid; + if (isChristmas21() && compare(getmap(), "@"+callfunc("X21ID2"))) { + if (getmonsterinfo(getarg(0), MOB_LV) >= 150) + getitem AquaTicket, 2; + else if (getmonsterinfo(getarg(0), MOB_LV) >= 100 && any(true, false)) + getitem AquaTicket, 2; + else if (getmonsterinfo(getarg(0), MOB_LV) >= 40 && any(true, false, false)) + getitem AquaTicket, 1; + else if (rand2(5) == 3) + getitem AquaTicket, 1; + } + if (MPQUEST) { .@moblv=strmobinfo(3,killedrid); diff --git a/npc/functions/vault.txt b/npc/functions/vault.txt index 4f45c871..2022b726 100644 --- a/npc/functions/vault.txt +++ b/npc/functions/vault.txt @@ -88,6 +88,8 @@ function script vaultOnLogout { "VAR1V", ##01_TMWQUEST, "VAR2N", "TMWGLOBAL", "VAR2V", ##01_TMWGLOBAL, + "VAR2N", "TMWEXP", + "VAR2V", ##01_TMWEXP, "VEXP", ##VAULT_EXP, "GOTO", ##VAULT_GOTO, "MLTO", ##VAULT_MLTO); diff --git a/npc/magic/config.txt b/npc/magic/config.txt index f8135b43..285fa379 100644 --- a/npc/magic/config.txt +++ b/npc/magic/config.txt @@ -237,7 +237,6 @@ function script rectharm { continue; harm(.@mbs[.@i], .@d, .@t, .@e); specialeffect(FX_ATTACK, AREA, .@mbs[.@i]); - // TODO: Handle MobPt to don't overload timer system? } return; } diff --git a/npc/scripts.conf b/npc/scripts.conf index 2b6aa0f8..c5f4bc98 100644 --- a/npc/scripts.conf +++ b/npc/scripts.conf @@ -126,6 +126,7 @@ "npc/annuals/xmas/list.txt", "npc/annuals/xmas/reagents.txt", "npc/annuals/xmas/mobmanager.txt", +"npc/annuals/xmas/2021.txt", "npc/annuals/halloween/config.txt", "npc/annuals/halloween/debug.txt", "npc/annuals/halloween/munro.txt", |