diff --git a/scripts/enum/item.lua b/scripts/enum/item.lua index eff563b781e..07510da5e41 100644 --- a/scripts/enum/item.lua +++ b/scripts/enum/item.lua @@ -5003,6 +5003,7 @@ xi.item = PINEAL_HAT = 15181, WALKURE_MASK = 15185, MAATS_CAP = 15194, + ELEGANT_RIBBON = 15196, YAGUDO_HEADGEAR = 15202, GOBLIN_COIF = 15203, GADZRADDS_HELM = 15214, diff --git a/scripts/quests/otherAreas/Elderly_Pursuits.lua b/scripts/quests/otherAreas/Elderly_Pursuits.lua new file mode 100644 index 00000000000..f4efce46dfb --- /dev/null +++ b/scripts/quests/otherAreas/Elderly_Pursuits.lua @@ -0,0 +1,163 @@ +----------------------------------- +-- Elderly Pursuits +----------------------------------- +-- Log ID: 4, Quest ID: 75 +-- Despachiaire : !pos 108 -40 -83 26 +-- Rouva : !pos -16 2 11 230 +-- ??? : !pos -412 0 -362 2 +----------------------------------- +-- !addquest 4 75 +----------------------------------- +require('scripts/globals/npc_util') +----------------------------------- +local carpentersLandingID = zones[xi.zone.CARPENTERS_LANDING] +----------------------------------- + +local quest = Quest:new(xi.quest.log_id.OTHER_AREAS, xi.quest.id.otherAreas.ELDERLY_PURSUITS) + +quest.reward = +{ + item = xi.item.ELEGANT_RIBBON, +} + +local function AllParaDead() + for i = 0, 4 do + local mob = GetMobByID(carpentersLandingID.mob.PARA_OFFSET + i) + if not mob:isDead() then + return false + end + end + + return true +end + +quest.sections = +{ + { + check = function(player, status, vars) + return status == xi.questStatus.QUEST_AVAILABLE and + player:hasCompletedQuest(xi.quest.log_id.OTHER_AREAS, xi.quest.id.otherAreas.SECRETS_OF_OVENS_LOST) + end, + + [xi.zone.TAVNAZIAN_SAFEHOLD] = + { + ['Despachiaire'] = + { + onTrigger = function(player, npc) + return quest:progressEvent(517) + end, + }, + + onEventFinish = + { + [517] = function(player, csid, option, npc) + quest:begin(player) -- begin quest + npcUtil.giveKeyItem(player, xi.ki.ANTIQUE_AMULET) + end, + }, + }, + }, + + { + check = function(player, status, vars) + return status == xi.questStatus.QUEST_ACCEPTED + end, + + [xi.zone.TAVNAZIAN_SAFEHOLD] = + { + ['Despachiaire'] = + { + onTrigger = function(player, npc) + if quest:getVar(player, 'Prog') == 3 then + return quest:progressEvent(518) + end + end, + }, + + onEventFinish = + { + [518] = function(player, csid, option, npc) + if quest:complete(player) then + player:delKeyItem(xi.ki.CATHEDRAL_MEDALLION) + end + end, + }, + }, + + [xi.zone.SOUTHERN_SAN_DORIA] = + { + ['Rouva'] = + { + onTrigger = function(player, npc) + if + quest:getVar(player, 'Prog') == 0 and + player:hasKeyItem(xi.ki.ANTIQUE_AMULET) + then + return quest:progressEvent(747) + elseif + quest:getVar(player, 'Prog') == 2 and + player:hasKeyItem(xi.ki.CATHEDRAL_MEDALLION) + then + return quest:progressEvent(748) + end + end, + }, + + onEventFinish = + { + [747] = function(player, csid, option, npc) + quest:setVar(player, 'Prog', 1) + end, + + [748] = function(player, csid, option, npc) + quest:setVar(player, 'Prog', 3) + end, + }, + }, + + [xi.zone.CARPENTERS_LANDING] = + { + ['qm_para'] = + { + onTrigger = function(player, npc) + if quest:getVar(player, 'Prog') == 1 then + if quest:getLocalVar(player, 'ParaKilled') == 1 then + player:messageSpecial(carpentersLandingID.text.POLISH, xi.ki.ANTIQUE_AMULET) + player:delKeyItem(xi.ki.ANTIQUE_AMULET) + quest:setVar(player, 'Prog', 2) + quest:setLocalVar(player, 'ParaKilled', 0) + return quest:keyItem(xi.ki.CATHEDRAL_MEDALLION) + elseif + GetNPCByID(carpentersLandingID.npc.QM_PARA):getLocalVar('engaged') < os.time() and + GetNPCByID(carpentersLandingID.npc.QM_PARA):getLocalVar('engaged') ~= 1 and + npcUtil.popFromQM(player, npc, { carpentersLandingID.mob.PARA_OFFSET }, { claim = true, hide = 0 }) + then + GetNPCByID(carpentersLandingID.npc.QM_PARA):setLocalVar('engaged', 1) + GetNPCByID(carpentersLandingID.npc.QM_PARA):setLocalVar('nextMob', carpentersLandingID.mob.PARA_OFFSET + 1) + return quest:messageSpecial(carpentersLandingID.text.STENCH_OF_DECAY) + end + end + end, + }, + + ['Para'] = + { + onMobDeath = function(mob, player, optParams) + if AllParaDead() then + quest:setLocalVar(player, 'ParaKilled', 1) + GetNPCByID(carpentersLandingID.npc.QM_PARA):setLocalVar('nextMob', 0) + end + end, + }, + + onZoneOut = + { + function(player, prevZone) + quest:setLocalVar(player, 'ParaKilled', 0) -- zoning resets kill progress + end + }, + } + }, +} + +return quest diff --git a/scripts/zones/Carpenters_Landing/DefaultActions.lua b/scripts/zones/Carpenters_Landing/DefaultActions.lua index 9989368f7bb..193b3f06538 100644 --- a/scripts/zones/Carpenters_Landing/DefaultActions.lua +++ b/scripts/zones/Carpenters_Landing/DefaultActions.lua @@ -3,4 +3,5 @@ local ID = zones[xi.zone.CARPENTERS_LANDING] return { ['Anguenet'] = { event = 21 }, ['qm_cryptonberries'] = { messageSpecial = ID.text.CRYPTONBERRY_FALLEN_TREE }, + ['qm_para'] = { messageSpecial = ID.text.NOTHING_OUT_OF_ORDINARY }, } diff --git a/scripts/zones/Carpenters_Landing/IDs.lua b/scripts/zones/Carpenters_Landing/IDs.lua index c0a077fb88b..63d9ddafc7b 100644 --- a/scripts/zones/Carpenters_Landing/IDs.lua +++ b/scripts/zones/Carpenters_Landing/IDs.lua @@ -28,9 +28,11 @@ zones[xi.zone.CARPENTERS_LANDING] = FISHING_MESSAGE_OFFSET = 7285, -- You can't fish here. LOGGING_IS_POSSIBLE_HERE = 7402, -- Logging is possible here if you have . BEUGUNGEL_SHOP_DIALOG = 7434, -- Hello, [sir/ma'am]! I'm selling goods direct from the Carpenters' Guild. + STENCH_OF_DECAY = 7484, -- You are overwhelmed by the putrid stench of decay! CRYPTONBERRY_EXECUTOR_DIE = 7486, -- ...Cleave our foesss with barren hate. CRYPTONBERRY_ASSASSIN_2HR = 7487, -- ..Take up thy lanternsss. The truth we shall illuminate. CRYPTONBERRY_EXECUTOR_2HR = 7488, -- Through this we ssseek our just reward... + POLISH = 7489, -- You polish the with the glowing mushroom. MYCOPHILE_MUSHROOM = 7505, -- There is a rotten mushroom here. There are 3 openings in its cap. HERCULES_TREE_NOTHING_YET = 7507, -- There is nothing here yet. Check again in the morning. UNITY_WANTED_BATTLE_INTERACT = 7550, -- Those who have accepted % must pay # Unity accolades to participate. The content for this Wanted battle is #. [Ready to begin?/You do not have the appropriate object set, so your rewards will be limited.] @@ -42,6 +44,7 @@ zones[xi.zone.CARPENTERS_LANDING] = TEMPEST_TIGON = GetFirstID('Tempest_Tigon'), OVERGROWN_IVY = GetFirstID('Overgrown_Ivy'), CRYPTONBERRY_EXECUTOR = GetFirstID('Cryptonberry_Executor'), + PARA_OFFSET = GetFirstID('Para'), MYCOPHILE = GetFirstID('Mycophile'), HERCULES_BEETLE = GetFirstID('Hercules_Beetle'), }, @@ -49,6 +52,7 @@ zones[xi.zone.CARPENTERS_LANDING] = { HERCULES_BEETLE_TREES = GetTableOfIDs('qm_hercules_beetle'), LOGGING = GetTableOfIDs('Logging_Point'), + QM_PARA = GetFirstID('qm_para') }, } diff --git a/scripts/zones/Carpenters_Landing/mobs/Para.lua b/scripts/zones/Carpenters_Landing/mobs/Para.lua new file mode 100644 index 00000000000..0bccbf636a3 --- /dev/null +++ b/scripts/zones/Carpenters_Landing/mobs/Para.lua @@ -0,0 +1,81 @@ +----------------------------------- +-- Area: Carpenters Landing +-- Mob: Para +----------------------------------- +local ID = zones[xi.zone.CARPENTERS_LANDING] +----------------------------------- + +local function spawnNextMob(player) + local mobId = GetNPCByID(ID.npc.QM_PARA):getLocalVar('nextMob') + + if mobId ~= 0 then + GetMobByID(mobId):setSpawn(player:getXPos()-1, player:getYPos()-1, player:getZPos(), player:getRotPos() - 180) -- spawn facing by player + SpawnMob(mobId):updateEnmity(player) + + if mobId < ID.mob.PARA_OFFSET + 4 then + GetNPCByID(ID.npc.QM_PARA):setLocalVar('nextMob', mobId + 1) + else + GetNPCByID(ID.npc.QM_PARA):setLocalVar('nextMob', 0) + end + end +end + +local function AllParaDead() + for i = 0, 4 do + local mob = GetMobByID(ID.mob.PARA_OFFSET + i) + if not mob:isDead() then + return false + end + end + + return true +end + +local entity = {} + +entity.onMobInitialize = function(mob) + mob:setMobMod(xi.mobMod.IDLE_DESPAWN, 180) -- 3 min despawn + --mob:addImmunity(xi.immunity.LIGHT_SLEEP) TODO: Mob is immune to light based sleep, but not dark + mob:setMod(xi.mod.UDMGMAGIC, -4000) + mob:setLocalVar('spawn', 0) +end + +entity.onMobFight = function(mob, target) + if + mob:getLocalVar('spawn') < os.time() and + mob:getLocalVar('spawn') ~= 0 + then + spawnNextMob(target) + mob:setLocalVar('spawn', 0) + end +end + +entity.onMobWeaponSkill = function(target, mob, skill) + local triggerSkills = { 310, 311, 312 } + local skillID = skill:getID() + if utils.contains(skillID, triggerSkills) then + if math.random(1, 100) <= 90 then + mob:setLocalVar('spawn', os.time() + 3) -- ~90% chance of replicating on shroom skill, need larger sample to hone in on this number but it isn't guaranteed + end + end + + return target +end + +entity.onMobDeath = function(mob, player, optParams) + mob:setLocalVar('died', 1) + if AllParaDead() then + GetNPCByID(ID.npc.QM_PARA):setLocalVar('engaged', os.time()) -- no time gate after death + end +end + +entity.onMobDespawn = function(mob) + if + AllParaDead() and + mob:getLocalVar('died') ~= 1 + then + GetNPCByID(ID.npc.QM_PARA):setLocalVar('engaged', os.time() + 180) -- time gate 3 min after despawn + end +end + +return entity diff --git a/scripts/zones/Carpenters_Landing/npcs/qm_para.lua b/scripts/zones/Carpenters_Landing/npcs/qm_para.lua new file mode 100644 index 00000000000..23b580609ad --- /dev/null +++ b/scripts/zones/Carpenters_Landing/npcs/qm_para.lua @@ -0,0 +1,17 @@ +----------------------------------- +-- Area: Carpenters' Landing (2) +-- NPC: ??? +-- Note: Used to spawn Para QNM +-- !pos -405 0 -368 2 +----------------------------------- +require('scripts/globals/npc_util') +----------------------------------- +local entity = {} + +entity.onTrade = function(player, npc, trade) +end + +entity.onTrigger = function(player, npc) +end + +return entity diff --git a/sql/mob_spawn_points.sql b/sql/mob_spawn_points.sql index 4a8e9a8ab1b..d4fec9d5fc6 100644 --- a/sql/mob_spawn_points.sql +++ b/sql/mob_spawn_points.sql @@ -357,10 +357,10 @@ INSERT INTO `mob_spawn_points` VALUES (16785713,'Cryptonberry_Assassin','Crypton INSERT INTO `mob_spawn_points` VALUES (16785714,'Tonberrys_Elemental','Tonberry\'s Elemental',46,125.207,-6.672,-392.863,160); INSERT INTO `mob_spawn_points` VALUES (16785715,'Tonberrys_Avatar','Tonberry\'s Avatar',47,118.650,-3.701,-389.903,99); INSERT INTO `mob_spawn_points` VALUES (16785716,'Para','Para',48,-415.948,-0.704,-358.041,76); -INSERT INTO `mob_spawn_points` VALUES (16785717,'Para','Para',48,-412.548,-0.500,-361.108,111); -INSERT INTO `mob_spawn_points` VALUES (16785718,'Para','Para',48,-412.864,-0.094,-359.222,26); -INSERT INTO `mob_spawn_points` VALUES (16785719,'Para','Para',48,0.000,0.000,0.000,0); -INSERT INTO `mob_spawn_points` VALUES (16785720,'Para','Para',48,0.000,0.000,0.000,0); +INSERT INTO `mob_spawn_points` VALUES (16785717,'Para','Para',48,-386.628,0.145,-374.600,0); +INSERT INTO `mob_spawn_points` VALUES (16785718,'Para','Para',48,-386.223,-0.187,-375.734,0); +INSERT INTO `mob_spawn_points` VALUES (16785719,'Para','Para',48,-385.080,-0.298,-374.396,122); +INSERT INTO `mob_spawn_points` VALUES (16785720,'Para','Para',48,-384.245,-0.402,-376.308,0); INSERT INTO `mob_spawn_points` VALUES (16785721,'Bullheaded_Grosvez','Bullheaded Grosvez',49,37.861,-8.684,-568.912,198); INSERT INTO `mob_spawn_points` VALUES (16785722,'Mycophile','Mycophile',50,145.500,-9.483,-699.000,74); INSERT INTO `mob_spawn_points` VALUES (16785723,'Hercules_Beetle','Hercules Beetle',51,-238.000,-5.950,-93.500,180); diff --git a/sql/npc_list.sql b/sql/npc_list.sql index 730d214bbdc..f693c1a5814 100644 --- a/sql/npc_list.sql +++ b/sql/npc_list.sql @@ -129,7 +129,7 @@ INSERT INTO `npc_list` VALUES (16785777,'Logging_Point','Logging Point',0,82.783 INSERT INTO `npc_list` VALUES (16785778,'Cofisephe','Cofisephe',177,210.327,-2.885,-532.511,14,50,50,0,1,0,0,27,0x0100010414101720003003400350006000700000,32,'COP',1); INSERT INTO `npc_list` VALUES (16785779,'Coupulie','Coupulie',131,-313.585,-2.628,490.944,1,40,40,0,1,0,0,27,0x0100000414102620083003400350006000700000,32,'COP',1); INSERT INTO `npc_list` VALUES (16785780,'Echanie','Echanie',139,-148.424,-2.948,45.675,1,50,50,0,1,0,0,27,0x010003041410172000300A400350006000700000,32,'COP',1); -INSERT INTO `npc_list` VALUES (16785781,'qm','???',0,-416.126,0.000,-363.468,32769,50,50,0,0,0,0,3,0x0000320000000000000000000000000000000000,0,'COP',0); +INSERT INTO `npc_list` VALUES (16785781,'qm_para','???',0,-416.126,0.000,-363.468,32769,50,50,0,0,0,0,3,0x0000320000000000000000000000000000000000,0,'COP',0); INSERT INTO `npc_list` VALUES (16785782,'qm','???',240,39.877,-7.397,-565.422,1,50,50,0,0,0,0,3,0x0000340000000000000000000000000000000000,0,'COP',0); INSERT INTO `npc_list` VALUES (16785783,'relic','',126,-99.577,-0.016,-514.720,32769,50,50,0,0,0,0,3,0x0000340000000000000000000000000000000000,0,'COP',1); INSERT INTO `npc_list` VALUES (16785784,'Perseus','Perseus',0,0.000,0.000,0.000,0,40,40,0,0,0,6,2075,0x010001014D104D204D304D404D50166133700000,32,'COP',1);