- Closes #26
This commit is contained in:
Leslie Krause 2020-05-19 09:19:00 -04:00
parent 5bd2aa6cac
commit 65e36d0f71
4 changed files with 87 additions and 127 deletions

View File

@ -1,4 +1,4 @@
Mobs Lite Mod v1.4
Mobs Lite Mod v1.5
By Leslie E. Krause
Mobs Lite is a fully-working proof of concept for the Extended Motion Mechanics API for

View File

@ -25,25 +25,25 @@ mobs.register_mob( "mobs:kitten", {
y_offset = 0,
density = 0.5,
groups = { mob = 1, animal = 1, walks = 1, mobile = 1 },
textures = { "mobs_kitten.png" },
makes_footstep_sound = false,
makes_bloodshed_effect = true,
offense_state = "follow",
defense_state = "ignore",
retreat_state = "escape",
hunger_params = { offset = -0.5, spread = 2.5 },
alertness_states = {
ignore = { view_offset = 2, view_radius = 4, view_height = 4, view_acuity = 3 },
search = { view_offset = 2, view_radius = 10, view_height = 4, view_acuity = 3, view_filter = function ( self, obj, clarity )
return clarity == 0.0 and "search" or "follow"
end },
search = { view_offset = 2, view_radius = 10, view_height = 4, view_acuity = 3 },
follow = { view_offset = 2, view_radius = 10, view_height = 4, view_acuity = 3 },
escape = { view_offset = 2, view_radius = 10, view_height = 4, view_acuity = 3 },
},
awareness_stages = {
search = { decay = 12.0, abort_state = "ignore" },
follow = { decay = 0.0, abort_state = "search" },
escape = { decay = 12.0, abort_state = "ignore" },
search = { decay = 12.0, fail_state = "search", wait_state = "ignore" },
follow = { decay = 0.0, fail_state = "search" },
escape = { decay = 12.0, pass_state = "escape", fail_state = "escape", wait_state = "ignore" },
},
certainty = 1.0,
@ -73,7 +73,7 @@ mobs.register_mob( "mobs:kitten", {
watch_players = { },
hp_max = 4,
hp_low = 3,
hp_low = 2,
armor = 100,
light_damage = 0,
water_damage = 4,
@ -129,33 +129,28 @@ mobs.register_mob( "mobs:rat", {
y_offset = 0,
density = 0.4,
groups = { mob = 1, animal = 1, walks = 1, mobile = 1 },
textures = {
"mobs_rat2.png", "mobs_rat2.png"
},
textures = { "mobs_rat2.png", "mobs_rat2.png" },
makes_footstep_sound = false,
makes_bloodshed_effect = true,
offense_state = "escape",
defense_state = "escape",
retreat_state = "escape",
hunger_params = { offset = 0.0, spread = 2.5 },
alertness_states = {
ignore = { view_offset = 0, view_radius = 3, view_height = 3, view_acuity = 4 },
search = { view_offset = 0, view_radius = 6, view_height = 3, view_acuity = 6, view_filter = function ( self, obj, clarity )
return clarity == 0.0 and "search" or "follow"
end },
follow = { view_offset = 0, view_radius = 6, view_height = 3, view_acuity = 6 },
escape = { view_offset = 0, view_radius = 6, view_height = 3, view_acuity = 6 },
},
awareness_stages = {
search = { decay = 12.0, abort_state = "ignore" },
follow = { decay = 0.0, abort_state = "search" },
escape = { decay = 12.0, abort_state = "ignore" },
escape = { decay = 4.0, pass_state = "escape", fail_state = "escape", wait_state = "ignore" },
},
certainty = 1.0,
sensitivity = 0.0,
fear_factor = 8,
fear_factor = 6,
flee_factor = 10,
sneak_velocity = 0.5,
walk_velocity = 0.5,
@ -163,8 +158,8 @@ mobs.register_mob( "mobs:rat", {
recoil_velocity = 0.5,
run_velocity = 1.2,
search_range = 2.0,
follow_range = 2.0,
pickup_range = 2.0,
follow_range = 2.5,
pickup_range = 2.5,
escape_range = 0.0,
can_jump = false,
can_walk = true,
@ -174,7 +169,7 @@ mobs.register_mob( "mobs:rat", {
["mobs:meat"] = "follow",
},
watch_spawnitems = {
["mobs:meat"] = mobs.presets.grab_handout { can_eat = true, grab_chance = 2, wait_chance = 4 },
["mobs:meat"] = mobs.presets.grab_handout { can_eat = true, grab_chance = 2, wait_chance = 1 },
},
watch_players = { },
@ -225,29 +220,26 @@ mobs.register_mob( "mobs:hare", {
y_offset = 0,
density = 0.6,
groups = { mob = 1, animal = 1, walks = 1, jumps = 1, mobile = 1, herbivore = 1 },
textures = { "mobs_bunny_grey.png" },
makes_footstep_sound = false,
makes_bloodshed_effect = true,
offense_state = "escape",
defense_state = "escape",
retreat_state = "escape",
hunger_params = { offset = 0.0, spread = 2.0 },
alertness_states = {
ignore = { view_offset = 0, view_radius = 2, view_height = 6, view_acuity = 0 },
search = { view_offset = 0, view_radius = 12, view_height = 6, view_acuity = 3, view_filter = function ( self, obj, clarity )
return clarity == 0.0 and "search" or "follow"
end },
follow = { view_offset = 0, view_radius = 12, view_height = 6, view_acuity = 3 },
escape = { view_offset = 0, view_radius = 12, view_height = 6, view_acuity = 3 },
ignore = { view_offset = 2, view_radius = 8, view_height = 6, view_acuity = 0 },
follow = { view_offset = 2, view_radius = 12, view_height = 6, view_acuity = 3 },
escape = { view_offset = 2, view_radius = 12, view_height = 6, view_acuity = 3 },
},
awareness_stages = {
search = { decay = 12.0, abort_state = "ignore" },
follow = { decay = 0.0, abort_state = "search" },
escape = { decay = 12.0, abort_state = "ignore" },
escape = { decay = 8.0, pass_state = "escape", fail_state = "escape", wait_state = "ignore" },
},
certainty = 1.0,
sensitivity = 0.5,
sensitivity = 0.0,
fear_factor = 6,
flee_factor = 10,
@ -257,8 +249,8 @@ mobs.register_mob( "mobs:hare", {
recoil_velocity = 2.0,
run_velocity = 3.5,
search_range = 3.0,
follow_range = 3.0,
pickup_range = 2.0,
follow_range = 2.5,
pickup_range = 2.5,
escape_range = 3.0,
can_jump = true,
can_walk = true,
@ -268,7 +260,7 @@ mobs.register_mob( "mobs:hare", {
["default:apple"] = "follow",
},
watch_spawnitems = {
["default:apple"] = mobs.presets.grab_handout { can_eat = true, grab_chance = 2, wait_chance = 5 },
["default:apple"] = mobs.presets.grab_handout { can_eat = true, grab_chance = 2, wait_chance = 1 },
},
watch_players = { },
@ -327,28 +319,26 @@ mobs.register_mob( "mobs:chicken", {
y_offset = 3,
density = 0.4,
groups = { mob = 1, animal = 1, walks = 1, jumps = 1, mobile = 1, herbivore = 1 },
textures = {
"mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png",
"mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png", "mobs_chicken.png",
},
makes_footstep_sound = true,
makes_bloodshed_effect = true,
offense_state = "follow",
defense_state = "escape",
retreat_state = "escape",
hunger_params = { offset = 0.0, spread = 2.0 },
alertness_states = {
ignore = { view_offset = 2, view_radius = 4, view_height = 4, view_acuity = 0 },
search = { view_offset = 2, view_radius = 6, view_height = 4, view_acuity = 2, view_filter = function ( self, obj, clarity )
return clarity == 0.0 and "search" or "follow"
end },
search = { view_offset = 2, view_radius = 6, view_height = 4, view_acuity = 2 },
follow = { view_offset = 2, view_radius = 6, view_height = 4, view_acuity = 2 },
escape = { view_offset = 2, view_radius = 6, view_height = 4, view_acuity = 2 },
},
awareness_stages = {
search = { decay = 12.0, abort_state = "ignore" },
follow = { decay = 0.0, abort_state = "search" },
escape = { decay = 12.0, abort_state = "ignore" },
escape = { decay = 12.0, pass_state = "escape", fail_state = "ignore", wait_state = "ignore" },
},
certainty = 1.0,
@ -362,7 +352,7 @@ mobs.register_mob( "mobs:chicken", {
recoil_velocity = 2.0,
run_velocity = 2.0,
search_range = 3.0,
follow_range = 3.0,
follow_range = 2.0,
pickup_range = 2.0,
escape_range = 3.0,
can_jump = true,

View File

@ -428,7 +428,9 @@ mobs.register_mob = function ( name, def )
shoot_count = 0,
timeout = def.timeout,
neutral_state = "ignore",
defense_state = def.type == "monster" and "attack" or "ignore",
offense_state = def.offense_state or def.type == "monster" and "attack" or "ignore",
defense_state = def.defense_state or def.type == "monster" and "attack" or "escape",
retreat_state = def.retreat_state or "escape",
is_tamed = false,
description = def.description,
after_activate = def.after_activate,
@ -574,7 +576,7 @@ mobs.register_mob = function ( name, def )
check_suspect = function ( self, target_obj, clarity, elapsed )
-- default to defense or neutral state if not in any watch list
local suspect = random( 10 ) <= self.fear_factor and self.defense_state or self.neutral_state
local suspect = random( 10 ) <= self.fear_factor and self.offense_state or self.neutral_state
local entity = target_obj:get_luaentity( )
if not entity then
@ -634,9 +636,9 @@ mobs.register_mob = function ( name, def )
-- when creating target it must be visible and evident!
if is_visible and is_evident then
if alertness and alertness.view_filter then
return alertness.view_filter( self, obj, clarity ), { obj = obj, pos = pos }
return alertness.view_filter( self, obj, clarity, 0.0 ), { obj = obj, pos = pos }
elseif clarity > 0.0 then
return self:check_suspect( obj, clarity ), { obj = obj, pos = pos }
return self:check_suspect( obj, clarity, 0.0 ), { obj = obj, pos = pos }
end
else
return self.state, self.target
@ -657,11 +659,11 @@ mobs.register_mob = function ( name, def )
end
if alertness and alertness.view_filter then
return alertness.view_filter( self, self.target.obj, clarity )
return alertness.view_filter( self, self.target.obj, clarity, elapsed )
elseif clarity > 0.0 then
return self:check_suspect( self.target.obj, clarity, elapsed )
return self.awareness.pass_state or self:check_suspect( self.target.obj, clarity, elapsed )
else
return self.abort_state or self.neutral_state
return self.awareness.fail_state or self.neutral_state
end
end
@ -676,7 +678,7 @@ mobs.register_mob = function ( name, def )
-- when not upset, seek out food or prey at random intervals
for obj in mobs.iterate_registry( self.pos, 30, 30, { players = true, spawnitems = true } ) do
if random( 10 ) <= self.fear_factor and obj:is_player( ) and not obj:get_attach( ) then
if random( 10 ) <= self.fear_factor and not obj:get_attach( ) then
local state, target = self:create_target( obj )
if state ~= self.state then
self:reset_alertness( state, target )
@ -689,19 +691,13 @@ mobs.register_mob = function ( name, def )
-- alertness and awareness functions --
start_awareness = function ( self )
local awareness = self.awareness_stages[ self.state ]
self.awareness = self.awareness_stages[ self.state ] or { }
if awareness then
self.abort_state = awareness.abort_state
if awareness.decay > 0 then
self.timekeeper.start( awareness.decay, "awareness", function ( )
self:reset_alertness( self.abort_state, self.target )
end )
else
self.timekeeper.clear( "awareness" )
end
if self.awareness.decay and self.awareness.decay > 0 then
self.timekeeper.start( self.awareness.decay, "awareness", function ( )
self:reset_alertness( self.awareness.wait_state, self.target )
end )
else
self.abort_state = nil
self.timekeeper.clear( "awareness" )
end
end,
@ -851,8 +847,8 @@ mobs.register_mob = function ( name, def )
local dist = self:get_target_distance( )
if cycles % 2 == 0 then
if self:get_target_yaw_delta( ) > rad_45 or random( 5 ) == 1 then
self:turn_to( self:get_target_yaw( rad_20 ), 10 )
if self:get_target_yaw_delta( ) > rad_45 or random( 3 ) == 1 then
self:turn_to( self:get_target_yaw( rad_20 ), 15 )
end
end
@ -1307,9 +1303,7 @@ mobs.register_mob = function ( name, def )
self:set_velocity_vert( 0 )
self:set_yaw( random( ) * rad_360 )
self.aware_level = 0
self.yield_level = 0
self.awareness = { certainty = self.certainty, sensitivity = self.sensitivity }
self.move_result = { collides_xz = false, collides_y = true, is_standing = true }
self.pos = self.object:get_pos( )
@ -1413,9 +1407,9 @@ mobs.register_mob = function ( name, def )
end
if hp - damage <= self.hp_low then
self:reset_alertness( "escape", { obj = hitter, pos = hitter:get_pos( ) } )
elseif self.type == "monster" then
self:reset_alertness( "attack", { obj = hitter, pos = hitter:get_pos( ) } )
self:reset_alertness( self.retreat_state, { obj = hitter, pos = hitter:get_pos( ) } )
else
self:reset_alertness( self.defense_state, { obj = hitter, pos = hitter:get_pos( ) } )
end
end
end,
@ -1610,11 +1604,11 @@ mobs.presets = {
texture = "heart.png",
} )
end
return "ignore"
return self.neutral_state
end
end
return random( wait_chance ) == 1 and "follow" or "ignore"
return random( wait_chance ) == 1 and "follow" or self.offense_state
end
end,
}
@ -1652,3 +1646,4 @@ dofile( minetest.get_modpath( "mobs" ) .. "/animals.lua" )
if not vector.origin then
dofile( minetest.get_modpath( "mobs" ) .. "/compatibility.lua" )
end

View File

@ -34,17 +34,12 @@ mobs.register_mob( "mobs:ghost", {
hunger_params = { offset = -0.1, spread = 3.0 },
alertness_states = {
ignore = { view_offset = 2, view_radius = 8, view_height = 8, view_acuity = 0 },
search = { view_offset = 2, view_radius = 14, view_height = 8, view_acuity = 3, view_filter = function ( self, obj, clarity )
return clarity == 0.0 and "search" or "attack"
end },
attack = { view_offset = 2, view_radius = 14, view_height = 8, view_acuity = 3 , view_filter = function ( self, obj, clarity )
return clarity == 0.0 and "search" or "attack"
end },
attack = { view_offset = 2, view_radius = 14, view_height = 8, view_acuity = 3 },
escape = { view_offset = 2, view_radius = 14, view_height = 8, view_acuity = 3 },
},
awareness_stages = {
attack = { decay = 15.0, abort_state = "ignore" },
escape = { decay = 10.0, abort_state = "ignore" },
attack = { decay = 0.0, pass_state = "attack", fail_state = "ignore" },
escape = { decay = 12.0, pass_state = "escape", fail_state = "escape", wait_state = "ignore" },
},
certainty = 1.0,
@ -66,8 +61,6 @@ mobs.register_mob( "mobs:ghost", {
can_fly = true,
can_walk = false,
watch_players = { },
hunger = 5,
hp_max = 10,
hp_low = 9,
@ -139,28 +132,17 @@ mobs.register_mob( "mobs:spider", {
textures = { "mobs_spider_gib.png" }
},
gibbage_params = {
pieces = { "teeny", "teeny" },
sound = "mobs_gib_chunky",
damage_groups = { blast_stim = 3 },
textures = { "mobs_paniki_gib.png" }
},
hunger_params = { offset = 0.3, spread = 4.0 },
alertness_states = {
ignore = { view_offset = 6, view_radius = 6, view_height = 6, view_acuity = 3 },
search = { view_offset = 6, view_radius = 12, view_height = 6, view_acuity = 5, view_filter = function ( self, obj, clarity )
return clarity == 0.0 and "search" or "attack"
end },
attack = { view_offset = 6, view_radius = 12, view_height = 6, view_acuity = 5, view_filter = function ( self, obj, clarity )
return clarity == 0.0 and "search" or "attack"
end },
search = { view_offset = 6, view_radius = 12, view_height = 6, view_acuity = 5 },
attack = { view_offset = 6, view_radius = 12, view_height = 6, view_acuity = 5 },
escape = { view_offset = 6, view_radius = 12, view_height = 6, view_acuity = 5 },
},
awareness_stages = {
search = { decay = 18.0, abort_state = "ignore" },
attack = { decay = 0.0, abort_state = "search" },
escape = { decay = 18.0, abort_state = "ignore" },
search = { decay = 18.0, pass_state = "attack", fail_state = "search", wait_state = "ignore" },
attack = { decay = 0.0, pass_state = "attack", fail_state = "search" },
escape = { decay = 18.0, pass_state = "escape", fail_state = "escape", wait_state = "ignore" },
},
certainty = 1.0,
@ -180,8 +162,6 @@ mobs.register_mob( "mobs:spider", {
can_walk = true,
can_jump = true,
watch_players = { },
hunger = 6,
hp_max = 16,
hp_low = 4,
@ -252,21 +232,24 @@ mobs.register_mob( "mobs:bat", {
makes_footstep_sound = false,
makes_bloodshed_effect = true,
gibbage_params = {
pieces = { "teeny", "teeny" },
sound = "mobs_gib_chunky",
damage_groups = { blast_stim = 3 },
textures = { "mobs_paniki_gib.png" }
},
hunger_params = { offset = 1.0, spread = 1.0 },
alertness_states = {
ignore = { view_offset = 10, view_radius = 15, view_height = 15, view_acuity = 3 },
search = { view_offset = 10, view_radius = 20, view_height = 15, view_acuity = 5, view_filter = function ( self, obj, clarity )
return clarity == 0.0 and "search" or "attack"
end },
attack = { view_offset = 10, view_radius = 20, view_height = 15, view_acuity = 5, view_filter = function ( self, obj, clarity )
return clarity == 0.0 and "search" or "attack"
end },
search = { view_offset = 10, view_radius = 20, view_height = 15, view_acuity = 5 },
attack = { view_offset = 10, view_radius = 20, view_height = 15, view_acuity = 5 },
escape = { view_offset = 10, view_radius = 20, view_height = 15, view_acuity = 3 },
},
awareness_stages = {
search = { decay = 14.0, abort_state = "ignore" },
attack = { decay = 0.0, abort_state = "search" },
escape = { decay = 14.0, abort_state = "ignore" },
search = { decay = 14.0, pass_state = "attack", fail_state = "search", wait_state = "ignore" },
attack = { decay = 0.0, pass_state = "attack", fail_state = "search" },
escape = { decay = 14.0, pass_state = "escape", fail_state = "escape", wait_state = "ignore" },
},
certainty = 1.0,
@ -287,8 +270,6 @@ mobs.register_mob( "mobs:bat", {
can_fly = true,
can_walk = false,
watch_players = { },
hunger = 6,
hp_max = 8,
hp_low = 2,
@ -359,18 +340,14 @@ mobs.register_mob( "mobs:griefer_ghost", {
hunger_params = { offset = 0.3, spread = 6.0 },
alertness_states = {
ignore = { view_offset = 5, view_radius = 10, view_height = 8, view_acuity = 2 },
search = { view_offset = 5, view_radius = 20, view_height = 8, view_acuity = 2, view_filter = function ( self, obj, clarity )
return clarity == 0.0 and "search" or "attack"
end },
attack = { view_offset = 5, view_radius = 20, view_height = 8, view_acuity = 2, view_filter = function ( self, obj, clarity )
return clarity == 0.0 and "search" or "attack"
end },
search = { view_offset = 5, view_radius = 20, view_height = 8, view_acuity = 2 },
attack = { view_offset = 5, view_radius = 20, view_height = 8, view_acuity = 2 },
escape = { view_offset = 5, view_radius = 20, view_height = 8, view_acuity = 2 },
},
awareness_stages = {
search = { decay = 8.0, abort_state = "ignore" },
attack = { decay = 25.0, abort_state = "search" },
escape = { decay = 8.0, abort_state = "ignore" },
search = { decay = 20.0, pass_state = "attack", fail_state = "search", wait_state = "ignore" },
attack = { decay = 0.0, pass_state = "attack", fail_state = "search" },
escape = { decay = 10.0, pass_state = "escape", fail_state = "escape", wait_state = "ignore" },
},
certainty = 1.0,
@ -390,8 +367,6 @@ mobs.register_mob( "mobs:griefer_ghost", {
can_jump = true,
can_walk = true,
watch_players = { },
hunger = 2,
hp_max = 12,
hp_low = 4,