3 --made for MC like Survival game
4 --License for code WTFPL and otherwise stated in readmes
7 local MP
= minetest
.get_modpath(minetest
.get_current_modname())
8 local S
, NS
= dofile(MP
.."/intllib.lua")
11 --################### HORSE
14 -- Return overlay texture for horse/donkey/mule, e.g. chest, saddle or horse armor
15 local horse_extra_texture
= function(horse
)
16 local base
= horse
._naked_texture
17 local saddle
= horse
._saddle
18 local chest
= horse
._chest
19 local armor
= horse
._horse_armor
21 if armor
and minetest
.get_item_group(armor
, "horse_armor") > 0 then
22 textures
[2] = base
.. "^" .. minetest
.registered_items
[armor
]._horse_overlay_image
29 textures
[3] = "blank.png"
34 textures
[1] = "blank.png"
39 -- Helper functions to determine equipment rules
40 local can_equip_horse_armor
= function(entity_id
)
41 return entity_id
== "mobs_mc:horse" or entity_id
== "mobs_mc:skeleton_horse" or entity_id
== "mobs_mc:zombie_horse"
43 local can_equip_chest
= function(entity_id
)
44 return entity_id
== "mobs_mc:mule" or entity_id
== "mobs_mc:donkey"
46 local can_breed
= function(entity_id
)
47 return entity_id
== "mobs_mc:horse" or "mobs_mc:mule" or entity_id
== "mobs_mc:donkey"
50 --[[ Generate all possible horse textures.
51 Horse textures are a combination of a base texture and an optional marking overlay. ]]
52 -- The base horse textures (fur) (fur)
54 "mobs_mc_horse_brown.png",
55 "mobs_mc_horse_darkbrown.png",
56 "mobs_mc_horse_white.png",
57 "mobs_mc_horse_gray.png",
58 "mobs_mc_horse_black.png",
59 "mobs_mc_horse_chestnut.png",
61 -- Horse marking texture overlay, to be appended to the base texture string
62 local horse_markings
= {
64 "mobs_mc_horse_markings_whitedots.png", -- snowflake appaloosa
65 "mobs_mc_horse_markings_blackdots.png", -- sooty
66 "mobs_mc_horse_markings_whitefield.png", -- paint
67 "mobs_mc_horse_markings_white.png", -- stockings and blaze
70 local horse_textures
= {}
71 for b
=1, #horse_base
do
72 for m
=1, #horse_markings
do
73 local fur
= horse_base
[b
]
74 if horse_markings
[m
] ~= "" then
75 fur
= fur
.. "^" .. horse_markings
[m
]
77 table.insert(horse_textures
, {
79 fur
, -- base texture + markings and optional armor
80 "blank.png", -- saddle
89 mesh
= "mobs_mc_horse.b3d",
90 visual_size
= {x
=3.0, y
=3.0},
91 collisionbox
= {-0.69825, -0.01, -0.69825, 0.69825, 1.59, 0.69825},
103 textures
= horse_textures
,
108 follow
= mobs_mc
.follow
.horse
,
115 makes_footstep_sound
= true,
117 jump_height
= 5.75, -- can clear 2.5 blocks
119 {name
= mobs_mc
.items
.leather
,
125 do_custom
= function(self
, dtime
)
127 -- set needed values if not already present
128 if not self
._regentimer
then
133 self
.max_speed_forward
= 7
134 self
.max_speed_reverse
= 2
136 self
.terrain_type
= 3
137 self
.driver_attach_at
= {x
= 0, y
= 7.5, z
= -1.75}
138 self
.driver_eye_offset
= {x
= 0, y
= 3, z
= 0}
139 self
.driver_scale
= {x
= 1/self
.visual_size
.x
, y
= 1/self
.visual_size
.y
}
142 -- Slowly regenerate health
143 self
._regentimer
= self
._regentimer
+ dtime
144 if self
._regentimer
>= 4 then
145 if self
.health
< self
.hp_max
then
146 self
.health
= self
.health
+ 1
151 -- if driver present allow control of horse
154 mobs
.drive(self
, "walk", "stand", false, dtime
)
156 return false -- skip rest of mob functions
162 on_die
= function(self
, pos
)
164 -- drop saddle when horse is killed while riding
166 minetest
.add_item(pos
, mobs_mc
.items
.saddle
)
168 -- also detach from horse properly
170 mobs
.detach(self
.driver
, {x
= 1, y
= 0, z
= 1})
175 on_rightclick
= function(self
, clicker
)
177 -- make sure player is clicking
178 if not clicker
or not clicker
:is_player() then
182 local item
= clicker
:get_wielded_item()
183 if can_breed(self
.name
) and (item
:get_name() == mobs_mc
.items
.golden_apple
or item
:get_name() == mobs_mc
.items
.golden_carrot
) then
184 -- Breed horse with golden apple or golden carrot
185 if mobs
:feed_tame(self
, clicker
, 1, true, false) then return end
187 -- Feed/tame with anything else
188 -- TODO: Different health bonus for feeding
189 if mobs
:feed_tame(self
, clicker
, 1, false, true) then return end
190 if mobs
:protect(self
, clicker
) then return end
192 -- Make sure tamed horse is mature and being clicked by owner only
193 if self
.tamed
and not self
.child
and self
.owner
== clicker
:get_player_name() then
195 local inv
= clicker
:get_inventory()
197 -- detatch player already riding horse
198 if self
.driver
and clicker
== self
.driver
then
200 mobs
.detach(clicker
, {x
= 1, y
= 0, z
= 1})
202 -- Put on saddle if tamed
203 elseif not self
.driver
and not self
._saddle
204 and clicker
:get_wielded_item():get_name() == mobs_mc
.items
.saddle
then
206 -- Put on saddle and take saddle from player's inventory
207 local w
= clicker
:get_wielded_item()
209 if not minetest
.settings
:get_bool("creative_mode") then
211 clicker
:set_wielded_item(w
)
215 if not self
._naked_texture
then
216 -- Base horse texture without chest or saddle
217 self
._naked_texture
= self
.base_texture
[2]
219 local tex
= horse_extra_texture(self
)
220 self
.base_texture
= tex
221 self
.object
:set_properties({textures
= self
.base_texture
})
223 -- Put on horse armor if tamed
224 elseif can_equip_horse_armor(self
.name
) and not self
.driver
and not self
._horse_armor
225 and minetest
.get_item_group(clicker
:get_wielded_item():get_name(), "horse_armor") > 0 then
228 -- Put on armor and take armor from player's inventory
229 local w
= clicker
:get_wielded_item()
230 local armor
= minetest
.get_item_group(w
:get_name(), "horse_armor")
231 self
._horse_armor
= w
:get_name()
232 if not minetest
.settings
:get_bool("creative_mode") then
234 clicker
:set_wielded_item(w
)
237 -- Set horse armor strength
239 local agroups
= self
.object
:get_armor_groups()
240 agroups
.fleshy
= self
.armor
241 self
.object
:set_armor_groups(agroups
)
244 if not self
._naked_texture
then
245 -- Base horse texture without chest or saddle
246 self
._naked_texture
= self
.base_texture
[2]
248 local tex
= horse_extra_texture(self
)
249 self
.base_texture
= tex
250 self
.object
:set_properties({textures
= self
.base_texture
})
254 elseif not self
.driver
and self
._saddle
then
256 self
.object
:set_properties({stepheight
= 1.1})
257 mobs
.attach(self
, clicker
)
259 -- Used to capture horse
260 elseif not self
.driver
and clicker
:get_wielded_item():get_name() ~= "" then
261 mobs
:capture_mob(self
, clicker
, 0, 5, 60, false, nil)
266 on_breed
= function(parent1
, parent2
)
267 local pos
= parent1
.object
:get_pos()
268 local child
= mobs
:spawn_child(pos
, parent1
.name
)
270 local ent_c
= child
:get_luaentity()
271 local p
= math
.random(1, 2)
273 -- Randomly pick one of the parents for the child texture
275 if parent1
._naked_texture
then
276 child_texture
= parent1
._naked_texture
278 child_texture
= parent1
.base_texture
[2]
281 if parent2
._naked_texture
then
282 child_texture
= parent2
._naked_texture
284 child_texture
= parent2
.base_texture
[2]
287 local splt
= string.split(child_texture
, "^")
289 -- Randomly mutate base texture (fur) and markings
290 -- with chance of 1/9 each
292 local markings
= splt
[2]
293 local mutate_base
= math
.random(1, 9)
294 local mutate_markings
= math
.random(1, 9)
295 if mutate_base
== 1 then
296 local b
= math
.random(1, #horse_base
)
299 if mutate_markings
== 1 then
300 local m
= math
.random(1, #horse_markings
)
301 markings
= horse_markings
[m
]
304 if markings
~= "" then
305 child_texture
= child_texture
.. "^" .. markings
308 ent_c
.base_texture
= { "blank.png", child_texture
, "blank.png" }
309 ent_c
._naked_texture
= child_texture
311 child
:set_properties({textures
= ent_c
.base_texture
})
317 mobs
:register_mob("mobs_mc:horse", horse
)
320 local skeleton_horse
= table.copy(horse
)
321 skeleton_horse
.textures
= {{"blank.png", "mobs_mc_horse_skeleton.png", "blank.png"}}
322 skeleton_horse
.drops
= {
323 {name
= mobs_mc
.items
.bone
,
328 skeleton_horse
.sounds
= {
329 random = "skeleton1",
330 death
= "skeletondeath",
331 damage
= "skeletonhurt1",
334 skeleton_horse
.blood_amount
= 0
335 mobs
:register_mob("mobs_mc:skeleton_horse", skeleton_horse
)
338 local zombie_horse
= table.copy(horse
)
339 zombie_horse
.textures
= {{"blank.png", "mobs_mc_horse_zombie.png", "blank.png"}}
340 zombie_horse
.drops
= {
341 {name
= mobs_mc
.items
.rotten_flesh
,
346 zombie_horse
.sounds
= {
347 random = "mobs_mc_zombie_idle",
348 war_cry
= "mobs_mc_zombie_idle",
349 death
= "mobs_mc_zombie_death",
350 damage
= "mobs_mc_zombie_hurt",
353 mobs
:register_mob("mobs_mc:zombie_horse", zombie_horse
)
356 local d
= 0.86 -- donkey scale
357 local donkey
= table.copy(horse
)
358 donkey
.textures
= {{"blank.png", "mobs_mc_donkey.png", "blank.png"}}
361 stand_start
= 0, stand_end
= 0,
362 walk_start
= 0, walk_end
= 40,
364 donkey
.visual_size
= { x
=horse
.visual_size
.x
*d
, y
=horse
.visual_size
.y
*d
}
365 donkey
.collisionbox
= {
366 horse
.collisionbox
[1] * d
,
367 horse
.collisionbox
[2] * d
,
368 horse
.collisionbox
[3] * d
,
369 horse
.collisionbox
[4] * d
,
370 horse
.collisionbox
[5] * d
,
371 horse
.collisionbox
[6] * d
,
374 donkey
.jump_height
= 3.75 -- can clear 1 block height
376 mobs
:register_mob("mobs_mc:donkey", donkey
)
380 local mule
= table.copy(donkey
)
381 mule
.textures
= {{"blank.png", "mobs_mc_mule.png", "blank.png"}}
382 mule
.visual_size
= { x
=horse
.visual_size
.x
*m
, y
=horse
.visual_size
.y
*m
}
383 mule
.collisionbox
= {
384 horse
.collisionbox
[1] * m
,
385 horse
.collisionbox
[2] * m
,
386 horse
.collisionbox
[3] * m
,
387 horse
.collisionbox
[4] * m
,
388 horse
.collisionbox
[5] * m
,
389 horse
.collisionbox
[6] * m
,
391 mobs
:register_mob("mobs_mc:mule", mule
)
393 --===========================
395 mobs
:spawn_specific("mobs_mc:horse", mobs_mc
.spawn
.grassland_savanna
, {"air"}, 0, minetest
.LIGHT_MAX
+1, 30, 15000, 12, mobs_mc
.spawn_height
.water
+3, mobs_mc
.spawn_height
.overworld_max
)
396 mobs
:spawn_specific("mobs_mc:donkey", mobs_mc
.spawn
.grassland_savanna
, {"air"}, 0, minetest
.LIGHT_MAX
+1, 30, 15000, 12, mobs_mc
.spawn_height
.water
+3, mobs_mc
.spawn_height
.overworld_max
)
399 mobs
:alias_mob("mobs:horse", "mobs_mc:horse")
402 mobs
:register_egg("mobs_mc:horse", S("Horse"), "mobs_mc_spawn_icon_horse.png", 0)
403 mobs
:register_egg("mobs_mc:skeleton_horse", S("Skeleton Horse"), "mobs_mc_spawn_icon_horse_skeleton.png", 0)
404 mobs
:register_egg("mobs_mc:zombie_horse", S("Zombie Horse"), "mobs_mc_spawn_icon_horse_zombie.png", 0)
405 mobs
:register_egg("mobs_mc:donkey", S("Donkey"), "mobs_mc_spawn_icon_donkey.png", 0)
406 mobs
:register_egg("mobs_mc:mule", S("Mule"), "mobs_mc_spawn_icon_mule.png", 0)
409 if minetest
.settings
:get_bool("log_mods") then
410 minetest
.log("action", "MC Horse loaded")