-- =================================================================== local codermobs_enable_thismob = minetest.setting_getbool ("codermobs_enable_whinny") -- =================================================================== local function is_ground (pos) local nn = minetest.get_node (pos).name return minetest.get_item_group (nn, "crumbly") ~= 0 or minetest.get_item_group (nn, "cracky") ~= 0 or minetest.get_item_group (nn, "choppy") ~= 0 or minetest.get_item_group (nn, "snappy") ~= 0 end -- =================================================================== local function get_sign(i) if i == 0 then return 0 else return i/math.abs(i) end end -- =================================================================== local function get_velocity (v, yaw, y) local x = math.cos(yaw)*v local z = math.sin(yaw)*v return {x=x, y=y, z=z} end -- =================================================================== local function get_v(v) return math.sqrt(v.x^2+v.z^2) end -- =================================================================== local function register_wildhorse (basename) local obj_name = "whinny:" .. basename whinny:register_mob (obj_name, { type = "animal", hp_min = 5, hp_max = 7, -- collisionbox = {-0.4, -0.01, -0.4, 0.4, 1, 0.4}, collisionbox = { -0.6, -0.015, -0.6, 0.6, 1.5, 0.6 } , visual_size = { x=1.5, y=1.5, } , available_textures = { total = 1, texture_1 = { "whinny_horse_"..basename..".png" } , }, visual = "mesh", mesh = "horse_model.x", makes_footstep_sound = true, walk_velocity = 1, armor = 200, drops = { { name = "whinny:meat_raw" , chance = 1 , min = 2 , max = 3 , } , } , drawtype = "front", water_damage = 1, lava_damage = 5, light_damage = 0, sounds = { random = "", }, animation = { speed_normal = 15, stand_start = 25, stand_end = 75, walk_start = 75, walk_end = 100, }, follow = "farming:wheat", view_range = 5, on_rightclick = function (self, clicker) local item = clicker:get_wielded_item() if item:get_name() == "farming:wheat" then minetest.add_entity (self.object:getpos(), "whinny:" .. basename .. "_tame") if not minetest.setting_getbool ("creative_mode") then item:take_item() clicker:set_wielded_item (item) end self.object:remove() end end, jump = true, step=1, passive = true, }) if codermobs_enable_thismob then whinny:register_spawn (obj_name, { "default:dirt_with_dry_grass" , "default:dirt_with_grass" , }, 20, -1, 250000, 1, 31000 ) end end -- =================================================================== local function register_basehorse (name, craftitem, horse) if craftitem ~= nil then function craftitem.on_place (itemstack, placer, pointed_thing) if pointed_thing.above then minetest.env:add_entity (pointed_thing.above, name) if not minetest.setting_getbool("creative_mode") then itemstack:take_item() end end return itemstack end minetest.register_craftitem (name, craftitem) end horse.v = 0 horse.driver = nil function horse:set_animation(type) if not self.animation then return end if not self.animation.current then self.animation.current = "" end if type == "stand" and self.animation.current ~= "stand" then if self.animation.stand_start and self.animation.stand_end and self.animation.speed_normal then self.object:set_animation( {x=self.animation.stand_start,y=self.animation.stand_end}, self.animation.speed_normal * 0.6, 0 ) self.animation.current = "stand" end elseif type == "walk" and self.animation.current ~= "walk" then if self.animation.walk_start and self.animation.walk_end and self.animation.speed_normal then self.object:set_animation( {x=self.animation.walk_start,y=self.animation.walk_end}, self.animation.speed_normal * 3, 0 ) self.animation.current = "walk" end end end function horse:on_step(dtime) local p = self.object:getpos() p.y = p.y - 0.1 local on_ground = is_ground(p) self.v = get_v(self.object:getvelocity())*get_sign(self.v) -- driver controls if self.driver then local ctrl = self.driver:get_player_control() -- rotation (the faster we go, the less we rotate) if ctrl.left then self.object:setyaw(self.object:getyaw()+2*(1.5-math.abs(self.v/self.max_speed))*math.pi/90 +dtime*math.pi/90) end if ctrl.right then self.object:setyaw(self.object:getyaw()-2*(1.5-math.abs(self.v/self.max_speed))*math.pi/90 -dtime*math.pi/90) end -- jumping (only if on ground) if ctrl.jump and on_ground then local v = self.object:getvelocity() local vel = 3 if name == "whinny:rainbow_tame" then vel = 30 end -- v.y = (self.jump_speed or 3) v.y = vel self.object:setvelocity (v) end -- forwards/backwards if ctrl.up then self.v = self.v + self.forward_boost elseif ctrl.down then self.v = self.v - 0.3 elseif on_ground then if math.abs(self.v) < 1 then self.v = 0 else self.v = self.v * 0.9 end end else if math.abs(self.v) < 1 then self.v = 0 else self.v = self.v * 0.95 end end if self.v == 0 then self.object:setvelocity({x=0,y=0,z=0}) self:set_animation("stand") return else self:set_animation("walk") end -- make sure we don't go past the limit if math.abs(self.v) > self.max_speed then self.v = self.max_speed*get_sign(self.v) end local p = self.object:getpos() p.y = p.y+1 if not is_ground(p) then if minetest.registered_nodes[minetest.get_node(p).name].walkable then self.v = 0 end self.object:setacceleration({x=0, y=-10, z=0}) self.object:setvelocity(get_velocity(self.v, self.object:getyaw(), self.object:getvelocity().y)) else self.object:setacceleration({x=0, y=0, z=0}) -- falling if math.abs(self.object:getvelocity().y) < 1 then local pos = self.object:getpos() pos.y = math.floor(pos.y)+0.5 self.object:setpos(pos) self.object:setvelocity(get_velocity(self.v, self.object:getyaw(), 0)) else self.object:setvelocity(get_velocity(self.v, self.object:getyaw(), self.object:getvelocity().y)) end end if self.object:getvelocity().y > 0.1 then local yaw = self.object:getyaw() if self.drawtype == "side" then yaw = yaw+(math.pi/2) end local x = math.sin(yaw) * -2 local z = math.cos(yaw) * 2 if minetest.get_item_group(minetest.get_node(self.object:getpos()).name, "water") ~= 0 then self.object:setacceleration({x = x, y = 2, z = z}) else self.object:setacceleration({x = x, y = -5, z = z}) end else if minetest.get_item_group(minetest.get_node(self.object:getpos()).name, "water") ~= 0 then self.object:setacceleration({x = 0, y = 2, z = 0}) else self.object:setacceleration({x = 0, y = -5, z = 0}) end end end function horse:on_rightclick(clicker) if not clicker or not clicker:is_player() then return end if self.driver and clicker == self.driver then self.driver = nil clicker:set_detach() elseif not self.driver then self.driver = clicker clicker:set_attach(self.object, "", {x=0,y=15,z=0}, {x=0,y=90,z=0}) self.object:setyaw(clicker:get_look_yaw()) end end function horse:on_activate(staticdata, dtime_s) self.object:set_armor_groups({immortal=1}) if staticdata then self.v = tonumber(staticdata) end end function horse:get_staticdata() return tostring (self.v) end function horse:on_punch (puncher, time_from_last_punch, tool_capabilities, direction) self.object:remove() if puncher and puncher:is_player() then puncher:get_inventory():add_item("main", name) end end minetest.register_entity (name, horse) end -- =================================================================== local function register_tamehorse (basename, description) register_basehorse ("whinny:" .. basename .. "_tame", { description = description , inventory_image = "whinny_horse_" .. basename .. "_inventory.png" , } , { physical = true , -- Old settings: -- collisionbox = {-0.4, -0.01, -0.4, 0.4, 1, 0.4}, -- visual_size = {x=1,y=1}, collisionbox = { -0.6, -0.015, -0.6, 0.6, 1.5, 0.6 } , visual_size = { x=1.5, y=1.5, } , visual = "mesh", stepheight = 1.1, mesh = "horseh1_model.x", textures = { "whinny_horse_" .. basename .. ".png" } , animation = { speed_normal = 10, stand_start = 0, stand_end = 50, walk_start = 75, walk_end = 98, }, max_speed = 7, forward_boost = 2.33, jump_boost = 4 }) end -- =================================================================== register_tamehorse ("brown" , "Brown Horse" ) register_wildhorse ("brown" ) register_tamehorse ("pegasus" , "White Horse" ) register_wildhorse ("pegasus" ) register_tamehorse ("mred" , "Mr. Ed" ) register_wildhorse ("mred" ) register_tamehorse ("rainbow" , "Rainbow Horse" ) register_wildhorse ("rainbow" ) register_tamehorse ("blue" , "Blue Horse" ) register_wildhorse ("blue" ) register_tamehorse ("arabic" , "Black Horse" ) register_wildhorse ("arabic" )