diff --git a/res/content/base/scripts/components/player_animator.lua b/res/content/base/scripts/components/player_animator.lua index eddbdb5d..f82927cc 100644 --- a/res/content/base/scripts/components/player_animator.lua +++ b/res/content/base/scripts/components/player_animator.lua @@ -1,11 +1,10 @@ local tsf = entity.transform local body = entity.rigidbody local rig = entity.skeleton +local mob = entity:require_component("core:mob") local itemid = 0 -local headIndex = rig:index("head") local itemIndex = rig:index("item") -local bodyIndex = rig:index("body") local function refresh_model(id) itemid = id @@ -19,9 +18,10 @@ function on_render() 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)) + local rx, _, _ = player.get_rot(pid, pid ~= hud.get_player()) + + local dir = vec2.rotate({0, -1}, -rx) + mob.set_dir({dir[1], 0, dir[2]}) local invid, slotid = player.get_inventory(pid) local id, _ = inventory.get(invid, slotid) diff --git a/res/scripts/components/mob.lua b/res/scripts/components/mob.lua index 8de81ba6..8a156dc9 100644 --- a/res/scripts/components/mob.lua +++ b/res/scripts/components/mob.lua @@ -26,8 +26,7 @@ def_prop("crouch_speed_mul", 0.35) def_prop("flight_speed_mul", 4.0) def_prop("gravity_scale", 1.0) -direction = {0, 0, -1} - +local dir = {0, 0, -1} local flight = false function jump(multiplier) @@ -85,25 +84,24 @@ function go(dir, speed_multiplier, sprint, crouch, vel) 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 function update_head(point) 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 viewdir = vec3.normalize(vec3.sub(point, pos)) + + local dot = vec3.dot(viewdir, dir) + if dot > 0.0 then + dir[1] = dir[1] * 0.8 + viewdir[1] * 0.2 + dir[3] = dir[3] * 0.8 + viewdir[3] * 0.2 + else + viewdir = mat4.mul(tsf:get_rot(), {0, 0, -1}) + end 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})) @@ -111,7 +109,7 @@ local function update_head() rig:set_matrix(headIndex, headrot) end -local function follow_waypoints(pathfinding, delta) +function follow_waypoints(pathfinding) local pos = tsf:get_pos() local waypoint = pathfinding.next_waypoint() if not waypoint then @@ -119,40 +117,76 @@ local function follow_waypoints(pathfinding, delta) end local speed = props.movement_speed local vel = body:get_vel() - direction = vec3.sub( + dir = vec3.sub( vec3.add(waypoint, {0.5, 0, 0.5}), {pos[1], math.floor(pos[2]), pos[3]} ) - 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(direction, direction) - move_horizontal(speed, direction, vel) + local upper = dir[2] > 0 + dir[2] = 0.0 + vec3.normalize(dir, dir) + move_horizontal(speed, dir, vel) if upper and body:is_grounded() then jump(1.0) end end +function set_dir(new_dir) + dir = new_dir +end + function is_flight() return flight end function set_flight(flag) flight = flag end +local prev_angle = 0.0 + +local function normalize_angle(angle) + while angle > 180 do + angle = angle - 360 + end + while angle <= -180 do + angle = angle + 360 + end + return angle +end + +local function angle_delta(a, b) + return normalize_angle(a - b) +end + function on_physics_update(tps) local delta = (1.0 / tps) - 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 ) + + local new_angle = (vec2.angle({dir[3], dir[1]})) % 360 + local angle = prev_angle + + local adelta = angle_delta( + normalize_angle(new_angle), + normalize_angle(prev_angle) + ) + local rotate_speed = entity:get_player() == -1 and 200 or 400 + + if math.abs(adelta) > 5 then + if adelta > 0 then + angle = angle + delta * rotate_speed + else + angle = angle - delta * rotate_speed + end + end + tsf:set_rot(mat4.rotate({0, 1, 0}, angle + 180)) + prev_angle = angle + + if entity:get_player() == -1 then + update_head({player.get_pos(hud.get_player())}) + else + local cam = cameras.get("core:first-person") + update_head(vec3.add({player.get_pos(entity:get_player())}, cam:get_front())) + end end