From 6e8ee7bfcef43660209dc873ca8184b61966595d Mon Sep 17 00:00:00 2001 From: dg <dg@51575b47-30f0-44d4-a5cc-537603b46e54> Date: Fri, 22 Apr 2011 20:01:05 +0000 Subject: [PATCH] Random parties of (hostile) adventurers can be met on the worldmap git-svn-id: http://svn.net-core.org/repos/t-engine4@3261 51575b47-30f0-44d4-a5cc-537603b46e54 --- game/modules/tome/class/Actor.lua | 2 +- game/modules/tome/class/GameState.lua | 46 ++++++++----- .../data/general/encounters/maj-eyal-npcs.lua | 25 +++++++ game/modules/tome/data/general/npcs/all.lua | 2 + .../general/npcs/humanoid_random_boss.lua | 66 +++++++++++++++++++ 5 files changed, 125 insertions(+), 16 deletions(-) create mode 100644 game/modules/tome/data/general/npcs/humanoid_random_boss.lua diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua index bcde5b5b8c..cd435792f0 100644 --- a/game/modules/tome/class/Actor.lua +++ b/game/modules/tome/class/Actor.lua @@ -1351,7 +1351,7 @@ function _M:die(src) if src and src.attr and src:attr("vim_on_death") and not self:attr("undead") then src:incVim(src:attr("vim_on_death")) end if src and src.last_vim_turn and src.last_vim_turn >= game.turn - 30 then src:incVim(src.last_vim_spent) src.last_vim_turn = nil end - if src and src.resolveSource and src:resolveSource().player or src.player then + if src and ((src.resolveSource and src:resolveSource().player) or src.player) then -- Achievements local p = game.party:findMember{main=true} if math.floor(p.life) <= 1 and not p.dead then world:gainAchievement("THAT_WAS_CLOSE", p) end diff --git a/game/modules/tome/class/GameState.lua b/game/modules/tome/class/GameState.lua index 1787940cf9..0ff38d328d 100644 --- a/game/modules/tome/class/GameState.lua +++ b/game/modules/tome/class/GameState.lua @@ -962,7 +962,10 @@ 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)) + if _G.type(filter.random_boss) == "boolean" then filter.random_boss = {} + else filter.random_boss = table.clone(filter.random_boss, true) end + filter.random_boss.level = filter.random_boss.level or zone:level_adjust_level(level, zone, type) + e = self:createRandomBoss(e, filter.random_boss) end end @@ -1209,7 +1212,7 @@ function _M:createRandomZone(zbase) return zone, boss end -function _M:createRandomBoss(base, level) +function _M:createRandomBoss(base, data) local b = base:clone() ------------------------------------------------------------ @@ -1221,10 +1224,14 @@ function _M:createRandomBoss(base, level) b.unique = b.name local boss_id = "RND_BOSS_"..b.name:upper():gsub("[^A-Z]", "_") b.color = colors.VIOLET - b.rank = rng.percent(30) and 4 or 3.5 - b.level_range[1] = level + b.rank = data.rank or (rng.percent(30) and 4 or 3.5) + b.level_range[1] = data.level b.fixed_rating = true - b.life_rating = b.life_rating * 1.7 + rng.range(4, 9) + if data.life_rating then + b.life_rating = data.life_rating(b.life_rating) + else + b.life_rating = b.life_rating * 1.7 + rng.range(4, 9) + end b.max_life = b.max_life or 150 -- Force resolving some stuff @@ -1255,8 +1262,8 @@ function _M:createRandomBoss(base, level) for _, k in ipairs(todel) do b[k] = nil end -- Boss worthy drops - b[#b+1] = resolvers.drops{chance=100, nb=3, {tome_drops="boss"} } - b[#b+1] = resolvers.drop_randart{} + b[#b+1] = resolvers.drops{chance=100, nb=data.loot_quantity or 3, {tome_drops=data.loot_quality or "boss"} } + if not data.no_loot_randart then b[#b+1] = resolvers.drop_randart{} end ------------------------------------------------------------ -- Apply talents from classes @@ -1286,7 +1293,7 @@ function _M:createRandomBoss(base, level) for i, d in ipairs(resolver[1]) do d.name = nil d.ego_chance = nil - d.tome_drops = "boss" + d.tome_drops = data.loot_quality or "boss" d.force_drop = true end b[#b+1] = resolver @@ -1304,14 +1311,14 @@ function _M:createRandomBoss(base, level) if not t.no_npc_use then local max = (t.points == 1) and 1 or math.ceil(t.points * 1.6) local step = max / 50 - tres[1][tid] = v + math.ceil(step * level) + tres[1][tid] = v + math.ceil(step * data.level) end end -- Select additional talents from the class local list = {} for _, t in pairs(b.talents_def) do if b.talents_types[t.type[1]] and not t.no_npc_use then list[t.id] = true end end - local nb = 4 + (level / 7) + local nb = 4 + (data.level / 7) nb = math.max(rng.range(math.floor(nb * 0.7), math.ceil(nb * 1.3)), 1) print("Adding "..nb.." random class talents to boss") @@ -1322,7 +1329,7 @@ function _M:createRandomBoss(base, level) print(" * talent", tid) local max = (t.points == 1) and 1 or math.ceil(t.points * 1.6) local step = max / 50 - b.learn_tids[tid] = math.ceil(step * level) + b.learn_tids[tid] = math.ceil(step * data.level) end end end @@ -1332,10 +1339,11 @@ function _M:createRandomBoss(base, level) local classes = Birther.birth_descriptor_def.subclass local list = {} for name, data in pairs(classes) do if not data.not_on_random_boss then list[#list+1] = data end end - local c1, c2 = rng.tableRemove(list), rng.tableRemove(list) - - apply_class(table.clone(c1, true)) - apply_class(table.clone(c2, true)) + for i = 1, data.nb_classes or 2 do + local c = rng.tableRemove(list) + if not c then break end + apply_class(table.clone(c, true)) + end b.rnd_boss_on_added_to_level = b.on_added_to_level b.on_added_to_level = function(self, ...) @@ -1347,6 +1355,14 @@ function _M:createRandomBoss(base, level) self.rnd_boss_on_added_to_level = nil self.learn_tids = nil self.on_added_to_level = nil + + -- Cheat a bit with ressources + self.max_mana = self.max_mana * 3 self.mana_regen = self.mana_regen + 1 + self.max_vim = self.max_vim * 3 self.vim_regen = self.vim_regen + 1 + self.max_stamina = self.max_stamina * 3 self.stamina_regen = self.stamina_regen + 1 + self.max_psi = self.max_psi * 3 self.psi_regen = self.psi_regen + 2 + self.equilibrium_regen = self.equilibrium_regen - 2 + self:resetToFull() end return b, boss_id diff --git a/game/modules/tome/data/general/encounters/maj-eyal-npcs.lua b/game/modules/tome/data/general/encounters/maj-eyal-npcs.lua index 5ded3b2f11..caf07ac2c2 100644 --- a/game/modules/tome/data/general/encounters/maj-eyal-npcs.lua +++ b/game/modules/tome/data/general/encounters/maj-eyal-npcs.lua @@ -78,3 +78,28 @@ newEntity{ ai = "world_hostile", ai_state = {chase_distance=3}, on_encounter = {type="ambush", width=10, height=10, nb={1,1}, filters={{type="dragon"}}}, } + +newEntity{ + name = "adventurers party", + type = "hostile", subtype = "humanoid", + display = '@', color = colors.UMBER, + level_range = {14, nil}, + sight = 1, + rarity = 12, + unit_power = 14, + ai = "world_hostile", ai_state = {chase_distance=3}, + on_encounter = { + type="ambush", + width=14, + height=14, + nb={2, 4}, + filters={{special_rarity="humanoid_random_boss", random_boss={ + nb_classes=1, + rank=3, + life_rating=function(v) return v * 1.3 + 2 end, + loot_quality = "store", + loot_quantity = 1, + no_loot_randart = true, + }}} + }, +} diff --git a/game/modules/tome/data/general/npcs/all.lua b/game/modules/tome/data/general/npcs/all.lua index a7fe14e3ad..f01de81f5e 100644 --- a/game/modules/tome/data/general/npcs/all.lua +++ b/game/modules/tome/data/general/npcs/all.lua @@ -80,6 +80,8 @@ loadIfNot("/data/general/npcs/vermin.lua") loadIfNot("/data/general/npcs/wight.lua") loadIfNot("/data/general/npcs/xorn.lua") +loadIfNot("/data/general/npcs/humanoid_random_boss.lua") + -- Select some random dominant ones for random zones if random_zone_mode then local nt = {} diff --git a/game/modules/tome/data/general/npcs/humanoid_random_boss.lua b/game/modules/tome/data/general/npcs/humanoid_random_boss.lua new file mode 100644 index 0000000000..f35e502e3f --- /dev/null +++ b/game/modules/tome/data/general/npcs/humanoid_random_boss.lua @@ -0,0 +1,66 @@ +-- ToME - Tales of Maj'Eyal +-- Copyright (C) 2009, 2010, 2011 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 + +-- Those are never generated randomly, but used when we want humanoid random bosses + +newEntity{ + define_as = "BASE_NPC_HUMANOID_RANDOM_BOSS", + type = "humanoid", subtype = "human", + display = "p", color=colors.UMBER, + + level_range = {1, nil}, + infravision = 20, + lite = 1, + + life_rating = 10, + rank = 3, + size_category = 3, + + open_door = true, +} + +newEntity{ base = "BASE_NPC_HUMANOID_RANDOM_BOSS", + name = "human", subtype = "human", color=colors.LIGHT_UMBER, + humanoid_random_boss = 1, + resolvers.racial(), +} + +newEntity{ base = "BASE_NPC_HUMANOID_RANDOM_BOSS", + name = "thalore", subtype = "thalore", color=colors.LIGHT_GREEN, + humanoid_random_boss = 1, + resolvers.racial(), +} + +newEntity{ base = "BASE_NPC_HUMANOID_RANDOM_BOSS", + name = "shalore", subtype = "shalore", color=colors.LIGHT_BLUE, + humanoid_random_boss = 1, + resolvers.racial(), +} + +newEntity{ base = "BASE_NPC_HUMANOID_RANDOM_BOSS", + name = "halflint", subtype = "halfling", color=colors.BLUE, + humanoid_random_boss = 1, + resolvers.racial(), +} + +newEntity{ base = "BASE_NPC_HUMANOID_RANDOM_BOSS", + name = "dwarf", subtype = "dwarf", color=colors.UMBER, + humanoid_random_boss = 2, + resolvers.racial(), +} -- GitLab