diff --git a/game/engines/default/engine/generator/map/Octopus.lua b/game/engines/default/engine/generator/map/Octopus.lua index 963c9c179362169d76743c3ba9a12999dbc6fc61..17d1d05d78016e0691547bdd689072181fdb61de 100644 --- a/game/engines/default/engine/generator/map/Octopus.lua +++ b/game/engines/default/engine/generator/map/Octopus.lua @@ -24,16 +24,17 @@ require "engine.generator.map.Roomer" --- @classmod engine.generator.map.Octopus module(..., package.seeall, class.inherit(engine.generator.map.Roomer)) +-- Creates a space (Pod room) at center of map, with a number of 'arms' (Pod rooms) around it connected by tunnels function _M:init(zone, map, level, data) engine.generator.map.Roomer.init(self, zone, map, level, data) self.spots = {} - self.nb_rooms = data.nb_rooms or {5, 10} + self.nb_rooms = data.nb_rooms or {5, 10} -- number of Pod rooms around center self.base_breakpoint = data.base_breakpoint or 0.4 - self.arms_range = data.arms_range or {0.5, 0.7} - self.arms_radius = data.arms_radius or {0.2, 0.3} - self.main_radius = data.main_radius or {0.3, 0.5} + self.arms_range = data.arms_range or {0.5, 0.7} -- fraction dist from map center to map edge for each Pod room + self.arms_radius = data.arms_radius or {0.2, 0.3} -- *(map.w + map.h)/4 ==> radius of each Pod room + self.main_radius = data.main_radius or {0.3, 0.5} -- *(map.w + map.h)/4 ==> radius of Pod at map center self.noise = data.noise or "fbm_perlin" self.zoom = data.zoom or 5 @@ -48,15 +49,16 @@ function _M:generate(lev, old_lev) end end local spots = self.spots - + local rooms = {} + self.map.room_map.rooms = rooms -- Main center room local cx, cy = math.floor(self.map.w / 2), math.floor(self.map.h / 2) - self:makePod(cx, cy, rng.float(self.main_radius[1], self.main_radius[2]) * ((self.map.w / 2) + (self.map.h / 2)) / 2, 1, self) + rooms[#rooms+1] = self:makePod(cx, cy, rng.float(self.main_radius[1], self.main_radius[2]) * ((self.map.w / 2) + (self.map.h / 2)) / 2, 1, self) + spots[#spots+1] = {x=cx, y=cy, type="room", subtype="main"} -- Rooms around it local nb_rooms = rng.range(self.nb_rooms[1], self.nb_rooms[2]) - local rooms = {} for i = 0, nb_rooms - 1 do local angle = math.rad(i * 360 / nb_rooms) diff --git a/game/modules/tome/class/GameState.lua b/game/modules/tome/class/GameState.lua index 742f2a88db3c1702758e897c99f46c4dac494964..605305f2e0a42b3851484166407a7a11c3cbdaea 100644 --- a/game/modules/tome/class/GameState.lua +++ b/game/modules/tome/class/GameState.lua @@ -2609,7 +2609,7 @@ function _M:infiniteDungeonChallengeFinish(zone, level) end, on_grant = function(self, who) game:onTickEnd(function() - -- mark enemies when quest is awarded (to prevent summons and any newly spawned npcs from t preventing completion) + -- mark enemies when quest is awarded (to prevent summons and any newly spawned npcs from preventing completion) for uid, e in pairs(self.check_level.entities) do if who:reactionToward(e) < 0 then e[self.id] = true @@ -2672,14 +2672,17 @@ function _M:infiniteDungeonChallengeFinish(zone, level) end end elseif id_challenge == "mirror-match" then - local x, y = rng.range(1, level.map.w - 2), rng.range(1, level.map.h - 2) - local tries = 0 - while not game.player:canMove(x, y) and tries < 100 and not level.map.attrs(x, y, "no_teleport") 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 - local q = self:makeChallengeQuest(level, "Mirror Match", "Find, challenge and kill your mirror clone on the level.", {}) + local x, y = self:findEventGrid(level, function(self, level, x, y) + if x > 10 and x < level.map.w-10 and y > 10 and y < level.map.h and self:canEventGrid(level, x, y)then return x, y end + end + ) + if x and y then + print("[Infinite Dungeon Challenge] spawning Mirror-Match at", x, y) + local q = self:makeChallengeQuest(level, "Mirror Match", "Find, challenge, and kill your mirror clone on the level.", { + on_exit_check = function(self, who) + if not self:isEnded() then who:setQuestStatus(self.id, self.FAILED) end + end, + }) local a = mod.class.NPC.new{} a:replaceWith(game:getPlayer(true):cloneFull()) @@ -2690,6 +2693,7 @@ function _M:infiniteDungeonChallengeFinish(zone, level) a.energy.value = 0 a.player = nil a.rank = 4 + a.desc = "An evil twin of "..a.name..(a.desc and ":\n"..a.desc or "") a.name = "Mirror Challenge of "..a.name a.killer_message = "but nobody knew why #sex# suddenly became evil" a.color_r = 150 a.color_g = 150 a.color_b = 150 @@ -2702,13 +2706,26 @@ function _M:infiniteDungeonChallengeFinish(zone, level) a.max_life = a.max_life * 2 a.life = a.max_life a.id_challenge_quest = q.id - a.invulnerable = 1 + a:attr("stealth", -1000) + a:attr("invisible", -1000) + a:attr("invulnerable", 1) + a:attr("negative_status_effect_immune", 1) a.on_bump = function(self, who) - Dialog:yesnoPopup("Challenge: #PURPLE#Mirror Match", "Challenge your mirror clone and triumph!", function(r) if not r then - self.invulnerable = nil + local p = game:getPlayer(true) + if who ~= p then + game.logPlayer(who, "#ORCHID#%s does not recognize you.", self.name:capitalize()) + return + end + require("engine.ui.Dialog"):yesnoPopup("Challenge: #PURPLE#Mirror Match", "Challenge your mirror clone and triumph!", function(r) if not r then + self:attr("invulnerable", -1) + self:attr("negative_status_effect_immune", -1) + self:attr("stealth", 1000) + self:attr("invisible", 1000) self.faction = "enemies" self.ai = "tactical" - game.bignews:say(60, "#CRIMSON#FIGHT!") + self:setTarget(p) + self:teleportRandom(p.x, p.y, 20, 10) + game.bignews:say(60, "#CRIMSON#The Fight Is Joined!") end end, "Refuse", "Accept", true) end a.on_die = function(self, who) @@ -2716,7 +2733,6 @@ function _M:infiniteDungeonChallengeFinish(zone, level) end game.zone:addEntity(game.level, a, "actor", x, y) - -- Remove some talents local tids = {} for tid, _ in pairs(a.talents) do @@ -2744,9 +2760,23 @@ function _M:infiniteDungeonChallengeFinish(zone, level) end end, "Refuse", "Accept", true) elseif id_challenge == "multiplicity" then - Dialog:yesnoPopup("Challenge: #PURPLE#Multiplicity", "Survive the level while all the foes have the multiply talent, even bosses, for a reward.", function(r) if not r then + local turns = level.map.h + level.map.w + Dialog:yesnoPopup("Challenge: #PURPLE#Multiplicity", "All foes (including bosses) gain the ability to multiply up to 3 times. You must survive for at least "..turns.." turns before exiting.", function(r) if not r then self:makeChallengeQuest(level, "Multiplicity", "All foes have the multiply talent!", { - on_exit_check = function(self, who) who:setQuestStatus(self.id, self.COMPLETED) end, + turns_left = turns, + dynamic_desc = function(self, desc) + desc[#desc+1] = "Turns left: #LIGHT_GREEN#"..math.max(0, self.turns_left) + end, + on_exit_check = function(self, who) + if who.dead and not self:isEnded() then who:setQuestStatus(self.id, self.FAILED); return end + if self.turns_left <= 0 and not who.dead then who:setQuestStatus(self.id, self.COMPLETED) else who:setQuestStatus(self.id, self.FAILED) end + end, + on_act_base = function(self, who) + self.turns_left = self.turns_left - 1 + if self.turns_left == 0 then + game.bignews:say(60, "#LIGHT_GREEN#Multiplicity: You have survived so far. Exit for your reward!") + end + end, }) game:onTickEnd(function() local p = game:getPlayer(true) diff --git a/game/modules/tome/class/Grid.lua b/game/modules/tome/class/Grid.lua index 120dbae2b9265c54758b339c6f47009d761f4c87..02d12cb0cd47bbfd70000a7349f7794938391608 100644 --- a/game/modules/tome/class/Grid.lua +++ b/game/modules/tome/class/Grid.lua @@ -222,8 +222,9 @@ function _M:tooltip(x, y) -- debugging info if game.level.map.room_map then local data = game.level.map.room_map[x][y] - local room = table.get(game.level.map.room_map.rooms, data.room, "room") - tstr:add(true, {"color", "PINK"}, ("room_map: rm:%s(%s), spec:%s, c/o:%s, bor:%s, tun:%s, rtun:%s"):format(data.room, room and room.name, data.special, data.can_open, data.border, data.tunnel, data.real_tunnel)) + local room_base = table.get(game.level.map.room_map.rooms, data.room) + local room = room_base and room_base.room + tstr:add(true, {"color", "PINK"}, ("room_map:rm:%s(id:%s,name:%s), spec:%s, c/o:%s, bor:%s, tun:%s, rtun:%s"):format(data.room, room_base and room_base.id, room and room.name, data.special, data.can_open, data.border, data.tunnel, data.real_tunnel)) end local attrs = game.level.map.attrs[x+y*game.level.map.w] if attrs then diff --git a/game/modules/tome/data/talents/misc/npcs.lua b/game/modules/tome/data/talents/misc/npcs.lua index 09b71e1e5e1f6759294c4705967f60dff184ab34..ff99a4ac2e0960f45a1883b605400cf357f8dd44 100644 --- a/game/modules/tome/data/talents/misc/npcs.lua +++ b/game/modules/tome/data/talents/misc/npcs.lua @@ -40,7 +40,7 @@ newTalent{ cooldown = 3, range = 10, requires_target = true, - tactical = { ATTACK = 3 }, + tactical = { ATTACK = function(self, t, aitarget) return 2*(1.2 + self.level/50) end }, action = function(self, t) if not self.can_multiply or self.can_multiply <= 0 then game.logPlayer(self, "You can not multiply anymore.") return nil end diff --git a/game/modules/tome/data/zones/infinite-dungeon/zone.lua b/game/modules/tome/data/zones/infinite-dungeon/zone.lua index b440164fa59985a7dce2901495887f7f6405ccbf..62448f25d337b63daa7a7638516748ad4624c818 100644 --- a/game/modules/tome/data/zones/infinite-dungeon/zone.lua +++ b/game/modules/tome/data/zones/infinite-dungeon/zone.lua @@ -164,10 +164,10 @@ return { { id_layout_name = "octopus", desc = ", subsided area", class = "engine.generator.map.Octopus", - main_radius = {0.3, 0.4}, + main_radius = {0.25, 0.35}, arms_radius = {0.1, 0.2}, arms_range = {0.7, 0.8}, - nb_rooms = {3, 9}, + nb_rooms = {5, 10}, }, { id_layout_name = "hexa", desc = ", geometrically ordered area",