-
Notifications
You must be signed in to change notification settings - Fork 663
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-Authored-By: 0x05010705 <[email protected]>
- Loading branch information
1 parent
bc1c0d4
commit 9b14bdf
Showing
8 changed files
with
342 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
----------------------------------- | ||
-- Two Horn the Savage | ||
----------------------------------- | ||
-- Log ID: 6, Quest ID: 17 | ||
----------------------------------- | ||
-- !zone 50 = Whitegate | ||
-- Milazahn = !pos -58.1921 0.000 1.9746 | ||
-- Cacaroon = !pos -71.1544 0.000 -86.0422 | ||
-- !zone 65 = Mamook | ||
-- Viscous Liquid = !pos -262.437 5.130 -141.241 | ||
----------------------------------- | ||
local ID = zones[xi.zone.MAMOOK] | ||
----------------------------------- | ||
|
||
local quest = Quest:new(xi.questLog.AHT_URHGAN, xi.quest.id.ahtUrhgan.TWO_HORN_THE_SAVAGE) | ||
|
||
quest.reward = | ||
{ | ||
item = xi.item.IMPERIAL_MYTHRIL_PIECE, | ||
} | ||
|
||
quest.sections = | ||
{ | ||
{ | ||
check = function(player, status, vars) | ||
return status == xi.questStatus.QUEST_AVAILABLE | ||
end, | ||
|
||
[xi.zone.AHT_URHGAN_WHITEGATE] = | ||
{ | ||
['Milazahn'] = quest:progressEvent(594), | ||
|
||
onEventFinish = | ||
{ | ||
[594] = function(player, csid, option, npc) | ||
if option == 1 then | ||
quest:begin(player) | ||
end | ||
end, | ||
}, | ||
}, | ||
}, | ||
|
||
{ | ||
check = function(player, status, vars) | ||
return status == xi.questStatus.QUEST_ACCEPTED | ||
end, | ||
|
||
[xi.zone.AHT_URHGAN_WHITEGATE] = | ||
{ | ||
['Cacaroon'] = | ||
{ | ||
onTrigger = function(player, npc) | ||
if quest:getVar(player, 'Temp') == 1 then | ||
return quest:event(608):oncePerZone() | ||
end | ||
end, | ||
|
||
onTrade = function(player, npc, trade) | ||
if | ||
quest:getVar(player, 'Prog') == 0 and | ||
npcUtil.tradeHasExactly(trade, { { 'gil', 1000 } }) | ||
then | ||
return quest:progressEvent(595) | ||
end | ||
end, | ||
}, | ||
|
||
['Milazahn'] = | ||
{ | ||
onTrigger = function(player, npc) | ||
if quest:getVar(player, 'Prog') == 4 then | ||
return quest:progressEvent(596) | ||
end | ||
end, | ||
}, | ||
|
||
onEventFinish = | ||
{ | ||
[596] = function(player, csid, option, npc) | ||
quest:complete(player) | ||
end, | ||
|
||
[595] = function(player, csid, option, npc) | ||
quest:setVar(player, 'Temp', 1) | ||
quest:setVar(player, 'Prog', 1) | ||
end, | ||
}, | ||
}, | ||
|
||
[xi.zone.MAMOOK] = | ||
{ | ||
['Viscous_Liquid'] = | ||
{ | ||
onTrigger = function(player, npc) | ||
local progress = quest:getVar(player, 'Prog') | ||
local liquid = npc:getID() | ||
|
||
if liquid == ID.npc.QUEST_LIQUID then | ||
if progress == 1 then | ||
return quest:progressEvent(212) | ||
elseif | ||
progress == 2 and | ||
npcUtil.popFromQM(player, npc, ID.mob.MAMOOL_JA, { claim = true, hide = 0 }) | ||
then | ||
return quest:messageSpecial(ID.text.IMPENDING_BATTLE) | ||
elseif progress == 3 then | ||
return quest:progressEvent(213) | ||
end | ||
end | ||
end, | ||
}, | ||
|
||
onEventFinish = | ||
{ | ||
[212] = function(player, csid, option, npc) | ||
quest:setVar(player, 'Prog', 2) | ||
end, | ||
|
||
[213] = function(player, csid, option, npc) | ||
quest:setVar(player, 'Prog', 4) | ||
end, | ||
}, | ||
|
||
['Mamool_Ja'] = | ||
{ | ||
onMobDeath = function(mob, player, optParams) | ||
if quest:getVar(player, 'Prog') == 2 then | ||
quest:setVar(player, 'Prog', 3) -- Zoning will NOT reset progress. Progress is gained and kept as long as the NM has died. | ||
end | ||
end, | ||
}, | ||
}, | ||
|
||
}, | ||
} | ||
|
||
return quest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
----------------------------------- | ||
-- Area: Mamook | ||
-- NM: Mamool Ja | ||
-- Quest: Two Horn the Savage | ||
-- !zone 65 | ||
-- !spawnmob 17043871 | ||
----------------------------------- | ||
mixins = { require('scripts/mixins/families/mamool_ja'), require('scripts/mixins/weapon_break') } | ||
----------------------------------- | ||
---@type TMobEntity | ||
local entity = {} | ||
|
||
local paths = | ||
{ | ||
HEAL1 = 1, | ||
HEAL2 = 2, | ||
HEAL3 = 3, | ||
HEAL4 = 4, | ||
HEAL5 = 5, | ||
HEAL6 = 6, | ||
HEAL7 = 7, | ||
HEAL8 = 8, | ||
SPAWN = 9, | ||
} | ||
|
||
local pathNodes = | ||
{ | ||
[paths.HEAL1] = | ||
{ | ||
{ x = -264.018, y = 004.920, z = -145.779 }, | ||
}, | ||
[paths.HEAL2] = | ||
{ | ||
{ x = -256.346, y = 005.062, z = -137.394 }, | ||
}, | ||
[paths.HEAL3] = | ||
{ | ||
{ x = -255.644, y = 004.907, z = -144.149 }, | ||
}, | ||
[paths.HEAL4] = | ||
{ | ||
{ x = -252.875, y = 005.091, z = -140.162 }, | ||
}, | ||
[paths.HEAL5] = | ||
{ | ||
{ x = -260.354, y = 004.878, z = -136.609 }, | ||
}, | ||
[paths.HEAL6] = | ||
{ | ||
{ x = -260.038, y = 004.989, z = -145.486 }, | ||
}, | ||
[paths.HEAL7] = | ||
{ | ||
{ x = -263.814, y = 005.118, z = -137.361 }, | ||
}, | ||
[paths.HEAL8] = | ||
{ | ||
{ x = -267.267, y = 005.109, z = -142.522 }, | ||
}, | ||
[paths.SPAWN] = | ||
{ | ||
-- From spawn to the staging spot before it engages | ||
{ x = -257.529, y = 4.627, z = -149.291 }, | ||
{ x = -252.861, y = 5.091, z = -140.169 }, -- Ending Spot | ||
}, | ||
} | ||
|
||
-- Determines the next spot where the NM will stand. It is intended for the NM to cycle between two spots and pace while its regen is active. | ||
local findHealNode = function(mob, target) | ||
local largestDist = 0.0 | ||
local nextNode = 0 | ||
local spawnPos = mob:getSpawnPos() | ||
|
||
if mob:checkDistance(pathNodes[paths.SPAWN][1].x, pathNodes[paths.SPAWN][1].y, pathNodes[paths.SPAWN][1].z) <= 20 then | ||
for idx = 1, 8, 1 do | ||
local currentNode = pathNodes[idx][1] | ||
local playerDist = target:checkDistance(currentNode.x, currentNode.y, currentNode.z) | ||
if | ||
playerDist > largestDist and | ||
mob:checkDistance(currentNode.x, currentNode.y, currentNode.z) > 1.0 | ||
then | ||
largestDist = playerDist | ||
nextNode = idx | ||
end | ||
end | ||
|
||
else | ||
nextNode = paths.SPAWN | ||
mob:setLocalVar('checkedDist', mob:checkDistance(spawnPos.x, spawnPos.y, spawnPos.z)) | ||
end | ||
|
||
mob:setLocalVar('healNode', nextNode) | ||
mob:pathTo(pathNodes[nextNode][1].x, pathNodes[nextNode][1].y, pathNodes[nextNode][1].z, bit.bor(xi.path.flag.SCRIPT, xi.path.flag.RUN)) | ||
end | ||
|
||
local doHealing = function(mob) | ||
mob:setLocalVar('isHealing', 1) | ||
mob:setAutoAttackEnabled(false) -- Stops the NM from attacking until it is fully re-engaged with the player | ||
mob:addStatusEffectEx(xi.effect.BIND, xi.effect.BIND, 0, 0, 5, 0, 0, 0, xi.effectFlag.NO_LOSS_MESSAGE, true) -- Will bind the NM to stop it from moving for a set time. | ||
if | ||
mob:getHPP() < 85 and | ||
not mob:hasStatusEffect(xi.effect.REGEN) | ||
then | ||
mob:addStatusEffectEx(xi.effect.REGEN, xi.effect.REGEN, 264, 5, 100, 0, 0, xi.effectFlag.NO_LOSS_MESSAGE, true) | ||
end | ||
end | ||
|
||
local spawnDance = function(mob) | ||
mob:pathTo(pathNodes[paths.SPAWN][1].x, pathNodes[paths.SPAWN][1].y, pathNodes[paths.SPAWN][1].z, bit.bor(xi.path.flag.SCRIPT)) | ||
mob:pathTo(pathNodes[paths.SPAWN][2].x, pathNodes[paths.SPAWN][2].y, pathNodes[paths.SPAWN][2].z, bit.bor(xi.path.flag.SCRIPT)) | ||
|
||
if mob:checkDistance(pathNodes[paths.SPAWN][2].x, pathNodes[paths.SPAWN][2].y, pathNodes[paths.SPAWN][2].z) < 1 then | ||
mob:addStatusEffectEx(xi.effect.BIND, xi.effect.BIND, 0, 0, 5, 0, 0, 0, xi.effectFlag.NO_LOSS_MESSAGE, true) | ||
mob:setLocalVar('justSpawned', 0) | ||
end | ||
end | ||
|
||
entity.onMobSpawn = function(mob) | ||
mob:setMobMod(xi.mobMod.IDLE_DESPAWN, 180) | ||
mob:setLocalVar('justSpawned', 1) | ||
end | ||
|
||
entity.onMobWeaponSkillPrepare = function(mob) | ||
if mob:getAnimationSub() >= 1 then | ||
return xi.mobSkill.FORCEFUL_BLOW -- Will ONLY use Forceful Blow when it's weapon is broken. | ||
end | ||
end | ||
|
||
entity.onMobFight = function(mob, target) | ||
local healNode = mob:getLocalVar('healNode') | ||
local spawnPos = mob:getSpawnPos() -- Checks the NM's spawn POS | ||
local checkedDist = mob:getLocalVar('checkedDist') -- Updates when the NM uses a TP move or when it heals more than 30 yalms away from spawn | ||
local targetDist = mob:checkDistance(target) -- Used to check the NM's disance from it's current Target | ||
local spawnDist = mob:checkDistance(spawnPos.x, spawnPos.y, spawnPos.z) | ||
local isHealing = mob:getLocalVar('isHealing') | ||
local justSpawned = mob:getLocalVar('justSpawned') | ||
local hpp = mob:getHPP() | ||
|
||
-- When the NM is spawned it will run to a set spot before engaging the player. | ||
if justSpawned == 1 then | ||
spawnDance(mob) | ||
end | ||
|
||
-- When the NM is taken down to 75% or less it has a high chance of being intimidated | ||
if | ||
hpp <= 75 and | ||
not mob:hasStatusEffect(xi.effect.INTIMIDATE) | ||
then | ||
mob:addStatusEffectEx(xi.effect.INTIMIDATE, xi.effect.NONE, 20, 0, 0xFFFF, 0, 0, 0, xi.effectFlag.NO_LOSS_MESSAGE, true) | ||
elseif hpp > 75 then | ||
mob:delStatusEffect(xi.effect.INTIMIDATE) | ||
end | ||
|
||
-- If the player enters melee range then the NM will re-engage and stop healing | ||
-- The NM will re-engage on its own if it heals over 85% of its health | ||
if | ||
isHealing == 1 and | ||
(hpp >= 85 or targetDist <= 5) | ||
then | ||
mob:delStatusEffectSilent(xi.effect.REGEN) | ||
mob:setAutoAttackEnabled(true) | ||
mob:clearPath() | ||
mob:setLocalVar('healNode', 0) | ||
mob:setLocalVar('isHealing', 0) | ||
end | ||
|
||
-- Determines how the NM will heal. | ||
-- If 20 yalms or more away from spawn the NM will travel back towards spawn stopping to heal along the way. | ||
-- If within 20 yalms of spawn it will cycle perform normal healing mechanics | ||
if healNode ~= 0 then | ||
if spawnDist <= 20 then | ||
if mob:checkDistance(pathNodes[healNode][1]) < 1 then | ||
doHealing(mob) | ||
findHealNode(mob, target) | ||
end | ||
elseif spawnDist > 20 then | ||
if checkedDist - spawnDist >= 10 then -- Checks if the NM has moved 10 yalms or more from the last time it healed. | ||
doHealing(mob) | ||
mob:setLocalVar('checkedDist', spawnDist) | ||
end | ||
end | ||
end | ||
end | ||
|
||
entity.onMobWeaponSkill = function(target, mob, skill) | ||
findHealNode(mob, target) | ||
end | ||
|
||
entity.onMobDeath = function(mob, player, optParams) | ||
end | ||
|
||
return entity |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters