Index: game/engines/default/engine/Target.lua =================================================================== --- game/engines/default/engine/Target.lua (revision 3922) +++ game/engines/default/engine/Target.lua (working copy) @@ -44,6 +44,12 @@ self.sg = core.display.newSurface(pot_width, pot_height) self.sg:erase(0, 255, 0, 90) self.sg = self.sg:glTexture() + self.sy = core.display.newSurface(pot_width, pot_height) + self.sy:erase(255, 255, 0, 90) + self.sy = self.sy:glTexture() + self.syg = core.display.newSurface(pot_width, pot_height) + self.syg:erase(153, 204, 50, 90) + self.syg = self.syg:glTexture() self.source_actor = source_actor @@ -85,12 +91,13 @@ while lx and ly do local 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) + block, hit, hit_radius = self.target_type:block_path(lx, ly, true) end -- Update coordinates and set color if hit and not stopped then stop_x, stop_y = lx, ly + if not block and hit == "unknown" then s = self.sy end else s = self.sr end @@ -124,13 +131,20 @@ game.level.map.h, self.target_type.ball, function(_, px, py) - if self.target_type.block_radius and self.target_type:block_radius(px, py) then return true end + if self.target_type.block_radius and self.target_type:block_radius(px, py, true) then return true end end, function(_, px, py) - self.sg:toScreen(self.display_x + (px - game.level.map.mx) * self.tile_w * Map.zoom, - self.display_y + (py - 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 not game.level.map.remembers(px, py) and not game.level.map.seens(px, py) then + self.syg:toScreen(self.display_x + (px - game.level.map.mx) * self.tile_w * Map.zoom, + self.display_y + (py - game.level.map.my) * self.tile_h * Map.zoom, + self.tile_w * Map.zoom, + self.tile_h * Map.zoom) + else + self.sg:toScreen(self.display_x + (px - game.level.map.mx) * self.tile_w * Map.zoom, + self.display_y + (py - game.level.map.my) * self.tile_h * Map.zoom, + self.tile_w * Map.zoom, + self.tile_h * Map.zoom) + end end, nil) elseif self.target_type.cone and self.target_type.cone > 0 then @@ -144,13 +158,20 @@ dir_angle, self.target_type.cone_angle, function(_, px, py) - if self.target_type.block_radius and self.target_type:block_radius(px, py) then return true end + if self.target_type.block_radius and self.target_type:block_radius(px, py, true) then return true end end, function(_, px, py) - self.sg:toScreen(self.display_x + (px - game.level.map.mx) * self.tile_w * Map.zoom, - self.display_y + (py - 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 not game.level.map.remembers(px, py) and not game.level.map.seens(px, py) then + self.syg:toScreen(self.display_x + (px - game.level.map.mx) * self.tile_w * Map.zoom, + self.display_y + (py - game.level.map.my) * self.tile_h * Map.zoom, + self.tile_w * Map.zoom, + self.tile_h * Map.zoom) + else + self.sg:toScreen(self.display_x + (px - game.level.map.mx) * self.tile_w * Map.zoom, + self.display_y + (py - game.level.map.my) * self.tile_h * Map.zoom, + self.tile_w * Map.zoom, + self.tile_h * Map.zoom) + end end, nil) end @@ -183,30 +204,45 @@ range=20, selffire=true, friendlyfire=true, - block_path = function(typ, lx, ly) + block_path = function(typ, lx, ly, for_highlights) if not typ.no_restrict then - if typ.range and typ.source_actor and typ.source_actor.x then + if typ.range and typ.start_x then + local dist = core.fov.distance(typ.start_x, typ.start_y, lx, ly) + if math.floor(dist - typ.range + 0.5) > 0 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 math.floor(dist - typ.range + 0.5) > 0 then return true, false, false end end - if typ.requires_knowledge and not game.level.map.remembers(lx, ly) and not game.level.map.seens(lx, ly) then + 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 - return true, true, false + 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") if nb > 1 or (nb == 1 and game.level.map:checkAllEntities(lx, ly, "block_move") and not game.level.map:checkEntity(lx, ly, engine.Map.TERRAIN, "pass_projectile")) then - return true, true, true + if for_highlights and not is_known then + return false, "unknown", true + else + return true, true, true + end 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) - return not typ.no_restrict and game.level.map:checkEntity(lx, ly, engine.Map.TERRAIN, "block_move") + 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 (for_highlights and not (game.level.map.remembers(lx, ly) or game.level.map.seens(lx, ly))) end } @@ -238,7 +274,7 @@ if v and type then self.target_type = self:getType(type) -- Targeting will generally want to stop at unseen/remembered tiles - table.update(self.target_type, {requires_knowledge=true}) +-- table.update(self.target_type, {requires_knowledge=true}) -- Is this used for any other reason except for targeting highlights? Commented out for improved highlighting. else self.target_type = {} end Index: game/engines/default/engine/interface/ActorProject.lua =================================================================== --- game/engines/default/engine/interface/ActorProject.lua (revision 3922) +++ game/engines/default/engine/interface/ActorProject.lua (working copy) @@ -169,6 +169,8 @@ function _M:canProject(t, x, y) local typ = Target:getType(t) typ.source_actor = self + typ.start_x = self.x + typ.start_y = self.y -- Stop at range or on block local lx, ly = x, y @@ -214,6 +216,8 @@ -- if type(dam) == "number" and dam < 0 then return end local typ = Target:getType(t) typ.source_actor = self + typ.start_x = self.x + typ.start_y = self.y local proj = require(self.projectile_class):makeProject(self, t.display, {x=x, y=y, start_x = t.x or self.x, start_y = t.y or self.y, damtype=damtype, tg=t, typ=typ, dam=dam, particles=particles}) game.zone:addEntity(game.level, proj, "projectile", t.x or self.x, t.y or self.y) Index: game/modules/tome/data/talents/spells/staff-combat.lua =================================================================== --- game/modules/tome/data/talents/spells/staff-combat.lua (revision 3922) +++ game/modules/tome/data/talents/spells/staff-combat.lua (working copy) @@ -29,14 +29,23 @@ proj_speed = 20, requires_target = true, target = function(self, t) - return {type="bolt", range=self:getTalentRange(t), talent=t, display = {particle=particle, trail=trail}, - -- Like a normal block_path, but goes over friendlies - block_path = function(typ, lx, ly) + return {type="bolt", range=self:getTalentRange(t), talent=t, display = {particle=particle, trail=trail}, friendlyfire=false, + -- Like a normal block_path, but goes over friendlies. Also, cannot gain additional range by firing over friendlies. + block_path = function(typ, lx, ly, for_highlights) + -- use default 'block_path' + local dummy_typ = engine.Target:getType({type="bolt"}) + local block, hit, hit_radius = dummy_typ.block_path(typ, lx, ly, for_highlights) local a = game.level.map(lx, ly, engine.Map.ACTOR) - if a and self:reactionToward(a) >= 0 then return false, lx, ly - elseif game.level.map:checkAllEntities(lx, ly, "block_move") then return true, lx, ly end - if typ.range and typ.source_actor and typ.source_actor.x and math.sqrt((typ.source_actor.x-lx)^2 + (typ.source_actor.y-ly)^2) > typ.range then return true end - return false, lx, ly + local block_from_range = false + if typ.range and typ.start_x then + local dist = core.fov.distance(typ.start_x, typ.start_y, lx, ly) + if math.floor(dist - typ.range + 0.5) > 0 then block_from_range = true 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 math.floor(dist - typ.range + 0.5) > 0 then block_from_range = true end + end + if a then return block_from_range or self:reactionToward(a) < 0, hit, hit_radius + else return block, hit, hit_radius end end, } end,