Crafter/mods/mob/init.lua

286 lines
6.6 KiB
Lua

--this is where mobs are defined
--this is going to be used to set an active mob limit
global_mob_table = {}
local path = minetest.get_modpath(minetest.get_current_modname())
dofile(path.."/spawning.lua")
dofile(path.."/items.lua")
--these are helpers to create entities
mob = {}
dofile(path.."/head_code.lua")
dofile(path.."/movement_code.lua")
dofile(path.."/data_handling_code.lua")
mob.initial_properties = {
hp_max = 1,
physical = true,
collide_with_objects = false,
collisionbox = {-0.37, -0.4, -0.37, 0.37, 0.5, 0.37},
visual = "mesh",
visual_size = {x = 3, y = 3},
mesh = "pig.x",
textures = {
"body.png","leg.png","leg.png","leg.png","leg.png"
},
is_visible = true,
pointable = true,
automatic_face_movement_dir = 0.0,
automatic_face_movement_max_rotation_per_sec = 300,
}
mob.hp = 5
mob.speed = 5
mob.mob = true
mob.hostile = false
mob.timer = 0
mob.state = 0
mob.hunger = 200
mob.view_distance = 20
----------------------------------
mob.on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
local hurt = tool_capabilities.damage_groups.fleshy
if not hurt then
hurt = 1
end
local hp = self.object:get_hp()
self.object:set_hp(hp-hurt)
if hp > 1 then
minetest.sound_play("hurt", {object=self.object, gain = 1.0, max_hear_distance = 60,pitch = math.random(80,100)/100})
end
self.hp = hp-hurt
end
mob.on_death = function(self, killer)
local pos = self.object:getpos()
pos.y = pos.y + 0.4
minetest.sound_play("mob_die", {pos = pos, gain = 1.0})
minetest.add_particlespawner({
amount = 40,
time = 0.001,
minpos = pos,
maxpos = pos,
minvel = vector.new(-5,-5,-5),
maxvel = vector.new(5,5,5),
minacc = {x=0, y=0, z=0},
maxacc = {x=0, y=0, z=0},
minexptime = 1.1,
maxexptime = 1.5,
minsize = 1,
maxsize = 2,
collisiondetection = false,
vertical = false,
texture = "smoke.png",
})
local obj = minetest.add_item(pos,"mob:raw_porkchop")
self.child:get_luaentity().parent = nil
end
--repel from players
mob.push = function(self)
local pos = self.object:getpos()
local radius = 1
for _,object in ipairs(minetest.get_objects_inside_radius(pos, radius)) do
if object:is_player() or object:get_luaentity().mob == true then
local player_pos = object:getpos()
pos.y = 0
player_pos.y = 0
local currentvel = self.object:getvelocity()
local vel = vector.subtract(pos, player_pos)
vel = vector.normalize(vel)
local distance = vector.distance(pos,player_pos)
distance = (radius-distance)*10
vel = vector.multiply(vel,distance)
local acceleration = vector.new(vel.x-currentvel.x,0,vel.z-currentvel.z)
self.object:add_velocity(acceleration)
acceleration = vector.multiply(acceleration, 5)
object:add_player_velocity(acceleration)
end
end
end
--makes the mob swim
mob.swim = function(self)
local pos = self.object:getpos()
pos.y = pos.y + 0.7
local node = minetest.get_node(pos).name
local vel = self.object:getvelocity()
local goal = 3
local acceleration = vector.new(0,goal-vel.y,0)
self.swimming = false
if node == "main:water" or node =="main:waterflow" then
self.swimming = true
self.object:add_velocity(acceleration)
end
end
--sets the mob animation and speed
mob.set_animation = function(self)
local distance = vector.distance(vector.new(0,0,0), self.object:getvelocity())
self.object:set_animation_frame_speed(distance*5)
end
mob.look_around = function(self)
local pos = self.object:get_pos()
--this is where the mob is actually looking
local eye_ray = self.raycast_look(self,dtime)
--this is below where the mob is pointed, checks if ledge
--[[ --work on this later
local ledge_ray = self.look_below(self)
local is_a_drop = true
--check if there's a drop
if ledge_ray then
for pointed_thing in ledge_ray do
if pointed_thing then
local pos2 = pointed_thing.under
local distance = math.floor(vector.subtract(pos2,pos).y-self.object:get_properties().collisionbox[2]+0.5+0.5)
if distance >= -3 then
is_a_drop = false
end
end
end
end
--turn around
if is_a_drop == true then
self.direction = vector.multiply(self.direction, -1)
print("turning around")
end
]]--
--a mob will check if it needs to jump
if eye_ray then
for pointed_thing in eye_ray do
local pos = self.object:get_pos()
local pos2 = pointed_thing.under
local walkable = minetest.registered_nodes[minetest.get_node(pos2).name].walkable
if walkable then
if vector.distance(pos,pos2) < 1 then
self.jump(self)
break
end
end
end
end
--STARE O_O
--and follow!
local player_found = false
for _,object in ipairs(minetest.get_objects_inside_radius(pos, 6)) do
if object:is_player() and player_found == false then
--print("test")
player_found = true
--look at player's camera
local pos2 = object:get_pos()
pos2.y = pos2.y + 1.625
self.move_head(self,pos2)
self.direction = vector.direction(pos,pos2)
local distance = vector.distance(pos,pos2)-2
if distance < 0 then
distance = 0
end
self.speed = distance
end
end
--stare straight if not found
if player_found == false then
self.move_head(self,nil)
end
end
--this is the info on the mob
mob.debug_nametag = function(self,dtime)
--we're doing this to the child because the nametage breaks the
--animation on the mob's body
if self.child then
--we add in items we want to see in this list
local debug_items = {"hunger","timer","yaw"}
local text = ""
for _,item in pairs(debug_items) do
if self[item] then
text = text..item..": "..self[item].."\n"
end
end
self.child:set_nametag_attributes({
color = "white",
text = text
})
end
end
--this depletes the mobs hunger
mob.do_hunger = function(self,dtime)
self.hunger = self.hunger - dtime
end
--this sets the state of the mob
mob.set_state = function(self,dtime)
self.do_hunger(self,dtime)
end
mob.on_step = function(self, dtime)
self.set_state(self,dtime)
self.move(self,dtime)
self.set_animation(self)
self.look_around(self)
mob.debug_nametag(self,dtime)
end
minetest.register_entity("mob:pig", mob)
------------------------------------------------------------------------the head
local head = {}
head.initial_properties = {
hp_max = 1,
physical = false,
collide_with_objects = false,
collisionbox = {0, 0, 0, 0, 0, 0},
visual = "mesh",
visual_size = {x = 1.1, y = 1.1},
mesh = "pig_head.x",
textures = {
"head.png","nose.png"
},
is_visible = true,
pointable = false,
--automatic_face_movement_dir = 0.0,
--automatic_face_movement_max_rotation_per_sec = 600,
}
--remove the head if no body
head.on_step = function(self, dtime)
if self.parent == nil then
self.object:remove()
end
end
minetest.register_entity("mob:head", head)