2014-06-20 13:17:17 +02:00
|
|
|
|
|
|
|
|
|
|
|
--[[
|
|
|
|
minetest.register_abm({
|
|
|
|
nodenames = {"air"},
|
|
|
|
interval = 10,
|
|
|
|
chance = 0.1,
|
|
|
|
action = function(pos, timer)
|
|
|
|
minetest.env:clear_objects()
|
|
|
|
end,
|
|
|
|
})
|
|
|
|
]]
|
|
|
|
|
2018-03-23 19:02:45 +01:00
|
|
|
|
|
|
|
--[[
|
|
|
|
Exportation des animations depuis blender:
|
|
|
|
il faut avoir la config suivante:
|
|
|
|
+ export normals
|
|
|
|
+ flip normals
|
|
|
|
+ export UV coords
|
|
|
|
+ export skin weight
|
|
|
|
- apply modifier
|
|
|
|
+ export armature bones
|
|
|
|
+ export rest animation
|
|
|
|
+ export animations
|
|
|
|
+ include frame rate
|
|
|
|
]]
|
|
|
|
|
|
|
|
local patroller = {
|
|
|
|
hp_max = 400,
|
2014-06-20 13:17:17 +02:00
|
|
|
physical = true,
|
|
|
|
collisionbox = {-2.5,-7,-2.5, 2.5,4,2.5},
|
|
|
|
visual = "mesh",
|
2018-03-23 19:02:45 +01:00
|
|
|
mesh = "patroller.x",
|
|
|
|
textures = {"technology_patroller.png"},
|
|
|
|
--automatic_rotate = true,
|
|
|
|
--makes_footstep_sound = true,
|
|
|
|
--spritediv = {x=1, y=1},
|
|
|
|
--initial_sprite_basepos = {x=0, y=0},
|
|
|
|
--is_visible = true,
|
|
|
|
can_punch = true,
|
2014-06-20 13:17:17 +02:00
|
|
|
|
|
|
|
driver = nil,
|
2018-03-23 19:02:45 +01:00
|
|
|
front_vel_target = 0, -- 0 is no speed, 1 is maximum speed
|
|
|
|
vert_vel_target = 0,
|
|
|
|
|
|
|
|
max_front_vel = 10,
|
|
|
|
max_vert_vel = 7,
|
2014-06-20 13:17:17 +02:00
|
|
|
}
|
|
|
|
|
2018-03-23 19:02:45 +01:00
|
|
|
local FPS = 15 -- frame per second for animations
|
|
|
|
local WEAPONS = minetest.get_modpath("firearms_guns") or false -- auto enable weapon support
|
|
|
|
|
|
|
|
function patroller:on_punch(puncher, time_from_last_punch, tool_capabilities, direction)
|
|
|
|
if self.driver and puncher == self.driver then
|
|
|
|
self:fire(self.driver:get_look_dir())
|
|
|
|
end
|
|
|
|
--[[
|
|
|
|
self.object:remove()
|
|
|
|
if puncher and puncher:is_player() then
|
|
|
|
puncher:get_inventory():add_item("main", "technology:patroller")
|
|
|
|
end
|
|
|
|
]]
|
|
|
|
end
|
|
|
|
|
|
|
|
function patroller:fire(direction)
|
|
|
|
if WEAPONS then
|
|
|
|
local p = self.object:getpos()
|
|
|
|
p.y = p.y-7
|
|
|
|
firearmslib.fire("technology:air_canon", p, direction)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if WEAPONS then
|
|
|
|
--[[
|
|
|
|
firearmslib.register_bullet("technology:air_canon_ammo", {
|
|
|
|
description = "5mm air canon amunition";
|
|
|
|
inventory_image = "firearms_bullet_556.png";
|
|
|
|
damage = 12;
|
|
|
|
power = 5;
|
|
|
|
gravity = 0;
|
|
|
|
});
|
|
|
|
|
|
|
|
firearmslib.register_firearm("technology:air_canon", {
|
|
|
|
description = "5mm air canon";
|
|
|
|
inventory_image = "firearms_m4.png";
|
|
|
|
bullets = "technology:air_canon_ammo";
|
|
|
|
clip_size = 42;
|
|
|
|
spread = 0.035;
|
|
|
|
burst = 3;
|
|
|
|
burst_interval = 0.15;
|
|
|
|
wield_scale = {x=2,y=2,z=2};
|
|
|
|
crosshair_image = "firearms_crosshair_rifle.png";
|
|
|
|
hud_image = "firearms_m4_hud.png";
|
|
|
|
sounds = {
|
|
|
|
shoot = "firearms_m4_shot";
|
|
|
|
empty = "firearms_default_empty";
|
|
|
|
reload = "firearms_rifle_reload";
|
|
|
|
};
|
|
|
|
});
|
|
|
|
]]
|
|
|
|
|
|
|
|
firearmslib.register_bullet("technology:air_canon_ammo", {
|
|
|
|
description = "Rocket";
|
|
|
|
inventory_image = "firearms_rocket.png";
|
|
|
|
texture = "firearms_rocket_entity.png";
|
|
|
|
damage = 10;
|
|
|
|
power = 5;
|
|
|
|
speed = 25;
|
|
|
|
gravity = 0;
|
|
|
|
explosion_range = 2.5;
|
|
|
|
explosion_damage = 6;
|
|
|
|
leaves_smoke = true;
|
|
|
|
on_destroy = firearmslib.on_destroy_explode;
|
|
|
|
});
|
|
|
|
|
|
|
|
firearmslib.register_firearm("technology:air_canon", {
|
|
|
|
description = "Bazooka";
|
|
|
|
inventory_image = "firearms_bazooka.png";
|
|
|
|
bullets = "technology:air_canon_ammo";
|
|
|
|
clip_size = 5;
|
|
|
|
spread = 0.035;
|
|
|
|
wield_scale = {x=3,y=3,z=3};
|
|
|
|
crosshair_image = "firearms_crosshair_rlauncher.png";
|
|
|
|
hud_image = "firearms_bazooka_hud.png";
|
|
|
|
sounds = {
|
|
|
|
shoot = "firearms_m79_shot"; -- TODO: Find a better sound
|
|
|
|
empty = "firearms_default_empty";
|
|
|
|
--reload = "firearms_default_reload";
|
|
|
|
};
|
|
|
|
});
|
|
|
|
end
|
|
|
|
|
|
|
|
function patroller:on_rightclick(clicker)
|
2014-06-20 13:17:17 +02:00
|
|
|
if not clicker or not clicker:is_player() then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
if self.driver and clicker == self.driver then
|
|
|
|
self.driver = nil
|
2018-03-23 19:02:45 +01:00
|
|
|
self.object:set_animation({x=54, y=54}, FPS, 0)
|
2014-06-20 13:17:17 +02:00
|
|
|
local pos = self.object:getpos()
|
2018-03-23 19:02:45 +01:00
|
|
|
local yaw = self.object:getyaw()
|
|
|
|
pos.x = pos.x - 4*math.cos(yaw)
|
|
|
|
pos.y = pos.y - 3
|
|
|
|
pos.z = pos.z - 4*math.sin(yaw)
|
2014-06-20 13:17:17 +02:00
|
|
|
clicker:set_detach()
|
2018-03-23 19:02:45 +01:00
|
|
|
default.player_set_animation(clicker, "stand" , 30)
|
|
|
|
minetest.after(0.2, function()
|
|
|
|
clicker:setpos(pos)
|
|
|
|
end)
|
|
|
|
--self.object:setvelocity({x=0, y=0, z=0})
|
|
|
|
self.front_vel_target = 0
|
|
|
|
self.vert_vel_target = 0
|
2014-06-20 13:17:17 +02:00
|
|
|
elseif not self.driver then
|
|
|
|
self.driver = clicker
|
2018-03-23 19:02:45 +01:00
|
|
|
clicker:set_attach(self.object, "", {x=0,y=0,z=10}, {x=0,y=0,z=-10})
|
|
|
|
default.player_set_animation(clicker, "sit" , 30)
|
|
|
|
self.object:set_animation({x=60, y=60}, FPS, 0)
|
2014-06-20 13:17:17 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-03-23 19:02:45 +01:00
|
|
|
function patroller:on_activate(staticdata, dtime_s)
|
2014-06-20 13:17:17 +02:00
|
|
|
self.object:set_armor_groups({immortal=1})
|
2018-03-23 19:02:45 +01:00
|
|
|
--[[
|
2014-06-20 13:17:17 +02:00
|
|
|
if staticdata then
|
|
|
|
self.v = tonumber(staticdata)
|
|
|
|
end
|
2018-03-23 19:02:45 +01:00
|
|
|
]]
|
2014-06-20 13:17:17 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
|
2018-03-23 19:02:45 +01:00
|
|
|
function patroller:get_staticdata()
|
|
|
|
return "" --tostring(v)
|
2014-06-20 13:17:17 +02:00
|
|
|
end
|
|
|
|
|
2018-03-23 19:02:45 +01:00
|
|
|
|
|
|
|
|
|
|
|
local command_increment = 0.05
|
|
|
|
hunter_step_tick = 0
|
|
|
|
|
|
|
|
function patroller:on_step(dtime)
|
2014-06-20 13:17:17 +02:00
|
|
|
-- make fire if damages are over 50%
|
|
|
|
-- explode when hp is under 5
|
2018-03-23 19:02:45 +01:00
|
|
|
hunter_step_tick = hunter_step_tick+dtime
|
2014-06-20 13:17:17 +02:00
|
|
|
if self.object:get_hp() < 5 then
|
|
|
|
explosion(self.object:getpos(), 30)
|
|
|
|
end
|
2018-03-23 19:02:45 +01:00
|
|
|
|
|
|
|
local command = false
|
|
|
|
--[[
|
|
|
|
if math.random(1,10) == 1 then
|
|
|
|
local yaw = self.object:getyaw()
|
|
|
|
local dir = {
|
|
|
|
x = math.cos(yaw),
|
|
|
|
y = 0,
|
|
|
|
z = math.sin(yaw),
|
|
|
|
}
|
|
|
|
self:fire(dir)
|
|
|
|
end
|
|
|
|
]]
|
|
|
|
|
2014-06-20 13:17:17 +02:00
|
|
|
if self.driver then
|
|
|
|
local ctrl = self.driver:get_player_control()
|
2018-03-23 19:02:45 +01:00
|
|
|
if hunter_step_tick > 0.1 then
|
|
|
|
hunter_step_tick = 0
|
|
|
|
-- have user commands
|
|
|
|
if ctrl.up and self.front_vel_target < 1 then
|
|
|
|
self.front_vel_target = self.front_vel_target + command_increment
|
|
|
|
command = true
|
|
|
|
elseif ctrl.down and self.front_vel_target > -0.05 then
|
|
|
|
self.front_vel_target = self.front_vel_target - command_increment
|
|
|
|
command = true
|
|
|
|
end
|
|
|
|
if ctrl.jump and self.vert_vel_target < 1 then
|
|
|
|
self.vert_vel_target = self.vert_vel_target + command_increment
|
|
|
|
command = true
|
|
|
|
elseif ctrl.sneak and self.vert_vel_target > -1 then
|
|
|
|
self.vert_vel_target = self.vert_vel_target - command_increment
|
|
|
|
command = true
|
|
|
|
end
|
2014-06-20 13:17:17 +02:00
|
|
|
end
|
|
|
|
if ctrl.left then
|
|
|
|
self.object:setyaw(self.object:getyaw()+math.pi/120+dtime*math.pi/120)
|
2018-03-23 19:02:45 +01:00
|
|
|
self.object:set_animation({x=5, y=5}, FPS, 0)
|
|
|
|
command = true
|
|
|
|
elseif ctrl.right then
|
2014-06-20 13:17:17 +02:00
|
|
|
self.object:setyaw(self.object:getyaw()-math.pi/120-dtime*math.pi/120)
|
2018-03-23 19:02:45 +01:00
|
|
|
self.object:set_animation({x=10, y=10}, FPS, 0)
|
|
|
|
command = true
|
|
|
|
else
|
|
|
|
--self.object:set_animation({x=60, y=60}, FPS, 0)
|
2014-06-20 13:17:17 +02:00
|
|
|
end
|
2018-03-23 19:02:45 +01:00
|
|
|
else
|
|
|
|
self.front_vel_target = 0
|
|
|
|
self.vert_vel_target = 0
|
|
|
|
--command = true
|
2014-06-20 13:17:17 +02:00
|
|
|
self.object:setvelocity({x=0, y=0, z=0})
|
2018-03-23 19:02:45 +01:00
|
|
|
self.object:set_animation({x=54, y=54}, FPS, 0)
|
2014-06-20 13:17:17 +02:00
|
|
|
end
|
2018-03-23 19:02:45 +01:00
|
|
|
|
|
|
|
if command then
|
|
|
|
local yaw = self.object:getyaw()
|
|
|
|
self.object:setvelocity({
|
|
|
|
x = self.front_vel_target * self.max_front_vel * math.cos(yaw),
|
|
|
|
y = self.vert_vel_target * self.max_vert_vel,
|
|
|
|
z = self.front_vel_target * self.max_front_vel * math.sin(yaw),
|
|
|
|
})
|
|
|
|
if self.vert_vel_target < 0 then
|
|
|
|
local frame = 40-5*self.vert_vel_target + 0.5
|
|
|
|
self.object:set_animation({x=frame, y=frame}, FPS, 0)
|
|
|
|
else
|
|
|
|
local frame = 30+5*self.vert_vel_target - 0.5
|
|
|
|
self.object:set_animation({x=frame, y=frame}, FPS, 0)
|
|
|
|
end
|
2014-06-20 13:17:17 +02:00
|
|
|
end
|
2018-03-23 19:02:45 +01:00
|
|
|
--[[
|
|
|
|
local Kf = 3.1
|
|
|
|
local Kv = 3.1
|
|
|
|
local v = self.object:getvelocity()
|
|
|
|
local yaw = self.object:getyaw()
|
|
|
|
local front_vel = v.x * -math.sin(yaw) + v.z * math.cos(yaw)
|
|
|
|
local vert_vel = v.y
|
|
|
|
local front_acc = Kf*(self.max_front_vel*self.front_vel_target - front_vel)
|
|
|
|
local vert_acc = Kv*(self.max_vert_vel*self.vert_vel_target - vert_vel)
|
|
|
|
self.object:setacceleration({x=-front_acc*math.sin(yaw), y=vert_acc, z=front_acc*math.cos(yaw)})
|
|
|
|
]]
|
|
|
|
--print("command "..self.front_vel_target.." "..self.vert_vel_target)
|
|
|
|
--print("command "..front_acc.." "..vert_acc)
|
|
|
|
|
2014-06-20 13:17:17 +02:00
|
|
|
end
|
|
|
|
|
2018-03-23 19:02:45 +01:00
|
|
|
minetest.register_entity("technology:patroller", patroller)
|
2014-06-20 13:17:17 +02:00
|
|
|
|
|
|
|
|
2018-03-23 19:02:45 +01:00
|
|
|
minetest.register_craftitem("technology:patroller", {
|
|
|
|
description = "patroller flying",
|
2014-06-20 13:17:17 +02:00
|
|
|
inventory_image = "hunter_inv.png",
|
|
|
|
wield_image = "hunter_inv.png",
|
|
|
|
wield_scale = {x=2, y=2, z=1},
|
|
|
|
liquids_pointable = true,
|
|
|
|
|
|
|
|
on_place = function(itemstack, placer, pointed_thing)
|
|
|
|
if pointed_thing.type ~= "node" then
|
|
|
|
return
|
|
|
|
end
|
2018-03-23 19:02:45 +01:00
|
|
|
print("patroller added !!!")
|
2014-06-20 13:17:17 +02:00
|
|
|
pointed_thing.under.y = pointed_thing.under.y+2
|
2018-03-23 19:02:45 +01:00
|
|
|
minetest.env:add_entity(pointed_thing.under, "technology:patroller")
|
2014-06-20 13:17:17 +02:00
|
|
|
itemstack:take_item()
|
|
|
|
return itemstack
|
|
|
|
end,
|
|
|
|
})
|
|
|
|
|
2018-03-23 19:02:45 +01:00
|
|
|
technology.register_plan("PATROLLER", "technology:patroller", "technology_plan_patroller.png", {
|
|
|
|
"technic:hv_transformer",
|
|
|
|
"technic:mv_transformer",
|
|
|
|
"technic:motor 8",
|
|
|
|
"technology:wire 10",
|
|
|
|
"default:steel_ingot 6",
|
|
|
|
"default:silver_ingot 1",
|
|
|
|
"default:mese 1",
|
|
|
|
"firearms:shell_12 1",
|
|
|
|
})
|
|
|
|
|