// TMW 2 Script // Author: // Jesusalva // Micksha // Description: // Controls the showdown 042-11,41,57,0 script #KDoor04211a NPC_HIDDEN,4,0,{ end; OnTouch: .@g=getcharid(2); if (.@g < 1) die(); if (!($KAMELOT_QUEST[.@g] & 64)) goto L_NoAccess; warp "042-10@"+.@g, 143, 21; end; L_NoAccess: dispbottom l("Can't leave right now."); end; } 042-11,20,28,0 script #KDoor04211b NPC_HIDDEN,0,2,{ end; OnTouch: .@g=getcharid(2); if (.@g < 1) die(); if (!($KAMELOT_QUEST[.@g] & 64)) goto L_NoAccess; mes l("Are you sure you want leave?"); mesc l("You wont be able to go back!"); next; if (askyesno() == ASK_YES) { warp "042-0@"+.@g, 46, 25; callfunc("KamelotTreasure", 1024, true); // Give a reward from the exclusive chest } close; L_NoAccess: dispbottom l("Can't leave right now."); end; } 042-11,0,0,0 script #KamelotBoss NPC_HIDDEN,{ end; OnDialog: announce "??? : "+l("Who sent you here? Merlin?"), bc_self|bc_pc; addtimer 8000, "#KamelotBoss::OnDialog2"; end; OnDialog2: .@g=getcharid(2); announce "??? : "+l("It matters not, because soon, all of you will be..."), bc_self|bc_pc; addtimer 7000, instance_npcname("#KamelotBoss", $@KAMELOT_ID[.@g])+"::OnBegin"; end; // Spawns Terogan OnBegin: .@g=getcharid(2); .@m$=instance_mapname("042-11"); .@avg=$KAMELOT_MX[.@g]+10; .@n$=instance_npcname("#KamelotBoss", $@KAMELOT_ID[.@g]); debugmes "GID: %d Map: %s Power: %d Label: %s", .@g, .@m$, .@avg, .@n$; // Dialog announce l("General Terogan : DEAD! Muahahahaha!"), bc_self|bc_pc; // Check if Terogan doesn't exists already .@exist=getd("$@GTEMP_"+.@m$); if (.@exist) end; // Check if quest isn't over already '-' if ($KAMELOT_QUEST[.@g] & 64) end; // Bring Terogan into existence .@mob=monster(.@m$, 40, 30, strmobinfo(1, GeneralTerogan), GeneralTerogan, 1, .@n$+"::OnKillBoss"); setd("$@GTEMP_"+.@m$, .@mob); setd("$@GTEMP_HP_"+.@m$, 20); // Reconfigure the monster setunitdata(.@mob, UDT_LEVEL, .@avg); setunitdata(.@mob, UDT_STR, 1+.@avg/2); setunitdata(.@mob, UDT_AGI, 1+.@avg/2); setunitdata(.@mob, UDT_VIT, 1+.@avg/2); setunitdata(.@mob, UDT_INT, 1+.@avg/2); setunitdata(.@mob, UDT_DEX, 1+.@avg/2); setunitdata(.@mob, UDT_LUK, 1+.@avg/2); setunitdata(.@mob, UDT_ADELAY, 1072); setunitdata(.@mob, UDT_ATKRANGE, 4); // Battle Status setunitdata(.@mob, UDT_MAXHP, .@avg*700); setunitdata(.@mob, UDT_HP, .@avg*700); setunitdata(.@mob, UDT_ATKMIN, .@avg*7); setunitdata(.@mob, UDT_ATKMAX, .@avg*9); setunitdata(.@mob, UDT_DEF, 4+.@avg); setunitdata(.@mob, UDT_MDEF, 1+.@avg); setunitdata(.@mob, UDT_HIT, .@avg*18); // Advised: x3 setunitdata(.@mob, UDT_FLEE, .@avg*5); // Advised: x4 setunitdata(.@mob, UDT_CRIT, 120); // Initial batch of reinforcements KamelotCaveSpawn(6, 30, 20, 50, 40, .@avg, "042-11"); // Save info again setd("$@GTEMP_"+.@m$, .@mob); setd("$@GTEMP_HP_"+.@m$, 20); initnpctimer; end; // Checks HP ratio again OnTimer5000: explode(.@map$, .map$, "@"); .@g=atoi(.@map$[1]); if (.@g < 1) { consolebug "[ERROR] [KAMELOT] Unable to find Terogan - Kamelot %s", .map$; .@g=0; } // Retrieve Terogan's GUID and MAP ID .@m$=instance_mapname("042-11"); .@mob=getd("$@GTEMP_"+.@m$); // Prepare the reinforcement strength data (min 3 Lv 22 spawn) .@gcount=$KAMELOT_PC[.@g]+2; .@avg=$KAMELOT_MX[.@g]+rand2(22, 27); // Calculate current HP ratio and the difference .@ratio=getunitdata(.@mob, UDT_HP)*20/getunitdata(.@mob, UDT_MAXHP); .@hplos=getd("$@GTEMP_HP_"+.@m$)-.@ratio; //debugmes "Ratio %d/%d", .@ratio, getd("$@GTEMP_HP_"+.@m$); if (.@ratio < getd("$@GTEMP_HP_"+.@m$)) { mapannounce .@m$, "General Terogan : "+any("Charge!", "To the Abyss with you already!", "Kill them already!", "More of them might be coming!", "Minions, ATTACK!", "Muahahaha, Pathetic!"), 0; // Unlike Krukan, spawn according to HP loss (no use fast killing) KamelotCaveSpawn(.@gcount*max(1, .@hplos), 20, 20, 57, 40, .@avg, "042-11"); } // Special skills (seldomly, but entirely randomly, triggered) if (rand2(10000) < ($KAMELOT_MX[.@g] + $KAMELOT_PC[.@g] + getguildlvl(.@g))) { // Taken from Aurora Boss Raid and Blanc .@skill = rand2(10); getmapxy(.@m$, .@x, .@y, UNITTYPE_MOB, .@mob); .@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); } } .@lv = $KAMELOT_MX[.@g]; .@t = rand2(2 + .@lv / 10); // Execute the skill switch (.@skill) { case 1: .@msg$ = sprintf("Witness my sublime rain of death. Regeneration!"); .@hp=getunitdata(.@mob, UDT_HP); .@mp=getunitdata(.@mob, UDT_MAXHP); setunitdata(.@mob, UDT_HP, min(.@mp, .@hp+(.@lv * 50))); .@mobid=(rand2(.@lv) > 50 ? DeathCat : GreenSlime); monster(.@m$, .@x, .@y, strmobinfo(1, .@mobid), .@mobid, 1); break; case 2: .@msg$ = sprintf("Chaos shall be my founding stone! Falling star!"); attachrid(.@rnd); percentheal -5, -10; detachrid(); .@mobid=(rand2(.@lv) > 50 ? BlackScorpion : RedSlime); monster(.@m$, .@x, .@y, strmobinfo(1, .@mobid), .@mobid, 1); break; case 3: .@msg$ = sprintf("I demand this world! Tyranny!"); attachrid(.@rnd); percentheal -1, -1; SC_Bonus(.@t, any(SC_BLIND, SC_POISON), 1); detachrid(); .@mobid=(rand2(.@lv) > 50 ? DarkLizard : Assassin); monster(.@m$, .@x, .@y, strmobinfo(1, .@mobid), .@mobid, 1); break; case 4: .@msg$ = sprintf("Stop on your tracks, unfair being! Freeze!"); attachrid(.@rnd); SC_Bonus((.@t / 2), any(SC_FREEZE, SC_SLEEP, SC_SLEEP, SC_SLEEP), 1); detachrid(); .@mobid=(rand2(.@lv) > 50 ? BlueSlime : WhiteSlime); monster(.@m$, .@x, .@y, strmobinfo(1, .@mobid), .@mobid, 1); break; case 5: .@msg$ = sprintf("There is no free speech. Censorship!"); attachrid(.@rnd); SC_Bonus(.@t, SC_SILENCE, 1); detachrid(); .@mobid=(rand2(.@lv) > 50 ? Thug : RedMushroom); monster(.@m$, .@x, .@y, strmobinfo(1, .@mobid), .@mobid, 1); break; case 6: .@msg$ = sprintf("And then... There was a quake. And all life died. Bleed!"); attachrid(.@rnd); SC_Bonus(.@t, SC_BLOODING, 1); detachrid(); .@mobid=(rand2(.@lv) > 50 ? BlackSlime : OldSnake); monster(.@m$, .@x, .@y, strmobinfo(1, .@mobid), .@mobid, 1); break; case 7: .@msg$ = sprintf("Puny mortal, do your best to entertain me! Curse!"); attachrid(.@rnd); SC_Bonus(.@t, SC_CURSE, 1); detachrid(); .@mobid=(rand2(.@lv) > 50 ? FireSkull : Skeleton); monster(.@m$, .@x, .@y, strmobinfo(1, .@mobid), .@mobid, 1); break; case 8: .@msg$ = sprintf("The problem with typos is - unpredictable side effects."); attachrid(.@rnd); SC_Bonus(.@t, any(SC_SILENCE, SC_CURSE, SC_FREEZE, SC_BLOODING, SC_BLIND, SC_POISON, SC_DPOISON, SC_POISON, SC_BURNING, SC_SLEEP), 1); detachrid(); .@mobid=(rand2(.@lv) > 50 ? Swashbuckler : Bluepar); monster(.@m$, .@x, .@y, strmobinfo(1, .@mobid), .@mobid, 1); break; case 9: // Second Attack Pattern: Holy Light (vs Tank) .@msg$ = sprintf("%s, I'll show you no mercy! ##BThunder Bolt##b!", strcharinfo(0, "cursed player", .@mvp)); .@PW=125; .@SPW=25; .@RG=1; .@mtk = calcdmg(.@mob, .@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; default: // First Attack Pattern: Napalm Beat (vs Random) .@msg$ = sprintf("This battle is over, %s! ##BThunder Neddle##b!", strcharinfo(0, "cursed player", .@rnd)); .@PW=35; .@SPW=5; .@RG=2; .@mtk = calcdmg(.@mob, .@rnd, HARM_MAGI); .@dmg = .@mtk * .@PW / 100; .@dsb = .@mtk * .@SPW / 100; sleep(1000); specialeffect(FX_LIGHTNING, AREA, .@rnd); areaharm(.@rnd, .@RG, .@dsb, HARM_MAGI, Ele_Wind, "filter_always", BL_PC|BL_MER|BL_HOM); harm(.@rnd, .@dmg, HARM_MAGI, Ele_Holy); break; } unittalk(.@mob, .@msg$); } // Always update the ratio - Terogan could have been healed setd("$@GTEMP_HP_"+.@m$, .@ratio); initnpctimer; end; // Monks Rewards OnKillMob: // Maybe a reward is due .@g=getcharid(2); if (.@g < 1) die(); getexp $KAMELOT_MX[.@g]*8, $KAMELOT_MX[.@g]*4; // Lower than previously end; // Boss rewards OnKillBoss: stopnpctimer; if (playerattached()) { // Setup .@g=getcharid(2); .@m$=getmap(); .@hero$=strcharinfo(0); // Player Reward for completing this stage getitem GuildCoin, 10; getexp $KAMELOT_MX[.@g]*150, $KAMELOT_MX[.@g]*30; specialeffect(FX_FANFARE, AREA, getcharid(3)); } else { explode(.@map$, .map$, "@"); .@g=atoi(.@map$[1]); if (.@g < 1) { consolebug "[ERROR] [KAMELOT] Unable to find Terogan Death %s", .map$; .@g=0; } .@m$=.map$; .@hero$="The guild"; } // Mark quest as completed $KAMELOT_QUEST[.@g]=$KAMELOT_QUEST[.@g]|64; // Get rid of temporary variables setd("$@GTEMP_"+.@m$, 0); setd("$@GTEMP_HP_"+.@m$, 0); killmonsterall(.@m$); // Guild Reward for completing this stage .@ggp=2000+$KAMELOT_MX[.@g]*100; .@gxp=$KAMELOT_MX[.@g]*250; $GUILD_BANK[.@g]+=.@ggp; guildgetexp(.@gxp); // Silently fails if no char attached // Announce mapannounce .@m$, .@hero$+" has defeated the evil in Kamelot!", 0; // Spawn GMGiftBox upon end .@gf=min(30, $KAMELOT_MX[.@g]/5); areamonster(.@m$, 20, 20, 57, 40, strmobinfo(1, GMGiftBox), GMGiftBox, .@gf); // Spawn Treasure Chests upon end .@gl=$KAMELOT_MX[.@g]; .@gtype=(.@gl > 100 ? SupremeChest : (.@gl > 75 ? PrismChest : (.@gl > 50 ? GoldenChest : (.@gl > 25 ? SilverChest : BronzeChest)))); .@gf=$KAMELOT_PC[.@g]; areamonster(.@m$, 20, 20, 57, 40, strmobinfo(1, .@gtype), .@gtype, .@gf); // Possibly, we forgot stuff in Throne Room... killmonsterall("042-0@"+.@g); // Guild Master Notification .@gm$=getguildmaster(.@g); if (!getcharid(3, .@gm$)) end; .@gma=getcharid(3, .@gm$); .@gmb=getcharid(0, .@gm$); if (!isloggedin(.@gma, .@gmb)) end; message .@gm$, strcharinfo(0)+" defeated the boss: Guild GP +"+.@ggp+" Guild XP +"+.@gxp; end; // Instance OnInstanceInit: end; }