// TMW2 Scripts
// Author:
// Jesusalva
// Description:
// Controls map domain 030 and provide helpers. See constants;
// Player Variables:
// MAZE_ID → ID of the maze being used
// MAZE_MAP$ → Map being used for the maze
// MAZE_INST → Instance ID of the Maze
/////////////////////////////////////////////////////////////////////////////////
// CreateMaze(scope=IOT_CHAR{, size=MAZE_SIZE_S})
// Creates the maze instances so they can be configured
// But does not initializes anything.
function script CreateMaze {
.@scope = getarg(0, IOT_CHAR);
.@size = getarg(1, MAZE_SIZE_S);
// Small mazes (30x30 average) (24 total)
if (.@size & MAZE_SIZE_S) {
.@p = getarraysize(.@ids);
setarray .@ids[.@p], 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24;
}
// Medium mazes (45x45 average) (15 total)
if (.@size & MAZE_SIZE_M) {
.@p = getarraysize(.@ids);
setarray .@ids[.@p], 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39;
}
// Great mazes (60x60 average) (20 total)
if (.@size & MAZE_SIZE_G) {
.@p = getarraysize(.@ids);
setarray .@ids[.@p], 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
53, 54, 55, 56, 57, 58, 59;
}
// Xtra mazes (75x75 average) (10 total)
if (.@size & MAZE_SIZE_X) {
.@p = getarraysize(.@ids);
setarray .@ids[.@p], 60, 61, 62, 63, 64, 65, 66, 67, 68, 69;
}
// Abs. mazes (90x90 average) (6 total)
if (.@size & MAZE_SIZE_A) {
.@p = getarraysize(.@ids);
setarray .@ids[.@p], 70, 71, 72, 73, 74, 75;
}
// Get a random maze, but it must not be repeated
do
{
.@r = any_of(.@ids);
if (MAZE_ID == .@r)
continue;
MAZE_ID = .@r;
.@MAZEMP$=sprintf("030-%02d", MAZE_ID);
MAZE_MAP$=sprintf("mz%02d@"+getcharid(0), MAZE_ID);
// Maze is not yet started
if (.@scope == IOT_CHAR) {
MAZE_INST = instance_create("Maze "+MAZE_ID+" "+getcharid(0), getcharid(3), IOT_CHAR);
// Failed
if (MAZE_INST < 0) {
consolebug("Instance \"%s\" already exists! (Error %d)", "Maze "+MAZE_ID+" "+getcharid(0), MAZE_INST);
continue; // Get a new maze
}
// Attach map
instance_attachmap(.@MAZEMP$, MAZE_INST, false, MAZE_MAP$);
} else {
consolebug("Scope %d not yet supported by maze system", .@scope);
return 0; // Exit early
}
} while (MAZE_INST < 0);
return MAZE_ID;
}
/////////////////////////////////////////////////////////////////////////////////
// InitMaze(duration=2 hours, random_coords=yes, treasure=no)
// Puts maze to work and send player there.
// Exit must have been configured prior to the maze.
function script InitMaze {
.@t = getarg(0, 7200);
instance_set_timeout(.@t, .@t, MAZE_INST);
instance_init(MAZE_INST);
// Find random, warpable coordinates
.@e=0; .@x=0; .@y=0;
if (getarg(1, true)) {
.@mx=getmapinfo(MAPINFO_SIZE_X, MAZE_MAP$)-20;
.@my=getmapinfo(MAPINFO_SIZE_Y, MAZE_MAP$)-20;
} else {
.@mx=40; // Wouldn't (30,30) be safer?
.@my=40;
}
do {
.@x = rand2(20, .@mx);
.@y = rand2(20, .@my);
.@e += 1;
if (.@e > 30) {
consolebug("Too many failures at Maze \"%s\"! Trying anyway!", MAZE_MAP$);
break;
}
} while (!checknpccell(MAZE_MAP$, .@x, .@y, cell_chkpass));
// Teleport the player
warp MAZE_MAP$, .@x, .@y;
// Add a random treasure chest if set to do so
if (getarg(2, false)) {
.@n$=instance_npcname(sprintf("#T_030-%02d", MAZE_ID), MAZE_INST);
.@mx=getmapinfo(MAPINFO_SIZE_X, MAZE_MAP$)-20;
.@my=getmapinfo(MAPINFO_SIZE_Y, MAZE_MAP$)-20;
do {
.@x = rand2(20, .@mx);
.@y = rand2(20, .@my);
.@e += 1;
if (.@e > 20)
break;
} while (!checknpccell(MAZE_MAP$, .@x, .@y, cell_chkpass));
movenpc(.@n$, .@x, .@y);
}
return true;
}
/////////////////////////////////////////////////////////////////////////////////
// MazeMobs(level=BaseLevel, chests=yes, density_redux=10)
// Puts monsters on the maze. Less density_redux is more mobs.
function script MazeMobs {
.@mx=getmapinfo(MAPINFO_SIZE_X, MAZE_MAP$)-20;
.@my=getmapinfo(MAPINFO_SIZE_Y, MAZE_MAP$)-20;
.@tl=(20-.@mx)*(20-.@my) * 3 / 10; // Total tiles + collision guess
.@tl=.@tl / getarg(2, 10) + 1; // Monster density
/* *** Copied from 006-5/groata.txt & 018-2-2/main.txt! *** */
/* ********* Spawn monsters based on DTOWER_FLOOR ********* */
.@lv = getarg(0, BaseLevel);
.@mb[0] = MagicGoblin;
.@mb[1] = CaveMaggot;
// Artillery & Chests
// TODO: Mimics?
if (getarg(1, true)) {
if (.@lv > 10)
array_push(.@mb, BronzeChest);
if (.@lv > 15)
array_push(.@mb, BronzeMimic);
if (.@lv > 20)
array_push(.@mb, SmallMagicBif);
if (.@lv > 30)
array_push(.@mb, Bif);
if (.@lv > 45)
array_push(.@mb, SilverChest);
if (.@lv > 50)
array_push(.@mb, SilverMimic);
if (.@lv > 55)
array_push(.@mb, MagicBif);
if (.@lv > 75)
array_push(.@mb, GoldenChest);
if (.@lv > 80)
array_push(.@mb, GoldenMimic);
if (.@lv > 85)
array_push(.@mb, BigMagicBif);
if (.@lv > 105)
array_push(.@mb, PrismChest);
}
if (.@lv > 40)
array_push(.@mb, RobinBandit);
if (.@lv > 50)
array_push(.@mb, DustGatling);
if (.@lv > 60)
array_push(.@mb, DustRifle);
if (.@lv > 70)
array_push(.@mb, DustRevolver);
if (.@lv > 80)
array_push(.@mb, DustBoss);
if (.@lv > 90)
array_push(.@mb, GreatMoubooSlime);
if (.@lv > 100)
array_push(.@mb, Jhon);
// Monsters
if (is_between2(0, .@lv, 30)) {
array_push(.@mb, Piou);
array_push(.@mb, Piousse);
array_push(.@mb, Squirrel);
array_push(.@mb, ManaPiou);
array_push(.@mb, ForestPiou);
array_push(.@mb, RedButterfly);
array_push(.@mb, Maggot);
array_push(.@mb, CandorScorpion);
array_push(.@mb, HouseMaggot);
array_push(.@mb, LittleYellowSlime);
array_push(.@mb, Ratto);
array_push(.@mb, RudolphSlime);
array_push(.@mb, MoubooSlime);
array_push(.@mb, Croc);
array_push(.@mb, Scorpion);
array_push(.@mb, SmallFrog);
}
if (is_between2(10, .@lv, 40)) {
array_push(.@mb, BigFrog);
array_push(.@mb, Lavern);
array_push(.@mb, LittleRedSlime);
array_push(.@mb, ChocolateSlime);
array_push(.@mb, Blub);
array_push(.@mb, Duck);
array_push(.@mb, Bat);
array_push(.@mb, CaveMaggot);
array_push(.@mb, ManaGhost);
array_push(.@mb, ManaBug);
array_push(.@mb, Fluffy);
array_push(.@mb, FireGoblin);
array_push(.@mb, ViciousSquirrel);
array_push(.@mb, RedScorpion);
array_push(.@mb, WhiteSlime);
array_push(.@mb, AzulSlime);
array_push(.@mb, DesertLogHead);
}
if (is_between2(20, .@lv, 50)) {
array_push(.@mb, RedSlime);
array_push(.@mb, PoisonSpikyMushroom);
array_push(.@mb, DesertBandit);
array_push(.@mb, OceanCroc);
array_push(.@mb, ToppyBlub);
array_push(.@mb, Sarracenus);
array_push(.@mb, IceMaggot);
array_push(.@mb, VampireBat);
array_push(.@mb, Bandit);
array_push(.@mb, Pinkie);
array_push(.@mb, LivingPotato);
array_push(.@mb, Assassin);
array_push(.@mb, Skeleton);
}
if (is_between2(30, .@lv, 60)) {
array_push(.@mb, CaveSnake);
array_push(.@mb, GreenSlime);
array_push(.@mb, CopperSlime);
array_push(.@mb, YellowSlime);
array_push(.@mb, SantaSlime);
array_push(.@mb, LavaSlime);
array_push(.@mb, Bluepar);
array_push(.@mb, DeathCat);
array_push(.@mb, Moggun);
array_push(.@mb, SeaSlime);
array_push(.@mb, RedMushroom);
array_push(.@mb, Mouboo);
array_push(.@mb, LogHead);
array_push(.@mb, CandiedSlime);
array_push(.@mb, OldSnake);
array_push(.@mb, GrassSnake);
}
if (is_between2(40, .@lv, 70)) {
array_push(.@mb, GiantMaggot);
array_push(.@mb, IcedFluffy);
array_push(.@mb, Snake);
array_push(.@mb, BlackSlime);
array_push(.@mb, Tipiou);
array_push(.@mb, AlphaMouboo);
array_push(.@mb, Pollet);
array_push(.@mb, PiouKnight);
array_push(.@mb, Shrewboo);
}
if (is_between2(40, .@lv, 80)) {
array_push(.@mb, Wolvern);
array_push(.@mb, FireSkull);
array_push(.@mb, DarkLizard);
}
if (is_between2(50, .@lv, 90)) {
array_push(.@mb, ArmoredSkeleton);
array_push(.@mb, BlackScorpion);
array_push(.@mb, ElectroWorm);
array_push(.@mb, EarthFairy);
array_push(.@mb, FireFairy);
array_push(.@mb, WaterFairy);
array_push(.@mb, WindFairy);
array_push(.@mb, PoisonFairy);
array_push(.@mb, MountainSnake);
array_push(.@mb, HoodedNinja);
array_push(.@mb, ForestMushroom);
array_push(.@mb, GoldenScorpion);
}
if (is_between2(60, .@lv, 100)) {
array_push(.@mb, Yeti);
array_push(.@mb, FallenGuard1);
array_push(.@mb, GreenSlimeMother);
array_push(.@mb, SnowFlower);
array_push(.@mb, BlueSlimeMother);
array_push(.@mb, WickedMushroom);
array_push(.@mb, CopperSlimeMother);
array_push(.@mb, YellowSlimeMother);
array_push(.@mb, RedSlimeMother);
array_push(.@mb, ChocolateSlimeMother);
array_push(.@mb, WhiteSlimeMother);
array_push(.@mb, Archant);
array_push(.@mb, Scar);
}
if (is_between2(70, .@lv, 110)) {
array_push(.@mb, AzulSlimeMother);
array_push(.@mb, SeaSlimeMother);
array_push(.@mb, LavaSlimeMother);
array_push(.@mb, BlackSlimeMother);
array_push(.@mb, Crafty);
array_push(.@mb, Forain);
array_push(.@mb, GreenDragon);
array_push(.@mb, Michel);
array_push(.@mb, Troll);
}
if (is_between2(80, .@lv, 120)) {
array_push(.@mb, EliteDuck);
array_push(.@mb, AzulSkullSlime);
array_push(.@mb, Moonshroom);
array_push(.@mb, RedSkullSlime);
array_push(.@mb, Terranite);
array_push(.@mb, JackO);
array_push(.@mb, BlackMamba);
array_push(.@mb, GreenSkullSlime);
array_push(.@mb, BloodyMouboo);
array_push(.@mb, Centaur);
array_push(.@mb, GoboBear);
}
if (is_between2(90, .@lv, 130)) {
array_push(.@mb, CopperSkullSlime);
array_push(.@mb, LavaSkullSlime);
array_push(.@mb, BlackSkullSlime);
array_push(.@mb, GiantCaveMaggot);
array_push(.@mb, TerraniteProtector);
array_push(.@mb, VanityPixie);
array_push(.@mb, HolyPixie);
}
if (is_between2(100, .@lv, 140)) {
array_push(.@mb, ShadowPixie);
array_push(.@mb, NulityPixie);
array_push(.@mb, Reaper);
array_push(.@mb, NightmareDragon);
array_push(.@mb, Snail);
array_push(.@mb, WhirlyBird);
}
if (is_between2(110, .@lv, 150)) {
array_push(.@mb, PinkieSuseran);
array_push(.@mb, Mandragora);
array_push(.@mb, PinkieMaximus);
}
if (.@lv > 120) {
array_push(.@mb, Junglefowl);
array_push(.@mb, Tengu);
array_push(.@mb, Moubi);
}
if (.@lv > 130) {
array_push(.@mb, SuperiorShroom);
array_push(.@mb, Nutcracker);
array_push(.@mb, Golem);
}
if (.@lv > 140) {
array_push(.@mb, SiegeTower);
array_push(.@mb, GreenhornAbomination);
array_push(.@mb, ShadowTortuga);
array_push(.@mb, FireElement);
array_push(.@mb, WaterElement);
array_push(.@mb, EarthElement);
array_push(.@mb, WindElement);
}
if (.@lv > 150) {
array_push(.@mb, SacredWisp);
array_push(.@mb, EvilWisp);
array_push(.@mb, PanthomWisp);
array_push(.@mb, EpiphanyWisp);
}
if (.@lv > 175)
array_push(.@mb, Tortuga);
/* Spawn them and make hostile */
freeloop(true);
for (.@i = 0; .@i < 1+(.@tl); .@i++) {
.@mid = any_of(.@mb);
.@m=areamonster(MAZE_MAP$, 20, 20, .@mx, .@my, strmobinfo(1, .@mid), .@mid, 1);
set_aggro(.@m);
}
freeloop(false);
return;
}
/////////////////////////////////////////////////////////////////////////////////
// RenewMaze(duration=2 hours)
// Renews the map expiration time
function script RenewMaze {
.@t = getarg(0, 7200);
instance_set_timeout(.@t, .@t, MAZE_INST);
return true;
}
/////////////////////////////////////////////////////////////////////////////////
// Configure maze maps as MMO zones
030-01 mapflag zone MMO
030-02 mapflag zone MMO
030-03 mapflag zone MMO
030-04 mapflag zone MMO
030-05 mapflag zone MMO
030-06 mapflag zone MMO
030-07 mapflag zone MMO
030-08 mapflag zone MMO
030-09 mapflag zone MMO
030-10 mapflag zone MMO
030-11 mapflag zone MMO
030-12 mapflag zone MMO
030-13 mapflag zone MMO
030-14 mapflag zone MMO
030-15 mapflag zone MMO
030-16 mapflag zone MMO
030-17 mapflag zone MMO
030-18 mapflag zone MMO
030-19 mapflag zone MMO
030-20 mapflag zone MMO
030-21 mapflag zone MMO
030-22 mapflag zone MMO
030-23 mapflag zone MMO
030-24 mapflag zone MMO
030-25 mapflag zone MMO
030-26 mapflag zone MMO
030-27 mapflag zone MMO
030-28 mapflag zone MMO
030-29 mapflag zone MMO
030-30 mapflag zone MMO
030-31 mapflag zone MMO
030-32 mapflag zone MMO
030-33 mapflag zone MMO
030-34 mapflag zone MMO
030-35 mapflag zone MMO
030-36 mapflag zone MMO
030-37 mapflag zone MMO
030-38 mapflag zone MMO
030-39 mapflag zone MMO
030-40 mapflag zone MMO
030-41 mapflag zone MMO
030-42 mapflag zone MMO
030-43 mapflag zone MMO
030-44 mapflag zone MMO
030-45 mapflag zone MMO
030-46 mapflag zone MMO
030-47 mapflag zone MMO
030-48 mapflag zone MMO
030-49 mapflag zone MMO
030-50 mapflag zone MMO
030-51 mapflag zone MMO
030-52 mapflag zone MMO
030-53 mapflag zone MMO
030-54 mapflag zone MMO
030-55 mapflag zone MMO
030-56 mapflag zone MMO
030-57 mapflag zone MMO
030-58 mapflag zone MMO
030-59 mapflag zone MMO
030-60 mapflag zone MMO
030-61 mapflag zone MMO
030-62 mapflag zone MMO
030-63 mapflag zone MMO
030-64 mapflag zone MMO
030-65 mapflag zone MMO
030-66 mapflag zone MMO
030-67 mapflag zone MMO
030-68 mapflag zone MMO
030-69 mapflag zone MMO
030-70 mapflag zone MMO
030-71 mapflag zone MMO
030-72 mapflag zone MMO
030-73 mapflag zone MMO
030-74 mapflag zone MMO
030-75 mapflag zone MMO
/////////////////////////////////////////////////////////////////////////////////
// Add Treasure chests
030-01,0,0,0 script #T_030-01 NPC_CHEST,{
if (!reachable(.x, .y, 3)) end;
callfunc "TreasureBox", 150; // 1.5% extra chance
specialeffect(.dir == 0 ? 24 : 25, AREA, getnpcid()); // closed ? opening : closing
close;
OnInit:
.distance=3;
end;
}
030-02,0,0,0 duplicate(#T_030-01) #T_030-02 NPC_CHEST
030-03,0,0,0 duplicate(#T_030-01) #T_030-03 NPC_CHEST
030-04,0,0,0 duplicate(#T_030-01) #T_030-04 NPC_CHEST
030-05,0,0,0 duplicate(#T_030-01) #T_030-05 NPC_CHEST
030-06,0,0,0 duplicate(#T_030-01) #T_030-06 NPC_CHEST
030-07,0,0,0 duplicate(#T_030-01) #T_030-07 NPC_CHEST
030-08,0,0,0 duplicate(#T_030-01) #T_030-08 NPC_CHEST
030-09,0,0,0 duplicate(#T_030-01) #T_030-09 NPC_CHEST
030-10,0,0,0 duplicate(#T_030-01) #T_030-10 NPC_CHEST
030-11,0,0,0 duplicate(#T_030-01) #T_030-11 NPC_CHEST
030-12,0,0,0 duplicate(#T_030-01) #T_030-12 NPC_CHEST
030-13,0,0,0 duplicate(#T_030-01) #T_030-13 NPC_CHEST
030-14,0,0,0 duplicate(#T_030-01) #T_030-14 NPC_CHEST
030-15,0,0,0 duplicate(#T_030-01) #T_030-15 NPC_CHEST
030-16,0,0,0 duplicate(#T_030-01) #T_030-16 NPC_CHEST
030-17,0,0,0 duplicate(#T_030-01) #T_030-17 NPC_CHEST
030-18,0,0,0 duplicate(#T_030-01) #T_030-18 NPC_CHEST
030-19,0,0,0 duplicate(#T_030-01) #T_030-19 NPC_CHEST
030-20,0,0,0 duplicate(#T_030-01) #T_030-20 NPC_CHEST
030-21,0,0,0 duplicate(#T_030-01) #T_030-21 NPC_CHEST
030-22,0,0,0 duplicate(#T_030-01) #T_030-22 NPC_CHEST
030-23,0,0,0 duplicate(#T_030-01) #T_030-23 NPC_CHEST
030-24,0,0,0 duplicate(#T_030-01) #T_030-24 NPC_CHEST
030-25,0,0,0 duplicate(#T_030-01) #T_030-25 NPC_CHEST
030-26,0,0,0 duplicate(#T_030-01) #T_030-26 NPC_CHEST
030-27,0,0,0 duplicate(#T_030-01) #T_030-27 NPC_CHEST
030-28,0,0,0 duplicate(#T_030-01) #T_030-28 NPC_CHEST
030-29,0,0,0 duplicate(#T_030-01) #T_030-29 NPC_CHEST
030-30,0,0,0 duplicate(#T_030-01) #T_030-30 NPC_CHEST
030-31,0,0,0 duplicate(#T_030-01) #T_030-31 NPC_CHEST
030-32,0,0,0 duplicate(#T_030-01) #T_030-32 NPC_CHEST
030-33,0,0,0 duplicate(#T_030-01) #T_030-33 NPC_CHEST
030-34,0,0,0 duplicate(#T_030-01) #T_030-34 NPC_CHEST
030-35,0,0,0 duplicate(#T_030-01) #T_030-35 NPC_CHEST
030-36,0,0,0 duplicate(#T_030-01) #T_030-36 NPC_CHEST
030-37,0,0,0 duplicate(#T_030-01) #T_030-37 NPC_CHEST
030-38,0,0,0 duplicate(#T_030-01) #T_030-38 NPC_CHEST
030-39,0,0,0 duplicate(#T_030-01) #T_030-39 NPC_CHEST
030-40,0,0,0 duplicate(#T_030-01) #T_030-40 NPC_CHEST
030-41,0,0,0 duplicate(#T_030-01) #T_030-41 NPC_CHEST
030-42,0,0,0 duplicate(#T_030-01) #T_030-42 NPC_CHEST
030-43,0,0,0 duplicate(#T_030-01) #T_030-43 NPC_CHEST
030-44,0,0,0 duplicate(#T_030-01) #T_030-44 NPC_CHEST
030-45,0,0,0 duplicate(#T_030-01) #T_030-45 NPC_CHEST
030-46,0,0,0 duplicate(#T_030-01) #T_030-46 NPC_CHEST
030-47,0,0,0 duplicate(#T_030-01) #T_030-47 NPC_CHEST
030-48,0,0,0 duplicate(#T_030-01) #T_030-48 NPC_CHEST
030-49,0,0,0 duplicate(#T_030-01) #T_030-49 NPC_CHEST
030-50,0,0,0 duplicate(#T_030-01) #T_030-50 NPC_CHEST
030-51,0,0,0 duplicate(#T_030-01) #T_030-51 NPC_CHEST
030-52,0,0,0 duplicate(#T_030-01) #T_030-52 NPC_CHEST
030-53,0,0,0 duplicate(#T_030-01) #T_030-53 NPC_CHEST
030-54,0,0,0 duplicate(#T_030-01) #T_030-54 NPC_CHEST
030-55,0,0,0 duplicate(#T_030-01) #T_030-55 NPC_CHEST
030-56,0,0,0 duplicate(#T_030-01) #T_030-56 NPC_CHEST
030-57,0,0,0 duplicate(#T_030-01) #T_030-57 NPC_CHEST
030-58,0,0,0 duplicate(#T_030-01) #T_030-58 NPC_CHEST
030-59,0,0,0 duplicate(#T_030-01) #T_030-59 NPC_CHEST
030-60,0,0,0 duplicate(#T_030-01) #T_030-60 NPC_CHEST
030-61,0,0,0 duplicate(#T_030-01) #T_030-61 NPC_CHEST
030-62,0,0,0 duplicate(#T_030-01) #T_030-62 NPC_CHEST
030-63,0,0,0 duplicate(#T_030-01) #T_030-63 NPC_CHEST
030-64,0,0,0 duplicate(#T_030-01) #T_030-64 NPC_CHEST
030-65,0,0,0 duplicate(#T_030-01) #T_030-65 NPC_CHEST
030-66,0,0,0 duplicate(#T_030-01) #T_030-66 NPC_CHEST
030-67,0,0,0 duplicate(#T_030-01) #T_030-67 NPC_CHEST
030-68,0,0,0 duplicate(#T_030-01) #T_030-68 NPC_CHEST
030-69,0,0,0 duplicate(#T_030-01) #T_030-69 NPC_CHEST
030-70,0,0,0 duplicate(#T_030-01) #T_030-70 NPC_CHEST
030-71,0,0,0 duplicate(#T_030-01) #T_030-71 NPC_CHEST
030-72,0,0,0 duplicate(#T_030-01) #T_030-72 NPC_CHEST
030-73,0,0,0 duplicate(#T_030-01) #T_030-73 NPC_CHEST
030-74,0,0,0 duplicate(#T_030-01) #T_030-74 NPC_CHEST
030-75,0,0,0 duplicate(#T_030-01) #T_030-75 NPC_CHEST