404 lines
11 KiB
Lua
404 lines
11 KiB
Lua
function yl_creatures.flash_red(self)
|
|
minetest.after(0.0, function(self)
|
|
self.object:settexturemod("^[colorize:#FF000040")
|
|
minetest.after(0.2, function(self)
|
|
if mobkit.is_alive(self) then
|
|
self.object:settexturemod("")
|
|
end
|
|
end,self)
|
|
end,self)
|
|
end
|
|
|
|
|
|
|
|
|
|
function yl_creatures.on_punch_basic(self, puncher, tool_capabilities, dir)
|
|
local item = puncher:get_wielded_item()
|
|
if mobkit.is_alive(self) then
|
|
|
|
local apply_damage = tool_capabilities.damage_groups.fleshy or 1
|
|
|
|
if self.immune_to then
|
|
for i = 1, #self.immune_to do
|
|
if item:get_name() == self.immune_to[i] then
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
if self.damage_mods then
|
|
for _,table in self.damage_mods do
|
|
if table[1] and table[1] == item:get_name() then
|
|
apply_damage = 0
|
|
if table[2] then
|
|
apply_damage = table[2]
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if self.protected == true and puncher:get_player_name() ~= self.owner then
|
|
return
|
|
else
|
|
|
|
if self.isonground then
|
|
local hvel = vector.multiply(vector.normalize({x=dir.x,y=0,z=dir.z}),4)
|
|
self.object:add_velocity({x=hvel.x,y=2,z=hvel.z})
|
|
end
|
|
if apply_damage and apply_damage < 0 then
|
|
local heal = -apply_damage
|
|
mobkit.heal(self,heal)
|
|
mob_core.make_sound(self, "random")
|
|
end
|
|
if apply_damage and apply_damage > 0 then
|
|
yl_creatures.flash_red(self)
|
|
mobkit.hurt(self,apply_damage)
|
|
mob_core.make_sound(self, "hurt")
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function yl_creatures.pick_up_drops(self, radius, item)
|
|
local pos = mobkit.get_stand_pos(self)
|
|
local objects = minetest.get_objects_inside_radius(pos, radius)
|
|
--minetest.chat_send_all('92')
|
|
if #objects < 1 then return end
|
|
for _, object in ipairs(objects) do
|
|
local ent = object:get_luaentity()
|
|
if ent and ent.name == "__builtin:item" then
|
|
local itemstring = ent.itemstring
|
|
local stack = ItemStack(itemstring)
|
|
local count = stack:get_count()
|
|
--minetest.chat_send_all(dump(ent))
|
|
if item == nil or item == 'any' or ItemStack(itemstring):get_name() == ItemStack(item):get_name() then
|
|
local stored_drops = {} --stored_drops is a table of itemstrings
|
|
local prev_drops = mobkit.recall(self,"stored_drops")
|
|
if prev_drops then
|
|
stored_drops = prev_drops
|
|
end
|
|
table.insert(stored_drops,itemstring)
|
|
|
|
mobkit.remember(self, "stored_drops", stored_drops)
|
|
|
|
object:remove()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
function yl_creatures.find_item_inside_radius(self, radius, item)
|
|
local pos = mobkit.get_stand_pos(self)
|
|
local objects = minetest.get_objects_inside_radius(pos, radius)
|
|
if #objects < 1 then return end
|
|
for _, object in ipairs(objects) do
|
|
local ent = object:get_luaentity()
|
|
if ent and ent.name == "__builtin:item" then
|
|
local itemstring = ent.itemstring
|
|
if item == nil or item == 'any' or ItemStack(itemstring):get_name() == ItemStack(item):get_name() then
|
|
return object
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
function yl_creatures.hq_seek_item(self, prty, itemstring)
|
|
local init = false
|
|
local timer = 2
|
|
local func = function(self)
|
|
local item = yl_creatures.find_item_inside_radius(self, self.view_range, itemstring)
|
|
if not item then return true end
|
|
if not init then
|
|
timer = timer - self.dtime
|
|
|
|
if timer <= 0 or vector.distance(self.object:get_pos(), item:get_pos()) < 8 then
|
|
init = true
|
|
mobkit.animate(self, "run")
|
|
end
|
|
end
|
|
self.status = mobkit.remember(self, "status", "seeking_item")
|
|
if mobkit.is_queue_empty_low(self) and self.isonground then
|
|
local pos = mobkit.get_stand_pos(self)
|
|
local opos = item:get_pos()
|
|
if vector.distance(pos, opos) < self.view_range * 1.1 then
|
|
|
|
mob_core.goto_next_waypoint(self, opos)
|
|
yl_creatures.pick_up_drops(self,0.8,itemstring)
|
|
|
|
else
|
|
|
|
mobkit.lq_idle(self, 1, "stand")
|
|
self.status = mobkit.remember(self, "status", "seeking_item")
|
|
|
|
-- self.object:set_velocity({x = 0, y = 0, z = 0})
|
|
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
mobkit.queue_high(self, func, prty)
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
-- register arrow for shoot attack
|
|
function yl_creatures.register_arrow(name, def)
|
|
|
|
if not name or not def then return end -- errorcheck
|
|
|
|
minetest.register_entity(name, {
|
|
|
|
physical = false,
|
|
visual = def.visual,
|
|
visual_size = def.visual_size,
|
|
textures = def.textures,
|
|
velocity = def.velocity,
|
|
hit_player = def.hit_player,
|
|
hit_node = def.hit_node,
|
|
hit_mob = def.hit_mob,
|
|
hit_object = def.hit_object,
|
|
drop = def.drop or false, -- drops arrow as registered item when true
|
|
collisionbox = def.collisionbox or {-.1, -.1, -.1, .1, .1, .1},
|
|
timer = 0,
|
|
lifetime = def.lifetime or 4.5,
|
|
switch = 0,
|
|
owner_id = def.owner_id,
|
|
rotate = def.rotate,
|
|
automatic_face_movement_dir = def.rotate
|
|
and (def.rotate - (pi / 180)) or false,
|
|
|
|
on_activate = def.on_activate,
|
|
|
|
on_punch = def.on_punch or function(
|
|
self, hitter, tflp, tool_capabilities, dir)
|
|
end,
|
|
|
|
on_step = def.on_step or function(self, dtime)
|
|
|
|
self.timer = self.timer + dtime
|
|
|
|
local pos = self.object:get_pos()
|
|
|
|
if self.switch == 0 or self.timer > self.lifetime then
|
|
|
|
self.object:remove() ; -- print("removed arrow")
|
|
|
|
return
|
|
end
|
|
|
|
-- does arrow have a tail (fireball)
|
|
if def.tail and def.tail == 1 and def.tail_texture then
|
|
|
|
minetest.add_particle({
|
|
pos = pos,
|
|
velocity = {x = 0, y = 0, z = 0},
|
|
acceleration = {x = 0, y = 0, z = 0},
|
|
expirationtime = def.expire or 0.25,
|
|
collisiondetection = false,
|
|
texture = def.tail_texture,
|
|
size = def.tail_size or 5,
|
|
glow = def.glow or 0
|
|
})
|
|
end
|
|
|
|
if self.hit_node then
|
|
|
|
|
|
local node = minetest.get_node(pos) or minetest.registered_nodes['default_dirt']
|
|
node = node.name
|
|
|
|
if minetest.registered_nodes[node].walkable then
|
|
|
|
self:hit_node(pos, node)
|
|
|
|
if self.drop == true then
|
|
|
|
pos.y = pos.y + 1
|
|
|
|
self.lastpos = (self.lastpos or pos)
|
|
|
|
minetest.add_item(self.lastpos,
|
|
self.object:get_luaentity().name)
|
|
end
|
|
|
|
self.object:remove() ; -- print("hit node")
|
|
|
|
return
|
|
end
|
|
end
|
|
|
|
if self.hit_player or self.hit_mob or self.hit_object then
|
|
|
|
for _,player in pairs(
|
|
minetest.get_objects_inside_radius(pos, 1.0)) do
|
|
|
|
if self.hit_player and player:is_player() then
|
|
|
|
self:hit_player(player)
|
|
|
|
self.object:remove() ; -- print("hit player")
|
|
|
|
return
|
|
end
|
|
|
|
local entity = player:get_luaentity()
|
|
|
|
if entity
|
|
and self.hit_mob
|
|
and entity._cmi_is_mob == true
|
|
and tostring(player) ~= self.owner_id
|
|
and entity.name ~= self.object:get_luaentity().name then
|
|
|
|
self:hit_mob(player)
|
|
|
|
self.object:remove()
|
|
minetest.chat_send_all("hit mob")
|
|
|
|
return
|
|
end
|
|
|
|
if entity
|
|
and self.hit_object
|
|
and (not entity._cmi_is_mob)
|
|
and tostring(player) ~= self.owner_id
|
|
and entity.name ~= self.object:get_luaentity().name then
|
|
|
|
self:hit_object(player)
|
|
|
|
self.object:remove()
|
|
minetest.chat_send_all("hit object")
|
|
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
self.lastpos = pos
|
|
end
|
|
})
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function yl_creatures.lq_dumb_shoot(self, t_pos)
|
|
local func = function(self)
|
|
minetest.chat_send_all('shooting')
|
|
local vel = self.object:get_velocity()
|
|
--self.object:set_velocity({x = 0, y = vel.y, z = 0})
|
|
local pos = self.object:get_pos()
|
|
local yaw = self.object:get_yaw()
|
|
|
|
local tyaw = minetest.dir_to_yaw(vector.direction(pos, t_pos))
|
|
if math.abs(tyaw - yaw) > 0.1 then mobkit.turn2yaw(self, tyaw, 4) end
|
|
local dist = vector.distance(t_pos,pos)
|
|
|
|
local p = self.object:get_pos() -- p is for the shooting height position
|
|
p.y = p.y + (self.collisionbox[2] + self.collisionbox[5]) / 2 --here we edit p for the shooting height
|
|
|
|
---------Calculate shoot vector --------
|
|
local s = pos
|
|
s.y = s.y + .5
|
|
t_pos.y = t_pos.y - .5
|
|
|
|
local vec = {x = t_pos.x - s.x, y = t_pos.y - s.y, z = t_pos.z - s.z}
|
|
----------------------------------------
|
|
|
|
if dist > self.view_range then --if target is out of range, then forget it (later, we can add walk to last known target pos)
|
|
mobkit.animate(self, "stand")
|
|
return true
|
|
end
|
|
|
|
local obj = minetest.add_entity(p, self.arrow)
|
|
local ent = obj:get_luaentity()
|
|
local amount = (vec.x * vec.x + vec.y * vec.y + vec.z * vec.z) ^ 0.5
|
|
local v = ent.velocity or 1 -- or set to default
|
|
|
|
ent.switch = 1
|
|
ent.owner_id = tostring(self.object) -- add unique owner id to arrow
|
|
|
|
-- offset makes shoot aim accurate
|
|
vec.y = vec.y + self.shoot_offset
|
|
vec.x = vec.x * (v / amount)
|
|
vec.y = vec.y * (v / amount)
|
|
vec.z = vec.z * (v / amount)
|
|
|
|
obj:set_velocity(vec)
|
|
|
|
return true
|
|
end
|
|
mobkit.queue_low(self, func)
|
|
end
|
|
|
|
|
|
|
|
|
|
--reqd props: arrow, shoot_offset, run_dist, meele_dist
|
|
function yl_creatures.hq_shoot_arrow(self,prty,target)
|
|
|
|
if not self.arrow then return end
|
|
if not (target) then return end --nil checks
|
|
if not minetest.registered_entities[self.arrow] then return end
|
|
|
|
|
|
local func = function(self)
|
|
|
|
|
|
local shoot_pos = self.object:get_pos()
|
|
shoot_pos.y = shoot_pos.y + (self.collisionbox[2] + self.collisionbox[5]) / 2
|
|
local t_pos = target:get_pos()
|
|
|
|
local dist = vector.distance(t_pos,shoot_pos)
|
|
local scan_pos = t_pos
|
|
scan_pos.y = scan_pos.y + 1
|
|
local line_of_sight = minetest.line_of_sight(shoot_pos, scan_pos, .9)
|
|
if line_of_sight and line_of_sight == true then
|
|
|
|
yl_creatures.lq_dumb_shoot(self, t_pos)
|
|
else
|
|
|
|
return true
|
|
end
|
|
|
|
|
|
end
|
|
mobkit.queue_high(self, func, prty)
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
--testing node for getting info about in-world items
|
|
-- minetest.register_node("yl_creatures:block", {
|
|
-- description = "Alien Diamond",
|
|
-- tiles = {"default_dirt.png"},
|
|
-- is_ground_content = true,
|
|
-- groups = {cracky=3, stone=1,oddly_breakable_by_hand = 1},
|
|
-- on_punch = function(pos, node, player, pointed_thing)
|
|
-- local obj = minetest.add_item(pos,'default:dirt')
|
|
-- local ent = obj:get_luaentity()
|
|
-- if ent then
|
|
-- if ent.name and ent.name == "__builtin:item" then
|
|
|
|
-- minetest.chat_send_all(dump(ent.itemstring))
|
|
-- end
|
|
-- end
|
|
-- end,
|
|
-- })
|
|
|