Skip to content
Snippets Groups Projects
Commit 256a264e authored by dg's avatar dg
Browse files

Refactored Target:getType() to be more generic

git-svn-id: http://svn.net-core.org/repos/t-engine4@1475 51575b47-30f0-44d4-a5cc-537603b46e54
parent cb174565
No related branches found
No related tags found
No related merge requests found
......@@ -73,12 +73,7 @@ function _M:display(dispx, dispy)
local stopx, stopy = self.source_actor.x, self.source_actor.y
while lx and ly do
if s == self.sb then stopx, stopy = lx, ly end
if not self.target_type.no_restrict then
if not game.level.map.seens(lx, ly) then s = self.sr end
if self.target_type.stop_block and game.level.map:checkAllEntities(lx, ly, "block_move") then s = self.sr
elseif game.level.map:checkEntity(lx, ly, Map.TERRAIN, "block_move") then s = self.sr end
end
if self.target_type.range and math.sqrt((self.source_actor.x-lx)^2 + (self.source_actor.y-ly)^2) > self.target_type.range then s = self.sr end
if self.target_type.block_path and self.target_type:block_path(lx, ly) then s = self.sr end
s:toScreen(self.display_x + (lx - game.level.map.mx) * self.tile_w * Map.zoom, self.display_y + (ly - game.level.map.my) * self.tile_h * Map.zoom, self.tile_w * Map.zoom, self.tile_h * Map.zoom)
lx, ly = l()
end
......@@ -89,49 +84,71 @@ function _M:display(dispx, dispy)
if self.target_type.ball and self.target_type.ball > 0 then
core.fov.calc_circle(stopx, stopy, self.target_type.ball, function(_, lx, ly)
self.sg:toScreen(self.display_x + (lx - game.level.map.mx) * self.tile_w * Map.zoom, self.display_y + (ly - game.level.map.my) * self.tile_h * Map.zoom, self.tile_w * Map.zoom, self.tile_h * Map.zoom)
if not self.target_type.no_restrict and game.level.map:checkEntity(lx, ly, Map.TERRAIN, "block_move") then return true end
if self.target_type.block_radius and self.target_type:block_radius(lx, ly) then return true end
end, function()end, nil)
elseif self.target_type.cone and self.target_type.cone > 0 then
core.fov.calc_beam(stopx, stopy, self.target_type.cone, initial_dir, self.target_type.cone_angle, function(_, lx, ly)
self.sg:toScreen(self.display_x + (lx - game.level.map.mx) * self.tile_w * Map.zoom, self.display_y + (ly - game.level.map.my) * self.tile_h * Map.zoom, self.tile_w * Map.zoom, self.tile_h * Map.zoom)
if not self.target_type.no_restrict and game.level.map:checkEntity(lx, ly, Map.TERRAIN, "block_move") then return true end
if self.target_type.block_radius and self.target_type:block_radius(lx, ly) then return true end
end, function()end, nil)
end
self.display_x, self.display_y = ox, oy
end
--- Returns data for the given target type
-- @return t The target table used by ActorProject, Projectile, GameTargeting, etc.
-- @param t Target table used to generate the
-- @param t.type The engine-defined type, populates other more complex variables (see below)
-- Hit: simple project in LOS<br/>
-- Beam: hits everything in LOS<br/>
-- Bolt: hits first thing in path<br/>
-- Ball: hits everything in a ball aounrd the target<br/>
-- Cone: hits everything in a cone in the direction<br/>
-- @param t.radius The radius of the ball/cone AoE
-- @param t.cone_angle The angle for the cone AoE (default 55°)
-- @param t.no_restrict Boolean that removes all restrictions in the t.type defined block functions.
-- @param t.stop_block Boolean that stops the target on the first tile that has an entity that blocks move.
-- @param t.range The range the target can be from the origin.
-- @param t.pass_terrain Boolean that allows the target to pass through terrain to remembered tiles on the other side.
-- @param t.block_path(typ, lx, ly) Function called on each tile to determine if the targeting is blocked. Automatically set when using t.typ, but the user can provide their own if they know what they are doing.
-- @param t.block_radius(typ, lx, ly) Function called on each tile when projecting the radius to determine if the radius projection is blocked. Automatically set when using t.typ, but the user can provide their own if they know what they are doing.
function _M:getType(t)
if not t or not t.type then return {} end
t.range = t.range or 20
if t.friendlyfire == nil then t.friendlyfire = true end
if t.type == "hit" then
return {range=t.range, friendlyfire=t.friendlyfire, no_restrict=t.no_restrict}
elseif t.type == "beam" then
return {range=t.range, friendlyfire=t.friendlyfire, no_restrict=t.no_restrict, line=true}
elseif t.type == "bolt" then
return {range=t.range, friendlyfire=t.friendlyfire, no_restrict=t.no_restrict, stop_block=true}
elseif t.type == "ball" then
return {range=t.range, friendlyfire=t.friendlyfire, no_restrict=t.no_restrict, ball=t.radius}
elseif t.type == "cone" then
return {range=t.range, friendlyfire=t.friendlyfire, no_restrict=t.no_restrict, cone=t.radius, cone_angle=t.cone_angle or 55}
elseif t.type == "ballbolt" then
return {range=t.range, friendlyfire=t.friendlyfire, no_restrict=t.no_restrict, ball=t.radius, stop_block=true}
elseif t.type == "conebolt" then
return {range=t.range, friendlyfire=t.friendlyfire, no_restrict=t.no_restrict, cone=t.radius, cone_angle=t.cone_angle or 55, stop_block=true}
elseif t.type == "ballbeam" then
return {range=t.range, friendlyfire=t.friendlyfire, no_restrict=t.no_restrict, ball=t.radius, line=true}
elseif t.type == "conebeam" then
return {range=t.range, friendlyfire=t.friendlyfire, no_restrict=t.no_restrict, cone=t.radius, cone_angle=t.cone_angle or 55, line=true}
else
return {}
if not t then return {} end
-- Add the default values
t = table.clone(t)
target_type = {
range=20,
friendlyfire=true,
block_path = function(typ, lx, ly)
if not typ.no_restrict then
if not game.level.map.remembers(lx, ly) then return true end
if typ.stop_block and game.level.map:checkAllEntities(lx, ly, "block_move") then return true
elseif not typ.pass_terrain and game.level.map:checkEntity(lx, ly, Map.TERRAIN, "block_move") then return true end
if typ.range and self.source_actor and math.sqrt((self.source_actor.x-lx)^2 + (self.source_actor.y-ly)^2) > typ.range then return true end
end
end,
block_radius=function(typ, lx, ly)
return typ.no_restrict and game.level.map:checkEntity(lx, ly, Map.TERRAIN, "block_move")
end
}
table.update(t, target_type)
-- And now modify for the default types
if t.type then
if t.type:find("ball") then
target_type.ball = t.radius
end
if t.type:find("cone") then
target_type.cone = t.radius
target_type.cone_angle = t.cone_angle or 55
end
if t.type:find("bolt") then
target_type.stop_block = true
elseif t.type:find("beam") then
target_type.line = true
end
end
table.update(t, target_type)
return t
end
function _M:setActive(v, type)
......
......@@ -60,11 +60,7 @@ function _M:project(t, x, y, damtype, dam, particles)
lx, ly = l()
local initial_dir = lx and coord_to_dir[lx - srcx][ly - srcy] or 5
while lx and ly do
if not typ.no_restrict then
if typ.stop_block and game.level.map:checkAllEntities(lx, ly, "block_move") then break
elseif game.level.map:checkEntity(lx, ly, Map.TERRAIN, "block_move") then break end
if typ.range and math.sqrt((srcx-lx)^2 + (srcy-ly)^2) > typ.range then break end
end
if typ.block_path and typ:block_path(lx, ly) then break end
-- Deam damage: beam
if typ.line then addGrid(lx, ly) end
......@@ -78,14 +74,14 @@ function _M:project(t, x, y, damtype, dam, particles)
core.fov.calc_circle(lx, ly, typ.ball, function(_, px, py)
-- Deal damage: ball
addGrid(px, py)
if not typ.no_restrict and game.level.map:checkEntity(px, py, Map.TERRAIN, "block_move") then return true end
if typ.block_radius and not typ:block_radius(lx, ly) then return true end
end, function()end, nil)
addGrid(lx, ly)
elseif typ.cone and typ.cone > 0 then
core.fov.calc_beam(lx, ly, typ.cone, initial_dir, typ.cone_angle, function(_, px, py)
-- Deal damage: cone
addGrid(px, py)
if not typ.no_restrict and game.level.map:checkEntity(px, py, Map.TERRAIN, "block_move") then return true end
if typ.block_radius and not typ:block_radius(lx, ly) then return true end
end, function()end, nil)
addGrid(lx, ly)
else
......@@ -144,11 +140,7 @@ function _M:canProject(t, x, y)
local l = line.new(self.x, self.y, x, y)
lx, ly = l()
while lx and ly do
if not typ.no_restrict then
if typ.stop_block and game.level.map:checkAllEntities(lx, ly, "block_move") then break
elseif game.level.map:checkEntity(lx, ly, Map.TERRAIN, "block_move") then break end
if typ.range and math.sqrt((self.x-lx)^2 + (self.y-ly)^2) > typ.range then break end
end
if typ.block_path and typ:block_path(lx, ly) then break end
lx, ly = l()
end
......@@ -193,11 +185,7 @@ function _M:projectDoMove(typ, tgtx, tgty, x, y, srcx, srcy)
if lx and ly then lx, ly = l() end
if lx and ly then
if not typ.no_restrict then
if typ.stop_block and game.level.map:checkAllEntities(lx, ly, "block_move") then return lx, ly, false, true
elseif game.level.map:checkEntity(lx, ly, Map.TERRAIN, "block_move") then return lx, ly, false, true end
if typ.range and math.sqrt((srcx-lx)^2 + (srcy-ly)^2) > typ.range then return lx, ly, false, true end
end
if typ.block_path and typ:block_path(lx, ly) then return lx, ly, false, true end
-- End of the map
if lx < 0 or lx >= game.level.map.w or ly < 0 or ly >= game.level.map.h then return lx, ly, false, true end
......@@ -251,7 +239,7 @@ function _M:projectDoStop(typ, tg, damtype, dam, particles, lx, ly, tmp)
core.fov.calc_circle(lx, ly, typ.ball, function(_, px, py)
-- Deal damage: ball
addGrid(px, py)
if not typ.no_restrict and game.level.map:checkEntity(px, py, Map.TERRAIN, "block_move") then return true end
if typ.block_radius and not typ:block_radius(lx, ly) then return true end
end, function()end, nil)
addGrid(lx, ly)
elseif typ.cone and typ.cone > 0 then
......@@ -259,7 +247,7 @@ function _M:projectDoStop(typ, tg, damtype, dam, particles, lx, ly, tmp)
core.fov.calc_beam(lx, ly, typ.cone, initial_dir, typ.cone_angle, function(_, px, py)
-- Deal damage: cone
addGrid(px, py)
if not typ.no_restrict and game.level.map:checkEntity(px, py, Map.TERRAIN, "block_move") then return true end
if typ.block_radius and not typ:block_radius(lx, ly) then return true end
end, function()end, nil)
addGrid(lx, ly)
else
......
......@@ -101,12 +101,25 @@ function table.reverse(t)
for i, e in ipairs(t) do tt[e] = i end
return tt
end
function table.listify(t)
local tt = {}
for k, e in pairs(t) do tt[#tt+1] = {k, e} end
return tt
end
function table.update(dst, src, deep)
for k, e in pairs(src) do
if deep and dst[k] and type(e) == "table" and type(dst[k]) == "table" and not e.__CLASSNAME then
table.update(dst[k], e, true)
elseif deep and not dst[k] and type(e) == "table" and not e.__CLASSNAME then
dst[k] = table.clone(e, true)
elseif not dst[k] then
dst[k] = e
end
end
end
function string.ordinal(number)
local suffix = "th"
number = tonumber(number)
......
......@@ -54,7 +54,7 @@ newTalent{
local x, y = self.x, self.y
if self:getTalentLevel(t) >= 4 then
local tg = {type="ball", nolock=true, no_restrict=true, nowarning=true, range=10 + self:combatSpellpower(0.1), radius=7 - self:getTalentLevel(t)}
local tg = {type="ball", nolock=true, pass_terrain=true, nowarning=true, range=10 + self:combatSpellpower(0.1), radius=7 - self:getTalentLevel(t)}
x, y = self:getTarget(tg)
if not x then return nil end
-- Target code doesnot restrict the target coordinates to the range, it lets the poject function do it
......@@ -123,7 +123,7 @@ newTalent{
local x, y = self.x, self.y
if self:getTalentLevel(t) >= 4 then
local tg = {type="ball", nolock=true, no_restrict=true, nowarning=true, range=100 + self:combatSpellpower(1), radius=20 - self:getTalentLevel(t)}
local tg = {type="ball", nolock=true, pass_terrain=true, nowarning=true, range=100 + self:combatSpellpower(1), radius=20 - self:getTalentLevel(t)}
x, y = self:getTarget(tg)
if not x then return nil end
-- Target code doesnot restrict the target coordinates to the range, it lets the poject function do it
......
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