SussyCraft/mods/amogus_entities/entities/mini_crewmate_entity.lua

291 lines
11 KiB
Lua

local entity = {
physical = true,
collisionbox = {-0.25, 0, -0.25, 0.25, 0.5, 0.25},
visual = "mesh",
visual_size = {x=5, y=5, z=5},
mesh = "amogus_entity.obj",
textures = {"amogus_entity.png"},
on_rightclick = function(self, clicker)
minetest.chat_send_player(clicker:get_player_name(), "SO SUSSY!")
minetest.sound_play("amogus_sound", {
pos = self.object:get_pos(),
gain = 1.0,
max_hear_distance = 5,
pitch = 2
})
end,
-- mini crewmate config --
walk_acceleration_speed = 0.05, -- acceleration speed when no panic, no stress
run_acceleration_speed = 0.2, -- acceleration speed when chasing player
run_away_acceleration_speed = 0.4, -- acceleration speed when running away from player
rotation_acceleration_speed = 0.5, -- self explainatory
gravity = 9.81, -- m/s^2
jump_force = 10, -- self explainatory
friction = 0.8, -- friction (0.0 - no friction like perfectly smooth ice | 1.0 - full friction and can't even move)
rotation_friction = 0.9, -- the same but for rotation
largest_distance_to_find_player = 6, -- largest distance to find player
smallest_distance_to_lost_player = 10, -- smallest distance to lost player
largest_distance_to_stand_still = 3, -- largest distance to stand still next to the player
smallest_distance_to_stop_run_away = 30, -- smallest distance to stop run away from player
--------------------------
block_lastly_in_front = false,
rotation_velocity = 0,
rotation_direction = nil,
sound_pitch = nil,
sound_propability = nil,
-- player detection variables
player = nil,
player_pos = nil,
mini_crewmate_pos = nil,
crewmate_player_vector = nil,
distance = nil,
current_distance = nil,
current_crewmate_player_vector = nil,
mode = 0, -- | 0 - stand still | 1 - walk | 2 - chase | 3 - run away | 4 - rest mode |
on_activate = function(self, staticdata)
self.object:set_yaw(math.random() * 2 * math.pi)
self.rotation_direction = math.random(-1, 1)
end,
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
self.mode = 3
end,
on_step = function(self, dtime)
-- play amogus sound randomly with different pitch depending on situation
if self.mode == 0 or self.mode == 1 then -- stand still or walk
sound_pitch = 1.8
sound_propability = 100
elseif self.mode == 2 then -- chase
sound_pitch = 2.5
sound_propability = 50
elseif self.mode == 3 then -- run away
sound_pitch = 3
sound_propability = 10
else -- rest mode (4)
sound_pitch = 2
sound_propability = 300
end
if math.random(sound_propability) == 1 then
minetest.sound_play("amogus_sound", {
pos = self.object:get_pos(),
gain = 1.0,
max_hear_distance = 50,
pitch = sound_pitch
})
end
-- if on singpleplayer mode or only one player is connected, calculate distance between player and mini crewmate
if minetest.is_singleplayer() or #minetest.get_connected_players() == 1 then
minetest.chat_send_all("singleplayer or multiplayer with only one player")
-- get first player
self.player = minetest.get_connected_players()[1]
self.player_pos = self.player:get_pos()
self.mini_crewmate_pos = self.object:get_pos()
self.crewmate_player_vector = vector.subtract(self.player_pos, self.mini_crewmate_pos)
self.distance = vector.length(self.crewmate_player_vector)
-- if on multiplayer mode, calculate distance between nearest player and mini crewmate
else
minetest.chat_send_all("multiplayer")
self.player = minetest.get_connected_players()
self.distance = nil
self.crewmate_player_vector = nil
self.mini_crewmate_pos = self.object:get_pos()
-- iterate over all players
for i = 1, #self.player do
minetest.chat_send_all("player " .. i)
self.player_pos = self.player[i]:get_pos()
--self.crewmate_player_vector = vector.subtract(self.player_pos, self.mini_crewmate_pos)
self.current_crewmate_player_vector = vector.subtract(self.player_pos, self.mini_crewmate_pos)
self.current_distance = vector.length(self.current_crewmate_player_vector)
-- if distance is nil or current_distance is smaller than distance, set distance to current_distance
if self.distance == nil or self.current_distance < self.distance then
self.distance = self.current_distance
self.crewmate_player_vector = self.current_crewmate_player_vector
end
end
end
-- if mode is 0 or 1 (stand still or walk) and distance is smaller or equal to largest_distance_to_find_player, set mode to 2 (chase)
if (self.mode == 0 or self.mode == 1) and self.distance <= self.largest_distance_to_find_player then
self.mode = 2
-- elseif mode is 2 (chase)
elseif self.mode == 2 then
-- if distance is greater or equal to smallest_distance_to_lost_player, set mode to 0 (stand still)
if self.distance >= self.smallest_distance_to_lost_player then
self.mode = 0
-- elif distance is smaller or equal to largest_distance_to_stand_still, set mode to 4 (rest mode)
elseif self.distance <= self.largest_distance_to_stand_still then
self.mode = 4
end
-- if mode is 4 (rest mode) and distance is greater than largest_distance_to_stand_still, set mode to 2 (chase)
elseif self.mode == 4 and self.distance > self.largest_distance_to_stand_still then
self.mode = 2
-- running away mode
elseif self.mode == 3 then
-- if distance is greater than smallest_distance_to_lost_player, set mode to 0 (stand still)
if self.distance > self.smallest_distance_to_stop_run_away then
self.mode = 1
else
-- jump if on ground
local pos = self.object:get_pos()
pos.y = pos.y - 0.2
local bnode = minetest.get_node(pos)
if bnode.name ~= "air" then
local vel = self.object:get_velocity()
vel.y = vel.y + self.jump_force
self.object:set_velocity(vel)
end
end
end
-- if if not performing an action related to the player
if (self.mode == 0 or self.mode == 1) then
-- make mini crewmate sometimes stand still and sometimes walk
if math.random(100) == 1 then
if self.mode == 0 then
self.mode = 1
else
self.mode = 0
end
end
-- some chance of chaning rotation_direction to random value
if math.random(10) == 1 then
--self.rotation_direction = math.random(-1, 1)
local rand = math.random()
if rand < 0.2 then
self.rotation_direction = 1
elseif rand < 0.4 then
self.rotation_direction = -1
else
self.rotation_direction = 0
end
end
-- update rotation_velocity
self.rotation_velocity = self.rotation_velocity + self.rotation_direction * self.rotation_acceleration_speed * dtime
-- update rotation
self.object:set_yaw(self.object:get_yaw() + self.rotation_velocity * dtime)
-- apply rotation_friction
self.rotation_velocity = self.rotation_velocity * (1 - self.rotation_friction * dtime)
else -- else performing an action related to the player
self.rotation_velocity = 0;
-- if mode is 3 (run away) set rotation so mini crewmate is facing either at the player or away from the player depending on situation
if self.mode == 3 then
-- look away from the player
self.object:set_yaw(math.atan2(-self.crewmate_player_vector.z, -self.crewmate_player_vector.x))
else
-- look at the player
self.object:set_yaw(math.atan2(self.crewmate_player_vector.z, self.crewmate_player_vector.x))
end
end
-- perform calculations on direction
local dir = self.object:get_yaw()
local dir_cos = math.cos(dir)
local dir_sin = math.sin(dir)
-- if not standing still and not in rest mode
if self.mode ~= 0 and self.mode ~= 4 then
-- make mini crewmate walk or run
local vel = self.object:get_velocity()
-- if walking
if self.mode == 1 then
vel.x = vel.x + dir_cos * self.walk_acceleration_speed
vel.z = vel.z + dir_sin * self.walk_acceleration_speed
-- elif chasing
elseif self.mode == 2 then
vel.x = vel.x + dir_cos * self.run_acceleration_speed
vel.z = vel.z + dir_sin * self.run_acceleration_speed
else -- else running away (3)
vel.x = vel.x + dir_cos * self.run_away_acceleration_speed
vel.z = vel.z + dir_sin * self.run_away_acceleration_speed
end
self.object:set_velocity(vel)
end
-- Make it also jump when some block is in front of it
local pos = self.object:get_pos()
pos.x = pos.x + dir_cos
pos.z = pos.z + dir_sin
local bnode = minetest.get_node(pos)
if bnode.name == "air" or bnode.name == "amogus_blocks:water" then
self.block_lastly_in_front = false
else
if self.block_lastly_in_front == false then
self.block_lastly_in_front = true
local vel = self.object:get_velocity()
vel.y = vel.y + self.jump_force
self.object:set_velocity(vel)
end
end
local vel = self.object:get_velocity()
-- change velocity by gravity
vel.y = vel.y - self.gravity * dtime * 2
-- change velocity by friction
vel.x = vel.x * (1 - self.friction * dtime)
vel.z = vel.z * (1 - self.friction * dtime)
self.object:set_velocity(vel)
end
}
minetest.register_entity("amogus_entities:mini_crewmate", entity)