summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hulka <sean.hulka@gmail.com>2021-06-06 03:20:28 +0000
committerSean Hulka <sean.hulka@gmail.com>2021-06-06 03:20:28 +0000
commit88db5f148f1f227995eb958aa393bd5fcf8967cd (patch)
tree0396e68cdf4b5d5da8d19f16b427c17af0a72060
parent9d5efb9d1586b702bc3fb57fe888f51170c576aa (diff)
downloadserverdata-88db5f148f1f227995eb958aa393bd5fcf8967cd.tar.gz
serverdata-88db5f148f1f227995eb958aa393bd5fcf8967cd.tar.bz2
serverdata-88db5f148f1f227995eb958aa393bd5fcf8967cd.tar.xz
serverdata-88db5f148f1f227995eb958aa393bd5fcf8967cd.zip
Add new Duck Side quest and corresponding skills
-rw-r--r--db/constants.conf2
-rw-r--r--db/quest_db.conf4
-rw-r--r--db/re/skill_db.conf144
-rw-r--r--db/re/skill_tree.conf3
-rw-r--r--npc/018-5-4/_import.txt1
-rw-r--r--npc/018-5-4/darklord.txt447
-rw-r--r--npc/functions/hub.txt36
7 files changed, 636 insertions, 1 deletions
diff --git a/db/constants.conf b/db/constants.conf
index b3dbbc723..6d961e0be 100644
--- a/db/constants.conf
+++ b/db/constants.conf
@@ -1938,6 +1938,8 @@ constants_db: {
NPC_KENTON: 458
NPC_GUARD_DEAD: 459
NPC_LEGACY_CHEST: 416
+ // 460 taken on clientside
+ NPC_DARK_LORD: 461
NPC_MONSTERKING: 500
NPC_AIRSHIP: 501
diff --git a/db/quest_db.conf b/db/quest_db.conf
index d01647d6e..ac47cdd01 100644
--- a/db/quest_db.conf
+++ b/db/quest_db.conf
@@ -465,6 +465,10 @@ quest_db: (
Id: 254
Name: "LilitQuest_Raify"
},
+{
+ Id: 255
+ Name: "LilitQuest_TheDuckSide"
+},
// ID 270 to 299: Land Of Fire Quests
{
diff --git a/db/re/skill_db.conf b/db/re/skill_db.conf
index 609039aca..0b582e88e 100644
--- a/db/re/skill_db.conf
+++ b/db/re/skill_db.conf
@@ -39238,7 +39238,73 @@ skill_db: (
Quest: true
}
},
-// 20045 and 20046 are free
+{
+ Id: 20045
+ Name: "TMW2_DISEMBODYSPIRIT"
+ Description: "Disembody Spirit"
+ MaxLevel: 10
+ SkillType: {
+ Self: true
+ }
+ SkillInfo: {
+ Quest: true
+ }
+ CoolDown: {
+ Lv1: 45000
+ Lv2: 44000
+ Lv3: 43000
+ Lv4: 42000
+ Lv5: 41000
+ Lv6: 40000
+ Lv7: 38000
+ Lv8: 37000
+ Lv9: 36000
+ Lv10: 35000
+ }
+ CastTime: 100
+ FixedCastTime: 100
+ Requirements: {
+ SPCost: 40
+ Items: {
+ Pearl: 1
+ PileOfAsh: 1
+ }
+ }
+},
+{
+ Id: 20046
+ Name: "TMW2_RAISEDEAD"
+ Description: "Raise Dead"
+ MaxLevel: 10
+ SkillType: {
+ Self: true
+ }
+ SkillInfo: {
+ Quest: true
+ }
+ CoolDown: {
+ Lv1: 45000
+ Lv2: 44000
+ Lv3: 43000
+ Lv4: 42000
+ Lv5: 41000
+ Lv6: 40000
+ Lv7: 38000
+ Lv8: 37000
+ Lv9: 36000
+ Lv10: 35000
+ }
+ CastTime: 400
+ FixedCastTime: 100
+ Requirements: {
+ SPCost: 70
+ Items: {
+ AnimalBones: 1
+ IronPowder: 1
+ PileOfAsh: 1
+ }
+ }
+},
{
Id: 20047
Name: "TMW2_DUCKY"
@@ -40383,6 +40449,82 @@ skill_db: (
}
}
},
+{
+ Id: 20077
+ Name: "TMW2_NECROTICBOLT"
+ Description: "Necrotic Bolt"
+ MaxLevel: 10
+ Range: 8
+ Hit: "BDT_MULTIHIT"
+ SkillType: {
+ Enemy: true
+ }
+ AttackType: "Undead"
+ Element: "Ele_Undead"
+ NumberOfHits: {
+ Lv1: 1
+ Lv2: 2
+ Lv3: 4
+ Lv4: 4
+ Lv5: 5
+ Lv6: 6
+ Lv7: 7
+ Lv8: 8
+ Lv9: 8
+ Lv10: 9
+ }
+ InterruptCast: true
+ CastTime: {
+ Lv1: 640
+ Lv2: 860
+ Lv3: 1180
+ Lv4: 1500
+ Lv5: 1720
+ Lv6: 1900
+ Lv7: 2360
+ Lv8: 2680
+ Lv9: 3000
+ Lv10: 3220
+ }
+ AfterCastActDelay: {
+ Lv1: 1000
+ Lv2: 1200
+ Lv3: 1400
+ Lv4: 1600
+ Lv5: 1800
+ Lv6: 2000
+ Lv7: 2200
+ Lv8: 2400
+ Lv9: 2600
+ Lv10: 2800
+ }
+ FixedCastTime: {
+ Lv1: 160
+ Lv2: 240
+ Lv3: 320
+ Lv4: 400
+ Lv5: 480
+ Lv6: 700
+ Lv7: 640
+ Lv8: 720
+ Lv9: 800
+ Lv10: 880
+ }
+ Requirements: {
+ SPCost: {
+ Lv1: 45
+ Lv2: 65
+ Lv3: 85
+ Lv4: 115
+ Lv5: 135
+ Lv6: 155
+ Lv7: 175
+ Lv8: 195
+ Lv9: 215
+ Lv10: 245
+ }
+ }
+},
diff --git a/db/re/skill_tree.conf b/db/re/skill_tree.conf
index 1ffa2296a..c792a5426 100644
--- a/db/re/skill_tree.conf
+++ b/db/re/skill_tree.conf
@@ -67,6 +67,8 @@ Human: {
TMW2_CUTEHEART: 5
TMW2_PLANTKINGDOM: 5
TMW2_FAIRYEMPIRE: 5
+ TMW2_DISEMBODYSPIRIT: 5
+ TMW2_RAISEDEAD: 5
// Thieves/Merchant-Police
ALL_INCCARRY: 0
@@ -104,6 +106,7 @@ Human: {
TMW2_FIREARROW: 0
TMW2_FIREBALL: 0
TMW2_ARMAGEDDON: 0
+ TMW2_NECROTICBOLT: 0
///////////////// Brawler class
TMW2_BRAWLING: 0
diff --git a/npc/018-5-4/_import.txt b/npc/018-5-4/_import.txt
index 13cfc009e..23d1e1035 100644
--- a/npc/018-5-4/_import.txt
+++ b/npc/018-5-4/_import.txt
@@ -2,5 +2,6 @@
// This file is generated automatically. All manually added changes will be removed when running the Converter.
"npc/018-5-4/_mobs.txt",
"npc/018-5-4/_warps.txt",
+"npc/018-5-4/darklord.txt",
"npc/018-5-4/elder.txt",
"npc/018-5-4/mapflags.txt",
diff --git a/npc/018-5-4/darklord.txt b/npc/018-5-4/darklord.txt
new file mode 100644
index 000000000..9e3a9ac4b
--- /dev/null
+++ b/npc/018-5-4/darklord.txt
@@ -0,0 +1,447 @@
+// TMW2 Script
+// Author:
+// dangerDuck
+// Description:
+// Dark Lord is a suspicious npc.
+// In order to start the Lord's quest, one must completed the first stage of the Elder's quest
+// The first/second stages of the Lord's quest consists of gathering items for necromancy summon skills
+// Third stage of the quest consists of killing pious and piou knights for the necromancy attack skill
+// Variables:
+// LilitQuest_TheDuckSide
+
+function script DarkLordMobCount {
+ .@q=getq(LilitQuest_TheDuckSide);
+ .@t1=getq2(LilitQuest_TheDuckSide);
+ .@t2=getq3(LilitQuest_TheDuckSide);
+ .@map=getmap();
+ if (.@t1 >= 300 && .@t2 >= 20)
+ {
+ dispbottom l("That must have been the last piou. I should return to Duck Isle.");
+ setq(LilitQuest_TheDuckSide, 6, 0, 0);
+ }
+
+ if ((.@map == "006-2" ||
+ .@map == "006-2-3" ||
+ .@map == "006-2-5" ||
+ .@map == "006-2-6") &&
+ .@q == 5 &&
+ (killedrid == Piou ||
+ killedrid == ForestPiou ||
+ killedrid == ManaPiou ||
+ killedrid == Piousse))
+ {
+ setq2(LilitQuest_Pouf, .@t1+1);
+ }
+
+ if (.@map == "006-2-4" &&
+ .@q == 5 &&
+ killedrid == PiouKnight)
+ {
+ setq3(LilitQuest_Pouf, .@t2+1);
+ }
+ return;
+}
+
+
+018-5-4,37,46,0 script Dark Lord NPC_DARK_LORD,{
+ function lordQuest;
+ function lordStage1;
+ function lordSupplyMenu1;
+ function lordSupplyList1;
+ function lordSupplyGive1;
+ function lordStage2;
+ function lordSupplyMenu2;
+ function lordSupplyList2;
+ function lordSupplyGive2;
+ function lordHuntStart;
+ function lordHuntReport;
+ function lordHuntReward;
+ function lordTrainingComplete;
+ function lordClose;
+ if (MAGIC_LVL && getq(LilitQuest_PiratesOfSARAH) > 1)
+ {
+ lordQuest();
+ }
+ lordClose();
+ close;
+
+function lordQuest
+{
+ if (BaseLevel < 60)
+ {
+ elderClose();
+ return;
+ }
+ .@q=getq(LilitQuest_TheDuckSide);
+ if (.@q <= 0)
+ {
+ lordStage1();
+ }
+ else
+ {
+ mesn;
+ mesq l("Yes, Apprentice?");
+ next;
+ select
+ rif(.@q == 1 || .@q == 3, l("I've returned, as you requested...")),
+ rif(.@q == 2, l("Do you have other tasks for me, Master?")),
+ rif(.@q == 4, l("I'm ready to begin the next stage of my training.")),
+ rif(.@q == 5, l("How many more pious do I have to kill?")),
+ rif(.@q == 6, l("Do you have more tasks for me, Master?")),
+ rif(.@q == 7, l("How can I obtain more power from the Duck Side?")),
+ l("Nothing, Master.");
+ mes "";
+ switch (@menu) {
+ case 1:
+ lordSupplyMenu1();
+ break;
+ case 2:
+ lordStage2();
+ break;
+ case 3:
+ lordSupplyMenu2();
+ break;
+ case 4:
+ lordHuntStart();
+ break;
+ case 5:
+ lordHuntReport();
+ break;
+ case 6:
+ lordHuntReward();
+ break;
+ case 7:
+ lordTrainingComplete();
+ break;
+ }
+ }
+ return;
+}
+
+function lordStage1
+{
+ mesn;
+ mesq l("Hello %s. I have heard tell of your great deeds. You have indeed grown powerful, but you still remain shackled to weakness.", get_race());
+ mesn;
+ mesq l("True power can only come by first embracing the Duck Side. I can guide and train you, but be warned: the Duck Side is not for the faint of heart.");
+ mesn;
+ mesc l("WARNING: Choosing this path is irreversible and will prevent you from obtaining piou skills. Do you wish to accept the quest?"), 1;
+ if (askyesno() == ASK_NO)
+ return;
+ mesn;
+ mesq l("You have chosen wisely. For our first lesson, I will need you to gather certain ... supplies.");
+ next;
+ setq(LilitQuest_TheDuckSide, 1, 0, 0);
+ lordSupplyList1();
+}
+
+function lordSupplyMenu1
+{
+ do
+ {
+ mesn;
+ mesq l("Did you bring the supplies?");
+ next;
+ select
+ l("I have them right here."),
+ l("What did you need again?"),
+ l("I haven't collected them yet.");
+ mes "";
+ switch (@menu) {
+ case 1:
+ lordSupplyGive1();
+ break;
+ case 2:
+ lordSupplyList1();
+ // fallthrough
+ case 3:
+ break;
+ }
+ } while (true);
+ return;
+}
+
+function lordSupplyList1
+{
+ mesq "";
+ mesn;
+ mesq l("You must bring me:");
+ mesq l("%d/%d %s", countitem(PileOfAsh), 15, getitemlink(PileOfAsh));
+ mesq l("%d/%d %s", countitem(Pearl), 10, getitemlink(Pearl));
+ mesq l("%d/%d %s", countitem(FluoPowder), 6, getitemlink(FluoPowder));
+ mesq l("%d/%d %s", countitem(DarkCrystal), 1, getitemlink(DarkCrystal));
+ next;
+ return;
+}
+
+function lordSupplyGive1
+{
+ countitem(PileOfAsh) < 15 ||
+ if (countitem(Pearl) < 10 ||
+ countitem(FluoPowder) < 6 ||
+ countitem(DarkCrystal) < 1)
+ {
+ mesn;
+ mesq l("This isn't what I requested. Learn to count your items more carefully... Or else.");
+ percentheal -75, 0;
+ return;
+ }
+ skill(TMW2_DISEMBODYSPIRIT,1,0);
+
+ delitem(PileOfAsh, 15);
+ delitem(Pearl, 10);
+ delitem(FluoPowder, 6);
+ delitem(DarkCrystal, 1);
+
+ setq(LilitQuest_TheDuckSide, 2, 0, 0);
+
+ mes "";
+ mesn;
+ mesq l("These ingredients allow one access to undeath and grant control over the dead.");
+ next;
+ mesn;
+ mesq l("With a little knowledge, you can harness the power of life and death to summon forth the disembodied spirits of mana itself.");
+ next;
+ mesn;
+ mesq l("Keep in mind the more power you have, the less control you'll have as well. Less control may result in failure to summon.");
+ next;
+ mesn;
+ mesq l("You will need a %s and a %s to use this skill. Fail rate is high if you can't control your magic.", getitemlink(Pearl), getitemlink(PileOfAsh));
+
+ if (BaseLevel < 65)
+ {
+ mesn;
+ mesq l("That's all you're capable of learning for now, Apprentice. Practice and return when you are stronger.");
+ }
+ else
+ {
+ mesn;
+ mesq l("You demonstrate amazing potential for one so young. Once I have spoken to the Council of Elders, return to me...");
+ }
+ next;
+ return;
+}
+
+function lordStage2
+{
+ if (BaseLevel < 65)
+ {
+ mesn;
+ mesq l("Practice and return when you are stronger.");
+ return;
+ }
+ mesn;
+ mesq l("The Council of Elders has approved your training. Now that you have learned to summon forth spirits, we will progress to more powerful and... dangerous spells.");
+ mesn;
+ mesq l("You will again need to gather materials. Do not fail me.");
+ next;
+ setq(LilitQuest_TheDuckSide, 3, 0, 0);
+ lordSupplyList2();
+ return;
+}
+
+function lordSupplyMenu2
+{
+ do
+ {
+ mesn;
+ mesq l("Did you bring the supplies?");
+ next;
+ select
+ l("I have them right here."),
+ l("What did you need again?"),
+ l("I haven't collected them yet.");
+ mes "";
+ switch (@menu) {
+ case 1:
+ lordSupplyGive1();
+ break;
+ case 2:
+ lordSupplyList1();
+ // fallthrough
+ case 3:
+ break;
+ }
+ } while (true);
+ return;
+}
+
+function lordSupplyList2
+{
+ mesq "";
+ mesn;
+ mesq l("You must bring me:");
+ mesq l("%d/%d %s", countitem(AnimalBones), 25, getitemlink(AnimalBones));
+ mesq l("%d/%d %s", countitem(IronPowder), 20, getitemlink(IronPowder));
+ mesq l("%d/%d %s", countitem(PileOfAsh), 15, getitemlink(PileOfAsh));
+ mesq l("%d/%d %s", countitem(DiseasedHeart), 7, getitemlink(DiseasedHeart));
+ next;
+ return;
+}
+
+function lordSupplyGive2
+{
+ if (countitem(AnimalBones) < 25 ||
+ countitem(IronPowder) < 20 ||
+ countitem(PileOfAsh) < 15 ||
+ countitem(DiseasedHeart) < 7)
+ {
+ mesn;
+ mesq l("This isn't what I requested. Learn to count your items more carefully... Or else.");
+ percentheal -75, 0;
+ return;
+ }
+ skill(TMW2_RAISEDEAD,1,0);
+
+ delitem(AnimalBones, 25);
+ delitem(IronPowder, 20);
+ delitem(PileOfAsh, 15);
+ delitem(DiseasedHeart, 7);
+
+ setq(LilitQuest_TheDuckSide, 4, 0, 0);
+
+ mes "";
+ mesn;
+ mesq l("In the same way as our last lesson, knowledge is key to harnessing the power of life and death.");
+ next;
+ mesn;
+ mesq l("This time we will be using the power of the Duck Side to raise the dead to carry out one's bidding.");
+ next;
+ mesn;
+ mesq l("The %s are sufficient enough to form a crude body to host the spirits of the dead. The bodies don't last very long, though.", getitemlink(AnimalBones));
+ next;
+ mesn;
+ mesq l("By now you should have enough control to not fail summoning forth undead. If not, well... let's just say it wouldn't go well for you.");
+ next;
+ mesn;
+ mesq l("You will need an %s, an %s, and a %s to use this skill.", getitemlink(AnimalBones), getitemlink(IronPowder), getitemlink(PileOfAsh));
+
+ if (BaseLevel < 70)
+ {
+ mesn;
+ mesq l("That's all you're capable of learning for now, Apprentice. Practice and return when you are stronger.");
+ }
+ else
+ {
+ mesn;
+ mesq l("You had shown great promise and are nearing the end of your training. I must think on your final task...");
+ }
+ next;
+ return;
+}
+
+function lordHuntStart
+{
+ if (BaseLevel < 70)
+ {
+ mesn;
+ mesq l("Practice and return when you are stronger.");
+ return;
+ }
+ mesn;
+ mesq l("To complete your training, you must pass a test, a final exam... of sorts.");
+ next;
+ mesn;
+ mesq l("For years, ducks have fought to preserve our homeland and carry out the will of the Moubootaur through our mastery of the Duck Side.");
+ next;
+ mesn;
+ mesq l("The pious have been staunchly opposed to our efforts to return the Moubootaur's power and fight on its behalf. They must be dealt with.");
+ next;
+ mesn;
+ mesq l("Unfortunately, the piou village has managed to hide from duck forces and confound our scouts. We have been unable to infiltrate it.");
+ next;
+ mesn;
+ mesq l("Your task is to infiltrate the piou village and kill %d pious and %d piou knights. If you are successful, I will complete your training.", 300, 20);
+ next;
+ setq(LilitQuest_TheDuckSide, 5, 0, 0);
+ return;
+}
+
+function lordHuntReport
+{
+ mesn;
+ mesq l("You have killed %d/%d pious and %d/%d piou knights.", getq2(LilitQuest_TheDuckSide), 300, getq3(LilitQuest_TheDuckSide), 20);
+ next;
+ return;
+}
+
+function lordHuntReward
+{
+ mesn;
+ mesq l("For our last lesson, you must draw upon your rage. This is the source of the Duck Side's power.");
+ next;
+ mesn;
+ mesq l("Only then can you channel your passion and call upon the Duck Side. This is most simply expressed in a bolt of lightning, but there are always other ways to unleash your anger.");
+ next;
+ mesn;
+ mesq l("Traditionally, ducks have found that the use of powerful weapons, called lightsabers by some, greatly enhances the power of the channeled bolt.");
+ next;
+ mesn;
+ mesq l("Congratulations, Apprentice. Your training is complete. You now truly belong to the Duck Side.");
+ next;
+ mesn;
+ mesq l("Remember to practice, youngling. Discipline is everything.");
+ next;
+ skill(TMW2_NECROTICBOLT,1,0);
+ setq(LilitQuest_TheDuckSide, 7, 0, 0);
+ return:
+}
+
+function lordTrainingComplete
+{
+ mesn;
+ mesq l("You have mastered much, but you must practice more before you can draw even greater power from the Duck Side.");
+ next;
+ return;
+}
+
+
+function lordClose
+{
+ mesn;
+ if (BaseLevel < 60)
+ {
+ mesn;
+ mesq l("Begone %s!", get_race());
+ next;
+ mesq l("The Duck Side does not take kindly to outsiders and weaklings like you!");
+ }
+ else
+ {
+ mesq l("You show potential %s, but only if you embrace the Duck Side. Return when you are prepared to seek true power...", get_race());
+ }
+ return;
+}
+
+OnTimer1000:
+ domovestep();
+ end;
+
+OnInit:
+ initpath "move", 33, 46,
+ "dir", DOWN, 0,
+ "wait", 20, 0,
+ "move", 33, 42,
+ "dir", DOWN, 0,
+ "wait", 20, 0,
+ "dir", RIGHT, 0,
+ "wait", 5, 0,
+ "move", 29, 73,
+ "dir", DOWN, 0,
+ "wait", 15, 0,
+ "move", 37, 46,
+ "dir", LEFT, 0,
+ "wait", 1, 0,
+
+ initialmove;
+ initnpctimer;
+
+ .sex = G_OTHER;
+ .distance = 7;
+ end;
+
+OnInstanceInit:
+ disablenpc instance_npcname(.name$);
+ end;
+}
+
diff --git a/npc/functions/hub.txt b/npc/functions/hub.txt
index 57bcd915a..10bb48d0f 100644
--- a/npc/functions/hub.txt
+++ b/npc/functions/hub.txt
@@ -598,6 +598,23 @@ function script HUB_SkillInvoke {
GetManaExp(TMW2_METEORSTRIKE, 3);
break;
/*
+ ////////////////////////////////
+ // XXX: Undead Class
+ case TMW2_NECROTICBOLT:
+ // Attack power
+ .@APW=80+(27*@skillLv);
+ // Heal power
+ .@HPW=(Vit/6)+(8*@skillLv);
+ // Increase damage and reduce healing if using a lightsaber
+ if (getequipid(EQI_HAND_L) == 3536 || getequipid(EQI_HAND_L) == 3537)
+ .@APW=.@APW*3/2;
+ .@HPW=.@HPW*3/5;
+ .@heal=max(AdjustSpellpower(.@HPW), AdjustAttackpower(.@HPW));
+ .@dmg=AdjustSpellpower(.@APW);
+ heal .@heal, 0;
+ harm(@skillTarget, .@dmg, HARM_MAGI, Ele_Undead);
+ GetManaExp(TMW2_NECROTICBOLT, 3);
+ break;
// TODO: Ultimate Skills (T5/0)
// Sanctum: AoE resurrection, HP like Resurrect, 30min+ cooldown and
@@ -907,6 +924,9 @@ function script HUB_SkillInvoke {
case TMW2_FAIRYEMPIRE:
SK_summon(any(VanityPixie, HolyPixie, ShadowPixie, NulityPixie), 5, any(4,5));
break;
+ case TMW2_DISEMBODYSPIRIT:
+ SK_summon(ManaGhost, 4, ((@skillLv*2)+rand2(@skillLv*2)));
+ break;
// More complex summons
case TMW2_KALMURK:
.@mobId=Maggot;
@@ -966,6 +986,22 @@ function script HUB_SkillInvoke {
SummonMagic(@skillId, .@mobId, 2);
GetManaExp(@skillId, 1);
break;
+ case TMW2_RAISEDEAD:
+ .@mobId=Skeleton;
+ .@amount=@skillLv*2;
+ if (MAGIC_LVL >= 2)
+ {
+ // Each skill level increases chance by 5% (the max is 25%)
+ .@r=rand2(20);
+ if (@skillLv-1 <= .@r)
+ {
+ .@mobId=ArmoredSkeleton;
+ .@amount=@skillLv;
+ }
+ }
+ SK_summon(.@mobId, 5, .@amount);
+ GetManaExp(@skillId, 1);
+ break;
// Special exception
case TMW2_TRANSMIGRATION: