From 88db5f148f1f227995eb958aa393bd5fcf8967cd Mon Sep 17 00:00:00 2001 From: Sean Hulka Date: Sun, 6 Jun 2021 03:20:28 +0000 Subject: Add new Duck Side quest and corresponding skills --- db/constants.conf | 2 + db/quest_db.conf | 4 + db/re/skill_db.conf | 144 ++++++++++++++- db/re/skill_tree.conf | 3 + npc/018-5-4/_import.txt | 1 + npc/018-5-4/darklord.txt | 447 +++++++++++++++++++++++++++++++++++++++++++++++ npc/functions/hub.txt | 36 ++++ 7 files changed, 636 insertions(+), 1 deletion(-) create mode 100644 npc/018-5-4/darklord.txt 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: -- cgit v1.2.3-60-g2f50