diff --git a/game/engines/default/engine/Entity.lua b/game/engines/default/engine/Entity.lua index 91696d1accbf8bcb34bcf3fd574da2e67bbf7b56..ddae7677c070036c8b8d83595e5f26be1527f877 100644 --- a/game/engines/default/engine/Entity.lua +++ b/game/engines/default/engine/Entity.lua @@ -385,7 +385,7 @@ function _M:loadList(file, no_default, res, mod, loaded) loaded = loaded or {} loaded[file] = true - setfenv(f, setmetatable({ + local newenv newenv = { class = self, loaded = loaded, resolvers = resolvers, @@ -416,7 +416,7 @@ function _M:loadList(file, no_default, res, mod, loaded) t.base = nil end - local e = self.new(t, no_default) + local e = newenv.class.new(t, no_default) if mod then mod(e) end @@ -429,7 +429,8 @@ function _M:loadList(file, no_default, res, mod, loaded) loadList = function(f, new_mod) return self:loadList(f, no_default, nil, new_mod or mod, loaded) end, - }, {__index=_G})) + } + setfenv(f, setmetatable(newenv, {__index=_G})) f() return res diff --git a/game/engines/default/engine/Zone.lua b/game/engines/default/engine/Zone.lua index 97ca512ce9ae63b04944aaff454f9ec1a53dd74a..ff0763d6fd1c5b7f71cbb968583d5941a7de7ebc 100644 --- a/game/engines/default/engine/Zone.lua +++ b/game/engines/default/engine/Zone.lua @@ -233,7 +233,7 @@ function _M:makeEntity(level, type, filter, force_level, prob_filter) if type == "actor" then base_list = self.npc_list elseif type == "object" then base_list = self.object_list elseif type == "trap" then base_list = self.trap_list - else return nil end + else base_list = level:getEntitiesList(type) if not base_list then return nil end end local list = self:computeRarities(type, base_list, level, function(e) return self:checkFilter(e, filter) end, filter.add_levels, filter.special_rarity) e = self:pickEntity(list) print("[MAKE ENTITY] prob list generation", e and e.name, "from list size", #list) diff --git a/game/engines/default/engine/generator/map/Static.lua b/game/engines/default/engine/generator/map/Static.lua index b68653e17eeabcd08ad23a8f28d115b0a75925b1..57ed5d5d22d846dcc468c90011ce57e8a58e0acc 100644 --- a/game/engines/default/engine/generator/map/Static.lua +++ b/game/engines/default/engine/generator/map/Static.lua @@ -64,6 +64,11 @@ function _M:loadMap(file) local list = require(class):loadList(file) self.level:setEntitiesList(type, list) end, + prepareEntitiesRaritiesList = function(type, class, file) + local list = require(class):loadList(file) + list = game.zone:computeRarities(type, list, game.level, nil) + self.level:setEntitiesList(type, list) + end, setStatusAll = function(s) self.status_all = s end, addData = function(t) table.merge(self.level.data, t, true) diff --git a/game/modules/tome/ai/worldnpcs.lua b/game/modules/tome/ai/worldnpcs.lua new file mode 100644 index 0000000000000000000000000000000000000000..5748d30ec735a4c3fec16aee2e274ee6b0fb4857 --- /dev/null +++ b/game/modules/tome/ai/worldnpcs.lua @@ -0,0 +1,113 @@ +-- 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 + +local Astar = require "engine.Astar" + +-- Find an hostile target on the worldmap +newAI("target_world", function(self) + if self.ai_target.actor and not self.ai_target.actor.dead and rng.percent(90) then return true end + + -- Find closer ennemy and target it + -- Get list of actors ordered by distance + local arr = self.fov.actors_dist + local act + local sqsense = self.sight or 4 + sqsense = sqsense * sqsense + for i = 1, #arr do + act = self.fov.actors_dist[i] +-- print("AI looking for target", self.uid, self.name, "::", act.uid, act.name, self.fov.actors[act].sqdist) + -- find the closest ennemy + if act and self:reactionToward(act) < 0 and not act.dead and + -- Otherwise check if we can see it with our "senses" + self.fov.actors[act].sqdist <= sqsense + then + + self.ai_target.actor = act + self:check("on_acquire_target", act) + act:check("on_targeted", self) + print("AI took for target", self.uid, self.name, "::", act.uid, act.name, self.fov.actors[act].sqdist, "<", sqsense) + return true + end + end +end) + +newAI("world_patrol", function(self) + if not self.energy.used then + if self:runAI("target_world") and self:reactionToward(self.ai_target.actor) < 0 then + self:runAI("move_dmap") + else + self:runAI("move_world_patrol") + end + end + return true +end) + +newAI("move_world_patrol", function(self) + if not self.ai_state.route then + self.ai_state.route = game.level:pickSpot{type="patrol", subtype=self.ai_state.route_kind} + else + local tx, ty = self.ai_state.route.x, self.ai_state.route.y + local a = Astar.new(game.level.map, self) + local path = self.ai_state.route_path + if not path then path = a:calc(self.x, self.y, tx, ty) end + if not path then + self.ai_state.route_path = nil self.ai_state.route = nil + return true + else + local ret = self:move(path[1].x, path[1].y) + table.remove(path, 1) + if #path == 0 then self.ai_state.route_path = nil self.ai_state.route = nil end + return ret + end + end +end) + +newAI("world_hostile", function(self) + if not self.energy.used then + if self:runAI("target_world") and self:reactionToward(self.ai_target.actor) < 0 and core.fov.distance(self.x, self.y, self.ai_target.actor.x, self.ai_target.actor.y) <= self.ai_state.chase_distance then + self:runAI("move_dmap") + else + self:runAI("move_world_hostile") + end + end + return true +end) + +newAI("move_world_hostile", function(self) + local tx, ty = self.ai_state.wander_x, self.ai_state.wander_y + if not tx or not ty then + local grids = core.fov.circle_grids(self.x, self.y, 4, true) + local gs = {} + for x, yy in pairs(grids) do for y, _ in pairs(yy) do + if not game.level.map:checkEntity(x, y, game.level.map.TERRAIN, "block_move") then + gs[#gs+1] = {x, y} + end + end end + local g = rng.table(gs) + self.ai_state.wander_x, self.ai_state.wander_y = g[1], g[2] + tx, ty = self.ai_state.wander_x, self.ai_state.wander_y + print("Hostile selected random wander", tx, ty) + end + + if tx and ty then + if (tx == self.x and ty == self.y) or rng.percent(10) then self.ai_state.wander_x, self.ai_state.wander_y = nil, nil return true end + self:moveDirection(tx, ty) + end + return true +end) diff --git a/game/modules/tome/class/GameState.lua b/game/modules/tome/class/GameState.lua index d7cfa0198d62e64189d0a5977ac566e09f1c017a..0bbc5262a5c543d49abec1f25718be5b3c528ee5 100644 --- a/game/modules/tome/class/GameState.lua +++ b/game/modules/tome/class/GameState.lua @@ -81,3 +81,22 @@ function _M:zoneCheckBackupGuardian() 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 diff --git a/game/modules/tome/class/Player.lua b/game/modules/tome/class/Player.lua index a66b31712a0cdbaa5d84fb9c6d2b47d6482b1f70..d967aaaf5acbb321edd7d6a754c886c0857591c8 100644 --- a/game/modules/tome/class/Player.lua +++ b/game/modules/tome/class/Player.lua @@ -120,6 +120,11 @@ function _M:onLeaveLevel(zone, level) end end +-- Wilderness encounter +function _M:onWorldEncounter(self) + print("PLAYER ENCOUNTER") +end + function _M:move(x, y, force) local moved = mod.class.Actor.move(self, x, y, force) if moved then @@ -151,6 +156,7 @@ function _M:move(x, y, force) self.wild_x, self.wild_y = self.x, self.y local g = game.level.map(self.x, self.y, Map.TERRAIN) + if g and g.can_encounter and game.level.data.encounters then local type = game.level.data.encounters.chance(self) if type then @@ -164,6 +170,8 @@ function _M:move(x, y, force) end end end + + game.state:worldDirectorAI() end return moved diff --git a/game/modules/tome/class/WorldNPC.lua b/game/modules/tome/class/WorldNPC.lua new file mode 100644 index 0000000000000000000000000000000000000000..c17da739ea0e7703728fcab0fd126116be70eb14 --- /dev/null +++ b/game/modules/tome/class/WorldNPC.lua @@ -0,0 +1,132 @@ +-- 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" +local ActorAI = require "engine.interface.ActorAI" +local Faction = require "engine.Faction" +local Emote = require("engine.Emote") +require "mod.class.Actor" + +module(..., package.seeall, class.inherit(mod.class.Actor, engine.interface.ActorAI)) + +function _M:init(t, no_default) + mod.class.Actor.init(self, t, no_default) + ActorAI.init(self, t) +end + +--- Checks what to do with the target +-- Talk ? attack ? displace ? +function _M:bumpInto(target) + local reaction = self:reactionToward(target) + if reaction < 0 then + return self:encounterAttack(target) + elseif reaction >= 0 then + -- Talk ? + if target.player and self.can_talk then + local chat = Chat.new(self.can_talk, self, target) + chat:invoke() + if self.can_talk_only_once then self.can_talk = nil end + elseif target.cant_be_moved and self.cant_be_moved then + -- Displace + local tx, ty, sx, sy = target.x, target.y, self.x, self.y + target.x = nil target.y = nil + self.x = nil self.y = nil + target:move(sx, sy, true) + self:move(tx, ty, true) + end + end +end + +function _M:encounterAttack(target) + if target.player then target:onWorldEncounter(self) return end + + self.unit_power = self.unit_power or 0 + target.unit_power = target.unit_power or 0 + + if self.unit_power > target.unit_power then + self.unit_power = self.unit_power - target.unit_power + target.unit_power = 0 + elseif self.unit_power < target.unit_power then + target.unit_power = target.unit_power - self.unit_power + self.unit_power = 0 + else + self.unit_power, target.unit_power = self.unit_power - target.unit_power, target.unit_power - self.unit_power + end + + if self.unit_power <= 0 then + game.logSeen(self, "%s kills %s.", target.name:capitalize(), self.name) + self:die(target) + end + if target.unit_power <= 0 then + game.logSeen(target, "%s kills %s.", self.name:capitalize(), target.name) + target:die(src) + end +end + +function _M:act() + while self:enoughEnergy() and not self.dead do + -- Do basic actor stuff + if not mod.class.Actor.act(self) then return end + + -- Compute FOV, if needed + self:doFOV() + + -- Let the AI think .... beware of Shub ! + -- If AI did nothing, use energy anyway + self:doAI() + + if not self.energy.used then self:useEnergy() end + end +end + +function _M:doFOV() + self:computeFOV(self.sight or 4, "block_sight", nil, nil, nil, true) +end + +function _M:tooltip(x, y, seen_by) + if seen_by and not seen_by:canSee(self) then return end + local factcolor, factstate, factlevel = "#ANTIQUE_WHITE#", "neutral", self:reactionToward(game.player) + if factlevel < 0 then factcolor, factstate = "#LIGHT_RED#", "hostile" + elseif factlevel > 0 then factcolor, factstate = "#LIGHT_GREEN#", "friendly" + end + + local rank, rank_color = self:TextRank() + + return ([[%s%s%s +%s / %s +Rank: %s%s +#00ffff#Level: %d +%s +Faction: %s%s (%s, %d) +Target: %s +UID: %d]]):format( + self:getDisplayString(), rank_color, self.name, + self.type:capitalize(), self.subtype:capitalize(), + rank_color, rank, + self.level, + self.desc or "", + factcolor, Faction.factions[self.faction].name, factstate, factlevel, + self.ai_target.actor and self.ai_target.actor.name or "none", + self.uid + ) +end + +function _M:die(src) + engine.interface.ActorLife.die(self, src) +end diff --git a/game/modules/tome/class/interface/Combat.lua b/game/modules/tome/class/interface/Combat.lua index 9d7a31b2b845e6f26bbfd4c736e0c56fbefffb29..ada0bb8ad60e305c3379590bb402219297e26603 100644 --- a/game/modules/tome/class/interface/Combat.lua +++ b/game/modules/tome/class/interface/Combat.lua @@ -43,7 +43,7 @@ function _M:bumpInto(target) local chat = Chat.new(self.can_talk, self, target) chat:invoke() if target.can_talk_only_once then target.can_talk = nil end - elseif self.move_others then + elseif self.move_others and not target.cant_be_moved then -- Displace local tx, ty, sx, sy = target.x, target.y, self.x, self.y target.x = nil target.y = nil diff --git a/game/modules/tome/data/birth/races/human.lua b/game/modules/tome/data/birth/races/human.lua index 5da4ed421114fe3c25e938cc8557edc20a29724d..1c08c222c1030f9c7dc7b5a142617b4325876c64 100644 --- a/game/modules/tome/data/birth/races/human.lua +++ b/game/modules/tome/data/birth/races/human.lua @@ -26,7 +26,7 @@ newBirthDescriptor{ desc = { "The humans are one of the main race on Maj'Eyal, along the halflings. For many thousands of years they fought each other until events, and great people, unified all the human and halfling nations under one rule.", "Humans of this Allied Kingdoms have know peace for over a century now.", - "Humans are split into two categories, the Highers and the rest. Highers have latent magic in their blood which gives them higher attributes and senses along with a longer life. + "Humans are split into two categories, the Highers and the rest. Highers have latent magic in their blood which gives them higher attributes and senses along with a longer life.", "The rest of humanity is gifted with quick learning nad mastery, they can do and become anything they desire.", }, descriptor_choices = diff --git a/game/modules/tome/data/general/encounters/arda-fareast.lua b/game/modules/tome/data/general/encounters/fareast.lua similarity index 100% rename from game/modules/tome/data/general/encounters/arda-fareast.lua rename to game/modules/tome/data/general/encounters/fareast.lua diff --git a/game/modules/tome/data/general/encounters/maj-eyal-npcs.lua b/game/modules/tome/data/general/encounters/maj-eyal-npcs.lua new file mode 100644 index 0000000000000000000000000000000000000000..26181b70b446d8e4328bd148b69e45a4a576642f --- /dev/null +++ b/game/modules/tome/data/general/encounters/maj-eyal-npcs.lua @@ -0,0 +1,119 @@ +-- 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 + +class = require("mod.class.WorldNPC") + +newEntity{ + name = "Allied Kingdoms human patrol", + type = "patrol", subtype = "allied kingdoms", cant_be_moved=true, + display = 'p', color = colors.LIGHT_UMBER, + faction = "allied-kingdoms", + level_range = {1, nil}, + sight = 4, + rarity = 3, + unit_power = 10, + ai = "world_patrol", ai_state = {route_kind="allied-kingdoms"}, +} + +newEntity{ + name = "Allied Kingdoms halfling patrol", + type = "patrol", subtype = "allied kingdoms", cant_be_moved=true, + display = 'p', color = colors.UMBER, + faction = "allied-kingdoms", + level_range = {1, nil}, + sight = 4, + rarity = 3, + unit_power = 10, + ai = "world_patrol", ai_state = {route_kind="allied-kingdoms"}, +} + +newEntity{ + name = "lone bear", + type = "hostile", subtype = "animal", cant_be_moved=true, + display = 'q', color = colors.UMBER, + level_range = {1, nil}, + sight = 3, + rarity = 4, + unit_power = 1, + ai = "world_hostile", ai_state = {chase_distance=3}, +} + +newEntity{ + name = "pack of wolves", + type = "hostile", subtype = "animal", cant_be_moved=true, + display = 'c', color = colors.RED, image="npc/canine_w.png", + level_range = {1, nil}, + sight = 3, + rarity = 4, + unit_power = 1, + ai = "world_hostile", ai_state = {chase_distance=3}, + on_encounter = function() + local gen = { class = "engine.generator.map.Forest", + edge_entrances = {4,6}, + sqrt_percent = 50, + zoom = 10, + floor = "GRASS", + wall = "TREE", + up = "UP", + down = "DOWN", + up = "UP_WILDERNESS_FAR_EAST", + } + local g = game.level.map(who.x, who.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 = {20, 50}, + 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 = 20, height = 20, + all_lited = true, + ambiant_music = "last", + generator = { + map = gen, + actor = { class = "engine.generator.actor.Random",nb_npc = {5, 7}, }, + trap = { class = "engine.generator.trap.Random", nb_trap = {0, 0}, }, + }, + + npc_list = mod.class.NPC:loadList("/data/general/npcs/orc.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 by a patrol of orcs!") + end, +} diff --git a/game/modules/tome/data/maps/wilderness/fareast.lua b/game/modules/tome/data/maps/wilderness/fareast.lua index 52a10a173a624a20dc3aa09567c7d9199a750950..a408ef2bfcf4a72bcff4cc76c473f03b9620f6fa 100644 --- a/game/modules/tome/data/maps/wilderness/fareast.lua +++ b/game/modules/tome/data/maps/wilderness/fareast.lua @@ -40,7 +40,7 @@ quickEntity('1', {always_remember = true, show_tooltip=true, name="Gates of Morn local p = getMap():particleEmitter(43, 25, 3, "istari_shield_map") -- Load encounters for this map -prepareEntitiesList("encounters", "mod.class.Encounter", "/data/general/encounters/arda-fareast.lua") +prepareEntitiesList("encounters", "mod.class.Encounter", "/data/general/encounters/fareast.lua") addData{ encounters = { chance=function(who) local harmless_chance = 1 + who:getLck(7) diff --git a/game/modules/tome/data/maps/wilderness/maj-eyal.lua b/game/modules/tome/data/maps/wilderness/maj-eyal.lua index 461a73a31c346ae221a503c455ae91b59c6f69fb..5552629d10047cc808d574f56fd3de2b1c71603b 100644 --- a/game/modules/tome/data/maps/wilderness/maj-eyal.lua +++ b/game/modules/tome/data/maps/wilderness/maj-eyal.lua @@ -68,16 +68,67 @@ end -- Load encounters for this map prepareEntitiesList("encounters", "mod.class.Encounter", "/data/general/encounters/maj-eyal.lua") -addData{ encounters = { - chance=function(who) - local harmless_chance = 1 + who:getLck(7) - local hostile_chance = 5 - if rng.percent(hostile_chance) then return "hostile" - elseif rng.percent(harmless_chance) then return "harmless" +prepareEntitiesList("encounters_npcs", "mod.class.WorldNPC", "/data/general/encounters/maj-eyal-npcs.lua") +addData{ + wda = { script="maj-eyal", }, + encounters = { + chance=function(who) + local harmless_chance = 1 + who:getLck(7) + local hostile_chance = 5 + if rng.percent(hostile_chance) then return "hostile" + elseif rng.percent(harmless_chance) then return "harmless" + end end - end} + }, } +-- addSpot section +addSpot({35, 33}, "patrol", "allied-kingdoms") +addSpot({23, 10}, "patrol", "allied-kingdoms") +addSpot({15, 33}, "patrol", "allied-kingdoms") +addSpot({40, 12}, "patrol", "allied-kingdoms") +addSpot({40, 13}, "patrol", "allied-kingdoms") +addSpot({63, 5}, "patrol", "allied-kingdoms") +addSpot({58, 32}, "patrol", "allied-kingdoms") +addSpot({22, 20}, "hostile", "random") +addSpot({23, 20}, "hostile", "random") +addSpot({24, 20}, "hostile", "random") +addSpot({22, 21}, "hostile", "random") +addSpot({23, 21}, "hostile", "random") +addSpot({24, 21}, "hostile", "random") +addSpot({22, 22}, "hostile", "random") +addSpot({23, 22}, "hostile", "random") +addSpot({24, 22}, "hostile", "random") +addSpot({54, 7}, "hostile", "random") +addSpot({55, 7}, "hostile", "random") +addSpot({56, 7}, "hostile", "random") +addSpot({54, 8}, "hostile", "random") +addSpot({55, 8}, "hostile", "random") +addSpot({56, 8}, "hostile", "random") +addSpot({54, 9}, "hostile", "random") +addSpot({55, 9}, "hostile", "random") +addSpot({56, 9}, "hostile", "random") +addSpot({43, 36}, "hostile", "random") +addSpot({44, 36}, "hostile", "random") +addSpot({45, 36}, "hostile", "random") +addSpot({43, 37}, "hostile", "random") +addSpot({44, 37}, "hostile", "random") +addSpot({45, 37}, "hostile", "random") +addSpot({43, 38}, "hostile", "random") +addSpot({44, 38}, "hostile", "random") +addSpot({45, 38}, "hostile", "random") +addSpot({8, 25}, "hostile", "random") +addSpot({9, 25}, "hostile", "random") +addSpot({10, 25}, "hostile", "random") +addSpot({8, 26}, "hostile", "random") +addSpot({9, 26}, "hostile", "random") +addSpot({10, 26}, "hostile", "random") +addSpot({8, 27}, "hostile", "random") +addSpot({9, 27}, "hostile", "random") +addSpot({10, 27}, "hostile", "random") +addSpot({35, 29}) + +-- ASCII map section return [[ ==========""""""""""""""""""""""""""""""""""""""""""""""""m########### ========""""""""""""""""""""""""""""""""""""""""""""""""mmm########### diff --git a/game/modules/tome/data/wda/maj-eyal.lua b/game/modules/tome/data/wda/maj-eyal.lua new file mode 100644 index 0000000000000000000000000000000000000000..e3366b169ee447a3d09b4707d88defa593257154 --- /dev/null +++ b/game/modules/tome/data/wda/maj-eyal.lua @@ -0,0 +1,47 @@ +-- 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 + +-- Maj'Eyal world map directory AI + +wda.cur_patrols = wda.cur_patrols or 0 +wda.cur_hostiles = wda.cur_hostiles or 0 + +-- Spawn some patrols +if wda.cur_patrols < 3 then + local e = game.zone:makeEntity(game.level, "encounters_npcs", {type="patrol"}, nil, true) + if e then + local spot = game.level:pickSpot{type="patrol", "allied-kingdoms"} + print("Spawned allied kingdom patrol", spot.x, spot.y, e.name) + game.zone:addEntity(game.level, e, "actor", spot.x, spot.y) + wda.cur_patrols = wda.cur_patrols + 1 + e.on_die = function() game.level.data.wda.cur_patrols = game.level.data.wda.cur_patrols - 1 end + end +end + +-- Spawn some hostiles +if wda.cur_hostiles < 1 and rng.percent(5) then + local e = game.zone:makeEntity(game.level, "encounters_npcs", {type="hostile"}, nil, true) + if e then + local spot = game.level:pickSpot{type="hostile", "random"} + print("Spawned hostile", spot.x, spot.y, e.name) + game.zone:addEntity(game.level, e, "actor", spot.x, spot.y) + wda.cur_hostiles = wda.cur_hostiles + 1 + e.on_die = function() game.level.data.wda.cur_hostiles = game.level.data.wda.cur_hostiles - 1 end + end +end