// TMW 2 Script // Author: // Jesusalva // Micksha // Description: // This NPC is a work on progress. It measures all players equal. // Controls the weekly guild dungeon feature. // Variable structure: // $@KAMELOT_ID [ guild_id ] = instance id // $@KAMELOT_WAVE [ guild_id ] = contains a temporary control value // $KAMELOT_MX [ guild_id ] = player average level - difficulty record // $KAMELOT_PC [ guild_id ] = total members in guild // $KAMELOT_QUEST [ guild_id ] = quest status (bitmask) // 0 - Not started // 1 - Quest Assigned by Arthur (new players cannot enter anymore) // 2 - Guinevere dialog clear // 4 - Weapon Room cutscene seen // 8 - Magic Seal 01 Broken // 16 - Magic Seal 02 Broken // 32 - Door opened // 64 - Boss defeated // 128 - Guild Reward Claimed // $KAMELOT_KEYMASK [ guild_id ] = (bitmask) Keys and Lockpicks // 1 - Treasure A (Boss Room key) // 2 - Treasure B // 4 - Treasure C // 8 - Treasure D // 16 - Weapon Room Key // $KAMELOT_PASSMASK [ guild_id ] = (bitmask) Switches in 042-10 // $KAMELOT_KEY [ guild_id ] = Which bit was assigned as the key // $KAMELOT_PASSCODE [ guild_id ] = A bitmask of passcode to use the key // $KAMELOT_COOLDOWN [ guild_id ] = Last attempt (weekly attempts) // KamelotCleanup(guildid) function script KamelotCleanup { .@g=getarg(0); //$@KAMELOT_ID[.@g]=0; $@KAMELOT_WAVE[.@g]=0; $KAMELOT_MX[.@g]=0; $KAMELOT_PC[.@g]=0; $KAMELOT_KEY[.@g]=0; $KAMELOT_QUEST[.@g]=0; $KAMELOT_KEYMASK[.@g]=0; $KAMELOT_PASSCODE[.@g]=0; $KAMELOT_PASSMASK[.@g]=0; // TODO: Instance Destroy? D: // And it couldn't be ran from Arthur? D: // Timers keep running and previous attempts leave artifacts D: return; } 014-4,67,26,0 script #KamelotEnter NPC_HIDDEN,0,0,{ end; OnTouch: // Not in a guild: Gate is sealed (MK might be excluded as well) if (getcharid(2) < 1) { dispbottom l("The gates are firmly shut. A warning is on the door, \"DO NOT ENTER. Guild Only.\""); end; } // Save your GID for reference .@g=getcharid(2); // Quest already started if ($KAMELOT_QUEST[.@g] & 1) { // Aurora Event Framework Handler if ($EVENT$ == "Kamelot") { FYE_Kamelot(); } // Quest started but Cooldown expired // Needs to cleanup - wipe all variables if ($KAMELOT_COOLDOWN[.@g] < gettimeparam(GETTIME_WEEKDAY)) { KamelotCleanup(.@g); } else { dispbottom l("The gates are firmly shut by some weird magical power. %s", (TUTORIAL ? l("Perhaps we should wait a few days."):"")); end; } } // Build instance if it doesn't exists or has been reallocated if (instanceowner($@KAMELOT_ID[.@g]) != .@g) { debugmes "Creating Instance for guild %d", .@g; .@inst=instance_create("Kamelot@"+.@g, .@g, IOT_GUILD); if (.@inst < 0) Exception("Kamelot Instance Error", RB_DEFAULT|RB_ISFATAL); instance_attachmap("042-0", .@inst, .@g, "042-0@"+.@g); instance_attachmap("042-1", .@inst, .@g, "042-1@"+.@g); instance_attachmap("042-2", .@inst, .@g, "042-2@"+.@g); instance_attachmap("042-3", .@inst, .@g, "042-3@"+.@g); instance_attachmap("042-4", .@inst, .@g, "042-4@"+.@g); instance_attachmap("042-5", .@inst, .@g, "042-5@"+.@g); instance_attachmap("042-6", .@inst, .@g, "042-6@"+.@g); instance_attachmap("042-7", .@inst, .@g, "042-7@"+.@g); instance_attachmap("042-8", .@inst, .@g, "042-8@"+.@g); instance_attachmap("042-9", .@inst, .@g, "042-9@"+.@g); instance_attachmap("042-10", .@inst, .@g, "042-10@"+.@g); instance_attachmap("042-11", .@inst, .@g, "042-11@"+.@g); instance_set_timeout(21600, 21600, .@inst); // Instance lasts 6 hours instance_init(.@inst); $@KAMELOT_ID[.@g] = .@inst; } // You can enter in every other state warp "042-0@"+.@g, any(59, 60), 80; // Renew the instance clock : 6 hours instance_set_timeout(21600, 21600, $@KAMELOT_ID[.@g]); end; // Debug is only allowed if server is in override mode OnDebug: if (!$@GM_OVERRIDE) goto L_SimplifiedDebug; /* mes "Guild ID:"; input .@g; if (.@g < 1 || .@g > 100) .@g=getcharid(2); */ .@g=getcharid(2); if (.@g < 1) end; mes "Kamelot Debug"; mesf "Guild: %d", .@g; mes ""; mesf "Keys: %d", $KAMELOT_KEYMASK[.@g]; mesf "Quest: %d", $KAMELOT_QUEST[.@g]; mesf "Wave: %d", $@KAMELOT_WAVE[.@g]; mes ""; mesf "Maze Password: %d", $KAMELOT_PASSCODE[.@g]; mesf "Maze Status: %d", $KAMELOT_PASSMASK[.@g]; mes ""; mesf "Guild Power: %d", $KAMELOT_MX[.@g]; mesf "Guild Count: %d", $KAMELOT_PC[.@g]; select l("Abort"), l("Reset"), l("Reset & Destroy"), l("Quest - Skip Weapons Room"), l("Quest - Skip Krukan fight"), l("Quest - Find all Keys"), l("Quest - Unlock Boss Room"), l("Quest - Mark as Completed"), "", l("Warp - Jump to Entrance"), // 10 l("Warp - Jump to Weapon Room"), l("Warp - Jump to Basement"), l("Warp - Jump to Jail"), l("Warp - Jump to Sewer Entrance"), l("Warp - Jump to Cave Exit"), l("Warp - Arrest me!"); mes ""; switch (@menu) { // 3 inheirs 2 case 3: instance_destroy($@KAMELOT_ID[.@g]); case 2: $KAMELOT_COOLDOWN[.@g] = 0; KamelotCleanup(.@g); break; // We now order from bottom-up case 8: $KAMELOT_QUEST[.@g]=$KAMELOT_QUEST[.@g]|64; mes "WARNING: Quest concluded"; case 7: $KAMELOT_QUEST[.@g]=$KAMELOT_QUEST[.@g]|8; $KAMELOT_QUEST[.@g]=$KAMELOT_QUEST[.@g]|16; $KAMELOT_QUEST[.@g]=$KAMELOT_QUEST[.@g]|32; mes "WARNING: Boss Room was unlocked"; case 6: $KAMELOT_KEYMASK[.@g]=$KAMELOT_KEYMASK[.@g]|1; $KAMELOT_KEYMASK[.@g]=$KAMELOT_KEYMASK[.@g]|2; $KAMELOT_KEYMASK[.@g]=$KAMELOT_KEYMASK[.@g]|4; $KAMELOT_KEYMASK[.@g]=$KAMELOT_KEYMASK[.@g]|8; mes "WARNING: Kamelot Basement Chests skipped (not lootable)."; case 5: $KAMELOT_QUEST[.@g]=$KAMELOT_QUEST[.@g]|4; mes "WARNING: Krukan Fight and jail skipped."; case 4: $KAMELOT_KEYMASK[.@g]=$KAMELOT_KEYMASK[.@g]|16; mes "WARNING: Weapons Room skipped."; break; // 10+ are the warp triggers case 10: warp "042-0@"+.@g, 60, 40; break; case 11: warp "042-1@"+.@g, 40, 65; break; case 12: warp "042-2@"+.@g, 44, 45; break; case 13: warp "042-3@"+.@g, 60, 130; break; case 14: warp "042-4@"+.@g, 60, 67; break; case 15: warp "042-10@"+.@g, 95, 52; break; case 16: .@t$="042-3@"+.@g; .@n$=instance_npcname("#KSlimeSpawn", $KAMELOT_ID[.@g]); setarray .@x, 33, 84, 41, 74, 36, 57, 79, 43, 24, 86, 59, 38; setarray .@y, 135, 127, 119, 107, 96, 84, 63, 67, 67, 22, 49, 27; specialeffect(FX_HIT, AREA, getcharid(3)); .@v = (rand2(12) % 12); .@r=attachrid(getcharid(3)); if (.@r) { warp .@t$, .@x[.@v], .@y[.@v]; if (!countitem(Lockpicks)) addtimer 700, .@n$+"::OnFirstSlime"; setpcblock(PCBLOCK_HARD, false); } else { unitwarp(getcharid(3), .@t$, .@x[.@v], .@y[.@v]); // And good luck D: consolebug "FATAL: Could not attach: %d", getcharid(3); } break; } close; L_SimplifiedDebug: mesc "THIS IS FOR JESUSALVA DEBUG ONLY - DO NOT USE NORMALLY", 1; mes "Guild ID:"; input .@gid; if (.@gid < 1 || .@gid > 100) close; $KAMELOT_COOLDOWN[.@gid] = 0; KamelotCleanup(.@gid); mesc "THE GUILD WAS WIPED FROM EXISTENCE.", 1; mesc "Have a nice day! %%l", 3; close; OnInit: bindatcmd "kdebug", "#KamelotEnter::OnDebug", 99, 100, 1; end; } ///////////////////////////////////////////////////////////////////////////// // KamelotCaveSpawn(Amount, x1, y1, x2, y2, power{, map}) function script KamelotCaveSpawn { .@label$=instance_npcname(.name$)+"::OnKillMob"; .@gcount=getarg(0); .@x1=getarg(1); .@y1=getarg(2); .@x2=getarg(3); .@y2=getarg(4); .@avg=getarg(5); .@m$=instance_mapname(getarg(6, .map$)); //debugmes "Total %d, map %s (power %d)", .@gcount, .@m$, .@avg; freeloop(true); for (.@i=0; .@i < .@gcount; .@i++) { .@mobId=any(CursedSoldier, CursedArcher); // 50-50 ratio .@mob=areamonster(.@m$, .@x1, .@y1, .@x2, .@y2, strmobinfo(1, .@mobId), .@mobId, 1, .@label$); // Reconfigure the monster setunitdata(.@mob, UDT_LEVEL, .@avg+1); setunitdata(.@mob, UDT_STR, 1+.@avg*6/10); setunitdata(.@mob, UDT_AGI, 1+.@avg*5/10); setunitdata(.@mob, UDT_VIT, 1+.@avg*5/10); setunitdata(.@mob, UDT_INT, 1+.@avg*6/10); setunitdata(.@mob, UDT_DEX, 1+.@avg*6/10); setunitdata(.@mob, UDT_LUK, 1+.@avg*5/10); setunitdata(.@mob, UDT_ADELAY, 1372); setunitdata(.@mob, UDT_ATKRANGE, (.@mobId == CursedArcher ? any(6,7) : any(1,2))); // Battle Status setunitdata(.@mob, UDT_MAXHP, .@avg*40); setunitdata(.@mob, UDT_HP, .@avg*40); setunitdata(.@mob, UDT_ATKMIN, .@avg*47/10); setunitdata(.@mob, UDT_ATKMAX, .@avg*67/10); setunitdata(.@mob, UDT_DEF, 1+.@avg*12/10); setunitdata(.@mob, UDT_MDEF, 1+.@avg*8/10); setunitdata(.@mob, UDT_HIT, .@avg*65/10); // Advised: x3 setunitdata(.@mob, UDT_FLEE, .@avg*45/10); // Advised: x4 // Critical calculation .@min=15; .@max=max(.@min, min(40, .@avg/3)); setunitdata(.@mob, UDT_CRIT, rand2(.@min, .@max)); // Loop through } freeloop(false); return; }