// TMW 2 Script // Author: // Jesusalva // Micksha // Description: // Controls the great hall // None of the exits work 042-10,86,139,0 script #KDoor04210a NPC_HIDDEN,3,0,{ end; OnTouch: .@g=getcharid(2); if (.@g < 1) percentheal -100, -100; dispbottom l("OH NOES! The ceiling seems to have collapsed. I hope we got the key, or the quest is over for us!"); end; } 042-10,149,136,0 duplicate(#KDoor04210a) #KDoor04210b NPC_HIDDEN,0,0 042-10,21,139,0 duplicate(#KDoor04210a) #KDoor04210c NPC_HIDDEN,2,0 042-10,20,80,0 duplicate(#KDoor04210a) #KDoor04210d NPC_HIDDEN,0,6 // Boss Room control 042-10,142,20,0 script #KDoor04210e NPC_HIDDEN,4,0,{ end; OnTouch: .@g=getcharid(2); if (.@g < 1) percentheal -100, -100; if (!($KAMELOT_QUEST[.@g] & 8) || !($KAMELOT_QUEST[.@g] & 16) || !($KAMELOT_QUEST[.@g] & 32)) goto L_NoAccess; warp "042-11@"+.@g, 41, 56; // TODO Fire Events end; L_NoAccess: dispbottom l("A powerful door is sealed shut. It has no keyhole, but I'm sure it can be opened somewhere else on these caves."); //dispbottom l("This door is locked, if we only had a %s...", getitemlink(KamelotKey)); end; } // Boss Room Warning 042-10,150,25,0 script Warning#Kamelot NPC_HIDDEN,{ mesc ".:: "+l("DANGER!")+" ::.", 1; mes ""; mesc l("I've sealed a massive amount of dark magic here."), 1; mesc l("Do not break my seal to prevent the curse from reaching Kamelot."), 1; mes ""; mes l("-- Merlin"); close; OnInit: .distance=4; end; } // Magic Seal Main 042-10,135,42,0 script #KamelotSeal NPC_HIDDEN,0,4,{ end; OnTouch: .@g=getcharid(2); if (.@g < 1) percentheal -100, -100; if (!($KAMELOT_QUEST[.@g] & 16) && !($KAMELOT_QUEST[.@g] & 8)) goto L_NoAccessBlock; if (!($KAMELOT_QUEST[.@g] & 16) || !($KAMELOT_QUEST[.@g] & 8)) goto L_NoAccess; // You can pass freely, so we do nothing end; L_NoAccess: slide 127, 36; percentheal -5, -5; dispbottom l("A powerful magic barrier repeals you!"); dispbottom l("It's weaker than before, probably only one is working right now."); end; L_NoAccessBlock: slide 127, 36; percentheal -10, -10; dispbottom l("A powerful magic barrier repeals you!"); dispbottom l("We need to find what powers these two seals and disable it."); end; } //////////////////////////////////////////////////////////////////// // KatazuliInfo( ) function script KatazuliInfo { mes ".:: Magical Seal ::."; mes ""; mes l("The Magical Seal which protects the final room is too strong."); mes l("However, by casting %s here, we'll be able to weaken the seal!", b("katazuli")); next; mes l("To cast, one must sit on the circle and say the chant on general chat."); mes l("The chant must be exact, without any prefix or suffix."); next; mes l("While breaking the seal, monsters will spawn. They may drop %s.", getitemlink(DarkPetal)); mes l("Drop these near the circle to make the breaking faster."); next; mes l("Multiple players may conduct Katazuli at once. If you move or stand, the spell may be aborted."); mes l("Remember: Taking damage will make you stand!"); next; mes l("Katazuli breaking proccess will cause the breaker some harm."); mes l("It'll also drain mana in the proccess. If you run out of mana, its over."); next; mes l("After casting %s, you must wait %d seconds before casting it again.", b("katazuli"), b("60")); mes l("However, as long as you remain seated and immobile, the spell will slowly destroy the seal."); next; mesc l("Caution"), 1; mes l("The seals slowly grow stronger as time passes!"); mes l("Once broken, they'll lose the link to the magical seal."); mes l("Even if they recover their strength, because the connection was severed, the barrier will not power up again."); return; } // KatazuliCore( Begin, ID ) function script KatazuliCore { // Basic checks // Not sitting - Do nothing and cancel if (!issit()) end; // Not sitting on the circle - Again, do nothing getmapxy(.@m$, .@x, .@y, 0); if (.@x != .x || .@y != .y) end; // No mana - do nothing if (!Sp) end; // Initialize local variables .@start=getarg(0); .@id=getarg(1); .@g=getcharid(2); // User cooldown if (.@start && @katazuli >= gettimetick(2)) end; if (!.@start && @katazuli <= gettimetick(2)) end; // We should give a message if (.@start) @kataspam=0; // All checks passed: KATAZULI specialeffect FX_MGSHIELD, AREA, getcharid(3); // Temporary FX // Consume Dark Petals nearby .@cat=getareadropitem(getmap(), .x-3, .y-3, .x+3, .y+3, DarkPetal, true); // Your own power boost .@cat+=1; // Power the circle .@power=getd("$@GTEMP_"+.@id+"_"+.@m$)+.@cat; setd("$@GTEMP_"+.@id+"_"+.@m$, .@power); // Inform new status if (.@power < 5 && @kataspam != 1) { unittalk(getcharid(3), "This circle is nearly at full power! We need to shut down it!", true); @kataspam=1; } else if (.@power < 100 && @kataspam != 2) { unittalk(getcharid(3), "There is still too much power! Please drop "+getitemlink(DarkPetal)+" nearby!", true); @kataspam=2; } else if (.@power < 200 && @kataspam != 3) { unittalk(getcharid(3), "At this rate, we will do it! Keep going! Please drop "+getitemlink(DarkPetal)+" nearby!", true); @kataspam=3; } else if (.@power < 300 && @kataspam != 4) { unittalk(getcharid(3), "Guys I'm close to shut it down! Please drop "+getitemlink(DarkPetal)+" nearby!", true); @kataspam=4; } // Debug Information if (is_staff() && $@GM_OVERRIDE) dispbottom l("[DEBUG] Current Power: %d", .@power); // Circle was shut down (give rewards if appropriate) if (.@power >= 300) { if ($KAMELOT_QUEST[.@g] & .@id) end; $KAMELOT_QUEST[.@g]=$KAMELOT_QUEST[.@g]|.@id; unittalk(getcharid(3), "We did it! The seal is now broken!", true); // Player Reward for completing this stage getitem GuildCoin, 1; getexp $KAMELOT_MX[.@g]*50, $KAMELOT_MX[.@g]*10; // Guild Reward for completing this stage .@ggp=1200+$KAMELOT_MX[.@g]*10; .@gxp=$KAMELOT_MX[.@g]*25; $GUILD_BANK[.@g]+=.@ggp; guildgetexp(.@gxp); // 25xp per player average level (max 2500/3750) // Announce mapannounce getmap(), strcharinfo(0)+" has broken a magic seal!", 0; // Guild Master Notification .@gm$=getguildmaster(.@g); if (!getcharid(3, .@gm$)) return; .@gma=getcharid(3, .@gm$); .@gmb=getcharid(0, .@gm$); if (!isloggedin(.@gma, .@gmb)) return; message .@gm$, strcharinfo(0)+" broke a magic seal: Guild GP +"+.@ggp+" Guild XP +"+.@gxp; end; } // TODO: Spawn monsters, drop Dark Petal // (Probably spawn Dark Rose Field) // PS. Every monster in this floor will drop them getmapxy(.@m$, .@x, .@y, 0); .@x+=any(-3,-2,-1,1,2,3); .@y+=any(-3,-2,-1,1,2,3); monster(.@m$, .@x, .@y, strmobinfo(1, MagicGoblin), MagicGoblin, rand2(3,6)); // Take away some HP and MP, but do not make you stand percentheal -1, -1; sit(); // If it took all your mana - its over if (!Sp) end; // Set cooldown on start if (.@start) { dispbottom l("Please wait 60 seconds to cast again."); @katazuli=gettimetick(2)+60; } return; } //////////////////////// // Katazuli's Engravings 042-10,36,110,0 script Engraving#Katazuli1 NPC_HIDDEN,{ mes "Read tutorial?"; select l("No"), l("Yes"); if (@menu == 2) KatazuliInfo(); close; OnInit: .distance=4; end; } 042-10,124,85,0 duplicate(Engraving#Katazuli1) Engraving#Katazuli2 NPC_HIDDEN //////////////////////// // The first Katazuli 042-10,128,85,0 script #Katazuli01 NPC_SUMMONING_CIRC,0,0,{ dispbottom l("This looks magical, I wonder what it does."); end; OnInit: .kataId=8; .distance=3; .pid=getnpcid(); debugmes "Pattern %d", .pid; //defpattern(.pid, "^([Kk][Aa][Tt][Aa][Zz][Uu][Ll][Ii])$", "OnTalkNearby"); defpattern(.pid, "^(.*)$", "OnTalkNearby"); activatepset(.pid); end; OnTouch: npctalkonce l("You must %s and chant %s to begin channeling.", b(l("sit")), b(l("katazuli"))); end; OnTalkNearby: // not very obvious stuff by gumi .@no_nick$ = strip(substr($@p0$, getstrlen(strcharinfo(PC_NAME)) + 3, getstrlen($@p0$) - 1)); .@message$ = strtoupper(.@no_nick$); // It is with us! if (.@message$ == "KATAZULI") { KatazuliCore(true, .kataId); addtimer 6000, instance_npcname(.name$)+"::OnKatazuli"; } end; OnKatazuli: KatazuliCore(false, .kataId); addtimer 6000, instance_npcname(.name$)+"::OnKatazuli"; end; OnInstanceInit: initnpctimer; end; // Every minute, recover some energy OnTimer60000: explode(.@map$, .map$, "@"); .@g=atoi(.@map$[1]); if (.@g < 1) { debugmes "[ERROR] [KAMELOT] Unable to recharge katazuli for Kamelot %s", .map$; .@g=0; } // Estimate .@pc=$KAMELOT_PC[.@g]+1; .@pow=rand2(.@pc); // Recover energy .@id=.kataId; .@m$=instance_mapname("042-10"); .@power=min(0, getd("$@GTEMP_"+.@id+"_"+.@m$)-.@pow); setd("$@GTEMP_"+.@id+"_"+.@m$, .@power); initnpctimer; end; } //////////////////////// // The second Katazuli 042-10,32,108,0 script #Katazuli02 NPC_SUMMONING_CIRC,0,0,{ dispbottom l("This looks magical, I wonder what it does."); end; OnInit: .kataId=16; .distance=3; .pid=getnpcid(); debugmes "Pattern %d", .pid; //defpattern(.pid, "^([Kk][Aa][Tt][Aa][Zz][Uu][Ll][Ii])$", "OnTalkNearby"); defpattern(.pid, "^(.*)$", "OnTalkNearby"); activatepset(.pid); end; OnTouch: npctalkonce l("You must %s and chant %s to begin channeling.", b(l("sit")), b(l("katazuli"))); end; OnTalkNearby: // not very obvious stuff by gumi .@no_nick$ = strip(substr($@p0$, getstrlen(strcharinfo(PC_NAME)) + 3, getstrlen($@p0$) - 1)); .@message$ = strtoupper(.@no_nick$); // It is with us! if (.@message$ == "KATAZULI") { KatazuliCore(true, .kataId); addtimer 6000, instance_npcname(.name$)+"::OnKatazuli"; } end; OnKatazuli: KatazuliCore(false, .kataId); addtimer 6000, instance_npcname(.name$)+"::OnKatazuli"; end; OnInstanceInit: initnpctimer; end; // Every minute, recover some energy OnTimer60000: explode(.@map$, .map$, "@"); .@g=atoi(.@map$[1]); if (.@g < 1) { debugmes "[ERROR] [KAMELOT] Unable to recharge katazuli for Kamelot %s", .map$; .@g=0; } // Estimate .@pc=$KAMELOT_PC[.@g]+1; .@pow=rand2(.@pc); // Recover energy .@id=.kataId; .@m$=instance_mapname("042-10"); .@power=min(0, getd("$@GTEMP_"+.@id+"_"+.@m$)-.@pow); setd("$@GTEMP_"+.@id+"_"+.@m$, .@power); initnpctimer; end; } //////////////////////////////////////////////////////////////////// // KamelotSwitch( "_SWITCH ID" ) function script KamelotSwitch { // Extract ID .@n$=getarg(0, "_0"); explode(.@ni$, .@n$, "_"); .@id=atoi(.@ni$[1]); if (.@id <= 0) Exception("Unparseable switch: "+.@n$, RB_DEFAULT|RB_ISFATAL); .@g=getcharid(2); if (!($KAMELOT_KEYMASK[.@g] & $KAMELOT_KEY[.@g])) end; // Don't care .@st=($KAMELOT_PASSMASK[.@g] & .@id); mes l("Status: %s", (.@st ? col(l("Active"),2) : col(l("Inactive"),1) )); if (!countitem(KamelotKey)) close; mes "Change switch status?"; next; if (askyesno() == ASK_YES) { $KAMELOT_PASSMASK[.@g]=$KAMELOT_PASSMASK[.@g]^.@id; // The meaning of st is now mixed if (.@st) setnpcdisplay instance_npcname(.name$), NPC_SWITCH_OFFLINE; else setnpcdisplay instance_npcname(.name$), NPC_SWITCH_ONLINE; } // Check password and delete key if ($KAMELOT_PASSMASK[.@g] == $KAMELOT_PASSCODE[.@g]) { delitem KamelotKey, 1; $KAMELOT_QUEST[.@g]=$KAMELOT_QUEST[.@g]|32; mesc l("Your hear a clink, and the key breaks."), 2; // Player Reward for completing this stage getitem GuildCoin, 1; getexp $KAMELOT_MX[.@g]*50, $KAMELOT_MX[.@g]*10; // Guild Reward for completing this stage .@ggp=1200+$KAMELOT_MX[.@g]*10; .@gxp=$KAMELOT_MX[.@g]*25; $GUILD_BANK[.@g]+=.@ggp; guildgetexp(.@gxp); // 25xp per player average level (max 2500/3750) // Announce mapannounce getmap(), strcharinfo(0)+" has opened the gate!", 0; // Guild Master Notification .@gm$=getguildmaster(.@g); if (!getcharid(3, .@gm$)) return; .@gma=getcharid(3, .@gm$); .@gmb=getcharid(0, .@gm$); if (!isloggedin(.@gma, .@gmb)) return; message .@gm$, strcharinfo(0)+" opened the gate: Guild GP +"+.@ggp+" Guild XP +"+.@gxp; } return; } // Switches hints // TODO: NPC_PAPER_NOTE sprite 042-10,97,126,0 script #K4210Note01 NPC_SWORDS_SIGN,{ .@g=getcharid(2); if (!($KAMELOT_KEYMASK[.@g] & $KAMELOT_KEY[.@g])) end; // Don't care if ($KAMELOT_PASSCODE[.@g] & 1) dispbottom l("There is power on the north"); else dispbottom l("The north sleeps."); end; OnInit: .distance=4; end; } 042-10,139,98,0 script #K4210Note02 NPC_SWORDS_SIGN,{ .@g=getcharid(2); if (!($KAMELOT_KEYMASK[.@g] & $KAMELOT_KEY[.@g])) end; // Don't care if ($KAMELOT_PASSCODE[.@g] & 2) dispbottom l("There is power on the south"); else dispbottom l("The south sleeps."); end; OnInit: .distance=4; end; } 042-10,127,45,0 script #K4210Note04 NPC_SWORDS_SIGN,{ .@g=getcharid(2); if (!($KAMELOT_KEYMASK[.@g] & $KAMELOT_KEY[.@g])) end; // Don't care if ($KAMELOT_PASSCODE[.@g] & 1) dispbottom l("There is power on the west"); else dispbottom l("The west sleeps."); end; OnInit: .distance=4; end; } 042-10,33,133,0 script #K4210Note08 NPC_SWORDS_SIGN,{ .@g=getcharid(2); if (!($KAMELOT_KEYMASK[.@g] & $KAMELOT_KEY[.@g])) end; // Don't care if ($KAMELOT_PASSCODE[.@g] & 8) dispbottom l("There is power on the east"); else dispbottom l("The east sleeps."); end; OnInit: .distance=4; end; } 042-10,38,39,0 script #K4210Note16 NPC_SWORDS_SIGN,{ .@g=getcharid(2); if (!($KAMELOT_KEYMASK[.@g] & $KAMELOT_KEY[.@g])) end; // Don't care if ($KAMELOT_PASSCODE[.@g] & 16) dispbottom l("There is power on the maze"); else dispbottom l("The maze sleeps."); end; OnInit: .distance=4; end; } // The "_" is used on explode 042-10,89,28,0 script #K4210Switch_1 NPC_SWITCH_OFFLINE,{ KamelotSwitch(strnpcinfo(0, "_0")); close; OnInit: .distance=2; end; } // Other switches 042-10,80,115,0 duplicate(#K4210Switch_1) #K4210Switch_2 NPC_HIDDEN,0,0 // S 042-10,63,76,0 duplicate(#K4210Switch_1) #K4210Switch_4 NPC_HIDDEN,0,0 // W 042-10,100,79,0 duplicate(#K4210Switch_1) #K4210Switch_8 NPC_HIDDEN,0,0 // E 042-10,82,64,0 duplicate(#K4210Switch_1) #K4210Switch_16 NPC_HIDDEN,0,0 // C /////////////////////////////////////////////////////////////////// // THIS CONTROLS EVERYTHING ELSE ON THIS ROOM 042-10,0,0,0 script #Kamelot4210 NPC_HIDDEN,{ end; OnKillMob: if (!playerattached()) goto OnRespawn; // Handle Dark Petal // XXX: How MX/PC should affect drop rates? // I imagine a higher MX will increase DR.... (Right now, level 100 = +10% DR) .@r=rand2(1000); if (.@r < 100+$KAMELOT_MX[.@g]) { getmapxy(.@m$, .@x, .@y, 0); makeitem(DarkPetal, 1, .@m$, rand2(.@x-1, .@x+1), rand2(.@y-1, .@y+1)); } // Maybe a reward is due .@g=getcharid(2); if (.@g < 1) percentheal -100, -100; getexp $KAMELOT_MX[.@g]*10, $KAMELOT_MX[.@g]*5; .@delay=max(5000, 30000-$KAMELOT_PC[.@g]*1250); // FALLTHROUGH OnRespawn: .@delay=(.@delay ? .@delay : 5000); sleep(.@delay); // Yes, we just hope it works out of box explode(.@map$, .map$, "@"); .@g=atoi(.@map$[1]); if (.@g < 1) { debugmes "[ERROR] [KAMELOT] Unable to respawn for Kamelot %s", .map$; .@g=0; } KamelotCaveSpawn(1, 20, 20, 160, 140, $KAMELOT_MX[.@g]+10); end; OnInstanceInit: explode(.@map$, .map$, "@"); .@g=atoi(.@map$[1]); if (.@g < 1) { debugmes "[ERROR] [KAMELOT] Unable to spawn for Kamelot %s", .map$; .@g=0; } .@pc=$KAMELOT_PC[.@g]+1; .@avg=$KAMELOT_MX[.@g]+15; // Monsters will be at least 15 levels stronger .@m$="042-10"; // or .@map$[0] // Spawns KamelotCaveSpawn(.@pc*15/10, 60, 24, 115, 85, .@avg, .@m$); // Central Chambers (150% of player population) // Fill the whole cave with at least, 1 per 1000 tiles // There are 16800 tiles, so = 18 guards should do the trick KamelotCaveSpawn(18, 20, 20, 160, 140, .@avg, .@m$); end; }