engine/bin/data/entities/scripts/player.lua

226 lines
7.1 KiB
Lua

local scene = entities.currentScene()
local metadata = ent:getComponent("Metadata")
local transform = ent:getComponent("Transform")
local physicsState = ent:getComponent("PhysicsState")
local camera = ent:getComponent("Camera")
local cameraTransform = camera:getTransform()
-- setup all timers
local timers = {
use = Timer.new(),
holp = Timer.new(),
flashlight = Timer.new(),
physcannon = Timer.new()
}
if not timers.use:running() then timers.use:start(); end
if not timers.holp:running() then timers.holp:start(); end
if not timers.flashlight:running() then timers.flashlight:start(); end
if not timers.physcannon:running() then timers.physcannon:start(); end
-- setup held object locals
local heldObject = {
uid = 0,
distance = 0,
smoothSpeed = 4,
scrollSpeed = 16,
momentum = Vector3f(0,0,0),
rotate = false,
}
-- setup light locals
local light = {
entity = nil
}
for k, v in pairs(ent:getChildren()) do
if v:name() == "Light" then
light.entity = v
end
end
if light.entity == nil then
light.entity = ent:loadChild("./playerLight.json",true)
end
light.metadata = light.entity:getComponent("Metadata")
light.transform = light.entity:getComponent("Transform")
light.power = light.metadata["light"]["power"]
light.origin = Vector3f(light.transform.position)
light.entity:setComponent("Metadata", { light = { power = 0 } })
-- sound emitter
local playSound = function( key, loop )
if not loop then loop = false end
local url = "/ui/" .. key .. ".ogg"
ent:queueHook("sound:Emit.%UID%", {
filename = string.resolveURI(url, metadata["system"]["root"]),
spatial = true,
streamed = true,
volume = "sfx",
loop = loop
}, 0)
end
local stopSound = function( key )
local url = "/ui/" .. key .. ".ogg"
ent:queueHook("sound:Stop.%UID%", {
filename = string.resolveURI(url, metadata["system"]["root"])
}, 0)
end
local useDistance = 6
local pullDistance = useDistance * 4
-- on tick
ent:bind( "tick", function(self)
-- eye transform
local flattenedTransform = cameraTransform:flatten()
flattenedTransform.forward = ( transform.forward + Vector3f( 0, cameraTransform.forward.y, 0 ) ):normalize();
-- toggle flashlight
light.transform.position = flattenedTransform.position + flattenedTransform.forward * 2
if timers.flashlight:elapsed() > 0.5 and inputs.key("F") then
timers.flashlight:reset()
local metadata = { light = { power = light.power } }
if light.entity:getComponent("Metadata")["light"]["power"] ~= light.power then
metadata["light"]["power"] = light.power
else
metadata["light"]["power"] = 0
end
light.entity:setComponent("Metadata", metadata)
playSound("flashlight")
end
-- fire use ray
if timers.use:elapsed() > 0.5 and inputs.key("E") then
timers.use:reset()
local center = flattenedTransform.position
local direction = flattenedTransform.forward * useDistance
local prop, depth = physicsState:rayCast( center, direction )
local payload = {
user = ent:uid(),
uid = prop and prop:uid() or 0,
depth = depth,
}
if prop then
prop:callHook("entity:Use.%UID%", payload)
end
ent:callHook("entity:Use.%UID%", payload)
end
-- update HOLP
if heldObject.uid == 0 then
local mouse2 = inputs.key("Mouse2");
if mouse2 then
--[[
local center = transform.position + cameraTransform.position
local direction = transform.forward + Vector3f( 0, cameraTransform.forward.y, 0 )
direction = direction:normalize() * 4
]]
local center = flattenedTransform.position
local direction = flattenedTransform.forward * pullDistance
local prop, depth = physicsState:rayCast( center, direction )
if depth >= 0 and prop and not string.matched( prop:name(), "/^worldspawn/" ) then
local heldObjectTransform = prop:getComponent("Transform")
local heldObjectPhysicsState = prop:getComponent("PhysicsState")
local strength = 500
local distanceSquared = (heldObjectTransform.position - flattenedTransform.position):magnitude()
heldObjectPhysicsState:applyImpulse( flattenedTransform.forward * -heldObjectPhysicsState:getMass() * strength / distanceSquared )
if timers.physcannon:elapsed() > 1.0 then
timers.physcannon:reset()
playSound("phys_tooHeavy")
end
end
end
else
local mouse1 = inputs.key("Mouse1");
local mouse3 = inputs.key("Mouse3");
local wheel = inputs.analog("MouseWheel")
if wheel ~= 0 then
heldObject.distance = heldObject.distance + (wheel / 120 * heldObject.scrollSpeed) * time.delta()
end
if mouse3 then
heldObject.rotate = not heldObject.rotate
end
local prop = entities.get( heldObject.uid )
local heldObjectTransform = prop:getComponent("Transform")
local heldObjectPhysicsState = prop:getComponent("PhysicsState")
if mouse1 and timers.physcannon:elapsed() > 0.5 then
timers.physcannon:reset()
heldObject.uid = 0
heldObjectPhysicsState:enableGravity(true)
heldObjectPhysicsState:applyImpulse( flattenedTransform.forward * heldObjectPhysicsState:getMass() * 1000 )
playSound("phys_launch"..math.random(1,4))
else
if heldObject.rotate then
heldObjectTransform.orientation = Quaternion.lookAt( (heldObjectTransform.position - flattenedTransform.position):normalize(), transform.up )
end
local forward = flattenedTransform.forward * heldObject.distance --flattenedTransform.orientation:rotate( Vector3f(0,0,1) )
if heldObject.smoothSpeed ~= 0 then
local target = flattenedTransform.position + forward
local offset = target - heldObjectTransform.position
local delta = offset * time.delta() * heldObject.smoothSpeed
local distance = delta:norm()
if distance > 0.001 then
if timers.holp:elapsed() > 0.125 then
timers.holp:reset()
heldObjectPhysicsState:setVelocity( delta * 20 )
end
else
heldObjectPhysicsState:setVelocity( Vector3f(0,0,0) )
end
else
heldObjectTransform.position = flattenedTransform.position + forward
end
end
end
end )
-- on use
ent:addHook( "entity:Use.%UID%", function( payload )
if payload.user ~= ent:uid() then return end
local validUse = false
if heldObject.uid == 0 then
local prop = entities.get( payload.uid )
local propMetadata = prop:getComponent("Metadata")
if propMetadata["holdable"] then
validUse = true
local offset = transform.position - prop:getComponent("Transform").position
heldObject.uid = payload.uid
heldObject.distance = offset:norm()
prop:getComponent("PhysicsState"):enableGravity(false)
end
elseif heldObject.uid ~= 0 then
validUse = true
local prop = entities.get( heldObject.uid )
local heldObjectPhysicsState = prop:getComponent("PhysicsState")
heldObjectPhysicsState:enableGravity(true)
heldObjectPhysicsState:applyImpulse( heldObject.momentum )
heldObject.uid = 0
heldObject.distance = 0
heldObject.momentum = Vector3f(0,0,0)
elseif payload.uid ~= 0 then
local hit = entities.get( heldObject.uid )
validUse = not string.matched( hit:name(), "/^worldspawn/" )
end
if validUse then
playSound("select")
else
playSound("deny")
end
end )