1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
|
// 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 requeriment
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, "Duck Elder::OnPirateKilled");
@total_pirates+=@pLvl;
monster(.@m$, 0, 0, "Pirate Captain", OceanPirate, (@pLvl/10), "Duck Elder::OnPirateKilled"); // FIXME
@total_pirates+=(@pLvl/10);
monster(.@m$, 0, 0, "Desert Pirate", DesertBandit, (@pLvl/3), "Duck Elder::OnPirateKilled");
@total_pirates+=(@pLvl/3);
monster(.@m$, 0, 0, "Marsh Pirate", Bandit, (@pLvl/3), "Duck Elder::OnPirateKilled");
@total_pirates+=(@pLvl/3);
monster(.@m$, 0, 0, "Buccaneer", Sarracenus, (@pLvl/6), "Duck Elder::OnPirateKilled");
@total_pirates+=(@pLvl/6);
monster(.@m$, 0, 0, "Corsair", RobinBandit, (@pLvl/5), "Duck Elder::OnPirateKilled");
@total_pirates+=(@pLvl/5);
monster(.@m$, 0, 0, "Pirate Lord", BanditLord, (@pLvl/11), "Duck Elder::OnPirateKilled");
@total_pirates+=(@pLvl/11);
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;
}
|