diff --git a/game/engine/utils.lua b/game/engine/utils.lua index 69bc2f099b492a1d179c78d193cfceca90020064..0bec443bec6b228f090aecf2677c1dbdeba8e736 100644 --- a/game/engine/utils.lua +++ b/game/engine/utils.lua @@ -164,6 +164,10 @@ local Pcode = (lpeg.R"af" + lpeg.R"09" + lpeg.R"AF") local Pcolorcode = Pcode * Pcode local Pcolorcodefull = Pcolorcode * Pcolorcode * Pcolorcode +function string.removeColorCodes(str) + return str:lpegSub("#" * (Puid + Pcolorcodefull + Pcolorname) * "#", "") +end + function string.splitLine(str, max_width, font) local space_w = font:size(" ") local lines = {} @@ -263,7 +267,7 @@ getmetatable(tmps).__index.drawColorString = function(s, font, str, x, y, r, g, oldr, oldg, oldb = r, g, b r, g, b = colors[col].r, colors[col].g, colors[col].b end - elseif uid and mo then + elseif uid and mo and game.level then uid = tonumber(uid) mo = tonumber(mo) local e = __uids[uid] @@ -312,7 +316,7 @@ getmetatable(tmps).__index.drawColorStringBlended = function(s, font, str, x, y, oldr, oldg, oldb = r, g, b r, g, b = colors[col].r, colors[col].g, colors[col].b end - elseif uid and mo then + elseif uid and mo and game.level then uid = tonumber(uid) mo = tonumber(mo) local e = __uids[uid] diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua index 9543a401277c948f5df725ff4b8360f2e3509611..21e1306c6fb2106e9dd5f9124d4c00e7290d571e 100644 --- a/game/modules/tome/class/Actor.lua +++ b/game/modules/tome/class/Actor.lua @@ -642,7 +642,7 @@ function _M:die(src) end -- Increase vim - if src and src:attr("vim_on_death") and not self:attr("undead") then src:incVim(src:attr("vim_on_death")) end + if src and src.attr and src:attr("vim_on_death") and not self:attr("undead") then src:incVim(src:attr("vim_on_death")) end if src and src.resolveSource and src:resolveSource().player then -- Achievements diff --git a/game/modules/tome/class/Player.lua b/game/modules/tome/class/Player.lua index 43611b7075e9d1e5aaf79d3ac352375f28c7ebc2..fca5e7790247872eb2e40537ea25948676fc3631 100644 --- a/game/modules/tome/class/Player.lua +++ b/game/modules/tome/class/Player.lua @@ -589,6 +589,7 @@ function _M:useOrbPortal(portal) local ok = false self:restInit(20, "using the portal", "used the poral", function(cnt, max) if cnt > max then ok = true end + print("*********** portaling one turn", ok) coroutine.resume(co) end) coroutine.yield() @@ -598,7 +599,7 @@ function _M:useOrbPortal(portal) end return true end --- if not wait() then return end + if not wait() then return end if portal.teleport_level then local x, y = util.findFreeGrid(portal.teleport_level.x, portal.teleport_level.y, 2, true, {[Map.ACTOR]=true}) diff --git a/game/modules/tome/class/PlayerDisplay.lua b/game/modules/tome/class/PlayerDisplay.lua index 30967e803c0f5c7b6ab57b23c05675b4c9deb41f..ab1283c070cceaa6273ce280ff1a685bfd1875a6 100644 --- a/game/modules/tome/class/PlayerDisplay.lua +++ b/game/modules/tome/class/PlayerDisplay.lua @@ -104,8 +104,8 @@ function _M:display() self.surface:drawColorStringBlended(self.font, ("#7fffd4#Negative:#ffffff#%d/%d"):format(player:getNegative(), player.max_negative), 0, h, 255, 255, 255) h = h + self.font_h end if player:knowTalent(player.T_VIM_POOL) then - self.surface:erase(0xff / 6, 0xcc / 6, 0x80 / 6, 255, self.bars_x, h, self.bars_w, self.font_h) - self.surface:erase(0xff / 3, 0xcc / 3, 0x80 / 3, 255, self.bars_x, h, self.bars_w * player:getVim() / player.max_vim, self.font_h) + self.surface:erase(0x90 / 6, 0x40 / 6, 0x10 / 6, 255, self.bars_x, h, self.bars_w, self.font_h) + self.surface:erase(0x90 / 3, 0x40 / 3, 0x10 / 3, 255, self.bars_x, h, self.bars_w * player:getVim() / player.max_vim, self.font_h) self.surface:drawColorStringBlended(self.font, ("#904010#Vim: #ffffff#%d/%d"):format(player:getVim(), player.max_vim), 0, h, 255, 255, 255) h = h + self.font_h end diff --git a/game/modules/tome/data/texts/win.lua b/game/modules/tome/data/texts/win.lua index e6edae43f701a698a02e264196998b8759898d08..f3c4bd48f0691ee732de126e502f9eb5b658234e 100644 --- a/game/modules/tome/data/texts/win.lua +++ b/game/modules/tome/data/texts/win.lua @@ -34,6 +34,9 @@ end if game.player:isQuestStatus("high-peak", engine.Quest.COMPLETED, "gates-of-morning-destroyed") then desc[#desc+1] = "" desc[#desc+1] = "The Gates of Morning have been destroyed and the Sunwall has fallen, the last remnants of the free people in the Far East will surely disminish and soon only orcs will inhabit this land." +else + desc[#desc+1] = "" + desc[#desc+1] = "The orc presence in the Far East has greatly been disminished by the loss of their leaders and the destruction of the Istari. The free people of the Sunwall will be able to prosper and thrive on this land." end desc[#desc+1] = "" @@ -44,4 +47,6 @@ if game.player.winner ~= "self-sacrifice" then desc[#desc+1] = "You may continue playing and enjoy the rest of the world." end +game.player.winner_text = desc + return table.concat(desc, "\n") diff --git a/game/modules/tome/data/zones/grushnak-pride/npcs.lua b/game/modules/tome/data/zones/grushnak-pride/npcs.lua index 30a88e259c6e991da78e3989133ee210b73ad072..578dd752205923573bfe837bae716834bddf5b57 100644 --- a/game/modules/tome/data/zones/grushnak-pride/npcs.lua +++ b/game/modules/tome/data/zones/grushnak-pride/npcs.lua @@ -51,8 +51,9 @@ newEntity{ base="BASE_NPC_ORC_GRUSHNAK", define_as = "GRUSHNAK", {type="armor", subtype="massive", ego_chance=100, autoreq=true}, {type="armor", subtype="head", ego_chance=100, autoreq=true}, {type="armor", subtype="feet", ego_chance=100, autoreq=true}, - {type="jewelry", subtype="amulet", ego_chance=100, autoreq=true}, - {type="jewelry", subtype="ring", ego_chance=100, autoreq=true}, +-- Commented because this can generate rings of invis or amulets of telepathy and drain the life of the boss +-- {type="jewelry", subtype="amulet", ego_chance=100, autoreq=true}, +-- {type="jewelry", subtype="ring", ego_chance=100, autoreq=true}, {type="jewelry", subtype="ring", defined="PRIDE_GLORY", autoreq=true}, }, resolvers.drops{chance=100, nb=5, {ego_chance=100} }, diff --git a/game/modules/tome/data/zones/high-peak/grids.lua b/game/modules/tome/data/zones/high-peak/grids.lua index b8e1190ef7304987c7e2afef676c7bd93fc2a113..9599b81964be7e7ac3c7002b9fd2a17d13cf12da 100644 --- a/game/modules/tome/data/zones/high-peak/grids.lua +++ b/game/modules/tome/data/zones/high-peak/grids.lua @@ -75,6 +75,7 @@ This one seems to go to an unknown place, seemingly out of this world. You dare } local invocation_close = function(self, who) + if not who:hasQuest("high-peak") or who:hasQuest("high-peak"):isCompleted() then return end game.logPlayer(who, "#LIGHT_BLUE#You use the orb on the portal, shutting it down easily.") -- Remove the level spot local spot = game.level:pickSpot{type="portal", subtype=self.summon} diff --git a/game/modules/tome/dialogs/CharacterSheet.lua b/game/modules/tome/dialogs/CharacterSheet.lua index 1565624384b613733b0bda5207ea05da30ba90d6..5744d85b56047c433f3140424122e05fa5ac2304 100644 --- a/game/modules/tome/dialogs/CharacterSheet.lua +++ b/game/modules/tome/dialogs/CharacterSheet.lua @@ -64,8 +64,14 @@ function _M:drawDialog(s) if game.player:knowTalent(game.player.T_MANA_POOL) then s:drawColorStringBlended(self.font, ("#7fffd4#Mana: #00ff00#%d/%d"):format(game.player:getMana(), game.player.max_mana), w, h, 255, 255, 255) h = h + self.font_h end - if game.player:knowTalent(game.player.T_SOUL_POOL) then - s:drawColorStringBlended(self.font, ("#777777#Soul: #00ff00#%d/%d"):format(game.player:getSoul(), game.player.max_soul), w, h, 255, 255, 255) h = h + self.font_h + if game.player:knowTalent(game.player.T_POSITIVE_POOL) then + s:drawColorStringBlended(self.font, ("#7fffd4#Positive:#00ff00#%d/%d"):format(game.player:getPositive(), game.player.max_positive), w, h, 255, 255, 255) h = h + self.font_h + end + if game.player:knowTalent(game.player.T_NEGATIVE_POOL) then + s:drawColorStringBlended(self.font, ("#7fffd4#Negative:#00ff00#%d/%d"):format(game.player:getNegative(), game.player.max_negative), w, h, 255, 255, 255) h = h + self.font_h + end + if game.player:knowTalent(game.player.T_VIM_POOL) then + s:drawColorStringBlended(self.font, ("#904010#Vim: #00ff00#%d/%d"):format(game.player:getVim(), game.player.max_vim), w, h, 255, 255, 255) h = h + self.font_h end if game.player:knowTalent(game.player.T_EQUILIBRIUM_POOL) then s:drawColorStringBlended(self.font, ("#00ff74#Equi: #00ff00#%d"):format(game.player:getEquilibrium()), w, h, 255, 255, 255) h = h + self.font_h @@ -144,6 +150,20 @@ function _M:drawDialog(s) end end + immune_type = "poison_immune" immune_name = "Poison Resistance" if self.actor:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end + immune_type = "cut_immune" immune_name = "Bleed Resistance" if self.actor:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end + immune_type = "confusion_immune" immune_name = "Confusion Resistance" if self.actor:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end + immune_type = "blind_immune" immune_name = "Blind Resistance" if self.actor:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end + immune_type = "silence_immune" immune_name = "Silence Resistance" if self.actor:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end + immune_type = "disarm_immune" immune_name = "Disarm Resistance" if self.actor:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end + immune_type = "pin_immune" immune_name = "Pinning Resistance" if self.actor:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end + immune_type = "stun_immune" immune_name = "Stun Resistance" if self.actor:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end + immune_type = "fear_immune" immune_name = "Fear Resistance" if self.actor:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end + immune_type = "knockback_immune" immune_name = "Knockback Resistance" if self.actor:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end + immune_type = "stone_immune" immune_name = "Stoning Resistance" if self.actor:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end + immune_type = "instakill_immune" immune_name = "Instadeath Resistance" if self.actor:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end + immune_type = "teleport_immune" immune_name = "Teleport Resistance" if self.actor:attr(immune_type) then s:drawColorStringBlended(self.font, ("%s: #00ff00#%3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100)), w, h, 255, 255, 255) h = h + self.font_h end + h = 0 w = 600 s:drawColorStringBlended(self.font, "#LIGHT_BLUE#Current effects:", w, h, 255, 255, 255) h = h + self.font_h @@ -167,8 +187,8 @@ function _M:dump() local file = "/character-dumps/"..(game.player.name:gsub("[^a-zA-Z0-9_-.]", "_")).."-"..os.date("%Y%m%d-%H%M%S")..".txt" local fff = fs.open(file, "w") local labelwidth = 17 - local nl = function(s) fff:write(s or "") fff:write("\n") end - local nnl = function(s) fff:write(s or "") end + local nl = function(s) s = s or "" fff:write(s:removeColorCodes()) fff:write("\n") end + local nnl = function(s) s = s or "" fff:write(s:removeColorCodes()) end --prepare label and value local makelabel = function(s,r) while s:len() < labelwidth do s = s.." " end return ("%s: %s"):format(s, r) end @@ -191,7 +211,7 @@ function _M:dump() nnl(("%-32s"):format(makelabel("Exp", ("%d%%"):format(100 * cur_exp / max_exp)))) nl(("CUN: %d"):format(game.player:getCun())) - nnl(("%-32s"):format(makelabel("Gold", ("%.2f"):format(game.player.money)))) + nnl(("%-32s"):format(makelabel("Gold", ("%.2f"):format(game.player.money)))) nl(("CON: %d"):format(game.player:getCon())) -- All weapons in main hands @@ -232,9 +252,21 @@ function _M:dump() nl() end nnl(("%-32s"):format(strings[4])) - if game.player:knowTalent(game.player.T_SOUL_POOL) then - nl(makelabel("Soul", (" %d/%d"):format(game.player:getSoul(), game.player.max_soul))) - else + if game.player:knowTalent(game.player.T_POSITIVE_POOL) then + nl(makelabel("Positive", (" %d/%d"):format(game.player:getPositive(), game.player.max_positive))) + else + nl() + end + nnl(("%-32s"):format(strings[4])) + if game.player:knowTalent(game.player.T_NEGATIVE_POOL) then + nl(makelabel("Negative", (" %d/%d"):format(game.player:getNegative(), game.player.max_negative))) + else + nl() + end + nnl(("%-32s"):format(strings[4])) + if game.player:knowTalent(game.player.T_VIM_POOL) then + nl(makelabel("Vim", (" %d/%d"):format(game.player:getVim(), game.player.max_vim))) + else nl() end nnl(("%-32s"):format(strings[5])) @@ -294,6 +326,20 @@ function _M:dump() end end + immune_type = "poison_immune" immune_name = "Poison Resistance" if self.actor:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100))) end + immune_type = "cut_immune" immune_name = "Bleed Resistance" if self.actor:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100))) end + immune_type = "confusion_immune" immune_name = "Confusion Resistance" if self.actor:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100))) end + immune_type = "blind_immune" immune_name = "Blind Resistance" if self.actor:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100))) end + immune_type = "silence_immune" immune_name = "Silence Resistance" if self.actor:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100))) end + immune_type = "disarm_immune" immune_name = "Disarm Resistance" if self.actor:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100))) end + immune_type = "pin_immune" immune_name = "Pinning Resistance" if self.actor:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100))) end + immune_type = "stun_immune" immune_name = "Stun Resistance" if self.actor:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100))) end + immune_type = "fear_immune" immune_name = "Fear Resistance" if self.actor:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100))) end + immune_type = "knockback_immune" immune_name = "Knockback Resistance" if self.actor:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100))) end + immune_type = "stone_immune" immune_name = "Stoning Resistance" if self.actor:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100))) end + immune_type = "instakill_immune" immune_name = "Instadeath Resistance" if self.actor:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100))) end + immune_type = "teleport_immune" immune_name = "Teleport Resistance" if self.actor:attr(immune_type) then nl(("%s: %3d%%"):format(immune_name, util.bound(self.actor:attr(immune_type) * 100, 0, 100))) end + nl() local most_kill, most_kill_max = "none", 0 local total_kill = 0 @@ -304,6 +350,15 @@ function _M:dump() nl(("Number of NPC killed: %s"):format(total_kill)) nl(("Most killed NPC: %s (%d)"):format(most_kill, most_kill_max)) + if self.actor.winner then + nl() + nl(" [Winner!]") + nl() + for i, line in ipairs(self.actor.winner_text) do + nl(("%s"):format(line:removeColorCodes())) + end + end + -- Talents nl() nl(" [Talents Chart]") @@ -321,7 +376,7 @@ function _M:dump() for j, t in ipairs(tt.talents) do if not t.hide then local typename = "class" - if t.skill then typename = "generic" end + if t.generic then typename = "generic" end local skillname = (" %s (%s)"):format(t.name, typename) nl(("%-37s %d/%d"):format(skillname, self.actor:getTalentLevelRaw(t.id), t.points)) end @@ -353,14 +408,14 @@ function _M:dump() local first = true for id, q in pairs(self.actor.quests or {}) do if q:isEnded() then - if first then - nl() - nl(" [Completed Quests]") - nl() - first=false - end - nl(" -- ".. q.name) - nl(q:desc(self.actor):gsub("#.-#", " ")) + if first then + nl() + nl(" [Completed Quests]") + nl() + first=false + end + nl(" -- ".. q.name) + nl(q:desc(self.actor):gsub("#.-#", " ")) end end @@ -368,13 +423,13 @@ function _M:dump() for id, q in pairs(self.actor.quests or {}) do if not q:isEnded() then if first then - first=false - nl() + first=false + nl() nl(" [Active Quests]") - nl() + nl() end - nl(" -- ".. q.name) - nl(q:desc(self.actor):gsub("#.-#", " ")) + nl(" -- ".. q.name) + nl(q:desc(self.actor):gsub("#.-#", " ")) end end @@ -405,9 +460,15 @@ function _M:dump() nl() nl(" [Player Achievements]") nl() + local achs = {} for id, data in pairs(self.actor.achievements or {}) do local a = world:getAchievementFromId(id) - nl(("%s Was Achieved for %s At %s"):format(a.name,a.desc,data.when)) + achs[#achs+1] = {id=id, data=data, name=a.name} + end + table.sort(achs, function(a, b) return a.name < b.name end) + for i, d in ipairs(achs) do + local a = world:getAchievementFromId(d.id) + nl(("'%s' was wchieved for %s At %s"):format(a.name, a.desc, d.data.when)) end nl() diff --git a/ideas/quests.ods b/ideas/quests.ods index f25186fb83d30b7eec9d446a221eb99835a12174..629365d1c26c7860d211a1c30782846c8a0f47d9 100644 Binary files a/ideas/quests.ods and b/ideas/quests.ods differ