diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua index 76840edbd60995cf0c65d5caf2c1bfdb7bb7a177..f79da91c696b6c4559b7bd276184b3caccb02220 100644 --- a/game/modules/tome/class/Game.lua +++ b/game/modules/tome/class/Game.lua @@ -918,7 +918,7 @@ end function _M:changeLevelReal(lev, zone, params) local oz, ol = self.zone, self.level - + -- Unlock first! if not params.temporary_zone_shift_back and self.level and self.level.temp_shift_zone then self:changeLevelReal(1, "useless", {temporary_zone_shift_back=true}) @@ -1101,7 +1101,7 @@ function _M:changeLevelReal(lev, zone, params) list[#list+1] = {i, j} end end end - if #list > 0 then x, y = unpack(rng.table(list)) end + if #list > 0 then x, y = unpack((rng.table(list))) end elseif params.auto_level_stair then -- Dirty but quick local list = {} @@ -1111,7 +1111,7 @@ function _M:changeLevelReal(lev, zone, params) list[#list+1] = {i, j} end end end - if #list > 0 then x, y = unpack(rng.table(list)) end + if #list > 0 then x, y = unpack((rng.table(list))) end end -- if self.level.exited then -- use the last location, if defined diff --git a/game/modules/tome/class/GameState.lua b/game/modules/tome/class/GameState.lua index f67934d1b2c98f5e3d875cad0fdf5e4344c35ed3..3625c01046a57fe0f91e836eaa97398cf28bf3a1 100644 --- a/game/modules/tome/class/GameState.lua +++ b/game/modules/tome/class/GameState.lua @@ -2360,8 +2360,13 @@ function _M:locationRevealAround(x, y) end end -function _M:doneEvent(id) - return self.used_events[id] +--- Has event been triggered in this game state? +-- @param id = the event id +-- @param[optional = number] v increment the event count for id +-- @return false or the number of times this event has been triggered +function _M:doneEvent(id, v) + if v then self.used_events[id] = (self.used_events[id] or 0) + v end + return self.used_events[id] and self.used_events[id] > 0 and self.used_events[id] or false end function _M:canEventGrid(level, x, y) @@ -2401,6 +2406,10 @@ function _M:findEventGridRadius(level, radius, min) return self:canEventGridRadius(level, x, y, radius, min) end +--- Get the file name for an event +-- @param[string] subdirectory of the base events directory containing the event file +-- @param[string] name the short name of the event +-- @return the complete file path for the event file (resolved for addons) function _M:eventBaseName(sub, name) local base = "/data" local _, _, addon, rname = name:find("^([^+]+)%+(.+)$") @@ -2411,8 +2420,30 @@ function _M:eventBaseName(sub, name) return base.."/general/events/"..sub..name..".lua" end +--- Process the zone.events table, managing spawning of events on each level +-- If zone.events_by_level is true, events will be assigned to each level as it's generated +-- otherwise events will be preassigned to each level (stored in zone.assigned_events) +-- If zone.events.one_per_level is true, only one major event will be preassigned to each level +-- (Some events may not spawn if there are not enough levels.) +-- Each event in the events list can have the following fields: +-- name: short name of the event (resolved with game.state:eventBaseName(dir, name) to get the full file path +-- group: if name is not set, load all events present in the associated group file in the groups subdirectory +-- percent_factor: percent multiplier for the loaded group events only +-- forbid, level_range will be merged +-- minor: flag event as a minor event that can spawn multiple times on the level +-- percent: (required) % chance for the event to be assigned to a given level +-- always: set true to force 100% spawn chance +-- level_range: table {low, high} containing the range of levels the event is allowed to spawn on +-- forbid: table of levels the event cannot spawn on +-- special: a function(lev) that, if present, must return true to allow the event to spawn on level lev +-- minor event fields: +-- max_repeat: attempt to spawn the event extra times (% chance halved after each repeat) +-- major event fields: +-- unique: set true to allow only one instance of the event for this game state +-- @return a function(level) to place events on the level (loaded from the event file) +-- this function loads and executes all of the required events files to modify the map, etc. function _M:startEvents() - if not game.zone.events then print("No zone events loaded") return end + if not game.zone.events then print("[STARTEVENTS] No zone events loaded") return end if not game.zone.assigned_events then local levels = {} @@ -2422,58 +2453,76 @@ function _M:startEvents() for i = 1, game.zone.max_level do levels[i] = {} end end - -- Generate the events list for this zone, eventually loading from group files + -- Generate the events list for this zone, possibly loading from group files local evts, mevts = {}, {} for i, e in ipairs(game.zone.events) do - if e.name then if e.minor then mevts[#mevts+1] = e else evts[#evts+1] = e end - elseif e.group then + if e.name then -- add a single event to the events list + if e.minor then mevts[#mevts+1] = e else evts[#evts+1] = e end + elseif e.group then -- load events from a group file and add them to the events list + -- print("[STARTEVENTS] loading events group", e.group) local f, err = loadfile(self:eventBaseName("groups/", e.group)) if not f then error(err) end setfenv(f, setmetatable({level=game.level, zone=game.zone}, {__index=_G})) local list = f() for j, ee in ipairs(list) do - if e.percent_factor and ee.percent then ee.percent = math.floor(ee.percent * e.percent_factor) end - if e.forbid then ee.forbid = table.append(ee.forbid or {}, e.forbid) end - if ee.name then if ee.minor then mevts[#mevts+1] = ee else evts[#evts+1] = ee end end + -- print("[STARTEVENTS]\t\tAdding Group Event:", j, tostring(ee.name)) + if ee.name then + if e.percent_factor and ee.percent then ee.percent = math.floor(ee.percent * e.percent_factor) end + if e.forbid then ee.forbid = table.append(ee.forbid or {}, e.forbid) end + if e.level_range then + if ee.level_range then + ee.level_range = {math.max(e.level_range[1] or 1, ee.level_range[1] or 1), + math.min(e.level_range[2] or math.huge, ee.level_range[2] or math.huge)} + else ee.level_range = e.level_range + end + end + if ee.minor then mevts[#mevts+1] = ee else evts[#evts+1] = ee end + end end end end -- Randomize the order they are checked as + print("[STARTEVENTS] Zone compiled events list: one_per_level=", game.zone.events.one_per_level) table.shuffle(evts) - print("[STARTEVENTS] Zone events list:") table.print(evts) table.shuffle(mevts) table.print(mevts) for i, e in ipairs(evts) do - -- If we allow it, try to find a level to host it - if (e.always or rng.percent(e.percent) or (e.special and e.special() == true)) and (not e.unique or not self:doneEvent(e.name)) then + -- If allowed, find a level to host the (major) event + if (e.always or rng.percent(e.percent)) and (not e.unique or not self:doneEvent(e.name)) then local lev = nil local forbid = e.forbid or {} forbid = table.reverse(forbid) if game.zone.events_by_level then lev = game.level.level + if forbid[lev] then lev = nil + elseif e.level_range and (lev < (e.level_range[1] or 1) or lev > (e.level_range[2] or game.zone.max_level)) then lev = nil end else - if game.zone.events.one_per_level then + local start, stop = 1, game.zone.max_level + if e.level_range then start, stop = e.level_range[1] or start, e.level_range[2] or stop end + if game.zone.events.one_per_level then -- find a random level with no assigned event local list = {} - for i = 1, #levels do if #levels[i] == 0 and not forbid[i] then list[#list+1] = i end end + for i = start, stop do + if #levels[i] == 0 and not forbid[i] and (not e.special or e.special(i)) then + list[#list+1] = i + end + end if #list > 0 then lev = rng.table(list) end - else - if forbid then - local t = table.genrange(1, game.zone.max_level, true) - t = table.minus_keys(t, forbid) - lev = rng.table(table.keys(t)) - else - lev = rng.range(1, game.zone.max_level) - end + else -- pick an allowed level at random to assign the event to + local t = table.genrange(start, stop, true) + if e.special then table.foreach(t, function(i, v) t[i] = e.special(i) and t[i] or nil end) end + t = table.minus_keys(t, forbid) + lev = rng.table(table.keys(t)) end end if lev then lev = levels[lev] lev[#lev+1] = e.name + self:doneEvent(e.name, 1) -- mark as done when assigned end end end @@ -2482,23 +2531,27 @@ function _M:startEvents() forbid = table.reverse(forbid) local start, stop = 1, game.zone.max_level - if game.zone.events_by_level then start, stop = game.level.level, game.level.level end - for lev = start, stop do - if rng.percent(e.percent) and not forbid[lev] then - local lev = levels[lev] - lev[#lev+1] = e.name - - if e.max_repeat then + if game.zone.events_by_level then + start, stop = game.level.level, game.level.level + end + if e.level_range then + start, stop = math.max(start, e.level_range[1] or start), math.min(stop, e.level_range[2] or stop) + end + for lv = start, stop do + if (e.always or rng.percent(e.percent)) and not forbid[lv] and (not e.special or e.special(lv)) then + local lev = levels[lv] + lev[#lev+1] = e.name self:doneEvent(e.name, 1) -- mark as done when assigned + if e.max_repeat then -- try to repeat the event with diminishing probability local nb = 1 - local p = e.percent + local p = e.percent or 100 while nb <= e.max_repeat do - if rng.percent(p) then - lev[#lev+1] = e.name + if e.always or rng.percent(p) and (not e.special or e.special(lv)) then + lev[#lev+1] = e.name self:doneEvent(e.name, 1) -- mark as done when assigned nb = nb + 1 + p = p/2 else break end - p = p / 2 end end end @@ -2508,6 +2561,7 @@ function _M:startEvents() game.zone.assigned_events = levels end + -- return a wrapper function to load and run all assigned events files return function() print("[STARTEVENTS] Assigned events list:") table.print(game.zone.assigned_events) @@ -2515,8 +2569,9 @@ function _M:startEvents() for i, e in ipairs(game.zone.assigned_events[game.level.level] or {}) do local f, err = loadfile(self:eventBaseName("", e)) if not f then error(err) end - setfenv(f, setmetatable({level=game.level, zone=game.zone, event_id=e.name, Map=Map}, {__index=_G})) - f() + setfenv(f, setmetatable({level=game.level, zone=game.zone, event_id=e, Map=Map}, {__index=_G})) + self:doneEvent(e, -1) -- unmark as done (for event code) + if f() then self:doneEvent(e, 1) end -- remark as done if event completed end game.zone.assigned_events[game.level.level] = {} if game.zone.events_by_level then game.zone.assigned_events = nil end diff --git a/game/modules/tome/class/generator/map/VaultLevel.lua b/game/modules/tome/class/generator/map/VaultLevel.lua index edde9883cf2cfbcbfcf6666e4e775f72ae110782..d0b7ae337461975005a84b8e0994ceaee6c97179 100644 --- a/game/modules/tome/class/generator/map/VaultLevel.lua +++ b/game/modules/tome/class/generator/map/VaultLevel.lua @@ -57,7 +57,7 @@ function _M:generate(lev, old_lev) local rm for i = 0, self.map.w - 1 do for j = 0, self.map.h - 1 do rm = self.map.room_map[i][j] - if not rm.room then + if not (rm.room or rm.special or rm.can_open) then local g if self.level.data.subvaults_surroundings then g = self:resolve(self.level.data.subvaults_surroundings, nil, true) else g = self:resolve("subvault_wall") end @@ -81,12 +81,13 @@ function _M:generate(lev, old_lev) sx, sy = e.sx, e.sy ex, ey = e.x, e.y if not (sx and sy) then -- vault connection point: connect to a (nearest) non-vault grid + print("[VaultLevel] generating level start point from vault connection at", ex, ey) + -- start at center of room and pick a random direction sx, sy = math.floor(rx+(room.w-1)/2), math.floor(ry+(room.h-1)/2) local dir, xd, yd = util.getDir(ex, ey, sx+rng.normal(0, 1), sy+rng.normal(0, 1)) if dir == 5 then dir = rng.table(util.primaryDirs()) end local rm - - local steps = (self.map.w + self.map.h)/4 + local steps = math.max(room.w, room.h) + 2*(room.border or 0) + 1 repeat steps = steps - 1 rm = self.map.room_map[sx][sy] diff --git a/game/modules/tome/data/general/events/conclave-vault.lua b/game/modules/tome/data/general/events/conclave-vault.lua index 7c687facfc281acaff79ab55a74d02a4760d2a65..51d566542417b7032c93e9c4478fea466f0254a4 100644 --- a/game/modules/tome/data/general/events/conclave-vault.lua +++ b/game/modules/tome/data/general/events/conclave-vault.lua @@ -21,6 +21,7 @@ local x, y = game.state:findEventGrid(level) if not x then return false end +print("[EVENT] Placing event conclave-vault at", x, y) local Talents = require("engine.interface.ActorTalents") local skeletons = mod.class.NPC:loadList("/data/general/npcs/skeleton.lua") diff --git a/game/modules/tome/data/general/events/cultists.lua b/game/modules/tome/data/general/events/cultists.lua index 9ca89541d9305a8407111f249df5b378b2ca940e..ccc70daa1e69af69c5e1a992f0812b9555cbf044 100644 --- a/game/modules/tome/data/general/events/cultists.lua +++ b/game/modules/tome/data/general/events/cultists.lua @@ -17,7 +17,7 @@ -- Nicolas Casalini "DarkGod" -- darkgod@te4.org --- Unique +-- Unique throughout the game if game.state:doneEvent(event_id) then return end local list = {} diff --git a/game/modules/tome/data/general/events/damp-cave.lua b/game/modules/tome/data/general/events/damp-cave.lua index 2a4e1420a34dbeb504a8708f748855f5816dee52..1a98048b483cc3c9d7e90187d9d575e5469859da 100644 --- a/game/modules/tome/data/general/events/damp-cave.lua +++ b/game/modules/tome/data/general/events/damp-cave.lua @@ -23,15 +23,21 @@ if not x then return false end local id = "damp-cave-"..game.turn +print("[EVENT] Placing event", id, "at", x, y) + local changer = function(id) local npcs = mod.class.NPC:loadList{"/data/general/npcs/thieve.lua"} local objects = mod.class.Object:loadList("/data/general/objects/objects.lua") local terrains = mod.class.Grid:loadList("/data/general/grids/cave.lua") terrains.CAVE_LADDER_UP_WILDERNESS.change_level_shift_back = true terrains.CAVE_LADDER_UP_WILDERNESS.change_zone_auto_stairs = true + terrains.CAVE_LADDER_UP_WILDERNESS.name = "ladder back to "..game.zone.name + terrains.CAVE_LADDER_UP_WILDERNESS.change_zone = game.zone.short_name local zone = mod.class.Zone.new(id, { name = "Damp Cave", - level_range = {game.zone:level_adjust_level(game.level, game.zone, "actor"), game.zone:level_adjust_level(game.level, game.zone, "actor")}, + level_range = game.zone.actor_adjust_level and {math.floor(game.zone:actor_adjust_level(game.level, game.player)*1.05), + math.ceil(game.zone:actor_adjust_level(game.level, game.player)*1.15)} or {game.zone.base_level, game.zone.base_level}, -- 5-15% higher actor levels + __applied_difficulty = true, -- Difficulty already applied to parent zone level_scheme = "player", max_level = 1, actor_adjust_level = function(zone, level, e) return zone.base_level + e:getRankLevelAdjust() + level.level-1 + rng.range(-1,2) end, @@ -39,8 +45,10 @@ local changer = function(id) ambient_music = "Swashing the buck.ogg", reload_lists = false, persistent = "zone", - min_material_level = game.zone.min_material_level, - max_material_level = game.zone.max_material_level, + + no_worldport = game.zone.no_worldport, + min_material_level = util.getval(game.zone.min_material_level), + max_material_level = util.getval(game.zone.max_material_level), generator = { map = { class = "engine.generator.map.Cavern", @@ -66,7 +74,6 @@ local changer = function(id) nb_trap = {6, 9}, }, }, --- levels = { [1] = { generator = { map = { up = "CAVEFLOOR", }, }, }, }, npc_list = npcs, grid_list = terrains, object_list = objects, @@ -77,6 +84,7 @@ end local g = game.level.map(x, y, engine.Map.TERRAIN):cloneFull() g.name = "damp cave" +g.always_remember = true g.display='>' g.color_r=0 g.color_g=0 g.color_b=255 g.notice = true g.change_level=1 g.change_zone=id g.glow=true g:removeAllMOs() @@ -84,6 +92,7 @@ if engine.Map.tiles.nicer_tiles then g.add_displays = g.add_displays or {} g.add_displays[#g.add_displays+1] = mod.class.Grid.new{image="terrain/crystal_ladder_down.png", z=5} end +g.nice_tiler = nil g:altered() g:initGlow() g.real_change = changer @@ -91,8 +100,9 @@ g.change_level_check = function(self) game:changeLevel(1, self.real_change(self.change_zone), {temporary_zone_shift=true, direct_switch=true}) self.change_level_check = nil self.real_change = nil + self.special_minimap = colors.VIOLET return true end game.zone:addEntity(game.level, g, "terrain", x, y) -return true +return x, y diff --git a/game/modules/tome/data/general/events/drake-cave.lua b/game/modules/tome/data/general/events/drake-cave.lua index 7268509e7ab4877a6b729754f5af97f5907e6665..83fa21f69201c8b56b811422f38d58ed9a23f5ad 100644 --- a/game/modules/tome/data/general/events/drake-cave.lua +++ b/game/modules/tome/data/general/events/drake-cave.lua @@ -18,27 +18,28 @@ -- darkgod@te4.org -- Find a random spot -local x, y = rng.range(1, level.map.w - 2), rng.range(1, level.map.h - 2) -local tries = 0 -while not game.state:canEventGrid(level, x, y) and tries < 100 do - x, y = rng.range(1, level.map.w - 2), rng.range(1, level.map.h - 2) - tries = tries + 1 -end -if tries >= 100 then return false end +local x, y = game.state:findEventGrid(level) +if not x then return false end local kind = rng.table{"fire", "fire", "cold", "cold", "storm", "storm", "multihued"} local id = kind.."-dragon-cave-"..game.turn +print("[EVENT] Placing event", id, "at", x, y) + local changer = function(id, kind) local npcs = mod.class.NPC:loadList{"/data/general/npcs/"..kind.."-drake.lua"} local objects = mod.class.Object:loadList("/data/general/objects/objects.lua") local terrains = mod.class.Grid:loadList("/data/general/grids/cave.lua") terrains.CAVE_LADDER_UP_WILDERNESS.change_level_shift_back = true terrains.CAVE_LADDER_UP_WILDERNESS.change_zone_auto_stairs = true + terrains.CAVE_LADDER_UP_WILDERNESS.name = "ladder back to "..game.zone.name + terrains.CAVE_LADDER_UP_WILDERNESS.change_zone = game.zone.short_name local zone = mod.class.Zone.new(id, { name = "Intimidating Cave", - level_range = {game.zone:level_adjust_level(game.level, game.zone, "actor"), game.zone:level_adjust_level(game.level, game.zone, "actor")}, + level_range = game.zone.actor_adjust_level and {math.floor(game.zone:actor_adjust_level(game.level, game.player)*1.05), + math.ceil(game.zone:actor_adjust_level(game.level, game.player)*1.15)} or {game.zone.base_level, game.zone.base_level}, -- 5-15% higher levels + __applied_difficulty = true, --Difficulty already applied to parent zone level_scheme = "player", max_level = 1, actor_adjust_level = function(zone, level, e) return zone.base_level + e:getRankLevelAdjust() + level.level-1 + rng.range(-1,2) end, @@ -46,8 +47,10 @@ local changer = function(id, kind) ambient_music = "Swashing the buck.ogg", reload_lists = false, persistent = "zone", - min_material_level = game.zone.min_material_level, - max_material_level = game.zone.max_material_level, + + no_worldport = game.zone.no_worldport, + min_material_level = util.getval(game.zone.min_material_level), + max_material_level = util.getval(game.zone.max_material_level), generator = { map = { class = "engine.generator.map.Cavern", @@ -61,7 +64,10 @@ local changer = function(id, kind) actor = { class = "mod.class.generator.actor.Random", nb_npc = {25, 25}, - guardian = {special=function(e) return e.rank and e.rank >= 2 end, random_elite={life_rating=function(v) return v * 1.5 + 4 end, nb_rares=3}}, + guardian = {special=function(e) return e.rank and e.rank >= 2 end, random_elite={life_rating=function(v) return v * 1.5 + 4 end, + nb_rares=(rng.percent(resolvers.current_level-50) and 4 or 3), + nb_classes=(rng.percent(resolvers.current_level-50) and 2 or 1)} + }, }, object = { class = "engine.generator.object.Random", @@ -73,7 +79,6 @@ local changer = function(id, kind) nb_trap = {6, 9}, }, }, --- levels = { [1] = { generator = { map = { up = "CAVEFLOOR", }, }, }, }, npc_list = npcs, grid_list = terrains, object_list = objects, @@ -85,12 +90,14 @@ end local g = game.level.map(x, y, engine.Map.TERRAIN):cloneFull() g.name = "intimidating cave" g.display='>' g.color_r=0 g.color_g=0 g.color_b=255 g.notice = true +g.always_remember = true g.change_level=1 g.change_zone=id g.glow=true g:removeAllMOs() if engine.Map.tiles.nicer_tiles then g.add_displays = g.add_displays or {} g.add_displays[#g.add_displays+1] = mod.class.Grid.new{image="terrain/crystal_ladder_down.png", z=5} end +g.nice_tiler = nil g:altered() g:initGlow() g.dragon_kind = kind @@ -99,6 +106,7 @@ g.change_level_check = function(self) game:changeLevel(1, self.real_change(self.change_zone, self.dragon_kind), {temporary_zone_shift=true, direct_switch=true}) self.change_level_check = nil self.real_change = nil + self.special_minimap = colors.VIOLET return true end game.zone:addEntity(game.level, g, "terrain", x, y) @@ -113,4 +121,4 @@ if m then game.zone:addEntity(game.level, m, "actor", i, j) end -return true +return x, y diff --git a/game/modules/tome/data/general/events/fearscape-portal.lua b/game/modules/tome/data/general/events/fearscape-portal.lua index 7e3b944c354ed43d294a722cc1c4df6a62c03288..b67792e30ac6d9581e3a02229af7fc3f20c4e044 100644 --- a/game/modules/tome/data/general/events/fearscape-portal.lua +++ b/game/modules/tome/data/general/events/fearscape-portal.lua @@ -18,16 +18,13 @@ -- darkgod@te4.org -- Find a random spot -local x, y = rng.range(1, level.map.w - 2), rng.range(1, level.map.h - 2) -local tries = 0 -while not game.state:canEventGrid(level, x, y) and tries < 100 do - x, y = rng.range(1, level.map.w - 2), rng.range(1, level.map.h - 2) - tries = tries + 1 -end -if tries >= 100 then return false end +local x, y = game.state:findEventGrid(level) +if not x then return false end local id = "fearscape-invasion-"..game.turn +print("[EVENT] Placing event", id, "at", x, y) + local changer = function(id) local npcs = mod.class.NPC:loadList{"/data/general/npcs/minor-demon.lua", "/data/general/npcs/major-demon.lua"} local objects = mod.class.Object:loadList("/data/general/objects/objects.lua") @@ -37,16 +34,24 @@ local changer = function(id) terrains.PORTAL_BACK = mod.class.Grid.new{ type = "floor", subtype = "floor", display = "&", color = colors.BLUE, - name = "portal", + name = "portal back to "..game.zone.name, image = "terrain/red_floating_rocks05_01.png", add_displays = { mod.class.Grid.new{image="terrain/demon_portal3.png"} }, - change_level = 1, change_zone = "wilderness", + change_level = 1, + change_zone = game.zone.short_name, change_level_shift_back = true, change_zone_auto_stairs = true, + change_level_check = function(self) + game.log("#VIOLET# You escape the Fearscape!") + -- May delete old zone file here? + return + end } local zone = mod.class.Zone.new(id, { name = "orbital fearscape platform", - level_range = {game.zone:level_adjust_level(game.level, game.zone, "actor"), game.zone:level_adjust_level(game.level, game.zone, "actor")}, + level_range = game.zone.actor_adjust_level and {math.floor(game.zone:actor_adjust_level(game.level, game.player)*1.05), + math.ceil(game.zone:actor_adjust_level(game.level, game.player)*1.15)} or {game.zone.base_level, game.zone.base_level}, -- 5-15% higher levels + __applied_difficulty = true, -- Difficulty already applied to parent zone level_scheme = "player", max_level = 1, actor_adjust_level = function(zone, level, e) return zone.base_level + e:getRankLevelAdjust() + level.level-1 + rng.range(-1,2) end, @@ -55,8 +60,10 @@ local changer = function(id) reload_lists = false, projectile_speed_mod = 0.3, persistent = "zone", - min_material_level = game.zone.min_material_level, - max_material_level = game.zone.max_material_level, + + no_worldport = game.zone.no_worldport, + min_material_level = util.getval(game.zone.min_material_level), + max_material_level = util.getval(game.zone.max_material_level), effects = {"EFF_ZONE_AURA_FEARSCAPE"}, generator = { map = { @@ -71,7 +78,10 @@ local changer = function(id) actor = { class = "mod.class.generator.actor.Random", nb_npc = {12, 12}, - guardian = {random_elite={life_rating=function(v) return v * 1.5 + 4 end, nb_rares=4, name_scheme="#rng# the Invader", on_die=function(self) world:gainAchievement("EVENT_FEARSCAPE", game:getPlayer(true)) end}}, + guardian = {random_elite={life_rating=function(v) return v * 1.5 + 4 end, name_scheme="#rng# the Invader", on_die=function(self) world:gainAchievement("EVENT_FEARSCAPE", game:getPlayer(true)) end, + nb_rares=(rng.percent(resolvers.current_level-50) and 5 or 4), + nb_classes=(rng.percent(resolvers.current_level-50) and 2 or 1) + }} }, object = { class = "engine.generator.object.Random", @@ -96,7 +106,6 @@ local changer = function(id) game.zone.world_sphere_rot = (game.zone.world_sphere_rot or 0) game.zone.cloud_sphere_rot = (game.zone.world_cloud_rot or 0) end, - background = function(level, x, y, nb_keyframes) local Map = require "engine.Map" local parx, pary = level.map.mx / (level.map.w - Map.viewport.mwidth), level.map.my / (level.map.h - Map.viewport.mheight) @@ -132,8 +141,6 @@ local changer = function(id) core.display.glMatrix(false) core.display.glDepthTest(false) end, - --- levels = { [1] = { generator = { map = { up = "CAVEFLOOR", }, }, }, }, npc_list = npcs, grid_list = terrains, object_list = objects, @@ -144,7 +151,10 @@ end local g = game.level.map(x, y, engine.Map.TERRAIN):cloneFull() g.name = "fearscape invasion portal" +g.always_remember = true +g.show_tooltip = true g.display='&' g.color_r=0 g.color_g=0 g.color_b=255 g.notice = true +g.special_minimap = colors.VIOLET g.change_level=1 g.change_zone=id g.glow=true g:removeAllMOs() if engine.Map.tiles.nicer_tiles then @@ -152,35 +162,43 @@ if engine.Map.tiles.nicer_tiles then g.add_displays[#g.add_displays+1] = mod.class.Grid.new{image="terrain/demon_portal3.png"} end g.grow = nil g.dig = nil +g.nice_tiler = nil g:altered() g:initGlow() g.special = true g.real_change = changer +g.break_portal = function(self) + self.broken = true + game.log("#VIOLET#The portal is broken!") + self.name = "broken fearscape invasion portal" + self.change_level = nil + self.autoexplore_ignore = true + self.show_tooltip = false +end g.change_level_check = function(self) + self:break_portal() game:changeLevel(1, self.real_change(self.change_zone), {temporary_zone_shift=true, direct_switch=true}) game.player:attr("planetary_orbit", 1) - self.change_level_check = nil - self.real_change = nil return true end -g.on_move = function(self, x, y, who) +g.on_move = function(self, x, y, who, act, couldpass) if not who or not who.player then return false end if self.broken then game.log("#VIOLET#The portal is already broken!") return false end - require("engine.ui.Dialog"):yesnoPopup("Fearscape Portal", "Do you wish to enter the portal or just destroy it?", function(ret) - game.log("#VIOLET#The portal is broken!") + require("engine.ui.Dialog"):yesnoPopup("Fearscape Portal", "Do you wish to enter the portal, destroy it, or ignore it (press escape)?", function(ret) + if ret == "Quit" then + game.log("#VIOLET#Ignoring the portal...") + return + end if not ret then self:change_level_check() + else self:break_portal() end - self.broken = true - self.name = "broken "..self.name - self.change_level = nil - self.autoexplore_ignore = true - end, "Destroy", "Enter") - + end, "Destroy", "Enter", false, "Quit") + return false end @@ -189,27 +207,35 @@ game.zone:addEntity(game.level, g, "terrain", x, y) local respawn = function(self) local portal = game.level.map(self.fearscape_portal_x, self.fearscape_portal_y, engine.Map.TERRAIN) if not portal or portal.broken then return end - local i, j = util.findFreeGrid(self.fearscape_portal_x, self.fearscape_portal_y+1, 10, true, {[engine.Map.ACTOR]=true}) - if not i then return end local npcs = mod.class.NPC:loadList{"/data/general/npcs/major-demon.lua"} local m = game.zone:makeEntity(game.level, "actor", {base_list=npcs}, nil, true) if not m then return end - m.fearscape_portal_x = self.fearscape_portal_x - m.fearscape_portal_y = self.fearscape_portal_y - m.fearscape_respawn = self.fearscape_respawn - m.exp_worth = 0 - m.no_drops = true - m.faction = "fearscape" - m.on_die = function(self) self:fearscape_respawn() end - game.zone:addEntity(game.level, m, "actor", i, j) - game.logSeen(m, "#VIOLET#A demon steps out of the portal!") + local adjacent = util.adjacentCoords(self.fearscape_portal_x, self.fearscape_portal_y) + adjacent[5] = {self.fearscape_portal_x, self.fearscape_portal_y} + + repeat + local grid = rng.tableRemove(adjacent) + if m:canMove(grid[1], grid[2]) then + m.fearscape_portal_x = self.fearscape_portal_x + m.fearscape_portal_y = self.fearscape_portal_y + m.fearscape_respawn = self.fearscape_respawn + m.exp_worth = 0 + m.no_drops = true + m.ingredient_on_death = nil + m.faction = "fearscape" + m.on_die = function(self) self:fearscape_respawn() end + game.zone:addEntity(game.level, m, "actor", grid[1], grid[2]) + game.logSeen(m, "#VIOLET#A demon steps out of the %s!", portal.name) + break + end + until #adjacent <= 0 end --- Spawn two that will keep on being replenished +-- Spawn two demons that will keep on being replenished local base = {fearscape_portal_x=x, fearscape_portal_y=y, fearscape_respawn=respawn} respawn(base) respawn(base) -return true +return x, y diff --git a/game/modules/tome/data/general/events/groups/outdoor-majeyal-gloomy.lua b/game/modules/tome/data/general/events/groups/outdoor-majeyal-gloomy.lua index 28eb458a3e8c4695d2047a929df2f45a57ef9102..97af7cd6ad39afb0233977790a5674e1552e79c6 100644 --- a/game/modules/tome/data/general/events/groups/outdoor-majeyal-gloomy.lua +++ b/game/modules/tome/data/general/events/groups/outdoor-majeyal-gloomy.lua @@ -21,5 +21,5 @@ return { {name="tombstones", percent=10}, {name="old-battle-field", percent=5}, {name="thunderstorm", percent=7}, - {name="rat-lich", percent=2}, + {name="rat-lich", percent=2, unique=true}, } diff --git a/game/modules/tome/data/general/events/naga-portal.lua b/game/modules/tome/data/general/events/naga-portal.lua index f0ec2c55f39494a1fc7e64d1810ff2e749bab21a..cc23c8b59fc953d98c3998a50c495ddf1bd3de45 100644 --- a/game/modules/tome/data/general/events/naga-portal.lua +++ b/game/modules/tome/data/general/events/naga-portal.lua @@ -18,16 +18,13 @@ -- darkgod@te4.org -- Find a random spot -local x, y = rng.range(1, level.map.w - 2), rng.range(1, level.map.h - 2) -local tries = 0 -while not game.state:canEventGrid(level, x, y) and tries < 100 do - x, y = rng.range(1, level.map.w - 2), rng.range(1, level.map.h - 2) - tries = tries + 1 -end -if tries >= 100 then return false end +local x, y = game.state:findEventGrid(level) +if not x then return false end local id = "naga-invasion-"..game.turn +print("[EVENT] Placing event", id, "at", x, y) + local changer = function(id) local npcs = mod.class.NPC:loadList{"/data/general/npcs/naga.lua"} local objects = mod.class.Object:loadList("/data/general/objects/objects.lua") @@ -36,30 +33,35 @@ local changer = function(id) type = "floor", subtype = "underwater", display = "&", color = colors.BLUE, name = "coral invasion portal", + name = "portal back to "..game.zone.name, image = "terrain/underwater/subsea_floor_02.png", add_displays = {mod.class.Grid.new{z=18, image="terrain/naga_portal.png", display_h=2, display_y=-1, embed_particles = { {name="naga_portal_smoke", rad=2, args={smoke="particles_images/smoke_whispery_bright"}}, {name="naga_portal_smoke", rad=2, args={smoke="particles_images/smoke_heavy_bright"}}, {name="naga_portal_smoke", rad=2, args={smoke="particles_images/smoke_dark"}}, }}}, - change_level = 1, change_zone = "wilderness", + change_level = 1, + change_zone = game.zone.short_name, change_level_shift_back = true, change_zone_auto_stairs = true, } local zone = mod.class.Zone.new(id, { name = "water cavern", - level_range = {game.zone:level_adjust_level(game.level, game.zone, "actor"), game.zone:level_adjust_level(game.level, game.zone, "actor")}, + level_range = game.zone.actor_adjust_level and {math.floor(game.zone:actor_adjust_level(game.level, game.player)*1.05), + math.ceil(game.zone:actor_adjust_level(game.level, game.player)*1.15)} or {game.zone.base_level, game.zone.base_level}, -- 5-15% higher levels + __applied_difficulty = true, -- Difficulty already applied to parent zone level_scheme = "player", max_level = 1, actor_adjust_level = function(zone, level, e) return zone.base_level + e:getRankLevelAdjust() + level.level-1 + rng.range(-1,2) end, width = 30, height = 30, ambient_music = "Dark Secrets.ogg", reload_lists = false, + no_worldport = game.zone.no_worldport, color_shown = {0.5, 1, 0.8, 1}, color_obscure = {0.5*0.6, 1*0.6, 0.8*0.6, 0.6}, persistent = "zone", - min_material_level = game.zone.min_material_level, - max_material_level = game.zone.max_material_level, + min_material_level = util.getval(game.zone.min_material_level), + max_material_level = util.getval(game.zone.max_material_level), effects = {"EFF_ZONE_AURA_UNDERWATER"}, generator = { map = { @@ -76,7 +78,10 @@ local changer = function(id) actor = { class = "mod.class.generator.actor.Random", nb_npc = {12, 12}, - guardian = {random_elite={life_rating=function(v) return v * 1.5 + 4 end, nb_rares=4, name_scheme="#rng# the Tidebender", on_die=function(self) world:gainAchievement("EVENT_NAGA", game:getPlayer(true)) end}}, + guardian = {random_elite={life_rating=function(v) return v * 1.5 + 4 end, name_scheme="#rng# the Tidebender", on_die=function(self) world:gainAchievement("EVENT_NAGA", game:getPlayer(true)) end, + nb_rares=(rng.percent(resolvers.current_level-50) and 4 or 3), + nb_classes=(rng.percent(resolvers.current_level-50) and 2 or 1) + }}, }, object = { class = "engine.generator.object.Random", @@ -89,7 +94,6 @@ local changer = function(id) }, }, post_process = function(level) for uid, e in pairs(level.entities) do e.faction = e.hard_faction or "vargh-republic" end end, --- levels = { [1] = { generator = { map = { up = "CAVEFLOOR", }, }, }, }, npc_list = npcs, grid_list = terrains, object_list = objects, @@ -100,7 +104,9 @@ end local g = game.level.map(x, y, engine.Map.TERRAIN):cloneFull() g.name = "naga invasion coral portal" +g.always_remember = true g.display='&' g.color_r=0 g.color_g=0 g.color_b=255 g.notice = true +g.special_minimap = colors.VIOLET g.change_level=1 g.change_zone=id g.glow=true g:removeAllMOs() if engine.Map.tiles.nicer_tiles then @@ -116,30 +122,37 @@ g.grow = nil g.dig = nil g:initGlow() g.special = true g.real_change = changer +g.break_portal = function(self) + game.log("#VIOLET#The portal is broken!") + self.broken = true + self.name = "broken naga invasion coral portal" + self.change_level = nil + self.autoexplore_ignore = true + self.show_tooltip = false +end g.change_level_check = function(self) + self:break_portal() game:changeLevel(1, self.real_change(self.change_zone), {temporary_zone_shift=true, direct_switch=true}) - self.change_level_check = nil - self.real_change = nil return true end -g.on_move = function(self, x, y, who) +g.on_move = function(self, x, y, who, act, couldpass) if not who or not who.player then return false end if self.broken then game.log("#VIOLET#The portal is already broken!") return false end - - require("engine.ui.Dialog"):yesnoPopup("Coral Portal", "Do you wish to enter the portal or just destroy it?", function(ret) - game.log("#VIOLET#The portal is broken!") + require("engine.ui.Dialog"):yesnoPopup("Coral Portal", "Do you wish to enter the portal, destroy it, or ignore it (press escape)?", function(ret) + if ret == "Quit" then + game.log("#VIOLET#Ignoring the portal...") + return + end if not ret then self:change_level_check() + else self:break_portal() end - self.broken = true - self.name = "broken "..self.name - self.change_level = nil - self.autoexplore_ignore = true - end, "Destroy", "Enter") + end, "Destroy", "Enter", false, "Quit") + return false end @@ -148,27 +161,35 @@ game.zone:addEntity(game.level, g, "terrain", x, y) local respawn = function(self) local portal = game.level.map(self.naga_portal_x, self.naga_portal_y, engine.Map.TERRAIN) if not portal or portal.broken then return end - local i, j = util.findFreeGrid(self.naga_portal_x, self.naga_portal_y+1, 10, true, {[engine.Map.ACTOR]=true}) - if not i then return end local npcs = mod.class.NPC:loadList{"/data/general/npcs/naga.lua"} local m = game.zone:makeEntity(game.level, "actor", {base_list=npcs}, nil, true) if not m then return end - m.naga_portal_x = self.naga_portal_x - m.naga_portal_y = self.naga_portal_y - m.naga_respawn = self.naga_respawn - m.exp_worth = 0 - m.no_drops = true - m.faction = "vargh-republic" - m.on_die = function(self) self:naga_respawn() end - game.zone:addEntity(game.level, m, "actor", i, j) - game.logSeen(m, "#VIOLET#A naga steps out of the coral portal!") + local adjacent = util.adjacentCoords(self.naga_portal_x, self.naga_portal_y) + adjacent[5] = {self.naga_portal_x, self.naga_portal_y} + + repeat + local grid = rng.tableRemove(adjacent) + if m:canMove(grid[1], grid[2]) then + m.naga_portal_x = self.naga_portal_x + m.naga_portal_y = self.naga_portal_y + m.naga_respawn = self.naga_respawn + m.exp_worth = 0 + m.no_drops = true + m.ingredient_on_death = nil + m.faction = "vargh-republic" + m.on_die = function(self) self:naga_respawn() end + game.zone:addEntity(game.level, m, "actor", grid[1], grid[2]) + game.logSeen(m, "#VIOLET#A naga steps out of the %s!", portal.name) + break + end + until #adjacent <= 0 end --- Spawn two that will keep on being replenished +-- Spawn two nagas that will keep on being replenished local base = {naga_portal_x=x, naga_portal_y=y, naga_respawn=respawn} respawn(base) respawn(base) -return true +return x, y diff --git a/game/modules/tome/data/general/events/old-battle-field.lua b/game/modules/tome/data/general/events/old-battle-field.lua index 439aa63dc4084ce90a917ac804dfc53f6ae4340e..cc6def746b514d2b666172560576c3dcfb20212d 100644 --- a/game/modules/tome/data/general/events/old-battle-field.lua +++ b/game/modules/tome/data/general/events/old-battle-field.lua @@ -42,9 +42,19 @@ if tries < 100 then local terrains = mod.class.Grid:loadList("/data/general/grids/cave.lua") terrains.CAVE_LADDER_UP_WILDERNESS.change_level_shift_back = true terrains.CAVE_LADDER_UP_WILDERNESS.change_zone_auto_stairs = true + terrains.CAVE_LADDER_UP_WILDERNESS.change_level = 1 + terrains.CAVE_LADDER_UP_WILDERNESS.name = "ramp up to "..game.zone.name + terrains.CAVE_LADDER_UP_WILDERNESS.change_zone = game.zone.short_name + terrains.CAVE_LADDER_UP_WILDERNESS.change_level_check = function(self, who) + game.log("#VIOLET# The ramp crumbles as you climb it, followed by the collapse of the cavern.") + -- May delete old zone file here? + return + end local zone = mod.class.Zone.new(id, { name = "Cavern beneath tombstones", - level_range = {game.zone:level_adjust_level(game.level, game.zone, "actor"), game.zone:level_adjust_level(game.level, game.zone, "actor")}, + level_range = game.zone.actor_adjust_level and {math.floor(game.zone:actor_adjust_level(game.level, game.player)*1.05), + math.ceil(game.zone:actor_adjust_level(game.level, game.player)*1.15)} or {game.zone.base_level, game.zone.base_level}, -- 5-15% higher levels + __applied_difficulty = true, -- Difficulty already applied to parent zone level_scheme = "player", max_level = 1, actor_adjust_level = function(zone, level, e) return zone.base_level + e:getRankLevelAdjust() + level.level-1 + rng.range(-1,2) end, @@ -52,8 +62,10 @@ if tries < 100 then ambient_music = "Swashing the buck.ogg", reload_lists = false, persistent = "zone", - min_material_level = game.zone.min_material_level, - max_material_level = game.zone.max_material_level, + + no_worldport = game.zone.no_worldport, + min_material_level = util.getval(game.zone.min_material_level), + max_material_level = util.getval(game.zone.max_material_level), generator = { map = { class = "engine.generator.map.Static", @@ -110,11 +122,12 @@ if tries < 100 then end local grids = check(x, y) + local graves = {} for i = 1, 5 do local p = rng.tableRemove(grids) local g = game.level.map(p.x, p.y, engine.Map.TERRAIN):cloneFull() - g.name = "grave" + g.name = "grave" g.x, g.y = p.x, p.y g.display='&' g.color_r=255 g.color_g=255 g.color_b=255 g.notice = true g.always_remember = true g.special_minimap = colors.OLIVE_DRAB g:removeAllMOs() @@ -124,25 +137,14 @@ if tries < 100 then end g.grow = nil g.dig = nil g.special = true + g.graves = graves g:altered() g.block_move = function(self, x, y, who, act, couldpass) if not who or not who.player or not act then return false end if game.level.event_battlefield_entered then return false end who:runStop("grave") require("engine.ui.Dialog"):yesnoPopup("Grave", "Do you wish to disturb the grave?", function(ret) if ret then - local g = game.level.map(x, y, engine.Map.TERRAIN) - g:removeAllMOs() - if g.add_displays then - local ov = g.add_displays[#g.add_displays] - ov.image = "terrain/grave_opened_0"..rng.range(1, 3).."_64.png" - end - g.name = "grave (opened)" - game.level.map:updateMap(x, y) - - self.block_move = nil - self.autoexplore_ignore = true self:change_level_check() - require("engine.ui.Dialog"):simplePopup("Fall...", "As you tried to dig the grave the ground fell under you. You find yourself stranded in an eerie lit cavern.") end end) return false end @@ -150,14 +152,29 @@ if tries < 100 then g.real_change = changer g.change_level_check = function(self) if game.level.event_battlefield_entered then return true end + self:removeAllMOs() + if self.add_displays then + local ov = self.add_displays[#self.add_displays] + ov.image = "terrain/grave_opened_0"..rng.range(1, 3).."_64.png" + end + self.name = "opened grave" + game.level.map:updateMap(self.x, self.y) game.level.event_battlefield_entered = true game:changeLevel(1, self.real_change(self.change_zone), {temporary_zone_shift=true, direct_switch=true}) + require("engine.ui.Dialog"):simplePopup("Fall...", "As you began digging up the grave, the ground collapsed beneath you. You fall into an eerily lit cavern.") + for i, gr in ipairs(self.graves) do + gr.change_level_check = nil + gr.change_level = nil + gr.block_move = nil + gr.autoexplore_ignore = true + end return true end + print("[EVENT] Placing grave for event", id, "at", p.x, p.y) game.zone:addEntity(game.level, g, "terrain", p.x, p.y) - print("[EVENT] grave placed at ", p.x, p.y) + table.insert(graves, g) end end -return true +return x, y \ No newline at end of file diff --git a/game/modules/tome/data/general/events/rat-lich.lua b/game/modules/tome/data/general/events/rat-lich.lua index 4ac29aa0c7835eddd623762e7f46eae7df7e5c02..a72f80d31375607dc8a65e5d1efef8805302f251 100644 --- a/game/modules/tome/data/general/events/rat-lich.lua +++ b/game/modules/tome/data/general/events/rat-lich.lua @@ -20,24 +20,27 @@ -- Unique if game.state:doneEvent(event_id) then return end --- Find a random spot -local x, y = rng.range(1, level.map.w - 2), rng.range(1, level.map.h - 2) -local tries = 0 -while not game.state:canEventGrid(level, x, y) and tries < 100 do - x, y = rng.range(1, level.map.w - 2), rng.range(1, level.map.h - 2) - tries = tries + 1 -end -if tries >= 100 then return false end +local x, y = game.state:findEventGrid(level) +if not x then return false end local id = "rat-lich-"..game.turn +print("[EVENT] Placing event", id, "at", x, y) + local changer = function(id) local npcs = mod.class.NPC:loadList{"/data/general/npcs/undead-rat.lua"} local objects = mod.class.Object:loadList("/data/general/objects/objects.lua") local terrains = mod.class.Grid:loadList("/data/general/grids/basic.lua") terrains.UP_WILDERNESS.change_level_shift_back = true terrains.UP_WILDERNESS.change_zone_auto_stairs = true - + terrains.UP_WILDERNESS.name = "way up to "..game.zone.name + terrains.UP_WILDERNESS.change_zone = game.zone.short_name + terrains.UP_WILDERNESS.change_level = 1 + terrains.UP_WILDERNESS.change_level_check = function(self) + game.log("#VIOLET# As you leave the crypt, the stairway collapses in upon itself.") + -- May delete old zone file here? + return + end objects.RATLICH_SKULL = mod.class.Object.new{ define_as = "RATLICH_SKULL", power_source = {arcane=true}, @@ -97,7 +100,9 @@ local changer = function(id) local zone = mod.class.Zone.new(id, { name = "Forsaken Crypt", - level_range = {game.zone:level_adjust_level(game.level, game.zone, "actor"), game.zone:level_adjust_level(game.level, game.zone, "actor")}, + level_range = game.zone.actor_adjust_level and {math.floor(game.zone:actor_adjust_level(game.level, game.player)*1.05), + math.ceil(game.zone:actor_adjust_level(game.level, game.player)*1.15)} or {game.zone.base_level, game.zone.base_level}, -- 5-15% higher levels + __applied_difficulty = true, --Difficulty already applied to parent zone level_scheme = "player", max_level = 1, actor_adjust_level = function(zone, level, e) return zone.base_level + e:getRankLevelAdjust() + level.level-1 + rng.range(-1,2) end, @@ -105,8 +110,10 @@ local changer = function(id) ambient_music = "Dark Secrets.ogg", reload_lists = false, persistent = "zone", - min_material_level = game.zone.min_material_level, - max_material_level = game.zone.max_material_level, + no_worldport = game.zone.no_worldport, + min_material_level = util.getval(game.zone.min_material_level), + max_material_level = util.getval(game.zone.max_material_level), + generator = { map = { class = "engine.generator.map.Roomer", @@ -142,7 +149,10 @@ local changer = function(id) end local g = game.level.map(x, y, engine.Map.TERRAIN):cloneFull() -g.name = "forsaken crypt" +g.name = "stairway leading downwards" +g.always_remember = true +g.desc = [[Stairs seem to lead into some kind of crypt.]] +g.show_tooltip = true g.display='>' g.color_r=0 g.color_g=0 g.color_b=255 g.notice = true g.change_level=1 g.change_zone=id g.glow=true g:removeAllMOs() @@ -157,7 +167,11 @@ g.change_level_check = function(self) game:changeLevel(1, self.real_change(self.change_zone), {temporary_zone_shift=true, direct_switch=true}) require("engine.ui.Dialog"):simplePopup("Forsaken Crypt", "You hear squeaks and the sounds of clicking bone echo around you... Pure death awaits. Flee!") self.change_level_check = nil - self.real_change = nil + self.change_level = nil + self.name = "collapsed forsaken crypt" + self.desc = [[Stairs lead downwards into rubble.]] + self.autoexplore_ignore = true + self.special_minimap = colors.VIOLET return true end game.zone:addEntity(game.level, g, "terrain", x, y) @@ -172,4 +186,4 @@ for z = 1, 3 do end end -return true +return x, y diff --git a/game/modules/tome/data/general/events/sludgenest.lua b/game/modules/tome/data/general/events/sludgenest.lua index 57d71eef188dca6755c03456c154001576c4ce11..280fe92fb1d8d27f86250d3b06bcd59d4d812dc4 100644 --- a/game/modules/tome/data/general/events/sludgenest.lua +++ b/game/modules/tome/data/general/events/sludgenest.lua @@ -37,7 +37,7 @@ level.data.on_enter_list.sludgenest = function() g:initGlow() game.zone:addEntity(game.level, g, "terrain", spot.x, spot.y) print("[WORLDMAP] sludgenest at", spot.x, spot.y) - require("engine.ui.Dialog"):simpleLongPopup("Lush forest", "Suddently it comes back to you. You remember long ago somebody told you about a strange lush forest in the cold icy wastes of the northland.", 400) + require("engine.ui.Dialog"):simpleLongPopup("Lush forest", "Suddenly it comes back to you. You remember long ago somebody told you about a strange lush forest in the cold icy wastes of the northland.", 400) end return true diff --git a/game/modules/tome/data/general/events/sub-vault.lua b/game/modules/tome/data/general/events/sub-vault.lua index ac4e362d626af0af89133341b4ef11287380714a..e1bacc600e58471febedb8ca641f0de66512057f 100644 --- a/game/modules/tome/data/general/events/sub-vault.lua +++ b/game/modules/tome/data/general/events/sub-vault.lua @@ -20,8 +20,8 @@ -- Find a random spot local x, y = game.state:findEventGrid(level) if not x then return false end -print("placing sub-vault at", x, y) local id = "sub-vault"..game.turn.."-"..rng.range(1,9999) +print("[EVENT] Placing event", id, "at", x, y) local changer = function(id) local grid_list = table.clone(game.zone.grid_list) @@ -72,9 +72,9 @@ local changer = function(id) ambient_music = game.zone.ambient_music, reload_lists = false, persistent = "zone", --- _max_level_generation_count = 2, - min_material_level = game.zone.min_material_level, - max_material_level = game.zone.max_material_level, +-- _max_level_generation_count = 5, + min_material_level = util.getval(game.zone.min_material_level), + max_material_level = util.getval(game.zone.max_material_level), no_worldport = game.zone.no_worldport, generator = { map = table.merge(basemap, { @@ -110,9 +110,11 @@ end local g = game.level.map(x, y, engine.Map.TERRAIN):cloneFull() g.name = "hidden vault" +g.always_remember = true g.desc = [[Crumbling stairs lead down to something.]] g.show_tooltip = true g.display='>' g.color_r=0 g.color_g=0 g.color_b=255 g.notice = true +g.special_minimap = colors.VIOLET g.change_level=1 g.change_zone=id g.glow=true g:removeAllMOs() if engine.Map.tiles.nicer_tiles then @@ -124,19 +126,17 @@ g:altered() g:initGlow() g.real_change = changer g.change_level_check = function(self) -- limit stair scumming - game:changeLevel(1, self.real_change(self.change_zone), {temporary_zone_shift=true, direct_switch=true}) self._use_count = self._use_count - 1 self.name = "collapsing hidden vault" if self._use_count < 1 then self.change_level_check = nil - self.real_change = nil self.change_level = nil self.name = "collapsed hidden vault" self.desc = [[A collapsed stairway, leading down]] elseif self._use_count < 2 then self.name = "nearly collapsed hidden vault" end - self.special_minimap = colors.BLUE + game:changeLevel(1, self.real_change(self.change_zone), {temporary_zone_shift=true, direct_switch=true}) return true end game.zone:addEntity(game.level, g, "terrain", x, y) diff --git a/game/modules/tome/data/zones/halfling-ruins/events.lua b/game/modules/tome/data/zones/halfling-ruins/events.lua index 5d303d5bb45ea170276cb04b712b06549c2eb7b0..4cf5cbb07a9513b8d0b229fba51b5f61d7e91803 100644 --- a/game/modules/tome/data/zones/halfling-ruins/events.lua +++ b/game/modules/tome/data/zones/halfling-ruins/events.lua @@ -22,5 +22,8 @@ return { one_per_level=true, {name="protective-aura", minor=true, percent=50}, {name="necrotic-air", minor=true, percent=50}, {name="glowing-chest", minor=true, percent=20}, - {name="conclave-vault", percent=30, forbid={1, 2, 4}, special=function() if game:getPlayer(true) and game:getPlayer(true).descriptor and game:getPlayer(true).descriptor.subrace == "Shalore" then return true end end}, + {name="conclave-vault", level_range={3, 3}, + -- always spawn conclave-vault event for Shalore + percent=(table.get(game:getPlayer(true), "descriptor", "subrace") == "Shalore" and 100 or 30) + } } diff --git a/game/modules/tome/data/zones/infinite-dungeon/events.lua b/game/modules/tome/data/zones/infinite-dungeon/events.lua index b7dd02f4099df64e6a476edbf6608e21b6756a3e..3ff5e452b3041cc814169ac57ff15918bf44199d 100644 --- a/game/modules/tome/data/zones/infinite-dungeon/events.lua +++ b/game/modules/tome/data/zones/infinite-dungeon/events.lua @@ -19,7 +19,7 @@ return { one_per_level=true, {group="majeyal-generic", percent_factor=0.5}, - {name="cultists", percent=5}, + {name="cultists", percent=5, level_range={15,nil}}, {name="icy-ground", minor=true, percent=20}, {name="font-life", minor=true, percent=20}, {name="whistling-vortex", minor=true, percent=20}, @@ -31,4 +31,12 @@ return { one_per_level=true, {name="protective-aura", minor=true, percent=20}, {name="spellblaze-scar", minor=true, percent=20}, {name="glowing-chest", minor=true, percent=30}, + + {name="rat-lich", percent=5, level_range={2,20}, unique=true}, + {name="old-battle-field", percent=5, level_range={8,40}}, + {name="damp-cave", percent=5, level_range={2,20}}, + {name="drake-cave", percent=5, level_range={10,nil}}, + {name="fearscape-portal", percent=5, level_range={18,nil}}, + {name="naga-portal", percent=5, level_range={15,nil}}, + } diff --git a/game/modules/tome/data/zones/wilderness/events.lua b/game/modules/tome/data/zones/wilderness/events.lua index 1270721f366d93e812815a4165662d7787554e44..1719ef02d5f4ce0851a9b632da92f816851a407e 100644 --- a/game/modules/tome/data/zones/wilderness/events.lua +++ b/game/modules/tome/data/zones/wilderness/events.lua @@ -17,7 +17,11 @@ -- Nicolas Casalini "DarkGod" -- darkgod@te4.org +local descriptor = table.get(game:getPlayer(true), "descriptor") + return { - {name="noxious-caldera", percent=30, special=function() if game:getPlayer(true) and game:getPlayer(true).descriptor and game:getPlayer(true).descriptor.race == "Yeek" then return true end end}, - {name="sludgenest", percent=30, special=function() if game:getPlayer(true) and game:getPlayer(true).descriptor and game:getPlayer(true).descriptor.subrace == "Thalore" then return true end end}, + -- always spawn noxious-caldera for Yeeks (event file does additional tests) + {name="noxious-caldera", percent=(table.get(descriptor, "race") == "Yeek" and 100 or 30)}, + -- always spawn sludgenest for Thalore (event file does additional tests) + {name="sludgenest", percent=(table.get(descriptor, "subrace") == "Thalore" and 100 or 30)}, }