Update
parent
dc4ef98f27
commit
cfd42b4868
|
@ -77,12 +77,12 @@ function mobs.default_prototype:on_step(dtime)
|
||||||
|
|
||||||
-- Disable collision when far enough
|
-- Disable collision when far enough
|
||||||
if self.collide_with_objects then
|
if self.collide_with_objects then
|
||||||
if nearest.distance > 8 then
|
if nearest.distance > 6 then
|
||||||
self.collide_with_objects = false
|
self.collide_with_objects = false
|
||||||
self.object:set_properties({collide_with_objects = self.collide_with_objects})
|
self.object:set_properties({collide_with_objects = self.collide_with_objects})
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if nearest.distance < 3 then
|
if nearest.distance < 1.5 then
|
||||||
self.collide_with_objects = true
|
self.collide_with_objects = true
|
||||||
self.object:set_properties({collide_with_objects = self.collide_with_objects})
|
self.object:set_properties({collide_with_objects = self.collide_with_objects})
|
||||||
end
|
end
|
||||||
|
@ -146,14 +146,7 @@ function mobs.default_prototype:hunt()
|
||||||
end
|
end
|
||||||
|
|
||||||
if direction then
|
if direction then
|
||||||
local sx = self.collisionbox[4] - self.collisionbox[1]
|
self.destination = vector.add(pos, vector.multiply(direction, 1.25))
|
||||||
local sy = self.collisionbox[5] - self.collisionbox[2]
|
|
||||||
local sz = self.collisionbox[6] - self.collisionbox[3]
|
|
||||||
local r = math.sqrt(sx*sx + sy*sy + sz*sz)/2 + 1
|
|
||||||
local x = pos.x + direction.x * r
|
|
||||||
local y = pos.y + direction.y * r
|
|
||||||
local z = pos.z + direction.z * r
|
|
||||||
self.destination = {x=x, y=y, z=z}
|
|
||||||
else
|
else
|
||||||
local r = math.max(0, self.attack_range - 2)
|
local r = math.max(0, self.attack_range - 2)
|
||||||
local dir = vector.direction(nearest.position, self.object:getpos())
|
local dir = vector.direction(nearest.position, self.object:getpos())
|
||||||
|
@ -339,11 +332,16 @@ function mobs.move_method:ground(dtime, destination)
|
||||||
self.object:setvelocity(v2)
|
self.object:setvelocity(v2)
|
||||||
|
|
||||||
-- Check for jump
|
-- Check for jump
|
||||||
local jump = false
|
local jump = nil
|
||||||
if self.smart_path then
|
if self.smart_path then
|
||||||
local p = self.object:getpos()
|
local p = self.object:getpos()
|
||||||
if destination.y > p.y + 0.5 then
|
if destination.y > p.y + 1 then
|
||||||
jump = true
|
for y=p.y,p.y+self.jump_height do
|
||||||
|
jump = defense.pathfinder:get_direction(self.name, {x=p.x, y=y, z=p.z})
|
||||||
|
if jump and (jump.x ~= 0 or jump.z ~= 0) then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if dist > 1 then
|
if dist > 1 then
|
||||||
|
@ -361,7 +359,7 @@ function mobs.move_method:ground(dtime, destination)
|
||||||
for _,f in ipairs(fronts) do
|
for _,f in ipairs(fronts) do
|
||||||
local node = minetest.get_node_or_nil(vector.add(p, f))
|
local node = minetest.get_node_or_nil(vector.add(p, f))
|
||||||
if not node or minetest.registered_nodes[node.name].walkable then
|
if not node or minetest.registered_nodes[node.name].walkable then
|
||||||
jump = true
|
jump = vector.direction(self.object:getpos(), destination)
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -369,7 +367,7 @@ function mobs.move_method:ground(dtime, destination)
|
||||||
end
|
end
|
||||||
|
|
||||||
if jump then
|
if jump then
|
||||||
self:jump(vector.direction(self.object:getpos(), destination))
|
self:jump(jump)
|
||||||
elseif self:is_standing() then
|
elseif self:is_standing() then
|
||||||
if speed > self.move_speed * 0.06 then
|
if speed > self.move_speed * 0.06 then
|
||||||
local yaw = self.object:getyaw()
|
local yaw = self.object:getyaw()
|
||||||
|
|
|
@ -19,37 +19,12 @@ defense.mobs.register_mob("defense:paniki", {
|
||||||
attack_range = 1.1,
|
attack_range = 1.1,
|
||||||
attack_interval = 1.2,
|
attack_interval = 1.2,
|
||||||
|
|
||||||
rank = 0,
|
|
||||||
leader = nil,
|
|
||||||
last_hp = 3,
|
last_hp = 3,
|
||||||
flee_timer = 0,
|
flee_timer = 0,
|
||||||
|
|
||||||
on_activate = function(self, staticdata)
|
|
||||||
defense.mobs.default_prototype.on_activate(self, staticdata)
|
|
||||||
self.rank = math.random()
|
|
||||||
local pos = self.object:getpos()
|
|
||||||
local radius = 2
|
|
||||||
minetest.after(1, function()
|
|
||||||
local greatest_paniki = self
|
|
||||||
local greatest_rank = self.rank
|
|
||||||
for _,o in pairs(minetest.get_objects_inside_radius(pos, radius)) do
|
|
||||||
if self.object ~= o then
|
|
||||||
local e = o:get_luaentity()
|
|
||||||
if e and e.name == self.name then
|
|
||||||
if greatest_rank < e.rank then
|
|
||||||
greatest_paniki = e
|
|
||||||
greatest_rank = e.rank
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
self.leader = greatest_paniki
|
|
||||||
end)
|
|
||||||
end,
|
|
||||||
|
|
||||||
on_step = function(self, dtime)
|
on_step = function(self, dtime)
|
||||||
defense.mobs.default_prototype.on_step(self, dtime)
|
defense.mobs.default_prototype.on_step(self, dtime)
|
||||||
if self.flee_timer > 0 or (self.leader and self.leader.flee_timer > 0) then
|
if self.flee_timer > 0 then
|
||||||
local nearest = self:find_nearest_player()
|
local nearest = self:find_nearest_player()
|
||||||
local pos = self.object:getpos()
|
local pos = self.object:getpos()
|
||||||
local delta = vector.subtract(pos, nearest.player:getpos())
|
local delta = vector.subtract(pos, nearest.player:getpos())
|
||||||
|
|
|
@ -46,13 +46,13 @@ defense.mobs.register_mob("defense:sarangay", {
|
||||||
|
|
||||||
on_step = function(self, dtime)
|
on_step = function(self, dtime)
|
||||||
defense.mobs.default_prototype.on_step(self, dtime)
|
defense.mobs.default_prototype.on_step(self, dtime)
|
||||||
|
local pos = self.object:getpos()
|
||||||
if self.charging then
|
if self.charging then
|
||||||
if self.charge_power > 0.5 then
|
if self.charge_power > 0.5 then
|
||||||
self:hunt()
|
self:hunt()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Break obstacles
|
-- Break obstacles
|
||||||
local pos = self.object:getpos()
|
|
||||||
pos.y = pos.y + 1.5
|
pos.y = pos.y + 1.5
|
||||||
local v = self.object:getvelocity()
|
local v = self.object:getvelocity()
|
||||||
v.y = 0
|
v.y = 0
|
||||||
|
@ -69,13 +69,13 @@ defense.mobs.register_mob("defense:sarangay", {
|
||||||
else
|
else
|
||||||
local nearest = self:find_nearest_player()
|
local nearest = self:find_nearest_player()
|
||||||
if nearest then
|
if nearest then
|
||||||
if nearest.distance > 4 and math.random() < 0.1 then
|
if nearest.distance > 4 and math.abs(nearest.position.y - pos.y) < 4 and math.random() < 0.1 then
|
||||||
self:set_charging_state(true)
|
self:set_charging_state(true)
|
||||||
self.destination = nil
|
self.destination = nil
|
||||||
elseif nearest.distance < 4 then
|
elseif nearest.distance < 4 then
|
||||||
self:hunt()
|
self:hunt()
|
||||||
else
|
else
|
||||||
local dir = vector.direction(nearest.position, self.object:getpos())
|
local dir = vector.direction(nearest.position, pos)
|
||||||
self.destination = vector.add(nearest.position, vector.multiply(dir, 12))
|
self.destination = vector.add(nearest.position, vector.multiply(dir, 12))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -61,7 +61,7 @@ defense.mobs.register_mob("defense:unggoy", {
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
local vel = self.object:getvelocity()
|
local vel = self.object:getvelocity()
|
||||||
if math.abs(vel.y) > 0.05 then
|
if math.abs(vel.y) > 0.2 then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ function music:update()
|
||||||
last_intensity = intensity
|
last_intensity = intensity
|
||||||
intensity = intensity + math.max(0, intensity - last_intensity) * 3
|
intensity = intensity + math.max(0, intensity - last_intensity) * 3
|
||||||
|
|
||||||
local il = {0.1, 0.45, 0.7, 0.85}
|
local il = {0.05, 0.35, 0.6, 0.8}
|
||||||
local last_level = current_level
|
local last_level = current_level
|
||||||
if intensity <= il[1] then
|
if intensity <= il[1] then
|
||||||
if current_level > 0 then
|
if current_level > 0 then
|
||||||
|
@ -68,7 +68,7 @@ function music:update()
|
||||||
loop = true,
|
loop = true,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
if current_level > 1 or last_level > 1 then
|
if last_level > 0 then
|
||||||
minetest.sound_play("defense_music_transit", {
|
minetest.sound_play("defense_music_transit", {
|
||||||
gain = 0.2 + last_level * 0.1
|
gain = 0.2 + last_level * 0.1
|
||||||
})
|
})
|
||||||
|
|
|
@ -37,6 +37,15 @@ end
|
||||||
|
|
||||||
-- Returns a vector
|
-- Returns a vector
|
||||||
function pathfinder:get_direction(class, position)
|
function pathfinder:get_direction(class, position)
|
||||||
|
local directions = {
|
||||||
|
{x=0, y=-1, z=0},
|
||||||
|
{x=0, y=1, z=0},
|
||||||
|
{x=0, y=0, z=-1},
|
||||||
|
{x=1, y=0, z=0},
|
||||||
|
{x=-1, y=0, z=0},
|
||||||
|
{x=0, y=0, z=1},
|
||||||
|
}
|
||||||
|
|
||||||
local total = vector.new(0, 0, 0)
|
local total = vector.new(0, 0, 0)
|
||||||
local count = 0
|
local count = 0
|
||||||
local time = minetest.get_gametime()
|
local time = minetest.get_gametime()
|
||||||
|
@ -54,21 +63,14 @@ function pathfinder:get_direction(class, position)
|
||||||
local field = self:get_field(class, p)
|
local field = self:get_field(class, p)
|
||||||
if field then
|
if field then
|
||||||
local last_time = player_last_update[field.player] or field.time
|
local last_time = player_last_update[field.player] or field.time
|
||||||
if last_time + field.distance > time then
|
if last_time + field.distance * 4 > time then
|
||||||
local direction = ({{x=-1, y=0, z=0},
|
local direction = directions[field.direction]
|
||||||
{x=1, y=0, z=0},
|
|
||||||
{x=0, y=-1, z=0},
|
|
||||||
{x=0, y=1, z=0},
|
|
||||||
{x=0, y=0, z=-1},
|
|
||||||
{x=0, y=0, z=1}})
|
|
||||||
[field.direction]
|
|
||||||
total = vector.add(total, direction)
|
total = vector.add(total, direction)
|
||||||
count = count + 1
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if count > 0 then
|
if total.x ~= 0 or total.y ~= 0 or total.z ~= 0 then
|
||||||
return vector.normalize(total)
|
return vector.normalize(total)
|
||||||
else
|
else
|
||||||
return nil
|
return nil
|
||||||
|
@ -78,9 +80,9 @@ end
|
||||||
-- Returns a table {time, distance}
|
-- Returns a table {time, distance}
|
||||||
function pathfinder:get_field(class, position)
|
function pathfinder:get_field(class, position)
|
||||||
local collisionbox = self.classes[class].collisionbox
|
local collisionbox = self.classes[class].collisionbox
|
||||||
local x = math.floor(position.x + collisionbox[1])
|
local x = math.floor(position.x + collisionbox[1] + 0.01)
|
||||||
local y = math.floor(position.y + collisionbox[2])
|
local y = math.floor(position.y + collisionbox[2] + 0.01)
|
||||||
local z = math.floor(position.z + collisionbox[3])
|
local z = math.floor(position.z + collisionbox[3] + 0.01)
|
||||||
|
|
||||||
local chunk_key = math.floor(x/chunk_size) ..
|
local chunk_key = math.floor(x/chunk_size) ..
|
||||||
":" .. math.floor(y/chunk_size) ..
|
":" .. math.floor(y/chunk_size) ..
|
||||||
|
@ -99,9 +101,9 @@ end
|
||||||
|
|
||||||
function pathfinder:set_field(class, position, player, distance, direction, time)
|
function pathfinder:set_field(class, position, player, distance, direction, time)
|
||||||
local collisionbox = self.classes[class].collisionbox
|
local collisionbox = self.classes[class].collisionbox
|
||||||
local x = math.floor(position.x + collisionbox[1])
|
local x = math.floor(position.x + collisionbox[1] + 0.01)
|
||||||
local y = math.floor(position.y + collisionbox[2])
|
local y = math.floor(position.y + collisionbox[2] + 0.01)
|
||||||
local z = math.floor(position.z + collisionbox[3])
|
local z = math.floor(position.z + collisionbox[3] + 0.01)
|
||||||
|
|
||||||
local chunk_key = math.floor(x/chunk_size) ..
|
local chunk_key = math.floor(x/chunk_size) ..
|
||||||
":" .. math.floor(y/chunk_size) ..
|
":" .. math.floor(y/chunk_size) ..
|
||||||
|
@ -119,6 +121,27 @@ function pathfinder:set_field(class, position, player, distance, direction, time
|
||||||
chunk[index] = {time=time, direction=direction, distance=distance, player=player}
|
chunk[index] = {time=time, direction=direction, distance=distance, player=player}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function pathfinder:delete_field(class, position)
|
||||||
|
local collisionbox = self.classes[class].collisionbox
|
||||||
|
local x = math.floor(position.x + collisionbox[1] + 0.01)
|
||||||
|
local y = math.floor(position.y + collisionbox[2] + 0.01)
|
||||||
|
local z = math.floor(position.z + collisionbox[3] + 0.01)
|
||||||
|
|
||||||
|
local chunk_key = math.floor(x/chunk_size) ..
|
||||||
|
":" .. math.floor(y/chunk_size) ..
|
||||||
|
":" .. math.floor(z/chunk_size)
|
||||||
|
local chunk = fields[class][chunk_key]
|
||||||
|
if not chunk then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local cx = x % chunk_size
|
||||||
|
local cy = y % chunk_size
|
||||||
|
local cz = z % chunk_size
|
||||||
|
local index = (cy * chunk_size + cz) * chunk_size + cx
|
||||||
|
chunk[index] = nil
|
||||||
|
end
|
||||||
|
|
||||||
function pathfinder:update(dtime)
|
function pathfinder:update(dtime)
|
||||||
if not defense:is_dark() then
|
if not defense:is_dark() then
|
||||||
-- reset flow fields in the morning
|
-- reset flow fields in the morning
|
||||||
|
@ -135,18 +158,19 @@ function pathfinder:update(dtime)
|
||||||
morning_reset = false
|
morning_reset = false
|
||||||
|
|
||||||
local neighborhood = {
|
local neighborhood = {
|
||||||
{x=1, y=0, z=0},
|
|
||||||
{x=-1, y=0, z=0},
|
|
||||||
{x=0, y=1, z=0},
|
{x=0, y=1, z=0},
|
||||||
{x=0, y=-1, z=0},
|
{x=0, y=-1, z=0},
|
||||||
{x=0, y=0, z=1},
|
{x=0, y=0, z=1},
|
||||||
|
{x=-1, y=0, z=0},
|
||||||
|
{x=1, y=0, z=0},
|
||||||
{x=0, y=0, z=-1},
|
{x=0, y=0, z=-1},
|
||||||
}
|
}
|
||||||
-- Update the field
|
-- Update the field
|
||||||
for c,class in pairs(self.classes) do
|
for c,class in pairs(self.classes) do
|
||||||
local vq = visit_queues[c]
|
local vq = visit_queues[c]
|
||||||
local size = Queue.size(vq)
|
local size = Queue.size(vq)
|
||||||
for i=1,math.min(size,20) do
|
local max_iter = 100 - math.floor(defense.director.intensity * 90)
|
||||||
|
for i=1,math.min(size,max_iter) do
|
||||||
local current = Queue.pop(vq)
|
local current = Queue.pop(vq)
|
||||||
for di,n in ipairs(neighborhood) do
|
for di,n in ipairs(neighborhood) do
|
||||||
local npos = vector.add(current.position, n)
|
local npos = vector.add(current.position, n)
|
||||||
|
@ -162,8 +186,9 @@ function pathfinder:update(dtime)
|
||||||
and neighbor_field.direction ~= di
|
and neighbor_field.direction ~= di
|
||||||
or neighbor_field.time == current.time
|
or neighbor_field.time == current.time
|
||||||
and neighbor_field.distance > next_distance then
|
and neighbor_field.distance > next_distance then
|
||||||
|
if next_distance < self.path_max_range then
|
||||||
|
if size < 800 then
|
||||||
self:set_field(c, npos, current.player, next_distance, di, current.time)
|
self:set_field(c, npos, current.player, next_distance, di, current.time)
|
||||||
if next_distance < self.path_max_range and size < 100 then
|
|
||||||
Queue.push(vq, {
|
Queue.push(vq, {
|
||||||
position = npos,
|
position = npos,
|
||||||
player = current.player,
|
player = current.player,
|
||||||
|
@ -172,6 +197,9 @@ function pathfinder:update(dtime)
|
||||||
time = current.time,
|
time = current.time,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
self:delete_field(c, npos)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -227,11 +255,6 @@ function pathfinder.cost_method.ground(class, pos, parent)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check if this is a fall
|
|
||||||
if parent.y < pos.y then
|
|
||||||
return 2
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Check if on top of solid
|
-- Check if on top of solid
|
||||||
local ground_distance = 9999
|
local ground_distance = 9999
|
||||||
for z=pos.z,pos.z+class.size.z-1 do
|
for z=pos.z,pos.z+class.size.z-1 do
|
||||||
|
@ -262,11 +285,16 @@ function pathfinder.cost_method.ground(class, pos, parent)
|
||||||
local node = minetest.get_node_or_nil(l)
|
local node = minetest.get_node_or_nil(l)
|
||||||
if not node then return nil end
|
if not node then return nil end
|
||||||
if minetest.registered_nodes[node.name].walkable then
|
if minetest.registered_nodes[node.name].walkable then
|
||||||
return 1 + (ground_distance - 1)
|
return ground_distance
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Check if this is a fall
|
||||||
|
if parent.y < pos.y then
|
||||||
|
return 2
|
||||||
|
end
|
||||||
|
|
||||||
return pathfinder.path_max_range + 1
|
return pathfinder.path_max_range + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue