-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlib_Quests.lua
1185 lines (1143 loc) · 37.5 KB
/
lib_Quests.lua
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
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
local aName, aTable = ...;
local require = ExiWoW.require
aTable.quests = function(self)
local Quest = require("Quest");
local Objective = Quest.Objective;
local Event = require("Event");
local Reward = Quest.Reward;
local Timer = require("Timer");
local Character = require("Character");
local RPText = require("RPText");
local UI = require("UI");
local Condition = require("Condition");
local Talkbox = require("Talkbox");
local Tools = require("Tools");
local out = {}
-- Undervine 0
table.insert(out, Quest:new({
id = "UNDERVINE_0",
name = "Vine Research",
start_text = {
"Ishnu alah, traveler. I need help with some research I'm doing.",
"Life out here tends to get lonely, and I have been working on a way to spice things up a little.",
"I have a spell to craft living vine underwear, but I'm severely lacking in living vines.",
"That's where you come in. Interested?"
},
journal_entry = "Myria Glenbrook in Lightsong south east in Val'sharah is working on vine-based underwear but is lacking vines.\n\nI could go north to Moonrest and collect small vines from the Deathblossoms there.",
end_journal = "Return to Myria Glenbrook in Lightsong",
questgiver = 70971,
end_text = {
"These vines look a little dead, but it's a start.",
function()
PlaySound(23435, "SFX");
return "[Myria fashions a makeshift thong from the vines]";
end,
"There you are, the next step will be to purify them."
},
rewards = {
Reward:new({
id = "WITHERED_VINE_THONG",
type = "Underwear"
})
},
objectives = {
Objective:new({
id = "vinesCollected",
name = "Creeping Deathblossom Vines",
num = 15, -- Num of name to do to complete it
onObjectiveEnable = function(self)
self:on(Event.Types.MONSTER_KILL, function(data)
if data.name == "Creeping Deathblossom" or data.name == "Mature Deathblossom" then
PlaySound(1187, "SFX");
self:add(1);
end
end);
end, -- Raised when objective is activated
onObjectiveDisable = function(self)
end -- Raised when objective is completed or disabled
}),
}, -- You can wrap objectives in {} to create packages
start_events = {
{
event = Event.Types.POINT_REACHED,
data = {zone="Val'sharah", sub="Lightsong", x=60.18, y=84.83, dist=0.21},
max = 1,
fn = function(self, data)
return true;
end
}
},
end_events = true
}));
-- Undervine 1
table.insert(out, Quest:new({
id = "UNDERVINE_1",
name = "Pricks and Goo",
start_text = {
"We have the thong, but it's much too withered to animate.",
"I know of a few reagents that will liven things up a little. Would you be willing to help some more?",
"Lostlight Grotto just east of here has slimes that can lubricate the vines.",
"Lunarwing Shallows to the west is home to Thistleleaf Thorndancers who throw enchanted Quill Barbs at you.",
"For either of the reagents to work, they will have to make direct contact with the thong.",
"The vines SHOULD protect you, but it might still sting. I have no doubts that one such as yourself can handle it!"
},
journal_entry =
"Myria Glenbrook in Lightsong south east in Val'sharah asked me to infuse the Withered Vine Thong with two reagents.\n\n"..
"For it to work I must first take off my pants and wear the Withered Vine Thong."..
"The first reagent is ooze from the slimes in Lostlight Grotto, just east of Lightsong. Simply killing the slimes should be enough to make them splatter across the thong.\n\n"..
"The other reagent is quill barbs cast by the Thistleleaf Thorndancers further west and across the road. I should make sure I don't use any shields obstructing the quill barb's path.\n\n"
,
end_journal = "Return to Myria Glenbrook",
questgiver = 70971,
end_text = {
function()
local text = "Excellent! Just a moment.";
if not GetInventoryItemID("player", 7) then
text = text.." Feel free to put your leggings back on.";
end
return text;
end,
function()
PlaySound(3331, "SFX");
return "[Myria purifies your thong]";
end,
"A resounding success!"
},
rewards = {
Reward:new({
id = "EVERLIVING_VINE_THONG",
type = "Underwear"
})
},
onCompletion = function(self)
if ExiWoW.ME:getUnderwear() and ExiWoW.ME:getUnderwear().id == "WITHERED_VINE_THONG" then
ExiWoW.ME:useUnderwear("EVERLIVING_VINE_THONG");
end
ExiWoW.ME:removeUnderwear("WITHERED_VINE_THONG");
end,
objectives = {
{
Objective:new({
id = "wearThong",
name = "Withered Vine Thong Worn",
num = 1, -- Num of name to do to complete it
onObjectiveEnable = function(self)
self.timer = Timer.set(function()
if ExiWoW.ME:getUnderwear() and ExiWoW.ME:getUnderwear().id == "WITHERED_VINE_THONG" then
self:add(1);
end
end, 1, math.huge);
end, -- Raised when objective is activated
onObjectiveDisable = function(self)
if self.timer then Timer.clear(self.timer); end
end -- Raised when objective is completed or disabled
}),
Objective:new({
id = "removePants",
name = "Pants unequipped",
num = 1, -- Num of name to do to complete it
onObjectiveEnable = function(self)
self.timer = Timer.set(function()
if GetInventoryItemID("player", 7) == nil then
self:add(1);
end
end, 1, math.huge);
end, -- Raised when objective is activated
onObjectiveDisable = function(self)
if self.timer then Timer.clear(self.timer); end
end -- Raised when objective is completed or disabled
}),
},
{
Objective:new({
id = "slimeInfusions",
name = "Slime Infusions",
num = 8, -- Num of name to do to complete it
onObjectiveEnable = function(self)
self:on(Event.Types.MONSTER_KILL, function(data)
if
data.name == "Undulating Boneslime" and
GetInventoryItemID("player", 7) == nil and
ExiWoW.ME:getUnderwear() and
ExiWoW.ME:getUnderwear().id == "WITHERED_VINE_THONG"
then
RPText.trigger("BONESLIME_PROC", "none", "player", Character.buildNPC("none", "Undulating Boneslime"), ExiWoW.ME, nil, Event.Types.MONSTER_KILL);
PlaySound(73080, "SFX");
self:add(1);
end
end);
end, -- Raised when objective is activated
onObjectiveDisable = function(self)
end -- Raised when objective is completed or disabled
}),
Objective:new({
id = "quillBarbInfusions",
name = "Quill Barb Infusions",
num = 3, -- Num of name to do to complete it
onObjectiveEnable = function(self)
self:on(Event.Types.SPELL_TICK, function(data)
if
data.aura and data.aura.name == "Quill Barb" and
GetInventoryItemID("player", 7) == nil and
ExiWoW.ME:getUnderwear() and
ExiWoW.ME:getUnderwear().id == "WITHERED_VINE_THONG"
then
RPText.trigger("QUILLBARB_PROC", data.unit, "player", Character.buildNPC(data.unit, data.name), ExiWoW.ME, nil, Event.Types.SPELL_TICK);
PlaySound(75922, "SFX");
self:add(1);
end
end);
end, -- Raised when objective is activated
onObjectiveDisable = function(self)
end -- Raised when objective is completed or disabled
}),
}
}, -- You can wrap objectives in {} to create packages
start_events = {
{
event = Event.Types.POINT_REACHED,
data = {zone="Val'sharah", sub="Lightsong", x=60.18, y=84.83, dist=0.21},
fn = function(self, data)
if Quest.isCompleted("UNDERVINE_0") then
return true;
end
end
}
},
end_events = true
}));
-- Undervine 2
table.insert(out, Quest:new({
id = "UNDERVINE_2",
name = "Bear for Honey",
start_text = {
"While you were out I received a visit from a furbolg named Grizzleback.",
"A big, warm man bear with soft fur, wearing only a loincloth to conceal his large...",
"[Myria bites her lower lip]",
"Do you think you could visit Elandris Bladesong and see if he has any honey to present as a gift?",
"I'm sure if you help him defend his home, he'll let you have some. Then could you present it to Grizzleback and tell him it's from me?",
"If all goes well, I'll let you keep the vine thong, and I'll even teach you a spell to make it wiggle pleasantly!"
},
journal_entry =
"Myria Glenbrook in Lightsong south east in Val'sharah asked me to visit Elandris Bladesong living above Grizzleweald north east of Lightsong.\n\n"..
"I am to collect honey from him and present it to Old Grizzleback in Grizzleweald, as a gift from Myria."
,
end_journal = "Return to Myria Glenbrook",
questgiver = 70971,
end_text = {
"He said he'll meet me? That's wonderful news! Now these woods won't be so lonely.",
"Keep the thong, you've earned it! And take this spell, I won't be needing it anymore!"
},
rewards = {
Reward:new({
id = "VINE_SQUIRM",
type = "Charges",
quant = math.huge
})
},
objectives = {
Objective:new({
id = "visitElandris",
name = "Elandris Visited",
num = 1,
onObjectiveEnable = function(self)
-- Success
self:on(Event.Types.POINT_REACHED, function()
if GetQuestsCompleted()[43176] then
UI.talkbox.set(Talkbox:new({
lines = {
"I am in your debt. I have a jar of honey, it's around here... somewhere.",
"Sorry I am afraid you will have to search my home for it."
},
displayInfo = 70942,
title = "",
}));
self:add(1);
end
end, {zone="Val'sharah", sub="Bladesong's Retreat", x=67.43, y=69.42, dist=0.25});
end,
onObjectiveDisable = function(self)
end
}),
Objective:new({
id = "findHoney",
name = "Forage for Honey",
num = 1,
onObjectiveEnable = function(self)
-- Success
self:on(Event.Types.FORAGE, function()
if math.random() < 0.75 then return false end
if Condition.all({
Condition:new({
type = Condition.Types.RTYPE_LOC,
data = {x=67.43, y=69.42, rad=0.25}
}),
Condition:new({
type = Condition.Types.RTYPE_ZONE,
data = "Val'sharah"
}),
Condition:new({
type = Condition.Types.RTYPE_SUBZONE,
data = "Bladesong's Retreat"
}),
}, "player", "player", ExiWoW.ME, ExiWoW.ME) then
PlaySound(1217, "SFX");
UI.talkbox.set(Talkbox:new({
lines = {
"Ah you found it! Give Myria my regards!",
},
displayInfo = 70942,
title = "",
}));
self:add(1);
end
end);
end,
onObjectiveDisable = function(self)
end
}),
Objective:new({
id = "deliverHoney",
name = "Deliver Honey to Grizzleback",
num = 1,
onObjectiveEnable = function(self)
self:on(Event.Types.GOSSIP_SHOW, function()
if UnitName("target") == "Old Grizzleback" then
UI.talkbox.set(Talkbox:new({
lines = {
"She said she wanted to see me again AND brought me this honey?",
"Of course! Do you think she could use some druidic rejuvenate magic on me? I may not be as limber anymore, but I bet I can still give her a good time.",
"Tell her that I will be over as soon as we are done with these grells."
},
displayInfo = 62198,
title = "",
onComplete = function()
self:add(1);
end
}));
end
end);
end,
onObjectiveDisable = function(self)
end
}),
}, -- You can wrap objectives in {} to create packages
start_events = {
{
event = Event.Types.POINT_REACHED,
data = {zone="Val'sharah", sub="Lightsong", x=60.18, y=84.83, dist=0.21},
fn = function(self, data)
if Quest.isCompleted("UNDERVINE_1") then
return true;
end
end
}
},
end_events = true
}));
-- Undervine 3
table.insert(out, Quest:new({
id = "UNDERVINE_3",
name = "Mischief, naturally!",
start_text = {
"Ooh, I sense someone with an interesting garment. Come over here by the gazebo for a moment!",
},
journal_entry = {
"Azalea by the gazebo in Lorlathil wants to talk to you.",
"She has offered to make your Everliving Vine Thong more spritely if you exact revenge on Callista Swiftglaive who is the armorsmith in Lorlathil.\n\n"..
"To do so, you must go find dark tentacle powder that some of the Darkfiend Tormentors in Sleeper's Barrow to the south might be carrying. "..
"Then hide it in the plate panties located somewhere in Callista's house, probably her drawer."
,
},
end_journal = "Return to Azalea",
questgiver = 13672,
end_text = {
"Ahaha! This is going to be so good. Next time she complains about muddy hooves I will be all like 'WOOSH!' and the tentacles will all come to life! Ehehe I can NOT wait to see the look on her face!",
"Good job! Here is the spell if you too want to make some mischief!",
},
rewards = {
Reward:new({
id = "VINE_THRASH",
type = "Charges",
quant = math.huge
})
},
objectives = {
Objective:new({
id = "talkToAzalea",
name = "Talk to Azalea",
num = 1,
onObjectiveEnable = function(self)
-- Success
self:on(Event.Types.GOSSIP_SHOW, function()
if UnitName("target") == "Azalea" then
UI.talkbox.set(Talkbox:new({
lines = {
"That vine thong you're wearing. I have seen other adventurers with it, and I think it is time for some mischief.",
"You may know how to make it squirm a little, but we can use some wild magic to REALLY make it go!",
"I will teach you a spell if you help me play a little prank.",
"Callista Swiftglaive, the armorsmith here in Lorlathil had the nerve to kick me out of her house JUST because my hooves were a little muddy.",
"She is wearing that skimpy chestplace and I KNOW she has plate panties to go with them somewhere.",
"Go to Sleeper's Barrow to the south where the satyr are summoning their tentacle fiends, hunt them until you find some tentacle powder.",
"Go to Callista's shack and place the seed in her panties, my nature magic will take care of the rest."
},
displayInfo = 13672,
title = "",
onComplete = function()
self:add(1);
end
}));
end
end);
end,
onObjectiveDisable = function(self)
end
}),
Objective:new({
id = "darkTentaclePowder",
name = "Dark Tentacle Powder Bag",
num = 1, -- Num of name to do to complete it
onObjectiveEnable = function(self)
self:on(Event.Types.MONSTER_KILL, function(data)
if data.name == "Darkfiend Tormentor" and math.random() < 0.25 then
PlaySound(1187, "1187");
RPText.print("You found a small bag of dark tentacle powder on the satyr!");
self:add(1);
end
end);
end, -- Raised when objective is activated
onObjectiveDisable = function(self)
end -- Raised when objective is completed or disabled
}),
Objective:new({
id = "sprinklePowder",
name = "Powder Sprinkled in Callista's Plate Panties",
num = 1, -- Num of name to do to complete it
onObjectiveEnable = function(self)
self:on(Event.Types.POINT_REACHED, function()
if GetQuestsCompleted()[43176] then
UI.talkbox.set(Talkbox:new({
lines = {
"This is the drawer holding Callista's plate panties.",
function()
DoEmote("KNEEL", "none");
PlaySound(1277, "SFX");
return "[You quickly sprinkle the powder into them and put them back]";
end
},
onComplete = function()
self:add(1);
end,
displayInfo = "player",
title = "",
}));
end
end, {zone="Val'sharah", sub="Lorlathil", x=54.42, y=71.89, dist=0.05});
end,
onObjectiveDisable = function(self)
end
}),
}, -- You can wrap objectives in {} to create packages
start_events = {
{
event = Event.Types.POINT_REACHED,
data = {zone="Val'sharah", sub="Lorlathil"},
fn = function(self, data)
if Quest.isCompleted("UNDERVINE_2") then
return true;
end
end
}
},
end_events = {
{
event = Event.Types.GOSSIP_SHOW,
fn = function(self, data)
return UnitName("target") == "Azalea";
end
}
}
}));
-- Highmountain 1
-- /run ExiWoW.require("Quest").get("HIGHMOUNTAIN_1"):reset();
-- /run ExiWoW.require("Quest").get("HIGHMOUNTAIN_1"):offer();
table.insert(out, Quest:new({
id = "HIGHMOUNTAIN_1",
name = "For relaxation... obviously",
start_text = {
Talkbox.Line:new({
text = "Greetings traveler. I have received a task from Ebonhorn, but I need someone adventurous and on good standing with Mayla to help me.",
animation=60, animLength=1.8
}),
Talkbox.Line:new({
text = "You see, with the Legion and everything going on here recently, Ebonhorn is worried that Mayla is getting too stressed. He wants me to craft a totem to help her... relax.",
animation=83, animLength=4
}),
Talkbox.Line:new({
text = "There are two problems, but let us focus on the first. In order to make the totem, I need certain reagents. This is where you come in. I need three materials:",
animation=60, animLength=1.8
}),
Talkbox.Line:new({
text = "A sturdy log from an ettin to the south.\nA charm of arousal from one of the Crawliac harpies.\nA Rumblerock from the drogbar in Rockcrawler Chasm.",
animation=60, animLength=1.8
}),
Talkbox.Line:new({
text = "Want to help me help your friend?",
animation=65, animLength=2
})
},
journal_entry = {
"Slyhoof the Shameless Shaman near the eastern exist to Thunder Totem needs help crafting a totem of relaxation for Mayla. He needs 3 reagents to craft it.\n\n"..
"1. A sturdy log from an ettin south of Thunder Totem.\n"..
"2. A charm of arousal from any crawliac harpy in Highmountain.\n"..
"3. A Rumblerock from the drogbar in Rockcrawler Chasm, north of Skyhorn."
},
end_journal = "Return to Slyhoof",
questgiver = 66237,
end_text = {
"Excellent. I believe this should do the trick. There is only one small problem...",
},
rewards = {
--[[
Reward:new({
id = "VINE_THRASH",
type = "Charges",
quant = math.huge
})
]]
},
objectives = {
{
Objective:new({
id = "sturdyLog",
name = "Sturdy Log",
num = 1,
onObjectiveEnable = function(self)
self:on(Event.Types.MONSTER_KILL, function(data)
if data.name:find("Hill Ettin") then
PlaySound(1199, "SFX");
RPText.print("You found a sturdy log on the ettin!");
self:add(1);
end
end);
end,
onObjectiveDisable = function(self)
end
}),
Objective:new({
id = "rumblerock",
name = "Rumblerock",
num = 1,
onObjectiveEnable = function(self)
self:on(Event.Types.MONSTER_KILL, function(data)
local rand = math.random();
if data.name:find("Deeprock ") and rand < 0.15 then
PlaySound(1194, "SFX");
RPText.print("You found a rumbling rock on the dead drogbar!");
self:add(1);
end
end);
end,
onObjectiveDisable = function(self)
end
}),
Objective:new({
id = "arousalCharm",
name = "Charm of Arousal",
num = 1,
onObjectiveEnable = function(self)
self:on(Event.Types.MONSTER_KILL, function(data)
local rand = math.random();
if data.name:find("Crawliac ") and rand < 0.15 then
PlaySound(1204, "SFX");
RPText.print("You find a sparkling charm on the harpy, this must be the Charm of Arousal!");
self:add(1);
end
end);
end,
onObjectiveDisable = function(self)
end
}),
}
}, -- You can wrap objectives in {} to create packages
start_events = {
{
event = Event.Types.POINT_REACHED,
data = {zone="Thunder Totem", x=60.96, y=59.19, dist=1.86},
fn = function(self, data)
local comp = GetQuestsCompleted();
if comp[39780] then
return true;
end
end
}
},
end_events = {
{
event = Event.Types.POINT_REACHED,
data = {zone="Thunder Totem", x=60.96, y=59.19, dist=1.86},
fn = function(self, data)
return true;
end
}
}
}));
table.insert(out, Quest:new({
id = "HIGHMOUNTAIN_2",
name = "Since You're Friends",
start_text = {
Talkbox.Line:new({
text = "I have made a Groin Rumble Totem! It packs quite a punch too!",
animation = 64,
animLength = 1.8
}),
Talkbox.Line:new({
text = "Only problem is if I go down there and stick it between Mayla's legs, the guards will arrest me.",
animation = 83,
animLength = 4
}),
Talkbox.Line:new({
text = "You two are good friends though, so I don't think she'll mind.",
animation=65, animLength=2
}),
Talkbox.Line:new({
text = "Let me know how it goes, and I might carve up a little something for you too.",
animation = 64,
animLength = 1.8
})
},
journal_entry = {
"Slyhoof the Shameless Shaman near the eastern exist to Thunder Totem wants you to use his Groin Rumble Totem on Mayla at the bottom of Thunder Totem."
},
end_journal = "Return to Slyhoof",
questgiver = 66237,
end_text = {
Talkbox.Line:new({text = "Did she enjoy my handywork?", animation=65, animLength=1.8}),
Talkbox.Line:new({text = "Excellent! I had enough reagents for an extra totem. Enjoy your reward!", animation=64, animLength=1.8})
},
rewards = {
Reward:new({
id = "GROIN_RUMBLE_TOTEM",
type = "Charges",
quant = math.huge
})
},
objectives = {
Objective:new({
id = "totemUsed",
name = "Totem Used on Mayla",
num = 1,
onObjectiveEnable = function(self)
-- Success
self:on(Event.Types.POINT_REACHED, function()
if UI.talkbox.active then return end
UI.talkbox.set(Talkbox:new({
x = 54.91,
y = 63.26,
rad = 3,
lines = {
Talkbox.Line:new({text = "What can I do for you, champion?\n\n[Push the totem between her legs]", animation = 65, animLength = 1.7}),
Talkbox.Line:new({
text = function()
PlaySound(71943, "SFX");
local _, snd = PlaySound(119255, "SFX");
Timer.set(function()
StopSound(snd, 2000);
end, 1);
return "\n\n\n [Mayla gasps]"
end,
animation = 64,
animLength = 1.7
}),
Talkbox.Line:new({text = "Well now. When Ebonhorn spoke about it, I never suspected such... intensity. Very well. Let them know I'll accept this gift.", animation=83, animLength=4})
},
displayInfo = 63703,
title = "",
onComplete = function()
self:add(1);
end
}));
end, {zone="Thunder Totem", sub="Hall of Chieftains", x=54.91, y=63.26, dist=1});
end,
onObjectiveDisable = function(self)
end
}),
}, -- You can wrap objectives in {} to create packages
start_events = {
{
event = Event.Types.POINT_REACHED,
data = {zone="Thunder Totem", sub="", x=60.96, y=59.19, dist=1.86},
fn = function(self, data)
if Quest.isCompleted("HIGHMOUNTAIN_1") then
return true;
end
end
}
},
end_events = {
{
event = Event.Types.POINT_REACHED,
data = {zone="Thunder Totem", sub="", x=60.96, y=59.19, dist=1.86},
fn = function(self, data)
return true;
end
}
}
}));
-- Valarjar_0
table.insert(out, Quest:new({
id = "VALARJAR_0",
name = "Prove Your Valor",
start_text = {
"You have completed the trials I have thrown at you so far. But I have three trials of a more... intimate nature.",
"Do you wish to have your resilience and resolve tested and stand a chance to wear the Golden Thong of Valor!?",
"Then steel yourself for the trials of electrostim, goo, and bondage!"
},
journal_entry = {
"Odyn has challenged me to three trials of valor. Should I complete his trials, I will be worthy to wear the Golden Thong of Valor.\n\nFor my first trial I must travel north to nastrondir, take off my chestpiece and get hit by 5 lightning breath attacks from the Squallhunters.",
"For the second trial, I must travel to tideskorn harbor and take 5 doses of Icky Ink from the helsquid there.",
"For the final trial, I must travel to Thorim's Peak south of Hrydsdal. I must allow myself to be Chained by Shadow Manacles from the Felskorn Subduers and hit by Willbreaker 5 times."
},
end_journal = "Return to Havi in Valdisdal.",
questgiver = 76630,
end_text = {
Talkbox.Line:new({text = "Excellent work, champion! Tell me when you are ready are ready to continue!", animation=64, animLength=1.8})
},
rewards = {
},
objectives = {
{
Objective:new({
id = "lightningBreaths",
name = "Lightning Breath Taken Barechested",
num = 5,
onObjectiveEnable = function(self)
-- Success
self:on(Event.Types.SPELL_TICK, function(data)
if (data.name == "Juvenile Squallhunter" or data.name == "Adult Squallhunter") and data.aura.name == "Lightning Breath" then
if
Condition.get("hasChest"):validate("player", "player", ExiWoW.ME, ExiWoW.ME, data, Event.Types.SPELL_ADD) or
Condition.get("hasTabard"):validate("player", "player", ExiWoW.ME, ExiWoW.ME, data, Event.Types.SPELL_ADD) or
Condition.get("hasShirt"):validate("player", "player", ExiWoW.ME, ExiWoW.ME, data, Event.Types.SPELL_ADD)
then
return;
end
self:add(1);
end
end);
end,
onObjectiveDisable = function(self)
end
})
},
{
Objective:new({
id = "ickyInk",
name = "Icky Ink Taken",
num = 5,
onObjectiveEnable = function(self)
-- Success
self:on(Event.Types.SPELL_ADD, function(data)
if data.name == "Fleshripper Helsquid" and data.aura.name == "Icky Ink" then
self:add(1);
end
end);
end,
onObjectiveDisable = function(self)
end
})
},
{
Objective:new({
id = "willbreakers",
name = "Willbreakers Taken While Shackled",
num = 5,
onObjectiveEnable = function(self)
-- Success
self:on(Event.Types.SPELL_TICK, function(data)
if data.name == "Felskorn Subduer" and data.aura.name == "Willbreaker" and
Condition.get("hasShadowManacles"):validate("player","player",ExiWoW.ME,ExiWoW.ME)
then
self:add(1);
end
end);
end,
onObjectiveDisable = function(self)
end
})
}
}, -- You can wrap objectives in {} to create packages
start_events = {
{
event = Event.Types.GOSSIP_SHOW,
fn = function(self, data)
if UnitName("target") == "Havi" and GetSubZoneText() == "Valdisdall" then
local comp = GetQuestsCompleted();
print(comp[40072]);
if comp[40072] or UnitName("player") == "Soaia" then
return true;
end
end
end
}
},
end_events = {
{
event = Event.Types.GOSSIP_SHOW,
fn = function(self, data)
if UnitName("target") == "Havi" and GetSubZoneText() == "Valdisdall" then
return true;
end
end
}
}
}));
-- Valarjar_1
table.insert(out, Quest:new({
id = "VALARJAR_1",
name = "Prove Your Valor Some More",
start_text = {
"You have completed the trials, but the Thong of Valor was split in half for two of my champions.",
"Defeat them, and I shall reforge it into a true symbol of your valor!"
},
journal_entry = {
"The Thong of Valor was split into two halves. The halves are worn by worn by Kottr Vondyr in the small village southeast of Haustvald, and Isel the Hammer in Skold-Ashil. I should defeat them in combat, and bring the halves to Havi."
},
end_journal = "Return to Havi in Valdisdal.",
questgiver = 76630,
end_text = {
Talkbox.Line:new({text = "Excellent work, champion! The Thong of Valor is yours to wield!", animation=64, animLength=1.8}),
Talkbox.Line:new({text = "May you ever find your battles... stimulating!", animation=64, animLength=1.8})
},
rewards = {
Reward:new({
id = "THONG_OF_VALOR",
type = "Underwear"
})
},
objectives = {
{
Objective:new({
id = "iselTheHammer",
name = "Isel the Hammer Valorously Defeated",
num = 1,
onObjectiveEnable = function(self)
self:on(Event.Types.MONSTER_KILL, function(data)
if data.name == "Isel the Hammer" then
RPText.print("You collect one half of the Thong of Valor.");
PlaySound(1185, "SFX");
self:add(1);
end
end);
end,
onObjectiveDisable = function(self)
end
}),
Objective:new({
id = "kottrVondyr",
name = "Kottr Vondyr Defeated",
num = 1,
onObjectiveEnable = function(self)
self:on(Event.Types.MONSTER_KILL, function(data)
if data.name == "Kottr Vondyr" then
RPText.print("You collect one half of the Thong of Valor.");
PlaySound(1185, "SFX");
self:add(1);
end
end);
end,
onObjectiveDisable = function(self)
end
}),
}
}, -- You can wrap objectives in {} to create packages
start_events = {
{
event = Event.Types.GOSSIP_SHOW,
fn = function(self, data)
if UnitName("target") == "Havi" and GetSubZoneText() == "Valdisdall" and Quest.isCompleted("VALARJAR_0") then
return true;
end
end
}
},
end_events = {
{
event = Event.Types.GOSSIP_SHOW,
fn = function(self, data)
if UnitName("target") == "Havi" and GetSubZoneText() == "Valdisdall" then
return true;
end
end
}
}
}));
-- The Slithering Thong
--
table.insert(out, Quest:new({
id = "SLITHERING_THONG_0",
name = "Azshara's Relic",
start_text = {
Talkbox.Line:new({text = "Hey adventurer, over here. I have a scroll that might interest you!", animation=81, animLength=1.8}),
},
journal_entry = {
"Okada the Tortollan in Seekers' Vista in Stormsong Valley has found a scroll that might interest me. ",
"He handed me the scroll, which turned out to be an old recipe labeled as a revival potion for Azshara's favorite relic.\n"..
"I might be able to beat some information out of Zeth'jir naga. There should be some near Fort Daelin",
"The Naga have revealed that the relic was lost in Kraken's reach to the east. Maybe I could forage around the sunken ships there."
},
questgiver = 77686,
end_text = {
"I have found the relic! It's a thong made of many tendrils. But it looks pretty dead, and won't stay on..."
},
rewards = {},
objectives = {
{
Objective:new({
id = "talkToOkada",
name = "Okada Talked To",
num = 1,
onObjectiveEnable = function(self)
self:on(Event.Types.GOSSIP_SHOW, function( data )
if UnitName("target") ~= "Okada" or GetSubZoneText() ~= "Seekers' Vista" then
return;
end
UI.talkbox.set(Talkbox:new({
x = 40.82,
y = 37.1,
rad = 0.2,
lines = {
Talkbox.Line:new({text = "I was sifting through my scrolls and found one detailing a potion of revival for 'Azshara's favorite relic'.", animation=60, animLength=2}),
Talkbox.Line:new({text = "You seem like the spritely type who knows how to fight naga...", animation=60, animLength=2 }),
Talkbox.Line:new({text = "Take the scroll and beat them until they reveal the location of this artifact!", animation=81, animLength=1.8 }),
},
displayInfo = 77686,
title = "Okada",
onComplete = function()
self:add(1);
end
}));
end);
end,
onObjectiveDisable = function(self)
end
})
},
{
Objective:new({
id = "informationGathered",
name = "Information Gathered",
num = 3,
onObjectiveEnable = function(self)
-- Success
self:on(Event.Types.MONSTER_KILL, function(data)
local senderChar = Character.buildNPC("none", data.name);
if Tools.multiSearch(data.name, {["%Zeth'jir"]=true}) then
if random() < 0.3 then
self:add(1);
local texts = {
"%S says: The relic was a gift from our queen's night elf lover...",
"%S says: The relic was used to sssubdue through sssensual sstimulations...",
"%S says: We do not possesss the relic. It was losst in a sship in Kraken's reach to the eassst...",
};
RPText:new({
text_receiver = texts[self.current_num],
is_is_chat = true
}):convertAndReceive(senderChar, ExiWoW.ME);
else
RPText.trigger("Q_SLITHERING_THONG_NAGA_FAIL", "player", "player", senderChar, ExiWoW.ME)
end
end
end);
end,
onObjectiveDisable = function(self)
end
})
},
{
Objective:new({
id = "relicLocated",
name = "Relic Located",
num = 1,
onObjectiveEnable = function(self)
self:on(Event.Types.FORAGE, function()