Commit 01df68a6d06f0056fa787d2ad7491d266aa9a780

Authored by Chris Davidson
1 parent df867540

Change how Bone Grab works

- Can now be targeted through allies (Rot worms, etc)

- Now checks Teleport resistance

- Always moves the target to the closest space adjacent to you
... ... @@ -1966,6 +1966,34 @@ function util.adjacentCoords(x, y, no_diagonals, no_cardinals)
1966 1966 return coords
1967 1967 end
1968 1968
  1969 +--- Return the closest adjacent coordinate to the source coordinate from the target coordinate (use for gap closer positioning, etc)
  1970 +-- @param x x-coordinate of the source tile.
  1971 +-- @param y y-coordinate of the source tile.
  1972 +-- @param tx x-coordinate of the target tile.
  1973 +-- @param ty y-coordinate of the target tile.
  1974 +-- @param check_block Boolean for whether to check for block_move
  1975 +-- @param extra_check(x,y) Function to run on each grid and return true if that grid is invalid
  1976 +-- @return Table containing the x,y coordinate of the closest grid.
  1977 +function util.closestAdjacentCoord(x, y, tx, ty, check_block, extra_check)
  1978 + local check_block = check_block or true
  1979 + local coords = util.adjacentCoords(x, y)
  1980 + local valid = {}
  1981 + for _, coord in pairs(coords) do
  1982 + if not (check_block and game.level.map:checkEntity(coord[1], coord[2], engine.Map.TERRAIN, "block_move")) and not (extra_check and extra_check(coord[1], coord[2])) then
  1983 + valid[#valid+1] = coord
  1984 + end
  1985 + end
  1986 +
  1987 + if #valid == 0 then return end
  1988 + local closest = valid[1]
  1989 + for _, coord in pairs(valid) do
  1990 + if core.fov.distance(closest[1], closest[2], tx, ty, true) > core.fov.distance(coord[1], coord[2], tx, ty, true) then
  1991 + closest = coord
  1992 + end
  1993 + end
  1994 +
  1995 + return closest
  1996 +end
1969 1997 function util.coordAddDir(x, y, dir)
1970 1998 local dx, dy = util.dirToCoord(dir, x, y)
1971 1999 return x + dx, y + dy
... ...
... ... @@ -72,7 +72,7 @@ newTalent{
72 72 getDuration = function(self, t) return math.floor(self:combatTalentScale(t, 4, 8)) end,
73 73 getDamage = function(self, t) return self:combatTalentSpellDamage(t, 5, 140) end,
74 74 action = function(self, t)
75   - local tg = {type="bolt", range=self:getTalentRange(t), talent=t}
  75 + local tg = {type="bolt", range=self:getTalentRange(t), friendlyblock=false, talent=t}
76 76 local x, y = self:getTarget(tg)
77 77 if not x or not y then return nil end
78 78
... ... @@ -82,13 +82,23 @@ newTalent{
82 82 if not target then return end
83 83
84 84 if core.fov.distance(self.x, self.y, target.x, target.y) > 1 then
85   - target:pull(self.x, self.y, tg.range)
86 85 DamageType:get(DamageType.PHYSICAL).projector(self, target.x, target.y, DamageType.PHYSICAL, dam)
87 86 if target:canBe("pin") then
88 87 target:setEffect(target.EFF_BONE_GRAB, t.getDuration(self, t), {apply_power=self:combatSpellpower()})
89 88 else
90 89 game.logSeen(target, "%s resists the pin!", target.name:capitalize())
91 90 end
  91 +
  92 + local hit = self:checkHit(self:combatSpellpower(), target:combatSpellResist() + (target:attr("continuum_destabilization") or 0))
  93 + if not target:canBe("teleport") or not hit then
  94 + game.logSeen(target, "%s resists being teleported by Bone Grab!", target.name:capitalize())
  95 + return true
  96 + end
  97 +
  98 + -- Grab the closest adjacent grid that doesn't have block_move or no_teleport
  99 + local grid = util.closestAdjacentCoord(self.x, self.y, target.x, target.y, true, function(x, y) return game.level.map.attrs(x, y, "no_teleport") end)
  100 + if not grid then return true end
  101 + target:teleportRandom(grid[1], grid[2], 0)
92 102 else
93 103 local tg = {type="cone", cone_angle=90, range=0, radius=6, friendlyfire=false}
94 104
... ... @@ -141,6 +151,7 @@ newTalent{
141 151 end,
142 152 callbackOnTalentPost = function(self, t, ab, ret, silent)
143 153 if ab.no_energy then return end
  154 + if ab.mode ~= "active" then return end
144 155 if self.turn_procs.bone_spike then return end
145 156 self.turn_procs.bone_spike = true
146 157
... ... @@ -182,7 +193,7 @@ newTalent{
182 193 direct_hit = true,
183 194 getRegen = function(self, t) return self:combatTalentLimit(t, 3, 20, 3.3) end,
184 195 getNb = function(self, t) return math.floor(self:combatTalentScale(t, 1, 3.5)) end,
185   - getThreshold = function(self, t) return math.floor(self:combatSpellpower()) end,
  196 + getThreshold = function(self, t) return math.floor(self:combatSpellpower() * 0.7) end,
186 197 iconOverlay = function(self, t, p)
187 198 local p = self.sustain_talents[t.id]
188 199 if not p or not p.nb then return "" end
... ...