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 table.insert(horse_textures
, {
75 horse_base
[b
] .. horse_markings
[m
], -- base texture + markings and optional armor
76 "blank.png", -- saddle
85 mesh
= "mobs_mc_horse.b3d",
86 visual_size
= {x
=3.0, y
=3.0},
87 collisionbox
= {-0.69825, -0.01, -0.69825, 0.69825, 1.59, 0.69825},
99 textures
= horse_textures
,
104 follow
= mobs_mc
.follow
.horse
,
111 makes_footstep_sound
= true,
113 jump_height
= 5.75, -- can clear 2.5 blocks
115 {name
= mobs_mc
.items
.leather
,
121 do_custom
= function(self
, dtime
)
123 -- set needed values if not already present
124 if not self
._regentimer
then
129 self
.max_speed_forward
= 7
130 self
.max_speed_reverse
= 2
132 self
.terrain_type
= 3
133 self
.driver_attach_at
= {x
= 0, y
= 7.5, z
= -1.75}
134 self
.driver_eye_offset
= {x
= 0, y
= 3, z
= 0}
135 self
.driver_scale
= {x
= 1/self
.visual_size
.x
, y
= 1/self
.visual_size
.y
}
138 -- Slowly regenerate health
139 self
._regentimer
= self
._regentimer
+ dtime
140 if self
._regentimer
>= 4 then
141 if self
.health
< self
.hp_max
then
142 self
.health
= self
.health
+ 1
147 -- if driver present allow control of horse
150 mobs
.drive(self
, "walk", "stand", false, dtime
)
152 return false -- skip rest of mob functions
158 on_die
= function(self
, pos
)
160 -- drop saddle when horse is killed while riding
162 minetest
.add_item(pos
, mobs_mc
.items
.saddle
)
164 -- also detach from horse properly
166 mobs
.detach(self
.driver
, {x
= 1, y
= 0, z
= 1})
171 on_rightclick
= function(self
, clicker
)
173 -- make sure player is clicking
174 if not clicker
or not clicker
:is_player() then
178 local item
= clicker
:get_wielded_item()
179 if can_breed(self
.name
) and (item
:get_name() == mobs_mc
.items
.golden_apple
or item
:get_name() == mobs_mc
.items
.golden_carrot
) then
180 -- Breed horse with golden apple or golden carrot
181 if mobs
:feed_tame(self
, clicker
, 1, true, false) then return end
183 -- Feed/tame with anything else
184 -- TODO: Different health bonus for feeding
185 if mobs
:feed_tame(self
, clicker
, 1, false, true) then return end
186 if mobs
:protect(self
, clicker
) then return end
188 -- Make sure tamed horse is mature and being clicked by owner only
189 if self
.tamed
and not self
.child
and self
.owner
== clicker
:get_player_name() then
191 local inv
= clicker
:get_inventory()
193 -- detatch player already riding horse
194 if self
.driver
and clicker
== self
.driver
then
196 mobs
.detach(clicker
, {x
= 1, y
= 0, z
= 1})
198 -- Put on saddle if tamed
199 elseif not self
.driver
and not self
._saddle
200 and clicker
:get_wielded_item():get_name() == mobs_mc
.items
.saddle
then
202 -- Put on saddle and take saddle from player's inventory
203 local w
= clicker
:get_wielded_item()
205 if not minetest
.settings
:get_bool("creative_mode") then
207 clicker
:set_wielded_item(w
)
211 if not self
._naked_texture
then
212 -- Base horse texture without chest or saddle
213 self
._naked_texture
= self
.base_texture
[2]
215 local tex
= horse_extra_texture(self
)
216 self
.base_texture
= tex
217 self
.object
:set_properties({textures
= self
.base_texture
})
219 -- Put on horse armor if tamed
220 elseif can_equip_horse_armor(self
.name
) and not self
.driver
and not self
._horse_armor
221 and minetest
.get_item_group(clicker
:get_wielded_item():get_name(), "horse_armor") > 0 then
224 -- Put on armor and take armor from player's inventory
225 local w
= clicker
:get_wielded_item()
226 local armor
= minetest
.get_item_group(w
:get_name(), "horse_armor")
227 self
._horse_armor
= w
:get_name()
228 if not minetest
.settings
:get_bool("creative_mode") then
230 clicker
:set_wielded_item(w
)
233 -- Set horse armor strength
235 local agroups
= self
.object
:get_armor_groups()
236 agroups
.fleshy
= self
.armor
237 self
.object
:set_armor_groups(agroups
)
240 if not self
._naked_texture
then
241 -- Base horse texture without chest or saddle
242 self
._naked_texture
= self
.base_texture
[2]
244 local tex
= horse_extra_texture(self
)
245 self
.base_texture
= tex
246 self
.object
:set_properties({textures
= self
.base_texture
})
250 elseif not self
.driver
and self
._saddle
then
252 self
.object
:set_properties({stepheight
= 1.1})
253 mobs
.attach(self
, clicker
)
255 -- Used to capture horse
256 elseif not self
.driver
and clicker
:get_wielded_item():get_name() ~= "" then
257 mobs
:capture_mob(self
, clicker
, 0, 5, 60, false, nil)
262 on_breed
= function(parent1
, parent2
)
263 local pos
= parent1
.object
:get_pos()
264 local child
= mobs
:spawn_child(pos
, parent1
.name
)
266 local ent_c
= child
:get_luaentity()
267 local p
= math
.random(1, 2)
269 ent_c
.base_texture
= parent1
.base_texture
271 ent_c
.base_texture
= parent2
.base_texture
273 child
:set_properties({textures
= ent_c
.base_texture
})
279 mobs
:register_mob("mobs_mc:horse", horse
)
282 local skeleton_horse
= table.copy(horse
)
283 skeleton_horse
.textures
= {{"blank.png", "mobs_mc_horse_skeleton.png", "blank.png"}}
284 skeleton_horse
.drops
= {
285 {name
= mobs_mc
.items
.bone
,
290 skeleton_horse
.sounds
= {
291 random = "skeleton1",
292 death
= "skeletondeath",
293 damage
= "skeletonhurt1",
296 skeleton_horse
.blood_amount
= 0
297 mobs
:register_mob("mobs_mc:skeleton_horse", skeleton_horse
)
300 local zombie_horse
= table.copy(horse
)
301 zombie_horse
.textures
= {{"blank.png", "mobs_mc_horse_zombie.png", "blank.png"}}
302 zombie_horse
.drops
= {
303 {name
= mobs_mc
.items
.rotten_flesh
,
308 zombie_horse
.sounds
= {
309 random = "mobs_mc_zombie_idle",
310 war_cry
= "mobs_mc_zombie_idle",
311 death
= "mobs_mc_zombie_death",
312 damage
= "mobs_mc_zombie_hurt",
315 mobs
:register_mob("mobs_mc:zombie_horse", zombie_horse
)
318 local d
= 0.86 -- donkey scale
319 local donkey
= table.copy(horse
)
320 donkey
.textures
= {{"blank.png", "mobs_mc_donkey.png", "blank.png"}}
323 stand_start
= 0, stand_end
= 0,
324 walk_start
= 0, walk_end
= 40,
326 donkey
.visual_size
= { x
=horse
.visual_size
.x
*d
, y
=horse
.visual_size
.y
*d
}
327 donkey
.collisionbox
= {
328 horse
.collisionbox
[1] * d
,
329 horse
.collisionbox
[2] * d
,
330 horse
.collisionbox
[3] * d
,
331 horse
.collisionbox
[4] * d
,
332 horse
.collisionbox
[5] * d
,
333 horse
.collisionbox
[6] * d
,
336 donkey
.jump_height
= 3.75 -- can clear 1 block height
338 mobs
:register_mob("mobs_mc:donkey", donkey
)
342 local mule
= table.copy(donkey
)
343 mule
.textures
= {{"blank.png", "mobs_mc_mule.png", "blank.png"}}
344 mule
.visual_size
= { x
=horse
.visual_size
.x
*m
, y
=horse
.visual_size
.y
*m
}
345 mule
.collisionbox
= {
346 horse
.collisionbox
[1] * m
,
347 horse
.collisionbox
[2] * m
,
348 horse
.collisionbox
[3] * m
,
349 horse
.collisionbox
[4] * m
,
350 horse
.collisionbox
[5] * m
,
351 horse
.collisionbox
[6] * m
,
353 mobs
:register_mob("mobs_mc:mule", mule
)
355 --===========================
357 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
)
358 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
)
361 mobs
:alias_mob("mobs:horse", "mobs_mc:horse")
364 mobs
:register_egg("mobs_mc:horse", S("Horse"), "mobs_mc_spawn_icon_horse.png", 0)
365 mobs
:register_egg("mobs_mc:skeleton_horse", S("Skeleton Horse"), "mobs_mc_spawn_icon_horse_skeleton.png", 0)
366 mobs
:register_egg("mobs_mc:zombie_horse", S("Zombie Horse"), "mobs_mc_spawn_icon_horse_zombie.png", 0)
367 mobs
:register_egg("mobs_mc:donkey", S("Donkey"), "mobs_mc_spawn_icon_donkey.png", 0)
368 mobs
:register_egg("mobs_mc:mule", S("Mule"), "mobs_mc_spawn_icon_mule.png", 0)
371 if minetest
.settings
:get_bool("log_mods") then
372 minetest
.log("action", "MC Horse loaded")