Index: game/engines/default/engine/Target.lua =================================================================== --- game/engines/default/engine/Target.lua (revision 3925) +++ 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 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 } @@ -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}) else self.target_type = {} end Index: game/engines/default/engine/interface/ActorProject.lua =================================================================== --- game/engines/default/engine/interface/ActorProject.lua (revision 3925) +++ 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 3925) +++ 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, Index: game/modules/tome/data/zones/trollmire/npcs.lua =================================================================== --- game/modules/tome/data/zones/trollmire/npcs.lua (revision 3925) +++ game/modules/tome/data/zones/trollmire/npcs.lua (working copy) @@ -77,6 +77,14 @@ end, on_die = function(self, who) + --force the note to drop if it hasn't dropped already (such as if he died via drowning) + if self.on_takehit then + local n = game.zone:makeEntityByName(game.level, "object", "PROX_NOTE") + if n then + self.on_takehit = nil + game.zone:addEntity(game.level, n, "object", self.x, self.y) + end + end game.state:activateBackupGuardian("ALUIN", 2, 35, "... and we thought the trollmire was safer now!") game.player:resolveSource():setQuestStatus("start-allied", engine.Quest.COMPLETED, "trollmire") end, Index: game/modules/tome/data/timed_effects.lua =================================================================== --- game/modules/tome/data/timed_effects.lua (revision 3925) +++ game/modules/tome/data/timed_effects.lua (working copy) @@ -2003,8 +2003,9 @@ self.life = self.life - eff.life self.changed = true if self.life <= 0 then - game.logSeen(self, "%s died when the effects of increased life wore off.", self.name:capitalize()) - self:die(self) + self.life = 1 + self:setEffect(target.EFF_STUNNED, 3, {}) + game.logSeen(self, "%s's increased life wears off and is stunned by the change.", self.name:capitalize()) end end, } Index: game/modules/tome/data/maps/zones/vor-armoury-last.lua =================================================================== --- game/modules/tome/data/maps/zones/vor-armoury-last.lua (revision 3925) +++ game/modules/tome/data/maps/zones/vor-armoury-last.lua (working copy) @@ -21,15 +21,16 @@ starty = 34 defineTile(".", "FLOOR") +defineTile(";", "FLOOR", nil, nil, nil, {no_teleport=true}) defineTile("~", "DEEP_WATER") defineTile("#", "HARDWALL") defineTile('&', "DOOR_VAULT") defineTile("$", "FLOOR", {random_filter={add_levels=5, ego_chance=30}}) defineTile("%", "LAVA_FLOOR") -defineTile("*", "FLOOR", {random_filter={add_levels=20}}, {random_filter={name="overpowered greater multi-hued wyrm", add_levels=50}}) -defineTile("=", "FLOOR", {random_filter={unique=true, not_properties={"lore"}}}, {random_filter={name="overpowered greater multi-hued wyrm", add_levels=50}}) +defineTile("*", "FLOOR", {random_filter={add_levels=20}}, {random_filter={name="overpowered greater multi-hued wyrm", add_levels=50}}, nil, {no_teleport=true}) +defineTile("=", "FLOOR", {random_filter={unique=true, not_properties={"lore"}}}, {random_filter={name="overpowered greater multi-hued wyrm", add_levels=50}}, nil, {no_teleport=true}) --defineTile("^", "LAVA_FLOOR", "ZEMEKKYS_HAT", {random_filter={name="overpowered greater multi-hued wyrm", add_levels=50}}) -defineTile("^", "FLOOR", nil, {random_filter={name="overpowered greater multi-hued wyrm", add_levels=50}}) +defineTile("^", "FLOOR", nil, {random_filter={name="overpowered greater multi-hued wyrm", add_levels=50}}, nil, {no_teleport=true}) defineTile("+", "DOOR") defineTile('<', "UP") defineTile("o", "FLOOR", nil, {random_filter={add_levels=5, subtype="orc"}}) @@ -38,16 +39,16 @@ return [[ .....~~############################ -.....~##.#^........=#.............# -....~~#..#..........#.............# -....~##..#..........#.$$$$...$$$$.# -....~#...#..........#.$##$...$##$.# -...~~#...&....**....#.$##$...$##$.# -..~~##...&....**....#.$$$$...$$$$.# -..~##....#..........#%.o.o###o.o..# -..~#.....#..........#%%...###...%%# -.~~#.....#..........#%%...$$$..%%$# -~~~#.....#.........=#%%%%%%%%%%%%$# +.....~##.#^;;;;;;;;=#.............# +....~~#..#;;;;;;;;;;#.............# +....~##..#;;;;;;;;;;#.$$$$...$$$$.# +....~#...#;;;;;;;;;;#.$##$...$##$.# +...~~#...&;;;;**;;;;#.$##$...$##$.# +..~~##...&;;;;**;;;;#.$$$$...$$$$.# +..~##....#;;;;;;;;;;#%.o.o###o.o..# +..~#.....#;;;;;;;;;;#%%...###...%%# +.~~#.....#;;;;;;;;;;#%%...$$$..%%$# +~~~#.....#;;;;;;;;;=#%%%%%%%%%%%%$# ~#####+##############%..........%$# ~#..o.o.o.........o##...oooooo...$# ~#................o##............$# Index: game/modules/tome/data/talents/misc/inscriptions.lua =================================================================== --- game/modules/tome/data/talents/misc/inscriptions.lua (revision 3925) +++ game/modules/tome/data/talents/misc/inscriptions.lua (working copy) @@ -176,12 +176,17 @@ name = "Infusion: Sun", type = {"inscriptions/infusions", 1}, points = 1, - tactical = { BUFF = 1, DISABLE = 2 }, + tactical = { ATTACK_AREA = 1, DISABLE = 2 }, + range = 0, + radius = function(self, t) + local data = self:getInscriptionData(t.short_name) + return data.range + end, action = function(self, t) local data = self:getInscriptionData(t.short_name) - self:project({type="ball", range=0, selffire=true, radius=data.range}, self.x, self.y, engine.DamageType.LITE, 1) - self:project({type="ball", range=0, selffire=true, radius=data.range}, self.x, self.y, engine.DamageType.BREAK_STEALTH, 1) - self:project({type="ball", range=0, selffire=false, radius=data.range}, self.x, self.y, engine.DamageType.BLINDCUSTOMMIND, {power=data.power + data.inc_stat, turns=data.turns}) + self:project({type="ball", range=self:getTalentRange(t), selffire=true, radius=self:getTalentRadius(t)}, self.x, self.y, engine.DamageType.LITE, 1) + self:project({type="ball", range=self:getTalentRange(t), selffire=true, radius=self:getTalentRadius(t)}, self.x, self.y, engine.DamageType.BREAK_STEALTH, 1) + self:project({type="ball", range=self:getTalentRange(t), selffire=false, radius=self:getTalentRadius(t)}, self.x, self.y, engine.DamageType.BLINDCUSTOMMIND, {power=data.power + data.inc_stat, turns=data.turns}) return true end, info = function(self, t) Index: game/modules/tome/data/general/objects/scrolls.lua =================================================================== --- game/modules/tome/data/general/objects/scrolls.lua (revision 3925) +++ game/modules/tome/data/general/objects/scrolls.lua (working copy) @@ -199,7 +199,7 @@ cost = 10, material_level = 1, - inscription_kind = "utility", + inscription_kind = "attack", inscription_data = { cooldown = resolvers.rngrange(9, 15), range = resolvers.mbonus_level(5, 5, function(e, v) return v * 0.1 end), Index: game/modules/tome/class/interface/Combat.lua =================================================================== --- game/modules/tome/class/interface/Combat.lua (revision 3925) +++ game/modules/tome/class/interface/Combat.lua (working copy) @@ -254,7 +254,7 @@ print("[ATTACK] after inc by type", dam) end - if crit then game.logSeen(self, "%s performs a critical strike!", self.name:capitalize()) end + if crit then game.logSeen(self, "#{bold}#%s performs a critical strike!#{normal}#", self.name:capitalize()) end DamageType:get(damtype).projector(self, target.x, target.y, damtype, math.max(0, dam)) hitted = true else @@ -763,7 +763,7 @@ if rng.percent(chance) then dam = dam * (1.5 + (self.combat_critical_power or 0) / 100) crit = true - game.logSeen(self, "%s's spell attains critical power!", self.name:capitalize()) + game.logSeen(self, "#{bold}#%s's spell attains critical power!#{normal}#", self.name:capitalize()) if self:attr("mana_on_crit") then self:incMana(self:attr("mana_on_crit")) end Index: game/modules/tome/class/interface/Archery.lua =================================================================== --- game/modules/tome/class/interface/Archery.lua (revision 3925) +++ game/modules/tome/class/interface/Archery.lua (working copy) @@ -151,7 +151,7 @@ dam = dam * mult print("[ATTACK ARCHERY] after mult", dam) - if crit then game.logSeen(self, "%s performs a critical strike!", self.name:capitalize()) end + if crit then game.logSeen(self, "#{bold}#%s performs a critical strike!#{normal}#", self.name:capitalize()) end DamageType:get(damtype).projector(self, target.x, target.y, damtype, math.max(0, dam)) game.level.map:particleEmitter(target.x, target.y, 1, "archery") hitted = true Index: game/modules/tome/data/talents/spells/explosives.lua =================================================================== --- game/modules/tome/data/talents/spells/explosives.lua (revision 3925) +++ game/modules/tome/data/talents/spells/explosives.lua (working copy) @@ -92,7 +92,7 @@ for px, ys in pairs(grids) do for py, _ in pairs(ys) do nb = nb + 1 end end nb = theorical_nb - nb if nb > 0 then - local mult = (math.log10(nb) / math.min(6 - self:getTalentLevelRaw(self.T_EXPLOSION_EXPERT), 5)) + local mult = math.log10(nb) / (6 - math.min(self:getTalentLevelRaw(self.T_EXPLOSION_EXPERT), 5)) print("Adjusting explosion damage to account for ", nb, " lost tiles => ", mult * 100) dam = dam + dam * mult end Index: game/modules/tome/data/talents/cursed/dark-sustenance.lua =================================================================== --- game/modules/tome/data/talents/cursed/dark-sustenance.lua (revision 3925) +++ game/modules/tome/data/talents/cursed/dark-sustenance.lua (working copy) @@ -37,7 +37,7 @@ requires_target = function(self, t) return self:getTalentLevel(t) >= 5 end, direct_hit = true, getHateGain = function(self, t) - return math.sqrt(self:getTalentLevel(t)) * 0.2 + self:getWil(0.15) + return math.sqrt(self:getTalentLevel(t)) * 0.2 + self:getWil(0.15, true) end, action = function(self, t) local range = self:getTalentRange(t)