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, 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 --local player_count = #minetest.get_connected_players() --if player_count == 1 then -- game is in singleplayer mode or there is only one player -- calculate distance between "singleplayer" player and mini crewmate local player = minetest.get_player_by_name("singleplayer") local player_pos = player:get_pos() local mini_crewmate_pos = self.object:get_pos() local crewmate_player_vector = vector.subtract(player_pos, mini_crewmate_pos) --local distance = vector.distance(player_pos, mini_crewmate_pos) local distance = vector.length(crewmate_player_vector) --minetest.chat_send_player("singleplayer", "HSUSS") --else -- game is in multiplayer mode with more than one player -- I will write it later. --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 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 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 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 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 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(-crewmate_player_vector.z, -crewmate_player_vector.x)) else -- look at the player self.object:set_yaw(math.atan2(crewmate_player_vector.z, 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)