// TMW2 Script
// Notes: The Monster King will retake the town every
// OnTue0000
// (Tuesday, midnight)
// Only the world hero may begin a siege.
// Only one siege per day is allowed
// Writes to MK Temp Var. This variable will unlock the castle gates
// Then the inner gates, and finally, will be a co-requisite to the floors
// Variables:
// $FORTRESS_STATE = int
// 0 - Locked
// 1 - Unlocked
// $@FORTRESS_STATUE = bitmask
// 1,2,4,8,16 - broken statues
// 1024 - Fortress Gate
// 2048 - Siege started
// $@FORT_BLACKLIST = int array
// Char ID which already raided this week
// TODO: Use bg() - maybe with dummysd? What will increase allies count?
// TODO: Gate control during siege (not $FORTRESS_STATE). Gate monster.
// TODO: Spawn the monster general for each statue. Count their deaths.
// TODO: Spawn Monster Governor (and add it) once statue is broken. ::OnConquest
// TODO: Record nº of victories. Strengthen the governor.
// TODO: Provide a way to resume failed attempts. Move Phoenix inside.
// TODO: Testing.
// Use setwall() instead of builtin collision? (Deprecates out NPC)
// TODO: NPCs from inside: Bank. Barber. Aeros Shop. Etc.
// TODO: Spawn inside and outside when siege begins.
// TODO: Heartbeat - (Re)Spawn monsters inside every X seconds
// MAPFLAGS
025-1 mapflag zone SuperMMO
025-3 mapflag zone SuperMMO
026-0 mapflag zone SuperMMO
026-1 mapflag zone SuperMMO
/////////////////////////////////////////
// FUNCTIONS
// FTCleanup(status)
function script FTCleanup {
$FORTRESS_STATE=getarg(0);
// TODO: Magic Statues (FTStatue)
$@FORTRESS_STATUE=0;
//enablenpc "Magic Statue#F_1";
//enablenpc "Magic Statue#F_2";
//enablenpc "Magic Statue#F_4";
//enablenpc "Magic Statue#F_8";
//enablenpc "Magic Statue#F_16";
// TODO: Gate
// TODO: ::OnConquest
// TODO: Kill stray monsters
//killmonsterall
// Main gate
if ($FORTRESS_STATE) {
disablenpc "Fortress";
donpcevent "#025-1_99_112::OnDisable";
} else {
enablenpc "Fortress";
donpcevent "#025-1_99_112::OnEnable";
mapwarp("025-1", "025-2", 100, 27);
}
deletearray $@FORT_BLACKLIST;
enablenpc "#025-1_100_123";
return;
}
// FTStatue(id)
function script FTStatue {
.@id=getarg(0);
mesn l("Magic Statue");
mes l("There is a reading: The Mana Source. The Moubootaur. The Monster King.");
mes l("The war. The blood. The inspiration. The mana. The world. The defiance.");
mes l("The guard. The heir. The originals. The races. The later. The seal.");
mes l("The fragments. The war. The Terranite. AEGIS MAGNA PROTECTIVE SCUTUM.");
next;
mesc l("It seems to be a defensive spell.");
if ($FORTRESS_STATE)
return;
// Break the statues?
mesc l("Break the Statue?"), 1;
next;
if (askyesno() == ASK_YES) {
if ($@FORTRESS_STATUE & .@id)
return;
sc_start SC_STUN, 10000, 1;
//getmapxy();
//areamonster();
//mapannounce();
//maybe spawn monster governor
$@FORTRESS_STATUE=$@FORTRESS_STATUE|.@id;
}
return;
}
/////////////////////////////////////////
// NPC SCRIPTS
// Main gate - Also where the World Hero can begin the siege
025-1,99,112,0 script Fortress NPC_NO_SPRITE,{
function spawnMob;
function spawnCore;
// Main Story block - WHAT
if ($GAME_STORYLINE < 3)
die();
// Still open
if ($FORTRESS_STATE)
end;
// Only World Hero may interact
if (strcharinfo(0) != $MOST_HEROIC$) {
dispbottom l("I will not assault the Fortress Island. I'll wait for %s.", $MOST_HEROIC$);
end;
}
// Hey, you can assault the town!
mesc ".:: "+l("THE FORTRESS ISLAND TOWN") + " ::.", 1;
mes l("Behind this gate, lies the Fortress Island Town.");
next;
mesc ".:: "+l("THE FORTRESS ISLAND TOWN") + " ::.", 1;
mes l("Assault?");
mesc l("Lorem ipsum dolor sit amet"), 1;
next;
if (askyesno() == ASK_NO)
close;
// FIRE THE EVENT
disablenpc .name$;
disablenpc "#025-1_100_123";
initnpctimer;
// Reset variables
$@FORTRESS_STATUE=2048;
// Spawn the gate
monster("025-1", 99, 113, "Fortress Gate", FortressGate, 1, .name$+"::OnOpenGate");
// Initial defending waves
spawnCore(true);
spawnCore(false);
// TODO: Enable the statues
// Player blacklist (unable to use 025-2 warp)
maptimer2("025-1", 10, "Fortress::OnMPBlacklist");
kamibroadcast($MOST_HEROIC$+"'s team has begun a siege on Fortress Town. Will they prevail?");
close;
/////////////////////////////////////////////////////////
OnOpenGate:
// FIXME Broken
$@FORTRESS_STATUE = $@FORTRESS_STATUE|1024;
donpcevent "#025-1_99_112::OnDisable";
kamibroadcast("The Fortress Town Gate has been breached!");
close;
// Heartbeat (B1)
OnTimer15000:
.@breach=($@FORTRESS_STATUE & 1024);
spawnCore(.@breach);
end;
// Heartbeat (B2)
OnTimer30000:
.@breach=($@FORTRESS_STATUE & 1024);
.@ppl=getmapusers("025-1");
// Fail condition
if (.@ppl <= 0) {
kamibroadcast("Players failed to conquest the Fortress Island!");
FTCleanup($FORTRESS_STATE);
end;
}
// Spawn mobs
spawnCore(.@breach);
// Summon reinforcements
maptimer2("025-1", 10, "Fortress::OnMPReinforce");
// Restart timer
initnpctimer;
end;
/////////////////////////////////////////////////////////
OnMPBlacklist:
array_push($@FORT_BLACKLIST, getcharid(0));
goto OnMPReinforce;
OnMPReinforce:
// Dispose dead bodies
if (ispcdead()) {
warp "025-2", 96, 25;
end;
}
// Summon allies
// Last a whole minute
summon("Allied Guard", any(FallenGuard1, FallenGuard2, FallenGuard3));
end;
/////////////////////////////////////////////////////////
// spawnMob(Mob, X1, Y1, X2, Y2)
function spawnMob {
.@mob=areamonster("025-1", getarg(1), getarg(2), getarg(3), getarg(4), strmobinfo(1, getarg(0)), getarg(0), 1);
.@opt=getunitdata(.@mob, UDT_MODE);
// Make aggressive
.@opt=.@opt|MD_AGGRESSIVE;
// All forces can suffer knockback
if (.@opt & MD_NOKNOCKBACK)
.@opt=.@opt^MD_NOKNOCKBACK;
// Save new options
setunitdata(.@ob, UDT_MODE, .@opt);
// Increase health in 1%+1% per siege
.@bhp=getunitdata(.@mob, UDT_MAXHP);
.@bhp=.@bhp*(101+$MK_TEMPVAR)/100;
setunitdata(.@mob, UDT_MAXHP, .@bhp);
setunitdata(.@mob, UDT_HP, .@bhp);
// Increase accuracy in 10%+1% per siege
.@acc=getunitdata(.@mob, UDT_HIT);
.@acc=.@acc*(110+$MK_TEMPVAR)/100;
setunitdata(.@mob, UDT_HIT, .@acc);
// TODO: adjust ViewRange
return;
}
// spawnCore(breach)
function spawnCore {
// Now, the thing is, I don't care with how powerful your invading forces are.
// I only care with how many success you have.
if (getarg(0)) {
.@x1=24;
.@y1=21;
.@x2=175;
.@y2=105;
.@am=2+$MK_TEMPVAR;
} else {
.@x1=25;
.@y1=110;
.@x2=180;
.@y2=120;
.@am=1+($MK_TEMPVAR/3);
}
freeloop(true);
// Level 40~60 Section
for (.@i = 0; .@i < .@am*3; ++.@i) {
spawnMob(any(Tipiou, Pollet, Wolvern, FireSkull, DarkLizard, BlackScorpion, EarthFairy, FireFairy, WaterFairy, WindFairy, NatureFairy, DustGatling, DustRifle, DustRevolver, MountainSnake, HoodedNinja, ForestMushroom, GoldenScorpion, Yeti), .@x1, .@y1, .@x2, .@y2);
}
// Level 60~80 Section
for (.@i = 0; .@i < .@am*2; ++.@i) {
spawnMob(any(Yeti, WickedMushroom, Archant, Scar, Crafty, AzulSkullSlime, YellowSkullSlime, Forain, GreenDragon, Michel, EliteDuck, Troll, Moonshroom, Terranite), .@x1, .@y1, .@x2, .@y2);
}
// Level 80~100 section
for (.@i = 0; .@i < .@am; ++.@i) {
spawnMob(any(RedSkullSlime, Terranite, JackO, BlackMamba, GreenSkullSlime, Centaur, GoboBear, TerraniteProtector), .@x1, .@y1, .@x2, .@y2);
}
// Summoners Section
for (.@i = 0; .@i < .@am; ++.@i) {
spawnMob(any(GreenSlimeMother, BlueSlimeMother, YellowSlimeMother, RedSlimeMother, WhiteSlimeMother, AzulSlimeMother, LavaSlimeMother, BlackSlimeMother), .@x1, .@y1, .@x2, .@y2);
}
if (getarg(0)) {
// DemiBoss section (Internal only, increases every ~2 weeks)
for (.@i = 0; .@i < (.@am/2); ++.@i) {
spawnMob(any(VanityPixie, HolyPixie, ShadowPixie, NulityPixie, Reaper, BlackSkullSlime, NightmareDragon, WhirlyBird, PinkieSuseran), .@x1, .@y1, .@x2, .@y2);
}
}
freeloop(false);
return;
}
/////////////////////////////////////////////////////////
OnInit:
FTCleanup($FORTRESS_STATE);
end;
OnTue0000:
FTCleanup(false);
kamibroadcast("The Monster Army has retaken Fortress Town!");
end;
OnConquest:
$MK_TEMPVAR+=1;
FTCleanup(true);
kamibroadcast("Fortress Town has been captured by the Allied Forces!");
end;
}
/////////////////////////////////////////////////////////
// This exit must work even if gate is closed (bugfix)
025-1,99,111,0 script #FortressTownOut NPC_HIDDEN,1,0,{
end;
OnTouch:
if (!$FORTRESS_STATE)
slide 100, 114;
end;
}
// TODO: 100,20 - The Impregnable Fortress Gate
// And don't forget the curse timer
/////////////////////////////////////////////////////////
// Real access to 025-1 map
025-2,96,24,0 script Fortress Town Access NPC_HIDDEN,8,0,{
end;
OnTouch:
// Disabled
if ($GAME_STORYLINE < 3 || !is_admin() || $@FORTRESS_STATUE)
end;
// Blacklisted
if (array_find($@FORT_BLACKLIST, getcharid(0)) != -1)
end;
// Not blacklisted
warp "025-1", 99, 122;
end;
}