Kalabasa's initial commit
parent
a9ac480dcd
commit
27abca74b7
|
@ -0,0 +1,17 @@
|
|||
Minetest Defense [minetest_defense]
|
||||
===================================
|
||||
|
||||
To use this game with Minetest, insert this repository as
|
||||
/games/minetest_defense
|
||||
in the Minetest Engine.
|
||||
|
||||
The Minetest Engine can be found in:
|
||||
https://github.com/minetest/minetest/
|
||||
|
||||
Compatibility
|
||||
--------------
|
||||
Minetest Defense is based on minetest_game 0.4.11, and should be compatible with Minetest 0.4.11.
|
||||
|
||||
License
|
||||
-------
|
||||
Most of the default minetest_game files are untouched. License of these files is in minetest_game-license.md.
|
|
@ -4,3 +4,6 @@ mgv6_spflags = biomeblend, jungles
|
|||
movement_liquid_sink = 25
|
||||
movement_liquid_fluidity = 0.8
|
||||
movement_liquid_fluidity_smooth = 2
|
||||
|
||||
creative_mode = false
|
||||
time_speed = 144
|
|
@ -1,25 +1,7 @@
|
|||
The main game for the Minetest game engine [minetest_game]
|
||||
==========================================================
|
||||
License of minetest_game files
|
||||
==============================
|
||||
|
||||
To use this game with Minetest, insert this repository as
|
||||
/games/minetest_game
|
||||
in the Minetest Engine.
|
||||
|
||||
The Minetest Engine can be found in:
|
||||
https://github.com/minetest/minetest/
|
||||
|
||||
Compatibility
|
||||
--------------
|
||||
The minetest_game github master HEAD is generally compatible with the github
|
||||
master HEAD of minetest.
|
||||
|
||||
Additionally, when the minetest engine is tagged to be a certain version (eg.
|
||||
0.4.10), minetest_game is tagged with the version too.
|
||||
|
||||
When stable releases are made, minetest_game is packaged and made available in
|
||||
http://minetest.net/download.php
|
||||
and in case the repository has grown too much, it may be reset. In that sense,
|
||||
this is not a "real" git repository. (Package maintainers please note!)
|
||||
minetest_game files include everything except mods/defense*/*
|
||||
|
||||
License of source code
|
||||
----------------------
|
|
@ -0,0 +1 @@
|
|||
defense_mobs
|
|
@ -0,0 +1,7 @@
|
|||
defense = {}
|
||||
|
||||
local function dofile2(file)
|
||||
dofile(minetest.get_modpath("defense") .. "/" .. file)
|
||||
end
|
||||
|
||||
dofile2("director.lua")
|
|
@ -0,0 +1,9 @@
|
|||
defense_mobs = {}
|
||||
defense_mobs.gravity = -9.81
|
||||
|
||||
local function dofile2(file)
|
||||
dofile(minetest.get_modpath("defense_mobs") .. "/" .. file)
|
||||
end
|
||||
|
||||
dofile2("mob.lua")
|
||||
dofile2("unggoy.lua")
|
|
@ -0,0 +1,270 @@
|
|||
defense_mobs.move_method = {
|
||||
air = function(self, dtime, destination)
|
||||
local delta = vector.subtract(destination, self.object:getpos())
|
||||
local dist = vector.length(delta)
|
||||
local speed = self.move_speed * math.max(0, math.min(1, 2 * dist - 0.5))
|
||||
if speed > 0.01 then
|
||||
local t = math.pow(0.1, dtime)
|
||||
self.object:setvelocity(vector.add(
|
||||
vector.multiply(self.object:getvelocity(), t),
|
||||
vector.multiply(vector.normalize(delta), speed * (1-t))
|
||||
))
|
||||
|
||||
local yaw = self.object:getyaw()
|
||||
local yaw_delta = math.atan2(delta.z, delta.x) - yaw
|
||||
if yaw_delta < -math.pi then
|
||||
yaw_delta = yaw_delta + math.pi * 2
|
||||
elseif yaw_delta > math.pi then
|
||||
yaw_delta = yaw_delta - math.pi * 2
|
||||
end
|
||||
self.object:setyaw(yaw + yaw_delta * (1-t))
|
||||
|
||||
self:set_animation("move", {"move_attack"})
|
||||
else
|
||||
self.object:setvelocity({x=0, y=0, z=0})
|
||||
self:set_animation("idle", {"attack", "move_attack"})
|
||||
end
|
||||
end,
|
||||
|
||||
ground = function(self, dtime, destination)
|
||||
local delta = vector.subtract(destination, self.object:getpos())
|
||||
local dy = delta.y
|
||||
delta.y = 0
|
||||
local dist = vector.length(delta)
|
||||
local speed = self.move_speed * math.max(0, math.min(1, 3 * dist - 0.5))
|
||||
if speed > 0.01 then
|
||||
local t
|
||||
if self:is_standing() then
|
||||
t = math.pow(0.001, dtime)
|
||||
else
|
||||
t = 0.9
|
||||
end
|
||||
local dir = vector.normalize(delta)
|
||||
local v = self.object:getvelocity()
|
||||
local v2 = vector.add(
|
||||
vector.multiply(v, t),
|
||||
vector.multiply(dir, speed * (1-t))
|
||||
)
|
||||
v2.y = v.y
|
||||
self.object:setvelocity(v2)
|
||||
|
||||
local yaw = self.object:getyaw()
|
||||
local yaw_delta = math.atan2(dir.z, dir.x) - yaw
|
||||
if yaw_delta < -math.pi then
|
||||
yaw_delta = yaw_delta + math.pi * 2
|
||||
elseif yaw_delta > math.pi then
|
||||
yaw_delta = yaw_delta - math.pi * 2
|
||||
end
|
||||
self.object:setyaw(yaw + yaw_delta * (1-t))
|
||||
|
||||
-- Check for obstacle to jump
|
||||
local jump = false
|
||||
if dist > 1 then
|
||||
local p = self.object:getpos()
|
||||
p.y = p.y + self.collisionbox[2] + 0.5
|
||||
local sx = self.collisionbox[4] - self.collisionbox[1]
|
||||
local sz = self.collisionbox[6] - self.collisionbox[3]
|
||||
local r = math.sqrt(sx*sx + sz*sz)
|
||||
local node = minetest.get_node_or_nil(vector.add(p, vector.multiply(dir, r)))
|
||||
if not node or minetest.registered_nodes[node.name].walkable then
|
||||
jump = true
|
||||
end
|
||||
end
|
||||
|
||||
if jump then
|
||||
self:jump(dir)
|
||||
elseif self:is_standing() then
|
||||
self:set_animation("move", {"move_attack"})
|
||||
end
|
||||
else
|
||||
local v = self.object:getvelocity()
|
||||
v.x = 0
|
||||
v.z = 0
|
||||
self.object:setvelocity(v)
|
||||
self:set_animation("idle", {"attack", "move_attack"})
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
function defense_mobs.register_mob(name, def)
|
||||
local prototype = {
|
||||
-- minetest properties & defaults
|
||||
physical = true,
|
||||
collide_with_objects = true,
|
||||
makes_footstep_sound = true,
|
||||
visual = "mesh",
|
||||
automatic_face_movement_dir = false,
|
||||
stepheight = 0.6,
|
||||
-- custom properties
|
||||
movement = "ground", -- "ground"/"air"
|
||||
move_speed = 1,
|
||||
jump_height = 1,
|
||||
armor = 100,
|
||||
attack_range = 1,
|
||||
attack_damage = 1,
|
||||
attack_interval = 1,
|
||||
|
||||
destination = nil, -- position
|
||||
current_animation = nil,
|
||||
current_animation_end = 0,
|
||||
last_attack_time = 0,
|
||||
timer = 0,
|
||||
}
|
||||
for k,v in pairs(def) do
|
||||
prototype[k] = v
|
||||
end
|
||||
|
||||
--
|
||||
-- Callbacks
|
||||
--
|
||||
|
||||
-- extendable
|
||||
function prototype:on_activate(staticdata)
|
||||
self.object:set_armor_groups({fleshy=self.armor})
|
||||
if self.movement == "ground" then
|
||||
self.object:setacceleration({x=0, y=defense_mobs.gravity, z=0})
|
||||
end
|
||||
self.timer = math.random() * 16
|
||||
|
||||
if def.on_activate then
|
||||
def.on_activate(self, staticdata)
|
||||
end
|
||||
end
|
||||
|
||||
-- extendable
|
||||
function prototype:on_step(dtime)
|
||||
if self.destination then
|
||||
self:move(dtime, self.destination)
|
||||
else
|
||||
self:move(dtime, self.object:getpos())
|
||||
end
|
||||
|
||||
if self.movement ~= "air" and not self:is_standing() then
|
||||
self:set_animation("fall", {"jump", "attack", "move_attack"})
|
||||
end
|
||||
|
||||
if def.on_step then
|
||||
def.on_step(self, dtime)
|
||||
end
|
||||
|
||||
self.timer = self.timer + dtime
|
||||
end
|
||||
|
||||
--
|
||||
-- Overridable methods
|
||||
--
|
||||
|
||||
-- overridable
|
||||
prototype.attack = def.attack or function(self, obj)
|
||||
local delta = vector.subtract(obj:getpos(), self.object:getpos())
|
||||
obj:punch(self.object, self.timer - self.last_attack_time, {
|
||||
full_punch_interval=self.attack_interval,
|
||||
damage_groups = {fleshy=self.attack_damage}
|
||||
}, delta)
|
||||
self.object:setyaw(math.atan2(delta.z, delta.x))
|
||||
end
|
||||
|
||||
-- overridable
|
||||
prototype.move = def.move or defense_mobs.move_method[prototype.movement]
|
||||
|
||||
--
|
||||
-- Methods
|
||||
--
|
||||
|
||||
function prototype:hunt(radius)
|
||||
local p = self.object:getpos()
|
||||
local nearest_player = nil
|
||||
local nearest_dist = radius + 1
|
||||
for _,obj in ipairs(minetest.env:get_objects_inside_radius(p, radius)) do
|
||||
if obj:is_player() then
|
||||
if nearest_player then
|
||||
local d = vector.distance(nearest_player:getpos(), p)
|
||||
if d < nearest_dist then
|
||||
nearest_player = obj
|
||||
nearest_dist = d
|
||||
end
|
||||
else
|
||||
nearest_player = obj
|
||||
nearest_dist = vector.distance(obj:getpos(), p)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if nearest_player then
|
||||
local nearest_pos = nearest_player:getpos()
|
||||
local dir = vector.direction(nearest_pos, self.object:getpos())
|
||||
self.destination = vector.add(nearest_pos, vector.multiply(dir, self.attack_range/2))
|
||||
if nearest_dist < self.attack_range then
|
||||
self:do_attack(nearest_player)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function prototype:do_attack(obj)
|
||||
if self.last_attack_time + self.attack_interval < self.timer then
|
||||
self:attack(obj)
|
||||
self.last_attack_time = self.timer
|
||||
if self.current_animation == "move" then
|
||||
self:set_animation("move_attack")
|
||||
else
|
||||
self:set_animation("attack")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function prototype:jump(direction)
|
||||
if self:is_standing() then
|
||||
direction = vector.normalize(direction)
|
||||
local v = self.object:getvelocity()
|
||||
v.y = math.sqrt(2 * -defense_mobs.gravity * (self.jump_height + 0.2))
|
||||
v.x = direction.x * v.y
|
||||
v.z = direction.z * v.y
|
||||
self.object:setvelocity(v)
|
||||
self:set_animation("jump")
|
||||
end
|
||||
end
|
||||
|
||||
function prototype:is_standing()
|
||||
if self.movement == "air" then
|
||||
return false
|
||||
end
|
||||
|
||||
local p = self.object:getpos()
|
||||
p.y = p.y + self.collisionbox[2] - 0.5
|
||||
local corners = {
|
||||
vector.add(p, {x=self.collisionbox[1], y=0, z=self.collisionbox[3]}),
|
||||
vector.add(p, {x=self.collisionbox[1], y=0, z=self.collisionbox[6]}),
|
||||
vector.add(p, {x=self.collisionbox[4], y=0, z=self.collisionbox[3]}),
|
||||
vector.add(p, {x=self.collisionbox[4], y=0, z=self.collisionbox[6]}),
|
||||
}
|
||||
for _,c in ipairs(corners) do
|
||||
local node = minetest.get_node_or_nil(c)
|
||||
if not node or minetest.registered_nodes[node.name].walkable and self.object:getvelocity().y == 0 then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function prototype:set_animation(name, inhibit)
|
||||
if self.current_animation == name then
|
||||
return
|
||||
end
|
||||
if inhibit then
|
||||
for _,p in ipairs(inhibit) do
|
||||
if self.current_animation == p and self.timer < self.current_animation_end then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local anim_prop = self.animation[name]
|
||||
if anim_prop then
|
||||
self.current_animation = name
|
||||
self.current_animation_end = self.timer + (anim_prop.b - anim_prop.a - 1) / anim_prop.rate
|
||||
self.object:set_animation({x=anim_prop.a, y=anim_prop.b}, anim_prop.rate, 0)
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_entity(name, prototype)
|
||||
end
|
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 9.8 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,31 @@
|
|||
defense_mobs.register_mob("defense_mobs:unggoy", {
|
||||
hp_max = 1,
|
||||
weight = 6,
|
||||
collisionbox = {-0.4,-0.01,-0.4, 0.4,1.5,0.4},
|
||||
visual_size = {x=2.5, y=2.5},
|
||||
mesh = "defense_mobs_unggoy.b3d",
|
||||
textures = {"defense_mobs_unggoy.png"},
|
||||
makes_footstep_sound = true,
|
||||
|
||||
animation = {
|
||||
idle = {a=0, b=39, rate=30},
|
||||
jump = {a=40, b=49, rate=15},
|
||||
fall = {a=50, b=64, rate=20},
|
||||
attack = {a=65, b=72, rate=15},
|
||||
move = {a=75, b=99, rate=40},
|
||||
move_attack = {a=100, b=113, rate=20},
|
||||
},
|
||||
|
||||
move_speed = 5,
|
||||
jump_height = 2,
|
||||
attack_damage = 1,
|
||||
attack_interval = 0.5,
|
||||
|
||||
on_activate = function(self, staticdata)
|
||||
self:hunt(70)
|
||||
end,
|
||||
|
||||
on_step = function(self, dtime)
|
||||
self:hunt(20)
|
||||
end,
|
||||
})
|
Loading…
Reference in New Issue