landsandboat/scripts/tests/systems/targetfind.lua
2026-04-14 19:43:10 -07:00

287 lines
10 KiB
Lua

describe('TargetFind', function()
---@type CClientEntityPair
local p1, p2, p3
local wyv1, wyv2, wyv3
before_each(function()
-- Spawn everyone in Dragon's Aery as DRG
local pConfig =
{
zone = xi.zone.DRAGONS_AERY,
job = xi.job.DRG,
level = 1,
}
p1 = xi.test.world:spawnPlayer(pConfig)
p1:setUnkillable(true)
p1.actions:useAbility(p1, xi.jobAbility.CALL_WYVERN)
xi.test.world:tickEntity(p1)
wyv1 = p1:getPet()
p2 = xi.test.world:spawnPlayer(pConfig)
p2:setUnkillable(true)
p2.actions:useAbility(p2, xi.jobAbility.CALL_WYVERN)
xi.test.world:tickEntity(p2)
wyv2 = p2:getPet()
p3 = xi.test.world:spawnPlayer(pConfig)
p3:setUnkillable(true)
p3.actions:useAbility(p3, xi.jobAbility.CALL_WYVERN)
xi.test.world:tickEntity(p3)
wyv3 = p3:getPet()
assert(wyv1, 'P1 did not get a Wyvern')
assert(wyv2, 'P2 did not get a Wyvern')
assert(wyv3, 'P3 did not get a Wyvern')
-- P1 and P2 are partied, P3 is solo
p1.actions:inviteToParty(p2)
p2.actions:acceptPartyInvite()
end)
it('Fafnir Spike Flail only hit claiming party', function()
-- Force Flail to always hit
local m = stub('xi.mobskills.mobPhysicalMove',
{
damage = 100,
hitsLanded = 3,
isCritical = false,
})
-- All of them should go to Fafnir
p1.entities:moveTo('Fafnir')
p2.entities:moveTo('Fafnir')
local fafnir = p3.entities:moveTo('Fafnir')
-- Spawn Fafnir and claim it to the party
fafnir:spawn()
fafnir.assert:isAlive()
fafnir:updateClaim(p1)
-- move wyverns to their masters
wyv1:setPos(p1:getPos())
wyv2:setPos(p2:getPos())
wyv3:setPos(p3:getPos())
-- Use Spike Flail
fafnir:setTP(3000)
fafnir:useMobAbility(952, p1)
-- Give some time for the AI to progress through Prepare and Complete
xi.test.world:skipTime(5)
xi.test.world:skipTime(5)
-- P1 and P2 should get hit. P3 should not.
m:called()
assert(p1:getHPP() ~= 100, 'P1 was not hit by Spike Flail')
assert(p2:getHPP() ~= 100, 'P2 was not hit by Spike Flail')
assert(p3:getHPP() == 100, 'P3 was hit by Spike Flail')
-- Same for their wyverns!
assert(wyv1:getHPP() ~= 100, 'P1 Wyvern was not hit by Spike Flail')
assert(wyv2:getHPP() ~= 100, 'P2 Wyvern was not hit by Spike Flail')
assert(wyv3:getHPP() == 100, 'P3 Wyvern was hit by Spike Flail')
end)
it('Nidhogg Spike Flail hits everyone', function()
-- Force Flail to always hit
local m = stub('xi.mobskills.mobPhysicalMove',
{
damage = 100,
hitsLanded = 3,
isCritical = false,
})
-- All players should go to Nidhogg
p1.entities:moveTo('Nidhogg')
p2.entities:moveTo('Nidhogg')
local nidhogg = p3.entities:moveTo('Nidhogg')
-- move wyverns to their masters
wyv1:setPos(p1:getPos())
wyv2:setPos(p2:getPos())
wyv3:setPos(p3:getPos())
-- Spawn Nidhogg and claim it to the party
nidhogg:spawn()
nidhogg.assert:isAlive()
nidhogg:updateClaim(p1)
nidhogg:setTP(3000)
nidhogg:useMobAbility(1040, p1)
-- Give some time for the AI to progress through Prepare and Complete
xi.test.world:skipTime(5)
xi.test.world:skipTime(5)
-- P1, P2 and P3 should get hit.
m:called()
assert(p1:getHPP() ~= 100, 'P1 was not hit by Spike Flail')
assert(p2:getHPP() ~= 100, 'P2 was not hit by Spike Flail')
assert(p3:getHPP() ~= 100, 'P3 was not hit by Spike Flail')
-- Same for their wyverns!
assert(wyv1:getHPP() ~= 100, 'P1 Wyvern was not hit by Spike Flail')
assert(wyv2:getHPP() ~= 100, 'P2 Wyvern was not hit by Spike Flail')
assert(wyv3:getHPP() ~= 100, 'P3 Wyvern was not hit by Spike Flail')
end)
it('King Behemoth Meteor hits everyone (MOBMOD_AOE_HIT_ALL)', function()
---@type CClientEntityPair
local charA, charB
-- Spawn two chars in Behemoth's Dominion
local pConfig =
{
zone = xi.zone.BEHEMOTHS_DOMINION,
job = xi.job.WAR,
level = 75,
}
charA = xi.test.world:spawnPlayer(pConfig)
charA:setUnkillable(true)
charB = xi.test.world:spawnPlayer(pConfig)
charB:setUnkillable(true)
-- Move both players to King Behemoth
charA.entities:moveTo('King_Behemoth')
local kb = charB.entities:moveTo('King_Behemoth')
-- Spawn King Behemoth and claim it with charA only
kb:spawn()
kb.assert:isAlive()
kb:updateClaim(charA)
-- Make King Behemoth cast Meteor on charA and assert both got hit
kb:castSpell(xi.magic.spell.METEOR, charA)
xi.test.world:tickEntity(kb)
xi.test.world:skipTime(10)
assert(charA:getHPP() ~= 100, 'CharA was not hit by Meteor')
assert(charB:getHPP() ~= 100, 'CharB was not hit by Meteor')
end)
it('Qultada trust Corsair Roll affects master and party', function()
local pConfig =
{
zone = xi.zone.WEST_RONFAURE,
job = xi.job.SMN,
level = 99,
}
local player = xi.test.world:spawnPlayer(pConfig)
player:setGMLevel(3)
player:setVisibleGMLevel(3)
player:spawnPet(xi.petId.TITAN)
local titan = player:getPet()
assert(titan, 'Titan was not summoned')
local partyMember = xi.test.world:spawnPlayer(pConfig)
partyMember:setPos(player:getXPos(), player:getYPos(), player:getZPos())
player.actions:inviteToParty(partyMember)
partyMember.actions:acceptPartyInvite()
local stranger = xi.test.world:spawnPlayer(pConfig)
stranger:setPos(player:getXPos(), player:getYPos(), player:getZPos())
player:addSpell(xi.magic.spell.QULTADA)
player.actions:useSpell(player, xi.magic.spell.QULTADA)
xi.test.world:tickEntity(player)
xi.test.world:skipTime(10)
local qultada = nil
for _, member in ipairs(player:getPartyWithTrusts()) do
if member:getName() == 'qultada' then
qultada = member
break
end
end
assert(qultada, 'Qultada was not summoned')
qultada:useJobAbility(xi.ja.CORSAIRS_ROLL, qultada)
xi.test.world:tickEntity(qultada)
xi.test.world:skipTime(5)
assert(qultada:hasStatusEffect(xi.effect.CORSAIRS_ROLL), 'Qultada does not have Corsair Roll')
assert(player:hasStatusEffect(xi.effect.CORSAIRS_ROLL), 'Player does not have Corsair Roll')
assert(partyMember:hasStatusEffect(xi.effect.CORSAIRS_ROLL), 'Party member does not have Corsair Roll')
assert(not stranger:hasStatusEffect(xi.effect.CORSAIRS_ROLL), 'Stranger incorrectly has Corsair Roll')
assert(not titan:hasStatusEffect(xi.effect.CORSAIRS_ROLL), 'Titan incorrectly has Corsair Roll')
end)
it('Player Corsair Roll affects self and party', function()
local pConfig =
{
zone = xi.zone.WEST_RONFAURE,
job = xi.job.COR,
sjob = xi.job.SMN,
level = 99,
}
local player = xi.test.world:spawnPlayer(pConfig)
player:addLearnedAbility(xi.ja.CORSAIRS_ROLL)
player:spawnPet(xi.petId.CARBUNCLE)
local carby = player:getPet()
assert(carby, 'Carbuncle was not summoned')
local partyMember = xi.test.world:spawnPlayer(pConfig)
partyMember:setPos(player:getXPos(), player:getYPos(), player:getZPos())
player.actions:inviteToParty(partyMember)
partyMember.actions:acceptPartyInvite()
local stranger = xi.test.world:spawnPlayer(pConfig)
stranger:setPos(player:getXPos(), player:getYPos(), player:getZPos())
player.actions:useAbility(player, xi.ja.CORSAIRS_ROLL)
xi.test.world:tickEntity(player)
xi.test.world:skipTime(5)
assert(player:hasStatusEffect(xi.effect.CORSAIRS_ROLL), 'Player does not have Corsair Roll')
assert(partyMember:hasStatusEffect(xi.effect.CORSAIRS_ROLL), 'Party member does not have Corsair Roll')
assert(not stranger:hasStatusEffect(xi.effect.CORSAIRS_ROLL), 'Stranger incorrectly has Corsair Roll')
assert(not carby:hasStatusEffect(xi.effect.CORSAIRS_ROLL), 'Carbuncle incorrectly has Corsair Roll')
end)
it('Valaineral trust Majesty + Cure III heals party', function()
local pConfig =
{
zone = xi.zone.WEST_RONFAURE,
job = xi.job.WAR,
level = 99,
}
local player = xi.test.world:spawnPlayer(pConfig)
player:setGMLevel(3)
player:setVisibleGMLevel(3)
local stranger = xi.test.world:spawnPlayer(pConfig)
player:addSpell(xi.magic.spell.VALAINERAL)
player.actions:useSpell(player, xi.magic.spell.VALAINERAL)
xi.test.world:tickEntity(player)
xi.test.world:skipTime(10)
local valaineral = nil
for _, member in ipairs(player:getPartyWithTrusts()) do
if member:getName() == 'valaineral' then
valaineral = member
break
end
end
assert(valaineral, 'Valaineral was not summoned')
player:setHP(1)
stranger:setHP(1)
stranger:setPos(player:getXPos(), player:getYPos(), player:getZPos())
valaineral:useJobAbility(xi.ja.MAJESTY, valaineral)
xi.test.world:tickEntity(valaineral)
xi.test.world:skipTime(3)
valaineral:castSpell(xi.magic.spell.CURE_III, valaineral)
xi.test.world:tickEntity(valaineral)
xi.test.world:skipTime(10)
assert(player:getHP() > 1, 'Player was not healed by Valaineral Cure III')
assert(stranger:getHP() == 1, 'Stranger was incorrectly healed by Valaineral Cure III')
end)
end)