Skip to content
Snippets Groups Projects
Commit 88009ead authored by dg's avatar dg
Browse files

betetr AE

Character Sheet right map click option renamed to Inspect Creature, it now works any any target


git-svn-id: http://svn.net-core.org/repos/t-engine4@4632 51575b47-30f0-44d4-a5cc-537603b46e54
parent 3649533a
No related branches found
No related tags found
No related merge requests found
......@@ -128,7 +128,7 @@ function _M:runStep()
if not self.running then return false end
local ret, msg = self:runCheck()
if not ret and self.running.cnt > 1 then
if not ret and (self.running.cnt > 1 or self.running.busy) then
self:runStop(msg)
return false
else
......@@ -139,8 +139,21 @@ function _M:runStep()
elseif 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)
-- Allow auto-explore to perform actions other than movement, which should be performed
-- or setup in "checkAutoExplore". Hence, modules can make auto-explore borg-like if desired.
-- For example, non-move actions can be picking up an item, using a talent, resting, etc.
-- Some actions can require moving into a tile, such as opening a door or bump-attacking an enemy.
-- "self.running.cnt" is not incremented while "self.running.busy" exists.
if not self.running.busy or self.running.busy.do_move then
self:move(self.running.path[self.running.cnt].x, self.running.path[self.running.cnt].y)
end
self:runMoved()
-- Did not move ? no use in running unless we were busy
if self.running and not self.running.busy and self.x == oldx and self.y == oldy then
self:runStop("didn't move")
end
end
if not self.running then return false end
else
-- Try to move around known traps if possible
local dir_is_cardinal = self.running.dir == 2 or self.running.dir == 4 or self.running.dir == 6 or self.running.dir == 8
......@@ -182,6 +195,10 @@ function _M:runStep()
end
-- Move!
self:moveDir(self.running.dir)
self:runMoved()
-- Did not move ? no use in running
if self.x == oldx and self.y == oldy then self:runStop() end
if not self.running then return false end
if self.running.block_left then self.running.ignore_left = nil end
if self.running.ignore_left then
......@@ -211,13 +228,12 @@ function _M:runStep()
end
end
self:runMoved()
-- Did not move ? no use in running
if self.x == oldx and self.y == oldy then self:runStop() end
if not self.running then return false end
self.running.cnt = self.running.cnt + 1
if not self.running.busy then
self.running.cnt = self.running.cnt + 1
elseif self.running.busy.no_energy then
return self:runStep()
end
return true
end
end
......
......@@ -636,9 +636,17 @@ function _M:runCheck(ignore_memory)
end
end
-- Only notice interesting terrains, but allow auto-explore to take us to the exit
-- Only notice interesting terrains, but allow auto-explore and A* to take us to the exit. Auto-explore can also take us through "safe" doors
local grid = game.level.map(x, y, Map.TERRAIN)
if grid and grid.notice and not (what ~= "self" and self.running and self.running.explore == "exit" and #self.running.path == self.running.cnt) then
if grid and grid.notice and not (self.running and self.running.path and (what ~= self and
(self.running.explore and grid.door_opened -- safe door
or #self.running.path == self.running.cnt and (self.running.explore == "exit" -- auto-explore onto exit
or not self.running.explore and grid.change_level)) -- A* onto exit
or #self.running.path - self.running.cnt < 2 and (self.running.explore == "portal" -- auto-explore onto portal
or not self.running.explore and grid.orb_portal) -- A* onto portal
or self.running.cnt < 3 and grid.orb_portal and -- path from portal
game.level.map:checkEntity(self.running.path[1].x, self.running.path[1].y, Map.TERRAIN, "orb_portal")))
then
noticed = "interesting terrain"; return
end
if grid and grid.type and grid.type == "store" then noticed = "store entrance spotted"; return end
......
......@@ -214,6 +214,7 @@ function _M:autoExplore()
local unseen_items = {}
local unseen_doors = {}
local exits = {}
local portals = {}
local values = {}
values[node[3]] = 0
local door_values = {}
......@@ -223,6 +224,7 @@ function _M:autoExplore()
local running = true
local minval = 999999999999999
local minval_items = 999999999999999
local minval_portals = 999999999999999
local val, _, anode, tile_list
-- a few tunable parameters
......@@ -287,7 +289,6 @@ function _M:autoExplore()
if (not values[c] or values[c] > move_cost or is_slow) and (not is_slow or not slow_values[c] or slow_values[c] > move_cost) then
-- if not game.level.map:checkEntity(x, y, Map.TERRAIN, "block_move", self, nil, true) then
-- if not game.level.map:checkAllEntities(x, y, "block_move", self) then
-- if not (terrain.does_block_move or terrain.is_door and terrain.door_opened then
-- This is a sinful man's "block_move". If it messes up, then players can explore the level themselves!
-- (and they can always interrupt running if something terrible happens)
......@@ -310,26 +311,45 @@ function _M:autoExplore()
minval_items = move_cost
end
-- default to reasonable targets if there are no accessible unseen tiles or objects left on the map
elseif #unseen_tiles == 0 and #unseen_items == 0 then
-- only go to closed doors with unseen grids behind them
if terrain.door_opened and do_unseen then
local is_unexplored = false
for _, anode in ipairs(listAdjacentTiles(node)) do
if not game.level.map.has_seens(anode[1], anode[2]) then
is_unexplored = true
break
end
-- only go to closed doors with unseen grids behind them. We can go through "safe" doors
elseif terrain.door_opened and do_unseen then
local is_unexplored = false
for _, anode in ipairs(listAdjacentTiles(node)) do
if not game.level.map.has_seens(anode[1], anode[2]) then
is_unexplored = true
break
end
if is_unexplored then
unseen_doors[#unseen_doors + 1] = c
if not door_values[c] or door_values[c] > move_cost then
door_values[c] = move_cost
end
end
if is_unexplored then
unseen_doors[#unseen_doors + 1] = c
if not door_values[c] or door_values[c] > move_cost then
door_values[c] = move_cost
end
else -- door is safe to move through
node[4] = move_cost + 1
values[c] = move_cost + 1
current_tiles_next[#current_tiles_next + 1] = node
end
-- go to next level, exit, previous level, or orb portal (in that order of precedence)
elseif terrain.change_level then
exits[#exits + 1] = c
values[c] = move_cost
elseif terrain.orb_portal then
local is_portal_center = true
local is_small_portal = true
for _, anode in ipairs(listAdjacentTiles(node)) do
if not game.level.map:checkEntity(anode[1], anode[2], Map.TERRAIN, "orb_portal") then
is_portal_center = false
else
is_small_portal = false
end
-- go to next level, exit, or previous level (in that order of precedence)
elseif terrain.change_level then
exits[#exits + 1] = c
end
if is_portal_center or is_small_portal then
portals[#portals + 1] = c
values[c] = move_cost
if move_cost < minval_portals then
minval_portals = move_cost
end
end
end
end
......@@ -379,7 +399,7 @@ function _M:autoExplore()
-- Negligible time is spent below
-- Choose target
if #unseen_tiles > 0 or #unseen_items > 0 or #unseen_doors > 0 or #exits > 0 then
if #unseen_tiles > 0 or #unseen_items > 0 or #unseen_doors > 0 or #exits > 0 or #portals > 0 then
local target_type
local choices = {}
local distances = {}
......@@ -470,12 +490,36 @@ function _M:autoExplore()
end
-- if no destination yet, go to nearest unexplored closed non-vault door
if #choices == 0 then
local add_values = {}
for _, c in ipairs(unseen_doors) do
local x, y = toDouble(c)
local terrain = game.level.map(x, y, Map.TERRAIN)
if not terrain.door_player_check then
target_type = "door"
choices[#choices + 1] = c
-- we may take an extra step to approach a door squarely from a cardinal direction, so let's account for this
local door_val = door_values[c]
local min_diagonal = door_val
local min_cardinal = door_val
for _, node in ipairs(listAdjacentTiles(c, true)) do
if values[node[3]] and values[node[3]] < min_cardinal then
min_cardinal = values[node[3]]
end
end
for _, node in ipairs(listAdjacentTiles(c, false, true)) do
if values[node[3]] and values[node[3]] < min_diagonal then
min_diagonal = values[node[3]]
end
end
if min_cardinal > min_diagonal then
for _, node in ipairs(listAdjacentTiles(c, false, true)) do
if values[node[3]] then
add_values[node[3]] = values[node[3]] + 1
door_values[c] = door_val + 1
end
end
end
local dist = core.fov.distance(self.x, self.y, x, y, true) + 10*door_values[c]
distances[c] = dist
if dist < mindist then
......@@ -483,6 +527,9 @@ function _M:autoExplore()
end
end
end
for _, c in ipairs(add_values) do
values[c] = values[c] + add_values[c]
end
end
-- ...or vault door
if #choices == 0 then
......@@ -548,6 +595,21 @@ function _M:autoExplore()
end
end
end
-- ...or orb portal
if #choices == 0 then
for _, c in ipairs(portals) do
if values[c] == minval_portals then
target_type = "portal"
choices[#choices + 1] = c
local x, y = toDouble(c)
local dist = core.fov.distance(self.x, self.y, x, y, true)
distances[c] = dist
if dist < mindist then
mindist = dist
end
end
end
end
-- if multiple choices, then choose nearest one based on fov distance metric
if #choices > 1 then
......@@ -633,8 +695,12 @@ function _M:autoExplore()
if #path > 0 then
if self.running and self.running.explore then
-- take care of a couple fringe cases
-- don't open adjacent doors if we've already been running
if #path == 1 and target_type == "door" then return false end
-- don't open adjacent or target doors if we've already been running
if target_type == "door" then
if #path == 1 then return false
else path[#path] = nil end
end
-- don't run into adjacent interesting terrain if we've already been running
local terrain = game.level.map(path[1].x, path[1].y, Map.TERRAIN)
if terrain.notice and not (#path == 1 and target_type == "exit") then
......@@ -655,6 +721,9 @@ function _M:autoExplore()
game.level.map.attrs(target_x, target_y, "obj_seen", true)
return self:autoExplore()
end
-- don't open non-adjacent target doors
if target_type == "door" and #path > 1 then path[#path] = nil end
self.running = {
path = path,
cnt = 1,
......@@ -686,26 +755,20 @@ function _M:checkAutoExplore()
-- If not, though, then stop, because the player *must* choose to open the door
local node = self.running.path[self.running.cnt]
local terrain = node and game.level.map(node.x, node.y, Map.TERRAIN)
if self.running.explore == "door" and #self.running.path == self.running.cnt then
if self.running.cnt == 1 then
-- let's not make assumptions. Double-check that there is a closed door there and that we open it
if terrain.door_opened then
local sx, sy = self.x, self.y
self:move(node.x, node.y)
self:runMoved()
-- check if there are enemies behind the open door
local ret, msg = self:runCheck()
if not ret then
self:runStop(msg)
return false
end
terrain = game.level.map(node.x, node.y, Map.TERRAIN)
if not terrain.door_opened and sx == self.x and sy == self.y then
return self:autoExplore()
end
end
end
return false
-- this is either a "safe" door or a target adjacent door. Either way, we can open it
if terrain and terrain.door_opened then
-- we already tried to open the door but failed
if self.running.busy and self.running.busy.type == "opening door" then return false end
self.running.busy = { type = "opening door", do_move = true, no_energy = true }
return true
end
self.running.busy = nil
-- if we opened the adjacent target door, then continue exploring elsewhere
if self.running.explore == "door" and #self.running.path == self.running.cnt and self.running.cnt == 1 and terrain.door_closed then
return self:autoExplore()
end
-- if we're at the end of the path and we're searching for unseen tiles, then continue with a new path
......
......@@ -306,9 +306,9 @@ function _M:drawDialog(kind, actor_to_compare)
local cur_exp, max_exp = player.exp, player:getExpChart(player.level+1)
h = 0
w = 0
s:drawStringBlended(self.font, "Sex : "..(player.descriptor.sex or (player.female and "Female" or "Male")), w, h, 0, 200, 255, true) h = h + self.font_h
s:drawStringBlended(self.font, "Race : "..(player.descriptor.subrace or player.type:capitalize()), w, h, 0, 200, 255, true) h = h + self.font_h
s:drawStringBlended(self.font, "Class: "..(player.descriptor.subclass or player.subtype:capitalize()), w, h, 0, 200, 255, true) h = h + self.font_h
s:drawStringBlended(self.font, "Sex : "..((player.descriptor and player.descriptor.sex) or (player.female and "Female" or "Male")), w, h, 0, 200, 255, true) h = h + self.font_h
s:drawStringBlended(self.font, (player.descriptor and "Race : " or "Type : ")..((player.descriptor and player.descriptor.subrace) or player.type:capitalize()), w, h, 0, 200, 255, true) h = h + self.font_h
s:drawStringBlended(self.font, (player.descriptor and "Class: " or "Stype: ")..((player.descriptor and player.descriptor.subclass) or player.subtype:capitalize()), w, h, 0, 200, 255, true) h = h + self.font_h
s:drawStringBlended(self.font, "Size : "..(player:TextSizeCategory():capitalize()), w, h, 0, 200, 255, true) h = h + self.font_h
h = h + self.font_h
......@@ -375,8 +375,10 @@ function _M:drawDialog(kind, actor_to_compare)
text = compare_fields(player, actor_to_compare, function(actor) return actor.combat_physspeed - 1 end, "%.2f%%", "%+.2f%%", 100)
self:mouseTooltip(self.TOOLTIP_SPEED_ATTACK, s:drawColorStringBlended(self.font, ("Attack speed : #00ff00#%s"):format(text), w, h, 255, 255, 255, true)) h = h + self.font_h
h = h + self.font_h
text = compare_fields(player, actor_to_compare, function(actor) return #actor.died_times end, "%3d", "%+.0f")
self:mouseTooltip(self.TOOLTIP_LIVES, s:drawColorStringBlended(self.font, ("Times died : #00ff00#%s"):format(text), w, h, 255, 255, 255, true)) h = h + self.font_h
if player.died_times then
text = compare_fields(player, actor_to_compare, function(actor) return #actor.died_times end, "%3d", "%+.0f")
self:mouseTooltip(self.TOOLTIP_LIVES, s:drawColorStringBlended(self.font, ("Times died : #00ff00#%s"):format(text), w, h, 255, 255, 255, true)) h = h + self.font_h
end
if player.easy_mode_lifes then
text = compare_fields(player, actor_to_compare, "easy_mode_lifes", "%3d", "%+.0f")
self:mouseTooltip(self.TOOLTIP_LIVES, s:drawColorStringBlended(self.font, ("Lives left : #00ff00#%s"):format(text), w, h, 255, 255, 255, true)) h = h + self.font_h
......@@ -670,7 +672,7 @@ function _M:drawDialog(kind, actor_to_compare)
end
end
end
local inc_damage_actor_types = {}
if player.inc_damage_actor_type then
for i, t in pairs(player.inc_damage_actor_type) do
......@@ -871,13 +873,13 @@ function _M:dump()
nl(" [Tome 4.00 @ www.te4.org Character Dump]")
nl()
nnl(("%-32s"):format(makelabel("Sex", player.descriptor.sex or (player.female and "Female" or "Male"))))
nnl(("%-32s"):format(makelabel("Sex", (player.descriptor and player.descriptor.sex) or (player.female and "Female" or "Male"))))
nl(("STR: %d"):format(player:getStr()))
nnl(("%-32s"):format(makelabel("Race", player.descriptor.subrace or player.type:capitalize())))
nnl(("%-32s"):format(makelabel("Race", (player.descriptor and player.descriptor.subrace) or player.type:capitalize())))
nl(("DEX: %d"):format(player:getDex()))
nnl(("%-32s"):format(makelabel("Class", player.descriptor.subclass or player.subtype:capitalize())))
nnl(("%-32s"):format(makelabel("Class", (player.descriptor and player.descriptor.subclass) or player.subtype:capitalize())))
nl(("MAG: %d"):format(player:getMag()))
nnl(("%-32s"):format(makelabel("Level", ("%d"):format(player.level))))
......@@ -934,8 +936,8 @@ function _M:dump()
else
nnl(("%-32s"):format(" "))
end
nl(makelabel("Difficulty", player.descriptor.difficulty or "???"))
nl(makelabel("Permadeath", player.descriptor.permadeath or "???"))
nl(makelabel("Difficulty", (player.descriptor and player.descriptor.difficulty) or "???"))
nl(makelabel("Permadeath", (player.descriptor and player.descriptor.permadeath) or "???"))
nnl(("%-32s"):format(strings[3]))
if player:knowTalent(player.T_MANA_POOL) then
......
......@@ -72,7 +72,7 @@ function _M:use(item)
elseif act == "order" then game.party:giveOrders(item.actor)
elseif act == "change_level" then game.key:triggerVirtual("CHANGE_LEVEL")
elseif act == "pickup" then game.key:triggerVirtual("PICKUP_FLOOR")
elseif act == "character_sheet" then game.key:triggerVirtual("SHOW_CHARACTER_SHEET")
elseif act == "character_sheet" then game:registerDialog(require("mod.dialogs.CharacterSheet").new(item.actor))
elseif act == "quests" then game.key:triggerVirtual("SHOW_QUESTS")
elseif act == "levelup" then game.key:triggerVirtual("LEVELUP")
elseif act == "inventory" then game.key:triggerVirtual("SHOW_INVENTORY")
......@@ -118,8 +118,8 @@ function _M:generateList()
if a and not self.on_player and game.party:canOrder(a, false) then list[#list+1] = {name="Give order", action="order", color=colors.simple(colors.TEAL), actor=a} end
if self.on_player then list[#list+1] = {name="Rest a while", action="rest", color=colors.simple(colors.ANTIQUE_WHITE)} end
if self.on_player then list[#list+1] = {name="Inventory", action="inventory", color=colors.simple(colors.ANTIQUE_WHITE)} end
if self.on_player then list[#list+1] = {name="Character Sheet", action="character_sheet", color=colors.simple(colors.ANTIQUE_WHITE)} end
if self.on_player then list[#list+1] = {name="Quest Log", action="quests", color=colors.simple(colors.ANTIQUE_WHITE)} end
if a then list[#list+1] = {name="Inspect Creature", action="character_sheet", color=colors.simple(colors.ANTIQUE_WHITE), actor=a} end
if not self.on_player and a and profile.auth and profile.hash_valid then list[#list+1] = {name="Link creature in chat", action="chat-link"} end
if self.on_player and (player.unused_stats > 0 or player.unused_talents > 0 or player.unused_generics > 0 or player.unused_talents_types > 0) then list[#list+1] = {name="Levelup!", action="levelup", color=colors.simple(colors.YELLOW)} end
......
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