diff --git a/game/engine/interface/PlayerHotkeys.lua b/game/engine/interface/PlayerHotkeys.lua new file mode 100644 index 0000000000000000000000000000000000000000..fac3acbc747f92587b3ae19069fab947741f0704 --- /dev/null +++ b/game/engine/interface/PlayerHotkeys.lua @@ -0,0 +1,41 @@ +require "engine.class" + +--- Handles player hotkey interface +-- This provides methods to bind and manage hotkeys as well as using them<br/> +-- This interface is designed to work with the engine.HotkeysDisplay class to display current hotkeys to the player +module(..., package.seeall, class.make) + +function _M:init(t) + self.hotkey = {} + self.hotkey_page = 1 +end + +--- Uses an hotkeyed talent +-- This requires the ActorTalents interface to use talents and a method player:playerUseItem(o, item) to use inventory objects +function _M:activateHotkey(id) + if self.hotkey[id] then + if self.hotkey[id][1] == "talent" then + self:useTalent(self.hotkey[id][2]) + elseif self.hotkey[id][1] == "inventory" then + local o, item = self:findInInventory(self:getInven("INVEN"), self.hotkey[id][2]) + if not o then + Dialog:simplePopup("Item not found", "You do not have any "..self.hotkey[id][2]..".") + else + self:playerUseItem(o, item) + end + end + else + Dialog:simplePopup("Hotkey not defined", "You may define a hotkey by pressing 'm' and following the inscructions there.") + end +end + +--- Switch to previous hotkey page +function _M:prevHotkeyPage() + self.hotkey_page = util.boundWrap(self.hotkey_page - 1, 1, 3) + self.changed = true +end +--- Switch to next hotkey page +function _M:nextHotkeyPage() + self.hotkey_page = util.boundWrap(self.hotkey_page + 1, 1, 3) + self.changed = true +end diff --git a/game/modules/tome/data/birth/classes.lua b/game/modules/tome/data/birth/classes.lua index 2f684d2a78a7cb462741ce75124e9da0a06781aa..0bf7c5e5034bcc633f1d29a4d70340cef97509fb 100644 --- a/game/modules/tome/data/birth/classes.lua +++ b/game/modules/tome/data/birth/classes.lua @@ -32,10 +32,10 @@ newBirthDescriptor{ }, stats = { str=3, con=2, dex=1, }, talents_types = { - ["physical/shield"]={true, 0.3}, - ["physical/2hweapon"]={true, 0.3}, - ["physical/combat-training"]={true, 0.3}, - ["physical/weapon-training"]={true, 0.3}, + ["technique/shield"]={true, 0.3}, + ["technique/2hweapon"]={true, 0.3}, + ["technique/combat-training"]={true, 0.3}, + ["technique/weapon-training"]={true, 0.3}, }, talents = { [ActorTalents.T_SHIELD_BASH] = 1, @@ -80,9 +80,9 @@ newBirthDescriptor{ }, stats = { dex=2, str=1, cun=3, }, talents_types = { - ["physical/dualweapon"]={true, 0.3}, - ["physical/combat-training"]={true, 0}, - ["physical/weapon-training"]={true, 0}, + ["technique/dualweapon"]={true, 0.3}, + ["technique/combat-training"]={true, 0}, + ["technique/weapon-training"]={true, 0}, ["cunning/stealth"]={true, 0.3}, ["cunning/traps"]={true, 0.3}, ["cunning/dirty"]={true, 0.3}, diff --git a/game/modules/tome/data/damage_types.lua b/game/modules/tome/data/damage_types.lua index 0bf269cb3bab6de918e33d6193d7c129692ac8e3..3a862093c41d5cf9d4792d2a086e7d39e7b50306 100644 --- a/game/modules/tome/data/damage_types.lua +++ b/game/modules/tome/data/damage_types.lua @@ -231,6 +231,18 @@ newDamageType{ end, } +-- Slime damage +newDamageType{ + name = "slime", type = "SLIME", + projector = function(src, x, y, type, dam) + DamageType:get(DamageType.NATURE).projector(src, x, y, DamageType.NATURE, dam) + local target = game.level.map(x, y, Map.ACTOR) + if target then + target:setEffect(target.EFF_SLOW, 3, {power=0.3}) + end + end, +} + -- Poisoning damage newDamageType{ name = "dig", type = "DIG", diff --git a/game/modules/tome/data/general/npcs/bear.lua b/game/modules/tome/data/general/npcs/bear.lua index 7fcb95a77d025a6a4e09504ab2fc24129aac3660..d4dd9b20858d78ffad74386bdff94c0431b044be 100644 --- a/game/modules/tome/data/general/npcs/bear.lua +++ b/game/modules/tome/data/general/npcs/bear.lua @@ -16,7 +16,7 @@ newEntity{ combat_armor = 1, combat_def = 1, combat = { dam=resolvers.rngavg(12,25), atk=10, apr=10, physspeed=2 }, life_rating = 13, - tmasteries = resolvers.tmasteries{ ["physical/other"]=0.25 }, + tmasteries = resolvers.tmasteries{ ["technique/other"]=0.25 }, resists = { [DamageType.FIRE] = 20, [DamageType.COLD] = 20, [DamageType.POISON] = 20 }, } diff --git a/game/modules/tome/data/general/npcs/skeleton.lua b/game/modules/tome/data/general/npcs/skeleton.lua index dd24826b56e772d5d3da95ddd046bd5ce3fdb16e..18f8af864e267c4346033e02bc89464d7c316491 100644 --- a/game/modules/tome/data/general/npcs/skeleton.lua +++ b/game/modules/tome/data/general/npcs/skeleton.lua @@ -16,7 +16,7 @@ newEntity{ energy = { mod=1 }, stats = { str=14, dex=12, mag=10, con=12 }, - tmasteries = resolvers.tmasteries{ ["physical/other"]=0.3, ["physical/2hweapon"]=0.3 }, + tmasteries = resolvers.tmasteries{ ["technique/other"]=0.3, ["technique/2hweapon"]=0.3 }, blind_immune = 1, see_invisible = 2, diff --git a/game/modules/tome/data/general/npcs/troll.lua b/game/modules/tome/data/general/npcs/troll.lua index 55d3e991a76891726a97e0a794fb7886e7b0ad20..84555ba7d070198a153028b8d4e10e6c6a653ecc 100644 --- a/game/modules/tome/data/general/npcs/troll.lua +++ b/game/modules/tome/data/general/npcs/troll.lua @@ -19,7 +19,7 @@ newEntity{ energy = { mod=1 }, stats = { str=20, dex=8, mag=6, con=16 }, - tmasteries = resolvers.tmasteries{ ["physical/other"]=0.3 }, + tmasteries = resolvers.tmasteries{ ["technique/other"]=0.3 }, resists = { [DamageType.FIRE] = -50 }, } diff --git a/game/modules/tome/data/general/objects/potions.lua b/game/modules/tome/data/general/objects/potions.lua index ec95af19323745eb0c317a69e576e6ef99c3f2d6..ed01b9d61aa1e67ff46cda49b4e335371529d8b3 100644 --- a/game/modules/tome/data/general/objects/potions.lua +++ b/game/modules/tome/data/general/objects/potions.lua @@ -159,10 +159,10 @@ newEntity{ base = "BASE_POTION", cost = 0.01, use_simple = { name="quaff", use = function(self, who) - game.logSeen(who, "%s quaff the slime juice. Yuck.", who.name:capitalize()) + game.logSeen(who, "%s quaffs the slime juice. Yuck.", who.name:capitalize()) -- 1% chance of gaining slime mold powers if rng.percent(1) then - who:learnTalentType("slime/slime", true) + who:learnTalentType("gift/slime", true) game.logSeen(who, "%s is transformed by the slime mold juice.", who.name:capitalize()) game.logPlayer(who, "#00FF00#You gain an affinity for the molds. You can now learn new slime talents (press G).") end diff --git a/game/modules/tome/data/general/objects/scrolls.lua b/game/modules/tome/data/general/objects/scrolls.lua index 54ecd1f33472178f35ddec9ed514703c0c7b88fc..cc86decc7d03aaefa1860852cfd1988c6a378215 100644 --- a/game/modules/tome/data/general/objects/scrolls.lua +++ b/game/modules/tome/data/general/objects/scrolls.lua @@ -23,6 +23,28 @@ newEntity{ base = "BASE_SCROLL", end} } +newEntity{ base = "BASE_SCROLL", + name = "scroll of identify", + level_range = {1, 50}, + rarity = 6, + cost = 1, + + use_simple = { name="identify one object (or all with high magic stat)", use = function(self, who) + if who:getMag() < 28 then + who:showInventory("Identify object", who:getInven(who.INVEN_INVEN), nil, function(o, item) + o:identify(true) + game.logPlayer(who, "You identify: "..o:getName()) + end) + else + for i, o in ipairs(who:getInven("INVEN")) do + o:identify(true) + end + game.logPlayer(who, "You identify all your inventory.") + end + return "destroy", true + end} +} + newEntity{ base = "BASE_SCROLL", name = "scroll of phase door", level_range = {1, 30}, diff --git a/game/modules/tome/data/gfx/particles/slime.lua b/game/modules/tome/data/gfx/particles/slime.lua new file mode 100644 index 0000000000000000000000000000000000000000..1377b0d4f3d2e18c41333faffd4b7f831baafaa5 --- /dev/null +++ b/game/modules/tome/data/gfx/particles/slime.lua @@ -0,0 +1,19 @@ +return { + base = 1000, + + angle = { 0, 360 }, anglev = { 2000, 4000 }, anglea = { 20, 60 }, + + life = { 5, 10 }, + size = { 4, 7 }, sizev = {0, 0}, sizea = {0, 0}, + + r = {0, 0}, rv = {0, 0}, ra = {0, 0}, + g = {80, 200}, gv = {0, 10}, ga = {0, 0}, + b = {0, 0}, bv = {0, 0}, ba = {0, 0}, + a = {155, 255}, av = {0, 0}, aa = {0, 0}, + +}, function(self) + self.nb = (self.nb or 0) + 1 + if self.nb < 6 then + self.ps:emit(100) + end +end diff --git a/game/modules/tome/data/talents/misc/random.lua b/game/modules/tome/data/talents/misc/random.lua index 71b28d73088ff8d328bd9d4dc00a361ac8f5f3fe..87afcb77c9089d6534518a80f8e26876003dcd74 100644 --- a/game/modules/tome/data/talents/misc/random.lua +++ b/game/modules/tome/data/talents/misc/random.lua @@ -12,17 +12,102 @@ newTalent{ message = "@Source@ releases poisonous spores at @target@.", cooldown = 10, range = 1, + require = {level = function(level) return 0 + (level-1) end,}, + tactical = { + ATTACK = 10, + }, action = function(self, t) local t = {type="hit", range=self:getTalentRange(t)} local x, y, target = self:getTarget(t) if not x or not y or not target then return nil end if math.floor(core.fov.distance(self.x, self.y, x, y)) > 1 then return nil end self.combat_apr = self.combat_apr + 1000 - self:attackTarget(target, DamageType.POISON, 1.5 + self:getTalentLevel(t) / 5, true) + self:attackTarget(target, DamageType.POISON, 1.5 + self:getTalentLevel(t) / 4, true) self.combat_apr = self.combat_apr - 1000 return true end, - info = function(self) - return ([[Releases poisonous spores at the target.]]) + info = function(self, t) + return ([[Releases poisonous spores at the target doing %d%% weapon damage.]]):format(100 * (1.5 + self:getTalentLevel(t) / 4)) + end, +} + +newTalent{ + name = "Acidic Skin", + type = {"gift/slime", 2}, + points = 5, + mode = "sustained", + message = "The skin of @Source@ starts dripping acid.", + cooldown = 10, + range = 1, + require = {level = function(level) return 4 + (level-1) end,}, + tactical = { + DEFEND = 10, + }, + activate = function(self, t) + local power = 10 + 5 * self:getTalentLevel(t) + return { + onhit = self:addTemporaryValue("on_melee_hit", {[DamageType.ACID]=power}), + } + end, + deactivate = function(self, t, p) + self:removeTemporaryValue("on_melee_hit", p.onhit) + return true + end, + info = function(self, t) + return ([[Your skin drips with acid, damaging all that hits your for %d acid damage.]]):format(10 + 5 * self:getTalentLevel(t)) + end, +} + +newTalent{ + name = "Slime Spit", + type = {"gift/slime", 3}, + points = 5, + cooldown = 30, + tactical = { + ATTACK = 10, + }, + range = 20, + require = {level = function(level) return 8 + (level-1) end,}, + action = function(self, t) + local tg = {type="bolt", range=self:getTalentRange(t)} + local x, y = self:getTarget(tg) + if not x or not y then return nil end + self:project(tg, x, y, DamageType.SLIME, 20 + (self:getMag() * self:getTalentLevel(t)) * 0.3, {type="slime"}) + return true + end, + info = function(self, t) + return ([[Spit slime at your target doing %0.2f nature damage and slowing it down for 3 turns. + The damage will increase with the Dexterity stat]]):format(20 + (self:getMag() * self:getTalentLevel(t)) * 0.3) + end, +} + +newTalent{ + name = "Slime Roots", + type = {"gift/slime", 4}, + points = 5, + cooldown = 20, + tactical = { + MOVEMENT = 10, + }, + range = 20, + require = {level = function(level) return 12 + (level-1) end,}, + action = function(self, t) + local x, y = self:getTarget{type="ball", range=20 + self:getTalentLevel(t), radius=7 - self:getTalentLevel(t)} + if not x then return nil end + -- Target code doesnot restrict the self coordinates to the range, it lets the poject function do it + -- but we cant ... + x, y = game.target:pointAtRange(self.x, self.y, x, y, 20 + self:getTalentLevel(t)) + game.level.map:particleEmitter(self.x, self.y, 1, "slime") + self:teleportRandom(x, y, 7 - self:getTalentLevel(t)) + game.level.map:particleEmitter(self.x, self.y, 1, "slime") + + -- Stunned! + self:setEffect(self.EFF_STUNNED, util.bound(5 - self:getTalentLevel(t) / 2, 2, 7), {}) + return true + end, + info = function(self, t) + return ([[You extend slimy roots into the ground, follow them and re-appear somewhere else in a range of %d. + The process is quite a strain on your body and you will be stunned for %d turns. + The damage will increase with the Dexterity stat]]):format(20 + (self:getMag() * self:getTalentLevel(t)) * 0.3, util.bound(5 - self:getTalentLevel(t) / 2, 2, 7)) end, } diff --git a/game/modules/tome/data/talents/spells/divination.lua b/game/modules/tome/data/talents/spells/divination.lua index 4df82f51815ac0b151b25c4a6b2981fa39a68faa..298718c80db4568d629fba032e1d8989d1c80974 100644 --- a/game/modules/tome/data/talents/spells/divination.lua +++ b/game/modules/tome/data/talents/spells/divination.lua @@ -38,6 +38,7 @@ newTalent{ if self:getTalentLevel(t) < 3 then self:showInventory("Identify object", self:getInven(self.INVEN_INVEN), nil, function(o, item) o:identify(true) + game.logPlayer(who, "You identify: "..o:getName()) end) return true end @@ -46,14 +47,18 @@ newTalent{ for i, o in ipairs(self:getInven("INVEN")) do o:identify(true) end + game.logPlayer(who, "You identify all your inventory.") end if self:getTalentLevel(t) >= 4 then + local idx = 1 while true do local o = game.level.map:getObject(self.x, self.y, idx) if not o then break end o:identify(true) + idx = idx + 1 end + game.logPlayer(who, "You identify everything around you.") end return true diff --git a/ideas/cunning.ods b/ideas/cunning.ods index c14f4360c3d4e193e6a1ee70c7619a64487496e6..24bf3e185f6822db83fd7cea59519b8519a8dfd3 100644 Binary files a/ideas/cunning.ods and b/ideas/cunning.ods differ diff --git a/ideas/gifts.ods b/ideas/gifts.ods new file mode 100644 index 0000000000000000000000000000000000000000..7644b1dc773d57163957e1abdd81a67e13242e4d Binary files /dev/null and b/ideas/gifts.ods differ diff --git a/ideas/technics.ods b/ideas/technics.ods index 0c1cf26af327085c07b5e8a250c3683a293eb8f8..37da15a8978da0673e576921a1797a5f638ed0d9 100644 Binary files a/ideas/technics.ods and b/ideas/technics.ods differ