Skip to content
Snippets Groups Projects
GameState.lua 5.43 KiB
Newer Older
  • Learn to ignore specific revisions
  • dg's avatar
    dg committed
    -- ToME - Tales of Maj'Eyal
    
    -- Copyright (C) 2009, 2010 Nicolas Casalini
    --
    -- This program is free software: you can redistribute it and/or modify
    -- it under the terms of the GNU General Public License as published by
    -- the Free Software Foundation, either version 3 of the License, or
    -- (at your option) any later version.
    --
    -- This program is distributed in the hope that it will be useful,
    -- but WITHOUT ANY WARRANTY; without even the implied warranty of
    -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    -- GNU General Public License for more details.
    --
    -- You should have received a copy of the GNU General Public License
    -- along with this program.  If not, see <http://www.gnu.org/licenses/>.
    --
    -- Nicolas Casalini "DarkGod"
    -- darkgod@te4.org
    
    require "engine.class"
    require "engine.Entity"
    
    module(..., package.seeall, class.inherit(engine.Entity))
    
    function _M:init(t, no_default)
    	engine.Entity.init(self, t, no_default)
    
    	self.allow_backup_guardians = {}
    end
    
    function _M:goneEast()
    	self.gone_east = true
    end
    
    
    function _M:activateBackupGuardian(guardian, on_level, zonelevel, rumor, action)
    
    	if self.gone_east then return end
    	print("Zone guardian dead, setting up backup guardian", guardian, zonelevel)
    	self.allow_backup_guardians[game.zone.short_name] =
    	{
    		name = game.zone.name,
    		guardian = guardian,
    		on_level = on_level,
    		new_level = zonelevel,
    		rumor = rumor,
    
    		action = action,
    
    	}
    end
    
    function _M:zoneCheckBackupGuardian()
    	if not self.gone_east then print("Not gone east, no backup guardian") return end
    
    	-- Adjust level of the zone
    	if self.allow_backup_guardians[game.zone.short_name] then
    		local data = self.allow_backup_guardians[game.zone.short_name]
    		game.zone.base_level = data.new_level
    
    		if data.action then data.action(false) end
    
    	end
    
    	-- Spawn the new guardian
    	if self.allow_backup_guardians[game.zone.short_name] and self.allow_backup_guardians[game.zone.short_name].on_level == game.level.level then
    		local data = self.allow_backup_guardians[game.zone.short_name]
    
    		-- Place the guardian, we do not check for connectivity, vault or whatever, the player is suppoed to be strong enough to get there
    		local m = game.zone:makeEntityByName(game.level, "actor", data.guardian)
    		if m then
    			local x, y = rng.range(0, game.level.map.w - 1), rng.range(0, game.level.map.h - 1)
    			local tries = 0
    			while not m:canMove(x, y) and tries < 100 do
    				x, y = rng.range(0, game.level.map.w - 1), rng.range(0, game.level.map.h - 1)
    				tries = tries + 1
    			end
    			if tries < 100 then
    				game.zone:addEntity(game.level, m, "actor", x, y)
    				print("Backup Guardian allocated: ", data.guardian, m.uid, m.name)
    			end
    		else
    			print("WARNING: Backup Guardian not found: ", data.guardian)
    		end
    
    
    		if data.action then data.action(true) end
    
    		self.allow_backup_guardians[game.zone.short_name] = nil
    	end
    end
    
    
    local wda_cache = {}
    
    --- Runs the worldmap directory AI
    function _M:worldDirectorAI()
    	if not game.level.data.wda or not game.level.data.wda.script then return end
    	local script = wda_cache[game.level.data.wda.script]
    	if not script then
    		local f, err = loadfile("/data/wda/"..game.level.data.wda.script..".lua")
    		if not f then error(err) end
    		wda_cache[game.level.data.wda.script] = f
    		script = f
    	end
    
    	game.level.level = game.player.level
    	setfenv(script, setmetatable({wda=game.level.data.wda}, {__index=_G}))
    	local ok, err = pcall(script)
    	if not ok and err then error(err) end
    end
    
    dg's avatar
    dg committed
    
    function _M:spawnWorldAmbush(enc)
    	local gen = { class = "engine.generator.map.Forest",
    		edge_entrances = {4,6},
    		sqrt_percent = 50,
    		zoom = 10,
    		floor = "GRASS",
    		wall = "TREE",
    		down = "DOWN",
    		up = "UP_WILDERNESS",
    	}
    	local g = game.level.map(game.player.x, game.player.y, engine.Map.TERRAIN)
    	if not g.can_encounter then return false end
    
    	if g.can_encounter == "desert" then gen.floor = "SAND" gen.wall = "PALMTREE" end
    
    	local zone = engine.Zone.new("ambush", {
    		name = "Ambush!",
    		level_range = {game.player.level, game.player.level},
    		level_scheme = "player",
    		max_level = 1,
    		actor_adjust_level = function(zone, level, e) return zone.base_level + e:getRankLevelAdjust() + level.level-1 + rng.range(-1,2) end,
    		width = enc.width or 20, height = enc.height or 20,
    		all_lited = true,
    		ambiant_music = "last",
    		generator =  {
    			map = gen,
    			actor = { class = "engine.generator.actor.Random", nb_npc = enc.nb or {1,1}, filters=enc.filters },
    		},
    
    		npc_list = mod.class.NPC:loadList("/data/general/npcs/all.lua", nil, nil, function(e) e.make_escort=nil end),
    		grid_list = mod.class.Grid:loadList{"/data/general/grids/basic.lua", "/data/general/grids/forest.lua", "/data/general/grids/sand.lua"},
    		object_list = mod.class.Object:loadList("/data/general/objects/objects.lua"),
    		trap_list = {},
    		post_process = function(level)
    			-- Find a good starting location, on the opposite side of the exit
    			local sx, sy = level.map.w-1, rng.range(0, level.map.h-1)
    			level.spots[#level.spots+1] = {
    				check_connectivity = "entrance",
    				x = sx,
    				y = sy,
    			}
    			level.default_down = level.default_up
    			level.default_up = {x=sx, y=sy}
    		end,
    	})
    	game.player:runStop()
    	game.player.energy.value = game.energy_to_act
    	game.paused = true
    	game:changeLevel(1, zone)
    	engine.ui.Dialog:simplePopup("Ambush!", "You have been ambushed!")
    end
    
    function _M:handleWorldEncounter(target)
    	local enc = target.on_encounter
    	if type(enc) == "function" then return enc() end
    	if type(enc) == "table" then
    		if enc.type == "ambush" then target:die() self:spawnWorldAmbush(enc)
    		end
    	end
    end