Tweaked code

This commit is contained in:
TenPlus1 2017-01-05 19:20:37 +00:00
parent 3fb24110bc
commit 093285bec9
1 changed files with 204 additions and 248 deletions

452
api.lua
View File

@ -1,9 +1,10 @@
-- Mobs Api (29th December 2016)
-- Mobs Api (5th January 2017)
mobs = {}
mobs.mod = "redo"
-- Intllib
local S
if minetest.get_modpath("intllib") then
@ -26,12 +27,14 @@ else
end
mobs.intllib = S
-- Invisibility mod check
mobs.invis = {}
if rawget(_G, "invisibility") then
mobs.invis = invisibility
end
-- Load settings
local damage_enabled = minetest.setting_getbool("enable_damage")
local peaceful_only = minetest.setting_getbool("only_peaceful_mobs")
@ -75,24 +78,34 @@ local atan = function(x)
end
local atan2 = math.atan2
do_attack = function(self, player)
if self.state ~= "attack" then
mob_sound = function(self, sound)
if random(0,100) < 90
and self.sounds.war_cry then
minetest.sound_play(self.sounds.war_cry, {
object = self.object,
max_hear_distance = self.sounds.distance
})
end
self.state = "attack"
self.attack = player
if sound then
minetest.sound_play(sound, {
object = self.object,
gain = 1.0,
max_hear_distance = self.sounds.distance
})
end
end
do_attack = function(self, player)
if self.state == "attack" then
return
end
self.attack = player
self.state = "attack"
if random(0, 100) < 90 then
mob_sound(self, self.sounds.war_cry)
end
end
set_velocity = function(self, v)
local yaw = self.object:getyaw() + self.rotate or 0
@ -104,6 +117,7 @@ set_velocity = function(self, v)
})
end
get_velocity = function(self)
local v = self.object:getvelocity()
@ -111,6 +125,21 @@ get_velocity = function(self)
return (v.x * v.x + v.z * v.z) ^ 0.5
end
set_anim = function(self, anim_start, anim_end, anim_speed, anim_name)
if not anim_start or not anim_end then
return
end
self.object:set_animation(
{x = anim_start, y = anim_end},
anim_speed or 15, 0)
self.animation.current = anim_name
end
set_animation = function(self, type)
if not self.animation then
@ -119,105 +148,58 @@ set_animation = function(self, type)
self.animation.current = self.animation.current or ""
self.animation.speed_normal = self.animation.speed_normal or 15
if type == "stand" and self.animation.current ~= "stand" then
if type == "stand"
and self.animation.current ~= "stand" then
set_anim(self,
self.animation.stand_start,
self.animation.stand_end,
self.animation.speed_stand, "stand")
if self.animation.stand_start
and self.animation.stand_end then
elseif type == "walk" and self.animation.current ~= "walk" then
self.object:set_animation({
x = self.animation.stand_start,
y = self.animation.stand_end},
(self.animation.speed_stand or self.animation.speed_normal), 0)
set_anim(self,
self.animation.walk_start,
self.animation.walk_end,
self.animation.speed_walk, "walk")
self.animation.current = "stand"
end
elseif type == "run" and self.animation.current ~= "run" then
elseif type == "walk"
and self.animation.current ~= "walk" then
set_anim(self,
self.animation.run_start,
self.animation.run_end,
self.animation.speed_run, "run")
if self.animation.walk_start
and self.animation.walk_end then
elseif type == "punch" and self.animation.current ~= "punch" then
self.object:set_animation({
x = self.animation.walk_start,
y = self.animation.walk_end},
(self.animation.speed_walk or self.animation.speed_normal), 0)
set_anim(self,
self.animation.punch_start,
self.animation.punch_end,
self.animation.speed_punch, "punch")
self.animation.current = "walk"
end
elseif type == "punch2" and self.animation.current ~= "punch2" then
elseif type == "run"
and self.animation.current ~= "run" then
set_anim(self,
self.animation.punch2_start,
self.animation.punch2_end,
self.animation.speed_punch2, "punch2")
if self.animation.run_start
and self.animation.run_end then
elseif type == "shoot" and self.animation.current ~= "shoot" then
self.object:set_animation({
x = self.animation.run_start,
y = self.animation.run_end},
(self.animation.speed_run or self.animation.speed_normal), 0)
set_anim(self,
self.animation.shoot_start,
self.animation.shoot_end,
self.animation.speed_shoot, "shoot")
self.animation.current = "run"
end
elseif type == "die" and self.animation.current ~= "die" then
elseif type == "punch"
and self.animation.current ~= "punch" then
if self.animation.punch_start
and self.animation.punch_end then
self.object:set_animation({
x = self.animation.punch_start,
y = self.animation.punch_end},
(self.animation.speed_punch or self.animation.speed_normal), 0)
self.animation.current = "punch"
end
elseif type == "punch2"
and self.animation.current ~= "punch2" then
if self.animation.punch2_start
and self.animation.punch2_end then
self.object:set_animation({
x = self.animation.punch2_start,
y = self.animation.punch2_end},
(self.animation.speed_punch2 or self.animation.speed_normal), 0)
self.animation.current = "punch2"
end
elseif type == "shoot"
and self.animation.current ~= "shoot" then
if self.animation.shoot_start
and self.animation.shoot_end then
self.object:set_animation({
x = self.animation.shoot_start,
y = self.animation.shoot_end},
(self.animation.speed_shoot or self.animation.speed_normal), 0)
self.animation.current = "shoot"
end
elseif type == "die"
and self.animation.current ~= "die" then
if self.animation.die_start
and self.animation.die_end then
self.object:set_animation({
x = self.animation.die_start,
y = self.animation.die_end},
(self.animation.speed_die or self.animation.speed_normal), 0)
self.animation.current = "die"
end
set_anim(self,
self.animation.die_start,
self.animation.die_end,
self.animation.speed_die, "die")
end
end
-- check line of sight for walkers and swimmers alike
function line_of_sight_water(self, pos1, pos2, stepsize)
@ -257,6 +239,7 @@ function line_of_sight_water(self, pos1, pos2, stepsize)
end
-- particle effects
function effect(pos, amount, texture, min_size, max_size, radius, gravity)
@ -282,6 +265,7 @@ function effect(pos, amount, texture, min_size, max_size, radius, gravity)
})
end
-- update nametag colour
function update_tag(self)
@ -307,6 +291,7 @@ function update_tag(self)
end
-- check if mob is dead or only hurt
function check_for_death(self)
@ -320,14 +305,7 @@ function check_for_death(self)
-- still got some health? play hurt sound
if self.health > 0 then
if self.sounds.damage then
minetest.sound_play(self.sounds.damage, {
object = self.object,
gain = 1.0,
max_hear_distance = self.sounds.distance
})
end
mob_sound(self, self.sounds.damage)
-- make sure health isn't higher than max
if self.health > self.hp_max then
@ -338,13 +316,15 @@ function check_for_death(self)
if not self.nametag2 then
self.nametag2 = self.nametag or ""
end
if show_health then
self.htimer = 2
self.nametag = "health: " .. self.health .. " of " .. self.hp_max
if show_health then
self.htimer = 2
self.nametag = "health: " .. self.health .. " of " .. self.hp_max
update_tag(self)
end
update_tag(self)
end
return false
end
@ -371,15 +351,7 @@ end
end
end
-- play death sound
if self.sounds.death then
minetest.sound_play(self.sounds.death, {
object = self.object,
gain = 1.0,
max_hear_distance = self.sounds.distance
})
end
mob_sound(self, self.sounds.death)
-- execute custom death function
if self.on_die then
@ -416,6 +388,7 @@ end
return true
end
-- check if within physical map limits (-30911 to 30927)
function within_limits(pos, radius)
@ -431,6 +404,7 @@ function within_limits(pos, radius)
return false -- beyond limits
end
-- is mob facing a cliff
local function is_at_cliff(self)
@ -455,6 +429,7 @@ local function is_at_cliff(self)
return false
end
-- get node but use fallback for nil or unknown
local function node_ok(pos, fallback)
@ -473,6 +448,7 @@ local function node_ok(pos, fallback)
return minetest.registered_nodes[fallback]
end
-- environmental damage (water, lava, fire, light)
do_env_damage = function(self)
@ -554,6 +530,7 @@ do_env_damage = function(self)
check_for_death(self)
end
-- jump if facing a solid node (not fences or gates)
do_jump = function(self)
@ -605,17 +582,11 @@ do_jump = function(self)
self.object:setvelocity(v)
if self.sounds.jump then
minetest.sound_play(self.sounds.jump, {
object = self.object,
gain = 1.0,
max_hear_distance = self.sounds.distance
})
end
mob_sound(self, self.sounds.jump)
end
end
-- this is a faster way to calculate distance
local get_distance = function(a, b)
@ -624,6 +595,7 @@ local get_distance = function(a, b)
return square(x * x + y * y + z * z)
end
-- blast damage to entities nearby (modified from TNT mod)
function entity_physics(pos, radius)
@ -656,6 +628,7 @@ function entity_physics(pos, radius)
end
end
-- should mob follow what I'm holding ?
function follow_holding(self, clicker)
@ -685,6 +658,7 @@ function follow_holding(self, clicker)
return false
end
-- find two animals of same type and breed if nearby and horny
local function breed(self)
@ -819,6 +793,7 @@ local function breed(self)
end
end
-- find and replace what mob is looking for (grass, wheat etc.)
function replace(self, pos)
@ -848,6 +823,7 @@ function replace(self, pos)
end
end
-- check if daytime and also if mob is docile during daylight hours
function day_docile(self)
@ -863,6 +839,7 @@ function day_docile(self)
end
end
-- path finding and smart mob routine by rnd
function smart_mobs(self, s, p, dist, dtime)
@ -992,26 +969,12 @@ function smart_mobs(self, s, p, dist, dtime)
self.path.stuck_timer = stuck_timeout - 2
-- frustration! cant find the damn path :(
if self.sounds.random then
minetest.sound_play(self.sounds.random, {
object = self.object,
max_hear_distance = self.sounds.distance
})
end
mob_sound(self, self.sounds.random)
else
-- yay i found path
if self.sounds.attack then
mob_sound(self, self.sounds.attack)
set_velocity(self, self.walk_velocity)
minetest.sound_play(self.sounds.attack, {
object = self.object,
max_hear_distance = self.sounds.distance
})
end
set_velocity(self, self.walk_velocity)
-- follow path now that it has it
self.path.following = true
@ -1019,6 +982,7 @@ function smart_mobs(self, s, p, dist, dtime)
end
end
-- specific attacks
local specific_attack = function(list, what)
@ -1038,6 +1002,7 @@ local specific_attack = function(list, what)
return false
end
-- monster find someone to attack
local monster_attack = function(self)
@ -1080,7 +1045,7 @@ local monster_attack = function(self)
-- 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
or (type == "animal" and self.attack_animals == true)) then
s = self.object:getpos()
p = player:getpos()
@ -1111,6 +1076,7 @@ local monster_attack = function(self)
end
end
-- npc, find closest monster to attack
local npc_attack = function(self)
@ -1148,6 +1114,7 @@ local npc_attack = function(self)
end
end
-- follow player if owner or holding item, if fish outta water then flop
local follow_flop = function(self)
@ -1267,6 +1234,7 @@ local follow_flop = function(self)
end
end
-- dogshoot attack switch and counter function
local dogswitch = function(self, dtime)
@ -1292,6 +1260,7 @@ local dogswitch = function(self, dtime)
return self.dogshoot_switch
end
-- execute current state (stand, walk, run, attacks)
local do_states = function(self, dtime)
@ -1552,14 +1521,7 @@ local do_states = function(self, dtime)
if minetest.find_node_near(pos, 1, {"group:water"})
or minetest.is_protected(pos, "") then
if self.sounds.explode then
minetest.sound_play(self.sounds.explode, {
object = self.object,
gain = 1.0,
max_hear_distance = 16
})
end
mob_sound(self, self.sounds.explode)
self.object:remove()
@ -1733,13 +1695,7 @@ local do_states = function(self, dtime)
if line_of_sight_water(self, p2, s2) == true then
-- play attack sound
if self.sounds.attack then
minetest.sound_play(self.sounds.attack, {
object = self.object,
max_hear_distance = self.sounds.distance
})
end
mob_sound(self, self.sounds.attack)
-- punch player (or what player is attached to)
local attached = self.attack:get_attach()
@ -1791,13 +1747,7 @@ local do_states = function(self, dtime)
set_animation(self, "shoot")
-- play shoot attack sound
if self.sounds.shoot_attack then
minetest.sound_play(self.sounds.shoot_attack, {
object = self.object,
max_hear_distance = self.sounds.distance
})
end
mob_sound(self, self.sounds.shoot_attack)
local p = self.object:getpos()
@ -1822,6 +1772,7 @@ local do_states = function(self, dtime)
end
end
-- falling and fall damage
local falling = function(self, pos)
@ -1883,6 +1834,7 @@ local falling = function(self, pos)
end
end
local mob_punch = function(self, hitter, tflp, tool_capabilities, dir)
-- error checking when mod profiling is enabled
@ -1957,81 +1909,80 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir)
hitter:set_wielded_item(weapon)
end
-- only play hit sound and show blood effects if damage is 1 or over
if damage >= 1 then
-- only play hit sound and show blood effects if damage is 1 or over
if damage >= 1 then
-- weapon sounds
if weapon:get_definition().sounds ~= nil then
-- weapon sounds
if weapon:get_definition().sounds ~= nil then
local s = random(0, #weapon:get_definition().sounds)
local s = random(0, #weapon:get_definition().sounds)
minetest.sound_play(weapon:get_definition().sounds[s], {
object = hitter,
max_hear_distance = 8
})
else
minetest.sound_play("default_punch", {
object = hitter,
max_hear_distance = 5
})
end
-- blood_particles
if self.blood_amount > 0
and not disable_blood then
local pos = self.object:getpos()
pos.y = pos.y + (-self.collisionbox[2] + self.collisionbox[5]) * .5
effect(pos, self.blood_amount, self.blood_texture)
end
-- do damage
self.health = self.health - floor(damage)
-- exit here if dead
if check_for_death(self) then
return
end
--[[ add healthy afterglow when hit (can cause hit lag with larger textures)
core.after(0.1, function()
self.object:settexturemod("^[colorize:#c9900070")
core.after(0.3, function()
self.object:settexturemod("")
end)
end) ]]
-- knock back effect (only on full punch)
if self.knock_back > 0
and tflp > punch_interval then
local v = self.object:getvelocity()
local r = 1.4 - min(punch_interval, 1.4)
local kb = r * 5
local up = 2
-- if already in air then dont go up anymore when hit
if v.y > 0
or self.fly then
up = 0
minetest.sound_play(weapon:get_definition().sounds[s], {
object = hitter,
max_hear_distance = 8
})
else
minetest.sound_play("default_punch", {
object = hitter,
max_hear_distance = 5
})
end
-- direction error check
dir = dir or {x = 0, y = 0, z = 0}
-- blood_particles
if self.blood_amount > 0
and not disable_blood then
self.object:setvelocity({
x = dir.x * kb,
y = up,
z = dir.z * kb
})
local pos = self.object:getpos()
self.pause_timer = r
end
pos.y = pos.y + (-self.collisionbox[2] + self.collisionbox[5]) * .5
end -- END if damage
effect(pos, self.blood_amount, self.blood_texture)
end
-- do damage
self.health = self.health - floor(damage)
-- exit here if dead
if check_for_death(self) then
return
end
--[[ add healthy afterglow when hit (can cause hit lag with larger textures)
core.after(0.1, function()
self.object:settexturemod("^[colorize:#c9900070")
core.after(0.3, function()
self.object:settexturemod("")
end)
end) ]]
-- knock back effect (only on full punch)
if self.knock_back > 0
and tflp > punch_interval then
local v = self.object:getvelocity()
local r = 1.4 - min(punch_interval, 1.4)
local kb = r * 5
local up = 2
-- if already in air then dont go up anymore when hit
if v.y > 0
or self.fly then
up = 0
end
-- direction error check
dir = dir or {x = 0, y = 0, z = 0}
self.object:setvelocity({
x = dir.x * kb,
y = up,
z = dir.z * kb
})
self.pause_timer = r
end
end -- END if damage
-- if skittish then run away
if self.runaway == true then
@ -2087,6 +2038,7 @@ end -- END if damage
end
end
local mob_activate = function(self, staticdata, dtime_s, def)
-- remove monsters in peaceful mode, or when no data
@ -2186,6 +2138,7 @@ local mob_activate = function(self, staticdata, dtime_s, def)
update_tag(self)
end
local mob_step = function(self, dtime)
local pos = self.object:getpos()
@ -2270,13 +2223,8 @@ local mob_step = function(self, dtime)
replace(self, pos)
-- mob plays random sound at times
if self.sounds.random
and random(1, 100) == 1 then
minetest.sound_play(self.sounds.random, {
object = self.object,
max_hear_distance = self.sounds.distance
})
if random(1, 100) == 1 then
mob_sound(self, self.sounds.random)
end
-- environmental damage timer (every 1 second)
@ -2302,6 +2250,7 @@ local mob_step = function(self, dtime)
end
-- default function when mobs are blown up with TNT
local do_tnt = function(obj, damage)
@ -2315,6 +2264,7 @@ local do_tnt = function(obj, damage)
return false, true, {}
end
mobs.spawning_mobs = {}
-- register mob function
@ -2466,6 +2416,7 @@ minetest.register_entity(name, {
end -- END mobs:register_mob function
-- count how many mobs of one type are inside an area
local count_mobs = function(pos, type)
@ -2488,6 +2439,7 @@ local count_mobs = function(pos, type)
return num
end
-- global functions
function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light,
@ -2626,6 +2578,7 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light,
})
end
-- compatibility with older mob registration
function mobs:register_spawn(name, nodes, max_light, min_light, chance, active_object_count, max_height, day_toggle)
@ -2633,6 +2586,7 @@ function mobs:register_spawn(name, nodes, max_light, min_light, chance, active_o
chance, active_object_count, -31000, max_height, day_toggle)
end
-- MarkBu's spawn function
function mobs:spawn(def)
@ -2653,6 +2607,7 @@ function mobs:spawn(def)
chance, active_object_count, min_height, max_height, day_toggle, on_spawn)
end
-- set content id's
local c_air = minetest.get_content_id("air")
local c_ignore = minetest.get_content_id("ignore")
@ -2746,6 +2701,7 @@ function mobs:explosion(pos, radius, fire, smoke, sound)
end
end
-- register arrow for shoot attack
function mobs:register_arrow(name, def)
@ -2871,6 +2827,7 @@ function mobs:register_arrow(name, def)
})
end
-- Spawn Egg
function mobs:register_egg(mob, desc, background, addegg, no_creative)
@ -2929,6 +2886,7 @@ function mobs:register_egg(mob, desc, background, addegg, no_creative)
})
end
-- capture critter (thanks to blert2112 for idea)
function mobs:capture_mob(self, clicker, chance_hand, chance_net, chance_lasso, force_take, replacewith)
@ -3006,6 +2964,7 @@ function mobs:capture_mob(self, clicker, chance_hand, chance_net, chance_lasso,
end
end
-- protect tamed mob with rune iten
function mobs:protect(self, clicker)
@ -3032,6 +2991,7 @@ function mobs:protect(self, clicker)
return false
end
local mob_obj = {}
local mob_sta = {}
@ -3112,13 +3072,7 @@ function mobs:feed_tame(self, clicker, feed_count, breed, tame)
end
-- make sound when fed so many times
if self.sounds.random then
minetest.sound_play(self.sounds.random, {
object = self.object,
max_hear_distance = self.sounds.distance
})
end
mob_sound(self, self.sounds.random)
end
return true
@ -3150,6 +3104,7 @@ function mobs:feed_tame(self, clicker, feed_count, breed, tame)
end
-- inspired by blockmen's nametag mod
minetest.register_on_player_receive_fields(function(player, formname, fields)
@ -3185,6 +3140,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end
end)
-- compatibility function for old entities to new modpack entities
function mobs:alias_mob(old_name, new_name)