Skip to content

Commit

Permalink
Add test for player's attack
Browse files Browse the repository at this point in the history
  • Loading branch information
elsid committed Aug 27, 2024
1 parent 5f26da0 commit 7998689
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 1 deletion.
111 changes: 111 additions & 0 deletions scripts/data/integration_tests/test_lua_api/player.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ local core = require('openmw.core')
local input = require('openmw.input')
local types = require('openmw.types')
local nearby = require('openmw.nearby')
local camera = require('openmw.camera')

types.Player.setControlSwitch(self, types.Player.CONTROL_SWITCH.Controls, false)
types.Player.setControlSwitch(self, types.Player.CONTROL_SWITCH.Fighting, false)
types.Player.setControlSwitch(self, types.Player.CONTROL_SWITCH.Jumping, false)
types.Player.setControlSwitch(self, types.Player.CONTROL_SWITCH.Looking, false)
Expand Down Expand Up @@ -230,6 +232,115 @@ testing.registerLocalTest('playerMemoryLimit',
testing.expectEqual(err, 'not enough memory')
end)

testing.registerLocalTest('playerWeaponAttack',
function()
camera.setMode(camera.MODE.ThirdPerson)

local options = {
agentBounds = types.Actor.getPathfindingAgentBounds(self),
}
local duration = 10
local endTime = core.getSimulationTime() + duration
local nextTime = 0
local use = self.ATTACK_TYPE.NoAttack

local attributes = {}
for k, v in pairs(types.Actor.stats.attributes) do
attributes[k] = v(self).base
end

types.Actor.stats.attributes.speed(self).base = 100
types.Actor.stats.attributes.strength(self).base = 1000
types.Actor.stats.attributes.agility(self).base = 1000

local weaponId = 'basic_dagger1h'
local weapon = types.Actor.inventory(self):find(weaponId)

local isWeapon = function(actual)
if actual == nil then
return weaponId .. ' is not found'
end
if actual.recordId ~= weaponId then
return 'found weapon recordId does not match expected: actual=' .. tostring(actual.id)
.. ', expected=' .. weaponId
end
return ''
end
testing.expectThat(weapon, isWeapon)

types.Actor.setEquipment(self, {[types.Actor.EQUIPMENT_SLOT.CarriedRight] = weapon})

coroutine.yield()

testing.expectThat(types.Actor.getEquipment(self, types.Actor.EQUIPMENT_SLOT.CarriedRight), isWeapon)

types.Actor.setStance(self, types.Actor.STANCE.Weapon)

local previousHealth = nil
local targetActor = nil

while true do
local time = core.getSimulationTime()
testing.expectLessOrEqual(time, endTime, 'Did not damage any targets in ' .. duration .. ' seconds')

if targetActor ~= nil and types.Actor.stats.dynamic.health(targetActor).current < previousHealth then
print('Dealt ' .. (previousHealth - types.Actor.stats.dynamic.health(targetActor).current) .. ' damage to ' .. tostring(targetActor))
break
end

local minDistance = nil
for i, actor in ipairs(nearby.actors) do
if actor.id ~= self.id then
local distance = (actor.position - self.position):length()
if minDistance == nil or minDistance > distance then
minDistance = distance
targetActor = actor
end
end
end
testing.expectNotEqual(targetActor, nil, 'No attack targets found')

previousHealth = types.Actor.stats.dynamic.health(targetActor).current

local destination = nil
if minDistance > 100 then
local status, path = nearby.findPath(self.position, targetActor.position, options)

testing.expectEqual(status, nearby.FIND_PATH_STATUS.Success,
'Failed to find path from ' .. tostring(self.position) .. ' to ' .. tostring(targetActor.position))

destination = path[2]
use = self.ATTACK_TYPE.NoAttack

self.controls.run = true
self.controls.movement = 1
else
destination = targetActor.position

if nextTime < time then
if use == 0 then
use = self.ATTACK_TYPE.Any
nextTime = time + 0.5
else
use = self.ATTACK_TYPE.NoAttack
end
end
end
self.controls.use = use

local direction = destination - self.position
direction = direction:normalize()
self.controls.yawChange = util.normalizeAngle(math.atan2(direction.x, direction.y) - self.rotation:getYaw())
self.controls.pitchChange = util.normalizeAngle(math.asin(util.clamp(-direction.z, -1, 1)) - self.rotation:getPitch())

coroutine.yield()
end

for k, v in pairs(types.Actor.stats.attributes) do
v(self).base = attributes[k]
end
end)

return {
engineHandlers = {
onFrame = testing.updateLocal,
Expand Down
7 changes: 6 additions & 1 deletion scripts/data/integration_tests/test_lua_api/test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,12 @@ tests = {
{'playerMemoryLimit', function()
initPlayer()
testing.runLocalTest(player, 'playerMemoryLimit')
end}
end},
{'player with equipped weapon on attack should damage health of other actors', function()
initPlayer()
world.createObject('basic_dagger1h', 1):moveInto(player)
testing.runLocalTest(player, 'playerWeaponAttack')
end},
}

return {
Expand Down
6 changes: 6 additions & 0 deletions scripts/data/integration_tests/testing_util/testing_util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ function M.expectEqual(v1, v2, msg)
end
end

function M.expectNotEqual(v1, v2, msg)
if v1 == v2 then
error(string.format('%s: %s == %s', msg or '', v1, v2), 2)
end
end

function M.closeToVector(expected, maxDistance)
return function(actual)
local distance = (expected - actual):length()
Expand Down

0 comments on commit 7998689

Please sign in to comment.