Skip to content
Snippets Groups Projects
Commit c4214930 authored by Grayswandir's avatar Grayswandir
Browse files

Added hooks and such for extending the targeting system.

parent 3899074a
No related branches found
No related tags found
No related merge requests found
...@@ -24,6 +24,8 @@ local Shader = require "engine.Shader" ...@@ -24,6 +24,8 @@ local Shader = require "engine.Shader"
--- handles targetting --- handles targetting
module(..., package.seeall, class.make) module(..., package.seeall, class.make)
_M.defaults = {}
function _M:init(map, source_actor) function _M:init(map, source_actor)
self.display_x, self.display_y = map.display_x, map.display_y self.display_x, self.display_y = map.display_x, map.display_y
self.w, self.h = map.viewport.width, map.viewport.height self.w, self.h = map.viewport.width, map.viewport.height
...@@ -69,7 +71,7 @@ function _M:createTextures() ...@@ -69,7 +71,7 @@ function _M:createTextures()
end end
function _M:enableFBORenderer(texture, shader) function _M:enableFBORenderer(texture, shader)
if not shader or not core.display.fboSupportsTransparency then if not shader or not core.display.fboSupportsTransparency then
self.fbo = nil self.fbo = nil
self:createTextures() self:createTextures()
return return
...@@ -112,7 +114,7 @@ function _M:display(dispx, dispy, prevfbo, rotate_keyframes) ...@@ -112,7 +114,7 @@ function _M:display(dispx, dispy, prevfbo, rotate_keyframes)
sx = sx + game.level.map.display_x sx = sx + game.level.map.display_x
sy = sy + game.level.map.display_y sy = sy + game.level.map.display_y
self.display_x, self.display_y = dispx or sx or self.display_x, dispy or sy or self.display_y self.display_x, self.display_y = dispx or sx or self.display_x, dispy or sy or self.display_y
if self.active then if self.active then
if not self.fbo then if not self.fbo then
self:realDisplay(self.display_x, self.display_y) self:realDisplay(self.display_x, self.display_y)
...@@ -149,11 +151,95 @@ function _M:display(dispx, dispy, prevfbo, rotate_keyframes) ...@@ -149,11 +151,95 @@ function _M:display(dispx, dispy, prevfbo, rotate_keyframes)
self.display_x, self.display_y = ox, oy self.display_x, self.display_y = ox, oy
end end
-- Being completely blocked by the corner of an adjacent tile is annoying, so let's make it a special case and hit it instead.
_M.defaults.display_blocked_by_adjacent = function(self, d)
if d.blocked_corner_x then
d.block = true
d.hit = true
d.hit_radius = false
stopped = true
if self.target_type.min_range and core.fov.distance(self.target_type.start_x, self.target_type.start_y, d.lx, d.ly) < self.target_type.min_range then
d.s = self.sr
end
if game.level.map:isBound(d.blocked_corner_x, d.blocked_corner_y) then
d.display_highlight(d.s, d.blocked_corner_x, d.blocked_corner_y)
end
d.s = self.sr
end
end
_M.defaults.display_check_block_path = function(self, d)
d.block, d.hit, d.hit_radius = false, true, true
d.block, d.hit, d.hit_radius = self.target_type:block_path(d.lx, d.ly, true)
end
-- Update coordinates and set color
_M.defaults.display_update_hit = function(self, d)
if d.hit then
d.stop_x, d.stop_y = d.lx, d.ly
if not d.block and d.hit == "unknown" then d.s = self.sy end
else
d.s = self.sr
end
end
_M.defaults.display_update_radius = function(self, d)
if d.hit_radius then
d.stop_radius_x, d.stop_radius_y = d.lx, d.ly
end
end
_M.defaults.display_update_min_range = function(self, d)
if self.target_type.min_range then
-- Check if we should be "red"
if core.fov.distance(self.target_type.start_x, self.target_type.start_y, d.lx, d.ly) < self.target_type.min_range then
d.s = self.sr
-- Check if we were only "red" because of minimum distance
elseif d.s == self.sr then
d.s = self.sb
end
end
end
_M.defaults.display_line_step = function(self, d)
d.display_highlight(d.s, d.lx, d.ly)
end
_M.defaults.display_on_block = function(self, d)
d.s = self.sr
d.stopped = true
end
_M.defaults.display_on_block_corner = function(self, d)
d.block = true
d.stopped = true
d.hit_radius = false
d.s = self.sr
-- double the fun :-P
if game.level.map:isBound(d.blocked_corner_x, d.blocked_corner_y) then
if self.target_type.display_corner_block then
self.target_type.display_corner_block(self, d)
else
d.display_highlight(d.s, d.blocked_corner_x, d.blocked_corner_y, 2)
end
end
end
_M.defaults.display_default_target = function(self, d)
-- Entity tracking, if possible and if visible
if self.target.entity and self.target.entity.x and self.target.entity.y and game.level.map.seens(self.target.entity.x, self.target.entity.y) then
self.target.x, self.target.y = self.target.entity.x, self.target.entity.y
end
self.target.x = self.target.x or self.source_actor.x
self.target.y = self.target.y or self.source_actor.y
end
function _M:realDisplay(dispx, dispy, display_highlight) function _M:realDisplay(dispx, dispy, display_highlight)
if not display_highlight then if not display_highlight then
if util.isHex() then if util.isHex() then
display_highlight = function(texture, tx, ty, count) display_highlight = function(texture, tx, ty, count)
count = count or 1 count = count or 1
if self.target_type.filter and not self.target_type.no_filter_highlight and self.target_type.filter(tx, ty) then count = count + 1 end
for i = 1, count do for i = 1, count do
texture:toScreenHighlightHex( texture:toScreenHighlightHex(
dispx + (tx - game.level.map.mx) * self.tile_w * Map.zoom, dispx + (tx - game.level.map.mx) * self.tile_w * Map.zoom,
...@@ -165,6 +251,7 @@ function _M:realDisplay(dispx, dispy, display_highlight) ...@@ -165,6 +251,7 @@ function _M:realDisplay(dispx, dispy, display_highlight)
else else
display_highlight = function(texture, tx, ty, count) display_highlight = function(texture, tx, ty, count)
count = count or 1 count = count or 1
if self.target_type.filter and not self.target_type.no_filter_highlight and self.target_type.filter(tx, ty) then count = count + 1 end
for i = 1, count do for i = 1, count do
texture:toScreen( texture:toScreen(
dispx + (tx - game.level.map.mx) * self.tile_w * Map.zoom, dispx + (tx - game.level.map.mx) * self.tile_w * Map.zoom,
...@@ -206,113 +293,70 @@ function _M:realDisplay(dispx, dispy, display_highlight) ...@@ -206,113 +293,70 @@ function _M:realDisplay(dispx, dispy, display_highlight)
return return
end end
local d = {}
d.display_highlight = display_highlight
-- Make sure we have a source -- Make sure we have a source
if not self.target_type.source_actor then if not self.target_type.source_actor then
self.target_type.source_actor = self.source_actor self.target_type.source_actor = self.source_actor
end end
-- Entity tracking, if possible and if visible
if self.target.entity and self.target.entity.x and self.target.entity.y and game.level.map.seens(self.target.entity.x, self.target.entity.y) then -- Pick default target
self.target.x, self.target.y = self.target.entity.x, self.target.entity.y self.target_type.display_default_target(self, d)
end
self.target.x = self.target.x or self.source_actor.x
self.target.y = self.target.y or self.source_actor.y
self.target_type.start_x = self.target_type.start_x or self.target_type.x or self.target_type.source_actor and self.target_type.source_actor.x or self.x self.target_type.start_x = self.target_type.start_x or self.target_type.x or self.target_type.source_actor and self.target_type.source_actor.x or self.x
self.target_type.start_y = self.target_type.start_y or self.target_type.y or self.target_type.source_actor and self.target_type.source_actor.y or self.y self.target_type.start_y = self.target_type.start_y or self.target_type.y or self.target_type.source_actor and self.target_type.source_actor.y or self.y
-- self.cursor:toScreen(dispx + (self.target.x - game.level.map.mx) * self.tile_w * Map.zoom, dispy + (self.target.y - game.level.map.my) * self.tile_h * Map.zoom, self.tile_w * Map.zoom, self.tile_h * Map.zoom) -- self.cursor:toScreen(dispx + (self.target.x - game.level.map.mx) * self.tile_w * Map.zoom, dispy + (self.target.y - game.level.map.my) * self.tile_h * Map.zoom, self.tile_w * Map.zoom, self.tile_h * Map.zoom)
-- Do not display if not requested -- Do not display if not requested
if not self.active then return end if not self.active then return end
local s = self.sb d.s = self.sb
local l
if self.target_type.source_actor.lineFOV then if self.target_type.source_actor.lineFOV then
l = self.target_type.source_actor:lineFOV(self.target.x, self.target.y, nil, nil, self.target_type.start_x, self.target_type.start_y) d.l = self.target_type.source_actor:lineFOV(self.target.x, self.target.y, nil, nil, self.target_type.start_x, self.target_type.start_y)
else else
l = core.fov.line(self.target_type.start_x, self.target_type.start_y, self.target.x, self.target.y) d.l = core.fov.line(self.target_type.start_x, self.target_type.start_y, self.target.x, self.target.y)
end end
local block_corner = self.target_type.block_path and function(_, bx, by) local b, h, hr = self.target_type:block_path(bx, by, true) ; return b and h and not hr end local block_corner = self.target_type.block_path and function(_, bx, by) local b, h, hr = self.target_type:block_path(bx, by, true) ; return b and h and not hr end
or function(_, bx, by) return false end or function(_, bx, by) return false end
l:set_corner_block(block_corner) d.l:set_corner_block(block_corner)
local lx, ly, blocked_corner_x, blocked_corner_y = l:step() d.lx, d.ly, d.blocked_corner_x, d.blocked_corner_y = d.l:step()
local stop_x, stop_y = self.target_type.start_x, self.target_type.start_y d.stop_x, d.stop_y = self.target_type.start_x, self.target_type.start_y
local stop_radius_x, stop_radius_y = self.target_type.start_x, self.target_type.start_y d.stop_radius_x, d.stop_radius_y = self.target_type.start_x, self.target_type.start_y
local stopped = false d.stopped = false
local block, hit, hit_radius
local firstx, firsty = lx, ly d.firstx, d.firsty = d.lx, d.ly
-- Being completely blocked by the corner of an adjacent tile is annoying, so let's make it a special case and hit it instead -- Being completely blocked by the corner of an adjacent tile is annoying, so let's make it a special case and hit it instead
if blocked_corner_x then self.target_type.display_blocked_by_adjacent(self, d)
block = true
hit = true
hit_radius = false
stopped = true
if self.target_type.min_range and core.fov.distance(self.target_type.start_x, self.target_type.start_y, lx, ly) < self.target_type.min_range then
s = self.sr
end
if game.level.map:isBound(blocked_corner_x, blocked_corner_y) then
display_highlight(s, blocked_corner_x, blocked_corner_y)
end
s = self.sr
end
while lx and ly do
if not stopped then
block, hit, hit_radius = false, true, true
if self.target_type.block_path then
block, hit, hit_radius = self.target_type:block_path(lx, ly, true)
end
while d.lx and d.ly do
if not d.stopped then
self.target_type.display_check_block_path(self, d)
-- Update coordinates and set color -- Update coordinates and set color
if hit then self.target_type.display_update_hit(self, d)
stop_x, stop_y = lx, ly self.target_type.display_update_radius(self, d)
if not block and hit == "unknown" then s = self.sy end self.target_type.display_update_min_range(self, d)
else
s = self.sr
end
if hit_radius then
stop_radius_x, stop_radius_y = lx, ly
end
if self.target_type.min_range then
-- Check if we should be "red"
if core.fov.distance(self.target_type.start_x, self.target_type.start_y, lx, ly) < self.target_type.min_range then
s = self.sr
-- Check if we were only "red" because of minimum distance
elseif s == self.sr then
s = self.sb
end
end
end
display_highlight(s, lx, ly)
if block then
s = self.sr
stopped = true
end end
lx, ly, blocked_corner_x, blocked_corner_y = l:step() self.target_type.display_line_step(self, d)
if blocked_corner_x and not stopped then if d.block then self.target_type.display_on_block(self, d) end
block = true
stopped = true d.lx, d.ly, d.blocked_corner_x, d.blocked_corner_y = d.l:step()
hit_radius = false
s = self.sr
-- double the fun :-P
if game.level.map:isBound(blocked_corner_x, blocked_corner_y) then
display_highlight(s, blocked_corner_x, blocked_corner_y, 2)
end
end
if d.blocked_corner_x and not d.stopped then
self.target_type.display_on_block_corner(self, d)
end
end end
if self.target_type.ball and self.target_type.ball > 0 then if self.target_type.ball and self.target_type.ball > 0 then
core.fov.calc_circle( core.fov.calc_circle(
stop_radius_x, d.stop_radius_x,
stop_radius_y, d.stop_radius_y,
game.level.map.w, game.level.map.w,
game.level.map.h, game.level.map.h,
self.target_type.ball, self.target_type.ball,
...@@ -321,17 +365,19 @@ function _M:realDisplay(dispx, dispy, display_highlight) ...@@ -321,17 +365,19 @@ function _M:realDisplay(dispx, dispy, display_highlight)
end, end,
function(_, px, py) function(_, px, py)
if not self.target_type.no_restrict and not game.level.map.remembers(px, py) and not game.level.map.seens(px, py) then if not self.target_type.no_restrict and not game.level.map.remembers(px, py) and not game.level.map.seens(px, py) then
display_highlight(self.syg, px, py) d.display_highlight(self.syg, px, py)
else else
display_highlight(self.sg, px, py) d.display_highlight(self.sg, px, py)
end end
end, end,
nil) nil)
elseif self.target_type.cone and self.target_type.cone > 0 then end
if self.target_type.cone and self.target_type.cone > 0 then
--local dir_angle = math.deg(math.atan2(self.target.y - self.source_actor.y, self.target.x - self.source_actor.x)) --local dir_angle = math.deg(math.atan2(self.target.y - self.source_actor.y, self.target.x - self.source_actor.x))
core.fov.calc_beam_any_angle( core.fov.calc_beam_any_angle(
stop_radius_x, d.stop_radius_x,
stop_radius_y, d.stop_radius_y,
game.level.map.w, game.level.map.w,
game.level.map.h, game.level.map.h,
self.target_type.cone, self.target_type.cone,
...@@ -345,16 +391,18 @@ function _M:realDisplay(dispx, dispy, display_highlight) ...@@ -345,16 +391,18 @@ function _M:realDisplay(dispx, dispy, display_highlight)
end, end,
function(_, px, py) function(_, px, py)
if not self.target_type.no_restrict and not game.level.map.remembers(px, py) and not game.level.map.seens(px, py) then if not self.target_type.no_restrict and not game.level.map.remembers(px, py) and not game.level.map.seens(px, py) then
display_highlight(self.syg, px, py) d.display_highlight(self.syg, px, py)
else else
display_highlight(self.sg, px, py) d.display_highlight(self.sg, px, py)
end end
end, end,
nil) nil)
elseif self.target_type.wall and self.target_type.wall > 0 then end
if self.target_type.wall and self.target_type.wall > 0 then
core.fov.calc_wall( core.fov.calc_wall(
stop_radius_x, d.stop_radius_x,
stop_radius_y, d.stop_radius_y,
game.level.map.w, game.level.map.w,
game.level.map.h, game.level.map.h,
self.target_type.wall, self.target_type.wall,
...@@ -368,15 +416,100 @@ function _M:realDisplay(dispx, dispy, display_highlight) ...@@ -368,15 +416,100 @@ function _M:realDisplay(dispx, dispy, display_highlight)
end, end,
function(_, px, py) function(_, px, py)
if not self.target_type.no_restrict and not game.level.map.remembers(px, py) and not game.level.map.seens(px, py) then if not self.target_type.no_restrict and not game.level.map.remembers(px, py) and not game.level.map.seens(px, py) then
display_highlight(self.syg, px, py) d.display_highlight(self.syg, px, py)
else else
display_highlight(self.sg, px, py) d.display_highlight(self.sg, px, py)
end end
end, end,
nil) nil)
end end
d[1] = "Target:realDisplay"
self:triggerHook(d)
end end
_M.defaults.block_path = function(typ, lx, ly, for_highlights)
if not game.level.map:isBound(lx, ly) then
return true, false, false
elseif not typ.no_restrict then
if typ.range and typ.start_x then
local dist = core.fov.distance(typ.start_x, typ.start_y, lx, ly)
if dist > typ.range then return true, false, false end
elseif typ.range and typ.source_actor and typ.source_actor.x then
local dist = core.fov.distance(typ.source_actor.x, typ.source_actor.y, lx, ly)
if dist > typ.range then return true, false, false end
end
local is_known = game.level.map.remembers(lx, ly) or game.level.map.seens(lx, ly)
if typ.requires_knowledge and not is_known then
return true, false, false
end
if not typ.pass_terrain and game.level.map:checkEntity(lx, ly, engine.Map.TERRAIN, "block_move") and not game.level.map:checkEntity(lx, ly, engine.Map.TERRAIN, "pass_projectile") then
if for_highlights and not is_known then
return false, "unknown", true
else
return true, true, false
end
-- If we explode due to something other than terrain, then we should explode ON the tile, not before it
elseif typ.stop_block then
local nb = game.level.map:checkAllEntitiesCount(lx, ly, "block_move")
-- Reduce for pass_projectile or pass_terrain, which was handled above
if game.level.map:checkEntity(lx, ly, engine.Map.TERRAIN, "block_move") and (typ.pass_terrain or game.level.map:checkEntity(lx, ly, engine.Map.TERRAIN, "pass_projectile")) then
nb = nb - 1
end
-- Reduce the nb blocking for friendlies
if not typ.friendlyblock and typ.source_actor and typ.source_actor.reactionToward then
local a = game.level.map(lx, ly, engine.Map.ACTOR)
if a and typ.source_actor:reactionToward(a) > 0 then
nb = nb - 1
end
end
if nb > 0 then
if for_highlights then
-- Targeting highlight should be yellow if we don't know what we're firing through
if not is_known then
return false, "unknown", true
-- Don't show the path as blocked if it's blocked by an actor we can't see
elseif nb == 1 and typ.source_actor and typ.source_actor.canSee and not typ.source_actor:canSee(game.level.map(lx, ly, engine.Map.ACTOR)) then
return false, true, true
end
end
return true, true, true
end
end
if for_highlights and not is_known then
return false, "unknown", true
end
end
-- If we don't block the path, then the explode point should be here
return false, true, true
end
_M.defaults.block_radius = function(typ, lx, ly, for_highlights)
return not typ.no_restrict and
game.level.map:checkEntity(lx, ly, engine.Map.TERRAIN, "block_move") and
not game.level.map:checkEntity(lx, ly, engine.Map.TERRAIN, "pass_projectile") and
not (for_highlights and not (game.level.map.remembers(lx, ly) or game.level.map.seens(lx, ly)))
end
--- targeting type strings -> modification function.
_M.types_def = {
ball = function(dest, src) dest.ball = src.radius end,
cone = function(dest, src)
dest.cone = src.radius
dest.cone_angle = src.cone_angle or 55
dest.selffire = false
end,
wall = function(dest, src)
if util.isHex() then
--with a hex grid, a wall should only be defined by the number of spots
src.halfmax_spots = src.halflength
src.halflength = 2 * src.halflength
end
dest.wall = src.halflength
end,
bolt = function(dest, src) dest.stop_block = true end,
beam = function(dest, scr) dest.line = true end,}
-- @return t The target table used by ActorProject, Projectile, GameTargeting, etc. -- @return t The target table used by ActorProject, Projectile, GameTargeting, etc.
-- @param t Target table used to generate the -- @param t Target table used to generate the
-- @param t.type The engine-defined type, populates other more complex variables (see below) -- @param t.type The engine-defined type, populates other more complex variables (see below)
...@@ -416,92 +549,16 @@ function _M:getType(t) ...@@ -416,92 +549,16 @@ function _M:getType(t)
selffire = true, selffire = true,
friendlyfire = true, friendlyfire = true,
friendlyblock = true, friendlyblock = true,
--- Determines how a path is blocked for a target type
--@param typ The target type table
block_path = function(typ, lx, ly, for_highlights)
if not game.level.map:isBound(lx, ly) then
return true, false, false
elseif not typ.no_restrict then
if typ.range and typ.start_x then
local dist = core.fov.distance(typ.start_x, typ.start_y, lx, ly)
if dist > typ.range then return true, false, false end
elseif typ.range and typ.source_actor and typ.source_actor.x then
local dist = core.fov.distance(typ.source_actor.x, typ.source_actor.y, lx, ly)
if dist > typ.range then return true, false, false end
end
local is_known = game.level.map.remembers(lx, ly) or game.level.map.seens(lx, ly)
if typ.requires_knowledge and not is_known then
return true, false, false
end
if not typ.pass_terrain and game.level.map:checkEntity(lx, ly, engine.Map.TERRAIN, "block_move") and not game.level.map:checkEntity(lx, ly, engine.Map.TERRAIN, "pass_projectile") then
if for_highlights and not is_known then
return false, "unknown", true
else
return true, true, false
end
-- If we explode due to something other than terrain, then we should explode ON the tile, not before it
elseif typ.stop_block then
local nb = game.level.map:checkAllEntitiesCount(lx, ly, "block_move")
-- Reduce for pass_projectile or pass_terrain, which was handled above
if game.level.map:checkEntity(lx, ly, engine.Map.TERRAIN, "block_move") and (typ.pass_terrain or game.level.map:checkEntity(lx, ly, engine.Map.TERRAIN, "pass_projectile")) then
nb = nb - 1
end
-- Reduce the nb blocking for friendlies
if not typ.friendlyblock and typ.source_actor and typ.source_actor.reactionToward then
local a = game.level.map(lx, ly, engine.Map.ACTOR)
if a and typ.source_actor:reactionToward(a) > 0 then
nb = nb - 1
end
end
if nb > 0 then
if for_highlights then
-- Targeting highlight should be yellow if we don't know what we're firing through
if not is_known then
return false, "unknown", true
-- Don't show the path as blocked if it's blocked by an actor we can't see
elseif nb == 1 and typ.source_actor and typ.source_actor.canSee and not typ.source_actor:canSee(game.level.map(lx, ly, engine.Map.ACTOR)) then
return false, true, true
end
end
return true, true, true
end
end
if for_highlights and not is_known then
return false, "unknown", true
end
end
-- If we don't block the path, then the explode point should be here
return false, true, true
end,
block_radius = function(typ, lx, ly, for_highlights)
return not typ.no_restrict and game.level.map:checkEntity(lx, ly, engine.Map.TERRAIN, "block_move") and not game.level.map:checkEntity(lx, ly, engine.Map.TERRAIN, "pass_projectile") and not (for_highlights and not (game.level.map.remembers(lx, ly) or game.level.map.seens(lx, ly)))
end
} }
for k, v in pairs(self.defaults) do target_type[k] = v end
-- And now modify for the default types -- And now modify for the default types
if t.type then if t.type then
if t.type:find("ball") then for type_name, fun in pairs(self.types_def) do
target_type.ball = t.radius if t.type:find(type_name) then fun(target_type, t) end
end
if t.type:find("cone") then
target_type.cone = t.radius
target_type.cone_angle = t.cone_angle or 55
target_type.selffire = false
end
if t.type:find("wall") then
if util.isHex() then
--with a hex grid, a wall should only be defined by the number of spots
t.halfmax_spots = t.halflength
t.halflength = 2*t.halflength
end
target_type.wall = t.halflength
end
if t.type:find("bolt") then
target_type.stop_block = true
elseif t.type:find("beam") then
target_type.line = true
end end
end end
table.update(t, target_type) table.update(t, target_type)
return t return t
end end
...@@ -551,7 +608,7 @@ function _M:scan(dir, radius, sx, sy, filter, kind) ...@@ -551,7 +608,7 @@ function _M:scan(dir, radius, sx, sy, filter, kind)
sx = sx or self.target.x sx = sx or self.target.x
sy = sy or self.target.y sy = sy or self.target.y
if not sx or not sy then return end if not sx or not sy then return end
kind = kind or engine.Map.ACTOR kind = kind or engine.Map.ACTOR
radius = radius or 20 radius = radius or 20
local actors = {} local actors = {}
...@@ -602,4 +659,3 @@ function _M:pointAtRange(srcx, srcy, destx, desty, dist) ...@@ -602,4 +659,3 @@ function _M:pointAtRange(srcx, srcy, destx, desty, dist)
return lx, ly return lx, ly
end end
end end
...@@ -56,6 +56,7 @@ function _M:project(t, x, y, damtype, dam, particles) ...@@ -56,6 +56,7 @@ function _M:project(t, x, y, damtype, dam, particles)
local grids = {} local grids = {}
local function addGrid(x, y) local function addGrid(x, y)
if typ.filter and not typ.filter(x, y) then return end
if not grids[x] then grids[x] = {} end if not grids[x] then grids[x] = {} end
grids[x][y] = true grids[x][y] = true
end end
...@@ -112,7 +113,9 @@ function _M:project(t, x, y, damtype, dam, particles) ...@@ -112,7 +113,9 @@ function _M:project(t, x, y, damtype, dam, particles)
end end
end end
local single_target = true
if typ.ball and typ.ball > 0 then if typ.ball and typ.ball > 0 then
single_target = false
core.fov.calc_circle( core.fov.calc_circle(
stop_radius_x, stop_radius_x,
stop_radius_y, stop_radius_y,
...@@ -128,7 +131,10 @@ function _M:project(t, x, y, damtype, dam, particles) ...@@ -128,7 +131,10 @@ function _M:project(t, x, y, damtype, dam, particles)
end, end,
nil) nil)
addGrid(stop_x, stop_y) addGrid(stop_x, stop_y)
elseif typ.cone and typ.cone > 0 then end
if typ.cone and typ.cone > 0 then
single_target = false
--local dir_angle = math.deg(math.atan2(y - self.y, x - self.x)) --local dir_angle = math.deg(math.atan2(y - self.y, x - self.x))
core.fov.calc_beam_any_angle( core.fov.calc_beam_any_angle(
stop_radius_x, stop_radius_x,
...@@ -149,7 +155,10 @@ function _M:project(t, x, y, damtype, dam, particles) ...@@ -149,7 +155,10 @@ function _M:project(t, x, y, damtype, dam, particles)
end, end,
nil) nil)
addGrid(stop_x, stop_y) addGrid(stop_x, stop_y)
elseif typ.wall and typ.wall > 0 then end
if typ.wall and typ.wall > 0 then
single_target = false
core.fov.calc_wall( core.fov.calc_wall(
stop_radius_x, stop_radius_x,
stop_radius_y, stop_radius_y,
...@@ -168,11 +177,11 @@ function _M:project(t, x, y, damtype, dam, particles) ...@@ -168,11 +177,11 @@ function _M:project(t, x, y, damtype, dam, particles)
addGrid(px, py) addGrid(px, py)
end, end,
nil) nil)
else
-- Deal damage: single
addGrid(stop_x, stop_y)
end end
-- Deal damage: single
if single_target then addGrid(stop_x, stop_y) end
-- Check for minimum range -- Check for minimum range
if typ.min_range and core.fov.distance(typ.start_x, typ.start_y, stop_x, stop_y) < typ.min_range then if typ.min_range and core.fov.distance(typ.start_x, typ.start_y, stop_x, stop_y) < typ.min_range then
return return
...@@ -188,7 +197,7 @@ function _M:project(t, x, y, damtype, dam, particles) ...@@ -188,7 +197,7 @@ function _M:project(t, x, y, damtype, dam, particles)
end end
end end
end end
self:check("on_project_grids", grids) self:check("on_project_grids", grids)
-- Now project on each grid, one type -- Now project on each grid, one type
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment