Skip to content
Snippets Groups Projects
Commit d8808e85 authored by DarkGod's avatar DarkGod
Browse files

Merge branch 'MajorEventsUpdate' into 'master'

Major events update

GameState:doneEvent is updated to allow incrementing the used count (which is returned), and it is automatically called for events that are placed or assigned to a level, allowing event code to check the count correctly.


GameState:startEvents() updated:

The zone events file supports some new fields:

unique = true prevents triggering of events that have previously been triggered (anywhere in the game)

level_range = a range of allowed levels the event is allowed to spawn on (complements the forbid field)

special = an optional function(lev) that can determine if the event should spawn or not (The logic is updated to be consistent with other "special" functions used in filters, etc.)

Fixed a bug in passing event_id to event functions (metatables).

Added documentation and output to the relevant GameState functions.

Fixed issues with major events that involve a change of zone (sub-vault, rat-lich, damp-cave, old-battle-field, drake-cave, naga-portal, fearscape-portal):

.no_worldport is set to that of the parent zone.

Actor levels are 5% to 15% higher than the parent zone and game difficulty adjustments are not compounded.

Object material levels match the parent zone.

Auto explore and minimap settings are updated.


This makes these events "safe" to add anywhere in the game and at higher difficulties, and they are added as standard to the I.D. (with appropriate level restrictions).


Fixed a bug in game:changeLevelReal that was causing the player to incorrectly be placed at level start when params.auto_level_stair was set.  (Affected the old-battle-field event and some other stairs)

Other event changes:
  
The player can choose to ignore the naga-portal and fearscape-portal by hitting escape at the pop-up.

The cultists event uniqueness is fixed (unique across the game) and it can only spawn from level 15+ in the I.D.

Fixed a bug in the sub-vault event that was preventing the stairs from crumbling as intended.

