From 69144ea802f2dcf951bccbe8bf6b682cbf5aa402 Mon Sep 17 00:00:00 2001
From: dg <dg@51575b47-30f0-44d4-a5cc-537603b46e54>
Date: Thu, 21 Apr 2011 22:49:59 +0000
Subject: [PATCH] The Shertul Fortress gains a new function: the exploratory
 farportal; a new subquest will trigger when it reaches enough energy

git-svn-id: http://svn.net-core.org/repos/t-engine4@3249 51575b47-30f0-44d4-a5cc-537603b46e54
---
 game/engines/default/engine/Zone.lua          |  2 +
 game/modules/tome/class/Game.lua              |  7 ++-
 game/modules/tome/class/GameState.lua         | 12 +++-
 .../modules/tome/data/achievements/quests.lua |  4 ++
 .../data/chats/shertul-fortress-butler.lua    | 10 +++
 .../tome/data/maps/zones/shertul-fortress.lua | 25 +++++---
 .../tome/data/quests/shertul-fortress.lua     | 44 +++++++++++++
 .../data/talents/psionic/psi-fighting.lua     |  2 +-
 .../data/zones/shertul-fortress/grids.lua     | 63 ++++++++++++++++++-
 tiled-maps/shertul-fortress.tmx               | 34 +++++++++-
 10 files changed, 185 insertions(+), 18 deletions(-)

diff --git a/game/engines/default/engine/Zone.lua b/game/engines/default/engine/Zone.lua
index c1f66a448a..00d887ec44 100644
--- a/game/engines/default/engine/Zone.lua
+++ b/game/engines/default/engine/Zone.lua
@@ -295,6 +295,8 @@ function _M:makeEntity(level, type, filter, force_level, prob_filter)
 
 	if filter then e.force_ego = filter.force_ego end
 
+	if filter and self.post_filter then e = util.getval(self.post_filter, self, level, type, e, filter) or e end
+
 	e = self:finishEntity(level, type, e, (filter and filter.ego_filter) or (filter and filter.ego_chance))
 	e.__forced_level = filter and filter.add_levels
 
diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua
index b5072383bd..00953681ad 100644
--- a/game/modules/tome/class/Game.lua
+++ b/game/modules/tome/class/Game.lua
@@ -337,6 +337,7 @@ function _M:loaded()
 	Zone.default_prob_filter = true
 	Zone.default_filter = function(...) return self.state:defaultEntityFilter(...) end
 	Zone.alter_filter = function(...) return self.state:entityFilterAlter(...) end
+	Zone.post_filter = function(...) return self.state:entityFilterPost(...) end
 	Map:setViewerActor(self.player)
 	self:setupDisplayMode(false, "init")
 	if self.player then self.player.changed = true end
@@ -916,9 +917,9 @@ function _M:setupCommands()
 			print(("	[ [[\n%d%d%d\n%d %d\n%d%d%d]] ] = '',"):format(g7,g8,g9,g4,g6,g1,g2,g3))
 		end end,
 		[{"_g","ctrl"}] = function() if config.settings.cheat then
---			self.nicer_tiles:postProcessLevelTiles(self.level)
---			game:registerDialog(require("mod.dialogs.Donation").new())
-			self.state:debugRandomZone()
+--			self.state:debugRandomZone()
+			local m = game.zone:makeEntity(game.level, "actor", {random_boss=true}, nil, true)
+			if m then game.zone:addEntity(game.level, m, "actor", game.player.x, game.player.y + 1) end
 		end end,
 	}
 
diff --git a/game/modules/tome/class/GameState.lua b/game/modules/tome/class/GameState.lua
index 75281a99b2..dc1dc57813 100644
--- a/game/modules/tome/class/GameState.lua
+++ b/game/modules/tome/class/GameState.lua
@@ -959,6 +959,16 @@ function _M:entityFilter(zone, e, filter, type)
 	end
 end
 
+function _M:entityFilterPost(zone, level, type, e, filter)
+	if type == "actor" then
+		if filter.random_boss then
+			e = self:createRandomBoss(e, zone:level_adjust_level(level, zone, type))
+		end
+	end
+
+	return e
+end
+
 --------------------------------------------------------------
 -- Random zones
 --------------------------------------------------------------
@@ -1196,7 +1206,7 @@ function _M:createRandomZone(zbase)
 		object_list = mod.class.Object:loadList("/data/general/objects/objects.lua"),
 		trap_list = mod.class.Trap:loadList("/data/general/traps/alarm.lua"),
 	})
-	return zone
+	return zone, boss
 end
 
 function _M:createRandomBoss(base, level)
