diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua index a27d3011725eb839954db3cf0c4bd3c7d64420a3..952022961001c3c8732437fe98f685cae8f3282c 100644 --- a/game/modules/tome/class/Game.lua +++ b/game/modules/tome/class/Game.lua @@ -100,6 +100,9 @@ function _M:run() self.log(self.flash.GOOD, "Welcome to #00FF00#Tales of Maj'Eyal!") + -- List of stuff to do on tick end + self.on_tick_end = {} + -- Setup inputs self:setupCommands() self:setupMouse() @@ -492,10 +495,23 @@ function _M:tick() -- (since display is on a set FPS while tick() ticks as much as possible -- engine.GameEnergyBased.tick(self) end + + -- Run tick end stuff + if #self.on_tick_end > 0 then + for i = 1, #self.on_tick_end do self.on_tick_end[i]() end + self.on_tick_end = {} + end + if savefile_pipe.saving then self.player.changed = true end if self.paused and not savefile_pipe.saving then return true end end +--- Register things to do on tick end +-- This is used for recall spells to let the tick finish before switching levels +function _M:onTickEnd(f) + self.on_tick_end[#self.on_tick_end+1] = f +end + --- Called every game turns -- Does nothing, you can override it function _M:onTurn() diff --git a/game/modules/tome/data/general/npcs/all.lua b/game/modules/tome/data/general/npcs/all.lua index 34f58ee08c56094e34befff25b1217e943171fd1..bc840793627461a58a2909718d588535b597d638 100644 --- a/game/modules/tome/data/general/npcs/all.lua +++ b/game/modules/tome/data/general/npcs/all.lua @@ -36,6 +36,7 @@ loadIfNot("/data/general/npcs/fire-drake.lua") loadIfNot("/data/general/npcs/ghost.lua") loadIfNot("/data/general/npcs/ghoul.lua") --loadIfNot("/data/general/npcs/gwelgoroth.lua") +loadIfNot("/data/general/npcs/horror.lua") loadIfNot("/data/general/npcs/jelly.lua") loadIfNot("/data/general/npcs/minor-demon.lua") loadIfNot("/data/general/npcs/major-demon.lua") diff --git a/game/modules/tome/data/general/npcs/horror.lua b/game/modules/tome/data/general/npcs/horror.lua new file mode 100644 index 0000000000000000000000000000000000000000..36ed62975f09a8df94a294dbca335071c3af2425 --- /dev/null +++ b/game/modules/tome/data/general/npcs/horror.lua @@ -0,0 +1,116 @@ +-- 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 + +-- last updated: 10:46 AM 2/3/2010 + +local Talents = require("engine.interface.ActorTalents") + +newEntity{ + define_as = "BASE_NPC_HORROR", + type = "horror", subtype = "eldritch", + display = "h", color=colors.WHITE, + body = { INVEN = 10 }, + autolevel = "warrior", + ai = "dumb_talented_simple", ai_state = { ai_move="move_dmap", talent_in=3, }, + + stats = { str=22, dex=20, wil=15, con=15 }, + energy = { mod=1 }, + combat_armor = 0, combat_def = 0, + combat = { dam=5, atk=15, apr=7, dammod={str=0.6} }, + infravision = 20, + max_life = resolvers.rngavg(10,20), + rank = 2, + size_category = 3, +} + +newEntity{ base="BASE_NPC_HORROR", define_as = "GRGGLCK_TENTACLE", + name = "Grgglck's Tentacle", + color = colors.GREY, + desc = [[This is one of Grgglck's tentacle, it looks more vulnerable than the main body.]], + level_range = {20, nil}, exp_worth = 0, + max_life = 100, life_rating = 3, fixed_rating = true, + equilibrium_regen = -20, + rank = 3, + no_breath = 1, + size_category = 2, + + stun_immune = 1, + knockback_immune = 1, + teleport_immune = 1, + + resists = { all=50, [DamageType.DARKNESS] = 100 }, + + combat = { dam=resolvers.mbonus(25, 15), atk=500, apr=500, dammod={str=1} }, + + autolevel = "warrior", + ai = "dumb_talented_simple", ai_state = { talent_in=3, ai_move="move_astar" }, + + on_act = function(self) + if self.summoner.dead then + self:die() + game.logSeen(self, "#AQUAMARINE#With Grgglck's death its tentacle also falls lifeless on the ground!") + end + end, + + on_die = function(self, who) + if self.summoner and not self.summoner.dead then + game.logSeen(self, "#AQUAMARINE#As %s falls you notice that %s seems to shudder in pain!", self.name, self.summoner.name) + self.summoner:takeHit(self.max_life, who) + end + end, +} + +newEntity{ base="BASE_NPC_HORROR", define_as = "TEST", + name = "Grgglck the Devouring Darkness", unique = true, + color = colors.DARK_GREY, + rarity = 50, + desc = [[An horror from the deepest pits of the earth. It looks like a huge pile of tentacles all trying to reach for you. +You can discern a huge ruond mouth covered in razor-sharp teeth.]], + level_range = {20, nil}, exp_worth = 2, + max_life = 300, life_rating = 25, fixed_rating = true, + equilibrium_regen = -20, + negative_regen = 20, + rank = 3.5, + no_breath = 1, + size_category = 4, + movement_speed = 0.5, + + stun_immune = 1, + knockback_immune = 1, + + combat = { dam=resolvers.mbonus(100, 15), atk=500, apr=0, dammod={str=1.2} }, + + body = { INVEN = 10, MAINHAND=1, OFFHAND=1, BODY=1 }, + resolvers.drops{chance=100, nb=1, {unique=true} }, + resolvers.drops{chance=100, nb=5, {ego_chance=100} }, + + resists = { all=500 }, + + resolvers.talents{ + [Talents.T_STARFALL]=4, + [Talents.T_MOONLIGHT_RAY]=4, + [Talents.T_PACIFICATION_HEX]=4, + [Talents.T_BURNING_HEX]=4, + [Talents.T_INVOKE_TENTACLE]=1, + }, + resolvers.sustains_at_birth(), + + autolevel = "warriormage", + ai = "dumb_talented_simple", ai_state = { talent_in=3, ai_move="move_astar" }, +} diff --git a/game/modules/tome/data/general/npcs/multihued-drake.lua b/game/modules/tome/data/general/npcs/multihued-drake.lua index 85a4b80c8cade82e672f842d9dab7c6eea6d9dee..dd2fea6f0374522adc22196549ecd9fd41b5900d 100644 --- a/game/modules/tome/data/general/npcs/multihued-drake.lua +++ b/game/modules/tome/data/general/npcs/multihued-drake.lua @@ -131,7 +131,7 @@ newEntity{ base = "BASE_NPC_MULTIHUED_DRAKE", }, } -newEntity{ base = "BASE_NPC_MULTIHUED_DRAKE", define_as="TEST", +newEntity{ base = "BASE_NPC_MULTIHUED_DRAKE", unique = true, name = "Ureslak the Prismatic", color=colors.VIOLET, display="D", desc = [[A huge multi-hued drake. It seems to shift color rapidly.]], diff --git a/game/modules/tome/data/lore/infinite-dungeon.lua b/game/modules/tome/data/lore/infinite-dungeon.lua index a904a7cc5bb5534d49a657b9f3dba85440e06cf5..5a9bb2cda4d5fbce309fe3db7212ff8330a35969 100644 --- a/game/modules/tome/data/lore/infinite-dungeon.lua +++ b/game/modules/tome/data/lore/infinite-dungeon.lua @@ -26,7 +26,7 @@ newLore{ category = "ruined dungeon", name = "clue (ruined dungeon)", lore = [[There is an inscription here: -#{italic}#"The river flows in its bed of stone...#{normal}#]], +#{italic}#The river flows in its bed of stone...#{normal}#]], } newLore{ @@ -35,7 +35,7 @@ newLore{ name = "clue (ruined dungeon)", lore = [[There is an inscription here: #{italic}#...The feather flies gently in the wind. -The tree's root run deep...#{normal}#]], +The tree's roots run deep...#{normal}#]], } newLore{ diff --git a/game/modules/tome/data/talents/misc/npcs.lua b/game/modules/tome/data/talents/misc/npcs.lua index 37b7c0d74768634b149446f97b981e59ace48452..a093d23d93b6715aa8e5f233abdd6895870741a8 100644 --- a/game/modules/tome/data/talents/misc/npcs.lua +++ b/game/modules/tome/data/talents/misc/npcs.lua @@ -1002,3 +1002,42 @@ newTalent{ The damage will increase with Magic stat.]]):format(self:combatTalentSpellDamage(t, 10, 170), 20 + self:getTalentLevel(t) * 10, self:combatTalentSpellDamage(t, 10, 220)) end, } + +newTalent{ + name = "Invoke Tentacle", + type = {"wild-gift/other", 1}, + cooldown = 1, + range = 20, + direct_hit = true, + action = function(self, t) + local tg = {type="hit", range=self:getTalentRange(t), talent=t} + local tx, ty = self:getTarget(tg) + if not tx or not ty then return nil end + + -- Find space + local x, y = util.findFreeGrid(tx, ty, 3, true, {[Map.ACTOR]=true}) + if not x then + game.logPlayer(self, "Not enough space to invoke!") + return + end + + -- Find an actor with that filter + local m = game.zone:makeEntityByName(game.level, "actor", "GRGGLCK_TENTACLE") + if m then + m.exp_worth = 0 + m:resolve() + + m.summoner = self + m.summon_time = 10 + + game.zone:addEntity(game.level, m, "actor", x, y) + + game.logSeen(self, "%s spawns one of its tentacle!", self.name:capitalize()) + end + + return true + end, + info = function(self, t) + return ([[Invoke your tentacles on your victim.]]) + end, +} diff --git a/game/modules/tome/data/timed_effects.lua b/game/modules/tome/data/timed_effects.lua index 30ab05622bd1e64f0249999c1bec14c68aa9d443..28e78caf2ba68c3e3fa2a39fd0b42993f32b74f3 100644 --- a/game/modules/tome/data/timed_effects.lua +++ b/game/modules/tome/data/timed_effects.lua @@ -1825,8 +1825,10 @@ newEffect{ end, deactivate = function(self, eff) if self:canBe("worldport") then - game.logPlayer(self, "You are yanked out of this place!") - game:changeLevel(1, game.player.last_wilderness) + game:onTickEnd(function() + game.logPlayer(self, "You are yanked out of this place!") + game:changeLevel(1, game.player.last_wilderness) + end) else game.logPlayer(self, "Space restabilizes around you.") end @@ -1855,8 +1857,10 @@ newEffect{ end if self:canBe("worldport") then - game.logPlayer(self, "You are yanked out of this place!") - game:changeLevel(1, "town-angolwen") + game:onTickEnd(function() + game.logPlayer(self, "You are yanked out of this place!") + game:changeLevel(1, "town-angolwen") + end) else game.logPlayer(self, "Space restabilizes around you.") end diff --git a/ideas/actor-types.ods b/ideas/actor-types.ods index 7b2520eaed9d75f69ba157ffb6cd05ad895b675d..7067e85b2183783b5aff153800f86443eeaad034 100644 Binary files a/ideas/actor-types.ods and b/ideas/actor-types.ods differ