master
Lean Rada 2015-02-02 18:05:23 +08:00
parent dc4ef98f27
commit cfd42b4868
6 changed files with 82 additions and 81 deletions

View File

@ -77,12 +77,12 @@ function mobs.default_prototype:on_step(dtime)
-- Disable collision when far enough
if self.collide_with_objects then
if nearest.distance > 8 then
if nearest.distance > 6 then
self.collide_with_objects = false
self.object:set_properties({collide_with_objects = self.collide_with_objects})
end
else
if nearest.distance < 3 then
if nearest.distance < 1.5 then
self.collide_with_objects = true
self.object:set_properties({collide_with_objects = self.collide_with_objects})
end
@ -146,14 +146,7 @@ function mobs.default_prototype:hunt()
end
if direction then
local sx = self.collisionbox[4] - self.collisionbox[1]
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}
self.destination = vector.add(pos, vector.multiply(direction, 1.25))
else
local r = math.max(0, self.attack_range - 2)
local dir = vector.direction(nearest.position, self.object:getpos())
@ -339,11 +332,16 @@ function mobs.move_method:ground(dtime, destination)
self.object:setvelocity(v2)
-- Check for jump
local jump = false
local jump = nil
if self.smart_path then
local p = self.object:getpos()
if destination.y > p.y + 0.5 then
jump = true
if destination.y > p.y + 1 then
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
else
if dist > 1 then
@ -361,7 +359,7 @@ function mobs.move_method:ground(dtime, destination)
for _,f in ipairs(fronts) do
local node = minetest.get_node_or_nil(vector.add(p, f))
if not node or minetest.registered_nodes[node.name].walkable then
jump = true
jump = vector.direction(self.object:getpos(), destination)
break
end
end
@ -369,7 +367,7 @@ function mobs.move_method:ground(dtime, destination)
end
if jump then
self:jump(vector.direction(self.object:getpos(), destination))
self:jump(jump)
elseif self:is_standing() then
if speed > self.move_speed * 0.06 then
local yaw = self.object:getyaw()

View File

@ -19,37 +19,12 @@ defense.mobs.register_mob("defense:paniki", {
attack_range = 1.1,
attack_interval = 1.2,
rank = 0,
leader = nil,
last_hp = 3,
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)
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 pos = self.object:getpos()
local delta = vector.subtract(pos, nearest.player:getpos())

View File

@ -46,13 +46,13 @@ defense.mobs.register_mob("defense:sarangay", {
on_step = function(self, dtime)
defense.mobs.default_prototype.on_step(self, dtime)
local pos = self.object:getpos()
if self.charging then
if self.charge_power > 0.5 then
self:hunt()
end
-- Break obstacles
local pos = self.object:getpos()
pos.y = pos.y + 1.5
local v = self.object:getvelocity()
v.y = 0
@ -69,13 +69,13 @@ defense.mobs.register_mob("defense:sarangay", {
else
local nearest = self:find_nearest_player()
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.destination = nil
elseif nearest.distance < 4 then
self:hunt()
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))
end
end

View File

@ -61,7 +61,7 @@ defense.mobs.register_mob("defense:unggoy", {
return true
else
local vel = self.object:getvelocity()
if math.abs(vel.y) > 0.05 then
if math.abs(vel.y) > 0.2 then
return false
end

View File

@ -24,7 +24,7 @@ function music:update()
last_intensity = intensity
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
if intensity <= il[1] then
if current_level > 0 then
@ -68,7 +68,7 @@ function music:update()
loop = true,
})
end
if current_level > 1 or last_level > 1 then
if last_level > 0 then
minetest.sound_play("defense_music_transit", {
gain = 0.2 + last_level * 0.1
})

View File

@ -37,6 +37,15 @@ end
-- Returns a vector
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 count = 0
local time = minetest.get_gametime()
@ -54,21 +63,14 @@ function pathfinder:get_direction(class, position)
local field = self:get_field(class, p)
if field then
local last_time = player_last_update[field.player] or field.time
if last_time + field.distance > time then
local direction = ({{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=0, z=-1},
{x=0, y=0, z=1}})
[field.direction]
if last_time + field.distance * 4 > time then
local direction = directions[field.direction]
total = vector.add(total, direction)
count = count + 1
end
end
end
if count > 0 then
if total.x ~= 0 or total.y ~= 0 or total.z ~= 0 then
return vector.normalize(total)
else
return nil
@ -78,9 +80,9 @@ end
-- Returns a table {time, distance}
function pathfinder:get_field(class, position)
local collisionbox = self.classes[class].collisionbox
local x = math.floor(position.x + collisionbox[1])
local y = math.floor(position.y + collisionbox[2])
local z = math.floor(position.z + collisionbox[3])
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) ..
@ -99,9 +101,9 @@ end
function pathfinder:set_field(class, position, player, distance, direction, time)
local collisionbox = self.classes[class].collisionbox
local x = math.floor(position.x + collisionbox[1])
local y = math.floor(position.y + collisionbox[2])
local z = math.floor(position.z + collisionbox[3])
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) ..
@ -119,6 +121,27 @@ function pathfinder:set_field(class, position, player, distance, direction, time
chunk[index] = {time=time, direction=direction, distance=distance, player=player}
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)
if not defense:is_dark() then
-- reset flow fields in the morning
@ -135,18 +158,19 @@ function pathfinder:update(dtime)
morning_reset = false
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=0, z=1},
{x=-1, y=0, z=0},
{x=1, y=0, z=0},
{x=0, y=0, z=-1},
}
-- Update the field
for c,class in pairs(self.classes) do
local vq = visit_queues[c]
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)
for di,n in ipairs(neighborhood) do
local npos = vector.add(current.position, n)
@ -162,15 +186,19 @@ function pathfinder:update(dtime)
and neighbor_field.direction ~= di
or neighbor_field.time == current.time
and neighbor_field.distance > next_distance then
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, {
position = npos,
player = current.player,
distance = next_distance,
direction = di,
time = current.time,
})
if next_distance < self.path_max_range then
if size < 800 then
self:set_field(c, npos, current.player, next_distance, di, current.time)
Queue.push(vq, {
position = npos,
player = current.player,
distance = next_distance,
direction = di,
time = current.time,
})
end
else
self:delete_field(c, npos)
end
end
end
@ -227,11 +255,6 @@ function pathfinder.cost_method.ground(class, pos, parent)
end
end
-- Check if this is a fall
if parent.y < pos.y then
return 2
end
-- Check if on top of solid
local ground_distance = 9999
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)
if not node then return nil end
if minetest.registered_nodes[node.name].walkable then
return 1 + (ground_distance - 1)
return ground_distance
end
end
end
-- Check if this is a fall
if parent.y < pos.y then
return 2
end
return pathfinder.path_max_range + 1
end