Updated the sludgenest and noxious-caldera events for the wilderness and the conclave-vault event for the halfling ruins.  (No game play change; the special field is removed as it's not needed.)




See merge request !441
parents 75fb217c cb1397f7
No related branches found
No related tags found
1 merge request!441Major events update
Pipeline #
Showing
with 351 additions and 183 deletions
...@@ -918,7 +918,7 @@ end ...@@ -918,7 +918,7 @@ end
function _M:changeLevelReal(lev, zone, params) function _M:changeLevelReal(lev, zone, params)
local oz, ol = self.zone, self.level local oz, ol = self.zone, self.level
-- Unlock first! -- Unlock first!
if not params.temporary_zone_shift_back and self.level and self.level.temp_shift_zone then 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}) self:changeLevelReal(1, "useless", {temporary_zone_shift_back=true})
...@@ -1101,7 +1101,7 @@ function _M:changeLevelReal(lev, zone, params) ...@@ -1101,7 +1101,7 @@ function _M:changeLevelReal(lev, zone, params)
list[#list+1] = {i, j} list[#list+1] = {i, j}
end end
end 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 elseif params.auto_level_stair then
-- Dirty but quick -- Dirty but quick
local list = {} local list = {}
...@@ -1111,7 +1111,7 @@ function _M:changeLevelReal(lev, zone, params) ...@@ -1111,7 +1111,7 @@ function _M:changeLevelReal(lev, zone, params)
list[#list+1] = {i, j} list[#list+1] = {i, j}
end end
end 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 end
-- if self.level.exited then -- use the last location, if defined -- if self.level.exited then -- use the last location, if defined
......
...@@ -2360,8 +2360,13 @@ function _M:locationRevealAround(x, y) ...@@ -2360,8 +2360,13 @@ function _M:locationRevealAround(x, y)
end end
end end
function _M:doneEvent(id) --- Has event been triggered in this game state?
return self.used_events[id] -- @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 end
function _M:canEventGrid(level, x, y) function _M:canEventGrid(level, x, y)
...@@ -2401,6 +2406,10 @@ function _M:findEventGridRadius(level, radius, min) ...@@ -2401,6 +2406,10 @@ function _M:findEventGridRadius(level, radius, min)
return self:canEventGridRadius(level, x, y, radius, min) return self:canEventGridRadius(level, x, y, radius, min)
end 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) function _M:eventBaseName(sub, name)
local base = "/data" local base = "/data"
local _, _, addon, rname = name:find("^([^+]+)%+(.+)$") local _, _, addon, rname = name:find("^([^+]+)%+(.+)$")
...@@ -2411,8 +2420,30 @@ function _M:eventBaseName(sub, name) ...@@ -2411,8 +2420,30 @@ function _M:eventBaseName(sub, name)
return base.."/general/events/"..sub..name..".lua" return base.."/general/events/"..sub..name..".lua"
end 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() 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 if not game.zone.assigned_events then
local levels = {} local levels = {}
...@@ -2422,58 +2453,76 @@ function _M:startEvents() ...@@ -2422,58 +2453,76 @@ function _M:startEvents()
for i = 1, game.zone.max_level do levels[i] = {} end for i = 1, game.zone.max_level do levels[i] = {} end
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 = {}, {} local evts, mevts = {}, {}
for i, e in ipairs(game.zone.events) do 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 if e.name then -- add a single event to the events list
elseif e.group then 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)) local f, err = loadfile(self:eventBaseName("groups/", e.group))
if not f then error(err) end if not f then error(err) end
setfenv(f, setmetatable({level=game.level, zone=game.zone}, {__index=_G})) setfenv(f, setmetatable({level=game.level, zone=game.zone}, {__index=_G}))
local list = f() local list = f()
for j, ee in ipairs(list) do 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 -- print("[STARTEVENTS]\t\tAdding Group Event:", j, tostring(ee.name))
if e.forbid then ee.forbid = table.append(ee.forbid or {}, e.forbid) end if ee.name then
if ee.name then if ee.minor then mevts[#mevts+1] = ee else evts[#evts+1] = ee end end 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 end
end end
-- Randomize the order they are checked as -- 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) table.shuffle(evts)
print("[STARTEVENTS] Zone events list:")
table.print(evts) table.print(evts)
table.shuffle(mevts) table.shuffle(mevts)
table.print(mevts) table.print(mevts)
for i, e in ipairs(evts) do for i, e in ipairs(evts) do
-- If we allow it, try to find a level to host it -- If allowed, find a level to host the (major) event
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 (e.always or rng.percent(e.percent)) and (not e.unique or not self:doneEvent(e.name)) then
local lev = nil local lev = nil
local forbid = e.forbid or {} local forbid = e.forbid or {}
forbid = table.reverse(forbid) forbid = table.reverse(forbid)
if game.zone.events_by_level then if game.zone.events_by_level then
lev = game.level.level 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 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 = {} 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 if #list > 0 then
lev = rng.table(list) lev = rng.table(list)
end end
else else -- pick an allowed level at random to assign the event to
if forbid then local t = table.genrange(start, stop, true)
local t = table.genrange(1, game.zone.max_level, 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) t = table.minus_keys(t, forbid)
lev = rng.table(table.keys(t)) lev = rng.table(table.keys(t))
else
lev = rng.range(1, game.zone.max_level)
end
end end
end end
if lev then if lev then
lev = levels[lev] lev = levels[lev]
lev[#lev+1] = e.name lev[#lev+1] = e.name
self:doneEvent(e.name, 1) -- mark as done when assigned
end end
end end
end end
...@@ -2482,23 +2531,27 @@ function _M:startEvents() ...@@ -2482,23 +2531,27 @@ function _M:startEvents()
forbid = table.reverse(forbid) forbid = table.reverse(forbid)
local start, stop = 1, game.zone.max_level local start, stop = 1, game.zone.max_level
if game.zone.events_by_level then start, stop = game.level.level, game.level.level end if game.zone.events_by_level then
for lev = start, stop do start, stop = game.level.level, game.level.level
if rng.percent(e.percent) and not forbid[lev] then end
local lev = levels[lev] if e.level_range then
lev[#lev+1] = e.name start, stop = math.max(start, e.level_range[1] or start), math.min(stop, e.level_range[2] or stop)
end
if e.max_repeat then 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 nb = 1
local p = e.percent local p = e.percent or 100
while nb <= e.max_repeat do while nb <= e.max_repeat do
if rng.percent(p) then if e.always or rng.percent(p) and (not e.special or e.special(lv)) then
lev[#lev+1] = e.name lev[#lev+1] = e.name self:doneEvent(e.name, 1) -- mark as done when assigned
nb = nb + 1 nb = nb + 1
p = p/2
else else
break break
end end
p = p / 2
end end
end end
end end
...@@ -2508,6 +2561,7 @@ function _M:startEvents() ...@@ -2508,6 +2561,7 @@ function _M:startEvents()
game.zone.assigned_events = levels game.zone.assigned_events = levels
end end
-- return a wrapper function to load and run all assigned events files
return function() return function()
print("[STARTEVENTS] Assigned events list:") print("[STARTEVENTS] Assigned events list:")
table.print(game.zone.assigned_events) table.print(game.zone.assigned_events)
...@@ -2515,8 +2569,9 @@ function _M:startEvents() ...@@ -2515,8 +2569,9 @@ function _M:startEvents()
for i, e in ipairs(game.zone.assigned_events[game.level.level] or {}) do for i, e in ipairs(game.zone.assigned_events[game.level.level] or {}) do
local f, err = loadfile(self:eventBaseName("", e)) local f, err = loadfile(self:eventBaseName("", e))
if not f then error(err) end if not f then error(err) end
setfenv(f, setmetatable({level=game.level, zone=game.zone, event_id=e.name, Map=Map}, {__index=_G})) setfenv(f, setmetatable({level=game.level, zone=game.zone, event_id=e, Map=Map}, {__index=_G}))
f() 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 end
game.zone.assigned_events[game.level.level] = {} game.zone.assigned_events[game.level.level] = {}
if game.zone.events_by_level then game.zone.assigned_events = nil end if game.zone.events_by_level then game.zone.assigned_events = nil end
......
...@@ -57,7 +57,7 @@ function _M:generate(lev, old_lev) ...@@ -57,7 +57,7 @@ function _M:generate(lev, old_lev)
local rm local rm
for i = 0, self.map.w - 1 do for j = 0, self.map.h - 1 do for i = 0, self.map.w - 1 do for j = 0, self.map.h - 1 do
rm = self.map.room_map[i][j] 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 local g
if self.level.data.subvaults_surroundings then g = self:resolve(self.level.data.subvaults_surroundings, nil, true) if self.level.data.subvaults_surroundings then g = self:resolve(self.level.data.subvaults_surroundings, nil, true)
else g = self:resolve("subvault_wall") end else g = self:resolve("subvault_wall") end
...@@ -81,12 +81,13 @@ function _M:generate(lev, old_lev) ...@@ -81,12 +81,13 @@ function _M:generate(lev, old_lev)
sx, sy = e.sx, e.sy sx, sy = e.sx, e.sy
ex, ey = e.x, e.y ex, ey = e.x, e.y
if not (sx and sy) then -- vault connection point: connect to a (nearest) non-vault grid 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) 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)) 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 if dir == 5 then dir = rng.table(util.primaryDirs()) end
local rm local rm
local steps = math.max(room.w, room.h) + 2*(room.border or 0) + 1
local steps = (self.map.w + self.map.h)/4
repeat repeat
steps = steps - 1 steps = steps - 1
rm = self.map.room_map[sx][sy] rm = self.map.room_map[sx][sy]
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
local x, y = game.state:findEventGrid(level) local x, y = game.state:findEventGrid(level)
if not x then return false end if not x then return false end
print("[EVENT] Placing event conclave-vault at", x, y)
local Talents = require("engine.interface.ActorTalents") local Talents = require("engine.interface.ActorTalents")
local skeletons = mod.class.NPC:loadList("/data/general/npcs/skeleton.lua") local skeletons = mod.class.NPC:loadList("/data/general/npcs/skeleton.lua")
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
-- Nicolas Casalini "DarkGod" -- Nicolas Casalini "DarkGod"
-- darkgod@te4.org -- darkgod@te4.org
-- Unique -- Unique throughout the game
if game.state:doneEvent(event_id) then return end if game.state:doneEvent(event_id) then return end
local list = {} local list = {}
......
...@@ -23,15 +23,21 @@ if not x then return false end ...@@ -23,15 +23,21 @@ if not x then return false end
local id = "damp-cave-"..game.turn local id = "damp-cave-"..game.turn
print("[EVENT] Placing event", id, "at", x, y)
local changer = function(id) local changer = function(id)
local npcs = mod.class.NPC:loadList{"/data/general/npcs/thieve.lua"} local npcs = mod.class.NPC:loadList{"/data/general/npcs/thieve.lua"}
local objects = mod.class.Object:loadList("/data/general/objects/objects.lua") local objects = mod.class.Object:loadList("/data/general/objects/objects.lua")
local terrains = mod.class.Grid:loadList("/data/general/grids/cave.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_level_shift_back = true
terrains.CAVE_LADDER_UP_WILDERNESS.change_zone_auto_stairs = 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, { local zone = mod.class.Zone.new(id, {
name = "Damp Cave", 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", level_scheme = "player",
max_level = 1, max_level = 1,
actor_adjust_level = function(zone, level, e) return zone.base_level + e:getRankLevelAdjust() + level.level-1 + rng.range(-1,2) end, 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) ...@@ -39,8 +45,10 @@ local changer = function(id)
ambient_music = "Swashing the buck.ogg", ambient_music = "Swashing the buck.ogg",
reload_lists = false, reload_lists = false,
persistent = "zone", 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 = { generator = {
map = { map = {
class = "engine.generator.map.Cavern", class = "engine.generator.map.Cavern",
...@@ -66,7 +74,6 @@ local changer = function(id) ...@@ -66,7 +74,6 @@ local changer = function(id)
nb_trap = {6, 9}, nb_trap = {6, 9},
}, },
}, },
-- levels = { [1] = { generator = { map = { up = "CAVEFLOOR", }, }, }, },
npc_list = npcs, npc_list = npcs,
grid_list = terrains, grid_list = terrains,
object_list = objects, object_list = objects,
...@@ -77,6 +84,7 @@ end ...@@ -77,6 +84,7 @@ end
local g = game.level.map(x, y, engine.Map.TERRAIN):cloneFull() local g = game.level.map(x, y, engine.Map.TERRAIN):cloneFull()
g.name = "damp cave" 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.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.change_level=1 g.change_zone=id g.glow=true
g:removeAllMOs() g:removeAllMOs()
...@@ -84,6 +92,7 @@ if engine.Map.tiles.nicer_tiles then ...@@ -84,6 +92,7 @@ if engine.Map.tiles.nicer_tiles then
g.add_displays = g.add_displays or {} 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} g.add_displays[#g.add_displays+1] = mod.class.Grid.new{image="terrain/crystal_ladder_down.png", z=5}
end end
g.nice_tiler = nil
g:altered() g:altered()
g:initGlow() g:initGlow()
g.real_change = changer g.real_change = changer
...@@ -91,8 +100,9 @@ g.change_level_check = function(self) ...@@ -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}) game:changeLevel(1, self.real_change(self.change_zone), {temporary_zone_shift=true, direct_switch=true})
self.change_level_check = nil self.change_level_check = nil
self.real_change = nil self.real_change = nil
self.special_minimap = colors.VIOLET
return true return true
end end
game.zone:addEntity(game.level, g, "terrain", x, y) game.zone:addEntity(game.level, g, "terrain", x, y)
return true return x, y
...@@ -18,27 +18,28 @@ ...@@ -18,27 +18,28 @@
-- darkgod@te4.org -- darkgod@te4.org
-- Find a random spot -- Find a random spot
local x, y = rng.range(1, level.map.w - 2), rng.range(1, level.map.h - 2) local x, y = game.state:findEventGrid(level)
local tries = 0 if not x then return false end
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 kind = rng.table{"fire", "fire", "cold", "cold", "storm", "storm", "multihued"} local kind = rng.table{"fire", "fire", "cold", "cold", "storm", "storm", "multihued"}
local id = kind.."-dragon-cave-"..game.turn local id = kind.."-dragon-cave-"..game.turn
print("[EVENT] Placing event", id, "at", x, y)
local changer = function(id, kind) local changer = function(id, kind)
local npcs = mod.class.NPC:loadList{"/data/general/npcs/"..kind.."-drake.lua"} local npcs = mod.class.NPC:loadList{"/data/general/npcs/"..kind.."-drake.lua"}
local objects = mod.class.Object:loadList("/data/general/objects/objects.lua") local objects = mod.class.Object:loadList("/data/general/objects/objects.lua")
local terrains = mod.class.Grid:loadList("/data/general/grids/cave.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_level_shift_back = true
terrains.CAVE_LADDER_UP_WILDERNESS.change_zone_auto_stairs = 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, { local zone = mod.class.Zone.new(id, {
name = "Intimidating Cave", 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", level_scheme = "player",
max_level = 1, max_level = 1,
actor_adjust_level = function(zone, level, e) return zone.base_level + e:getRankLevelAdjust() + level.level-1 + rng.range(-1,2) end, 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) ...@@ -46,8 +47,10 @@ local changer = function(id, kind)
ambient_music = "Swashing the buck.ogg", ambient_music = "Swashing the buck.ogg",
reload_lists = false, reload_lists = false,
persistent = "zone", 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 = { generator = {
map = { map = {
class = "engine.generator.map.Cavern", class = "engine.generator.map.Cavern",
...@@ -61,7 +64,10 @@ local changer = function(id, kind) ...@@ -61,7 +64,10 @@ local changer = function(id, kind)
actor = { actor = {
class = "mod.class.generator.actor.Random", class = "mod.class.generator.actor.Random",
nb_npc = {25, 25}, 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 = { object = {
class = "engine.generator.object.Random", class = "engine.generator.object.Random",
...@@ -73,7 +79,6 @@ local changer = function(id, kind) ...@@ -73,7 +79,6 @@ local changer = function(id, kind)
nb_trap = {6, 9}, nb_trap = {6, 9},
}, },
}, },
-- levels = { [1] = { generator = { map = { up = "CAVEFLOOR", }, }, }, },
npc_list = npcs, npc_list = npcs,
grid_list = terrains, grid_list = terrains,
object_list = objects, object_list = objects,
...@@ -85,12 +90,14 @@ end ...@@ -85,12 +90,14 @@ end
local g = game.level.map(x, y, engine.Map.TERRAIN):cloneFull() local g = game.level.map(x, y, engine.Map.TERRAIN):cloneFull()
g.name = "intimidating cave" g.name = "intimidating cave"
g.display='>' g.color_r=0 g.color_g=0 g.color_b=255 g.notice = true 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.change_level=1 g.change_zone=id g.glow=true
g:removeAllMOs() g:removeAllMOs()
if engine.Map.tiles.nicer_tiles then if engine.Map.tiles.nicer_tiles then
g.add_displays = g.add_displays or {} 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} g.add_displays[#g.add_displays+1] = mod.class.Grid.new{image="terrain/crystal_ladder_down.png", z=5}
end end
g.nice_tiler = nil
g:altered() g:altered()
g:initGlow() g:initGlow()
g.dragon_kind = kind g.dragon_kind = kind
...@@ -99,6 +106,7 @@ g.change_level_check = function(self) ...@@ -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}) 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.change_level_check = nil
self.real_change = nil self.real_change = nil
self.special_minimap = colors.VIOLET
return true return true
end end
game.zone:addEntity(game.level, g, "terrain", x, y) game.zone:addEntity(game.level, g, "terrain", x, y)
...@@ -113,4 +121,4 @@ if m then ...@@ -113,4 +121,4 @@ if m then
game.zone:addEntity(game.level, m, "actor", i, j) game.zone:addEntity(game.level, m, "actor", i, j)
end end
return true return x, y
...@@ -18,16 +18,13 @@ ...@@ -18,16 +18,13 @@
-- darkgod@te4.org -- darkgod@te4.org
-- Find a random spot -- Find a random spot
local x, y = rng.range(1, level.map.w - 2), rng.range(1, level.map.h - 2) local x, y = game.state:findEventGrid(level)
local tries = 0 if not x then return false end
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 id = "fearscape-invasion-"..game.turn local id = "fearscape-invasion-"..game.turn
print("[EVENT] Placing event", id, "at", x, y)
local changer = function(id) local changer = function(id)
local npcs = mod.class.NPC:loadList{"/data/general/npcs/minor-demon.lua", "/data/general/npcs/major-demon.lua"} 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") local objects = mod.class.Object:loadList("/data/general/objects/objects.lua")
...@@ -37,16 +34,24 @@ local changer = function(id) ...@@ -37,16 +34,24 @@ local changer = function(id)
terrains.PORTAL_BACK = mod.class.Grid.new{ terrains.PORTAL_BACK = mod.class.Grid.new{
type = "floor", subtype = "floor", type = "floor", subtype = "floor",
display = "&", color = colors.BLUE, display = "&", color = colors.BLUE,
name = "portal", name = "portal back to "..game.zone.name,
image = "terrain/red_floating_rocks05_01.png", image = "terrain/red_floating_rocks05_01.png",
add_displays = { mod.class.Grid.new{image="terrain/demon_portal3.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_level_shift_back = true,
change_zone_auto_stairs = 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, { local zone = mod.class.Zone.new(id, {
name = "orbital fearscape platform", 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", level_scheme = "player",
max_level = 1, max_level = 1,
actor_adjust_level = function(zone, level, e) return zone.base_level + e:getRankLevelAdjust() + level.level-1 + rng.range(-1,2) end, 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) ...@@ -55,8 +60,10 @@ local changer = function(id)
reload_lists = false, reload_lists = false,
projectile_speed_mod = 0.3, projectile_speed_mod = 0.3,
persistent = "zone", 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"}, effects = {"EFF_ZONE_AURA_FEARSCAPE"},
generator = { generator = {
map = { map = {
...@@ -71,7 +78,10 @@ local changer = function(id) ...@@ -71,7 +78,10 @@ local changer = function(id)
actor = { actor = {
class = "mod.class.generator.actor.Random", class = "mod.class.generator.actor.Random",
nb_npc = {12, 12}, 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 = { object = {
class = "engine.generator.object.Random", class = "engine.generator.object.Random",
...@@ -96,7 +106,6 @@ local changer = function(id) ...@@ -96,7 +106,6 @@ local changer = function(id)
game.zone.world_sphere_rot = (game.zone.world_sphere_rot or 0) game.zone.world_sphere_rot = (game.zone.world_sphere_rot or 0)
game.zone.cloud_sphere_rot = (game.zone.world_cloud_rot or 0) game.zone.cloud_sphere_rot = (game.zone.world_cloud_rot or 0)
end, end,
background = function(level, x, y, nb_keyframes) background = function(level, x, y, nb_keyframes)
local Map = require "engine.Map" 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) 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) ...@@ -132,8 +141,6 @@ local changer = function(id)
core.display.glMatrix(false) core.display.glMatrix(false)
core.display.glDepthTest(false) core.display.glDepthTest(false)
end, end,
-- levels = { [1] = { generator = { map = { up = "CAVEFLOOR", }, }, }, },
npc_list = npcs, npc_list = npcs,
grid_list = terrains, grid_list = terrains,
object_list = objects, object_list = objects,
...@@ -144,7 +151,10 @@ end ...@@ -144,7 +151,10 @@ end
local g = game.level.map(x, y, engine.Map.TERRAIN):cloneFull() local g = game.level.map(x, y, engine.Map.TERRAIN):cloneFull()
g.name = "fearscape invasion portal" 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.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.change_level=1 g.change_zone=id g.glow=true
g:removeAllMOs() g:removeAllMOs()
if engine.Map.tiles.nicer_tiles then if engine.Map.tiles.nicer_tiles then
...@@ -152,35 +162,43 @@ 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"} g.add_displays[#g.add_displays+1] = mod.class.Grid.new{image="terrain/demon_portal3.png"}
end end
g.grow = nil g.dig = nil g.grow = nil g.dig = nil
g.nice_tiler = nil
g:altered() g:altered()
g:initGlow() g:initGlow()
g.special = true g.special = true
g.real_change = changer 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) 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:changeLevel(1, self.real_change(self.change_zone), {temporary_zone_shift=true, direct_switch=true})
game.player:attr("planetary_orbit", 1) game.player:attr("planetary_orbit", 1)
self.change_level_check = nil
self.real_change = nil
return true return true
end 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 not who or not who.player then return false end
if self.broken then if self.broken then
game.log("#VIOLET#The portal is already broken!") game.log("#VIOLET#The portal is already broken!")
return false return false
end end
require("engine.ui.Dialog"):yesnoPopup("Fearscape Portal", "Do you wish to enter the portal or just destroy it?", function(ret) require("engine.ui.Dialog"):yesnoPopup("Fearscape Portal", "Do you wish to enter the portal, destroy it, or ignore it (press escape)?", function(ret)
game.log("#VIOLET#The portal is broken!") if ret == "Quit" then
game.log("#VIOLET#Ignoring the portal...")
return
end
if not ret then if not ret then
self:change_level_check() self:change_level_check()
else self:break_portal()
end end
self.broken = true end, "Destroy", "Enter", false, "Quit")
self.name = "broken "..self.name
self.change_level = nil
self.autoexplore_ignore = true
end, "Destroy", "Enter")
return false return false
end end
...@@ -189,27 +207,35 @@ game.zone:addEntity(game.level, g, "terrain", x, y) ...@@ -189,27 +207,35 @@ game.zone:addEntity(game.level, g, "terrain", x, y)
local respawn = function(self) local respawn = function(self)
local portal = game.level.map(self.fearscape_portal_x, self.fearscape_portal_y, engine.Map.TERRAIN) 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 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 npcs = mod.class.NPC:loadList{"/data/general/npcs/major-demon.lua"}
local m = game.zone:makeEntity(game.level, "actor", {base_list=npcs}, nil, true) local m = game.zone:makeEntity(game.level, "actor", {base_list=npcs}, nil, true)
if not m then return end if not m then return end
m.fearscape_portal_x = self.fearscape_portal_x local adjacent = util.adjacentCoords(self.fearscape_portal_x, self.fearscape_portal_y)
m.fearscape_portal_y = self.fearscape_portal_y adjacent[5] = {self.fearscape_portal_x, self.fearscape_portal_y}
m.fearscape_respawn = self.fearscape_respawn
m.exp_worth = 0 repeat
m.no_drops = true local grid = rng.tableRemove(adjacent)
m.faction = "fearscape" if m:canMove(grid[1], grid[2]) then
m.on_die = function(self) self:fearscape_respawn() end m.fearscape_portal_x = self.fearscape_portal_x
game.zone:addEntity(game.level, m, "actor", i, j) m.fearscape_portal_y = self.fearscape_portal_y
game.logSeen(m, "#VIOLET#A demon steps out of the portal!") 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 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} local base = {fearscape_portal_x=x, fearscape_portal_y=y, fearscape_respawn=respawn}
respawn(base) respawn(base)
respawn(base) respawn(base)
return true return x, y
...@@ -21,5 +21,5 @@ return { ...@@ -21,5 +21,5 @@ return {
{name="tombstones", percent=10}, {name="tombstones", percent=10},
{name="old-battle-field", percent=5}, {name="old-battle-field", percent=5},
{name="thunderstorm", percent=7}, {name="thunderstorm", percent=7},
{name="rat-lich", percent=2}, {name="rat-lich", percent=2, unique=true},
} }
...@@ -18,16 +18,13 @@ ...@@ -18,16 +18,13 @@
-- darkgod@te4.org -- darkgod@te4.org
-- Find a random spot -- Find a random spot
local x, y = rng.range(1, level.map.w - 2), rng.range(1, level.map.h - 2) local x, y = game.state:findEventGrid(level)
local tries = 0 if not x then return false end
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 id = "naga-invasion-"..game.turn local id = "naga-invasion-"..game.turn
print("[EVENT] Placing event", id, "at", x, y)
local changer = function(id) local changer = function(id)
local npcs = mod.class.NPC:loadList{"/data/general/npcs/naga.lua"} local npcs = mod.class.NPC:loadList{"/data/general/npcs/naga.lua"}
local objects = mod.class.Object:loadList("/data/general/objects/objects.lua") local objects = mod.class.Object:loadList("/data/general/objects/objects.lua")
...@@ -36,30 +33,35 @@ local changer = function(id) ...@@ -36,30 +33,35 @@ local changer = function(id)
type = "floor", subtype = "underwater", type = "floor", subtype = "underwater",
display = "&", color = colors.BLUE, display = "&", color = colors.BLUE,
name = "coral invasion portal", name = "coral invasion portal",
name = "portal back to "..game.zone.name,
image = "terrain/underwater/subsea_floor_02.png", 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 = { 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_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_heavy_bright"}},
{name="naga_portal_smoke", rad=2, args={smoke="particles_images/smoke_dark"}}, {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_level_shift_back = true,
change_zone_auto_stairs = true, change_zone_auto_stairs = true,
} }
local zone = mod.class.Zone.new(id, { local zone = mod.class.Zone.new(id, {
name = "water cavern", 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", level_scheme = "player",
max_level = 1, max_level = 1,
actor_adjust_level = function(zone, level, e) return zone.base_level + e:getRankLevelAdjust() + level.level-1 + rng.range(-1,2) end, 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, width = 30, height = 30,
ambient_music = "Dark Secrets.ogg", ambient_music = "Dark Secrets.ogg",
reload_lists = false, reload_lists = false,
no_worldport = game.zone.no_worldport,
color_shown = {0.5, 1, 0.8, 1}, color_shown = {0.5, 1, 0.8, 1},
color_obscure = {0.5*0.6, 1*0.6, 0.8*0.6, 0.6}, color_obscure = {0.5*0.6, 1*0.6, 0.8*0.6, 0.6},
persistent = "zone", persistent = "zone",
min_material_level = game.zone.min_material_level, min_material_level = util.getval(game.zone.min_material_level),
max_material_level = game.zone.max_material_level, max_material_level = util.getval(game.zone.max_material_level),
effects = {"EFF_ZONE_AURA_UNDERWATER"}, effects = {"EFF_ZONE_AURA_UNDERWATER"},
generator = { generator = {
map = { map = {
...@@ -76,7 +78,10 @@ local changer = function(id) ...@@ -76,7 +78,10 @@ local changer = function(id)
actor = { actor = {
class = "mod.class.generator.actor.Random", class = "mod.class.generator.actor.Random",
nb_npc = {12, 12}, 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 = { object = {
class = "engine.generator.object.Random", class = "engine.generator.object.Random",
...@@ -89,7 +94,6 @@ local changer = function(id) ...@@ -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, 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, npc_list = npcs,
grid_list = terrains, grid_list = terrains,
object_list = objects, object_list = objects,
...@@ -100,7 +104,9 @@ end ...@@ -100,7 +104,9 @@ end
local g = game.level.map(x, y, engine.Map.TERRAIN):cloneFull() local g = game.level.map(x, y, engine.Map.TERRAIN):cloneFull()
g.name = "naga invasion coral portal" 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.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.change_level=1 g.change_zone=id g.glow=true
g:removeAllMOs() g:removeAllMOs()
if engine.Map.tiles.nicer_tiles then if engine.Map.tiles.nicer_tiles then
...@@ -116,30 +122,37 @@ g.grow = nil g.dig = nil ...@@ -116,30 +122,37 @@ g.grow = nil g.dig = nil
g:initGlow() g:initGlow()
g.special = true g.special = true
g.real_change = changer 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) 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: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 return true
end 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 not who or not who.player then return false end
if self.broken then if self.broken then
game.log("#VIOLET#The portal is already broken!") game.log("#VIOLET#The portal is already broken!")
return false return false
end end
require("engine.ui.Dialog"):yesnoPopup("Coral Portal", "Do you wish to enter the portal, destroy it, or ignore it (press escape)?", function(ret)
require("engine.ui.Dialog"):yesnoPopup("Coral Portal", "Do you wish to enter the portal or just destroy it?", function(ret) if ret == "Quit" then
game.log("#VIOLET#The portal is broken!") game.log("#VIOLET#Ignoring the portal...")
return
end
if not ret then if not ret then
self:change_level_check() self:change_level_check()
else self:break_portal()
end 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 return false
end end
...@@ -148,27 +161,35 @@ game.zone:addEntity(game.level, g, "terrain", x, y) ...@@ -148,27 +161,35 @@ game.zone:addEntity(game.level, g, "terrain", x, y)
local respawn = function(self) local respawn = function(self)
local portal = game.level.map(self.naga_portal_x, self.naga_portal_y, engine.Map.TERRAIN) 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 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 npcs = mod.class.NPC:loadList{"/data/general/npcs/naga.lua"}
local m = game.zone:makeEntity(game.level, "actor", {base_list=npcs}, nil, true) local m = game.zone:makeEntity(game.level, "actor", {base_list=npcs}, nil, true)
if not m then return end if not m then return end
m.naga_portal_x = self.naga_portal_x local adjacent = util.adjacentCoords(self.naga_portal_x, self.naga_portal_y)
m.naga_portal_y = self.naga_portal_y adjacent[5] = {self.naga_portal_x, self.naga_portal_y}
m.naga_respawn = self.naga_respawn
m.exp_worth = 0 repeat
m.no_drops = true local grid = rng.tableRemove(adjacent)
m.faction = "vargh-republic" if m:canMove(grid[1], grid[2]) then
m.on_die = function(self) self:naga_respawn() end m.naga_portal_x = self.naga_portal_x
game.zone:addEntity(game.level, m, "actor", i, j) m.naga_portal_y = self.naga_portal_y
game.logSeen(m, "#VIOLET#A naga steps out of the coral portal!") 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 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} local base = {naga_portal_x=x, naga_portal_y=y, naga_respawn=respawn}
respawn(base) respawn(base)
respawn(base) respawn(base)
return true return x, y
...@@ -42,9 +42,19 @@ if tries < 100 then ...@@ -42,9 +42,19 @@ if tries < 100 then
local terrains = mod.class.Grid:loadList("/data/general/grids/cave.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_level_shift_back = true
terrains.CAVE_LADDER_UP_WILDERNESS.change_zone_auto_stairs = 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, { local zone = mod.class.Zone.new(id, {
name = "Cavern beneath tombstones", 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", level_scheme = "player",
max_level = 1, max_level = 1,
actor_adjust_level = function(zone, level, e) return zone.base_level + e:getRankLevelAdjust() + level.level-1 + rng.range(-1,2) end, 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 ...@@ -52,8 +62,10 @@ if tries < 100 then
ambient_music = "Swashing the buck.ogg", ambient_music = "Swashing the buck.ogg",
reload_lists = false, reload_lists = false,
persistent = "zone", 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 = { generator = {
map = { map = {
class = "engine.generator.map.Static", class = "engine.generator.map.Static",
...@@ -110,11 +122,12 @@ if tries < 100 then ...@@ -110,11 +122,12 @@ if tries < 100 then
end end
local grids = check(x, y) local grids = check(x, y)
local graves = {}
for i = 1, 5 do for i = 1, 5 do
local p = rng.tableRemove(grids) local p = rng.tableRemove(grids)
local g = game.level.map(p.x, p.y, engine.Map.TERRAIN):cloneFull() 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.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.always_remember = true g.special_minimap = colors.OLIVE_DRAB
g:removeAllMOs() g:removeAllMOs()
...@@ -124,25 +137,14 @@ if tries < 100 then ...@@ -124,25 +137,14 @@ if tries < 100 then
end end
g.grow = nil g.dig = nil g.grow = nil g.dig = nil
g.special = true g.special = true
g.graves = graves
g:altered() g:altered()
g.block_move = function(self, x, y, who, act, couldpass) 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 not who or not who.player or not act then return false end
if game.level.event_battlefield_entered then return false end if game.level.event_battlefield_entered then return false end
who:runStop("grave") who:runStop("grave")
require("engine.ui.Dialog"):yesnoPopup("Grave", "Do you wish to disturb the grave?", function(ret) if ret then 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() 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) end end)
return false return false
end end
...@@ -150,14 +152,29 @@ if tries < 100 then ...@@ -150,14 +152,29 @@ if tries < 100 then
g.real_change = changer g.real_change = changer
g.change_level_check = function(self) g.change_level_check = function(self)
if game.level.event_battlefield_entered then return true end 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.level.event_battlefield_entered = true
game:changeLevel(1, self.real_change(self.change_zone), {temporary_zone_shift=true, direct_switch=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 return true
end end
print("[EVENT] Placing grave for event", id, "at", p.x, p.y)
game.zone:addEntity(game.level, g, "terrain", 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
end end
return true return x, y
\ No newline at end of file
...@@ -20,24 +20,27 @@ ...@@ -20,24 +20,27 @@
-- Unique -- Unique
if game.state:doneEvent(event_id) then return end if game.state:doneEvent(event_id) then return end
-- Find a random spot local x, y = game.state:findEventGrid(level)
local x, y = rng.range(1, level.map.w - 2), rng.range(1, level.map.h - 2) if not x then return false end
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 id = "rat-lich-"..game.turn local id = "rat-lich-"..game.turn
print("[EVENT] Placing event", id, "at", x, y)
local changer = function(id) local changer = function(id)
local npcs = mod.class.NPC:loadList{"/data/general/npcs/undead-rat.lua"} local npcs = mod.class.NPC:loadList{"/data/general/npcs/undead-rat.lua"}
local objects = mod.class.Object:loadList("/data/general/objects/objects.lua") local objects = mod.class.Object:loadList("/data/general/objects/objects.lua")
local terrains = mod.class.Grid:loadList("/data/general/grids/basic.lua") local terrains = mod.class.Grid:loadList("/data/general/grids/basic.lua")
terrains.UP_WILDERNESS.change_level_shift_back = true terrains.UP_WILDERNESS.change_level_shift_back = true
terrains.UP_WILDERNESS.change_zone_auto_stairs = 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{ objects.RATLICH_SKULL = mod.class.Object.new{
define_as = "RATLICH_SKULL", define_as = "RATLICH_SKULL",
power_source = {arcane=true}, power_source = {arcane=true},
...@@ -97,7 +100,9 @@ local changer = function(id) ...@@ -97,7 +100,9 @@ local changer = function(id)
local zone = mod.class.Zone.new(id, { local zone = mod.class.Zone.new(id, {
name = "Forsaken Crypt", 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", level_scheme = "player",
max_level = 1, max_level = 1,
actor_adjust_level = function(zone, level, e) return zone.base_level + e:getRankLevelAdjust() + level.level-1 + rng.range(-1,2) end, 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) ...@@ -105,8 +110,10 @@ local changer = function(id)
ambient_music = "Dark Secrets.ogg", ambient_music = "Dark Secrets.ogg",
reload_lists = false, reload_lists = false,
persistent = "zone", persistent = "zone",
min_material_level = game.zone.min_material_level, no_worldport = game.zone.no_worldport,
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),
generator = { generator = {
map = { map = {
class = "engine.generator.map.Roomer", class = "engine.generator.map.Roomer",
...@@ -142,7 +149,10 @@ local changer = function(id) ...@@ -142,7 +149,10 @@ local changer = function(id)
end end
local g = game.level.map(x, y, engine.Map.TERRAIN):cloneFull() 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.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.change_level=1 g.change_zone=id g.glow=true
g:removeAllMOs() g:removeAllMOs()
...@@ -157,7 +167,11 @@ g.change_level_check = function(self) ...@@ -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}) 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!") 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.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 return true
end end
game.zone:addEntity(game.level, g, "terrain", x, y) game.zone:addEntity(game.level, g, "terrain", x, y)
...@@ -172,4 +186,4 @@ for z = 1, 3 do ...@@ -172,4 +186,4 @@ for z = 1, 3 do
end end
end end
return true return x, y
...@@ -37,7 +37,7 @@ level.data.on_enter_list.sludgenest = function() ...@@ -37,7 +37,7 @@ level.data.on_enter_list.sludgenest = function()
g:initGlow() g:initGlow()
game.zone:addEntity(game.level, g, "terrain", spot.x, spot.y) game.zone:addEntity(game.level, g, "terrain", spot.x, spot.y)
print("[WORLDMAP] sludgenest at", 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 end
return true return true
...@@ -20,8 +20,8 @@ ...@@ -20,8 +20,8 @@
-- Find a random spot -- Find a random spot
local x, y = game.state:findEventGrid(level) local x, y = game.state:findEventGrid(level)
if not x then return false end if not x then return false end
print("placing sub-vault at", x, y)
local id = "sub-vault"..game.turn.."-"..rng.range(1,9999) local id = "sub-vault"..game.turn.."-"..rng.range(1,9999)
print("[EVENT] Placing event", id, "at", x, y)
local changer = function(id) local changer = function(id)
local grid_list = table.clone(game.zone.grid_list) local grid_list = table.clone(game.zone.grid_list)
...@@ -72,9 +72,9 @@ local changer = function(id) ...@@ -72,9 +72,9 @@ local changer = function(id)
ambient_music = game.zone.ambient_music, ambient_music = game.zone.ambient_music,
reload_lists = false, reload_lists = false,
persistent = "zone", persistent = "zone",
-- _max_level_generation_count = 2, -- _max_level_generation_count = 5,
min_material_level = game.zone.min_material_level, min_material_level = util.getval(game.zone.min_material_level),
max_material_level = game.zone.max_material_level, max_material_level = util.getval(game.zone.max_material_level),
no_worldport = game.zone.no_worldport, no_worldport = game.zone.no_worldport,
generator = { generator = {
map = table.merge(basemap, { map = table.merge(basemap, {
...@@ -110,9 +110,11 @@ end ...@@ -110,9 +110,11 @@ end
local g = game.level.map(x, y, engine.Map.TERRAIN):cloneFull() local g = game.level.map(x, y, engine.Map.TERRAIN):cloneFull()
g.name = "hidden vault" g.name = "hidden vault"
g.always_remember = true
g.desc = [[Crumbling stairs lead down to something.]] g.desc = [[Crumbling stairs lead down to something.]]
g.show_tooltip = true g.show_tooltip = true
g.display='>' g.color_r=0 g.color_g=0 g.color_b=255 g.notice = 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.change_level=1 g.change_zone=id g.glow=true
g:removeAllMOs() g:removeAllMOs()
if engine.Map.tiles.nicer_tiles then if engine.Map.tiles.nicer_tiles then
...@@ -124,19 +126,17 @@ g:altered() ...@@ -124,19 +126,17 @@ g:altered()
g:initGlow() g:initGlow()
g.real_change = changer g.real_change = changer
g.change_level_check = function(self) -- limit stair scumming 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._use_count = self._use_count - 1
self.name = "collapsing hidden vault" self.name = "collapsing hidden vault"
if self._use_count < 1 then if self._use_count < 1 then
self.change_level_check = nil self.change_level_check = nil
self.real_change = nil
self.change_level = nil self.change_level = nil
self.name = "collapsed hidden vault" self.name = "collapsed hidden vault"
self.desc = [[A collapsed stairway, leading down]] self.desc = [[A collapsed stairway, leading down]]
elseif self._use_count < 2 then elseif self._use_count < 2 then
self.name = "nearly collapsed hidden vault" self.name = "nearly collapsed hidden vault"
end end
self.special_minimap = colors.BLUE game:changeLevel(1, self.real_change(self.change_zone), {temporary_zone_shift=true, direct_switch=true})
return true return true
end end
game.zone:addEntity(game.level, g, "terrain", x, y) game.zone:addEntity(game.level, g, "terrain", x, y)
......
...@@ -22,5 +22,8 @@ return { one_per_level=true, ...@@ -22,5 +22,8 @@ return { one_per_level=true,
{name="protective-aura", minor=true, percent=50}, {name="protective-aura", minor=true, percent=50},
{name="necrotic-air", minor=true, percent=50}, {name="necrotic-air", minor=true, percent=50},
{name="glowing-chest", minor=true, percent=20}, {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)
}
} }
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
return { one_per_level=true, return { one_per_level=true,
{group="majeyal-generic", percent_factor=0.5}, {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="icy-ground", minor=true, percent=20},
{name="font-life", minor=true, percent=20}, {name="font-life", minor=true, percent=20},
{name="whistling-vortex", minor=true, percent=20}, {name="whistling-vortex", minor=true, percent=20},
...@@ -31,4 +31,12 @@ return { one_per_level=true, ...@@ -31,4 +31,12 @@ return { one_per_level=true,
{name="protective-aura", minor=true, percent=20}, {name="protective-aura", minor=true, percent=20},
{name="spellblaze-scar", minor=true, percent=20}, {name="spellblaze-scar", minor=true, percent=20},
{name="glowing-chest", minor=true, percent=30}, {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}},
} }
...@@ -17,7 +17,11 @@ ...@@ -17,7 +17,11 @@
-- Nicolas Casalini "DarkGod" -- Nicolas Casalini "DarkGod"
-- darkgod@te4.org -- darkgod@te4.org
local descriptor = table.get(game:getPlayer(true), "descriptor")
return { 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}, -- always spawn noxious-caldera for Yeeks (event file does additional tests)
{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}, {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)},
} }
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