// TMW2 Scripts
// Author:
// Jesusalva
// Description:
// Controls boss raid showdown (Freeyorp Event System - Boss Raid)
function script FYRaid_Select {
.@abort = getarg(0, false);
if ($EVENT$ != "Raid") return;
sleep2(100); // Anti-flood protection: Hold execution for 100ms
mes l("Current Boss: %s", $RAIDING_BOSS$);
.@id = array_find($FYRAID_OWNER, getcharid(3));
if (.@id >= 0) {
// Same level (challenge ongoing)
if ($FYRAID_LV[.@id] == FYRAID_LV) {
// Was defeated when you weren't loooking (limited precedence)
if ($FYRAID_HP[.@id] <= 0) {
mesc l("Boss defeated!"), 3;
FYRAID_LV+=1;
$FYRAID_HP[.@id]=0;
Mobpt += FYRAID_LV * 10;
getitem EventNaftalin, FYRAID_LV;
}
// Time is running out
else if (gettimetick(2) < $FYRAID_TIME[.@id]) {
mesc l("You found a Level %d %s!", FYRAID_LV, $RAIDING_BOSS$), 2;
mesc l("Time left: %s", FuzzyTime($FYRAID_TIME[.@id])), 1;
}
// Time has expired - free for next boss
else if (gettimetick(2) > $FYRAID_TIME[.@id]) {
mesc l("The boss you discovered has ran away!");
$FYRAID_LV[.@id] = 0;
$FYRAID_HP[.@id] = 0;
$FYRAID_TIME[.@id] = 0;
Mobpt += rand2(FYRAID_LV);
}
}
}
if (.@abort)
return;
next;
setarray .@opt$, l("Cancel"), -1;
freeloop(true);
// Build menu
for (.@i=0; .@i < getarraysize($FYRAID_OWNER) ; .@i++) {
if ($FYRAID_HP[.@i] <= 0)
continue;
if ($FYRAID_TIME[.@i] < gettimetick(2))
continue;
.@hp=$FYRAID_HP[.@i];
.@lv=$FYRAID_LV[.@i];
.@on=$FYRAID_OWNER[.@i];
array_push(.@opt$, (.@on == getcharid(3) ? "**" : "") + l("Level %d (%s HP) (Found by %s)", .@lv, .@hp, strcharinfo(0, l("offline player"), .@on)) + (.@on == getcharid(3) ? "**" : ""));
array_push(.@opt$, str(.@i));
}
freeloop(false);
menuint2(.@opt$);
if (@menuret < 0)
return;
// Validate again if the prey is still valid
.@i = @menuret;
if ($FYRAID_HP[.@i] <= 0) {
mesc l("Someone else has already defeated this bounty.");
return;
}
if ($FYRAID_TIME[.@i] < gettimetick(2)) {
mesc l("This bounty has expired.");
return;
}
if (ispcdead()) {
mesc l("You are dead.");
return;
}
// Prepare the room (time limit = 3 minutes)
.@inst = instance_create("Showdown "+getcharid(0), getcharid(3), IOT_CHAR);
// Failed
if (.@inst < 0) {
mesc l("You can only try every %d minutes.", 3);
return;
}
// Attach map
// TODO: Different scenarios: Sewer, Concrete Dungeon, Crypt, Desert Castle, Mountain, Snowland, Lake Region, Ukar Shrine, Woodland...
.@lv = $FYRAID_LV[.@i];
.@mp$="fyrb@"+getcharid(0);
instance_attachmap(sprintf("001-13-%d", (.@lv % 4)), .@inst, false, .@mp$);
// Recreate the boss
.@mob=monster(.@mp$, 47, 33, $RAIDING_BOSS$, WanderingShadow, 1, "sBossRaid::OnBossDie");
setunitdata(.@mob, UDT_LEVEL, min(.@lv * 7, 200));
setunitdata(.@mob, UDT_STR, .@lv * 4);
setunitdata(.@mob, UDT_AGI, min(.@lv * 4, 255));
setunitdata(.@mob, UDT_VIT, .@lv * 5);
setunitdata(.@mob, UDT_INT, .@lv * 2);
setunitdata(.@mob, UDT_DEX, .@lv * 6);
setunitdata(.@mob, UDT_LUK, .@lv * 5);
setunitdata(.@mob, UDT_ADELAY, max(640, 1672-(.@lv * 24)));
setunitdata(.@mob, UDT_MAXHP, 2000+.@lv*1000+(FYRAID_LV/5*500));
setunitdata(.@mob, UDT_HP, $FYRAID_HP[.@i]);
setunitdata(.@mob, UDT_ATKMIN, 90+.@lv*10);
setunitdata(.@mob, UDT_ATKMAX, 90+.@lv*12);
setunitdata(.@mob, UDT_DEF, 10+.@lv*5);
setunitdata(.@mob, UDT_MDEF, 10+.@lv*3);
setunitdata(.@mob, UDT_HIT, (BaseLevel+.@lv)*45/10);
setunitdata(.@mob, UDT_FLEE, min((BaseLevel+.@lv)*27/10, 750));
setunitdata(.@mob, UDT_CRIT, rand2(60, min(180, 60+.@lv)));
// Save some persistent data
@map$=.@mp$;
@id=.@i;
@mb=.@mob;
@tm=gettimetick(2)+180;
// Good luck!
instance_set_timeout(190, 190, .@inst);
instance_init(.@inst);
warp .@mp$, 47, 52;
.@tski = limit(10000, 46000-(.@lv*500), 40000);
addtimer 180000, "sBossRaid::OnTimeout";
addtimer .@tski, "sBossRaid::OnPump";
dispbottom l("Time left: %s", FuzzyTime(@tm));
closeclientdialog;
// Spawn an auxiliar every 5 levels AFTER level 10
if (.@lv > 10) {
.@qnt = (.@lv % 5) + 1;
.@str = (.@lv / 5);
explode(.@n$, $RAIDING_BOSS$, " ");
.@n$ = l("%s's Minion", .@n$);
for (.@i=0;.@i < .@qnt;.@i++) {
.@m=areamonster(.@mp$, 44, 31, 50, 34, .@n$, MeagerShadow, 1);
setunitdata(.@m, UDT_STR, .@str);
setunitdata(.@m, UDT_AGI, .@str);
setunitdata(.@m, UDT_VIT, .@str);
setunitdata(.@m, UDT_INT, .@str);
setunitdata(.@m, UDT_DEX, .@str);
setunitdata(.@m, UDT_LUK, .@str);
setunitdata(.@m, UDT_ATKMIN, BaseLevel+.@str*3);
setunitdata(.@m, UDT_ATKMAX, BaseLevel+.@str*4);
setunitdata(.@m, UDT_MAXHP, .@str*400);
setunitdata(.@m, UDT_HP, .@str*400);
setunitdata(.@m, UDT_HIT, BaseLevel+.@lv+rand2(.@str*5));
setunitdata(.@m, UDT_FLEE, 1+rand2(.@str));
setunitdata(.@m, UDT_CRIT, 1+rand2(.@str));
}
}
return;
}
// ------------------------------------------------------------------------------
- script sBossRaid NPC_HIDDEN,{
OnPump:
if (@map$ != getmap()) end;
.@msg$=l("In all the mana worlds, I alone am feared.");
.@lv=$FYRAID_LV[@id];
.@t = min(45, 10+rand2(.@lv));
// Apply boss skill based on their name
if ($RAIDING_BOSS$ == "Xakabael the Dark") {
.@msg$ = l("Witness my sublime rain of death. Regeneration!");
.@hp=getunitdata(@mb, UDT_HP);
.@mp=getunitdata(@mb, UDT_MAXHP);
setunitdata(@mb, UDT_HP, min(.@mp, .@hp+(.@lv * 50)));
.@mob=(rand2(.@lv) > 50 ? DeathCat : GreenSlime);
} else if ($RAIDING_BOSS$ == "Janeb the Evil") {
.@msg$ = l("Chaos shall be the founding stone of my town! Falling star!");
percentheal -5, -10;
.@mob=(rand2(.@lv) > 50 ? BlackScorpion : RedSlime);
} else if ($RAIDING_BOSS$ == "Platyna the Red") {
.@msg$ = l("I, the rightful ruler, demand back this world! Tyranny!");
percentheal -1, -1;
SC_Bonus(.@t, any(SC_BLIND, SC_POISON), 1);
.@mob=(rand2(.@lv) > 50 ? DarkLizard : Assassin);
} else if ($RAIDING_BOSS$ == "Benjamin the Frost") {
.@msg$ = l("Stop on your tracks, unfair being! Freeze!");
SC_Bonus((.@t / 2), any(SC_FREEZE, SC_SLEEP, SC_SLEEP, SC_SLEEP), 1);
.@mob=(rand2(.@lv) > 50 ? BlueSlime : WhiteSlime);
} else if ($RAIDING_BOSS$ == "Reid the Terrific") {
.@msg$ = l("There is no free speech. Censorship!");
SC_Bonus(.@t, SC_SILENCE, 1);
.@mob=(rand2(.@lv) > 50 ? Thug : RedMushroom);
} else if ($RAIDING_BOSS$ == "Nu'Rem the Destroyer") {
.@msg$ = l("And then... There was a quake. And all life died. Bleed!");
SC_Bonus(.@t, SC_BLOODING, 1);
.@mob=(rand2(.@lv) > 50 ? BlackSlime : OldSnake);
} else if ($RAIDING_BOSS$ == "Golbenez the Cruel") {
.@msg$ = l("Puny mortal, do your best to entertain me! Curse!");
SC_Bonus(.@t, SC_CURSE, 1);
.@mob=(rand2(.@lv) > 50 ? FireSkull : Skeleton);
} else if ($RAIDING_BOSS$ == "King of Typos") {
.@msg$ = l("The problem with typos is - unpredictable side effects.");
SC_Bonus(.@t, any(SC_SILENCE, SC_CURSE, SC_FREEZE, SC_BLOODING, SC_BLIND, SC_POISON, SC_DPOISON, SC_POISON, SC_BURNING, SC_SLEEP), 1);
.@mob=(rand2(.@lv) > 50 ? Swashbuckler : Bluepar);
} else {
consolewarn("Unknown raiding boss: %s. No skill will be used.", $RAIDING_BOSS$);
}
unittalk(@mb, .@msg$);
dispbottom l("Time left: %s", FuzzyTime(@tm));
// TODO: Maybe flush the boss HP to upstream to prevent farming?
addtimer max(20000, 46000-($FYRAID_LV[@id]*1000)), "sBossRaid::OnPump";
// Spawn reinforcements when applicable
if (.@mob && rand2(100) < .@lv) {
monster(@map$, 47, 33, "Minion", .@mob, 1);
}
end;
// Boss defeated
OnBossDie:
dispbottom l("Boss defeated!");
// Clear bonus
getitem EventNaftalin, $FYRAID_LV[@id]/2+1;
getexp $FYRAID_LV[@id], $FYRAID_LV[@id]/2+1;
.@new = 0;
specialeffect(FX_FANFARE, SELF, getcharid(3));
goto OnClose;
// Ran out of time
OnTimeout:
dispbottom l("Time out!");
.@new = getunitdata(@mb, UDT_HP);
goto OnClose;
// What a noob, you died!
OnDie:
dispbottom l("Killed in action!");
.@new = getunitdata(@mb, UDT_HP);
goto OnClose;
// Warp you back
OnClose:
// Time Penalty every time you attack the boss yourself
if (.@new > 0 && $FYRAID_OWNER[@id] == getcharid(3))
$FYRAID_TIME[@id] -= 300;
// Update boss parameters
.@old = $FYRAID_HP[@id];
.@dmg = .@old - .@new;
if ($@GM_OVERRIDE)
debugmes "Old %d New %d Damage %d", .@old, .@new, .@dmg;
// Damage Bonus
if (.@dmg / 2000 > 1)
getitem EventNaftalin, .@dmg / 2000;
// Record new HP info and give you rewards
$FYRAID_HP[@id] = .@new;
Mobpt += $FYRAID_LV[@id];
getexp $FYRAID_LV[@id], $FYRAID_LV[@id]/2+1;
// Send you back
deltimer("sBossRaid::OnPump");
deltimer("sBossRaid::OnTimeout");
sleep2(500);
if (@aurora_map$ != "" && @aurora_x && @aurora_y) {
// TODO: Maybe not if you're dead...? (heal hack?)
warp @aurora_map$, @aurora_x, @aurora_y;
@aurora_map$="";
@aurora_x=0;
@aurora_y=0;
} else {
teleporthome();
}
FYRaid_Select(true); // Formally close the raid session
close;
}
001-13 mapflag zone MMO
001-13-0 mapflag zone MMO
001-13-1 mapflag zone MMO
001-13-2 mapflag zone MMO