From 2b1c997c74b7657f4a347ca70ae1976f347b316e Mon Sep 17 00:00:00 2001 From: dg <dg@51575b47-30f0-44d4-a5cc-537603b46e54> Date: Sat, 19 Mar 2011 12:38:22 +0000 Subject: [PATCH] Better running algorithm Recalling will fail when you can not move, to prevent being stuck on the worldmap git-svn-id: http://svn.net-core.org/repos/t-engine4@3032 51575b47-30f0-44d4-a5cc-537603b46e54 --- .../default/engine/interface/PlayerRun.lua | 248 +++++++++++++----- game/modules/tome/class/Player.lua | 27 +- .../data/general/objects/quest-artifacts.lua | 2 +- .../tome/data/maps/towns/gates-of-morning.lua | 30 +-- .../tome/data/maps/towns/last-hope.lua | 36 +-- game/modules/tome/data/talents/misc/misc.lua | 2 +- game/modules/tome/data/timed_effects.lua | 4 +- 7 files changed, 243 insertions(+), 106 deletions(-) diff --git a/game/engines/default/engine/interface/PlayerRun.lua b/game/engines/default/engine/interface/PlayerRun.lua index 1f9e7febce..767f1520a2 100644 --- a/game/engines/default/engine/interface/PlayerRun.lua +++ b/game/engines/default/engine/interface/PlayerRun.lua @@ -26,59 +26,58 @@ module(..., package.seeall, class.make) local sides = { - [1] = {left=2, right=4}, - [2] = {left=3, right=1}, - [3] = {left=6, right=2}, - [4] = {left=1, right=7}, - [6] = {left=9, right=3}, - [7] = {left=4, right=8}, - [8] = {left=7, right=9}, - [9] = {left=8, right=6}, -} - -local turn = -{ - [1] = {left=3, right=7}, - [2] = {left=6, right=4}, - [3] = {left=9, right=1}, - [4] = {left=2, right=8}, - [6] = {left=8, right=2}, - [7] = {left=1, right=9}, - [8] = {left=4, right=6}, - [9] = {left=7, right=3}, + [1] = {hard_left=3, soft_left=2, soft_right=4, hard_right=7}, + [4] = {hard_left=2, soft_left=1, soft_right=7, hard_right=8}, + [7] = {hard_left=1, soft_left=4, soft_right=8, hard_right=9}, + [8] = {hard_left=4, soft_left=7, soft_right=9, hard_right=6}, + [9] = {hard_left=7, soft_left=8, soft_right=6, hard_right=3}, + [6] = {hard_left=8, soft_left=9, soft_right=3, hard_right=2}, + [3] = {hard_left=9, soft_left=6, soft_right=2, hard_right=1}, + [2] = {hard_left=6, soft_left=3, soft_right=1, hard_right=4}, } local function checkDir(a, dir, dist) dist = dist or 1 local dx, dy = dir_to_coord[dir][1], dir_to_coord[dir][2] local x, y = a.x + dx * dist, a.y + dy * dist - return game.level.map:checkAllEntities(x, y, "block_move", a) and true or false -end -local function isEdge(a, dir, dist) - dist = dist or 1 - local dx, dy = dir_to_coord[dir][1], dir_to_coord[dir][2] - local x, y = a.x + dx * dist, a.y + dy * dist - return not game.level.map:isBound(x, y) and true or false + -- don't treat other actors as terrain or as something to notice (let the module handle this) + if game.level.map(x, y, game.level.map.ACTOR) and not game.level.map:checkEntity(x, y, game.level.map.TERRAIN, "block_move") then return false end + return (game.level.map:checkAllEntities(x, y, "block_move", a) or not game.level.map:isBound(x, y)) and true or false end --- Initializes running -- We check the direction sides to know if we are in a tunnel, along a wall or in open space. function _M:runInit(dir) - local block_left, block_right = false, false - - -- Check sides - if checkDir(self, sides[dir].left) then block_left = true end - if checkDir(self, sides[dir].right) then block_right = true end + if checkDir(self, dir) then return end self.running = { dir = dir, - block_left = block_left, - block_right = block_right, + block_left = false, + block_right = false, + block_hard_left = false, + block_hard_right = false, cnt = 1, dialog = Dialog:simplePopup("Running...", "You are running, press Enter to stop.", function() self:runStop() end, false, true), } + + -- Check sides + if checkDir(self, sides[dir].hard_left) then self.running.block_hard_left = true end + if checkDir(self, sides[dir].hard_right) then self.running.block_hard_right = true end + + if checkDir(self, sides[dir].soft_left) then + self.running.block_left = true + else + self.running.ignore_left = 2 + end + + if checkDir(self, sides[dir].soft_right) then + self.running.block_right = true + else + self.running.ignore_right = 2 + end + self.running.dialog.__showup = nil self.running.dialog.__hidden = true @@ -132,12 +131,50 @@ function _M:runStep() return false else local oldx, oldy = self.x, self.y + local dir_is_cardinal = self.running.dir == 2 or self.running.dir == 4 or self.running.dir == 6 or self.running.dir == 8 if self.running.path then if not self.running.path[self.running.cnt] then self:runStop() else self:move(self.running.path[self.running.cnt].x, self.running.path[self.running.cnt].y) end else - if isEdge(self, self.running.dir) then self:runStop() - else self:moveDir(self.running.dir) end + -- Try to move around known traps if possible + local dx, dy = dir_to_coord[self.running.dir][1], dir_to_coord[self.running.dir][2] + local x, y = self.x + dx, self.y + dy + local trap = game.level.map(x, y, game.level.map.TRAP) + if trap and trap:knownBy(self) then + -- Take a phantom step forward and check path; backup current data first + local running_bak = table.clone(self.running) + self.x, self.y = x, y + local ret2, msg2 = self:runCheck(true) -- don't remember other items or traps from phantom steps + if self.running.dir == sides[running_bak.dir].hard_left then + running_bak.dir = sides[running_bak.dir].soft_left + elseif self.running.dir == sides[running_bak.dir].hard_right then + running_bak.dir = sides[running_bak.dir].soft_right + else + ret2 = false + end + if self.running.ignore_left then + running_bak.ignore_left = running_bak.ignore_left - 1 + if running_bak.ignore_left <= 0 then running_bak.ignore_left = nil end + if checkDir(self, sides[self.running.dir].soft_left) and (not checkDir(self, self.running.dir) or not dir_is_cardinal) then running_bak.block_left = true end + end + if self.running.ignore_right then + running_bak.ignore_right = running_bak.ignore_right - 1 + if running_bak.ignore_right <= 0 then running_bak.ignore_right = nil end + if checkDir(self, sides[self.running.dir].soft_right) and (not checkDir(self, self.running.dir) or not dir_is_cardinal) then running_bak.block_right = true end + end + if self.running.block_left then running_bak.ignore_left = nil end + if self.running.block_right then running_bak.ignore_right = nil end + -- Put data back + self.x, self.y = oldx, oldy + self.running = running_bak + -- Can't run around the trap + if not ret2 then + self:runStop("trap spotted") + return false + end + end + -- Move! + self:moveDir(self.running.dir) end self:runMoved() @@ -147,17 +184,17 @@ function _M:runStep() if not self.running then return false end self.running.cnt = self.running.cnt + 1 - if self.running.newdir then - self.running.dir = self.running.newdir - self.running.newdir = nil - end + if self.running.block_left then self.running.ignore_left = nil end if self.running.ignore_left then self.running.ignore_left = self.running.ignore_left - 1 if self.running.ignore_left <= 0 then self.running.ignore_left = nil end + if checkDir(self, sides[self.running.dir].soft_left) and (not checkDir(self, self.running.dir) or not dir_is_cardinal) then self.running.block_left = true end end + if self.running.block_right then self.running.ignore_right = nil end if self.running.ignore_right then self.running.ignore_right = self.running.ignore_right - 1 if self.running.ignore_right <= 0 then self.running.ignore_right = nil end + if checkDir(self, sides[self.running.dir].soft_right) and (not checkDir(self, self.running.dir) or not dir_is_cardinal) then self.running.block_right = true end end return true @@ -171,27 +208,109 @@ end -- @return true if we can continue to run, false otherwise function _M:runCheck() if not self.running.path then + local dir_is_cardinal = self.running.dir == 2 or self.running.dir == 4 or self.running.dir == 6 or self.running.dir == 8 + local blocked_ahead = checkDir(self, self.running.dir) + local blocked_soft_left = checkDir(self, sides[self.running.dir].soft_left) + local blocked_hard_left = checkDir(self, sides[self.running.dir].hard_left) + local blocked_soft_right = checkDir(self, sides[self.running.dir].soft_right) + local blocked_hard_right = checkDir(self, sides[self.running.dir].hard_right) + -- Do we change run direction ? We can only choose to change for left or right, never backwards. -- We must also be in a tunnel (both sides blocked) - if self.running.block_left and self.running.block_right then - -- Turn left - if not checkDir(self, self.running.dir) and checkDir(self, self.running.dir, 2) and not checkDir(self, sides[self.running.dir].left) and checkDir(self, sides[self.running.dir].right) then - self.running.newdir = turn[self.running.dir].left - self.running.ignore_left = 2 - return true - end - - -- Turn right - if not checkDir(self, self.running.dir) and checkDir(self, self.running.dir, 2) and checkDir(self, sides[self.running.dir].left) and not checkDir(self, sides[self.running.dir].right) then - self.running.newdir = turn[self.running.dir].right - self.running.ignore_right = 2 - return true + if (self.running.block_left or self.running.ignore_left) and (self.running.block_right or self.running.ignore_right) then + if blocked_ahead then + if blocked_soft_right and (blocked_hard_right or self.running.ignore_right) then + local blocked_back_left = checkDir(self, sides[sides[self.running.dir].hard_left].soft_left) + -- Turn soft left + if not blocked_soft_left and (blocked_hard_left or not dir_is_cardinal) then + if not dir_is_cardinal and not blocked_hard_left and not (checkDir(self, sides[self.running.dir].soft_left, 2) and blocked_back_left) then + return false, "terrain changed ahead" + end + self.running.dir = sides[self.running.dir].soft_left + self.running.block_right = true + if blocked_hard_left then self.running.block_left = true end + return true + end + -- Turn hard left + if not blocked_hard_left and (not self.running.ignore_left or (self.running.block_hard_left and self.running.block_right)) then + if dir_is_cardinal and not blocked_soft_left and not checkDir(self, sides[self.running.dir].hard_left, 2) then + return false, "terrain change on the left" + end + if not dir_is_cardinal and not blocked_back_left then + return false, "terrain ahead blocks" + end + self.running.dir = sides[self.running.dir].hard_left + if self.running.block_hard_left and self.running.ignore_left and self.running.ignore_left == 1 then + self.running.block_left = true + end + return true + end + end + + if blocked_soft_left and (blocked_hard_left or self.running.ignore_left) then + local blocked_back_right = checkDir(self, sides[sides[self.running.dir].hard_right].soft_right) + -- Turn soft right + if not blocked_soft_right and (blocked_hard_right or not dir_is_cardinal) then + if not dir_is_cardinal and not blocked_hard_right and not (checkDir(self, sides[self.running.dir].soft_right, 2) and blocked_back_right) then + return false, "terrain changed ahead" + end + self.running.dir = sides[self.running.dir].soft_right + self.running.block_left = true + if blocked_hard_right then self.running.block_right = true end + return true + end + -- Turn hard right + if not blocked_hard_right and (not self.running.ignore_right or (self.running.block_hard_right and self.running.block_left)) then + if dir_is_cardinal and not blocked_soft_right and not checkDir(self, sides[self.running.dir].hard_right, 2) then + return false, "terrain change on the right" + end + if not dir_is_cardinal and not blocked_back_right then + return false, "terrain ahead blocks" + end + self.running.dir = sides[self.running.dir].hard_right + if self.running.block_hard_right and self.running.ignore_right and self.running.ignore_right == 1 then + self.running.block_right = true + end + return true + end + end + else + -- Favor cardinal directions if possible, otherwise we may miss something interesting + if not dir_is_cardinal then + -- Turn soft left + if blocked_soft_right and blocked_hard_left and not blocked_soft_left and checkDir(self, sides[self.running.dir].soft_left, 2) and (not self.running.ignore_left or self.running.ignore_left ~= 2) then + self.running.dir = sides[self.running.dir].soft_left + self.running.block_left = true + self.running.block_right = true + return true + end + -- Turn soft right + if blocked_soft_left and blocked_hard_right and not blocked_soft_right and checkDir(self, sides[self.running.dir].soft_right, 2) and (not self.running.ignore_right or self.running.ignore_right ~= 2) then + self.running.dir = sides[self.running.dir].soft_right + self.running.block_left = true + self.running.block_right = true + return true + end + end + if checkDir(self, self.running.dir, 2) then + if not dir_is_cardinal and ((self.running.block_left and not blocked_hard_left and not self.running.ignore_left) or (self.running.block_right and not blocked_hard_right and not self.running.ignore_right)) then + return false, "terrain changed ahead" + end + -- Continue forward so we may turn + if (blocked_soft_left and not blocked_soft_right) or (blocked_soft_right and not blocked_soft_left) then return true end + end end end - - if not self.running.ignore_left and self.running.block_left ~= checkDir(self, sides[self.running.dir].left) then return false, "terrain change on left side" end - if not self.running.ignore_right and self.running.block_right ~= checkDir(self, sides[self.running.dir].right) then return false, "terrain change on right side" end - if checkDir(self, self.running.dir) then return false, "terrain ahead blocks" end + + if not self.running.ignore_left and (self.running.block_left ~= blocked_soft_left or self.running.block_left ~= blocked_hard_left) then + return false, "terrain change on left side" + end + if not self.running.ignore_right and (self.running.block_right ~= blocked_soft_right or self.running.block_right ~= blocked_hard_right) then + return false, "terrain change on right side" + end + if blocked_ahead then + return false, "terrain ahead blocks" + end end return true @@ -221,14 +340,25 @@ function _M:runScan(fct) fct(x, y, "ahead") -- Ahead left - local dx, dy = dir_to_coord[sides[self.running.dir].left][1], dir_to_coord[sides[self.running.dir].left][2] + local dx, dy = dir_to_coord[sides[self.running.dir].soft_left][1], dir_to_coord[sides[self.running.dir].soft_left][2] local x, y = self.x + dx, self.y + dy fct(x, y, "ahead left") -- Ahead right - local dx, dy = dir_to_coord[sides[self.running.dir].right][1], dir_to_coord[sides[self.running.dir].right][2] + local dx, dy = dir_to_coord[sides[self.running.dir].soft_right][1], dir_to_coord[sides[self.running.dir].soft_right][2] local x, y = self.x + dx, self.y + dy fct(x, y, "ahead right") + + -- Left + local dx, dy = dir_to_coord[sides[self.running.dir].hard_left][1], dir_to_coord[sides[self.running.dir].hard_left][2] + local x, y = self.x + dx, self.y + dy + fct(x, y, "left") + + -- Right + local dx, dy = dir_to_coord[sides[self.running.dir].hard_right][1], dir_to_coord[sides[self.running.dir].hard_right][2] + local x, y = self.x + dx, self.y + dy + fct(x, y, "right") + elseif self.running.path[self.running.cnt] then -- Ahead local x, y = self.running.path[self.running.cnt].x, self.running.path[self.running.cnt].y diff --git a/game/modules/tome/class/Player.lua b/game/modules/tome/class/Player.lua index f9a8e10391..1eb931cd52 100644 --- a/game/modules/tome/class/Player.lua +++ b/game/modules/tome/class/Player.lua @@ -522,8 +522,10 @@ function _M:restCheck() end --- Can we continue running? --- We can run if no hostiles are in sight, and if we no interesting terrains are next to us -function _M:runCheck() +-- We can run if no hostiles are in sight, and if no interesting terrain or characters are next to us. +-- Known traps aren't interesting. We let the engine run around traps, or stop if it can't. +-- 'ignore_memory' is only used when checking for paths around traps. This ensures we don't remember items "obj_seen" that we aren't supposed to +function _M:runCheck(ignore_memory) local spotted = spotHostiles(self) if spotted then return false, ("hostile spotted (%s%s)"):format(spotted.actor.name, game.level.map:isOnScreen(spotted.x, spotted.y) and "" or " - offscreen") end @@ -532,22 +534,27 @@ function _M:runCheck() -- Notice any noticeable terrain local noticed = false self:runScan(function(x, y, what) - -- Only notice interesting terrains - local grid = game.level.map(x, y, Map.TERRAIN) - if grid and grid.notice then noticed = "interesting terrain" end - -- Objects are always interesting, only on curent spot if what == "self" and not game.level.map.attrs(x, y, "obj_seen") then local obj = game.level.map:getObject(x, y, 1) if obj then noticed = "object seen" - game.level.map.attrs(x, y, "obj_seen", true) + if not ignore_memory then game.level.map.attrs(x, y, "obj_seen", true) end + return end end - -- Traps are always interesting if known - local trap = game.level.map(x, y, Map.TRAP) - if trap and trap:knownBy(self) then noticed = "trap spotted" end + -- Only notice interesting terrains + local grid = game.level.map(x, y, Map.TERRAIN) + if grid and grid.notice then noticed = "interesting terrain"; return end + if grid and grid.type and grid.type == "store" then noticed = "store entrance spotted"; return end + + -- Only notice interesting characters + local actor = game.level.map(x, y, Map.ACTOR) + if actor and actor.can_talk then noticed = "interesting character"; return end + + -- We let the engine take care of traps, but we should still notice "trap" stores. + if game.level.map:checkAllEntities(x, y, "store") then noticed = "store entrance spotted"; return end end) if noticed then return false, noticed end diff --git a/game/modules/tome/data/general/objects/quest-artifacts.lua b/game/modules/tome/data/general/objects/quest-artifacts.lua index 3be1449c48..34f3bd1d59 100644 --- a/game/modules/tome/data/general/objects/quest-artifacts.lua +++ b/game/modules/tome/data/general/objects/quest-artifacts.lua @@ -314,7 +314,7 @@ You have heard of such items before, they are very useful to adventurers, allowi max_power = 1000, power_regen = 1, use_power = { name = "recall the user to the worldmap", power = 1000, use = function(self, who) - if who:canBe("worldport") then + if who:canBe("worldport") and not self:attr("never_move") then who:setEffect(who.EFF_RECALL, 40, {}) game.logPlayer(who, "Space around you starts to dissolve...") else diff --git a/game/modules/tome/data/maps/towns/gates-of-morning.lua b/game/modules/tome/data/maps/towns/gates-of-morning.lua index 3b54e4b505..4f9ad0028b 100644 --- a/game/modules/tome/data/maps/towns/gates-of-morning.lua +++ b/game/modules/tome/data/maps/towns/gates-of-morning.lua @@ -56,21 +56,21 @@ defineTile('s', "FLOOR", nil, mod.class.NPC.new{ can_quest = true, }) -quickEntity('1', {show_tooltip=true, name="Closed store", display='1', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}, {no_teleport=true}) -quickEntity('2', {show_tooltip=true, name="Armour Smith", display='2', color=colors.UMBER, resolvers.store("ARMOR"), image="terrain/wood_store_armor.png"}, {no_teleport=true}) -quickEntity('3', {show_tooltip=true, name="Weapon Smith", display='3', color=colors.UMBER, resolvers.store("WEAPON"), image="terrain/wood_store_weapon.png"}, {no_teleport=true}) -quickEntity('4', {show_tooltip=true, name="Alchemist", display='4', color=colors.LIGHT_BLUE, resolvers.store("POTION"), image="terrain/wood_store_potion.png"}, {no_teleport=true}) -quickEntity('5', {show_tooltip=true, name="Scribe", display='5', color=colors.WHITE, resolvers.store("SCROLL"), resolvers.chatfeature("magic-store"), image="terrain/wood_store_book.png"}, {no_teleport=true}) -quickEntity('6', {show_tooltip=true, name="Closed store", display='6', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}, {no_teleport=true}) -quickEntity('7', {show_tooltip=true, name="Closed store", display='7', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}, {no_teleport=true}) -quickEntity('8', {show_tooltip=true, name="Closed store", display='8', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}, {no_teleport=true}) -quickEntity('9', {show_tooltip=true, name="Closed store", display='9', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}, {no_teleport=true}) -quickEntity('0', {show_tooltip=true, name="Closed store", display='0', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}, {no_teleport=true}) -quickEntity('a', {show_tooltip=true, name="Closed store", display='*', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}, {no_teleport=true}) -quickEntity('b', {show_tooltip=true, name="Closed store", display='*', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}, {no_teleport=true}) -quickEntity('c', {show_tooltip=true, name="Closed store", display='*', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}, {no_teleport=true}) -quickEntity('d', {show_tooltip=true, name="Closed store", display='*', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}, {no_teleport=true}) -quickEntity('e', {show_tooltip=true, name="Zemekkys Home", display='+', color=colors.LIGHT_UMBER, resolvers.chatfeature("zemekkys"), image="terrain/wood_store_closed.png"}, {no_teleport=true}) +quickEntity('1', {type="store", show_tooltip=true, name="Closed store", display='1', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}, {no_teleport=true}) +quickEntity('2', {type="store", show_tooltip=true, name="Armour Smith", display='2', color=colors.UMBER, resolvers.store("ARMOR"), image="terrain/wood_store_armor.png"}, {no_teleport=true}) +quickEntity('3', {type="store", show_tooltip=true, name="Weapon Smith", display='3', color=colors.UMBER, resolvers.store("WEAPON"), image="terrain/wood_store_weapon.png"}, {no_teleport=true}) +quickEntity('4', {type="store", show_tooltip=true, name="Alchemist", display='4', color=colors.LIGHT_BLUE, resolvers.store("POTION"), image="terrain/wood_store_potion.png"}, {no_teleport=true}) +quickEntity('5', {type="store", show_tooltip=true, name="Scribe", display='5', color=colors.WHITE, resolvers.store("SCROLL"), resolvers.chatfeature("magic-store"), image="terrain/wood_store_book.png"}, {no_teleport=true}) +quickEntity('6', {type="store", show_tooltip=true, name="Closed store", display='6', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}, {no_teleport=true}) +quickEntity('7', {type="store", show_tooltip=true, name="Closed store", display='7', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}, {no_teleport=true}) +quickEntity('8', {type="store", show_tooltip=true, name="Closed store", display='8', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}, {no_teleport=true}) +quickEntity('9', {type="store", show_tooltip=true, name="Closed store", display='9', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}, {no_teleport=true}) +quickEntity('0', {type="store", show_tooltip=true, name="Closed store", display='0', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}, {no_teleport=true}) +quickEntity('a', {type="store", show_tooltip=true, name="Closed store", display='*', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}, {no_teleport=true}) +quickEntity('b', {type="store", show_tooltip=true, name="Closed store", display='*', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}, {no_teleport=true}) +quickEntity('c', {type="store", show_tooltip=true, name="Closed store", display='*', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}, {no_teleport=true}) +quickEntity('d', {type="store", show_tooltip=true, name="Closed store", display='*', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}, {no_teleport=true}) +quickEntity('e', {type="store", show_tooltip=true, name="Zemekkys Home", display='+', color=colors.LIGHT_UMBER, resolvers.chatfeature("zemekkys"), image="terrain/wood_store_closed.png"}, {no_teleport=true}) startx = 0 starty = 27 diff --git a/game/modules/tome/data/maps/towns/last-hope.lua b/game/modules/tome/data/maps/towns/last-hope.lua index 35daee7fe4..5b68959881 100644 --- a/game/modules/tome/data/maps/towns/last-hope.lua +++ b/game/modules/tome/data/maps/towns/last-hope.lua @@ -34,25 +34,25 @@ quickEntity(',', {name='dirt', display='.', color=colors.LIGHT_UMBER, image="ter quickEntity('I', {name='tunneled wall', show_tooltip=true, display='#', color=colors.WHITE, image="terrain/wood_wall1.png"}) quickEntity('M', {name='tunneled hills', show_tooltip=true, display='^', color=colors.SLATE, image="terrain/mountain.png"}) -quickEntity('1', {show_tooltip=true, name="Closed store", display='1', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}) -quickEntity('2', {show_tooltip=true, name="Armour Smith", display='2', color=colors.UMBER, resolvers.store("ARMOR"), image="terrain/wood_store_armor.png"}) -quickEntity('3', {show_tooltip=true, name="Weapon Smith", display='3', color=colors.UMBER, resolvers.store("WEAPON"), resolvers.chatfeature("last-hope-weapon-store"), image="terrain/wood_store_weapon.png"}) -quickEntity('4', {show_tooltip=true, name="Alchemist", display='4', color=colors.LIGHT_BLUE, resolvers.store("POTION"), image="terrain/wood_store_potion.png"}) -quickEntity('5', {show_tooltip=true, name="Scribe", display='5', color=colors.WHITE, resolvers.store("SCROLL"), resolvers.chatfeature("magic-store"), image="terrain/wood_store_book.png"}) -quickEntity('6', {show_tooltip=true, name="Closed store", display='6', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}) -quickEntity('7', {show_tooltip=true, name="Closed store", display='7', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}) -quickEntity('8', {show_tooltip=true, name="Closed store", display='8', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}) -quickEntity('9', {show_tooltip=true, name="Closed store", display='9', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}) -quickEntity('0', {show_tooltip=true, name="Closed store", display='0', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}) -quickEntity('a', {show_tooltip=true, name="Closed store", display='*', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}) -quickEntity('b', {show_tooltip=true, name="Hall of the King", display='*', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}) -quickEntity('c', {show_tooltip=true, name="Library", display='*', color=colors.LIGHT_RED, resolvers.store("LAST_HOPE_LIBRARY"), image="terrain/wood_store_book.png"}) -quickEntity('d', {show_tooltip=true, name="Closed store", display='*', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}) -quickEntity('e', {show_tooltip=true, name="Rare goods", display='*', color=colors.AQUAMARINE, resolvers.store("LOST_MERCHANT"), resolvers.chatfeature("last-hope-lost-merchant"), image="terrain/wood_store_weapon.png"}) -quickEntity('g', {show_tooltip=true, name="Rich merchant", display='*', color=colors.AQUAMARINE, resolvers.chatfeature("last-hope-melinda-father"), image="terrain/wood_store_closed.png"}) +quickEntity('1', {type="store", show_tooltip=true, name="Closed store", display='1', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}) +quickEntity('2', {type="store", show_tooltip=true, name="Armour Smith", display='2', color=colors.UMBER, resolvers.store("ARMOR"), image="terrain/wood_store_armor.png"}) +quickEntity('3', {type="store", show_tooltip=true, name="Weapon Smith", display='3', color=colors.UMBER, resolvers.store("WEAPON"), resolvers.chatfeature("last-hope-weapon-store"), image="terrain/wood_store_weapon.png"}) +quickEntity('4', {type="store", show_tooltip=true, name="Alchemist", display='4', color=colors.LIGHT_BLUE, resolvers.store("POTION"), image="terrain/wood_store_potion.png"}) +quickEntity('5', {type="store", show_tooltip=true, name="Scribe", display='5', color=colors.WHITE, resolvers.store("SCROLL"), resolvers.chatfeature("magic-store"), image="terrain/wood_store_book.png"}) +quickEntity('6', {type="store", show_tooltip=true, name="Closed store", display='6', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}) +quickEntity('7', {type="store", show_tooltip=true, name="Closed store", display='7', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}) +quickEntity('8', {type="store", show_tooltip=true, name="Closed store", display='8', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}) +quickEntity('9', {type="store", show_tooltip=true, name="Closed store", display='9', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}) +quickEntity('0', {type="store", show_tooltip=true, name="Closed store", display='0', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}) +quickEntity('a', {type="store", show_tooltip=true, name="Closed store", display='*', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}) +quickEntity('b', {type="store", show_tooltip=true, name="Hall of the King", display='*', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}) +quickEntity('c', {type="store", show_tooltip=true, name="Library", display='*', color=colors.LIGHT_RED, resolvers.store("LAST_HOPE_LIBRARY"), image="terrain/wood_store_book.png"}) +quickEntity('d', {type="store", show_tooltip=true, name="Closed store", display='*', color=colors.LIGHT_UMBER, block_move=true, block_sight=true, image="terrain/wood_store_closed.png"}) +quickEntity('e', {type="store", show_tooltip=true, name="Rare goods", display='*', color=colors.AQUAMARINE, resolvers.store("LOST_MERCHANT"), resolvers.chatfeature("last-hope-lost-merchant"), image="terrain/wood_store_weapon.png"}) +quickEntity('g', {type="store", show_tooltip=true, name="Rich merchant", display='*', color=colors.AQUAMARINE, resolvers.chatfeature("last-hope-melinda-father"), image="terrain/wood_store_closed.png"}) -quickEntity('E', {show_tooltip=true, name="The Elder", display='*', color=colors.VIOLET, resolvers.chatfeature("last-hope-elder"), image="terrain/wood_store_closed.png"}) -quickEntity('f', {show_tooltip=true, name="Tannen's Tower", display='*', color=colors.VIOLET, resolvers.chatfeature("tannen"), image="terrain/wood_store_closed.png"}) +quickEntity('E', {type="store", show_tooltip=true, name="The Elder", display='*', color=colors.VIOLET, resolvers.chatfeature("last-hope-elder"), image="terrain/wood_store_closed.png"}) +quickEntity('f', {type="store", show_tooltip=true, name="Tannen's Tower", display='*', color=colors.VIOLET, resolvers.chatfeature("tannen"), image="terrain/wood_store_closed.png"}) quickEntity('@', {show_tooltip=true, name="Statue of King Tolak the Fair", display='@', image="terrain/grass.png", add_displays = {mod.class.Grid.new{image="terrain/statue1.png"}}, color=colors.LIGHT_BLUE, block_move=function(self, x, y, e, act, couldpass) if e and e.player and act then e:learnLore("last-hope-tolak-statue") end return true end}) quickEntity('Z', {show_tooltip=true, name="Statue of King Toknor the Brave", display='@', image="terrain/grass.png", add_displays = {mod.class.Grid.new{image="terrain/statue1.png"}}, color=colors.LIGHT_BLUE, block_move=function(self, x, y, e, act, couldpass) if e and e.player and act then e:learnLore("last-hope-toknor-statue") end return true end}) diff --git a/game/modules/tome/data/talents/misc/misc.lua b/game/modules/tome/data/talents/misc/misc.lua index 405fe12905..664374d648 100644 --- a/game/modules/tome/data/talents/misc/misc.lua +++ b/game/modules/tome/data/talents/misc/misc.lua @@ -178,7 +178,7 @@ newTalent{ no_npc_use = true, no_silence=true, is_spell=true, action = function(self, t) - if not self:canBe("worldport") then + if not self:canBe("worldport") or self:attr("never_move") then game.logPlayer(self, "The spell fizzles...") return end diff --git a/game/modules/tome/data/timed_effects.lua b/game/modules/tome/data/timed_effects.lua index c974bd7de0..2ee8c33546 100644 --- a/game/modules/tome/data/timed_effects.lua +++ b/game/modules/tome/data/timed_effects.lua @@ -2206,7 +2206,7 @@ newEffect{ activate = function(self, eff) end, deactivate = function(self, eff) - if self:canBe("worldport") then + if self:canBe("worldport") and not self:attr("never_move") then game:onTickEnd(function() game.logPlayer(self, "You are yanked out of this place!") game:changeLevel(1, game.player.last_wilderness) @@ -2238,7 +2238,7 @@ newEffect{ return end - if self:canBe("worldport") then + if self:canBe("worldport") and not self:attr("never_move") then game:onTickEnd(function() game.logPlayer(self, "You are yanked out of this place!") game:changeLevel(1, "town-angolwen") -- GitLab