diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua index 4605ac262c526637311bb703cd6952f52e8da6c5..d428df0fd5746f96747ff43d8f44d1d4c4b24c04 100644 --- a/game/modules/tome/class/Actor.lua +++ b/game/modules/tome/class/Actor.lua @@ -63,8 +63,8 @@ function _M:init(t, no_default) -- Default regen t.mana_regen = t.mana_regen or 0.5 - t.stamina_regen = t.stamina_regen or 0.2 -- Stamina regens slower than mana - t.life_regen = t.life_regen or 0.1 -- Life regen real slow + t.stamina_regen = t.stamina_regen or 0.4 -- Stamina regens slower than mana + t.life_regen = t.life_regen or 0.3 -- Life regen real slow -- Default melee barehanded damage self.combat = { dam=1, atk=1, apr=0, dammod={str=1} } @@ -105,6 +105,13 @@ end function _M:move(x, y, force) local moved = false if force or self:enoughEnergy() then + -- Confused ? + if not force and self:attr("confused") then + if rng.chance(self:attr("confused")) then + x, y = self.x + rng.range(-1, 1), self.y + rng.range(-1, 1) + end + end + -- Should we prob travel through walls ? if not force and self:attr("prob_travel") and game.level.map:checkEntity(x, y, Map.TERRAIN, "block_move", self) then moved = self:probabilityTravel(x, y, self:attr("prob_travel")) diff --git a/game/modules/tome/data/birth/classes.lua b/game/modules/tome/data/birth/classes.lua index 0bf7c5e5034bcc633f1d29a4d70340cef97509fb..59de7415bec0f560f2133cfdd37673e97de6c510 100644 --- a/game/modules/tome/data/birth/classes.lua +++ b/game/modules/tome/data/birth/classes.lua @@ -16,11 +16,6 @@ newBirthDescriptor{ copy = { max_life = 120, life_rating = 10, - equipment = resolvers.equip{ id=true, - {type="weapon", subtype="longsword", name="iron longsword"}, - {type="armor", subtype="shield", name="iron shield"}, - {type="armor", subtype="massive", name="iron massive armor"} - }, }, } @@ -33,14 +28,21 @@ newBirthDescriptor{ stats = { str=3, con=2, dex=1, }, talents_types = { ["technique/shield"]={true, 0.3}, - ["technique/2hweapon"]={true, 0.3}, + ["technique/2hweapon-offense"]={true, 0.3}, + ["technique/2hweapon-cripple"]={true, 0.3}, ["technique/combat-training"]={true, 0.3}, ["technique/weapon-training"]={true, 0.3}, }, talents = { - [ActorTalents.T_SHIELD_BASH] = 1, + [ActorTalents.T_BERSERKER] = 1, [ActorTalents.T_WEAPON_COMBAT] = 1, - [ActorTalents.T_SWORD_MASTERY] = 1, + [ActorTalents.T_HEAVY_ARMOUR_TRAINING] = 1, + }, + copy = { + equipment = resolvers.equip{ id=true, + {type="weapon", subtype="greatsword", name="iron greatsword"}, + {type="armor", subtype="heavy", name="iron mail armour"} + }, }, } diff --git a/game/modules/tome/data/damage_types.lua b/game/modules/tome/data/damage_types.lua index 3a862093c41d5cf9d4792d2a086e7d39e7b50306..fc04e0c6d44dde526eac51251e3c91d54e27480a 100644 --- a/game/modules/tome/data/damage_types.lua +++ b/game/modules/tome/data/damage_types.lua @@ -292,3 +292,18 @@ newDamageType{ end end, } + +-- Confusion +newDamageType{ + name = "confusion", type = "CONFUSION", + projector = function(src, x, y, type, dam) + local target = game.level.map(x, y, Map.ACTOR) + if target then + if target:checkHit(src:combatSpellpower(), target:combatSpellResist(), 0, 95, 15) and target:canBe("stun") then + target:setEffect(target.EFF_CONFUSED, dam.dur, {power=dam.dam}) + else + game.logSeen(target, "%s resists!", target.name:capitalize()) + end + end + end, +} diff --git a/game/modules/tome/data/general/npcs/skeleton.lua b/game/modules/tome/data/general/npcs/skeleton.lua index 18f8af864e267c4346033e02bc89464d7c316491..a66837ce2bd601d1347af26bca1a452b710a966f 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{ ["technique/other"]=0.3, ["technique/2hweapon"]=0.3 }, + tmasteries = resolvers.tmasteries{ ["technique/other"]=0.3, ["technique/2hweapon-offense"]=0.3, ["technique/2hweapon-cripple"]=0.3 }, blind_immune = 1, see_invisible = 2, diff --git a/game/modules/tome/data/general/objects/heavy-armors.lua b/game/modules/tome/data/general/objects/heavy-armors.lua index db81c31bd4d1cd921b1ba7945a22482962a3c19d..3935e35ecbe9a02aa333c5ace719c093c4184b01 100644 --- a/game/modules/tome/data/general/objects/heavy-armors.lua +++ b/game/modules/tome/data/general/objects/heavy-armors.lua @@ -14,7 +14,7 @@ newEntity{ newEntity{ base = "BASE_HEAVY_ARMOR", name = "iron mail armour", level_range = {1, 10}, - require = { stat = { str=18 }, }, + require = { stat = { str=14 }, }, cost = 20, wielder = { combat_def = 2, diff --git a/game/modules/tome/data/gfx/particles/teleport.lua b/game/modules/tome/data/gfx/particles/teleport.lua new file mode 100644 index 0000000000000000000000000000000000000000..15e22ffd6577c006d65ab073090690d80707b9c3 --- /dev/null +++ b/game/modules/tome/data/gfx/particles/teleport.lua @@ -0,0 +1,19 @@ +return { + base = 1000, + + angle = { 0, 360 }, anglev = { 2000, 5000 }, anglea = { 20, 60 }, + + life = { 20, 30 }, + size = { 3, 7 }, sizev = {0, 0}, sizea = {0, 0}, + + r = {10, 220}, rv = {0, 10}, ra = {0, 0}, + g = {10, 100}, gv = {0, 0}, ga = {0, 0}, + b = {20, 255}, bv = {0, 10}, ba = {0, 0}, + a = {25, 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/spells/spells.lua b/game/modules/tome/data/talents/spells/spells.lua index 0a4e4428af7022c4a39f3b5368cb6f9fc03af9dd..fc66f743947db2703d48bdd59ae09f39c384adcd 100644 --- a/game/modules/tome/data/talents/spells/spells.lua +++ b/game/modules/tome/data/talents/spells/spells.lua @@ -13,7 +13,6 @@ newTalentType{ type="spell/phantasm", name = "phantasm", description = "Control newTalentType{ type="spell/necromancy", name = "necromancy", description = "Necromancy is a dark school of magic dealing with death, and undeath." } -- Generic requires for spells based on talent level --- spells_req1 = { stat = { mag=function(level) return 12 + (level-1) * 2 end }, level = function(level) return 0 + (level-1) end, diff --git a/game/modules/tome/data/talents/techniques/2hweapon.lua b/game/modules/tome/data/talents/techniques/2hweapon.lua index bc356977b815947c8493b2c478db55a98632f832..3cf392289ea5255380b251df12cadd3a0e2fe415 100644 --- a/game/modules/tome/data/talents/techniques/2hweapon.lua +++ b/game/modules/tome/data/talents/techniques/2hweapon.lua @@ -1,42 +1,97 @@ newTalent{ - name = "Stunning Blow", - type = {"technique/2hweapon", 1}, + name = "Berserker", + type = {"technique/2hweapon-offense", 1}, + require = techs_req1, points = 5, - cooldown = 6, - stamina = 8, - require = { stat = { str=12 }, }, - action = function(self, t) + mode = "sustained", + cooldown = 30, + sustain_stamina = 40, + activate = function(self, t) local weapon = self:getInven("MAINHAND")[1] if not weapon or not weapon.twohanded then - game.logPlayer(self, "You cannot use Stunning Blow without a two handed weapon!") + game.logPlayer(self, "You cannot use Berserker without a two handed weapon!") return nil end - 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 - local speed, hit = self:attackTargetWith(target, weapon.combat, nil, 1.5 + self:getTalentLevel(t) / 10) + return { + atk = self:addTemporaryValue("combat_dam", 5 + self:getStr(6) * self:getTalentLevel(t)), + dam = self:addTemporaryValue("combat_atk", 5 + self:getDex(6) * self:getTalentLevel(t)), + def = self:addTemporaryValue("combat_def", -5 - 2 * self:getTalentLevel(t)), + armor = self:addTemporaryValue("combat_armor", -5 - 2 * self:getTalentLevel(t)), + } + end, - -- Try to stun ! - if hit then - if target:checkHit(self:combatAttackStr(weapon.combat), target:combatPhysicalResist(), 0, 95, 5 - self:getTalentLevel(t) / 2) and target:canBe("stun") then - target:setEffect(target.EFF_STUNNED, 2 + self:getTalentLevel(t), {}) - else - game.logSeen(target, "%s resists the stunning blow!", target.name:capitalize()) - end + deactivate = function(self, t, p) + self:removeTemporaryValue("combat_def", p.def) + self:removeTemporaryValue("combat_armor", p.armor) + self:removeTemporaryValue("combat_atk", p.atk) + self:removeTemporaryValue("combat_dam", p.dam) + return true + end, + info = function(self, t) + return ([[Enters an aggressive battle stance, increasing attack by %d and damage by %d at the cost of %d defense and %d armor.]]): + format(5 + self:getDex(6) * self:getTalentLevel(t), 5 + self:getStr(6) * self:getTalentLevel(t), -5 - 2 * self:getTalentLevel(t), -5 - 2 * self:getTalentLevel(t)) + end, +} + + +newTalent{ + name = "Death Dance", + type = {"technique/2hweapon-offense", 2}, + require = techs_req2, + points = 5, + cooldown = 10, + stamina = 30, + action = function(self, t) + local weapon = self:getInven("MAINHAND")[1] + if not weapon or not weapon.twohanded then + game.logPlayer(self, "You cannot use Death Dance without a two handed weapon!") + return nil end + for i = -1, 1 do for j = -1, 1 do + local x, y = self.x + i, self.y + j + if (self.x ~= x or self.y ~= y) and game.level.map:isBound(x, y) and game.level.map(x, y, Map.ACTOR) then + local target = game.level.map(x, y, Map.ACTOR) + self:attackTargetWith(target, weapon.combat, nil, 1.4 + self:getTalentLevel(t) / 8) + end + end end + return true end, info = function(self, t) - return ([[Hits the target with your weapon doing %d%% damage, if the atatck hits, the target is stunned.]]):format(100 * (1.5 + self:getTalentLevel(t) / 10)) + return ([[Spin around, extending your weapon and damaging all targets around for %d%% weapon damage.]]):format(100 * (1.4 + self:getTalentLevel(t) / 8)) + end, +} + +newTalent{ + name = "Warshout", + type = {"technique/2hweapon-offense",3}, + require = techs_req3, + points = 5, + stamina = 30, + cooldown = 18, + tactical = { + ATTACKAREA = 10, + }, + range = 1, + action = function(self, t) + local tg = {type="cone", range=0, radius=3 + self:getTalentLevelRaw(t), friendlyfire=false} + local x, y = self:getTarget(tg) + if not x or not y then return nil end + self:project(tg, x, y, DamageType.CONFUSION, {dur=self:getTalentLevelRaw(t), dam=50+self:getTalentLevelRaw(t)*10}, {type="flame"}) + return true + end, + info = function(self, t) + return ([[Shout your warcry in a frontal cone, any targets caught inside will be confused for %d turns.]]): + format(self:getTalentLevelRaw(t)) end, } newTalent{ name = "Death Blow", - type = {"technique/2hweapon", 2}, + type = {"technique/2hweapon-offense", 4}, + require = techs_req4, points = 5, cooldown = 30, stamina = 30, @@ -77,7 +132,6 @@ newTalent{ game.logSeen(target, "%s resists the death blow!", target.name:capitalize()) end end - return true end, info = function(self, t) @@ -86,65 +140,42 @@ newTalent{ end, } +----------------------------------------------------------------------------- +-- Cripple +----------------------------------------------------------------------------- newTalent{ - name = "Death Dance", - type = {"technique/2hweapon", 3}, + name = "Stunning Blow", + type = {"technique/2hweapon-cripple", 1}, + require = techs_req1, points = 5, - cooldown = 10, - stamina = 30, - require = { stat = { str=30 }, }, + cooldown = 6, + stamina = 8, + require = { stat = { str=12 }, }, action = function(self, t) local weapon = self:getInven("MAINHAND")[1] if not weapon or not weapon.twohanded then - game.logPlayer(self, "You cannot use Death Dance without a two handed weapon!") + game.logPlayer(self, "You cannot use Stunning Blow without a two handed weapon!") return nil end - for i = -1, 1 do for j = -1, 1 do - local x, y = self.x + i, self.y + j - if (self.x ~= x or self.y ~= y) and game.level.map:isBound(x, y) and game.level.map(x, y, Map.ACTOR) then - local target = game.level.map(x, y, Map.ACTOR) - self:attackTargetWith(target, weapon.combat, nil, 1.4 + self:getTalentLevel(t) / 8) - end - end end - - return true - end, - info = function(self, t) - return ([[Spin around, extending your weapon and damaging all targets around for %d%% weapon damage.]]):format(100 * (1.4 + self:getTalentLevel(t) / 8)) - end, -} + 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 + local speed, hit = self:attackTargetWith(target, weapon.combat, nil, 1.5 + self:getTalentLevel(t) / 10) -newTalent{ - name = "Berserker", - type = {"technique/2hweapon", 3}, - mode = "sustained", - points = 5, - cooldown = 30, - sustain_stamina = 100, - require = { stat = { str=20 }, }, - activate = function(self, t) - local weapon = self:getInven("MAINHAND")[1] - if not weapon or not weapon.twohanded then - game.logPlayer(self, "You cannot use Berserker without a two handed weapon!") - return nil + -- Try to stun ! + if hit then + if target:checkHit(self:combatAttackStr(weapon.combat), target:combatPhysicalResist(), 0, 95, 5 - self:getTalentLevel(t) / 2) and target:canBe("stun") then + target:setEffect(target.EFF_STUNNED, 2 + self:getTalentLevel(t), {}) + else + game.logSeen(target, "%s resists the stunning blow!", target.name:capitalize()) + end end - return { - atk = self:addTemporaryValue("combat_dam", 5 + self:getStr(4) * self:getTalentLevel(t)), - dam = self:addTemporaryValue("combat_atk", 5 + self:getDex(4) * self:getTalentLevel(t)), - def = self:addTemporaryValue("combat_def", -15), - armor = self:addTemporaryValue("combat_armor", -15), - } - end, - deactivate = function(self, t, p) - self:removeTemporaryValue("combat_def", p.def) - self:removeTemporaryValue("combat_armor", p.armor) - self:removeTemporaryValue("combat_atk", p.atk) - self:removeTemporaryValue("combat_dam", p.dam) return true end, info = function(self, t) - return ([[Enters a protective battle stance, increasing attack by %d and damage by %d at the cost of 15 defense and 15 armor.]]):format(5 + self:getDex(4) * self:getTalentLevel(t), 5 + self:getStr(4) * self:getTalentLevel(t)) + return ([[Hits the target with your weapon doing %d%% damage, if the atatck hits, the target is stunned.]]):format(100 * (1.5 + self:getTalentLevel(t) / 10)) end, } diff --git a/game/modules/tome/data/talents/techniques/techniques.lua b/game/modules/tome/data/talents/techniques/techniques.lua index d3b78fef7accee4736b5928b20305d74ff7b0c04..32a1ece2dc7fbde9158772ce5fe835d420fd171a 100644 --- a/game/modules/tome/data/talents/techniques/techniques.lua +++ b/game/modules/tome/data/talents/techniques/techniques.lua @@ -1,10 +1,55 @@ -- Physical combat -newTalentType{ type="technique/2hweapon", name = "two handed weapons", description = "Allows the user to be more proficient with two handed weapons." } +newTalentType{ type="technique/2hweapon-offense", name = "two handed weapons", description = "Specialized two handed techniques." } +newTalentType{ type="technique/2hweapon-cripple", name = "two handed weapons", description = "Specialized two handed techniques." } newTalentType{ type="technique/dualweapon", name = "dual wielding", description = "Allows the user to be more proficient with dual wielding weapons." } newTalentType{ type="technique/shield", name = "weapon and shields", description = "Allows the user to be more proficient with shields and one handed weapons." } newTalentType{ type="technique/weapon-training", name = "weapon-training", description = "Grants bonuses to the different weapon types." } newTalentType{ type="technique/combat-training", name = "combat-training", description = "Teaches to use various armors and improves health." } +-- Generic requires for techs based on talent level +techs_req1 = { + stat = { str=function(level) return 12 + (level-1) * 2 end }, + level = function(level) return 0 + (level-1) end, +} +techs_req2 = { + stat = { str=function(level) return 20 + (level-1) * 2 end }, + level = function(level) return 4 + (level-1) end, +} +techs_req3 = { + stat = { str=function(level) return 28 + (level-1) * 2 end }, + level = function(level) return 8 + (level-1) end, +} +techs_req4 = { + stat = { str=function(level) return 36 + (level-1) * 2 end }, + level = function(level) return 12 + (level-1) end, +} +techs_req5 = { + stat = { str=function(level) return 44 + (level-1) * 2 end }, + level = function(level) return 16 + (level-1) end, +} + +-- Generic requires for techs_dex based on talent level +techs_dex_req1 = { + stat = { str=function(level) return 12 + (level-1) * 2 end }, + level = function(level) return 0 + (level-1) end, +} +techs_dex_req2 = { + stat = { str=function(level) return 20 + (level-1) * 2 end }, + level = function(level) return 4 + (level-1) end, +} +techs_dex_req3 = { + stat = { str=function(level) return 28 + (level-1) * 2 end }, + level = function(level) return 8 + (level-1) end, +} +techs_dex_req4 = { + stat = { str=function(level) return 36 + (level-1) * 2 end }, + level = function(level) return 12 + (level-1) end, +} +techs_dex_req5 = { + stat = { str=function(level) return 44 + (level-1) * 2 end }, + level = function(level) return 16 + (level-1) end, +} + load("/data/talents/techniques/2hweapon.lua") load("/data/talents/techniques/dualweapon.lua") load("/data/talents/techniques/weaponshield.lua") diff --git a/game/modules/tome/data/timed_effects.lua b/game/modules/tome/data/timed_effects.lua index 5185c29797bacaa072c4f6c927188896f841fced..0a35435c7caf447cd07c71addac427ffe500cbc8 100644 --- a/game/modules/tome/data/timed_effects.lua +++ b/game/modules/tome/data/timed_effects.lua @@ -220,6 +220,22 @@ newEffect{ end, } +newEffect{ + name = "CONFUSED", + desc = "Confused", + type = "magical", + status = "detrimental", + parameters = {}, + on_gain = function(self, err) return "#Target# wanders around!.", "+Confused" end, + on_lose = function(self, err) return "#Target# seems more focused.", "-Confused" end, + activate = function(self, eff) + eff.tmpid = self:addTemporaryValue("confused", eff.power) + end, + deactivate = function(self, eff) + self:removeTemporaryValue("confused", eff.tmpid) + end, +} + newEffect{ name = "DWARVEN_RESILIENCE", desc = "Dwarven Resilience", diff --git a/ideas/technics.ods b/ideas/technics.ods index 37da15a8978da0673e576921a1797a5f638ed0d9..adfe86bf63aac3a16491ad7554545aea84600f11 100644 Binary files a/ideas/technics.ods and b/ideas/technics.ods differ