// TMW2 Script
// Author:
// dangerDuck
// Description:
// Duck Elder is a friendly npc.
// The first stage of the Elder's quest consists of a supply restock
// Second/third stage of the quest consists of a pirate attack
// Fourth (last) stage will be the Duck Dungeon, an HH-like training ground for initiates of the Duck Side (WIP)
// Variables:
// LilitQuest_PiratesOfSARAH
018-5-4,28,73,0 script Duck Elder NPC_DUCK_ELDER,{
function elderQuest;
function elderSupplyMenu;
function elderSupplyList;
function elderSupplyGive;
function elderPirateAttack;
function elderPirateVictory;
function elderPirateDefeat;
function elderPirateReward;
function elderAbout;
function elderAboutSarah;
function elderInitiate;
function elderClose;
.@q=getq(LilitQuest_PiratesOfSARAH);
mesn;
mesq l("Hello %s. What brings you here?", get_race());
next;
select
rif(.@q == 0, l("I've heard tidings of strange goings-on in this area...")),
rif(.@q == 1, l("I'm here to help you restock...")),
rif(.@q == 2, l("What did the Council of Elders say? Is there any news of the pirates?")), // FIXME Lv50 players missed this info S:
rif(.@q == 3, l("Have the pirates been routed? Will they return?")),
rif(.@q == 4, l("I'm here as an Initiate. May I enter Duck Dungeon?")),
l("Oh, I'm just exploring. What can you tell me about this island?"),
l("I came to enjoy a beautiful day with some ducks!");
mes "";
switch (@menu) {
case 1:
elderQuest();
break;
case 2:
elderSupplyMenu();
break;
case 3:
elderPirateAttack();
break;
case 4:
elderPirateReward();
break;
case 5:
elderInitiate();
break;
case 6:
elderAbout();
// fallthrough
default:
elderClose();
break;
}
close;
function elderQuest {
if (BaseLevel < 50) {
mesn;
mesq l("Unfortunately, a mere fledgling like you is not strong enough to help us.");
next;
elderClose();
return;
}
mesn;
mesq l("Your information is correct, %s. Pirates have been plaguing our shores and cutting off our supply lines.", get_race());
next;
mesn;
mesq l("We are in desperate need of food and nesting material, as well as our sacred supply of @@.", getitemlink(CrystallizedMaggot));
next;
setq LilitQuest_PiratesOfSARAH, 1;
elderSupplyList();
elderClose();
return;
}
function elderSupplyMenu {
do
{
mesn;
mesq l("Did you bring the supplies?");
next;
select
l("Yes, I have them right here."),
l("What did you want? I've forgotten."),
l("Not yet. I've been... delayed.");
mes "";
switch (@menu) {
case 1:
elderSupplyGive();
break;
case 2:
elderSupplyList();
break;
case 3:
elderClose();
close;
break;
}
} while (true);
return;
}
function elderSupplyList {
mesq "";
mesn;
mesq l("We need:");
mesq l("%d/%d %s", countitem(Moss), 300, getitemlink(Moss));
mesq l("%d/%d %s", countitem(RoastedMaggot), 250, getitemlink(RoastedMaggot));
mesq l("%d/%d %s", countitem(FishBox), 20, getitemlink(FishBox));
mesq l("%d/%d %s", countitem(CrystallizedMaggot), 1, getitemlink(CrystallizedMaggot));
next;
mesn;
mesq l("Of course, we'll find a way to reward you for your efforts.");
next;
return;
}
function elderSupplyGive {
if (countitem(Moss) < 300 ||
countitem(RoastedMaggot) < 250 ||
countitem(FishBox) < 20 ||
countitem(CrystallizedMaggot) < 1) {
mesn;
mesq l("This isn't what we requested. Perhaps you should count your items more carefully.");
next;
mesn;
mesq l("If you aren't more careful, we might... accidentally... mistake you for an agent of S.A.R.A.H.");
percentheal -99, 0;
close;
}
inventoryplace RubberDucky, 1;
delitem(Moss, 300);
delitem(RoastedMaggot, 250);
delitem(FishBox, 20);
delitem(CrystallizedMaggot, 1);
getitem(RubberDucky, 1);
getexp(34576, 19226);
setq(LilitQuest_PiratesOfSARAH, 2);
mes "";
mesn;
mesq l("We appreciate your help. Take this %s as a token of goodwill.", getitemlink(RubberDucky));
next;
mesn;
mesq l("If you're ever in need, you may use it to call upon the aid of the ducks.");
next;
if (BaseLevel < 75) {
mesn;
mesq l("Go now, with the blessing of ducks. There may come a time when we require your aid once again, O %s.", get_race());
} else {
mesn;
mesq l("We may require your aid again soon. The tritan pirates are amassing and we fear they are planning a siege of Duck Island. I must speak with the Council of Elders...");
}
close;
}
function elderPirateAttack {
// Level requirement
if (BaseLevel < 75) {
mesn;
mesq l("The pirates amass for their siege, but they will not attack yet. Return when you are stronger. King DD is working to find a solution.");
return;
}
mesn;
mesq l("The pirates have been surrounding our island for many sun rises. We expect they will attack any time.");
next;
mesn;
mesq l("The Council of Elders has enlisted ducks of our island into a militia. In addition, the masters of the Duck Side have seen fit to spare %d Duck initiates to assist us.", (BaseLevel/20));
next;
mesn;
mesq l("Please be careful when fighting. A mighty warrior such as yourself can harm their allies with any AoE effects they may use.");
next;
mesc l("Accept quest?"), 1;
if (askyesno() == ASK_NO)
return;
.@mapn$="duck@"+getcharid(0);
// Build instance if it doesn't exists or has been reallocated
if (instanceowner(@duckinst) != getcharid(3)) {
@duckinst = instance_create("duck@a"+getcharid(0), getcharid(3), IOT_CHAR);
instance_attachmap("018-5-4", @duckinst, false, .@mapn$);
// Instance lasts 6 minutes
instance_set_timeout(360, 360, @duckinst);
instance_init(@duckinst);
} else {
// Restart instance timer if it already exists
instance_set_timeout(360, 360, @duckinst);
}
getmapxy(.@m$, .@x, .@y, 0);
warp .@mapn$, .@x, .@y;
//debugmes "Warp successful";
//debugmes "Prepare timer, target: %s in %d - aka. %s", .name$, @duckinst, instance_npcname(.name$, @duckinst);
addtimer(300, .name$+"::OnBegin");
closeclientdialog;
close;
return;
}
OnBegin:
//debugmes "BEGIN NPC %s, char %s. Map %s", instance_npcname(.name$, @duckinst), strcharinfo(0), getmap();
.@n$=instance_npcname(.name$, @duckinst);
.@m$=getmap();
killmonsterall(getmap());
@pLvl = BaseLevel;
@pirate_killed = 0;
@duck_killed = 0;
@total_pirates = 0;
@total_ducks = 0;
setnpcdisplay .@n$, NPC_NO_SPRITE;
sleep2(1000);
mapannounce(getmap(), "Duck Elder : Here they come...", bc_map);
sleep2(1000);
mapannounce(getmap(), "Duck Elder : DUCKS TO ARMS! KILL ALL, SHOW NO MERCY!", bc_map);
sleep2(1000);
mapannounce(getmap(), "##2Victory: Kill all pirates within 5 minutes. Protect the duck fighters.", bc_map);
mapannounce(getmap(), "##1Defeat: All ducks are slain.", bc_map);
// Spawn Monsters
// FIXME MIGHT NOT WORK WITH COORDINATES ZERO (for several reasons)
// PLEASE PREFER AREAMONSTER
monster(.@m$, 0, 0, "Ocean Pirate", OceanPirate, (@pLvl/2), "Duck Elder::OnPirateKilled");
@total_pirates+=(@pLvl/2);
monster(.@m$, 0, 0, "Pirate Captain", OceanPirate, (@pLvl/15), "Duck Elder::OnPirateKilled"); // FIXME
@total_pirates+=(@pLvl/15);
monster(.@m$, 0, 0, "Desert Pirate", DesertBandit, (@pLvl/3), "Duck Elder::OnPirateKilled");
@total_pirates+=(@pLvl/3);
monster(.@m$, 0, 0, "Marsh Pirate", Bandit, (@pLvl/4), "Duck Elder::OnPirateKilled");
@total_pirates+=(@pLvl/4);
monster(.@m$, 0, 0, "Buccaneer", Sarracenus, (@pLvl/7), "Duck Elder::OnPirateKilled");
@total_pirates+=(@pLvl/7);
monster(.@m$, 0, 0, "Corsair", RobinBandit, (@pLvl/7), "Duck Elder::OnPirateKilled");
@total_pirates+=(@pLvl/7);
monster(.@m$, 0, 0, "Pirate Lord", BanditLord, (@pLvl/12), "Duck Elder::OnPirateKilled");
@total_pirates+=(@pLvl/12);
monster(.@m$, 0, 0, "Pirate Assassin", HoodedAssassin, (@pLvl/25), "Duck Elder::OnPirateKilled");
@total_pirates+=(@pLvl/25);
debugmes "Pirates of SARAH, \"%s\" - Total: %d (Lv %d)", strcharinfo(0), @total_pirates, @pLvl;
// Reinforcements
// FIXME: We might not want summon() here (summon is immune to AOE)
// We probably want bg_monster (blame Jesusalva) or monster w/ alchemy flag
for(.@i = 0; .@i < min(10, @pLvl/5); ++.@i) {
.@sd=summon("Duck Soldier", Duck, 300000, "Duck Elder::OnDuckKilled");
.@bhp=getunitdata(.@sd, UDT_MAXHP);
// Abizit makes bonus HP vary (like AdjustSpellpower)
.@lvx = .@bhp * (80 + abizit() * rand2(5,10)) / 100;
setunitdata(.@sd, UDT_MAXHP, .@lvx);
setunitdata(.@sd, UDT_HP, .@lvx);
@total_duck++;
}
for(.@i = 0; .@i < min(5, @pLvl/20); ++.@i) {
.@sd=summon("Duck Initiate", EliteDuck, 300000, "Duck Elder::OnDuckKilled");
.@bhp=getunitdata(.@sd, UDT_MAXHP);
// Abizit makes bonus HP vary (like AdjustSpellpower)
.@lvx = .@bhp * (80 + abizit() * rand2(5,10)) / 100;
setunitdata(.@sd, UDT_MAXHP, .@lvx);
setunitdata(.@sd, UDT_HP, .@lvx);
@total_duck++;
}
// Begin timer
//initnpctimer();
addtimer 300000, "Duck Elder::OnTimerQuit";
end;
OnPirateKilled:
@pirate_killed++;
.@mia=@total_ducks-@duck_killed;
if (.@mia < mobcount(getmap(), "Duck Elder::OnDuckKilled"))
@duck_killed=@total_ducks-mobcount(getmap(), "Duck Elder::OnDuckKilled");
if (@duck_killed >= @total_ducks) {
elderPirateDefeat();
}
if (@pirate_killed >= @total_pirates) {
elderPirateVictory();
}
end;
OnDuckKilled:
if (!playerattached())
end;
@duck_killed++;
if (@duck_killed >= @total_ducks) {
elderPirateDefeat();
}
end;
OnTimer300000:
elderPirateDefeat();
end;
// Do this even work O.o
OnTimerQuit:
elderPirateDefeat();
end;
function elderPirateVictory {
stopnpctimer();
@pirate_killed = 0;
@duck_killed = -50; // Set to -50 to make sure defeat doesn't trigger when monsters are killed
announce("Duck Elder : Success! The pirates have been thwarted.", bc_self);
.@n$=instance_npcname(.name$, @duckinst);
setnpcdisplay .@n$, NPC_DUCK_ELDER;
setq(LilitQuest_PiratesOfSARAH, 3);
getmapxy(.@m$, .@x, .@y, 0);
killmonsterall(.@m$);
warp "018-5-4", .@x, .@y;
sleep2(10);
dispbottom l("Duck Elder : Success! The pirates have been thwarted.");
end;
}
function elderPirateDefeat {
//stopnpctimer();
@pirate_killed = -50; // Set to -50 to make sure victory doesn't trigger when monsters are killed
@duck_killed = -50;
announce("Duck Elder : We have failed. The pirates will regroup and replenish their fallen. They will strike again, until we are defeated.", bc_self);
.@n$=instance_npcname(.name$, @duckinst);
setnpcdisplay .@n$, NPC_DUCK_ELDER;
getmapxy(.@m$, .@x, .@y, 0);
killmonsterall(.@m$);
warp "018-5-4", .@x, .@y;
sleep2(10);
dispbottom l("Duck Elder : We have failed. The pirates will regroup and replenish their fallen. They will strike again, until we are defeated.");
end;
}
function elderPirateReward {
mesn;
mesq l("We are no longer in danger, thanks to you. The pirates were thoroughly defeated. None survived the battle.");
next;
mesn;
mesq l("The masters of the Duck Side, The Council of Elders, and King DD himself, on behalf of all ducks, thank you for your help. We wouldn't have survived without it.");
getexp(458593, 59505);
setq(LilitQuest_PiratesOfSARAH, 4);
next;
mesn;
mesq l("The masters have decided you are to be given honorary initiation into the Duck Side. The Duck Side is powerful, much more so than you could possibly understand.");
next;
mesn;
mesq l("You must understand that this honor has never been granted to a non-duck before. You will have access to Duck Dungeon, a training grounds for Initiates.");
next;
mesn;
mesq l("As an honorary member of the Duck Side, know that we are more than we appear. The Moubootaur itself has seen fit to reward us when it awakens. Do not attempt to cross us.");
// NOTE: The Moubootaur is "evil"; Therefore, Duck Side is evil too
// (This is a de facto standard; A global truth any specie which knows
// the Moubootaur Legend is aware of)
close;
return;
}
function elderInitiate {
mesn;
mesq l("We are deliberating. Some do not... approve of your initiation. Leave.");
mesc "* "+l("Kolchak and dangerDuck are working to finish Duck Dungeon. Contact them for updates...");
return;
}
function elderAbout {
mesn;
mesq l("This is Duck Island, the last safe refuge for birds. Ducks tend to be very peaceful, but our young ruler, King DD, has been taken up with the art of war.");
next;
mesn;
mesq l("Unfortunately, he has been corrupted by the terrorist organization calling itself S.A.R.A.H. Hopefully, he will return to the ways of peace and bring prosperity to Duck Island once again.");
next;
select
l("What's S.A.R.A.H.?"),
l("Thanks, I think I'll continue exploring.");
mes "";
if (@menu == 1)
elderAboutSarah();
close;
return;
}
function elderAboutSarah {
mesn;
mesq l("As I said, S.A.R.A.H. is a terrorist organization. They are dedicated to wiping out every single duck, worldwide. No duck has ever survived an encounter with a S.A.R.A.H. agent. You would do best to avoid them.");
next;
mesn;
mesq l("I suggest you leave now, %s. If you are even suspected of being a S.A.R.A.H. agent...", get_race());
close;
return;
}
function elderClose {
mesn;
mesq l("Enjoy your time here, %s. And keep your eye out for agents of S.A.R.A.H.", get_race());
next;
mesn;
if (BaseLevel < 50) {
mesq l("Perhaps you may be of assistance later...");
} else {
mesq l("I may have a task for you. Return when you tired of exploring...");
}
close;
return;
}
OnInit:
.sex = G_OTHER;
.distance = 4;
end;
OnInstanceInit:
disablenpc instance_npcname(.name$);
end;
}