diff --git a/game/modules/tome/data/achievements/quests.lua b/game/modules/tome/data/achievements/quests.lua
index 6f51530cb7..887d85eba1 100644
--- a/game/modules/tome/data/achievements/quests.lua
+++ b/game/modules/tome/data/achievements/quests.lua
@@ -191,3 +191,7 @@ newAchievement{
 	name = "Paradoxology", id = "PARADOX_FULL",
 	desc = [[Both killed your future self and got killed by your future self.]],
 }
+newAchievement{
+	name = "Explorer", id = "EXPLORER",
+	desc = [[Use the Sher'Tul fortress exploratory farportal at least 7 times with the same character.]],
+}
diff --git a/game/modules/tome/data/chats/shertul-fortress-butler.lua b/game/modules/tome/data/chats/shertul-fortress-butler.lua
index 78a337c62a..a54bd9b7c8 100644
--- a/game/modules/tome/data/chats/shertul-fortress-butler.lua
+++ b/game/modules/tome/data/chats/shertul-fortress-butler.lua
@@ -26,6 +26,7 @@ newChat{ id="welcome",
 	text = [[*#LIGHT_GREEN#The creature slowly turns to you. You hear its terrible voice directly in your head.#WHITE#*
 Welcome, master.]],
 	answers = {
+		{"You asked me to come, about a farportal?", jump="farportal", cond=function() return q:isCompleted("farportal") and not q:isCompleted("farportal-spawn") end},
 		{"What are you and what is this place?", jump="what", cond=isNotSet"what", action=set"what"},
 		{"Master? I am not your mas..", jump="master", cond=isNotSet"master", action=set"master"},
 		{"Why do I understand you, the texts are unreadable to me.", jump="understand", cond=isNotSet"understand", action=set"understand"},
@@ -101,4 +102,13 @@ There are however unwanted byproducts to this operation, the generation of a met
 	}
 }
 
+newChat{ id="farportal",
+	text = [[Long ago the Sher'tuls used farportals not only for transportation to know locations but also to explore new parts of the new world, or even other worlds.
+This Fortress is equiped with an exploratory farportal, and now has enough energy to allow one teleportation. Each teleportation will take you to a random part of the universe and use 30 energy.
+You maye use the farportal, however beware I sense a strange presence in the farportal room.]],
+	answers = {
+		{"I will check it out, thanks.", action=function() q:spawn_farportal_guardian() end},
+	}
+}
+
 return "welcome"
diff --git a/game/modules/tome/data/maps/zones/shertul-fortress.lua b/game/modules/tome/data/maps/zones/shertul-fortress.lua
index a209046792..e5a7a47649 100644
--- a/game/modules/tome/data/maps/zones/shertul-fortress.lua
+++ b/game/modules/tome/data/maps/zones/shertul-fortress.lua
@@ -26,8 +26,10 @@ stopy = 29
 
 -- defineTile section
 defineTile("#", "HARD_BIGWALL")
+defineTile("F", "CFARPORTAL")
 defineTile("h", "OLD_FLOOR", nil, "WEIRDLING_BEAST")
 defineTile("G", "GREEN_DRAPPING")
+defineTile("&", "FARPORTAL")
 defineTile("*", "TELEPORT_OUT")
 defineTile("<", "LAKE_NUR")
 defineTile("+", "SEALED_DOOR")
@@ -41,12 +43,15 @@ addSpot({11, 29}, "door", "weirdling")
 addSpot({17, 31}, "portal", "back")
 addSpot({1, 29}, "stair", "up")
 addSpot({17, 27}, "portal", "back")
-addSpot({24, 26}, "spawn", "butler")
+addSpot({23, 25}, "spawn", "butler")
+addSpot({36, 29}, "door", "farportal")
+addSpot({40, 29}, "spawn", "farportal")
 
 -- addZone section
 addZone({21, 23, 33, 35}, "zonename", "Control Room")
 addZone({16, 26, 18, 32}, "zonename", "Portal Room")
 addZone({13, 37, 23, 41}, "zonename", "Storage Room", {sort_drops=true,})
+addZone({38, 26, 44, 32}, "zonename", "Exploratory Farportal")
 addZone({15, 28, 19, 28}, "particle", "house_flamebeam")
 addZone({15, 30, 19, 30}, "particle", "house_flamebeam", {reverse=true,})
 addZone({27, 29, 28, 30}, "particle", "house_orbcontrol")
@@ -78,15 +83,15 @@ return [[
 ===========#################################################
 ===========##########...##...##...##########################
 ========..=##########.............##########################
-======....=######P###.............##########################
-=====.....=#####...##P...........G##########################
-====..==..=#####.*.###...........###########################
-=.........==####...##.............##########################
-=<.......h.+............... ......##########################
-====..==..==##.#...##.............##########################
-=====.....=###.#.*.###...........###########################
-======....=###.#...##G...........P##########################
-========..=###.##G###.............##########################
+======....=######P###.............#####P###G################
+=====.....=#####...##P...........G####.......###############
+====..==..=#####.*.###...........#####.......###############
+=.........==####...##.............####...&&&.###############
+=<.......h.+............... ........+....&F&.###############
+====..==..==##.#...##.............####...&&&.###############
+=====.....=###.#.*.###...........#####.......###############
+======....=###.#...##G...........P####.......###############
+========..=###.##G###.............#####P###G################
 ===========###.######.............##########################
 ===========###.######...##...##...##########################
 ===========###.############.################################
diff --git a/game/modules/tome/data/quests/shertul-fortress.lua b/game/modules/tome/data/quests/shertul-fortress.lua
index 371522da25..a978499944 100644
--- a/game/modules/tome/data/quests/shertul-fortress.lua
+++ b/game/modules/tome/data/quests/shertul-fortress.lua
@@ -31,6 +31,13 @@ desc = function(self, who)
 	if self:isCompleted("butler") then
 		desc[#desc+1] = "You have activated what seems to be a ... butler? with your rod of recall."
 	end
+	if self:isCompleted("farportal") then
+		if self:isCompleted("farportal-done") then
+			desc[#desc+1] = "You have entered the exploratory farportal room and defeated the horror lurking there, you can now use the farportal."
+		else
+			desc[#desc+1] = "The fortress shadow has asked that you come back as soon as possible."
+		end
+	end
 	if self.shertul_energy > 0 then
 		desc[#desc+1] = ("The Fortress current energy level is: %d."):format(self.shertul_energy)
 	end
@@ -39,6 +46,7 @@ end
 
 on_grant = function(self, who)
 	self.shertul_energy = 0
+	self.explored = 0
 end
 
 spawn_butler = function(self)
@@ -62,4 +70,40 @@ end
 
 gain_energy = function(self, energy)
 	self.shertul_energy = self.shertul_energy + energy
+
+	if self.shertul_energy >= 30 and not self:isCompleted("farportal") then
+		game.player:setQuestStatus(self.id, self.COMPLETED, "farportal")
+		local Dialog = require "engine.ui.Dialog"
+		Dialog:simpleLongPopup("Fortress Shadow", "Master, you have sent enough energy to activate the exploratory farportal.\nHowever there seems to be a disturbance in that room, please return as soon as possible.", 400)
+	end
+end
+
+exploratory_energy = function(self, check_only)
+	if self.shertul_energy < 30 then return false end
+	if not self:isCompleted("farportal-done") then return false end
+	if check_only then return true end
+
+	self.shertul_energy = self.shertul_energy - 30
+	self.explored = self.explored + 1
+	if self.explored == 7 then world:gainAchievement("EXPLORER", game.player) end
+	return true
+end
+
+spawn_farportal_guardian = function(self)
+	game.player:setQuestStatus("shertul-fortress", self.COMPLETED, "farportal-spawn")
+
+	-- Pop a random boss
+	local spot = game.level:pickSpot{type="spawn", subtype="farportal"}
+	local boss = game.zone:makeEntity(game.level, "actor", {type="horror", not_properties={"unique"}, random_boss=true}, nil, true)
+	boss.shertul_on_die = boss.on_die
+	boss.on_die = function(self, ...)
+		game.player:setQuestStatus("shertul-fortress", engine.Quest.COMPLETED, "farportal-done")
+		self:check("shertul_on_die", ...)
+	end
+	game.zone:addEntity(game.level, boss, "actor", spot.x, spot.y)
+
+	-- Open the door, destroy the stairs
+	local g = game.zone:makeEntityByName(game.level, "terrain", "OLD_FLOOR")
+	local spot = game.level:pickSpot{type="door", subtype="farportal"}
+	game.zone:addEntity(game.level, g, "terrain", spot.x, spot.y)
 end
diff --git a/game/modules/tome/data/talents/psionic/psi-fighting.lua b/game/modules/tome/data/talents/psionic/psi-fighting.lua
index 278ade32f7..07145e4c87 100644
--- a/game/modules/tome/data/talents/psionic/psi-fighting.lua
+++ b/game/modules/tome/data/talents/psionic/psi-fighting.lua
@@ -38,7 +38,7 @@ newTalent{
 	requires_target = true,
 	tactical = { ATTACK = 2 },
 	action = function(self, t)
-		local tkweapon = self:getInven("MAINHAND")[1]
+		local tkweapon = self:getInven("MAINHAND") and self:getInven("MAINHAND")[1]
 		if type(tkweapon) == "boolean" then tkweapon = nil end
 		if not tkweapon then
 			game.logPlayer(self, "You cannot do that without a weapon in your hands.")
diff --git a/game/modules/tome/data/zones/shertul-fortress/grids.lua b/game/modules/tome/data/zones/shertul-fortress/grids.lua
index 1342b8378d..99834011c2 100644
--- a/game/modules/tome/data/zones/shertul-fortress/grids.lua
+++ b/game/modules/tome/data/zones/shertul-fortress/grids.lua
@@ -38,7 +38,7 @@ newEntity{
 	does_block_move = true,
 }
 
-newEntity{ base = "BIGWALL",
+newEntity{ base = "HARDWALL",
 	define_as = "HARD_BIGWALL",
 	block_sense = true,
 	block_esp = true,
@@ -76,3 +76,64 @@ newEntity{ base = "HARD_BIGWALL",
 	define_as = "PURPLE_DRAPPING",
 	add_displays = {class.new{image="terrain/purple_drapping.png"}},
 }
+
+newEntity{
+	define_as = "FARPORTAL",
+	name = "Exploratory Farportal",
+	display = '&', color_r=255, color_g=0, color_b=220, back_color=colors.VIOLET, image = "terrain/maze_floor.png",
+	notice = true,
+	always_remember = true,
+	show_tooltip = true,
+	desc = [[A farportal is a way to travel incredible distances in the blink of an eye. They are left over of the powerful Sher'tul race.
+This farportal is not connected to any other portal, it is made for exploration, you can not know where it will send you.
+It should automatically create a portal back, but it might not be near your arrival zone.]],
+
+	on_move = function(self, x, y, who)
+		local Dialog = require "engine.ui.Dialog"
+		local q = who:hasQuest("shertul-fortress")
+		if not q then Dialog:simplePopup("Exploratory Farportal", "The farportal seems to be inactive") return end
+		if not q:exploratory_energy(true) then Dialog:simplePopup("Exploratory Farportal", "The fortress does not have enough energy to power a trip through the portal.") return end
+
+		Dialog:yesnoPopup("Exploratory Farportal", "Do you want to travel in the farportal? You can not know where you will end up.", function(ret) if ret then
+			local zone, boss = game.state:createRandomZone()
+			zone.no_worldport = true
+			boss.explo_portal_on_die = boss.on_die
+			boss.on_die = function(self, ...)
+				local x, y = self.x or game.player.x, self.y or game.player.y
+				local g = game.level.map(x, y, engine.Map.TERRAIN)
+				g = g:cloneFull()
+				g.show_tooltip = true
+				g.name = "Exploratory Farportal exit"
+				g.display = '&' g.color_r = colors.VIOLET.r g.color_g = colors.VIOLET.g g.color_b = colors.VIOLET.b
+				g.add_displays = g.add_displays or {}
+				g.add_displays[#g.add_displays+1] = mod.class.Grid.new{image="terrain/maze_teleport.png"}
+				g.notice = true
+				g.change_level = 1 g.change_zone = "shertul-fortress"
+				g._mo = nil
+				g:resolve() g:resolve(nil, true)
+				game.zone:addEntity(game.level, g, "terrain", x, y)
+				game.logSeen(self, "#VIOLET#As %s falls you notice a portal appearing.", self.name)
+
+				self:check("explo_portal_on_die", ...)
+				self.on_die = self.explo_portal_on_die
+				self.explo_portal_on_die = nil
+			end
+			game:changeLevel(1, zone)
+			q:exploratory_energy()
+			game.log("#VIOLET#You enter the swirling portal and in the blink of an eye you set foot in an unfamiliar zone, with no trace of the portal...")
+		end end)
+	end,
+}
+
+newEntity{ base = "FARPORTAL", define_as = "CFARPORTAL",
+	image = "terrain/maze_floor.png",
+	add_displays = {
+		class.new{image="terrain/farportal-base.png", display_x=-1, display_y=-1, display_w=3, display_h=3},
+	},
+	on_added = function(self, level, x, y)
+		level.map:particleEmitter(x, y, 3, "farportal_vortex")
+		level.map:particleEmitter(x, y, 3, "farportal_lightning")
+		level.map:particleEmitter(x, y, 3, "farportal_lightning")
+		level.map:particleEmitter(y, y, 3, "farportal_lightning")
+	end,
+}
diff --git a/tiled-maps/shertul-fortress.tmx b/tiled-maps/shertul-fortress.tmx
index f3d1f74c45..2375f0c646 100644
--- a/tiled-maps/shertul-fortress.tmx
+++ b/tiled-maps/shertul-fortress.tmx
@@ -34,13 +34,25 @@
   </tile>
  </tileset>
  <tileset firstgid="91" name="tome-terrains" tilewidth="32" tileheight="32">
-  <image source="gfx/tome-terrains.png" width="256" height="544"/>
+  <image source="gfx/tome-terrains.png" width="256" height="576"/>
   <tile id="1">
    <properties>
     <property name="display" value="#"/>
     <property name="value" value="&quot;HARD_BIGWALL&quot;"/>
    </properties>
   </tile>
+  <tile id="9">
+   <properties>
+    <property name="display" value="&amp;"/>
+    <property name="value" value="&quot;FARPORTAL&quot;"/>
+   </properties>
+  </tile>
+  <tile id="10">
+   <properties>
+    <property name="display" value="F"/>
+    <property name="value" value="&quot;CFARPORTAL&quot;"/>
+   </properties>
+  </tile>
   <tile id="27">
    <properties>
     <property name="display" value="G"/>
@@ -62,7 +74,7 @@
  </tileset>
  <layer name="Terrain" width="60" height="60">
   <data encoding="base64" compression="zlib">
-   eJzt1sENwyAMBVBuvXYYpC6REToHa2TC7lLlEAkhYozVgn/4h69KtJX8YjDZQgibMu8bRGulFzP00ksvbuill17c0EsvvbZEeuG9SXBJ6zuoNxaRvNJvUb09uYP37v1d7fy2ej/C5MXrIf/w1s6kdm2296zH6vU0myVvWY/kLWcNmrdWz5W3VvPeaU0TvblPs5+P716VHnns7enV1HQ1s1pzyJv5MDyVNT2MljMfJ17tfs77G7NPtP5a5lXuRTu/lvtI6m+q/F/KqHdnyduaz6XP2lsP+1nzPinVuLK3dw3RKz2HUa5feq37lF7/3t67ZuZdO7u/HkKvbj6jhl566cUNvfTSixt66aUXN/TSSy9uVvN+AbgwtF4=
+   eJzt1sENgzAMBVBuvXaYSF2CEXqkK7AGE3aXigNSFBnjuEnIh3/4qgRt8cPBYRyGYTTmfYFYrfRihl566cUNvfTSixt66aXXl0AvvHdWXNrxBdQbkmhe7buo3pxcwXv1/t7t+T3qfQtTL94eUsMrPZPWY2d7t3q83p5ms+ZN69G86awp5U3/d67klerZ80o1L5lWyVFrLWjr17Ke13MvoY5/e1vTa6lpb2YdzSGvOT43RSnhfRprejgtW77Oa6zOT0GvdT3H/Q3RJ1p/PfMq9qI9v579SOvvLPxei/Tu3Np7NJ9Tn7e3mqHV/mt5n9TucylvjdT25h5D9Gr3oZWrpNe7Tunt35u715w1l3robw+h1zafUUMvvfTihl566cUNvfTSixt66aUXN3fz/gBlv640
   </data>
  </layer>
  <objectgroup color="#ff0000" name="Actor" width="60" height="60">
@@ -104,6 +116,18 @@
     <property name="type" value="&quot;spawn&quot;"/>
    </properties>
   </object>
+  <object x="1160" y="932" width="19" height="23">
+   <properties>
+    <property name="subtype" value="&quot;farportal&quot;"/>
+    <property name="type" value="&quot;door&quot;"/>
+   </properties>
+  </object>
+  <object name="Farportal guardian" x="1285" y="929" width="19" height="23">
+   <properties>
+    <property name="subtype" value="&quot;farportal&quot;"/>
+    <property name="type" value="&quot;spawn&quot;"/>
+   </properties>
+  </object>
  </objectgroup>
  <objectgroup name="addZone#rooms" width="60" height="60" visible="0">
   <object name="control room" x="673" y="738" width="412" height="408">
@@ -125,6 +149,12 @@
     <property name="type" value="&quot;zonename&quot;"/>
    </properties>
   </object>
+  <object name="Farportal" x="1220" y="835" width="219" height="215">
+   <properties>
+    <property name="subtype" value="&quot;Exploratory Farportal&quot;"/>
+    <property name="type" value="&quot;zonename&quot;"/>
+   </properties>
+  </object>
  </objectgroup>
  <objectgroup color="#ff55ff" name="addZone#particles" width="60" height="60">
   <object name="flamewall" x="484" y="900" width="148" height="23">
-- 
GitLab