From 93e7ae159ae9e6675bc12fe040f33e8de734b24f Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 6 Sep 2025 22:30:01 +0300 Subject: [PATCH] add core:player component --- res/content/base/entities/player.json | 1 + .../scripts/components/player_animator.lua | 2 +- res/scripts/components/mob.lua | 153 ++++++++---------- res/scripts/components/pathfinding.lua | 9 +- res/scripts/components/player.lua | 59 +++++++ 5 files changed, 132 insertions(+), 92 deletions(-) create mode 100644 res/scripts/components/player.lua diff --git a/res/content/base/entities/player.json b/res/content/base/entities/player.json index d3d5712c..b6656914 100644 --- a/res/content/base/entities/player.json +++ b/res/content/base/entities/player.json @@ -6,6 +6,7 @@ "jump_force": 8.0 } }, + "core:player", "base:player_animator" ], "hitbox": [0.6, 1.8, 0.6] diff --git a/res/content/base/scripts/components/player_animator.lua b/res/content/base/scripts/components/player_animator.lua index 78049a2c..eddbdb5d 100644 --- a/res/content/base/scripts/components/player_animator.lua +++ b/res/content/base/scripts/components/player_animator.lua @@ -18,7 +18,7 @@ function on_render() if pid == -1 then return end - + local rx, ry, rz = player.get_rot(pid, pid ~= hud.get_player()) rig:set_matrix(headIndex, mat4.rotate({1, 0, 0}, ry)) rig:set_matrix(bodyIndex, mat4.rotate({0, 1, 0}, rx)) diff --git a/res/scripts/components/mob.lua b/res/scripts/components/mob.lua index b423e30c..3cbf285d 100644 --- a/res/scripts/components/mob.lua +++ b/res/scripts/components/mob.lua @@ -1,5 +1,6 @@ local body = entity.rigidbody local tsf = entity.transform +local rig = entity.skeleton local props = {} @@ -23,9 +24,12 @@ def_prop("movement_speed", 3.0) def_prop("run_speed_mul", 1.5) def_prop("crouch_speed_mul", 0.35) def_prop("flight_speed_mul", 4.0) -def_prop("cheat_speed_mul", 5.0) def_prop("gravity_scale", 1.0) +direction = {0, 0, -1} + +local flight = false + function jump(multiplier) if body:is_grounded() then local vel = body:get_vel() @@ -37,13 +41,13 @@ end function elevate(speed, delta, vel) vel = vel or body:get_vel() body:set_vel( - vec3.add(vel, {0, speed * delta, 0}, vel)) + vec3.add(vel, {0, speed * delta * props.movement_speed, 0}, vel)) end function lower(speed, delta, vel) vel = vel or body:get_vel() body:set_vel( - vec3.add(vel, {0, -speed * delta, 0}, vel)) + vec3.add(vel, {0, -speed * delta * props.movement_speed, 0}, vel)) end function move_horizontal(speed, dir, vel) @@ -57,119 +61,90 @@ function move_horizontal(speed, dir, vel) body:set_vel(vel) end -local function process_player_inputs(pid, delta) - if not hud or hud.is_inventory_open() or menu.page ~= "" then - return - end - -- todo: replace with entity direction - local cam = cameras.get("core:first-person") - local front = cam:get_front() - local right = cam:get_right() - front[2] = 0.0 - vec3.normalize(front, front) - - local grounded = body:is_grounded() - - local isjump = input.is_active('movement.jump') - local issprint = input.is_active('movement.sprint') - local iscrouch = input.is_active('movement.crouch') - local isforward = input.is_active('movement.forward') - local ischeat = input.is_active('movement.cheat') - local isback = input.is_active('movement.back') - local isleft = input.is_active('movement.left') - local isright = input.is_active('movement.right') - local flight = player.is_flight(pid) - local noclip = player.is_noclip(pid) - - local vel = body:get_vel() - - local speed = props.movement_speed - +function go(dir, speed_multiplier, sprint, crouch, vel) + local speed = props.movement_speed * speed_multiplier if flight then speed = speed * props.flight_speed_mul - elseif issprint then + end + if sprint then speed = speed * props.run_speed_mul - elseif iscrouch and grounded then + elseif crouch then speed = speed * props.crouch_speed_mul end - body:set_crouching(iscrouch) - - if ischeat then - speed = speed * props.cheat_speed_mul - end - - local dir = {0, 0, 0} - if isforward then - vec3.add(dir, front, dir) - end - if isback then - vec3.sub(dir, front, dir) - end - if isright then - vec3.add(dir, right, dir) - end - if isleft then - vec3.sub(dir, right, dir) - end - - if vec3.length(dir) > 0.0 then - move_horizontal(speed, dir, vel) - end - - if flight then - if isjump then - elevate(speed * 8.0, delta) - elseif iscrouch then - lower(speed * 8.0, delta) - end - elseif isjump then - jump() - end - body:set_vdamping(flight) - body:set_gravity_scale({0, flight and 0.0 or props.gravity_scale, 0}) - body:set_linear_damping( - (flight or not grounded) and props.air_damping or props.ground_damping - ) - body:set_body_type(noclip and "kinematic" or "dynamic") + move_horizontal(speed, dir, vel) end local prev_angle = 0.0 +local headIndex = rig:index("head") + + +-- todo: move somewhere +local watchtimer = math.random(0, 1000) +local function update_head() + watchtimer = watchtimer + 1 + + local pos = tsf:get_pos() + local viewdir = vec3.normalize(vec3.sub({player.get_pos(hud.get_player())}, pos)) + local isfront = vec3.dot(viewdir, direction) > 0.0 + + local headrot = mat4.idt() + local curdir = mat4.mul(mat4.mul(tsf:get_rot(), rig:get_matrix(headIndex)), {0, 0, -1}) + + if not isfront or not (watchtimer % 300 < 100) then + viewdir = mat4.mul(tsf:get_rot(), {0, 0, -1}) + end + + vec3.mix(curdir, viewdir, 0.2, viewdir) + + headrot = mat4.inverse(mat4.look_at({0,0,0}, viewdir, {0, 1, 0})) + headrot = mat4.mul(mat4.inverse(tsf:get_rot()), headrot) + rig:set_matrix(headIndex, headrot) +end local function follow_waypoints(pathfinding, delta) local pos = tsf:get_pos() - pathfinding.set_target(vec3.add(pos, {math.random(-15, 15), 1, math.random(-15, 15)})) + pathfinding.set_target(vec3.add(pos, + {math.random(-15, 15), math.random(-2, 2), math.random(-15, 15)})) local waypoint = pathfinding.next_waypoint() if not waypoint then return end local speed = props.movement_speed local vel = body:get_vel() - local dir = vec3.sub( + direction = vec3.sub( vec3.add(waypoint, {0.5, 0, 0.5}), {pos[1], math.floor(pos[2]), pos[3]} ) - local upper = dir[2] > 0 - dir[2] = 0.0 - local t = delta * 16.0 - local angle = (vec2.angle({dir[3], dir[1]}) + 180) * t + prev_angle * (1 - t) + local upper = direction[2] > 0 + direction[2] = 0.0 + local t = delta * 6.0 + local angle = (vec2.angle({direction[3], direction[1]}) + 180) * t + prev_angle * (1 - t) tsf:set_rot(mat4.rotate({0, 1, 0}, angle)) prev_angle = angle - vec3.normalize(dir, dir) - move_horizontal(speed, dir, vel) - if body:is_grounded() and upper then + vec3.normalize(direction, direction) + move_horizontal(speed, direction, vel) + if upper and body:is_grounded() then jump(1.0) end end +function is_flight() return flight end + +function set_flight(flag) flight = flag end + function on_physics_update(tps) local delta = (1.0 / tps) - local pid = entity:get_player() - if pid ~= -1 then - process_player_inputs(pid, delta) - else - local pathfinding = entity:get_component("core:pathfinding") - if pathfinding then - follow_waypoints(pathfinding, delta) - end + + update_head() + local pathfinding = entity:get_component("core:pathfinding") + if pathfinding then + follow_waypoints(pathfinding, delta) end + + local grounded = body:is_grounded() + body:set_vdamping(flight) + body:set_gravity_scale({0, flight and 0.0 or props.gravity_scale, 0}) + body:set_linear_damping( + (flight or not grounded) and props.air_damping or props.ground_damping + ) end diff --git a/res/scripts/components/pathfinding.lua b/res/scripts/components/pathfinding.lua index 39ec5af7..797bde9d 100644 --- a/res/scripts/components/pathfinding.lua +++ b/res/scripts/components/pathfinding.lua @@ -41,13 +41,18 @@ function next_waypoint() return route[#route] end -local frameid = 0 +local refresh_internal = 100 +local frameid = math.random(0, refresh_internal) + +function set_refresh_interval(interval) + refresh_internal = interval +end function on_update() if not started then if body:is_grounded() then frameid = frameid + 1 - if target and frameid % 100 == 1 then + if target and (frameid % refresh_internal == 1 or not route) then pathfinding.make_route_async(agent, tsf:get_pos(), target) started = true end diff --git a/res/scripts/components/player.lua b/res/scripts/components/player.lua new file mode 100644 index 00000000..e892d2c8 --- /dev/null +++ b/res/scripts/components/player.lua @@ -0,0 +1,59 @@ +local body = entity.rigidbody +local mob = entity:require_component("core:mob") + +local cheat_speed_mul = 5.0 + +local function process_player_inputs(pid, delta) + if not hud or hud.is_inventory_open() or menu.page ~= "" then + return + end + local cam = cameras.get("core:first-person") + local front = cam:get_front() + local right = cam:get_right() + front[2] = 0.0 + vec3.normalize(front, front) + + local isjump = input.is_active('movement.jump') + local issprint = input.is_active('movement.sprint') + local iscrouch = input.is_active('movement.crouch') + local isforward = input.is_active('movement.forward') + local ischeat = input.is_active('movement.cheat') + local isback = input.is_active('movement.back') + local isleft = input.is_active('movement.left') + local isright = input.is_active('movement.right') + mob.set_flight(player.is_flight(pid)) + body:set_body_type(player.is_noclip(pid) and "kinematic" or "dynamic") + body:set_crouching(iscrouch) + + local vel = body:get_vel() + local speed = ischeat and cheat_speed_mul or 1.0 + + local dir = {0, 0, 0} + + if isforward then vec3.add(dir, front, dir) end + if isback then vec3.sub(dir, front, dir) end + if isright then vec3.add(dir, right, dir) end + if isleft then vec3.sub(dir, right, dir) end + + if vec3.length(dir) > 0.0 then + mob.go(dir, speed, issprint, iscrouch, vel) + end + + if mob.is_flight() then + if isjump then + mob.elevate(speed * 24, delta) + elseif iscrouch then + mob.lower(speed * 24, delta) + end + elseif isjump then + mob.jump() + end +end + +function on_physics_update(tps) + local delta = (1.0 / tps) + local pid = entity:get_player() + if pid ~= -1 then + process_player_inputs(pid, delta) + end +end