diff options
author | Jesusaves <cpntb1@ymail.com> | 2022-10-23 21:44:22 -0300 |
---|---|---|
committer | Jesusaves <cpntb1@ymail.com> | 2022-10-23 21:44:22 -0300 |
commit | a7c45a192268da2601cef47a4cdba987ae2327ca (patch) | |
tree | c5fb5b97db109fe7106496dd96498c475881046b /npc/006-7 | |
download | serverdata-a7c45a192268da2601cef47a4cdba987ae2327ca.tar.gz serverdata-a7c45a192268da2601cef47a4cdba987ae2327ca.tar.bz2 serverdata-a7c45a192268da2601cef47a4cdba987ae2327ca.tar.xz serverdata-a7c45a192268da2601cef47a4cdba987ae2327ca.zip |
Initial commit (Moubootaur Legends fork)
Diffstat (limited to 'npc/006-7')
-rw-r--r-- | npc/006-7/_import.txt | 3 | ||||
-rw-r--r-- | npc/006-7/ctrl.txt | 354 |
2 files changed, 357 insertions, 0 deletions
diff --git a/npc/006-7/_import.txt b/npc/006-7/_import.txt new file mode 100644 index 0000000..87e9595 --- /dev/null +++ b/npc/006-7/_import.txt @@ -0,0 +1,3 @@ +// Map 006-7: Aethyr Chamber +// This file is generated automatically. All manually added changes will be removed when running the Converter. +"npc/006-7/ctrl.txt", diff --git a/npc/006-7/ctrl.txt b/npc/006-7/ctrl.txt new file mode 100644 index 0000000..17243b5 --- /dev/null +++ b/npc/006-7/ctrl.txt @@ -0,0 +1,354 @@ +// TMW2 Script +// Author: +// Jesusalva + +006-7 mapflag zone MMO + +006-7,44,50,0 script #OutOf0067 NPC_HIDDEN,0,0,{ + end; + +OnTouch: + if (!$@ICICLE_CHALLENGE) + warp "006-6", 40, 36; + end; + +OnRw: + getexp 1000000, 0; + Mobpt += 10000; + dispbottom l("Der Schneemann has been defeated: %s Monster Points gained.", fnum(10000)); + RegEasterEgg(EE_SNOWMAN, 25); + specialeffect(FX_FANFARE, SELF, getcharid(3)); + end; +} + +006-7,44,35,0 script Ice Lord NPC_YETIFLY,{ + if ($@ICICLE_CHALLENGE) end; + if (.ticks > gettimetick(2)) { + mesn; + mesq l("This challenge will be available in %s. Please wait until then.", FuzzyTime(.ticks)); + close; + } + mesn; + mesq l("With Magic and Blades, The Icicle shall break. Do you undertake the challenge?"); + mesc l("Advised: 6+ players"), 1; + mesc l("Advised: 1+ mage, 1+ tanker, 2+ healers"), 1; + mesc l("Time Limit: 90 minutes"), 1; + mesc l("Enter/Leave after start: %s", b(l("NO"))), 1; + next; + select + l("Not yet."), + l("Bring it on!"), + rif(REBIRTH, l("Bring me, my worst nightmare.")); + mes ""; + if (@menu == 1) { + closeclientdialog; + close; + } + if (@menu == 2) + .hard = false; + else + .hard = true; + + // Der Schneemann + .ticks = gettimetick(2) + 5400; // 90 minutes + .BOSS = monster("006-7", 44, 36, "The Icicle", SnowmanBoss, 1); + .@mlt = (.hard ? 15 : 10); + + // Basic attributes + setunitdata(.BOSS, UDT_MAXHP, 750000 * .@mlt / 10); // 750k ~ 1250k + setunitdata(.BOSS, UDT_HP, 750000 * .@mlt / 10); + setunitdata(.BOSS, UDT_ATKRANGE, (.hard ? 7 : 6)); + + // Reconfigure the AI + .@opt=getunitdata(.BOSS, 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(.BOSS, UDT_MODE, .@opt); + + // Nerf the damage, but never miss a hit + setunitdata(.BOSS, UDT_ATKMIN, 60 * .@mlt / 10); // 60~90 dmg + setunitdata(.BOSS, UDT_ATKMAX, 60 * .@mlt / 10); + setunitdata(.BOSS, UDT_ADELAY, 2220 / .@mlt * 10); // 2220 or 1480ms + setunitdata(.BOSS, UDT_HIT, 2400); + + // 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 + + $@ICICLE_CHALLENGE = true; + disablenpc .name$; + initnpctimer; + closeclientdialog; + close; + +// Fail-safe Mechanism (will never happen) +OnTimer60000: + consolebug("Warning! final fail-safe mechanism triggered to Icicle."); + initnpctimer; + end; +OnTimer25000: +OnTimer15000: + consolewarn("Warning, fail-safe mechanism triggered to Icicle."); +// This is the boss' core +OnTimer5000: + /* Maybe the fight is over */ + if (!mobcount("006-7", "all")) + maptimer2("006-7", 10, "#OutOf0067::OnRw"); + if (.ticks < gettimetick(2) || !mobcount("006-7", "all") || !getmapusers("006-7")) { + killmonsterall("006-7"); + enablenpc .name$; + npctalk "The battle is over!"; + .ticks = min(.ticks, gettimetick(2) + 1800); // Min. Cooldown: 30 min + .beats = 0; + .warn = 0; + $@ICICLE_CHALLENGE = false; + stopnpctimer; + end; + } + + /* Warn players when time is about to end */ + if (.ticks - 1800 < gettimetick(2) && .warn < 1) { + mapannounce("006-7", "Warning : ##1##BTime left: 30 minutes##b", 0); + .warn = 1; + } + else if (.ticks - 900 < gettimetick(2) && .warn < 2) { + mapannounce("006-7", "Warning : ##1##BTime left: 15 minutes##b", 0); + .warn = 2; + } + else if (.ticks - 600 < gettimetick(2) && .warn < 3) { + mapannounce("006-7", "Warning : ##1##BTime left: 10 minutes##b", 0); + .warn = 3; + } + else if (.ticks - 300 < gettimetick(2) && .warn < 4) { + mapannounce("006-7", "Warning : ##1##BTime left: 5 minutes##b", 0); + .warn = 4; + } + + /* Prepare some data */ + .@hp = getunitdata(.BOSS, UDT_HP) * 10 / getunitdata(.BOSS, UDT_MAXHP); + getmapxy(.@m$, .@x, .@y, UNITTYPE_MOB, .BOSS); + .@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; + + /* Everyone is dead, get rid of them */ + if (!.@mvp || !.@rnd) { + mapwarp("006-7", "006-6", 40, 36); + initnpctimer; + 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 0: + case 6: + case 12: + unittalk(.BOSS, "Come forth, ##Bsnow army##b, for the Icicle shall live forever!"); + specialeffect(65, AREA, .BOSS); // Actually 64, but won't do well here + sleep(1000); + monster("006-7", 44, 22, strmobinfo(1, Snowman), Snowman, max(1, (11 - .@hp) / 10)); + break; + // (2/6) Tanker (~30s) + case 1: + case 4: + case 7: + case 10: + case 13: + case 16: + specialeffect(702, AREA, .BOSS); + sleep(1000); + if (.@hp < 3) { + // Third Attack Pattern: Judgment + unittalk(.BOSS, sprintf("%s cannot stop me! ##BJudgment##b!", strcharinfo(0, "cursed player", .@mvp))); + .@PW=240; .@SPW=60; .@RG=3; + } else if (.@hp < 7) { + // Second Attack Pattern: Holy Light + unittalk(.BOSS, sprintf("%s, I'll show you no mercy! ##BHoly Light##b!", strcharinfo(0, "cursed player", .@mvp))); + .@PW=125; .@SPW=25; .@RG=1; + } else { + // First Attack Pattern: Napalm Beat + unittalk(.BOSS, sprintf("This battle is over, %s! ##BNapalm Beat##b!", strcharinfo(0, "cursed player", .@mvp))); + .@PW=35; .@SPW=5; .@RG=2; + } + .@mtk = calcdmg(.BOSS, .@mvp, HARM_MAGI); + .@dmg = .@mtk * .@PW / 100; + .@dsb = .@mtk * .@SPW / 100; + sleep(1000); + areaharm(.@mvp, .@RG, .@dsb, HARM_MAGI, Ele_Holy, "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(50, AREA, .BOSS); + sleep(1000); + .@time=rand2(18000, 36000) + 10000 - (.@hp * 1000); + // Switch between curse and disable + if (any(true,false)) { + unittalk(.BOSS, sprintf("I hereby ##Bcurse##b you, %s!", strcharinfo(0, "cursed player", .@rnd))); + sc_start(SC_CURSE, .@time, 1, 10000, SCFLAG_FIXEDRATE, .@rnd); + } else { + unittalk(.BOSS, 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); + } + break; + // (4/6) Traps (~60s) + case 3: + case 9: + case 15: + .@x1=rand2(31, 58); .@x2=rand2(31, 58); .@x3=rand2(31, 58); + .@y1=rand2(23, 49); .@y2=rand2(23, 49); .@y3=rand2(23, 49); + .@t1=monster("006-7", .@x1, .@y1, "", Dummy, 1); + .@t2=monster("006-7", .@x2, .@y2, "", Dummy, 1); + .@t3=monster("006-7", .@x3, .@y3, "", Dummy, 1); + specialeffect(67, AREA, .@t1); + specialeffect(67, AREA, .@t2); + specialeffect(67, AREA, .@t3); + immortal(.@t1); immortal(.@t2); immortal(.@t3); + if (.@hp < 5 || .hard) { + .@x4=rand2(31, 58); .@x5=rand2(31, 58); .@x6=rand2(31, 58); + .@y4=rand2(23, 49); .@y5=rand2(23, 49); .@y6=rand2(23, 49); + .@t4=monster("006-7", .@x1, .@y1, "", Dummy, 1); + .@t5=monster("006-7", .@x2, .@y2, "", Dummy, 1); + .@t6=monster("006-7", .@x3, .@y3, "", Dummy, 1); + specialeffect(67, AREA, .@t4); + specialeffect(67, AREA, .@t5); + specialeffect(67, AREA, .@t6); + immortal(.@t4); immortal(.@t5); immortal(.@t6); + } + sleep(2000); + specialeffect(11, AREA, .@t1); + specialeffect(11, AREA, .@t2); + specialeffect(11, AREA, .@t3); + if (.@hp < 5 || .hard) { + specialeffect(11, AREA, .@t4); + specialeffect(11, AREA, .@t5); + specialeffect(11, AREA, .@t6); + } + areaharm(.@t1, 2, 450, HARM_MISC, Ele_Neutral, "filter_always", BL_PC|BL_MER|BL_HOM); + areaharm(.@t2, 2, 450, HARM_MISC, Ele_Neutral, "filter_always", BL_PC|BL_MER|BL_HOM); + areaharm(.@t3, 2, 450, HARM_MISC, Ele_Neutral, "filter_always", BL_PC|BL_MER|BL_HOM); + if (.@hp < 5 || .hard) { + areaharm(.@t4, 2, 450, HARM_MISC, Ele_Neutral, "filter_always", BL_PC|BL_MER|BL_HOM); + areaharm(.@t5, 2, 450, HARM_MISC, Ele_Neutral, "filter_always", BL_PC|BL_MER|BL_HOM); + areaharm(.@t6, 2, 450, HARM_MISC, Ele_Neutral, "filter_always", BL_PC|BL_MER|BL_HOM); + } + sleep(1000); + // FIXME: M+ fails to remove them, need @refresh + unitkill(.@t1); unitkill(.@t2); unitkill(.@t3); + if (.@hp < 5 || .hard) { + unitkill(.@t4); unitkill(.@t5); unitkill(.@t6); + } + break; + // (5/6) Weak AOE (~60s) + case 5: + case 11: + case 17: + specialeffect(60, AREA, .BOSS); + sleep(500); + switch (rand2(3)) { + case 1: + unittalk(.BOSS, "I shall ##Bpoison##b you all!"); + .@sc = (.@hp < 1 ? SC_DPOISON : SC_POISON); + break; + case 2: + unittalk(.BOSS, "I shall ##Bhurt##b you all!"); + .@sc = SC_BLOODING; + break; + case 3: + unittalk(.BOSS, "I shall ##Bsilence##b you all!"); + .@sc = SC_SILENCE; + break; + default: + unittalk(.BOSS, "I shall ##Bcripple##b you all!"); + .@sc = SC_BLIND; + break; + } + areasc((.hard ? 7 : 6), 45000, .@sc, BL_PC|BL_HOM|BL_MER, 1, "filter_always", .BOSS, 95000); + areaharm(.BOSS, (.hard ? 7 : 6), 100, HARM_MAGI, Ele_Water, "filter_always", BL_PC|BL_MER|BL_HOM); + break; + } + // Strong AOE: Every 3 minutes (case = 0) + // Stalls all other skills for a while + if (.beats % 18 == 0) { + specialeffect(66, AREA, .BOSS); + unittalk(.BOSS, "I am the Icicle, the immortal."); + sleep((.hard ? 1000 : 1500)); + specialeffect(700, AREA, .BOSS); + unittalk(.BOSS, "You're no match for me, so..."); + sleep((.hard ? 1000 : 1500)); + specialeffect(700, AREA, .BOSS); + if (.@hp < 3) { + unittalk(.BOSS, "Perish! ##BSnowstorm##b!"); + .@dmg=rand2(900, 1100); + areasc(3, 5000, SC_FREEZE, BL_PC|BL_HOM|BL_MER, 1, "filter_always", .BOSS, 2000); + areasc(6, 10000, SC_BLIND, BL_PC|BL_HOM|BL_MER, 1, "filter_always", .BOSS, 2000); + } else if (.@hp < 7) { + unittalk(.BOSS, "Perish! ##BBlizzard##b!"); + .@dmg=rand2(650, 900); + areasc(3, 5000, SC_FREEZE, BL_PC|BL_HOM|BL_MER, 1, "filter_always", .BOSS, 1500); + } else { + unittalk(.BOSS, "Perish! ##BShattering Winds##b!"); + .@dmg=rand2(400, 650); + } + /* Three blocks */ + specialeffect(66, AREA, .BOSS); + areaharm(.BOSS, (.hard ? 7 : 6), .@dmg, HARM_MAGI, Ele_Neutral, "filter_always", BL_PC|BL_MER|BL_HOM); + sleep(500); + specialeffect(66, AREA, .BOSS); + areaharm(.BOSS, (.hard ? 18 : 12), .@dmg, HARM_MAGI, Ele_Water, "filter_always", BL_PC|BL_MER|BL_HOM); + sleep(500); + specialeffect(66, AREA, .BOSS); + specialeffect(312, AREA, .BOSS); + areaharm(.BOSS, (.hard ? 24 : 18), .@dmg, HARM_MAGI, Ele_Holy, "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", .BOSS, 10001 - (.@hp * 1000)); // FIXME + // SC_COLD freezes you, so trying SC_FROSTMISTY + } + + initnpctimer; + end; + +OnInit: + .distance = 4; + .ticks = gettimetick(2); + .beats = 0; + .hard = 0; + .warn = 0; + end; +} + |