summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--db/re/mob_db.conf44
-rw-r--r--npc/001-13/_import.txt1
-rw-r--r--npc/001-13/main.txt195
-rw-r--r--npc/003-1/events.txt2
-rw-r--r--npc/commands/event.txt14
-rw-r--r--npc/functions/aurora.txt55
-rw-r--r--npc/functions/news.txt13
-rw-r--r--npc/functions/soul_menhir.txt7
-rw-r--r--npc/functions/util.txt2
9 files changed, 327 insertions, 6 deletions
diff --git a/db/re/mob_db.conf b/db/re/mob_db.conf
index 2f13cfdfb..959a35571 100644
--- a/db/re/mob_db.conf
+++ b/db/re/mob_db.conf
@@ -11879,6 +11879,50 @@ mob_db: (
},
// System
{
+ Id: 1491
+ SpriteName: "WanderingShadow"
+ Name: "Wandering Shadow"
+ Lv: 60
+ Hp: 9987
+ Sp: 1248
+ Exp: 1674
+ JExp: 168
+ AttackRange: 2
+ Attack: [380, 460]
+ Def: 75
+ Mdef: 75
+ WalkMask: "WALK_AIR"
+ Stats: {
+ Str: 30
+ Agi: 60
+ Vit: 62
+ Int: 0
+ Dex: 60
+ Luk: 33
+ }
+ ViewRange: 9
+ ChaseRange: 14
+ Race: 9
+ Element: (8, 2)
+ Mode: {
+ CanMove: true
+ Aggressive: true
+ Angry: true
+ CanAttack: true
+ ChangeTargetMelee: true
+ ChangeChase: true
+ Boss: true
+ }
+ MoveSpeed: 480
+ AttackDelay: 1600
+ AttackMotion: 672
+ DamageMotion: 480
+ Drops: {
+ HastePotion: 500
+ StrengthPotion: 500
+ }
+},
+{
Id: 1492
SpriteName: "Gladiator"
Name: "Gladiator"
diff --git a/npc/001-13/_import.txt b/npc/001-13/_import.txt
index 8f6744511..1ec37b78f 100644
--- a/npc/001-13/_import.txt
+++ b/npc/001-13/_import.txt
@@ -1,2 +1,3 @@
// Map 001-13: Showdown
// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-13/main.txt",
diff --git a/npc/001-13/main.txt b/npc/001-13/main.txt
new file mode 100644
index 000000000..1b7e145d1
--- /dev/null
+++ b/npc/001-13/main.txt
@@ -0,0 +1,195 @@
+// TMW2 Scripts
+// Author:
+// Jesusalva
+// Description:
+// Controls boss raid showdown (Freeyorp Event System - Boss Raid)
+
+function script FYRaid_Select {
+ 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
+ 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
+ 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);
+ }
+ }
+ }
+ 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) ? "##B" : "") + l("Level %d (%s HP) (Found by %s)", .@lv, .@hp, strcharinfo(0, l("offline player"), .@on)) + (.@on == getcharid(3) ? "##b" : ""));
+ 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;
+ }
+ // 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
+ .@mp$="fyrb@"+getcharid(0);
+ instance_attachmap("001-13", .@inst, false, .@mp$);
+
+ // Recreate the boss
+ .@lv = $FYRAID_HP[.@i];
+ .@mob=monster(.@mp$, 47, 33, $RAIDING_BOSS$, WanderingShadow, 1, "sBossRaid::OnBossDie");
+ setunitdata(.@mob, UDT_LEVEL, min(.@lv * 10, 200));
+ setunitdata(.@mob, UDT_STR, .@lv * 4);
+ setunitdata(.@mob, UDT_AGI, .@lv * 4);
+ 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);
+ 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;
+ addtimer 180000, "sBossRaid::OnTimeout";
+ addtimer 60000, "sBossRaid::OnPump";
+ dispbottom l("Time left: %s", FuzzyTime(@tm));
+ closeclientdialog;
+ 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];
+
+ // 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)));
+ } else if ($RAIDING_BOSS$ == "Janeb the Evil") {
+ .@msg$ = l("Chaos shall be the founding stone of my town! Falling star!");
+ percentheal -5, -10;
+ } else if ($RAIDING_BOSS$ == "Platyna the Red") {
+ .@msg$ = l("I, the rightful ruler, demand back this world! Tyranny!");
+ percentheal -1, -1;
+ SC_Bonus(10+.@lv, any(SC_BLIND, SC_POISON), 1);
+ } else if ($RAIDING_BOSS$ == "Benjamin the Frost") {
+ .@msg$ = l("Stop on your tracks, unfair being! Freeze!");
+ SC_Bonus(10+.@lv, any(SC_FREEZE, SC_SLEEP), 1);
+ } else if ($RAIDING_BOSS$ == "Reid the Terrific") {
+ .@msg$ = l("There is no free speech. Censorship!");
+ SC_Bonus(10+.@lv, SC_SILENCE, 1);
+ } else if ($RAIDING_BOSS$ == "Nu'Rem the Destroyer") {
+ .@msg$ = l("And then... There was a quake. And all life died. Bleed!");
+ SC_Bonus(10+.@lv, SC_BLOODING, 1);
+ } else if ($RAIDING_BOSS$ == "Golbenez the Cruel") {
+ .@msg$ = l("Puny mortal, do your best to entertain me! Curse!");
+ SC_Bonus(10+.@lv, SC_CURSE, 1);
+ } else if ($RAIDING_BOSS$ == "King of Typos") {
+ .@msg$ = l("The problem with typos is - unpredictable side effects.");
+ SC_Bonus(10+.@lv, any(SC_SILENCE, SC_CURSE, SC_FREEZE, SC_BLOODING, SC_BLIND, SC_POISON, SC_DPOISON, SC_POISON, SC_BURNING, SC_SLEEP), 1);
+ } else {
+ consolewarn("Unknown raiding boss: %s. No skill will be used.", $RAIDING_BOSS$);
+ }
+
+ unittalk(@mb, .@msg$);
+ dispbottom l("Time left: %s", FuzzyTime(@tm));
+ addtimer 60000, "sBossRaid::OnPump";
+ end;
+
+// Boss defeated
+OnBossDie:
+ dispbottom l("Boss defeated!");
+ // Clear bonus
+ getitem EventNaftalin, $FYRAID_LV[@id]/2+1;
+ .@new = 0;
+ goto OnClose;
+
+// Ran out of time
+OnTimeout:
+ dispbottom l("Time out!");
+ .@new = getunitdata(@mb, UDT_HP);
+ goto OnClose;
+
+// Warp you back
+OnClose:
+ .@old = $FYRAID_HP[@id];
+ .@dmg = .@new - .@old;
+ // Damage Bonus
+ if (.@dmg / 1000 > 1)
+ getitem EventNaftalin, .@dmg / 1000;
+
+ // 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");
+ sleep2(500);
+ teleporthome();
+ end;
+}
+
+001-13 mapflag zone MMO
diff --git a/npc/003-1/events.txt b/npc/003-1/events.txt
index 5540cc211..6175b9ebd 100644
--- a/npc/003-1/events.txt
+++ b/npc/003-1/events.txt
@@ -333,6 +333,8 @@ L_Aurora:
.@WHAT$=l("candor battle season");
} else if ($EVENT$ == "Tower") {
.@WHAT$=l("dream tower apparition");
+ } else if ($EVENT$ == "Raid") {
+ .@WHAT$=l("boss raid");
}
mesn;
diff --git a/npc/commands/event.txt b/npc/commands/event.txt
index 31fd527f2..ba81ca96c 100644
--- a/npc/commands/event.txt
+++ b/npc/commands/event.txt
@@ -535,11 +535,23 @@ OnEffect:
message strcharinfo(0), l("You are now at the Christmas Workshop.");
end;
}
- // FIXME: Dream Tower Warp
if ($EVENT$ == "Tower" && countitem(EventDreamTicket)) {
doevent "sDreamTower::OnWarpTo";
end;
}
+ if ($EVENT$ == "Raid") {
+ .@id = array_find($FYRAID_OWNER, getcharid(3));
+ if (.@id >= 0) {
+ if ($FYRAID_TIME[.@id] > gettimetick(2) &&
+ $FYRAID_HP[.@id] > 0) {
+ teleporthome();
+ dispbottom l("Talk to Soul Menhir to start.");
+ end;
+ }
+ // Boss expired or already defeated - ignore
+ }
+ // Have not yet taken part on boss raid - ignore
+ }
}
// Block here
diff --git a/npc/functions/aurora.txt b/npc/functions/aurora.txt
index d02f7747c..859bdd48f 100644
--- a/npc/functions/aurora.txt
+++ b/npc/functions/aurora.txt
@@ -39,6 +39,16 @@
//
// $WORLDEXPO_ENEMY$
// Name of the enemy responsible for ruining the World's Expo
+// $RAIDING_BOSS$
+// Name of the enemy who is raiding down the world
+// $DREAMTOWER_SAGE$
+// Name of the sage who owns the Dream Towers
+// DTOWER_DAY (CharReg)
+// Player variable which controls Dream Tower reset
+// DTOWER_ROLL (CharReg)
+// Player variable which controls Dream Ticket drop rate
+// DTOWER_FLOOR (CharReg)
+// Player variable which controls current Dream Tower floor
// AEF: BEGIN
@@ -60,9 +70,11 @@ function script FYNewEvent {
DelItemFromEveryPlayer(EventOre);
DelItemFromEveryPlayer(BrokenMedal);
DelItemFromEveryPlayer(EventDreamTicket);
+ DelItemFromEveryPlayer(EventNaftalin);
DelChrRegFromEveryPlayer(DTOWER_DAY);
DelChrRegFromEveryPlayer(DTOWER_ROLL);
DelChrRegFromEveryPlayer(DTOWER_FLOOR);
+ DelChrRegFromEveryPlayer(FYRAID_LV);
// Select the event
switch ($FYEVENT_CYCLE % 12) {
case 1:
@@ -122,7 +134,6 @@ function script FYNewEvent {
kamibroadcast("Candor Battle Season is now open!", "Aurora Events");
break;
default:
- // FIXME: PLACEHOLDER
$EVENT$="Tower";
callfunc("FYEConf_Tower");
kamibroadcast("Dream Towers have appeared!", "Aurora Events");
@@ -394,6 +405,40 @@ function script FYE_Tower1 {
+// Configure Boss Raid
+function script FYEConf_Raid {
+ $RAIDING_BOSS$=any("Xakabael the Dark", "Janeb the Evil", "Platyna the Red", "Benjamin the Frost", "Reid the Terrific", "Nu'Rem the Destroyer", "Golbenez the Cruel", "King of Typos");
+ deletearray $FYRAID_OWNER;
+ deletearray $FYRAID_TIME;
+ deletearray $FYRAID_HP;
+ deletearray $FYRAID_LV;
+ setarray $FYREWARD_PT, 10, 25, 50, 100, 150,
+ 200, 300, 500, 750, 1000,
+ 1250, 1500, 1750, 2000, 2500,
+ 3000, 3500, 4000, 5000, 6000,
+ 7500, 9000, 11000, 15000, 20000,
+ 25000, 30000, 35000, 40000, 50000;
+ // PS. Max Est. ?
+
+ FYE_Autoset();
+ $FYLOGIN_PTS=rand2(1, 2);
+ return;
+}
+
+// Boss Raid Appears!
+function script FYE_Raid {
+ .@mob=getarg(0, killedrid);
+ // Obtain the monster level and roll a hidden counter
+ .@lv=getmonsterinfo(.@mob, MOB_LV);
+ DTOWER_ROLL+=.@lv;
+ return;
+}
+
+
+
+
+
+
// Configure Fishing
function script FYEConf_Fishing {
@@ -504,6 +549,12 @@ function script FYE_Submit {
setq2 Q_AuroraEvent, .@pts;
delitem BrokenMedal, countitem(BrokenMedal);
+ } else if ($EVENT$ == "Raid") {
+ // .:: BOSS RAID ::.
+ .@pts+=countitem(EventNaftalin)*1;
+
+ setq2 Q_AuroraEvent, .@pts;
+ delitem EventNaftalin, countitem(EventNaftalin);
} else {
// Wut? This is not an Aurora Event
Exception($EVENT$+" is NOT a valid Aurora Event; Misdefinition.\n\nPlease ensure that it is defined in utils, aurora, news, and command/event.\n\nFYE_Submit - FYEventUsesRanking - FYE_* - FYEConf_* - FYStopEvent", RB_DEFAULT|RB_ISFATAL);
@@ -518,7 +569,7 @@ function script FYE_Submit {
// Stops any Aurora Event
function script FYStopEvent {
- setarray .@av$, "Kamelot", "Regnum", "Expo", "Fishing", "Candor", "Mining", "Tower";
+ setarray .@av$, "Kamelot", "Regnum", "Expo", "Fishing", "Candor", "Mining", "Tower", "Raid";
if (array_find(.@av$, $EVENT$) >= 0) {
sClear();
$EVENT$="";
diff --git a/npc/functions/news.txt b/npc/functions/news.txt
index ab5be1b52..1b1e51ae2 100644
--- a/npc/functions/news.txt
+++ b/npc/functions/news.txt
@@ -288,13 +288,24 @@ function script EventHelp {
mes l("The dream towers have shown up. They have several floors filled with treasure and dangerous monsters.");
mes l("Every day, they disappear and a new one shows up on its place.");
mes "";
- mes l("You need a %s for each floor, and defeat the gatekeeper to advance.", "Dream Ticket");
+ mes l("You need a %s for each floor, and defeat the gatekeeper to advance.", getitemlink(EventDreamTicket));
mes l("Floors cannot be re-visited, and rewards increase at each floor.");
mes "";
mes l("These towers must hold unfathomable secrets from %s.", $DREAMTOWER_SAGE$);
mes l("We must find out what lies at the top, whatever the cost!");
mesc l("Location: The Mana Plane, Dream Tower"), 3;
/////////////////////////////////////////////////////////////////////////
+ } else if ($EVENT$ == "Raid") {
+ mesc ".:: " + l("Boss Raid") + " ::.", 2;
+ mes "";
+ mes l("This is terrible - a fiend from a parallel dimension has broken in ours!");
+ mes l("We are unsure of the cause, but they must be repelled at any cost!");
+ mes l("Meanwhile, the sages of destiny will prepare a way to kick them back to wherever they belong!");
+ mes "";
+ mes l("Can we keep %s at bay long enough?", $RAIDING_BOSS$);
+ mes l("Collect their %s as well, so our wizards can do their magic!", getitemlink(EventNaftalin));
+ mesc l("Location: The Mana Plane, Showdown Chamber"), 3;
+ /////////////////////////////////////////////////////////////////////////
} else {
mesc l("There's no help available for this event.");
/////////////////////////////////////////////////////////////////////////
diff --git a/npc/functions/soul_menhir.txt b/npc/functions/soul_menhir.txt
index 2b2b1a897..92fd8b688 100644
--- a/npc/functions/soul_menhir.txt
+++ b/npc/functions/soul_menhir.txt
@@ -22,6 +22,7 @@ function script SoulMenhir {
rif($EVENT$ == "Worker", l("[Worker Day] Send soul to the Contributor Cave!")), L_Worker,
rif($EVENT$ == "Christmas" && BaseLevel >= 20, l("[Christmas] Send soul to the Christmas Workshop!")), L_Xmas, // TODO: In future there'll be an event map
rif($EVENT$ == "Tower" && countitem(EventDreamTicket), l("Dream Tower")), L_Tower,
+ rif($EVENT$ == "Raid", l("Boss Raid")), L_Raid,
l("Leave it alone."), -;
return;
@@ -92,13 +93,17 @@ L_Xmas:
message strcharinfo(0), l("You are now at the Christmas Workshop.");
close;
-// FIXME: Dream Tower Warp
L_Tower:
if ($EVENT$ != "Tower") goto L_DontPanic;
if (!countitem(EventDreamTicket)) goto L_DontPanic;
doevent "sDreamTower::OnWarpTo";
close;
+L_Raid:
+ if ($EVENT$ != "Raid") goto L_DontPanic;
+ callfunc("FYRaid_Select");
+ close;
+
L_DontPanic:
message strcharinfo(0), l("(A strange barrier keeps you from touching the stone at this time.)");
return;
diff --git a/npc/functions/util.txt b/npc/functions/util.txt
index abcbfc903..f64383b69 100644
--- a/npc/functions/util.txt
+++ b/npc/functions/util.txt
@@ -662,7 +662,7 @@ function script islegendary {
// Returns if an event is a ranked Aurora Event or not
// (Had to be moved from functions/aurora.txt)
function script FYEventUsesRanking {
- setarray .@av$, "Expo", "Fishing", "Mining", "Tower";
+ setarray .@av$, "Expo", "Fishing", "Mining", "Tower", "Raid";
if (array_find(.@av$, $EVENT$) >= 0) {
return true;
}