// 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;
addtimer 3000, "#KamelotBoss::OnDialog";
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_NO_SPRITE,{
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+=limit(1, readparam2(bInt)/40, 3);
// 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 >= 5 && .@power < 100 && @kataspam != 2) {
unittalk(getcharid(3), "There is still too much power! Please drop "+getitemlink(DarkPetal)+" nearby!", true);
@kataspam=2;
} else if (.@power >= 100 && .@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 >= 200 && .@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_NO_SPRITE,{
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_NO_SPRITE
////////////////////////
// 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=max(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=max(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_SWITCH_OFFLINE,0,0 // S
042-10,63,76,0 duplicate(#K4210Switch_1) #K4210Switch_4 NPC_SWITCH_OFFLINE,0,0 // W
042-10,100,79,0 duplicate(#K4210Switch_1) #K4210Switch_8 NPC_SWITCH_OFFLINE,0,0 // E
042-10,82,64,0 duplicate(#K4210Switch_1) #K4210Switch_16 NPC_SWITCH_OFFLINE,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 = +20% DR)
.@r=rand2(500);
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*25/10, 60, 24, 115, 85, .@avg, .@m$); // Central Chambers (250% of player population)
// Fill the whole cave with at least, 1 per 500 tiles
// There are 16800 tiles, so = 36 guards should do the trick
KamelotCaveSpawn(36, 20, 20, 160, 140, .@avg, .@m$);
end;
}