123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- local textures =
- {
- "eg_goats_torso.png", --torso
- "eg_goats_leg.png", --legs
- "eg_goats_head.png", --head
- "eg_goats_mouth.png", --mouth
- "blank.png", --unihorn
- "eg_goats_horns.png", --horns
- }
- local function hq_follow_until_near(self, prty, tgtobj)
- local tgtpos = tgtobj:get_pos()
- local func = function()
- if mobkit.timer(self, 0.5)
- then
- if not mobkit.exists(tgtobj)
- then
- return true
- end
- tgtpos = tgtobj:get_pos()
- if vector.distance(self.object:get_pos(), tgtpos) < 5
- then
- return true
- end
- end
- if mobkit.is_queue_empty_low(self) and self.isonground
- then
- eg_moblib.goto_next_waypoint(self, tgtpos, 0.3)
- end
- end
- mobkit.queue_high(self, func, prty)
- end
- local function hq_gather(self, prty, attempts)
- local follow
- local func = function()
- if mobkit.timer(self, 2)
- then
- if not mobkit.exists(follow)
- then
- follow = mobkit.get_nearby_entity(self, self.name)
- return
- end
- hq_follow_until_near(self, prty + 1, follow)
- attempts = attempts - 1
- end
- return attempts < 1
- end
- mobkit.queue_high(self, func, prty)
- end
- local function defend(self)
- --get two random nearby players and select the worse one
- local nearbies = {mobkit.get_nearby_player(self), mobkit.get_nearby_player(self)}
- local badness = 0
- local worse
- for i, nearby in ipairs(nearbies)
- do
- local new_badness = self.enemy[nearby:get_player_name()]
- if new_badness and new_badness > badness
- then
- badness = new_badness
- worse = nearby
- end
- end
- if worse
- then
- if badness < 2
- then
- --forgive
- return
- elseif badness < self.hp * 1.5 --TODO: fine tune
- then
- --attack
- mobkit.hq_hunt(self, 20, worse)
- else
- --run
- mobkit.clear_queue_high(self)
- mobkit.clear_queue_low(self)
- mobkit.hq_runfrom(self, 21, worse)
- end
- end
- end
- local function lq_sleep(self, time)
- mobkit.animate(self, "sleep")
- local func = function()
- if mobkit.timer(self, 3) and math.random(5) == 1
- then
- mobkit.heal(self, 1)
- mobkit.make_sound(self, "snore")
- if math.random(5) == 1
- then
- --slowly forgive enemies
- for k, v in pairs(self.enemy)
- do
- v = v - 1
- self.enemy[k] = v > 0 and v or nil
- end
- end
- end
- if math.random(10) == 1
- then
- defend(self)
- end
- time = time - self.dtime
- return time <= 0
- end
- mobkit.queue_low(self, func)
- end
- local function is_day()
- local tod = minetest.get_timeofday()
- return tod > 0.25 and tod < 0.75
- end
- local function hq_sleep(self, prty)
- hq_gather(self, prty + 1, 5)
- local func = function()
- if mobkit.is_queue_empty_low(self)
- then
- lq_sleep(self, 3)
- return is_day()
- end
- end
- mobkit.queue_high(self, func, prty)
- end
- local function hq_eat(self, prty)
- local func = function()
- --TODO
- end
- mobkit.queue_high(self, func, prty)
- end
- local function alert_danger(self, attacker, damage)
- for i, obj in ipairs(self.nearby_objects)
- do
- local luae = obj:get_luaentity()
- if luae and luae.name == self.name
- then
- if attacker:is_player()
- then
- local name = attacker:get_player_name()
- luae.enemy[name] = (luae.enemy[name] or 0) + damage
- defend(luae)
- end
- end
- end
- end
- minetest.register_entity("eg_goats:goat",
- {
- initial_properties =
- {
- physical = true,
- collide_with_objects = true,
- collisionbox = {-0.3, 0, -0.3, 0.3, 1, 0.3},
- visual = "mesh",
- mesh = "eg_goats_goat.b3d",
- backface_culling = false,
- },
- timeout = 0,
- buoyancy = 0.5,
- lung_capacity = 5, --more than 5 is a waste after all
- max_hp = 30,
- on_step = mobkit.stepfunc,
- on_activate = function(self, staticdata, dtime_s)
- mobkit.actfunc(self, staticdata, dtime_s)
- --set textures
- local props = self.object:get_properties()
- props.textures = textures
- self.object:set_properties(props)
- --load enemy table and set it to be saved again
- self.enemy = mobkit.recall(self, "enemy") or {}
- mobkit.remember(self, "enemy", self.enemy)
- --start doing something
- if is_day()
- then
- mobkit.hq_roam(self, 1)
- else
- hq_sleep(self, 10)
- end
- end,
- get_staticdata = mobkit.statfunc,
- logic = function(self)
- if not mobkit.is_alive(self)
- then
- mobkit.clear_queue_high(self)
- mobkit.clear_queue_low(self)
- mobkit.hq_die(self, 100)
- return
- end
- if mobkit.timer(self, 1)
- then
- local prty = mobkit.get_queue_priority(self)
- if self.isinliquid and prty < 30
- then
- mobkit.hq_liquid_recovery(self, 30)
- end
- if is_day()
- then
- if prty < 20
- then
- defend(self)
- end
- if mobkit.is_queue_empty_high(self)
- then
- mobkit.hq_roam(self, 1)
- end
- else
- if prty < 10
- then
- hq_sleep(self, 10)
- end
- end
- end
- end,
- on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
- local hvel = vector.multiply(vector.normalize({x=dir.x,y=0,z=dir.z}),4)
- self.object:set_velocity({x=hvel.x,y=2,z=hvel.z})
- local dmg = tool_capabilities.damage_groups.fleshy or 1
- mobkit.hurt(self, dmg)
- if mobkit.is_alive(self)
- then
- if puncher:is_player()
- then
- local name = puncher:get_player_name()
- self.enemy[name] = (self.enemy[name] or 0) + dmg
- defend(self)
- end
- alert_danger(self, puncher, dmg)
- mobkit.make_sound(self, "hurt")
- end
- end,
- --TODO: animation
- --TODO: sounds
- max_speed = 12,
- jump_height = 2,
- view_range = 30,
- attack =
- {
- range = 1,
- damage_groups = {fleshy = 4},
- },
- armor_groups = {fleshy = 4},
- })
|