better 0.4.16 comatibility and new general attack function added

This commit is contained in:
TenPlus1 2018-06-27 09:44:00 +01:00
parent 7ed80b6a89
commit 21c52c0a87
2 changed files with 98 additions and 130 deletions

220
api.lua
View File

@ -3,7 +3,7 @@
mobs = {}
mobs.mod = "redo"
mobs.version = "20180617"
mobs.version = "20180627"
-- Intllib
@ -127,15 +127,15 @@ local set_velocity = function(self, v)
-- do not move if mob has been ordered to stay
if self.order == "stand" then
self.object:setvelocity({x = 0, y = 0, z = 0})
self.object:set_velocity({x = 0, y = 0, z = 0})
return
end
local yaw = (self.object:get_yaw() or 0) + self.rotate
self.object:setvelocity({
self.object:set_velocity({
x = sin(yaw) * -v,
y = self.object:getvelocity().y,
y = self.object:get_velocity().y,
z = cos(yaw) * v
})
end
@ -144,7 +144,7 @@ end
-- calculate mob velocity
local get_velocity = function(self)
local v = self.object:getvelocity()
local v = self.object:get_velocity()
return (v.x * v.x + v.z * v.z) ^ 0.5
end
@ -411,7 +411,7 @@ local item_drop = function(self, cooked)
if obj and obj:get_luaentity() then
obj:setvelocity({
obj:set_velocity({
x = random(-10, 10) / 9,
y = 6,
z = random(-10, 10) / 9,
@ -639,7 +639,7 @@ local do_env_damage = function(self)
]]
-- don't fall when on ignore, just stand still
if self.standing_in == "ignore" then
self.object:setvelocity({x = 0, y = 0, z = 0})
self.object:set_velocity({x = 0, y = 0, z = 0})
end
local nodef = minetest.registered_nodes[self.standing_in]
@ -719,7 +719,7 @@ local do_jump = function(self)
-- something stopping us while moving?
if self.state ~= "stand"
and get_velocity(self) > 0.5
and self.object:getvelocity().y ~= 0 then
and self.object:get_velocity().y ~= 0 then
return false
end
@ -761,13 +761,13 @@ local do_jump = function(self)
if not nod.name:find("fence")
and not nod.name:find("gate") then
local v = self.object:getvelocity()
local v = self.object:get_velocity()
v.y = self.jump_height
set_animation(self, "jump") -- only when defined
self.object:setvelocity(v)
self.object:set_velocity(v)
-- when in air move forward
minetest.after(0.3, function(self, v)
@ -879,7 +879,7 @@ local breed = function(self)
self.on_grown(self)
else
-- jump when fully grown so as not to fall into ground
self.object:setvelocity({
self.object:set_velocity({
x = 0,
y = self.jump_height,
z = 0
@ -1027,7 +1027,7 @@ local replace = function(self, pos)
or not self.replace_rate
or not self.replace_what
or self.child == true
or self.object:getvelocity().y ~= 0
or self.object:get_velocity().y ~= 0
or random(1, self.replace_rate) > 1 then
return
end
@ -1283,7 +1283,7 @@ local smart_mobs = function(self, s, p, dist, dtime)
end
s.y = s.y - sheight
self.object:setpos({x = s.x, y = s.y + 2, z = s.z})
self.object:set_pos({x = s.x, y = s.y + 2, z = s.z})
else -- dig 2 blocks to make door toward player direction
@ -1366,114 +1366,81 @@ local specific_attack = function(list, what)
end
-- monster find someone to attack
local monster_attack = function(self)
-- general attack function for all mobs ==========
local general_attack = function(self)
if self.type ~= "monster"
or not damage_enabled
or creative
-- return if already attacking, passive or docile during day
if self.passive
or self.state == "attack"
or day_docile(self) then
return
end
local s = self.object:get_pos()
local p, sp, dist
local player, obj, min_player
local type, name = "", ""
local min_dist = self.view_range + 1
local objs = minetest.get_objects_inside_radius(s, self.view_range)
-- remove entities we aren't interested in
for n = 1, #objs do
local ent = objs[n]:get_luaentity()
-- are we a player?
if objs[n]:is_player() then
if mobs.invis[ objs[n]:get_player_name() ] then
type = ""
else
player = objs[n]
type = "player"
name = "player"
-- if player invisible or mob not setup to attack then remove from list
if self.attack_players == false
or (self.owner and self.type ~= "monster")
or mobs.invis[objs[n]:get_player_name()]
or not specific_attack(self.specific_attack, "player") then
objs[n] = nil
--print("- pla", n)
end
-- or are we a mob?
elseif ent and ent._cmi_is_mob then
-- remove mobs not to attack
if self.name == ent.name
or (not self.attack_animals and ent.type == "animal")
or (not self.attack_monsters and ent.type == "monster")
or (not self.attack_npcs and ent.type == "npc")
or not specific_attack(self.specific_attack, ent.name) then
objs[n] = nil
--print("- mob", n, self.name, ent.name)
end
-- remove all other entities
else
obj = objs[n]:get_luaentity()
if obj then
player = obj.object
type = obj.type
name = obj.name or ""
end
end
-- find specific mob to attack, failing that attack player/npc/animal
if specific_attack(self.specific_attack, name)
and (type == "player" or type == "npc"
or (type == "animal" and self.attack_animals == true)) then
p = player:get_pos()
sp = s
dist = get_distance(p, s)
-- aim higher to make looking up hills more realistic
p.y = p.y + 1
sp.y = sp.y + 1
-- choose closest player to attack
if dist < min_dist
and line_of_sight(self, sp, p, 2) == true then
min_dist = dist
min_player = player
end
--print(" -obj", n)
objs[n] = nil
end
end
-- attack player
if min_player then
do_attack(self, min_player)
end
end
-- npc, find closest monster to attack
local npc_attack = function(self)
if self.type ~= "npc"
or not self.attacks_monsters
or self.state == "attack" then
return
end
local p, sp, obj, min_player, dist
local s = self.object:get_pos()
local p, sp, dist, min_player
local min_dist = self.view_range + 1
local objs = minetest.get_objects_inside_radius(s, self.view_range)
for n = 1, #objs do
-- go through remaining entities and select closest
for _,player in pairs(objs) do
obj = objs[n]:get_luaentity()
p = player:get_pos()
sp = s
if obj and obj.type == "monster" then
dist = get_distance(p, s)
p = obj.object:get_pos()
sp = s
-- aim higher to make looking up hills more realistic
p.y = p.y + 1
sp.y = sp.y + 1
dist = get_distance(p, s)
-- aim higher to make looking up hills more realistic
p.y = p.y + 1
sp.y = sp.y + 1
if dist < min_dist
and line_of_sight(self, sp, p, 2) == true then
min_dist = dist
min_player = obj.object
end
-- choose closest player to attack that isnt self
if dist ~= 0
and dist < min_dist
and line_of_sight(self, sp, p, 2) == true then
min_dist = dist
min_player = player
end
end
-- attack closest player or mob
if min_player then
do_attack(self, min_player)
end
@ -1508,9 +1475,8 @@ local runaway_from = function(self)
end
local s = self.object:get_pos()
local p, sp, dist
local player, obj, min_player
local type, name = "", ""
local p, sp, dist, pname
local player, obj, min_player, name
local min_dist = self.view_range + 1
local objs = minetest.get_objects_inside_radius(s, self.view_range)
@ -1518,13 +1484,14 @@ local runaway_from = function(self)
if objs[n]:is_player() then
if mobs.invis[ objs[n]:get_player_name() ]
or self.owner == objs[n]:get_player_name() then
pname = objs[n]:get_player_name()
type = ""
if mobs.invis[pname]
or self.owner == pname then
name = ""
else
player = objs[n]
type = "player"
name = "player"
end
else
@ -1532,7 +1499,6 @@ local runaway_from = function(self)
if obj then
player = obj.object
type = obj.type
name = obj.name or ""
end
end
@ -1550,8 +1516,7 @@ local runaway_from = function(self)
dist = get_distance(p, s)
-- choose closest player/mpb to runaway from
-- choose closest player/mob to runaway from
if dist < min_dist
and line_of_sight(self, sp, p, 2) == true then
min_dist = dist
@ -1688,7 +1653,7 @@ local follow_flop = function(self)
if not flight_check(self, s) then
self.state = "flop"
self.object:setvelocity({x = 0, y = -5, z = 0})
self.object:set_velocity({x = 0, y = -5, z = 0})
set_animation(self, "stand")
@ -1787,10 +1752,10 @@ local do_states = function(self, dtime)
--[[ fly up/down randomly for flying mobs
if self.fly and random(1, 100) <= self.walk_chance then
local v = self.object:getvelocity()
local v = self.object:get_velocity()
local ud = random(-1, 2) / 9
self.object:setvelocity({x = v.x, y = ud, z = v.z})
self.object:set_velocity({x = v.x, y = ud, z = v.z})
end--]]
end
end
@ -2057,13 +2022,13 @@ local do_states = function(self, dtime)
local me_y = floor(p1.y)
local p2 = p
local p_y = floor(p2.y + 1)
local v = self.object:getvelocity()
local v = self.object:get_velocity()
if flight_check(self, s) then
if me_y < p_y then
self.object:setvelocity({
self.object:set_velocity({
x = v.x,
y = 1 * self.walk_velocity,
z = v.z
@ -2071,7 +2036,7 @@ local do_states = function(self, dtime)
elseif me_y > p_y then
self.object:setvelocity({
self.object:set_velocity({
x = v.x,
y = -1 * self.walk_velocity,
z = v.z
@ -2080,7 +2045,7 @@ local do_states = function(self, dtime)
else
if me_y < p_y then
self.object:setvelocity({
self.object:set_velocity({
x = v.x,
y = 0.01,
z = v.z
@ -2088,7 +2053,7 @@ local do_states = function(self, dtime)
elseif me_y > p_y then
self.object:setvelocity({
self.object:set_velocity({
x = v.x,
y = -0.01,
z = v.z
@ -2272,7 +2237,7 @@ local do_states = function(self, dtime)
vec.y = vec.y * (v / amount)
vec.z = vec.z * (v / amount)
obj:setvelocity(vec)
obj:set_velocity(vec)
end
end
end
@ -2288,12 +2253,12 @@ local falling = function(self, pos)
end
-- floating in water (or falling)
local v = self.object:getvelocity()
local v = self.object:get_velocity()
if v.y > 0 then
-- apply gravity when moving up
self.object:setacceleration({
self.object:set_acceleration({
x = 0,
y = -10,
z = 0
@ -2302,14 +2267,14 @@ local falling = function(self, pos)
elseif v.y <= 0 and v.y > self.fall_speed then
-- fall downwards at set speed
self.object:setacceleration({
self.object:set_acceleration({
x = 0,
y = self.fall_speed,
z = 0
})
else
-- stop accelerating once max fall speed hit
self.object:setacceleration({x = 0, y = 0, z = 0})
self.object:set_acceleration({x = 0, y = 0, z = 0})
end
-- in water then float up
@ -2317,7 +2282,7 @@ local falling = function(self, pos)
if self.floats == 1 then
self.object:setacceleration({
self.object:set_acceleration({
x = 0,
y = -self.fall_speed / (max(1, v.y) ^ 8), -- 8 was 2
z = 0
@ -2327,7 +2292,7 @@ local falling = function(self, pos)
-- fall damage onto solid ground
if self.fall_damage == 1
and self.object:getvelocity().y == 0 then
and self.object:get_velocity().y == 0 then
local d = (self.old_y or 0) - self.object:get_pos().y
@ -2523,7 +2488,7 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir)
if self.knock_back
and tflp >= punch_interval then
local v = self.object:getvelocity()
local v = self.object:get_velocity()
local r = 1.4 - min(punch_interval, 1.4)
local kb = r * 5
local up = 2
@ -2544,7 +2509,7 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir)
kb = kb * 1.5
end
self.object:setvelocity({
self.object:set_velocity({
x = dir.x * kb,
y = up,
z = dir.z * kb
@ -2583,6 +2548,7 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir)
if self.passive == false
and self.state ~= "flop"
and self.child == false
and self.attack_players == true
and hitter:get_player_name() ~= self.owner
and not mobs.invis[ name ] then
@ -2598,7 +2564,7 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir)
obj = objs[n]:get_luaentity()
if obj then
if obj and obj._cmi_is_mob then
-- only alert members of same mob
if obj.group_attack == true
@ -2975,9 +2941,7 @@ local mob_step = function(self, dtime)
replace(self, pos)
end
monster_attack(self)
npc_attack(self)
general_attack(self)
breed(self)
@ -3058,8 +3022,6 @@ minetest.register_entity(name, {
follow = def.follow,
jump = def.jump ~= false,
walk_chance = def.walk_chance or 50,
attacks_monsters = def.attacks_monsters or false,
group_attack = def.group_attack or false,
passive = def.passive or false,
knock_back = def.knock_back ~= false,
blood_amount = def.blood_amount or 5,
@ -3102,7 +3064,11 @@ minetest.register_entity(name, {
dogshoot_count = 0,
dogshoot_count_max = def.dogshoot_count_max or 5,
dogshoot_count2_max = def.dogshoot_count2_max or (def.dogshoot_count_max or 5),
group_attack = def.group_attack or false,
attack_monsters = def.attacks_monsters or def.attack_monsters or false,
attack_animals = def.attack_animals or false,
attack_players = def.attack_players ~= false,
attack_npcs = def.attack_npcs ~= false,
specific_attack = def.specific_attack,
runaway_from = def.runaway_from,
owner_loyal = def.owner_loyal,

View File

@ -71,9 +71,11 @@ functions needed for the mob to work properly which contains the following:
'docile_by_day' when true has mobs wandering around during daylight
hours and only attacking player at night or when
provoked.
'attacks_monsters' when true has npc's attacking monsters or not.
'attack_animals' when true will have monsters attacking animals.
'owner_loyal' when true will have tamed mobs attack anything player
'attack_monsters' when true mob will attack monsters.
'attack_animals' when true mob will attack animals.
'attack_npcs' when true mob will attack npcs within range.
'attack_players' when true mob will attack players nearby.
'owner_loyal' when true non-docile tamed mobs attack anything player
punches when nearby.
'group_attack' when true has same mob type grouping together to attack
offender.